NVIDIA / NVIDIA/OpenShell

Add identity-bound CAS and secret-free attestation for provider mutations

Open
#2,722 6 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

state:needs-info state:stale
Dominant language
Rust
Stars
8.7k
Forks
1.3k
Avg merge
2d 11h
Merged PRs (30d)
253

Description

Problem Statement

Provider automation cannot currently bind a credential/config mutation atomically to the provider identity it inspected.

In OpenShell v0.0.104 (dd2b4e3bc0688bdd59f90030f7c1d52511d6e354):

  • openshell provider list --output json returns a useful secret-free identity view (id, name, workspace, type, credential/config key names, and resource_version).
  • The gateway supports client-driven optimistic concurrency when Provider.metadata.resource_version is non-zero.
  • The provider update CLI always sends an empty provider ID and resource_version: 0.
  • The gateway therefore resolves the provider by name at mutation time and CASes against the version it just read, rather than an identity/version previously observed by the caller.

If a provider is updated or deleted/recreated between an automation client's read and update, the new identity can receive the submitted credential/config before a client-side post-read detects drift. A post-mutation receipt cannot undo that credential delivery.

This blocks fail-closed consumers that need multiple endpoint-bound providers, including NemoClaw's judge/weak/strong model targets for native Hermes → NeMo Relay → Switchyard routing (NVIDIA/NemoClaw#8887).

The current secret-free inventory also cannot attest endpoint configuration or the resolved provider-profile revision: it intentionally exposes config key names but not a non-secret config digest or profile provenance. Consequently, callers cannot distinguish two same-shaped providers targeting different endpoints.

Proposed Design

Add an identity-bound conditional mutation contract to the provider API and CLI.

  1. Extend provider update with explicit expected identity fields, for example:
    • expected_provider_id
    • expected_resource_version
  2. Expose corresponding CLI flags, such as:
    • openshell provider update NAME --expected-id ID --expected-resource-version N ...
  3. Validate both fields against the current record before preparing or storing any submitted credential material.
  4. Preserve the existing unconditional behavior only when neither expectation is supplied; reject partial expectation pairs.
  5. Return a machine-readable, secret-free mutation receipt from create/update and a matching read surface containing:
    • provider ID, name, workspace, type, and resource version;
    • credential/config key names, never values;
    • resolved profile ID, scope/workspace, and profile resource version;
    • a versioned digest of canonical non-secret provider config (or another stable endpoint/config attestation).

The receipt should be generated by the gateway from the committed record, not reconstructed by the CLI.

Security Requirements
  • A stale expected provider ID or resource version fails before any new credential reaches persistent or external credential storage.
  • A concurrent delete/recreate under the same name cannot satisfy an update authorized for the old provider, even if its numeric resource version happens to match.
  • Errors and structured output never contain credential values or credential-store handles.
  • The config attestation format is versioned and deterministic; unknown/unsupported versions fail closed for consumers that require it.
  • Profile provenance is resolved at the same gateway snapshot used for the mutation receipt.
Acceptance
  • CLI and API can conditionally update a provider by exact ID plus resource version.
  • Concurrent update and delete/recreate tests prove stale mutations do not persist or deliver submitted credentials.
  • Successful create/update returns a secret-free receipt bound to the committed identity/version.
  • A read API exposes the same attestation fields without credential values.
  • Same-shaped providers with different endpoint config produce different config attestations.
  • Resolved provider-profile revision/scope drift is observable.
  • Backward-compatible unconditional updates remain explicitly documented, while security-sensitive automation can require the conditional path.
Alternatives Considered

Client-side read → update → read: detects some drift after the fact but cannot prevent credential delivery to the wrong identity.

Resource version without provider ID: does not fully protect delete/recreate under the same name when versions coincide.

Expose raw provider config: unnecessary for the transaction and can expand disclosure. A stable versioned digest plus resolved profile provenance is sufficient for exact automation checks.

Checklist
  • Existing issues were searched for provider CAS, expected resource version, concurrent provider update, and provider attestation.
  • The current CLI, proto, gateway update path, and concurrency tests were inspected.
  • This is a design/API request, not a request to expose credentials.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the provider update CLI, provider proto/API, gateway update path, and existing concurrency tests mentioned in the issue. Trace how identity, resource version, credentials, and profile data flow through create/update and read operations. Done means the acceptance checklist is covered, including stale identity tests, secret-free receipts, deterministic config attestations, and profile provenance.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
api, backend, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.