Skip to content

Provide secure multi-target OpenShell providers for Switchyard routing #8887

Closed as not planned

Description

@cjagwani

Parent Epic: #7937

Outcome

Switchyard judge, weak, and strong targets resolve to distinct OpenShell-managed provider identities without placing raw provider credentials in the sandbox or permitting direct-provider bypass.

Proposed V5 decision

Use three separately attached OpenShell providers for the first released-path integration:

  • judge/classifier;
  • weak/efficient; and
  • strong/capable.

Keep inference.local as Hermes's ordinary bootstrap/default route. Do not use it for Switchyard targets: the current gateway-wide inference route selects one host model and cannot represent two simultaneous target models plus a judge.

Canonical NemoClaw scope was accepted in #7937 on 2026-08-13. This recommendation defines the initial provider boundary, but it does not authorize activation or a support claim before the remaining release and qualification gates pass.

Provider bundle contract

NemoClaw should provision the bundle against the final OpenShell gateway and attach all three providers to the sandbox create/rebuild plan as one activation unit.

For each provider, the gateway-authored receipt or attestation must identify:

  • provider ID, resource version, type, workspace, and resolved profile revision;
  • a versioned digest of canonical non-secret endpoint/configuration data;
  • credential and configuration key names, never values; and
  • the sandbox-local provider endpoint used by the generated Switchyard llm_client.

NemoClaw generates Switchyard llm_clients and targets only from that committed evidence. Each llm_client receives an endpoint-scoped raw-key placeholder through api_key_env; Switchyard constructs the provider Authorization header. Set forward_auth = false so caller authorization cannot reach the judge or selected target.

Provider names are labels, not security identities. Any partial create or attach leaves routing inactive and rolls back or quarantines the incomplete bundle. No provider request may occur until all three identities and bindings are attested.

Current OpenShell gate (2026-08-27)

OpenShell v0.0.113 is released, but NVIDIA/OpenShell#2722 remains open. The current CLI cannot bind an update atomically to a previously observed provider ID plus resource version, and the read surface does not expose a stable endpoint/profile attestation.

OpenShell PR #2962 now proposes making built-in or imported provider profiles authoritative while retiring legacy public provider workflows. That direction aligns with this issue's declarative judge/weak/strong profiles and means NemoClaw must not depend on the legacy generic creation path. The PR is still open with a non-green required gate and does not implement #2722's conditional mutation or attestation contract.

Therefore the initial milestone is deliberately narrow:

  • qualify fresh creation of uniquely named judge, weak, and strong providers;
  • do not claim safe reuse, update, credential rotation, or mutation of existing provider records;
  • fail closed when a requested name already exists or its identity cannot be proven; and
  • keep mutation/rotation blocked until docs: add Brev troubleshooting guide #2722 or an accepted equivalent contract is released and qualified.

This fresh-only boundary remains intentionally narrower than the final lifecycle contract and may be tightened by security review.

Scope

  • Define stable semantic target identities for judge/classifier, weak/efficient, and strong/capable.
  • Transactionally create and attach the three-provider bundle against the final gateway authority.
  • Translate only attested OpenShell endpoint/model identities into Switchyard llm_clients, targets, and routes.
  • Keep raw provider credentials behind OpenShell placeholder rewriting.
  • Deny caller-auth forwarding, cross-provider placeholder use, and direct-provider bypass.
  • Keep the Switchyard path inactive when any provider, receipt, route, or policy binding is missing or inconsistent.
  • Validate two real target models and canonical routing evidence end to end.

Acceptance

  • A fresh onboarding flow creates and attaches judge, weak, and strong as one bundle with no manual credentials-add loop.
  • Two simultaneous real model targets return distinguishable, recorded responses.
  • Classifier/judge traffic uses its separately declared provider when the router requires it.
  • Switchyard target configuration contains no inference.local endpoint.
  • Raw provider credentials are absent from sandbox environment, files, argv, logs, errors, telemetry, and captured artifacts.
  • Caller-supplied authorization cannot reach or replace a gateway-owned credential; forward_auth remains false.
  • Each placeholder resolves only at its approved provider endpoint; cross-endpoint use and direct-provider bypass are denied.
  • Missing, partial, stale, duplicate-name, or unattestable provider state fails before routing activation or any provider request.
  • Existing-provider mutation, reuse, and credential rotation remain rejected until identity-bound CAS and secret-free endpoint/profile attestation are available and qualified.
  • Removing or losing one provider produces an explicit unavailable state rather than silent fallback to inference.local or another target.

Activity

  1. self-assigned this
    on Aug 12, 2026
  2. added
    area: networkingDNS, proxy, TLS, ports, host aliases, or connectivity
    area: providersInference provider integrations and provider behavior
    area: routingRequest routing, policy routing, model selection, or fallback logic
    on Aug 12, 2026
  3. cjagwani commented on Aug 12, 2026

    @cjagwani
    CollaboratorAuthor

    Maintainer design decision details are tracked in #8893; endpoint-bound OpenShell Providers v2 are the V1 boundary, not single-model inference.local.

  4. cjagwani commented on Aug 12, 2026

    @cjagwani
    CollaboratorAuthor

    The OpenShell 0.0.103 audit narrows the supported V1 provider boundary:

    • judge, weak, and strong must use distinct, non-overlapping host:port:path selectors;
    • OpenShell rejects different provider bindings on the same endpoint as ambiguous;
    • endpoint binding does not enforce the request JSON model field, so two tiers sharing a normal /v1/chat/completions endpoint cannot be claimed as model-isolated;
    • the existing unbound Hermes NVIDIA policy can conflict with a bound Switchyard target on the same endpoint and must be suppressed or rejected as part of Enforce Switchyard routing network, retry, fallback, and cancellation policy #8888;
    • routed calls must derive header_env from exact attached-provider credential keys; callers cannot supply literal credential values.

    Therefore the direct-provider V1 will require distinct model-pinned endpoints. Same-endpoint multi-model routing remains dependent on named multi-target inference.local support upstream. The public configure path should land with native activation and network/bypass enforcement, not as dormant provider scaffolding.

  5. cjagwani commented on Aug 12, 2026

    @cjagwani
    CollaboratorAuthor

    Provider transaction blocker discovered

    A security review of the proposed provider-mutation receipt found that a client-side read → CLI update → read sequence is not sufficient for #8887.

    OpenShell's gateway supports resource-version CAS internally, but the v0.0.104 CLI still sends provider updates with an empty ID and resource_version: 0. The gateway therefore resolves the current provider by name at mutation time. A concurrent update or delete/recreate can receive the submitted credential/config before NemoClaw's post-read detects identity drift. The secret-free inventory also exposes config key names, not an endpoint/config digest or resolved provider-profile revision.

    I did not publish the local receipt implementation because it would have detected drift only after credential delivery and could have been mistaken for endpoint attestation.

    The required upstream identity-bound transaction and attestation surface is now tracked in NVIDIA/OpenShell#2722: NVIDIA/OpenShell#2722

    Implication for this issue:

    • exact judge/weak/strong target validation must use provider ID + resource-version CAS before any credential mutation;
    • endpoint/profile attestation must come from a gateway-authored, secret-free receipt;
    • local post-verification is not an acceptable substitute;
    • packaging, Hermes activation, and topology work remain independent and can continue.
  6. cjagwani commented on Aug 13, 2026

    @cjagwani
    CollaboratorAuthor

    Selected V1 contract — direct endpoint-bound providers

    The V1 choice is option 2: separately attached OpenShell providers, not multi-target inference.local.

    The exact contract is:

    • judge, weak, and strong use unique provider names, profile IDs, environment keys, and non-overlapping model-pinned host:port:path endpoints;
    • Switchyard owns each target URL/model and reads the complete target header value from header_env;
    • the sandbox sees only revision-bound openshell:resolve:env:vN_* placeholders;
    • the Switchyard target client discards caller HTTP headers before adding target-owned headers, because OpenShell does not strip an arbitrary marker-free caller Authorization value;
    • OpenShell 0.0.103 resolves each placeholder only for its attached provider and bound endpoint, and missing/expired/mismatched placeholders fail before upstream bytes are sent;
    • provider-derived policy permits only the three reviewed endpoints.

    The first prototype can create fresh, uniquely named providers without mutating them. Canonical rotation/update remains blocked on NVIDIA/OpenShell#2722's exact provider-ID/resource-version mutation plus gateway-authored profile/config attestation. Until that exists, NemoClaw must not update a security-sensitive provider by mutable name and then treat a post-read as proof.

    Remaining proof items here are two distinct real models, a separate judge call, no raw-secret/caller-auth leakage, exact endpoint denial, restart persistence, and defined removal/failure behavior. Runtime provider failure also needs the fail-closed versus trusted-fallback decision tracked in #8888.

  7. cjagwani commented on Aug 13, 2026

    @cjagwani
    CollaboratorAuthor

    Draft integration slice security review

    The first native Hermes Relay/Switchyard configuration slice is safe to publish only as a dormant draft, not merge as a supported integration.

    What passes: secret-free durable profiles, fail-closed shape validation, same-revision OpenShell resolver checks, caller credential values excluded from durable files, exact generated TOML replay, root-owned read-only artifacts, stale configuration cleanup, and redacted errors.

    Merge blockers:

    1. Target URLs are currently caller-supplied HTTPS values rather than endpoints derived from an authoritative attached-provider receipt, leaving SSRF and credential-destination trust unresolved.
    2. The profile does not yet bind provider ID/resource version, endpoint/model, credential key, and policy into one gateway-authored attestation.
    3. The reviewed Switchyard plugin artifact/version/digest is not yet packaged, and startup does not prove nvidia.switchyard is active.
    4. Tests still need endpoint rejection, authoritative provider binding, missing/inactive plugin readiness, and full lifecycle coverage.

    The authorization chain required before merge remains:

    attached provider -> approved endpoint/model -> injected credential key -> active plugin -> readiness

    These blockers map to #8885, #8886, #8887, #8888, #8889, and NVIDIA/OpenShell#2722. The draft intentionally has no public onboarding producer or support documentation.

  8. cjagwani commented on Aug 13, 2026

    @cjagwani
    CollaboratorAuthor

    Draft #9012 implements the secret-free profile/TOML/runtime-placeholder mechanics for judge, weak, and strong. It remains dormant and does not satisfy this issue: endpoint/model/credential keys still need to be derived from authoritative attached-provider identity/resource-version and gateway-authored attestation before merge or public activation.

  9. cjagwani commented on Aug 24, 2026

    @cjagwani
    CollaboratorAuthor

    2026-08-24 provider-boundary contract update

    The final #528 contract supersedes the prototype header_env design. Switchyard deployment targets now use api_key_env containing the raw provider key; the Switchyard client constructs the Bearer header. NemoClaw should therefore provision an OpenShell resolver placeholder for the raw key, never a literal secret or prebuilt Authorization header.

    NemoClaw main now deliberately pins OpenShell 0.0.106, and the prior 0.0.103 upgrade work in #8893 is complete. Fresh uniquely named provider creation and attachment can be qualified independently. Security-sensitive mutation/rotation still requires NVIDIA/OpenShell#2722 or an equivalent identity plus resource-version conditional update and gateway-authored attestation contract.

    The production binding remains:

    attached provider identity -> approved endpoint/model -> api_key_env placeholder -> selected target policy -> active plugin/readiness

    #528 also still has an unresolved review concern around selected-target policy validation, so the supported path must not claim this boundary until both upstream target validation and NemoClaw endpoint/policy tests pass.

  10. cjagwani commented on Oct 27, 2026

    @cjagwani
    CollaboratorAuthor

    Superseded by #13863 under the replanned #7937 implementation. The replacement narrows the first slice to two freshly created OpenShell-managed targets.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area: networkingDNS, proxy, TLS, ports, host aliases, or connectivityarea: providersInference provider integrations and provider behaviorarea: routingRequest routing, policy routing, model selection, or fallback logicintegration: hermesHermes integration behavior

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions