The event-DB sweep marker is monotonic and trusts itself, so a downgrade re-leaks target rows permanently #238
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Raised during the third review of #223, which closes #206 by sweeping leaked
targetsrows out of each per-webhook event DB and recording the sweep in the file'suser_version.The sweep is gated on that marker:
user_version >= 1means swept, and the open returns immediately without looking at the file's contents.The failure sequence:
events-{uuid}.db, deletes the leakedtargetsrows, vacuums, stampsuser_version = 1.DATA_DIR. It has no association-omitting callback, so it writestargetsrows — with plaintext credential-bearingconfig— back into a file that is already marked as swept.The old
RowsAffected > 0gate would have caught this, because it inspected the file rather than a marker. The marker is what fixed the round-2 self-healing defect, so this is a genuine trade rather than a regression to undo.Why this is not milestoned: the README's Downgrading section already declares running an older binary against a newer
DATA_DIRunsupported, and names silent divergence as the consequence. This is an instance of exactly that documented hazard. Recording it so the trade is explicit rather than accidental.Possible remedy, noted as partial: a
SELECT count(*) FROM targetseven on marked files would catch re-leaked ROWS at trivial cost — one cheap query per open. It would NOT catch recoverable BYTES, since those need the vacuum, and it does not detect a downgrade that wrote rows and then had them deleted by something else. So it narrows the window rather than closing it.Definition of done (if taken):
targetsrows into a file already atuser_version = 1and asserts the next open removes them and re-vacuums