Summary
Lower-severity robustness items from the audit. None are silent-data-loss on their own; grouping them so they aren't lost.
-
Run-gate asymmetry (LOW). store/runs.go — index/sync can begin while an offload run is in flight (the offload gate blocks on every kind, but not vice versa). Worst case is loud, not silent: MarkMissing can flip a just-unlinked row before MarkOffloaded runs, yielding spurious OutcomeErrors. Fix: include 'offload' in the sync and index begin-gates' blocking sets.
-
FinishHookRun has no terminal-state guard (LOW). store/hookruns.go — a double finish overwrites the first terminal record; it's the only runs-like table without FinishRun's first-write-wins guard. Fix: mirror the read-status-refuse-terminal shape.
-
--checksum --hash blake3 may silently degrade (MEDIUM). sync/handler.go sets verified purely from flags + exit-0; sync/rclone.go drops NOTICE-level events, so rclone's "no common hash → fall back to size/modtime" path would still be recorded as blake3-verified on a backend that can't serve blake3. Fix: per-destination hash-capability preflight, or parse the NOTICE and downgrade to size+mtime (no advance).
-
Sync handlers don't check config-path ↔ DB-volume-path agreement (MEDIUM). sync/sync.go looks up the volume by name only; offload and restore already cross-check. A stale DB path makes a handler push the config path's tree while the advance covers the DB volume's rows — a wholesale false durability claim. Fix: add the same path cross-check the offload path has.
-
kopia repo silently re-created on connect failure (MEDIUM). sync/kopia.go — connect-fail → create evaporates destination history while its vector components persist (monotonic). Note there is no CLI to rewind destination_run_ids at all (--allow-rewind exists only on the peer pull), so recovery from any poisoned vector is manual SQL. Fix: require explicit init; treat re-creation as a vector-reset event; consider a guarded destination-run-ids rewind command.
-
No durability-evidence staleness policy (LOW). The gate ignores updated_at_ns; evidence never expires even for a dead destination; equal-value re-advances refresh timestamps without re-verification.
Adversarial audit of offload-v1 (auditors B LOW-8/9, D F6/F8/F9/F11).
Summary
Lower-severity robustness items from the audit. None are silent-data-loss on their own; grouping them so they aren't lost.
Run-gate asymmetry (LOW).
store/runs.go—index/synccan begin while anoffloadrun is in flight (the offload gate blocks on every kind, but not vice versa). Worst case is loud, not silent:MarkMissingcan flip a just-unlinked row beforeMarkOffloadedruns, yielding spuriousOutcomeErrors. Fix: include'offload'in thesyncandindexbegin-gates' blocking sets.FinishHookRunhas no terminal-state guard (LOW).store/hookruns.go— a double finish overwrites the first terminal record; it's the only runs-like table withoutFinishRun's first-write-wins guard. Fix: mirror the read-status-refuse-terminal shape.--checksum --hash blake3may silently degrade (MEDIUM).sync/handler.gosetsverifiedpurely from flags + exit-0;sync/rclone.godrops NOTICE-level events, so rclone's "no common hash → fall back to size/modtime" path would still be recorded as blake3-verified on a backend that can't serve blake3. Fix: per-destination hash-capability preflight, or parse the NOTICE and downgrade to size+mtime (no advance).Sync handlers don't check config-path ↔ DB-volume-path agreement (MEDIUM).
sync/sync.golooks up the volume by name only; offload and restore already cross-check. A stale DB path makes a handler push the config path's tree while the advance covers the DB volume's rows — a wholesale false durability claim. Fix: add the same path cross-check the offload path has.kopia repo silently re-created on connect failure (MEDIUM).
sync/kopia.go—connect-fail →createevaporates destination history while its vector components persist (monotonic). Note there is no CLI to rewinddestination_run_idsat all (--allow-rewindexists only on the peer pull), so recovery from any poisoned vector is manual SQL. Fix: require explicit init; treat re-creation as a vector-reset event; consider a guardeddestination-run-idsrewind command.No durability-evidence staleness policy (LOW). The gate ignores
updated_at_ns; evidence never expires even for a dead destination; equal-value re-advances refresh timestamps without re-verification.Adversarial audit of offload-v1 (auditors B LOW-8/9, D F6/F8/F9/F11).