The conformance board (tests/afi/test_capability_parity.py) is now fully green: 90 capability cells + 4 meta-locks + 3 codegen byte-parity = 97 passed. The gaps the prose table used to launder as "Django-only" / "out of scope" are wired, against the pinned-spec model (single-authored spec, byte-identical conformance across languages) — never per-language reimplementation. FastAPI — edge_manifest + PSR (logic single-sourced in mizan_core.manifest), WebSocket RPC (/ws/ through the shared dispatch), SSR (the framework-agnostic SSRBridge relocated to mizan_core.ssr; Django rides it from there), Shapes (SQLAlchemy projection, same declaration surface as django-readers), Forms (Pydantic schema/validate/submit). Rust (Axum + Tauri + cores/mizan-rust) — X-Mizan-Invalidate header, auth= enforcement, origin HMAC cache, edge manifest + PSR, WebSocket handler / IPC subscription channel, multipart upload, SSR bridge, Shapes, Forms; JWT/MWT mint+verify and cache-key derivation byte-pinned to the Python reference (cache_keys_pin, token_pin, invalidate_header_pin). TypeScript — a KDL IR emitter byte-identical to the Python build_ir (so a TS backend can feed the codegen — the largest gap), multipart upload, session-init, WebSocket transport, SSR bridge, JWT/MWT mint (pinned to Python), Shapes, Forms. Verified in the merged tree: core 25, fastapi 74, django 353/21-skip, mizan-rust (incl. cross-language pins) green, axum 10, tauri 8, mizan-ts 103/2-skip. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
123 lines
6.5 KiB
Markdown
123 lines
6.5 KiB
Markdown
# Mizan
|
|
|
|
Mizan is an Application Framework Interface (AFI). A single `@client` decorator on a
|
|
server function generates a typed frontend client; cache invalidation and caching are
|
|
handled by the protocol.
|
|
|
|
```python
|
|
from mizan import client, ReactContext
|
|
|
|
UserContext = ReactContext('user')
|
|
|
|
# Context function — bundled into GET /api/mizan/ctx/user/
|
|
@client(context=UserContext)
|
|
def user_profile(request, user_id: int) -> UserShape:
|
|
return UserShape.query(lambda qs: qs.filter(pk=user_id))[0]
|
|
|
|
# Mutation — invalidation scoped automatically by matching param name
|
|
@client(affects=UserContext)
|
|
def update_profile(request, user_id: int, name: str) -> dict:
|
|
...
|
|
```
|
|
|
|
Adapters exist for Django, FastAPI, Rust/Axum, Tauri, and TypeScript. Django is the
|
|
reference implementation; per-adapter support is inventoried below.
|
|
|
|
> **Status:** Mizan is not production-tested. It passes its own test suites but has not
|
|
> been run in a production deployment. Treat it as pre-release.
|
|
|
|
## Documentation
|
|
|
|
- [`docs/`](docs/) — architecture references: AFI, SSR, cache keying, MWT, PSR vs. Edge
|
|
- [`ROADMAP.md`](ROADMAP.md) · [`ISSUES.md`](ISSUES.md) — planned work and known gaps
|
|
|
|
## 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 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.
|
|
|
|
### Protocol core
|
|
|
|
| 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) | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
| Function discovery / registration | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
| Codegen IR export (KDL) | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
| File uploads (`Upload` type) | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
|
|
### 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
|
|
|
|
| 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) | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
|
|
**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 -->
|
|
|
|
## 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.
|
|
|
|
## License
|
|
|
|
Mizan is licensed under the [Elastic License 2.0](LICENSE) (SPDX: `Elastic-2.0`). You
|
|
may use, copy, modify, and distribute it freely, including in commercial products you
|
|
build on top of it. You may **not** provide Mizan to third parties as a hosted or
|
|
managed service that exposes a substantial set of its features.
|