Skip to content

Commit db3c4ba

Browse files
committed
refactor(gateway): collapse method metadata shims
1 parent 7c639d4 commit db3c4ba

34 files changed

Lines changed: 354 additions & 549 deletions

extensions/whatsapp/src/shared.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ export function createWhatsAppPluginBase(params: {
220220
},
221221
},
222222
reload: { configPrefixes: ["web"], noopPrefixes: ["channels.whatsapp"] },
223-
gatewayMethods: ["web.login.start", "web.login.wait"],
223+
gatewayMethodDescriptors: [{ name: "web.login.start" }, { name: "web.login.wait" }],
224224
configSchema: WhatsAppChannelConfigSchema,
225225
config: {
226226
...whatsappConfigAdapter,
@@ -254,7 +254,7 @@ export function createWhatsAppPluginBase(params: {
254254
setupWizard: base.setupWizard!,
255255
capabilities: base.capabilities!,
256256
reload: base.reload!,
257-
gatewayMethods: base.gatewayMethods!,
257+
gatewayMethodDescriptors: base.gatewayMethodDescriptors!,
258258
configSchema: base.configSchema!,
259259
config: base.config!,
260260
messaging: {
@@ -278,7 +278,7 @@ export function createWhatsAppPluginBase(params: {
278278
| "setupWizard"
279279
| "capabilities"
280280
| "reload"
281-
| "gatewayMethods"
281+
| "gatewayMethodDescriptors"
282282
| "configSchema"
283283
| "config"
284284
| "messaging"

src/auto-reply/reply/commands-diagnostics.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,6 @@ function createBundledPluginRecord(id: string): PluginRecord {
129129
migrationProviderIds: [],
130130
memoryEmbeddingProviderIds: [],
131131
agentHarnessIds: [],
132-
gatewayMethods: [],
133132
cliCommands: [],
134133
services: [],
135134
gatewayDiscoveryServiceIds: [],

src/cli/plugins-cli.list.test.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,6 @@ describe("plugins cli list", () => {
279279
cliCommands: [],
280280
services: [],
281281
gatewayDiscoveryServices: [],
282-
gatewayMethods: [],
283282
mcpServers: [],
284283
lspServers: [],
285284
httpRouteCount: 0,
@@ -328,7 +327,6 @@ describe("plugins cli list", () => {
328327
cliCommands: [],
329328
services: [],
330329
gatewayDiscoveryServices: [],
331-
gatewayMethods: [],
332330
mcpServers: [],
333331
lspServers: [],
334332
httpRouteCount: 0,

src/gateway/method-scopes.test.ts

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,28 @@ import {
66
isGatewayMethodClassified,
77
resolveLeastPrivilegeOperatorScopesForMethod,
88
} from "./method-scopes.js";
9+
import { createPluginGatewayMethodDescriptor } from "./methods/registry.js";
910
import { listGatewayMethods } from "./server-methods-list.js";
1011
import { coreGatewayHandlers } from "./server-methods.js";
12+
import type { GatewayRequestHandler } from "./server-methods/types.js";
1113

1214
const RESERVED_ADMIN_PLUGIN_METHOD = "config.plugin.inspect";
15+
const pluginHandler: GatewayRequestHandler = ({ respond }) => respond(true, {});
1316

1417
function setPluginGatewayMethodScope(
1518
method: string,
1619
scope: "operator.read" | "operator.write" | "operator.admin",
1720
) {
1821
const registry = createEmptyPluginRegistry();
19-
registry.gatewayMethodScopes = {
20-
[method]: scope,
21-
};
22+
registry.gatewayHandlers[method] = pluginHandler;
23+
registry.gatewayMethodDescriptors.push(
24+
createPluginGatewayMethodDescriptor({
25+
pluginId: "test",
26+
name: method,
27+
handler: pluginHandler,
28+
scope,
29+
}),
30+
);
2231
setActivePluginRegistry(registry);
2332
}
2433

@@ -183,9 +192,15 @@ describe("method scope resolution", () => {
183192

184193
it("reads plugin-registered gateway method scopes from the active plugin registry", () => {
185194
const registry = createEmptyPluginRegistry();
186-
registry.gatewayMethodScopes = {
187-
"browser.request": "operator.admin",
188-
};
195+
registry.gatewayHandlers["browser.request"] = pluginHandler;
196+
registry.gatewayMethodDescriptors.push(
197+
createPluginGatewayMethodDescriptor({
198+
pluginId: "browser",
199+
name: "browser.request",
200+
handler: pluginHandler,
201+
scope: "operator.admin",
202+
}),
203+
);
189204
setActivePluginRegistry(registry);
190205

191206
expect(resolveLeastPrivilegeOperatorScopesForMethod("browser.request")).toEqual([

src/gateway/method-scopes.ts

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import { getPluginRegistryState } from "../plugins/runtime-state.js";
22
import { resolveReservedGatewayMethodScope } from "../shared/gateway-method-policy.js";
33
import {
4-
DYNAMIC_OPERATOR_SCOPE_METHODS,
5-
METHOD_SCOPE_BY_NAME,
6-
NODE_ROLE_METHODS,
7-
} from "./methods/legacy-metadata.js";
4+
isCoreGatewayMethodClassified,
5+
isCoreNodeGatewayMethod,
6+
isDynamicOperatorGatewayMethod,
7+
resolveCoreOperatorGatewayMethodScope,
8+
} from "./methods/core-descriptors.js";
89
import {
910
ADMIN_SCOPE,
1011
APPROVALS_SCOPE,
@@ -36,19 +37,19 @@ export const CLI_DEFAULT_OPERATOR_SCOPES: OperatorScope[] = [
3637
];
3738

3839
function resolveScopedMethod(method: string): OperatorScope | undefined {
39-
const explicitScope = METHOD_SCOPE_BY_NAME.get(method);
40+
const explicitScope = resolveCoreOperatorGatewayMethodScope(method);
4041
if (explicitScope) {
4142
return explicitScope;
4243
}
4344
const reservedScope = resolveReservedGatewayMethodScope(method);
4445
if (reservedScope) {
4546
return reservedScope;
4647
}
47-
const pluginScope = getPluginRegistryState()?.activeRegistry?.gatewayMethodScopes?.[method];
48-
if (pluginScope) {
49-
return pluginScope;
50-
}
51-
return undefined;
48+
const pluginDescriptor = getPluginRegistryState()?.activeRegistry?.gatewayMethodDescriptors?.find(
49+
(descriptor) => descriptor.name === method,
50+
);
51+
const pluginScope = pluginDescriptor?.scope;
52+
return pluginScope === "node" || pluginScope === "dynamic" ? undefined : pluginScope;
5253
}
5354

5455
export function isApprovalMethod(method: string): boolean {
@@ -68,7 +69,7 @@ export function isWriteMethod(method: string): boolean {
6869
}
6970

7071
export function isNodeRoleMethod(method: string): boolean {
71-
return NODE_ROLE_METHODS.has(method);
72+
return isCoreNodeGatewayMethod(method);
7273
}
7374

7475
export function isAdminOnlyMethod(method: string): boolean {
@@ -135,7 +136,7 @@ export function resolveLeastPrivilegeOperatorScopesForMethod(
135136
method: string,
136137
params?: unknown,
137138
): OperatorScope[] {
138-
if (DYNAMIC_OPERATOR_SCOPE_METHODS.has(method)) {
139+
if (isDynamicOperatorGatewayMethod(method)) {
139140
return resolveDynamicLeastPrivilegeOperatorScopesForMethod(method, params);
140141
}
141142
const requiredScope = resolveRequiredOperatorScopeForMethod(method);
@@ -154,7 +155,7 @@ export function authorizeOperatorScopesForMethod(
154155
if (scopes.includes(ADMIN_SCOPE)) {
155156
return { allowed: true };
156157
}
157-
if (DYNAMIC_OPERATOR_SCOPE_METHODS.has(method)) {
158+
if (isDynamicOperatorGatewayMethod(method)) {
158159
const registeredScopes = resolveSessionActionRegisteredScopes(params);
159160
if (!registeredScopes && params && typeof params === "object" && !Array.isArray(params)) {
160161
const pluginId = normalizeSessionActionParam((params as { pluginId?: unknown }).pluginId);
@@ -188,8 +189,11 @@ export function isGatewayMethodClassified(method: string): boolean {
188189
if (isNodeRoleMethod(method)) {
189190
return true;
190191
}
191-
if (DYNAMIC_OPERATOR_SCOPE_METHODS.has(method)) {
192+
if (isDynamicOperatorGatewayMethod(method)) {
192193
return true;
193194
}
194-
return resolveRequiredOperatorScopeForMethod(method) !== undefined;
195+
return (
196+
isCoreGatewayMethodClassified(method) ||
197+
resolveRequiredOperatorScopeForMethod(method) !== undefined
198+
);
195199
}

0 commit comments

Comments
 (0)