Files
openclaw/extensions/matrix/src/approval-native.test.ts
2026-04-10 18:50:40 +01:00

330 lines
9.2 KiB
TypeScript

import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import { describe, expect, it } from "vitest";
import { matrixApprovalCapability } from "./approval-native.js";
function buildConfig(
overrides?: Partial<NonNullable<NonNullable<OpenClawConfig["channels"]>["matrix"]>>,
): OpenClawConfig {
return {
channels: {
matrix: {
homeserver: "https://matrix.example.org",
userId: "@bot:example.org",
accessToken: "tok",
execApprovals: {
enabled: true,
approvers: ["@owner:example.org"],
target: "both",
},
...overrides,
},
},
} as OpenClawConfig;
}
describe("matrix approval capability", () => {
it("describes the correct Matrix exec-approval setup path", () => {
const text = matrixApprovalCapability.describeExecApprovalSetup?.({
channel: "matrix",
channelLabel: "Matrix",
});
expect(text).toContain("`channels.matrix.execApprovals.approvers`");
expect(text).toContain("`channels.matrix.dm.allowFrom`");
});
it("describes the named-account Matrix exec-approval setup path", () => {
const text = matrixApprovalCapability.describeExecApprovalSetup?.({
channel: "matrix",
channelLabel: "Matrix",
accountId: "work",
});
expect(text).toContain("`channels.matrix.accounts.work.execApprovals.approvers`");
expect(text).toContain("`channels.matrix.accounts.work.dm.allowFrom`");
expect(text).not.toContain("`channels.matrix.execApprovals.approvers`");
});
it("describes native matrix approval delivery capabilities", () => {
const capabilities = matrixApprovalCapability.native?.describeDeliveryCapabilities({
cfg: buildConfig(),
accountId: "default",
approvalKind: "exec",
request: {
id: "req-1",
request: {
command: "echo hi",
turnSourceChannel: "matrix",
turnSourceTo: "room:!ops:example.org",
turnSourceAccountId: "default",
sessionKey: "agent:main:matrix:channel:!ops:example.org",
},
createdAtMs: 0,
expiresAtMs: 1000,
},
});
expect(capabilities).toEqual({
enabled: true,
preferredSurface: "both",
supportsOriginSurface: true,
supportsApproverDmSurface: true,
notifyOriginWhenDmOnly: true,
});
});
it("resolves origin targets from matrix turn source", async () => {
const target = await matrixApprovalCapability.native?.resolveOriginTarget?.({
cfg: buildConfig(),
accountId: "default",
approvalKind: "exec",
request: {
id: "req-1",
request: {
command: "echo hi",
turnSourceChannel: "matrix",
turnSourceTo: "room:!ops:example.org",
turnSourceThreadId: "$thread",
turnSourceAccountId: "default",
sessionKey: "agent:main:matrix:channel:!ops:example.org",
},
createdAtMs: 0,
expiresAtMs: 1000,
},
});
expect(target).toEqual({
to: "room:!ops:example.org",
threadId: "$thread",
});
});
it("resolves approver dm targets", async () => {
const targets = await matrixApprovalCapability.native?.resolveApproverDmTargets?.({
cfg: buildConfig(),
accountId: "default",
approvalKind: "exec",
request: {
id: "req-1",
request: {
command: "echo hi",
},
createdAtMs: 0,
expiresAtMs: 1000,
},
});
expect(targets).toEqual([{ to: "user:@owner:example.org" }]);
});
it("suppresses same-channel plugin forwarding when Matrix native delivery is available", () => {
const shouldSuppress = matrixApprovalCapability.delivery?.shouldSuppressForwardingFallback;
if (!shouldSuppress) {
throw new Error("delivery suppression helper unavailable");
}
expect(
shouldSuppress({
cfg: buildConfig({
dm: { allowFrom: ["@owner:example.org"] },
}),
approvalKind: "plugin",
target: {
channel: "matrix",
to: "room:!ops:example.org",
accountId: "default",
},
request: {
id: "plugin:req-1",
request: {
title: "Plugin Approval Required",
description: "Allow plugin action",
pluginId: "git-tools",
turnSourceChannel: "matrix",
turnSourceTo: "room:!ops:example.org",
turnSourceAccountId: "default",
},
createdAtMs: 0,
expiresAtMs: 1000,
},
} as never),
).toBe(true);
});
it("preserves room-id case when matching Matrix origin targets", async () => {
const target = await matrixApprovalCapability.native?.resolveOriginTarget?.({
cfg: buildConfig(),
accountId: "default",
approvalKind: "exec",
request: {
id: "req-1",
request: {
command: "echo hi",
turnSourceChannel: "matrix",
turnSourceTo: "room:!Ops:Example.org",
turnSourceThreadId: "$thread",
turnSourceAccountId: "default",
sessionKey: "agent:main:matrix:channel:!Ops:Example.org",
},
createdAtMs: 0,
expiresAtMs: 1000,
},
});
expect(target).toEqual({
to: "room:!Ops:Example.org",
threadId: "$thread",
});
});
it("keeps plugin approval auth independent from exec approvers", () => {
const cfg = buildConfig({
dm: { allowFrom: ["@owner:example.org"] },
execApprovals: {
enabled: true,
approvers: ["@exec:example.org"],
target: "both",
},
});
expect(
matrixApprovalCapability.authorizeActorAction?.({
cfg,
accountId: "default",
senderId: "@owner:example.org",
action: "approve",
approvalKind: "plugin",
}),
).toEqual({ authorized: true });
expect(
matrixApprovalCapability.authorizeActorAction?.({
cfg,
accountId: "default",
senderId: "@exec:example.org",
action: "approve",
approvalKind: "plugin",
}),
).toEqual({
authorized: false,
reason: "❌ You are not authorized to approve plugin requests on Matrix.",
});
expect(
matrixApprovalCapability.authorizeActorAction?.({
cfg,
accountId: "default",
senderId: "@exec:example.org",
action: "approve",
approvalKind: "exec",
}),
).toEqual({ authorized: true });
});
it("requires Matrix DM approvers before enabling plugin approval auth", () => {
const cfg = buildConfig({
dm: { allowFrom: [] },
execApprovals: {
enabled: true,
approvers: ["@exec:example.org"],
target: "both",
},
});
expect(
matrixApprovalCapability.authorizeActorAction?.({
cfg,
accountId: "default",
senderId: "@exec:example.org",
action: "approve",
approvalKind: "plugin",
}),
).toEqual({
authorized: false,
reason: "❌ Matrix plugin approvals are not enabled for this bot account.",
});
});
it("reports exec initiating-surface availability independently from plugin auth", () => {
const cfg = buildConfig({
dm: { allowFrom: ["@owner:example.org"] },
execApprovals: {
enabled: false,
approvers: [],
target: "both",
},
});
expect(
matrixApprovalCapability.getActionAvailabilityState?.({
cfg,
accountId: "default",
action: "approve",
approvalKind: "plugin",
}),
).toEqual({ kind: "enabled" });
expect(
matrixApprovalCapability.getExecInitiatingSurfaceState?.({
cfg,
accountId: "default",
action: "approve",
}),
).toEqual({ kind: "disabled" });
});
it("enables matrix-native plugin approval delivery when DM approvers are configured", () => {
const capabilities = matrixApprovalCapability.native?.describeDeliveryCapabilities({
cfg: buildConfig({
dm: { allowFrom: ["@owner:example.org"] },
}),
accountId: "default",
approvalKind: "plugin",
request: {
id: "plugin:req-1",
request: {
title: "Plugin Approval Required",
description: "Allow plugin access",
pluginId: "git-tools",
},
createdAtMs: 0,
expiresAtMs: 1000,
},
});
expect(capabilities).toEqual({
enabled: true,
preferredSurface: "both",
supportsOriginSurface: true,
supportsApproverDmSurface: true,
notifyOriginWhenDmOnly: true,
});
});
it("keeps matrix-native plugin approval delivery disabled without DM approvers", () => {
const capabilities = matrixApprovalCapability.native?.describeDeliveryCapabilities({
cfg: buildConfig(),
accountId: "default",
approvalKind: "plugin",
request: {
id: "plugin:req-1",
request: {
title: "Plugin Approval Required",
description: "Allow plugin access",
pluginId: "git-tools",
},
createdAtMs: 0,
expiresAtMs: 1000,
},
});
expect(capabilities).toEqual({
enabled: false,
preferredSurface: "both",
supportsOriginSurface: true,
supportsApproverDmSurface: true,
notifyOriginWhenDmOnly: true,
});
});
});