@openhi/constructs 0.0.104 → 0.0.106

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 (83) hide show
  1. package/README.md +14 -0
  2. package/lib/chunk-2PM2NGXI.mjs +31 -0
  3. package/lib/chunk-2PM2NGXI.mjs.map +1 -0
  4. package/lib/chunk-AGF3RAAZ.mjs +20 -0
  5. package/lib/chunk-AGF3RAAZ.mjs.map +1 -0
  6. package/lib/chunk-AO3E22CS.mjs +108 -0
  7. package/lib/chunk-AO3E22CS.mjs.map +1 -0
  8. package/lib/chunk-CHPEQRXU.mjs +45 -0
  9. package/lib/chunk-CHPEQRXU.mjs.map +1 -0
  10. package/lib/chunk-JUNL76HF.mjs +428 -0
  11. package/lib/chunk-JUNL76HF.mjs.map +1 -0
  12. package/lib/chunk-L6UAP4KP.mjs +27 -0
  13. package/lib/chunk-L6UAP4KP.mjs.map +1 -0
  14. package/lib/{chunk-3QS3WKRC.mjs → chunk-LZOMFHX3.mjs} +9 -2
  15. package/lib/chunk-QMIOLLAS.mjs +531 -0
  16. package/lib/chunk-QMIOLLAS.mjs.map +1 -0
  17. package/lib/chunk-SYBADQXI.mjs +607 -0
  18. package/lib/chunk-SYBADQXI.mjs.map +1 -0
  19. package/lib/chunk-VXX4I3EF.mjs +19 -0
  20. package/lib/chunk-VXX4I3EF.mjs.map +1 -0
  21. package/lib/{chunk-MLTYFMSE.mjs → chunk-VYDIGFIX.mjs} +74 -29
  22. package/lib/chunk-VYDIGFIX.mjs.map +1 -0
  23. package/lib/chunk-YU2HRNUP.mjs +33 -0
  24. package/lib/chunk-YU2HRNUP.mjs.map +1 -0
  25. package/lib/chunk-YZZDUJHI.mjs +37 -0
  26. package/lib/chunk-YZZDUJHI.mjs.map +1 -0
  27. package/lib/cors-options-lambda.handler.mjs +1 -1
  28. package/lib/data-store-postgres-replication.handler.mjs +1 -1
  29. package/lib/events-BfrkMoBD.d.mts +44 -0
  30. package/lib/events-BfrkMoBD.d.ts +44 -0
  31. package/lib/events-CVA3_eEB.d.mts +23 -0
  32. package/lib/events-CVA3_eEB.d.ts +23 -0
  33. package/lib/events-DGep6C7w.d.mts +207 -0
  34. package/lib/events-DGep6C7w.d.ts +207 -0
  35. package/lib/firehose-archive-transform.handler.mjs +1 -1
  36. package/lib/index.d.mts +508 -29
  37. package/lib/index.d.ts +773 -30
  38. package/lib/index.js +2536 -105
  39. package/lib/index.js.map +1 -1
  40. package/lib/index.mjs +899 -106
  41. package/lib/index.mjs.map +1 -1
  42. package/lib/openhi-context-CaBH8SFo.d.mts +39 -0
  43. package/lib/openhi-context-CaBH8SFo.d.ts +39 -0
  44. package/lib/platform-deploy-bridge.handler.d.mts +14 -0
  45. package/lib/platform-deploy-bridge.handler.d.ts +14 -0
  46. package/lib/platform-deploy-bridge.handler.js +762 -0
  47. package/lib/platform-deploy-bridge.handler.js.map +1 -0
  48. package/lib/platform-deploy-bridge.handler.mjs +134 -0
  49. package/lib/platform-deploy-bridge.handler.mjs.map +1 -0
  50. package/lib/post-authentication.handler.mjs +1 -1
  51. package/lib/post-confirmation.handler.js +50 -904
  52. package/lib/post-confirmation.handler.js.map +1 -1
  53. package/lib/post-confirmation.handler.mjs +37 -112
  54. package/lib/post-confirmation.handler.mjs.map +1 -1
  55. package/lib/pre-token-generation.handler.js +135 -55
  56. package/lib/pre-token-generation.handler.js.map +1 -1
  57. package/lib/pre-token-generation.handler.mjs +25 -32
  58. package/lib/pre-token-generation.handler.mjs.map +1 -1
  59. package/lib/provision-default-workspace.handler.d.mts +13 -0
  60. package/lib/provision-default-workspace.handler.d.ts +13 -0
  61. package/lib/provision-default-workspace.handler.js +1172 -0
  62. package/lib/provision-default-workspace.handler.js.map +1 -0
  63. package/lib/provision-default-workspace.handler.mjs +175 -0
  64. package/lib/provision-default-workspace.handler.mjs.map +1 -0
  65. package/lib/rest-api-lambda.handler.js +114 -59
  66. package/lib/rest-api-lambda.handler.js.map +1 -1
  67. package/lib/rest-api-lambda.handler.mjs +60 -587
  68. package/lib/rest-api-lambda.handler.mjs.map +1 -1
  69. package/lib/seed-demo-data.handler.d.mts +107 -0
  70. package/lib/seed-demo-data.handler.d.ts +107 -0
  71. package/lib/seed-demo-data.handler.js +2037 -0
  72. package/lib/seed-demo-data.handler.js.map +1 -0
  73. package/lib/seed-demo-data.handler.mjs +23 -0
  74. package/lib/seed-demo-data.handler.mjs.map +1 -0
  75. package/lib/seed-system-data.handler.d.mts +64 -0
  76. package/lib/seed-system-data.handler.d.ts +64 -0
  77. package/lib/seed-system-data.handler.js +1631 -0
  78. package/lib/seed-system-data.handler.js.map +1 -0
  79. package/lib/seed-system-data.handler.mjs +135 -0
  80. package/lib/seed-system-data.handler.mjs.map +1 -0
  81. package/package.json +4 -2
  82. package/lib/chunk-MLTYFMSE.mjs.map +0 -1
  83. /package/lib/{chunk-3QS3WKRC.mjs.map → chunk-LZOMFHX3.mjs.map} +0 -0
@@ -0,0 +1,1172 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/workflows/control-plane/user-onboarding/provision-default-workspace.handler.ts
21
+ var provision_default_workspace_handler_exports = {};
22
+ __export(provision_default_workspace_handler_exports, {
23
+ handler: () => handler
24
+ });
25
+ module.exports = __toCommonJS(provision_default_workspace_handler_exports);
26
+ var import_node_crypto = require("crypto");
27
+ var import_types9 = require("@openhi/types");
28
+
29
+ // src/data/dynamo/dynamo-control-service.ts
30
+ var import_electrodb8 = require("electrodb");
31
+
32
+ // src/data/dynamo/dynamo-client.ts
33
+ var import_client_dynamodb = require("@aws-sdk/client-dynamodb");
34
+ var defaultTableName = process.env.DYNAMO_TABLE_NAME ?? "jesttesttable";
35
+ var dynamoClient = new import_client_dynamodb.DynamoDBClient({
36
+ ...process.env.MOCK_DYNAMODB_ENDPOINT && {
37
+ endpoint: process.env.MOCK_DYNAMODB_ENDPOINT,
38
+ sslEnabled: false,
39
+ region: "local"
40
+ }
41
+ });
42
+
43
+ // src/data/dynamo/entities/control/configuration-entity.ts
44
+ var import_electrodb = require("electrodb");
45
+
46
+ // src/data/dynamo/entities/control/control-entity-common.ts
47
+ var import_types = require("@openhi/types");
48
+
49
+ // src/data/dynamo/shard.ts
50
+ var SHARD_COUNT = 4;
51
+ function computeShard(id) {
52
+ let hash = 2166136261;
53
+ for (let i = 0; i < id.length; i++) {
54
+ hash ^= id.charCodeAt(i);
55
+ hash = Math.imul(hash, 16777619);
56
+ }
57
+ return (hash >>> 0) % SHARD_COUNT;
58
+ }
59
+
60
+ // src/data/dynamo/entities/control/control-entity-common.ts
61
+ var gsi1ShardAttribute = {
62
+ type: "string",
63
+ watch: ["id"],
64
+ set: (_val, item) => {
65
+ if (typeof item?.id !== "string" || item.id.length === 0) {
66
+ return void 0;
67
+ }
68
+ return String(computeShard(item.id));
69
+ }
70
+ };
71
+ var gsi1skAttribute = {
72
+ type: "string",
73
+ watch: ["resource", "lastUpdated", "id"],
74
+ set: (_val, item) => {
75
+ const id = typeof item?.id === "string" ? item.id : "";
76
+ const lastUpdated = typeof item?.lastUpdated === "string" ? item.lastUpdated : "";
77
+ const fallback = `${lastUpdated}#${id}`;
78
+ if (typeof item?.resource !== "string" || item.resource.length === 0) {
79
+ return fallback;
80
+ }
81
+ let parsed;
82
+ try {
83
+ parsed = JSON.parse(item.resource);
84
+ } catch {
85
+ return fallback;
86
+ }
87
+ if (!parsed || typeof parsed !== "object") return fallback;
88
+ const resourceType = parsed.resourceType;
89
+ if (typeof resourceType !== "string") return fallback;
90
+ const label = (0, import_types.extractLabel)(parsed);
91
+ return label !== void 0 ? `${label}#${id}` : fallback;
92
+ }
93
+ };
94
+
95
+ // src/data/dynamo/entities/control/configuration-entity.ts
96
+ var ConfigurationEntity = new import_electrodb.Entity({
97
+ model: {
98
+ entity: "configuration",
99
+ service: "control",
100
+ version: "01"
101
+ },
102
+ attributes: {
103
+ /** Sort key. "CURRENT" for current version; version history in S3. */
104
+ sk: {
105
+ type: "string",
106
+ required: true,
107
+ default: "CURRENT"
108
+ },
109
+ /** Tenant scope. Use "BASELINE" when the config is baseline default (no tenant). */
110
+ tenantId: {
111
+ type: "string",
112
+ required: true,
113
+ default: "BASELINE"
114
+ },
115
+ /** Workspace scope. Use "-" when absent. */
116
+ workspaceId: {
117
+ type: "string",
118
+ required: true,
119
+ default: "-"
120
+ },
121
+ /** User scope. Use "-" when absent. */
122
+ userId: {
123
+ type: "string",
124
+ required: true,
125
+ default: "-"
126
+ },
127
+ /** Role scope. Use "-" when absent. */
128
+ roleId: {
129
+ type: "string",
130
+ required: true,
131
+ default: "-"
132
+ },
133
+ /** Config type (category), e.g. endpoints, branding, display. */
134
+ key: {
135
+ type: "string",
136
+ required: true
137
+ },
138
+ /** FHIR Resource.id; logical id in URL and for the Configuration resource. */
139
+ id: {
140
+ type: "string",
141
+ required: true
142
+ },
143
+ /** Payload as JSON string. JSON.stringify(resource) on write; JSON.parse(item.resource) on read. */
144
+ resource: {
145
+ type: "string",
146
+ required: true
147
+ },
148
+ /**
149
+ * Summary projection (key display fields as JSON string: id, key, status).
150
+ * Populated on every write via extractSummary(resource); GSI1 INCLUDE surfaces it on lists.
151
+ */
152
+ summary: {
153
+ type: "string",
154
+ required: true
155
+ },
156
+ /** Version id (e.g. ULID). Tracks current version; S3 history key. */
157
+ vid: {
158
+ type: "string",
159
+ required: true
160
+ },
161
+ lastUpdated: {
162
+ type: "string",
163
+ required: true
164
+ },
165
+ gsi1Shard: gsi1ShardAttribute,
166
+ deleted: {
167
+ type: "boolean",
168
+ required: false
169
+ },
170
+ bundleId: {
171
+ type: "string",
172
+ required: false
173
+ },
174
+ msgId: {
175
+ type: "string",
176
+ required: false
177
+ }
178
+ },
179
+ indexes: {
180
+ /** Base table: PK, SK (data store key names). PK is built from tenantId, workspaceId, userId, roleId; SK is built from key and sk. Do not supply PK or SK from outside. */
181
+ record: {
182
+ pk: {
183
+ field: "PK",
184
+ composite: ["tenantId", "workspaceId", "userId", "roleId"],
185
+ template: "CONFIG#TID#${tenantId}#WID#${workspaceId}#UID#${userId}#RID#${roleId}"
186
+ },
187
+ sk: {
188
+ field: "SK",
189
+ composite: ["key", "sk"],
190
+ template: "KEY#${key}#SK#${sk}"
191
+ }
192
+ },
193
+ /**
194
+ * GSI1 — Unified Sharded List per ADR-011: list all Configuration entries for a
195
+ * (tenant, workspace) across the four shards. Use for "list configs scoped to this tenant"
196
+ * (workspaceId = "-") or "list configs scoped to this workspace". Does not support
197
+ * hierarchical resolution in one query; use base table GetItem in fallback order
198
+ * (user → workspace → tenant → baseline) for that.
199
+ * SK is `<key>#<id>` — Configuration's `key` is a required entity attribute (the
200
+ * config category: endpoints, branding, display, …) and the natural sort/lookup
201
+ * dimension. `casing: "none"` preserves the literal key value.
202
+ */
203
+ gsi1: {
204
+ index: "GSI1",
205
+ pk: {
206
+ field: "GSI1PK",
207
+ composite: ["tenantId", "workspaceId", "gsi1Shard"],
208
+ template: "TID#${tenantId}#WID#${workspaceId}#RT#Configuration#SHARD#${gsi1Shard}"
209
+ },
210
+ sk: {
211
+ field: "GSI1SK",
212
+ casing: "none",
213
+ composite: ["key", "id"],
214
+ template: "${key}#${id}"
215
+ }
216
+ }
217
+ }
218
+ });
219
+
220
+ // src/data/dynamo/entities/control/membership-entity.ts
221
+ var import_electrodb2 = require("electrodb");
222
+ var MembershipEntity = new import_electrodb2.Entity({
223
+ model: {
224
+ entity: "membership",
225
+ service: "control",
226
+ version: "01"
227
+ },
228
+ attributes: {
229
+ /** Sort key sentinel. Always "CURRENT". */
230
+ sk: {
231
+ type: "string",
232
+ required: true,
233
+ default: "CURRENT"
234
+ },
235
+ /** Tenant in which the user has membership (required). */
236
+ tenantId: {
237
+ type: "string",
238
+ required: true
239
+ },
240
+ /** FHIR Resource.id; membership id. */
241
+ id: {
242
+ type: "string",
243
+ required: true
244
+ },
245
+ /** Full Membership resource serialized as JSON string. */
246
+ resource: {
247
+ type: "string",
248
+ required: true
249
+ },
250
+ /**
251
+ * Summary projection (key display fields as JSON string: id, displayName, status).
252
+ * Populated on every write via extractSummary(resource); GSI1 INCLUDE surfaces it on lists.
253
+ */
254
+ summary: {
255
+ type: "string",
256
+ required: true
257
+ },
258
+ /** Version id (e.g. ULID). */
259
+ vid: {
260
+ type: "string",
261
+ required: true
262
+ },
263
+ lastUpdated: {
264
+ type: "string",
265
+ required: true
266
+ },
267
+ gsi1Shard: gsi1ShardAttribute,
268
+ /** Derived GSI1 sort key — name-based when extractable; else `<lastUpdated>#<id>`. */
269
+ gsi1sk: gsi1skAttribute,
270
+ deleted: {
271
+ type: "boolean",
272
+ required: false
273
+ },
274
+ bundleId: {
275
+ type: "string",
276
+ required: false
277
+ },
278
+ msgId: {
279
+ type: "string",
280
+ required: false
281
+ }
282
+ },
283
+ indexes: {
284
+ /** Base table: PK = TID#<tenantId>#MEMBERSHIP#ID#<id>, SK = CURRENT. Do not supply PK or SK from outside. */
285
+ record: {
286
+ pk: {
287
+ field: "PK",
288
+ composite: ["tenantId", "id"],
289
+ template: "TID#${tenantId}#MEMBERSHIP#ID#${id}"
290
+ },
291
+ sk: {
292
+ field: "SK",
293
+ composite: ["sk"],
294
+ template: "${sk}"
295
+ }
296
+ },
297
+ /**
298
+ * GSI1 — Unified Sharded List per ADR-011: list all Memberships for a tenant across the
299
+ * four shards. Membership is tenant-scoped only, so `WID#-` is a sentinel.
300
+ * SK is derived via `gsi1skAttribute` — uses the resource's natural label when
301
+ * extractable, else `<lastUpdated>#<id>` (DR-004). `casing: "none"` preserves the
302
+ * normalized label and ISO-8601 `T`/`Z`.
303
+ */
304
+ gsi1: {
305
+ index: "GSI1",
306
+ pk: {
307
+ field: "GSI1PK",
308
+ composite: ["tenantId", "gsi1Shard"],
309
+ template: "TID#${tenantId}#WID#-#RT#Membership#SHARD#${gsi1Shard}"
310
+ },
311
+ sk: {
312
+ field: "GSI1SK",
313
+ casing: "none",
314
+ composite: ["gsi1sk"],
315
+ template: "${gsi1sk}"
316
+ }
317
+ }
318
+ }
319
+ });
320
+
321
+ // src/data/dynamo/entities/control/role-entity.ts
322
+ var import_electrodb3 = require("electrodb");
323
+ var RoleEntity = new import_electrodb3.Entity({
324
+ model: {
325
+ entity: "role",
326
+ service: "control",
327
+ version: "01"
328
+ },
329
+ attributes: {
330
+ /** Sort key sentinel. Always "CURRENT". */
331
+ sk: {
332
+ type: "string",
333
+ required: true,
334
+ default: "CURRENT"
335
+ },
336
+ /** FHIR Resource.id; role id. */
337
+ id: {
338
+ type: "string",
339
+ required: true
340
+ },
341
+ /** Full Role resource serialized as JSON string. */
342
+ resource: {
343
+ type: "string",
344
+ required: true
345
+ },
346
+ /**
347
+ * Summary projection (key display fields as JSON string: id, displayName, status).
348
+ * Populated on every write via extractSummary(resource); GSI1 INCLUDE surfaces it on lists.
349
+ */
350
+ summary: {
351
+ type: "string",
352
+ required: true
353
+ },
354
+ /** Version id (e.g. ULID). */
355
+ vid: {
356
+ type: "string",
357
+ required: true
358
+ },
359
+ lastUpdated: {
360
+ type: "string",
361
+ required: true
362
+ },
363
+ gsi1Shard: gsi1ShardAttribute,
364
+ /** Derived GSI1 sort key — name-based when extractable; else `<lastUpdated>#<id>`. */
365
+ gsi1sk: gsi1skAttribute,
366
+ deleted: {
367
+ type: "boolean",
368
+ required: false
369
+ },
370
+ bundleId: {
371
+ type: "string",
372
+ required: false
373
+ },
374
+ msgId: {
375
+ type: "string",
376
+ required: false
377
+ }
378
+ },
379
+ indexes: {
380
+ /** Base table: PK = ROLE#ID#<id>, SK = CURRENT. Do not supply PK or SK from outside. */
381
+ record: {
382
+ pk: {
383
+ field: "PK",
384
+ composite: ["id"],
385
+ template: "ROLE#ID#${id}"
386
+ },
387
+ sk: {
388
+ field: "SK",
389
+ composite: ["sk"],
390
+ template: "${sk}"
391
+ }
392
+ },
393
+ /**
394
+ * GSI1 — Unified Sharded List per ADR-011: list all Roles across the four shards.
395
+ * Non-tenant-isolated, so `TID#-#WID#-` sentinels precede `RT#Role#SHARD#<n>`.
396
+ * SK is derived via `gsi1skAttribute` — uses the resource's natural label when
397
+ * extractable, else `<lastUpdated>#<id>` (DR-004). `casing: "none"` preserves the
398
+ * normalized label and ISO-8601 `T`/`Z`.
399
+ */
400
+ gsi1: {
401
+ index: "GSI1",
402
+ pk: {
403
+ field: "GSI1PK",
404
+ composite: ["gsi1Shard"],
405
+ template: "TID#-#WID#-#RT#Role#SHARD#${gsi1Shard}"
406
+ },
407
+ sk: {
408
+ field: "GSI1SK",
409
+ casing: "none",
410
+ composite: ["gsi1sk"],
411
+ template: "${gsi1sk}"
412
+ }
413
+ }
414
+ }
415
+ });
416
+
417
+ // src/data/dynamo/entities/control/roleassignment-entity.ts
418
+ var import_electrodb4 = require("electrodb");
419
+ var RoleAssignmentEntity = new import_electrodb4.Entity({
420
+ model: {
421
+ entity: "roleassignment",
422
+ service: "control",
423
+ version: "01"
424
+ },
425
+ attributes: {
426
+ /** Sort key sentinel. Always "CURRENT". */
427
+ sk: {
428
+ type: "string",
429
+ required: true,
430
+ default: "CURRENT"
431
+ },
432
+ /** Tenant in which the role assignment applies (required). */
433
+ tenantId: {
434
+ type: "string",
435
+ required: true
436
+ },
437
+ /** FHIR Resource.id; role assignment id. */
438
+ id: {
439
+ type: "string",
440
+ required: true
441
+ },
442
+ /** Full RoleAssignment resource serialized as JSON string. */
443
+ resource: {
444
+ type: "string",
445
+ required: true
446
+ },
447
+ /**
448
+ * Summary projection (key display fields as JSON string: id, displayName, status).
449
+ * Populated on every write via extractSummary(resource); GSI1 INCLUDE surfaces it on lists.
450
+ */
451
+ summary: {
452
+ type: "string",
453
+ required: true
454
+ },
455
+ /** Version id (e.g. ULID). */
456
+ vid: {
457
+ type: "string",
458
+ required: true
459
+ },
460
+ lastUpdated: {
461
+ type: "string",
462
+ required: true
463
+ },
464
+ gsi1Shard: gsi1ShardAttribute,
465
+ /** Derived GSI1 sort key — name-based when extractable; else `<lastUpdated>#<id>`. */
466
+ gsi1sk: gsi1skAttribute,
467
+ deleted: {
468
+ type: "boolean",
469
+ required: false
470
+ },
471
+ bundleId: {
472
+ type: "string",
473
+ required: false
474
+ },
475
+ msgId: {
476
+ type: "string",
477
+ required: false
478
+ }
479
+ },
480
+ indexes: {
481
+ /** Base table: PK = TID#<tenantId>#ROLEASSIGNMENT#ID#<id>, SK = CURRENT. Do not supply PK or SK from outside. */
482
+ record: {
483
+ pk: {
484
+ field: "PK",
485
+ composite: ["tenantId", "id"],
486
+ template: "TID#${tenantId}#ROLEASSIGNMENT#ID#${id}"
487
+ },
488
+ sk: {
489
+ field: "SK",
490
+ composite: ["sk"],
491
+ template: "${sk}"
492
+ }
493
+ },
494
+ /**
495
+ * GSI1 — Unified Sharded List per ADR-011: list all RoleAssignments for a tenant across the
496
+ * four shards. Tenant-scoped only, so `WID#-` is a sentinel.
497
+ * SK is derived via `gsi1skAttribute` — uses the resource's natural label when
498
+ * extractable, else `<lastUpdated>#<id>` (DR-004). `casing: "none"` preserves the
499
+ * normalized label and ISO-8601 `T`/`Z`.
500
+ */
501
+ gsi1: {
502
+ index: "GSI1",
503
+ pk: {
504
+ field: "GSI1PK",
505
+ composite: ["tenantId", "gsi1Shard"],
506
+ template: "TID#${tenantId}#WID#-#RT#RoleAssignment#SHARD#${gsi1Shard}"
507
+ },
508
+ sk: {
509
+ field: "GSI1SK",
510
+ casing: "none",
511
+ composite: ["gsi1sk"],
512
+ template: "${gsi1sk}"
513
+ }
514
+ }
515
+ }
516
+ });
517
+
518
+ // src/data/dynamo/entities/control/tenant-entity.ts
519
+ var import_electrodb5 = require("electrodb");
520
+ var TenantEntity = new import_electrodb5.Entity({
521
+ model: {
522
+ entity: "tenant",
523
+ service: "control",
524
+ version: "01"
525
+ },
526
+ attributes: {
527
+ /** Sort key sentinel. Always "CURRENT". */
528
+ sk: {
529
+ type: "string",
530
+ required: true,
531
+ default: "CURRENT"
532
+ },
533
+ /** The tenant's own id (= resource id). Drives the partition key. */
534
+ tenantId: {
535
+ type: "string",
536
+ required: true
537
+ },
538
+ /** FHIR Resource.id; logical id in URL. Equals tenantId. */
539
+ id: {
540
+ type: "string",
541
+ required: true
542
+ },
543
+ /** Full Tenant resource serialized as JSON string. */
544
+ resource: {
545
+ type: "string",
546
+ required: true
547
+ },
548
+ /**
549
+ * Summary projection (key display fields as JSON string: id, displayName, status).
550
+ * Populated on every write via extractSummary(resource); GSI1 INCLUDE surfaces it on lists.
551
+ */
552
+ summary: {
553
+ type: "string",
554
+ required: true
555
+ },
556
+ /** Version id (e.g. ULID). */
557
+ vid: {
558
+ type: "string",
559
+ required: true
560
+ },
561
+ lastUpdated: {
562
+ type: "string",
563
+ required: true
564
+ },
565
+ gsi1Shard: gsi1ShardAttribute,
566
+ /** Derived GSI1 sort key — name-based when extractable; else `<lastUpdated>#<id>`. */
567
+ gsi1sk: gsi1skAttribute,
568
+ deleted: {
569
+ type: "boolean",
570
+ required: false
571
+ },
572
+ bundleId: {
573
+ type: "string",
574
+ required: false
575
+ },
576
+ msgId: {
577
+ type: "string",
578
+ required: false
579
+ }
580
+ },
581
+ indexes: {
582
+ /** Base table: PK = TENANT#ID#<tenantId>, SK = CURRENT. Do not supply PK or SK from outside. */
583
+ record: {
584
+ pk: {
585
+ field: "PK",
586
+ composite: ["tenantId"],
587
+ template: "TENANT#ID#${tenantId}"
588
+ },
589
+ sk: {
590
+ field: "SK",
591
+ composite: ["sk"],
592
+ template: "${sk}"
593
+ }
594
+ },
595
+ /**
596
+ * GSI1 — Unified Sharded List per ADR-011: list all Tenants across the four shards.
597
+ * Tenant lives at the platform tier (no parent tenant or workspace), so `TID#-#WID#-`
598
+ * sentinels precede `RT#Tenant#SHARD#<n>`. SK is derived via `gsi1skAttribute` —
599
+ * `<normalizedName>#<id>` when the resource carries a `name`, else `<lastUpdated>#<id>`
600
+ * (DR-004). `casing: "none"` preserves the normalized label and ISO-8601 `T`/`Z`.
601
+ */
602
+ gsi1: {
603
+ index: "GSI1",
604
+ pk: {
605
+ field: "GSI1PK",
606
+ composite: ["gsi1Shard"],
607
+ template: "TID#-#WID#-#RT#Tenant#SHARD#${gsi1Shard}"
608
+ },
609
+ sk: {
610
+ field: "GSI1SK",
611
+ casing: "none",
612
+ composite: ["gsi1sk"],
613
+ template: "${gsi1sk}"
614
+ }
615
+ }
616
+ }
617
+ });
618
+
619
+ // src/data/dynamo/entities/control/user-entity.ts
620
+ var import_electrodb6 = require("electrodb");
621
+ var UserEntity = new import_electrodb6.Entity({
622
+ model: {
623
+ entity: "user",
624
+ service: "control",
625
+ version: "01"
626
+ },
627
+ attributes: {
628
+ /** Sort key sentinel. Always "CURRENT". */
629
+ sk: {
630
+ type: "string",
631
+ required: true,
632
+ default: "CURRENT"
633
+ },
634
+ /** FHIR Resource.id; platform user id (ohi_uid). */
635
+ id: {
636
+ type: "string",
637
+ required: true
638
+ },
639
+ /** Full User resource serialized as JSON string. */
640
+ resource: {
641
+ type: "string",
642
+ required: true
643
+ },
644
+ /**
645
+ * Summary projection (key display fields as JSON string: id, displayName, status).
646
+ * Populated on every write via extractSummary(resource); GSI1 INCLUDE surfaces it on lists.
647
+ */
648
+ summary: {
649
+ type: "string",
650
+ required: true
651
+ },
652
+ /**
653
+ * Immutable Cognito-issued `sub` claim. Drives GSI2 (sub-lookup). Optional until the
654
+ * Post Confirmation Lambda (#770) lands; required thereafter.
655
+ */
656
+ cognitoSub: {
657
+ type: "string",
658
+ required: false
659
+ },
660
+ /** Version id (e.g. ULID). */
661
+ vid: {
662
+ type: "string",
663
+ required: true
664
+ },
665
+ lastUpdated: {
666
+ type: "string",
667
+ required: true
668
+ },
669
+ gsi1Shard: gsi1ShardAttribute,
670
+ /** Derived GSI1 sort key — name-based when extractable; else `<lastUpdated>#<id>`. */
671
+ gsi1sk: gsi1skAttribute,
672
+ deleted: {
673
+ type: "boolean",
674
+ required: false
675
+ },
676
+ bundleId: {
677
+ type: "string",
678
+ required: false
679
+ },
680
+ msgId: {
681
+ type: "string",
682
+ required: false
683
+ }
684
+ },
685
+ indexes: {
686
+ /** Base table: PK = USER#ID#<id>, SK = CURRENT. Do not supply PK or SK from outside. */
687
+ record: {
688
+ pk: {
689
+ field: "PK",
690
+ composite: ["id"],
691
+ template: "USER#ID#${id}"
692
+ },
693
+ sk: {
694
+ field: "SK",
695
+ composite: ["sk"],
696
+ template: "${sk}"
697
+ }
698
+ },
699
+ /**
700
+ * GSI1 — Unified Sharded List per ADR-011: list all Users across the four shards.
701
+ * Non-tenant-isolated, so `TID#-#WID#-` sentinels precede `RT#User#SHARD#<n>`.
702
+ * SK is derived via `gsi1skAttribute` — uses the resource's natural label when
703
+ * extractable (string `name`/`title` via introspection), else `<lastUpdated>#<id>`
704
+ * (DR-004). `casing: "none"` preserves the normalized label and ISO-8601 `T`/`Z`.
705
+ */
706
+ gsi1: {
707
+ index: "GSI1",
708
+ pk: {
709
+ field: "GSI1PK",
710
+ composite: ["gsi1Shard"],
711
+ template: "TID#-#WID#-#RT#User#SHARD#${gsi1Shard}"
712
+ },
713
+ sk: {
714
+ field: "GSI1SK",
715
+ casing: "none",
716
+ composite: ["gsi1sk"],
717
+ template: "${gsi1sk}"
718
+ }
719
+ },
720
+ /**
721
+ * GSI2 — Cognito sub-lookup per ADR-011: resolves the UserEntity from a Cognito `sub` claim.
722
+ * `condition` skips the index when `cognitoSub` is missing so legacy items without a sub are
723
+ * not indexed.
724
+ */
725
+ gsi2: {
726
+ index: "GSI2",
727
+ condition: (attrs) => typeof attrs.cognitoSub === "string" && attrs.cognitoSub.length > 0,
728
+ pk: {
729
+ field: "GSI2PK",
730
+ casing: "none",
731
+ composite: ["cognitoSub"],
732
+ template: "USER#SUB#${cognitoSub}"
733
+ },
734
+ sk: {
735
+ field: "GSI2SK",
736
+ casing: "none",
737
+ composite: [],
738
+ template: "CURRENT"
739
+ }
740
+ }
741
+ }
742
+ });
743
+
744
+ // src/data/dynamo/entities/control/workspace-entity.ts
745
+ var import_electrodb7 = require("electrodb");
746
+ var WorkspaceEntity = new import_electrodb7.Entity({
747
+ model: {
748
+ entity: "workspace",
749
+ service: "control",
750
+ version: "01"
751
+ },
752
+ attributes: {
753
+ /** Sort key sentinel. Always "CURRENT". */
754
+ sk: {
755
+ type: "string",
756
+ required: true,
757
+ default: "CURRENT"
758
+ },
759
+ /** Tenant that contains this workspace (required). */
760
+ tenantId: {
761
+ type: "string",
762
+ required: true
763
+ },
764
+ /** FHIR Resource.id; logical id in URL. */
765
+ id: {
766
+ type: "string",
767
+ required: true
768
+ },
769
+ /** Full Workspace resource serialized as JSON string. */
770
+ resource: {
771
+ type: "string",
772
+ required: true
773
+ },
774
+ /**
775
+ * Summary projection (key display fields as JSON string: id, displayName, status).
776
+ * Populated on every write via extractSummary(resource); GSI1 INCLUDE surfaces it on lists.
777
+ */
778
+ summary: {
779
+ type: "string",
780
+ required: true
781
+ },
782
+ /** Version id (e.g. ULID). */
783
+ vid: {
784
+ type: "string",
785
+ required: true
786
+ },
787
+ lastUpdated: {
788
+ type: "string",
789
+ required: true
790
+ },
791
+ gsi1Shard: gsi1ShardAttribute,
792
+ /** Derived GSI1 sort key — name-based when extractable; else `<lastUpdated>#<id>`. */
793
+ gsi1sk: gsi1skAttribute,
794
+ deleted: {
795
+ type: "boolean",
796
+ required: false
797
+ },
798
+ bundleId: {
799
+ type: "string",
800
+ required: false
801
+ },
802
+ msgId: {
803
+ type: "string",
804
+ required: false
805
+ }
806
+ },
807
+ indexes: {
808
+ /** Base table: PK = TID#<tenantId>#WORKSPACE#ID#<id>, SK = CURRENT. Do not supply PK or SK from outside. */
809
+ record: {
810
+ pk: {
811
+ field: "PK",
812
+ composite: ["tenantId", "id"],
813
+ template: "TID#${tenantId}#WORKSPACE#ID#${id}"
814
+ },
815
+ sk: {
816
+ field: "SK",
817
+ composite: ["sk"],
818
+ template: "${sk}"
819
+ }
820
+ },
821
+ /**
822
+ * GSI1 — Unified Sharded List per ADR-011: list all Workspaces for a tenant across the
823
+ * four shards. Workspace is itself the workspace identity, so `WID#-` is a sentinel.
824
+ * SK is derived via `gsi1skAttribute` — `<normalizedName>#<id>` when the resource
825
+ * carries a `name`, else `<lastUpdated>#<id>` (DR-004). `casing: "none"` preserves
826
+ * the normalized label and ISO-8601 `T`/`Z`.
827
+ */
828
+ gsi1: {
829
+ index: "GSI1",
830
+ pk: {
831
+ field: "GSI1PK",
832
+ composite: ["tenantId", "gsi1Shard"],
833
+ template: "TID#${tenantId}#WID#-#RT#Workspace#SHARD#${gsi1Shard}"
834
+ },
835
+ sk: {
836
+ field: "GSI1SK",
837
+ casing: "none",
838
+ composite: ["gsi1sk"],
839
+ template: "${gsi1sk}"
840
+ }
841
+ }
842
+ }
843
+ });
844
+
845
+ // src/data/dynamo/dynamo-control-service.ts
846
+ var controlPlaneEntities = {
847
+ configuration: ConfigurationEntity,
848
+ membership: MembershipEntity,
849
+ role: RoleEntity,
850
+ roleAssignment: RoleAssignmentEntity,
851
+ tenant: TenantEntity,
852
+ user: UserEntity,
853
+ workspace: WorkspaceEntity
854
+ };
855
+ var controlPlaneService = new import_electrodb8.Service(controlPlaneEntities, {
856
+ table: defaultTableName,
857
+ client: dynamoClient
858
+ });
859
+ var DynamoControlService = {
860
+ entities: controlPlaneService.entities
861
+ };
862
+ function getDynamoControlService(tableName) {
863
+ const resolved = tableName ?? defaultTableName;
864
+ const service = new import_electrodb8.Service(controlPlaneEntities, {
865
+ table: resolved,
866
+ client: dynamoClient
867
+ });
868
+ return {
869
+ entities: service.entities
870
+ };
871
+ }
872
+
873
+ // src/data/operations/control/membership/membership-create-operation.ts
874
+ var import_types2 = require("@openhi/types");
875
+ async function createMembershipOperation(params) {
876
+ const { context, body, tableName } = params;
877
+ const service = getDynamoControlService(tableName);
878
+ const id = body.id ?? `membership-${Date.now()}`;
879
+ const parsedResource = typeof body.resource === "string" ? JSON.parse(body.resource) : body.resource ?? {};
880
+ const lastUpdated = context.date ?? (/* @__PURE__ */ new Date()).toISOString();
881
+ const vid = `1`;
882
+ const resource = { resourceType: "Membership", id, ...parsedResource };
883
+ const summary = JSON.stringify((0, import_types2.extractSummary)(resource));
884
+ await service.entities.membership.put({
885
+ tenantId: context.tenantId,
886
+ id,
887
+ resource: JSON.stringify(resource),
888
+ summary,
889
+ vid,
890
+ lastUpdated
891
+ }).go();
892
+ return {
893
+ id,
894
+ resource,
895
+ meta: { lastUpdated, versionId: vid }
896
+ };
897
+ }
898
+
899
+ // src/data/operations/control/roleassignment/roleassignment-create-operation.ts
900
+ var import_types3 = require("@openhi/types");
901
+ async function createRoleAssignmentOperation(params) {
902
+ const { context, body, tableName } = params;
903
+ const service = getDynamoControlService(tableName);
904
+ const id = body.id ?? `roleassignment-${Date.now()}`;
905
+ const parsedResource = typeof body.resource === "string" ? JSON.parse(body.resource) : body.resource ?? {};
906
+ const lastUpdated = context.date ?? (/* @__PURE__ */ new Date()).toISOString();
907
+ const vid = `1`;
908
+ const resource = { resourceType: "RoleAssignment", id, ...parsedResource };
909
+ const summary = JSON.stringify((0, import_types3.extractSummary)(resource));
910
+ await service.entities.roleAssignment.put({
911
+ tenantId: context.tenantId,
912
+ id,
913
+ resource: JSON.stringify(resource),
914
+ summary,
915
+ vid,
916
+ lastUpdated
917
+ }).go();
918
+ return {
919
+ id,
920
+ resource,
921
+ meta: { lastUpdated, versionId: vid }
922
+ };
923
+ }
924
+
925
+ // src/data/operations/control/tenant/tenant-create-operation.ts
926
+ var import_types4 = require("@openhi/types");
927
+ async function createTenantOperation(params) {
928
+ const { context, body, tableName } = params;
929
+ const service = getDynamoControlService(tableName);
930
+ const id = body.id ?? `tenant-${Date.now()}`;
931
+ const lastUpdated = context.date;
932
+ const vid = lastUpdated.replace(/[-:T.Z]/g, "").slice(0, 12) || Date.now().toString(36);
933
+ const parsedResource = typeof body.resource === "string" ? JSON.parse(body.resource) : body.resource ?? {};
934
+ const resource = { resourceType: "Tenant", id, ...parsedResource };
935
+ const summary = JSON.stringify((0, import_types4.extractSummary)(resource));
936
+ await service.entities.tenant.put({
937
+ tenantId: id,
938
+ id,
939
+ resource: JSON.stringify(resource),
940
+ summary,
941
+ vid,
942
+ lastUpdated
943
+ }).go();
944
+ return { id, resource, meta: { lastUpdated, versionId: vid } };
945
+ }
946
+
947
+ // src/data/operations/control/user/user-create-operation.ts
948
+ var import_types5 = require("@openhi/types");
949
+
950
+ // src/data/operations/control/user/user-find-by-sub-operation.ts
951
+ async function findUserBySubOperation(params) {
952
+ const { cognitoSub, tableName } = params;
953
+ const service = getDynamoControlService(tableName);
954
+ const result = await service.entities.user.query.gsi2({ cognitoSub }).go({ limit: 1 });
955
+ const item = result.data?.[0];
956
+ if (!item) {
957
+ return void 0;
958
+ }
959
+ return {
960
+ id: item.id,
961
+ cognitoSub: item.cognitoSub,
962
+ resource: item.resource,
963
+ vid: item.vid
964
+ };
965
+ }
966
+
967
+ // src/data/operations/data-operations-common.ts
968
+ var import_types6 = require("@openhi/types");
969
+
970
+ // src/lib/compression.ts
971
+ var import_node_zlib = require("zlib");
972
+
973
+ // src/data/operations/control/user/user-update-operation.ts
974
+ var import_types7 = require("@openhi/types");
975
+
976
+ // src/data/operations/control/user/user-resource-helpers.ts
977
+ function parseUserResource(resource) {
978
+ try {
979
+ return JSON.parse(resource);
980
+ } catch {
981
+ return void 0;
982
+ }
983
+ }
984
+
985
+ // src/data/operations/control/workspace/workspace-create-operation.ts
986
+ var import_types8 = require("@openhi/types");
987
+ async function createWorkspaceOperation(params) {
988
+ const { context, body, tableName } = params;
989
+ const { tenantId } = context;
990
+ const service = getDynamoControlService(tableName);
991
+ const id = body.id ?? `workspace-${Date.now()}`;
992
+ const lastUpdated = context.date;
993
+ const vid = lastUpdated.replace(/[-:T.Z]/g, "").slice(0, 12) || Date.now().toString(36);
994
+ const parsedResource = typeof body.resource === "string" ? JSON.parse(body.resource) : body.resource ?? {};
995
+ const resource = { resourceType: "Workspace", id, ...parsedResource };
996
+ const summary = JSON.stringify((0, import_types8.extractSummary)(resource));
997
+ await service.entities.workspace.put({
998
+ tenantId,
999
+ id,
1000
+ resource: JSON.stringify(resource),
1001
+ summary,
1002
+ vid,
1003
+ lastUpdated
1004
+ }).go();
1005
+ return { id, resource, meta: { lastUpdated, versionId: vid } };
1006
+ }
1007
+
1008
+ // src/data/operations/fhir-reference.ts
1009
+ function idFromReference(reference, prefix) {
1010
+ if (!reference || !reference.startsWith(prefix)) {
1011
+ return void 0;
1012
+ }
1013
+ const id = reference.slice(prefix.length);
1014
+ return id.length > 0 ? id : void 0;
1015
+ }
1016
+
1017
+ // src/workflows/control-plane/user-onboarding/provision-default-workspace.handler.ts
1018
+ var CURRENT_SK = "CURRENT";
1019
+ var VID = "1";
1020
+ var summaryFor = (resource) => {
1021
+ return JSON.stringify((0, import_types9.extractSummary)(resource));
1022
+ };
1023
+ var stableOnboardingId = (kind, cognitoSub) => {
1024
+ return (0, import_node_crypto.createHash)("sha256").update(kind).update("\0").update(cognitoSub).digest("hex").slice(0, 26).toUpperCase();
1025
+ };
1026
+ var handler = async (event) => {
1027
+ const detail = event.detail;
1028
+ if (!detail?.cognitoSub) {
1029
+ console.warn(
1030
+ "ProvisionDefaultWorkspace: event missing cognitoSub; skipping"
1031
+ );
1032
+ return;
1033
+ }
1034
+ const service = getDynamoControlService();
1035
+ const existingUser = await findUserBySubOperation({
1036
+ context: {
1037
+ tenantId: "",
1038
+ workspaceId: "",
1039
+ date: "",
1040
+ actorId: "",
1041
+ actorName: "",
1042
+ actorType: "internal-system"
1043
+ },
1044
+ cognitoSub: detail.cognitoSub
1045
+ });
1046
+ const existingResource = existingUser ? parseUserResource(existingUser.resource) : void 0;
1047
+ const existingTenantId = idFromReference(
1048
+ existingResource?.currentTenant?.reference,
1049
+ "Tenant/"
1050
+ );
1051
+ const existingWorkspaceId = idFromReference(
1052
+ existingResource?.currentWorkspace?.reference,
1053
+ "Workspace/"
1054
+ );
1055
+ if (existingUser && existingTenantId && existingWorkspaceId) {
1056
+ return;
1057
+ }
1058
+ const displayName = detail.displayName || detail.email || event.resources?.[0] || detail.cognitoSub;
1059
+ const userId = existingUser?.id ?? detail.userId ?? stableOnboardingId("user", detail.cognitoSub);
1060
+ const tenantId = stableOnboardingId("tenant", detail.cognitoSub);
1061
+ const workspaceId = stableOnboardingId("workspace", detail.cognitoSub);
1062
+ const userTenantMembershipId = stableOnboardingId(
1063
+ "tenant-membership",
1064
+ detail.cognitoSub
1065
+ );
1066
+ const userWorkspaceMembershipId = stableOnboardingId(
1067
+ "workspace-membership",
1068
+ detail.cognitoSub
1069
+ );
1070
+ const roleAssignmentId = stableOnboardingId(
1071
+ "tenant-user-role-assignment",
1072
+ detail.cognitoSub
1073
+ );
1074
+ const lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
1075
+ const context = {
1076
+ tenantId,
1077
+ workspaceId,
1078
+ date: lastUpdated,
1079
+ actorId: userId,
1080
+ actorName: displayName,
1081
+ actorType: "internal-system"
1082
+ };
1083
+ const tenantResource = {
1084
+ id: tenantId,
1085
+ displayName: `${displayName}'s Practice`,
1086
+ status: "active"
1087
+ };
1088
+ const workspaceResource = {
1089
+ id: workspaceId,
1090
+ displayName: "Default Workspace",
1091
+ status: "active",
1092
+ tenant: { reference: `Tenant/${tenantId}` }
1093
+ };
1094
+ const userResource = {
1095
+ ...existingResource ?? {},
1096
+ resourceType: "User",
1097
+ id: userId,
1098
+ name: existingResource?.name ?? [{ text: displayName }],
1099
+ status: "active",
1100
+ currentTenant: { reference: `Tenant/${tenantId}` },
1101
+ currentWorkspace: { reference: `Workspace/${workspaceId}` }
1102
+ };
1103
+ const userTenantMembershipResource = {
1104
+ id: userTenantMembershipId,
1105
+ status: "active",
1106
+ user: { reference: `User/${userId}` },
1107
+ tenant: { reference: `Tenant/${tenantId}` }
1108
+ };
1109
+ const userWorkspaceMembershipResource = {
1110
+ id: userWorkspaceMembershipId,
1111
+ status: "active",
1112
+ user: { reference: `User/${userId}` },
1113
+ tenant: { reference: `Tenant/${tenantId}` },
1114
+ workspace: { reference: `Workspace/${workspaceId}` }
1115
+ };
1116
+ const roleAssignmentResource = {
1117
+ id: roleAssignmentId,
1118
+ status: "active",
1119
+ user: { reference: `User/${userId}` },
1120
+ tenant: { reference: `Tenant/${tenantId}` },
1121
+ role: "tenant-user"
1122
+ };
1123
+ await createTenantOperation({
1124
+ context,
1125
+ body: { id: tenantId, resource: tenantResource }
1126
+ });
1127
+ await createWorkspaceOperation({
1128
+ context,
1129
+ body: { id: workspaceId, resource: workspaceResource }
1130
+ });
1131
+ if (existingUser) {
1132
+ await service.entities.user.patch({ id: userId, sk: CURRENT_SK }).set({
1133
+ resource: JSON.stringify(userResource),
1134
+ summary: summaryFor(userResource),
1135
+ cognitoSub: detail.cognitoSub,
1136
+ vid: VID,
1137
+ lastUpdated
1138
+ }).go();
1139
+ } else {
1140
+ await service.entities.user.put({
1141
+ id: userId,
1142
+ cognitoSub: detail.cognitoSub,
1143
+ resource: JSON.stringify(userResource),
1144
+ summary: summaryFor(userResource),
1145
+ vid: VID,
1146
+ lastUpdated
1147
+ }).go();
1148
+ }
1149
+ await createMembershipOperation({
1150
+ context,
1151
+ body: {
1152
+ id: userTenantMembershipId,
1153
+ resource: userTenantMembershipResource
1154
+ }
1155
+ });
1156
+ await createMembershipOperation({
1157
+ context,
1158
+ body: {
1159
+ id: userWorkspaceMembershipId,
1160
+ resource: userWorkspaceMembershipResource
1161
+ }
1162
+ });
1163
+ await createRoleAssignmentOperation({
1164
+ context,
1165
+ body: { id: roleAssignmentId, resource: roleAssignmentResource }
1166
+ });
1167
+ };
1168
+ // Annotate the CommonJS export names for ESM import in node:
1169
+ 0 && (module.exports = {
1170
+ handler
1171
+ });
1172
+ //# sourceMappingURL=provision-default-workspace.handler.js.map