Restore approved state (tree of 4effcc7 "Added LICENSE")
Roll the working tree back to the last approved shape, before the post-LICENSE span that false-greened the AFI parity matrix with symbol-presence probes and smuggled an unauthorized SQLAlchemy dependency into FastAPI's Shapes binding.
Forward commit, not a history rewrite — the six commits since 4effcc7 stay in the log as the record of what happened.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
116
README.md
116
README.md
@@ -33,86 +33,86 @@ reference implementation; per-adapter support is inventoried below.
|
||||
|
||||
## Backend adapters
|
||||
|
||||
Every adapter implements the same AFI wire protocol. The matrix below is **generated**
|
||||
from the conformance probes in [`tests/afi/`](tests/afi/) by `make parity-table` — it is
|
||||
output, not prose. A cell goes `✅` only when that adapter wires the capability into its
|
||||
own dispatch surface; it cannot be set to "supported" or "Django-only" by editing this
|
||||
file (a hand-edit fails `python tests/afi/parity_table.py --check` in CI, the same
|
||||
forcing function the codegen byte-parity tests use).
|
||||
Every adapter implements the same AFI wire protocol. The matrix below inventories
|
||||
support per adapter, grouped to separate protocol guarantees from Django-specific
|
||||
features (forms, ORM projection, auth providers, SSR). A cell counts as supported only
|
||||
when that adapter wires the capability into its own dispatch surface, not merely that a
|
||||
shared core primitive exists.
|
||||
|
||||
Every capability in the matrix is **AFI-common** — each adapter owes a binding, and a
|
||||
`❌` is a gap on the owed-work board, never a "this framework doesn't do that." The line
|
||||
between AFI-common and genuinely backend-bound lives in
|
||||
[`tests/afi/manifest.py`](tests/afi/manifest.py): what sits *outside* the matrix by
|
||||
design is the `allauth` integration (a Django-ecosystem package) and the per-stack
|
||||
*bindings* of common capabilities (`django-readers` is Django's Shapes binding; Django
|
||||
Forms is Django's Forms binding) — the capability is common; the binding is not.
|
||||
|
||||
<!-- MIZAN:PARITY:START — generated by tests/afi/parity_table.py; do not edit by hand -->
|
||||
Legend: ✅ wired · ◑ partial (declared/stubbed) · ❌ gap (AFI-common, owed) · — not applicable to this adapter's transport
|
||||
|
||||
Every capability below is **AFI-common**: each adapter owes a binding, and a ❌ is a gap on the owed-work board (`tests/afi/`), never a category. Backend-specific *bindings* of common capabilities (django-readers for Shapes, Django Forms for Forms) and genuinely Django-ecosystem features (allauth) are out of this matrix by design — see `tests/afi/manifest.py` for the line.
|
||||
Legend: ✅ supported · ◑ partial · ❌ not implemented · — not applicable to this transport
|
||||
|
||||
### Protocol core
|
||||
|
||||
The surface every Mizan adapter implements.
|
||||
|
||||
| Capability | Django | FastAPI | Rust / Axum | Tauri | TypeScript |
|
||||
|---|:---:|:---:|:---:|:---:|:---:|
|
||||
| RPC call dispatch (`{result, invalidate}`) | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| RPC call dispatch (`{result, invalidate}`) | ✅ | ✅ | ✅ | ✅ ¹ | ✅ |
|
||||
| Named-context bundle fetch | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| Invalidation — JSON body | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| Invalidation — `X-Mizan-Invalidate` header | ✅ | ✅ | ✅ | — | ✅ |
|
||||
| Invalidation auto-scoping (three-tier) | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| Function discovery / registration | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| Codegen IR export (KDL) | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| File uploads (`Upload` type) | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| Codegen IR export (KDL) | ✅ | ✅ | ✅ ⁶ | ✅ ⁶ | — ⁸ |
|
||||
|
||||
### Edge, cache & enforcement
|
||||
|
||||
| Capability | Django | FastAPI | Rust / Axum | Tauri | TypeScript |
|
||||
|---|:---:|:---:|:---:|:---:|:---:|
|
||||
| Auth-guard enforcement (`auth=…` rejects) | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| Origin-side HMAC cache | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| Edge manifest export | ✅ | ✅ | ✅ | — | ✅ |
|
||||
| PSR (`render_strategy` in manifest) | ✅ | ✅ | ✅ | — | ✅ |
|
||||
| Session / CSRF init endpoint | ✅ | ✅ | ✅ | — | ✅ |
|
||||
|
||||
### Extension points
|
||||
Protocol transports and guarantees co-equal with the body channel in the spec.
|
||||
|
||||
| Capability | Django | FastAPI | Rust / Axum | Tauri | TypeScript |
|
||||
|---|:---:|:---:|:---:|:---:|:---:|
|
||||
| WebSocket transport (`websocket=` declared) | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| SSR bridge (subprocess renderer) | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| JWT auth (access / refresh) | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| MWT (edge identity token) | ✅ | ✅ | ✅ | — | ✅ |
|
||||
| Typed query projection (Shapes) | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| Forms (schema / validate / submit) | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| Invalidation — `X-Mizan-Invalidate` header | ✅ | ❌ | ❌ | — ¹ | ✅ |
|
||||
| Auth-guard enforcement (`auth=…` rejects) | ✅ | ✅ | ❌ ⁵ | ◑ ⁵ | ❌ |
|
||||
| Origin-side HMAC cache | ✅ | ❌ | ❌ | ❌ | ✅ |
|
||||
| Edge manifest export | ✅ | ❌ | ❌ | — | ✅ |
|
||||
| PSR (`render_strategy` in manifest) | ✅ | ❌ | ❌ | — | ✅ |
|
||||
| Session / CSRF init endpoint | ✅ | ◑ ⁷ | ◑ ⁷ | — | ❌ |
|
||||
|
||||
> **Caveat:** Rust/Axum and Tauri accept `auth=` on a function but do not yet enforce
|
||||
> it — do not rely on `auth=` for access control on those adapters.
|
||||
|
||||
### Stack extensions (Django)
|
||||
|
||||
Django ecosystem features Mizan wraps. Other adapters provide these only where the
|
||||
target stack calls for them.
|
||||
|
||||
| Capability | Django | FastAPI | Rust / Axum | Tauri | TypeScript |
|
||||
|---|:---:|:---:|:---:|:---:|:---:|
|
||||
| WebSocket channels (declared transport) | ✅ | ❌ | ◑ ² | ❌ | ❌ |
|
||||
| Forms (schema / validate / submit) | ✅ | ❌ | ◑ ³ | ❌ | ❌ |
|
||||
| Formsets | ✅ | ❌ | ❌ | ❌ | ❌ |
|
||||
| API shapes (ORM query projection) ⁴ | ✅ | — | — | — | — |
|
||||
| JWT auth (access / refresh, session validation) | ✅ | ❌ | ❌ | ❌ | ❌ |
|
||||
| MWT (edge identity token) | ✅ | ❌ | ❌ | — | ❌ |
|
||||
| SSR bridge | ✅ | ❌ | ❌ | — | ❌ |
|
||||
| Auth-provider integration (allauth) | ✅ | ❌ | ❌ | ❌ | ❌ |
|
||||
|
||||
**Notes**
|
||||
|
||||
- **Invalidation — `X-Mizan-Invalidate` header** — The header channel is co-equal with the body channel in the spec. IPC transports carry invalidation in the response envelope instead.
|
||||
- **Edge manifest export** — The manifest configures an HTTP/CDN edge; a desktop IPC shell has no edge.
|
||||
- **MWT (edge identity token)** — MWT exists to key an edge cache; without an edge there is nothing to key.
|
||||
- **Typed query projection (Shapes)** — The capability is AFI-common; the binding is per-ORM (django-readers on Django, the project's ORM elsewhere).
|
||||
- **Forms (schema / validate / submit)** — The capability is AFI-common; the binding is per-framework (Django Forms on Django, Pydantic-or-equivalent elsewhere).
|
||||
<!-- MIZAN:PARITY:END -->
|
||||
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.
|
||||
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; the dispatch path does not
|
||||
enforce them. Rust/Axum has no enforcement either.
|
||||
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; CSRF is Django-only.
|
||||
8. TypeScript is an edge/protocol-reference adapter (HMAC cache, manifest, PSR), not a
|
||||
codegen source — it demonstrates the cache + invalidation protocol is
|
||||
language-agnostic.
|
||||
|
||||
## Conformance
|
||||
|
||||
Adapter parity is gated by the AFI conformance suite in [`tests/afi/`](tests/afi/), at
|
||||
two layers:
|
||||
|
||||
- **IR-shape parity** (`test_codegen_parity.py`) — Django, FastAPI, and the Rust adapter
|
||||
emit byte-identical KDL for the same registered fixture. The IR is the contract; the
|
||||
language that wrote the backend is irrelevant to the codegen-facing artifact.
|
||||
- **Capability parity** (`test_capability_parity.py`) — every `(capability, applicable
|
||||
adapter)` pair declared in `manifest.py` is probed for its actual wiring (`probes.py`).
|
||||
A gap is a **red test that names the owed binding**, not a footnote. The suite is
|
||||
intentionally red wherever a capability is unwired: that redness is the owed-work
|
||||
board, itemized and loud, and a gap turns green by being *wired*, never by being
|
||||
*described*. This is the per-capability gate the roadmap previously deferred.
|
||||
|
||||
The generated table above is rendered from the capability layer, and the `--check`
|
||||
diff keeps the README honest to the probes on every CI run.
|
||||
Adapter parity is gated by the AFI conformance suite in [`tests/afi/`](tests/afi/). It
|
||||
currently asserts **IR-shape parity** — the same fixture through Django, FastAPI, and
|
||||
the Rust adapter emits byte-identical KDL (`test_codegen_parity.py`). Per-capability
|
||||
runtime assertions (header transport, `auth=` enforcement, cache behavior) are planned.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
Reference in New Issue
Block a user