mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 04:32:42 +00:00
Key rotation re-sealed a single-value backup in place, which holds the stored string, its bytes, the plaintext and the new ciphertext at once; a copy can be over a hundred megabytes and the in-app rotation walked 25 of them per page, enough to run a 1 GB container out of memory. Rotation now converts each such copy into pieces under the active key instead, one row at a time. The ~hlgcm1. stream of v1.38.6 to v1.39.1 is read a megabyte at a time with its tag checked at the end, inside one transaction, so a copy that fails the check is left untouched; the copy keeps its date. The scan reads only the first characters of each value. Measured on a copy of a 2.6 million-reading account (126 MB stored): converted in 25 s with the heap flat at 57 MB under a 200 MB limit, where re-sealing in place ran out of heap. The weekly and manual backup leave an account alone while a restore of its current copy is queued or running, and count it as skipped, not failed. A reader whose copy is replaced mid-read answers 409 backup_changed, "replaced by a newer one while it was being read", rather than the undecryptable error; a restore rolls back with the same code. Pieces are sealed with a fixed associated-data label, so a value the same key sealed for another purpose never opens as a piece; rotation re-seals under the same label. A row holding both a single value and pieces, which only an older release writing after a downgrade produces, is refused with a message saying so, and the next weekly run replaces it. Rotation treats a row deleted between its read and its write as gone rather than an error.
2.5 MiB
2.5 MiB