1 Commits
Author SHA1 Message Date
sneak cf2f085e80 Record the defect-hunt fixes in TODO.md Completed Steps (closes #334)
check / check (push) Canceled after 0s
Adds a Completed Steps entry, newest first, for every issue from the
defect hunt (#288) that a merged
fix closed and that had none: the hunt's own issues, those filed while
fixing them, and the owner's ruling on
#239. Each entry says only what
its fix changed, as checked against that fix's commit and the code on
`next`. Next Step now says the hunt's fixes have landed.

Judgement call: #332, closed as
covered by the fix for #296, is
named in that entry rather than given its own.
Judgement call: #351, a Docker
build fix filed while gating these fixes, gets an entry.

Model: opus-5-5
2026-10-14 06:35:05 +00:00
+44 -40
View File
@@ -38,10 +38,11 @@ owner's; a `v*` tag runs the release build in
it skips anything it cannot read it skips anything it cannot read
([issue #310](https://git.eeqj.de/sneak/vaultik/issues/310)). The run ([issue #310](https://git.eeqj.de/sneak/vaultik/issues/310)). The run
printed its skip errors, then `Finished successfully.`, and exited 0, printed its skip errors, then `Finished successfully.`, and exited 0,
so a cron wrapper could not tell it from a complete backup. Each so a cron wrapper could not tell it from a complete backup. Such a
skipped entry, a directory the walk could not list included, is now run now keeps its snapshots and then fails with
counted as failed, and the run keeps its snapshots and then fails with `Backup completed, but N file(s) could not be read`, and an entry the
`Backup completed, but N file(s) could not be read`. walk could not read, such as a directory it could not list, now
counts as failed too.
- 2026-10-14: Kept the local index when `remote nuke` cannot list or - 2026-10-14: Kept the local index when `remote nuke` cannot list or
find the destination store find the destination store
@@ -61,10 +62,10 @@ owner's; a `v*` tag runs the release build in
backup queued every directory and symlink to be backed up, so the backup queued every directory and symlink to be backed up, so the
line ending the walk counted directories and their sizes as files and line ending the walk counted directories and their sizes as files and
data to back up while its enumerated count left them out, and every data to back up while its enumerated count left them out, and every
symlink was reported as backed up on every run. Directories are now symlink was reported as backed up on every run. Directories are no
recorded apart and never counted as files or data, and a symlink is longer counted as files or data to back up, and a symlink is compared
compared with its record like a regular file, so an unchanged one with its record like a regular file, so an unchanged one counts as
counts as unchanged. unchanged.
- 2026-10-14: Refused a backup destination that an unplugged volume - 2026-10-14: Refused a backup destination that an unplugged volume
left empty, as the owner ruled left empty, as the owner ruled
@@ -73,18 +74,19 @@ owner's; a `v*` tag runs the release build in
as an empty store, so `prune` dropped every local snapshot record, and as an empty store, so `prune` dropped every local snapshot record, and
`snapshot create` wrote a whole backup to the internal disk under the `snapshot create` wrote a whole backup to the internal disk under the
empty mount point. Every backup now writes `vaultik-destination.txt` empty mount point. Every backup now writes `vaultik-destination.txt`
at the destination root, and while the local index holds snapshots, a at the destination root, and while the local index holds snapshots
destination without it is treated as not present: `snapshot create` stored there, a destination without it is treated as not present:
refuses before writing, and `prune` deletes nothing. The `file://` `snapshot create` refuses before writing, and `prune` deletes
backend also never creates its destination directory. nothing. The `file://` backend also never creates its destination
directory.
- 2026-10-14: Warned about restored ownership only when an entry's - 2026-10-14: Warned about restored ownership only when an entry's
owner or group differs owner or group differs
([issue #316](https://git.eeqj.de/sneak/vaultik/issues/316)). Every ([issue #316](https://git.eeqj.de/sneak/vaultik/issues/316)). A
restore by a normal user warned that file ownership was not preserved, restore by a normal user warned that file ownership was not preserved
even when every entry came out with its recorded owner and group. The even when every entry came out with its recorded owner and group. The
owner and group each restored entry has on disk are now compared with owner and group the restored entries have on disk are now compared
the recorded ones, and the warning is printed once if any differ. with the recorded ones, and the warning is printed once if any differ.
- 2026-10-14: Made `snapshot list` report a changed destination instead - 2026-10-14: Made `snapshot list` report a changed destination instead
of advising `prune` of advising `prune`
@@ -108,9 +110,9 @@ owner's; a `v*` tag runs the release build in
- 2026-10-14: Named each prefix once in restore, verify and purge errors - 2026-10-14: Named each prefix once in restore, verify and purge errors
([issue #327](https://git.eeqj.de/sneak/vaultik/issues/327)). A ([issue #327](https://git.eeqj.de/sneak/vaultik/issues/327)). A
missing blob during restore, a failed shallow verify and an invalid missing blob during restore, a failed shallow verify and an invalid
purge duration each printed their prefix twice, and deep verify named purge duration each printed their prefix twice, and a deep verify log
S3 whatever the destination. Each prefix now appears once, and deep line named S3 whatever the destination. Each prefix now appears once,
verify no longer names S3. and that log line names storage instead.
- 2026-10-14: Refused credentials in a storage URL's endpoint or rclone - 2026-10-14: Refused credentials in a storage URL's endpoint or rclone
remote name remote name
@@ -118,7 +120,8 @@ owner's; a `v*` tag runs the release build in
inside the `endpoint=` value of an `s3://` URL, and rclone inside the `endpoint=` value of an `s3://` URL, and rclone
`remote,param=value` parameters, were accepted and then printed by `remote,param=value` parameters, were accepted and then printed by
`info`, `remote info` and `snapshot create`. Both are now refused `info`, `remote info` and `snapshot create`. Both are now refused
without echoing the value, as is a query that cannot be decoded. without echoing the value, as is an `s3://` or `rclone://` query that
cannot be decoded.
- 2026-10-14: Ran `$EDITOR` through the shell in `config edit` - 2026-10-14: Ran `$EDITOR` through the shell in `config edit`
([issue #315](https://git.eeqj.de/sneak/vaultik/issues/315)). The ([issue #315](https://git.eeqj.de/sneak/vaultik/issues/315)). The
@@ -140,8 +143,8 @@ owner's; a `v*` tag runs the release build in
each backup as totals each backup as totals
([issue #306](https://git.eeqj.de/sneak/vaultik/issues/306)). Each ([issue #306](https://git.eeqj.de/sneak/vaultik/issues/306)). Each
removed count was followed by `(N remain)`, which read as incomplete removed count was followed by `(N remain)`, which read as incomplete
or orphaned rows left over but was every snapshot, file, chunk or blob or orphaned rows left over but counted every snapshot, file, chunk or
left in the local index, so removing the only incomplete snapshot blob left in the local index, so removing the only incomplete snapshot
printed `1 removed (1 remain)`. Each line now names that figure as the printed `1 removed (1 remain)`. Each line now names that figure as the
total left in the local index. total left in the local index.
@@ -149,9 +152,9 @@ owner's; a `v*` tag runs the release build in
it ([issue #324](https://git.eeqj.de/sneak/vaultik/issues/324)). A it ([issue #324](https://git.eeqj.de/sneak/vaultik/issues/324)). A
blob was freed only once every file in the snapshot that uses it had blob was freed only once every file in the snapshot that uses it had
been restored, which a file outside the selected paths, or one that been restored, which a file outside the selected paths, or one that
failed under `--skip-errors`, never is, so such a restore kept that failed under `--skip-errors`, never is, so such a restore kept those
file's blobs in the temporary cache until it ended. A cached blob is blobs in the temporary cache until it ended. A cached blob is now
now freed as soon as no file still pending in this restore uses it. freed once no file still pending in this restore uses it.
- 2026-10-13: Kept the whole startup error when it contains `): ` - 2026-10-13: Kept the whole startup error when it contains `): `
([issue #320](https://git.eeqj.de/sneak/vaultik/issues/320)). A ([issue #320](https://git.eeqj.de/sneak/vaultik/issues/320)). A
@@ -234,17 +237,18 @@ owner's; a `v*` tag runs the release build in
directory directory
([issue #296](https://git.eeqj.de/sneak/vaultik/issues/296)). The ([issue #296](https://git.eeqj.de/sneak/vaultik/issues/296)). The
listing did not follow a symlinked `metadata/` or `blobs/`, while listing did not follow a symlinked `metadata/` or `blobs/`, while
reads and writes did, so the store listed as empty and `prune` dropped reads and writes did, so what was behind the link listed as empty;
the local snapshot records and deleted every blob. The listings now with `metadata/` linked, `prune` then dropped the local snapshot
read through such a link, and fail when its target is missing records and deleted every blob. The listings now read through such a
link, and fail when its target is missing
([issue #332](https://git.eeqj.de/sneak/vaultik/issues/332)). ([issue #332](https://git.eeqj.de/sneak/vaultik/issues/332)).
- 2026-10-13: Made `snapshot verify --deep --json` report its blob - 2026-10-13: Made `snapshot verify --deep --json` report its blob
counts ([issue #314](https://git.eeqj.de/sneak/vaultik/issues/314)). counts ([issue #314](https://git.eeqj.de/sneak/vaultik/issues/314)).
Deep verify set `verified` only on success and never set `missing`, Deep verify set `verified` only on success and never set `missing`,
so a failed run reported 0 for both. It now counts each blob whose so a failed run reported 0 for both. It now counts each blob whose
contents pass, and first checks every blob's presence and size, contents pass, and before reading any, counts missing and wrong-size
counting missing and wrong-size blobs as shallow verify does. blobs as shallow verify does.
- 2026-10-13: Limited and retried the module download in the Docker - 2026-10-13: Limited and retried the module download in the Docker
build ([issue #351](https://git.eeqj.de/sneak/vaultik/issues/351)). build ([issue #351](https://git.eeqj.de/sneak/vaultik/issues/351)).
@@ -276,7 +280,7 @@ owner's; a `v*` tag runs the release build in
- 2026-10-13: Recorded the stored size of a blob a backup finds already - 2026-10-13: Recorded the stored size of a blob a backup finds already
stored ([issue #300](https://git.eeqj.de/sneak/vaultik/issues/300)). stored ([issue #300](https://git.eeqj.de/sneak/vaultik/issues/300)).
The upload was skipped, but the local index and the manifest kept the The upload was skipped, but the local index and the manifest kept the
size of the local copy, which differs from the stored object once size of the local copy, which can differ from the stored object when
`compression_level` or the recipients changed, so `snapshot verify` `compression_level` or the recipients changed, so `snapshot verify`
failed on a good snapshot. The size the destination store reports for failed on a good snapshot. The size the destination store reports for
the existing object is now recorded. the existing object is now recorded.
@@ -285,7 +289,7 @@ owner's; a `v*` tag runs the release build in
the process on a rollback after Ctrl-C, a failed close of query the process on a rollback after Ctrl-C, a failed close of query
results, or a failed temp file cleanup results, or a failed temp file cleanup
([issue #345](https://git.eeqj.de/sneak/vaultik/issues/345)). Each ([issue #345](https://git.eeqj.de/sneak/vaultik/issues/345)). Each
exited at once with a fatal log line and skipped the run's cleanup. ended the process at once and skipped the run's cleanup.
Read-only transactions now handle the rollback as other transactions Read-only transactions now handle the rollback as other transactions
do, the query functions report a close failure through the error they do, the query functions report a close failure through the error they
already return, and a failed close or removal of a blob temp file already return, and a failed close or removal of a blob temp file
@@ -313,7 +317,8 @@ owner's; a `v*` tag runs the release build in
listing page marked truncated but carrying no continuation token listing page marked truncated but carrying no continuation token
ended the listing without an error, so `prune` saw only the snapshots ended the listing without an error, so `prune` saw only the snapshots
on the first page and treated the blobs of the rest as unreferenced. on the first page and treated the blobs of the rest as unreferenced.
Such a page now fails the listing, and `prune` deletes nothing. Such a page now fails the listing, so `prune` stops before deleting
any blob.
- 2026-10-13: Made shallow `snapshot verify` report a blob it could not - 2026-10-13: Made shallow `snapshot verify` report a blob it could not
check apart from a missing one check apart from a missing one
@@ -329,8 +334,7 @@ owner's; a `v*` tag runs the release build in
([issue #326](https://git.eeqj.de/sneak/vaultik/issues/326)). Restore ([issue #326](https://git.eeqj.de/sneak/vaultik/issues/326)). Restore
planning stopped at the first such file, before the flag could skip planning stopped at the first such file, before the flag could skip
it, so nothing was restored. That file now fails like any other file it, so nothing was restored. That file now fails like any other file
that cannot be restored, skipped under the flag while every other that cannot be restored: skipped under the flag, and fatal without it.
file is restored, and fatal without it.
- 2026-10-13: Recorded each snapshot's new chunk size when its backup - 2026-10-13: Recorded each snapshot's new chunk size when its backup
runs ([issue #311](https://git.eeqj.de/sneak/vaultik/issues/311)). runs ([issue #311](https://git.eeqj.de/sneak/vaultik/issues/311)).
@@ -354,10 +358,10 @@ owner's; a `v*` tag runs the release build in
- 2026-10-13: Printed `snapshot list` and `snapshot purge` sizes like - 2026-10-13: Printed `snapshot list` and `snapshot purge` sizes like
every other command every other command
([issue #312](https://git.eeqj.de/sneak/vaultik/issues/312)). They, ([issue #312](https://git.eeqj.de/sneak/vaultik/issues/312)). They,
and the byte values in terminal log lines, divided by 1024 but and the `bytes` value in terminal log lines, divided by 1024 but
labelled the result KB or MB, so 6,329,198 bytes read 6.0 MB there and labelled the result KB or MB, so 6,329,198 bytes read 6.0 MB there and
6.3 MB everywhere else. All three now use the 1000-based units of the 6.3 MB in other commands. All three now use 1000-based units, as other
rest of the program. commands do.
- 2026-10-13: Stopped a stalled blob read when restore or deep verify - 2026-10-13: Stopped a stalled blob read when restore or deep verify
is interrupted is interrupted
@@ -367,8 +371,8 @@ owner's; a `v*` tag runs the release build in
device outlasted the 30-second shutdown timeout and the decrypted device outlasted the 30-second shutdown timeout and the decrypted
snapshot database and blob cache were left in the temporary snapshot database and blob cache were left in the temporary
directory. Each blob's storage reader is now closed as soon as the directory. Each blob's storage reader is now closed as soon as the
command is cancelled, which ends the stalled read and lets the command is cancelled, which ends a stalled read unless it is stuck in
cleanup run. the kernel.
- 2026-10-13: Made a mistyped subcommand under a group command an error - 2026-10-13: Made a mistyped subcommand under a group command an error
([issue #319](https://git.eeqj.de/sneak/vaultik/issues/319)). ([issue #319](https://git.eeqj.de/sneak/vaultik/issues/319)).