Files
openclaw/test/helpers/channels/config-write-contract-suites.ts
2026-04-04 04:11:00 +09:00

194 lines
5.9 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
authorizeConfigWrite,
canBypassConfigWritePolicy,
formatConfigWriteDeniedMessage,
resolveExplicitConfigWriteTarget,
resolveConfigWriteTargetFromPath,
} from "../../../src/channels/plugins/config-writes.js";
import { INTERNAL_MESSAGE_CHANNEL } from "../../../src/utils/message-channel.js";
const demoOriginChannelId = "demo-origin";
const demoTargetChannelId = "demo-target";
function makeDemoConfigWritesCfg(accountIdKey: string) {
return {
channels: {
[demoOriginChannelId]: {
configWrites: true,
accounts: {
[accountIdKey]: { configWrites: false },
},
},
[demoTargetChannelId]: {
configWrites: true,
accounts: {
[accountIdKey]: { configWrites: false },
},
},
},
};
}
function expectConfigWriteBlocked(params: {
disabledAccountId: string;
reason: "target-disabled" | "origin-disabled";
blockedScope: "target" | "origin";
}) {
expect(
authorizeConfigWrite({
cfg: makeDemoConfigWritesCfg(params.disabledAccountId),
origin: { channelId: demoOriginChannelId, accountId: "default" },
target: resolveExplicitConfigWriteTarget({
channelId: params.blockedScope === "target" ? demoTargetChannelId : demoOriginChannelId,
accountId: "work",
}),
}),
).toEqual({
allowed: false,
reason: params.reason,
blockedScope: {
kind: params.blockedScope,
scope: {
channelId: params.blockedScope === "target" ? demoTargetChannelId : demoOriginChannelId,
accountId: params.blockedScope === "target" ? "work" : "default",
},
},
});
}
function expectAuthorizedConfigWriteCase(
input: Parameters<typeof authorizeConfigWrite>[0],
expected: ReturnType<typeof authorizeConfigWrite>,
) {
expect(authorizeConfigWrite(input)).toEqual(expected);
}
function expectResolvedConfigWriteTargetCase(pathSegments: readonly string[], expected: unknown) {
expect(resolveConfigWriteTargetFromPath([...pathSegments])).toEqual(expected);
}
function expectExplicitConfigWriteTargetCase(
input: Parameters<typeof resolveExplicitConfigWriteTarget>[0],
expected: ReturnType<typeof resolveExplicitConfigWriteTarget>,
) {
expect(resolveExplicitConfigWriteTarget(input)).toEqual(expected);
}
function expectFormattedDeniedMessage(
result: Exclude<ReturnType<typeof authorizeConfigWrite>, { allowed: true }>,
) {
expect(
formatConfigWriteDeniedMessage({
result,
}),
).toContain(`channels.${demoTargetChannelId}.accounts.work.configWrites=true`);
}
export function describeChannelConfigWritePolicyContract() {
describe("authorizeConfigWrite policy contract", () => {
it.each([
{
name: "blocks when a target account disables writes",
disabledAccountId: "work",
reason: "target-disabled",
blockedScope: "target",
},
{
name: "blocks when the origin account disables writes",
disabledAccountId: "default",
reason: "origin-disabled",
blockedScope: "origin",
},
] as const)("$name", (testCase) => {
expectConfigWriteBlocked(testCase);
});
it.each([
{
name: "allows bypass for internal operator.admin writes",
input: {
cfg: makeDemoConfigWritesCfg("work"),
origin: { channelId: demoOriginChannelId, accountId: "default" },
target: resolveExplicitConfigWriteTarget({
channelId: demoTargetChannelId,
accountId: "work",
}),
allowBypass: canBypassConfigWritePolicy({
channel: INTERNAL_MESSAGE_CHANNEL,
gatewayClientScopes: ["operator.admin"],
}),
},
expected: { allowed: true },
},
{
name: "treats non-channel config paths as global writes",
input: {
cfg: makeDemoConfigWritesCfg("work"),
origin: { channelId: demoOriginChannelId, accountId: "default" },
target: resolveConfigWriteTargetFromPath(["messages", "ackReaction"]),
},
expected: { allowed: true },
},
] as const)("$name", ({ input, expected }) => {
expectAuthorizedConfigWriteCase(input, expected);
});
});
}
export function describeChannelConfigWriteTargetContract() {
describe("authorizeConfigWrite target contract", () => {
it.each([
{
name: "rejects bare channel collection writes",
pathSegments: ["channels", "demo-channel"],
expected: { kind: "ambiguous", scopes: [{ channelId: "demo-channel" }] },
},
{
name: "rejects account collection writes",
pathSegments: ["channels", "demo-channel", "accounts"],
expected: { kind: "ambiguous", scopes: [{ channelId: "demo-channel" }] },
},
] as const)("$name", ({ pathSegments, expected }) => {
expectResolvedConfigWriteTargetCase(pathSegments, expected);
});
it.each([
{
name: "resolves explicit channel target",
input: { channelId: demoOriginChannelId },
expected: {
kind: "channel",
scope: { channelId: demoOriginChannelId },
},
},
{
name: "resolves explicit account target",
input: { channelId: demoTargetChannelId, accountId: "work" },
expected: {
kind: "account",
scope: { channelId: demoTargetChannelId, accountId: "work" },
},
},
] as const)("$name", ({ input, expected }) => {
expectExplicitConfigWriteTargetCase(input, expected);
});
it.each([
{
name: "formats denied messages consistently",
result: {
allowed: false,
reason: "target-disabled",
blockedScope: {
kind: "target",
scope: { channelId: demoTargetChannelId, accountId: "work" },
},
} as const,
},
] as const)("$name", ({ result }) => {
expectFormattedDeniedMessage(result);
});
});
}