openclaw-plugin-onepassword 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -6,6 +6,24 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.1.1] - 2026-09-01
10
+
11
+ ### Added
12
+
13
+ - **File sync mode** (`syncToFile`): resolve `op://` references in-process and
14
+ write them to a JSON file that OpenClaw's built-in `source: "file"` provider
15
+ reads. This unblocks channels (e.g. Slack) that reject `source: "store"` at
16
+ config validation. Writes are atomic (temp file + rename) with `0600`
17
+ permissions, and failed keys keep their last-known-good value from the existing
18
+ file. Independent of store sync — both can run together.
19
+ - `onepassword.sync` now returns `fileWritten` and `fileErrors`; `onepassword.status`
20
+ now reports `syncToFileEnabled`, `managedFileKeys`, and `filePath`.
21
+ - On startup, the plugin logs the key count of an existing sync file.
22
+
23
+ ### Changed
24
+
25
+ - `failFastOnStartup` now also covers file-write failures when `syncToFile` is configured.
26
+
9
27
  ## [0.1.0] - 2026-09-01
10
28
 
11
29
  ### Added
@@ -23,5 +41,6 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
23
41
  - **Optional exec resolver mode** via `secretProviderIntegrations` for setups
24
42
  that allowlist 1Password egress and prefer `op://` ids on `SecretRef`s.
25
43
 
26
- [Unreleased]: https://github.com/ioleksiy/openclaw-plugin-onepassword/compare/v0.1.0...HEAD
44
+ [Unreleased]: https://github.com/ioleksiy/openclaw-plugin-onepassword/compare/v0.1.1...HEAD
45
+ [0.1.1]: https://github.com/ioleksiy/openclaw-plugin-onepassword/releases/tag/v0.1.1
27
46
  [0.1.0]: https://github.com/ioleksiy/openclaw-plugin-onepassword/releases/tag/v0.1.0
package/README.md CHANGED
@@ -31,12 +31,15 @@ A native [OpenClaw](https://openclaw.ai) plugin that resolves **[1Password](http
31
31
 
32
32
  ## How it works
33
33
 
34
- There are two ways a plugin can feed secrets to OpenClaw. This plugin ships both, but **the in-process store sync is the recommended path** because it is the only one that reliably bypasses the exec sandbox.
34
+ This plugin can feed secrets to OpenClaw three ways. The in-process modes (store sync and file sync) run inside the Gateway and reliably bypass the exec sandbox; pick based on what the consuming channel/provider accepts.
35
35
 
36
- | Mode | Runs where | Bypasses exec sandbox? | `SecretRef` you write | Vault/item paths live in |
37
- | ---------------------------- | ---------------------- | -------------------------------- | -------------------------------------- | ----------------------------- |
38
- | **Store sync** (default) | In-process (Gateway) | ✅ Yes | `source: "store"` | plugin `config.secrets` map |
39
- | **Exec resolver** (advanced) | Sandboxed child `node` | ⚠️ Only with egress allowlisting | `source: "exec"` + `pluginIntegration` | the `SecretRef.id` (`op://…`) |
36
+ | Mode | Runs where | Bypasses exec sandbox? | `SecretRef` you write | Vault/item paths live in |
37
+ | ---------------------------- | ---------------------- | -------------------------------- | -------------------------------------- | ------------------------------ |
38
+ | **Store sync** (default) | In-process (Gateway) | ✅ Yes | `source: "store"` | plugin `config.secrets` map |
39
+ | **File sync** | In-process (Gateway) | Yes | `source: "file"` | plugin `config.syncToFile` map |
40
+ | **Exec resolver** (advanced) | Sandboxed child `node` | ⚠️ Only with egress allowlisting | `source: "exec"` + `pluginIntegration` | the `SecretRef.id` (`op://…`) |
41
+
42
+ > **Which in-process mode?** Prefer **store sync** (`source: "store"`). But some bundled channel plugins — notably **Slack** — reject `source: "store"` at config-validation time and accept only `env`, `file`, or `exec`. For those, use **file sync** (`source: "file"`). The two are independent and can run together (e.g. store sync for OpenAI, file sync for Slack).
40
43
 
41
44
  **Store sync**, in one picture:
42
45
 
@@ -141,22 +144,82 @@ Store keys must match `^[A-Z][A-Z0-9_]{0,127}$` (OpenClaw store-id grammar). Val
141
144
 
142
145
  See [`examples/`](./examples) for complete config files.
143
146
 
147
+ ## File sync mode (for channels that reject `source: "store"`)
148
+
149
+ Some bundled channel plugins — **Slack** in particular — reject `source: "store"` SecretRefs at config-validation time and accept only `env`, `file`, or `exec`. Because this plugin runs in-process, it can resolve `op://` references and write them to a JSON file that OpenClaw's built-in **`source: "file"`** provider reads — which those channels accept.
150
+
151
+ 1. **Configure `syncToFile`** in the plugin config (independent of `secrets`; both can be active):
152
+
153
+ ```json
154
+ {
155
+ "plugins": {
156
+ "entries": {
157
+ "onepassword": {
158
+ "enabled": true,
159
+ "config": {
160
+ "serviceAccountTokenEnvVar": "OP_SERVICE_ACCOUNT_TOKEN",
161
+ "syncToFile": {
162
+ "path": "/home/node/.openclaw/op-secrets.json",
163
+ "mode": "json",
164
+ "secrets": {
165
+ "SLACK_BOT_TOKEN_A": "op://MyVault/SlackBot/bot_token",
166
+ "SLACK_APP_TOKEN_A": "op://MyVault/SlackBot/app_token"
167
+ }
168
+ }
169
+ }
170
+ }
171
+ }
172
+ }
173
+ }
174
+ ```
175
+
176
+ 2. **Declare a `file` provider and reference the keys** with `source: "file"` (the `id` is a JSON pointer, `/KEY`):
177
+
178
+ ```json
179
+ {
180
+ "secrets": {
181
+ "providers": {
182
+ "op-file": {
183
+ "source": "file",
184
+ "path": "/home/node/.openclaw/op-secrets.json",
185
+ "mode": "json"
186
+ }
187
+ }
188
+ },
189
+ "channels": {
190
+ "slack": {
191
+ "accounts": {
192
+ "myworkspace": {
193
+ "botToken": { "source": "file", "provider": "op-file", "id": "/SLACK_BOT_TOKEN_A" },
194
+ "appToken": { "source": "file", "provider": "op-file", "id": "/SLACK_APP_TOKEN_A" }
195
+ }
196
+ }
197
+ }
198
+ }
199
+ }
200
+ ```
201
+
202
+ The file is written **atomically** (temp file + rename) with `0600` permissions. Keys that fail to resolve keep their last-known-good value from the existing file, so a transient 1Password failure doesn't break a running channel. See [`examples/openclaw.file-mode.json`](./examples/openclaw.file-mode.json).
203
+
204
+ > **⚠️ The sync file contains plaintext secret values.** It lives in the OpenClaw data volume (same trust boundary as the SQLite store). Keep its path **inside that volume and outside any path an agent can read** — otherwise an agent with file tools could exfiltrate it. Add the file (or its directory) to your agent file-access denylist (e.g. `tools.exec.denyPaths` or the equivalent for your sandbox).
205
+
144
206
  ## Configuration reference
145
207
 
146
208
  All keys live under `plugins.entries.onepassword.config`.
147
209
 
148
- | Key | Type | Default | Description |
149
- | --------------------------- | ------- | ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
150
- | `serviceAccountTokenEnvVar` | string | `"OP_SERVICE_ACCOUNT_TOKEN"` | Name of the environment variable holding the service account token. |
151
- | `secrets` | object | `{}` | Map of **store key → `op://…` reference**. Store keys must match `^[A-Z][A-Z0-9_]{0,127}$`. |
152
- | `syncOnStartup` | boolean | `true` | Fetch `secrets` from 1Password and write to the store at Gateway startup. |
153
- | `failFastOnStartup` | boolean | `false` | If `true`, a startup sync failure throws and prevents startup. If `false`, log and fall back to last-known-good store values. |
154
- | `integrationName` | string | `"openclaw-plugin-onepassword"` | Integration name reported to 1Password audit logs. |
155
- | `requestTimeoutMs` | number | `15000` | Per-operation timeout for 1Password SDK calls. |
156
- | `tools.enabled` | boolean | `false` | Register the read-only 1Password agent tools. |
157
- | `tools.allowWrite` | boolean | `false` | Also register create/update/delete tools. Requires `tools.enabled`. |
210
+ | Key | Type | Default | Description |
211
+ | --------------------------- | ------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
212
+ | `serviceAccountTokenEnvVar` | string | `"OP_SERVICE_ACCOUNT_TOKEN"` | Name of the environment variable holding the service account token. |
213
+ | `secrets` | object | `{}` | Map of **store key → `op://…` reference** (store sync). Keys must match `^[A-Z][A-Z0-9_]{0,127}$`. |
214
+ | `syncToFile` | object | | File sync block: `{ path, mode: "json", secrets }`. See [File sync mode](#file-sync-mode-for-channels-that-reject-source-store). |
215
+ | `syncOnStartup` | boolean | `true` | Fetch configured secrets from 1Password and sync them (store + file) at Gateway startup. |
216
+ | `failFastOnStartup` | boolean | `false` | If `true`, a startup sync failure (resolve, store write, or file write) throws and prevents startup. If `false`, log and fall back to last-known-good values. |
217
+ | `integrationName` | string | `"openclaw-plugin-onepassword"` | Integration name reported to 1Password audit logs. |
218
+ | `requestTimeoutMs` | number | `15000` | Per-operation timeout for 1Password SDK calls. |
219
+ | `tools.enabled` | boolean | `false` | Register the read-only 1Password agent tools. |
220
+ | `tools.allowWrite` | boolean | `false` | Also register create/update/delete tools. Requires `tools.enabled`. |
158
221
 
159
- The plugin **hardcodes no vault names, item paths, or field names**. The only 1Password-specific configuration is the env var name and the `secrets` map you provide.
222
+ The plugin **hardcodes no vault names, item paths, or field names**. The only 1Password-specific configuration is the env var name and the `secrets` / `syncToFile.secrets` maps you provide.
160
223
 
161
224
  ## Agent tools (optional)
162
225
 
@@ -189,8 +252,8 @@ Set `tools.enabled: true` to expose in-process tools to the agent. Read tools re
189
252
 
190
253
  Both require the `operator.admin` scope.
191
254
 
192
- - **`onepassword.sync`** — re-fetch every configured secret from 1Password and write it into the store. Returns `{ written, total, resolveErrors, storeErrors }`.
193
- - **`onepassword.status`** — non-secret health/config summary: `{ version, serviceAccountTokenEnvVar, tokenPresent, syncOnStartup, managedStoreKeys, toolsEnabled, toolsWriteEnabled }`.
255
+ - **`onepassword.sync`** — re-fetch every configured secret from 1Password and write it to the store and/or the sync file. Returns `{ written, fileWritten, total, resolveErrors, storeErrors, fileErrors }`.
256
+ - **`onepassword.status`** — non-secret health/config summary: `{ version, serviceAccountTokenEnvVar, tokenPresent, syncOnStartup, managedStoreKeys, syncToFileEnabled, managedFileKeys, filePath, toolsEnabled, toolsWriteEnabled }`.
194
257
 
195
258
  ## Refreshing secrets at runtime
196
259
 
@@ -247,19 +310,22 @@ Use the host that matches your 1Password account region. If your environment can
247
310
  ## Security notes
248
311
 
249
312
  - **The token is the crown jewel.** Anyone with the service account token has the service account's access. Scope the service account to the minimum vaults required, and inject the token via your platform's secret mechanism — never commit it.
250
- - **No plaintext secrets in config.** The plugin only reads an env var name and `op://` references; resolved values live only in OpenClaw's store.
313
+ - **No plaintext secrets in config.** The plugin only reads an env var name and `op://` references; resolved values live only in OpenClaw's store (store sync) or the sync file (file sync).
314
+ - **The file sync output is plaintext.** If you use `syncToFile`, keep its path inside the OpenClaw data volume and out of any agent-readable path; add it to your agent file-access denylist. See [File sync mode](#file-sync-mode-for-channels-that-reject-source-store).
251
315
  - **Plugin code runs in your Gateway process** with full Gateway privileges (this is true of every OpenClaw plugin). Review the source before installing.
252
316
  - **Write tools are opt-in** (`tools.allowWrite`) and **concealed fields are redacted** by read tools unless `includeSecrets: true`.
253
317
  - Report vulnerabilities per [SECURITY.md](./SECURITY.md).
254
318
 
255
319
  ## Troubleshooting
256
320
 
257
- | Symptom | Likely cause / fix |
258
- | ------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
259
- | `... token not found` at startup | The env var named by `serviceAccountTokenEnvVar` is unset on the Gateway process. |
260
- | `SECRETS_PROVIDER_DEGRADED` for a store ref | The store key hasn't been populated yet — run `onepassword.sync`, or check the startup logs for resolve errors. |
261
- | Resolve error `NOT_FOUND` | The `op://` reference is wrong or the service account can't access that vault/item/field. |
262
- | Exec resolver returns nothing | Sandbox is blocking network add your 1Password host to `secrets.egressProxy.allowedHosts`, or switch to store sync. |
321
+ | Symptom | Likely cause / fix |
322
+ | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
323
+ | `... token not found` at startup | The env var named by `serviceAccountTokenEnvVar` is unset on the Gateway process. |
324
+ | `SECRETS_PROVIDER_DEGRADED` for a store ref | The store key hasn't been populated yet — run `onepassword.sync`, or check the startup logs for resolve errors. |
325
+ | `source: must be equal to constant (allowed: "env"/"file"/"exec")` on a channel | That channel (e.g. Slack) rejects `source: "store"`. Use [File sync mode](#file-sync-mode-for-channels-that-reject-source-store) with `source: "file"`. |
326
+ | `source: "file"` ref resolves empty | The sync file wasn't written yet, or the `id` JSON pointer is wrong (must be `/KEY`). Check `onepassword.status` `filePath` and startup logs. |
327
+ | Resolve error `NOT_FOUND` | The `op://` reference is wrong or the service account can't access that vault/item/field. |
328
+ | Exec resolver returns nothing | Sandbox is blocking network — add your 1Password host to `secrets.egressProxy.allowedHosts`, or switch to store sync. |
263
329
 
264
330
  ## Development
265
331
 
package/dist/config.d.ts CHANGED
@@ -17,21 +17,34 @@ export interface OnePasswordToolsConfig {
17
17
  enabled: boolean;
18
18
  allowWrite: boolean;
19
19
  }
20
+ export type SyncToFileMode = "json";
21
+ export interface SyncToFileConfig {
22
+ /** Absolute path of the JSON file to write inside the OpenClaw data volume. */
23
+ path: string;
24
+ /** File format. Only "json" (flat object, JSON-pointer ids) is supported. */
25
+ mode: SyncToFileMode;
26
+ /** Map of file key -> 1Password secret reference. */
27
+ secrets: Record<string, string>;
28
+ }
20
29
  export interface OnePasswordPluginConfig {
21
30
  serviceAccountTokenEnvVar: string;
22
31
  integrationName: string;
23
32
  requestTimeoutMs: number;
24
33
  syncOnStartup: boolean;
25
34
  failFastOnStartup: boolean;
26
- /** Map of OpenClaw store key -> 1Password secret reference. */
35
+ /** Map of OpenClaw store key -> 1Password secret reference (store sync). */
27
36
  secrets: Record<string, string>;
37
+ /** Optional JSON-file sync, for channels that reject `source: "store"`. */
38
+ syncToFile?: SyncToFileConfig;
28
39
  tools: OnePasswordToolsConfig;
29
40
  }
30
41
  export declare class ConfigError extends Error {
31
42
  readonly name = "ConfigError";
32
43
  }
33
- /** Validate a single `storeKey -> op://...` secrets mapping. */
34
- export declare function parseSecretsMap(value: unknown): Record<string, string>;
44
+ /** Validate a `key -> op://...` secrets mapping. `label` names it in errors. */
45
+ export declare function parseSecretsMap(value: unknown, label?: string): Record<string, string>;
46
+ /** Parse and validate the optional `syncToFile` block. */
47
+ export declare function parseSyncToFile(value: unknown): SyncToFileConfig | undefined;
35
48
  /**
36
49
  * Parse and validate the plugin config, applying defaults. Throws
37
50
  * {@link ConfigError} on any invalid input so misconfiguration surfaces at
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,iDAAiD;AACjD,eAAO,MAAM,iBAAiB,QAA4B,CAAC;AAE3D,wEAAwE;AACxE,eAAO,MAAM,oBAAoB,QAAsB,CAAC;AAExD,eAAO,MAAM,qBAAqB,6BAA6B,CAAC;AAChE,eAAO,MAAM,wBAAwB,gCAAgC,CAAC;AACtE,eAAO,MAAM,0BAA0B,QAAS,CAAC;AAEjD,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,uBAAuB;IACtC,yBAAyB,EAAE,MAAM,CAAC;IAClC,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,OAAO,CAAC;IACvB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,+DAA+D;IAC/D,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,KAAK,EAAE,sBAAsB,CAAC;CAC/B;AAED,qBAAa,WAAY,SAAQ,KAAK;IACpC,SAAyB,IAAI,iBAAiB;CAC/C;AAiCD,gEAAgE;AAChE,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAiBtE;AAYD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,uBAAuB,CAgBzE;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,IAAI,CAAC,uBAAuB,EAAE,2BAA2B,CAAC,EAClE,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,GAAG,SAAS,CAMpB"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,iDAAiD;AACjD,eAAO,MAAM,iBAAiB,QAA4B,CAAC;AAE3D,wEAAwE;AACxE,eAAO,MAAM,oBAAoB,QAAsB,CAAC;AAExD,eAAO,MAAM,qBAAqB,6BAA6B,CAAC;AAChE,eAAO,MAAM,wBAAwB,gCAAgC,CAAC;AACtE,eAAO,MAAM,0BAA0B,QAAS,CAAC;AAEjD,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC;AAEpC,MAAM,WAAW,gBAAgB;IAC/B,+EAA+E;IAC/E,IAAI,EAAE,MAAM,CAAC;IACb,6EAA6E;IAC7E,IAAI,EAAE,cAAc,CAAC;IACrB,qDAAqD;IACrD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,uBAAuB;IACtC,yBAAyB,EAAE,MAAM,CAAC;IAClC,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,OAAO,CAAC;IACvB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,4EAA4E;IAC5E,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,2EAA2E;IAC3E,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,KAAK,EAAE,sBAAsB,CAAC;CAC/B;AAED,qBAAa,WAAY,SAAQ,KAAK;IACpC,SAAyB,IAAI,iBAAiB;CAC/C;AAiCD,gFAAgF;AAChF,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,SAAY,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAiBzF;AAED,0DAA0D;AAC1D,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB,GAAG,SAAS,CAmB5E;AAYD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,uBAAuB,CAiBzE;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,IAAI,CAAC,uBAAuB,EAAE,2BAA2B,CAAC,EAClE,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,GAAG,SAAS,CAMpB"}
package/dist/config.js CHANGED
@@ -46,21 +46,43 @@ function optionalPositiveNumber(value, field) {
46
46
  }
47
47
  return value;
48
48
  }
49
- /** Validate a single `storeKey -> op://...` secrets mapping. */
50
- export function parseSecretsMap(value) {
49
+ /** Validate a `key -> op://...` secrets mapping. `label` names it in errors. */
50
+ export function parseSecretsMap(value, label = "secrets") {
51
51
  const raw = asRecord(value);
52
52
  const out = {};
53
53
  for (const [key, ref] of Object.entries(raw)) {
54
54
  if (!STORE_KEY_PATTERN.test(key)) {
55
- throw new ConfigError(`secrets store key "${key}" is invalid; keys must match ${STORE_KEY_PATTERN.source} (uppercase env-var grammar).`);
55
+ throw new ConfigError(`${label} key "${key}" is invalid; keys must match ${STORE_KEY_PATTERN.source} (uppercase env-var grammar).`);
56
56
  }
57
57
  if (typeof ref !== "string" || !OP_REFERENCE_PATTERN.test(ref)) {
58
- throw new ConfigError(`secrets["${key}"] must be a 1Password reference like "op://Vault/Item/field"; got ${JSON.stringify(ref)}.`);
58
+ throw new ConfigError(`${label}["${key}"] must be a 1Password reference like "op://Vault/Item/field"; got ${JSON.stringify(ref)}.`);
59
59
  }
60
60
  out[key] = ref;
61
61
  }
62
62
  return out;
63
63
  }
64
+ /** Parse and validate the optional `syncToFile` block. */
65
+ export function parseSyncToFile(value) {
66
+ if (value === undefined || value === null)
67
+ return undefined;
68
+ if (typeof value !== "object" || Array.isArray(value)) {
69
+ throw new ConfigError('"syncToFile" must be an object.');
70
+ }
71
+ const raw = value;
72
+ const path = optionalString(raw.path, "syncToFile.path");
73
+ if (!path) {
74
+ throw new ConfigError('"syncToFile.path" is required and must be a non-empty string.');
75
+ }
76
+ const mode = optionalString(raw.mode, "syncToFile.mode") ?? "json";
77
+ if (mode !== "json") {
78
+ throw new ConfigError('"syncToFile.mode" must be "json" (the only supported mode).');
79
+ }
80
+ const secrets = parseSecretsMap(raw.secrets, "syncToFile.secrets");
81
+ if (Object.keys(secrets).length === 0) {
82
+ throw new ConfigError('"syncToFile.secrets" must contain at least one key -> op:// mapping.');
83
+ }
84
+ return { path, mode, secrets };
85
+ }
64
86
  function parseTools(value) {
65
87
  const raw = asRecord(value);
66
88
  const enabled = optionalBoolean(raw.enabled, "tools.enabled") ?? false;
@@ -86,6 +108,7 @@ export function parsePluginConfig(input) {
86
108
  syncOnStartup: optionalBoolean(raw.syncOnStartup, "syncOnStartup") ?? true,
87
109
  failFastOnStartup: optionalBoolean(raw.failFastOnStartup, "failFastOnStartup") ?? false,
88
110
  secrets: parseSecretsMap(raw.secrets),
111
+ syncToFile: parseSyncToFile(raw.syncToFile),
89
112
  tools: parseTools(raw.tools),
90
113
  };
91
114
  }
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * File sync mode.
3
+ *
4
+ * Some bundled OpenClaw channel plugins (e.g. Slack) reject `source: "store"`
5
+ * SecretRefs at config-validation time, allowing only `env`, `file`, and
6
+ * `exec`. Since the plugin runs in-process (no exec sandbox), it can resolve
7
+ * `op://` references and write them to a JSON file that OpenClaw's built-in
8
+ * `source: "file"` provider reads — which those channels accept.
9
+ *
10
+ * The file contains plaintext secret values. It must live inside the OpenClaw
11
+ * data volume (same trust boundary as the SQLite store) and outside any path an
12
+ * agent can read. Writes are atomic (temp file + rename) and `0600`.
13
+ */
14
+ import type { OnePasswordClient } from "./op-client.js";
15
+ import type { SyncLogger } from "./secret-sync.js";
16
+ export interface FileSyncOptions {
17
+ client: OnePasswordClient;
18
+ path: string;
19
+ secrets: Record<string, string>;
20
+ logger?: SyncLogger;
21
+ }
22
+ export interface FileSyncResult {
23
+ /** File keys written with a freshly resolved value this run. */
24
+ fileWritten: string[];
25
+ /** File key -> error message for references that failed to resolve. */
26
+ resolveErrors: Record<string, string>;
27
+ /** File key -> error message when persisting the file failed. */
28
+ fileErrors: Record<string, string>;
29
+ /** Number of configured file keys. */
30
+ total: number;
31
+ }
32
+ /** Expand a leading `~` to the current user's home directory. */
33
+ export declare function expandHome(path: string): string;
34
+ /** Count keys in an existing sync file, or `undefined` if it can't be read. */
35
+ export declare function readExistingKeyCount(path: string): Promise<number | undefined>;
36
+ /**
37
+ * Resolve the configured references and write them to a JSON file. Keys that
38
+ * fail to resolve are reported in `resolveErrors`; if a previous value for such
39
+ * a key exists in the current file it is carried forward (last-known-good) so a
40
+ * transient 1Password failure does not break a running channel.
41
+ */
42
+ export declare function syncSecretsToFile(options: FileSyncOptions): Promise<FileSyncResult>;
43
+ //# sourceMappingURL=file-sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-sync.d.ts","sourceRoot":"","sources":["../src/file-sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAMH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAKnD,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,iBAAiB,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,gEAAgE;IAChE,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,uEAAuE;IACvE,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,iEAAiE;IACjE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;CACf;AAED,iEAAiE;AACjE,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI/C;AAmBD,+EAA+E;AAC/E,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAUpF;AAoBD;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CAoDzF"}
@@ -0,0 +1,133 @@
1
+ /**
2
+ * File sync mode.
3
+ *
4
+ * Some bundled OpenClaw channel plugins (e.g. Slack) reject `source: "store"`
5
+ * SecretRefs at config-validation time, allowing only `env`, `file`, and
6
+ * `exec`. Since the plugin runs in-process (no exec sandbox), it can resolve
7
+ * `op://` references and write them to a JSON file that OpenClaw's built-in
8
+ * `source: "file"` provider reads — which those channels accept.
9
+ *
10
+ * The file contains plaintext secret values. It must live inside the OpenClaw
11
+ * data volume (same trust boundary as the SQLite store) and outside any path an
12
+ * agent can read. Writes are atomic (temp file + rename) and `0600`.
13
+ */
14
+ import { chmod, mkdir, readFile, rename, writeFile } from "node:fs/promises";
15
+ import { homedir } from "node:os";
16
+ import { dirname, join } from "node:path";
17
+ const FILE_MODE = 0o600;
18
+ const DIR_MODE = 0o700;
19
+ /** Expand a leading `~` to the current user's home directory. */
20
+ export function expandHome(path) {
21
+ if (path === "~")
22
+ return homedir();
23
+ if (path.startsWith("~/"))
24
+ return join(homedir(), path.slice(2));
25
+ return path;
26
+ }
27
+ /** Best-effort read of the existing file's flat string map (for last-known-good). */
28
+ async function readExistingValues(path) {
29
+ try {
30
+ const parsed = JSON.parse(await readFile(path, "utf8"));
31
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
32
+ const out = {};
33
+ for (const [k, v] of Object.entries(parsed)) {
34
+ if (typeof v === "string")
35
+ out[k] = v;
36
+ }
37
+ return out;
38
+ }
39
+ }
40
+ catch {
41
+ // Missing/unreadable/invalid file — treat as empty.
42
+ }
43
+ return {};
44
+ }
45
+ /** Count keys in an existing sync file, or `undefined` if it can't be read. */
46
+ export async function readExistingKeyCount(path) {
47
+ try {
48
+ const parsed = JSON.parse(await readFile(expandHome(path), "utf8"));
49
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
50
+ return Object.keys(parsed).length;
51
+ }
52
+ }
53
+ catch {
54
+ return undefined;
55
+ }
56
+ return undefined;
57
+ }
58
+ /** Atomically write `content` to `path` with `0600` perms (temp file + rename). */
59
+ async function writeFileAtomic(path, content) {
60
+ const dir = dirname(path);
61
+ await mkdir(dir, { recursive: true, mode: DIR_MODE });
62
+ const tmp = `${path}.tmp-${process.pid}-${Date.now()}`;
63
+ await writeFile(tmp, content, { mode: FILE_MODE });
64
+ try {
65
+ await rename(tmp, path);
66
+ }
67
+ catch (err) {
68
+ // Clean up the temp file on failure; ignore secondary errors.
69
+ await import("node:fs/promises").then((fs) => fs.rm(tmp, { force: true })).catch(() => { });
70
+ throw err;
71
+ }
72
+ // rename preserves the temp file's mode, but enforce it in case the target
73
+ // pre-existed with looser permissions on some platforms.
74
+ await chmod(path, FILE_MODE).catch(() => { });
75
+ }
76
+ /**
77
+ * Resolve the configured references and write them to a JSON file. Keys that
78
+ * fail to resolve are reported in `resolveErrors`; if a previous value for such
79
+ * a key exists in the current file it is carried forward (last-known-good) so a
80
+ * transient 1Password failure does not break a running channel.
81
+ */
82
+ export async function syncSecretsToFile(options) {
83
+ const { client, secrets, logger } = options;
84
+ const path = expandHome(options.path);
85
+ const entries = Object.entries(secrets);
86
+ const result = {
87
+ fileWritten: [],
88
+ resolveErrors: {},
89
+ fileErrors: {},
90
+ total: entries.length,
91
+ };
92
+ if (entries.length === 0)
93
+ return result;
94
+ const references = [...new Set(entries.map(([, ref]) => ref))];
95
+ const { values, errors } = await client.resolveAll(references);
96
+ const existing = await readExistingValues(path);
97
+ const output = {};
98
+ const freshKeys = [];
99
+ for (const [key, reference] of entries) {
100
+ const value = values[reference];
101
+ if (value !== undefined) {
102
+ output[key] = value;
103
+ freshKeys.push(key);
104
+ }
105
+ else {
106
+ const message = errors[reference] ?? "reference did not resolve";
107
+ result.resolveErrors[key] = message;
108
+ logger?.warn?.(`onepassword: failed to resolve file key ${key} (${reference}): ${message}`);
109
+ if (existing[key] !== undefined) {
110
+ // Preserve the last-known-good value so the channel keeps working.
111
+ output[key] = existing[key];
112
+ logger?.debug?.(`onepassword: kept last-known-good file value for ${key}`);
113
+ }
114
+ }
115
+ }
116
+ if (Object.keys(output).length === 0) {
117
+ logger?.warn?.(`onepassword: nothing resolved for file sync; leaving ${path} unchanged`);
118
+ return result;
119
+ }
120
+ try {
121
+ await writeFileAtomic(path, JSON.stringify(output, null, 2) + "\n");
122
+ result.fileWritten = freshKeys;
123
+ logger?.info?.(`onepassword: wrote ${freshKeys.length} secret(s) to ${path} (${Object.keys(output).length} total keys)`);
124
+ }
125
+ catch (err) {
126
+ const message = err instanceof Error ? err.message : String(err);
127
+ for (const [key] of entries)
128
+ result.fileErrors[key] = message;
129
+ logger?.error?.(`onepassword: failed to write ${path}: ${message}`);
130
+ }
131
+ return result;
132
+ }
133
+ //# sourceMappingURL=file-sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-sync.js","sourceRoot":"","sources":["../src/file-sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAK1C,MAAM,SAAS,GAAG,KAAK,CAAC;AACxB,MAAM,QAAQ,GAAG,KAAK,CAAC;AAoBvB,iEAAiE;AACjE,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,IAAI,IAAI,KAAK,GAAG;QAAE,OAAO,OAAO,EAAE,CAAC;IACnC,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACjE,OAAO,IAAI,CAAC;AACd,CAAC;AAED,qFAAqF;AACrF,KAAK,UAAU,kBAAkB,CAAC,IAAY;IAC5C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAY,CAAC;QACnE,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACnE,MAAM,GAAG,GAA2B,EAAE,CAAC;YACvC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAiC,CAAC,EAAE,CAAC;gBACvE,IAAI,OAAO,CAAC,KAAK,QAAQ;oBAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YACxC,CAAC;YACD,OAAO,GAAG,CAAC;QACb,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,oDAAoD;IACtD,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,+EAA+E;AAC/E,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,IAAY;IACrD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,CAAY,CAAC;QAC/E,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACnE,OAAO,MAAM,CAAC,IAAI,CAAC,MAAiC,CAAC,CAAC,MAAM,CAAC;QAC/D,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,mFAAmF;AACnF,KAAK,UAAU,eAAe,CAAC,IAAY,EAAE,OAAe;IAC1D,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;IACtD,MAAM,GAAG,GAAG,GAAG,IAAI,QAAQ,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;IACvD,MAAM,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;IACnD,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC1B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,8DAA8D;QAC9D,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAC3F,MAAM,GAAG,CAAC;IACZ,CAAC;IACD,2EAA2E;IAC3E,yDAAyD;IACzD,MAAM,KAAK,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;AAC/C,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,OAAwB;IAC9D,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAC5C,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACxC,MAAM,MAAM,GAAmB;QAC7B,WAAW,EAAE,EAAE;QACf,aAAa,EAAE,EAAE;QACjB,UAAU,EAAE,EAAE;QACd,KAAK,EAAE,OAAO,CAAC,MAAM;KACtB,CAAC;IACF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC;IAExC,MAAM,UAAU,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC/D,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;IAC/D,MAAM,QAAQ,GAAG,MAAM,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAEhD,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,KAAK,MAAM,CAAC,GAAG,EAAE,SAAS,CAAC,IAAI,OAAO,EAAE,CAAC;QACvC,MAAM,KAAK,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;QAChC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;YACpB,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACtB,CAAC;aAAM,CAAC;YACN,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,2BAA2B,CAAC;YACjE,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC;YACpC,MAAM,EAAE,IAAI,EAAE,CAAC,2CAA2C,GAAG,KAAK,SAAS,MAAM,OAAO,EAAE,CAAC,CAAC;YAC5F,IAAI,QAAQ,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;gBAChC,mEAAmE;gBACnE,MAAM,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;gBAC5B,MAAM,EAAE,KAAK,EAAE,CAAC,oDAAoD,GAAG,EAAE,CAAC,CAAC;YAC7E,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrC,MAAM,EAAE,IAAI,EAAE,CAAC,wDAAwD,IAAI,YAAY,CAAC,CAAC;QACzF,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QACpE,MAAM,CAAC,WAAW,GAAG,SAAS,CAAC;QAC/B,MAAM,EAAE,IAAI,EAAE,CACZ,sBAAsB,SAAS,CAAC,MAAM,iBAAiB,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,cAAc,CACzG,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,KAAK,MAAM,CAAC,GAAG,CAAC,IAAI,OAAO;YAAE,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC;QAC9D,MAAM,EAAE,KAAK,EAAE,CAAC,gCAAgC,IAAI,KAAK,OAAO,EAAE,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;;;;;;;;;;;;;;AAwFH,wBAqHG"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;;;;;;;;;;;;;;AA4GH,wBAqKG"}
package/dist/index.js CHANGED
@@ -14,11 +14,17 @@
14
14
  import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
15
15
  import { parsePluginConfig, readServiceAccountToken, } from "./config.js";
16
16
  import { createOnePasswordClient } from "./op-client.js";
17
- import { syncSecrets, syncResultIsClean, } from "./secret-sync.js";
17
+ import { syncSecrets } from "./secret-sync.js";
18
+ import { readExistingKeyCount, syncSecretsToFile } from "./file-sync.js";
18
19
  import { createTools } from "./tools.js";
19
20
  import { PLUGIN_ID, PLUGIN_VERSION } from "./version.js";
20
21
  const SERVICE_ID = "onepassword-secret-sync";
21
22
  const STORE_SET_METHOD = "secrets.store.set";
23
+ function unifiedSyncIsClean(result) {
24
+ return (Object.keys(result.resolveErrors).length === 0 &&
25
+ Object.keys(result.storeErrors).length === 0 &&
26
+ Object.keys(result.fileErrors).length === 0);
27
+ }
22
28
  /**
23
29
  * StoreWriter backed by the `secrets.store.set` Gateway RPC dispatched through
24
30
  * the trusted plugin runtime. Retries briefly while the Gateway request context
@@ -96,19 +102,58 @@ export default definePluginEntry({
96
102
  }
97
103
  const getClient = createClientFactory(config);
98
104
  const store = createStoreWriter(api);
105
+ const storeKeyCount = Object.keys(config.secrets).length;
106
+ const fileKeyCount = config.syncToFile ? Object.keys(config.syncToFile.secrets).length : 0;
107
+ const hasSyncWork = storeKeyCount > 0 || fileKeyCount > 0;
108
+ // Resolve configured references from 1Password and write them to the store
109
+ // and/or the JSON sync file, merging both passes into one result.
99
110
  const runSync = async () => {
100
111
  const client = await getClient();
101
- return syncSecrets({ client, store, secrets: config.secrets, logger });
112
+ const result = {
113
+ written: [],
114
+ fileWritten: [],
115
+ total: 0,
116
+ resolveErrors: {},
117
+ storeErrors: {},
118
+ fileErrors: {},
119
+ };
120
+ if (storeKeyCount > 0) {
121
+ const r = await syncSecrets({ client, store, secrets: config.secrets, logger });
122
+ result.written = r.written;
123
+ result.total += r.total;
124
+ Object.assign(result.resolveErrors, r.resolveErrors);
125
+ result.storeErrors = r.storeErrors;
126
+ }
127
+ if (config.syncToFile) {
128
+ const f = await syncSecretsToFile({
129
+ client,
130
+ path: config.syncToFile.path,
131
+ secrets: config.syncToFile.secrets,
132
+ logger,
133
+ });
134
+ result.fileWritten = f.fileWritten;
135
+ result.total += f.total;
136
+ Object.assign(result.resolveErrors, f.resolveErrors);
137
+ result.fileErrors = f.fileErrors;
138
+ }
139
+ return result;
102
140
  };
103
141
  // --- Startup / reload sync service -----------------------------------
104
142
  api.registerService({
105
143
  id: SERVICE_ID,
106
144
  async start() {
145
+ // On startup, report whether a previous boot left a populated sync file.
146
+ if (config.syncToFile) {
147
+ const count = await readExistingKeyCount(config.syncToFile.path);
148
+ if (count !== undefined) {
149
+ logger?.info?.(`onepassword: existing sync file ${config.syncToFile.path} has ${count} key(s)`);
150
+ }
151
+ }
107
152
  if (!config.syncOnStartup) {
108
153
  logger?.debug?.("onepassword: syncOnStartup disabled; skipping startup sync");
109
154
  return;
110
155
  }
111
- if (Object.keys(config.secrets).length === 0) {
156
+ if (!hasSyncWork) {
112
157
  logger?.debug?.("onepassword: no secrets configured; nothing to sync at startup");
113
158
  return;
114
159
  }
@@ -121,8 +166,9 @@ export default definePluginEntry({
121
166
  }
122
167
  try {
123
168
  const result = await runSync();
124
- if (config.failFastOnStartup && !syncResultIsClean(result)) {
125
- throw new Error(`onepassword: startup sync failed for ${result.total - result.written.length} of ${result.total} secret(s)`);
169
+ if (config.failFastOnStartup && !unifiedSyncIsClean(result)) {
170
+ const done = result.written.length + result.fileWritten.length;
171
+ throw new Error(`onepassword: startup sync failed for ${result.total - done} of ${result.total} secret(s)`);
126
172
  }
127
173
  }
128
174
  catch (err) {
@@ -141,9 +187,11 @@ export default definePluginEntry({
141
187
  const result = await runSync();
142
188
  respond(true, {
143
189
  written: result.written,
190
+ fileWritten: result.fileWritten,
144
191
  total: result.total,
145
192
  resolveErrors: result.resolveErrors,
146
193
  storeErrors: result.storeErrors,
194
+ fileErrors: result.fileErrors,
147
195
  });
148
196
  }
149
197
  catch (err) {
@@ -161,6 +209,9 @@ export default definePluginEntry({
161
209
  tokenPresent: readServiceAccountToken(config) !== undefined,
162
210
  syncOnStartup: config.syncOnStartup,
163
211
  managedStoreKeys: Object.keys(config.secrets),
212
+ syncToFileEnabled: config.syncToFile !== undefined,
213
+ managedFileKeys: config.syncToFile ? Object.keys(config.syncToFile.secrets) : [],
214
+ filePath: config.syncToFile?.path ?? null,
164
215
  toolsEnabled: config.tools.enabled,
165
216
  toolsWriteEnabled: config.tools.allowWrite,
166
217
  });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/version.d.ts CHANGED
@@ -4,6 +4,6 @@
4
4
  *
5
5
  * Kept in sync with package.json by the `version-matches-package` unit test.
6
6
  */
7
- export declare const PLUGIN_VERSION = "0.1.0";
7
+ export declare const PLUGIN_VERSION = "0.1.1";
8
8
  export declare const PLUGIN_ID = "onepassword";
9
9
  //# sourceMappingURL=version.d.ts.map
package/dist/version.js CHANGED
@@ -4,6 +4,6 @@
4
4
  *
5
5
  * Kept in sync with package.json by the `version-matches-package` unit test.
6
6
  */
7
- export const PLUGIN_VERSION = "0.1.0";
7
+ export const PLUGIN_VERSION = "0.1.1";
8
8
  export const PLUGIN_ID = "onepassword";
9
9
  //# sourceMappingURL=version.js.map
@@ -0,0 +1,41 @@
1
+ {
2
+ "$comment": "File sync mode. Use this when a channel plugin (e.g. Slack) rejects source:'store' and only accepts env/file/exec. The plugin resolves op:// references in-process and writes them to a JSON file that OpenClaw's built-in source:'file' provider reads. The file holds PLAINTEXT secrets: keep it inside the OpenClaw data volume and out of any agent-readable path. Set OP_SERVICE_ACCOUNT_TOKEN on the Gateway process.",
3
+ "plugins": {
4
+ "entries": {
5
+ "onepassword": {
6
+ "enabled": true,
7
+ "config": {
8
+ "serviceAccountTokenEnvVar": "OP_SERVICE_ACCOUNT_TOKEN",
9
+ "syncToFile": {
10
+ "path": "/home/node/.openclaw/op-secrets.json",
11
+ "mode": "json",
12
+ "secrets": {
13
+ "SLACK_BOT_TOKEN_A": "op://MyVault/SlackBot/bot_token",
14
+ "SLACK_APP_TOKEN_A": "op://MyVault/SlackBot/app_token"
15
+ }
16
+ }
17
+ }
18
+ }
19
+ }
20
+ },
21
+ "secrets": {
22
+ "providers": {
23
+ "env-default": { "source": "env" },
24
+ "op-file": {
25
+ "source": "file",
26
+ "path": "/home/node/.openclaw/op-secrets.json",
27
+ "mode": "json"
28
+ }
29
+ }
30
+ },
31
+ "channels": {
32
+ "slack": {
33
+ "accounts": {
34
+ "myworkspace": {
35
+ "botToken": { "source": "file", "provider": "op-file", "id": "/SLACK_BOT_TOKEN_A" },
36
+ "appToken": { "source": "file", "provider": "op-file", "id": "/SLACK_APP_TOKEN_A" }
37
+ }
38
+ }
39
+ }
40
+ }
41
+ }
@@ -2,7 +2,7 @@
2
2
  "id": "onepassword",
3
3
  "name": "1Password",
4
4
  "description": "Resolve 1Password secrets in-process into the OpenClaw shared store, and expose 1Password vault/item tools to agents.",
5
- "version": "0.1.0",
5
+ "version": "0.1.1",
6
6
  "activation": {
7
7
  "onStartup": true,
8
8
  "onConfigPaths": ["plugins.entries.onepassword"]
@@ -63,17 +63,17 @@
63
63
  },
64
64
  "syncOnStartup": {
65
65
  "type": "boolean",
66
- "description": "Fetch the configured `secrets` mapping from 1Password and write it into the OpenClaw store when the gateway starts.",
66
+ "description": "Fetch the configured secrets from 1Password and sync them (store and/or file) when the gateway starts.",
67
67
  "default": true
68
68
  },
69
69
  "failFastOnStartup": {
70
70
  "type": "boolean",
71
- "description": "If true, a startup sync failure throws and prevents the gateway from starting. If false, the plugin logs the error and lets last-known-good store values be used.",
71
+ "description": "If true, a startup sync failure (resolve, store write, or file write) throws and prevents the gateway from starting. If false, the plugin logs the error and falls back to last-known-good values.",
72
72
  "default": false
73
73
  },
74
74
  "secrets": {
75
75
  "type": "object",
76
- "description": "Map of OpenClaw store key -> 1Password secret reference (op://Vault/Item[/Section]/Field). Store keys must match ^[A-Z][A-Z0-9_]{0,127}$.",
76
+ "description": "Map of OpenClaw store key -> 1Password secret reference (op://Vault/Item[/Section]/Field). Store keys must match ^[A-Z][A-Z0-9_]{0,127}$. Referenced with source:'store'.",
77
77
  "propertyNames": { "pattern": "^[A-Z][A-Z0-9_]{0,127}$" },
78
78
  "additionalProperties": {
79
79
  "type": "string",
@@ -81,6 +81,31 @@
81
81
  },
82
82
  "default": {}
83
83
  },
84
+ "syncToFile": {
85
+ "type": "object",
86
+ "additionalProperties": false,
87
+ "description": "Resolve op:// references and write them to a JSON file that OpenClaw's source:'file' provider reads. For channels (e.g. Slack) that reject source:'store'. Independent of `secrets`; both can be active.",
88
+ "required": ["path", "secrets"],
89
+ "properties": {
90
+ "path": {
91
+ "type": "string",
92
+ "description": "Absolute path of the JSON file to write. Keep it inside the OpenClaw data volume and out of any agent-readable path. Written 0600.",
93
+ "minLength": 1
94
+ },
95
+ "mode": {
96
+ "type": "string",
97
+ "enum": ["json"],
98
+ "default": "json",
99
+ "description": "File format. Only 'json' (flat object; SecretRef ids are JSON pointers like /KEY) is supported."
100
+ },
101
+ "secrets": {
102
+ "type": "object",
103
+ "description": "Map of file key -> 1Password secret reference. Keys must match ^[A-Z][A-Z0-9_]{0,127}$.",
104
+ "propertyNames": { "pattern": "^[A-Z][A-Z0-9_]{0,127}$" },
105
+ "additionalProperties": { "type": "string", "pattern": "^op://" }
106
+ }
107
+ }
108
+ },
84
109
  "tools": {
85
110
  "type": "object",
86
111
  "additionalProperties": false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-plugin-onepassword",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Native OpenClaw plugin that resolves 1Password secrets in-process (no exec sandbox), plus agent tools for vault/item CRUD.",
5
5
  "keywords": [
6
6
  "openclaw",