Skip to content

fix(ocsf-audit): declare sink capabilities, re-pin to praxis #84 5b76fa6 - #530

Merged
Levaj2000 merged 1 commit into
mainfrom
claude/ocsf-sink-capabilities
Sep 10, 2026
Merged

fix(ocsf-audit): declare sink capabilities, re-pin to praxis #84 5b76fa6#530
Levaj2000 merged 1 commit into
mainfrom
claude/ocsf-sink-capabilities

Conversation

@Levaj2000

Copy link
Copy Markdown
Owner

praxis-proxy/policy PR #84's 0651258 makes audit sinks filtered like any other plugin: the engine pairs each handler with its own plugins: capability set in a new AttachedSink and hands handle a filtered Extensions rather than the executor's working copy. Correct design. This crate declared no capabilities, so it silently lost three of the six typed fields it maps.

The regression

request, mcp and completion are ungated. agent sits behind read_agent, delegation behind read_delegation, and security labels behind read_labels.

Reproduced through examples/panic_drive.rs, which drives a real engine through load_config. The unit tests build Extensions directly and never reach the filter, which is why 34 green did not catch it:

Pin Capabilities declared Emitted record
499ee91 (old) none carries ai_agent.uid: agent-7
5b76fa6 (new) none no ai_agent block, still chains, still signs, still verifies offline
5b76fa6 (new) the three carries ai_agent.uid: agent-7 again

The middle row is the point. Records still emit, still chain and still pass offline verification while carrying less than they should. A verifier cannot distinguish "no delegation occurred" from "the sink was not permitted to see it", which is the failure mode this project exists to prevent. A load error would have been better.

The change

  • Both demo config variants in panic_drive.rs and both README wiring examples declare the three capabilities.
  • The README gains a note on why omitting them costs evidence rather than failing to load.
  • The pin moves to 5b76fa6, with Cargo.lock regenerated.
  • PRAXIS-INTREE-PLAN.md records the finding and the state of the five review items under a 2026-09-10 status.

The cpex host accepts the capabilities: key and is unaffected, verified by running panic_drive on it.

The seam itself held

AuditHandler::handle, on_effect and Plugin::as_audit_handler are unchanged at the new head, so the crate needed no source change. Only Executor::with_audit_handlers changed shape, and that is host-side.

The same head also answers our review comment on #84: emit_decision is the single verdict finalizer, route-resolution denials seed a decision log, and reconciled effects take their place in the current stream rather than under the sequence numbers of the run that crashed, which was the AID-EMIT-1 section 7 density concern.

Verification

Run the way CI runs it, toolchain 1.96.1, cpex sibling at 64c8eba:

Step cpex host ppe host
check --locked --all-targets, RUSTFLAGS=-D warnings clean clean
test --locked 34 passed, 0 failed 34 passed, 0 failed
emit_sample vs the AID-EMIT-1 section 12 vector byte-identical byte-identical

Split out of #529, which is docs only and now carries just the ocsf#1756 filing.

🤖 Generated with Claude Code

https://claude.ai/code/session_01XyU3PRkgvMxgimkPBC5726


Generated by Claude Code

PR #84's `0651258` makes audit sinks filtered like any other plugin: the
engine pairs each handler with its own `plugins:` capability set in a new
`AttachedSink` and hands `handle` a filtered `Extensions` rather than the
executor's working copy. That is the right design. This crate declared no
capabilities, so it silently lost three of the six typed fields it maps.

`request`, `mcp` and `completion` are ungated. `agent` sits behind
`read_agent`, `delegation` behind `read_delegation`, and security labels
behind `read_labels`.

Reproduced through `examples/panic_drive.rs`, which drives a real engine
through `load_config`; the unit tests build `Extensions` directly and so
never reach the filter. At the old pin `499ee91` the emitted record carries
`ai_agent.uid: agent-7`. At `5b76fa6` with no capabilities declared it
carries no `ai_agent` block at all, and still chains, still signs and still
verifies offline. Declaring the three restores it.

A silent evidence loss rather than a load error, which is the failure mode
this project exists to prevent: a verifier cannot distinguish "no delegation
occurred" from "the sink was not permitted to see it".

Both demo config variants and both README wiring examples now declare the
three, with a note on why omitting them costs evidence. The cpex host
accepts the key and is unaffected.

The seam itself held: `AuditHandler::handle`, `on_effect` and
`Plugin::as_audit_handler` are unchanged at the new head, so the crate
needed no source change. Only `Executor::with_audit_handlers` changed, and
that is host-side.

Verified the way CI runs it, toolchain 1.96.1 with a cpex sibling at
`64c8eba`: warning-free `--locked` checks and 34 tests green on each host,
`emit_sample` byte-identical to the AID-EMIT-1 section 12 conformance vector
on both.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XyU3PRkgvMxgimkPBC5726
@vercel

vercel Bot commented Sep 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
ai-identity-landing Ready Ready Preview Sep 10, 2026 10:48pm UTC
dashboard Ready Ready Preview Sep 10, 2026 10:48pm UTC

@Levaj2000
Levaj2000 marked this pull request as ready for review September 10, 2026 22:52
@Levaj2000
Levaj2000 merged commit c4a6512 into main Sep 10, 2026
12 checks passed
@Levaj2000
Levaj2000 deleted the claude/ocsf-sink-capabilities branch September 10, 2026 23:19
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.

2 participants