refactor(gateway): dedupe auth and discord monitor suites

This commit is contained in:
Peter Steinberger
2026-03-02 21:30:43 +00:00
parent ab8b8dae70
commit 5f0cbd0edc
14 changed files with 434 additions and 500 deletions

View File

@@ -94,6 +94,39 @@ async function expectDiscordSessionTargetRequest(params: {
expect(deliver).toHaveBeenCalledTimes(params.expectedDeliveryCount);
}
async function expectSessionFilterRequestResult(params: {
sessionFilter: string[];
sessionKey: string;
expectedAccepted: boolean;
expectedDeliveryCount: number;
}) {
const cfg = {
approvals: {
exec: {
enabled: true,
mode: "session",
sessionFilter: params.sessionFilter,
},
},
} as OpenClawConfig;
const { deliver, forwarder } = createForwarder({
cfg,
resolveSessionTarget: () => ({ channel: "slack", to: "U1" }),
});
const request = {
...baseRequest,
request: {
...baseRequest.request,
sessionKey: params.sessionKey,
},
};
await expect(forwarder.handleRequested(request)).resolves.toBe(params.expectedAccepted);
expect(deliver).toHaveBeenCalledTimes(params.expectedDeliveryCount);
}
describe("exec approval forwarder", () => {
it("forwards to session target and resolves", async () => {
vi.useFakeTimers();
@@ -167,59 +200,21 @@ describe("exec approval forwarder", () => {
});
it("rejects unsafe nested-repetition regex in sessionFilter", async () => {
const cfg = {
approvals: {
exec: {
enabled: true,
mode: "session",
sessionFilter: ["(a+)+$"],
},
},
} as OpenClawConfig;
const { deliver, forwarder } = createForwarder({
cfg,
resolveSessionTarget: () => ({ channel: "slack", to: "U1" }),
await expectSessionFilterRequestResult({
sessionFilter: ["(a+)+$"],
sessionKey: `${"a".repeat(28)}!`,
expectedAccepted: false,
expectedDeliveryCount: 0,
});
const request = {
...baseRequest,
request: {
...baseRequest.request,
sessionKey: `${"a".repeat(28)}!`,
},
};
await expect(forwarder.handleRequested(request)).resolves.toBe(false);
expect(deliver).not.toHaveBeenCalled();
});
it("matches long session keys with tail-bounded regex checks", async () => {
const cfg = {
approvals: {
exec: {
enabled: true,
mode: "session",
sessionFilter: ["discord:tail$"],
},
},
} as OpenClawConfig;
const { deliver, forwarder } = createForwarder({
cfg,
resolveSessionTarget: () => ({ channel: "slack", to: "U1" }),
await expectSessionFilterRequestResult({
sessionFilter: ["discord:tail$"],
sessionKey: `${"x".repeat(5000)}discord:tail`,
expectedAccepted: true,
expectedDeliveryCount: 1,
});
const request = {
...baseRequest,
request: {
...baseRequest.request,
sessionKey: `${"x".repeat(5000)}discord:tail`,
},
};
await expect(forwarder.handleRequested(request)).resolves.toBe(true);
expect(deliver).toHaveBeenCalledTimes(1);
});
it("returns false when all targets are skipped", async () => {

View File

@@ -46,6 +46,33 @@ function tryResolveRealpath(filePath: string | undefined): string | undefined {
}
}
function buildCommandResolution(params: {
rawExecutable: string;
cwd?: string;
env?: NodeJS.ProcessEnv;
effectiveArgv: string[];
wrapperChain: string[];
policyBlocked: boolean;
blockedWrapper?: string;
}): CommandResolution {
const resolvedPath = resolveExecutableCandidatePath(params.rawExecutable, {
cwd: params.cwd,
env: params.env,
});
const resolvedRealPath = tryResolveRealpath(resolvedPath);
const executableName = resolvedPath ? path.basename(resolvedPath) : params.rawExecutable;
return {
rawExecutable: params.rawExecutable,
resolvedPath,
resolvedRealPath,
executableName,
effectiveArgv: params.effectiveArgv,
wrapperChain: params.wrapperChain,
policyBlocked: params.policyBlocked,
blockedWrapper: params.blockedWrapper,
};
}
export function resolveCommandResolution(
command: string,
cwd?: string,
@@ -55,18 +82,14 @@ export function resolveCommandResolution(
if (!rawExecutable) {
return null;
}
const resolvedPath = resolveExecutableCandidatePath(rawExecutable, { cwd, env });
const resolvedRealPath = tryResolveRealpath(resolvedPath);
const executableName = resolvedPath ? path.basename(resolvedPath) : rawExecutable;
return {
return buildCommandResolution({
rawExecutable,
resolvedPath,
resolvedRealPath,
executableName,
effectiveArgv: [rawExecutable],
wrapperChain: [],
policyBlocked: false,
};
cwd,
env,
});
}
export function resolveCommandResolutionFromArgv(
@@ -80,19 +103,15 @@ export function resolveCommandResolutionFromArgv(
if (!rawExecutable) {
return null;
}
const resolvedPath = resolveExecutableCandidatePath(rawExecutable, { cwd, env });
const resolvedRealPath = tryResolveRealpath(resolvedPath);
const executableName = resolvedPath ? path.basename(resolvedPath) : rawExecutable;
return {
return buildCommandResolution({
rawExecutable,
resolvedPath,
resolvedRealPath,
executableName,
effectiveArgv,
wrapperChain: plan.wrappers,
policyBlocked: plan.policyBlocked,
blockedWrapper: plan.blockedWrapper,
};
cwd,
env,
});
}
function normalizeMatchTarget(value: string): string {