feat: correlate native search outcomes in audit history#98704
Conversation
|
Codex review: needs changes before merge. Reviewed July 6, 2026, 6:56 AM ET / 10:56 UTC. Summary Reproducibility: not applicable. this is a feature PR adding a new audit ledger and query surface, not a bug report. Current-main source search confirms the requested audit surface does not already exist. Review metrics: 2 noteworthy metrics.
Stored data model Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Copy recommended automerge instructionNext step before merge
Security Review findings
Review detailsBest possible solution: Fix the exact-head tooling blockers, let the remaining CI finish, and merge only after maintainers accept the already-discussed audit contract and default-on config behavior. Do we have a high-confidence way to reproduce the issue? Not applicable; this is a feature PR adding a new audit ledger and query surface, not a bug report. Current-main source search confirms the requested audit surface does not already exist. Is this the best way to solve the issue? Yes for the overall architecture, but not yet merge-ready. Shared SQLite plus metadata-only Gateway/CLI reads fit repository policy and the linked issue, while the current head still needs the two tooling repairs before it is the best mergeable form. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against cbf9acff374c. Label changesLabel changes:
Label justifications:
Evidence reviewedAcceptance criteria:
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
Review history (3 earlier review cycles)
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
5f1291c to
08e437d
Compare
a04ced6 to
0c159d6
Compare
0c159d6 to
8147c8a
Compare
Metadata-only audit ledger for agent runs and tool actions in the shared state DB: stable event identity, closed action/status/error vocabularies, one-way-hashed tool-call ids, never-inferred terminal outcomes for native web-search (explicit completed/failed only; otherwise unknown), bounded retention, audit.list gateway RPC and openclaw audit CLI. Squashed from the 82-commit audit stack for replay onto current main.
The metadata-only audit ledger records by default: an audit trail enabled only after an incident cannot explain the incident, and the rows are strictly less sensitive than the transcripts every install already stores. audit.enabled=false stops new writes at the gateway subscription seam; audit.list and openclaw audit keep serving existing records until they expire. Documented in the configuration reference, protocol page, and CLI reference.
- break the dynamic-tools/dynamic-tool-execution import cycle by extracting resolveCodexToolAbortTerminalReason into a leaf module - restore main's session-worktree protocol exports lost in the index.ts auto-merge - register the audit event writer worker as a knip entry point - docs table formatting; subagent wait-cancellation test scoped to its audit intent (outcome + timing) and advanced past main's new lifecycle-timeout retry grace
8147c8a to
e8e4440
Compare
* feat: correlate native search outcomes in audit history Metadata-only audit ledger for agent runs and tool actions in the shared state DB: stable event identity, closed action/status/error vocabularies, one-way-hashed tool-call ids, never-inferred terminal outcomes for native web-search (explicit completed/failed only; otherwise unknown), bounded retention, audit.list gateway RPC and openclaw audit CLI. Squashed from the 82-commit audit stack for replay onto current main. * feat(audit): add audit.enabled config gate (default on) The metadata-only audit ledger records by default: an audit trail enabled only after an incident cannot explain the incident, and the rows are strictly less sensitive than the transcripts every install already stores. audit.enabled=false stops new writes at the gateway subscription seam; audit.list and openclaw audit keep serving existing records until they expire. Documented in the configuration reference, protocol page, and CLI reference. * fix: repair full-matrix CI findings after rebase - break the dynamic-tools/dynamic-tool-execution import cycle by extracting resolveCodexToolAbortTerminalReason into a leaf module - restore main's session-worktree protocol exports lost in the index.ts auto-merge - register the audit event writer worker as a knip entry point - docs table formatting; subagent wait-cancellation test scoped to its audit intent (outcome + timing) and advanced past main's new lifecycle-timeout retry grace
* feat: correlate native search outcomes in audit history Metadata-only audit ledger for agent runs and tool actions in the shared state DB: stable event identity, closed action/status/error vocabularies, one-way-hashed tool-call ids, never-inferred terminal outcomes for native web-search (explicit completed/failed only; otherwise unknown), bounded retention, audit.list gateway RPC and openclaw audit CLI. Squashed from the 82-commit audit stack for replay onto current main. * feat(audit): add audit.enabled config gate (default on) The metadata-only audit ledger records by default: an audit trail enabled only after an incident cannot explain the incident, and the rows are strictly less sensitive than the transcripts every install already stores. audit.enabled=false stops new writes at the gateway subscription seam; audit.list and openclaw audit keep serving existing records until they expire. Documented in the configuration reference, protocol page, and CLI reference. * fix: repair full-matrix CI findings after rebase - break the dynamic-tools/dynamic-tool-execution import cycle by extracting resolveCodexToolAbortTerminalReason into a leaf module - restore main's session-worktree protocol exports lost in the index.ts auto-merge - register the audit event writer worker as a knip entry point - docs table formatting; subagent wait-cancellation test scoped to its audit intent (outcome + timing) and advanced past main's new lifecycle-timeout retry grace
Closes #98521
What Problem This Solves
Operators currently have to correlate runtime output, session transcripts, task records, and logs to answer who ran an agent or tool, what action occurred, when it happened, and how it ended. There is no single durable, bounded, redaction-safe query surface for those operational questions.
Why This Change Was Made
This adds a typed, metadata-only audit contract over the existing agent-run and tool lifecycle signals. Events use stable identities and database order, carry agent/session/actor provenance and closed action/result/error codes, and persist through one Kysely-backed table in the shared state database. Existing transcript ownership remains unchanged; this is not a second conversation store.
The canonical read surfaces are the read-authorized
audit.listGateway method andopenclaw audit, with bounded filters, cursor pagination, and bounded JSON output. Prompts, message bodies, tool arguments, tool results, raw error text, and provider-controlled identifiers are excluded or one-way hashed by contract.Native search correlation follows the dependency contract conservatively. Explicit terminal
completedstatus is success; explicit failed terminal state is failure; missing, unavailable, or non-terminal status istool_outcome_unknownand never inferred as success. Lifecycle timestamps remain authoritative, with local observation time only as a documented fallback.User Impact
Authorized operators can inspect recent agent runs and tool actions by agent, session, actor, action, status, and time range. Records survive process restarts, retain deterministic ordering, and are capped by a 30-day retention window, a 100,000-row limit, and 500-row query pages.
Evidence
Final candidate:
0ad58848b399ca47ab9e0c644d14e9efd1cbd222d3f2be300b19ffda04789020ff282a276c6c9982cdfb3876495826eb9c4aa676ad5fd37db0e7846eFocused local proof on the final base:
node scripts/run-vitest.mjs src/audit/audit-events.test.ts src/audit/audit-event-writer.test.ts src/commands/audit.test.ts src/gateway/server-methods/audit.test.ts packages/gateway-protocol/src/schema/audit.test.ts— 53/53 passed; ordering, filters, pagination, redaction, persistence/reopen, and terminal/failure states.node scripts/run-vitest.mjs src/auto-reply/reply/agent-runner-execution.test.ts src/auto-reply/reply/followup-runner.test.ts src/auto-reply/reply/dispatch-from-config.test.ts— 7/7 passed across the latest session-binding overlap.node --import tsx scripts/protocol-gen.ts,node --import tsx scripts/protocol-gen-swift.ts,node scripts/generate-kysely-types.mjs, andnode scripts/generate-docs-map.mjs --check— generated surfaces clean.node scripts/format-docs.mjs --checkandnode scripts/check-docs-mdx.mjs docs README.md— 673 documents and 689 MDX inputs passed.Exact-tree remote proof:
tbx_01kwmfd7hgjjx9js0xpae9gmma(Actions run), exit 0 in 13m59.947s.build:strict-smokepassed, including CLI bootstrap and canonical plugin SDK declarations.gateway healthand boundedaudit --json --limit 1passed.check:changedpassed full typecheck, lint, database-first guardrails, and import-cycle checks.test:changedpassed 3,553 tests in 78 files across 15 shards.pnpm buildpassed. The Testbox lease stopped cleanly. No alternate cloud slot was used.Supporting real-path proof from the earlier reviewed tree remains useful for behavior continuity: Testbox
tbx_01kwf7yk3968m7vh2634qabet9ran a real Gateway turn with one tool action, returned four ordered metadata-only records, opened a pre-feature shared database without losing its existing row, added the audit table, proved cursor pagination, and found no prompt/reply/tool-result sentinels.Fresh explicit
koffing-updatedxhigh review against the final base/head returned no findings (confidence 0.96). The reviewer specifically checked terminal precedence, incomplete-client outcome handling, redaction/hashing, stable Kysely pagination, and the direct dependency contract below.Direct dependency contract source audit
Pinned dependency checkout:
db887d03e1f907467e33271572dffb73bceecd6b.codex-rs/app-server-protocol/src/protocol/v2/thread.rs:143-147,310-398,1275-1287,1303-1334codex-rs/app-server-protocol/src/protocol/common.rs:632-643codex-rs/app-server/src/message_processor.rs:1223-1230codex-rs/app-server/src/request_processors/thread_processor.rs:899-1001,2181-2304,2368-2420,2577-2612,2615-2805,2953-3000,3073-3132codex-rs/protocol/src/items.rs:145-152,188-194,229-235,268-273,291-301,363-370codex-rs/protocol/src/models.rs:1094-1114,3171-3245codex-rs/core/src/event_mapping.rs:194-203codex-rs/app-server-protocol/src/protocol/v2/item.rs:350-362,921-925,992-1025,1070-1141,1155-1161,1240-1250,1314-1333codex-rs/core/src/tools/handlers/extension_tools.rs:269-279codex-rs/app-server/src/bespoke_event_handling.rs:1010-1028,1070-1103,1384-1411,1452-1476codex-rs/app-server/src/thread_state.rs:78-84,130-132,492-518codex-rs/app-server/src/request_processors/thread_lifecycle.rs:311-340,530-675codex-rs/core/tests/common/responses.rs:803-824codex-rs/app-server-protocol/src/protocol/event_mapping.rs:401-415,425-460codex-rs/ext/image-generation/src/tool.rs:117-125,139-151,179-185codex-rs/core/src/stream_events_utils.rs:445-475The source establishes that normalized live and persisted search items carry identity/query/action but no terminal status; optional raw status is live-only and opt-in. Cold resume does not provide raw state, while warm loaded state may retain it. The action value
openis not terminalcompleted. Image generation emitsin_progressbefore explicitcompletedorfailed. This PR therefore preserves unknown/non-success whenever authoritative terminal status is absent.Risks and Non-Goals
origin/main. This branch does not touch those files and does not import that unrelated drift.AI Disclosure
AI-assisted implementation and review. Maintainer review remains required.