@burdenoff/mcp-libs 2026.1009.2 → 2026.1012.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/modules/groups/index.cjs +360 -89
- package/dist/modules/groups/index.cjs.map +1 -1
- package/dist/modules/groups/index.js +356 -90
- package/dist/modules/groups/index.js.map +1 -1
- package/dist/modules/rbac/index.cjs +373 -71
- package/dist/modules/rbac/index.cjs.map +1 -1
- package/dist/modules/rbac/index.js +369 -72
- package/dist/modules/rbac/index.js.map +1 -1
- package/dist/modules/scheduler/index.cjs +1044 -70
- package/dist/modules/scheduler/index.cjs.map +1 -1
- package/dist/modules/scheduler/index.js +1038 -69
- package/dist/modules/scheduler/index.js.map +1 -1
- package/dist/modules/security/index.cjs +507 -42
- package/dist/modules/security/index.cjs.map +1 -1
- package/dist/modules/security/index.js +501 -41
- package/dist/modules/security/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,6 +1,104 @@
|
|
|
1
|
-
import { mcpToolName, errorResult } from '../../chunk-G76DKEPI.js';
|
|
1
|
+
import { mcpToolName, errorResult, jsonResult } from '../../chunk-G76DKEPI.js';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
|
|
4
|
+
// src/modules/rbac/operations.ts
|
|
5
|
+
var LIST_ROLES = `
|
|
6
|
+
query ListRoles($filter: RoleFilterInput, $pagination: PaginationInput, $scopeId: String!) {
|
|
7
|
+
roles(filter: $filter, pagination: $pagination, scopeId: $scopeId) {
|
|
8
|
+
id
|
|
9
|
+
name
|
|
10
|
+
description
|
|
11
|
+
isSystem
|
|
12
|
+
scopeId
|
|
13
|
+
priority
|
|
14
|
+
defaultPermissions {
|
|
15
|
+
level
|
|
16
|
+
resourceType
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
`;
|
|
21
|
+
var GET_ROLE = `
|
|
22
|
+
query GetRole($id: ID!) {
|
|
23
|
+
role(id: $id) {
|
|
24
|
+
id
|
|
25
|
+
name
|
|
26
|
+
description
|
|
27
|
+
isSystem
|
|
28
|
+
scopeId
|
|
29
|
+
priority
|
|
30
|
+
defaultPermissions {
|
|
31
|
+
level
|
|
32
|
+
resourceType
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
`;
|
|
37
|
+
var CREATE_ROLE = `
|
|
38
|
+
mutation CreateRole($input: CreateRoleInput!) {
|
|
39
|
+
createRole(input: $input) {
|
|
40
|
+
id
|
|
41
|
+
name
|
|
42
|
+
description
|
|
43
|
+
scopeId
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
`;
|
|
47
|
+
var UPDATE_ROLE = `
|
|
48
|
+
mutation UpdateRole($id: ID!, $input: UpdateRoleInput!) {
|
|
49
|
+
updateRole(id: $id, input: $input) {
|
|
50
|
+
id
|
|
51
|
+
name
|
|
52
|
+
description
|
|
53
|
+
priority
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
`;
|
|
57
|
+
var DELETE_ROLE = `
|
|
58
|
+
mutation DeleteRole($id: ID!, $reassignToRoleId: ID) {
|
|
59
|
+
deleteRole(id: $id, reassignToRoleId: $reassignToRoleId)
|
|
60
|
+
}
|
|
61
|
+
`;
|
|
62
|
+
var CHECK_PERMISSION = `
|
|
63
|
+
query CheckPermission($input: PermissionCheckInput!) {
|
|
64
|
+
checkPermission(input: $input) {
|
|
65
|
+
allowed
|
|
66
|
+
decisionPath
|
|
67
|
+
roleName
|
|
68
|
+
roleLevel
|
|
69
|
+
overrideType
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
`;
|
|
73
|
+
var LIST_POLICY_REFERENCES = `
|
|
74
|
+
query PolicyReferences($filter: PolicyReferenceFilterInput, $pagination: PaginationInput) {
|
|
75
|
+
policyReferences(filter: $filter, pagination: $pagination) {
|
|
76
|
+
id
|
|
77
|
+
name
|
|
78
|
+
description
|
|
79
|
+
opaPackage
|
|
80
|
+
resourceType
|
|
81
|
+
action
|
|
82
|
+
isActive
|
|
83
|
+
priority
|
|
84
|
+
createdAt
|
|
85
|
+
updatedAt
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
`;
|
|
89
|
+
|
|
90
|
+
// src/modules/rbac/tools.ts
|
|
91
|
+
var LayerEnum = z.enum(["workspace", "global"]);
|
|
92
|
+
var ActorTypeEnum = z.enum(["USER", "BOT", "GROUP", "INTEGRATION", "DELEGATED_AGENT"]);
|
|
93
|
+
function clientForLayer(ctx, layer) {
|
|
94
|
+
return layer === "workspace" ? ctx.gql.workspace : ctx.gql.global;
|
|
95
|
+
}
|
|
96
|
+
function defaultScopeId(ctx, layer) {
|
|
97
|
+
const auth = ctx.auth.read();
|
|
98
|
+
if (!auth) return null;
|
|
99
|
+
if (layer === "workspace") return auth.workspaceId ?? null;
|
|
100
|
+
return auth.organizationId ?? null;
|
|
101
|
+
}
|
|
4
102
|
function stubbedTool(server, toolName, title, description, featureNote, inputSchema, altSuggestions) {
|
|
5
103
|
server.registerTool(
|
|
6
104
|
toolName,
|
|
@@ -14,89 +112,288 @@ function stubbedTool(server, toolName, title, description, featureNote, inputSch
|
|
|
14
112
|
)
|
|
15
113
|
);
|
|
16
114
|
}
|
|
17
|
-
function registerRbacTools(server,
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
115
|
+
function registerRbacTools(server, ctx, track) {
|
|
116
|
+
server.registerTool(
|
|
117
|
+
track(mcpToolName(ctx.productName, "rbac_roles_list")),
|
|
118
|
+
{
|
|
119
|
+
title: "List Roles",
|
|
120
|
+
description: "List RBAC roles for a workspace or global scope.",
|
|
121
|
+
inputSchema: {
|
|
122
|
+
layer: LayerEnum.optional().describe("workspace or global (default: workspace)"),
|
|
123
|
+
scopeId: z.string().optional().describe("Override scope id (workspace or tenant)"),
|
|
124
|
+
includeSystem: z.boolean().optional().describe("Include system roles"),
|
|
125
|
+
limit: z.number().optional().describe("Page size")
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
async ({ layer, scopeId, includeSystem, limit }) => {
|
|
129
|
+
try {
|
|
130
|
+
const targetLayer = layer ?? "workspace";
|
|
131
|
+
const resolvedScope = scopeId ?? defaultScopeId(ctx, targetLayer);
|
|
132
|
+
if (!resolvedScope) {
|
|
133
|
+
return errorResult(
|
|
134
|
+
`No ${targetLayer} scope. Pass scopeId or authenticate to a workspace/organization.`
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
const filter = {};
|
|
138
|
+
if (includeSystem) filter.includeSystem = true;
|
|
139
|
+
const data = await clientForLayer(ctx, targetLayer).request(
|
|
140
|
+
LIST_ROLES,
|
|
141
|
+
{
|
|
142
|
+
filter: Object.keys(filter).length ? filter : void 0,
|
|
143
|
+
pagination: { limit: limit ?? 100, offset: 0 },
|
|
144
|
+
scopeId: resolvedScope
|
|
145
|
+
}
|
|
146
|
+
);
|
|
147
|
+
return jsonResult(data.roles);
|
|
148
|
+
} catch (error) {
|
|
149
|
+
ctx.logger.error("rbac_roles_list failed", { error: String(error) });
|
|
150
|
+
return errorResult(
|
|
151
|
+
`Failed to list roles: ${error instanceof Error ? error.message : String(error)}`
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
28
155
|
);
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
156
|
+
server.registerTool(
|
|
157
|
+
track(mcpToolName(ctx.productName, "rbac_roles_get")),
|
|
158
|
+
{
|
|
159
|
+
title: "Get Role",
|
|
160
|
+
description: "Get a role by id from the workspace or global layer.",
|
|
161
|
+
inputSchema: {
|
|
162
|
+
id: z.string().describe("Role ID"),
|
|
163
|
+
layer: LayerEnum.optional().describe("workspace or global (default: workspace)")
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
async ({ id, layer }) => {
|
|
167
|
+
try {
|
|
168
|
+
const targetLayer = layer ?? "workspace";
|
|
169
|
+
const data = await clientForLayer(ctx, targetLayer).request(
|
|
170
|
+
GET_ROLE,
|
|
171
|
+
{ id }
|
|
172
|
+
);
|
|
173
|
+
if (!data.role) return errorResult(`Role ${id} not found`);
|
|
174
|
+
return jsonResult(data.role);
|
|
175
|
+
} catch (error) {
|
|
176
|
+
ctx.logger.error("rbac_roles_get failed", { error: String(error) });
|
|
177
|
+
return errorResult(
|
|
178
|
+
`Failed to get role: ${error instanceof Error ? error.message : String(error)}`
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
37
182
|
);
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
183
|
+
server.registerTool(
|
|
184
|
+
track(mcpToolName(ctx.productName, "rbac_roles_create")),
|
|
185
|
+
{
|
|
186
|
+
title: "Create Role",
|
|
187
|
+
description: "Create a new RBAC role at the workspace or global layer.",
|
|
188
|
+
inputSchema: {
|
|
189
|
+
name: z.string().describe("Role name"),
|
|
190
|
+
description: z.string().optional().describe("Role description"),
|
|
191
|
+
parentId: z.string().optional().describe("Parent role id"),
|
|
192
|
+
priority: z.number().optional().describe("Priority"),
|
|
193
|
+
layer: LayerEnum.optional().describe("workspace or global (default: workspace)"),
|
|
194
|
+
scopeId: z.string().optional().describe("Override scope id"),
|
|
195
|
+
scopeType: z.string().optional().describe("wspace|entity (global layer only)")
|
|
196
|
+
}
|
|
197
|
+
},
|
|
198
|
+
async ({ name, description, parentId, priority, layer, scopeId, scopeType }) => {
|
|
199
|
+
try {
|
|
200
|
+
const targetLayer = layer ?? "workspace";
|
|
201
|
+
const resolvedScope = scopeId ?? defaultScopeId(ctx, targetLayer);
|
|
202
|
+
if (!resolvedScope) {
|
|
203
|
+
return errorResult(
|
|
204
|
+
`No ${targetLayer} scope. Pass scopeId or authenticate to a workspace/organization.`
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
const input = { name, scopeId: resolvedScope };
|
|
208
|
+
if (description !== void 0) input.description = description;
|
|
209
|
+
if (parentId !== void 0) input.parentId = parentId;
|
|
210
|
+
if (priority !== void 0) input.priority = priority;
|
|
211
|
+
if (targetLayer === "global" && scopeType) input.scopeType = scopeType;
|
|
212
|
+
const data = await clientForLayer(ctx, targetLayer).request(
|
|
213
|
+
CREATE_ROLE,
|
|
214
|
+
{ input }
|
|
215
|
+
);
|
|
216
|
+
return jsonResult(data.createRole);
|
|
217
|
+
} catch (error) {
|
|
218
|
+
ctx.logger.error("rbac_roles_create failed", { error: String(error) });
|
|
219
|
+
return errorResult(
|
|
220
|
+
`Failed to create role: ${error instanceof Error ? error.message : String(error)}`
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
46
224
|
);
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
225
|
+
server.registerTool(
|
|
226
|
+
track(mcpToolName(ctx.productName, "rbac_roles_update")),
|
|
227
|
+
{
|
|
228
|
+
title: "Update Role",
|
|
229
|
+
description: "Update an existing role.",
|
|
230
|
+
inputSchema: {
|
|
231
|
+
id: z.string().describe("Role ID"),
|
|
232
|
+
name: z.string().optional().describe("Updated name"),
|
|
233
|
+
description: z.string().optional().describe("Updated description"),
|
|
234
|
+
priority: z.number().optional().describe("Updated priority"),
|
|
235
|
+
parentId: z.string().optional().describe("Updated parent role id"),
|
|
236
|
+
layer: LayerEnum.optional().describe("workspace or global (default: workspace)")
|
|
237
|
+
}
|
|
238
|
+
},
|
|
239
|
+
async ({ id, name, description, priority, parentId, layer }) => {
|
|
240
|
+
try {
|
|
241
|
+
const targetLayer = layer ?? "workspace";
|
|
242
|
+
const input = {};
|
|
243
|
+
if (name !== void 0) input.name = name;
|
|
244
|
+
if (description !== void 0) input.description = description;
|
|
245
|
+
if (priority !== void 0) input.priority = priority;
|
|
246
|
+
if (parentId !== void 0) input.parentId = parentId;
|
|
247
|
+
if (!Object.keys(input).length) {
|
|
248
|
+
return errorResult("No updates specified");
|
|
249
|
+
}
|
|
250
|
+
const data = await clientForLayer(ctx, targetLayer).request(
|
|
251
|
+
UPDATE_ROLE,
|
|
252
|
+
{ id, input }
|
|
253
|
+
);
|
|
254
|
+
return jsonResult(data.updateRole);
|
|
255
|
+
} catch (error) {
|
|
256
|
+
ctx.logger.error("rbac_roles_update failed", { error: String(error) });
|
|
257
|
+
return errorResult(
|
|
258
|
+
`Failed to update role: ${error instanceof Error ? error.message : String(error)}`
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
55
262
|
);
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
263
|
+
server.registerTool(
|
|
264
|
+
track(mcpToolName(ctx.productName, "rbac_roles_delete")),
|
|
265
|
+
{
|
|
266
|
+
title: "Delete Role",
|
|
267
|
+
description: "Delete a role, optionally reassigning actors to another role.",
|
|
268
|
+
inputSchema: {
|
|
269
|
+
id: z.string().describe("Role ID"),
|
|
270
|
+
reassignToRoleId: z.string().optional().describe("Reassign actors to this role"),
|
|
271
|
+
layer: LayerEnum.optional().describe("workspace or global (default: workspace)")
|
|
272
|
+
}
|
|
273
|
+
},
|
|
274
|
+
async ({ id, reassignToRoleId, layer }) => {
|
|
275
|
+
try {
|
|
276
|
+
const targetLayer = layer ?? "workspace";
|
|
277
|
+
const data = await clientForLayer(ctx, targetLayer).request(
|
|
278
|
+
DELETE_ROLE,
|
|
279
|
+
{ id, reassignToRoleId }
|
|
280
|
+
);
|
|
281
|
+
return jsonResult({ deleted: data.deleteRole, roleId: id });
|
|
282
|
+
} catch (error) {
|
|
283
|
+
ctx.logger.error("rbac_roles_delete failed", { error: String(error) });
|
|
284
|
+
return errorResult(
|
|
285
|
+
`Failed to delete role: ${error instanceof Error ? error.message : String(error)}`
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
64
289
|
);
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
290
|
+
server.registerTool(
|
|
291
|
+
track(mcpToolName(ctx.productName, "rbac_policies_list")),
|
|
292
|
+
{
|
|
293
|
+
title: "List Policy References",
|
|
294
|
+
description: "List OPA policy references registered on the chosen gateway (workspace or global), optionally filtered by resource/action/active state. Returns an array of PolicyReference.",
|
|
295
|
+
inputSchema: {
|
|
296
|
+
layer: LayerEnum.optional().describe("workspace or global (default: workspace)"),
|
|
297
|
+
resourceType: z.string().optional().describe("Filter by resource type (e.g. project)"),
|
|
298
|
+
action: z.string().optional().describe("Filter by action (e.g. read/write/delete)"),
|
|
299
|
+
isActive: z.boolean().optional().describe("Only active/inactive policies"),
|
|
300
|
+
limit: z.number().int().optional().describe("Page size (default 100)"),
|
|
301
|
+
offset: z.number().int().optional().describe("Pagination offset (default 0)")
|
|
302
|
+
}
|
|
303
|
+
},
|
|
304
|
+
async ({ layer, resourceType, action, isActive, limit, offset }) => {
|
|
305
|
+
try {
|
|
306
|
+
const targetLayer = layer ?? "workspace";
|
|
307
|
+
const filter = {};
|
|
308
|
+
if (resourceType !== void 0) filter.resourceType = resourceType;
|
|
309
|
+
if (action !== void 0) filter.action = action;
|
|
310
|
+
if (isActive !== void 0) filter.isActive = isActive;
|
|
311
|
+
const data = await clientForLayer(ctx, targetLayer).request(LIST_POLICY_REFERENCES, {
|
|
312
|
+
filter: Object.keys(filter).length ? filter : void 0,
|
|
313
|
+
pagination: { limit: limit ?? 100, offset: offset ?? 0 }
|
|
314
|
+
});
|
|
315
|
+
return jsonResult(data.policyReferences);
|
|
316
|
+
} catch (error) {
|
|
317
|
+
ctx.logger.error("rbac_policies_list failed", { error: String(error) });
|
|
318
|
+
return errorResult(
|
|
319
|
+
`Failed to list policy references: ${error instanceof Error ? error.message : String(error)}`
|
|
320
|
+
);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
73
323
|
);
|
|
74
324
|
stubbedTool(
|
|
75
325
|
server,
|
|
76
|
-
track(mcpToolName(
|
|
77
|
-
"
|
|
78
|
-
"
|
|
79
|
-
|
|
80
|
-
{
|
|
81
|
-
|
|
326
|
+
track(mcpToolName(ctx.productName, "rbac_policies_attach")),
|
|
327
|
+
"Attach Policy To Role",
|
|
328
|
+
"Attach an OPA policy reference to a role on the chosen gateway. Returns the attached PolicyReference.",
|
|
329
|
+
"Live alpha does not expose `Mutation.attachPolicyToRole` \u2014 the rbac service has never defined it. Policy-role attachment is implicit in `createRole(input)` and `assignRoleToActor` instead.",
|
|
330
|
+
{
|
|
331
|
+
roleId: z.string().describe("Role ID"),
|
|
332
|
+
policyId: z.string().describe("PolicyReference ID"),
|
|
333
|
+
layer: LayerEnum.optional().describe("workspace or global (default: workspace)")
|
|
334
|
+
},
|
|
335
|
+
[
|
|
336
|
+
"the next alpha release that adds `attachPolicyToRole` to the rbac service",
|
|
337
|
+
"the SDK rbac.attachPolicyToRole when it lands"
|
|
338
|
+
]
|
|
82
339
|
);
|
|
83
340
|
stubbedTool(
|
|
84
341
|
server,
|
|
85
|
-
track(mcpToolName(
|
|
86
|
-
"
|
|
87
|
-
"
|
|
88
|
-
|
|
89
|
-
{
|
|
90
|
-
|
|
342
|
+
track(mcpToolName(ctx.productName, "rbac_policies_detach")),
|
|
343
|
+
"Detach Policy From Role",
|
|
344
|
+
"Detach an OPA policy reference from a role on the chosen gateway. Returns { detached: boolean, roleId, policyId }.",
|
|
345
|
+
"Live alpha does not expose `Mutation.detachPolicyFromRole` \u2014 same as attach/detach (see above).",
|
|
346
|
+
{
|
|
347
|
+
roleId: z.string().describe("Role ID"),
|
|
348
|
+
policyId: z.string().describe("PolicyReference ID"),
|
|
349
|
+
layer: LayerEnum.optional().describe("workspace or global (default: workspace)")
|
|
350
|
+
},
|
|
351
|
+
["the next alpha release that adds `detachPolicyFromRole` to the rbac service"]
|
|
91
352
|
);
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
353
|
+
server.registerTool(
|
|
354
|
+
track(mcpToolName(ctx.productName, "rbac_check")),
|
|
355
|
+
{
|
|
356
|
+
title: "Check Permission",
|
|
357
|
+
description: "Check whether an actor has permission for an action on a resource.",
|
|
358
|
+
inputSchema: {
|
|
359
|
+
actorId: z.string().describe("Actor id (user/app/service/super_admin)"),
|
|
360
|
+
action: z.string().describe("Action like read/write/delete"),
|
|
361
|
+
resourceType: z.string().describe("Resource type like project/task"),
|
|
362
|
+
actorType: ActorTypeEnum.optional().describe("Actor type (default: USER)"),
|
|
363
|
+
resourceId: z.string().optional().describe("Specific resource id (optional)"),
|
|
364
|
+
scopeId: z.string().optional().describe("Scope id (workspaceId or tenantId)"),
|
|
365
|
+
layer: LayerEnum.optional().describe("workspace or global (default: workspace)")
|
|
366
|
+
}
|
|
367
|
+
},
|
|
368
|
+
async ({ actorId, action, resourceType, actorType, resourceId, scopeId, layer }) => {
|
|
369
|
+
try {
|
|
370
|
+
const targetLayer = layer ?? "workspace";
|
|
371
|
+
const resolvedScope = scopeId ?? defaultScopeId(ctx, targetLayer);
|
|
372
|
+
if (!resolvedScope) {
|
|
373
|
+
return errorResult(
|
|
374
|
+
`No ${targetLayer} scope. Pass scopeId or authenticate to a workspace/organization.`
|
|
375
|
+
);
|
|
376
|
+
}
|
|
377
|
+
const input = {
|
|
378
|
+
actorId,
|
|
379
|
+
actorType: actorType ?? "USER",
|
|
380
|
+
action,
|
|
381
|
+
resourceType,
|
|
382
|
+
scopeId: resolvedScope
|
|
383
|
+
};
|
|
384
|
+
if (resourceId !== void 0) input.resourceId = resourceId;
|
|
385
|
+
const data = await clientForLayer(ctx, targetLayer).request(
|
|
386
|
+
CHECK_PERMISSION,
|
|
387
|
+
{ input }
|
|
388
|
+
);
|
|
389
|
+
return jsonResult(data.checkPermission);
|
|
390
|
+
} catch (error) {
|
|
391
|
+
ctx.logger.error("rbac_check failed", { error: String(error) });
|
|
392
|
+
return errorResult(
|
|
393
|
+
`Failed to check permission: ${error instanceof Error ? error.message : String(error)}`
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
100
397
|
);
|
|
101
398
|
}
|
|
102
399
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/modules/rbac/tools.ts","../../../src/modules/rbac/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { z } from 'zod';\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { errorResult, mcpToolName, type McpContext } from '../../core/index.js';\n\ntype StubInputSchema = Record<string, z.ZodTypeAny>;\nfunction stubbedTool(\n server: McpServer,\n toolName: string,\n title: string,\n description: string,\n featureNote: string,\n inputSchema: StubInputSchema,\n altSuggestions: string[],\n): void {\n server.registerTool(\n toolName,\n {\n title,\n description: `${description} [STUB]`,\n inputSchema,\n },\n async () =>\n errorResult(\n `[stubbed] ${featureNote} Use ${altSuggestions.join(', ')} instead. The tool remains registered so callers receive a meaningful response instead of a schema-validation error.`,\n ),\n );\n}\n\nexport function registerRbacTools(\n server: McpServer,\n _ctx: McpContext,\n track: (n: string) => string,\n): void {\n // BOFF-8195: `Mutation.attachPolicyToRole` / `detachPolicyFromRole`\n // removed from the live alpha gateway (gateway returned a missing-\n // `@rbac`-directive error). The `rbac_check` and `rbac_policies_list`\n // queries are gone too (`Query.roles` / `Query.policies` do not\n // exist). Whole rbac module unreachable today. Stubs preserve the\n // per-call wiring for the day the service re-exposes the surface.\n const featureNote =\n 'Live alpha removed the rbac policies surface (no `attachPolicyToRole` / `detachPolicyFromRole` mutations; `roles` / `policies` queries are gone).';\n const alts = ['the next alpha release that re-exposes the rbac surface'];\n\n stubbedTool(\n server,\n track(mcpToolName(_ctx.productName, 'rbac_check')),\n 'Check Permission',\n 'Check whether the calling actor has a given permission.',\n featureNote,\n { permission: z.string() },\n alts,\n );\n stubbedTool(\n server,\n track(mcpToolName(_ctx.productName, 'rbac_policies_list')),\n 'List Policy References',\n 'List references to a policy across the system.',\n featureNote,\n { policyId: z.string() },\n alts,\n );\n stubbedTool(\n server,\n track(mcpToolName(_ctx.productName, 'rbac_policies_attach')),\n 'Attach Policy to Role',\n 'Attach a policy to a role.',\n featureNote,\n { roleId: z.string(), policyId: z.string() },\n alts,\n );\n stubbedTool(\n server,\n track(mcpToolName(_ctx.productName, 'rbac_policies_detach')),\n 'Detach Policy from Role',\n 'Detach a policy from a role.',\n featureNote,\n { roleId: z.string(), policyId: z.string() },\n alts,\n );\n stubbedTool(\n server,\n track(mcpToolName(_ctx.productName, 'rbac_roles_list')),\n 'List Roles',\n 'List roles (workspace or global layer).',\n featureNote,\n { layer: z.enum(['workspace', 'global']).optional() },\n alts,\n );\n stubbedTool(\n server,\n track(mcpToolName(_ctx.productName, 'rbac_roles_get')),\n 'Get Role',\n 'Get a role by ID.',\n featureNote,\n { id: z.string() },\n alts,\n );\n stubbedTool(\n server,\n track(mcpToolName(_ctx.productName, 'rbac_roles_create')),\n 'Create Role',\n 'Create a new role.',\n featureNote,\n { name: z.string() },\n alts,\n );\n stubbedTool(\n server,\n track(mcpToolName(_ctx.productName, 'rbac_roles_update')),\n 'Update Role',\n 'Update a role.',\n featureNote,\n { id: z.string() },\n alts,\n );\n stubbedTool(\n server,\n track(mcpToolName(_ctx.productName, 'rbac_roles_delete')),\n 'Delete Role',\n 'Delete a role.',\n featureNote,\n { id: z.string() },\n alts,\n );\n}\n","/**\n * RBAC module — role-based access control across workspace + global layers.\n *\n * Tools:\n * <product>_rbac_roles_{list,get,create,update,delete}\n * <product>_rbac_check\n *\n * Backend: ~/products/wspace/rbac/wspace-rbac-svc/, ~/products/global/rbac/global-rbac-svc/.\n */\n\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { McpContext, McpModule, ModuleRegistration } from '../../core/index.js';\nimport { registerRbacTools } from './tools.js';\n\nconst rbacModule: McpModule = {\n id: 'rbac',\n version: '0.0.1',\n displayName: 'RBAC',\n dependsOn: ['auth'],\n capabilities: { tools: {} },\n\n register(server: McpServer, ctx: McpContext): ModuleRegistration {\n const tools: string[] = [];\n const track = (n: string): string => {\n tools.push(n);\n return n;\n };\n\n registerRbacTools(server, ctx, track);\n\n return { tools, resources: [], prompts: [] };\n },\n};\n\nexport default rbacModule;\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/modules/rbac/operations.ts","../../../src/modules/rbac/tools.ts","../../../src/modules/rbac/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["export const LIST_ROLES = `\n query ListRoles($filter: RoleFilterInput, $pagination: PaginationInput, $scopeId: String!) {\n roles(filter: $filter, pagination: $pagination, scopeId: $scopeId) {\n id\n name\n description\n isSystem\n scopeId\n priority\n defaultPermissions {\n level\n resourceType\n }\n }\n }\n`;\n\nexport const GET_ROLE = `\n query GetRole($id: ID!) {\n role(id: $id) {\n id\n name\n description\n isSystem\n scopeId\n priority\n defaultPermissions {\n level\n resourceType\n }\n }\n }\n`;\n\nexport const CREATE_ROLE = `\n mutation CreateRole($input: CreateRoleInput!) {\n createRole(input: $input) {\n id\n name\n description\n scopeId\n }\n }\n`;\n\nexport const UPDATE_ROLE = `\n mutation UpdateRole($id: ID!, $input: UpdateRoleInput!) {\n updateRole(id: $id, input: $input) {\n id\n name\n description\n priority\n }\n }\n`;\n\nexport const DELETE_ROLE = `\n mutation DeleteRole($id: ID!, $reassignToRoleId: ID) {\n deleteRole(id: $id, reassignToRoleId: $reassignToRoleId)\n }\n`;\n\nexport const CHECK_PERMISSION = `\n query CheckPermission($input: PermissionCheckInput!) {\n checkPermission(input: $input) {\n allowed\n decisionPath\n roleName\n roleLevel\n overrideType\n }\n }\n`;\n\nexport const LIST_POLICY_REFERENCES = `\n query PolicyReferences($filter: PolicyReferenceFilterInput, $pagination: PaginationInput) {\n policyReferences(filter: $filter, pagination: $pagination) {\n id\n name\n description\n opaPackage\n resourceType\n action\n isActive\n priority\n createdAt\n updatedAt\n }\n }\n`;\n\nexport const ATTACH_POLICY = `\n mutation AttachPolicy($roleId: ID!, $policyId: ID!) {\n attachPolicyToRole(roleId: $roleId, policyId: $policyId) {\n id\n name\n resourceType\n action\n isActive\n }\n }\n`;\n\nexport const DETACH_POLICY = `\n mutation DetachPolicy($roleId: ID!, $policyId: ID!) {\n detachPolicyFromRole(roleId: $roleId, policyId: $policyId)\n }\n`;\n","import { z } from 'zod';\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { jsonResult, errorResult, mcpToolName, type McpContext } from '../../core/index.js';\nimport {\n LIST_ROLES,\n GET_ROLE,\n CREATE_ROLE,\n UPDATE_ROLE,\n DELETE_ROLE,\n CHECK_PERMISSION,\n LIST_POLICY_REFERENCES,\n} from './operations.js';\n\nconst LayerEnum = z.enum(['workspace', 'global']);\nconst ActorTypeEnum = z.enum(['USER', 'BOT', 'GROUP', 'INTEGRATION', 'DELEGATED_AGENT']);\n\ntype Layer = 'workspace' | 'global';\n\nfunction clientForLayer(ctx: McpContext, layer: Layer) {\n return layer === 'workspace' ? ctx.gql.workspace : ctx.gql.global;\n}\n\nfunction defaultScopeId(ctx: McpContext, layer: Layer): string | null {\n const auth = ctx.auth.read();\n if (!auth) return null;\n if (layer === 'workspace') return auth.workspaceId ?? null;\n return auth.organizationId ?? null;\n}\n\n// BOFF-9166 (un-stub pass for PR #25's rbac module):\n// 7 of the 9 stubbed tools are real here — the rbac service exposes\n// `roles` / `role` / `createRole` / `updateRole` / `deleteRole` /\n// `checkPermission` / `policyReferences` with proper `@rbac` directives.\n// The remaining 2 (`rbac_policies_attach` / `rbac_policies_detach`)\n// reference `Mutation.attachPolicyToRole` / `Mutation.detachPolicyFromRole`,\n// which the rbac service has never defined (policy-role attachment is\n// implicit in `createRole(input)` and `assignRoleToActor` instead). The\n// original BOFF-8195 error \"missing @rbac directive\" was a transient /\n// misread — `git log -S attachPolicyToRole` returns nothing. The two\n// tools stay stubbed until the rbac service gains the mutations (or the\n// SDK manifest drops the surface); every other rbac tool calls the real\n// gateway and surfaces real data on alpha.\ntype StubInputSchema = Record<string, z.ZodTypeAny>;\nfunction stubbedTool(\n server: McpServer,\n toolName: string,\n title: string,\n description: string,\n featureNote: string,\n inputSchema: StubInputSchema,\n altSuggestions: string[],\n): void {\n server.registerTool(\n toolName,\n {\n title,\n description: `${description} [STUB]`,\n inputSchema,\n },\n async () =>\n errorResult(\n `[stubbed] ${featureNote} Use ${altSuggestions.join(', ')} instead. The tool remains registered so callers receive a meaningful response instead of a schema-validation error.`,\n ),\n );\n}\n\nexport function registerRbacTools(\n server: McpServer,\n ctx: McpContext,\n track: (n: string) => string,\n): void {\n server.registerTool(\n track(mcpToolName(ctx.productName, 'rbac_roles_list')),\n {\n title: 'List Roles',\n description: 'List RBAC roles for a workspace or global scope.',\n inputSchema: {\n layer: LayerEnum.optional().describe('workspace or global (default: workspace)'),\n scopeId: z.string().optional().describe('Override scope id (workspace or tenant)'),\n includeSystem: z.boolean().optional().describe('Include system roles'),\n limit: z.number().optional().describe('Page size'),\n },\n },\n async ({ layer, scopeId, includeSystem, limit }) => {\n try {\n const targetLayer: Layer = layer ?? 'workspace';\n const resolvedScope = scopeId ?? defaultScopeId(ctx, targetLayer);\n if (!resolvedScope) {\n return errorResult(\n `No ${targetLayer} scope. Pass scopeId or authenticate to a workspace/organization.`,\n );\n }\n const filter: Record<string, unknown> = {};\n if (includeSystem) filter.includeSystem = true;\n const data = await clientForLayer(ctx, targetLayer).request<{ roles: unknown }>(\n LIST_ROLES,\n {\n filter: Object.keys(filter).length ? filter : undefined,\n pagination: { limit: limit ?? 100, offset: 0 },\n scopeId: resolvedScope,\n },\n );\n return jsonResult(data.roles);\n } catch (error) {\n ctx.logger.error('rbac_roles_list failed', { error: String(error) });\n return errorResult(\n `Failed to list roles: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n },\n );\n\n server.registerTool(\n track(mcpToolName(ctx.productName, 'rbac_roles_get')),\n {\n title: 'Get Role',\n description: 'Get a role by id from the workspace or global layer.',\n inputSchema: {\n id: z.string().describe('Role ID'),\n layer: LayerEnum.optional().describe('workspace or global (default: workspace)'),\n },\n },\n async ({ id, layer }) => {\n try {\n const targetLayer: Layer = layer ?? 'workspace';\n const data = await clientForLayer(ctx, targetLayer).request<{ role: unknown | null }>(\n GET_ROLE,\n { id },\n );\n if (!data.role) return errorResult(`Role ${id} not found`);\n return jsonResult(data.role);\n } catch (error) {\n ctx.logger.error('rbac_roles_get failed', { error: String(error) });\n return errorResult(\n `Failed to get role: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n },\n );\n\n server.registerTool(\n track(mcpToolName(ctx.productName, 'rbac_roles_create')),\n {\n title: 'Create Role',\n description: 'Create a new RBAC role at the workspace or global layer.',\n inputSchema: {\n name: z.string().describe('Role name'),\n description: z.string().optional().describe('Role description'),\n parentId: z.string().optional().describe('Parent role id'),\n priority: z.number().optional().describe('Priority'),\n layer: LayerEnum.optional().describe('workspace or global (default: workspace)'),\n scopeId: z.string().optional().describe('Override scope id'),\n scopeType: z.string().optional().describe('wspace|entity (global layer only)'),\n },\n },\n async ({ name, description, parentId, priority, layer, scopeId, scopeType }) => {\n try {\n const targetLayer: Layer = layer ?? 'workspace';\n const resolvedScope = scopeId ?? defaultScopeId(ctx, targetLayer);\n if (!resolvedScope) {\n return errorResult(\n `No ${targetLayer} scope. Pass scopeId or authenticate to a workspace/organization.`,\n );\n }\n const input: Record<string, unknown> = { name, scopeId: resolvedScope };\n if (description !== undefined) input.description = description;\n if (parentId !== undefined) input.parentId = parentId;\n if (priority !== undefined) input.priority = priority;\n if (targetLayer === 'global' && scopeType) input.scopeType = scopeType;\n const data = await clientForLayer(ctx, targetLayer).request<{ createRole: unknown }>(\n CREATE_ROLE,\n { input },\n );\n return jsonResult(data.createRole);\n } catch (error) {\n ctx.logger.error('rbac_roles_create failed', { error: String(error) });\n return errorResult(\n `Failed to create role: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n },\n );\n\n server.registerTool(\n track(mcpToolName(ctx.productName, 'rbac_roles_update')),\n {\n title: 'Update Role',\n description: 'Update an existing role.',\n inputSchema: {\n id: z.string().describe('Role ID'),\n name: z.string().optional().describe('Updated name'),\n description: z.string().optional().describe('Updated description'),\n priority: z.number().optional().describe('Updated priority'),\n parentId: z.string().optional().describe('Updated parent role id'),\n layer: LayerEnum.optional().describe('workspace or global (default: workspace)'),\n },\n },\n async ({ id, name, description, priority, parentId, layer }) => {\n try {\n const targetLayer: Layer = layer ?? 'workspace';\n const input: Record<string, unknown> = {};\n if (name !== undefined) input.name = name;\n if (description !== undefined) input.description = description;\n if (priority !== undefined) input.priority = priority;\n if (parentId !== undefined) input.parentId = parentId;\n if (!Object.keys(input).length) {\n return errorResult('No updates specified');\n }\n const data = await clientForLayer(ctx, targetLayer).request<{ updateRole: unknown }>(\n UPDATE_ROLE,\n { id, input },\n );\n return jsonResult(data.updateRole);\n } catch (error) {\n ctx.logger.error('rbac_roles_update failed', { error: String(error) });\n return errorResult(\n `Failed to update role: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n },\n );\n\n server.registerTool(\n track(mcpToolName(ctx.productName, 'rbac_roles_delete')),\n {\n title: 'Delete Role',\n description: 'Delete a role, optionally reassigning actors to another role.',\n inputSchema: {\n id: z.string().describe('Role ID'),\n reassignToRoleId: z.string().optional().describe('Reassign actors to this role'),\n layer: LayerEnum.optional().describe('workspace or global (default: workspace)'),\n },\n },\n async ({ id, reassignToRoleId, layer }) => {\n try {\n const targetLayer: Layer = layer ?? 'workspace';\n const data = await clientForLayer(ctx, targetLayer).request<{ deleteRole: unknown }>(\n DELETE_ROLE,\n { id, reassignToRoleId },\n );\n return jsonResult({ deleted: data.deleteRole, roleId: id });\n } catch (error) {\n ctx.logger.error('rbac_roles_delete failed', { error: String(error) });\n return errorResult(\n `Failed to delete role: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n },\n );\n\n // ── Policies ────────────────────────────────────────────────────────────\n server.registerTool(\n track(mcpToolName(ctx.productName, 'rbac_policies_list')),\n {\n title: 'List Policy References',\n description:\n 'List OPA policy references registered on the chosen gateway (workspace or global), optionally filtered by resource/action/active state. Returns an array of PolicyReference.',\n inputSchema: {\n layer: LayerEnum.optional().describe('workspace or global (default: workspace)'),\n resourceType: z.string().optional().describe('Filter by resource type (e.g. project)'),\n action: z.string().optional().describe('Filter by action (e.g. read/write/delete)'),\n isActive: z.boolean().optional().describe('Only active/inactive policies'),\n limit: z.number().int().optional().describe('Page size (default 100)'),\n offset: z.number().int().optional().describe('Pagination offset (default 0)'),\n },\n },\n async ({ layer, resourceType, action, isActive, limit, offset }) => {\n try {\n const targetLayer: Layer = layer ?? 'workspace';\n const filter: Record<string, unknown> = {};\n if (resourceType !== undefined) filter.resourceType = resourceType;\n if (action !== undefined) filter.action = action;\n if (isActive !== undefined) filter.isActive = isActive;\n const data = await clientForLayer(ctx, targetLayer).request<{\n policyReferences: unknown[];\n }>(LIST_POLICY_REFERENCES, {\n filter: Object.keys(filter).length ? filter : undefined,\n pagination: { limit: limit ?? 100, offset: offset ?? 0 },\n });\n return jsonResult(data.policyReferences);\n } catch (error) {\n ctx.logger.error('rbac_policies_list failed', { error: String(error) });\n return errorResult(\n `Failed to list policy references: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n },\n );\n\n // BOFF-9166: keep attach/detach as stubs — the underlying mutations don't\n // exist in any subgraph. See the file-header comment for context.\n stubbedTool(\n server,\n track(mcpToolName(ctx.productName, 'rbac_policies_attach')),\n 'Attach Policy To Role',\n 'Attach an OPA policy reference to a role on the chosen gateway. Returns the attached PolicyReference.',\n 'Live alpha does not expose `Mutation.attachPolicyToRole` — the rbac service has never defined it. Policy-role attachment is implicit in `createRole(input)` and `assignRoleToActor` instead.',\n {\n roleId: z.string().describe('Role ID'),\n policyId: z.string().describe('PolicyReference ID'),\n layer: LayerEnum.optional().describe('workspace or global (default: workspace)'),\n },\n [\n 'the next alpha release that adds `attachPolicyToRole` to the rbac service',\n 'the SDK rbac.attachPolicyToRole when it lands',\n ],\n );\n\n stubbedTool(\n server,\n track(mcpToolName(ctx.productName, 'rbac_policies_detach')),\n 'Detach Policy From Role',\n 'Detach an OPA policy reference from a role on the chosen gateway. Returns { detached: boolean, roleId, policyId }.',\n 'Live alpha does not expose `Mutation.detachPolicyFromRole` — same as attach/detach (see above).',\n {\n roleId: z.string().describe('Role ID'),\n policyId: z.string().describe('PolicyReference ID'),\n layer: LayerEnum.optional().describe('workspace or global (default: workspace)'),\n },\n ['the next alpha release that adds `detachPolicyFromRole` to the rbac service'],\n );\n\n server.registerTool(\n track(mcpToolName(ctx.productName, 'rbac_check')),\n {\n title: 'Check Permission',\n description: 'Check whether an actor has permission for an action on a resource.',\n inputSchema: {\n actorId: z.string().describe('Actor id (user/app/service/super_admin)'),\n action: z.string().describe('Action like read/write/delete'),\n resourceType: z.string().describe('Resource type like project/task'),\n actorType: ActorTypeEnum.optional().describe('Actor type (default: USER)'),\n resourceId: z.string().optional().describe('Specific resource id (optional)'),\n scopeId: z.string().optional().describe('Scope id (workspaceId or tenantId)'),\n layer: LayerEnum.optional().describe('workspace or global (default: workspace)'),\n },\n },\n async ({ actorId, action, resourceType, actorType, resourceId, scopeId, layer }) => {\n try {\n const targetLayer: Layer = layer ?? 'workspace';\n const resolvedScope = scopeId ?? defaultScopeId(ctx, targetLayer);\n if (!resolvedScope) {\n return errorResult(\n `No ${targetLayer} scope. Pass scopeId or authenticate to a workspace/organization.`,\n );\n }\n const input: Record<string, unknown> = {\n actorId,\n actorType: actorType ?? 'USER',\n action,\n resourceType,\n scopeId: resolvedScope,\n };\n if (resourceId !== undefined) input.resourceId = resourceId;\n const data = await clientForLayer(ctx, targetLayer).request<{ checkPermission: unknown }>(\n CHECK_PERMISSION,\n { input },\n );\n return jsonResult(data.checkPermission);\n } catch (error) {\n ctx.logger.error('rbac_check failed', { error: String(error) });\n return errorResult(\n `Failed to check permission: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n },\n );\n}\n","/**\n * RBAC module — role-based access control across workspace + global layers.\n *\n * Tools:\n * <product>_rbac_roles_{list,get,create,update,delete}\n * <product>_rbac_check\n *\n * Backend: ~/products/wspace/rbac/wspace-rbac-svc/, ~/products/global/rbac/global-rbac-svc/.\n */\n\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { McpContext, McpModule, ModuleRegistration } from '../../core/index.js';\nimport { registerRbacTools } from './tools.js';\n\nconst rbacModule: McpModule = {\n id: 'rbac',\n version: '0.0.1',\n displayName: 'RBAC',\n dependsOn: ['auth'],\n capabilities: { tools: {} },\n\n register(server: McpServer, ctx: McpContext): ModuleRegistration {\n const tools: string[] = [];\n const track = (n: string): string => {\n tools.push(n);\n return n;\n };\n\n registerRbacTools(server, ctx, track);\n\n return { tools, resources: [], prompts: [] };\n },\n};\n\nexport default rbacModule;\n"]}
|