Gateway: scope node pending drain to nodes

This commit is contained in:
Mariano Belinky
2026-03-09 21:24:32 +01:00
parent 54536e48f5
commit c49af9ea7c
4 changed files with 6 additions and 6 deletions

View File

@@ -18,6 +18,10 @@ describe("method scope resolution", () => {
expect(resolveLeastPrivilegeOperatorScopesForMethod("poll")).toEqual(["operator.write"]);
});
it("leaves node-only pending drain outside operator scopes", () => {
expect(resolveLeastPrivilegeOperatorScopesForMethod("node.pending.drain")).toEqual([]);
});
it("returns empty scopes for unknown methods", () => {
expect(resolveLeastPrivilegeOperatorScopesForMethod("totally.unknown.method")).toEqual([]);
});

View File

@@ -22,6 +22,7 @@ export const CLI_DEFAULT_OPERATOR_SCOPES: OperatorScope[] = [
const NODE_ROLE_METHODS = new Set([
"node.invoke.result",
"node.event",
"node.pending.drain",
"node.canvas.capability.refresh",
"node.pending.pull",
"node.pending.ack",
@@ -78,7 +79,6 @@ const METHOD_SCOPE_GROUPS: Record<OperatorScope, readonly string[]> = {
"last-heartbeat",
"node.list",
"node.describe",
"node.pending.drain",
"chat.history",
"config.get",
"config.schema.lookup",

View File

@@ -24,7 +24,7 @@ describe("gateway role policy", () => {
expect(isRoleAuthorizedForMethod("node", "node.pending.drain")).toBe(true);
expect(isRoleAuthorizedForMethod("node", "status")).toBe(false);
expect(isRoleAuthorizedForMethod("operator", "status")).toBe(true);
expect(isRoleAuthorizedForMethod("operator", "node.pending.drain")).toBe(true);
expect(isRoleAuthorizedForMethod("operator", "node.pending.drain")).toBe(false);
expect(isRoleAuthorizedForMethod("operator", "node.event")).toBe(false);
});
});

View File

@@ -1,7 +1,6 @@
import { isNodeRoleMethod } from "./method-scopes.js";
export const GATEWAY_ROLES = ["operator", "node"] as const;
const SHARED_ROLE_METHODS = new Set(["node.pending.drain"]);
export type GatewayRole = (typeof GATEWAY_ROLES)[number];
@@ -17,9 +16,6 @@ export function roleCanSkipDeviceIdentity(role: GatewayRole, sharedAuthOk: boole
}
export function isRoleAuthorizedForMethod(role: GatewayRole, method: string): boolean {
if (SHARED_ROLE_METHODS.has(method)) {
return true;
}
if (isNodeRoleMethod(method)) {
return role === "node";
}