Secrets management
WednesdayAI supports SecretRefs so supported credentials do not have to live as plaintext in your config. SecretRefs are opt-in, additive, and per-credential — plaintext still works everywhere it did before. A SecretRef points the gateway at a credential held in an environment variable, a local file, or an external resolver command (1Password, Vault, sops, and so on). The credential is resolved into an in-memory snapshot at activation time, never on the hot request path.Runtime model
- Resolution is eager during activation, not lazy on each request.
- Startup fails fast if an effectively active SecretRef cannot be resolved.
- Reload uses an atomic swap: full success, or the last-known-good snapshot is kept.
- Requests read only from the active in-memory snapshot.
SECRETS_RELOADER_DEGRADED) and keeps serving from the last good snapshot until a later reload recovers (SECRETS_RELOADER_RECOVERED).
Active-surface filtering
SecretRefs are only validated on surfaces that are actually in use. A ref on a disabled channel, an unselected web-search provider, or an inactive auth path does not block startup — it emits a non-fatal diagnostic (SECRETS_REF_IGNORED_INACTIVE_SURFACE) instead.
Gateway auth surfaces (gateway.auth.password, gateway.remote.token, gateway.remote.password) log their state explicitly as active or inactive under SECRETS_GATEWAY_AUTH_SURFACE, with the reason, so you can see why a credential was required or skipped.
SecretRef contract
Every SecretRef uses the same object shape:- env
- file
- exec
providermatches^[a-z][a-z0-9_-]{0,63}$idmatches^[A-Z][A-Z0-9_]{0,127}$- Missing or empty env values fail resolution.
Defining providers
Providers live undersecrets.providers, with defaults selecting one provider per source:
path: mode: "json" resolves id as a JSON pointer; mode: "singleValue" returns the whole file for id: "value". The exec provider runs an absolute binary path; by default the command must be a regular file (not a symlink). For package-manager shims (such as Homebrew), set allowSymlinkCommand: true and pair it with trustedDirs.
Exec integration examples
1Password CLI
1Password CLI
HashiCorp Vault CLI
HashiCorp Vault CLI
sops
sops
Precedence
- A field without a ref is left unchanged.
- A field with a ref is required on active surfaces during activation.
- If both plaintext and a ref are present, the ref wins on supported precedence paths and the gateway logs
SECRETS_REF_OVERRIDES_PLAINTEXT. - When
auth-profiles.jsoncredentials shadow anopenclaw.jsonref, the audit reportsREF_SHADOWED.
Runtime-minted or rotating credentials and OAuth refresh material are intentionally excluded from read-only SecretRef resolution. Use the auth profile flows for those.
Audit and configure workflow
The standard operator flow:secrets auditreports plaintext values at rest (inopenclaw.json,auth-profiles.json,.env), unresolved refs, precedence shadowing, and legacy residues.secrets configureis an interactive helper: set upsecrets.providers, pick the secret-bearing fields to convert, capture the SecretRef details, run preflight resolution, and optionally apply. Useful modes:--providers-only,--skip-provider-setup,--agent <id>.
One-way safety policy
WednesdayAI deliberately does not write rollback backups containing historical plaintext secrets. Preflight must succeed before write mode, runtime activation is validated before commit, and applies use atomic file replacement with best-effort restore on failure. When you convert a field to a SecretRef,configure --apply scrubs the matching plaintext from auth-profiles.json, legacy auth.json, and <config-dir>/.env.
Related: Authentication · Gateway configuration · Security hardening