sysknife audit verify reports success over a database whose rows have all been deleted.
$ sqlite3 daemon.sqlite 'DELETE FROM transactions; DELETE FROM audit_events;'
$ sysknife audit verify
OK: 0 row(s) verified in .../daemon.sqlite
NOTE: no independent checkpoint anchor is configured, so removal of the newest rows
would not be detectable — a truncated chain still verifies. Set SYSKNIFE_CHECKPOINT_DB
and run `sysknife audit checkpoint` periodically; see docs/the-audit-chain.md.
OK: 0 approval event(s) verified
OK: 0 row(s) still match the approval event they committed to
$ echo $?
0
Three previously signed actions were deleted. The verdict is OK and the exit code is 0.
Why this is not simply a bug
A forward hash chain cannot detect the removal of its own tail without an external anchor. That is what checkpoint anchoring exists for, the tool says so in the NOTE, and docs/the-audit-chain.md explains it. Nothing here is hidden.
The problem is what an operator reads. Two very different states produce the same headline:
- a fresh install where nothing has run yet
- a host where the entire trail was deleted
Both print OK and exit 0. The one line that distinguishes them is a NOTE the reader has to interpret, below a verdict that already told them everything is fine.
Scope
Make the verdict carry the distinction the tool already knows:
- Zero rows and no anchor configured is not
OK. It is "nothing to verify, and this command cannot tell an empty log from a deleted one". A distinct exit code, or at minimum a different word than OK, gives a monitoring script something to alert on.
- Zero rows with an anchor configured genuinely is verifiable: the anchor either names a tip that should exist or it does not. That case can stay
OK or become an explicit failure, and the anchor is what makes the difference.
- The
--json shape should carry the same distinction, since that is what automation reads.
Worth considering alongside it: whether the daemon should anchor on a schedule by default rather than only when SYSKNIFE_CHECKPOINT_DB is set, so the mitigating control is not opt-in on a product whose subject is tamper evidence. That is a bigger decision and can be split out.
Tests first
A test that writes rows, deletes them, and asserts the verdict is not the same one a fresh store produces. Then a second that configures an anchor and asserts the truncation is caught, so the fix is proved to add detection rather than only to change wording.
Difficulty
medium. The verdict logic is small; deciding the exit-code contract is the part that needs care, and #335 is already open on exit codes generally.
Getting started
CONTRIBUTING.md has the build and test commands, and docs/the-audit-chain.md covers what the chain does and does not protect. No CLA and no copyright waiver. The project is MIT.
sysknife audit verifyreports success over a database whose rows have all been deleted.Three previously signed actions were deleted. The verdict is
OKand the exit code is 0.Why this is not simply a bug
A forward hash chain cannot detect the removal of its own tail without an external anchor. That is what checkpoint anchoring exists for, the tool says so in the NOTE, and
docs/the-audit-chain.mdexplains it. Nothing here is hidden.The problem is what an operator reads. Two very different states produce the same headline:
Both print
OKand exit 0. The one line that distinguishes them is a NOTE the reader has to interpret, below a verdict that already told them everything is fine.Scope
Make the verdict carry the distinction the tool already knows:
OK. It is "nothing to verify, and this command cannot tell an empty log from a deleted one". A distinct exit code, or at minimum a different word thanOK, gives a monitoring script something to alert on.OKor become an explicit failure, and the anchor is what makes the difference.--jsonshape should carry the same distinction, since that is what automation reads.Worth considering alongside it: whether the daemon should anchor on a schedule by default rather than only when
SYSKNIFE_CHECKPOINT_DBis set, so the mitigating control is not opt-in on a product whose subject is tamper evidence. That is a bigger decision and can be split out.Tests first
A test that writes rows, deletes them, and asserts the verdict is not the same one a fresh store produces. Then a second that configures an anchor and asserts the truncation is caught, so the fix is proved to add detection rather than only to change wording.
Difficulty
medium. The verdict logic is small; deciding the exit-code contract is the part that needs care, and #335 is already open on exit codes generally.Getting started
CONTRIBUTING.md has the build and test commands, and docs/the-audit-chain.md covers what the chain does and does not protect. No CLA and no copyright waiver. The project is MIT.