From 1584acb124a8f51a4e65ae57177173a353e2ac83 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sun, 3 May 2026 12:16:05 +0100 Subject: [PATCH] fix(secrets): stabilize credential matrix docs --- .../reference/secretref-credential-surface.md | 2 + ...tref-user-supplied-credentials-matrix.json | 14 +++++++ src/secrets/credential-matrix.ts | 4 +- src/secrets/target-registry-data.ts | 42 ++++++++++++++----- 4 files changed, 49 insertions(+), 13 deletions(-) diff --git a/docs/reference/secretref-credential-surface.md b/docs/reference/secretref-credential-surface.md index 5e75dbeb51e..045ec2128f6 100644 --- a/docs/reference/secretref-credential-surface.md +++ b/docs/reference/secretref-credential-surface.md @@ -90,6 +90,8 @@ Scope intent: - `channels.feishu.accounts.*.appSecret` - `channels.feishu.accounts.*.encryptKey` - `channels.feishu.accounts.*.verificationToken` +- `channels.qqbot.clientSecret` +- `channels.qqbot.accounts.*.clientSecret` - `channels.msteams.appPassword` - `channels.mattermost.botToken` - `channels.mattermost.accounts.*.botToken` diff --git a/docs/reference/secretref-user-supplied-credentials-matrix.json b/docs/reference/secretref-user-supplied-credentials-matrix.json index 995094fcb93..da473149004 100644 --- a/docs/reference/secretref-user-supplied-credentials-matrix.json +++ b/docs/reference/secretref-user-supplied-credentials-matrix.json @@ -281,6 +281,20 @@ "secretShape": "secret_input", "optIn": true }, + { + "id": "channels.qqbot.accounts.*.clientSecret", + "configFile": "openclaw.json", + "path": "channels.qqbot.accounts.*.clientSecret", + "secretShape": "secret_input", + "optIn": true + }, + { + "id": "channels.qqbot.clientSecret", + "configFile": "openclaw.json", + "path": "channels.qqbot.clientSecret", + "secretShape": "secret_input", + "optIn": true + }, { "id": "channels.slack.accounts.*.appToken", "configFile": "openclaw.json", diff --git a/src/secrets/credential-matrix.ts b/src/secrets/credential-matrix.ts index 649d3e6fc84..b3bddaec4e8 100644 --- a/src/secrets/credential-matrix.ts +++ b/src/secrets/credential-matrix.ts @@ -1,4 +1,4 @@ -import { listSecretTargetRegistryEntries } from "./target-registry.js"; +import { getSourceSecretTargetRegistry } from "./target-registry-data.js"; import { getUnsupportedSecretRefSurfacePatterns } from "./unsupported-surface-policy.js"; type CredentialMatrixEntry = { @@ -22,7 +22,7 @@ export type SecretRefCredentialMatrixDocument = { }; export function buildSecretRefCredentialMatrix(): SecretRefCredentialMatrixDocument { - const entries: CredentialMatrixEntry[] = listSecretTargetRegistryEntries() + const entries: CredentialMatrixEntry[] = getSourceSecretTargetRegistry() .map((entry) => { const isCanonicalFirecrawlWebFetchEntry = entry.id === "plugins.entries.firecrawl.config.webFetch.apiKey"; diff --git a/src/secrets/target-registry-data.ts b/src/secrets/target-registry-data.ts index 37d55553c1a..23a26b8a620 100644 --- a/src/secrets/target-registry-data.ts +++ b/src/secrets/target-registry-data.ts @@ -441,6 +441,25 @@ const CORE_SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [ let cachedSecretTargetRegistry: SecretTargetRegistryEntry[] | null = null; +function loadSecretTargetRegistryFromPluginMetadata(params: { + env: NodeJS.ProcessEnv; + preferPersisted?: boolean; +}): SecretTargetRegistryEntry[] { + const plugins = loadPluginMetadataSnapshot({ + config: {}, + env: params.env, + ...(params.preferPersisted !== undefined ? { preferPersisted: params.preferPersisted } : {}), + }).plugins; + const bundledPlugins = plugins.filter((record) => record.origin === "bundled"); + const channelPlugins = plugins.filter((record) => record.channels.length > 0); + return [ + ...CORE_SECRET_TARGET_REGISTRY, + ...listBundledWebProviderSecretTargetRegistryEntries(bundledPlugins), + ...listBundledPluginConfigSecretTargetRegistryEntries(bundledPlugins), + ...listChannelSecretTargetRegistryEntries(channelPlugins), + ]; +} + export function getCoreSecretTargetRegistry(): SecretTargetRegistryEntry[] { return CORE_SECRET_TARGET_REGISTRY; } @@ -449,17 +468,18 @@ export function getSecretTargetRegistry(): SecretTargetRegistryEntry[] { if (cachedSecretTargetRegistry) { return cachedSecretTargetRegistry; } - const plugins = loadPluginMetadataSnapshot({ - config: {}, + cachedSecretTargetRegistry = loadSecretTargetRegistryFromPluginMetadata({ env: process.env, - }).plugins; - const bundledPlugins = plugins.filter((record) => record.origin === "bundled"); - const channelPlugins = plugins.filter((record) => record.channels.length > 0); - cachedSecretTargetRegistry = [ - ...CORE_SECRET_TARGET_REGISTRY, - ...listBundledWebProviderSecretTargetRegistryEntries(bundledPlugins), - ...listBundledPluginConfigSecretTargetRegistryEntries(bundledPlugins), - ...listChannelSecretTargetRegistryEntries(channelPlugins), - ]; + }); return cachedSecretTargetRegistry; } + +export function getSourceSecretTargetRegistry(): SecretTargetRegistryEntry[] { + return loadSecretTargetRegistryFromPluginMetadata({ + env: { + ...process.env, + OPENCLAW_BUNDLED_PLUGINS_DIR: process.env.OPENCLAW_BUNDLED_PLUGINS_DIR ?? "extensions", + }, + preferPersisted: false, + }); +}