Skip to content
Open
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
2 changes: 2 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions _context/wiki/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Origin and Host settings retain the explicitly configured
| `--token-verification-public-key <path>` | `CONTEXTFORGE_DATA_PLANE_TOKEN_VERIFICATION_PUBLIC_KEY` | For RSA tokens | Verifies `RS256`, `RS384`, and `RS512` tokens. |
| `--token-verification-secret <secret>` | `CONTEXTFORGE_DATA_PLANE_TOKEN_SECRET` | For HMAC tokens | Verifies `HS256`, `HS384`, and `HS512` tokens. |
| `--token-verification-private-key <path>` | `CONTEXTFORGE_DATA_PLANE_TOKEN_VERIFICATION_PRIVATE_KEY` | Required when built with `with_tools` | Signs tokens for the optional local bootstrap helper. |
| `--task-handle-key <key>` | `CONTEXTFORGE_DATA_PLANE_TASK_HANDLE_KEY` | Optional | Base64url-no-pad 32-byte AES-256 key. Share it across replicas; rotation invalidates outstanding handles. |

### MCP request validation

Expand Down
7 changes: 7 additions & 0 deletions _context/wiki/routing.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ The gateway wraps per-backend cursors inside its own opaque token (JSON, treated

**Known limitation:** if backend set changes between pages, removed backend's cursor is silently dropped.

## Task Handles

- Never expose an upstream task ID directly.
- Encode it as `cfth1.<base64url>` with AES-256-GCM and a random nonce.
- Bind the payload to JWT `sub`, virtual host, and backend; reject mismatches and removed backends as `invalid task ID`.
- Handles are stateless. Replicas must share the key; key rotation invalidates outstanding handles.

## Session State (local process)

Backend RMCP services are stored in `BackendTransports` keyed by:
Expand Down
3 changes: 3 additions & 0 deletions _context/wiki/security.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ dataplane contract.
| If this is compromised | Impact |
| --- | --- |
| JWT signing key or HMAC secret | Attacker mints tokens for any subject and reaches that subject's backends. Rotate the key and restart; no revocation exists. |
| Task-handle key | Attacker decrypts or forges upstream task routes. Rotate the key; outstanding handles become invalid. |
| Redis write access | Attacker rewrites routing (arbitrary backend URLs receive caller traffic) and, if runtime plugins are enabled, chooses which registered hooks run on payloads. Protect Redis with TLS/mTLS and control-plane-only write access. |
| A backend MCP server | Attacker sees requests routed to that backend and controls its responses; the namespace prefix limits blast radius to that backend's objects. |
| The gateway process | Full compromise: it holds the decoding keys in memory and live backend sessions. |
Expand Down Expand Up @@ -79,4 +80,6 @@ These routes are registered **outside the authentication middleware** — unauth
## Secrets Handling

- The HMAC secret is held as a `SecretString`; key and certificate material is read from disk paths at startup.
- Task handles are authenticated, encrypted, and scoped to JWT `sub` + virtual host + backend. They do not replace JWT validation.
- Never log: tokens, authorization headers, secrets, Redis key/value bytes, full `UserConfig` documents, or backend credentials.
- Treat task handles as opaque; do not log them.
2 changes: 2 additions & 0 deletions crates/contextforge-data-plane-lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ tokio-rustls = "0.26.4"
typed-builder = "0.23.2"
url = { workspace = true, features = ["serde"] }
secret-string = "0.0.2"
base64 = "0.22.1"
ring = "0.17.14"


[features]
Expand Down
6 changes: 6 additions & 0 deletions crates/contextforge-data-plane-lib/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use thiserror::Error;
use typed_builder::TypedBuilder;
use url::Url;

use crate::task_handle::TaskHandleKey;
use crate::user_config_store::UserConfigStore;

#[derive(Clone)]
Expand Down Expand Up @@ -156,6 +157,11 @@ pub struct Config {
#[arg(long, env = "CONTEXTFORGE_DATA_PLANE_TOKEN_SECRET")]
pub token_verification_secret: Option<SecretString<String>>,

/// Shared AES-256 key used to protect stateless task handles. The value is
/// URL-safe base64 without padding and must decode to exactly 32 bytes.
#[arg(long, env = "CONTEXTFORGE_DATA_PLANE_TASK_HANDLE_KEY")]
pub task_handle_key: Option<TaskHandleKey>,

#[arg(long, env = "CONTEXTFORGE_DATA_PLANE_ENABLE_OPEN_TELEMETRY")]
pub enable_open_telemetry: Option<bool>,

Expand Down
1 change: 1 addition & 0 deletions crates/contextforge-data-plane-lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ mod common;
mod const_values;
mod gateway;
mod layers;
pub mod task_handle;
mod telemetry;
mod transports;

Expand Down
Loading
Loading