{"id":612,"date":"2026-03-21T22:52:56","date_gmt":"2026-03-21T14:52:56","guid":{"rendered":"https:\/\/pa.yingzhi8.cn\/index.php\/2026\/03\/21\/gateway-secrets-plan-contract\/"},"modified":"2026-03-21T23:28:50","modified_gmt":"2026-03-21T15:28:50","slug":"gateway-secrets-plan-contract","status":"publish","type":"post","link":"https:\/\/pa.yingzhi8.cn\/index.php\/2026\/03\/21\/gateway-secrets-plan-contract\/","title":{"rendered":"Secrets Apply Plan Contract"},"content":{"rendered":"<h1>Secrets Apply Plan Contract<\/h1>\n<h1>Secrets apply plan contract<\/h1>\n<p>This page defines the strict contract enforced by <code>openclaw secrets apply<\/code>.<\/p>\n<p>If a target does not match these rules, apply fails before mutating configuration.<\/p>\n<h2>Plan file shape<\/h2>\n<p><code>openclaw secrets apply --from &lt;plan.json&gt;<\/code> expects a <code>targets<\/code> array of plan targets:<\/p>\n<p>&#8220;`json5  theme={&#8220;theme&#8221;:{&#8220;light&#8221;:&#8221;min-light&#8221;,&#8221;dark&#8221;:&#8221;min-dark&#8221;}}<br \/>\n{<br \/>\n  version: 1,<br \/>\n  protocolVersion: 1,<br \/>\n  targets: [<br \/>\n    {<br \/>\n      type: &#8220;models.providers.apiKey&#8221;,<br \/>\n      path: &#8220;models.providers.openai.apiKey&#8221;,<br \/>\n      pathSegments: [&#8220;models&#8221;, &#8220;providers&#8221;, &#8220;openai&#8221;, &#8220;apiKey&#8221;],<br \/>\n      providerId: &#8220;openai&#8221;,<br \/>\n      ref: { source: &#8220;env&#8221;, provider: &#8220;default&#8221;, id: &#8220;OPENAI_API_KEY&#8221; },<br \/>\n    },<br \/>\n    {<br \/>\n      type: &#8220;auth-profiles.api_key.key&#8221;,<br \/>\n      path: &#8220;profiles.openai:default.key&#8221;,<br \/>\n      pathSegments: [&#8220;profiles&#8221;, &#8220;openai:default&#8221;, &#8220;key&#8221;],<br \/>\n      agentId: &#8220;main&#8221;,<br \/>\n      ref: { source: &#8220;env&#8221;, provider: &#8220;default&#8221;, id: &#8220;OPENAI_API_KEY&#8221; },<br \/>\n    },<br \/>\n  ],<br \/>\n}<\/p>\n<pre><code>\n## Supported target scope\n\nPlan targets are accepted for supported credential paths in:\n\n* [SecretRef Credential Surface](\/reference\/secretref-credential-surface)\n\n## Target type behavior\n\nGeneral rule:\n\n* `target.type` must be recognized and must match the normalized `target.path` shape.\n\nCompatibility aliases remain accepted for existing plans:\n\n* `models.providers.apiKey`\n* `skills.entries.apiKey`\n* `channels.googlechat.serviceAccount`\n\n## Path validation rules\n\nEach target is validated with all of the following:\n\n* `type` must be a recognized target type.\n* `path` must be a non-empty dot path.\n* `pathSegments` can be omitted. If provided, it must normalize to exactly the same path as `path`.\n* Forbidden segments are rejected: `__proto__`, `prototype`, `constructor`.\n* The normalized path must match the registered path shape for the target type.\n* If `providerId` or `accountId` is set, it must match the id encoded in the path.\n* `auth-profiles.json` targets require `agentId`.\n* When creating a new `auth-profiles.json` mapping, include `authProfileProvider`.\n\n## Failure behavior\n\nIf a target fails validation, apply exits with an error like:\n\n```text  theme={&quot;theme&quot;:{&quot;light&quot;:&quot;min-light&quot;,&quot;dark&quot;:&quot;min-dark&quot;}}\nInvalid plan target path for models.providers.apiKey: models.providers.openai.baseUrl\n<\/code><\/pre>\n<p>No writes are committed for an invalid plan.<\/p>\n<h2>Exec provider consent behavior<\/h2>\n<ul>\n<li><code>--dry-run<\/code> skips exec SecretRef checks by default.<\/li>\n<li>Plans containing exec SecretRefs\/providers are rejected in write mode unless <code>--allow-exec<\/code> is set.<\/li>\n<li>When validating\/applying exec-containing plans, pass <code>--allow-exec<\/code> in both dry-run and write commands.<\/li>\n<\/ul>\n<h2>Runtime and audit scope notes<\/h2>\n<ul>\n<li>Ref-only <code>auth-profiles.json<\/code> entries (<code>keyRef<\/code>\/<code>tokenRef<\/code>) are included in runtime resolution and audit coverage.<\/li>\n<li><code>secrets apply<\/code> writes supported <code>openclaw.json<\/code> targets, supported <code>auth-profiles.json<\/code> targets, and optional scrub targets.<\/li>\n<\/ul>\n<h2>Operator checks<\/h2>\n<p>&#8220;`bash  theme={&#8220;theme&#8221;:{&#8220;light&#8221;:&#8221;min-light&#8221;,&#8221;dark&#8221;:&#8221;min-dark&#8221;}}<\/p>\n<h1>Validate plan without writes<\/h1>\n<p>openclaw secrets apply &#8211;from \/tmp\/openclaw-secrets-plan.json &#8211;dry-run<\/p>\n<h1>Then apply for real<\/h1>\n<p>openclaw secrets apply &#8211;from \/tmp\/openclaw-secrets-plan.json<\/p>\n<h1>For exec-containing plans, opt in explicitly in both modes<\/h1>\n<p>openclaw secrets apply &#8211;from \/tmp\/openclaw-secrets-plan.json &#8211;dry-run &#8211;allow-exec<br \/>\nopenclaw secrets apply &#8211;from \/tmp\/openclaw-secrets-plan.json &#8211;allow-exec<br \/>\n&#8220;`<\/p>\n<p>If apply fails with an invalid target path message, regenerate the plan with <code>openclaw secrets configure<\/code> or fix the target path to a supported shape above.<\/p>\n<h2>Related docs<\/h2>\n<ul>\n<li><a href=\"https:\/\/pa.yingzhi8.cn\/?p=611\">Secrets Management<\/a><\/li>\n<li><a href=\"https:\/\/pa.yingzhi8.cn\/?p=607\">CLI <code>secrets<\/code><\/a><\/li>\n<li><a href=\"https:\/\/pa.yingzhi8.cn\/?p=635\">SecretRef Credential Surface<\/a><\/li>\n<li><a href=\"https:\/\/pa.yingzhi8.cn\/?p=122\">\u914d\u7f6e\u8bf4\u660e Reference<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Secrets Apply Plan Contract Secrets apply plan contract [&hellip;]<\/p>\n","protected":false},"author":0,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-612","post","type-post","status-publish","format-standard","hentry","category-docs"],"_links":{"self":[{"href":"https:\/\/pa.yingzhi8.cn\/index.php\/wp-json\/wp\/v2\/posts\/612","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pa.yingzhi8.cn\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pa.yingzhi8.cn\/index.php\/wp-json\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/pa.yingzhi8.cn\/index.php\/wp-json\/wp\/v2\/comments?post=612"}],"version-history":[{"count":3,"href":"https:\/\/pa.yingzhi8.cn\/index.php\/wp-json\/wp\/v2\/posts\/612\/revisions"}],"predecessor-version":[{"id":813,"href":"https:\/\/pa.yingzhi8.cn\/index.php\/wp-json\/wp\/v2\/posts\/612\/revisions\/813"}],"wp:attachment":[{"href":"https:\/\/pa.yingzhi8.cn\/index.php\/wp-json\/wp\/v2\/media?parent=612"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pa.yingzhi8.cn\/index.php\/wp-json\/wp\/v2\/categories?post=612"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pa.yingzhi8.cn\/index.php\/wp-json\/wp\/v2\/tags?post=612"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}