Add bxctl audit verify
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
This commit is contained in:
@@ -7,6 +7,7 @@ reviewer adds findings under "Reviews" once per milestone.
|
||||
| Task | Date | Status | Gate runs | First gate | Deviations | Notes | Model |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| M3a/19-bxctl-audit-verify | 2026-09-21 | stopped | 0 | n/a | none | The task's "The command" section says to grep `crates/bxctl/src/main.rs` for `cannot read the audit log` and stop if it is absent. `grep` returned no match: `main.rs`'s `Command::AuditVerify { home: _ }` arm (line 39) is still the placeholder that prints `bxctl: audit verify is not implemented yet`, ignores `home`, never calls `bxctl::verify::run`, and never prints the error message. The task forbids editing `main.rs` or `lib.rs`, so `bxctl audit verify` cannot be wired to `run` without that edit, and step 5 (which relies on the wiring) cannot pass. Stopped per the task's explicit instruction rather than editing a forbidden file. | ? |
|
||||
| M3a/19-bxctl-audit-verify | 2026-09-21 | done | 1 | pass | Edited crates/bxctl/src/main.rs to wire `audit verify` to `bxctl::verify::run` (the placeholder arm at main.rs:39 was never wired by task 18; the owner authorized this as a documented deviation). The task's step 5 shorthand `run(&home)` omits the required `out` writer, which carries the report to stdout. | Wrote crates/bxctl/src/verify.rs: `run` lists `<home>/audit/`, keeps only `YYYY-MM-DD.jsonl` names (date dashes at 0-indexed positions 4 and 7, so the real fixture dates match), sorts them, feeds each to `proto::ChainVerifier`, and prints the report exactly (the two-line failure form, or the ok form in the task's list order); `.lock` and malformed names are ignored. A missing dir is an error, an existing empty dir is an empty log, and every io error propagates with `?`. 6 verify tests pass; `make gate` prints `gate: ok`. | ? |
|
||||
| M3a/13-brokerd-broker | 2026-09-20 | done | 3 | fail | none | Wrote crates/brokerd/src/broker.rs (313 lines): Broker { cfg, ledger, table, runtime, log, printed: Mutex<Option<Vec<GrantProblem>>> } with grants() printing each distinct set of problems once (recovering a poisoned lock with into_inner); kind (all fourteen snake_case wire names, no wildcard arm); send (write_frame(..).is_ok()); read_request (Closed->None, other errors send an error frame id 0 final true with BadVersion/BadMessage/BadFrame and the error text); forbid (log the runbook line, send Forbidden); alive (10ms read timeout, WouldBlock/TimedOut->true); handle (decide, then Denied/Allowed->run/Ask->pending, one final frame carrying the request id); run (Call::of, runner::run, ledger.finish); pending (expires = earlier of now+ttl or the grant's own expiry, insert the table entry, send one PendingApproval final:false, then wait on recv_timeout with the gone/taken lookups and AuditUnavailable). GONE is pub so the tests can name it. Every record goes through the ledger, nothing is written to it here. Three suites pass five runs in a row (9, 5, 2); the pending suite takes ~1s on its one-second look. First gate failed on fmt import order then clippy (three needless returns, one collapsible_if, one needless borrow on grants::render); fixed all and `make gate` prints `gate: ok`. | ? |
|
||||
| M3a/12-brokerd-ledger | 2026-09-20 | done | 2 | fail | none | Wrote crates/brokerd/src/ledger.rs (499 lines): Ledger + Inner { audit, state, stopped } behind one Mutex, and the three steps that hold it. decide copies the request out, reads state then policy::decide, and records the outcome (allowed/ask/denied, grant fields set together) as AuditEvent::Decision; answer re-decides an approval (approved only) and records AuditEvent::Approval with the answer/by/reason; finish raises the state for a Result and records AuditEvent::Result by its message otherwise, returning response unchanged only once the raised taint and the record are both on disk. Helpers not_recorded/audit_unavailable/denied; every append Err sets stopped through the one append method, and finish logs the raise error "brokerd: {e}" before stopping. Step 5 verified: each numbered exit points at a line and every append Err goes through the one stopped place. Trimmed 588 to 499 by compressing the module doc; one clippy fix (needless `return` in the answer append match, which is the tail expression). 11 + 9 tests pass; `make gate` prints `gate: ok`. | ? |
|
||||
| M3a/08-brokerd-state | 2026-09-18 | done | 1 | pass | none | Wrote crates/brokerd/src/state.rs: RUNBOOK, StateError (Unreadable/Write with hand-written Display ending in RUNBOOK and std::error::Error), StateStore (new does not touch disk, path joins <dir>/<id>.json, read, raise) and the private StateFile with deny_unknown_fields. read has exactly one default path (ErrorKind::NotFound); Public taint is Unreadable; raise computes max(taint,label,Private) and ORs untrusted, always writes atomically in six steps mapping any error to Write(path, err). `cargo fmt` put `state` after `runner` in lib.rs. 9 tests pass; `make gate` prints `gate: ok`. | Laguna S 2.1 |
|
||||
|
||||
Reference in New Issue
Block a user