Files
mizan/ROADMAP.md
Ryth Azhur b2f990b4e5 Architecture rework: fix protocol bugs, add origin-side cache, document spec
8-expert review identified 3 bugs in shipped code (Vary header hallucination,
fn/function wire key mismatch, max-age=0 defeating PSR) — all fixed with
tests updated across Python and TypeScript.

Added: manifest version field, affects validation, wire format convention,
origin-side cache module (HMAC key derivation, MemoryCache + RedisCache
backends, reverse index for scoped invalidation, executor integration).

16 known issues documented in cache/KNOWN_ISSUES.md from expert review —
critical items (user_id not passed, purge race condition, no Redis error
handling) to be fixed in follow-up.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 22:40:55 -04:00

5.9 KiB

Mizan Roadmap

v1 — Django + React

Done

  • @client decoratorcontext=, 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 endpointGET /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 exportx-mizan-functions + x-mizan-contexts for codegen
  • Auth guardsauth=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
  • CDN-ready headersCache-Control, deterministic JSON on context GETs, no-store on mutations

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-Invalidate header.

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-Invalidate header from mutation responses to purge caches
  • Reads JSON invalidate key 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 deploy from 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: public, max-age=0, s-maxage=31536000

{
    "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"]
        }
    }
}