refactor(providers): unify provider profile identity and scoped references
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 8.7k
- Forks
- 1.3k
- Avg merge
- 2d 11h
- Merged PRs (30d)
- 253
Description
Description
Unify provider-profile identity around the OpenShell resource convention and make profile references explicitly workspace-aware.
ProviderProfile was introduced as an unscoped catalog value with a logical id. Custom profile storage later wrapped it in StoredProviderProfile.metadata, copying profile.id into metadata.name. Providers now refer to that same logical key through Provider.type, with the profile scope carried separately in Provider.profile_workspace.
The resulting identity model has several names for the same value and two meanings of id:
provider.type == profile.id == stored_profile.metadata.name
stored_profile.metadata.id == opaque resource UUID
For user-managed profiles, the actual reference is composite:
(provider.profile_workspace, provider.type)
->
(stored_profile.metadata.workspace, stored_profile.metadata.name)
This is easy for both humans and agents to misuse. It has also allowed runtime catalog code to erase profile scope and index entries only by normalized profile ID.
Context
ProviderProfile.idoriginated when profiles were catalog payloads rather than stored resources: #1037.StoredProviderProfile { ObjectMeta metadata; ProviderProfile profile; }was added with the custom registry: #1170.- Workspace scoping in #2243 exposes the mismatch because the profile scope is stored outside the profile payload and is lost when source snapshots are reduced to
ProviderProfilevalues. - Profile List/Get currently also serve two different concerns: exact-scope management of user profiles and discovery of the effective runtime catalog. Those concerns need explicit APIs or read models.
This cleanup does not need to preserve the existing provider-profile wire or file shape. Do not add compatibility aliases, fallback lookup paths, or data backfills; update the model and its consumers atomically.
Proposed Direction
-
Separate profile specification from profile identity. For example, introduce a
ProviderProfileSpeccontaining credentials, endpoints, binaries, discovery, and presentation fields. -
Use
ObjectMeta.nameas the canonical name for stored user-managed profile resources. KeepObjectMeta.idas the opaque resource UUID. -
Introduce one typed profile key/reference containing scope and canonical name. Provider runtime code should resolve profiles through this type rather than passing bare strings:
ProfileKey { scope: Platform | Workspace(name) | WorkspaceAgnostic, name: NormalizedProfileName, } -
Have profile sources return entries that retain scope and source provenance. Built-in and interceptor-provided entries should be represented explicitly as workspace-agnostic/source-managed rather than relying on implicit fallback behavior.
-
Key
EffectiveProviderProfileCatalogby the typed profile key and require provider resolution, policy composition, refresh, environment resolution, and revision hashing to use the provider's complete profile reference. -
Separate effective-catalog discovery from exact-scope user-profile CRUD, or otherwise make the read semantics explicit. CLI preflight and runtime creation must observe the same effective catalog; mutation APIs must target only mutable user-managed resources in the requested scope.
-
Rename or restructure
Provider.typeandProvider.profile_workspaceso the protobuf expresses a single profile reference instead of two independently interpreted fields. -
Update profile YAML, CLI output/input, protobufs, architecture documentation, published provider documentation, and interceptor contracts to use the new terminology consistently.
Definition of Done
- A profile's canonical name is represented once;
ProviderProfile.idis removed rather than mirrored intometadata.name. - Resource UUIDs and human-addressable names have distinct, consistently documented meanings.
- No runtime profile lookup accepts only a raw profile ID/name when scope is required.
- Platform and workspace profiles with the same canonical name can coexist and resolve according to an explicit provider reference.
- Different workspaces can independently define the same profile name.
- Built-in and interceptor-provided profiles retain explicit source and scope semantics.
- Effective catalog List/Get or replacement discovery APIs use the configured provider-profile sources.
- User-managed CRUD operates on the exact requested scope and cannot mutate source-managed profiles.
- Tests cover same-name platform/workspace profiles, same-name profiles across workspaces, source-managed profiles, CLI creation, policy composition, refresh, and environment resolution.
- Architecture and user-facing provider documentation describe the canonical terminology and lookup rules.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by tracing ProviderProfile, StoredProviderProfile, Provider, and EffectiveProviderProfileCatalog through runtime lookup, CRUD, CLI, protobuf, YAML, and interceptor paths. Map every use of profile.id, metadata.name, profile_workspace, and raw-name lookup before restructuring them around a scoped typed reference; done means the listed coexistence, source-management, CLI, policy, refresh, environment, test, and documentation requirements pass.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- backend-api-design, cli, documentation
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100