Skip to content

feat(secrets): add keyring and 1Password secret providers#43641

Closed
akoscz wants to merge 2 commits into
openclaw:mainfrom
akoscz:feature/secrets-keyring-provider
Closed

feat(secrets): add keyring and 1Password secret providers#43641
akoscz wants to merge 2 commits into
openclaw:mainfrom
akoscz:feature/secrets-keyring-provider

Conversation

@akoscz

@akoscz akoscz commented Mar 12, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds two providers for local/desktop credential storage:

KeyringSecretProvider

OS-native keychain integration:

  • macOS: Keychain via keytar (lazy-loaded optional peer dep)
  • Linux: secret-tool CLI (libsecret)

Config:

{ "secrets": { "providers": { "keyring": { "account": "openclaw" } } } }

Usage: ${keyring:my-api-key}

OnePasswordSecretProvider

1Password CLI integration via op read:

Config:

{ "secrets": { "providers": { "1password": { "vault": "OpenClaw" } } } }

Usage: ${1password:My Item.api-key}

Notes

Split from #24272 per @vincentkoc's request.

@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation gateway Gateway runtime size: L labels Mar 12, 2026
@greptile-apps

greptile-apps Bot commented Mar 12, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds two new local/desktop secret providers — KeyringSecretProvider (OS-native keychain via security CLI on macOS and secret-tool on Linux) and OnePasswordSecretProvider (via the op CLI) — along with the core secret-resolution.ts engine that wires all providers together.

Critical issue found:

  • The SECRET_REF_PATTERN regex in secret-resolution.ts (line 17) uses [a-z]+ for the provider name group, which only matches lowercase alphabetic characters. The 1password provider name starts with the digit 1 and will therefore never match, making every ${1password:...} config reference silently ignored. The 1Password provider is entirely non-functional as shipped. The same [a-z]+ pattern appears in the stripEscapedRefs helper and must also be fixed there.

Other notable issues:

  • linuxGetSecret in keyring-secret-provider.ts swallows all secret-tool errors under a generic "Secret not found" message, hiding real failures such as a locked keyring or missing D-Bus session.
  • The documentation appended to docs/gateway/secrets.md contains raw YAML frontmatter fields (summary:, read_when:, title:) rendered as plain markdown text (likely a copy-paste artefact from a separate doc), and the "Supported Providers" table in that section omits the keyring and 1password providers introduced by this PR.

Confidence Score: 1/5

  • Not safe to merge — the 1Password provider is completely broken due to a regex bug that prevents any 1password secret reference from ever resolving.
  • The SECRET_REF_PATTERN regex uses [a-z]+ for provider names, which does not allow the leading digit in '1password'. Every ${1password:...} reference will be silently skipped, so the feature is entirely non-functional without a fix. The keyring provider works but has a secondary error-swallowing issue that hurts debuggability.
  • src/config/secret-resolution.ts (critical regex bug on line 17 and line 263), src/config/keyring-secret-provider.ts (error swallowing in linuxGetSecret), docs/gateway/secrets.md (malformed frontmatter and missing provider entries in the table)
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/config/keyring-secret-provider.ts
Line: 193-196

Comment:
**All `secret-tool` errors coerced to "not found"**

The bare `catch` block discards the real error from `execFileAsync` and rethrows a generic "not found" message. If `secret-tool` fails for any reason other than the secret not existing — e.g. the GNOME Keyring is locked, the D-Bus session bus is not running, or the daemon crashes — users will see `Secret "x" not found in keyring` rather than the actual problem, making it very hard to diagnose.

Consider rethrowing the original error for non-"not-found" failures:

```ts
  } catch (err: unknown) {
    const msg = err instanceof Error ? err.message : String(err);
    // secret-tool exits 1 with empty stdout when key doesn't exist
    if (!msg || msg.includes("No such attribute")) {
      throw new Error(`Secret "${name}" not found in keyring`);
    }
    throw new Error(`Failed to retrieve secret "${name}" from keyring: ${msg}`, { cause: err instanceof Error ? err : undefined });
  }
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: docs/gateway/secrets.md
Line: 454-462

Comment:
**Malformed YAML frontmatter pasted as plain markdown**

The block starting here contains what looks like document-level YAML frontmatter fields (`summary:`, `read_when:`, `title:`) rendered as raw markdown text. This is likely a copy-paste artefact from a separate doc that was accidentally appended inline rather than structured as proper markdown.

In addition, the "Supported Providers" table that follows only lists GCP, AWS, HashiCorp Vault, and Azure Key Vault, with no mention of the `keyring` and `1password` providers actually being introduced by this PR. The table should be updated to reflect the new providers:

| Provider            | Status       |
| ------------------- | ------------ |
| GCP Secret Manager  | ✅ Supported |
| OS Keyring          | ✅ Supported |
| 1Password           | ✅ Supported |
| AWS Secrets Manager | Planned      |
| HashiCorp Vault     | Planned      |
| Azure Key Vault     | Planned      |

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: src/config/secret-resolution.ts
Line: 17

Comment:
**`1password` provider name never matched by regex**

The `SECRET_REF_PATTERN` uses `[a-z]+` for the provider group, which only matches lowercase ASCII letters. The provider name `1password` starts with the digit `1`, so any config reference using this provider will **never match** — the reference is silently left unresolved and the `1password` provider is completely non-functional.

This bug affects all three resolution paths: `extractSecretReferences`, `containsSecretReference`, and `resolveString`.

The `stripEscapedRefs` helper at line 263 has the same `[a-z]+` pattern and needs the same fix.

Fix: expand the provider character class to allow a leading digit:

```suggestion
const SECRET_REF_PATTERN = /\$\{([a-z0-9][a-z0-9]*):([a-zA-Z0-9_\-/.]+?)(?:#([a-zA-Z0-9]+))?\}/g;
```

How can I resolve this? If you propose a fix, please make it concise.

Last reviewed commit: 53a6e3e

Comment on lines +193 to +196
return value;
} catch {
throw new Error(`Secret "${name}" not found in keyring`);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All secret-tool errors coerced to "not found"

The bare catch block discards the real error from execFileAsync and rethrows a generic "not found" message. If secret-tool fails for any reason other than the secret not existing — e.g. the GNOME Keyring is locked, the D-Bus session bus is not running, or the daemon crashes — users will see Secret "x" not found in keyring rather than the actual problem, making it very hard to diagnose.

Consider rethrowing the original error for non-"not-found" failures:

  } catch (err: unknown) {
    const msg = err instanceof Error ? err.message : String(err);
    // secret-tool exits 1 with empty stdout when key doesn't exist
    if (!msg || msg.includes("No such attribute")) {
      throw new Error(`Secret "${name}" not found in keyring`);
    }
    throw new Error(`Failed to retrieve secret "${name}" from keyring: ${msg}`, { cause: err instanceof Error ? err : undefined });
  }
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/config/keyring-secret-provider.ts
Line: 193-196

Comment:
**All `secret-tool` errors coerced to "not found"**

The bare `catch` block discards the real error from `execFileAsync` and rethrows a generic "not found" message. If `secret-tool` fails for any reason other than the secret not existing — e.g. the GNOME Keyring is locked, the D-Bus session bus is not running, or the daemon crashes — users will see `Secret "x" not found in keyring` rather than the actual problem, making it very hard to diagnose.

Consider rethrowing the original error for non-"not-found" failures:

```ts
  } catch (err: unknown) {
    const msg = err instanceof Error ? err.message : String(err);
    // secret-tool exits 1 with empty stdout when key doesn't exist
    if (!msg || msg.includes("No such attribute")) {
      throw new Error(`Secret "${name}" not found in keyring`);
    }
    throw new Error(`Failed to retrieve secret "${name}" from keyring: ${msg}`, { cause: err instanceof Error ? err : undefined });
  }
```

How can I resolve this? If you propose a fix, please make it concise.

Comment thread docs/gateway/secrets.md
Comment on lines 454 to +462
- Environment precedence: [Environment Variables](/help/environment)

---

## Additional Secrets Providers

summary: "External secrets management: store credentials in GCP Secret Manager instead of plaintext files"
read_when:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Malformed YAML frontmatter pasted as plain markdown

The block starting here contains what looks like document-level YAML frontmatter fields (summary:, read_when:, title:) rendered as raw markdown text. This is likely a copy-paste artefact from a separate doc that was accidentally appended inline rather than structured as proper markdown.

In addition, the "Supported Providers" table that follows only lists GCP, AWS, HashiCorp Vault, and Azure Key Vault, with no mention of the keyring and 1password providers actually being introduced by this PR. The table should be updated to reflect the new providers:

Provider Status
GCP Secret Manager ✅ Supported
OS Keyring ✅ Supported
1Password ✅ Supported
AWS Secrets Manager Planned
HashiCorp Vault Planned
Azure Key Vault Planned
Prompt To Fix With AI
This is a comment left during a code review.
Path: docs/gateway/secrets.md
Line: 454-462

Comment:
**Malformed YAML frontmatter pasted as plain markdown**

The block starting here contains what looks like document-level YAML frontmatter fields (`summary:`, `read_when:`, `title:`) rendered as raw markdown text. This is likely a copy-paste artefact from a separate doc that was accidentally appended inline rather than structured as proper markdown.

In addition, the "Supported Providers" table that follows only lists GCP, AWS, HashiCorp Vault, and Azure Key Vault, with no mention of the `keyring` and `1password` providers actually being introduced by this PR. The table should be updated to reflect the new providers:

| Provider            | Status       |
| ------------------- | ------------ |
| GCP Secret Manager  | ✅ Supported |
| OS Keyring          | ✅ Supported |
| 1Password           | ✅ Supported |
| AWS Secrets Manager | Planned      |
| HashiCorp Vault     | Planned      |
| Azure Key Vault     | Planned      |

How can I resolve this? If you propose a fix, please make it concise.

// Matches ${provider:name} or ${provider:name#version}
// Provider: lowercase alpha. Name: alphanum, hyphens, underscores, slashes, dots.
// Version (optional): after #, alphanumeric.
const SECRET_REF_PATTERN = /\$\{([a-z]+):([a-zA-Z0-9_\-/.]+?)(?:#([a-zA-Z0-9]+))?\}/g;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1password provider name never matched by regex

The SECRET_REF_PATTERN uses [a-z]+ for the provider group, which only matches lowercase ASCII letters. The provider name 1password starts with the digit 1, so any config reference using this provider will never match — the reference is silently left unresolved and the 1password provider is completely non-functional.

This bug affects all three resolution paths: extractSecretReferences, containsSecretReference, and resolveString.

The stripEscapedRefs helper at line 263 has the same [a-z]+ pattern and needs the same fix.

Fix: expand the provider character class to allow a leading digit:

Suggested change
const SECRET_REF_PATTERN = /\$\{([a-z]+):([a-zA-Z0-9_\-/.]+?)(?:#([a-zA-Z0-9]+))?\}/g;
const SECRET_REF_PATTERN = /\$\{([a-z0-9][a-z0-9]*):([a-zA-Z0-9_\-/.]+?)(?:#([a-zA-Z0-9]+))?\}/g;
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/config/secret-resolution.ts
Line: 17

Comment:
**`1password` provider name never matched by regex**

The `SECRET_REF_PATTERN` uses `[a-z]+` for the provider group, which only matches lowercase ASCII letters. The provider name `1password` starts with the digit `1`, so any config reference using this provider will **never match** — the reference is silently left unresolved and the `1password` provider is completely non-functional.

This bug affects all three resolution paths: `extractSecretReferences`, `containsSecretReference`, and `resolveString`.

The `stripEscapedRefs` helper at line 263 has the same `[a-z]+` pattern and needs the same fix.

Fix: expand the provider character class to allow a leading digit:

```suggestion
const SECRET_REF_PATTERN = /\$\{([a-z0-9][a-z0-9]*):([a-zA-Z0-9_\-/.]+?)(?:#([a-zA-Z0-9]+))?\}/g;
```

How can I resolve this? If you propose a fix, please make it concise.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 53a6e3e36f

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

// Matches ${provider:name} or ${provider:name#version}
// Provider: lowercase alpha. Name: alphanum, hyphens, underscores, slashes, dots.
// Version (optional): after #, alphanumeric.
const SECRET_REF_PATTERN = /\$\{([a-z]+):([a-zA-Z0-9_\-/.]+?)(?:#([a-zA-Z0-9]+))?\}/g;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Expand provider regex to resolve 1password references

The secret reference pattern only accepts provider names matching [a-z]+, so ${1password:...} never matches. Both extraction and substitution rely on this regex, which means 1Password placeholders are silently left unresolved instead of being fetched (or even rejected), making the newly added 1Password provider effectively unusable in real configs.

Useful? React with 👍 / 👎.

// Matches ${provider:name} or ${provider:name#version}
// Provider: lowercase alpha. Name: alphanum, hyphens, underscores, slashes, dots.
// Version (optional): after #, alphanumeric.
const SECRET_REF_PATTERN = /\$\{([a-z]+):([a-zA-Z0-9_\-/.]+?)(?:#([a-zA-Z0-9]+))?\}/g;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Allow 1Password item and URI syntax in secret names

The name token class excludes spaces and :, so common 1Password inputs like item titles with spaces (for example My Item.api-key) and full op://... URIs cannot be parsed by ${provider:name} references. Even after provider matching is fixed, these valid 1Password lookup forms remain unresolved and will propagate as literal placeholders into runtime auth fields.

Useful? React with 👍 / 👎.

@akoscz akoscz force-pushed the feature/secrets-keyring-provider branch from c1f8a60 to ddcc013 Compare March 12, 2026 15:28

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ddcc0135bf

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +318 to +322
if (name === "gcp" && config && config.project) {
providers.set(
"gcp",
new GcpSecretProvider(
config as { project: string; cacheTtlSeconds?: number; credentialsFile?: string },

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Align provider config shape with validated secrets schema

buildSecretProviders assumes secrets.providers contains provider-specific objects like { gcp: { project }, keyring: { ... }, "1password": { ... } }, but the validated config schema still enforces secrets.providers.* to match SecretProviderSchema (src/config/zod-schema.core.ts), which requires a source discriminator (env/file/exec) and rejects these fields. In normal openclaw.json loading, configs matching the new provider docs fail validation before resolution runs, so the new providers cannot be configured through the standard path.

Useful? React with 👍 / 👎.

Comment on lines +106 to +107
await execFileAsync("which", ["op"]);
this.opChecked = true;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Replace Unix-only which probe for 1Password CLI

ensureOp shells out to which op, which is not available on Windows, so OnePasswordSecretProvider reports the CLI as missing even when op.exe is installed and in PATH. This makes the provider unusable on Windows hosts despite the implementation not otherwise being platform-gated.

Useful? React with 👍 / 👎.

Comment on lines +421 to +423
const resolved = await Promise.all(
matches.map(async ({ provider: pName, name, version, full }) => {
const provider = providers.get(pName);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Deduplicate identical secret refs before parallel fetch

resolveString resolves every regex match concurrently without deduplicating identical references, so repeated placeholders in one config value can trigger multiple simultaneous getSecret calls for the same key before cache population. This can unnecessarily amplify external secret-store traffic and hit rate limits/timeouts when the same secret is reused across fields.

Useful? React with 👍 / 👎.

@akoscz akoscz force-pushed the feature/secrets-keyring-provider branch from ddcc013 to fc5007d Compare March 12, 2026 20:20

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fc5007dba2

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

);

for (const { full, value: sv } of resolved) {
working = working.replace(full, sv);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve raw secret text during placeholder substitution

resolveString substitutes with working.replace(full, sv), but JavaScript treats $ patterns in replacement strings specially ($$, $&, $1, etc.). That means secrets containing dollar-sign sequences are mutated during resolution (for example, pa$$word becomes pa$word), which can silently corrupt credentials and cause authentication failures when those values are used downstream.

Useful? React with 👍 / 👎.

version: string | undefined,
cacheTtlMs: number,
): Promise<string> {
const cacheKey = `${provider.name}:${name}#${version ?? "latest"}`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Scope cache keys to provider configuration

fetchWithCache keys entries only by provider name, secret name, and version, so cached values survive across provider reconfiguration (for example changing GCP project, keyring account, or 1Password vault/field) within the same process. On reloads that keep the same ref names, resolution can return secrets from the previous provider context until TTL expiry, causing the app to authenticate against the wrong credentials.

Useful? React with 👍 / 👎.

@akoscz akoscz force-pushed the feature/secrets-keyring-provider branch 2 times, most recently from bfc3a87 to ce72021 Compare March 13, 2026 02:05
Adds two providers for local/desktop credential storage:

**KeyringSecretProvider** — OS-native keychain:
- macOS: Keychain via `keytar` (lazy-loaded optional peer dep)
- Linux: `secret-tool` CLI (libsecret)
- Supports custom keychain path and account names

**OnePasswordSecretProvider** — 1Password CLI (`op`):
- Uses `op read` to resolve secrets from 1Password vaults
- Configurable vault and field names

Config example:
  "secrets": {
    "providers": {
      "keyring": { "account": "openclaw" },
      "1password": { "vault": "OpenClaw" }
    }
  }

Usage: ${keyring:my-secret} or ${1password:my-item.field}

Split from openclaw#24272 per @vincentkoc's request.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ce7202116a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/config/config.ts
Comment on lines +31 to +33
resolveConfigSecrets,
configNeedsSecretResolution,
clearSecretCache,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Wire secret resolver into config loading pipeline

resolveConfigSecrets is only re-exported here and never invoked in the normal config read path (repo-wide rg "resolveConfigSecrets\(" only finds its definition), while loadConfig returns the validated object directly, so ${gcp:...}, ${keyring:...}, and ${1password:...} values remain literal strings in runtime config. This makes the new provider implementations effectively unreachable for standard openclaw.json usage.

Useful? React with 👍 / 👎.

Comment thread docs/gateway/secrets.md
Comment on lines +544 to +545
openclaw secrets setup --project my-gcp-project --agents main,chai
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Update secrets docs to use existing CLI subcommands

This quick-start step documents openclaw secrets setup (and later set/test), but the CLI in src/cli/secrets-cli.ts only registers reload, audit, configure, and apply, so users following these instructions will hit unknown-command errors and cannot complete the documented flow.

Useful? React with 👍 / 👎.

@akoscz akoscz force-pushed the feature/secrets-keyring-provider branch from ce72021 to 48e8323 Compare March 13, 2026 05:53

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 48e8323d9c

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +377 to +380
// Stale-while-revalidate: if we have an expired entry, use it
if (cached) {
return cached.value;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restrict stale-cache fallback to transient provider failures

fetchWithCache currently returns expired cached values for every provider error, not only transient outages. When a secret is deleted/disabled or permissions are revoked after a value was cached, provider.getSecret will throw but this branch still serves the stale credential, so revocation and rotation failures are silently masked and can persist indefinitely.

Useful? React with 👍 / 👎.

@akoscz

akoscz commented Mar 13, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the contribution! After reviewing this PR alongside the related secrets provider PRs (#43640, #43641, #43643, #43644, #43645, #43646), we need to close these for an architectural rework before they can land.

The issue: parallel implementation instead of extending the existing system

OpenClaw already has a mature secrets infrastructure in src/secrets/ (resolve.ts, runtime.ts, ref-contract.ts, etc.) and src/config/types.secrets.ts. That system uses SecretRef / SecretProviderConfig as the core provider contract and already supports exec and file provider types wired into the gateway and runtime.

These PRs introduce a new parallel system — a new src/config/secret-resolution.ts module, a new SecretProvider / getSecret() interface, and a new ${provider:name} syntax — without connecting to the existing infrastructure at all.

There's also a hidden dependency across the PR set: the aws, azure, keyring, and vault branches all import SecretProvider from ./secret-resolution.js, but that file only exists in #43640 (env-provider). Those four PRs cannot compile against main independently.

What we need instead

New cloud-backend providers (AWS Secrets Manager, Azure Key Vault, HashiCorp Vault, OS keyring, env vars) should be implemented as resolvers within the existing src/secrets/ provider contract — plugging into SecretProviderConfig so they're available to the full resolution pipeline already wired into the gateway and runtime.

src/secrets/resolve.ts, src/config/types.secrets.ts, and src/gateway/server-methods/secrets.ts are the right starting points to understand the provider contract.

We'd love to see these re-submitted with the corrected architecture.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Improvements or additions to documentation gateway Gateway runtime size: L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant