Secrets Apply Plan Contract: Target Validation and Path Matching
This page details the strict contract enforced by `openclaw secrets apply` for plan files, including size limits, target validation, and path matching. It is essential for developers writing or generating plan files.
Read this when
- Generating or reviewing `openclaw secrets apply` plans
- Debugging `Invalid plan target path` errors
- Understanding target type and path validation behavior
This page describes the strict contract enforced by openclaw secrets apply. Apply fails before any file is modified if a target does not conform to these rules.
Plan file requirements
openclaw secrets apply --from <plan.json> accepts regular files up to 16 MiB (16,777,216 bytes). This limit applies to the entire serialized file, including whitespace. Directories, FIFOs, device files, and files exceeding the limit are rejected before JSON parsing or target validation.
openclaw secrets configure --plan-out <plan.json> applies the same limit to the UTF-8 serialized output before the file is created. Hand-written plans and external plan generators must also ensure the serialized file stays within this boundary.
Plan file shape
openclaw secrets apply --from <plan.json> expects a targets array of plan targets:
{
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" },
},
{
type: "auth-profiles.api_key.key",
path: "profiles.openai:default.key",
pathSegments: ["profiles", "openai:default", "key"],
agentId: "main",
ref: { source: "env", provider: "default", id: "OPENAI_API_KEY" },
},
],
}
openclaw secrets configure produces plans in this format. You can also write or edit one by hand.
Provider upserts and deletes
Plans may also include two optional top-level fields that modify the secrets.providers map alongside the per-target writes:
providerUpserts: an object keyed by provider alias. Each value is a provider definition (the same shape accepted undersecrets.providers.<alias>inopenclaw.json, for example anexecorfileprovider).providerDeletes: an array of provider aliases to remove.
providerUpserts runs before targets, so a target.ref.provider may reference a provider alias that the same plan introduces in providerUpserts. Without this ordering, plans referencing an alias not yet configured in openclaw.json fail with provider "<alias>" is not configured.
{
version: 1,
protocolVersion: 1,
providerUpserts: {
onepassword_anthropic: {
source: "exec",
command: "/usr/bin/op",
args: ["read", "op://Vault/Anthropic/credential"],
},
},
providerDeletes: ["legacy_unused_alias"],
targets: [
{
type: "models.providers.apiKey",
path: "models.providers.anthropic.apiKey",
pathSegments: ["models", "providers", "anthropic", "apiKey"],
providerId: "anthropic",
ref: { source: "exec", provider: "onepassword_anthropic", id: "credential" },
},
],
}
Exec providers introduced through providerUpserts are still subject to the exec consent rules in Exec provider consent behavior: plans containing exec providers require --allow-exec in write mode.
Supported target scope
Plan targets are accepted for supported credential paths in SecretRef Credential Surface.
Target type behavior
target.type must be a recognized target type, and the normalized target.path must match the registered path shape for that type.
Some target types accept a compatibility alias as target.type for existing plans, in addition to their canonical type name:
| Canonical type | Accepted alias |
|---|---|
models.providers.apiKey | models.providers.*.apiKey |
skills.entries.apiKey | skills.entries.*.apiKey |
channels.googlechat.serviceAccount | channels.googlechat.accounts.*.serviceAccount |
Path validation rules
Each target is validated against all of the following:
typemust be a recognized target type.pathmust be a non-empty dot path.pathSegmentscan be omitted. If provided, it must normalize to exactly the same path aspath.- Forbidden segments are rejected:
__proto__,prototype,constructor. - The normalized path must match the registered path shape for the target type.
- If
providerIdoraccountIdis set, it must match the id encoded in the path. auth-profiles.jsontargets requireagentId.- When creating a new
auth-profiles.jsonmapping, includeauthProfileProvider.
Failure behavior
If a target fails validation, apply exits with an error like:
Invalid plan target path for models.providers.apiKey: models.providers.openai.baseUrl
No writes are committed for an invalid plan: target resolution and path validation run before any file is touched. Separately, once a valid plan starts writing, apply snapshots every touched file first and restores those snapshots if a later write in the same run fails, so a partial write never leaves config, auth-profile, or env state out of sync.
Exec provider consent behavior
--dry-runskips exec SecretRef checks by default.- Plans containing exec SecretRefs/providers are rejected in write mode unless
--allow-execis set. - When validating/applying exec-containing plans, pass
--allow-execin both dry-run and write commands.
Runtime and audit scope notes
- Entries of type
auth-profiles.jsonthat are ref-only (keyRef/tokenRef) participate in credential resolution at runtime and fall under audit coverage. secrets applywrites toopenclaw.jsontargets,auth-profiles.jsontargets, and three optional scrub passes, each enabled by default:scrubEnv(strips migrated plaintext values from.envfiles located in the effective state and active-config directories),scrubAuthProfilesForProviderTargets(removes plaintext or unused ref residue fromauth-profiles.jsonfor providers that a plan just migrated), andscrubLegacyAuthJson(deletes migratedapi_keyentries from legacyauth.jsonstores). To skip a particular pass, setoptions.scrubEnv,options.scrubAuthProfilesForProviderTargets, oroptions.scrubLegacyAuthJsontofalsein the plan.
Operator checks
# 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
# For exec-containing plans, opt in explicitly in both modes
openclaw secrets apply --from /tmp/openclaw-secrets-plan.json --dry-run --allow-exec
openclaw secrets apply --from /tmp/openclaw-secrets-plan.json --allow-exec
When an apply fails due to an invalid target path message, either regenerate the plan with openclaw secrets configure or adjust the target path to one of the supported forms listed above.