You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Provider profiles can define endpoints and binaries without any credentials — the built-in pypi profile is a shipping example. However, openshell provider create requires at least one credential source, making it impossible to create a provider instance from a credential-less profile without the --credential NOOP= workaround.
This is inconvenient for downstream harnesses that use custom provider profiles purely for policy composition (network endpoint allow-lists contributed through provider attachment) without needing credential injection. The --credential NOOP= workaround exists but persists a dummy credential in the provider record, polluting credential state for a provider that has no credential semantics.
The gap exists at two layers:
CLI (crates/openshell-cli/src/main.rs:719): the cred_source clap arg group is required(true), so provider create always demands one of --credential, --from-existing, or --from-gcloud-adc at parse time.
Server (crates/openshell-server/src/grpc/provider.rs:96-101): CreateProvider rejects empty credentials unless provider_type_allows_empty_credentials_for_refresh() returns true — but that function (crates/openshell-providers/src/profiles.rs:323-336) requires at least one gateway-mintable credential. A profile with zero credentials always returns false.
Proposed Design
Allow credential-less provider creation when the provider type's profile declares no required credentials.
CLI changes:
Make the cred_source arg group conditionally required. When no credential flag is provided, the CLI fetches the provider profile (it already does this for the refresh-bootstrap path at run.rs:4556-4559) and proceeds without credentials if the profile has no required credential entries. If the profile has required credentials and none were provided, the existing error is preserved.
Server changes:
Extend the CreateProvider validation (provider.rs:96-101) to also allow empty credentials when the profile exists and declares no required credentials. This can reuse the existing get_provider_type_profile lookup and add a check like:
The existing allows_gateway_refresh_bootstrap path remains unchanged for its OAuth use case.
No changes needed to:
Policy composition — already works with credential-less providers once they exist
Provider attachment — SandboxSpec.providers is name-based, credential-agnostic
Effective policy fetch — profile_provider_policy_layers reads endpoints/binaries from the profile regardless of credentials
Alternatives Considered
Add a --no-credential CLI flag. This would work but adds a flag for what should be the default behavior when a profile has no credentials. The profile already declares what credentials it needs — the CLI should respect that.
Keep --credential NOOP= as the documented workaround. This persists a dummy credential in the provider record, which is confusing for operators inspecting provider state and may interact poorly with future credential driver backends (#1931).
Agent Investigation
Confirmed pypi built-in profile (providers/pypi.yaml) has no credentials section — only endpoints and binaries.
Confirmed CLI arg group cred_source at crates/openshell-cli/src/main.rs:719 is required(true).
Confirmed server validation at crates/openshell-server/src/grpc/provider.rs:96-101 rejects empty credentials unless allows_gateway_refresh_bootstrap() returns true.
Confirmed allows_gateway_refresh_bootstrap() at crates/openshell-providers/src/profiles.rs:323-336 requires at least one gateway-mintable credential — zero-credential profiles always return false.
Confirmed the existing empty-credential test (provider_create_allows_empty_credentials_for_gateway_refresh_profiles at crates/openshell-cli/tests/provider_commands_integration.rs:1102) only covers the OAuth refresh bootstrap case, not the zero-credential profile case.
Searched open and closed issues — no existing issue covers this gap.
Problem Statement
Provider profiles can define endpoints and binaries without any credentials — the built-in
pypiprofile is a shipping example. However,openshell provider createrequires at least one credential source, making it impossible to create a provider instance from a credential-less profile without the--credential NOOP=workaround.This is inconvenient for downstream harnesses that use custom provider profiles purely for policy composition (network endpoint allow-lists contributed through provider attachment) without needing credential injection. The
--credential NOOP=workaround exists but persists a dummy credential in the provider record, polluting credential state for a provider that has no credential semantics.The gap exists at two layers:
CLI (
crates/openshell-cli/src/main.rs:719): thecred_sourceclap arg group isrequired(true), soprovider createalways demands one of--credential,--from-existing, or--from-gcloud-adcat parse time.Server (
crates/openshell-server/src/grpc/provider.rs:96-101):CreateProviderrejects empty credentials unlessprovider_type_allows_empty_credentials_for_refresh()returns true — but that function (crates/openshell-providers/src/profiles.rs:323-336) requires at least one gateway-mintable credential. A profile with zero credentials always returns false.Proposed Design
Allow credential-less provider creation when the provider type's profile declares no required credentials.
CLI changes:
Make the
cred_sourcearg group conditionally required. When no credential flag is provided, the CLI fetches the provider profile (it already does this for the refresh-bootstrap path atrun.rs:4556-4559) and proceeds without credentials if the profile has no required credential entries. If the profile has required credentials and none were provided, the existing error is preserved.Server changes:
Extend the
CreateProvidervalidation (provider.rs:96-101) to also allow empty credentials when the profile exists and declares no required credentials. This can reuse the existingget_provider_type_profilelookup and add a check like:The existing
allows_gateway_refresh_bootstrappath remains unchanged for its OAuth use case.No changes needed to:
SandboxSpec.providersis name-based, credential-agnosticprofile_provider_policy_layersreads endpoints/binaries from the profile regardless of credentialsAlternatives Considered
Add a
--no-credentialCLI flag. This would work but adds a flag for what should be the default behavior when a profile has no credentials. The profile already declares what credentials it needs — the CLI should respect that.Keep
--credential NOOP=as the documented workaround. This persists a dummy credential in the provider record, which is confusing for operators inspecting provider state and may interact poorly with future credential driver backends (#1931).Agent Investigation
pypibuilt-in profile (providers/pypi.yaml) has nocredentialssection — only endpoints and binaries.cred_sourceatcrates/openshell-cli/src/main.rs:719isrequired(true).crates/openshell-server/src/grpc/provider.rs:96-101rejects empty credentials unlessallows_gateway_refresh_bootstrap()returns true.allows_gateway_refresh_bootstrap()atcrates/openshell-providers/src/profiles.rs:323-336requires at least one gateway-mintable credential — zero-credential profiles always return false.provider_create_allows_empty_credentials_for_gateway_refresh_profilesatcrates/openshell-cli/tests/provider_commands_integration.rs:1102) only covers the OAuth refresh bootstrap case, not the zero-credential profile case.