Skip to content

bug(gateway): provider environment revision is not deterministic when a provider profile has several annotations #3929

Description

@rain-sicoreai

User Story

As a platform operator driving the OpenShell gateway API (operator workspace mode, Kubernetes driver) to create sandboxes with bound provider credentials,
I want the provider environment revision to be stable while nothing changes,
so that the supervisor installs the provider credentials and policy updates apply promptly.

Problem Statement

When a provider profile has more than one entry in a map field (for example two annotations), the gateway reports a different provider environment revision on successive calls although no provider, profile or policy changed. In our runs GetSandboxProviderEnvironment alternated between exactly two provider_env_revision values from poll to poll for the same sandbox, and the configuration snapshot's revision did not match the environment's.

The revision hash includes the profile's protobuf encoding (hash_scoped_profile_revision in crates/openshell-server/src/provider_profile_sources.rs calls entry.response.encode_to_vec(); also lines 105 and 126 on main). ProviderProfile.annotations is map<string, string> and openshell-core's build does not configure ordered maps, so the encoded bytes depend on hash-map iteration order.

Impact / Why This Matters

  • On every settings poll the supervisor logs Settings poll: config change detected [... provider_env_changed:true], then CONFIG:FAIL_CLOSED [HIGH] Provider environment refresh failed; static credentials were revoked ... and Provider environment is unavailable or changed during preparation: provider credentials are withheld from the workload for as long as the sandbox runs.
  • ReportEndpointStatus fails with FailedPrecondition ("tool server endpoint status revisions do not match the current sandbox configuration") on every report.
  • Sandbox startup can fail with Startup configuration did not stabilize after 5 attempts, and a policy update took ~60 s to load instead of ~10 s, because preparation keeps being retried.
  • Workaround: keep at most one entry in every map field of provider profiles. With one annotation the revision is stable, credentials are installed and policy updates load within ~10 s.

Acceptance Criteria

  • The provider environment revision (config snapshot and GetSandboxProviderEnvironment) is identical across calls when providers, profiles and policy are unchanged, for profiles with several annotations (and any other map field).
  • A sandbox whose provider profile has several annotations installs its static credentials, with no FAIL_CLOSED provider refresh events and no ReportEndpointStatus FailedPrecondition in steady state.

Reproduction Steps

  1. Import a provider profile with two annotations, e.g. ImportProviderProfiles with annotations: {"example.com/a": "1", "example.com/b": "2"} and one credential.
  2. Create a provider of that type and a sandbox whose policy binds an endpoint to it (credential_binding).
  3. Watch the gateway log line GetSandboxProviderEnvironment request completed successfully ... provider_env_revision=<n> over a few minutes: the value alternates between two numbers.
  4. Watch the supervisor log: repeated provider_env_changed:true and CONFIG:FAIL_CLOSED events.
  5. Repeat with a single annotation: the revision is stable and the events stop.

Environment

  • OpenShell: gateway and supervisor v0.1.0 (Helm chart); the hashing code is unchanged on main as of 2026-09-30
  • OS: Ubuntu 24.04 (kernel 6.8)
  • Runtime: Kubernetes v1.34 (kubeadm), containerd 2.3; sandboxes on runc and on Kata Containers 4.2 (Cloud Hypervisor), same result
  • Deployment or integration: gateway in workspace_mode = "operator", driven through the gateway gRPC API by a control plane that creates sandboxes, provider profiles and providers

Logs

OCSF CONFIG:DETECTED [INFO] Settings poll: config change detected [old_revision:... new_revision:... policy_changed:false provider_env_changed:true]
OCSF CONFIG:FAIL_CLOSED [HIGH] Provider environment refresh failed; static credentials were revoked and previous dynamic grants remain active
OCSF CONFIG:CONFIGURATION_ERROR [HIGH] Provider environment is unavailable or changed during preparation
WARN openshell_supervisor::endpoint_status: Endpoint status report failed transiently; retaining immutable snapshot

Gateway, same sandbox, consecutive polls (no changes in between):

GetSandboxProviderEnvironment request completed successfully ... provider_env_revision=12427382202249825736
GetSandboxProviderEnvironment request completed successfully ... provider_env_revision=9706283966309050004
GetSandboxProviderEnvironment request completed successfully ... provider_env_revision=12427382202249825736

Activity

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

    state:triage-neededOpened without agent diagnostics and needs triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions