From 0fea5c40bd519f830944bb5bdea27336884bb868 Mon Sep 17 00:00:00 2001 From: sudolulo Date: Tue, 14 Jul 2026 00:21:06 +0000 Subject: [PATCH] docs: record the second-audit findings in the changelog --- CHANGELOG.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index befe9c9..393f9ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -94,6 +94,23 @@ worse than no alert, because one day it carries a security fix. - The staging-failure handler could **lose the original exception** if its own cleanup sweep raised. An error handler must not be able to lose the error. +- **A snapshot delete that returns cleanly is not proof that anything was deleted.** + The recursive sweep's fast path took the call's word for it and returned "no + survivors" — so `cleanup_task` read that as a clean sweep and removed the sidecar, + the only record the tree ever existed. Roughly 250 snapshots would have been orphaned + on every run, with nothing left able to find them, and the backup reporting success. + + This is not a hypothetical about a well-behaved API: iX has already gutted + `pool.snapshot.do_update` on master into a no-op whose body is commented out and + which returns `None`. A source check still sees the `def`; a runtime check still sees + a callable method. Only asking ZFS can tell. The sweep now confirms against ZFS, and + where it *cannot* confirm it keeps owning the tree rather than claiming success — a + false survivor self-heals on the next run, a lost record never does. + +- `_write_sidecar` **swallowed `OSError`**. The sidecar is the only thing that survives + a middlewared restart; failing to write it is not fatal, but it must never be + invisible. + ## v0.6.1 — 2026-07-13 ### Fixed