feat(core): add governAction() for non-LLM action governance#10
Conversation
Add `governAction<R>()` method to `TrustedClient` that runs arbitrary agent actions (tool use, file access, shell commands, API requests) through the same governance pipeline as LLM calls: mutex → circuit breaker → policy gate → PII check → PENDING hold → execute → POST/VOID → audit → receipt New types: ActionKind, ActionDescriptor, GovernedActionResult. TrustReceipt gains optional `actionKind` field (backward compat). Security: AUD-466 validates cost >= 0 to prevent budget inflation. Safety: AUD-465 uses holdReleased guard to prevent double-decrement. 14 unit tests + 5 E2E tests covering policy denial, budget enforcement, PII detection, audit chain integrity, mixed LLM+action governance, negative cost rejection, and destroyed client behavior. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Codex Review (gpt-5.3-codex)Severity: High ...(action.params != null ? { params: action.params } : {}),This can persist raw sensitive payloads (including prompts/secrets/PII) to audit storage, which conflicts with your security model (“only SHA-256 hashes allowed” for sensitive raw content). Even with PII detection, const paramsHash =
action.params != null
? createHash("sha256").update(stableStringify(action.params)).digest("hex")
: null;
// ...
data: {
actionName: action.name,
cost: action.cost,
settled,
transferId,
...(paramsHash != null ? { paramsHash } : {}),
},(Use the project’s canonical serialization utility if available; otherwise ensure stable key ordering.) |
Codex Remediation Summary
Reasoning for deferralThe suggestion to hash The "only hashes allowed" principle applies to raw prompt content, not structured action metadata. The PII detector already catches sensitive data in params when If we change this pattern, it should be a separate PR that addresses both the LLM and action paths consistently. Deliberations: 0 of 2 used |
CI Results (Final)
Commit: |
Ship Pipeline CompleteBranch: ship/action-governance Audit Trail
Summary
|
… log AUD-467: Spread action.params BEFORE governance fields in policy context so callers cannot shadow budget_remaining, estimated_cost, or tier with user-supplied values. Adds regression test. Also adds stderr log for audit degradation in governAction (failure mode 15.3 consistency with interceptCall). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remediation Round 2 — Review FindingsFixed (this commit: a0cf27a)
Previously fixed (commit 2d88f70)
Verified false positive
Deferred (pre-existing, out of scope)
CI Results (Final — commit a0cf27a)
|
Summary
governAction<R>()method toTrustedClient— governs arbitrary agent actions (tool use, file access, shell commands, API requests) through the same pipeline as LLM callsActionKind,ActionDescriptor,GovernedActionResult— exported fromusertrustTrustReceiptgains optionalactionKindfield (backward compatible)action.cost >= 0to prevent budget inflation via negative valuesholdReleasedguard to prevent double-decrement of in-flight hold trackingAPI
Governance pipeline for actions
mutex → circuit breaker → policy gate → PII check → PENDING hold → execute → POST/VOID → audit → receiptTest plan
🤖 Generated with Claude Code