Skip to content

refactor(providers)!: make provider behavior explicit in imported profiles #3442

Description

@feloy

Sub-issue of #3171 (provider boundary in step 5). Follows #3299 / PR #3383, which made provider profiles import-only. Coordinated pre-0.1.0 breaking change under #2565.

User Story

As an operator, I want an imported provider profile to declare every behavior it activates, so I can inspect, fork, and rename the profile without silently changing the sandbox environment.

Problem Statement

#3299 removed the compiled provider profile catalog, but two compiled adapters remain:

  • google-cloud projects provider config into GCP SDK variables and sets GCE_METADATA_HOST.
  • google-vertex-ai projects project and region config into GCP and Vertex variables and sets a GOOSE_PROVIDER default.

ProviderRegistry::inject_env_for_profile_id selects these adapters by the resolved profile ID. Importing the same profile as google-cloud and acme-gcp therefore produces different environments even though the imported definitions are identical.

Other provider-specific behavior is also compiled rather than declared: Vertex discovery scans a fixed list of config variables, and child-environment preparation contains GCP-specific metadata and non-secret configuration handling. ProviderProfile can declare credential environment variables, but not non-secret config projection, fixed non-secret values, discovery config keys, or a required platform adapter.

Impact / Why This Matters

An imported profile is not currently its complete definition. Operators must preserve canonical IDs and know release-specific implementation details, or provider creation succeeds while the workload later fails because expected SDK configuration is absent. This contradicts the import-only contract and makes profile forks unsafe.

Proposed Design

Inventory every compiled provider behavior reachable from an imported profile and give it one disposition:

  1. Express in the profile. Add bounded declarative fields for generic non-secret behavior such as config-to-environment projection, fixed values, and discovery config keys. Do not introduce templating or scripting.
  2. Declare a platform adapter. If behavior is genuinely platform-specific, the profile names the required adapter. Import or attachment fails with a bounded diagnostic when the adapter is unavailable.
  3. Remove it. Delete behavior or APIs with no remaining caller, including ProviderDiscoverySpec and discover_with_spec unless a supported use is identified.

Projection must preserve the existing rule that caller-supplied environment values win. Linting must reject collisions between non-secret projection and credential env_vars.

Update the Google Cloud and Vertex examples so their YAML describes their complete environment and discovery effects. A fork imported under a different ID must behave identically to the canonical example.

Credential refresh strategies are out of scope because profiles already declare them.

Acceptance Criteria

  • Every compiled provider behavior reachable from an imported profile is inventoried as profile-declared, named platform adapter, or removed.
  • No provider behavior activates from the profile ID alone.
  • The Google Cloud and Vertex examples declare their complete non-secret environment and discovery effects.
  • A profile forked under another ID produces the same sandbox environment and discovery behavior as the canonical profile.
  • Environment projection never overwrites an existing value.
  • Import or attachment fails with a bounded diagnostic when a declared platform adapter is unavailable.
  • Profile lint rejects unknown adapters and collisions between non-secret projection and credential environment variables.
  • ProviderDiscoverySpec and discover_with_spec are removed or have a documented supported caller.
  • ProviderProfile.source and resource_version documentation no longer refers to built-in profiles or builtin provenance.
  • Provider examples, architecture/user documentation, and 0.1.0 migration notes describe the resulting contract.
  • Tests cover profile/proto round trips, forked-ID equivalence, collision handling, non-overwrite semantics, and unavailable adapters.

Alternatives Considered

  • Delete both adapters: restores a clean boundary but breaks existing GCP and Vertex workloads at upgrade.
  • Document ID-keyed behavior only: leaves profile forks behaviorally different and the binary authoritative for part of the profile definition.
  • Add a general templating language: unnecessarily turns reviewable profile data into executable configuration; bounded projection covers the observed generic cases.
  • Restore aliases: cannot support an unbounded operator catalog and reintroduces hidden ID coupling.

Technical Notes

  • crates/openshell-providers/src/lib.rs: ProviderRegistry registers the two remaining adapters and selects them by exact profile ID.
  • crates/openshell-providers/src/discovery.rs: discover_from_profile special-cases google-vertex-ai config keys.
  • crates/openshell-core/src/provider_credentials.rs: child environment preparation contains GCP-specific metadata and non-secret resolution.
  • crates/openshell-server/src/grpc/provider.rs: provider environment assembly and key-collision validation are the runtime integration points.
  • proto/openshell.proto and crates/openshell-providers/src/profiles.rs: the public profile schema and YAML/protobuf conversion currently lack this declaration surface.

Checklist

  • Existing issues and architecture documentation reviewed
  • Design proposal; implementation planning follows human disposition

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    state:triage-neededOpened without agent diagnostics and needs triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions