Repository navigation
feat(providers): support safe custom provider profile updates #1881
Description
Activity
- addedarea:cliCLI-related workCLI-related workarea:policyPolicy engine and policy lifecycle workPolicy engine and policy lifecycle workarea:gatewayGateway server and control-plane workGateway server and control-plane work
on Jun 11, 2026 🏗️ build-plan
Implementation Plan
Issue type:
feat
Complexity: Medium
Confidence: High — clear pathSummary
Add safe update support for custom provider profiles through a new provider-profile update RPC and
openshell provider profile update -f|--from. The implementation will preserve stored profile identity/metadata, reject built-ins and missing custom profiles, reuse existing validation and attached-sandbox ambiguity checks, and rely on existing just-in-time policy/env revision composition so provider instances and sandbox source policies are not mutated.Scope
proto/openshell.proto: Add provider profile update RPC and request/response messages modeled after existing import/lint diagnostics.crates/openshell-server/src/grpc/mod.rs: Wire the new RPC with provider-profile write permissions matching import/delete.crates/openshell-server/src/grpc/provider.rs: Implement profile update handling, ID normalization, built-in/missing-profile rejection, metadata preservation, validation, attached-sandbox dynamic-token ambiguity checks, and persistence with resource-version update semantics.crates/openshell-cli/src/main.rs: Addopenshell provider profile updatewith-f/--fileand--frominputs.crates/openshell-cli/src/run.rs: Addprovider_profile_updateusing existing profile loading, diagnostics, and output conventions.crates/openshell-server/src/grpc/policy.rs: Add tests proving updated custom profile endpoints and provider env revision flow through config/environment paths without rewriting provider instances or sandbox source policy.docs/sandboxes/providers-v2.mdx: Document update semantics, rollout behavior, built-in immutability, and providers-v2/global-policy interactions.docs/sandboxes/manage-providers.mdx: Add concise examples for updating custom profiles.
Implementation Steps
- Define the proto API and regenerate/update generated bindings through the normal Rust build path.
- Add server trait wiring in
grpc/mod.rs. - Refactor provider-profile validation helpers so import and update can share parsing, validation, dynamic-token ambiguity checks, and diagnostics without reusing import’s “must not already exist” conflict rule.
- Implement update persistence: fetch the existing custom profile, verify the candidate profile ID normalizes to the same ID, copy existing metadata, replace only
profile, and write with update/CAS semantics. - Add the CLI subcommand and runner using existing profile file loading, diagnostics, and output conventions.
- Add server tests for success, built-in rejection, missing profile rejection, ID-change rejection, metadata preservation, and dynamic token grant ambiguity.
- Add policy/env tests for effective policy and
provider_env_revisionchanges after update. - Update docs.
Test Plan
- Unit tests: Provider update handler tests in
provider.rs; CLI parse tests inmain.rs; policy/env revision tests inpolicy.rs. - Integration tests: Handler-level import → update → get/list flows using test store/state;
GetSandboxConfigbehavior with providers v2 enabled/disabled and with global policy active. - E2E tests: Not expected. This is control-plane CRUD plus existing config sync behavior; existing unit/integration coverage should be sufficient unless an existing provider-profile CLI/gateway E2E suite is found and already covers this path.
Risks & Open Questions
- Batch update semantics: prefer all-or-none server-side batch diagnostics if supporting
--from; sequential CLI updates could partially roll out a directory. - Public CAS usability: current profile response exposes
ProviderProfile, not stored metadata/resource version. If CAS is included, decide whether the CLI can fetch a version, expose an optional flag, or leaveexpected_resource_version=0. - Auth scope should match import/delete profile behavior rather than provider read.
- Validation must avoid reusing import’s “already exists” conflict diagnostic for the profile being updated.
- Custom profile YAML is untrusted input that can expand sandbox network egress; strict validation and pre-persistence ambiguity rejection are required.
Documentation Impact
- Update
docs/sandboxes/providers-v2.mdxanddocs/sandboxes/manage-providers.mdx. - No gateway TOML, driver config, config default, or Helm-rendered
gateway.tomlchanges are expected, sodocs/reference/gateway-config.mdxis not expected to change.
LSM Compatibility
- No LSM-specific impact expected. The change is gateway/CLI/control-plane profile persistence and policy composition; it does not touch process identity,
/proc, binary execution, Landlock, seccomp, SELinux, or AppArmor behavior.
Revision 1 — initial plan
- addedstate:review-readyReady for human reviewReady for human reviewstate:agent-readyApproved for agent implementationApproved for agent implementationstate:in-progressWork is currently in progressWork is currently in progress
on Jun 11, 2026 🏗️ build-from-issue-agent
Implementation Complete
PR: #1914
What was built
Added custom provider profile update support through a new RPC and
openshell provider profile update -f|--from. Updates validate profile batches before writing, preserve stored custom profile metadata, reject built-ins and missing profiles, and keep provider-derived policy resolved dynamically from the current profile.Tests
- Unit: provider update handler tests for success, metadata preservation, built-in/missing rejection, and dynamic token ambiguity rejection
- Integration: CLI lifecycle and sandbox effective-policy/provider-env revision behavior
- E2E: skipped; no
e2e/files changed
Docs updated
docs/sandboxes/providers-v2.mdxdocs/sandboxes/manage-providers.mdx
The issue will auto-close when the PR is merged.
- addedstate:pr-openedPR has been opened for this issuePR has been opened for this issuegator:validatedGator validated this issue as ready for workGator validated this issue as ready for workand removedstate:in-progressWork is currently in progressWork is currently in progressstate:review-readyReady for human reviewReady for human review
on Jun 15, 2026 - added a parent issue
on Jun 16, 2026
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsDone
Problem Statement
Providers v2 supports importing, exporting, linting, and deleting custom provider profiles, but it does not support updating an existing custom provider profile.
This makes custom profile lifecycle management awkward and blocks safe rollout of profile changes. Provider instances reference profiles by
provider.type; they do not copy endpoint or binary policy into the provider instance. Effective sandbox policy is composed just-in-time from the sandbox policy plus the attached providers' profiles. That means a provider profile update is the natural control-plane operation for changing provider-derived policy across all provider instances of that type.Today, users must create a new profile ID, recreate or update provider instances to use the new type, and reattach or recreate sandbox state. That is unnecessary because the runtime model already resolves profiles dynamically.
Related umbrella issue: #896.
Proposed Design
Add first-class update support for custom provider profiles.
User-facing CLI:
Optional batch form:
Server/API behavior:
UpdateProviderProfileRPC.StoredProviderProfile.metadata.id,name,created_at_ms, and labels.StoredProviderProfile.profileand incrementresource_version.expected_resource_versionif practical.type, credentials, config, and credential expiry metadata.Effective policy behavior:
GetSandboxConfigcomposes effective policy from the current sandbox policy plusprofile_provider_policy_layers(...).providers_v2_enabled=false, profile network policy changes should not affect sandbox effective policy.Credential/dynamic credential behavior:
compute_provider_env_revision(...)already hashes custom profile payloads; tests should lock this in through the public update path.Validation and safety:
Implementation outline:
proto/openshell.proto: addUpdateProviderProfileRequestandUpdateProviderProfileResponseor reuseProviderProfileResponse.crates/openshell-cli/src/main.rs: addopenshell provider profile update.crates/openshell-cli/src/run.rs: parse YAML/JSON profile input using existing profile import helpers.crates/openshell-server/src/grpc/provider.rs: add handler that validates, fetches existing custom profile, runs attached-sandbox diagnostics with the candidate profile, then writes with CAS/update semantics instead ofWriteCondition::MustCreate.crates/openshell-server/src/grpc/policy.rs: add or extend tests proving updated profile endpoints appear in effective policy without modifying provider instances or persisted sandbox source policy.docs/sandboxes/providers-v2.mdx: document update semantics and rollout behavior.docs/sandboxes/manage-providers.mdx: add CLI examples for updating custom profiles.Definition of done:
openshell provider profile update -f profile.yamlupdates an existing custom profile._provider_*rules.Alternatives Considered
Use
openshell provider profile import --replace.This is compact, but it makes import more dangerous because the existing command is create-only today. A dedicated
updatecommand is clearer, easier to gate with stronger validation, and avoids accidental replacement when users expect import to be non-destructive.Create a new profile ID for every change.
This works today but forces provider instance churn and sandbox attachment churn. It does not match the current runtime model, where providers reference profiles dynamically by type.
Copy profile network policy into provider instances.
This would make profile updates harder because every provider instance would need migration. The current design already avoids this by resolving profiles from
provider.typeduring policy composition.Agent Investigation
export,import,lint, anddelete, but noupdate.ImportProviderProfilespersists custom profiles withWriteCondition::MustCreate.metadata,type,credentials,config, andcredential_expires_at_ms.SandboxSpec.providers, a repeated list of provider names.provider.typeto the provider profile.compute_provider_env_revision(...)hashes custom profile payloads, so profile changes can trigger sandbox-side provider refresh behavior.Checklist