feat(config): add tools.alsoAllow additive allowlist

This commit is contained in:
Vignesh Natarajan
2026-01-25 00:29:28 -08:00
committed by Pocket Clawd
parent b9098f3401
commit 2ad3508a33
7 changed files with 109 additions and 8 deletions
+37 -1
View File
@@ -1,12 +1,19 @@
import { describe, expect, it, vi } from "vitest";
import { beforeEach, describe, expect, it, vi } from "vitest";
import type { IncomingMessage, ServerResponse } from "node:http";
import { installGatewayTestHooks, getFreePort, startGatewayServer } from "./test-helpers.server.js";
import { resetTestPluginRegistry, setTestPluginRegistry, testState } from "./test-helpers.mocks.js";
import { createTestRegistry } from "../test-utils/channel-plugins.js";
installGatewayTestHooks({ scope: "suite" });
beforeEach(() => {
// Ensure these tests are not affected by host env vars.
delete process.env.CLAWDBOT_GATEWAY_TOKEN;
delete process.env.CLAWDBOT_GATEWAY_PASSWORD;
});
const resolveGatewayToken = (): string => {
const token = (testState.gatewayAuth as { token?: string } | undefined)?.token;
if (!token) throw new Error("test gateway token missing");
@@ -47,6 +54,35 @@ describe("POST /tools/invoke", () => {
await server.close();
});
it("supports tools.alsoAllow as additive allowlist (profile stage)", async () => {
// No explicit tool allowlist; rely on profile + alsoAllow.
testState.agentsConfig = {
list: [{ id: "main" }],
} as any;
// minimal profile does NOT include sessions_list, but alsoAllow should.
const { writeConfigFile } = await import("../config/config.js");
await writeConfigFile({
tools: { profile: "minimal", alsoAllow: ["sessions_list"] },
} as any);
const port = await getFreePort();
const server = await startGatewayServer(port, { bind: "loopback" });
const token = resolveGatewayToken();
const res = await fetch(`http://127.0.0.1:${port}/tools/invoke`, {
method: "POST",
headers: { "content-type": "application/json", authorization: `Bearer ${token}` },
body: JSON.stringify({ tool: "sessions_list", action: "json", args: {}, sessionKey: "main" }),
});
expect(res.status).toBe(200);
const body = await res.json();
expect(body.ok).toBe(true);
await server.close();
});
it("accepts password auth when bearer token matches", async () => {
testState.agentsConfig = {
list: [