@kybernesis/arp-scope-catalog 0.2.0

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.
Files changed (61) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +80 -0
  3. package/dist/index.cjs +518 -0
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/index.d.cts +144 -0
  6. package/dist/index.d.ts +144 -0
  7. package/dist/index.js +501 -0
  8. package/dist/index.js.map +1 -0
  9. package/generated/manifest.json +1542 -0
  10. package/generated/scopes.json +1536 -0
  11. package/package.json +49 -0
  12. package/scopes/calendar.availability.read.yaml +35 -0
  13. package/scopes/calendar.events.cancel.yaml +24 -0
  14. package/scopes/calendar.events.create.yaml +31 -0
  15. package/scopes/calendar.events.modify.yaml +24 -0
  16. package/scopes/calendar.events.propose.yaml +35 -0
  17. package/scopes/calendar.events.read.yaml +38 -0
  18. package/scopes/connection.extend.yaml +28 -0
  19. package/scopes/connection.rescope.request.yaml +21 -0
  20. package/scopes/contacts.attributes.read.yaml +25 -0
  21. package/scopes/contacts.introduce.yaml +21 -0
  22. package/scopes/contacts.search.yaml +26 -0
  23. package/scopes/contacts.share.yaml +30 -0
  24. package/scopes/credentials.present.request.yaml +29 -0
  25. package/scopes/credentials.proof.zk.request.yaml +31 -0
  26. package/scopes/delegation.forward.task.yaml +36 -0
  27. package/scopes/files.project.files.delete.yaml +31 -0
  28. package/scopes/files.project.files.list.yaml +22 -0
  29. package/scopes/files.project.files.read.yaml +35 -0
  30. package/scopes/files.project.files.summarize.yaml +30 -0
  31. package/scopes/files.project.files.write.yaml +34 -0
  32. package/scopes/files.project.metadata.read.yaml +21 -0
  33. package/scopes/files.projects.list.yaml +18 -0
  34. package/scopes/files.share.external.yaml +39 -0
  35. package/scopes/identity.card.read.yaml +18 -0
  36. package/scopes/identity.introduction.request.yaml +24 -0
  37. package/scopes/identity.principal.verify.yaml +19 -0
  38. package/scopes/knowledge.query.yaml +31 -0
  39. package/scopes/messaging.chat.send.yaml +27 -0
  40. package/scopes/messaging.email.draft.compose.yaml +23 -0
  41. package/scopes/messaging.email.send.reviewed.yaml +36 -0
  42. package/scopes/messaging.email.summary.yaml +26 -0
  43. package/scopes/messaging.email.thread.read.yaml +29 -0
  44. package/scopes/messaging.relay.to_principal.yaml +22 -0
  45. package/scopes/notes.read.yaml +25 -0
  46. package/scopes/notes.search.yaml +24 -0
  47. package/scopes/notes.write.yaml +32 -0
  48. package/scopes/payments.authorize.capped.yaml +37 -0
  49. package/scopes/payments.history.read.yaml +28 -0
  50. package/scopes/payments.quote.request.yaml +18 -0
  51. package/scopes/payments.refund.request.yaml +24 -0
  52. package/scopes/tasks.assign.yaml +27 -0
  53. package/scopes/tasks.create.yaml +31 -0
  54. package/scopes/tasks.list.yaml +21 -0
  55. package/scopes/tasks.read.yaml +22 -0
  56. package/scopes/tasks.status.update.yaml +22 -0
  57. package/scopes/tools.invoke.mutating.yaml +37 -0
  58. package/scopes/tools.invoke.read.yaml +28 -0
  59. package/scopes/work.projects.list.yaml +18 -0
  60. package/scopes/work.reports.summary.yaml +29 -0
  61. package/scopes/work.status.read.yaml +18 -0
package/dist/index.js ADDED
@@ -0,0 +1,501 @@
1
+ import { readFileSync, statSync, readdirSync } from 'fs';
2
+ import { resolve } from 'path';
3
+ import { parse } from 'yaml';
4
+ import { ScopeTemplateSchema, ScopeCatalogManifestSchema, DID_URI_REGEX } from '@kybernesis/arp-spec';
5
+ import { createHash } from 'crypto';
6
+ import Handlebars from 'handlebars';
7
+
8
+ // src/loader.ts
9
+ var ScopeLoadError = class extends Error {
10
+ file;
11
+ issues;
12
+ constructor(message, opts) {
13
+ super(message);
14
+ this.name = "ScopeLoadError";
15
+ if (opts?.file !== void 0) this.file = opts.file;
16
+ if (opts?.issues !== void 0) this.issues = opts.issues;
17
+ }
18
+ };
19
+ function loadScopeFile(filePath) {
20
+ let raw;
21
+ try {
22
+ raw = readFileSync(filePath, "utf8");
23
+ } catch (e) {
24
+ throw new ScopeLoadError(`cannot read ${filePath}: ${e.message}`, {
25
+ file: filePath
26
+ });
27
+ }
28
+ let parsed;
29
+ try {
30
+ parsed = parse(raw);
31
+ } catch (e) {
32
+ throw new ScopeLoadError(`invalid YAML in ${filePath}: ${e.message}`, {
33
+ file: filePath
34
+ });
35
+ }
36
+ const result = ScopeTemplateSchema.safeParse(parsed);
37
+ if (!result.success) {
38
+ throw new ScopeLoadError(`scope ${filePath} failed schema validation`, {
39
+ file: filePath,
40
+ issues: result.error.issues
41
+ });
42
+ }
43
+ return result.data;
44
+ }
45
+ function loadScopesFromDirectory(scopesDir) {
46
+ const st = statSync(scopesDir);
47
+ if (!st.isDirectory()) {
48
+ throw new ScopeLoadError(`${scopesDir} is not a directory`);
49
+ }
50
+ const files = readdirSync(scopesDir).filter((f) => f.endsWith(".yaml") || f.endsWith(".yml")).sort();
51
+ const seen = /* @__PURE__ */ new Set();
52
+ const scopes = [];
53
+ for (const file of files) {
54
+ const full = resolve(scopesDir, file);
55
+ const scope = loadScopeFile(full);
56
+ const expected = `${scope.id}.yaml`;
57
+ if (file !== expected && !(file === `${scope.id}.yml`)) {
58
+ throw new ScopeLoadError(
59
+ `filename ${file} does not match scope id ${scope.id} (expected ${expected})`,
60
+ { file: full }
61
+ );
62
+ }
63
+ if (seen.has(scope.id)) {
64
+ throw new ScopeLoadError(`duplicate scope id ${scope.id}`, { file: full });
65
+ }
66
+ seen.add(scope.id);
67
+ scopes.push(scope);
68
+ }
69
+ scopes.sort((a, b) => a.id.localeCompare(b.id));
70
+ return scopes;
71
+ }
72
+ function canonicalize(value) {
73
+ if (value === null) return "null";
74
+ if (typeof value === "number" && !Number.isFinite(value)) {
75
+ throw new Error("canonicalize: non-finite numbers are not allowed");
76
+ }
77
+ if (typeof value !== "object") {
78
+ return JSON.stringify(value);
79
+ }
80
+ if (Array.isArray(value)) {
81
+ return `[${value.map(canonicalize).join(",")}]`;
82
+ }
83
+ const obj = value;
84
+ const keys = Object.keys(obj).sort();
85
+ const parts = keys.map((k) => `${JSON.stringify(k)}:${canonicalize(obj[k])}`);
86
+ return `{${parts.join(",")}}`;
87
+ }
88
+ function sha256Hex(input) {
89
+ return createHash("sha256").update(input, "utf8").digest("hex");
90
+ }
91
+ function buildCatalogManifest(scopes, options = {}) {
92
+ const sorted = [...scopes].sort((a, b) => a.id.localeCompare(b.id));
93
+ const canonical = canonicalize(sorted);
94
+ const checksum = `sha256:${sha256Hex(canonical)}`;
95
+ const manifest = {
96
+ version: options.version ?? "v1",
97
+ updated_at: options.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
98
+ scope_count: sorted.length,
99
+ checksum,
100
+ scopes: sorted
101
+ };
102
+ const parsed = ScopeCatalogManifestSchema.parse(manifest);
103
+ return parsed;
104
+ }
105
+ var ScopeCompileError = class extends Error {
106
+ scopeId;
107
+ parameter;
108
+ constructor(message, opts) {
109
+ super(message);
110
+ this.name = "ScopeCompileError";
111
+ if (opts?.scopeId !== void 0) this.scopeId = opts.scopeId;
112
+ if (opts?.parameter !== void 0) this.parameter = opts.parameter;
113
+ }
114
+ };
115
+ function parseRangeValidation(validation) {
116
+ const match = /^(-?\d+(?:\.\d+)?)\.\.(-?\d+(?:\.\d+)?)$/.exec(validation);
117
+ if (!match) return null;
118
+ return { min: Number(match[1]), max: Number(match[2]) };
119
+ }
120
+ function coerceToNumber(value) {
121
+ if (typeof value === "number" && Number.isFinite(value)) return value;
122
+ if (typeof value === "string" && value.trim() !== "") {
123
+ const n = Number(value);
124
+ if (Number.isFinite(n)) return n;
125
+ }
126
+ return null;
127
+ }
128
+ function validateParameter(scopeId, def, initial) {
129
+ let value = initial;
130
+ const present = value !== void 0 && value !== null;
131
+ if (!present) {
132
+ if (def.default !== void 0) {
133
+ value = def.default;
134
+ } else if (def.required) {
135
+ throw new ScopeCompileError(
136
+ `missing required parameter '${def.name}' for scope ${scopeId}`,
137
+ { scopeId, parameter: def.name }
138
+ );
139
+ } else {
140
+ return void 0;
141
+ }
142
+ }
143
+ switch (def.type) {
144
+ case "Integer": {
145
+ const n = coerceToNumber(value);
146
+ if (n === null || !Number.isInteger(n)) {
147
+ throw new ScopeCompileError(
148
+ `parameter '${def.name}' must be an integer`,
149
+ { scopeId, parameter: def.name }
150
+ );
151
+ }
152
+ if (typeof def.validation === "string") {
153
+ const range = parseRangeValidation(def.validation);
154
+ if (range && (n < range.min || n > range.max)) {
155
+ throw new ScopeCompileError(
156
+ `parameter '${def.name}'=${n} out of range ${def.validation}`,
157
+ { scopeId, parameter: def.name }
158
+ );
159
+ }
160
+ }
161
+ return n;
162
+ }
163
+ case "Decimal": {
164
+ const n = coerceToNumber(value);
165
+ if (n === null) {
166
+ throw new ScopeCompileError(
167
+ `parameter '${def.name}' must be a number`,
168
+ { scopeId, parameter: def.name }
169
+ );
170
+ }
171
+ if (typeof def.validation === "string") {
172
+ const range = parseRangeValidation(def.validation);
173
+ if (range && (n < range.min || n > range.max)) {
174
+ throw new ScopeCompileError(
175
+ `parameter '${def.name}'=${n} out of range ${def.validation}`,
176
+ { scopeId, parameter: def.name }
177
+ );
178
+ }
179
+ }
180
+ return n;
181
+ }
182
+ case "Enum": {
183
+ if (Array.isArray(def.validation) && !def.validation.includes(String(value))) {
184
+ throw new ScopeCompileError(
185
+ `parameter '${def.name}'='${String(value)}' is not one of [${def.validation.join(", ")}]`,
186
+ { scopeId, parameter: def.name }
187
+ );
188
+ }
189
+ return value;
190
+ }
191
+ case "AgentDID": {
192
+ if (typeof value !== "string" || !DID_URI_REGEX.test(value)) {
193
+ throw new ScopeCompileError(
194
+ `parameter '${def.name}' must be a valid DID URI`,
195
+ { scopeId, parameter: def.name }
196
+ );
197
+ }
198
+ return value;
199
+ }
200
+ case "AgentDIDList": {
201
+ if (!Array.isArray(value) || value.length === 0) {
202
+ throw new ScopeCompileError(
203
+ `parameter '${def.name}' must be a non-empty array of DID URIs`,
204
+ { scopeId, parameter: def.name }
205
+ );
206
+ }
207
+ for (const entry of value) {
208
+ if (typeof entry !== "string" || !DID_URI_REGEX.test(entry)) {
209
+ throw new ScopeCompileError(
210
+ `parameter '${def.name}' contains an invalid DID URI: ${String(entry)}`,
211
+ { scopeId, parameter: def.name }
212
+ );
213
+ }
214
+ }
215
+ return value;
216
+ }
217
+ case "ToolIDList":
218
+ case "AttributeList":
219
+ case "EmailList": {
220
+ if (!Array.isArray(value)) {
221
+ throw new ScopeCompileError(
222
+ `parameter '${def.name}' must be an array`,
223
+ { scopeId, parameter: def.name }
224
+ );
225
+ }
226
+ return value;
227
+ }
228
+ case "ProjectID": {
229
+ if (typeof value !== "string" || value.trim() === "") {
230
+ throw new ScopeCompileError(
231
+ `parameter '${def.name}' must be a non-empty string`,
232
+ { scopeId, parameter: def.name }
233
+ );
234
+ }
235
+ return value;
236
+ }
237
+ case "Duration":
238
+ case "Timezone":
239
+ case "IANATimezone": {
240
+ if (typeof value !== "string" || value.trim() === "") {
241
+ throw new ScopeCompileError(
242
+ `parameter '${def.name}' must be a non-empty string`,
243
+ { scopeId, parameter: def.name }
244
+ );
245
+ }
246
+ return value;
247
+ }
248
+ }
249
+ }
250
+ function buildHandlebarsContext(audienceDid, scope, validated) {
251
+ const ctx = {
252
+ audience_did: audienceDid,
253
+ ...validated
254
+ };
255
+ for (const [key, value] of Object.entries(validated)) {
256
+ if (Array.isArray(value)) {
257
+ ctx[`${key}_json`] = JSON.stringify(value);
258
+ ctx[`${key}_display`] = value.map((v) => String(v)).join(", ");
259
+ }
260
+ }
261
+ if (scope.id === "calendar.events.read") {
262
+ ctx.include_private_flag = (validated.include_private ?? scope.parameters.find((p) => p.name === "include_private")?.default) === "yes";
263
+ }
264
+ return ctx;
265
+ }
266
+ function compileScope({
267
+ scope,
268
+ params = {},
269
+ audienceDid
270
+ }) {
271
+ if (!DID_URI_REGEX.test(audienceDid)) {
272
+ throw new ScopeCompileError(`audienceDid '${audienceDid}' is not a valid DID URI`, {
273
+ scopeId: scope.id
274
+ });
275
+ }
276
+ const validated = {};
277
+ for (const def of scope.parameters) {
278
+ validated[def.name] = validateParameter(scope.id, def, params[def.name]);
279
+ }
280
+ const ctx = buildHandlebarsContext(audienceDid, scope, validated);
281
+ const template = Handlebars.compile(scope.cedar_template, { noEscape: true });
282
+ const rendered = template(ctx);
283
+ return normalizeBareEntityTypes(rendered.trim());
284
+ }
285
+ function normalizeBareEntityTypes(cedar) {
286
+ return cedar.replace(
287
+ /(principal|resource)\s*==\s*([A-Z][A-Za-z0-9_]*)(?=\s*[,)\n])/g,
288
+ "$1 is $2"
289
+ );
290
+ }
291
+
292
+ // src/bundle-compiler.ts
293
+ var BundleCompileError = class extends Error {
294
+ scopeId;
295
+ conflict;
296
+ constructor(message, opts) {
297
+ super(message);
298
+ this.name = "BundleCompileError";
299
+ if (opts?.scopeId !== void 0) this.scopeId = opts.scopeId;
300
+ if (opts?.conflict !== void 0) this.conflict = opts.conflict;
301
+ }
302
+ };
303
+ function indexCatalog(catalog) {
304
+ const map = /* @__PURE__ */ new Map();
305
+ for (const scope of catalog) {
306
+ map.set(scope.id, scope);
307
+ }
308
+ return map;
309
+ }
310
+ function expandImplications(seed, catalog) {
311
+ const order = [];
312
+ const visited = /* @__PURE__ */ new Set();
313
+ const impliedBy = /* @__PURE__ */ new Map();
314
+ const queue = seed.map((id) => ({
315
+ id,
316
+ parent: null
317
+ }));
318
+ while (queue.length > 0) {
319
+ const { id, parent } = queue.shift();
320
+ if (visited.has(id)) continue;
321
+ visited.add(id);
322
+ const scope = catalog.get(id);
323
+ if (!scope) {
324
+ throw new BundleCompileError(`unknown scope id '${id}'`, { scopeId: id });
325
+ }
326
+ order.push(id);
327
+ if (parent !== null && !impliedBy.has(id)) impliedBy.set(id, parent);
328
+ for (const implied of scope.implies) {
329
+ if (!visited.has(implied)) {
330
+ queue.push({ id: implied, parent: id });
331
+ }
332
+ }
333
+ }
334
+ return { order, impliedBy };
335
+ }
336
+ function detectConflicts(expanded, catalog) {
337
+ const set = new Set(expanded);
338
+ for (const id of expanded) {
339
+ const scope = catalog.get(id);
340
+ if (!scope) continue;
341
+ for (const conflict of scope.conflicts_with) {
342
+ if (set.has(conflict)) {
343
+ throw new BundleCompileError(
344
+ `scope '${id}' conflicts with '${conflict}' \u2014 cannot coexist in the same bundle`,
345
+ { conflict: [id, conflict] }
346
+ );
347
+ }
348
+ }
349
+ }
350
+ }
351
+ function resolveParamsForScope(scope, paramsMap, impliedBy, idx) {
352
+ const own = { ...paramsMap[scope.id] ?? {} };
353
+ let parentId = impliedBy.get(scope.id);
354
+ while (parentId) {
355
+ const parentParams = paramsMap[parentId];
356
+ if (parentParams) {
357
+ for (const [k, v] of Object.entries(parentParams)) {
358
+ if (own[k] === void 0) own[k] = v;
359
+ }
360
+ }
361
+ const grandparentId = impliedBy.get(parentId);
362
+ parentId = grandparentId && grandparentId !== parentId ? grandparentId : void 0;
363
+ }
364
+ return own;
365
+ }
366
+ function compileBundle({
367
+ scopeIds,
368
+ paramsMap = {},
369
+ audienceDid,
370
+ catalog
371
+ }) {
372
+ const idx = indexCatalog(catalog);
373
+ const { order, impliedBy } = expandImplications(scopeIds, idx);
374
+ detectConflicts(order, idx);
375
+ const policies = [];
376
+ const obligations = [];
377
+ for (const id of order) {
378
+ const scope = idx.get(id);
379
+ if (!scope) continue;
380
+ const params = resolveParamsForScope(scope, paramsMap, impliedBy);
381
+ try {
382
+ policies.push(
383
+ compileScope({
384
+ scope,
385
+ audienceDid,
386
+ params
387
+ })
388
+ );
389
+ } catch (e) {
390
+ if (e instanceof ScopeCompileError) throw e;
391
+ throw new BundleCompileError(
392
+ `failed to compile scope '${id}': ${e.message}`,
393
+ { scopeId: id }
394
+ );
395
+ }
396
+ for (const ob of scope.obligations_forced) {
397
+ obligations.push({ type: ob.type, params: ob.params });
398
+ }
399
+ }
400
+ return { policies, obligations, expandedScopeIds: order };
401
+ }
402
+
403
+ // src/bundles.ts
404
+ var BUNDLES = [
405
+ {
406
+ id: "bundle.project_collaboration.v1",
407
+ version: "1.0.0",
408
+ label: "Project collaboration",
409
+ description: "Collaborate on a project \u2014 read files, task status, and notes; no writes or external sharing.",
410
+ scopes: [
411
+ { id: "files.projects.list" },
412
+ { id: "files.project.metadata.read", params: { project_id: "<user-picks>" } },
413
+ { id: "files.project.files.read", params: { project_id: "<user-picks>", max_size_mb: 25 } },
414
+ { id: "files.project.files.summarize", params: { project_id: "<user-picks>", max_output_words: 2e3 } },
415
+ { id: "tasks.list", params: { project_id: "<user-picks>" } },
416
+ { id: "tasks.read", params: { project_id: "<user-picks>" } },
417
+ { id: "tasks.status.update", params: { project_id: "<user-picks>" } },
418
+ { id: "notes.search", params: { collection_id: "<user-picks>" } },
419
+ { id: "notes.read", params: { collection_id: "<user-picks>" } }
420
+ ]
421
+ },
422
+ {
423
+ id: "bundle.scheduling_assistant.v1",
424
+ version: "1.0.0",
425
+ label: "Scheduling assistant",
426
+ description: "Coordinate meetings on your calendar.",
427
+ scopes: [
428
+ { id: "calendar.availability.read", params: { days_ahead: 14 } },
429
+ {
430
+ id: "calendar.events.propose",
431
+ params: { max_attendees: 10, max_duration_min: 60 }
432
+ },
433
+ { id: "contacts.search", params: { attribute_allowlist: ["name", "email"] } },
434
+ { id: "messaging.relay.to_principal" }
435
+ ]
436
+ },
437
+ {
438
+ id: "bundle.research_agent.v1",
439
+ version: "1.0.0",
440
+ label: "Research agent",
441
+ description: "Pull research without writing.",
442
+ scopes: [
443
+ { id: "files.projects.list" },
444
+ { id: "files.project.files.read", params: { project_id: "<user-picks>", max_size_mb: 25 } },
445
+ { id: "files.project.files.summarize", params: { project_id: "<user-picks>", max_output_words: 2e3 } },
446
+ { id: "notes.search", params: { collection_id: "<user-picks>" } },
447
+ { id: "notes.read", params: { collection_id: "<user-picks>" } },
448
+ { id: "knowledge.query", params: { kb_id: "<user-picks>", max_tokens: 8e3 } },
449
+ { id: "credentials.proof.zk.request", params: { attribute: "verified_human" } }
450
+ ]
451
+ },
452
+ {
453
+ id: "bundle.procurement_agent.v1",
454
+ version: "1.0.0",
455
+ label: "Procurement agent",
456
+ description: "Buy things under tight caps.",
457
+ scopes: [
458
+ { id: "payments.quote.request" },
459
+ {
460
+ id: "payments.authorize.capped",
461
+ params: { max_per_txn_usd: 25, max_per_30d_usd: 200 }
462
+ },
463
+ { id: "payments.history.read", params: { days_back: 90 } },
464
+ { id: "messaging.relay.to_principal" }
465
+ ]
466
+ },
467
+ {
468
+ id: "bundle.executive_assistant.v1",
469
+ version: "1.0.0",
470
+ label: "Executive assistant",
471
+ description: "Broad assistant; step-up on anything external-facing.",
472
+ scopes: [
473
+ { id: "calendar.availability.read", params: { days_ahead: 14 } },
474
+ {
475
+ id: "calendar.events.propose",
476
+ params: { max_attendees: 10, max_duration_min: 60 }
477
+ },
478
+ { id: "calendar.events.modify" },
479
+ { id: "messaging.email.summary" },
480
+ { id: "messaging.email.draft.compose" },
481
+ { id: "messaging.email.send.reviewed", params: { recipient_allowlist: [] } },
482
+ { id: "contacts.search", params: { attribute_allowlist: ["name", "email"] } },
483
+ { id: "tasks.list", params: { project_id: "<user-picks>" } },
484
+ { id: "tasks.read", params: { project_id: "<user-picks>" } },
485
+ { id: "tasks.create", params: { project_id: "<user-picks>", max_per_day: 50 } },
486
+ { id: "tasks.status.update", params: { project_id: "<user-picks>" } },
487
+ { id: "notes.search", params: { collection_id: "<user-picks>" } },
488
+ { id: "notes.read", params: { collection_id: "<user-picks>" } },
489
+ { id: "notes.write", params: { collection_id: "<user-picks>", max_per_day: 100 } },
490
+ { id: "work.status.read" },
491
+ { id: "work.reports.summary", params: { period: "week" } }
492
+ ]
493
+ }
494
+ ];
495
+ function findBundle(id) {
496
+ return BUNDLES.find((b) => b.id === id);
497
+ }
498
+
499
+ export { BUNDLES, BundleCompileError, ScopeCompileError, ScopeLoadError, buildCatalogManifest, canonicalize, compileBundle, compileScope, findBundle, loadScopeFile, loadScopesFromDirectory, sha256Hex };
500
+ //# sourceMappingURL=index.js.map
501
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/loader.ts","../src/catalog-manifest.ts","../src/compiler.ts","../src/bundle-compiler.ts","../src/bundles.ts"],"names":["parseYaml"],"mappings":"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","file":"index.js","sourcesContent":["import { readdirSync, readFileSync, statSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { parse as parseYaml } from 'yaml';\nimport { ScopeTemplateSchema, type ScopeTemplate } from '@kybernesis/arp-spec';\n\nexport class ScopeLoadError extends Error {\n public readonly file?: string;\n public readonly issues?: unknown;\n\n constructor(message: string, opts?: { file?: string; issues?: unknown }) {\n super(message);\n this.name = 'ScopeLoadError';\n if (opts?.file !== undefined) this.file = opts.file;\n if (opts?.issues !== undefined) this.issues = opts.issues;\n }\n}\n\n/**\n * Load a single YAML scope file, validate it against `ScopeTemplateSchema`,\n * and return the parsed value. Throws `ScopeLoadError` on YAML parse errors\n * or schema validation failures.\n */\nexport function loadScopeFile(filePath: string): ScopeTemplate {\n let raw: string;\n try {\n raw = readFileSync(filePath, 'utf8');\n } catch (e) {\n throw new ScopeLoadError(`cannot read ${filePath}: ${(e as Error).message}`, {\n file: filePath,\n });\n }\n\n let parsed: unknown;\n try {\n parsed = parseYaml(raw);\n } catch (e) {\n throw new ScopeLoadError(`invalid YAML in ${filePath}: ${(e as Error).message}`, {\n file: filePath,\n });\n }\n\n const result = ScopeTemplateSchema.safeParse(parsed);\n if (!result.success) {\n throw new ScopeLoadError(`scope ${filePath} failed schema validation`, {\n file: filePath,\n issues: result.error.issues,\n });\n }\n return result.data;\n}\n\n/**\n * Load every `*.yaml` file under `scopesDir`, validate each, and return the\n * sorted-by-id array. Also verifies that every filename matches the scope's\n * `id` field (`<id>.yaml`) — cheap but valuable invariant.\n */\nexport function loadScopesFromDirectory(scopesDir: string): ScopeTemplate[] {\n const st = statSync(scopesDir);\n if (!st.isDirectory()) {\n throw new ScopeLoadError(`${scopesDir} is not a directory`);\n }\n\n const files = readdirSync(scopesDir)\n .filter((f) => f.endsWith('.yaml') || f.endsWith('.yml'))\n .sort();\n\n const seen = new Set<string>();\n const scopes: ScopeTemplate[] = [];\n\n for (const file of files) {\n const full = resolve(scopesDir, file);\n const scope = loadScopeFile(full);\n const expected = `${scope.id}.yaml`;\n if (file !== expected && !(file === `${scope.id}.yml`)) {\n throw new ScopeLoadError(\n `filename ${file} does not match scope id ${scope.id} (expected ${expected})`,\n { file: full }\n );\n }\n if (seen.has(scope.id)) {\n throw new ScopeLoadError(`duplicate scope id ${scope.id}`, { file: full });\n }\n seen.add(scope.id);\n scopes.push(scope);\n }\n\n scopes.sort((a, b) => a.id.localeCompare(b.id));\n return scopes;\n}\n","import { createHash } from 'node:crypto';\nimport {\n ScopeCatalogManifestSchema,\n type ScopeCatalogManifest,\n type ScopeTemplate,\n} from '@kybernesis/arp-spec';\n\n/**\n * Deterministically canonicalize a value for checksum computation.\n *\n * We implement a minimal RFC 8785 JCS subset here (objects sorted by key,\n * arrays in order, primitives as JSON.stringify encodes them) rather than\n * pulling in the `canonicalize` dep — the catalog only needs this inside the\n * build step, and we control the inputs. Phase 2 (which actually signs\n * canonicalized payloads) will import `canonicalize` properly.\n */\nexport function canonicalize(value: unknown): string {\n if (value === null) return 'null';\n if (typeof value === 'number' && !Number.isFinite(value)) {\n throw new Error('canonicalize: non-finite numbers are not allowed');\n }\n if (typeof value !== 'object') {\n return JSON.stringify(value);\n }\n if (Array.isArray(value)) {\n return `[${value.map(canonicalize).join(',')}]`;\n }\n const obj = value as Record<string, unknown>;\n const keys = Object.keys(obj).sort();\n const parts = keys.map((k) => `${JSON.stringify(k)}:${canonicalize(obj[k])}`);\n return `{${parts.join(',')}}`;\n}\n\nexport function sha256Hex(input: string): string {\n return createHash('sha256').update(input, 'utf8').digest('hex');\n}\n\nexport interface BuildManifestOptions {\n /** Catalog version label, default \"v1\". */\n version?: string;\n /**\n * `updated_at` timestamp. When computing deterministic checksums, pass a\n * fixed ISO string. Defaults to the current time.\n */\n updatedAt?: string;\n}\n\n/**\n * Build a `ScopeCatalogManifest` from a list of scope templates. The checksum\n * covers the sorted scopes array (not the top-level metadata) so it is\n * stable across re-runs with different `updated_at` values but identical\n * scope content.\n */\nexport function buildCatalogManifest(\n scopes: readonly ScopeTemplate[],\n options: BuildManifestOptions = {}\n): ScopeCatalogManifest {\n const sorted = [...scopes].sort((a, b) => a.id.localeCompare(b.id));\n const canonical = canonicalize(sorted);\n const checksum = `sha256:${sha256Hex(canonical)}`;\n\n const manifest = {\n version: options.version ?? 'v1',\n updated_at: options.updatedAt ?? new Date().toISOString(),\n scope_count: sorted.length,\n checksum,\n scopes: sorted,\n };\n\n const parsed = ScopeCatalogManifestSchema.parse(manifest);\n return parsed;\n}\n","import Handlebars from 'handlebars';\nimport { DID_URI_REGEX, type ScopeTemplate, type ScopeParameter } from '@kybernesis/arp-spec';\n\nexport class ScopeCompileError extends Error {\n public readonly scopeId?: string;\n public readonly parameter?: string;\n\n constructor(message: string, opts?: { scopeId?: string; parameter?: string }) {\n super(message);\n this.name = 'ScopeCompileError';\n if (opts?.scopeId !== undefined) this.scopeId = opts.scopeId;\n if (opts?.parameter !== undefined) this.parameter = opts.parameter;\n }\n}\n\nfunction parseRangeValidation(\n validation: string\n): { min: number; max: number } | null {\n const match = /^(-?\\d+(?:\\.\\d+)?)\\.\\.(-?\\d+(?:\\.\\d+)?)$/.exec(validation);\n if (!match) return null;\n return { min: Number(match[1]), max: Number(match[2]) };\n}\n\nfunction coerceToNumber(value: unknown): number | null {\n if (typeof value === 'number' && Number.isFinite(value)) return value;\n if (typeof value === 'string' && value.trim() !== '') {\n const n = Number(value);\n if (Number.isFinite(n)) return n;\n }\n return null;\n}\n\nfunction validateParameter(\n scopeId: string,\n def: ScopeParameter,\n initial: unknown\n): unknown {\n let value = initial;\n const present = value !== undefined && value !== null;\n if (!present) {\n if (def.default !== undefined) {\n // Required + default is a valid combo in the catalog — \"required\" here\n // means the compiler must end up with a value. If the caller omits,\n // fall through to type-validate the default the same way we'd validate\n // a caller-supplied value.\n value = def.default;\n } else if (def.required) {\n throw new ScopeCompileError(\n `missing required parameter '${def.name}' for scope ${scopeId}`,\n { scopeId, parameter: def.name }\n );\n } else {\n return undefined;\n }\n }\n\n switch (def.type) {\n case 'Integer': {\n const n = coerceToNumber(value);\n if (n === null || !Number.isInteger(n)) {\n throw new ScopeCompileError(\n `parameter '${def.name}' must be an integer`,\n { scopeId, parameter: def.name }\n );\n }\n if (typeof def.validation === 'string') {\n const range = parseRangeValidation(def.validation);\n if (range && (n < range.min || n > range.max)) {\n throw new ScopeCompileError(\n `parameter '${def.name}'=${n} out of range ${def.validation}`,\n { scopeId, parameter: def.name }\n );\n }\n }\n return n;\n }\n case 'Decimal': {\n const n = coerceToNumber(value);\n if (n === null) {\n throw new ScopeCompileError(\n `parameter '${def.name}' must be a number`,\n { scopeId, parameter: def.name }\n );\n }\n if (typeof def.validation === 'string') {\n const range = parseRangeValidation(def.validation);\n if (range && (n < range.min || n > range.max)) {\n throw new ScopeCompileError(\n `parameter '${def.name}'=${n} out of range ${def.validation}`,\n { scopeId, parameter: def.name }\n );\n }\n }\n return n;\n }\n case 'Enum': {\n if (Array.isArray(def.validation) && !def.validation.includes(String(value))) {\n throw new ScopeCompileError(\n `parameter '${def.name}'='${String(value)}' is not one of [${def.validation.join(', ')}]`,\n { scopeId, parameter: def.name }\n );\n }\n return value;\n }\n case 'AgentDID': {\n if (typeof value !== 'string' || !DID_URI_REGEX.test(value)) {\n throw new ScopeCompileError(\n `parameter '${def.name}' must be a valid DID URI`,\n { scopeId, parameter: def.name }\n );\n }\n return value;\n }\n case 'AgentDIDList': {\n if (!Array.isArray(value) || value.length === 0) {\n throw new ScopeCompileError(\n `parameter '${def.name}' must be a non-empty array of DID URIs`,\n { scopeId, parameter: def.name }\n );\n }\n for (const entry of value) {\n if (typeof entry !== 'string' || !DID_URI_REGEX.test(entry)) {\n throw new ScopeCompileError(\n `parameter '${def.name}' contains an invalid DID URI: ${String(entry)}`,\n { scopeId, parameter: def.name }\n );\n }\n }\n return value;\n }\n case 'ToolIDList':\n case 'AttributeList':\n case 'EmailList': {\n if (!Array.isArray(value)) {\n throw new ScopeCompileError(\n `parameter '${def.name}' must be an array`,\n { scopeId, parameter: def.name }\n );\n }\n return value;\n }\n case 'ProjectID': {\n if (typeof value !== 'string' || value.trim() === '') {\n throw new ScopeCompileError(\n `parameter '${def.name}' must be a non-empty string`,\n { scopeId, parameter: def.name }\n );\n }\n return value;\n }\n case 'Duration':\n case 'Timezone':\n case 'IANATimezone': {\n if (typeof value !== 'string' || value.trim() === '') {\n throw new ScopeCompileError(\n `parameter '${def.name}' must be a non-empty string`,\n { scopeId, parameter: def.name }\n );\n }\n return value;\n }\n }\n}\n\n/**\n * Build the Handlebars context for a scope template. Derives list-shaped\n * helpers (`<name>_json`, `<name>_display`, and flag-style `<name>_flag` for\n * enum parameters) so Cedar templates stay declarative.\n */\nfunction buildHandlebarsContext(\n audienceDid: string,\n scope: ScopeTemplate,\n validated: Record<string, unknown>\n): Record<string, unknown> {\n const ctx: Record<string, unknown> = {\n audience_did: audienceDid,\n ...validated,\n };\n\n for (const [key, value] of Object.entries(validated)) {\n if (Array.isArray(value)) {\n ctx[`${key}_json`] = JSON.stringify(value);\n ctx[`${key}_display`] = value.map((v) => String(v)).join(', ');\n }\n }\n\n // Per-scope helpers. Keeping the catalog's consent_text_template compile\n // path decoupled from the Cedar path would duplicate this for both — we\n // share the same context for both.\n if (scope.id === 'calendar.events.read') {\n ctx.include_private_flag =\n (validated.include_private ?? scope.parameters.find((p) => p.name === 'include_private')?.default) ===\n 'yes';\n }\n\n return ctx;\n}\n\nexport interface CompileScopeOptions {\n scope: ScopeTemplate;\n params?: Record<string, unknown>;\n audienceDid: string;\n}\n\n/**\n * Compile a scope template + parameters + audience DID into a Cedar policy\n * string.\n *\n * - Validates parameters against the scope's declared types + validation\n * rules (ranges, enum values, DID shape). Throws `ScopeCompileError` on\n * any mismatch.\n * - Uses Handlebars under the hood; `{{audience_did}}` is always in scope,\n * plus any validated parameters and the derived `<name>_json` /\n * `<name>_display` helpers.\n */\nexport function compileScope({\n scope,\n params = {},\n audienceDid,\n}: CompileScopeOptions): string {\n if (!DID_URI_REGEX.test(audienceDid)) {\n throw new ScopeCompileError(`audienceDid '${audienceDid}' is not a valid DID URI`, {\n scopeId: scope.id,\n });\n }\n\n const validated: Record<string, unknown> = {};\n for (const def of scope.parameters) {\n validated[def.name] = validateParameter(scope.id, def, params[def.name]);\n }\n\n const ctx = buildHandlebarsContext(audienceDid, scope, validated);\n\n const template = Handlebars.compile(scope.cedar_template, { noEscape: true });\n const rendered = template(ctx);\n return normalizeBareEntityTypes(rendered.trim());\n}\n\n/**\n * Post-process the Handlebars output to produce valid Cedar.\n *\n * Several scope templates in ARP-scope-catalog-v1.md §5 use the shorthand\n * `resource == Tool` (and similar bare-type forms) to mean \"any entity of\n * type Tool\". Cedar's parser requires an entity UID on the right-hand side\n * of `==`, not a bare type name — the idiomatic form is `resource is Tool`.\n *\n * We rewrite `<scope> == <TypeName>` → `<scope> is <TypeName>` whenever the\n * right-hand side is a bare UpperCamelCase identifier (no `::\"...\"` UID and\n * no lower-case head, which would indicate a variable or attribute access).\n *\n * Keeps the YAML sources faithful to the spec doc while guaranteeing the\n * compiled output parses with @cedar-policy/cedar-wasm.\n */\nfunction normalizeBareEntityTypes(cedar: string): string {\n return cedar.replace(\n /(principal|resource)\\s*==\\s*([A-Z][A-Za-z0-9_]*)(?=\\s*[,)\\n])/g,\n '$1 is $2'\n );\n}\n","import type { ScopeTemplate, Obligation } from '@kybernesis/arp-spec';\nimport { compileScope, ScopeCompileError } from './compiler.js';\n\nexport interface CompileBundleInput {\n scopeIds: readonly string[];\n paramsMap?: Record<string, Record<string, unknown>>;\n audienceDid: string;\n /** Lookup table from scope id → template. Usually the loader's output. */\n catalog: readonly ScopeTemplate[];\n}\n\nexport interface CompiledBundle {\n policies: string[];\n obligations: Obligation[];\n /** Fully-expanded scope IDs (original + implied, deduped and topologically sorted). */\n expandedScopeIds: string[];\n}\n\nexport class BundleCompileError extends Error {\n public readonly scopeId?: string;\n public readonly conflict?: [string, string];\n\n constructor(message: string, opts?: { scopeId?: string; conflict?: [string, string] }) {\n super(message);\n this.name = 'BundleCompileError';\n if (opts?.scopeId !== undefined) this.scopeId = opts.scopeId;\n if (opts?.conflict !== undefined) this.conflict = opts.conflict;\n }\n}\n\nfunction indexCatalog(catalog: readonly ScopeTemplate[]): Map<string, ScopeTemplate> {\n const map = new Map<string, ScopeTemplate>();\n for (const scope of catalog) {\n map.set(scope.id, scope);\n }\n return map;\n}\n\ninterface ExpansionResult {\n order: string[];\n /** For each implied scope, the id of the scope that pulled it in. */\n impliedBy: Map<string, string>;\n}\n\n/**\n * Transitively expand `implies` relations starting from `seed`.\n * Returns a stable-ordered array: requested scopes first (in their original\n * order), then any implied scopes added by the expansion (in discovery\n * order). Also records the parent that pulled each implied scope in, so\n * callers can inherit parameter values along the implication edge.\n * Guards against cycles.\n */\nfunction expandImplications(\n seed: readonly string[],\n catalog: Map<string, ScopeTemplate>\n): ExpansionResult {\n const order: string[] = [];\n const visited = new Set<string>();\n const impliedBy = new Map<string, string>();\n const queue: Array<{ id: string; parent: string | null }> = seed.map((id) => ({\n id,\n parent: null,\n }));\n\n while (queue.length > 0) {\n const { id, parent } = queue.shift() as { id: string; parent: string | null };\n if (visited.has(id)) continue;\n visited.add(id);\n const scope = catalog.get(id);\n if (!scope) {\n throw new BundleCompileError(`unknown scope id '${id}'`, { scopeId: id });\n }\n order.push(id);\n if (parent !== null && !impliedBy.has(id)) impliedBy.set(id, parent);\n for (const implied of scope.implies) {\n if (!visited.has(implied)) {\n queue.push({ id: implied, parent: id });\n }\n }\n }\n\n return { order, impliedBy };\n}\n\nfunction detectConflicts(\n expanded: readonly string[],\n catalog: Map<string, ScopeTemplate>\n): void {\n const set = new Set(expanded);\n for (const id of expanded) {\n const scope = catalog.get(id);\n // Existence already checked in expandImplications.\n if (!scope) continue;\n for (const conflict of scope.conflicts_with) {\n if (set.has(conflict)) {\n throw new BundleCompileError(\n `scope '${id}' conflicts with '${conflict}' — cannot coexist in the same bundle`,\n { conflict: [id, conflict] }\n );\n }\n }\n }\n}\n\n/**\n * Resolve the parameter map for `scopeId`. Starts from any explicit entry in\n * `paramsMap`, then — if the scope was pulled in via implication — walks up\n * the chain and fills in any missing required parameters that the parent\n * scope also declares (e.g., `project_id` propagates from\n * `files.project.files.read` down to its implied `.list` / `.metadata.read`).\n */\nfunction resolveParamsForScope(\n scope: ScopeTemplate,\n paramsMap: Record<string, Record<string, unknown>>,\n impliedBy: Map<string, string>,\n idx: Map<string, ScopeTemplate>\n): Record<string, unknown> {\n const own = { ...(paramsMap[scope.id] ?? {}) };\n let parentId = impliedBy.get(scope.id);\n while (parentId) {\n const parentParams = paramsMap[parentId];\n if (parentParams) {\n for (const [k, v] of Object.entries(parentParams)) {\n if (own[k] === undefined) own[k] = v;\n }\n }\n // follow any further implication chain (e.g., A→B→C)\n const grandparentId = impliedBy.get(parentId);\n parentId = grandparentId && grandparentId !== parentId ? grandparentId : undefined;\n }\n // nothing more to do — missing required-with-default params are handled by\n // the per-scope compiler using catalog defaults.\n void idx; // reserved for richer inheritance in the future\n return own;\n}\n\n/**\n * Compile a bundle of scopes into a Cedar policy string list + aggregated\n * obligations.\n *\n * Semantics:\n * 1. Expand `implies` transitively (user-requested ids first, implied\n * later). Each implied scope remembers which scope pulled it in.\n * 2. Check `conflicts_with` across the expanded set; throw if any pair\n * conflicts.\n * 3. Compile each scope using `compileScope`. Implied scopes inherit any\n * required parameters (`project_id`, `collection_id`, …) from the\n * scope that implied them if the caller didn't provide their own\n * `paramsMap` entry.\n * 4. Concatenate `obligations_forced` from every expanded scope into the\n * bundle's obligations array.\n */\nexport function compileBundle({\n scopeIds,\n paramsMap = {},\n audienceDid,\n catalog,\n}: CompileBundleInput): CompiledBundle {\n const idx = indexCatalog(catalog);\n const { order, impliedBy } = expandImplications(scopeIds, idx);\n detectConflicts(order, idx);\n\n const policies: string[] = [];\n const obligations: Obligation[] = [];\n\n for (const id of order) {\n const scope = idx.get(id);\n if (!scope) continue;\n const params = resolveParamsForScope(scope, paramsMap, impliedBy, idx);\n try {\n policies.push(\n compileScope({\n scope,\n audienceDid,\n params,\n })\n );\n } catch (e) {\n if (e instanceof ScopeCompileError) throw e;\n throw new BundleCompileError(\n `failed to compile scope '${id}': ${(e as Error).message}`,\n { scopeId: id }\n );\n }\n for (const ob of scope.obligations_forced) {\n obligations.push({ type: ob.type, params: ob.params });\n }\n }\n\n return { policies, obligations, expandedScopeIds: order };\n}\n","/**\n * Named multi-scope bundles offered as one-tap presets in the consent UI.\n *\n * Source: ARP-scope-catalog-v1.md §6.\n *\n * `params` values marked `null` are user-picked (the UI prompts at\n * bundle-activation time). Values marked with a concrete number/string are\n * presets baked into the bundle.\n */\nexport interface BundleDefinition {\n id: string;\n version: string;\n label: string;\n description: string;\n /**\n * Ordered list of scopes. Each has an optional `params` object; values\n * that are `'<user-picks>'` (string) indicate user-supplied inputs at\n * activation time (the UI collects them).\n */\n scopes: Array<{\n id: string;\n params?: Record<string, unknown>;\n }>;\n}\n\nexport const BUNDLES: readonly BundleDefinition[] = [\n {\n id: 'bundle.project_collaboration.v1',\n version: '1.0.0',\n label: 'Project collaboration',\n description:\n 'Collaborate on a project — read files, task status, and notes; no writes or external sharing.',\n scopes: [\n { id: 'files.projects.list' },\n { id: 'files.project.metadata.read', params: { project_id: '<user-picks>' } },\n { id: 'files.project.files.read', params: { project_id: '<user-picks>', max_size_mb: 25 } },\n { id: 'files.project.files.summarize', params: { project_id: '<user-picks>', max_output_words: 2000 } },\n { id: 'tasks.list', params: { project_id: '<user-picks>' } },\n { id: 'tasks.read', params: { project_id: '<user-picks>' } },\n { id: 'tasks.status.update', params: { project_id: '<user-picks>' } },\n { id: 'notes.search', params: { collection_id: '<user-picks>' } },\n { id: 'notes.read', params: { collection_id: '<user-picks>' } },\n ],\n },\n {\n id: 'bundle.scheduling_assistant.v1',\n version: '1.0.0',\n label: 'Scheduling assistant',\n description: 'Coordinate meetings on your calendar.',\n scopes: [\n { id: 'calendar.availability.read', params: { days_ahead: 14 } },\n {\n id: 'calendar.events.propose',\n params: { max_attendees: 10, max_duration_min: 60 },\n },\n { id: 'contacts.search', params: { attribute_allowlist: ['name', 'email'] } },\n { id: 'messaging.relay.to_principal' },\n ],\n },\n {\n id: 'bundle.research_agent.v1',\n version: '1.0.0',\n label: 'Research agent',\n description: 'Pull research without writing.',\n scopes: [\n { id: 'files.projects.list' },\n { id: 'files.project.files.read', params: { project_id: '<user-picks>', max_size_mb: 25 } },\n { id: 'files.project.files.summarize', params: { project_id: '<user-picks>', max_output_words: 2000 } },\n { id: 'notes.search', params: { collection_id: '<user-picks>' } },\n { id: 'notes.read', params: { collection_id: '<user-picks>' } },\n { id: 'knowledge.query', params: { kb_id: '<user-picks>', max_tokens: 8000 } },\n { id: 'credentials.proof.zk.request', params: { attribute: 'verified_human' } },\n ],\n },\n {\n id: 'bundle.procurement_agent.v1',\n version: '1.0.0',\n label: 'Procurement agent',\n description: 'Buy things under tight caps.',\n scopes: [\n { id: 'payments.quote.request' },\n {\n id: 'payments.authorize.capped',\n params: { max_per_txn_usd: 25, max_per_30d_usd: 200 },\n },\n { id: 'payments.history.read', params: { days_back: 90 } },\n { id: 'messaging.relay.to_principal' },\n ],\n },\n {\n id: 'bundle.executive_assistant.v1',\n version: '1.0.0',\n label: 'Executive assistant',\n description: 'Broad assistant; step-up on anything external-facing.',\n scopes: [\n { id: 'calendar.availability.read', params: { days_ahead: 14 } },\n {\n id: 'calendar.events.propose',\n params: { max_attendees: 10, max_duration_min: 60 },\n },\n { id: 'calendar.events.modify' },\n { id: 'messaging.email.summary' },\n { id: 'messaging.email.draft.compose' },\n { id: 'messaging.email.send.reviewed', params: { recipient_allowlist: [] } },\n { id: 'contacts.search', params: { attribute_allowlist: ['name', 'email'] } },\n { id: 'tasks.list', params: { project_id: '<user-picks>' } },\n { id: 'tasks.read', params: { project_id: '<user-picks>' } },\n { id: 'tasks.create', params: { project_id: '<user-picks>', max_per_day: 50 } },\n { id: 'tasks.status.update', params: { project_id: '<user-picks>' } },\n { id: 'notes.search', params: { collection_id: '<user-picks>' } },\n { id: 'notes.read', params: { collection_id: '<user-picks>' } },\n { id: 'notes.write', params: { collection_id: '<user-picks>', max_per_day: 100 } },\n { id: 'work.status.read' },\n { id: 'work.reports.summary', params: { period: 'week' } },\n ],\n },\n] as const;\n\nexport function findBundle(id: string): BundleDefinition | undefined {\n return BUNDLES.find((b) => b.id === id);\n}\n"]}