Repository navigation
feat(cpex-ocsf-audit): keyed content provenance vector (AID-EMIT-1 1.1.2) - #586
Merged
Merged
Conversation
…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
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 carryingunmapped."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.ContentKey, the function the executor calls at entry and at emission, under keys the demo resolves through the engine's secret store (envbackend, the pathengine_settings.content_provenance_keytakes 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// verifylines, so every digest recomputes with Pythonhmacandhashlibalone.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.mdand the crate README name the vector.Verification
rustup 1.96.1, cpex sibling at the CI rev:
cargo check --locked --all-targets,RUSTFLAGS=-D warningscargo test --lockedprovenance_demo, two runsprovenance_demovs the committed vectoremit_sample,decision_sink_demovs their vectorsAll eight digests in the vector were recomputed independently from the printed keys and bytes with Python
hmacandhashlib, and the key ids differ across the rotation. The four records parse as JSON and none contains the demo SSN.cargo fmt --checkis clean on the example.One thing to know when reading the vector: the
// verifylines 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