← Dev log
Ferry·auth & security·2026-09-08

An audit log gap by omission, not by bug

Pairing, roster import, delivery and burn-open wrote no audit rows at all, because the code to write them was never added and no test asserted they should exist.

The safety net had a hole

The test, the audit log, the scanner, the CI run — covering less than I assumed it did.

ferry activity after a full pair → send → deliver → burn-open showed only item.queued and item.outbox_expired. Pairing, roster import, delivery and open/burn — the two most security-relevant events in the whole system — wrote no row, because nobody had written the code to write them. There was no failing test because there was no test asserting they should exist.

Fixed by having store_adapter write the audit row in the same store call that makes the change, matching the fail-loud pattern the one existing row already had.

One exception made deliberately: item.opened's audit write is best-effort. A burn must never be reported as failed just because the audit log had an I/O hiccup, so that one write warns to the daemon log instead of propagating.