Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

feat(grid): add secure provider gateway boundary#386

Draft
nerdalert wants to merge 7 commits into
praxis-proxy:mainpraxis-proxy/ai:mainfrom
nerdalert:grid-credential-injectnerdalert/ai:grid-credential-injectCopy head branch name to clipboard
Draft

feat(grid): add secure provider gateway boundary#386
nerdalert wants to merge 7 commits into
praxis-proxy:mainpraxis-proxy/ai:mainfrom
nerdalert:grid-credential-injectnerdalert/ai:grid-credential-injectCopy head branch name to clipboard

Conversation

@nerdalert

@nerdalert nerdalert commented Jul 16, 2026

Copy link
Copy Markdown
Member

Dependencies

This PR is the final change in the existing Grid data-plane stack:

  1. feat(filters): add grid_route #339 adds grid_route.
  2. feat(grid): hot reload route overlays #540 adds overlay hot reload and authenticated provider-hop context.
  3. This PR adds the secure provider gateway boundary and final-hop credential replacement.

It remains draft until its dependencies land. No separate provider-boundary PR is required.

Summary

Adds the provider-side Praxis AI pipeline used after an edge grid_route decision:

edge grid_route
  -> mTLS provider connection
  -> peer_identity_trust
  -> request/model parsing
  -> grid_provider_route
  -> grid_credential_inject, when required
  -> load_balancer
  -> private provider backend

The provider gateway is a Praxis AI inference gateway, not a generic reverse proxy. It validates the edge-selected candidate against provider-local policy, selects a preconfigured local backend cluster, replaces customer credentials at the final hop, and forwards through the normal Praxis load-balancer pipeline.

grid_provider_route

grid_provider_route is an exact provider-local validation and mapping filter, not a second Grid routing engine. It maps:

authenticated selected candidate
  + model
  + request path
  + provider-local route map
  -> local backend cluster
  + optional credential reference metadata

It:

  • fails closed for missing, unknown, blank, or oversized candidate identity;
  • rejects disallowed models and paths;
  • strips spoofable edge/provider attribution and customer authorization state;
  • emits provider attribution from the provider gateway;
  • writes shared typed metadata for the selected local route;
  • selects only clusters declared in provider-local configuration.

Provider boundary enforcement

Proxy startup validation rejects a Grid provider chain unless:

  • the listener requires downstream client certificates;
  • peer_identity_trust is the first filter;
  • peer_identity_trust precedes grid_provider_route.

This keeps x-grid-peer-* values from being treated as trusted merely because they are present. They are consumed only after Praxis establishes the mTLS peer identity and the provider-local trust policy accepts it.

grid_credential_inject

The credential filter consumes credential-reference metadata from either grid_route or grid_provider_route. It:

  • resolves an allow-listed (name, namespace, key, strategy) entry;
  • supports mounted-file, environment, and explicit-value sources;
  • requires exactly one source per credential;
  • stores token material in zeroizing memory;
  • removes the incoming Authorization header;
  • injects the provider bearer token only on the final upstream hop;
  • fails closed for missing, malformed, unsupported, or unknown credential references.

Only references appear in Grid overlays and route metadata. Provider token values are not written to overlays, filter metadata, logs, or errors.

Architecture boundary

  • Grid owns discovery, admission, scoring, candidate ordering, and overlay rendering.
  • Edge grid_route makes the Grid candidate selection.
  • Provider grid_provider_route validates that selection against a local allow-list and maps it to a local cluster.
  • grid_credential_inject performs final-hop credential replacement.
  • Praxis core continues to provide generic mTLS, peer identity, filter execution, and load-balancer mechanics.

This PR does not add another scoring engine, session store, dynamic cluster system, credential subsystem, or Grid-specific Praxis core abstraction.

Validation

The final stacked head passes:

  • cargo +nightly fmt --all -- --check
  • cargo check --workspace
  • cargo test --workspace
  • cargo clippy --workspace --all-targets --all-features -- -D warnings
  • RUSTDOCFLAGS="-D warnings" cargo doc --workspace --no-deps
  • cargo xtask lint-separators
  • cargo xtask lint-filter-docs
  • git diff --check

Focused tests cover filter construction, chain validation, header stripping, unknown candidates, model/path denial, metadata output, credential replacement, missing credentials, and fail-closed runtime behavior.

The combined Grid GLB environment additionally proves the Praxis edge-to-provider mTLS hop, valid and invalid peer identities, provider-local route denial, private backend traversal, provider attribution, customer-token removal, and Secret-backed provider credential replacement.

Review focus

  • provider-chain startup invariants;
  • exact provider-local mapping semantics;
  • trusted-context stripping and reconstruction;
  • credential-reference bounds and fail-closed behavior;
  • absence of token material from metadata and diagnostics.

@praxis-bot praxis-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: Grid credential inject

Well-structured PR. The two-filter design (grid_route writes credential reference metadata, grid_credential_inject reads it and injects the bearer token) is clean separation of concerns. Security properties are solid: tokens stored in Zeroizing<String>, never written to metadata/traces/error bodies, fail-closed on mismatch. Config validation is thorough with deny_unknown_fields on all structs and bounded field lengths.

Findings

Severity Count
Critical 0
Large 0
Medium 4

See inline comments for details. Summary:

  1. [Medium] Doc table uses secret_ref (snake_case) but YAML config requires secretRef (camelCase) due to #[serde(rename_all = "camelCase")] on CandidateCredential. Will cause config parsing errors for users following the docs.
  2. [Medium] No functional integration test for grid-route-mcp.yaml example config. Only inference routing has an integration test in tests/schema/tests/suite/examples/ai/grid_route.rs. Project conventions require functional integration tests for all example configs.
  3. [Medium] No example config or functional integration test for grid_credential_inject. Unit tests are thorough, but project conventions require an example config in examples/configs/ and a corresponding integration test for new capabilities.
  4. [Medium] Test credential_not_written_to_route_metadata has a misleading name and checks keys that would never be written. Credential references ARE written to route metadata by record_route_decision (under grid.route.credential.*). The test only checks non-existent key patterns (grid.route.credential, grid.route.strategy, grid.route.secret_ref, grid.route.token), which pass trivially. The companion test credential_reference_written_to_route_metadata does the meaningful positive assertion.

Comment thread docs/filters/grid_route.md Outdated
Comment thread filters/src/grid/route.rs Outdated
Comment thread tests/schema/tests/suite/examples/ai/grid_route.rs
Add AI-owned grid_route inference and MCP tool routing under praxis-ai-filters and register it from praxis-ai-proxy.

The filter selects ctx.cluster from static candidates, prefers fresh candidates over stale, applies local-site preference on equal freshness, and routes MCP tools/call by mcp metadata with precedence over model-header routing.

Add docs, examples, and schema coverage for the new filter.

Signed-off-by: Brent Salisbury <bsalisbu@redhat.com>
Add an end-to-end schema test for the MCP grid_route example. The test runs the mcp filter, routes a tools/call request through grid_route, and verifies the selected tool-owning backend responds.

Signed-off-by: Brent Salisbury <bsalisbu@redhat.com>
Add overlay-file mode for grid_route with bounded reads, last-known-good reload behavior, parent-directory watching for Kubernetes ConfigMap symlink swaps, and ArcSwap-backed snapshot updates.

Include overlay example config, generated filter docs, and schema-level tests covering initial overlay routing and in-process hot reload. This is stacked on the grid_route PR and remains draft/WIP for broader review.

Signed-off-by: Brent Salisbury <bsalisbu@redhat.com>
Treat Grid candidate order as authoritative, enforce admission state, and retain existing-only candidates only for valid session bindings.

Accept the canonical credential.secretRef overlay shape while preserving the compatibility alias, and reject embedded credential values.

Signed-off-by: Brent Salisbury <bsalisbu@redhat.com>
Forward stable candidate and request identities only to explicitly configured provider-hop clusters. Strip client-supplied peer fields before writing canonical x-grid-peer values so direct backends never receive Grid peer context.

Use the AI-owned x-grid-peer namespace because Praxis reserves and removes x-praxis headers at upstream boundaries.

Signed-off-by: Brent Salisbury <bsalisbu@redhat.com>
Add grid_provider_route as an exact provider-local candidate, model, and path validation filter. Consume edge-selected peer context only after the Praxis mTLS and peer-identity chain, then map it to a configured local backend and optional credential reference.

Register shared Grid metadata contracts and reject provider pipelines that omit required client certificates, unconditional peer trust, or safe filter ordering. This is provider-local validation and mapping, not a second Grid routing decision.

Signed-off-by: Brent Salisbury <bsalisbu@redhat.com>
Bound credential counts, locator fields, token sources, and token bytes before request processing. Fail closed for incomplete, unsupported, or unknown references and keep resolved values in zeroizing storage.

Use the shared Grid credential metadata contract so both grid_route and grid_provider_route can select final-hop credentials without carrying secret bytes in overlays or peer headers.

Signed-off-by: Brent Salisbury <bsalisbu@redhat.com>
@nerdalert
nerdalert force-pushed the grid-credential-inject branch from bb1a97d to 2c88c95 Compare July 26, 2026 23:41
@nerdalert nerdalert changed the title Grid credential inject feat(grid): add secure provider gateway boundary Jul 26, 2026
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

Morty Proxy This is a proxified and sanitized view of the page, visit original site.