Go on with a backup when the destination marker cannot be checked (closes #389)
check / check (push) Waiting to run

A source host whose credentials allow only PUT, which the documents
say is enough to back up, failed every backup after its first: the
marker check looks the marker up with an S3 HEAD, which those
credentials are refused, and any error other than not found was
fatal.

Such an error now means the check could not be made: it is logged at
info level, so --cron stays silent, and the command goes on. Not found
still stops it. The documents now say so, and that such a host does
not notice an emptied destination, so vaultik database delete must be
run on it after the destination is emptied. The fault-injecting test
store gains a Stat hook for the test.

Model: opus-5-5
This commit was merged in pull request #392.
This commit is contained in:
2026-10-15 02:02:35 +02:00
parent 6a57750a7b
commit 850e2de25a
9 changed files with 132 additions and 54 deletions
+15 -10
View File
@@ -312,7 +312,7 @@ Repository interfaces:
```
CreateSnapshot(opts)
│
├─► markDestination() // Refuse a destination without the marker, then write it
├─► markDestination() // Check the marker (see Storage Layout in S3), then write it
│
├─► PruneDatabase() // Critical: avoid dedup errors
│
@@ -382,15 +382,20 @@ bucket/
└── manifest.json.zst # Blob list (for pruning/verification)
```
A destination without `vaultik-destination.txt` is treated as not present
while the local index holds snapshots stored there (`checkDestinationMarker`
in `internal/vaultik/destination_marker.go`): `snapshot create` refuses to
write to it, `prune`, `snapshot purge` and `remote nuke` fail, and
`snapshot list` and `snapshot remove` behave as for a destination that cannot
be listed. This keeps those commands from taking an unplugged volume's empty
mount point for a destination whose snapshots are all gone. The `file://`
backend never creates its destination directory, so a write to a missing one
fails.
A destination that answers a look-up of `vaultik-destination.txt` with not
found is treated as not present while the local index holds snapshots stored
there (`checkDestinationMarker` in `internal/vaultik/destination_marker.go`):
`snapshot create` refuses to write to it, `prune`, `snapshot purge` and
`remote nuke` fail, and `snapshot list` and `snapshot remove` behave as for a
destination that cannot be listed. This keeps those commands from taking an
unplugged volume's empty mount point for a destination whose snapshots are
all gone. When the look-up fails for any reason other than not found, for
example when S3 refuses it to credentials that allow only PUT, the check is
skipped, so a host with such credentials does not notice an emptied
destination; see
[docs/REPOSTRUCTURE.md](docs/REPOSTRUCTURE.md#marker-file-vaultik-destinationtxt).
The `file://` backend never creates its destination directory, so a write to a
missing one fails.
The `{remote-key}` directory name is a one-way double SHA-256 hash of the human
snapshot ID, so the human ID (hostname, snapshot name, timestamp) is never