diff --git a/docs/cli/secrets.md b/docs/cli/secrets.md index 397433aa68a..43bb4c9b977 100644 --- a/docs/cli/secrets.md +++ b/docs/cli/secrets.md @@ -97,6 +97,10 @@ openclaw secrets apply --from /tmp/openclaw-secrets-plan.json --dry-run openclaw secrets apply --from /tmp/openclaw-secrets-plan.json --json ``` +Plan contract details (allowed target paths, validation rules, and failure semantics): + +- [Secrets Apply Plan Contract](/gateway/secrets-plan-contract) + ## Why no rollback backups `secrets apply` intentionally does not write rollback backups containing old plaintext values. diff --git a/docs/docs.json b/docs/docs.json index 3211976230a..a6329ce0e06 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -1141,6 +1141,7 @@ "gateway/configuration-examples", "gateway/authentication", "gateway/secrets", + "gateway/secrets-plan-contract", "gateway/trusted-proxy-auth", "gateway/health", "gateway/heartbeat", diff --git a/docs/gateway/index.md b/docs/gateway/index.md index 8b4ef53aecb..f64de55f32a 100644 --- a/docs/gateway/index.md +++ b/docs/gateway/index.md @@ -19,6 +19,9 @@ Use this page for day-1 startup and day-2 operations of the Gateway service. SecretRef contract, runtime snapshot behavior, and migrate/reload operations. + + Exact `secrets apply` target/path rules and ref-only auth-profile behavior. + ## 5-minute local startup diff --git a/docs/gateway/secrets-plan-contract.md b/docs/gateway/secrets-plan-contract.md new file mode 100644 index 00000000000..d503d6cac82 --- /dev/null +++ b/docs/gateway/secrets-plan-contract.md @@ -0,0 +1,94 @@ +--- +summary: "Contract for `secrets apply` plans: allowed target paths, validation, and ref-only auth-profile behavior" +read_when: + - Generating or reviewing `openclaw secrets apply` plan files + - Debugging `Invalid plan target path` errors + - Understanding how `keyRef` and `tokenRef` influence implicit provider discovery +title: "Secrets Apply Plan Contract" +--- + +# Secrets apply plan contract + +This page defines the strict contract enforced by `openclaw secrets apply`. + +If a target does not match these rules, apply fails before mutating config. + +## Plan file shape + +`openclaw secrets apply --from ` expects a `targets` array of plan targets: + +```json5 +{ + version: 1, + protocolVersion: 1, + targets: [ + { + type: "models.providers.apiKey", + path: "models.providers.openai.apiKey", + pathSegments: ["models", "providers", "openai", "apiKey"], + providerId: "openai", + ref: { source: "env", provider: "default", id: "OPENAI_API_KEY" }, + }, + ], +} +``` + +## Allowed target types and paths + +| `target.type` | Allowed `target.path` shape | Optional id match rule | +| ------------------------------------ | --------------------------------------------------------- | --------------------------------------------------- | +| `models.providers.apiKey` | `models.providers..apiKey` | `providerId` must match `` when present | +| `skills.entries.apiKey` | `skills.entries..apiKey` | n/a | +| `channels.googlechat.serviceAccount` | `channels.googlechat.serviceAccount` | `accountId` must be empty/omitted | +| `channels.googlechat.serviceAccount` | `channels.googlechat.accounts..serviceAccount` | `accountId` must match `` when present | + +## Path validation rules + +Each target is validated with all of the following: + +- `type` must be one of the allowed target types above. +- `path` must be a non-empty dot path. +- `pathSegments` can be omitted. If provided, it must normalize to exactly the same path as `path`. +- Forbidden segments are rejected: `__proto__`, `prototype`, `constructor`. +- The normalized path must match one of the allowed path shapes for the target type. +- If `providerId` / `accountId` is set, it must match the id encoded in the path. + +## Failure behavior + +If a target fails validation, apply exits with an error like: + +```text +Invalid plan target path for models.providers.apiKey: models.providers.openai.baseUrl +``` + +No partial mutation is committed for that invalid target path. + +## Ref-only auth profiles and implicit providers + +Implicit provider discovery also considers auth profiles that store refs instead of plaintext credentials: + +- `type: "api_key"` profiles can use `keyRef` (for example env-backed refs). +- `type: "token"` profiles can use `tokenRef`. + +Behavior: + +- For API-key providers (for example `volcengine`, `byteplus`), ref-only profiles can still activate implicit provider entries. +- For `github-copilot`, if the profile has no plaintext token, discovery will try `tokenRef` env resolution before token exchange. + +## Operator checks + +```bash +# Validate plan without writes +openclaw secrets apply --from /tmp/openclaw-secrets-plan.json --dry-run + +# Then apply for real +openclaw secrets apply --from /tmp/openclaw-secrets-plan.json +``` + +If apply fails with an invalid target path message, regenerate the plan with `openclaw secrets configure` or fix the target path to one of the allowed shapes above. + +## Related docs + +- [Secrets Management](/gateway/secrets) +- [CLI `secrets`](/cli/secrets) +- [Configuration Reference](/gateway/configuration-reference) diff --git a/docs/gateway/secrets.md b/docs/gateway/secrets.md index 6b44e23e899..9fdec280d61 100644 --- a/docs/gateway/secrets.md +++ b/docs/gateway/secrets.md @@ -355,6 +355,10 @@ openclaw secrets apply --from /tmp/openclaw-secrets-plan.json openclaw secrets apply --from /tmp/openclaw-secrets-plan.json --dry-run ``` +For strict target/path contract details and exact rejection rules, see: + +- [Secrets Apply Plan Contract](/gateway/secrets-plan-contract) + ## One-way safety policy OpenClaw intentionally does **not** write rollback backups that contain pre-migration plaintext secret values. @@ -376,6 +380,7 @@ For static credentials, OpenClaw runtime no longer depends on plaintext `auth.js ## Related docs - CLI commands: [secrets](/cli/secrets) +- Plan contract details: [Secrets Apply Plan Contract](/gateway/secrets-plan-contract) - Auth setup: [Authentication](/gateway/authentication) - Security posture: [Security](/gateway/security) - Environment precedence: [Environment Variables](/help/environment)