Files
mizan/ROADMAP.md
Ryth Azhur e5f8fafc01 Remove CDN Cache-Control headers; fix cross-language sort bug
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>
2026-04-07 01:38:24 -04:00

5.8 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
  • Protocol-managed cachingno-store on 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-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: 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"]
        }
    }
}