Mizan's protocol layers (origin Redis cache, Edge Worker) handle caching
autonomously. The origin emits Cache-Control: no-store on ALL responses —
browsers and non-Mizan intermediaries must not cache. The Edge Worker
controls CDN caching via cf object, independent of origin headers.
Also fixes:
- TS localeCompare → byte-order sort (localeCompare is locale-sensitive,
would produce different HMAC keys for non-ASCII params vs Python)
- Python cache_purge: empty {} params no longer treated as falsy
(was inconsistent with JS where {} is truthy)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
5.8 KiB
Mizan Roadmap
v1 — Django + React
Done
- @client decorator —
context=,affects=,auth=,websocket= - ReactContext class — type-safe context/affects references with linting
- Named contexts — functions sharing a context name are grouped into one provider and one fetch
- Context bundling endpoint —
GET /api/mizan/ctx/<name>/returns all functions in one response - Server-driven invalidation (JSON body) — mutation responses carry
{"result": ..., "invalidate": [...]} - Scoped invalidation — runtime supports
invalidate: [{context: "user", params: {user_id: 5}}] - Param elevation — shared params become required provider props, non-shared become optional
- Schema export —
x-mizan-functions+x-mizan-contextsfor codegen - Auth guards —
auth=True,auth='staff',auth='superuser',auth=callable - JWT + session auth — auto-detected, CSRF handled
- Shapes — Pydantic + django-readers for typed query projections
- WebSocket channels — real-time bidirectional communication
- Codegen — generates typed React providers, hooks, mutations from schema
- Protocol-managed caching —
no-storeon all origin responses, deterministic JSON on context GETs
Next: X-Mizan-Invalidate Header
Second invalidation transport. For view responses (redirects, HTML), invalidation goes in an HTTP header instead of the JSON body. Both transports are first-class AFI spec.
- Header format:
X-Mizan-Invalidate: user;user_id=5, notifications - Comma-separated contexts, semicolon-separated params per context
- Decorator auto-adds header to any HttpResponse with
affects= - Edge reads this header to purge cached pages
- Runtime also reads it on XHR/fetch responses (htmx path)
Next: Return-Type Branching
@client serves both RPC developers (React/SPA) and view developers (htmx/templates). Return type determines behavior:
- Data return (dict, Shape, BaseModel) → RPC path. Generates typed hooks. Invalidation in JSON body.
- HttpResponse return (render, redirect) → View path. No codegen. Invalidation in
X-Mizan-Invalidateheader.
Same decorator. Same affects=. Same invalidation graph. Two paths.
Next: affects_params
Scoped invalidation with a lambda that extracts which params were affected:
@client(affects='user', affects_params=lambda req: {'user_id': req.user.pk})
def update_name(request, name: str) -> dict:
...
Produces invalidate: [{context: "user", params: {user_id: 5}}] in JSON body or X-Mizan-Invalidate: user;user_id=5 in header.
Next: Edge Manifest
mizan-generate --manifest compiles the decorator registry + Django URL conf into static JSON for Edge:
{
"contexts": {
"user": {
"endpoints": ["/api/mizan/ctx/user/"],
"views": ["/profile/:user_id/"],
"params": ["user_id"]
}
}
}
Edge reads the manifest at deploy time. When it receives X-Mizan-Invalidate: user;user_id=5, it resolves URL patterns with params and purges /profile/5/ and /api/mizan/ctx/user/?user_id=5.
Generated alongside React code. Covers both RPC and view-path functions.
Next: Codegen Rewrite
Generated code uses the runtime directly (mizanFetch, mizanCall, registerContext) instead of the legacy MizanProvider pattern. Mutations have zero invalidation knowledge — the runtime reads the server response.
Next: SSR Bridge
Django renders React components server-side via a persistent Bun subprocess.
- Bun worker: stdin/stdout JSON-RPC,
renderToString, component registry - Django bridge: subprocess management, IPC, request synthesis
- Template tag:
{% mizan_render "ProfilePage" user_profile=profile %} - Hydration:
window.__MIZAN_SSR_DATA__consumed by generated providers - Generated contexts check SSR data before first fetch
Mizan Cloud (closed-source)
Mizan Edge
Cloudflare Workers for automatic edge caching.
- Reads the Edge manifest to configure cache rules
- Context GETs cached at edge, keyed by context name + params
- Reads
X-Mizan-Invalidateheader from mutation responses to purge caches - Reads JSON
invalidatekey from RPC responses for the same purpose - Resolves URL patterns from manifest to purge view pages
- Zero configuration — the manifest IS the cache policy
Mizan Render
SSR at the edge via Cloudflare Workers.
- The Bun SSR bridge, running on Cloudflare instead of colocated with Django
- Context data fetched from Django (or edge cache), rendered at the edge
- HTML response streamed to the user from the nearest PoP
Mizan Deploy
One-command deployment for Django + React apps.
- Container orchestration (AWS/Azure)
- Edge + Render auto-configured
mizan deployfrom the CLI- The Vercel experience for Django
Protocol Spec (AFI)
The protocol is the product. Two invalidation transports. Every endpoint CDN-ready.
Context fetch
GET /api/mizan/ctx/<name>/?param=value
200 OK
Cache-Control: no-store
{
"function_a": { ... },
"function_b": [ ... ]
}
Mutation call (RPC path — JSON body transport)
POST /api/mizan/call/
Cache-Control: no-store
{
"result": { ... },
"invalidate": ["context_name"]
}
Mutation call (View path — header transport)
POST /profile/update/
302 Found
Location: /profile/5/
Cache-Control: no-store
X-Mizan-Invalidate: user;user_id=5, notifications
Scoped invalidation (JSON)
{
"result": { ... },
"invalidate": [
"notifications",
{ "context": "user", "params": { "user_id": 5 } }
]
}
Scoped invalidation (Header)
X-Mizan-Invalidate: user;user_id=5, notifications
Edge manifest
{
"contexts": {
"user": {
"endpoints": ["/api/mizan/ctx/user/"],
"views": ["/profile/:user_id/"],
"params": ["user_id"]
}
}
}