Skip to content

feat(providers): make Providers v2 the only provider system #1988

Closed

Description

@johntmyers

Problem Statement

OpenShell currently has two provider behaviors: legacy credential-only providers and Providers v2 profile-backed providers. The split makes provider behavior harder to reason about: profile-owned policy is gated behind providers_v2_enabled, CLI and TUI discovery still depend on the legacy registry, and profile-only providers that contribute policy without credentials are not consistently first-class.

We should make Providers v2 the only provider system, even if that breaks older workflows. Provider profiles should define provider semantics: credential requirements, discovery, endpoint and binary policy, refresh behavior, and policy-only providers. Provider instances should bind a name to a profile plus concrete credential/config values when the profile needs them.

Related: #1978 should be folded into this work. Credential-less policy-only profiles, such as pypi, must be creatable without dummy credentials like --credential NOOP=.

Proposed Design

Make provider profiles authoritative and remove the compatibility switch.

  • Remove providers_v2_enabled from registered runtime settings and CLI/docs examples.
  • Always compose attached provider profile policy into the effective sandbox policy.
  • Stop accepting profileless provider types for new provider records.
  • Treat provider records as instances of built-in or imported provider profiles.
  • Replace public legacy registry discovery with profile-backed discovery.
  • Update CLI and TUI provider creation to drive type selection, credential labels, discovery, and validation from provider profiles.
  • Allow provider creation with no credential source when the profile declares no required static credentials or declares required credentials that are runtime-resolvable through refresh/token-grant metadata.
  • Fail clearly when a profile requires static credentials and none are supplied or discoverable.

Credential-less providers should be normal, not a workaround. For a policy-only profile such as pypi, this should work:

openshell provider create --name pypi --type pypi
openshell sandbox create --provider pypi -- <command>

The resulting provider record should have no dummy credential entries, while the attached profile still contributes its endpoint and binary policy layer.

Affected Components

Component Key files Required work
Provider profiles providers/*.yaml, crates/openshell-providers/src/profiles.rs Ensure every supported provider type is represented as a profile and that profile metadata can express static, runtime-resolvable, and no-credential providers.
Gateway provider API crates/openshell-server/src/grpc/provider.rs Validate provider creation/update against profile requirements. Allow empty credentials when the profile permits it. Reject profileless provider types.
Gateway policy config crates/openshell-server/src/grpc/policy.rs Remove the providers_v2_enabled gate and always compose provider profile policy for attached providers. Revisit global-policy interaction so provider layers are not accidentally suppressed in the v2-only model unless that remains intentional.
CLI crates/openshell-cli/src/main.rs, crates/openshell-cli/src/run.rs Remove the unconditional provider credential-source requirement. Fetch the profile to decide whether credentials are required. Remove legacy registry fallback and update sandbox provider auto-create behavior.
TUI crates/openshell-tui/src/app.rs, crates/openshell-tui/src/lib.rs Replace legacy ProviderRegistry type/env-var selection with profile RPCs and profile credential metadata.
Docs docs/sandboxes/manage-providers.mdx, docs/sandboxes/providers-v2.mdx, quickstarts, man pages Collapse the two-provider-system story into one profile-backed provider model. Remove enable/disable docs. Document credential-less policy-only providers.
Tests provider, policy, CLI, TUI-adjacent integration tests Remove disabled-v2 expectations. Add coverage for profile-required credentials, runtime-resolvable credentials, policy-only providers, and profileless provider rejection.

Alternatives Considered

Only change the default for providers_v2_enabled. This preserves legacy behavior and keeps two provider systems alive. It does not satisfy the goal of making Providers v2 the only provider system.

Keep profileless credential-only providers as an escape hatch. This reduces migration pain, but it preserves the ambiguity that v2 is meant to remove. If a provider has no profile, OpenShell cannot know its policy, credential requirements, refresh model, or user-facing semantics.

Add a --no-credential flag for policy-only providers. This is less desirable than letting the profile declare whether credentials are needed. A pypi-style profile has no credential semantics, so the CLI should not require the user to opt out of credentials manually.

Agent Investigation

The local checkout shows the compatibility split clearly:

  • providers_v2_enabled is registered as a runtime setting in crates/openshell-core/src/settings.rs.
  • GetSandboxConfig reads that setting and only composes provider profile policy when it is enabled in crates/openshell-server/src/grpc/policy.rs.
  • Provider profile policy composition already exists and is just-in-time derived data; it does not persist provider-generated rules back into the sandbox-authored policy.
  • openshell provider create --from-existing switches between profile discovery and the legacy provider registry in crates/openshell-cli/src/run.rs.
  • openshell sandbox create currently suppresses command-derived provider inference when Providers v2 is enabled.
  • The TUI still uses openshell_providers::ProviderRegistry directly for provider type lists and credential env-var labels.
  • Server-side provider creation currently rejects empty credentials unless the provider type allows empty credentials for gateway-managed refresh bootstrap.

Remote main has advanced provider-profile work that should be treated as the current target shape:

  • Built-in profiles now include pypi.yaml and several other profile-backed providers.
  • pypi.yaml has endpoints and binaries but no credentials, making it a concrete policy-only provider case.
  • The CLI has expanded credential-source options, including --from-gcloud-adc and runtime credentials, but the create command still has an unconditionally required cred_source arg group.
  • The server uses a generic provider_type_allows_empty_credentials() helper backed by profile metadata, but the current profile helper still requires at least one runtime-resolvable credential. A zero-credential policy-only profile still needs explicit support.

Definition of Done

  • providers_v2_enabled is removed from user-facing settings and no longer gates provider policy composition.
  • New provider records must reference a built-in or imported provider profile.
  • Profile-backed discovery is the only provider discovery path exposed by CLI/TUI workflows.
  • Credential-less policy-only profiles can be instantiated without dummy credentials.
  • Profiles with required static credentials still fail clearly when no credential source is supplied.
  • Runtime-resolvable credential profiles keep working for refresh/token-grant bootstrap flows.
  • TUI provider creation uses provider profile metadata rather than the legacy registry.
  • Docs describe one provider model and remove Providers v2 opt-in instructions.
  • Tests cover policy-only providers, required credentials, runtime credentials, profileless rejection, and unconditional provider policy composition.

Notes

This is intentionally a breaking change. Existing profileless provider records may need a migration story, a one-time warning, or a release note explaining that unsupported provider types must be recreated from imported profiles.

Related issues:

Activity

  1. added this to the OpenShell Beta milestone on Jun 24, 2026
  2. self-assigned this
    on Jun 24, 2026
  3. github-actions commented on Jul 9, 2026

    @github-actions

    This issue has had no activity for 14 days and is now marked stale. It may be closed in 7 days if there is no further activity. Comment or remove the state:stale label to keep it open.

  4. steve-todorov commented on Jul 15, 2026

    @steve-todorov

    Looks like this is still a thing.

  5. johntmyers commented on Aug 26, 2026

    @johntmyers
    CollaboratorAuthor

    🏗️ build-plan

    Implementation Plan

    Issue type: feat
    Complexity: High
    Confidence: High — the supported-profile matrix and legacy compatibility policy are now decided
    Review basis: origin/main at c3993426498d5b602ec080bc1d3cbad5e8460f4a (2026-08-26)

    Summary

    Make profile-backed providers the only creation and discovery model, remove providers_v2_enabled, and compose attached provider profile policy automatically for sandbox-scoped policies. Add authoritative built-in profiles for openai and anthropic; retire generic, gitlab, opencode, and outlook from new public workflows while preserving existing records and allowing imported custom profiles, including custom GitLab deployments. Reject all other new profileless records, retain the current global-policy suppression behavior, and allow true zero-credential policy-only profiles such as pypi.

    Issue #1978 remains unimplemented on main and is included here. Issue #1982 is already implemented by PR #1991 and does not need duplicate work.

    Scope

    • providers/*.yaml, crates/openshell-providers/src/profiles.rs, and crates/openshell-providers/src/lib.rs: add built-in openai and anthropic profiles; retire generic, gitlab, opencode, and outlook from new registry-backed discovery/type selection; distinguish zero-credential, required-static, and runtime-resolvable credential capabilities; retain only internal compatibility behavior required for existing records.
    • crates/openshell-server/src/grpc/provider.rs and crates/openshell-server/src/provider_refresh.rs: require a built-in or imported profile for every new provider record, validate credentials from that profile, allow empty credentials when the profile permits them, and remove refresh behavior gated by providers_v2_enabled.
    • crates/openshell-server/src/grpc/policy.rs and crates/openshell-core/src/settings.rs: remove the registered setting and all conditional composition branches; always compose provider layers for sandbox-scoped policy while retaining current suppression when a gateway-global policy is active.
    • crates/openshell-cli/src/main.rs and crates/openshell-cli/src/run.rs: make the credential-source argument group optional, derive credential requirements and discovery from profiles, remove legacy registry fallback, and update sandbox provider inference/auto-create behavior for the profile-backed model.
    • crates/openshell-tui/src/app.rs, crates/openshell-tui/src/lib.rs, and crates/openshell-tui/src/ui/providers.rs: remove v2 feature gating and drive provider type selection, labels, validation, and actions from profile RPC data.
    • proto/openshell.proto and committed generated SDK artifacts: remove the feature-flag-specific GetGatewayConfig comment and regenerate affected bindings.
    • Provider docs, tutorials, examples, and related agent skills: describe one provider model, credential-less profiles, legacy-record compatibility, retired legacy types, custom imported profiles, and removal of the opt-in setting.

    Implementation Steps

    1. Add authoritative built-in openai and anthropic profiles with credential, discovery, endpoint, binary, and inference metadata aligned with their existing routing semantics. Remove generic, gitlab, opencode, and outlook from new public registry discovery/type selection. Do not add a built-in GitLab profile; users with custom GitLab deployments continue through workspace- or platform-scoped imported profiles.
    2. Split profile credential capability logic into explicit predicates for zero-credential profiles and runtime-resolvable bootstrap profiles. Cover zero, optional, required-static, token-grant, refresh, and mixed credential declarations with unit tests.
    3. Require profile resolution during server-side create before persisting credentials. Accept empty credentials only when profile metadata permits it, fail clearly for missing required static credentials, and leave existing profileless records readable/updatable without attempting an automatic migration. A retired type name remains usable for new creation only when a matching imported profile resolves in the requested scope.
    4. Remove providers_v2_enabled from registered settings, server composition checks, candidate validation, provider refresh configuration/rotation, and their tests. Compose provider layers for sandbox-scoped source policy unconditionally; preserve the existing gateway-global policy override semantics.
    5. Update CLI provider creation so no credential flag is valid for zero-credential or runtime-resolvable profiles, while --runtime-credentials remains an explicit bootstrap choice where applicable. Make --from-existing profile-backed only and return profile-specific missing-credential errors.
    6. Update sandbox create provider inference to consult profiles and attach existing instances or auto-create only when profile discovery/credential capabilities can satisfy creation non-interactively; otherwise emit an actionable prompt/error rather than silently creating invalid records.
    7. Rework TUI provider refresh/create/update state and UI to always load profile metadata and remove ProviderRegistry-driven type/env-var behavior and v2-gated actions.
    8. Update docs, proto comments, generated bindings, and related OpenShell CLI/provider skills. Run the sync-agent-infra maintenance checks because the provider workflow changes.

    Test Plan

    • Unit tests: openai/anthropic built-in profile metadata; profile capability helpers; registered-setting removal; server profile-resolution and credential validation; policy composition/global-policy behavior; TUI state and form enablement from profile metadata.
    • Integration tests: CLI creation of openai, anthropic, and built-in/imported zero-credential profiles; failure for missing required static credentials; runtime-resolvable bootstrap behavior; rejection of generic, gitlab, opencode, outlook, and arbitrary profileless records; successful creation of a custom imported gitlab profile; profile-backed --from-existing; sandbox provider inference; unconditional effective-policy composition.
    • Compatibility tests: existing persisted profileless and retired-type records remain readable/updatable and continue supplying their stored credentials, but cannot be newly created or recreated without importing a matching profile.
    • E2E tests: N/A unless implementation changes an existing provider/sandbox smoke lane. The core behavior is covered more deterministically by server and CLI integration tests.

    Risks & Open Questions

    • Retirement boundary: retirement removes generic, gitlab, opencode, and outlook from new public discovery/type-selection workflows. Internal adapters may remain where required to keep persisted legacy records operable; they must not make those types valid for new profileless creation.
    • Custom GitLab deployments: no built-in GitLab policy will be introduced. The profile ID remains available to workspace- or platform-scoped imported profiles so deployment-specific endpoints and credentials remain authoritative.
    • Existing profileless records: no automatic migration. Keep them operable, reject new profileless creates, and document recreation through an imported profile.
    • Global policy: preserve current suppression of provider-derived layers under a gateway-global policy. Changing that merge contract requires a separately reviewed policy decision.
    • Sandbox auto-create: use non-interactive creation only when profile metadata and discovery fully satisfy requirements; otherwise require the user to create the provider explicitly.
    • Removing a registered setting means stale persisted providers_v2_enabled values may remain in storage but become ignored/unregistered; tests should verify settings reads and writes fail or omit the removed key cleanly.

    Documentation Impact

    • Consolidate docs/sandboxes/providers-v2.mdx into the canonical provider documentation (or rename/reframe it) and update docs/sandboxes/manage-providers.mdx.
    • Remove opt-in examples from related tutorials and provider pages, including Microsoft Graph and Google Vertex AI guidance.
    • Document built-in openai and anthropic, the retirement of new profileless generic/gitlab/opencode/outlook records, and how custom GitLab deployments use imported profiles.
    • Update navigation and any generated CLI/man-page examples that expose the old setting.
    • No gateway TOML or compute-driver option changes are expected, so docs/reference/gateway-config.mdx and docs/reference/sandbox-compute-drivers.mdx do not require changes for this issue.

    LSM Compatibility

    No SELinux/AppArmor-specific behavior is expected. This work does not change process identity, /proc access, binary execution, or inter-process visibility.


    Revision 2 — retain OpenAI/Anthropic; retire generic/GitLab/OpenCode/Outlook from new public workflows while preserving custom imported profiles and existing records
    Revision 1 — initial plan reviewed against latest main

  6. johntmyers commented on Aug 26, 2026

    @johntmyers
    CollaboratorAuthor

    Implementation is ready for review in #2962.

    Highlights:

    • provider profiles are authoritative for new creation/discovery
    • providers_v2_enabled is removed and sandbox-scoped provider policy composition is unconditional
    • built-in OpenAI and Anthropic profiles are added
    • public generic/GitLab/OpenCode/Outlook legacy workflows are retired; imported custom profiles remain supported
    • existing persisted legacy providers remain readable/updateable
    • credentialless and runtime-resolvable profiles work without dummy credentials
    • CLI, TUI, docs, examples, e2e fixtures, generated bindings, and agent skills are updated

    Validation:

    • mise run ci
    • mise run test
    • mise run e2e:rust
    • mise run e2e:python (89 passed, 84 skipped)
    • strict docs build and all-feature e2e compilation
  7. added 6 commits that reference this issue on Aug 27, 2026
    d94f4e3
    3755ce5
    d6db495
    b9aac8a
    bf7e780
    943b96b
  8. added a commit that references this issue on Sep 1, 2026
    07df822
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions