refactor(security): unify gateway scope authorization flows

This commit is contained in:
Peter Steinberger
2026-02-19 15:06:28 +01:00
parent f4b288b8f7
commit 2777d8ad93
14 changed files with 202 additions and 86 deletions

View File

@@ -10,8 +10,8 @@ import {
} from "../../infra/restart-sentinel.js";
import { scheduleGatewaySigusr1Restart } from "../../infra/restart.js";
import { stringEnum } from "../schema/typebox.js";
import { type AnyAgentTool, jsonResult, readStringParam } from "./common.js";
import { callGatewayTool } from "./gateway.js";
import { assertOwnerSender, type AnyAgentTool, jsonResult, readStringParam } from "./common.js";
import { callGatewayTool, readGatewayCallOptions } from "./gateway.js";
const DEFAULT_UPDATE_TIMEOUT_MS = 20 * 60_000;
@@ -74,9 +74,7 @@ export function createGatewayTool(opts?: {
"Restart, apply config, or update the gateway in-place (SIGUSR1). Use config.patch for safe partial config updates (merges with existing). Use config.apply only when replacing entire config. Both trigger restart after writing. Always pass a human-readable completion message via the `note` parameter so the system can deliver it to the user after restart.",
parameters: GatewayToolSchema,
execute: async (_toolCallId, args) => {
if (opts?.senderIsOwner === false) {
throw new Error("Tool restricted to owner senders.");
}
assertOwnerSender(opts?.senderIsOwner);
const params = args as Record<string, unknown>;
const action = readStringParam(params, "action", { required: true });
if (action === "restart") {
@@ -129,19 +127,7 @@ export function createGatewayTool(opts?: {
return jsonResult(scheduled);
}
const gatewayUrl =
typeof params.gatewayUrl === "string" && params.gatewayUrl.trim()
? params.gatewayUrl.trim()
: undefined;
const gatewayToken =
typeof params.gatewayToken === "string" && params.gatewayToken.trim()
? params.gatewayToken.trim()
: undefined;
const timeoutMs =
typeof params.timeoutMs === "number" && Number.isFinite(params.timeoutMs)
? Math.max(1, Math.floor(params.timeoutMs))
: undefined;
const gatewayOpts = { gatewayUrl, gatewayToken, timeoutMs };
const gatewayOpts = readGatewayCallOptions(params);
const resolveGatewayWriteMeta = (): {
sessionKey: string | undefined;
@@ -214,15 +200,16 @@ export function createGatewayTool(opts?: {
}
if (action === "update.run") {
const { sessionKey, note, restartDelayMs } = resolveGatewayWriteMeta();
const updateTimeoutMs = gatewayOpts.timeoutMs ?? DEFAULT_UPDATE_TIMEOUT_MS;
const updateGatewayOpts = {
...gatewayOpts,
timeoutMs: timeoutMs ?? DEFAULT_UPDATE_TIMEOUT_MS,
timeoutMs: updateTimeoutMs,
};
const result = await callGatewayTool("update.run", updateGatewayOpts, {
sessionKey,
note,
restartDelayMs,
timeoutMs: timeoutMs ?? DEFAULT_UPDATE_TIMEOUT_MS,
timeoutMs: updateTimeoutMs,
});
return jsonResult({ ok: true, result });
}