Add TypeScript cache adapter with cross-language conformance tests

Port of Python's origin-side cache to TypeScript:
- cache/keys.ts: deriveCacheKey with stableStringify for JSON-canonical HMAC
- cache/backend.ts: MemoryCache (same API as Python)
- cache/index.ts: cacheGet, cachePut, cachePurge with AND semantics

Integrated into dispatch.ts:
- handleContextFetch: cache lookup before execution, store after
- handleMutationCall: purge on invalidation

Cross-language pin test proves Python and TypeScript produce identical
HMAC-SHA256 output for the same inputs:
  Public:      605a1ca5ad5994e9b765c8d1b330474c2a0d51a7b8fbbdc402f992da7ba902f6
  User-scoped: 30fc08eb46ee4ff2cf7d317e97dca90fd616511e0587304416f71dc863338dc2

34 TypeScript tests (9 new), 165 Python tests (1 new pin test).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-07 01:03:24 -04:00
parent 54581d184f
commit 4744ff052e
7 changed files with 474 additions and 1 deletions

View File

@@ -2841,6 +2841,26 @@ class CacheKeyDerivationTests(TestCase):
scoped = derive_cache_key(self.SECRET, "products", {"id": "1"}, user_id="5")
self.assertNotEqual(public, scoped)
def test_cross_language_pin(self):
"""Pinned HMAC values — must match TypeScript adapter exactly."""
from mizan.cache.keys import derive_cache_key
pin_secret = "test-pin-secret-that-is-32bytes!"
public_key = derive_cache_key(pin_secret, "user", {"user_id": "5"}, rev=0)
self.assertEqual(
public_key,
"605a1ca5ad5994e9b765c8d1b330474c2a0d51a7b8fbbdc402f992da7ba902f6",
)
user_scoped_key = derive_cache_key(
pin_secret, "user", {"user_id": "5"}, user_id="5", rev=0,
)
self.assertEqual(
user_scoped_key,
"30fc08eb46ee4ff2cf7d317e97dca90fd616511e0587304416f71dc863338dc2",
)
class CacheBackendTests(TestCase):
"""Tests for MemoryCache backend operations."""