Repository navigation
v1.9.4 — the scanner daemon's calls are audited, the TTL delete first
A family survey on 2026-09-15 found that the scanner daemon deleted VMs whose TTL had expired with no row in
either audit trail, on success or failure, and without the guard() that stops the same deletion over MCP or the
CLI. Its scan cycles against vCenter and its webhook sends left no row either, and daemon start was marked
@cli_local, so the family's CLI gate could not see it.
- TTL delete. Before deleting, the daemon passes
guard()asvm_delete(riskcritical), so a deny rule on
vm_deletenow stops an expiry too; the entry is kept for when the rule is lifted. Each attempt writes one
vm_deleterow withtrigger: ttl_expiry:okwhen deleted,deniedwhen refused,errorwhen the delete
failed (entry kept for retry) or the VM was already gone (stale entry dropped). A policy check that fails is an
errorand skips the delete. - Scan cycle. One
daemon_scanrow per cycle,errorwhen a connection or a pass failed, with the failed
passes in the result. - Webhook. One
webhook_sendrow per send,errorwhen it was not delivered. The URL is not recorded — it can
carry a token. - No row flood. The TTL check runs every minute, so a refused or failing entry records its outcome once and
again only when it changes (a different status, refusing rule or error class); every successful delete is
recorded. Retries still happen every minute. Without this, an entry refused by a deny rule wrote 1,440 rows a day. - Interrupts are
interrupted. Ctrl+C during a scan or a webhook send (the first scan runs before the signal
handlers are installed) recordsinterruptedinstead ofok. daemon startis@audited(daemon_start). Its row is written when the daemon stops.
Tests: tests/eval/regression/test_daemon_calls_are_audited.py (12 tests, each red before its fix; suite 594 passed). Works with
vmware-policy 1.15.0: the daemon passes each status explicitly.