Summary
secretsForOpen() returns newest OTKs first, then SPKs, then .slice(0, OPEN_SECRET_CAP) (28). With OTK_POOL_CEILING (24) OTKs plus a multi-hour SPK ring, older SPK secrets can fall off the trial list. Mail sealed to an aged-but-still-retained SPK becomes silently undeliverable even though the secret is still in memory.
Relevance / residual of #15
Side effect of the #15 review fix for trial-decrypt cost. Docs still claim: “In-flight after SPK rotation | SPK ring retained 6h.” Retention is true for storage; the open walk can exclude those secrets.
Evidence
src/lib/prekeys.ts — secretsForOpen, OPEN_SECRET_CAP, OTK_POOL_CEILING
RECEIVE_KEY_RETENTION_MS ≈ 6h hourly SPK rotation → up to ~6 SPKs
PoC steps
- Load a
LocalPrekeys snapshot with 24 OTKs + 6 SPKs (oldest SPK at now - 5h).
- Seal to the oldest SPK public.
open(bob, sealed, secretsForOpen()) → null.
open(bob, sealed, allSecretsWithoutCap) → succeeds.
Done when
Trial set always includes the full retained SPK ring (cap OTKs only, or raise/partition the cap), with a regression test for aged-SPK delivery under a full OTK pool.
Summary
secretsForOpen()returns newest OTKs first, then SPKs, then.slice(0, OPEN_SECRET_CAP)(28). WithOTK_POOL_CEILING(24) OTKs plus a multi-hour SPK ring, older SPK secrets can fall off the trial list. Mail sealed to an aged-but-still-retained SPK becomes silently undeliverable even though the secret is still in memory.Relevance / residual of #15
Side effect of the #15 review fix for trial-decrypt cost. Docs still claim: “In-flight after SPK rotation | SPK ring retained 6h.” Retention is true for storage; the open walk can exclude those secrets.
Evidence
src/lib/prekeys.ts—secretsForOpen,OPEN_SECRET_CAP,OTK_POOL_CEILINGRECEIVE_KEY_RETENTION_MS≈ 6h hourly SPK rotation → up to ~6 SPKsPoC steps
LocalPrekeyssnapshot with 24 OTKs + 6 SPKs (oldest SPK atnow - 5h).open(bob, sealed, secretsForOpen())→null.open(bob, sealed, allSecretsWithoutCap)→ succeeds.Done when
Trial set always includes the full retained SPK ring (cap OTKs only, or raise/partition the cap), with a regression test for aged-SPK delivery under a full OTK pool.