refactor: share plugin config trust helpers

This commit is contained in:
Peter Steinberger
2026-04-18 23:55:05 +01:00
parent 57326feb8d
commit 17fcbcefbc
3 changed files with 77 additions and 97 deletions

View File

@@ -1,8 +1,11 @@
import type { OpenClawConfig } from "../config/types.openclaw.js";
import { loadPluginManifestRegistry } from "../plugins/manifest-registry.js";
import type { PluginManifestRecord } from "../plugins/manifest-registry.js";
import {
isWorkspacePluginAllowedByConfig,
normalizePluginConfigId,
} from "../plugins/plugin-config-trust.js";
import type { PluginOrigin } from "../plugins/plugin-origin.types.js";
import { normalizeOptionalLowercaseString } from "../shared/string-coerce.js";
import { normalizeProviderId } from "./provider-id.js";
export type ProviderAuthAliasLookupParams = {
@@ -17,8 +20,6 @@ type ProviderAuthAliasCandidate = {
target: string;
};
type PluginEntriesConfig = NonNullable<NonNullable<OpenClawConfig["plugins"]>["entries"]>;
const PROVIDER_AUTH_ALIAS_ORIGIN_PRIORITY: Readonly<Record<PluginOrigin, number>> = {
config: 0,
bundled: 1,
@@ -33,54 +34,16 @@ function resolveProviderAuthAliasOriginPriority(origin: PluginOrigin | undefined
return PROVIDER_AUTH_ALIAS_ORIGIN_PRIORITY[origin] ?? Number.MAX_SAFE_INTEGER;
}
function normalizePluginConfigId(id: unknown): string {
return normalizeOptionalLowercaseString(id) ?? "";
}
function hasPluginId(list: unknown, pluginId: string): boolean {
return Array.isArray(list) && list.some((entry) => normalizePluginConfigId(entry) === pluginId);
}
function findPluginEntry(
entries: PluginEntriesConfig | undefined,
pluginId: string,
): { enabled?: boolean } | undefined {
if (!entries || typeof entries !== "object" || Array.isArray(entries)) {
return undefined;
}
for (const [key, value] of Object.entries(entries)) {
if (normalizePluginConfigId(key) !== pluginId) {
continue;
}
return value && typeof value === "object" && !Array.isArray(value)
? (value as { enabled?: boolean })
: {};
}
return undefined;
}
function isWorkspacePluginTrustedForAuthAliases(
plugin: PluginManifestRecord,
config: OpenClawConfig | undefined,
): boolean {
const pluginsConfig = config?.plugins;
if (pluginsConfig?.enabled === false) {
return false;
}
const pluginId = normalizePluginConfigId(plugin.id);
if (!pluginId || hasPluginId(pluginsConfig?.deny, pluginId)) {
return false;
}
const entry = findPluginEntry(pluginsConfig?.entries, pluginId);
if (entry?.enabled === false) {
return false;
}
if (entry?.enabled === true || hasPluginId(pluginsConfig?.allow, pluginId)) {
return true;
}
return normalizePluginConfigId(pluginsConfig?.slots?.contextEngine) === pluginId;
return isWorkspacePluginAllowedByConfig({
config,
isImplicitlyAllowed: (pluginId) =>
normalizePluginConfigId(config?.plugins?.slots?.contextEngine) === pluginId,
plugin,
});
}
function shouldUsePluginAuthAliases(

View File

@@ -0,0 +1,56 @@
import type { OpenClawConfig } from "../config/types.openclaw.js";
import { normalizeOptionalLowercaseString } from "../shared/string-coerce.js";
import type { PluginManifestRecord } from "./manifest-registry.js";
type PluginEntriesConfig = NonNullable<NonNullable<OpenClawConfig["plugins"]>["entries"]>;
export function normalizePluginConfigId(id: unknown): string {
return normalizeOptionalLowercaseString(id) ?? "";
}
function hasPluginConfigId(list: unknown, pluginId: string): boolean {
return Array.isArray(list) && list.some((entry) => normalizePluginConfigId(entry) === pluginId);
}
function findPluginConfigEntry(
entries: PluginEntriesConfig | undefined,
pluginId: string,
): { enabled?: boolean } | undefined {
if (!entries || typeof entries !== "object" || Array.isArray(entries)) {
return undefined;
}
for (const [key, value] of Object.entries(entries)) {
if (normalizePluginConfigId(key) !== pluginId) {
continue;
}
return value && typeof value === "object" && !Array.isArray(value)
? (value as { enabled?: boolean })
: {};
}
return undefined;
}
export function isWorkspacePluginAllowedByConfig(params: {
config: OpenClawConfig | undefined;
isImplicitlyAllowed?: (pluginId: string) => boolean;
plugin: PluginManifestRecord;
}): boolean {
const pluginsConfig = params.config?.plugins;
if (pluginsConfig?.enabled === false) {
return false;
}
const pluginId = normalizePluginConfigId(params.plugin.id);
if (!pluginId || hasPluginConfigId(pluginsConfig?.deny, pluginId)) {
return false;
}
const entry = findPluginConfigEntry(pluginsConfig?.entries, pluginId);
if (entry?.enabled === false) {
return false;
}
if (entry?.enabled === true || hasPluginConfigId(pluginsConfig?.allow, pluginId)) {
return true;
}
return params.isImplicitlyAllowed?.(pluginId) ?? false;
}

View File

@@ -2,8 +2,11 @@ import { resolveProviderAuthAliasMap } from "../agents/provider-auth-aliases.js"
import type { OpenClawConfig } from "../config/types.openclaw.js";
import { loadPluginManifestRegistry } from "../plugins/manifest-registry.js";
import type { PluginManifestRecord } from "../plugins/manifest-registry.js";
import {
isWorkspacePluginAllowedByConfig,
normalizePluginConfigId,
} from "../plugins/plugin-config-trust.js";
import { hasKind } from "../plugins/slots.js";
import { normalizeOptionalLowercaseString } from "../shared/string-coerce.js";
const CORE_PROVIDER_AUTH_ENV_VAR_CANDIDATES = {
anthropic: ["ANTHROPIC_OAUTH_TOKEN", "ANTHROPIC_API_KEY"],
@@ -25,59 +28,17 @@ export type ProviderEnvVarLookupParams = {
includeUntrustedWorkspacePlugins?: boolean;
};
type PluginEntriesConfig = NonNullable<NonNullable<OpenClawConfig["plugins"]>["entries"]>;
function normalizePluginConfigId(id: unknown): string {
return normalizeOptionalLowercaseString(id) ?? "";
}
function hasPluginId(list: unknown, pluginId: string): boolean {
return Array.isArray(list) && list.some((entry) => normalizePluginConfigId(entry) === pluginId);
}
function findPluginEntry(
entries: PluginEntriesConfig | undefined,
pluginId: string,
): { enabled?: boolean } | undefined {
if (!entries || typeof entries !== "object" || Array.isArray(entries)) {
return undefined;
}
for (const [key, value] of Object.entries(entries)) {
if (normalizePluginConfigId(key) !== pluginId) {
continue;
}
return value && typeof value === "object" && !Array.isArray(value)
? (value as { enabled?: boolean })
: {};
}
return undefined;
}
function isWorkspacePluginTrustedForProviderEnvVars(
plugin: PluginManifestRecord,
config: OpenClawConfig | undefined,
): boolean {
const pluginsConfig = config?.plugins;
if (pluginsConfig?.enabled === false) {
return false;
}
const pluginId = normalizePluginConfigId(plugin.id);
if (!pluginId || hasPluginId(pluginsConfig?.deny, pluginId)) {
return false;
}
const entry = findPluginEntry(pluginsConfig?.entries, pluginId);
if (entry?.enabled === false) {
return false;
}
if (entry?.enabled === true || hasPluginId(pluginsConfig?.allow, pluginId)) {
return true;
}
return (
hasKind(plugin.kind, "context-engine") &&
normalizePluginConfigId(pluginsConfig?.slots?.contextEngine) === pluginId
);
return isWorkspacePluginAllowedByConfig({
config,
isImplicitlyAllowed: (pluginId) =>
hasKind(plugin.kind, "context-engine") &&
normalizePluginConfigId(config?.plugins?.slots?.contextEngine) === pluginId,
plugin,
});
}
function shouldUsePluginProviderEnvVars(