Skip to content

feat(cpex-ocsf-audit): keyed content provenance vector (AID-EMIT-1 1.1.2) - #586

Merged
Levaj2000 merged 3 commits into
mainfrom
claude/blissful-maxwell-gnw45t
Oct 1, 2026
Merged

Levaj2000 merged 3 commits into
mainfrom
claude/blissful-maxwell-gnw45t

Conversation

@Levaj2000

@Levaj2000 Levaj2000 commented Oct 1, 2026 •

Copy link
Copy Markdown
Owner

Why

#584 moved the plugin onto the keyed content digest praxis-proxy/policy#84 records, and #585 wrote the digest form into AID-EMIT-1, but no committed vector exercised it: the existing demos never enable provenance, so the form was covered by one unit test only. This adds the vector.

What

  • examples/provenance_demo.rs: four finalized decision records carrying unmapped."cpex.content". Unchanged content (equal digests, one key id); a redaction (different digests, same key id, and the redacted value is in neither the record nor a digest, since the OCSF event carries no tool arguments at all); the same content under a rotated key (a different key id, so a reader knows not to compare); and the explicit unkeyed form.
  • On PPE the digests are the engine's own ContentKey, the function the executor calls at entry and at emission, under keys the demo resolves through the engine's secret store (env backend, the path engine_settings.content_provenance_key takes at startup). The example feeds it the bytes and places the result on the log the way the executor does; the emitter copies both values and never holds a key. On cpex, which has no provenance key, records 1 to 3 carry the unkeyed form over the same bytes.
  • SAMPLE-OUTPUT-PROVENANCE.md: the verbatim PPE output, what each record demonstrates, the cpex delta in full, and a recompute recipe. The demo keys, the key-id label and the canonical audit bytes are printed as // verify lines, so every digest recomputes with Python hmac and hashlib alone.
  • docs/specs/aid-emit-1.md: 1.1.2-draft, naming the vector in section 12 and the patch in section 13. No covered byte and no existing vector changes.
  • PRAXIS-PORT-RESULTS.md and the crate README name the vector.

Verification

rustup 1.96.1, cpex sibling at the CI rev:

Check cpex host ppe host
cargo check --locked --all-targets, RUSTFLAGS=-D warnings clean clean
cargo test --locked 35 passed, 0 failed 35 passed, 0 failed
provenance_demo, two runs byte-identical byte-identical
provenance_demo vs the committed vector differs only by the documented digest lines of records 1 to 3 byte-identical
emit_sample, decision_sink_demo vs their vectors unchanged byte-identical

All eight digests in the vector were recomputed independently from the printed keys and bytes with Python hmac and hashlib, and the key ids differ across the rotation. The four records parse as JSON and none contains the demo SSN. cargo fmt --check is clean on the example.

One thing to know when reading the vector: the // verify lines deliberately print the pre-redaction bytes of record 2 so the digests can be checked. The records themselves do not carry them.

Generated with Claude Code

https://claude.ai/code/session_019BKU46zuw1Yu8E8yBQj4DP

Levaj2000 and others added 3 commits October 1, 2026 21:08
…1.2)

A fourth conformance vector, SAMPLE-OUTPUT-PROVENANCE.md, generated by the
new examples/provenance_demo.rs: four decision records carrying the
unmapped."cpex.content" digests of AID-EMIT-1 section 9.2. Unchanged
content (equal digests, one key id), a redaction (different digests, same
key id, the redacted value in neither the record nor a digest), the same
content under a rotated key (a different key id, so a reader knows not to
compare), and the explicit unkeyed form.

On PPE the digests are the engine's own: ContentKey, the function the
executor calls at entry and at emission, under keys the demo resolves
through the engine's secret store (env backend, the path
engine_settings.content_provenance_key takes at startup). The example
feeds it the bytes and places the result on the log the way the executor
does. The demo keys, the key-id label and the canonical audit bytes are
printed as verify lines, so every digest recomputes with Python hmac and
hashlib alone; all eight were recomputed that way and match. On cpex,
which has no provenance key, records 1 to 3 carry the unkeyed form over
the same bytes, and the file shows that delta. Timestamps, span ids,
stream stamps and keys are fixed: two runs are byte-identical.

AID-EMIT-1 moves to 1.1.2-draft, naming the vector in section 12 and the
patch in section 13; no covered byte and no existing vector changes
(emit_sample and decision_sink_demo re-run byte-identical). The port
results table and the crate README name the vector.

Verified with rustup 1.96.1: check --locked --all-targets under
RUSTFLAGS=-D warnings and test --locked on both hosts (35 passed each),
and the example run on both.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019BKU46zuw1Yu8E8yBQj4DP
…586)

ruff 0.16 formats Python code blocks inside Markdown, and CI runs
`ruff format --check .` over the repo, so the recipe in
SAMPLE-OUTPUT-PROVENANCE.md takes ruff's quote style and comment
spacing. The vector itself is untouched.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019BKU46zuw1Yu8E8yBQj4DP
@Levaj2000
Levaj2000 marked this pull request as ready for review October 1, 2026 21:11
@Levaj2000
Levaj2000 merged commit fd000e6 into main Oct 1, 2026
9 checks passed
@Levaj2000
Levaj2000 deleted the claude/blissful-maxwell-gnw45t branch October 1, 2026 21:12
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