Repository navigation
refactor(providers)!: make provider behavior explicit in imported profiles #3442
Description
Activity
- addedstate:triage-neededOpened without agent diagnostics and needs triageOpened without agent diagnostics and needs triage
on Sep 18, 2026 - changed the title
[-]refactor(providers)!: inventory type-specific provider adapters and classify built-in middleware[/-][+]refactor(providers)!: make provider behavior explicit in imported profiles[/+]on Sep 23, 2026 🏗️ build-plan
Implementation Plan
Issue type:
refactor
Complexity: High
Confidence: High — the profile, gateway, and sandbox paths have been verified; history confirms PR #2942 removed the GCP metadata server.Summary
Make imported profiles the authority for non-secret environment projection and local discovery. Declare the unavailable GCP metadata capability explicitly, remove exact-ID switches and unused APIs, and make a renamed profile behave like its source. Preserve caller environment values, exclude legacy Vertex service-account private keys without withholding the rest of the provider environment, and allow multiple providers to share identical non-secret defaults.
Scope
- Add bounded profile declarations for config-to-environment projection, fixed non-secret values, discovery config keys, and a required platform adapter. Keep profile revision encoding deterministic and regenerate the tracked Go protobuf bindings and domain converters.
- Apply declarations in the gateway without profile-ID switches. Sandbox template and create-time environment values, including empty values, take precedence over non-secret profile defaults in both main and exec paths; provider credential placeholders remain provider-owned.
- Reject credential-key collisions across attached providers. Accept shared non-secret destination keys only when the projected values are identical; reject differing values with the key and both provider names.
- Reject new import, update, and lint requests that declare
GOOGLE_SERVICE_ACCOUNT_KEYas a provider credential or as anenvironment.configorenvironment.fixeddestination. Keep older stored profiles loadable while excluding that key from workload environment, credential bindings, and proxy substitution. Skip a stale stored private key before undeclared-credential readiness checks so the access token and non-secret SDK settings remain available after the declaration is removed. Continue to supply private key material through credential refresh configuration. - Declare
gcp-metadatain the Google Cloud example and fail import/update/attachment while the adapter is unavailable. Vertex bearer-token authentication remains usable. - Remove the ID-selected Google Cloud and Vertex adapters, orphaned metadata helpers, unused discovery API, and CLI hints selected by profile ID. Update examples, architecture docs, published docs, migration notes, and the affected operator skill.
Implementation Steps
- Complete: Add profile/protobuf declarations, bounded validation, YAML/protobuf round trips, deterministic maps, and SDK bindings.
- Complete: Replace ID-selected projection and discovery with profile-selected behavior; verify canonical and forked IDs and adapter errors.
- Complete: Filter non-secret profile defaults when callers supply the same sandbox environment key. Verify main and exec launch paths, including explicit empty values and credential placeholders.
- Complete: Reject differing cross-provider non-secret values in both attachment orders while accepting identical Vertex defaults and distinct credential keys. Skip stale private-key credentials before readiness checks, including after a profile removes the legacy declaration. Reject the legacy key in credential declarations and non-secret defaults, and suppress it from older stored profiles without invalidating the catalog.
- Complete: Document atomic directory imports and use selected compatible examples; update the cluster debug skill, provider guides, architecture overview, and upgrade guidance.
- Complete: Publish
fix-3442/vertexat signed-off commit5e32a9462and open PR #3775 for review.
Verification
mise run pre-commitpassed after the final edits and in the amend hook.mise run testpassed after the Vertex fixes, including the gatewaytest-supportrun and the wider Rust, Python, TypeScript, and repository checks.mise run cipassed on the amended commit before PR creation.- All 156 focused gateway provider tests passed. New regressions cover import rejection for both non-secret legacy-key defaults, retaining token and SDK values when an undeclared private key remains stored, and attaching two Vertex providers with identical defaults and distinct credential keys. The provider projection test confirms old stored defaults cannot emit the private-key variable.
- The focused Podman provider-refresh lane and six CLI conformance scenarios passed for the profile projection and caller-precedence implementation before the later gateway-only safeguards. The later safeguards were covered by the gateway and provider tests above.
Risks and Operational Notes
- Commit
c1f2e7189f837f98d00fb3821b6fb8d1253ceec3(September 16, PR feat(isolation): implement the RFC 0012 sandbox architecture #2942) deleted the metadata HTTP server and startup integration. A batch import containingproviders/google-cloud.yamlfails atomically untilgcp-metadatais implemented; import selected compatible profiles instead. - Existing stored profiles that declare
GOOGLE_SERVICE_ACCOUNT_KEYremain readable but cannot inject it. Removing the declaration while a provider record still holds the key leaves that key excluded without marking the whole snapshot withheld; the access token and SDK configuration remain available. Operators should migrate private key material to refresh configuration. - Two attached providers may share a non-secret destination when both projected values match. Different values and overlapping credential keys still fail validation; operators can use distinct destination names or attach one provider in those cases. A sandbox environment override does not bypass the provider collision check.
Documentation Impact
Updated
architecture/google-vertex-ai-provider.md,docs/how-it-works/providers/profiles.mdx,docs/how-it-works/providers/google.mdx,docs/upgrade/0-1-0.mdx,providers/README.md, andskills/debug-openshell-cluster/SKILL.md. No gateway TOML or Helm field changes; no LSM or/procbehavior changes.
Revision 5 — published PR #3775 and verified full local CI on the amended commit
Revision 4 — preserve Vertex snapshots after legacy declaration removal, reject private-key defaults, and allow equal-value provider overlaps
Revision 3 — implementation results, legacy private-key safety, deterministic collision rejection, and compatible example imports
Revision 2 — verified metadata removal, deterministic profile serialization, and explicit refresh-material migration
Revision 1 — initial plan- added 3 commits that reference this issue
on Sep 29, 2026 - added 5 commits that reference this issue
on Sep 30, 2026
Sub-issue of #3171 (provider boundary in step 5). Follows #3299 / PR #3383, which made provider profiles import-only. Coordinated pre-
0.1.0breaking 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-cloudprojects provider config into GCP SDK variables and setsGCE_METADATA_HOST.google-vertex-aiprojects project and region config into GCP and Vertex variables and sets aGOOSE_PROVIDERdefault.ProviderRegistry::inject_env_for_profile_idselects these adapters by the resolved profile ID. Importing the same profile asgoogle-cloudandacme-gcptherefore 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.
ProviderProfilecan 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:
ProviderDiscoverySpecanddiscover_with_specunless 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
ProviderDiscoverySpecanddiscover_with_specare removed or have a documented supported caller.ProviderProfile.sourceandresource_versiondocumentation no longer refers to built-in profiles orbuiltinprovenance.0.1.0migration notes describe the resulting contract.Alternatives Considered
Technical Notes
crates/openshell-providers/src/lib.rs:ProviderRegistryregisters the two remaining adapters and selects them by exact profile ID.crates/openshell-providers/src/discovery.rs:discover_from_profilespecial-casesgoogle-vertex-aiconfig 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.protoandcrates/openshell-providers/src/profiles.rs: the public profile schema and YAML/protobuf conversion currently lack this declaration surface.Checklist