perf: speed up security audit test imports

This commit is contained in:
Peter Steinberger
2026-04-16 21:54:01 +01:00
parent cd45f53b4e
commit 8a37bb4ed6
19 changed files with 321 additions and 37 deletions

View File

@@ -0,0 +1,6 @@
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import { inspectDiscordAccount } from "./src/account-inspect.js";
export function inspectDiscordReadOnlyAccount(cfg: OpenClawConfig, accountId?: string | null) {
return inspectDiscordAccount({ cfg, accountId });
}

View File

@@ -22,6 +22,10 @@ export default defineBundledChannelEntry({
specifier: "./runtime-api.js",
exportName: "setDiscordRuntime",
},
accountInspect: {
specifier: "./account-inspect-api.js",
exportName: "inspectDiscordReadOnlyAccount",
},
registerFull(api) {
api.on("subagent_spawning", async (event) => {
const { handleDiscordSubagentSpawning } = await loadDiscordSubagentHooksModule();

View File

@@ -1 +1,81 @@
export { collectFeishuSecurityAuditFindings } from "./src/security-audit.js";
import type { OpenClawConfig } from "./runtime-api.js";
function asRecord(value: unknown): Record<string, unknown> | undefined {
return value && typeof value === "object" && !Array.isArray(value)
? (value as Record<string, unknown>)
: undefined;
}
function hasNonEmptyString(value: unknown): boolean {
return typeof value === "string" && value.trim().length > 0;
}
function hasConfiguredSecretInput(value: unknown): boolean {
if (hasNonEmptyString(value)) {
return true;
}
const record = asRecord(value);
return (
Boolean(record) &&
hasNonEmptyString(record?.source) &&
hasNonEmptyString(record?.provider) &&
hasNonEmptyString(record?.id)
);
}
function isFeishuDocToolEnabled(cfg: OpenClawConfig): boolean {
const channels = asRecord(cfg.channels);
const feishu = asRecord(channels?.feishu);
if (!feishu || feishu.enabled === false) {
return false;
}
const baseTools = asRecord(feishu.tools);
const baseDocEnabled = baseTools?.doc !== false;
const baseAppId = hasNonEmptyString(feishu.appId);
const baseAppSecret = hasConfiguredSecretInput(feishu.appSecret);
const baseConfigured = baseAppId && baseAppSecret;
const accounts = asRecord(feishu.accounts);
if (!accounts || Object.keys(accounts).length === 0) {
return baseDocEnabled && baseConfigured;
}
for (const accountValue of Object.values(accounts)) {
const account = asRecord(accountValue) ?? {};
if (account.enabled === false) {
continue;
}
const accountTools = asRecord(account.tools);
const effectiveTools = accountTools ?? baseTools;
const docEnabled = effectiveTools?.doc !== false;
if (!docEnabled) {
continue;
}
const accountConfigured =
(hasNonEmptyString(account.appId) || baseAppId) &&
(hasConfiguredSecretInput(account.appSecret) || baseAppSecret);
if (accountConfigured) {
return true;
}
}
return false;
}
export function collectFeishuSecurityAuditFindings(params: { cfg: OpenClawConfig }) {
if (!isFeishuDocToolEnabled(params.cfg)) {
return [];
}
return [
{
checkId: "channels.feishu.doc_owner_open_id",
severity: "warn" as const,
title: "Feishu doc create can grant requester permissions",
detail:
'channels.feishu tools include "doc"; feishu_doc action "create" can grant document access to the trusted requesting Feishu user.',
remediation:
"Disable channels.feishu.tools.doc when not needed, and restrict tool access for untrusted prompts.",
},
];
}

View File

@@ -0,0 +1,6 @@
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import { inspectSlackAccount } from "./src/account-inspect.js";
export function inspectSlackReadOnlyAccount(cfg: OpenClawConfig, accountId?: string | null) {
return inspectSlackAccount({ cfg, accountId });
}

View File

@@ -29,5 +29,9 @@ export default defineBundledChannelEntry({
specifier: "./runtime-api.js",
exportName: "setSlackRuntime",
},
accountInspect: {
specifier: "./account-inspect-api.js",
exportName: "inspectSlackReadOnlyAccount",
},
registerFull: registerSlackPluginHttpRoutes,
});

View File

@@ -0,0 +1,6 @@
import type { OpenClawConfig } from "./runtime-api.js";
import { inspectTelegramAccount } from "./src/account-inspect.js";
export function inspectTelegramReadOnlyAccount(cfg: OpenClawConfig, accountId?: string | null) {
return inspectTelegramAccount({ cfg, accountId });
}

View File

@@ -17,4 +17,8 @@ export default defineBundledChannelEntry({
specifier: "./runtime-api.js",
exportName: "setTelegramRuntime",
},
accountInspect: {
specifier: "./account-inspect-api.js",
exportName: "inspectTelegramReadOnlyAccount",
},
});

View File

@@ -0,0 +1,3 @@
// Keep bundled channel entry imports narrow so bootstrap/discovery paths do
// not drag setup-only or tool runtime surfaces into lightweight plugin loads.
export { zalouserPlugin } from "./src/channel.js";

View File

@@ -21,7 +21,7 @@ export default defineBundledChannelEntry({
description: "Zalo personal account messaging via native zca-js integration",
importMetaUrl: import.meta.url,
plugin: {
specifier: "./api.js",
specifier: "./channel-plugin-api.js",
exportName: "zalouserPlugin",
},
runtime: {

View File

@@ -3,7 +3,7 @@ import { defineBundledChannelSetupEntry } from "openclaw/plugin-sdk/channel-entr
export default defineBundledChannelSetupEntry({
importMetaUrl: import.meta.url,
plugin: {
specifier: "./api.js",
specifier: "./setup-plugin-api.js",
exportName: "zalouserSetupPlugin",
},
});

View File

@@ -0,0 +1,2 @@
// Keep setup-entry imports narrow so setup loads do not pull tool surfaces.
export { zalouserSetupPlugin } from "./src/channel.setup.js";

View File

@@ -27,12 +27,14 @@ import {
} from "./channel.adapters.js";
import { listZalouserDirectoryGroupMembers } from "./directory.js";
import type { ZalouserProbeResult } from "./probe.js";
import { zalouserSetupAdapter } from "./setup-core.js";
import { zalouserSetupWizard } from "./setup-surface.js";
import { createZalouserSetupWizardProxy, zalouserSetupAdapter } from "./setup-core.js";
import { createZalouserPluginBase } from "./shared.js";
import { collectZalouserStatusIssues } from "./status-issues.js";
const loadZalouserChannelRuntime = createLazyRuntimeModule(() => import("./channel.runtime.js"));
const zalouserSetupWizardProxy = createZalouserSetupWizardProxy(
async () => (await import("./setup-surface.js")).zalouserSetupWizard,
);
function mapUser(params: {
id: string;
@@ -66,7 +68,7 @@ export const zalouserPlugin: ChannelPlugin<ResolvedZalouserAccount, ZalouserProb
createChatChannelPlugin({
base: {
...createZalouserPluginBase({
setupWizard: zalouserSetupWizard,
setupWizard: zalouserSetupWizardProxy,
setup: zalouserSetupAdapter,
}),
groups: zalouserGroupsAdapter,

View File

@@ -1,4 +1,8 @@
import { createPatchedAccountSetupAdapter } from "openclaw/plugin-sdk/setup-runtime";
import {
createDelegatedSetupWizardProxy,
createPatchedAccountSetupAdapter,
type ChannelSetupWizard,
} from "openclaw/plugin-sdk/setup-runtime";
const channel = "zalouser" as const;
@@ -7,3 +11,23 @@ export const zalouserSetupAdapter = createPatchedAccountSetupAdapter({
validateInput: () => null,
buildPatch: () => ({}),
});
export function createZalouserSetupWizardProxy(
loadWizard: () => Promise<ChannelSetupWizard>,
): ChannelSetupWizard {
return createDelegatedSetupWizardProxy({
channel,
loadWizard,
status: {
configuredLabel: "logged in",
unconfiguredLabel: "needs QR login",
configuredHint: "recommended · logged in",
unconfiguredHint: "recommended · QR login",
configuredScore: 1,
unconfiguredScore: 15,
},
credentials: [],
delegatePrepare: true,
delegateFinalize: true,
});
}