Repository navigation
feat(providers): make Providers v2 the only provider system #1988
Description
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_enabledfrom 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_enabledis registered as a runtime setting incrates/openshell-core/src/settings.rs.GetSandboxConfigreads that setting and only composes provider profile policy when it is enabled incrates/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-existingswitches between profile discovery and the legacy provider registry incrates/openshell-cli/src/run.rs.openshell sandbox createcurrently suppresses command-derived provider inference when Providers v2 is enabled.- The TUI still uses
openshell_providers::ProviderRegistrydirectly 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.yamland several other profile-backed providers. pypi.yamlhas endpoints and binaries but no credentials, making it a concrete policy-only provider case.- The CLI has expanded credential-source options, including
--from-gcloud-adcand runtime credentials, but the create command still has an unconditionally requiredcred_sourcearg 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_enabledis 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:
- feat(providers): support credential-less provider creation for policy-only profiles #1978 — credential-less provider creation for policy-only profiles.
- bug: reserve
_provider_*policy key prefix and enforce at gateway boundaries #1982 — reserved_provider_*policy key hardening; relevant because unconditional provider policy composition makes generated provider rule namespaces more important.
Activity
github-actions commentedon Jul 9, 2026
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.
steve-todorov commentedon Jul 15, 2026
Looks like this is still a thing.
johntmyers commentedon Aug 26, 2026
Implementation Plan
Issue type:
featComplexity: High
Confidence: High — the supported-profile matrix and legacy compatibility policy are now decided
Review basis:
origin/mainatc3993426498d5b602ec080bc1d3cbad5e8460f4a(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 foropenaiandanthropic; retiregeneric,gitlab,opencode, andoutlookfrom 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 aspypi.Issue #1978 remains unimplemented on
mainand 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, andcrates/openshell-providers/src/lib.rs: add built-inopenaiandanthropicprofiles; retiregeneric,gitlab,opencode, andoutlookfrom 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.rsandcrates/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 byproviders_v2_enabled.crates/openshell-server/src/grpc/policy.rsandcrates/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.rsandcrates/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, andcrates/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.protoand committed generated SDK artifacts: remove the feature-flag-specificGetGatewayConfigcomment and regenerate affected bindings.Implementation Steps
openaiandanthropicprofiles with credential, discovery, endpoint, binary, and inference metadata aligned with their existing routing semantics. Removegeneric,gitlab,opencode, andoutlookfrom 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.providers_v2_enabledfrom 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.--runtime-credentialsremains an explicit bootstrap choice where applicable. Make--from-existingprofile-backed only and return profile-specific missing-credential errors.sandbox createprovider 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.ProviderRegistry-driven type/env-var behavior and v2-gated actions.sync-agent-inframaintenance checks because the provider workflow changes.Test Plan
openai/anthropicbuilt-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.openai,anthropic, and built-in/imported zero-credential profiles; failure for missing required static credentials; runtime-resolvable bootstrap behavior; rejection ofgeneric,gitlab,opencode,outlook, and arbitrary profileless records; successful creation of a custom importedgitlabprofile; profile-backed--from-existing; sandbox provider inference; unconditional effective-policy composition.Risks & Open Questions
generic,gitlab,opencode, andoutlookfrom 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.providers_v2_enabledvalues may remain in storage but become ignored/unregistered; tests should verify settings reads and writes fail or omit the removed key cleanly.Documentation Impact
docs/sandboxes/providers-v2.mdxinto the canonical provider documentation (or rename/reframe it) and updatedocs/sandboxes/manage-providers.mdx.openaiandanthropic, the retirement of new profilelessgeneric/gitlab/opencode/outlookrecords, and how custom GitLab deployments use imported profiles.docs/reference/gateway-config.mdxanddocs/reference/sandbox-compute-drivers.mdxdo not require changes for this issue.LSM Compatibility
No SELinux/AppArmor-specific behavior is expected. This work does not change process identity,
/procaccess, 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
mainjohntmyers commentedon Aug 26, 2026
Implementation is ready for review in #2962.
Highlights:
providers_v2_enabledis removed and sandbox-scoped provider policy composition is unconditionalValidation:
mise run cimise run testmise run e2e:rustmise run e2e:python(89 passed, 84 skipped)feat(providers): make profiles authoritative
feat(providers): make profiles authoritative
feat(providers): make profiles authoritative
feat(providers): make profiles authoritative
feat(providers): make profiles authoritative
feat(providers): make profiles authoritative
feat(providers): make profiles authoritative (NVIDIA#2962)