The key new frames are sealed with, plus the retired keys old frames still need.
A rotation cannot re-seal the whole store, so the store holds several generations at once.
Re-sealing every frame means reading, decrypting, re-encrypting and re-uploading every byte of
history, which for a site with a year of files is hours of work and a full month's request budget.
So a rotation changes which key SEALS and leaves what is already sealed alone; the retired keys stay
on the ring for as long as any frame still needs one.
The frame format carries no key fingerprint, and that is what makes a ring necessary rather
than optional. A frame records the cipher id, not which key sealed it, so the only way to find the
right key is to try them. The cost is one failed AEAD open per stale key per frame, and AEAD runs
at 392 MB/s, so a ring of two or three keys is not measurable next to the network.
The honest limitation. When no key on the ring opens a frame, that is indistinguishable from
the bytes being corrupt - a wrong key and a flipped bit both fail the Poly1305 tag. So a frame that
no key opens is reported as unreadable, never as "sealed under a key you have lost", because
nothing here can tell those apart.
Order matters: the active key is tried first, so the common case costs one open and the retired
keys are only reached for frames that predate the rotation.
Each one costs a failed open on every frame that predates it, so a ring that grew without bound
would make the oldest frames the most expensive to read. A site needing more generations than
this has not finished a rotation it started.
The order a caller must try them in: the active key opens everything written since the last
rotation, which on any site that has been running is nearly everything.