@openhi/constructs 0.0.111 → 0.0.112

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 (111) hide show
  1. package/lib/chunk-23PUSHBV.mjs +24 -0
  2. package/lib/chunk-23PUSHBV.mjs.map +1 -0
  3. package/lib/{chunk-7FUAMZOF.mjs → chunk-53OHXLIL.mjs} +3 -3
  4. package/lib/chunk-6NBGYGFL.mjs +1803 -0
  5. package/lib/chunk-6NBGYGFL.mjs.map +1 -0
  6. package/lib/chunk-7RZHFI77.mjs +22 -0
  7. package/lib/chunk-7RZHFI77.mjs.map +1 -0
  8. package/lib/{chunk-7Q2IJ2J5.mjs → chunk-CUUKXDB2.mjs} +6 -6
  9. package/lib/chunk-FYHBHHWK.mjs +47 -0
  10. package/lib/chunk-FYHBHHWK.mjs.map +1 -0
  11. package/lib/{chunk-MULKGFIJ.mjs → chunk-GBDIGTNV.mjs} +165 -10
  12. package/lib/chunk-GBDIGTNV.mjs.map +1 -0
  13. package/lib/chunk-HQ67J7BP.mjs +199 -0
  14. package/lib/chunk-HQ67J7BP.mjs.map +1 -0
  15. package/lib/{chunk-AJ3G3THO.mjs → chunk-KO64HPWQ.mjs} +2 -2
  16. package/lib/{chunk-BB5MK4L3.mjs → chunk-KSFC72TT.mjs} +3 -3
  17. package/lib/{chunk-2TPJ6HOF.mjs → chunk-NZRW7ROK.mjs} +72 -54
  18. package/lib/chunk-NZRW7ROK.mjs.map +1 -0
  19. package/lib/chunk-QJDHVMKT.mjs +117 -0
  20. package/lib/chunk-QJDHVMKT.mjs.map +1 -0
  21. package/lib/{chunk-IS4VQRI4.mjs → chunk-QMBJ4VHC.mjs} +12 -47
  22. package/lib/chunk-QMBJ4VHC.mjs.map +1 -0
  23. package/lib/chunk-TRY7JGWO.mjs +16 -0
  24. package/lib/chunk-TRY7JGWO.mjs.map +1 -0
  25. package/lib/chunk-W4KR4CSL.mjs +236 -0
  26. package/lib/chunk-W4KR4CSL.mjs.map +1 -0
  27. package/lib/{chunk-AGF3RAAZ.mjs → chunk-WPCBVDFZ.mjs} +2 -2
  28. package/lib/chunk-WQWFVEVX.mjs +66 -0
  29. package/lib/chunk-WQWFVEVX.mjs.map +1 -0
  30. package/lib/{chunk-SYBADQXI.mjs → chunk-ZM4GDHHC.mjs} +77 -2
  31. package/lib/chunk-ZM4GDHHC.mjs.map +1 -0
  32. package/lib/delete-chunk.handler.d.mts +29 -0
  33. package/lib/delete-chunk.handler.d.ts +29 -0
  34. package/lib/delete-chunk.handler.js +2716 -0
  35. package/lib/delete-chunk.handler.js.map +1 -0
  36. package/lib/delete-chunk.handler.mjs +47 -0
  37. package/lib/delete-chunk.handler.mjs.map +1 -0
  38. package/lib/events-CjS-sm0W.d.mts +107 -0
  39. package/lib/events-CjS-sm0W.d.ts +107 -0
  40. package/lib/events-Da_cFgtc.d.mts +208 -0
  41. package/lib/events-Da_cFgtc.d.ts +208 -0
  42. package/lib/finalize.handler.d.mts +35 -0
  43. package/lib/finalize.handler.d.ts +35 -0
  44. package/lib/finalize.handler.js +875 -0
  45. package/lib/finalize.handler.js.map +1 -0
  46. package/lib/finalize.handler.mjs +166 -0
  47. package/lib/finalize.handler.mjs.map +1 -0
  48. package/lib/index.d.mts +189 -2
  49. package/lib/index.d.ts +500 -3
  50. package/lib/index.js +1753 -174
  51. package/lib/index.js.map +1 -1
  52. package/lib/index.mjs +571 -17
  53. package/lib/index.mjs.map +1 -1
  54. package/lib/list-chunks.handler.d.mts +28 -0
  55. package/lib/list-chunks.handler.d.ts +28 -0
  56. package/lib/list-chunks.handler.js +2746 -0
  57. package/lib/list-chunks.handler.js.map +1 -0
  58. package/lib/list-chunks.handler.mjs +54 -0
  59. package/lib/list-chunks.handler.mjs.map +1 -0
  60. package/lib/platform-deploy-bridge.handler.js +76 -1
  61. package/lib/platform-deploy-bridge.handler.js.map +1 -1
  62. package/lib/platform-deploy-bridge.handler.mjs +1 -1
  63. package/lib/pre-token-generation.handler.js +1106 -155
  64. package/lib/pre-token-generation.handler.js.map +1 -1
  65. package/lib/pre-token-generation.handler.mjs +6 -4
  66. package/lib/pre-token-generation.handler.mjs.map +1 -1
  67. package/lib/provision-default-workspace.handler.js +1529 -142
  68. package/lib/provision-default-workspace.handler.js.map +1 -1
  69. package/lib/provision-default-workspace.handler.mjs +8 -4
  70. package/lib/provision-default-workspace.handler.mjs.map +1 -1
  71. package/lib/rename-finalize.handler.d.mts +30 -0
  72. package/lib/rename-finalize.handler.d.ts +30 -0
  73. package/lib/rename-finalize.handler.js +795 -0
  74. package/lib/rename-finalize.handler.js.map +1 -0
  75. package/lib/rename-finalize.handler.mjs +90 -0
  76. package/lib/rename-finalize.handler.mjs.map +1 -0
  77. package/lib/rename-list-targets.handler.d.mts +26 -0
  78. package/lib/rename-list-targets.handler.d.ts +26 -0
  79. package/lib/rename-list-targets.handler.js +2985 -0
  80. package/lib/rename-list-targets.handler.js.map +1 -0
  81. package/lib/rename-list-targets.handler.mjs +431 -0
  82. package/lib/rename-list-targets.handler.mjs.map +1 -0
  83. package/lib/rename-rewrite-chunk.handler.d.mts +35 -0
  84. package/lib/rename-rewrite-chunk.handler.d.ts +35 -0
  85. package/lib/rename-rewrite-chunk.handler.js +2021 -0
  86. package/lib/rename-rewrite-chunk.handler.js.map +1 -0
  87. package/lib/rename-rewrite-chunk.handler.mjs +27 -0
  88. package/lib/rename-rewrite-chunk.handler.mjs.map +1 -0
  89. package/lib/rest-api-lambda.handler.js +4021 -932
  90. package/lib/rest-api-lambda.handler.js.map +1 -1
  91. package/lib/rest-api-lambda.handler.mjs +1786 -80
  92. package/lib/rest-api-lambda.handler.mjs.map +1 -1
  93. package/lib/seed-demo-data.handler.js +1588 -124
  94. package/lib/seed-demo-data.handler.js.map +1 -1
  95. package/lib/seed-demo-data.handler.mjs +10 -6
  96. package/lib/seed-system-data.handler.js +1179 -155
  97. package/lib/seed-system-data.handler.js.map +1 -1
  98. package/lib/seed-system-data.handler.mjs +5 -4
  99. package/lib/seed-system-data.handler.mjs.map +1 -1
  100. package/package.json +3 -3
  101. package/lib/chunk-2TPJ6HOF.mjs.map +0 -1
  102. package/lib/chunk-IS4VQRI4.mjs.map +0 -1
  103. package/lib/chunk-MULKGFIJ.mjs.map +0 -1
  104. package/lib/chunk-QR5JVSCF.mjs +0 -862
  105. package/lib/chunk-QR5JVSCF.mjs.map +0 -1
  106. package/lib/chunk-SYBADQXI.mjs.map +0 -1
  107. /package/lib/{chunk-7FUAMZOF.mjs.map → chunk-53OHXLIL.mjs.map} +0 -0
  108. /package/lib/{chunk-7Q2IJ2J5.mjs.map → chunk-CUUKXDB2.mjs.map} +0 -0
  109. /package/lib/{chunk-AJ3G3THO.mjs.map → chunk-KO64HPWQ.mjs.map} +0 -0
  110. /package/lib/{chunk-BB5MK4L3.mjs.map → chunk-KSFC72TT.mjs.map} +0 -0
  111. /package/lib/{chunk-AGF3RAAZ.mjs.map → chunk-WPCBVDFZ.mjs.map} +0 -0
@@ -1,862 +0,0 @@
1
- // src/data/dynamo/dynamo-control-service.ts
2
- import { Service } from "electrodb";
3
-
4
- // src/data/dynamo/dynamo-client.ts
5
- import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
6
- var defaultTableName = process.env.DYNAMO_TABLE_NAME ?? "jesttesttable";
7
- var dynamoClient = new DynamoDBClient({
8
- ...process.env.MOCK_DYNAMODB_ENDPOINT && {
9
- endpoint: process.env.MOCK_DYNAMODB_ENDPOINT,
10
- sslEnabled: false,
11
- region: "local"
12
- }
13
- });
14
-
15
- // src/data/dynamo/entities/control/configuration-entity.ts
16
- import { Entity } from "electrodb";
17
-
18
- // src/data/dynamo/entities/control/control-entity-common.ts
19
- import { extractLabel } from "@openhi/types";
20
-
21
- // src/data/dynamo/shard.ts
22
- var SHARD_COUNT = 4;
23
- function computeShard(id) {
24
- let hash = 2166136261;
25
- for (let i = 0; i < id.length; i++) {
26
- hash ^= id.charCodeAt(i);
27
- hash = Math.imul(hash, 16777619);
28
- }
29
- return (hash >>> 0) % SHARD_COUNT;
30
- }
31
-
32
- // src/data/dynamo/entities/control/control-entity-common.ts
33
- var gsi1ShardAttribute = {
34
- type: "string",
35
- watch: ["id"],
36
- set: (_val, item) => {
37
- if (typeof item?.id !== "string" || item.id.length === 0) {
38
- return void 0;
39
- }
40
- return String(computeShard(item.id));
41
- }
42
- };
43
- var gsi1skAttribute = {
44
- type: "string",
45
- watch: ["resource", "lastUpdated", "id"],
46
- set: (_val, item) => {
47
- const id = typeof item?.id === "string" ? item.id : "";
48
- const lastUpdated = typeof item?.lastUpdated === "string" ? item.lastUpdated : "";
49
- const fallback = `${lastUpdated}#${id}`;
50
- if (typeof item?.resource !== "string" || item.resource.length === 0) {
51
- return fallback;
52
- }
53
- let parsed;
54
- try {
55
- parsed = JSON.parse(item.resource);
56
- } catch {
57
- return fallback;
58
- }
59
- if (!parsed || typeof parsed !== "object") return fallback;
60
- const resourceType = parsed.resourceType;
61
- if (typeof resourceType !== "string") return fallback;
62
- const label = extractLabel(parsed);
63
- return label !== void 0 ? `${label}#${id}` : fallback;
64
- }
65
- };
66
-
67
- // src/data/dynamo/entities/control/configuration-entity.ts
68
- var ConfigurationEntity = new Entity({
69
- model: {
70
- entity: "configuration",
71
- service: "control",
72
- version: "01"
73
- },
74
- attributes: {
75
- /** Sort key. "CURRENT" for current version; version history in S3. */
76
- sk: {
77
- type: "string",
78
- required: true,
79
- default: "CURRENT"
80
- },
81
- /** Tenant scope. Use "BASELINE" when the config is baseline default (no tenant). */
82
- tenantId: {
83
- type: "string",
84
- required: true,
85
- default: "BASELINE"
86
- },
87
- /** Workspace scope. Use "-" when absent. */
88
- workspaceId: {
89
- type: "string",
90
- required: true,
91
- default: "-"
92
- },
93
- /** User scope. Use "-" when absent. */
94
- userId: {
95
- type: "string",
96
- required: true,
97
- default: "-"
98
- },
99
- /** Role scope. Use "-" when absent. */
100
- roleId: {
101
- type: "string",
102
- required: true,
103
- default: "-"
104
- },
105
- /** Config type (category), e.g. endpoints, branding, display. */
106
- key: {
107
- type: "string",
108
- required: true
109
- },
110
- /** FHIR Resource.id; logical id in URL and for the Configuration resource. */
111
- id: {
112
- type: "string",
113
- required: true
114
- },
115
- /** Payload as JSON string. JSON.stringify(resource) on write; JSON.parse(item.resource) on read. */
116
- resource: {
117
- type: "string",
118
- required: true
119
- },
120
- /**
121
- * Summary projection (key display fields as JSON string: id, key, status).
122
- * Populated on every write via extractSummary(resource); GSI1 INCLUDE surfaces it on lists.
123
- */
124
- summary: {
125
- type: "string",
126
- required: true
127
- },
128
- /** Version id (e.g. ULID). Tracks current version; S3 history key. */
129
- vid: {
130
- type: "string",
131
- required: true
132
- },
133
- lastUpdated: {
134
- type: "string",
135
- required: true
136
- },
137
- gsi1Shard: gsi1ShardAttribute,
138
- deleted: {
139
- type: "boolean",
140
- required: false
141
- },
142
- bundleId: {
143
- type: "string",
144
- required: false
145
- },
146
- msgId: {
147
- type: "string",
148
- required: false
149
- }
150
- },
151
- indexes: {
152
- /** 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. */
153
- record: {
154
- pk: {
155
- field: "PK",
156
- composite: ["tenantId", "workspaceId", "userId", "roleId"],
157
- template: "CONFIG#TID#${tenantId}#WID#${workspaceId}#UID#${userId}#RID#${roleId}"
158
- },
159
- sk: {
160
- field: "SK",
161
- composite: ["key", "sk"],
162
- template: "KEY#${key}#SK#${sk}"
163
- }
164
- },
165
- /**
166
- * GSI1 — Unified Sharded List per ADR-011: list all Configuration entries for a
167
- * (tenant, workspace) across the four shards. Use for "list configs scoped to this tenant"
168
- * (workspaceId = "-") or "list configs scoped to this workspace". Does not support
169
- * hierarchical resolution in one query; use base table GetItem in fallback order
170
- * (user → workspace → tenant → baseline) for that.
171
- * SK is `<key>#<id>` — Configuration's `key` is a required entity attribute (the
172
- * config category: endpoints, branding, display, …) and the natural sort/lookup
173
- * dimension. `casing: "none"` preserves the literal key value.
174
- */
175
- gsi1: {
176
- index: "GSI1",
177
- pk: {
178
- field: "GSI1PK",
179
- composite: ["tenantId", "workspaceId", "gsi1Shard"],
180
- template: "TID#${tenantId}#WID#${workspaceId}#RT#Configuration#SHARD#${gsi1Shard}"
181
- },
182
- sk: {
183
- field: "GSI1SK",
184
- casing: "none",
185
- composite: ["key", "id"],
186
- template: "${key}#${id}"
187
- }
188
- }
189
- }
190
- });
191
-
192
- // src/data/dynamo/entities/control/membership-entity.ts
193
- import { Entity as Entity2 } from "electrodb";
194
- var MembershipEntity = new Entity2({
195
- model: {
196
- entity: "membership",
197
- service: "control",
198
- version: "01"
199
- },
200
- attributes: {
201
- /** Sort key sentinel. Always "CURRENT". */
202
- sk: {
203
- type: "string",
204
- required: true,
205
- default: "CURRENT"
206
- },
207
- /** Tenant in which the user has membership (required). */
208
- tenantId: {
209
- type: "string",
210
- required: true
211
- },
212
- /** FHIR Resource.id; membership id. */
213
- id: {
214
- type: "string",
215
- required: true
216
- },
217
- /** Full Membership resource serialized as JSON string. */
218
- resource: {
219
- type: "string",
220
- required: true
221
- },
222
- /**
223
- * Summary projection (key display fields as JSON string: id, displayName, status).
224
- * Populated on every write via extractSummary(resource); GSI1 INCLUDE surfaces it on lists.
225
- */
226
- summary: {
227
- type: "string",
228
- required: true
229
- },
230
- /** Version id (e.g. ULID). */
231
- vid: {
232
- type: "string",
233
- required: true
234
- },
235
- lastUpdated: {
236
- type: "string",
237
- required: true
238
- },
239
- gsi1Shard: gsi1ShardAttribute,
240
- /** Derived GSI1 sort key — name-based when extractable; else `<lastUpdated>#<id>`. */
241
- gsi1sk: gsi1skAttribute,
242
- deleted: {
243
- type: "boolean",
244
- required: false
245
- },
246
- bundleId: {
247
- type: "string",
248
- required: false
249
- },
250
- msgId: {
251
- type: "string",
252
- required: false
253
- },
254
- /**
255
- * Denormalized `linked-data-identity` Reference (e.g. `Practitioner/abc`).
256
- * Populated from the FHIR extension on the Membership resource at write
257
- * time so future GSIs can index data-plane identity lookups without
258
- * deserializing the full resource JSON. See ADR 2026-03-13-02 §6.
259
- */
260
- linkedDataIdentityRef: {
261
- type: "string",
262
- required: false
263
- }
264
- },
265
- indexes: {
266
- /** Base table: PK = TID#<tenantId>#MEMBERSHIP#ID#<id>, SK = CURRENT. Do not supply PK or SK from outside. */
267
- record: {
268
- pk: {
269
- field: "PK",
270
- composite: ["tenantId", "id"],
271
- template: "TID#${tenantId}#MEMBERSHIP#ID#${id}"
272
- },
273
- sk: {
274
- field: "SK",
275
- composite: ["sk"],
276
- template: "${sk}"
277
- }
278
- },
279
- /**
280
- * GSI1 — Unified Sharded List per ADR-011: list all Memberships for a tenant across the
281
- * four shards. Membership is tenant-scoped only, so `WID#-` is a sentinel.
282
- * SK is derived via `gsi1skAttribute` — uses the resource's natural label when
283
- * extractable, else `<lastUpdated>#<id>` (DR-004). `casing: "none"` preserves the
284
- * normalized label and ISO-8601 `T`/`Z`.
285
- */
286
- gsi1: {
287
- index: "GSI1",
288
- pk: {
289
- field: "GSI1PK",
290
- composite: ["tenantId", "gsi1Shard"],
291
- template: "TID#${tenantId}#WID#-#RT#Membership#SHARD#${gsi1Shard}"
292
- },
293
- sk: {
294
- field: "GSI1SK",
295
- casing: "none",
296
- composite: ["gsi1sk"],
297
- template: "${gsi1sk}"
298
- }
299
- }
300
- }
301
- });
302
-
303
- // src/data/dynamo/entities/control/role-entity.ts
304
- import { Entity as Entity3 } from "electrodb";
305
- var RoleEntity = new Entity3({
306
- model: {
307
- entity: "role",
308
- service: "control",
309
- version: "01"
310
- },
311
- attributes: {
312
- /** Sort key sentinel. Always "CURRENT". */
313
- sk: {
314
- type: "string",
315
- required: true,
316
- default: "CURRENT"
317
- },
318
- /** FHIR Resource.id; role id. */
319
- id: {
320
- type: "string",
321
- required: true
322
- },
323
- /** Full Role resource serialized as JSON string. */
324
- resource: {
325
- type: "string",
326
- required: true
327
- },
328
- /**
329
- * Summary projection (key display fields as JSON string: id, displayName, status).
330
- * Populated on every write via extractSummary(resource); GSI1 INCLUDE surfaces it on lists.
331
- */
332
- summary: {
333
- type: "string",
334
- required: true
335
- },
336
- /** Version id (e.g. ULID). */
337
- vid: {
338
- type: "string",
339
- required: true
340
- },
341
- lastUpdated: {
342
- type: "string",
343
- required: true
344
- },
345
- gsi1Shard: gsi1ShardAttribute,
346
- /** Derived GSI1 sort key — name-based when extractable; else `<lastUpdated>#<id>`. */
347
- gsi1sk: gsi1skAttribute,
348
- deleted: {
349
- type: "boolean",
350
- required: false
351
- },
352
- bundleId: {
353
- type: "string",
354
- required: false
355
- },
356
- msgId: {
357
- type: "string",
358
- required: false
359
- }
360
- },
361
- indexes: {
362
- /** Base table: PK = ROLE#ID#<id>, SK = CURRENT. Do not supply PK or SK from outside. */
363
- record: {
364
- pk: {
365
- field: "PK",
366
- composite: ["id"],
367
- template: "ROLE#ID#${id}"
368
- },
369
- sk: {
370
- field: "SK",
371
- composite: ["sk"],
372
- template: "${sk}"
373
- }
374
- },
375
- /**
376
- * GSI1 — Unified Sharded List per ADR-011: list all Roles across the four shards.
377
- * Non-tenant-isolated, so `TID#-#WID#-` sentinels precede `RT#Role#SHARD#<n>`.
378
- * SK is derived via `gsi1skAttribute` — uses the resource's natural label when
379
- * extractable, else `<lastUpdated>#<id>` (DR-004). `casing: "none"` preserves the
380
- * normalized label and ISO-8601 `T`/`Z`.
381
- */
382
- gsi1: {
383
- index: "GSI1",
384
- pk: {
385
- field: "GSI1PK",
386
- composite: ["gsi1Shard"],
387
- template: "TID#-#WID#-#RT#Role#SHARD#${gsi1Shard}"
388
- },
389
- sk: {
390
- field: "GSI1SK",
391
- casing: "none",
392
- composite: ["gsi1sk"],
393
- template: "${gsi1sk}"
394
- }
395
- }
396
- }
397
- });
398
-
399
- // src/data/dynamo/entities/control/roleassignment-entity.ts
400
- import { Entity as Entity4 } from "electrodb";
401
- var RoleAssignmentEntity = new Entity4({
402
- model: {
403
- entity: "roleassignment",
404
- service: "control",
405
- version: "01"
406
- },
407
- attributes: {
408
- /** Sort key sentinel. Always "CURRENT". */
409
- sk: {
410
- type: "string",
411
- required: true,
412
- default: "CURRENT"
413
- },
414
- /** Tenant in which the role assignment applies (required). */
415
- tenantId: {
416
- type: "string",
417
- required: true
418
- },
419
- /** FHIR Resource.id; role assignment id. */
420
- id: {
421
- type: "string",
422
- required: true
423
- },
424
- /** Full RoleAssignment resource serialized as JSON string. */
425
- resource: {
426
- type: "string",
427
- required: true
428
- },
429
- /**
430
- * Summary projection (key display fields as JSON string: id, displayName, status).
431
- * Populated on every write via extractSummary(resource); GSI1 INCLUDE surfaces it on lists.
432
- */
433
- summary: {
434
- type: "string",
435
- required: true
436
- },
437
- /** Version id (e.g. ULID). */
438
- vid: {
439
- type: "string",
440
- required: true
441
- },
442
- lastUpdated: {
443
- type: "string",
444
- required: true
445
- },
446
- gsi1Shard: gsi1ShardAttribute,
447
- /** Derived GSI1 sort key — name-based when extractable; else `<lastUpdated>#<id>`. */
448
- gsi1sk: gsi1skAttribute,
449
- deleted: {
450
- type: "boolean",
451
- required: false
452
- },
453
- bundleId: {
454
- type: "string",
455
- required: false
456
- },
457
- msgId: {
458
- type: "string",
459
- required: false
460
- }
461
- },
462
- indexes: {
463
- /** Base table: PK = TID#<tenantId>#ROLEASSIGNMENT#ID#<id>, SK = CURRENT. Do not supply PK or SK from outside. */
464
- record: {
465
- pk: {
466
- field: "PK",
467
- composite: ["tenantId", "id"],
468
- template: "TID#${tenantId}#ROLEASSIGNMENT#ID#${id}"
469
- },
470
- sk: {
471
- field: "SK",
472
- composite: ["sk"],
473
- template: "${sk}"
474
- }
475
- },
476
- /**
477
- * GSI1 — Unified Sharded List per ADR-011: list all RoleAssignments for a tenant across the
478
- * four shards. Tenant-scoped only, so `WID#-` is a sentinel.
479
- * SK is derived via `gsi1skAttribute` — uses the resource's natural label when
480
- * extractable, else `<lastUpdated>#<id>` (DR-004). `casing: "none"` preserves the
481
- * normalized label and ISO-8601 `T`/`Z`.
482
- */
483
- gsi1: {
484
- index: "GSI1",
485
- pk: {
486
- field: "GSI1PK",
487
- composite: ["tenantId", "gsi1Shard"],
488
- template: "TID#${tenantId}#WID#-#RT#RoleAssignment#SHARD#${gsi1Shard}"
489
- },
490
- sk: {
491
- field: "GSI1SK",
492
- casing: "none",
493
- composite: ["gsi1sk"],
494
- template: "${gsi1sk}"
495
- }
496
- }
497
- }
498
- });
499
-
500
- // src/data/dynamo/entities/control/tenant-entity.ts
501
- import { Entity as Entity5 } from "electrodb";
502
- var TenantEntity = new Entity5({
503
- model: {
504
- entity: "tenant",
505
- service: "control",
506
- version: "01"
507
- },
508
- attributes: {
509
- /** Sort key sentinel. Always "CURRENT". */
510
- sk: {
511
- type: "string",
512
- required: true,
513
- default: "CURRENT"
514
- },
515
- /** The tenant's own id (= resource id). Drives the partition key. */
516
- tenantId: {
517
- type: "string",
518
- required: true
519
- },
520
- /** FHIR Resource.id; logical id in URL. Equals tenantId. */
521
- id: {
522
- type: "string",
523
- required: true
524
- },
525
- /** Full Tenant resource serialized as JSON string. */
526
- resource: {
527
- type: "string",
528
- required: true
529
- },
530
- /**
531
- * Summary projection (key display fields as JSON string: id, displayName, status).
532
- * Populated on every write via extractSummary(resource); GSI1 INCLUDE surfaces it on lists.
533
- */
534
- summary: {
535
- type: "string",
536
- required: true
537
- },
538
- /** Version id (e.g. ULID). */
539
- vid: {
540
- type: "string",
541
- required: true
542
- },
543
- lastUpdated: {
544
- type: "string",
545
- required: true
546
- },
547
- gsi1Shard: gsi1ShardAttribute,
548
- /** Derived GSI1 sort key — name-based when extractable; else `<lastUpdated>#<id>`. */
549
- gsi1sk: gsi1skAttribute,
550
- deleted: {
551
- type: "boolean",
552
- required: false
553
- },
554
- bundleId: {
555
- type: "string",
556
- required: false
557
- },
558
- msgId: {
559
- type: "string",
560
- required: false
561
- }
562
- },
563
- indexes: {
564
- /** Base table: PK = TENANT#ID#<tenantId>, SK = CURRENT. Do not supply PK or SK from outside. */
565
- record: {
566
- pk: {
567
- field: "PK",
568
- composite: ["tenantId"],
569
- template: "TENANT#ID#${tenantId}"
570
- },
571
- sk: {
572
- field: "SK",
573
- composite: ["sk"],
574
- template: "${sk}"
575
- }
576
- },
577
- /**
578
- * GSI1 — Unified Sharded List per ADR-011: list all Tenants across the four shards.
579
- * Tenant lives at the platform tier (no parent tenant or workspace), so `TID#-#WID#-`
580
- * sentinels precede `RT#Tenant#SHARD#<n>`. SK is derived via `gsi1skAttribute` —
581
- * `<normalizedName>#<id>` when the resource carries a `name`, else `<lastUpdated>#<id>`
582
- * (DR-004). `casing: "none"` preserves the normalized label and ISO-8601 `T`/`Z`.
583
- */
584
- gsi1: {
585
- index: "GSI1",
586
- pk: {
587
- field: "GSI1PK",
588
- composite: ["gsi1Shard"],
589
- template: "TID#-#WID#-#RT#Tenant#SHARD#${gsi1Shard}"
590
- },
591
- sk: {
592
- field: "GSI1SK",
593
- casing: "none",
594
- composite: ["gsi1sk"],
595
- template: "${gsi1sk}"
596
- }
597
- }
598
- }
599
- });
600
-
601
- // src/data/dynamo/entities/control/user-entity.ts
602
- import { Entity as Entity6 } from "electrodb";
603
- var UserEntity = new Entity6({
604
- model: {
605
- entity: "user",
606
- service: "control",
607
- version: "01"
608
- },
609
- attributes: {
610
- /** Sort key sentinel. Always "CURRENT". */
611
- sk: {
612
- type: "string",
613
- required: true,
614
- default: "CURRENT"
615
- },
616
- /** FHIR Resource.id; platform user id (ohi_uid). */
617
- id: {
618
- type: "string",
619
- required: true
620
- },
621
- /** Full User resource serialized as JSON string. */
622
- resource: {
623
- type: "string",
624
- required: true
625
- },
626
- /**
627
- * Summary projection (key display fields as JSON string: id, displayName, status).
628
- * Populated on every write via extractSummary(resource); GSI1 INCLUDE surfaces it on lists.
629
- */
630
- summary: {
631
- type: "string",
632
- required: true
633
- },
634
- /**
635
- * Immutable Cognito-issued `sub` claim. Drives GSI2 (sub-lookup). Optional until the
636
- * Post Confirmation Lambda (#770) lands; required thereafter.
637
- */
638
- cognitoSub: {
639
- type: "string",
640
- required: false
641
- },
642
- /** Version id (e.g. ULID). */
643
- vid: {
644
- type: "string",
645
- required: true
646
- },
647
- lastUpdated: {
648
- type: "string",
649
- required: true
650
- },
651
- gsi1Shard: gsi1ShardAttribute,
652
- /** Derived GSI1 sort key — name-based when extractable; else `<lastUpdated>#<id>`. */
653
- gsi1sk: gsi1skAttribute,
654
- deleted: {
655
- type: "boolean",
656
- required: false
657
- },
658
- bundleId: {
659
- type: "string",
660
- required: false
661
- },
662
- msgId: {
663
- type: "string",
664
- required: false
665
- }
666
- },
667
- indexes: {
668
- /** Base table: PK = USER#ID#<id>, SK = CURRENT. Do not supply PK or SK from outside. */
669
- record: {
670
- pk: {
671
- field: "PK",
672
- composite: ["id"],
673
- template: "USER#ID#${id}"
674
- },
675
- sk: {
676
- field: "SK",
677
- composite: ["sk"],
678
- template: "${sk}"
679
- }
680
- },
681
- /**
682
- * GSI1 — Unified Sharded List per ADR-011: list all Users across the four shards.
683
- * Non-tenant-isolated, so `TID#-#WID#-` sentinels precede `RT#User#SHARD#<n>`.
684
- * SK is derived via `gsi1skAttribute` — uses the resource's natural label when
685
- * extractable (string `name`/`title` via introspection), else `<lastUpdated>#<id>`
686
- * (DR-004). `casing: "none"` preserves the normalized label and ISO-8601 `T`/`Z`.
687
- */
688
- gsi1: {
689
- index: "GSI1",
690
- pk: {
691
- field: "GSI1PK",
692
- composite: ["gsi1Shard"],
693
- template: "TID#-#WID#-#RT#User#SHARD#${gsi1Shard}"
694
- },
695
- sk: {
696
- field: "GSI1SK",
697
- casing: "none",
698
- composite: ["gsi1sk"],
699
- template: "${gsi1sk}"
700
- }
701
- },
702
- /**
703
- * GSI2 — Cognito sub-lookup per ADR-011: resolves the UserEntity from a Cognito `sub` claim.
704
- * `condition` skips the index when `cognitoSub` is missing so legacy items without a sub are
705
- * not indexed.
706
- */
707
- gsi2: {
708
- index: "GSI2",
709
- condition: (attrs) => typeof attrs.cognitoSub === "string" && attrs.cognitoSub.length > 0,
710
- pk: {
711
- field: "GSI2PK",
712
- casing: "none",
713
- composite: ["cognitoSub"],
714
- template: "USER#SUB#${cognitoSub}"
715
- },
716
- sk: {
717
- field: "GSI2SK",
718
- casing: "none",
719
- composite: [],
720
- template: "CURRENT"
721
- }
722
- }
723
- }
724
- });
725
-
726
- // src/data/dynamo/entities/control/workspace-entity.ts
727
- import { Entity as Entity7 } from "electrodb";
728
- var WorkspaceEntity = new Entity7({
729
- model: {
730
- entity: "workspace",
731
- service: "control",
732
- version: "01"
733
- },
734
- attributes: {
735
- /** Sort key sentinel. Always "CURRENT". */
736
- sk: {
737
- type: "string",
738
- required: true,
739
- default: "CURRENT"
740
- },
741
- /** Tenant that contains this workspace (required). */
742
- tenantId: {
743
- type: "string",
744
- required: true
745
- },
746
- /** FHIR Resource.id; logical id in URL. */
747
- id: {
748
- type: "string",
749
- required: true
750
- },
751
- /** Full Workspace resource serialized as JSON string. */
752
- resource: {
753
- type: "string",
754
- required: true
755
- },
756
- /**
757
- * Summary projection (key display fields as JSON string: id, displayName, status).
758
- * Populated on every write via extractSummary(resource); GSI1 INCLUDE surfaces it on lists.
759
- */
760
- summary: {
761
- type: "string",
762
- required: true
763
- },
764
- /** Version id (e.g. ULID). */
765
- vid: {
766
- type: "string",
767
- required: true
768
- },
769
- lastUpdated: {
770
- type: "string",
771
- required: true
772
- },
773
- gsi1Shard: gsi1ShardAttribute,
774
- /** Derived GSI1 sort key — name-based when extractable; else `<lastUpdated>#<id>`. */
775
- gsi1sk: gsi1skAttribute,
776
- deleted: {
777
- type: "boolean",
778
- required: false
779
- },
780
- bundleId: {
781
- type: "string",
782
- required: false
783
- },
784
- msgId: {
785
- type: "string",
786
- required: false
787
- }
788
- },
789
- indexes: {
790
- /** Base table: PK = TID#<tenantId>#WORKSPACE#ID#<id>, SK = CURRENT. Do not supply PK or SK from outside. */
791
- record: {
792
- pk: {
793
- field: "PK",
794
- composite: ["tenantId", "id"],
795
- template: "TID#${tenantId}#WORKSPACE#ID#${id}"
796
- },
797
- sk: {
798
- field: "SK",
799
- composite: ["sk"],
800
- template: "${sk}"
801
- }
802
- },
803
- /**
804
- * GSI1 — Unified Sharded List per ADR-011: list all Workspaces for a tenant across the
805
- * four shards. Workspace is itself the workspace identity, so `WID#-` is a sentinel.
806
- * SK is derived via `gsi1skAttribute` — `<normalizedName>#<id>` when the resource
807
- * carries a `name`, else `<lastUpdated>#<id>` (DR-004). `casing: "none"` preserves
808
- * the normalized label and ISO-8601 `T`/`Z`.
809
- */
810
- gsi1: {
811
- index: "GSI1",
812
- pk: {
813
- field: "GSI1PK",
814
- composite: ["tenantId", "gsi1Shard"],
815
- template: "TID#${tenantId}#WID#-#RT#Workspace#SHARD#${gsi1Shard}"
816
- },
817
- sk: {
818
- field: "GSI1SK",
819
- casing: "none",
820
- composite: ["gsi1sk"],
821
- template: "${gsi1sk}"
822
- }
823
- }
824
- }
825
- });
826
-
827
- // src/data/dynamo/dynamo-control-service.ts
828
- var controlPlaneEntities = {
829
- configuration: ConfigurationEntity,
830
- membership: MembershipEntity,
831
- role: RoleEntity,
832
- roleAssignment: RoleAssignmentEntity,
833
- tenant: TenantEntity,
834
- user: UserEntity,
835
- workspace: WorkspaceEntity
836
- };
837
- var controlPlaneService = new Service(controlPlaneEntities, {
838
- table: defaultTableName,
839
- client: dynamoClient
840
- });
841
- var DynamoControlService = {
842
- entities: controlPlaneService.entities
843
- };
844
- function getDynamoControlService(tableName) {
845
- const resolved = tableName ?? defaultTableName;
846
- const service = new Service(controlPlaneEntities, {
847
- table: resolved,
848
- client: dynamoClient
849
- });
850
- return {
851
- entities: service.entities
852
- };
853
- }
854
-
855
- export {
856
- defaultTableName,
857
- dynamoClient,
858
- SHARD_COUNT,
859
- computeShard,
860
- getDynamoControlService
861
- };
862
- //# sourceMappingURL=chunk-QR5JVSCF.mjs.map