From 1136a2b0a41e128c85c530552f191d0b134e0378 Mon Sep 17 00:00:00 2001 From: Jeff Leva <120221487+Levaj2000@users.noreply.github.com> Date: Wed, 9 Sep 2026 18:38:52 +0000 Subject: [PATCH] chore(cpex-ocsf-audit): track PR #84 at 499ee91, hold base64 at 0.22 to match the PPE tree Teryl answered the two dependency findings on praxis-proxy/policy PR #84 on 2026-09-09: sha2 is a workspace dependency at 0.11 (ef20d8f), and base64 stays at 0.22 across the tree because jsonwebtoken 11 requires it. The same head merges the #82 docs reorganisation (docs/content/auditing.md). Nothing on the seam this crate consumes changed between 3e7734e and 499ee91. - Move the praxis-policy-core pin to 499ee91; regenerate the lock. - Pin base64 down from 0.23 to 0.22 so the in-tree copy under reference/plugins/ocsf-audit is a copy and PPE stays on one base64; a Renovate rule holds it there. - PRAXIS-INTREE-PLAN.md: only p256 is a workspace-table add now; the base64 question is settled; auditing guide path updated. - PRAXIS-PORT-RESULTS.md, README, Cargo.toml and the CI comment record the re-verification. Verified on 1.96.1 with cpex at 64c8eba: warning-free --locked builds and 34 tests green on both hosts; emit_sample and decision_sink_demo byte-identical to the committed vectors; panic_drive lands on gw-1:decision on PPE. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_019XNHGsnzrXrncvFnSSCZTF --- .github/workflows/rust.yml | 7 +- CHANGELOG.md | 3 + integrations/cpex-ocsf-audit/Cargo.lock | 8 +- integrations/cpex-ocsf-audit/Cargo.toml | 22 +++-- .../cpex-ocsf-audit/PRAXIS-INTREE-PLAN.md | 87 ++++++++++--------- .../cpex-ocsf-audit/PRAXIS-PORT-RESULTS.md | 5 ++ integrations/cpex-ocsf-audit/README.md | 7 +- renovate.json | 6 ++ 8 files changed, 87 insertions(+), 58 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 41df6e9..0bd1bf5 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -60,9 +60,10 @@ env: # The second host. praxis-proxy/policy PR #84 is Teryl's port of the # same seam into the Praxis Policy Engine; the crate builds against it # under `--no-default-features --features ppe`. That dependency is a - # git dep pinned by full SHA in Cargo.toml (PR #84 head `20798ae`, the - # rev PRAXIS-PORT-RESULTS.md was measured on), so there is nothing to - # clone here — Cargo fetches it, and --locked holds it to the lock. + # git dep pinned by full SHA in Cargo.toml (the PR #84 head the crate + # was last re-verified on; PRAXIS-PORT-RESULTS.md records each bump), + # so there is nothing to clone here: Cargo fetches it, and --locked + # holds it to the lock. # Both hosts build in this one job because the cpex path dependency # has to resolve even when the `cpex` feature is off. diff --git a/CHANGELOG.md b/CHANGELOG.md index 092d6d5..a39747f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,9 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). - **The validator declares its Python floor.** `scripts/aid_emit1_validator.py` requires 3.10+ for `zip(..., strict=True)` (which the repo's ruff B905 rule mandates, so it isn't going away) and said so nowhere — an outside verifier hit it as an opaque `TypeError` deep in a chain check. Now a docstring line and a startup version gate with a message that names the requirement. - **Corrected two question citations in the WS4 #172 evidence-contract mapping.** `docs/cosai-ws4-ocsf-mapping/evidence-contract-ocsf-mapping.md` is linked from a CoSAI thread that now has named reviewers, and two of its citations did not survive a check against the issue text as filed. (1) The header claimed the document as the **Q14/Q15** deliverable, but WS4 #172 Q15 asks for the false-positive profile of normal agent behaviour and what cross-run correlation requires operationally — detection-side material the document explicitly defers in its own scope note. Header retitled to Q14 alone, and the scope note now says plainly that Q15 is out of scope and unclaimed, matching what the CHANGELOG entry for #493 already said. (2) The schema gap register cited **Q16** for cross-boundary causal binding; Q16 is reachability minimisation versus patch hygiene (§9). The resource owner's record naming the causing tool call is the evidence complement of §5 (Q9–Q10), where a permitted party acts on the agent's behalf — re-cited accordingly. No mapping row, status, or OCSF claim changes. Docs only — no product impact. +### Changed +- **The OCSF audit plugin tracks PR #84 at `499ee91` and holds `base64` at 0.22 to match the PPE tree.** Teryl answered the two dependency findings on praxis-proxy/policy PR #84 on 2026-09-09: `sha2` is now a workspace dependency at `0.11` (`ef20d8f`), and `base64` stays at `0.22` across the tree because `jsonwebtoken` 11, which `identity-jwt` depends on, requires it, so `0.23` would put two majors in the build (verified against the PPE lock). The same head merges the #82 docs reorganisation, which moves the auditing guide to `docs/content/auditing.md`; nothing on the seam this crate consumes changed between `3e7734e` and `499ee91`. `integrations/cpex-ocsf-audit` moves its pin to that head and its `base64` requirement from `0.23` (a Renovate bump, #497) down to `0.22`, so the copy that lands under `reference/plugins/ocsf-audit` (`PRAXIS-INTREE-PLAN.md`) is a copy and the PPE build stays on one base64; a Renovate rule holds it there. Verified the way CI runs it, on toolchain 1.96.1 with a cpex sibling at `64c8eba`: warning-free `--locked` builds and 34 tests green on each host, `emit_sample` and `decision_sink_demo` byte-identical to the committed vectors, so the AID-EMIT-1 section 12 conformance vector is untouched. The in-tree plan drops `sha2` and `base64` from its list of workspace-table adds (only `p256` remains), records the `base64` answer as settled, and follows the auditing guide to its new path. He also repeated that the `plugin_settings:` load error predates #84 (praxis-proxy/policy #55), which `PRAXIS-PORT-RESULTS.md` observation 3 already records. + ### Added - **The in-tree port plan now sizes the `base64` version conflict, and answers the #84 review's version-spec claim before it reaches our PR.** `PRAXIS-INTREE-PLAN.md` listed `p256`, `sha2` and `base64` as three equal adds to PPE's `[workspace.dependencies]`. Read against the manifests at `3e7734e`, only `p256` is one: `sha2 = "0.11"` is already declared directly by four crates (`ppe-core`, `ppe-apl-runtime`, `builtins/plugins/delegator-oauth`, `builtins/session/valkey`) at the version this crate uses, which is the inconsistency praxis-bot flagged on PR #84 on 2026-09-09, and `base64` is a conflict rather than an add, since `identity-jwt`, `delegator-oauth` and `elicitation-ciba` each declare `0.22` directly while this crate is on `0.23`, a semver-incompatible major. The plan's default is now to pin this crate down to `0.22`: base64 is reached only through `Engine::encode` and `Engine::decode` on `general_purpose::STANDARD` in `src/sign.rs` and `src/emitter.rs`, an API unchanged across both versions, so the expected cost is the manifest line rather than a base64 upgrade across three builtins the port PR has no other reason to touch. Carrying both majors is the third option and the worst one; `deny.toml` sets `multiple-versions = "warn"`, so `make audit` would not fail, but the tree has one major today. The choice goes to the PR thread as an open question. The plan also records that the other half of the #84 review, a patch component on the version spec (`sha2 = "0.11.0"`), is not this tree's convention: the workspace table uses `tokio = "1"`, `thiserror = "2"` and `hashbrown = "0.17"` throughout. Docs only, no product impact. - **In-tree port plan for the OCSF plugin into praxis-proxy/policy.** Teryl settled the two open decisions on 2026-09-08 after talking to Fred: the plugin lands under `reference/plugins/ocsf-audit` next to `audit-logger`, `publish = false` and not supported, and moves to `builtins/` after feedback; the source is this directory on `main` (v0.0.3, 34 tests, AID-EMIT-1 1.1.0), not cpex#128, and he will swap the link on praxis #12. `PRAXIS-INTREE-PLAN.md` records the decisions and everything PPE's own rules demand of the copy, read from `CONTRIBUTING.md`, `AGENTS.md`, the workspace lints, `clippy.toml`, `.markdownlint.yaml` and `deny.toml` at `3e7734e`: human-signed commits with no AI trailers, two-line SPDX headers, no history in comments (93 lines to restate), edition 2024, and a lint set that denies `unwrap_used`, `missing_assert_message` (159 sites), `print_stdout`, `missing_docs` and `doc_markdown`, with `allow-git = []` so `p256`, `sha2` and `base64` join `[workspace.dependencies]`. It sizes each pass, lists what is not carried (`run-demo.sh`, the measurement records, the lock), sets the acceptance bar (34 green, `emit_sample` byte-identical to the section 12 vector, zero mapping diff), and offers the history-preserving `git-filter-repo` import PPE documents in `docs/port-provenance.md` as the recommended landing. Gated on PR #84 merging; the earlier one-hour estimate becomes a day. Docs only, no product impact. diff --git a/integrations/cpex-ocsf-audit/Cargo.lock b/integrations/cpex-ocsf-audit/Cargo.lock index a531138..24f179c 100644 --- a/integrations/cpex-ocsf-audit/Cargo.lock +++ b/integrations/cpex-ocsf-audit/Cargo.lock @@ -51,9 +51,9 @@ checksum = "fd307490d624467aa6f74b0eabb77633d1f758a7b25f12bceb0b22e08d9726f6" [[package]] name = "base64" -version = "0.23.1" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" @@ -643,7 +643,7 @@ dependencies = [ [[package]] name = "praxis-policy-core" version = "0.2.0" -source = "git+https://github.com/praxis-proxy/policy?rev=3e7734ed46609e337d14262aaa6d152eb5757732#3e7734ed46609e337d14262aaa6d152eb5757732" +source = "git+https://github.com/praxis-proxy/policy?rev=499ee91ff1e1102f3e38357450f3f9d4e213c602#499ee91ff1e1102f3e38357450f3f9d4e213c602" dependencies = [ "arc-swap", "async-trait", @@ -669,7 +669,7 @@ dependencies = [ [[package]] name = "praxis-policy-orchestration" version = "0.2.0" -source = "git+https://github.com/praxis-proxy/policy?rev=3e7734ed46609e337d14262aaa6d152eb5757732#3e7734ed46609e337d14262aaa6d152eb5757732" +source = "git+https://github.com/praxis-proxy/policy?rev=499ee91ff1e1102f3e38357450f3f9d4e213c602#499ee91ff1e1102f3e38357450f3f9d4e213c602" dependencies = [ "futures", "tokio", diff --git a/integrations/cpex-ocsf-audit/Cargo.toml b/integrations/cpex-ocsf-audit/Cargo.toml index 080fa1c..fe5780a 100644 --- a/integrations/cpex-ocsf-audit/Cargo.toml +++ b/integrations/cpex-ocsf-audit/Cargo.toml @@ -49,15 +49,27 @@ ppe = ["dep:praxis-policy-core"] # Pin a rev rather than tracking `dev` for anything reproducible. cpex-core = { path = "../../../cpex/crates/cpex-core", optional = true } -# The PR #84 head, `3e7734e`, which accepts the documented -# `engine_settings` audit keys at load (PRAXIS-PORT-RESULTS.md obs 1). A -# full SHA, not a branch: the PR is a draft and its branch will move. +# The PR #84 head, `499ee91` (2026-09-09): `3e7734e` accepted the +# documented `engine_settings` audit keys at load (PRAXIS-PORT-RESULTS.md +# obs 1), `ef20d8f` made `sha2` a workspace dependency, and the rest is +# the docs reorganisation (#82) merged in, with `docs/auditing.md` now at +# `docs/content/auditing.md`. Nothing on the seam this crate consumes +# changed between the two heads. A full SHA, not a branch: the PR is a +# draft and its branch will move. # Bump deliberately, with the crate re-verified — the same rule as the # cpex pin in .github/workflows/rust.yml. -praxis-policy-core = { git = "https://github.com/praxis-proxy/policy", rev = "3e7734ed46609e337d14262aaa6d152eb5757732", optional = true } +praxis-policy-core = { git = "https://github.com/praxis-proxy/policy", rev = "499ee91ff1e1102f3e38357450f3f9d4e213c602", optional = true } async-trait = "0.1" -base64 = "0.23" +# 0.22, not the current 0.23: praxis-proxy/policy holds base64 at 0.22 +# because `jsonwebtoken` 11 (identity-jwt) depends on it, and this crate +# is copied into that tree as `reference/plugins/ocsf-audit` +# (PRAXIS-INTREE-PLAN.md). Pinning down here keeps the copy a copy and the +# PPE build on one base64. Only `Engine::{encode,decode}` on +# `general_purpose::STANDARD` is used, identical across both majors; +# the conformance vectors are byte-identical either way. Hold it here +# until the in-tree copy lands or the PPE tree moves. +base64 = "0.22" chrono = { version = "0.4", features = ["serde"] } # ECDSA P-256 for the DSSE signer — same curve as the production JWKS # (https://api.ai-identity.co/.well-known/ai-identity-public-keys.json). diff --git a/integrations/cpex-ocsf-audit/PRAXIS-INTREE-PLAN.md b/integrations/cpex-ocsf-audit/PRAXIS-INTREE-PLAN.md index 9adc50d..4e2ba88 100644 --- a/integrations/cpex-ocsf-audit/PRAXIS-INTREE-PLAN.md +++ b/integrations/cpex-ocsf-audit/PRAXIS-INTREE-PLAN.md @@ -33,9 +33,11 @@ Settled with Teryl on Slack, 2026-09-08, after he talked to Fred: ## PPE rules the copy must satisfy -Read from `praxis-proxy/policy` at `3e7734e`: `CONTRIBUTING.md`, `AGENTS.md`, -`Cargo.toml` (workspace lints), `clippy.toml`, `.markdownlint.yaml`, -`deny.toml`, `docs/port-provenance.md`. +Read from `praxis-proxy/policy` at `3e7734e`, dependencies re-read at +`499ee91`: `CONTRIBUTING.md`, `AGENTS.md`, `Cargo.toml` (workspace lints), +`clippy.toml`, `.markdownlint.yaml`, `deny.toml`, `docs/port-provenance.md`. +The auditing guide moved from `docs/auditing.md` to `docs/content/auditing.md` +when #84 took the #82 docs reorganisation (`a1e8621`, `499ee91`). - **Commits.** Human-authored, `Signed-off-by` the human, no AI co-author or session trailers (`AGENTS.md`, first paragraph). Same rule as this repo's @@ -79,42 +81,41 @@ Read from `praxis-proxy/policy` at `3e7734e`: `CONTRIBUTING.md`, `AGENTS.md`, bar as the library. - **Dependencies.** `deny.toml` has `allow-git = []`: no git dependencies, so the pinned `praxis-policy-core` git dep becomes - `praxis-policy-core = { workspace = true }`. Every third-party dependency - must already be in `[workspace.dependencies]`; `p256`, `sha2` and - `base64` are not there today and are added in the same PR, `p256` with - `ecdsa`, `pem`, `pkcs8`. `serde`, `serde_json`, `chrono`, `async-trait`, - `tracing` and `tokio` exist. All are Apache-2.0 OR MIT, inside the - `deny.toml` allow-list. `make audit` (`cargo deny check`) is a CI gate. - - Two of the three are not clean adds, read from the manifests at - `3e7734e`. `sha2 = "0.11"` is already declared directly by four crates - (`ppe-core`, `ppe-apl-runtime`, `builtins/plugins/delegator-oauth`, - `builtins/session/valkey`) at the version this crate uses, the - inconsistency praxis-bot flagged on #84 on 2026-09-09; if Teryl lands the - workspace-dep half of that finding, the table entry arrives ahead of this - PR and the port matches it. `base64` is a version conflict rather than an - add: `identity-jwt`, `delegator-oauth` and `elicitation-ciba` each - declare `base64 = "0.22"` directly and this crate is on `0.23`, which is - semver-incompatible. `p256` is the only genuinely new dependency in the - tree. - - Pinning this crate down to `0.22` is the cheaper resolution and the - plan's default. base64 is reached only through `Engine::encode` and - `Engine::decode` on `general_purpose::STANDARD` (`src/sign.rs`, - `src/emitter.rs`), an API unchanged across both versions, so the expected - cost is the manifest line, to be confirmed by the build rather than - assumed. Taking the tree to `0.23` instead makes this PR a base64 upgrade - across three builtins it has no other reason to touch. Carrying both is a - third option and a worse one: `deny.toml` sets `multiple-versions = - "warn"`, so `make audit` would not fail, but the tree has one major of - base64 today and this PR is not the reason to make it two. + `praxis-policy-core = { workspace = true }`. `serde`, `serde_json`, + `chrono`, `async-trait`, `tracing`, `tokio` and, since `ef20d8f`, `sha2` + are in `[workspace.dependencies]` and are taken with `{ workspace = true }`. + `p256` is the one genuinely new dependency in the tree and joins the + table in this PR with `ecdsa`, `pem`, `pkcs8`. All are Apache-2.0 OR MIT, + inside the `deny.toml` allow-list. `make audit` (`cargo deny check`) is a + CI gate. + + How the other two resolved, read from the manifests at `499ee91`: + + - `sha2`. praxis-bot flagged four crates each declaring `sha2 = "0.11"` + directly on #84 (2026-09-09). Teryl answered with `ef20d8f`, "make sha + 0.11 a workspace dependency": `sha2 = "0.11"` is in the table and the + four crates take it from there. The port does the same and adds + nothing. + - `base64`. This crate was on `0.23`; `identity-jwt`, `delegator-oauth` + and `elicitation-ciba` declare `0.22` directly. Teryl settled it on the + same day: the tree stays on `0.22` because `jsonwebtoken` 11, which + `identity-jwt` depends on, requires base64 `0.22`, so `0.23` would put + two majors in the build (verified against the PPE lock: `jsonwebtoken + 11.0.0` lists `base64 0.22.1`). This crate is pinned down to `0.22` + ahead of the port. The cost was the manifest line, confirmed by the + build: base64 is reached only through `Engine::encode` and + `Engine::decode` on `general_purpose::STANDARD` (`src/sign.rs`, + `src/emitter.rs`), 34 tests green on both hosts, `emit_sample` and + `decision_sink_demo` byte-identical. `base64` is not in the workspace + table at `499ee91`; the port declares `base64 = "0.22"` directly, the + way the three builtins do, unless Teryl prefers a table entry. On the version spec itself, follow the table and not the bot. The #84 - review also asks for a patch component (`sha2 = "0.11.0"`), but - `[workspace.dependencies]` at `3e7734e` uses major or major.minor - throughout: `tokio = "1"`, `thiserror = "2"`, `hashbrown = "0.17"`, - `serde_yaml = "0.9"`. Expect the same comment on this PR and answer it - the same way. + review also asked for a patch component (`sha2 = "0.11.0"`), and + `ef20d8f` wrote `sha2 = "0.11"`, matching the rest of + `[workspace.dependencies]`: `tokio = "1"`, `thiserror = "2"`, + `hashbrown = "0.17"`, `serde_yaml = "0.9"`. Expect the same comment on + this PR and answer it the same way. - **Markdown.** 80-column prose, 120 in code blocks, tables exempt (MD013); every fence declares a language (MD040); no bare URLs (MD034); asterisk emphasis (MD049). Long prose lines today: `README.md` 89, @@ -141,8 +142,8 @@ reference/plugins/ocsf-audit/ Workspace edits in the same PR: add the path to `members` and `default-members` in the root `Cargo.toml` under the existing reference -comment; add the three dependencies to `[workspace.dependencies]`; -`docs/auditing.md` "PPE ships one, `audit-logger`" becomes two, with a +comment; add `p256` to `[workspace.dependencies]`; +`docs/content/auditing.md` "PPE ships one, `audit-logger`" becomes two, with a `kind: audit/ocsf` YAML block after the `audit-logger` one; `README.md` line 52 "two worked examples" becomes three. `kind` stays `audit/ocsf`. @@ -232,10 +233,10 @@ reflow. Plan a day, verified against the acceptance list, not an hour. ## Open questions for the PR thread -- Whether `base64` enters `[workspace.dependencies]` at `0.22` with this - crate pinned down to match the three builtins, or at `0.23` with those - builtins bumped in the same PR. Pinning down is the plan's default; - Teryl's call. +- *(Settled 2026-09-09.)* `base64` stays at `0.22` in the tree, held there + by `jsonwebtoken` 11; this crate is pinned down to match. Still open is + only whether the port declares it directly, as the three builtins do, or + adds a workspace table entry. - `doc-valid-idents` additions in `clippy.toml` for OCSF, DSSE, PAE, ECDSA, AID-EMIT-1, or backticks throughout; Teryl's preference. - Whether the praxis `demos` repository, which registers the reference diff --git a/integrations/cpex-ocsf-audit/PRAXIS-PORT-RESULTS.md b/integrations/cpex-ocsf-audit/PRAXIS-PORT-RESULTS.md index affa64f..254f956 100644 --- a/integrations/cpex-ocsf-audit/PRAXIS-PORT-RESULTS.md +++ b/integrations/cpex-ocsf-audit/PRAXIS-PORT-RESULTS.md @@ -10,6 +10,11 @@ auditing", closes praxis#11), head `20798ae` — five commits on top of `main` `rust-toolchain.toml` says 1.96.0, its MSRV) **Baseline it is compared with:** the same crate on cpex `feat/audit-seam` `64c8eba` (the CI pin), run the same day on the same toolchain. +**Re-verified 2026-09-09** against PR #84 head `499ee91` (`3e7734e` plus +`ef20d8f`, sha2 as a workspace dependency, and the docs reorganisation +from #82; no seam change), with this crate on base64 0.22: warning-free +`--locked` builds and 34 tests green on each host, `emit_sample` and +`decision_sink_demo` byte-identical to the committed vectors. This is the re-run `PRAXIS-PORT-PLAN.md` describes: same crate, same protocol as `SEAM-PORT-RESULTS.md`, retargeted at the praxis seam. The plan expected diff --git a/integrations/cpex-ocsf-audit/README.md b/integrations/cpex-ocsf-audit/README.md index 6ae1bd2..0dccaa6 100644 --- a/integrations/cpex-ocsf-audit/README.md +++ b/integrations/cpex-ocsf-audit/README.md @@ -68,9 +68,10 @@ record it emits is a real fail-closed deny on the host-named stream. > policy dispatch, which refuses a hook-listed plugin that carries a > `priority:`. The plugin host is `PolicyEngine`, with the same > `register_factory` / `load_config` / `initialize` surface. The audit keys -> `docs/auditing.md` documents, `audit_stream_namespace` among them, load from -> the file as of PR #84 `3e7734e`, which fixed the allowlist gap reported as -> `PRAXIS-PORT-RESULTS.md` observation 1. +> `docs/content/auditing.md` documents, `audit_stream_namespace` among them, +> load from the file as of PR #84 `3e7734e`, which fixed the allowlist gap +> reported as `PRAXIS-PORT-RESULTS.md` observation 1. The crate pins the PR +> head at `499ee91` (2026-09-09), re-verified on both hosts. **Post-hook observer mode (legacy; pre-seam cpex):** list the CMF POST hooks to observe. This path sees allowed traffic only — it structurally cannot record a diff --git a/renovate.json b/renovate.json index 38d6ae9..0cc004b 100644 --- a/renovate.json +++ b/renovate.json @@ -41,6 +41,12 @@ "matchUpdateTypes": ["minor", "patch"], "groupName": "rust non-major" }, + { + "description": "cpex-ocsf-audit holds base64 at 0.22: praxis-proxy/policy is on 0.22 (jsonwebtoken 11 requires it) and the crate is copied into that tree; see the comment in its Cargo.toml", + "matchManagers": ["cargo"], + "matchPackageNames": ["base64"], + "allowedVersions": "<0.23" + }, { "description": "Majors always ride solo so each gets its own review", "matchUpdateTypes": ["major"],