Skip to content

refactor(providers): unify provider profile identity and scoped references #2371

Description

@drew

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

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

  1. Separate profile specification from profile identity. For example, introduce a ProviderProfileSpec containing credentials, endpoints, binaries, discovery, and presentation fields.

  2. Use ObjectMeta.name as the canonical name for stored user-managed profile resources. Keep ObjectMeta.id as the opaque resource UUID.

  3. 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,
    }
    
  4. 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.

  5. Key EffectiveProviderProfileCatalog by the typed profile key and require provider resolution, policy composition, refresh, environment resolution, and revision hashing to use the provider's complete profile reference.

  6. 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.

  7. Rename or restructure Provider.type and Provider.profile_workspace so the protobuf expresses a single profile reference instead of two independently interpreted fields.

  8. 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.id is removed rather than mirrored into metadata.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.

Activity

  1. github-actions commented on Aug 4, 2026

    @github-actions

    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.

  2. Ygnas commented on Sep 28, 2026

    @Ygnas
    Contributor

    @drew Question on test scope: Would the planned work here include a deployed-gateway Rust CLI E2E for same-ID platform and workspace profiles?

    Existing server and Python E2E tests cover the underlying shadowing and visibility behavior, but I couldn’t find a Rust CLI E2E that verifies provider creation selects the workspace profile by default and the platform profile with provider create --global-profile. The proposed test would use synthetic discovery credentials and assert credential-key names only; there’s no known defect or need for real credentials.

    Would you prefer this scenario to be folded into #2371 if that work resumes, or tracked as a separate test/issue?

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions