Skip to content

feat: support custom provider profile import and export #1081

@johntmyers

Description

@johntmyers

Problem Statement

Issue #947 and PR #1037 added the first provider profile composition path using built-in YAML-backed profiles. The next incremental step from the broader provider v2 design in #896 is to let users inspect, export, customize, validate, register, and delete custom provider profiles without changing runtime credential injection yet.

Users need a practical way to start from OpenShell's built-in provider profiles, customize endpoints/deny rules/auth declarations, and register those custom profiles as new provider profile definitions. They also need profile import validation that reports all schema and semantic issues in one pass, instead of failing one error at a time.

Related: #896, #947, #1037

Current Baseline From #1037

  • Built-in provider profiles are authored as one YAML file per provider under the top-level providers/ directory.
  • The first provider profile browsing command is openshell provider list-profiles.
  • Profile categories are an enum: inference, agent, source_control, messaging, data, knowledge, and other.
  • Provider v2 behavior is gated by the global gateway setting providers_v2_enabled, which defaults to false.
  • Existing provider behavior remains the default when providers_v2_enabled is false.
  • Credential injection is unchanged for now. Legacy provider mode and provider v2 still use the existing credential resolution/injection path until profile-defined credential injection is implemented later.
  • Gateway global policy remains a hammer override: when a global policy is configured, it suppresses provider profile policy layers so operators can make rapid policy changes when needed. Effective policy composition must always use the sandbox's current provider attachment list, so detaching a provider removes that provider's profile-generated policy layer on the next JIT policy fetch.

Proposed Design

Add a provider profile registry and import/export UX on top of the built-in profile catalog.

Built-in profiles remain available as read-only defaults. Custom profiles are stored by the gateway/control plane in the existing objects table using a distinct object type; do not add profile-specific persistence tables or migrations. They are exposed through the same provider profile browsing APIs as built-ins. Custom profiles can also be deleted by id. Deletion applies only to custom profiles; built-in profiles remain immutable read-only defaults and attempts to delete them should return a clear error. Custom profile deletion should also be rejected while any sandbox is using the profile. With the current schema, usage is derived from SandboxSpec.providers provider names and the referenced Provider.type matching the profile id. In the first iteration, avoid silently overwriting built-in profiles; custom profiles should use distinct ids unless an explicit replace/override mode is added.

Built-in profile files should continue to use the YAML DTO shape introduced in #1037. That means import/export should preserve the human-authored profile format, including fields such as id, display_name, description, category, credentials, endpoints, binaries, and inference_capable. The DTO should continue mapping compact authoring forms, such as binaries: [/usr/bin/gh], into the richer internal policy structs.

Add CLI commands for profile inspection and file-based profile management. Exact command names can follow the existing provider command shape, but expected capabilities are:

openshell provider list-profiles
openshell provider profile export <id> -o yaml|json
openshell provider profile import -f profile.yaml
openshell provider profile import --from ./profiles/
openshell provider profile lint -f profile.yaml
openshell provider profile delete <id>

Support K8s-style output modes where useful:

-o table
-o yaml
-o json

Default output should remain human-readable table output for list/browse commands. Profile export should default to YAML because profiles are authored as YAML.

For import/lint, validate both schema-level and semantic constraints and return an aggregated diagnostic summary. The implementation should collect all discoverable issues before returning, including examples such as:

  • missing or empty id
  • unsupported category outside the current enum values
  • duplicate profile ids in a bulk import
  • duplicate credential names within a profile
  • duplicate credential environment variable names within a profile
  • invalid or incomplete auth declarations
  • missing header_name for header auth
  • missing query_param for query auth
  • endpoint port out of range
  • empty endpoint host
  • invalid deny rules
  • empty binary paths
  • unsupported output/import file format

Bulk import should support a directory of *.yaml, *.yml, and *.json files. Multi-document YAML support is desirable if it fits cleanly. Recursive directory import can be deferred or gated behind an explicit --recursive flag.

Definition of Done

  • Gateway stores custom provider profiles separately from built-in profiles using the existing objects table and a distinct object type; no new profile-specific storage tables are added.
  • Built-in profiles remain available from the top-level providers/ catalog and cannot be accidentally overwritten by import.
  • Profile list/get APIs return both built-in and registered custom profiles with clear precedence semantics.
  • Profile list/get APIs expose the current category enum values: inference, agent, source_control, messaging, data, knowledge, and other.
  • CLI preserves and extends the existing openshell provider list-profiles UX; do not introduce the older list-types naming.
  • CLI can export a profile as YAML and JSON.
  • CLI supports K8s-style output modes for profile browsing where appropriate.
  • CLI can import a single profile file.
  • CLI can bulk import profiles from a directory.
  • CLI can lint profile files without registering them.
  • CLI can delete registered custom profiles by id.
  • Custom profile deletion is rejected when any sandbox attaches a provider whose Provider.type matches the profile id.
  • Built-in profile deletion is rejected with a clear error.
  • Import/lint returns an aggregated summary of all validation issues found in the provided input set.
  • Tests cover successful single import, bulk import, export round trip, custom profile deletion, in-use deletion rejection, built-in overwrite/delete rejection, and multi-error validation output.
  • Existing provider behavior remains unchanged unless the global providers_v2_enabled setting is enabled.
  • Provider v2 import/export does not change runtime credential injection behavior yet.
  • Effective policy composition uses the current sandbox provider attachment list; detached providers no longer contribute profile-generated policy on the next JIT policy fetch.
  • Internal architecture notes are updated if implementation details change; published docs/* updates are out of scope for this issue and will be handled in a later docs sweep.

Non-Goals

  • Do not implement proxy-side credential injection from profile auth declarations in this issue.
  • Do not implement OAuth2 credential refresh in this issue.
  • Do not implement provider attach/detach for running sandboxes in this issue.
    • If attach/detach exists or is added elsewhere, this issue should preserve the invariant that JIT policy composition reflects the current provider list, not a cached profile layer.
  • Do not change the default behavior of existing providers.
  • Do not add new profile-specific persistence tables; use the existing object store/objects table.
  • Do not delete or hide built-in provider profiles.
  • Do not cascade custom profile deletion into existing provider records or sandboxes.
  • Do not introduce a new sandbox attached-profile field in this issue; infer profile usage through existing sandbox providers and provider types.
  • Do not rename openshell provider list-profiles back to list-types.

Agent Investigation

Reviewed #896 after #1037 merged. This is the next low-risk chunk because it extends profile management and validation without changing sandbox runtime injection behavior. It prepares the registry surface needed by later provider v2 work: profile-backed credential injection, attach/detach, inference automation, verification, and refresh.

Updated after #1037 to reflect the merged command and setting names, top-level built-in provider YAML location, category enum, global policy override behavior, and current credential injection boundary.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions