Mutation responses now carry invalidation via two transports:
1. JSON body: {"result": ..., "invalidate": ["user"]}
2. HTTP header: X-Mizan-Invalidate: user, notifications
Both are set on every mutation response. The JSON body is consumed
by the client runtime (mizanCall). The header is consumed by Edge
for CDN cache purging and by XHR responses for htmx-style apps.
Header format: comma-separated contexts, semicolon-separated params.
X-Mizan-Invalidate: user;user_id=5, notifications
Also: _resolve_invalidation and _format_invalidate_header extracted
as reusable helpers for when return-type branching adds HttpResponse
support (view-path mutations will only use the header transport).
Updated ROADMAP.md with full v1 plan including both transports,
return-type branching, affects_params, and Edge manifest.
270 Django tests pass.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Mutation responses now include invalidation directives from the server:
POST /api/mizan/call/
→ {"result": {...}, "invalidate": ["user"]}
The client never hardcodes invalidation targets. The server resolves
affects= metadata and returns what to invalidate. mizan-runtime reads
the invalidate key and triggers refetches automatically.
Context fetch returns raw bundled data (not wrapped):
GET /api/mizan/ctx/user/?user_id=5
→ {"user_profile": {...}, "user_orders": [...]}
Also fixed QueryDict handling (use .dict() not dict() to avoid
list-wrapped values).
267 Django tests pass.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
packages/
mizan-runtime/ Framework-agnostic state engine (~150 lines)
Context registry, batched invalidation, fetch primitives
mizan-django/ Django server adapter (was packages/mizan-rpc/adapters/django/)
Codegen moved to mizan-django/generate/
mizan-react/ React adapter (was packages/mizan-csr/adapters/react/)
Removed premature abstractions: mizan-ast, mizan-schema, mizan-rpc,
mizan-csr, mizan-ssr stub packages. The actual architecture is three
concrete packages, not five abstract layers.
mizan-runtime implements the v1 spec: registerContext with params,
scoped invalidation via microtask batching, server-driven invalidation
from mutation responses, mizanFetch for context bundles, mizanCall for
mutations.
264 Django + 33 React tests pass.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Mizan is an Application Framework Interface (AFI) with five
independent packages:
packages/
mizan-ast/ Language layer (source → KDL schema)
mizan-schema/ IR layer (KDL schema definition)
mizan-rpc/ Protocol layer (client gen + server adapters)
adapters/django/ ← was django/
generator/ ← was react/src/generator/
mizan-csr/ State layer (client state engine)
adapters/react/ ← was react/
mizan-ssr/ Rendering layer (server-side rendering)
Each package is independent. The adapter directories contain the
framework-specific implementations. Stub packages (ast, schema, ssr)
establish the structure for future work.
264 Django tests + 33 React tests pass from new locations.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>