Skip to content

feat: build the CPEX demo against the Praxis Policy Engine - #9

Draft
araujof wants to merge 5 commits into
praxis-proxy:mainfrom
araujof:feat/ppe
Draft

feat: build the CPEX demo against the Praxis Policy Engine#9
araujof wants to merge 5 commits into
praxis-proxy:mainfrom
araujof:feat/ppe

Conversation

@araujof

@araujof araujof commented Aug 9, 2026

Copy link
Copy Markdown
Member

Builds the HR demo gateway against the new praxis-proxy/policy crates. Depends on praxis-proxy/praxis#943.

Draft until the engine is published, since praxis pins it by git revision rather than a version.

Changes

  • Bumps praxis-ai-proxy to a revision that wants praxis 0.5. The old pin wanted ^0.4, which [patch.crates-io] could not satisfy, so cargo silently pulled 0.4.1 from crates.io and the graph carried two praxis stacks. praxis-ai then built its pipeline from the one without the policy filter, producing unknown filter type: 'policy'.
  • Renames the enabling feature to policy-engine.

The engine itself needs no local checkout: praxis pins it by git revision, and the patch only redirects praxis-proxy-*, so cargo fetches it.

Verification

All 11 scenarios pass: identity, RFC 8693 token exchange, Cedar and CEL decisions, redaction, PII scanning, session taint across requests and principals, and out-of-band CIBA approval.

The policy documents are untouched. cpex.yaml and cpex-cel.yaml are byte-identical to their pre-port versions, which is the wire-compatibility guarantee demonstrated end to end.

Adds a second link, gateway/praxis-policy. praxis depends on the engine by
relative path and cargo resolves that lexically rather than through the .praxis
symlink, so ../praxis-policy lands inside the gateway directory. patch.crates-io
cannot redirect it either, because the engine is unpublished.

Bumps praxis-ai to a revision that wants praxis 0.5. The old pin wanted ^0.4, which
the patch could not satisfy, so cargo silently pulled 0.4.1 from crates.io and the
graph carried two praxis stacks. praxis-ai then built its pipeline from the one
without the policy filter, giving 'unknown filter type: policy'.

Renames the enabling feature off the old project name.

All eleven scenarios pass against the ported engine.

Signed-off-by: Frederico Araujo <frederico.araujo@ibm.com>
@araujof araujof changed the title Build the CPEX demo against the Praxis Policy Engine feat: build the CPEX demo against the Praxis Policy Engine Aug 9, 2026
araujof added 3 commits August 9, 2026 21:29
praxis now depends on the policy engine by git revision rather than a sibling
path, and the patch only redirects praxis-proxy-*, so cargo fetches the engine
itself. The second link is dead: verified the gateway builds without it.

Signed-off-by: Frederico Araujo <frederico.araujo@ibm.com>
The demo already showed the same policy expressed for two decision
points, Cedar and CEL. OPA is now gated and exposed in the engine the
same way, so the demo gains the third: cpex-opa.yaml carries the Rego
modules and an `opa` route step, praxis-opa.yaml selects it.

Verified against the running stack: all 11 scenarios pass, and OPA is
the component deciding rather than passing incidentally. Scenario 04
allows on `visibility=internal` and scenario 05 reports
`opa.policy_denied`, so the Rego rule was evaluated in both directions.

The gateway needs no change. Its `policy-engine` feature pulls `dep:ppe`,
which now carries `opa`, so the lock gains the regorus interpreter.

Signed-off-by: Frederico Araujo <frederico.araujo@ibm.com>
Praxis moved to the engine's single `builtins` umbrella, so the revision
this lock pins moves with it. A pure revision swap, 16 entries for 16: the
umbrella resolves to the same crates the nine enumerated features did.

Verified on a fresh stack under praxis-opa.yaml: 11 scenarios pass, and
scenario 05 still reports `X-Policy-Violation: opa.policy_denied` with no
Cedar or CEL code present, so the Rego decision point is still the one
deciding.

Signed-off-by: Frederico Araujo <frederico.araujo@ibm.com>
@jordigilh

Copy link
Copy Markdown
Contributor

Heads up — while independently digging into the cpex gateway's unknown filter type: 'policy' failure, I hit the exact same root cause you describe above (the old ^0.4 pin + [patch.crates-io] producing two praxis stacks, with praxis-ai building its pipeline from the copy missing the policy filter).

Opened #12 as a narrow, standalone fix for that: drops the personal HIL fork patch (verified its remaining changes already landed on praxis main independently) and pins praxis-proxy-filter to the same git tag ai uses so Cargo resolves one shared instance. It's unblocked and all 11 scenarios pass against it.

Since #12 touches the same gateway/Cargo.toml/Cargo.lock/build-gateway.sh, if it lands first this branch will need a small rebase once praxis#943 merges — the .praxis/ fork override block in particular will conflict since #12 removes it outright. Flagging now so it's not a surprise. Happy to help reconcile once #943 is in.

@araujof

araujof commented Aug 12, 2026

Copy link
Copy Markdown
Member Author

Heads up — while independently digging into the cpex gateway's unknown filter type: 'policy' failure, I hit the exact same root cause you describe above (the old ^0.4 pin + [patch.crates-io] producing two praxis stacks, with praxis-ai building its pipeline from the copy missing the policy filter).

Opened #12 as a narrow, standalone fix for that: drops the personal HIL fork patch (verified its remaining changes already landed on praxis main independently) and pins praxis-proxy-filter to the same git tag ai uses so Cargo resolves one shared instance. It's unblocked and all 11 scenarios pass against it.

Since #12 touches the same gateway/Cargo.toml/Cargo.lock/build-gateway.sh, if it lands first this branch will need a small rebase once praxis#943 merges — the .praxis/ fork override block in particular will conflict since #12 removes it outright. Flagging now so it's not a surprise. Happy to help reconcile once #943 is in.

Thanks for the heads up! The plan is to merge this PR as soon as we publish PPE (which will replace cpex as a dependency in praxis). Merging #12 now, will reconcile with this one.

Reconciles praxis-proxy#12, which dropped the HIL fork patch and moved the demo onto
published praxis. All three conflicts are the same decision, where praxis comes
from, and all resolve to this branch: the demo exercises the Praxis Policy
Engine, and no published praxis carries the `policy-engine` feature yet.

Taken from main: the praxis-ai revision bump. Ours was a strict ancestor of it,
148 commits behind on the same line, so it is a clean upgrade.

That bump turned out to introduce the exact problem praxis-proxy#12 describes, and the fix
needed here differs from main's. Between the two revisions praxis-ai moved its
praxis-proxy-* dependencies from crates.io to a git tag, and
`[patch.crates-io]` cannot redirect a git dependency. The graph ended up with
two copies of praxis-proxy-filter: the patched local one carrying
`policy-engine`, and the tagged one from v0.5.2 without it. The AI server
registers filters from its own copy, so the `policy` filter would have silently
never loaded. A second `[patch]` on the git source unifies both references on
the local checkout; the lock now resolves one copy.

Also restored two blocks that git deleted without reporting a conflict, because
main removed them and the removals merged cleanly: the `[patch.crates-io]`
section itself, and the praxis-resolution step in build-gateway.sh. Without
them the tree documents a `.praxis` checkout it never creates and quietly
resolves praxis from crates.io. Its default ref is now `main` rather than the
retired fork branch.

Verified against the running stack, not just a build. All 11 scenarios pass on
the OPA config, and each of the three decision points is confirmed to be the
one deciding: `opa.policy_denied`, `cedar.default_deny`, `cel.policy_denied`.

Signed-off-by: Frederico Araujo <frederico.araujo@ibm.com>
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