Closes #157 (HIGH: silent backup-data loss, no attacker).
Prune finds in-use blobs by reading every snapshot's manifest. A manifest it could not download or decode was logged and skipped, so blobs referenced only by that snapshot looked unreferenced and were deleted — and the command still exited 0, while snapshot create --prune runs it unattended with force. collectReferencedBlobs now returns an error naming the remote key; PruneBlobs propagates it, so prune deletes nothing and exits non-zero.
Three related integrity gaps from the same issue are closed too:
Manifest generation logged and skipped a blob whose lookup failed or returned no row, producing a manifest shorter than the snapshot needs (that blob would be pruned next cycle). It now fails instead.
Deep verify treated the database as authoritative and only warned when the manifest omitted a database blob. It now fails on any divergence.
docs/REPOSTRUCTURE.md described a latest-local vs latest-remote comparison that does not exist; corrected to the real behavior (keeps manifests' blobs, deletes nothing if any manifest is unreadable, needs exclusive access during backups).
Tests: prune deletes nothing and errors on an undecodable manifest; manifest generation errors on a missing blob; deep verify fails when the manifest omits a database blob.
Judgement call: implemented the issue's full four-item Definition of Done, not only the two prune/manifest fixes the brief emphasized.
Model: opus-4-8
Closes https://git.eeqj.de/sneak/vaultik/issues/157 (HIGH: silent backup-data loss, no attacker).
Prune finds in-use blobs by reading every snapshot's manifest. A manifest it could not download or decode was logged and skipped, so blobs referenced only by that snapshot looked unreferenced and were deleted — and the command still exited 0, while `snapshot create --prune` runs it unattended with force. `collectReferencedBlobs` now returns an error naming the remote key; `PruneBlobs` propagates it, so prune deletes nothing and exits non-zero.
Three related integrity gaps from the same issue are closed too:
- Manifest generation logged and skipped a blob whose lookup failed or returned no row, producing a manifest shorter than the snapshot needs (that blob would be pruned next cycle). It now fails instead.
- Deep verify treated the database as authoritative and only warned when the manifest omitted a database blob. It now fails on any divergence.
- `docs/REPOSTRUCTURE.md` described a latest-local vs latest-remote comparison that does not exist; corrected to the real behavior (keeps manifests' blobs, deletes nothing if any manifest is unreadable, needs exclusive access during backups).
Tests: prune deletes nothing and errors on an undecodable manifest; manifest generation errors on a missing blob; deep verify fails when the manifest omits a database blob.
Judgement call: implemented the issue's full four-item Definition of Done, not only the two prune/manifest fixes the brief emphasized.
Model: opus-4-8
Prune learned which blobs are in use by reading every snapshot's
manifest, but merely logged and skipped one it could not download or
decode. Blobs referenced only by that snapshot then looked unreferenced
and were deleted, with a zero exit — and `snapshot create --prune` runs
this unattended. collectReferencedBlobs now errors, naming the remote
key, so prune deletes nothing and exits non-zero.
Manifest generation likewise skipped a blob whose lookup failed or was
missing, yielding a manifest short of what the snapshot needs; it now
fails. Deep verify only warned when the manifest omitted a database
blob; it now fails on any divergence. Docs corrected.
Model: opus-4-8
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Closes #157 (HIGH: silent backup-data loss, no attacker).
Prune finds in-use blobs by reading every snapshot's manifest. A manifest it could not download or decode was logged and skipped, so blobs referenced only by that snapshot looked unreferenced and were deleted — and the command still exited 0, while
snapshot create --pruneruns it unattended with force.collectReferencedBlobsnow returns an error naming the remote key;PruneBlobspropagates it, so prune deletes nothing and exits non-zero.Three related integrity gaps from the same issue are closed too:
docs/REPOSTRUCTURE.mddescribed a latest-local vs latest-remote comparison that does not exist; corrected to the real behavior (keeps manifests' blobs, deletes nothing if any manifest is unreadable, needs exclusive access during backups).Tests: prune deletes nothing and errors on an undecodable manifest; manifest generation errors on a missing blob; deep verify fails when the manifest omits a database blob.
Judgement call: implemented the issue's full four-item Definition of Done, not only the two prune/manifest fixes the brief emphasized.
Model: opus-4-8
PASS
Model: opus-4-8