What is wrong: When a volume is normally mounted below a configured source path (configured path /data, an NFS share or USB disk mounted at /data/nas) and is not mounted at backup time, snapshot create finds /data/nas as an empty directory, counts every file the previous snapshot held under it as deleted, and succeeds. With --prune (default retention, keep the latest) that run then purges the older snapshot that holds the volume's files and prunes their blobs; with --keep-newer-than 4w the same happens once the volume has been away for the window. This is the data loss of #388 one level down: that fix (#394) catches a configured path that is empty, but here the configured path still holds other files. Found by the reviewer of #394; shown by reading the code (the scan crosses onto other filesystems and records nothing about them), not run.
Where:internal/snapshot/scanner.go (the walk); internal/vaultik/snapshot.goCreateSnapshot (the switch that decides the post-backup prune).
Plan:
The scan records, for each snapshot, the directories at or below a configured path that sit on a different filesystem from their parent directory (device number differs), the configured path itself included. They are stored in the local index with the snapshot, in a new table in internal/database/schema/001.sql (vaultik is pre-1.0: edit the schema in place).
Under --prune, snapshot create skips the post-backup prune when an earlier snapshot of that name in the local index recorded such a directory that this run did not find on a different filesystem. It warns naming the directory and snapshot, keeps every older snapshot and its blobs, and exits non-zero, as for an empty configured path.
A volume retired on purpose is cleared by removing the older snapshots by hand with snapshot purge; the warning and the README's --prune text say so.
The scanner reads the device number through one small function the tests can replace, since the in-memory test filesystem has none.
Definition of done
snapshot create --prune does not prune after a backup in which a volume mounted at or below a configured path in an earlier snapshot of that name is not mounted; it keeps the older snapshots and their blobs, says why, and exits non-zero.
The README's --prune text says so.
A test covers a backup with such a volume missing under --prune keeping the earlier snapshot, over two consecutive runs, and a run with the volume present still pruning.
Model: opus-5-5
**Severity:** high
**What is wrong:** When a volume is normally mounted below a configured source path (configured path `/data`, an NFS share or USB disk mounted at `/data/nas`) and is not mounted at backup time, `snapshot create` finds `/data/nas` as an empty directory, counts every file the previous snapshot held under it as deleted, and succeeds. With `--prune` (default retention, keep the latest) that run then purges the older snapshot that holds the volume's files and prunes their blobs; with `--keep-newer-than 4w` the same happens once the volume has been away for the window. This is the data loss of https://git.eeqj.de/sneak/vaultik/issues/388 one level down: that fix (https://git.eeqj.de/sneak/vaultik/pulls/394) catches a configured path that is empty, but here the configured path still holds other files. Found by the reviewer of https://git.eeqj.de/sneak/vaultik/pulls/394; shown by reading the code (the scan crosses onto other filesystems and records nothing about them), not run.
**Where:** `internal/snapshot/scanner.go` (the walk); `internal/vaultik/snapshot.go` `CreateSnapshot` (the `switch` that decides the post-backup prune).
**Plan:**
- The scan records, for each snapshot, the directories at or below a configured path that sit on a different filesystem from their parent directory (device number differs), the configured path itself included. They are stored in the local index with the snapshot, in a new table in `internal/database/schema/001.sql` (vaultik is pre-1.0: edit the schema in place).
- Under `--prune`, `snapshot create` skips the post-backup prune when an earlier snapshot of that name in the local index recorded such a directory that this run did not find on a different filesystem. It warns naming the directory and snapshot, keeps every older snapshot and its blobs, and exits non-zero, as for an empty configured path.
- A volume retired on purpose is cleared by removing the older snapshots by hand with `snapshot purge`; the warning and the README's `--prune` text say so.
- The scanner reads the device number through one small function the tests can replace, since the in-memory test filesystem has none.
**Definition of done**
- `snapshot create --prune` does not prune after a backup in which a volume mounted at or below a configured path in an earlier snapshot of that name is not mounted; it keeps the older snapshots and their blobs, says why, and exits non-zero.
- The README's `--prune` text says so.
- A test covers a backup with such a volume missing under `--prune` keeping the earlier snapshot, over two consecutive runs, and a run with the volume present still pruning.
Model: opus-5-5
Built as planned in #396 (base next): each snapshot now records in the local index the directories it found on a different filesystem from their parent, and snapshot create --prune skips the prune, keeps the older snapshots and exits non-zero when one an earlier snapshot of that name recorded is not found as one. The PR body lists the one judgement call and the one rule suppressed.
Model: opus-5-5
Built as planned in https://git.eeqj.de/sneak/vaultik/pulls/396 (base `next`): each snapshot now records in the local index the directories it found on a different filesystem from their parent, and `snapshot create --prune` skips the prune, keeps the older snapshots and exits non-zero when one an earlier snapshot of that name recorded is not found as one. The PR body lists the one judgement call and the one rule suppressed.
Model: opus-5-5
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.
Severity: high
What is wrong: When a volume is normally mounted below a configured source path (configured path
/data, an NFS share or USB disk mounted at/data/nas) and is not mounted at backup time,snapshot createfinds/data/nasas an empty directory, counts every file the previous snapshot held under it as deleted, and succeeds. With--prune(default retention, keep the latest) that run then purges the older snapshot that holds the volume's files and prunes their blobs; with--keep-newer-than 4wthe same happens once the volume has been away for the window. This is the data loss of #388 one level down: that fix (#394) catches a configured path that is empty, but here the configured path still holds other files. Found by the reviewer of #394; shown by reading the code (the scan crosses onto other filesystems and records nothing about them), not run.Where:
internal/snapshot/scanner.go(the walk);internal/vaultik/snapshot.goCreateSnapshot(theswitchthat decides the post-backup prune).Plan:
internal/database/schema/001.sql(vaultik is pre-1.0: edit the schema in place).--prune,snapshot createskips the post-backup prune when an earlier snapshot of that name in the local index recorded such a directory that this run did not find on a different filesystem. It warns naming the directory and snapshot, keeps every older snapshot and its blobs, and exits non-zero, as for an empty configured path.snapshot purge; the warning and the README's--prunetext say so.Definition of done
snapshot create --prunedoes not prune after a backup in which a volume mounted at or below a configured path in an earlier snapshot of that name is not mounted; it keeps the older snapshots and their blobs, says why, and exits non-zero.--prunetext says so.--prunekeeping the earlier snapshot, over two consecutive runs, and a run with the volume present still pruning.Model: opus-5-5
Built as planned in #396 (base
next): each snapshot now records in the local index the directories it found on a different filesystem from their parent, andsnapshot create --pruneskips the prune, keeps the older snapshots and exits non-zero when one an earlier snapshot of that name recorded is not found as one. The PR body lists the one judgement call and the one rule suppressed.Model: opus-5-5