perf(config): use generated SecretRef policy metadata

This commit is contained in:
Vincent Koc
2026-04-13 20:19:04 +01:00
parent a0a4a768dc
commit bd20a920a2
5 changed files with 210 additions and 165 deletions

View File

@@ -9,10 +9,10 @@
"hooks.gmail.pushToken",
"hooks.mappings[].sessionKey",
"auth-profiles.oauth.*",
"channels.discord.threadBindings.webhookToken",
"channels.discord.accounts.*.threadBindings.webhookToken",
"channels.whatsapp.creds.json",
"channels.whatsapp.accounts.*.creds.json"
"channels.discord.threadBindings.webhookToken",
"channels.whatsapp.accounts.*.creds.json",
"channels.whatsapp.creds.json"
],
"entries": [
{

View File

@@ -1,6 +1,7 @@
#!/usr/bin/env node
import fs from "node:fs";
import path from "node:path";
import { loadBundledPluginPublicArtifactModuleSync } from "../src/plugins/public-surface-loader.js";
import { loadChannelConfigSurfaceModule } from "./load-channel-config-surface.ts";
const GENERATED_BY = "scripts/generate-bundled-channel-config-metadata.ts";
@@ -63,6 +64,11 @@ type BundledChannelConfigMetadata = {
description?: string;
schema: Record<string, unknown>;
uiHints?: Record<string, unknown>;
unsupportedSecretRefSurfacePatterns?: readonly string[];
};
type BundledChannelSecuritySurface = {
unsupportedSecretRefSurfacePatterns?: readonly string[];
};
function resolveChannelConfigSchemaModulePath(rootDir: string): string | null {
@@ -131,6 +137,34 @@ function formatTypeScriptModule(source: string, outputPath: string, repoRoot: st
});
}
function resolveChannelUnsupportedSecretRefSurfacePatterns(
source: BundledPluginSource,
channelId: string,
): string[] {
try {
const surface = loadBundledPluginPublicArtifactModuleSync<BundledChannelSecuritySurface>({
dirName: source.dirName,
artifactBasename: "security-contract-api.js",
});
const prefix = `channels.${channelId}.`;
return [
...new Set(
(surface.unsupportedSecretRefSurfacePatterns ?? []).filter(
(pattern): pattern is string => typeof pattern === "string" && pattern.startsWith(prefix),
),
),
].toSorted((left, right) => left.localeCompare(right));
} catch (error) {
if (
error instanceof Error &&
error.message.startsWith("Unable to resolve bundled plugin public surface ")
) {
return [];
}
throw error;
}
}
export async function collectBundledChannelConfigMetadata(params?: { repoRoot?: string }) {
const repoRoot = path.resolve(params?.repoRoot ?? process.cwd());
const sources = collectBundledPluginSources({ repoRoot, requirePackageJson: true });
@@ -156,6 +190,10 @@ export async function collectBundledChannelConfigMetadata(params?: { repoRoot?:
for (const channelId of channelIds) {
const label = resolveRootLabel(source, channelId);
const description = resolveRootDescription(source, channelId);
const unsupportedSecretRefSurfacePatterns = resolveChannelUnsupportedSecretRefSurfacePatterns(
source,
channelId,
);
entries.push({
pluginId: source.manifest.id,
channelId,
@@ -163,6 +201,9 @@ export async function collectBundledChannelConfigMetadata(params?: { repoRoot?:
...(description ? { description } : {}),
schema: surface.schema,
...(Object.keys(surface.uiHints ?? {}).length > 0 ? { uiHints: surface.uiHints } : {}),
...(unsupportedSecretRefSurfacePatterns.length > 0
? { unsupportedSecretRefSurfacePatterns }
: {}),
});
}
}

View File

@@ -3129,6 +3129,10 @@ export const GENERATED_BUNDLED_CHANNEL_CONFIG_METADATA = [
sensitive: true,
},
},
unsupportedSecretRefSurfacePatterns: [
"channels.discord.accounts.*.threadBindings.webhookToken",
"channels.discord.threadBindings.webhookToken",
],
},
{
pluginId: "feishu",
@@ -15432,6 +15436,10 @@ export const GENERATED_BUNDLED_CHANNEL_CONFIG_METADATA = [
help: "Allow WhatsApp to write config in response to channel events/commands (default: true).",
},
},
unsupportedSecretRefSurfacePatterns: [
"channels.whatsapp.accounts.*.creds.json",
"channels.whatsapp.creds.json",
],
},
{
pluginId: "zalo",

View File

@@ -1,88 +1,4 @@
import { describe, expect, it, vi } from "vitest";
const { loadBundledChannelSecurityContractApiMock, loadPluginManifestRegistryMock } = vi.hoisted(
() => ({
loadBundledChannelSecurityContractApiMock: vi.fn((channelId: string) => {
if (channelId === "discord") {
return {
unsupportedSecretRefSurfacePatterns: [
"channels.discord.threadBindings.webhookToken",
"channels.discord.accounts.*.threadBindings.webhookToken",
],
collectUnsupportedSecretRefConfigCandidates: (raw: Record<string, unknown>) => {
const discord = (raw.channels as Record<string, unknown> | undefined)?.discord as
| Record<string, unknown>
| undefined;
const candidates: Array<{ path: string; value: unknown }> = [];
const threadBindings = discord?.threadBindings as Record<string, unknown> | undefined;
candidates.push({
path: "channels.discord.threadBindings.webhookToken",
value: threadBindings?.webhookToken,
});
const accounts = discord?.accounts as Record<string, unknown> | undefined;
for (const [accountId, account] of Object.entries(accounts ?? {})) {
const accountThreadBindings = (account as Record<string, unknown>).threadBindings as
| Record<string, unknown>
| undefined;
candidates.push({
path: `channels.discord.accounts.${accountId}.threadBindings.webhookToken`,
value: accountThreadBindings?.webhookToken,
});
}
return candidates;
},
};
}
if (channelId === "whatsapp") {
return {
unsupportedSecretRefSurfacePatterns: [
"channels.whatsapp.creds.json",
"channels.whatsapp.accounts.*.creds.json",
],
collectUnsupportedSecretRefConfigCandidates: (raw: Record<string, unknown>) => {
const whatsapp = (raw.channels as Record<string, unknown> | undefined)?.whatsapp as
| Record<string, unknown>
| undefined;
const candidates: Array<{ path: string; value: unknown }> = [];
const creds = whatsapp?.creds as Record<string, unknown> | undefined;
candidates.push({
path: "channels.whatsapp.creds.json",
value: creds?.json,
});
const accounts = whatsapp?.accounts as Record<string, unknown> | undefined;
for (const [accountId, account] of Object.entries(accounts ?? {})) {
const accountCreds = (account as Record<string, unknown>).creds as
| Record<string, unknown>
| undefined;
candidates.push({
path: `channels.whatsapp.accounts.${accountId}.creds.json`,
value: accountCreds?.json,
});
}
return candidates;
},
};
}
return undefined;
}),
loadPluginManifestRegistryMock: vi.fn(() => ({
plugins: [
{ id: "discord", origin: "bundled", channels: ["discord"] },
{ id: "whatsapp", origin: "bundled", channels: ["whatsapp"] },
],
diagnostics: [],
})),
}),
);
vi.mock("../plugins/manifest-registry.js", () => ({
loadPluginManifestRegistry: loadPluginManifestRegistryMock,
}));
vi.mock("./channel-contract-api.js", () => ({
loadBundledChannelSecurityContractApi: loadBundledChannelSecurityContractApiMock,
}));
import { describe, expect, it } from "vitest";
import {
collectUnsupportedSecretRefConfigCandidates,
getUnsupportedSecretRefSurfacePatterns,
@@ -90,17 +6,19 @@ import {
describe("unsupported SecretRef surface policy metadata", () => {
it("exposes the canonical unsupported surface patterns", () => {
expect(getUnsupportedSecretRefSurfacePatterns()).toEqual([
"commands.ownerDisplaySecret",
"hooks.token",
"hooks.gmail.pushToken",
"hooks.mappings[].sessionKey",
"auth-profiles.oauth.*",
"channels.discord.threadBindings.webhookToken",
"channels.discord.accounts.*.threadBindings.webhookToken",
"channels.whatsapp.creds.json",
"channels.whatsapp.accounts.*.creds.json",
]);
expect(getUnsupportedSecretRefSurfacePatterns().toSorted()).toEqual(
[
"commands.ownerDisplaySecret",
"hooks.token",
"hooks.gmail.pushToken",
"hooks.mappings[].sessionKey",
"auth-profiles.oauth.*",
"channels.discord.threadBindings.webhookToken",
"channels.discord.accounts.*.threadBindings.webhookToken",
"channels.whatsapp.creds.json",
"channels.whatsapp.accounts.*.creds.json",
].toSorted(),
);
});
it("discovers concrete config candidates for unsupported mutable surfaces", () => {

View File

@@ -1,6 +1,5 @@
import { loadPluginManifestRegistry } from "../plugins/manifest-registry.js";
import { GENERATED_BUNDLED_CHANNEL_CONFIG_METADATA } from "../config/bundled-channel-config-metadata.generated.js";
import { isRecord } from "../utils.js";
import { loadBundledChannelSecurityContractApi } from "./channel-contract-api.js";
const CORE_UNSUPPORTED_SECRETREF_SURFACE_PATTERNS = [
"commands.ownerDisplaySecret",
@@ -10,33 +9,149 @@ const CORE_UNSUPPORTED_SECRETREF_SURFACE_PATTERNS = [
"auth-profiles.oauth.*",
] as const;
function listBundledChannelIds(): string[] {
return [
...new Set(
loadPluginManifestRegistry({})
.plugins.filter((entry) => entry.origin === "bundled")
.flatMap((entry) => entry.channels),
const CORE_UNSUPPORTED_SECRETREF_CONFIG_CANDIDATE_PATTERNS = [
"commands.ownerDisplaySecret",
"hooks.token",
"hooks.gmail.pushToken",
"hooks.mappings[].sessionKey",
] as const;
type PatternToken =
| { kind: "key"; key: string }
| { kind: "array"; key: string }
| { kind: "wildcard" };
const bundledChannelUnsupportedSecretRefSurfacePatterns = [
...new Set(
GENERATED_BUNDLED_CHANNEL_CONFIG_METADATA.flatMap((entry) =>
"unsupportedSecretRefSurfacePatterns" in entry
? (entry.unsupportedSecretRefSurfacePatterns ?? [])
: [],
),
].toSorted((left, right) => left.localeCompare(right));
}
),
];
function collectChannelUnsupportedSecretRefSurfacePatterns(): string[] {
const patterns: string[] = [];
for (const channelId of listBundledChannelIds()) {
const contract = loadBundledChannelSecurityContractApi(channelId);
patterns.push(...(contract?.unsupportedSecretRefSurfacePatterns ?? []));
const unsupportedSecretRefSurfacePatterns = [
...CORE_UNSUPPORTED_SECRETREF_SURFACE_PATTERNS,
...bundledChannelUnsupportedSecretRefSurfacePatterns,
];
const unsupportedSecretRefConfigCandidatePatterns = [
...CORE_UNSUPPORTED_SECRETREF_CONFIG_CANDIDATE_PATTERNS,
...bundledChannelUnsupportedSecretRefSurfacePatterns,
];
const parsedPatternCache = new Map<string, PatternToken[]>();
function parseUnsupportedSecretRefSurfacePattern(pattern: string): PatternToken[] {
const cached = parsedPatternCache.get(pattern);
if (cached) {
return cached;
}
return patterns;
const parsed = pattern
.split(".")
.filter((segment) => segment.length > 0)
.map<PatternToken>((segment) => {
if (segment === "*") {
return { kind: "wildcard" };
}
if (segment.endsWith("[]")) {
return {
kind: "array",
key: segment.slice(0, -2),
};
}
return {
kind: "key",
key: segment,
};
});
parsedPatternCache.set(pattern, parsed);
return parsed;
}
let cachedUnsupportedSecretRefSurfacePatterns: string[] | null = null;
function collectPatternCandidates(params: {
current: unknown;
tokens: readonly PatternToken[];
tokenIndex: number;
pathSegments: string[];
candidates: UnsupportedSecretRefConfigCandidate[];
}): void {
if (params.tokenIndex >= params.tokens.length) {
params.candidates.push({
path: params.pathSegments.join("."),
value: params.current,
});
return;
}
const token = params.tokens[params.tokenIndex];
if (!token) {
return;
}
if (token.kind === "wildcard") {
if (Array.isArray(params.current)) {
for (const [index, value] of params.current.entries()) {
collectPatternCandidates({
...params,
current: value,
tokenIndex: params.tokenIndex + 1,
pathSegments: [...params.pathSegments, String(index)],
});
}
return;
}
if (!isRecord(params.current)) {
return;
}
for (const [key, value] of Object.entries(params.current)) {
collectPatternCandidates({
...params,
current: value,
tokenIndex: params.tokenIndex + 1,
pathSegments: [...params.pathSegments, key],
});
}
return;
}
if (!isRecord(params.current)) {
return;
}
if (token.kind === "array") {
if (!Object.hasOwn(params.current, token.key)) {
return;
}
const value = params.current[token.key];
if (!Array.isArray(value)) {
return;
}
for (const [index, entry] of value.entries()) {
collectPatternCandidates({
...params,
current: entry,
tokenIndex: params.tokenIndex + 1,
pathSegments: [...params.pathSegments, token.key, String(index)],
});
}
return;
}
if (!Object.hasOwn(params.current, token.key)) {
return;
}
collectPatternCandidates({
...params,
current: params.current[token.key],
tokenIndex: params.tokenIndex + 1,
pathSegments: [...params.pathSegments, token.key],
});
}
export function getUnsupportedSecretRefSurfacePatterns(): string[] {
cachedUnsupportedSecretRefSurfacePatterns ??= [
...CORE_UNSUPPORTED_SECRETREF_SURFACE_PATTERNS,
...collectChannelUnsupportedSecretRefSurfacePatterns(),
];
return cachedUnsupportedSecretRefSurfacePatterns;
return [...unsupportedSecretRefSurfacePatterns];
}
export type UnsupportedSecretRefConfigCandidate = {
@@ -52,51 +167,14 @@ export function collectUnsupportedSecretRefConfigCandidates(
}
const candidates: UnsupportedSecretRefConfigCandidate[] = [];
const commands = isRecord(raw.commands) ? raw.commands : null;
if (commands) {
candidates.push({
path: "commands.ownerDisplaySecret",
value: commands.ownerDisplaySecret,
for (const pattern of unsupportedSecretRefConfigCandidatePatterns) {
collectPatternCandidates({
current: raw,
tokens: parseUnsupportedSecretRefSurfacePattern(pattern),
tokenIndex: 0,
pathSegments: [],
candidates,
});
}
const hooks = isRecord(raw.hooks) ? raw.hooks : null;
if (hooks) {
candidates.push({ path: "hooks.token", value: hooks.token });
const gmail = isRecord(hooks.gmail) ? hooks.gmail : null;
if (gmail) {
candidates.push({
path: "hooks.gmail.pushToken",
value: gmail.pushToken,
});
}
const mappings = hooks.mappings;
if (Array.isArray(mappings)) {
for (const [index, mapping] of mappings.entries()) {
if (!isRecord(mapping)) {
continue;
}
candidates.push({
path: `hooks.mappings.${index}.sessionKey`,
value: mapping.sessionKey,
});
}
}
}
if (isRecord(raw.channels)) {
for (const channelId of Object.keys(raw.channels)) {
const contract = loadBundledChannelSecurityContractApi(channelId);
const channelCandidates = contract?.collectUnsupportedSecretRefConfigCandidates?.(raw);
if (!channelCandidates?.length) {
continue;
}
candidates.push(...channelCandidates);
}
}
return candidates;
}