@openhi/constructs 0.0.105 → 0.0.107
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/chunk-36UPY7YQ.mjs +529 -0
- package/lib/chunk-36UPY7YQ.mjs.map +1 -0
- package/lib/chunk-AGF3RAAZ.mjs +20 -0
- package/lib/chunk-AGF3RAAZ.mjs.map +1 -0
- package/lib/{chunk-BXEG7IOZ.mjs → chunk-AO3E22CS.mjs} +2 -2
- package/lib/{chunk-WNUH2WDZ.mjs → chunk-CHPEQRXU.mjs} +2 -2
- package/lib/chunk-JUNL76HF.mjs +428 -0
- package/lib/chunk-JUNL76HF.mjs.map +1 -0
- package/lib/chunk-L6UAP4KP.mjs +27 -0
- package/lib/chunk-L6UAP4KP.mjs.map +1 -0
- package/lib/{chunk-3QS3WKRC.mjs → chunk-LZOMFHX3.mjs} +9 -2
- package/lib/chunk-SYBADQXI.mjs +607 -0
- package/lib/chunk-SYBADQXI.mjs.map +1 -0
- package/lib/chunk-VXX4I3EF.mjs +19 -0
- package/lib/chunk-VXX4I3EF.mjs.map +1 -0
- package/lib/{chunk-36YCDLLA.mjs → chunk-VYDIGFIX.mjs} +75 -481
- package/lib/chunk-VYDIGFIX.mjs.map +1 -0
- package/lib/chunk-YU2HRNUP.mjs +33 -0
- package/lib/chunk-YU2HRNUP.mjs.map +1 -0
- package/lib/chunk-YZZDUJHI.mjs +37 -0
- package/lib/chunk-YZZDUJHI.mjs.map +1 -0
- package/lib/cors-options-lambda.handler.mjs +1 -1
- package/lib/data-store-postgres-replication.handler.mjs +1 -1
- package/lib/events-BfrkMoBD.d.mts +44 -0
- package/lib/events-BfrkMoBD.d.ts +44 -0
- package/lib/events-DPodvl07.d.mts +207 -0
- package/lib/events-DPodvl07.d.ts +207 -0
- package/lib/firehose-archive-transform.handler.mjs +1 -1
- package/lib/index.d.mts +417 -9
- package/lib/index.d.ts +663 -10
- package/lib/index.js +2398 -111
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +779 -104
- package/lib/index.mjs.map +1 -1
- package/lib/openhi-context-CaBH8SFo.d.mts +39 -0
- package/lib/openhi-context-CaBH8SFo.d.ts +39 -0
- package/lib/platform-deploy-bridge.handler.d.mts +14 -0
- package/lib/platform-deploy-bridge.handler.d.ts +14 -0
- package/lib/platform-deploy-bridge.handler.js +762 -0
- package/lib/platform-deploy-bridge.handler.js.map +1 -0
- package/lib/platform-deploy-bridge.handler.mjs +134 -0
- package/lib/platform-deploy-bridge.handler.mjs.map +1 -0
- package/lib/post-authentication.handler.mjs +1 -1
- package/lib/post-confirmation.handler.mjs +1 -1
- package/lib/pre-token-generation.handler.js +76 -31
- package/lib/pre-token-generation.handler.js.map +1 -1
- package/lib/pre-token-generation.handler.mjs +5 -3
- package/lib/pre-token-generation.handler.mjs.map +1 -1
- package/lib/provision-default-workspace.handler.js +86 -41
- package/lib/provision-default-workspace.handler.js.map +1 -1
- package/lib/provision-default-workspace.handler.mjs +6 -4
- package/lib/provision-default-workspace.handler.mjs.map +1 -1
- package/lib/rest-api-lambda.handler.js +114 -59
- package/lib/rest-api-lambda.handler.js.map +1 -1
- package/lib/rest-api-lambda.handler.mjs +40 -61
- package/lib/rest-api-lambda.handler.mjs.map +1 -1
- package/lib/seed-demo-data.handler.d.mts +107 -0
- package/lib/seed-demo-data.handler.d.ts +107 -0
- package/lib/seed-demo-data.handler.js +2037 -0
- package/lib/seed-demo-data.handler.js.map +1 -0
- package/lib/seed-demo-data.handler.mjs +23 -0
- package/lib/seed-demo-data.handler.mjs.map +1 -0
- package/lib/seed-system-data.handler.d.mts +64 -0
- package/lib/seed-system-data.handler.d.ts +64 -0
- package/lib/seed-system-data.handler.js +1631 -0
- package/lib/seed-system-data.handler.js.map +1 -0
- package/lib/seed-system-data.handler.mjs +135 -0
- package/lib/seed-system-data.handler.mjs.map +1 -0
- package/package.json +4 -2
- package/lib/chunk-36YCDLLA.mjs.map +0 -1
- /package/lib/{chunk-BXEG7IOZ.mjs.map → chunk-AO3E22CS.mjs.map} +0 -0
- /package/lib/{chunk-WNUH2WDZ.mjs.map → chunk-CHPEQRXU.mjs.map} +0 -0
- /package/lib/{chunk-3QS3WKRC.mjs.map → chunk-LZOMFHX3.mjs.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/data/dynamo/dynamo-control-service.ts","../src/data/dynamo/dynamo-client.ts","../src/data/dynamo/entities/control/configuration-entity.ts","../src/data/dynamo/entities/control/control-entity-common.ts","../src/data/dynamo/shard.ts","../src/data/dynamo/entities/control/membership-entity.ts","../src/data/dynamo/entities/control/role-entity.ts","../src/data/dynamo/entities/control/roleassignment-entity.ts","../src/data/dynamo/entities/control/tenant-entity.ts","../src/data/dynamo/entities/control/user-entity.ts","../src/data/dynamo/entities/control/workspace-entity.ts"],"sourcesContent":["import { Service } from \"electrodb\";\nimport { defaultTableName, dynamoClient } from \"./dynamo-client\";\nimport { ConfigurationEntity } from \"./entities/control/configuration-entity\";\nimport { MembershipEntity } from \"./entities/control/membership-entity\";\nimport { RoleEntity } from \"./entities/control/role-entity\";\nimport { RoleAssignmentEntity } from \"./entities/control/roleassignment-entity\";\nimport { TenantEntity } from \"./entities/control/tenant-entity\";\nimport { UserEntity } from \"./entities/control/user-entity\";\nimport { WorkspaceEntity } from \"./entities/control/workspace-entity\";\n\n/**\n * Control-plane entities only (service \"control\"). Same table as data plane; use\n * DynamoDataService for data-plane entities.\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n * @see sites/www-docs/content/architecture/adr/2026-03-03-01-tenant-isolated-vs-non-tenant-isolated-entities.md\n */\n\nconst controlPlaneEntities = {\n configuration: ConfigurationEntity,\n membership: MembershipEntity,\n role: RoleEntity,\n roleAssignment: RoleAssignmentEntity,\n tenant: TenantEntity,\n user: UserEntity,\n workspace: WorkspaceEntity,\n};\n\nconst controlPlaneService = new Service(controlPlaneEntities, {\n table: defaultTableName,\n client: dynamoClient,\n});\n\n/**\n * Control-plane service: entities for configuration and control. Use with the\n * data store table (PK, SK, GSI1; UserEntity also uses GSI2).\n */\nexport const DynamoControlService = {\n entities: controlPlaneService.entities,\n};\n\nexport type DynamoControlServiceType = typeof DynamoControlService;\n\n/**\n * Returns the control-plane service. Table name is resolved from tableName (optional override),\n * then DYNAMO_TABLE_NAME, then \"jesttesttable\".\n */\nexport function getDynamoControlService(\n tableName?: string,\n): DynamoControlServiceType {\n const resolved = tableName ?? defaultTableName;\n const service = new Service(controlPlaneEntities, {\n table: resolved,\n client: dynamoClient,\n });\n return {\n entities: service.entities,\n };\n}\n","import { DynamoDBClient } from \"@aws-sdk/client-dynamodb\";\n\n/**\n * DynamoDB table name for the data store. Set via DYNAMO_TABLE_NAME at runtime\n * (e.g. from Lambda env); defaults for local/test.\n */\nexport const defaultTableName =\n process.env.DYNAMO_TABLE_NAME ?? \"jesttesttable\";\n\n/**\n * DynamoDB client. When MOCK_DYNAMODB_ENDPOINT is set (e.g. local DynamoDB or\n * jest-dynalite), uses that endpoint with no SSL and region \"local\".\n */\nexport const dynamoClient = new DynamoDBClient({\n ...(process.env.MOCK_DYNAMODB_ENDPOINT && {\n endpoint: process.env.MOCK_DYNAMODB_ENDPOINT,\n sslEnabled: false,\n region: \"local\",\n }),\n});\n","import { Entity } from \"electrodb\";\nimport { gsi1ShardAttribute } from \"./control-entity-common\";\n\n/**\n * Configuration data-store entity (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Partially tenant-isolated, control plane. Cascade of scope\n * levels: resolution order user → workspace → tenant → baseline. Sentinels: tenantId \"BASELINE\" for\n * baseline tier; workspaceId/userId/roleId \"-\" for absent dimension.\n *\n * Key structure: PK = CONFIG#TID#<tenantId>#WID#<workspaceId>#UID#<userId>#RID#<roleId>,\n * SK = KEY#<key>#SK#<sk>. Uniqueness: one Configuration per (tenantId, workspaceId, userId, roleId, key).\n * Standard attributes and key-building conventions align with single-table design.\n *\n * GSI1 — Unified Sharded List per ADR-011: lists all Configuration entries in a tenant/workspace\n * across the four shards.\n *\n * @see sites/www-docs/content/architecture/adr/2026-03-03-01-tenant-isolated-vs-non-tenant-isolated-entities.md\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/entities/configuration.md\n * @see sites/www-docs/content/architecture/control-plane/configuration.md\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/entity-standards.md — Key-building conventions (keys built inside entity)\n */\nexport const ConfigurationEntity = new Entity({\n model: {\n entity: \"configuration\",\n service: \"control\",\n version: \"01\",\n },\n attributes: {\n /** Sort key. \"CURRENT\" for current version; version history in S3. */\n sk: {\n type: \"string\" as const,\n required: true,\n default: \"CURRENT\",\n },\n /** Tenant scope. Use \"BASELINE\" when the config is baseline default (no tenant). */\n tenantId: {\n type: \"string\" as const,\n required: true,\n default: \"BASELINE\",\n },\n /** Workspace scope. Use \"-\" when absent. */\n workspaceId: {\n type: \"string\" as const,\n required: true,\n default: \"-\",\n },\n /** User scope. Use \"-\" when absent. */\n userId: {\n type: \"string\" as const,\n required: true,\n default: \"-\",\n },\n /** Role scope. Use \"-\" when absent. */\n roleId: {\n type: \"string\" as const,\n required: true,\n default: \"-\",\n },\n /** Config type (category), e.g. endpoints, branding, display. */\n key: {\n type: \"string\" as const,\n required: true,\n },\n /** FHIR Resource.id; logical id in URL and for the Configuration resource. */\n id: {\n type: \"string\" as const,\n required: true,\n },\n /** Payload as JSON string. JSON.stringify(resource) on write; JSON.parse(item.resource) on read. */\n resource: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Summary projection (key display fields as JSON string: id, key, status).\n * Populated on every write via extractSummary(resource); GSI1 INCLUDE surfaces it on lists.\n */\n summary: {\n type: \"string\" as const,\n required: true,\n },\n /** Version id (e.g. ULID). Tracks current version; S3 history key. */\n vid: {\n type: \"string\" as const,\n required: true,\n },\n lastUpdated: {\n type: \"string\" as const,\n required: true,\n },\n gsi1Shard: gsi1ShardAttribute,\n deleted: {\n type: \"boolean\" as const,\n required: false,\n },\n bundleId: {\n type: \"string\" as const,\n required: false,\n },\n msgId: {\n type: \"string\" as const,\n required: false,\n },\n },\n indexes: {\n /** 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. */\n record: {\n pk: {\n field: \"PK\",\n composite: [\"tenantId\", \"workspaceId\", \"userId\", \"roleId\"],\n template:\n \"CONFIG#TID#${tenantId}#WID#${workspaceId}#UID#${userId}#RID#${roleId}\",\n },\n sk: {\n field: \"SK\",\n composite: [\"key\", \"sk\"],\n template: \"KEY#${key}#SK#${sk}\",\n },\n },\n\n /**\n * GSI1 — Unified Sharded List per ADR-011: list all Configuration entries for a\n * (tenant, workspace) across the four shards. Use for \"list configs scoped to this tenant\"\n * (workspaceId = \"-\") or \"list configs scoped to this workspace\". Does not support\n * hierarchical resolution in one query; use base table GetItem in fallback order\n * (user → workspace → tenant → baseline) for that.\n * SK is `<key>#<id>` — Configuration's `key` is a required entity attribute (the\n * config category: endpoints, branding, display, …) and the natural sort/lookup\n * dimension. `casing: \"none\"` preserves the literal key value.\n */\n gsi1: {\n index: \"GSI1\",\n pk: {\n field: \"GSI1PK\",\n composite: [\"tenantId\", \"workspaceId\", \"gsi1Shard\"],\n template:\n \"TID#${tenantId}#WID#${workspaceId}#RT#Configuration#SHARD#${gsi1Shard}\",\n },\n sk: {\n field: \"GSI1SK\",\n casing: \"none\" as const,\n composite: [\"key\", \"id\"],\n template: \"${key}#${id}\",\n },\n },\n },\n});\n","import { extractLabel } from \"@openhi/types\";\nimport { computeShard } from \"../../shard\";\n\n/**\n * Shared GSI1 shard attribute for control-plane entities.\n *\n * Control-plane entities (User, Tenant, Workspace, Membership, Role, RoleAssignment,\n * Configuration) use the same `TID#/WID#/RT#/SHARD#` PK shape on GSI1 as data-plane\n * FHIR resources per ADR-011. The shard index is derived deterministically from `id`\n * via `computeShard` so updates always land on the same shard. Stored as a string\n * because it appears as a literal segment in the GSI1 PK template; the underlying\n * value is 0..3.\n *\n * Not `required` because the value is derived via `watch`/`set`; ElectroDB's\n * required-field check runs before watch propagation, so callers must not fail\n * validation on a derived field.\n */\nexport const gsi1ShardAttribute = {\n type: \"string\" as const,\n watch: [\"id\"] as const,\n set: (_val?: string, item?: { id?: string }) => {\n if (typeof item?.id !== \"string\" || item.id.length === 0) {\n return undefined;\n }\n return String(computeShard(item.id));\n },\n};\n\n/**\n * Shared GSI1 sort-key attribute for control-plane entities.\n *\n * Derives the GSI1SK value at write time from the entity's `resource` JSON\n * string, applying the same label-extraction strategy as the data plane\n * (DR-004 / `@openhi/types` `extractLabel`). When the resource carries a\n * natural label (Tenant.name, Workspace.name, Configuration.key, …) the\n * sort key is `<normalizedLabel>#<id>` so list endpoints sort alphabetically\n * and `BEGINS_WITH` queries serve prefix searches. When no label is\n * extractable, falls back to `<entity.lastUpdated>#<id>` for stable\n * reverse-chronological ordering.\n *\n * Falls back gracefully on malformed `resource` payloads — JSON parse\n * failures and missing fields both route to the lastUpdated fallback so a\n * single bad write never blocks an entity put. The entity-level\n * `lastUpdated` is preferred over `resource.meta.lastUpdated` so the\n * fallback uses the authoritative timestamp the entity write supplies.\n *\n * Not `required` because the value is derived via `watch`/`set`.\n */\nexport const gsi1skAttribute = {\n type: \"string\" as const,\n watch: [\"resource\", \"lastUpdated\", \"id\"] as const,\n set: (\n _val?: string,\n item?: { resource?: string; lastUpdated?: string; id?: string },\n ) => {\n const id = typeof item?.id === \"string\" ? item.id : \"\";\n const lastUpdated =\n typeof item?.lastUpdated === \"string\" ? item.lastUpdated : \"\";\n const fallback = `${lastUpdated}#${id}`;\n\n if (typeof item?.resource !== \"string\" || item.resource.length === 0) {\n return fallback;\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(item.resource);\n } catch {\n return fallback;\n }\n if (!parsed || typeof parsed !== \"object\") return fallback;\n const resourceType = (parsed as { resourceType?: unknown }).resourceType;\n if (typeof resourceType !== \"string\") return fallback;\n\n const label = extractLabel(parsed as Parameters<typeof extractLabel>[0]);\n return label !== undefined ? `${label}#${id}` : fallback;\n },\n};\n","/**\n * Shard selection for the data-plane single-table GSI1 partitioning per ADR-011.\n *\n * GSI1's partition key embeds a `SHARD#<n>` segment with `n = computeShard(id)`.\n * The hash is deterministic so updates to the same resource id always land on\n * the same shard (no cross-shard migration on update); reads fan out to all\n * shards in parallel and merge by SK.\n *\n * @see sites/www-docs/content/architecture/adr/ — ADR-011 (single-table DynamoDB)\n */\n\n/** Number of shards in the GSI1 partition key. Fixed at 4 in v1; raising it later is a backfill, not a schema migration. */\nexport const SHARD_COUNT = 4;\n\n/**\n * Returns a deterministic shard index in [0, SHARD_COUNT) for the given resource id.\n *\n * Implementation: 32-bit FNV-1a over the UTF-16 code units of the id, modulo SHARD_COUNT.\n * The function is pure and stable; the same id always returns the same shard.\n *\n * ESLint's `no-bitwise` rule is disabled inside this function because FNV-1a is\n * defined in terms of XOR and unsigned-right-shift — the bitwise ops are the\n * algorithm, not an accidental logical-operator confusion.\n */\nexport function computeShard(id: string): number {\n /* eslint-disable no-bitwise */\n let hash = 0x811c9dc5;\n for (let i = 0; i < id.length; i++) {\n hash ^= id.charCodeAt(i);\n hash = Math.imul(hash, 0x01000193);\n }\n return (hash >>> 0) % SHARD_COUNT;\n /* eslint-enable no-bitwise */\n}\n","import { Entity } from \"electrodb\";\nimport { gsi1ShardAttribute, gsi1skAttribute } from \"./control-entity-common\";\n\n/**\n * Membership data-store entity (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, control plane. Membership links a User\n * to a Tenant (and optionally a Workspace). One record per (tenantId, id).\n *\n * Key structure: PK = TID#<tenantId>#MEMBERSHIP#ID#<id>, SK = CURRENT.\n * Uniqueness: one Membership per (tenantId, id).\n *\n * GSI1 — Unified Sharded List per ADR-011: lists all Memberships in a tenant across the four\n * shards. Membership is tenant-scoped (not workspace-scoped), so the GSI1 PK uses `WID#-` as a\n * sentinel.\n *\n * @see sites/www-docs/content/architecture/adr/2026-03-03-01-tenant-isolated-vs-non-tenant-isolated-entities.md\n * @see sites/www-docs/content/architecture/adr/2026-03-13-02-control-plane-roles-and-user-tenant-workspace-linkage.md\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MembershipEntity = new Entity({\n model: {\n entity: \"membership\",\n service: \"control\",\n version: \"01\",\n },\n attributes: {\n /** Sort key sentinel. Always \"CURRENT\". */\n sk: {\n type: \"string\" as const,\n required: true,\n default: \"CURRENT\",\n },\n /** Tenant in which the user has membership (required). */\n tenantId: {\n type: \"string\" as const,\n required: true,\n },\n /** FHIR Resource.id; membership id. */\n id: {\n type: \"string\" as const,\n required: true,\n },\n /** Full Membership resource serialized as JSON string. */\n resource: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Summary projection (key display fields as JSON string: id, displayName, status).\n * Populated on every write via extractSummary(resource); GSI1 INCLUDE surfaces it on lists.\n */\n summary: {\n type: \"string\" as const,\n required: true,\n },\n /** Version id (e.g. ULID). */\n vid: {\n type: \"string\" as const,\n required: true,\n },\n lastUpdated: {\n type: \"string\" as const,\n required: true,\n },\n gsi1Shard: gsi1ShardAttribute,\n /** Derived GSI1 sort key — name-based when extractable; else `<lastUpdated>#<id>`. */\n gsi1sk: gsi1skAttribute,\n deleted: {\n type: \"boolean\" as const,\n required: false,\n },\n bundleId: {\n type: \"string\" as const,\n required: false,\n },\n msgId: {\n type: \"string\" as const,\n required: false,\n },\n },\n indexes: {\n /** Base table: PK = TID#<tenantId>#MEMBERSHIP#ID#<id>, SK = CURRENT. Do not supply PK or SK from outside. */\n record: {\n pk: {\n field: \"PK\",\n composite: [\"tenantId\", \"id\"],\n template: \"TID#${tenantId}#MEMBERSHIP#ID#${id}\",\n },\n sk: {\n field: \"SK\",\n composite: [\"sk\"],\n template: \"${sk}\",\n },\n },\n\n /**\n * GSI1 — Unified Sharded List per ADR-011: list all Memberships for a tenant across the\n * four shards. Membership is tenant-scoped only, so `WID#-` is a sentinel.\n * SK is derived via `gsi1skAttribute` — uses the resource's natural label when\n * extractable, else `<lastUpdated>#<id>` (DR-004). `casing: \"none\"` preserves the\n * normalized label and ISO-8601 `T`/`Z`.\n */\n gsi1: {\n index: \"GSI1\",\n pk: {\n field: \"GSI1PK\",\n composite: [\"tenantId\", \"gsi1Shard\"],\n template: \"TID#${tenantId}#WID#-#RT#Membership#SHARD#${gsi1Shard}\",\n },\n sk: {\n field: \"GSI1SK\",\n casing: \"none\" as const,\n composite: [\"gsi1sk\"],\n template: \"${gsi1sk}\",\n },\n },\n },\n});\n","import { Entity } from \"electrodb\";\nimport { gsi1ShardAttribute, gsi1skAttribute } from \"./control-entity-common\";\n\n/**\n * Role data-store entity (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Non-tenant-isolated, control plane. Role is a\n * platform-wide role catalog (e.g. tenant-admin, tenant-user, system-admin); not scoped by tenant.\n * RoleAssignment references Role to assign a role to a User in a Tenant/Workspace context.\n *\n * Key structure: PK = ROLE#ID#<id>, SK = CURRENT.\n * The ROLE# prefix prevents key collisions with other non-tenant-isolated entities (User, etc.)\n * sharing the same table (ADR 2026-03-11-01 — preferred pattern for all control plane entities).\n * Uniqueness: one Role per id.\n *\n * GSI1 — Unified Sharded List per ADR-011: lists all Roles across the four shards. Non-tenant-\n * isolated, so the PK uses `TID#-#WID#-` sentinels.\n *\n * @see sites/www-docs/content/architecture/adr/2026-03-03-01-tenant-isolated-vs-non-tenant-isolated-entities.md\n * @see sites/www-docs/content/architecture/adr/2026-03-13-02-control-plane-roles-and-user-tenant-workspace-linkage.md\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const RoleEntity = new Entity({\n model: {\n entity: \"role\",\n service: \"control\",\n version: \"01\",\n },\n attributes: {\n /** Sort key sentinel. Always \"CURRENT\". */\n sk: {\n type: \"string\" as const,\n required: true,\n default: \"CURRENT\",\n },\n /** FHIR Resource.id; role id. */\n id: {\n type: \"string\" as const,\n required: true,\n },\n /** Full Role resource serialized as JSON string. */\n resource: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Summary projection (key display fields as JSON string: id, displayName, status).\n * Populated on every write via extractSummary(resource); GSI1 INCLUDE surfaces it on lists.\n */\n summary: {\n type: \"string\" as const,\n required: true,\n },\n /** Version id (e.g. ULID). */\n vid: {\n type: \"string\" as const,\n required: true,\n },\n lastUpdated: {\n type: \"string\" as const,\n required: true,\n },\n gsi1Shard: gsi1ShardAttribute,\n /** Derived GSI1 sort key — name-based when extractable; else `<lastUpdated>#<id>`. */\n gsi1sk: gsi1skAttribute,\n deleted: {\n type: \"boolean\" as const,\n required: false,\n },\n bundleId: {\n type: \"string\" as const,\n required: false,\n },\n msgId: {\n type: \"string\" as const,\n required: false,\n },\n },\n indexes: {\n /** Base table: PK = ROLE#ID#<id>, SK = CURRENT. Do not supply PK or SK from outside. */\n record: {\n pk: {\n field: \"PK\",\n composite: [\"id\"],\n template: \"ROLE#ID#${id}\",\n },\n sk: {\n field: \"SK\",\n composite: [\"sk\"],\n template: \"${sk}\",\n },\n },\n\n /**\n * GSI1 — Unified Sharded List per ADR-011: list all Roles across the four shards.\n * Non-tenant-isolated, so `TID#-#WID#-` sentinels precede `RT#Role#SHARD#<n>`.\n * SK is derived via `gsi1skAttribute` — uses the resource's natural label when\n * extractable, else `<lastUpdated>#<id>` (DR-004). `casing: \"none\"` preserves the\n * normalized label and ISO-8601 `T`/`Z`.\n */\n gsi1: {\n index: \"GSI1\",\n pk: {\n field: \"GSI1PK\",\n composite: [\"gsi1Shard\"],\n template: \"TID#-#WID#-#RT#Role#SHARD#${gsi1Shard}\",\n },\n sk: {\n field: \"GSI1SK\",\n casing: \"none\" as const,\n composite: [\"gsi1sk\"],\n template: \"${gsi1sk}\",\n },\n },\n },\n});\n","import { Entity } from \"electrodb\";\nimport { gsi1ShardAttribute, gsi1skAttribute } from \"./control-entity-common\";\n\n/**\n * RoleAssignment data-store entity (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, control plane. RoleAssignment assigns\n * a Role to a User in a Tenant (and optionally Workspace) context.\n *\n * Key structure: PK = TID#<tenantId>#ROLEASSIGNMENT#ID#<id>, SK = CURRENT.\n * Uniqueness: one RoleAssignment per (tenantId, id).\n *\n * GSI1 — Unified Sharded List per ADR-011: lists all RoleAssignments in a tenant across the four\n * shards. Tenant-scoped only (workspace context lives inside the resource), so the GSI1 PK uses\n * `WID#-` as a sentinel.\n *\n * @see sites/www-docs/content/architecture/adr/2026-03-03-01-tenant-isolated-vs-non-tenant-isolated-entities.md\n * @see sites/www-docs/content/architecture/adr/2026-03-13-02-control-plane-roles-and-user-tenant-workspace-linkage.md\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const RoleAssignmentEntity = new Entity({\n model: {\n entity: \"roleassignment\",\n service: \"control\",\n version: \"01\",\n },\n attributes: {\n /** Sort key sentinel. Always \"CURRENT\". */\n sk: {\n type: \"string\" as const,\n required: true,\n default: \"CURRENT\",\n },\n /** Tenant in which the role assignment applies (required). */\n tenantId: {\n type: \"string\" as const,\n required: true,\n },\n /** FHIR Resource.id; role assignment id. */\n id: {\n type: \"string\" as const,\n required: true,\n },\n /** Full RoleAssignment resource serialized as JSON string. */\n resource: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Summary projection (key display fields as JSON string: id, displayName, status).\n * Populated on every write via extractSummary(resource); GSI1 INCLUDE surfaces it on lists.\n */\n summary: {\n type: \"string\" as const,\n required: true,\n },\n /** Version id (e.g. ULID). */\n vid: {\n type: \"string\" as const,\n required: true,\n },\n lastUpdated: {\n type: \"string\" as const,\n required: true,\n },\n gsi1Shard: gsi1ShardAttribute,\n /** Derived GSI1 sort key — name-based when extractable; else `<lastUpdated>#<id>`. */\n gsi1sk: gsi1skAttribute,\n deleted: {\n type: \"boolean\" as const,\n required: false,\n },\n bundleId: {\n type: \"string\" as const,\n required: false,\n },\n msgId: {\n type: \"string\" as const,\n required: false,\n },\n },\n indexes: {\n /** Base table: PK = TID#<tenantId>#ROLEASSIGNMENT#ID#<id>, SK = CURRENT. Do not supply PK or SK from outside. */\n record: {\n pk: {\n field: \"PK\",\n composite: [\"tenantId\", \"id\"],\n template: \"TID#${tenantId}#ROLEASSIGNMENT#ID#${id}\",\n },\n sk: {\n field: \"SK\",\n composite: [\"sk\"],\n template: \"${sk}\",\n },\n },\n\n /**\n * GSI1 — Unified Sharded List per ADR-011: list all RoleAssignments for a tenant across the\n * four shards. Tenant-scoped only, so `WID#-` is a sentinel.\n * SK is derived via `gsi1skAttribute` — uses the resource's natural label when\n * extractable, else `<lastUpdated>#<id>` (DR-004). `casing: \"none\"` preserves the\n * normalized label and ISO-8601 `T`/`Z`.\n */\n gsi1: {\n index: \"GSI1\",\n pk: {\n field: \"GSI1PK\",\n composite: [\"tenantId\", \"gsi1Shard\"],\n template: \"TID#${tenantId}#WID#-#RT#RoleAssignment#SHARD#${gsi1Shard}\",\n },\n sk: {\n field: \"GSI1SK\",\n casing: \"none\" as const,\n composite: [\"gsi1sk\"],\n template: \"${gsi1sk}\",\n },\n },\n },\n});\n","import { Entity } from \"electrodb\";\nimport { gsi1ShardAttribute, gsi1skAttribute } from \"./control-entity-common\";\n\n/**\n * Tenant data-store entity (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, control plane. Tenant IS the top scope;\n * the workspace dimension is not applicable and uses the sentinel `TENANT`. The tenant's own `id`\n * is stored as `tenantId` to drive the partition key.\n *\n * Key structure: PK = TENANT#ID#<tenantId>, SK = CURRENT.\n * Uniqueness: one Tenant per tenantId (id).\n *\n * GSI1 — Unified Sharded List per ADR-011: lists all Tenants across the four shards. Tenant has\n * no parent tenant or workspace, so the PK uses `TID#-#WID#-` sentinels.\n *\n * @see sites/www-docs/content/architecture/adr/2026-03-03-01-tenant-isolated-vs-non-tenant-isolated-entities.md\n * @see sites/www-docs/content/architecture/adr/2026-03-13-01-tenant-and-workspace-fhir-types-control-plane.md\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const TenantEntity = new Entity({\n model: {\n entity: \"tenant\",\n service: \"control\",\n version: \"01\",\n },\n attributes: {\n /** Sort key sentinel. Always \"CURRENT\". */\n sk: {\n type: \"string\" as const,\n required: true,\n default: \"CURRENT\",\n },\n /** The tenant's own id (= resource id). Drives the partition key. */\n tenantId: {\n type: \"string\" as const,\n required: true,\n },\n /** FHIR Resource.id; logical id in URL. Equals tenantId. */\n id: {\n type: \"string\" as const,\n required: true,\n },\n /** Full Tenant resource serialized as JSON string. */\n resource: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Summary projection (key display fields as JSON string: id, displayName, status).\n * Populated on every write via extractSummary(resource); GSI1 INCLUDE surfaces it on lists.\n */\n summary: {\n type: \"string\" as const,\n required: true,\n },\n /** Version id (e.g. ULID). */\n vid: {\n type: \"string\" as const,\n required: true,\n },\n lastUpdated: {\n type: \"string\" as const,\n required: true,\n },\n gsi1Shard: gsi1ShardAttribute,\n /** Derived GSI1 sort key — name-based when extractable; else `<lastUpdated>#<id>`. */\n gsi1sk: gsi1skAttribute,\n deleted: {\n type: \"boolean\" as const,\n required: false,\n },\n bundleId: {\n type: \"string\" as const,\n required: false,\n },\n msgId: {\n type: \"string\" as const,\n required: false,\n },\n },\n indexes: {\n /** Base table: PK = TENANT#ID#<tenantId>, SK = CURRENT. Do not supply PK or SK from outside. */\n record: {\n pk: {\n field: \"PK\",\n composite: [\"tenantId\"],\n template: \"TENANT#ID#${tenantId}\",\n },\n sk: {\n field: \"SK\",\n composite: [\"sk\"],\n template: \"${sk}\",\n },\n },\n\n /**\n * GSI1 — Unified Sharded List per ADR-011: list all Tenants across the four shards.\n * Tenant lives at the platform tier (no parent tenant or workspace), so `TID#-#WID#-`\n * sentinels precede `RT#Tenant#SHARD#<n>`. SK is derived via `gsi1skAttribute` —\n * `<normalizedName>#<id>` when the resource carries a `name`, else `<lastUpdated>#<id>`\n * (DR-004). `casing: \"none\"` preserves the normalized label and ISO-8601 `T`/`Z`.\n */\n gsi1: {\n index: \"GSI1\",\n pk: {\n field: \"GSI1PK\",\n composite: [\"gsi1Shard\"],\n template: \"TID#-#WID#-#RT#Tenant#SHARD#${gsi1Shard}\",\n },\n sk: {\n field: \"GSI1SK\",\n casing: \"none\" as const,\n composite: [\"gsi1sk\"],\n template: \"${gsi1sk}\",\n },\n },\n },\n});\n","import { Entity } from \"electrodb\";\nimport { gsi1ShardAttribute, gsi1skAttribute } from \"./control-entity-common\";\n\n/**\n * User data-store entity (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Non-tenant-isolated, control plane. User is a\n * platform-wide identity; association with tenants and workspaces is through Membership and\n * RoleAssignment, not the User entity's own key.\n *\n * Key structure: PK = USER#ID#<id>, SK = CURRENT.\n * The USER# prefix prevents key collisions with other non-tenant-isolated entities (Role, etc.)\n * sharing the same table (ADR 2026-03-11-01 — preferred pattern for all control plane entities).\n * Uniqueness: one User per id.\n *\n * GSI1 — Unified Sharded List per ADR-011: lists all Users across the four shards. Non-tenant-\n * isolated, so the PK uses `TID#-#WID#-` sentinels.\n * GSI2 — Cognito sub-lookup per ADR-011: resolves a UserEntity from a Cognito `sub` claim\n * (`USER#SUB#<cognitoSub>` PK, `CURRENT` SK). The `cognitoSub` attribute is populated by the\n * Post Confirmation Lambda (Epic #765 / #770); kept optional here until that write path lands.\n *\n * @see sites/www-docs/content/architecture/adr/2026-03-03-01-tenant-isolated-vs-non-tenant-isolated-entities.md\n * @see sites/www-docs/content/architecture/adr/2026-03-11-01-user-type-definition-fhir-and-data-layer.md\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const UserEntity = new Entity({\n model: {\n entity: \"user\",\n service: \"control\",\n version: \"01\",\n },\n attributes: {\n /** Sort key sentinel. Always \"CURRENT\". */\n sk: {\n type: \"string\" as const,\n required: true,\n default: \"CURRENT\",\n },\n /** FHIR Resource.id; platform user id (ohi_uid). */\n id: {\n type: \"string\" as const,\n required: true,\n },\n /** Full User resource serialized as JSON string. */\n resource: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Summary projection (key display fields as JSON string: id, displayName, status).\n * Populated on every write via extractSummary(resource); GSI1 INCLUDE surfaces it on lists.\n */\n summary: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Immutable Cognito-issued `sub` claim. Drives GSI2 (sub-lookup). Optional until the\n * Post Confirmation Lambda (#770) lands; required thereafter.\n */\n cognitoSub: {\n type: \"string\" as const,\n required: false,\n },\n /** Version id (e.g. ULID). */\n vid: {\n type: \"string\" as const,\n required: true,\n },\n lastUpdated: {\n type: \"string\" as const,\n required: true,\n },\n gsi1Shard: gsi1ShardAttribute,\n /** Derived GSI1 sort key — name-based when extractable; else `<lastUpdated>#<id>`. */\n gsi1sk: gsi1skAttribute,\n deleted: {\n type: \"boolean\" as const,\n required: false,\n },\n bundleId: {\n type: \"string\" as const,\n required: false,\n },\n msgId: {\n type: \"string\" as const,\n required: false,\n },\n },\n indexes: {\n /** Base table: PK = USER#ID#<id>, SK = CURRENT. Do not supply PK or SK from outside. */\n record: {\n pk: {\n field: \"PK\",\n composite: [\"id\"],\n template: \"USER#ID#${id}\",\n },\n sk: {\n field: \"SK\",\n composite: [\"sk\"],\n template: \"${sk}\",\n },\n },\n\n /**\n * GSI1 — Unified Sharded List per ADR-011: list all Users across the four shards.\n * Non-tenant-isolated, so `TID#-#WID#-` sentinels precede `RT#User#SHARD#<n>`.\n * SK is derived via `gsi1skAttribute` — uses the resource's natural label when\n * extractable (string `name`/`title` via introspection), else `<lastUpdated>#<id>`\n * (DR-004). `casing: \"none\"` preserves the normalized label and ISO-8601 `T`/`Z`.\n */\n gsi1: {\n index: \"GSI1\",\n pk: {\n field: \"GSI1PK\",\n composite: [\"gsi1Shard\"],\n template: \"TID#-#WID#-#RT#User#SHARD#${gsi1Shard}\",\n },\n sk: {\n field: \"GSI1SK\",\n casing: \"none\" as const,\n composite: [\"gsi1sk\"],\n template: \"${gsi1sk}\",\n },\n },\n\n /**\n * GSI2 — Cognito sub-lookup per ADR-011: resolves the UserEntity from a Cognito `sub` claim.\n * `condition` skips the index when `cognitoSub` is missing so legacy items without a sub are\n * not indexed.\n */\n gsi2: {\n index: \"GSI2\",\n condition: (attrs: { cognitoSub?: string }) =>\n typeof attrs.cognitoSub === \"string\" && attrs.cognitoSub.length > 0,\n pk: {\n field: \"GSI2PK\",\n casing: \"none\" as const,\n composite: [\"cognitoSub\"],\n template: \"USER#SUB#${cognitoSub}\",\n },\n sk: {\n field: \"GSI2SK\",\n casing: \"none\" as const,\n composite: [],\n template: \"CURRENT\",\n },\n },\n },\n});\n","import { Entity } from \"electrodb\";\nimport { gsi1ShardAttribute, gsi1skAttribute } from \"./control-entity-common\";\n\n/**\n * Workspace data-store entity (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, control plane. Each workspace belongs\n * to exactly one tenant; both tenantId and workspace id are in the partition key.\n *\n * Key structure: PK = TID#<tenantId>#WORKSPACE#ID#<id>, SK = CURRENT.\n * Uniqueness: one Workspace per (tenantId, id).\n *\n * GSI1 — Unified Sharded List per ADR-011: lists all Workspaces in a tenant across the four\n * shards. Workspace is itself the workspace identity, so the GSI1 PK uses `WID#-` as a sentinel.\n *\n * @see sites/www-docs/content/architecture/adr/2026-03-03-01-tenant-isolated-vs-non-tenant-isolated-entities.md\n * @see sites/www-docs/content/architecture/adr/2026-03-13-01-tenant-and-workspace-fhir-types-control-plane.md\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const WorkspaceEntity = new Entity({\n model: {\n entity: \"workspace\",\n service: \"control\",\n version: \"01\",\n },\n attributes: {\n /** Sort key sentinel. Always \"CURRENT\". */\n sk: {\n type: \"string\" as const,\n required: true,\n default: \"CURRENT\",\n },\n /** Tenant that contains this workspace (required). */\n tenantId: {\n type: \"string\" as const,\n required: true,\n },\n /** FHIR Resource.id; logical id in URL. */\n id: {\n type: \"string\" as const,\n required: true,\n },\n /** Full Workspace resource serialized as JSON string. */\n resource: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Summary projection (key display fields as JSON string: id, displayName, status).\n * Populated on every write via extractSummary(resource); GSI1 INCLUDE surfaces it on lists.\n */\n summary: {\n type: \"string\" as const,\n required: true,\n },\n /** Version id (e.g. ULID). */\n vid: {\n type: \"string\" as const,\n required: true,\n },\n lastUpdated: {\n type: \"string\" as const,\n required: true,\n },\n gsi1Shard: gsi1ShardAttribute,\n /** Derived GSI1 sort key — name-based when extractable; else `<lastUpdated>#<id>`. */\n gsi1sk: gsi1skAttribute,\n deleted: {\n type: \"boolean\" as const,\n required: false,\n },\n bundleId: {\n type: \"string\" as const,\n required: false,\n },\n msgId: {\n type: \"string\" as const,\n required: false,\n },\n },\n indexes: {\n /** Base table: PK = TID#<tenantId>#WORKSPACE#ID#<id>, SK = CURRENT. Do not supply PK or SK from outside. */\n record: {\n pk: {\n field: \"PK\",\n composite: [\"tenantId\", \"id\"],\n template: \"TID#${tenantId}#WORKSPACE#ID#${id}\",\n },\n sk: {\n field: \"SK\",\n composite: [\"sk\"],\n template: \"${sk}\",\n },\n },\n\n /**\n * GSI1 — Unified Sharded List per ADR-011: list all Workspaces for a tenant across the\n * four shards. Workspace is itself the workspace identity, so `WID#-` is a sentinel.\n * SK is derived via `gsi1skAttribute` — `<normalizedName>#<id>` when the resource\n * carries a `name`, else `<lastUpdated>#<id>` (DR-004). `casing: \"none\"` preserves\n * the normalized label and ISO-8601 `T`/`Z`.\n */\n gsi1: {\n index: \"GSI1\",\n pk: {\n field: \"GSI1PK\",\n composite: [\"tenantId\", \"gsi1Shard\"],\n template: \"TID#${tenantId}#WID#-#RT#Workspace#SHARD#${gsi1Shard}\",\n },\n sk: {\n field: \"GSI1SK\",\n casing: \"none\" as const,\n composite: [\"gsi1sk\"],\n template: \"${gsi1sk}\",\n },\n },\n },\n});\n"],"mappings":"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","names":["Entity","Entity","Entity","Entity","Entity","Entity","Entity","Entity","Entity","Entity","Entity","Entity"]}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getDynamoControlService
|
|
3
|
+
} from "./chunk-VYDIGFIX.mjs";
|
|
4
|
+
|
|
5
|
+
// src/data/operations/control/role/role-create-operation.ts
|
|
6
|
+
import { extractSummary } from "@openhi/types";
|
|
7
|
+
async function createRoleOperation(params) {
|
|
8
|
+
const { context, body, tableName } = params;
|
|
9
|
+
const service = getDynamoControlService(tableName);
|
|
10
|
+
const id = body.id ?? `role-${Date.now()}`;
|
|
11
|
+
const parsedResource = typeof body.resource === "string" ? JSON.parse(body.resource) : body.resource ?? {};
|
|
12
|
+
const lastUpdated = context.date ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
13
|
+
const vid = `1`;
|
|
14
|
+
const resource = { resourceType: "Role", id, ...parsedResource };
|
|
15
|
+
const summary = JSON.stringify(extractSummary(resource));
|
|
16
|
+
await service.entities.role.put({
|
|
17
|
+
id,
|
|
18
|
+
resource: JSON.stringify(resource),
|
|
19
|
+
summary,
|
|
20
|
+
vid,
|
|
21
|
+
lastUpdated
|
|
22
|
+
}).go();
|
|
23
|
+
return {
|
|
24
|
+
id,
|
|
25
|
+
resource,
|
|
26
|
+
meta: { lastUpdated, versionId: vid }
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export {
|
|
31
|
+
createRoleOperation
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=chunk-YU2HRNUP.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/data/operations/control/role/role-create-operation.ts"],"sourcesContent":["import { extractSummary, type FhirResourceLike } from \"@openhi/types\";\nimport { getDynamoControlService } from \"../../../dynamo/dynamo-control-service\";\nimport { OpenHiContext } from \"../../../openhi-context\";\n\nexport interface RoleCreateParams {\n context: OpenHiContext;\n body: { id?: string; resource?: Record<string, unknown> | string };\n tableName?: string;\n}\n\nexport interface RoleCreateResult {\n id: string;\n resource: { resourceType: string; id: string; [key: string]: unknown };\n meta: { lastUpdated: string; versionId: string };\n}\n\nexport async function createRoleOperation(\n params: RoleCreateParams,\n): Promise<RoleCreateResult> {\n const { context, body, tableName } = params;\n const service = getDynamoControlService(tableName);\n\n const id = body.id ?? `role-${Date.now()}`;\n const parsedResource =\n typeof body.resource === \"string\"\n ? (JSON.parse(body.resource) as Record<string, unknown>)\n : (body.resource ?? {});\n\n const lastUpdated = context.date ?? new Date().toISOString();\n const vid = `1`;\n\n const resource = { resourceType: \"Role\", id, ...parsedResource };\n const summary = JSON.stringify(extractSummary(resource as FhirResourceLike));\n\n await service.entities.role\n .put({\n id,\n resource: JSON.stringify(resource),\n summary,\n vid,\n lastUpdated,\n })\n .go();\n\n return {\n id,\n resource,\n meta: { lastUpdated, versionId: vid },\n };\n}\n"],"mappings":";;;;;AAAA,SAAS,sBAA6C;AAgBtD,eAAsB,oBACpB,QAC2B;AAC3B,QAAM,EAAE,SAAS,MAAM,UAAU,IAAI;AACrC,QAAM,UAAU,wBAAwB,SAAS;AAEjD,QAAM,KAAK,KAAK,MAAM,QAAQ,KAAK,IAAI,CAAC;AACxC,QAAM,iBACJ,OAAO,KAAK,aAAa,WACpB,KAAK,MAAM,KAAK,QAAQ,IACxB,KAAK,YAAY,CAAC;AAEzB,QAAM,cAAc,QAAQ,SAAQ,oBAAI,KAAK,GAAE,YAAY;AAC3D,QAAM,MAAM;AAEZ,QAAM,WAAW,EAAE,cAAc,QAAQ,IAAI,GAAG,eAAe;AAC/D,QAAM,UAAU,KAAK,UAAU,eAAe,QAA4B,CAAC;AAE3E,QAAM,QAAQ,SAAS,KACpB,IAAI;AAAA,IACH;AAAA,IACA,UAAU,KAAK,UAAU,QAAQ;AAAA,IACjC;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC,EACA,GAAG;AAEN,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,MAAM,EAAE,aAAa,WAAW,IAAI;AAAA,EACtC;AACF;","names":[]}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// src/data/errors/domain-errors.ts
|
|
2
|
+
var DomainError = class extends Error {
|
|
3
|
+
constructor(message, code, options) {
|
|
4
|
+
super(message, options);
|
|
5
|
+
this.name = this.constructor.name;
|
|
6
|
+
this.code = code;
|
|
7
|
+
this.details = options?.details;
|
|
8
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
var NotFoundError = class extends DomainError {
|
|
12
|
+
constructor(message, options) {
|
|
13
|
+
super(message, "NOT_FOUND", options);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
var ValidationError = class extends DomainError {
|
|
17
|
+
constructor(message, options) {
|
|
18
|
+
super(message, "VALIDATION", options);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
var ConflictError = class extends DomainError {
|
|
22
|
+
constructor(message, options) {
|
|
23
|
+
super(message, "CONFLICT", options);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
function domainErrorToHttpStatus(err) {
|
|
27
|
+
if (err instanceof NotFoundError) return 404;
|
|
28
|
+
if (err instanceof ValidationError) return 400;
|
|
29
|
+
if (err instanceof ConflictError) return 409;
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export {
|
|
34
|
+
NotFoundError,
|
|
35
|
+
domainErrorToHttpStatus
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=chunk-YZZDUJHI.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/data/errors/domain-errors.ts"],"sourcesContent":["/**\n * Typed domain errors for the data operations layer.\n * Data operations throw these; adapters (REST, GraphQL, Step Function) map them to\n * HTTP status, GraphQL errors, or workflow envelopes. No HTTP or OperationOutcome here.\n *\n * Full documentation (error types, HTTP mapping, FHIR OperationOutcome.issue.code alignment):\n * @see sites/www-docs/content/packages/@openhi/constructs/data/errors.md\n */\n\n/**\n * Base class for domain errors thrown by data operations.\n * Adapters use instanceof checks or domainErrorToHttpStatus() to map to transport.\n */\nexport class DomainError extends Error {\n /** Stable code for adapter mapping (e.g. \"NOT_FOUND\", \"VALIDATION\", \"CONFLICT\"). */\n readonly code: string;\n\n /** Optional details for validation messages or conflict context. */\n readonly details?: unknown;\n\n constructor(\n message: string,\n code: string,\n options?: { cause?: unknown; details?: unknown },\n ) {\n super(message, options);\n this.name = this.constructor.name;\n this.code = code;\n this.details = options?.details;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when a requested resource or entity is not found (e.g. get by id returns nothing). */\nexport class NotFoundError extends DomainError {\n constructor(\n message: string,\n options?: { cause?: unknown; details?: unknown },\n ) {\n super(message, \"NOT_FOUND\", options);\n }\n}\n\n/** Thrown when input fails validation (e.g. missing required field, invalid format). */\nexport class ValidationError extends DomainError {\n constructor(\n message: string,\n options?: { cause?: unknown; details?: unknown },\n ) {\n super(message, \"VALIDATION\", options);\n }\n}\n\n/** Thrown when an operation conflicts with current state (e.g. duplicate key, version conflict). */\nexport class ConflictError extends DomainError {\n constructor(\n message: string,\n options?: { cause?: unknown; details?: unknown },\n ) {\n super(message, \"CONFLICT\", options);\n }\n}\n\n/**\n * Maps a thrown value to the HTTP status code that adapters should use for that domain error.\n * Returns null if the value is not a known domain error (adapter may use 500 or handle otherwise).\n * REST adapters use this to choose status; response body/OperationOutcome remain adapter responsibility.\n */\nexport function domainErrorToHttpStatus(err: unknown): number | null {\n if (err instanceof NotFoundError) return 404;\n if (err instanceof ValidationError) return 400;\n if (err instanceof ConflictError) return 409;\n return null;\n}\n"],"mappings":";AAaO,IAAM,cAAN,cAA0B,MAAM;AAAA,EAOrC,YACE,SACA,MACA,SACA;AACA,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO,KAAK,YAAY;AAC7B,SAAK,OAAO;AACZ,SAAK,UAAU,SAAS;AACxB,WAAO,eAAe,MAAM,WAAW,SAAS;AAAA,EAClD;AACF;AAGO,IAAM,gBAAN,cAA4B,YAAY;AAAA,EAC7C,YACE,SACA,SACA;AACA,UAAM,SAAS,aAAa,OAAO;AAAA,EACrC;AACF;AAGO,IAAM,kBAAN,cAA8B,YAAY;AAAA,EAC/C,YACE,SACA,SACA;AACA,UAAM,SAAS,cAAc,OAAO;AAAA,EACtC;AACF;AAGO,IAAM,gBAAN,cAA4B,YAAY;AAAA,EAC7C,YACE,SACA,SACA;AACA,UAAM,SAAS,YAAY,OAAO;AAAA,EACpC;AACF;AAOO,SAAS,wBAAwB,KAA6B;AACnE,MAAI,eAAe,cAAe,QAAO;AACzC,MAAI,eAAe,gBAAiB,QAAO;AAC3C,MAAI,eAAe,cAAe,QAAO;AACzC,SAAO;AACT;","names":[]}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @see sites/www-docs/content/packages/@openhi/constructs/workflows/control-plane/platform-deploy-bridge/index.md
|
|
3
|
+
*/
|
|
4
|
+
/** EventBridge `source` for the AWS-native CloudFormation events the bridge listens to. */
|
|
5
|
+
declare const CLOUDFORMATION_EVENT_SOURCE: "aws.cloudformation";
|
|
6
|
+
/** EventBridge `detail-type` for terminal stack status events. */
|
|
7
|
+
declare const CLOUDFORMATION_STACK_STATUS_CHANGE_DETAIL_TYPE: "CloudFormation Stack Status Change";
|
|
8
|
+
/** Stack statuses the bridge republishes. Other statuses are pre-filtered at the rule. */
|
|
9
|
+
declare const BRIDGED_STATUSES: readonly ["CREATE_COMPLETE", "UPDATE_COMPLETE"];
|
|
10
|
+
type BridgedStatus = (typeof BRIDGED_STATUSES)[number];
|
|
11
|
+
/** Env var the bridge handler reads to discover the control event bus name. */
|
|
12
|
+
declare const CONTROL_EVENT_BUS_NAME_ENV_VAR = "CONTROL_EVENT_BUS_NAME";
|
|
13
|
+
/**
|
|
14
|
+
* Env var the bridge handler reads for the resolved
|
|
15
|
+
* `openhi:repo-name`-shaped tag key. Resolved at synth time from the host
|
|
16
|
+
* stack's `appName` + {@link OPENHI_TAG_SUFFIX_REPO_NAME}.
|
|
17
|
+
*/
|
|
18
|
+
declare const OPENHI_REPO_TAG_KEY_ENV_VAR = "OPENHI_REPO_TAG_KEY";
|
|
19
|
+
/**
|
|
20
|
+
* Env var the bridge handler reads for the resolved `openhi:` tag prefix.
|
|
21
|
+
* Resolved at synth time from the host stack's `appName`. Used to project
|
|
22
|
+
* the relevant stack tags into the published envelope.
|
|
23
|
+
*/
|
|
24
|
+
declare const OPENHI_TAG_KEY_PREFIX_ENV_VAR = "OPENHI_TAG_KEY_PREFIX";
|
|
25
|
+
/** Free-form `actor.system` value per TR-016 § Decision points #1 (bootstrap-role pattern). */
|
|
26
|
+
declare const PLATFORM_DEPLOY_BRIDGE_ACTOR_SYSTEM = "platform-deploy-bridge";
|
|
27
|
+
/**
|
|
28
|
+
* Subset of the CloudFormation Stack Status Change `detail` field the
|
|
29
|
+
* bridge handler reads. AWS-side schema lives at
|
|
30
|
+
* <https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/monitoring-cloudformation.html>.
|
|
31
|
+
*/
|
|
32
|
+
interface CloudFormationStackStatusChangeDetail {
|
|
33
|
+
readonly "stack-id": string;
|
|
34
|
+
readonly "logical-resource-id"?: string;
|
|
35
|
+
readonly "physical-resource-id"?: string;
|
|
36
|
+
readonly "status-details": {
|
|
37
|
+
readonly status: string;
|
|
38
|
+
readonly "status-reason"?: string;
|
|
39
|
+
};
|
|
40
|
+
readonly "resource-type"?: string;
|
|
41
|
+
readonly "client-request-token"?: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export { BRIDGED_STATUSES as B, CLOUDFORMATION_EVENT_SOURCE as C, OPENHI_REPO_TAG_KEY_ENV_VAR as O, PLATFORM_DEPLOY_BRIDGE_ACTOR_SYSTEM as P, type BridgedStatus as a, CLOUDFORMATION_STACK_STATUS_CHANGE_DETAIL_TYPE as b, CONTROL_EVENT_BUS_NAME_ENV_VAR as c, type CloudFormationStackStatusChangeDetail as d, OPENHI_TAG_KEY_PREFIX_ENV_VAR as e };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @see sites/www-docs/content/packages/@openhi/constructs/workflows/control-plane/platform-deploy-bridge/index.md
|
|
3
|
+
*/
|
|
4
|
+
/** EventBridge `source` for the AWS-native CloudFormation events the bridge listens to. */
|
|
5
|
+
declare const CLOUDFORMATION_EVENT_SOURCE: "aws.cloudformation";
|
|
6
|
+
/** EventBridge `detail-type` for terminal stack status events. */
|
|
7
|
+
declare const CLOUDFORMATION_STACK_STATUS_CHANGE_DETAIL_TYPE: "CloudFormation Stack Status Change";
|
|
8
|
+
/** Stack statuses the bridge republishes. Other statuses are pre-filtered at the rule. */
|
|
9
|
+
declare const BRIDGED_STATUSES: readonly ["CREATE_COMPLETE", "UPDATE_COMPLETE"];
|
|
10
|
+
type BridgedStatus = (typeof BRIDGED_STATUSES)[number];
|
|
11
|
+
/** Env var the bridge handler reads to discover the control event bus name. */
|
|
12
|
+
declare const CONTROL_EVENT_BUS_NAME_ENV_VAR = "CONTROL_EVENT_BUS_NAME";
|
|
13
|
+
/**
|
|
14
|
+
* Env var the bridge handler reads for the resolved
|
|
15
|
+
* `openhi:repo-name`-shaped tag key. Resolved at synth time from the host
|
|
16
|
+
* stack's `appName` + {@link OPENHI_TAG_SUFFIX_REPO_NAME}.
|
|
17
|
+
*/
|
|
18
|
+
declare const OPENHI_REPO_TAG_KEY_ENV_VAR = "OPENHI_REPO_TAG_KEY";
|
|
19
|
+
/**
|
|
20
|
+
* Env var the bridge handler reads for the resolved `openhi:` tag prefix.
|
|
21
|
+
* Resolved at synth time from the host stack's `appName`. Used to project
|
|
22
|
+
* the relevant stack tags into the published envelope.
|
|
23
|
+
*/
|
|
24
|
+
declare const OPENHI_TAG_KEY_PREFIX_ENV_VAR = "OPENHI_TAG_KEY_PREFIX";
|
|
25
|
+
/** Free-form `actor.system` value per TR-016 § Decision points #1 (bootstrap-role pattern). */
|
|
26
|
+
declare const PLATFORM_DEPLOY_BRIDGE_ACTOR_SYSTEM = "platform-deploy-bridge";
|
|
27
|
+
/**
|
|
28
|
+
* Subset of the CloudFormation Stack Status Change `detail` field the
|
|
29
|
+
* bridge handler reads. AWS-side schema lives at
|
|
30
|
+
* <https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/monitoring-cloudformation.html>.
|
|
31
|
+
*/
|
|
32
|
+
interface CloudFormationStackStatusChangeDetail {
|
|
33
|
+
readonly "stack-id": string;
|
|
34
|
+
readonly "logical-resource-id"?: string;
|
|
35
|
+
readonly "physical-resource-id"?: string;
|
|
36
|
+
readonly "status-details": {
|
|
37
|
+
readonly status: string;
|
|
38
|
+
readonly "status-reason"?: string;
|
|
39
|
+
};
|
|
40
|
+
readonly "resource-type"?: string;
|
|
41
|
+
readonly "client-request-token"?: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export { BRIDGED_STATUSES as B, CLOUDFORMATION_EVENT_SOURCE as C, OPENHI_REPO_TAG_KEY_ENV_VAR as O, PLATFORM_DEPLOY_BRIDGE_ACTOR_SYSTEM as P, type BridgedStatus as a, CLOUDFORMATION_STACK_STATUS_CHANGE_DETAIL_TYPE as b, CONTROL_EVENT_BUS_NAME_ENV_VAR as c, type CloudFormationStackStatusChangeDetail as d, OPENHI_TAG_KEY_PREFIX_ENV_VAR as e };
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { PlatformRoleCode } from '@openhi/types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @see sites/www-docs/content/packages/@openhi/constructs/workflows/control-plane/seed-demo-data/events.md
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Stable logical name this workflow registers with the shared
|
|
8
|
+
* `WorkflowDedupTable` (TR-015). Used in both the construct grant
|
|
9
|
+
* (`workflowDedupTable.grantConsumer(lambda, SEED_DEMO_DATA_CONSUMER_NAME)`)
|
|
10
|
+
* and the handler's runtime `recordIfAbsent` call — keep them aligned by
|
|
11
|
+
* importing this constant in both places.
|
|
12
|
+
*/
|
|
13
|
+
declare const SEED_DEMO_DATA_CONSUMER_NAME = "seed-demo-data";
|
|
14
|
+
/** FHIR `Identifier.system` for the demo-scenario URN scheme. */
|
|
15
|
+
declare const DEMO_URN_SYSTEM = "urn:openhi:demo";
|
|
16
|
+
/**
|
|
17
|
+
* FHIR `Identifier.system` for the canonical OpenHI resource URN
|
|
18
|
+
* (ADR 2026-03-12-01). The value form is
|
|
19
|
+
* `urn:ohi:<tenantId>:<workspaceId>:<resourceType>:<id>`; empty
|
|
20
|
+
* workspaceId means the resource has tenant-wide scope (or is itself
|
|
21
|
+
* the workspace identity, in the Workspace case).
|
|
22
|
+
*/
|
|
23
|
+
declare const OPENHI_RESOURCE_URN_SYSTEM = "http://openhi.org/";
|
|
24
|
+
/**
|
|
25
|
+
* Period stamped on every demo Membership and RoleAssignment. Fixed
|
|
26
|
+
* start so re-runs produce byte-identical bodies (decision #4); no
|
|
27
|
+
* end so demo memberships are open-ended.
|
|
28
|
+
*/
|
|
29
|
+
declare const DEMO_PERIOD: {
|
|
30
|
+
readonly start: "2026-01-01T00:00:00Z";
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Sentinel `tenantId` used on every dev user's `system-admin`
|
|
34
|
+
* RoleAssignment. A `system-admin` RA is platform-scoped (it spans
|
|
35
|
+
* every tenant), but the RoleAssignment entity requires a tenantId on
|
|
36
|
+
* its key for sharding — there is no real tenant to point at. The
|
|
37
|
+
* `"platform"` literal is a reserved value that never matches a real
|
|
38
|
+
* Tenant id and signals "this RA scopes across all tenants".
|
|
39
|
+
*
|
|
40
|
+
* Renaming this constant is a wire-format break — the IAM grant in
|
|
41
|
+
* `seed-demo-data-lambda.ts` enumerates exact-match `LeadingKeys`
|
|
42
|
+
* computed from this value, and the in-band records written under it
|
|
43
|
+
* become unreachable if the sentinel changes.
|
|
44
|
+
*/
|
|
45
|
+
declare const PLATFORM_SCOPE_TENANT_ID = "platform";
|
|
46
|
+
/** Placeholder Tenant id seeded by the workflow as the dev-user `currentTenant`. */
|
|
47
|
+
declare const PLACEHOLDER_TENANT_ID = "placeholder-tenant-id";
|
|
48
|
+
/** Placeholder Workspace id seeded by the workflow as the dev-user `currentWorkspace`. */
|
|
49
|
+
declare const PLACEHOLDER_WORKSPACE_ID = "placeholder-workspace-id";
|
|
50
|
+
/**
|
|
51
|
+
* Dev-user descriptor. Every entry produces:
|
|
52
|
+
* - one Cognito user (idempotent create-then-skip),
|
|
53
|
+
* - one DynamoDB User record (id = `dev-<email-local-part>`),
|
|
54
|
+
* - four Memberships (placeholder + the three demo tenants),
|
|
55
|
+
* - four `tenant-admin` RoleAssignments (one per tenant the user
|
|
56
|
+
* belongs to),
|
|
57
|
+
* - one `system-admin` RoleAssignment scoped to {@link PLATFORM_SCOPE_TENANT_ID}.
|
|
58
|
+
*/
|
|
59
|
+
interface DemoDevUser {
|
|
60
|
+
/** Stable DynamoDB User id. */
|
|
61
|
+
readonly id: string;
|
|
62
|
+
/** Email used as the Cognito `Username` and as the seed for the password algorithm. */
|
|
63
|
+
readonly email: string;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Hardcoded dev-user roster. Adding a new developer is a one-line
|
|
67
|
+
* change here plus a re-deploy. The list intentionally lives in-source
|
|
68
|
+
* (not behind an env-var seam) so the IAM grant in
|
|
69
|
+
* `seed-demo-data-lambda.ts` can enumerate per-user PKs at synth time.
|
|
70
|
+
*/
|
|
71
|
+
declare const DEV_USERS: ReadonlyArray<DemoDevUser>;
|
|
72
|
+
/**
|
|
73
|
+
* A single workspace inside a demo tenant. The mixed tenant has two
|
|
74
|
+
* workspaces (wound-care and primary-care sub-workspaces); the other
|
|
75
|
+
* two tenants have one each.
|
|
76
|
+
*/
|
|
77
|
+
interface DemoWorkspaceSpec {
|
|
78
|
+
/** Stable id (DynamoDB record id; also drives the canonical OHI URN). */
|
|
79
|
+
readonly id: string;
|
|
80
|
+
/** FHIR `Workspace.name`. */
|
|
81
|
+
readonly name: string;
|
|
82
|
+
/**
|
|
83
|
+
* Role suffix used in the demo URN value (`<scenario>:<roleSuffix>`).
|
|
84
|
+
* Mirrors seed-fixtures' role suffix convention: `workspace` for
|
|
85
|
+
* single-workspace tenants, `workspace-<sub>` for the mixed tenant.
|
|
86
|
+
*/
|
|
87
|
+
readonly roleSuffix: string;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* One demo tenant + the workspaces it owns. Re-exported via {@link
|
|
91
|
+
* DEMO_TENANT_SPECS} as the canonical list; iterate that constant in
|
|
92
|
+
* the handler and the IAM-grant builder so the value sets agree.
|
|
93
|
+
*/
|
|
94
|
+
interface DemoTenantSpec {
|
|
95
|
+
/**
|
|
96
|
+
* Scenario slug — `placeholder`, `demo-wound-care`, `demo-primary-care`,
|
|
97
|
+
* `demo-mixed`. The placeholder tenant's slug is `placeholder`; the
|
|
98
|
+
* three demo tenants mirror seed-fixtures' `fixture-*` slugs renamed
|
|
99
|
+
* to `demo-*`.
|
|
100
|
+
*/
|
|
101
|
+
readonly scenario: string;
|
|
102
|
+
/** Stable id (DynamoDB record id; also drives the canonical OHI URN). */
|
|
103
|
+
readonly tenantId: string;
|
|
104
|
+
/** FHIR `Tenant.name`. */
|
|
105
|
+
readonly tenantName: string;
|
|
106
|
+
/** Workspaces owned by this tenant. */
|
|
107
|
+
readonly workspaces: ReadonlyArray<DemoWorkspaceSpec>;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* The full demo-tenant graph. Four entries: the placeholder tenant the
|
|
111
|
+
* JWT-claim fallback resolves to, plus the three v1 demo scenarios
|
|
112
|
+
* (OPS-009 §"v1 scenarios"):
|
|
113
|
+
*
|
|
114
|
+
* 0. Placeholder tenant — dereferences the JWT-claim fallback in
|
|
115
|
+
* `pre-token-generation.handler.ts` and acts as every dev user's
|
|
116
|
+
* `currentTenant`/`currentWorkspace` so Post-Confirmation skips
|
|
117
|
+
* default provisioning when a seeded User signs in.
|
|
118
|
+
* 1. Single-workspace wound-care tenant.
|
|
119
|
+
* 2. Single-workspace primary-care tenant.
|
|
120
|
+
* 3. Two-workspace mixed tenant — exercises the cross-workspace
|
|
121
|
+
* isolation flow that single-workspace tenants cannot.
|
|
122
|
+
*/
|
|
123
|
+
declare const DEMO_TENANT_SPECS: ReadonlyArray<DemoTenantSpec>;
|
|
124
|
+
/** Stable Membership id derived from `(devUserId, tenantId)`. */
|
|
125
|
+
declare const demoMembershipId: (devUserId: string, tenantId: string) => string;
|
|
126
|
+
/**
|
|
127
|
+
* Stable RoleAssignment id derived from `(devUserId, tenantId, roleCode)`.
|
|
128
|
+
* Each (user, tenant, role) tuple maps to exactly one record — re-runs
|
|
129
|
+
* upsert the same id.
|
|
130
|
+
*/
|
|
131
|
+
declare const demoRoleAssignmentId: (devUserId: string, tenantId: string, roleCode: PlatformRoleCode) => string;
|
|
132
|
+
/**
|
|
133
|
+
* Demo-scenario FHIR `Identifier` entry — `urn:openhi:demo:<scenario>:<role>`.
|
|
134
|
+
* Mirrors the `urn:openhi:fixture:<scenario>:<role>` pattern from
|
|
135
|
+
* `@openhi/seed-fixtures/src/urn.ts`, renamed to the `demo` namespace.
|
|
136
|
+
*/
|
|
137
|
+
declare const demoScenarioIdentifier: (scenario: string, roleSuffix: string) => {
|
|
138
|
+
system: string;
|
|
139
|
+
value: string;
|
|
140
|
+
};
|
|
141
|
+
/**
|
|
142
|
+
* Canonical OpenHI resource FHIR `Identifier` entry per ADR
|
|
143
|
+
* 2026-03-12-01. `workspaceId` is empty for both Tenant resources and
|
|
144
|
+
* Workspace resources — for a Tenant, the resource is tenant-scoped
|
|
145
|
+
* with no workspace context; for a Workspace, the resource IS the
|
|
146
|
+
* workspace identity rather than living inside one.
|
|
147
|
+
*/
|
|
148
|
+
declare const openhiResourceIdentifier: (params: {
|
|
149
|
+
tenantId: string;
|
|
150
|
+
workspaceId: string;
|
|
151
|
+
resourceType: string;
|
|
152
|
+
id: string;
|
|
153
|
+
}) => {
|
|
154
|
+
use: string;
|
|
155
|
+
system: string;
|
|
156
|
+
value: string;
|
|
157
|
+
};
|
|
158
|
+
/**
|
|
159
|
+
* Roles every dev user holds in every tenant they belong to. Per scope
|
|
160
|
+
* decision Q3, every dev user is `tenant-admin` in every tenant — there
|
|
161
|
+
* is no per-(user, tenant) variance to drive from.
|
|
162
|
+
*/
|
|
163
|
+
declare const demoRolesForUserInTenant: (_user: DemoDevUser, _tenantId: string) => ReadonlyArray<PlatformRoleCode>;
|
|
164
|
+
/**
|
|
165
|
+
* DynamoDB single-table partition-key builders. The IAM grant in
|
|
166
|
+
* `seed-demo-data-lambda.ts` uses these to enumerate exact-match
|
|
167
|
+
* `dynamodb:LeadingKeys` values; the entity definitions in
|
|
168
|
+
* `data/dynamo/entities/control/` own the canonical key templates.
|
|
169
|
+
*
|
|
170
|
+
* These builders MUST emit the keys ElectroDB actually writes — not
|
|
171
|
+
* the entity definition's pretty template. None of the control-plane
|
|
172
|
+
* entities sets `casing: "none"` on the base-table PK template, so
|
|
173
|
+
* ElectroDB applies its default lowercase casing at runtime: the
|
|
174
|
+
* entity's `ROLE#ID#${id}` becomes `role#id#<id>` on the wire. A
|
|
175
|
+
* builder that returns the uppercase template form produces a
|
|
176
|
+
* silently-broken IAM grant (every PutItem denied with "no
|
|
177
|
+
* identity-based policy allows" because the request's leading-key
|
|
178
|
+
* never matches a policy value).
|
|
179
|
+
*/
|
|
180
|
+
declare const rolePartitionKey: (roleId: string) => string;
|
|
181
|
+
declare const demoTenantPartitionKey: (tenantId: string) => string;
|
|
182
|
+
declare const demoWorkspacePartitionKey: (tenantId: string, workspaceId: string) => string;
|
|
183
|
+
declare const demoMembershipPartitionKey: (tenantId: string, membershipId: string) => string;
|
|
184
|
+
declare const demoRoleAssignmentPartitionKey: (tenantId: string, roleAssignmentId: string) => string;
|
|
185
|
+
/** User entity PK template — `USER#ID#<id>` → `user#id#<id>` on the wire. */
|
|
186
|
+
declare const demoUserPartitionKey: (userId: string) => string;
|
|
187
|
+
/**
|
|
188
|
+
* Tenant + Workspace PKs the workflow writes on every fire: the 4
|
|
189
|
+
* tenant PKs (placeholder + 3 demo) plus their workspaces (1 + 1 + 1 + 2 = 5).
|
|
190
|
+
*/
|
|
191
|
+
declare const demoBasePartitionKeys: () => ReadonlyArray<string>;
|
|
192
|
+
/**
|
|
193
|
+
* Membership + RoleAssignment + User PKs the workflow writes per dev
|
|
194
|
+
* user. Empty when `devUsers` is empty (used by tests). The list
|
|
195
|
+
* mirrors the handler's iteration order so the IAM grant covers every
|
|
196
|
+
* write the handler can make.
|
|
197
|
+
*
|
|
198
|
+
* Per dev user the function emits:
|
|
199
|
+
* - one User PK,
|
|
200
|
+
* - per tenant in {@link DEMO_TENANT_SPECS}: one Membership PK plus
|
|
201
|
+
* one `tenant-admin` RoleAssignment PK,
|
|
202
|
+
* - one platform-scoped `system-admin` RoleAssignment PK keyed by
|
|
203
|
+
* {@link PLATFORM_SCOPE_TENANT_ID}.
|
|
204
|
+
*/
|
|
205
|
+
declare const demoDevUserPartitionKeys: (devUsers: ReadonlyArray<DemoDevUser>) => ReadonlyArray<string>;
|
|
206
|
+
|
|
207
|
+
export { DEMO_PERIOD as D, OPENHI_RESOURCE_URN_SYSTEM as O, PLACEHOLDER_TENANT_ID as P, SEED_DEMO_DATA_CONSUMER_NAME as S, DEMO_TENANT_SPECS as a, DEMO_URN_SYSTEM as b, DEV_USERS as c, type DemoDevUser as d, type DemoTenantSpec as e, type DemoWorkspaceSpec as f, PLACEHOLDER_WORKSPACE_ID as g, PLATFORM_SCOPE_TENANT_ID as h, demoBasePartitionKeys as i, demoDevUserPartitionKeys as j, demoMembershipId as k, demoMembershipPartitionKey as l, demoRoleAssignmentId as m, demoRoleAssignmentPartitionKey as n, demoRolesForUserInTenant as o, demoScenarioIdentifier as p, demoTenantPartitionKey as q, demoUserPartitionKey as r, demoWorkspacePartitionKey as s, openhiResourceIdentifier as t, rolePartitionKey as u };
|