Golden backups
One disaster-recovery backup file per release, written by that release's own
exporter, and a manifest of what it held. tests/integration/golden-backups.test.ts
uploads every file here through the admin upload route, restores it into an
empty account through the restore route and job, exports the account again and
checks the counts section by section against the manifest. A backup a person
downloaded from an older release has to keep restoring after every later
change; this is where that is held still.
| File | What it is |
|---|---|
v<release>.json |
the file exactly as the exporter wrote it (compact JSON, never reformatted) |
v<release>.manifest.json |
release, schema version, owner id, exportedAt, SHA-256, byte size, counts |
The account is the shared backup seed (tests/integration/backup-fixture.ts:
one row of every two-ended model plus the column shapes), so every section the
backup writes holds at least one row. Ciphertext inside the file is sealed
under the integration suite's fixed key (ENCRYPTION_KEY in
vitest.integration.config.mts), so the file opens on every machine that runs
the suite and no real key is involved.
Adding the next release's file
Once per release, on the release branch after the version bump, with Docker running:
GOLDEN_BACKUP_WRITE=1 pnpm vitest run --config vitest.integration.config.mts tests/integration/golden-backups.test.ts
pnpm vitest run --config vitest.integration.config.mts tests/integration/golden-backups.test.ts
The first command writes v<version from package.json>.json and its manifest;
the second restores every file here, the new one included. Commit both files.
Never rewrite an existing release's file: the test checks each file against the SHA-256 in its manifest, because a file regenerated by today's exporter would prove only that today's exporter and today's restore agree. When a change means an old file can no longer restore as it was written, that is a breaking change to the backup format, and it is decided in the restore code, not by replacing the fixture.
A count the restore is documented to drop by age (a measurement tombstone past
its retention) is listed in AGES_OUT in the test and may only go down.