Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).

## [Unreleased]

## [0.3.1] - 2026-10-15

### Added

- Host opt-in for delegated credentials: `cpex_apl_install` flag `CPEX_APL_EXPOSE_DELEGATED_CREDENTIALS` (Go `WithDelegatedCredentials()`) returns the credentials `delegate()` minted on allowed results as `delegated_credentials` (Go `PipelineResult.DelegatedCredentials`, value redacted when printed). Additive; the C ABI stays at 3.

## [0.3.0] - 2026-10-14

CPEX now runs on the [praxis-policy engine](https://github.com/praxis-proxy/policy) (PPE) 0.5.0 from crates.io instead of its own engine crates. API names, hook names, several config keys, defaults and security checks change. The [migration guide](docs/content/docs/migration-0.3.md) lists every change by surface.
Expand Down Expand Up @@ -211,7 +217,8 @@ PPE 0.5.0 also updates CEL to 0.15, adds the `delegator/vault` builtin, validate

- Initial release

[Unreleased]: https://github.com/contextforge-org/cpex/compare/0.3.0...HEAD
[Unreleased]: https://github.com/contextforge-org/cpex/compare/0.3.1...HEAD
[0.3.1]: https://github.com/contextforge-org/cpex/compare/0.3.0...0.3.1
[0.3.0]: https://github.com/contextforge-org/cpex/compare/0.2.3...0.3.0
[0.2.3]: https://github.com/contextforge-org/cpex/compare/0.2.2...0.2.3
[0.2.2]: https://github.com/contextforge-org/cpex/compare/0.2.1...0.2.2
Expand Down
12 changes: 6 additions & 6 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,17 +85,17 @@ and a `version`; when adding a new internal dependency, include the `version` so
the crate remains publishable. `cpex-ffi` is `publish = false` (distributed as
signed prebuilt artifacts).

For 0.3.0 the complete crates.io publish order is `cpex-hosts-python`,
For 0.3.1 the complete crates.io publish order is `cpex-hosts-python`,
`cpex-plugin-delegator-biscuit`, `cpex`, then `cpex-python`. The facade consumes
PPE 0.5.0 from crates.io; the removed CPEX core, SDK, APL and builtin crates
remain at 0.2.3 and must not be added back to the release list.

Run the local preparation checks before tagging:

```bash
make release-check VERSION=0.3.0 # manifests, Go demo, PPE pins, publish set, ABI
make release-dry VERSION=0.3.0 # cargo-release preview; no changes
make release-verify VERSION=0.3.0 # lint, tests, verified .crates, FFI, examples
make release-check VERSION=0.3.1 # manifests, Go demo, PPE pins, publish set, ABI
make release-dry VERSION=0.3.1 # cargo-release preview; no changes
make release-verify VERSION=0.3.1 # lint, tests, verified .crates, FFI, examples
```

`make publish-dry` builds and verifies all four `.crate` archives in
Expand All @@ -112,8 +112,8 @@ The Rust workflow packages and verifies every retained crate before any
publish, and tests the facade with `python-host` enabled as well. The FFI
workflow checks all five target bundles, with Go race tests on the GNU/Linux
and macOS targets. Actual publishing requires a tag matching the workspace
version. `make tag VERSION=0.3.0` creates and pushes the `v0.3.0`,
`go/cpex/v0.3.0` and `0.3.0` tags; it starts publication immediately.
version. `make tag VERSION=0.3.1` creates and pushes the `v0.3.1`,
`go/cpex/v0.3.1` and `0.3.1` tags; it starts publication immediately.

The broader integration checks remain separate: `make test-python-e2e`
requires a compatible `CPEX_PYTHON_SOURCE` checkout, `make parity` needs
Expand Down
17 changes: 9 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ default-members = [
]

[workspace.package]
version = "0.3.0"
version = "0.3.1"
edition = "2024"
# MSRV — keep in sync with rust-toolchain.toml `channel` and clippy.toml `msrv`.
rust-version = "1.96"
Expand Down Expand Up @@ -96,9 +96,9 @@ praxis-policy-core = { version = "=0.5.0" }
# time cargo substitutes it for the `path`. `cargo release` keeps these in sync
# with the workspace version. Keys are package names (builtins differ from their
# directory names), paths are workspace-root-relative.
cpex = { path = "crates/cpex", version = "0.3.0" }
cpex-plugin-delegator-biscuit = { path = "builtins/plugins/delegator-biscuit", version = "0.3.0" }
cpex-hosts-python = { path = "crates/cpex-hosts-python", version = "0.3.0", default-features = false }
cpex = { path = "crates/cpex", version = "0.3.1" }
cpex-plugin-delegator-biscuit = { path = "builtins/plugins/delegator-biscuit", version = "0.3.1" }
cpex-hosts-python = { path = "crates/cpex-hosts-python", version = "0.3.1", default-features = false }

# Size-first release profile. The FFI artifact (libcpex_ffi.a) is linked
# statically into host binaries, so its compiled size flows straight into
Expand Down
1 change: 1 addition & 0 deletions crates/cpex-ffi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ default = []

[dev-dependencies]
async-trait = { workspace = true }
chrono = { workspace = true }
# Mint test JWTs and their JWKS for the identity-jwt egress tests. The key is
# generated at test time, so no private key is checked in.
jsonwebtoken = { version = "11", default-features = false, features = ["aws_lc_rs"] }
Expand Down
14 changes: 7 additions & 7 deletions crates/cpex-ffi/RELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ without needing a Rust toolchain.
This document covers what is published, how to consume and verify
an artifact, and the FFI ABI policy that makes the contract durable.

For CPEX 0.3.0, use the Go module tag `go/cpex/v0.3.0` together with the
`v0.3.0` FFI artifact. Both expect C ABI **3**; upgrade them together.
For CPEX 0.3.1, use the Go module tag `go/cpex/v0.3.1` together with the
`v0.3.1` FFI artifact. Both expect C ABI **3**; upgrade them together.

## Local preparation

```sh
make ffi-package VERSION=0.3.0 # host tarball + .sha256 in dist/
make ffi-verify VERSION=0.3.0 # checksum, metadata, ABI, Go vet + race tests
make ffi-package VERSION=0.3.1 # host tarball + .sha256 in dist/
make ffi-verify VERSION=0.3.1 # checksum, metadata, ABI, Go vet + race tests
```

Verification uses the extracted static library from a temporary SDK copy,
Expand Down Expand Up @@ -108,7 +108,7 @@ into your build (or fetch via `raw.githubusercontent.com` pinned to
a tag) and call it before `go build` / `cargo build` / etc.

```sh
export CPEX_FFI_VERSION=v0.3.0
export CPEX_FFI_VERSION=v0.3.1
ARTIFACT_DIR=$(bash scripts/download-ffi-artifact.sh)
export CGO_LDFLAGS="-L${ARTIFACT_DIR} -lcpex_ffi"
go build ./...
Expand All @@ -134,7 +134,7 @@ Subsequent runs against the same version + dest are no-ops.
If you want to do it by hand:

```sh
VER=v0.3.0
VER=v0.3.1
TUPLE=linux-amd64-gnu
BASE="https://github.com/contextforge-org/cpex/releases/download/${VER}"
NAME="cpex-ffi-${VER}-${TUPLE}.tar.gz"
Expand Down Expand Up @@ -168,7 +168,7 @@ unpacked artifact directory and the cgo `-L` from `LDFLAGS` will be
augmented by the env var:

```sh
ARTIFACT_DIR=$(CPEX_FFI_VERSION=v0.3.0 bash scripts/download-ffi-artifact.sh)
ARTIFACT_DIR=$(CPEX_FFI_VERSION=v0.3.1 bash scripts/download-ffi-artifact.sh)
CGO_LDFLAGS="-L${ARTIFACT_DIR}" go build ./...
```

Expand Down
17 changes: 15 additions & 2 deletions crates/cpex-ffi/src/apl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,17 @@ pub(crate) enum InstallState {
/// host decision; no policy document can turn it on.
pub const CPEX_APL_ALLOW_PRIVATE_DESTINATIONS: u32 = 1;

/// `cpex_apl_install` flag: return the delegated credentials minted by
/// `delegate()` steps on allowed results (`delegated_credentials`), so the
/// host can attach them to the upstream request. Off by default: without
/// it no token bytes leave Rust.
pub const CPEX_APL_EXPOSE_DELEGATED_CREDENTIALS: u32 = 2;

/// Every flag bit this build understands. Any other bit is rejected with
/// `RC_INVALID_INPUT`, so a host built against a newer flag set fails
/// loudly instead of silently losing a setting.
pub const CPEX_APL_KNOWN_FLAGS: u32 = CPEX_APL_ALLOW_PRIVATE_DESTINATIONS;
pub const CPEX_APL_KNOWN_FLAGS: u32 =
CPEX_APL_ALLOW_PRIVATE_DESTINATIONS | CPEX_APL_EXPOSE_DELEGATED_CREDENTIALS;

/// Install the bundled builtins, the outbound HTTP transport, and the
/// secret providers on `handle`.
Expand All @@ -73,7 +80,9 @@ pub const CPEX_APL_KNOWN_FLAGS: u32 = CPEX_APL_ALLOW_PRIVATE_DESTINATIONS;
/// `flags` is a bit set of `CPEX_APL_*` values. With
/// `CPEX_APL_ALLOW_PRIVATE_DESTINATIONS` set, the transport may reach
/// private and loopback addresses; without it, such requests are refused
/// and builtins report their egress-denied codes.
/// and builtins report their egress-denied codes. With
/// `CPEX_APL_EXPOSE_DELEGATED_CREDENTIALS` set, allowed results carry the
/// delegated credentials minted for the request.
///
/// Idempotent per handle: once a call has succeeded, later calls do
/// nothing and return `RC_OK`, whatever their flags. A call that panicked
Expand Down Expand Up @@ -139,6 +148,10 @@ pub unsafe extern "C" fn cpex_apl_install(handle: *const CpexEngineInner, flags:

match result {
Ok(()) => {
inner.expose_delegated_credentials.store(
flags & CPEX_APL_EXPOSE_DELEGATED_CREDENTIALS != 0,
std::sync::atomic::Ordering::Release,
);
*state = InstallState::Installed;
RC_OK
},
Expand Down
Loading
Loading