Updates
Probe caches key on token fingerprints and are bounded (issue #910)WRITABLE_ENRICHMENT_CACHE and _ENRICHMENT_OPTION_CACHE — the process-level
caches behind the select-schema drift guard (#914) — were keyed by
(token, slug) with the raw workspace API token in the key, mirroring
preflight._owner_member_cache. In a long-lived process (Modal webhook
handlers) serving many workspaces that left two problems: the raw API token
of every workspace served was copied into a second, unbounded-lifetime dict
outside any key-scope lifecycle and never evicted, and nothing capped either
dict, so distinct (token, slug) pairs accumulated forever. Low severity on
its own — guard behavior was correct — but cheap to close.
Both caches now key on (token_fingerprint, slug) where the fingerprint is
hashlib.sha256(token.encode("utf-8")).hexdigest() — non-reversible, with the
unresolved-token bucket keeping its own non-hex sentinel key so it can never
collide with the digest of a real workspace. Per-workspace separation is
preserved: distinct tokens still hash to distinct buckets, so the schema of
one workspace continues to never govern the writes of another. Both caches
cap at 256 entries with FIFO eviction past the cap — probes carry no recency
signal worth LRU tracking, and the cap exists to bound memory across
workspaces, not to optimize hit rate. This composes with the #911 TTL
entries: eviction swaps whole (value, expires_at) pairs, so a capped cache
never serves an expired verdict as fresh, and the drift-shaped invalidation
paths are untouched.