diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 923a5697..a4e7bd45 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -81,8 +81,8 @@ jobs: ref: ${{ github.event.pull_request.head.sha || github.sha }} - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2.9.1 - - name: Build the workspace - run: cargo build --locked --workspace --all-features + - name: Build the production binary for conformance testing + run: cargo build --locked -p contextforge-data-plane --features plugins - name: Strip the conformance binary run: strip target/debug/contextforge-data-plane diff --git a/.github/workflows/conformance.yml b/.github/workflows/conformance.yml index 6654fd94..506217cb 100644 --- a/.github/workflows/conformance.yml +++ b/.github/workflows/conformance.yml @@ -5,10 +5,6 @@ on: issue_comment: types: [created] -concurrency: - group: conformance-pr-${{ github.event.issue.number }} - cancel-in-progress: true - env: CARGO_TERM_COLOR: always @@ -19,6 +15,9 @@ jobs: github.event.issue.pull_request && github.event.comment.body == '/conformance' && contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association) + concurrency: + group: conformance-pr-${{ github.event.issue.number }} + cancel-in-progress: true permissions: actions: read contents: read @@ -62,8 +61,8 @@ jobs: with: tool: cargo-binstall - - name: Install cf-integration 0.3.1 binary - run: cargo binstall cf-integration@0.3.1 --no-confirm + - name: Install cf-integration 0.3.2 binary + run: cargo binstall cf-integration@0.3.2 --no-confirm - name: Prepare the exact data-plane image env: @@ -74,11 +73,6 @@ jobs: --binary contextforge-data-plane --image contextforge-data-plane:conformance - - name: Install Node.js 22 - uses: actions/setup-node@v6.5.0 - with: - node-version: 22 - - name: Run strict modern conformance id: conformance env: diff --git a/.secrets.baseline b/.secrets.baseline index 2cd6744a..05731c8e 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "(?x)(Cargo\\.lock$|\\.lock$)|^\\.secrets\\.baseline$|^.secrets.baseline$", "lines": null }, - "generated_at": "2026-09-04T15:25:27Z", + "generated_at": "2026-09-07T12:56:51Z", "plugins_used": [ { "name": "AWSKeyDetector" @@ -382,19 +382,11 @@ } ], "docker/docker-compose.yml": [ - { - "hashed_secret": "2a8bfc0ce436d55ca907d0162989481bcb7677b4", - "is_secret": false, - "is_verified": false, - "line_number": 189, - "type": "Secret Keyword", - "verified_result": null - }, { "hashed_secret": "fdda45b7f6d2ead95d9991fc4678640c3bab0d84", "is_secret": false, "is_verified": false, - "line_number": 363, + "line_number": 342, "type": "Secret Keyword", "verified_result": null }, @@ -402,7 +394,7 @@ "hashed_secret": "093d378410a5cfa4bd5088f3fef62fbdb8a95665", "is_secret": false, "is_verified": false, - "line_number": 369, + "line_number": 348, "type": "Secret Keyword", "verified_result": null }, @@ -410,7 +402,7 @@ "hashed_secret": "c3de40d5e3fc71ed62771c2127a8e42585026c97", "is_secret": false, "is_verified": false, - "line_number": 371, + "line_number": 350, "type": "Secret Keyword", "verified_result": null }, @@ -418,7 +410,7 @@ "hashed_secret": "4d4acd9b084d13f5fdb23807d857e1c48a1cfd0f", "is_secret": false, "is_verified": false, - "line_number": 460, + "line_number": 439, "type": "Secret Keyword", "verified_result": null }, @@ -426,7 +418,7 @@ "hashed_secret": "bd0160c2cf35d950843c88f3be2b9412ed71f485", "is_secret": false, "is_verified": false, - "line_number": 495, + "line_number": 474, "type": "Secret Keyword", "verified_result": null }, @@ -434,7 +426,7 @@ "hashed_secret": "293324f6824bb3a6db5c4dc42a60ddd4a9851c99", "is_secret": false, "is_verified": false, - "line_number": 658, + "line_number": 637, "type": "Hex High Entropy String", "verified_result": null } diff --git a/Makefile b/Makefile index 24a82517..2f8d118b 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ DETECT_SECRETS_EXCLUDE := '(?x)(Cargo\.lock$$|\.lock$$)|^\.secrets\.baseline$$' help: ## Show available commands @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-22s\033[0m %s\n", $$1, $$2}' -docker-prod: ## Build production Docker image (contextforge-data-plane:latest) from docker/Dockerfile +docker-prod: ## Build production Docker image with plugins and without testing-only with_tools docker build -t $(IMAGE_NAME) -f docker/Dockerfile . compose-up: ## Launch stack: nginx, control plane, redis, postgres, pgbouncer, dataplane, fast_time_server diff --git a/README.md b/README.md index 8dad5f3d..2f4afbfb 100644 --- a/README.md +++ b/README.md @@ -14,10 +14,16 @@ Build the production image and start the supported control-plane + data-plane test stack: ```bash +export CONTEXTFORGE_DATA_PLANE_JWKS_URL=https://your-issuer.example/.well-known/jwks.json make docker-prod make compose-up ``` +Replace the example JWKS URL with the HTTPS endpoint for the issuer of your +control-plane tokens. The production image includes the plugin factories and +`/contextforge-rs/health`; it does not include `with_tools`. That feature is for +testing only and enables unauthenticated token, JWKS, and config helpers. + The stack uses the current `fast_time_server` backend and exercises config publication through the external ContextForge control plane. See [getting-started.md](_context/wiki/getting-started.md) for the complete smoke @@ -72,29 +78,31 @@ cargo run --release \ --address 0.0.0.0:8001 \ --redis-port 6379 \ --redis-address 127.0.0.1 \ - --token-verification-public-key assets/jwt.key.pub \ - --token-verification-private-key assets/jwt.key \ + --jwks-url "$CONTEXTFORGE_DATA_PLANE_JWKS_URL" \ --number-of-cpus 16 \ --redis-mode=plain-text \ --upstream-connection-mode=plain-text-or-tls \ --runtime-plugins-enabled true ``` +### Testing-Only Bootstrap Helpers + +For local testing, explicitly enable `with_tools` and use its local JWKS +endpoint. Never enable this feature or use `--all-features` in production. ```bash -cargo run --features contextforge-data-plane-lib/with_tools \ +cargo run -p contextforge-data-plane --features with_tools \ -- \ ---address 0.0.0.0:8080 \ +--address 127.0.0.1:8080 \ --redis-address 127.0.0.1 \ --redis-port 6379 \ --redis-mode plain-text \ --token-verification-private-key ./assets/jwt.key \ ---token-verification-public-key ./assets/jwt.key.pub \ +--jwks-url http://127.0.0.1:8080/contextforge-rs/admin/.well-known/jwks.json \ --upstream-connection-mode plain-text-or-tls \ ---tls-address 0.0.0.0:8443 \ +--tls-address 127.0.0.1:8443 \ --server-private-key ./assets/tls_key.pem \ --server-certificate ./assets/tls_certificate.pem ---runtime-plugins-enabled true ``` ## Tracing and Metrics diff --git a/_context/wiki/architecture.md b/_context/wiki/architecture.md index 2fc8d141..ae34d161 100644 --- a/_context/wiki/architecture.md +++ b/_context/wiki/architecture.md @@ -29,8 +29,10 @@ at the RMCP boundary, so earlier middleware may return first. MCP header budgets apply before JWT verification, configuration reads, and body parsing. See [Security](security.md#mcp-origin-and-host-validation). -Health and development helper routes are registered outside the MCP auth/config -layers. MCP handlers consume typed extensions; they do not parse Redis keys. +Health is registered in every build outside the MCP auth/config layers, while +token, JWKS, and config helpers are compiled only with testing-only `with_tools`. +Both remain covered by the outer HTTP tracing and metrics layers. MCP handlers +consume typed extensions; they do not parse Redis keys. `tools/call` also reads the HTTP headers from the request-context `Parts`. ## Pipeline Shape diff --git a/_context/wiki/config.md b/_context/wiki/config.md index dfa53b99..0b1bd36c 100644 --- a/_context/wiki/config.md +++ b/_context/wiki/config.md @@ -294,7 +294,8 @@ docker compose -f docker/docker-compose-local.yaml exec -T redis \ }' ``` -Build and run with demo factories and runtime execution enabled: +For local testing only, build and run with demo factories, `with_tools` helpers, +and runtime execution enabled: ```bash cargo run -p contextforge-data-plane \ diff --git a/_context/wiki/deployment.md b/_context/wiki/deployment.md index 165fa335..b0cef3b2 100644 --- a/_context/wiki/deployment.md +++ b/_context/wiki/deployment.md @@ -24,7 +24,8 @@ operation. There is no sticky-session requirement. Follow `GET /contextforge-rs/health` returns HTTP `200` and `{"status":"healthy"}` without authentication in every build. It checks HTTP liveness, not Redis, -JWKS, plugin reload health, or backend readiness. Verify an authenticated routed +JWKS, plugin reload health, or backend readiness. The reference nginx also +exposes it at `/health`. Verify an authenticated routed request separately when checking deployment readiness. ## nginx Front-Door Routing @@ -67,6 +68,8 @@ Build a production binary with bundled plugin factories and without local bootstrap helpers: ```bash +make docker-prod +# Equivalent native build: cargo build --locked --release -p contextforge-data-plane --features plugins ``` @@ -74,11 +77,12 @@ That feature compiles factories; `--runtime-plugins-enabled true` and a valid Redis plugin document are still required to execute them. Production uses the issuer's JWKS endpoint and does not supply a local token-signing private key. -**The current reference `docker/Dockerfile` includes `with_tools`.** The image -workflow uses that Dockerfile, so its published images and the `docker-prod` -Compose example are not production-hardened builds. Package the production -binary above in a deployment image that excludes helpers before using it in a -real environment. The all-features CI conformance artifact includes helpers too. +`make docker-prod`, `docker/Dockerfile`, the image publishing workflow, and +CI's conformance binary build enable production plugin factories without +`with_tools`. Do not use `--all-features` for production artifacts: it enables +unauthenticated testing helpers and demo plugins. Set `--jwks-url` or +`CONTEXTFORGE_DATA_PLANE_JWKS_URL` to the token issuer's HTTPS JWKS endpoint; +the production dataplane does not receive a signing private key. The image workflow publishes `ghcr.io//contextforge-data-plane:latest` and `:v` on pushes to `main`, using the Cargo package version. Repeated diff --git a/_context/wiki/getting-started.md b/_context/wiki/getting-started.md index 04e2c75b..2f4a5e6d 100644 --- a/_context/wiki/getting-started.md +++ b/_context/wiki/getting-started.md @@ -233,39 +233,51 @@ docker compose -f docker/docker-compose-local.yaml down ## Full Docker Stack -The repository also contains a full Compose topology with nginx, the Python -control plane/built-in dataplane, Postgres, Redis, and automatic registration of -a Fast Time backend. **It needs configuration updates before it is a runnable -JWKS-based setup.** Use the local Cargo steps above for the working quick start. - -Before using the full topology: - -- Replace the old token public-key/secret settings with a reachable - `CONTEXTFORGE_DATA_PLANE_JWKS_URL` trusted by the Rust service. -- The current reference image includes `with_tools`, so it also needs an - explicit `--token-verification-private-key` path and mounted development key. - For production, package a build without helpers instead. -- Check that the control-plane publisher emits the current backend protocol - field and explicit object routes, with keys matching the extracted user ID. -- Match CPU and memory reservations to the Docker host and account for both - publisher and Rust-cache delay when verifying route changes. - -The Compose lifecycle targets are `make docker-prod`, `make compose-up`, and -`make compose-down`; their names do not imply production readiness. See -[Deployment](deployment.md#builds-and-images) for the current image boundary. -The reference nginx listener is `http://localhost:8080`, with external MCP at -`/contextforge-rs/servers/{virtual_host_id}/mcp`. Other MCP paths reach the -Python service. `fast_time_server` is a sample backend, not a gateway dependency. +The full Compose topology adds nginx, the Python control plane/built-in +dataplane, Postgres, Redis, and automatic registration of a Fast Time backend. +It requires a configured token issuer and compatible control-plane publisher; +the local Cargo workflow above supplies a self-contained development fixture. + +Set the HTTPS endpoint serving the signing keys for your control-plane tokens, +then build and start the stack: + +```bash +export CONTEXTFORGE_DATA_PLANE_JWKS_URL=https://your-issuer.example/.well-known/jwks.json +make docker-prod +make compose-up +``` + +Replace the example URL with your issuer's reachable JWKS endpoint. Compose +passes it to the Rust service. The production image includes plugin factories +and health, and excludes testing-only `with_tools` helpers and signing-key mounts. +Obtain bearer tokens through the control plane or configured identity provider. + +Check that the publisher emits the backend protocol field and explicit object +routes with keys matching the extracted user ID. Match resource reservations +to the Docker host, and account for publisher and Rust-cache delay when verifying +route changes. See [Deployment](deployment.md#builds-and-images). + +The reference nginx listener is `http://localhost:8080`. External MCP uses +`/contextforge-rs/servers/{virtual_host_id}/mcp`, and health is at `/health` or +`/contextforge-rs/health`. Other MCP paths reach Python. `fast_time_server` is a +sample backend, not a gateway dependency. + +Stop the stack with `make compose-down`; volumes are kept. ## cf-integration Conformance +Install the same released harness version used by CI. Conformance and Inspector +install and run Node/npm only inside Docker images. + ```bash -cargo binstall cf-integration@0.3.1 --no-confirm +cargo binstall cf-integration@0.3.2 --no-confirm make conformance ``` This runs the modern client and modern server eras through the committed external-dataplane `HEAD`, including fixture-direct server comparison and the -scoped client suite. Use `make conformance-bless` to replace all selected +scoped client suite. It uses the production build without `with_tools`; the +harness owns JWT signing, loopback JWKS, and Redis fixture publication. +Use `make conformance-bless` to replace all selected baselines transactionally after a fully successful run. Generated checkouts, results, reports, and logs stay under `.integration/`. diff --git a/_context/wiki/index.md b/_context/wiki/index.md index 364399ea..8fb2b6e2 100644 --- a/_context/wiki/index.md +++ b/_context/wiki/index.md @@ -16,7 +16,7 @@ then follow only the links that are relevant. | [mcp-capability-allocation.md](mcp-capability-allocation.md) | Tentative ContextForge 2.0 target topology, ownership, state model, Phase 1-4 roadmap, and Phase 3 flows | | [failure-modes.md](failure-modes.md) | HTTP/MCP/routing/backend/plugin failure table — exact HTTP codes and JSON-RPC errors | | [config.md](config.md) | Key CLI flags, JWT claims, UserConfig shape, plugin config, telemetry debugging, startup validation, local observability stack | -| [deployment.md](deployment.md) | External-dataplane deployment checklist, JWKS trust, health checks, nginx routing, TLS choices, replicas, Redis availability, and production build/image limitations | +| [deployment.md](deployment.md) | External-dataplane deployment checklist, JWKS trust, health checks, nginx routing, TLS choices, replicas, Redis availability, and production builds and image pinning | | [security.md](security.md) | Trust boundaries among the control plane, built-in dataplane, and external dataplane; Origin/Host validation; transport security; secrets handling | | [performance.md](performance.md) | Current cf-integration load commands, standalone/full-stack comparisons, and benchmark controls | | [testing.md](testing.md) | Workspace checks, in-repo integration tests, full-stack harness lanes, settings, and control-plane baseline | diff --git a/_context/wiki/performance.md b/_context/wiki/performance.md index f17a55f5..38655c9a 100644 --- a/_context/wiki/performance.md +++ b/_context/wiki/performance.md @@ -1,7 +1,7 @@ # Performance and Load Testing Load testing is owned by [`cf-integration`](https://crates.io/crates/cf-integration). -The commands below match **0.3.1**, the version pinned by this repository's +The commands below match **0.3.2**, the version pinned by this repository's conformance workflow. The old `scripts/cf-integration.sh` wrapper is no longer in this repository. @@ -11,7 +11,7 @@ Use Docker with enough resources for the selected topology. Install the pinned CLI and check its command reference: ```bash -cargo binstall cf-integration@0.3.1 --no-confirm +cargo binstall cf-integration@0.3.2 --no-confirm cf-integration load --help ``` @@ -70,7 +70,7 @@ Use equivalent backends, tools, hardware, authentication, policy, cache settings and client metadata for comparisons. A full-stack failure while discovering or publishing the catalog is a setup failure, not a throughput measurement. Standalone measurements omit control-plane publication and must be labeled as -such. See the [pinned harness documentation](https://github.com/contextforge-org/contextforge-dev-tools/blob/v0.3.1/README.md) +such. See the [pinned harness documentation](https://github.com/contextforge-org/contextforge-dev-tools/blob/v0.3.2/README.md) for topology and source selection. ## Benchmark Controls diff --git a/_context/wiki/preferences.md b/_context/wiki/preferences.md index cc75c8a6..b8f23b01 100644 --- a/_context/wiki/preferences.md +++ b/_context/wiki/preferences.md @@ -7,7 +7,7 @@ A change is not done until: 2. `cargo clippy --locked --workspace --all-targets -- -D warnings` is clean. 3. `cargo nextest run --locked --workspace --all-features` passes (fallback: `cargo test`). 4. `cargo deny check advisories bans licenses` passes (CI; pre-commit runs advisories and licenses). -5. `cargo build --locked --workspace --all-features` succeeds. +5. `cargo build --locked -p contextforge-data-plane --features plugins` succeeds (production feature selection). 6. If the change touches the hot path, update the matching wiki page in `_context/wiki/` in the same change. CI additionally runs `cargo shear --check-test-targets --deny-warnings --locked` diff --git a/_context/wiki/security.md b/_context/wiki/security.md index 638e9846..6bce9a18 100644 --- a/_context/wiki/security.md +++ b/_context/wiki/security.md @@ -123,7 +123,7 @@ The binary's `with_tools` feature forwards to - `GET /contextforge-rs/admin/.well-known/jwks.json` - `POST /contextforge-rs/admin/userconfigs/{user_id}` -These routes are registered **outside the authentication middleware** — unauthenticated by design. They exist only for local bootstrap. **Production builds must not enable this feature.** In a real deployment the control plane mints tokens and writes config. +These routes are registered **outside the authentication middleware** — unauthenticated by design. They exist only for local bootstrap. **Production builds must not enable this feature**, including through `--all-features`. In a real deployment the control plane mints tokens and writes config. `GET /contextforge-rs/health` is also unauthenticated, but is available in every build without `with_tools`. The local token and JWKS helpers use the same RSA diff --git a/_context/wiki/testing.md b/_context/wiki/testing.md index 37f7c902..af443955 100644 --- a/_context/wiki/testing.md +++ b/_context/wiki/testing.md @@ -16,13 +16,22 @@ cargo fmt --all --check cargo clippy --locked --workspace --all-targets -- -D warnings cargo nextest run --locked --workspace --all-features cargo deny check advisories bans licenses -cargo build --locked --workspace --all-features +cargo build --locked -p contextforge-data-plane --features plugins cargo bench --no-run cargo shear --check-test-targets --deny-warnings --locked ``` Use `cargo test` when nextest is unavailable. For wiki changes, also run `mdbook build _context/wiki` and `mdbook test _context/wiki`. +`with_tools` is for testing only. It provides unauthenticated token, JWKS, and +user-config helpers for local fixtures. The all-features unit test commands +include it. Production builds and conformance images omit it and must not use +`--all-features`. The harness owns conformance authentication and Redis setup. +`/contextforge-rs/health` is available without +this feature. See [Deployment](deployment.md#builds-and-images) for production +build commands and [Getting Started](getting-started.md#local-cargo-dev-workflow) +for local testing. + New protocol-sensitive tests target MCP `2026-07-28`, connect through `server/discover`, and send the required per-request client metadata. A small `compatibility` module retains `2025-11-25`/`initialize` migration cases. These @@ -86,18 +95,23 @@ so changes to `main` do not invalidate the artifact. It runs the modern client and modern server eras through the external dataplane in standalone mode. This starts Redis, the dataplane, nginx, and the official fixture without the control plane. The harness discovers the fixture's tools, resources, templates, and -prompts and publishes their routes and actual tool schemas through the -dataplane serializer. Selecting that lane also runs the fixture-direct server -leg and the scoped external-dataplane client leg: - -```bash -cargo binstall cf-integration@0.3.1 --no-confirm -make conformance -``` - -The Make target tests the committed data-plane `HEAD`. It rejects tracked -uncommitted changes because the CLI clones the selected repository and commit -into `.integration/`. To use another local CLI binary: +prompts and publishes their routes and actual tool schemas directly to Redis +as named MessagePack maps. Its own auth service signs test JWTs and serves +loopback JWKS; the production dataplane receives no signing key. Selecting that +lane also runs the fixture-direct server leg and the scoped external-dataplane +client leg: + +Install the pinned harness version from +[Getting Started](getting-started.md#cf-integration-conformance), then run +`make conformance`. CI installs that same version; conformance and Inspector +install and run Node/npm only inside Docker images. + +The Make target tests the committed data-plane `HEAD` and rejects tracked +uncommitted changes. The harness builds `CF_DATAPLANE_REF` from +`CF_DATAPLANE_REPO` using the production Dockerfile with `plugins` and without +`with_tools`. CI supplies a prebuilt production binary in its conformance image +and sets `CF_DATAPLANE_REF` empty to skip the source build. To use another local +CLI binary: ```bash CF_INTEGRATION=/path/to/cf-integration \ diff --git a/crates/contextforge-data-plane-lib/Cargo.toml b/crates/contextforge-data-plane-lib/Cargo.toml index d73d5ce5..5b151020 100644 --- a/crates/contextforge-data-plane-lib/Cargo.toml +++ b/crates/contextforge-data-plane-lib/Cargo.toml @@ -51,6 +51,7 @@ cel = "0.14.5" [features] default = [] +# Testing only: unauthenticated token, JWKS, and config helpers. Health is always available. with_tools = ["axum/json", "axum/query"] diff --git a/crates/contextforge-data-plane/Cargo.toml b/crates/contextforge-data-plane/Cargo.toml index cf301a13..cade2b62 100644 --- a/crates/contextforge-data-plane/Cargo.toml +++ b/crates/contextforge-data-plane/Cargo.toml @@ -35,6 +35,7 @@ rustls.workspace = true [features] plugins = ["dep:cpex-secrets-detection"] test-plugins = ["dep:cpex-payload-marker", "dep:cpex-text-prefixer", "dep:cpex-tool-namespace"] +# Testing only: unauthenticated token, JWKS, and config helpers. Never enable in production. with_tools = ["contextforge-data-plane-lib/with_tools"] [dev-dependencies] diff --git a/docker/Dockerfile b/docker/Dockerfile index 6005f0ab..05fd82e2 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -7,13 +7,14 @@ apt install -y ca-certificates protobuf-compiler EOF COPY . . +# Production builds exclude the testing-only with_tools feature. RUN --mount=type=cache,id=cargo,target=/usr/local/cargo/registry,sharing=locked \ --mount=type=cache,id=cargo-git,target=/usr/local/cargo/git,sharing=locked \ cargo fetch --locked RUN --mount=type=cache,id=cargo,target=/usr/local/cargo/registry,sharing=locked \ --mount=type=cache,id=cargo-git,target=/usr/local/cargo/git,sharing=locked \ --mount=type=cache,id=contextforge-data-plane-target,target=/app/target,sharing=locked \ - cargo build --release --features "contextforge-data-plane-lib/with_tools contextforge-data-plane/plugins" \ + cargo build --locked --release -p contextforge-data-plane --features plugins \ && mkdir -p /out \ && cp /app/target/release/contextforge-data-plane /out/contextforge-data-plane diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 918e3aaf..e8d95a31 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -74,8 +74,8 @@ services: - CONTEXTFORGE_DATA_PLANE_REDIS_PORT=6379 - CONTEXTFORGE_DATA_PLANE_REDIS_CONNECTION_MODE=plain-text - CONTEXTFORGE_DATA_PLANE_UPSTREAM_CONNECTION_MODE=plain-text-or-tls - - CONTEXTFORGE_DATA_PLANE_TOKEN_VERIFICATION_PUBLIC_KEY=/keys/jwt.key.pub - - CONTEXTFORGE_DATA_PLANE_TOKEN_VERIFICATION_PRIVATE_KEY=/keys/jwt.key + # Set the HTTPS JWKS endpoint for the token issuer in the host environment. + - CONTEXTFORGE_DATA_PLANE_JWKS_URL - RUST_LOG=debug sysctls: @@ -93,7 +93,7 @@ services: condition: service_healthy healthcheck: - ## Uncomment for HTTP healthcheck + # Health is available in production builds without with_tools. test: [ "CMD", @@ -122,13 +122,6 @@ services: cpus: '${GATEWAY_CPU_RESERVATION:-1}' memory: ${GATEWAY_MEM_RESERVATION:-512M} - # ────────────────────────────────────────────────────────────────────── - # Volume Mounts - # ────────────────────────────────────────────────────────────────────── - # Mount catalog configuration and SSL certificates - volumes: - - ../assets/:/keys:z # mount catalog configuration - contextforge-data-plane-one: image: ${IMAGE_LOCAL:-contextforge-data-plane:latest} container_name: contextforge-data-plane-one @@ -141,8 +134,8 @@ services: - CONTEXTFORGE_DATA_PLANE_REDIS_PORT=6379 - CONTEXTFORGE_DATA_PLANE_REDIS_CONNECTION_MODE=plain-text - CONTEXTFORGE_DATA_PLANE_UPSTREAM_CONNECTION_MODE=plain-text-or-tls - - CONTEXTFORGE_DATA_PLANE_TOKEN_VERIFICATION_PUBLIC_KEY=/keys/jwt.key.pub - - CONTEXTFORGE_DATA_PLANE_TOKEN_VERIFICATION_PRIVATE_KEY=/keys/jwt.key + # Set the HTTPS JWKS endpoint for the token issuer in the host environment. + - CONTEXTFORGE_DATA_PLANE_JWKS_URL - RUST_LOG=debug sysctls: @@ -166,13 +159,6 @@ services: cpus: '${GATEWAY_CPU_RESERVATION:-1}' memory: ${GATEWAY_MEM_RESERVATION:-512M} - # ────────────────────────────────────────────────────────────────────── - # Volume Mounts - # ────────────────────────────────────────────────────────────────────── - # Mount catalog configuration and SSL certificates - volumes: - - ../assets/:/keys:z # mount catalog configuration - contextforge-data-plane-two: image: ${IMAGE_LOCAL:-contextforge-data-plane:latest} container_name: contextforge-data-plane-two @@ -185,8 +171,8 @@ services: - CONTEXTFORGE_DATA_PLANE_REDIS_PORT=6379 - CONTEXTFORGE_DATA_PLANE_REDIS_CONNECTION_MODE=plain-text - CONTEXTFORGE_DATA_PLANE_UPSTREAM_CONNECTION_MODE=plain-text-or-tls - - CONTEXTFORGE_DATA_PLANE_TOKEN_VERIFICATION_PUBLIC_KEY=/keys/jwt.key.pub - - CONTEXTFORGE_DATA_PLANE_TOKEN_VERIFICATION_PRIVATE_KEY=/keys/jwt.key + # Set the HTTPS JWKS endpoint for the token issuer in the host environment. + - CONTEXTFORGE_DATA_PLANE_JWKS_URL - RUST_LOG=debug sysctls: @@ -210,13 +196,6 @@ services: cpus: '${GATEWAY_CPU_RESERVATION:-1}' memory: ${GATEWAY_MEM_RESERVATION:-512M} - # ────────────────────────────────────────────────────────────────────── - # Volume Mounts - # ────────────────────────────────────────────────────────────────────── - # Mount catalog configuration and SSL certificates - volumes: - - ../assets/:/keys:z # mount catalog configuration - mcp-counter-tool-one: image: ghcr.io/mcp-counter-tool:latest container_name: mcp-counter-tool-one