Skip to content

M2: durable audit events - #57

Open
kgarg2468 wants to merge 3 commits into
mainfrom
loop/m2-audit-events
Open

M2: durable audit events#57
kgarg2468 wants to merge 3 commits into
mainfrom
loop/m2-audit-events

Conversation

@kgarg2468

@kgarg2468 kgarg2468 commented Sep 1, 2026

Copy link
Copy Markdown
Owner

M2 slice 13: the audit store (spec §14 audit log; S14-005; roadmap M2 exit criterion "audit events survive restart").

  • Migration 12 audit_events: one recorded fact per row in a run's §14 accountability trail — closed case-sensitive ten-kind taxonomy (authorizer, source, packet_version, permission_granted, file_accessed, service_accessed, permission_requested, user_response, artifact, final_status), backend-stamped dense per-record seq that clients cannot forge (forged seq/at_ms ignored, pinned by test + demo), bounded detail.
  • record_audit_event: double-Option record_id, unknown_run split, single-item list-envelope admission probe at i64::MAX stamp ceilings before insert (mutant-proven binding); list_audit_events: seq-ordered, limit-51 truncation probe, end-popping byte budget keeping the trail's start.
  • Swift AuditEvent/AuditEventPage + request builders/decoders/tests.
  • Security fix found via worker flag: four persistence tests were opening the user's REAL default store (flock race under parallel test runs + test residue written into user data). All four now use fixture stores; residue inventory recorded in the verification summary, not deleted.

TDD: red-first vs merged main 5c82fab (unknown_request_type ×3). Gates: 172 Rust + 62 Swift tests, fmt, clippy -D warnings, verify-m0.sh exit 0. Real-binary demo: self-contained hand-built v11 fixture migrated 11→12, legacy run gains a trail, all ten kinds recorded, restart survival, 0600. Evidence: .loop/verification/m2-audit-events/.

Traceability: S14-005 → in_progress with this PR (durable store + protocol; fact producers land M6/M9).

🤖 Generated with Claude Code

Greptile Summary

This PR adds durable, backend-sequenced audit events for runs, including migration, Rust protocol/store support, and Swift client models.

  • Adds migration 12 and persistent per-run audit-event sequencing.
  • Adds record and list protocol operations with validation and response-size bounds.
  • Adds Swift request builders, decoders, persistence tests, and restart-verification artifacts.

Confidence Score: 4/5

The PR should not merge until truncated audit trails provide a way to retrieve later events.

Runs exceeding the count or byte limit expose only their earliest audit events; the backend and Swift client still provide no cursor or offset for retrieving the omitted tail.

Files Needing Attention: backend/src/lib.rs, backend/src/store.rs, Sources/CaptureDelegateIPC/IPCClient.swift

Important Files Changed

Filename Overview
backend/src/lib.rs Adds audit-event protocol handling and bounded listing, but the existing inability to continue a truncated trail remains.
backend/src/store.rs Adds migration 12 and transactional, per-run audit-event persistence ordered by backend-assigned sequence.
Sources/CaptureDelegateIPC/IPCClient.swift Adds AuditEvent models plus record/list request and decoding support.
backend/tests/persistence.rs Adds persistence, validation, listability, scoping, and restart-survival coverage.

Reviews (2): Last reviewed commit: "Record Sol PASS review and user-stop pau..." | Re-trigger Greptile

kgarg2468 and others added 2 commits September 1, 2026 02:59
Spec §14 audit log: every run records authorizer, source, packet version,
permissions, access, requests, responses, artifacts, and final status.
These tests pin the durable half M2 owns: a closed ten-kind taxonomy, a
backend-stamped dense per-record sequence that clients cannot forge,
bounded detail text, unknown_run splits, restart survival, and the
single-item list-envelope admission probe.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Spec §14 audit log, S14-005, roadmap M2 audit store. Migration 12 adds
audit_events: one recorded fact per row in a run's accountability trail,
under a closed ten-kind taxonomy with a backend-stamped dense per-record
sequence that clients cannot forge. record_audit_event admits bounded
detail against the single-item list envelope at ceiling stamps;
list_audit_events pages the trail in sequence order, keeping its start
under the frame budget. Swift AuditEvent/AuditEventPage.

Also stops four persistence tests from opening the user's real default
store, which raced on the owner flock under parallel runs and left test
residue in user data (recorded in the verification summary).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment thread backend/src/lib.rs
Comment on lines +2322 to +2331
let mut events =
match store.list_audit_events(&record_id, LIST_AUDIT_EVENTS_LIMIT + 1) {
Ok(events) => events,
Err(error) => {
eprintln!("store read error: {error}");
return write_protocol_error(&mut stream, "store_unavailable");
}
};
let mut truncated = events.len() > LIST_AUDIT_EVENTS_LIMIT;
events.truncate(LIST_AUDIT_EVENTS_LIMIT);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Truncated trails cannot continue

When a run has more than 50 audit events, or the response exceeds the byte budget, list_audit_events returns only the earliest bounded prefix with truncated set but accepts no cursor or offset. Clients therefore cannot retrieve later durable facts, including a final status, leaving the accountability trail incomplete through the protocol.

Prompt To Fix With AI
This is a comment left during a code review.
Path: backend/src/lib.rs
Line: 2322-2331

Comment:
**Truncated trails cannot continue**

When a run has more than 50 audit events, or the response exceeds the byte budget, `list_audit_events` returns only the earliest bounded prefix with `truncated` set but accepts no cursor or offset. Clients therefore cannot retrieve later durable facts, including a final status, leaving the accountability trail incomplete through the protocol.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Claude Code Fix in Conductor Fix in Codex

Sol round 1: PASS, zero blockers, two MINOR test-coverage follow-ups
recorded. Fresh merge-gate verify-m0 exit 0 archived. Merge withheld:
user sent 'stop'; recurring job fa669dd2 cancelled, state persisted for
resume (squash-merge PR #57 + closeout).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kgarg2468

Copy link
Copy Markdown
Owner Author

Status: paused by user, ready to merge on resume.

Independent review (gpt-5.6-sol, xhigh): PASS, zero blockers — report at .loop/verification/m2-audit-events/sol-round1-report.md. Two MINOR test-coverage follow-ups (concurrent-append tripwire; audit-list truncation/byte-budget persistence coverage) recorded in verification.txt for the next touch of this area.

All ADR-007 merge conditions are green: fresh verify-m0.sh exit 0 (verify-m0-merge-gate.log, 172 Rust + 62 Swift), runtime v11→v12 demo, mutant evidence. Merge was intentionally withheld because the user sent "stop" during this window; the recurring loop job was cancelled. Resume = squash-merge this PR, then the cycle-31 closeout.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant