MIZAN.md's phase-numbered implementation order, PRODUCT_ARCHITECTURE's "Deferred until Render revenue funds it" and "Shipped in", PSR_VS_EDGE's current-state section, and the READMEs' passing-test counts were all reporting where the work stood rather than what the system is. OWED_SURFACE keeps its subject — surface that is specified but unbuilt — stated as the shape each unit owes. The channel sections follow the renamed slots: Params / ClientMessage / ServerMessage, and Channel as the base class on both backends. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2.7 KiB
Cache Keying
What cache keying is for
Mizan's invalidation surface names which entries die. Cache keying names which entry is which. A key that does not separate User A's content from User B's turns Edge caching into a security vulnerability — it serves one user's content to another.
Why Vary is not the mechanism
All major CDNs ignore Vary for personalized content, and no
standardized replacement exists. The key itself carries identity.
HMAC cache key (JSON-canonical form)
ctx:{context}:HMAC-SHA256(secret, json.dumps({
"c": context,
"p": sorted_params, // values normalized to JSON-native strings
"r": rev,
"u": user_id // omitted for public content
}, sort_keys=True, separators=(",", ":")))
derive_cache_key(secret, context, params, user_id=None, rev=0) →
"ctx:{context}:{hmac_hex}". The ctx:{context}: prefix lets broad
purge SCAN by prefix. Param values are normalized for cross-language
consistency (True→"true", None→"null") before stringification.
The derivation lives in
cores/mizan-python/src/mizan_core/cache/keys.py and
backends/mizan-ts/src/cache/keys.ts (deriveCacheKey); pinned
vectors hold the two outputs byte-identical.
Key derivation rules
- Public content — URL path + query params (standard CDN).
- User-scoped content — HMAC key derivation above.
@client(auth=...)determines whether content is user-scoped.revparameter on@clientfor deploy-time logic invalidation. Bumped by the developer when function logic changes.
Identity layer
MWT (Mizan Web Token) — see MWT_SPEC.md. JWT with
Mizan claims on X-Mizan-Token header.
Cache architecture
Not a compiled binary ABI. Not a pluggable Python protocol.
Each backend adapter (Python, TypeScript, PHP, C#, Go) implements the cache protocol in its own language. Conformance is verified by a shared test suite, so the implementations cannot drift apart silently.
Required operations
cache_getcache_putcache_purge(scoped recomputes the key; broad SCANs thectx:{context}:*prefix)
Storage
Two backends behind a CacheBackend protocol
(mizan_core/cache/backend.py):
MemoryCache— dict-based, for testing.RedisCache— production; persistence, cross-worker sharing, crash recovery. Broad purge via SCAN, delete via UNLINK.
Deploy invalidation
No full context flush. The rev parameter on @client is part of
the HMAC key. When the developer bumps rev, old cache entries
become unreachable orphans. No purge needed; no thundering herd.
Invariant
All cache-related code implements identical HMAC key derivation. Cross-language conformance tests enforce this. Any divergence is a security vulnerability.