Skip to content

folded-runs: bound crypto-provider cache with idle TTL eviction - #529

Merged
TheGreatAxios merged 4 commits into
mainfrom
cl-7223-bound-crypto-cache
Aug 31, 2026
Merged

TheGreatAxios merged 4 commits into
mainfrom
cl-7223-bound-crypto-cache

Conversation

@TheGreatAxios

Copy link
Copy Markdown
Contributor

CL-7223

createCryptoProviderCache minted one CryptoProvider per cache key
(a workbench or instance id) in a plain Map with no eviction, so a
long-lived hub process accumulated one entry per distinct key it ever
saw, forever -- including for workbenches/instances deleted long ago.

Fix

Routes the cache through @corbits/collections' createExpiringMap
(added by CL-7233) instead of hand-rolling eviction: a 7-day idle ttl,
refreshed on every access, so a key in steady use is never evicted --
only one nobody has touched in a full week is treated as abandoned and
re-minted on next use.

Eviction-safety reasoning

The original doc comment argued against eviction because "a key going
momentarily unreachable (idle sleep, a sweep) does not mean it is gone
for good" -- rotating a signing key on every idle-sleep wake would be
wrong. An idle-refreshed ttl addresses this directly: the default
idle-sleep reap window (DEFAULT_CHAT_IDLE_REAP_MS, 30 minutes) is
far shorter than the 7-day ttl, so a normal sleep/wake cycle, or even
someone coming back to a workbench the next day, never sees a
rotation.

For the rare key that goes untouched for a full week, re-minting is
cheap (one Ed25519 keypair generation, no external registration) and
not side-effect-bearing: nothing in this codebase persists a
CryptoProvider's public key or re-checks it against an earlier value
for continuity. The one place CryptoProvider.getPublicKey() feeds a
verification decision, @intx/mailbox's fetch.ts
(verifyMessageSignature), takes its expected-signer lookup as a
caller-supplied callback and is never wired up against this cache
anywhere in this repo -- sendFoldedMail/listFoldedMail sign
outbound mail and read it back via parseMailToEmail, which never
re-verifies a signature. So a rotated key for a truly abandoned
workbench/instance has no observable effect: nothing today checks that
two messages from the same key came from the same key.

Testing

  • bun run typecheck
  • HUB_DATA_DIR=$(mktemp -d) bun test packages/folded-runs (pre-existing
    unrelated failures in launch.test.ts/credential-delivery-error.test.ts
    from a stale @intx/db export also fail identically on main)
  • bun run check:structural (all checks pass except check:report-error,
    which fails identically on main and is not wired into CI)

Route createCryptoProviderCache through @corbits/collections'
createExpiringMap instead of an unbounded Map. Each access refreshes
the entry's ttl, so a key in active use is never evicted -- only one
untouched for a full week is treated as abandoned and re-minted on
next use.

Re-minting is safe: nothing in this codebase persists or re-checks a
signing key's public half against an earlier value (the one place
CryptoProvider.getPublicKey() feeds a verification check,
@intx/mailbox's fetch.ts, is never wired to this cache), so an idle
key rotating after a week of disuse is not a correctness risk.
@TheGreatAxios
TheGreatAxios merged commit 41f39f9 into main Aug 31, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant