Added parity table.
This commit is contained in:
90
README.md
Normal file
90
README.md
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
# Mizan
|
||||||
|
|
||||||
|
An **Application Framework Interface (AFI)** — one decorator on a server function, a
|
||||||
|
typed client generated, invalidation automatic, caching protocol-driven. Any backend,
|
||||||
|
any frontend, one wire protocol.
|
||||||
|
|
||||||
|
For the wire protocol, package layout, and codegen state, see [`CLAUDE.md`](CLAUDE.md).
|
||||||
|
Architecture deep-dives live in [`docs/`](docs/). Open work is tracked in
|
||||||
|
[`ROADMAP.md`](ROADMAP.md) and [`ISSUES.md`](ISSUES.md).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Backend Adapter Parity
|
||||||
|
|
||||||
|
**Django is the maximal rubric** — it implements the full AFI surface. Every other
|
||||||
|
adapter is measured against it. A cell is marked supported only when *that adapter*
|
||||||
|
wires the capability into its own dispatch surface (not merely that a shared core
|
||||||
|
primitive exists).
|
||||||
|
|
||||||
|
Legend: ✅ full · ◑ partial · ❌ absent · — not applicable to this transport
|
||||||
|
|
||||||
|
| Capability | Django | FastAPI | Rust / Axum | Tauri | TypeScript |
|
||||||
|
|---|:---:|:---:|:---:|:---:|:---:|
|
||||||
|
| RPC call dispatch (`{result, invalidate}`) | ✅ | ✅ | ✅ | ✅ ¹ | ✅ |
|
||||||
|
| Named-context bundle fetch | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||||
|
| Invalidation — JSON body | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||||
|
| Invalidation — `X-Mizan-Invalidate` header | ✅ | ❌ | ❌ | — ¹ | ✅ |
|
||||||
|
| Invalidation auto-scoping (three-tier) | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||||
|
| Origin-side HMAC cache | ✅ | ❌ | ❌ | ❌ | ✅ |
|
||||||
|
| WebSocket channels | ✅ | ❌ | ◑ ² | ❌ | ❌ |
|
||||||
|
| Forms (schema / validate / submit) | ✅ | ❌ | ◑ ³ | ❌ | ❌ |
|
||||||
|
| Formsets | ✅ | ❌ | ❌ | ❌ | ❌ |
|
||||||
|
| API shapes (ORM query projection) ⁴ | ✅ | — | — | — | — |
|
||||||
|
| Auth guards (`auth=True/'staff'/'superuser'/callable`) | ✅ | ✅ | ❌ | ◑ ⁵ | ❌ |
|
||||||
|
| JWT auth (access / refresh, session validation) | ✅ | ❌ | ❌ | ❌ | ❌ |
|
||||||
|
| MWT (edge identity token) | ✅ | ❌ | ❌ | — | ❌ |
|
||||||
|
| SSR bridge | ✅ | ❌ | ❌ | — | ❌ |
|
||||||
|
| PSR (`render_strategy` in manifest) | ✅ | ❌ | ❌ | — | ✅ |
|
||||||
|
| Edge manifest export | ✅ | ❌ | ❌ | — | ✅ |
|
||||||
|
| Codegen IR export (KDL) | ✅ | ✅ | ✅ ⁶ | ✅ ⁶ | ❌ |
|
||||||
|
| Session / CSRF init endpoint | ✅ | ◑ ⁷ | ◑ ⁷ | — | ❌ |
|
||||||
|
| Function discovery / registration | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||||
|
| Auth-provider integration (allauth) | ✅ | ❌ | ❌ | ❌ | ❌ |
|
||||||
|
|
||||||
|
**Notes**
|
||||||
|
|
||||||
|
1. Tauri's transport is Tauri IPC (a single `#[tauri::command]` envelope), not HTTP.
|
||||||
|
Invalidation rides in the JSON response body; there is no header channel, so the
|
||||||
|
header row is N/A.
|
||||||
|
2. Rust/Axum declares `Transport::Websocket` in the IR/macro but routes no Axum
|
||||||
|
WebSocket handler yet.
|
||||||
|
3. Rust/Axum carries `is_form`/`form_role` trait stubs but no validate/submit
|
||||||
|
endpoint.
|
||||||
|
4. "API shapes" is Django's django-readers queryset projection — ORM-coupled. Every
|
||||||
|
adapter carries typed input/output through the KDL IR; the *projection primitive*
|
||||||
|
itself is Django-only.
|
||||||
|
5. Tauri's `FunctionSpec` carries `auth`/`private` fields, but the dispatch path does
|
||||||
|
not enforce them.
|
||||||
|
6. Rust/Axum and Tauri *are* the IR authority via the `#[mizan::client]` macro +
|
||||||
|
linkme registry; the codegen links the crate directly (`build_ir()` / the
|
||||||
|
`export-ir` bin) rather than fetching over HTTP.
|
||||||
|
7. FastAPI and Rust/Axum expose `GET /session/` returning a null CSRF token for wire
|
||||||
|
parity; real CSRF is Django-only.
|
||||||
|
|
||||||
|
### Reading the columns
|
||||||
|
|
||||||
|
- **FastAPI** — the AFI-common HTTP subset: dispatch, contexts, body invalidation,
|
||||||
|
auth guards, IR export. Channels / forms / SSR / cache are deliberately delegated to
|
||||||
|
native FastAPI equivalents.
|
||||||
|
- **Rust / Axum** — core dispatch + context bundling + compile-time registry, and the
|
||||||
|
*server-side* IR authority. No HTTP-layer cache, auth enforcement, or edge surface
|
||||||
|
yet.
|
||||||
|
- **Tauri** — the same Rust core over IPC for desktop/mobile. Edge, SSR, MWT, and CSRF
|
||||||
|
are structurally inapplicable to a local app.
|
||||||
|
- **TypeScript** — the edge/protocol reference: HMAC cache, edge manifest, and PSR
|
||||||
|
strategy, proving the cache + invalidation protocol is language-agnostic. It is not a
|
||||||
|
codegen IR source.
|
||||||
|
|
||||||
|
### Keeping this honest
|
||||||
|
|
||||||
|
This table is a **snapshot**, and a hand-maintained snapshot drifts the moment an
|
||||||
|
adapter gains or loses a target. The enforcing layer is the AFI conformance suite at
|
||||||
|
[`tests/afi/`](tests/afi/), which today gates **IR-shape parity** — the same fixture
|
||||||
|
through Django, FastAPI, and the Rust adapter must emit byte-identical KDL
|
||||||
|
(`test_codegen_parity.py`). It does **not yet** assert *runtime capability* parity
|
||||||
|
(e.g. "every adapter that claims the header transport actually emits
|
||||||
|
`X-Mizan-Invalidate`," "every adapter that claims `auth=` actually rejects an
|
||||||
|
unauthorized call"). Extending `tests/afi/` with per-capability assertions — one row of
|
||||||
|
this table per asserted behavior — is what turns the table from documentation into a
|
||||||
|
red-on-regression contract.
|
||||||
Reference in New Issue
Block a user