@openhi/constructs 0.0.159 → 0.0.160

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../workflows/src/envelope-version.ts","../../workflows/src/envelope.ts","../../workflows/src/sources.ts","../../workflows/src/detail-types/registry.ts","../../workflows/src/detail-types/control-plane.ts","../../workflows/src/detail-types/platform.ts","../../workflows/src/detail-types/index.ts","../../workflows/src/publisher.ts","../../workflows/src/consumer.ts","../../workflows/src/dedup/env.ts","../../workflows/src/dedup/workflow-dedup-client.ts","../../workflows/src/dedup/index.ts","../../workflows/src/index.ts","../src/workflows/control-plane/seed-demo-data/seed-demo-data.handler.ts","../src/workflows/control-plane/seed-demo-data/events.ts","../src/data/operations/control/membership-constraints/platform-scope-tenant-id.ts","../src/workflows/control-plane/seed-demo-data/data-plane-fixtures.ts","../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/configuration-user-projection-entity.ts","../src/data/dynamo/entities/control/configuration-workspace-projection-entity.ts","../src/data/dynamo/entities/control/membership-entity.ts","../src/data/dynamo/entities/control/membership-user-projection-entity.ts","../src/data/dynamo/entities/control/membership-workspace-projection-entity.ts","../src/data/dynamo/entities/control/role-entity.ts","../src/data/dynamo/entities/control/roleassignment-entity.ts","../src/data/dynamo/entities/control/roleassignment-user-projection-entity.ts","../src/data/dynamo/entities/control/roleassignment-workspace-projection-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","../src/data/errors/domain-errors.ts","../src/data/operations/control/membership/membership-create-operation.ts","../src/data/operations/control/membership/membership-user-projection.ts","../src/data/operations/control/membership/membership-workspace-projection.ts","../src/data/operations/control/denormalized-display-names.ts","../src/data/operations/control/membership-constraints/assert-workspace-in-tenant-operation.ts","../src/data/operations/control/multi-write-operation.ts","../src/data/operations/control/role/role-get-by-id-operation.ts","../src/data/operations/control/roleassignment/roleassignment-create-operation.ts","../src/data/operations/control/roleassignment/roleassignment-user-projection.ts","../src/data/operations/control/roleassignment/roleassignment-workspace-projection.ts","../src/data/operations/control/membership-constraints/assert-user-has-tenant-membership-operation.ts","../src/data/operations/control/tenant/tenant-create-operation.ts","../src/data/operations/control/workspace/workspace-create-operation.ts","../src/data/dynamo/dynamo-data-service.ts","../src/data/dynamo/entities/data-entity-common.ts","../src/data/dynamo/entities/data/account-entity.ts","../src/data/dynamo/entities/data/activity-definition-entity.ts","../src/data/dynamo/entities/data/adverse-event-entity.ts","../src/data/dynamo/entities/data/allergy-intolerance-entity.ts","../src/data/dynamo/entities/data/appointment-entity.ts","../src/data/dynamo/entities/data/appointment-response-entity.ts","../src/data/dynamo/entities/data/audit-event-entity.ts","../src/data/dynamo/entities/data/basic-entity.ts","../src/data/dynamo/entities/data/biologically-derived-product-entity.ts","../src/data/dynamo/entities/data/body-structure-entity.ts","../src/data/dynamo/entities/data/capability-statement-entity.ts","../src/data/dynamo/entities/data/care-plan-entity.ts","../src/data/dynamo/entities/data/care-team-entity.ts","../src/data/dynamo/entities/data/catalog-entry-entity.ts","../src/data/dynamo/entities/data/charge-item-definition-entity.ts","../src/data/dynamo/entities/data/charge-item-entity.ts","../src/data/dynamo/entities/data/claim-entity.ts","../src/data/dynamo/entities/data/claim-response-entity.ts","../src/data/dynamo/entities/data/clinical-impression-entity.ts","../src/data/dynamo/entities/data/code-system-entity.ts","../src/data/dynamo/entities/data/communication-entity.ts","../src/data/dynamo/entities/data/communication-request-entity.ts","../src/data/dynamo/entities/data/compartment-definition-entity.ts","../src/data/dynamo/entities/data/composition-entity.ts","../src/data/dynamo/entities/data/concept-map-entity.ts","../src/data/dynamo/entities/data/condition-entity.ts","../src/data/dynamo/entities/data/consent-entity.ts","../src/data/dynamo/entities/data/contract-entity.ts","../src/data/dynamo/entities/data/coverage-eligibility-request-entity.ts","../src/data/dynamo/entities/data/coverage-eligibility-response-entity.ts","../src/data/dynamo/entities/data/coverage-entity.ts","../src/data/dynamo/entities/data/detected-issue-entity.ts","../src/data/dynamo/entities/data/device-definition-entity.ts","../src/data/dynamo/entities/data/device-entity.ts","../src/data/dynamo/entities/data/device-metric-entity.ts","../src/data/dynamo/entities/data/device-request-entity.ts","../src/data/dynamo/entities/data/device-use-statement-entity.ts","../src/data/dynamo/entities/data/diagnostic-report-entity.ts","../src/data/dynamo/entities/data/document-manifest-entity.ts","../src/data/dynamo/entities/data/document-reference-entity.ts","../src/data/dynamo/entities/data/effect-evidence-synthesis-entity.ts","../src/data/dynamo/entities/data/encounter-entity.ts","../src/data/dynamo/entities/data/endpoint-entity.ts","../src/data/dynamo/entities/data/enrollment-request-entity.ts","../src/data/dynamo/entities/data/enrollment-response-entity.ts","../src/data/dynamo/entities/data/episode-of-care-entity.ts","../src/data/dynamo/entities/data/event-definition-entity.ts","../src/data/dynamo/entities/data/evidence-entity.ts","../src/data/dynamo/entities/data/evidence-variable-entity.ts","../src/data/dynamo/entities/data/example-scenario-entity.ts","../src/data/dynamo/entities/data/explanation-of-benefit-entity.ts","../src/data/dynamo/entities/data/family-member-history-entity.ts","../src/data/dynamo/entities/data/flag-entity.ts","../src/data/dynamo/entities/data/goal-entity.ts","../src/data/dynamo/entities/data/graph-definition-entity.ts","../src/data/dynamo/entities/data/group-entity.ts","../src/data/dynamo/entities/data/guidance-response-entity.ts","../src/data/dynamo/entities/data/healthcare-service-entity.ts","../src/data/dynamo/entities/data/imaging-study-entity.ts","../src/data/dynamo/entities/data/immunization-entity.ts","../src/data/dynamo/entities/data/immunization-evaluation-entity.ts","../src/data/dynamo/entities/data/immunization-recommendation-entity.ts","../src/data/dynamo/entities/data/implementation-guide-entity.ts","../src/data/dynamo/entities/data/insurance-plan-entity.ts","../src/data/dynamo/entities/data/invoice-entity.ts","../src/data/dynamo/entities/data/library-entity.ts","../src/data/dynamo/entities/data/linkage-entity.ts","../src/data/dynamo/entities/data/list-entity.ts","../src/data/dynamo/entities/data/location-entity.ts","../src/data/dynamo/entities/data/measure-entity.ts","../src/data/dynamo/entities/data/measure-report-entity.ts","../src/data/dynamo/entities/data/media-entity.ts","../src/data/dynamo/entities/data/medication-administration-entity.ts","../src/data/dynamo/entities/data/medication-dispense-entity.ts","../src/data/dynamo/entities/data/medication-entity.ts","../src/data/dynamo/entities/data/medication-knowledge-entity.ts","../src/data/dynamo/entities/data/medication-request-entity.ts","../src/data/dynamo/entities/data/medication-statement-entity.ts","../src/data/dynamo/entities/data/medicinal-product-authorization-entity.ts","../src/data/dynamo/entities/data/medicinal-product-contraindication-entity.ts","../src/data/dynamo/entities/data/medicinal-product-entity.ts","../src/data/dynamo/entities/data/medicinal-product-indication-entity.ts","../src/data/dynamo/entities/data/medicinal-product-ingredient-entity.ts","../src/data/dynamo/entities/data/medicinal-product-interaction-entity.ts","../src/data/dynamo/entities/data/medicinal-product-manufactured-entity.ts","../src/data/dynamo/entities/data/medicinal-product-packaged-entity.ts","../src/data/dynamo/entities/data/medicinal-product-pharmaceutical-entity.ts","../src/data/dynamo/entities/data/medicinal-product-undesirable-effect-entity.ts","../src/data/dynamo/entities/data/message-definition-entity.ts","../src/data/dynamo/entities/data/message-header-entity.ts","../src/data/dynamo/entities/data/molecular-sequence-entity.ts","../src/data/dynamo/entities/data/naming-system-entity.ts","../src/data/dynamo/entities/data/nutrition-order-entity.ts","../src/data/dynamo/entities/data/observation-definition-entity.ts","../src/data/dynamo/entities/data/observation-entity.ts","../src/data/dynamo/entities/data/operation-definition-entity.ts","../src/data/dynamo/entities/data/organization-affiliation-entity.ts","../src/data/dynamo/entities/data/organization-entity.ts","../src/data/dynamo/entities/data/patient-entity.ts","../src/data/dynamo/entities/data/payment-notice-entity.ts","../src/data/dynamo/entities/data/payment-reconciliation-entity.ts","../src/data/dynamo/entities/data/person-entity.ts","../src/data/dynamo/entities/data/plan-definition-entity.ts","../src/data/dynamo/entities/data/practitioner-entity.ts","../src/data/dynamo/entities/data/practitioner-role-entity.ts","../src/data/dynamo/entities/data/procedure-entity.ts","../src/data/dynamo/entities/data/provenance-entity.ts","../src/data/dynamo/entities/data/questionnaire-entity.ts","../src/data/dynamo/entities/data/questionnaire-response-entity.ts","../src/data/dynamo/entities/data/related-person-entity.ts","../src/data/dynamo/entities/data/request-group-entity.ts","../src/data/dynamo/entities/data/research-definition-entity.ts","../src/data/dynamo/entities/data/research-element-definition-entity.ts","../src/data/dynamo/entities/data/research-study-entity.ts","../src/data/dynamo/entities/data/research-subject-entity.ts","../src/data/dynamo/entities/data/risk-assessment-entity.ts","../src/data/dynamo/entities/data/risk-evidence-synthesis-entity.ts","../src/data/dynamo/entities/data/schedule-entity.ts","../src/data/dynamo/entities/data/search-parameter-entity.ts","../src/data/dynamo/entities/data/service-request-entity.ts","../src/data/dynamo/entities/data/slot-entity.ts","../src/data/dynamo/entities/data/specimen-definition-entity.ts","../src/data/dynamo/entities/data/specimen-entity.ts","../src/data/dynamo/entities/data/structure-definition-entity.ts","../src/data/dynamo/entities/data/structure-map-entity.ts","../src/data/dynamo/entities/data/subscription-entity.ts","../src/data/dynamo/entities/data/substance-entity.ts","../src/data/dynamo/entities/data/substance-nucleic-acid-entity.ts","../src/data/dynamo/entities/data/substance-polymer-entity.ts","../src/data/dynamo/entities/data/substance-protein-entity.ts","../src/data/dynamo/entities/data/substance-reference-information-entity.ts","../src/data/dynamo/entities/data/substance-source-material-entity.ts","../src/data/dynamo/entities/data/substance-specification-entity.ts","../src/data/dynamo/entities/data/supply-delivery-entity.ts","../src/data/dynamo/entities/data/supply-request-entity.ts","../src/data/dynamo/entities/data/task-entity.ts","../src/data/dynamo/entities/data/terminology-capabilities-entity.ts","../src/data/dynamo/entities/data/test-report-entity.ts","../src/data/dynamo/entities/data/test-script-entity.ts","../src/data/dynamo/entities/data/value-set-entity.ts","../src/data/dynamo/entities/data/verification-result-entity.ts","../src/data/dynamo/entities/data/vision-prescription-entity.ts","../src/data/operations/data-operations-common.ts","../src/lib/compression.ts","../src/data/audit-meta.ts","../src/data/operations/data/organization/organization-provision-for-workspace-operation.ts","../src/data/operations/data/account/account-create-operation.ts","../src/data/operations/data/encounter/encounter-create-operation.ts","../src/data/operations/data/observation/observation-create-operation.ts","../src/data/operations/data/patient/patient-create-operation.ts","../src/data/operations/data/practitioner/practitioner-create-operation.ts"],"sourcesContent":["/**\n * Envelope version pinned by the publisher SDK on every emitted envelope.\n *\n * Shape is `\"<major>.<minor>\"` per TR-016 §Open Items #3 (P1).\n * Additive optional fields bump the minor; breaking changes bump the\n * major and require a documented overlap window in the consumer SDK.\n */\nexport const ENVELOPE_VERSION = \"1.0\";\n\nconst ENVELOPE_VERSION_PATTERN = /^\\d+\\.\\d+$/;\n\n/**\n * Lowest envelope major version this SDK's consumer parser accepts.\n *\n * Bump this when a deprecated major reaches end-of-life and the\n * overlap window closes.\n */\nconst MIN_SUPPORTED_MAJOR = 1;\n\n/**\n * Highest envelope major version this SDK's consumer parser accepts.\n *\n * Bump this in lockstep with `ENVELOPE_VERSION` whenever a new major\n * ships; the consumer always supports its own publish major.\n */\nconst MAX_SUPPORTED_MAJOR = 1;\n\n/**\n * Return `true` when `version` is shaped `<major>.<minor>` and its\n * major lies within `[MIN_SUPPORTED_MAJOR, MAX_SUPPORTED_MAJOR]`.\n */\nexport function isSupportedEnvelopeVersion(version: string): boolean {\n if (!ENVELOPE_VERSION_PATTERN.test(version)) {\n return false;\n }\n const major = Number.parseInt(version.split(\".\")[0], 10);\n return major >= MIN_SUPPORTED_MAJOR && major <= MAX_SUPPORTED_MAJOR;\n}\n","import type { OhiJwtClaims } from \"@openhi/types\";\n\n/**\n * Discriminated-union actor field per ADR-016 §Decision #3.\n *\n * User-initiated workflows project the four ADR-014 JWT claims (with\n * `ohi_tid` / `ohi_wid` required — a workflow event without a tenant\n * + workspace context belongs to the `system` variant); bootstrap\n * workflows run before a User exists and carry the bootstrap-role\n * name instead. The `system` value is free-form pending the\n * onboarding-bootstrap IAM role TR (TR-016 §Open Items #4).\n */\nexport type WorkflowActor = WorkflowUserActor | WorkflowSystemActor;\n\n/** User-actor variant — required projection of the ADR-014 JWT claims. */\nexport interface WorkflowUserActor {\n readonly ohi_tid: string;\n readonly ohi_wid: string;\n readonly ohi_uid: string;\n readonly ohi_uname: string;\n}\n\n/** Bootstrap-actor variant — carries the bootstrap-role name. */\nexport interface WorkflowSystemActor {\n readonly system: string;\n}\n\n/**\n * Type guard for the user-actor variant.\n */\nexport function isWorkflowUserActor(\n actor: WorkflowActor,\n): actor is WorkflowUserActor {\n return (actor as WorkflowUserActor).ohi_uid !== undefined;\n}\n\n/**\n * Type guard for the system-actor variant.\n */\nexport function isWorkflowSystemActor(\n actor: WorkflowActor,\n): actor is WorkflowSystemActor {\n return (actor as WorkflowSystemActor).system !== undefined;\n}\n\n/**\n * Standard workflow event envelope per ADR-016 §Decision #3 / TR-016.\n *\n * The generic `TPayload` parameter narrows the per-workflow payload.\n *\n * Field naming note: the payload lives under `payload` (not `detail`)\n * deliberately. EventBridge's outer event already has its own `detail`\n * field that carries this whole envelope; nesting another `detail`\n * inside it produced double-`detail` paths in rule patterns\n * (`detail.detail.<x>`) that consistently bit consumers writing\n * filters. The unambiguous name is worth the rename.\n */\nexport interface WorkflowEvent<TPayload = Record<string, unknown>> {\n /** Per-event UUID. Dedup keys on `(eventId, attempt)`. */\n readonly eventId: string;\n /** 1-indexed delivery attempt. */\n readonly attempt: number;\n /** Originating cross-plane chain identifier. */\n readonly correlationId: string;\n /** Immediate predecessor event id, or null for a chain origin. */\n readonly causationId: string | null;\n /** Discriminated actor — JWT-claim projection or bootstrap-role marker. */\n readonly actor: WorkflowActor;\n /** ISO-8601 timestamp marking when the envelope was constructed. */\n readonly occurredAt: string;\n /** Semver-shaped envelope version (e.g. `\"1.0\"`). */\n readonly envelopeVersion: string;\n /** Per-workflow payload narrowed by the generic parameter. */\n readonly payload: TPayload;\n}\n\n/**\n * Promote a raw `OhiJwtClaims` projection to a fully-required\n * `WorkflowUserActor`.\n *\n * Throws `MissingActorContextError` when `ohi_tid` or `ohi_wid` is\n * absent — those claims are optional on the JWT but required on the\n * workflow user-actor.\n */\nexport function workflowUserActorFromClaims(\n claims: OhiJwtClaims,\n): WorkflowUserActor {\n if (claims.ohi_tid === undefined || claims.ohi_wid === undefined) {\n throw new MissingActorContextError(\n \"workflowUserActorFromClaims: ohi_tid and ohi_wid are required on the workflow user-actor; the caller's JWT is missing one or both. Use a system-actor for pre-provisioning bootstrap workflows.\",\n );\n }\n return {\n ohi_tid: claims.ohi_tid,\n ohi_wid: claims.ohi_wid,\n ohi_uid: claims.ohi_uid,\n ohi_uname: claims.ohi_uname,\n };\n}\n\n/** Thrown when JWT claims lack a field required by the workflow user-actor. */\nexport class MissingActorContextError extends Error {\n /** @param message - human-readable description of the missing claim. */\n constructor(message: string) {\n super(message);\n this.name = \"MissingActorContextError\";\n }\n}\n","/**\n * Per-bus `Source` constants for the three OpenHI EventBridge buses.\n *\n * Every workflow event carries one of these values in its EventBridge\n * `Source` field. Bus selection follows ADR-016 §Decision #1.\n *\n * @see https://github.com/codedrifters/openhi-planning/blob/main/docs/src/content/docs/requirements/architectural-decisions/ADR-016-workflow-boundary-strategy.md\n */\n\n/** Source for control-plane workflow events (Tenant / Workspace / User / Membership / Role / RoleAssignment / Configuration). */\nexport const OPENHI_CONTROL_SOURCE = \"openhi.control\" as const;\n\n/** Source for data-plane workflow events (committed writes to the FHIR data store). */\nexport const OPENHI_DATA_SOURCE = \"openhi.data\" as const;\n\n/** Source for ops-plane workflow events (platform telemetry, deployments, build events). */\nexport const OPENHI_OPS_SOURCE = \"openhi.ops\" as const;\n\n/**\n * Discriminated union over the three OpenHI EventBridge sources.\n *\n * A publisher that passes any other string for the EventBridge `Source`\n * field is rejected at compile time.\n */\nexport type OpenHiSource =\n | typeof OPENHI_CONTROL_SOURCE\n | typeof OPENHI_DATA_SOURCE\n | typeof OPENHI_OPS_SOURCE;\n\n/**\n * Default EventBridge bus name for each OpenHI source.\n *\n * Deployments may override per-source via\n * `PublisherOptions.busNameByPlane`.\n */\nexport const DEFAULT_BUS_NAME_BY_SOURCE: Record<OpenHiSource, string> = {\n [OPENHI_CONTROL_SOURCE]: \"openhi-control-event-bus\",\n [OPENHI_DATA_SOURCE]: \"openhi-data-event-bus\",\n [OPENHI_OPS_SOURCE]: \"openhi-ops-event-bus\",\n};\n","import type { OpenHiSource } from \"../sources\";\n\n/**\n * One entry in the workflow detail-type registry.\n *\n * Each registered detail-type binds a typed `detail` payload to:\n * - the EventBridge `Source` (and therefore the bus) it ships on,\n * - the `detail-type` string consumers subscribe to,\n * - per-event metadata (`crossPlane`, `dedupRequired`) read by\n * downstream tooling (AsyncAPI generator, placement matrix).\n *\n * The `_detail` property is a phantom marker type only — never\n * read, never written, never instantiated. It carries the\n * compile-time TDetail through the entry so callers of\n * `publishWorkflowEvent` / `parseWorkflowEvent` see the typed\n * payload at the call site.\n */\nexport interface WorkflowDetailTypeEntry<TDetail> {\n /** Versioned detail-type string, e.g. `tenant.onboarded.v1`. */\n readonly detailType: string;\n /** The bus this detail-type ships on (compile-time enforced). */\n readonly source: OpenHiSource;\n /** Phantom marker carrying the payload shape. */\n readonly _detail?: TDetail;\n /** Marks events that cross plane boundaries (placement-matrix metadata). */\n readonly crossPlane?: boolean;\n /** Marks events that retryable consumers MUST dedupe on. */\n readonly dedupRequired?: boolean;\n}\n\n/**\n * Declare a registry entry with type inference.\n *\n * Call sites:\n *\n * ```ts\n * export const TenantOnboardedV1 = defineDetailType<TenantOnboardedV1Detail>({\n * detailType: \"tenant.onboarded.v1\",\n * source: OPENHI_CONTROL_SOURCE,\n * dedupRequired: true,\n * });\n * ```\n *\n * Detail-type strings follow `<area>.<event>.<version>` (TR-016 §Open\n * Items #2). The conformance regex below is the platform-wide format.\n */\nexport function defineDetailType<TDetail>(\n entry: Omit<WorkflowDetailTypeEntry<TDetail>, \"_detail\">,\n): WorkflowDetailTypeEntry<TDetail> {\n if (!isWellFormedDetailType(entry.detailType)) {\n throw new InvalidDetailTypeRegistrationError(\n `Detail-type \"${entry.detailType}\" does not match the platform-wide format <area>.<event>.v<integer>. See TR-016 §Open Items #2.`,\n );\n }\n return entry;\n}\n\n/**\n * Pattern enforced on every registered detail-type:\n * `<area>.<event>.v<integer>` where each segment is lowercase\n * alphanumeric with optional dashes.\n *\n * Multi-level areas (e.g. `fhir.audit-event.recorded.v1`) are\n * intentionally not yet allowed; TR-016 §Open Items #2 defers that.\n */\nconst DETAIL_TYPE_PATTERN =\n /^[a-z0-9]+(?:-[a-z0-9]+)*\\.[a-z0-9]+(?:-[a-z0-9]+)*\\.v\\d+$/;\n\n/** Return `true` when `detailType` matches the platform-wide format. */\nexport function isWellFormedDetailType(detailType: string): boolean {\n return DETAIL_TYPE_PATTERN.test(detailType);\n}\n\n/** Thrown by `defineDetailType` when the supplied string violates the format. */\nexport class InvalidDetailTypeRegistrationError extends Error {\n /** @param message - human-readable description of the violation. */\n constructor(message: string) {\n super(message);\n this.name = \"InvalidDetailTypeRegistrationError\";\n }\n}\n","import { OPENHI_DATA_SOURCE, OPENHI_OPS_SOURCE } from \"../sources\";\nimport { defineDetailType } from \"./registry\";\n\n/**\n * Owning-entity types covered by the TR-022 hard-delete cascade.\n * The cascade pipeline today targets {@link OWNING_ENTITY_TYPE.Workspace}\n * and {@link OWNING_ENTITY_TYPE.User} — the two owning entities whose\n * deletion orphans adjacency-list projections under their partition.\n * Tenant hard-delete is intentionally out of scope (it cascades a much\n * wider graph and is handled outside this pipeline).\n */\nexport const OWNING_ENTITY_TYPE = {\n Workspace: \"Workspace\",\n User: \"User\",\n} as const;\n/** Union of the values of {@link OWNING_ENTITY_TYPE}. */\nexport type OwningEntityType =\n (typeof OWNING_ENTITY_TYPE)[keyof typeof OWNING_ENTITY_TYPE];\n\n/**\n * Payload (`detail.payload`) of `control-plane.owning-delete.v1` —\n * published on the `openhi.data` data event bus when the Firehose\n * transform Lambda observes a stream record showing\n * `lifecycleState: active → deleting` on a canonical Workspace or\n * User record. The owning-delete cascade state machine subscribes to\n * this detail-type.\n *\n * The full EventBridge `detail` carries this payload nested inside a\n * `WorkflowEvent<ControlPlaneOwningDeleteV1Detail>` envelope per\n * ADR-016 standard envelope shape — `eventId`, `attempt`,\n * `correlationId`, `causationId`, `actor`, `occurredAt` live on the\n * envelope, not on this payload.\n *\n * @see .state/adr-018-implementation-guide.md section 4 (TR-022 Hard-Delete-Cascade Contract)\n */\nexport interface ControlPlaneOwningDeleteV1Detail {\n readonly ownerType: OwningEntityType;\n readonly ownerId: string;\n /** Present for Workspace owners; absent for User (cross-tenant identity). */\n readonly tenantId?: string;\n}\n\n/**\n * Registry entry for `control-plane.owning-delete.v1`.\n *\n * The platform-wide detail-type format\n * (`<area>.<event>.v<integer>` enforced by `isWellFormedDetailType`)\n * does not allow the bare `ControlPlaneOwningDelete` shape the\n * ADR-018 implementation guide pseudocode uses; the registered string\n * is the format-compliant equivalent. The EventBridge rule pattern on\n * the cascade state machine matches this exact string.\n *\n * `dedupRequired: true` — the cascade state machine MUST dedupe on\n * `(eventId, attempt)` via `WorkflowDedupClient` so EventBridge retries\n * (which the data event bus delivers at-least-once) never start two\n * concurrent cascades on the same owning entity.\n */\nexport const ControlPlaneOwningDeleteV1 =\n defineDetailType<ControlPlaneOwningDeleteV1Detail>({\n detailType: \"control-plane.owning-delete.v1\",\n source: OPENHI_DATA_SOURCE,\n dedupRequired: true,\n });\n\n/**\n * Payload of `control-plane.owning-delete-complete.v1` — terminal\n * event published on the `openhi.ops` ops event bus when the cascade\n * state machine has successfully deleted every child projection and\n * the canonical owning record itself. Observability sinks subscribe\n * to this event to confirm cascade completion and emit metrics.\n *\n * @see .state/adr-018-implementation-guide.md section 4 (Terminal events on EventBridge)\n */\nexport interface ControlPlaneOwningDeleteCompleteV1Detail {\n readonly ownerType: OwningEntityType;\n readonly ownerId: string;\n readonly tenantId?: string;\n /** Number of `TransactWriteItems` chunks the cascade issued. */\n readonly chunkCount: number;\n /** Total number of projection rows removed by the cascade. */\n readonly projectionsRemoved: number;\n /** Wall-clock duration of the cascade, in milliseconds. */\n readonly durationMs: number;\n /** ISO-8601 UTC timestamp of cascade completion. */\n readonly completedAt: string;\n}\n\n/** Registry entry for `control-plane.owning-delete-complete.v1`. */\nexport const ControlPlaneOwningDeleteCompleteV1 =\n defineDetailType<ControlPlaneOwningDeleteCompleteV1Detail>({\n detailType: \"control-plane.owning-delete-complete.v1\",\n source: OPENHI_OPS_SOURCE,\n dedupRequired: true,\n });\n\n/**\n * Payload of `control-plane.owning-delete-failed.v1` — terminal event\n * published on the `openhi.ops` ops event bus when the cascade state\n * machine fails irrecoverably. The canonical owning record is left at\n * `lifecycleState = \"deleted-failed\"` for operator-driven recovery;\n * alerting subscribers fan out to oncall.\n *\n * @see .state/adr-018-implementation-guide.md section 4 (Terminal events on EventBridge)\n */\nexport interface ControlPlaneOwningDeleteFailedV1Detail {\n readonly ownerType: OwningEntityType;\n readonly ownerId: string;\n readonly tenantId?: string;\n /** Step Functions execution ARN — operators dereference for root cause. */\n readonly executionArn: string;\n readonly chunkCount: number;\n /** Last opaque cursor the state machine successfully processed, or null. */\n readonly lastProcessedCursor: string | null;\n /** Short failure cause string from the Step Functions Catch block. */\n readonly failureCause: string;\n readonly failedAt: string;\n}\n\n/** Registry entry for `control-plane.owning-delete-failed.v1`. */\nexport const ControlPlaneOwningDeleteFailedV1 =\n defineDetailType<ControlPlaneOwningDeleteFailedV1Detail>({\n detailType: \"control-plane.owning-delete-failed.v1\",\n source: OPENHI_OPS_SOURCE,\n dedupRequired: true,\n });\n\n/**\n * Renamable entity types covered by the TR-023 rename cascade.\n *\n * Per ADR-018 only the three carrier entities whose display name is\n * denormalized onto Membership / RoleAssignment projections trigger a\n * cascade — Tenant, User, Role. A Workspace rename is intentionally\n * **not** in scope: Workspace's display name is denormalized onto the\n * Membership user-projection workspace sub-lane, but TR-024 § Open Item\n * #4 defers a formal Workspace-rename cascade — the SK falls back to a\n * sentinel until a future TR commits the contract.\n */\nexport const RENAMABLE_ENTITY_TYPE = {\n Tenant: \"Tenant\",\n User: \"User\",\n Role: \"Role\",\n} as const;\n/** Union of the values of {@link RENAMABLE_ENTITY_TYPE}. */\nexport type RenamableEntityType =\n (typeof RENAMABLE_ENTITY_TYPE)[keyof typeof RENAMABLE_ENTITY_TYPE];\n\n/**\n * Payload (`detail.payload`) of `control-plane.rename.v1` — published\n * on the `openhi.data` data event bus when the Firehose transform\n * Lambda observes a stream record showing a display-name change on a\n * canonical Tenant, User, or Role record. The rename-cascade state\n * machine subscribes to this detail-type.\n *\n * The full EventBridge `detail` carries this payload nested inside a\n * `WorkflowEvent<ControlPlaneRenameV1Detail>` envelope per ADR-016\n * standard envelope shape — `eventId`, `attempt`, `correlationId`,\n * `causationId`, `actor`, `occurredAt` live on the envelope, not on\n * this payload.\n *\n * The platform-wide detail-type format\n * (`<area>.<event>.v<integer>` enforced by `isWellFormedDetailType`)\n * does not allow the bare `ControlPlaneRename` shape the ADR-018\n * implementation guide pseudocode uses; the registered string is the\n * format-compliant equivalent (mirroring the\n * `control-plane.owning-delete.v1` naming).\n *\n * @see .state/adr-018-implementation-guide.md section 5 (TR-023 Rename-Cascade Consumer Contract)\n */\nexport interface ControlPlaneRenameV1Detail {\n readonly entityType: RenamableEntityType;\n readonly entityId: string;\n /** Present for User and Role; absent for Tenant (Tenant is the partition root). */\n readonly tenantId?: string;\n readonly oldName: string;\n readonly newName: string;\n /** Pre-computed via `extractLabel` so consumers do not re-normalize. */\n readonly oldNormalizedName: string;\n readonly newNormalizedName: string;\n}\n\n/**\n * Registry entry for `control-plane.rename.v1`.\n *\n * `dedupRequired: true` — the cascade state machine MUST dedupe on\n * `(eventId, attempt)` via `WorkflowDedupClient` so EventBridge retries\n * (which the data event bus delivers at-least-once) never start two\n * concurrent cascades on the same rename.\n */\nexport const ControlPlaneRenameV1 =\n defineDetailType<ControlPlaneRenameV1Detail>({\n detailType: \"control-plane.rename.v1\",\n source: OPENHI_DATA_SOURCE,\n dedupRequired: true,\n });\n\n/**\n * Payload of `control-plane.rename-complete.v1` — terminal event\n * published on the `openhi.ops` ops event bus when the cascade state\n * machine has successfully rewritten every affected projection row.\n * UI clients subscribe so they can refresh stale list views.\n *\n * @see .state/adr-018-implementation-guide.md section 5\n */\nexport interface ControlPlaneRenameCompleteV1Detail {\n readonly entityType: RenamableEntityType;\n readonly entityId: string;\n readonly tenantId?: string;\n readonly newName: string;\n /** Number of `TransactWriteItems` chunks the cascade issued. */\n readonly chunkCount: number;\n /** Total number of projection rows rewritten by the cascade. */\n readonly itemsRewritten: number;\n /** Wall-clock duration of the cascade, in milliseconds. */\n readonly durationMs: number;\n /** ISO-8601 UTC timestamp of cascade completion. */\n readonly completedAt: string;\n}\n\n/** Registry entry for `control-plane.rename-complete.v1`. */\nexport const ControlPlaneRenameCompleteV1 =\n defineDetailType<ControlPlaneRenameCompleteV1Detail>({\n detailType: \"control-plane.rename-complete.v1\",\n source: OPENHI_OPS_SOURCE,\n dedupRequired: true,\n });\n\n/**\n * Payload of `control-plane.rename-failed.v1` — terminal event\n * published on the `openhi.ops` ops event bus when the cascade state\n * machine fails irrecoverably. Alerting subscribers fan out to oncall.\n *\n * @see .state/adr-018-implementation-guide.md section 5\n */\nexport interface ControlPlaneRenameFailedV1Detail {\n readonly entityType: RenamableEntityType;\n readonly entityId: string;\n readonly tenantId?: string;\n /** Step Functions execution ARN — operators dereference for root cause. */\n readonly executionArn: string;\n readonly chunkCount: number;\n /** Short failure cause string from the Step Functions Catch block. */\n readonly failureCause: string;\n readonly failedAt: string;\n}\n\n/** Registry entry for `control-plane.rename-failed.v1`. */\nexport const ControlPlaneRenameFailedV1 =\n defineDetailType<ControlPlaneRenameFailedV1Detail>({\n detailType: \"control-plane.rename-failed.v1\",\n source: OPENHI_OPS_SOURCE,\n dedupRequired: true,\n });\n","import { OPENHI_CONTROL_SOURCE } from \"../sources\";\nimport { defineDetailType } from \"./registry\";\n\n/**\n * `detail` payload for `platform.deployment-completed.v1`.\n *\n * Projected by the platform-deploy bridge from a CloudFormation\n * `Stack Status Change` event (`CREATE_COMPLETE` / `UPDATE_COMPLETE`)\n * on a tagged OpenHI platform stack. Downstream control-plane\n * workflows (e.g. seed-system-roles, seed-demo-data) subscribe\n * to this detail-type on the control event bus.\n */\nexport interface PlatformDeploymentCompletedV1Detail {\n /** CloudFormation stack name (`AWS::CloudFormation::Stack` `StackName`). */\n readonly stackName: string;\n /** Full CloudFormation stack ARN. */\n readonly stackId: string;\n /** AWS region the stack deployed into (e.g. `us-east-1`). */\n readonly region: string;\n /** 12-digit AWS account id the stack deployed into. */\n readonly accountId: string;\n /** Terminal stack status that triggered the bridge. */\n readonly status: \"CREATE_COMPLETE\" | \"UPDATE_COMPLETE\";\n /** Free-form reason text from CloudFormation; absent on most events. */\n readonly statusReason?: string;\n /**\n * Projected subset of stack tags. The bridge resolves tags via\n * `cloudformation:DescribeStacks` because the source EventBridge\n * event omits them.\n */\n readonly stackTags: ReadonlyArray<{\n readonly key: string;\n readonly value: string;\n }>;\n /** ISO-8601 timestamp from the source EventBridge `time` field. */\n readonly cloudformationEventTime: string;\n}\n\n/**\n * Registry entry for `platform.deployment-completed.v1`.\n *\n * Published on the control event bus (`OPENHI_CONTROL_SOURCE`) per\n * the workflow placement matrix (codedrifters/openhi#953 row 4):\n * the AWS-native source is the ops-plane default bus, but the bridge\n * republishes onto the control bus because the downstream consumers\n * are control-plane workflows.\n *\n * `dedupRequired: true` — at-least-once redelivery from EventBridge\n * means retryable consumers MUST dedupe on `(eventId, attempt)` via\n * `WorkflowDedupClient`.\n */\nexport const PlatformDeploymentCompletedV1 =\n defineDetailType<PlatformDeploymentCompletedV1Detail>({\n detailType: \"platform.deployment-completed.v1\",\n source: OPENHI_CONTROL_SOURCE,\n dedupRequired: true,\n });\n\n/**\n * `detail` payload for `platform.system-data-seeded.v1`.\n *\n * Published by the `seed-system-data` workflow after it has\n * idempotently re-asserted every platform-singleton control-plane\n * record (today: the three canonical Roles; future: additional system\n * data) on the back of a `platform.deployment-completed.v1` event.\n *\n * Downstream control-plane workflows that depend on the\n * platform-singleton records existing — `seed-demo-data`, for\n * example — subscribe to this detail-type instead of the raw\n * deploy-completion event so the dependency is enforced by a\n * happens-before edge rather than by EventBridge retry timing.\n */\nexport interface PlatformSystemDataSeededV1Detail {\n /**\n * EventBridge `eventId` of the originating\n * `platform.deployment-completed.v1` event that triggered the\n * system-data seeding. Propagated for correlation in logs and\n * downstream causation chains.\n */\n readonly sourceEventId: string;\n /**\n * Full CloudFormation stack ARN of the deploy that triggered the\n * system-data seeding. Mirrors the field on the originating\n * `PlatformDeploymentCompletedV1Detail`; downstream consumers can\n * filter by stack-id prefix without re-reading the source event.\n */\n readonly sourceStackId: string;\n /**\n * Number of platform-singleton records re-asserted on this run.\n * Useful for sanity checks and observability — divergence between\n * deploys signals either a generator-emitted catalog change or a\n * partial-failure recovery from the replay tooling.\n */\n readonly seededRecordCount: number;\n}\n\n/**\n * Registry entry for `platform.system-data-seeded.v1`.\n *\n * Published onto the control event bus (`OPENHI_CONTROL_SOURCE`).\n * `dedupRequired: true` — downstream consumers MUST dedup on\n * `(eventId, attempt)` via `WorkflowDedupClient`, same as every other\n * retryable consumer.\n */\nexport const PlatformSystemDataSeededV1 =\n defineDetailType<PlatformSystemDataSeededV1Detail>({\n detailType: \"platform.system-data-seeded.v1\",\n source: OPENHI_CONTROL_SOURCE,\n dedupRequired: true,\n });\n","export * from \"./control-plane\";\nexport * from \"./platform\";\nexport * from \"./registry\";\n","import { randomUUID } from \"node:crypto\";\nimport {\n EventBridgeClient,\n PutEventsCommand,\n} from \"@aws-sdk/client-eventbridge\";\n\nimport type { WorkflowDetailTypeEntry } from \"./detail-types/registry\";\nimport type { WorkflowActor, WorkflowEvent } from \"./envelope\";\nimport { ENVELOPE_VERSION } from \"./envelope-version\";\nimport { DEFAULT_BUS_NAME_BY_SOURCE, type OpenHiSource } from \"./sources\";\n\n/**\n * Caller-supplied envelope context the publisher consumes.\n *\n * The actor is required on every publish — pre-provisioning bootstrap\n * workflows pass a `{ system: <role-name> }` actor.\n *\n * `correlationId` and `causationId` propagate from an upstream event\n * when this publisher is consuming-then-publishing; pass them through\n * verbatim from the inbound envelope's fields. Both are optional;\n * when omitted the publisher treats the publish as a chain origin\n * (`correlationId` = fresh UUID, `causationId` = null).\n */\nexport interface PublishContext {\n readonly actor: WorkflowActor;\n readonly correlationId?: string;\n readonly causationId?: string | null;\n}\n\n/**\n * Per-call output of a successful publish.\n */\nexport interface PublishResult {\n readonly eventId: string;\n}\n\n/**\n * Publisher overrides applied to every call against a single client.\n *\n * `eventIdGenerator`, `correlationIdGenerator`, and `now` are\n * test-only seams; production callers omit them and the publisher\n * uses `crypto.randomUUID()` and `new Date()`.\n */\nexport interface PublisherOptions {\n /** Override the default bus name for one or more sources. */\n readonly busNameByPlane?: Partial<Record<OpenHiSource, string>>;\n /** Test seam — supply a deterministic UUID generator for `eventId`. */\n readonly eventIdGenerator?: () => string;\n /** Test seam — supply a deterministic UUID generator for new `correlationId` values. */\n readonly correlationIdGenerator?: () => string;\n /** Test seam — supply a deterministic clock for `occurredAt`. */\n readonly now?: () => Date;\n}\n\n/**\n * Tree-shaped publisher client per ADR-016 Recommendation.\n *\n * The `publish` primitive accepts any registered detail-type and\n * returns a typed `PublishResult`. Downstream tree shaping\n * (`client.<bus>.<area>.<event>.publish(payload, ctx)`) is built from\n * the detail-type registry once entries are registered; until then,\n * callers invoke `client.publish(entry, payload, ctx)` directly.\n */\nexport interface WorkflowsClient {\n /**\n * Construct a workflow envelope around `payload` and publish it to\n * the EventBridge bus configured for `entry.source`.\n */\n publish<TPayload>(\n entry: WorkflowDetailTypeEntry<TPayload>,\n payload: TPayload,\n ctx: PublishContext,\n ): Promise<PublishResult>;\n}\n\n/**\n * Factory that returns a `WorkflowsClient` bound to a single\n * `EventBridgeClient`.\n */\nexport function workflowsClient(\n bridge: EventBridgeClient,\n options: PublisherOptions = {},\n): WorkflowsClient {\n return {\n publish: (entry, payload, ctx) =>\n publishWorkflowEvent(bridge, entry, payload, ctx, options),\n };\n}\n\n/**\n * Construct a workflow envelope and publish it via\n * `EventBridge.PutEvents`.\n *\n * Exposed as a stand-alone function for callers that prefer the\n * primitive over the `WorkflowsClient` indirection.\n */\nexport async function publishWorkflowEvent<TPayload>(\n bridge: EventBridgeClient,\n entry: WorkflowDetailTypeEntry<TPayload>,\n payload: TPayload,\n ctx: PublishContext,\n options: PublisherOptions = {},\n): Promise<PublishResult> {\n const eventIdGenerator = options.eventIdGenerator ?? (() => randomUUID());\n const correlationIdGenerator =\n options.correlationIdGenerator ?? (() => randomUUID());\n const now = options.now ?? (() => new Date());\n\n const envelope: WorkflowEvent<TPayload> = {\n eventId: eventIdGenerator(),\n attempt: 1,\n correlationId: ctx.correlationId ?? correlationIdGenerator(),\n causationId: ctx.causationId ?? null,\n actor: ctx.actor,\n occurredAt: now().toISOString(),\n envelopeVersion: ENVELOPE_VERSION,\n payload,\n };\n\n const busName =\n options.busNameByPlane?.[entry.source] ??\n DEFAULT_BUS_NAME_BY_SOURCE[entry.source];\n\n const result = await bridge.send(\n new PutEventsCommand({\n Entries: [\n {\n EventBusName: busName,\n Source: entry.source,\n DetailType: entry.detailType,\n Detail: JSON.stringify(envelope),\n },\n ],\n }),\n );\n\n if ((result.FailedEntryCount ?? 0) > 0) {\n const first = result.Entries?.[0];\n throw new WorkflowPublishError(\n `EventBridge rejected ${entry.detailType} publish on bus ${busName}: ${first?.ErrorCode ?? \"unknown\"} — ${first?.ErrorMessage ?? \"no error message\"}`,\n );\n }\n\n return { eventId: envelope.eventId };\n}\n\n/** Thrown when EventBridge rejects a `PutEvents` entry. */\nexport class WorkflowPublishError extends Error {\n /** @param message - human-readable description of the failed publish. */\n constructor(message: string) {\n super(message);\n this.name = \"WorkflowPublishError\";\n }\n}\n","import type { WorkflowDetailTypeEntry } from \"./detail-types/registry\";\nimport type { WorkflowEvent } from \"./envelope\";\nimport { isSupportedEnvelopeVersion } from \"./envelope-version\";\n\n/**\n * Structural shape of the EventBridge event objects this SDK's\n * consumer parses.\n *\n * Matches `@types/aws-lambda`'s `EventBridgeEvent<string, unknown>`\n * by structural compatibility without requiring callers to import\n * that types package — consumers may pass either an\n * `EventBridgeEvent` from `aws-lambda` or any record-shaped object\n * carrying the same keys.\n */\nexport interface EventBridgeEventLike {\n readonly source: string;\n readonly \"detail-type\": string;\n readonly detail: unknown;\n}\n\n/**\n * The `(eventId, attempt)` tuple every retryable consumer hands to\n * the `WorkflowDedupTable` client.\n */\nexport interface DedupKey {\n readonly eventId: string;\n readonly attempt: number;\n}\n\n/**\n * Output of `parseWorkflowEvent` — the validated envelope plus the\n * dedup tuple.\n */\nexport interface ParsedWorkflowEvent<TPayload> {\n readonly envelope: WorkflowEvent<TPayload>;\n readonly dedupKey: DedupKey;\n}\n\n/**\n * Parse an EventBridge event into a typed envelope and surface the\n * `(eventId, attempt)` tuple the dedup-table client consumes.\n *\n * Validates:\n * - `event.source` matches `expected.source`\n * - `event[\"detail-type\"]` matches `expected.detailType`\n * - the envelope's `envelopeVersion` is within the SDK's supported range\n * - every required envelope field is present and well-shaped\n */\nexport function parseWorkflowEvent<TPayload>(\n event: EventBridgeEventLike,\n expected: WorkflowDetailTypeEntry<TPayload>,\n): ParsedWorkflowEvent<TPayload> {\n if (event.source !== expected.source) {\n throw new InvalidWorkflowEventError(\n `EventBridge source \"${event.source}\" does not match expected detail-type's source \"${expected.source}\".`,\n );\n }\n\n if (event[\"detail-type\"] !== expected.detailType) {\n throw new InvalidWorkflowEventError(\n `EventBridge detail-type \"${event[\"detail-type\"]}\" does not match expected \"${expected.detailType}\".`,\n );\n }\n\n const candidate = asEnvelopeCandidate(event.detail);\n\n if (!isSupportedEnvelopeVersion(candidate.envelopeVersion)) {\n throw new UnsupportedEnvelopeVersionError(\n `Envelope version \"${candidate.envelopeVersion}\" is outside the SDK's supported range.`,\n );\n }\n\n const envelope: WorkflowEvent<TPayload> = {\n eventId: candidate.eventId,\n attempt: candidate.attempt,\n correlationId: candidate.correlationId,\n causationId: candidate.causationId,\n actor: candidate.actor,\n occurredAt: candidate.occurredAt,\n envelopeVersion: candidate.envelopeVersion,\n payload: candidate.payload as TPayload,\n };\n\n return {\n envelope,\n dedupKey: { eventId: envelope.eventId, attempt: envelope.attempt },\n };\n}\n\n/**\n * Validate that the EventBridge `detail` (which carries the workflow\n * envelope) has every required field with a plausible type. Returns a\n * typed `WorkflowEvent<unknown>` so the caller can narrow `payload`\n * once routing has succeeded.\n */\nfunction asEnvelopeCandidate(detail: unknown): WorkflowEvent<unknown> {\n if (detail === null || typeof detail !== \"object\") {\n throw new InvalidWorkflowEventError(\n \"EventBridge detail is not a non-null object.\",\n );\n }\n\n const obj = detail as Record<string, unknown>;\n\n assertString(obj, \"eventId\");\n assertPositiveInteger(obj, \"attempt\");\n assertString(obj, \"correlationId\");\n assertCausationId(obj);\n assertActor(obj);\n assertString(obj, \"occurredAt\");\n assertString(obj, \"envelopeVersion\");\n\n if (!(\"payload\" in obj)) {\n throw new InvalidWorkflowEventError(\n \"Envelope is missing required field: payload.\",\n );\n }\n\n return obj as unknown as WorkflowEvent<unknown>;\n}\n\nfunction assertString(\n obj: Record<string, unknown>,\n field: string,\n): asserts obj is Record<string, unknown> & Record<typeof field, string> {\n const value = obj[field];\n if (typeof value !== \"string\" || value.length === 0) {\n throw new InvalidWorkflowEventError(\n `Envelope field \"${field}\" must be a non-empty string.`,\n );\n }\n}\n\nfunction assertPositiveInteger(\n obj: Record<string, unknown>,\n field: string,\n): void {\n const value = obj[field];\n if (typeof value !== \"number\" || !Number.isInteger(value) || value < 1) {\n throw new InvalidWorkflowEventError(\n `Envelope field \"${field}\" must be a 1-indexed integer.`,\n );\n }\n}\n\nfunction assertCausationId(obj: Record<string, unknown>): void {\n if (!(\"causationId\" in obj)) {\n throw new InvalidWorkflowEventError(\n \"Envelope is missing required field: causationId.\",\n );\n }\n const value = obj.causationId;\n if (value !== null && (typeof value !== \"string\" || value.length === 0)) {\n throw new InvalidWorkflowEventError(\n 'Envelope field \"causationId\" must be a non-empty string or null.',\n );\n }\n}\n\nfunction assertActor(obj: Record<string, unknown>): void {\n const actor = obj.actor;\n if (actor === null || typeof actor !== \"object\") {\n throw new InvalidWorkflowEventError(\n 'Envelope field \"actor\" must be an object.',\n );\n }\n const actorObj = actor as Record<string, unknown>;\n const isUserActor =\n typeof actorObj.ohi_uid === \"string\" &&\n typeof actorObj.ohi_uname === \"string\" &&\n typeof actorObj.ohi_tid === \"string\" &&\n typeof actorObj.ohi_wid === \"string\";\n const isSystemActor = typeof actorObj.system === \"string\";\n if (!isUserActor && !isSystemActor) {\n throw new InvalidWorkflowEventError(\n 'Envelope field \"actor\" must be either a user-actor (ohi_tid, ohi_wid, ohi_uid, ohi_uname) or a system-actor ({ system: string }).',\n );\n }\n}\n\n/** Thrown when the event does not match the expected detail-type entry. */\nexport class InvalidWorkflowEventError extends Error {\n /** @param message - human-readable description of the validation failure. */\n constructor(message: string) {\n super(message);\n this.name = \"InvalidWorkflowEventError\";\n }\n}\n\n/** Thrown when the envelope version is outside the SDK's supported range. */\nexport class UnsupportedEnvelopeVersionError extends Error {\n /** @param message - human-readable description of the unsupported version. */\n constructor(message: string) {\n super(message);\n this.name = \"UnsupportedEnvelopeVersionError\";\n }\n}\n","/**\n * Environment-variable name the construct's `grantConsumer` integration\n * injects into a consumer Lambda; the runtime `WorkflowDedupClient`\n * reads it to discover the shared dedup table without a prop or import.\n *\n * The constant is the single cross-package contract between\n * `@openhi/constructs` (which emits the env var) and `@openhi/workflows`\n * (which consumes it). Renaming or removing it is a breaking change.\n */\nexport const WORKFLOW_DEDUP_TABLE_NAME_ENV_VAR =\n \"OPENHI_WORKFLOW_DEDUP_TABLE_NAME\";\n\n/** Default TTL for dedup rows: 14 days, expressed in seconds (per TR-015). */\nexport const WORKFLOW_DEDUP_DEFAULT_TTL_SECONDS = 14 * 24 * 60 * 60;\n\n/** Maximum length of a `consumerName` (per TR-015). */\nexport const WORKFLOW_DEDUP_MAX_CONSUMER_NAME_LENGTH = 64;\n","import {\n ConditionalCheckFailedException,\n DynamoDBClient,\n PutItemCommand,\n UpdateItemCommand,\n} from \"@aws-sdk/client-dynamodb\";\n\nimport {\n WORKFLOW_DEDUP_DEFAULT_TTL_SECONDS,\n WORKFLOW_DEDUP_MAX_CONSUMER_NAME_LENGTH,\n WORKFLOW_DEDUP_TABLE_NAME_ENV_VAR,\n} from \"./env\";\n\n/**\n * Inputs to `recordIfAbsent`.\n *\n * `eventId` and `attempt` are the dedup tuple every retryable\n * consumer derives from the standard envelope (see `parseWorkflowEvent`\n * and the `DedupKey` type); call sites typically spread the dedupKey\n * directly alongside the consumer name.\n */\nexport interface RecordIfAbsentInput {\n /** Stable logical name of the consumer. At most 64 chars; no whitespace. */\n readonly consumerName: string;\n /** Per-event UUID from the standard envelope. */\n readonly eventId: string;\n /** 1-indexed delivery attempt from the standard envelope. */\n readonly attempt: number;\n /** Override the 14-day default TTL. Must be a positive integer. */\n readonly ttlSeconds?: number;\n}\n\n/**\n * Result shape per TR-015. `recorded` is true on first delivery and\n * false on a duplicate; on a duplicate `alreadyProcessed` is also\n * true so callers can pattern-match without re-checking the boolean.\n */\nexport type RecordIfAbsentResult =\n | { readonly recorded: true }\n | { readonly recorded: false; readonly alreadyProcessed: true };\n\n/**\n * Inputs to `markFailed`.\n *\n * Updates the existing dedup row with `failed: true`, `failureReason`,\n * `failedAt` so the replay tooling (TR-016 follow-up) can re-publish\n * the originating event with a fresh `attempt`.\n */\nexport interface MarkFailedInput {\n /** Stable logical name of the consumer. */\n readonly consumerName: string;\n /** Per-event UUID. */\n readonly eventId: string;\n /** 1-indexed delivery attempt. */\n readonly attempt: number;\n /** Short string describing why the consumer gave up. */\n readonly reason: string;\n}\n\n/**\n * Runtime SDK every retryable workflow consumer calls before\n * performing its side-effect. See TR-015 for the contract.\n */\nexport interface WorkflowDedupClient {\n /**\n * Conditionally record a dedup token for the supplied consumer name\n * and dedup tuple. See `RecordIfAbsentResult` for the return shape.\n */\n recordIfAbsent(input: RecordIfAbsentInput): Promise<RecordIfAbsentResult>;\n /**\n * Mark the existing dedup row as permanently failed. Fire-and-forget\n * semantics for the caller; unexpected DynamoDB errors propagate.\n */\n markFailed(input: MarkFailedInput): Promise<void>;\n}\n\n/** Options shared by the factory and the standalone primitives. */\nexport interface WorkflowDedupClientOptions {\n /**\n * Table name. Defaults to `process.env[WORKFLOW_DEDUP_TABLE_NAME_ENV_VAR]`\n * (populated by the `WorkflowDedupTable` construct's `grantConsumer`).\n */\n readonly tableName?: string;\n /** Override the 14-day default TTL for every `recordIfAbsent` call. */\n readonly defaultTtlSeconds?: number;\n /** Test seam — deterministic clock for `recordedAt` / `expiresAt`. */\n readonly now?: () => Date;\n}\n\n/** Factory that returns a `WorkflowDedupClient` bound to a single DynamoDB client. */\nexport function workflowDedupClient(\n dynamodb: DynamoDBClient,\n options: WorkflowDedupClientOptions = {},\n): WorkflowDedupClient {\n return {\n recordIfAbsent: (input) => recordIfAbsent(dynamodb, input, options),\n markFailed: (input) => markFailed(dynamodb, input, options),\n };\n}\n\n/**\n * Standalone primitive — exposed for callers that prefer it over the\n * `WorkflowDedupClient` indirection.\n */\nexport async function recordIfAbsent(\n dynamodb: DynamoDBClient,\n input: RecordIfAbsentInput,\n options: WorkflowDedupClientOptions = {},\n): Promise<RecordIfAbsentResult> {\n assertConsumerName(input.consumerName);\n assertPositiveInteger(input.attempt, \"attempt\");\n const ttlSeconds =\n input.ttlSeconds ??\n options.defaultTtlSeconds ??\n WORKFLOW_DEDUP_DEFAULT_TTL_SECONDS;\n if (!Number.isInteger(ttlSeconds) || ttlSeconds <= 0) {\n throw new WorkflowDedupInvalidInputError(\n `ttlSeconds must be a positive integer; got ${ttlSeconds}.`,\n );\n }\n\n const tableName = resolveTableName(options.tableName);\n const now = (options.now ?? defaultNow)();\n const sk = encodeSortKey(input.eventId, input.attempt);\n const expiresAt = Math.floor(now.getTime() / 1000) + ttlSeconds;\n\n try {\n await dynamodb.send(\n new PutItemCommand({\n TableName: tableName,\n Item: {\n consumerName: { S: input.consumerName },\n sk: { S: sk },\n eventId: { S: input.eventId },\n attempt: { N: String(input.attempt) },\n recordedAt: { S: now.toISOString() },\n expiresAt: { N: String(expiresAt) },\n },\n ConditionExpression:\n \"attribute_not_exists(consumerName) AND attribute_not_exists(sk)\",\n }),\n );\n return { recorded: true };\n } catch (err) {\n if (err instanceof ConditionalCheckFailedException) {\n return { recorded: false, alreadyProcessed: true };\n }\n throw err;\n }\n}\n\n/** Standalone primitive — flips `failed: true` on an existing dedup row. */\nexport async function markFailed(\n dynamodb: DynamoDBClient,\n input: MarkFailedInput,\n options: WorkflowDedupClientOptions = {},\n): Promise<void> {\n assertConsumerName(input.consumerName);\n assertPositiveInteger(input.attempt, \"attempt\");\n if (input.reason.length === 0) {\n throw new WorkflowDedupInvalidInputError(\"reason must be non-empty.\");\n }\n\n const tableName = resolveTableName(options.tableName);\n const now = (options.now ?? defaultNow)();\n const sk = encodeSortKey(input.eventId, input.attempt);\n\n await dynamodb.send(\n new UpdateItemCommand({\n TableName: tableName,\n Key: {\n consumerName: { S: input.consumerName },\n sk: { S: sk },\n },\n UpdateExpression:\n \"SET #failed = :failed, #failureReason = :reason, #failedAt = :failedAt\",\n ExpressionAttributeNames: {\n \"#failed\": \"failed\",\n \"#failureReason\": \"failureReason\",\n \"#failedAt\": \"failedAt\",\n },\n ExpressionAttributeValues: {\n \":failed\": { BOOL: true },\n \":reason\": { S: input.reason },\n \":failedAt\": { S: now.toISOString() },\n },\n }),\n );\n}\n\n/** Compose the composite sort key per the TR-015 encoding. */\nexport function encodeSortKey(eventId: string, attempt: number): string {\n if (eventId.length === 0) {\n throw new WorkflowDedupInvalidInputError(\"eventId must be non-empty.\");\n }\n return `${eventId}#${attempt}`;\n}\n\nfunction resolveTableName(explicit?: string): string {\n const name = explicit ?? process.env[WORKFLOW_DEDUP_TABLE_NAME_ENV_VAR];\n if (!name) {\n throw new WorkflowDedupTableNameMissingError(\n `Workflow dedup table name not set. Pass options.tableName or set ${WORKFLOW_DEDUP_TABLE_NAME_ENV_VAR}.`,\n );\n }\n return name;\n}\n\nfunction assertConsumerName(consumerName: string): void {\n if (consumerName.length === 0) {\n throw new WorkflowDedupInvalidInputError(\"consumerName must be non-empty.\");\n }\n if (consumerName.length > WORKFLOW_DEDUP_MAX_CONSUMER_NAME_LENGTH) {\n throw new WorkflowDedupInvalidInputError(\n `consumerName must be ≤${WORKFLOW_DEDUP_MAX_CONSUMER_NAME_LENGTH} chars; got ${consumerName.length}.`,\n );\n }\n if (/\\s/.test(consumerName)) {\n throw new WorkflowDedupInvalidInputError(\n \"consumerName must not contain whitespace.\",\n );\n }\n}\n\nfunction assertPositiveInteger(value: number, field: string): void {\n if (!Number.isInteger(value) || value < 1) {\n throw new WorkflowDedupInvalidInputError(\n `${field} must be a 1-indexed integer; got ${value}.`,\n );\n }\n}\n\nfunction defaultNow(): Date {\n return new Date();\n}\n\n/** Thrown when the dedup table name cannot be resolved. */\nexport class WorkflowDedupTableNameMissingError extends Error {\n /** @param message - human-readable description. */\n constructor(message: string) {\n super(message);\n this.name = \"WorkflowDedupTableNameMissingError\";\n }\n}\n\n/** Thrown when an input violates a TR-015 invariant. */\nexport class WorkflowDedupInvalidInputError extends Error {\n /** @param message - human-readable description. */\n constructor(message: string) {\n super(message);\n this.name = \"WorkflowDedupInvalidInputError\";\n }\n}\n","export {\n WORKFLOW_DEDUP_DEFAULT_TTL_SECONDS,\n WORKFLOW_DEDUP_MAX_CONSUMER_NAME_LENGTH,\n WORKFLOW_DEDUP_TABLE_NAME_ENV_VAR,\n} from \"./env\";\nexport {\n WorkflowDedupInvalidInputError,\n WorkflowDedupTableNameMissingError,\n encodeSortKey,\n markFailed,\n recordIfAbsent,\n workflowDedupClient,\n} from \"./workflow-dedup-client\";\nexport type {\n MarkFailedInput,\n RecordIfAbsentInput,\n RecordIfAbsentResult,\n WorkflowDedupClient,\n WorkflowDedupClientOptions,\n} from \"./workflow-dedup-client\";\n","export {\n ENVELOPE_VERSION,\n isSupportedEnvelopeVersion,\n} from \"./envelope-version\";\nexport {\n MissingActorContextError,\n isWorkflowSystemActor,\n isWorkflowUserActor,\n workflowUserActorFromClaims,\n} from \"./envelope\";\nexport type {\n WorkflowActor,\n WorkflowEvent,\n WorkflowSystemActor,\n WorkflowUserActor,\n} from \"./envelope\";\nexport {\n DEFAULT_BUS_NAME_BY_SOURCE,\n OPENHI_CONTROL_SOURCE,\n OPENHI_DATA_SOURCE,\n OPENHI_OPS_SOURCE,\n} from \"./sources\";\nexport type { OpenHiSource } from \"./sources\";\nexport {\n ControlPlaneOwningDeleteCompleteV1,\n ControlPlaneOwningDeleteFailedV1,\n ControlPlaneOwningDeleteV1,\n ControlPlaneRenameCompleteV1,\n ControlPlaneRenameFailedV1,\n ControlPlaneRenameV1,\n InvalidDetailTypeRegistrationError,\n OWNING_ENTITY_TYPE,\n PlatformDeploymentCompletedV1,\n PlatformSystemDataSeededV1,\n RENAMABLE_ENTITY_TYPE,\n defineDetailType,\n isWellFormedDetailType,\n} from \"./detail-types\";\nexport type {\n ControlPlaneOwningDeleteCompleteV1Detail,\n ControlPlaneOwningDeleteFailedV1Detail,\n ControlPlaneOwningDeleteV1Detail,\n ControlPlaneRenameCompleteV1Detail,\n ControlPlaneRenameFailedV1Detail,\n ControlPlaneRenameV1Detail,\n OwningEntityType,\n PlatformDeploymentCompletedV1Detail,\n PlatformSystemDataSeededV1Detail,\n RenamableEntityType,\n WorkflowDetailTypeEntry,\n} from \"./detail-types\";\nexport {\n WorkflowPublishError,\n publishWorkflowEvent,\n workflowsClient,\n} from \"./publisher\";\nexport type {\n PublishContext,\n PublishResult,\n PublisherOptions,\n WorkflowsClient,\n} from \"./publisher\";\nexport {\n InvalidWorkflowEventError,\n UnsupportedEnvelopeVersionError,\n parseWorkflowEvent,\n} from \"./consumer\";\nexport type {\n DedupKey,\n EventBridgeEventLike,\n ParsedWorkflowEvent,\n} from \"./consumer\";\nexport {\n WORKFLOW_DEDUP_DEFAULT_TTL_SECONDS,\n WORKFLOW_DEDUP_MAX_CONSUMER_NAME_LENGTH,\n WORKFLOW_DEDUP_TABLE_NAME_ENV_VAR,\n WorkflowDedupInvalidInputError,\n WorkflowDedupTableNameMissingError,\n encodeSortKey,\n markFailed,\n recordIfAbsent,\n workflowDedupClient,\n} from \"./dedup\";\nexport type {\n MarkFailedInput,\n RecordIfAbsentInput,\n RecordIfAbsentResult,\n WorkflowDedupClient,\n WorkflowDedupClientOptions,\n} from \"./dedup\";\n","import {\n AdminCreateUserCommand,\n AdminGetUserCommand,\n AdminSetUserPasswordCommand,\n CognitoIdentityProviderClient,\n UsernameExistsException,\n type AttributeType,\n} from \"@aws-sdk/client-cognito-identity-provider\";\nimport { DynamoDBClient } from \"@aws-sdk/client-dynamodb\";\nimport {\n GetParameterCommand,\n ParameterNotFound,\n SSMClient,\n} from \"@aws-sdk/client-ssm\";\nimport {\n PLATFORM_ROLE_CODE,\n PLATFORM_ROLE_CONCEPTS,\n PLATFORM_ROLE_IDS,\n extractSummary,\n type PlatformRoleCode,\n type FhirResourceLike,\n} from \"@openhi/types\";\nimport {\n parseWorkflowEvent,\n workflowDedupClient,\n type WorkflowDedupClient,\n} from \"@openhi/workflows\";\nimport type { EventBridgeEvent } from \"aws-lambda\";\nimport {\n DEMO_DATA_PLANE_FIXTURES,\n type DemoWorkspaceDataPlaneFixtures,\n} from \"./data-plane-fixtures\";\nimport {\n DEMO_PERIOD,\n DEMO_TENANT_SPECS,\n DEV_USERS,\n PLACEHOLDER_TENANT_ID,\n PLACEHOLDER_WORKSPACE_ID,\n PLATFORM_SCOPE_TENANT_ID,\n PlatformSystemDataSeededV1,\n SEED_DEMO_DATA_CONSUMER_NAME,\n demoMembershipId,\n demoRoleAssignmentId,\n demoRolesForUserInTenant,\n demoScenarioIdentifier,\n openhiResourceIdentifier,\n type DemoDevUser,\n} from \"./events\";\nimport { getDynamoControlService } from \"../../../data/dynamo/dynamo-control-service\";\nimport { NotFoundError } from \"../../../data/errors\";\nimport type { OpenHiContext } from \"../../../data/openhi-context\";\nimport { createMembershipOperation } from \"../../../data/operations/control/membership/membership-create-operation\";\nimport { getRoleByIdOperation } from \"../../../data/operations/control/role/role-get-by-id-operation\";\nimport { createRoleAssignmentOperation } from \"../../../data/operations/control/roleassignment/roleassignment-create-operation\";\nimport { createTenantOperation } from \"../../../data/operations/control/tenant/tenant-create-operation\";\nimport { createWorkspaceOperation } from \"../../../data/operations/control/workspace/workspace-create-operation\";\nimport { createAccountOperation } from \"../../../data/operations/data/account/account-create-operation\";\nimport { createEncounterOperation } from \"../../../data/operations/data/encounter/encounter-create-operation\";\nimport { createObservationOperation } from \"../../../data/operations/data/observation/observation-create-operation\";\nimport { createPatientOperation } from \"../../../data/operations/data/patient/patient-create-operation\";\nimport { createPractitionerOperation } from \"../../../data/operations/data/practitioner/practitioner-create-operation\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/constructs/workflows/control-plane/seed-demo-data/seed-demo-data-handler.md\n *\n * EventBridge workflow handler invoked once per platform-deploy event\n * on the control event bus. Pre-flight verifies that\n * `seed-system-data` has already seeded the canonical Role records,\n * then idempotently re-asserts the demo-data graph: the placeholder\n * Tenant + Workspace, the three demo tenants + their workspaces, and\n * for each entry in {@link DEV_USERS} a Cognito user, a DynamoDB User,\n * 4 Memberships, 4 `tenant-admin` RoleAssignments, plus 1\n * platform-scoped `system-admin` RoleAssignment.\n */\n\ntype SeedDemoDataEvent = EventBridgeEvent<\n \"platform.system-data-seeded.v1\",\n unknown\n>;\n\n/** Env var the lambda construct injects with the Cognito User Pool ID. */\nexport const SEED_DEMO_DATA_USER_POOL_ID_ENV_VAR =\n \"SEED_DEMO_DATA_USER_POOL_ID\";\n\n/** Inputs the handler needs to provision Cognito users for every dev. */\nexport interface CognitoProvisioner {\n /**\n * Ensure a Cognito user exists for `email`. Returns the user's\n * `sub`. Implementations MUST be idempotent: a second invocation\n * for the same email returns the existing user's sub without\n * resetting its password or touching any attribute.\n */\n readonly ensureUser: (email: string) => Promise<string>;\n}\n\n/**\n * Dependency seam for tests. The factory mirrors the production\n * arrangement: a real DynamoDB client + the real `workflowDedupClient`\n * factory bound to the `OPENHI_WORKFLOW_DEDUP_TABLE_NAME` env var the\n * construct injects via `grantConsumer`.\n */\nexport interface SeedDemoDataDependencies {\n readonly dedupClient: WorkflowDedupClient;\n /**\n * Reads every id in `PLATFORM_ROLE_IDS`. Throws when any Role\n * record is missing — that means `seed-system-data` has not yet\n * run on this environment, and emitting demo RoleAssignments that\n * reference non-existent Roles would produce orphaned records.\n */\n readonly verifyRoles: () => Promise<void>;\n /**\n * Upserts every Tenant + Workspace in {@link DEMO_TENANT_SPECS},\n * plus per-dev-user Cognito users, DynamoDB User records,\n * Memberships, and RoleAssignments.\n */\n readonly seedDemoGraph: (params: {\n readonly baseContext: OpenHiContext;\n readonly devUsers: ReadonlyArray<DemoDevUser>;\n readonly cognito: CognitoProvisioner;\n }) => Promise<void>;\n /** Cognito provisioner threaded into `seedDemoGraph`. */\n readonly cognito: CognitoProvisioner;\n}\n\nconst errorMessage = (err: unknown): string => {\n if (err instanceof Error) {\n return err.message;\n }\n return String(err);\n};\n\n/**\n * Structured per-item failure record collected during {@link seedDemoGraph}.\n * Every individual upsert in Phases 1-3 is wrapped so a single item's\n * failure (transient AWS error, write-time constraint violation, etc.)\n * does not skip the rest of its phase. After all phases run, the\n * collected failures are aggregate-thrown so EventBridge still routes\n * the workflow into its failure-detection path (DLQ + CloudWatch\n * alarm) and the outer `runSeedDemoData` records `markFailed` on the\n * dedup row.\n *\n * @see sites/www-docs/content/packages/@openhi/constructs/workflows/control-plane/seed-demo-data/index.md\n */\ntype SeedPhase = \"phase-1\" | \"phase-2\" | \"phase-3\";\n\ninterface SeedFailure {\n readonly phase: SeedPhase;\n /**\n * Short human label identifying where the failure happened\n * (e.g. tenant id, workspace id, user id). Used purely to enrich\n * the aggregate-throw message; no machine reads it.\n */\n readonly scope: string;\n readonly resourceType: string;\n readonly resourceId: string;\n readonly error: unknown;\n}\n\n/**\n * Wrap a single upsert call. On success, returns `true`. On failure,\n * pushes a structured {@link SeedFailure} onto `failures` and returns\n * `false` — the caller can use the boolean to decide whether to skip\n * downstream writes that strictly depend on this one. Most call sites\n * ignore the boolean (per-item isolation: the next item is attempted\n * regardless of this one's outcome).\n *\n * The wrapped function's return value is discarded; only the success/\n * failure signal is propagated. Callers that need the operation's\n * result (e.g. the `cognitoSub` from `cognito.ensureUser`) must hoist\n * the call out of `tryRun` and handle the failure inline.\n */\nconst tryRun = async (\n failures: Array<SeedFailure>,\n phase: SeedPhase,\n scope: string,\n resourceType: string,\n resourceId: string,\n fn: () => Promise<unknown>,\n): Promise<boolean> => {\n try {\n await fn();\n return true;\n } catch (err) {\n failures.push({ phase, scope, resourceType, resourceId, error: err });\n return false;\n }\n};\n\n/**\n * Format collected failures into a single Error suitable for the\n * outer `markFailed` reason and CloudWatch alarm payload. Lists every\n * failure as `<phase> <scope>/<resourceType>/<resourceId>: <message>`\n * joined by `; ` so a single CloudWatch line carries the full picture.\n */\nconst aggregateFailureError = (failures: ReadonlyArray<SeedFailure>): Error => {\n const summary = failures\n .map(\n (f) =>\n `${f.phase} ${f.scope}/${f.resourceType}/${f.resourceId}: ${errorMessage(\n f.error,\n )}`,\n )\n .join(\"; \");\n return new Error(\n `seed-demo-data: ${failures.length} item(s) failed across phases: ${summary}`,\n );\n};\n\n/**\n * Map a role code back to its canonical stable id from\n * `PLATFORM_ROLE_IDS`. Mirrors the lookup in\n * `seed-system-data.handler.ts` — the generator emits `_IDS` and\n * `_CONCEPTS` in lockstep, so a single SCREAMING_SNAKE key resolves\n * both projections.\n */\nconst idForRoleCode = (code: PlatformRoleCode): string => {\n for (const key of Object.keys(PLATFORM_ROLE_IDS) as Array<\n keyof typeof PLATFORM_ROLE_IDS\n >) {\n if (PLATFORM_ROLE_CONCEPTS[key].code === code) {\n return PLATFORM_ROLE_IDS[key];\n }\n }\n throw new Error(`No id mapping for role code \"${code}\".`);\n};\n\n/**\n * Pre-flight Role check. Iterates every id in\n * `PLATFORM_ROLE_IDS` and reads the record. If any read returns\n * not-found, this throws and `markFailed`'s the dedup row — the\n * replay tooling can retry once `seed-system-data` has populated the\n * Roles.\n */\nconst verifySystemRolesExist = async (): Promise<void> => {\n const probeContext: OpenHiContext = {\n tenantId: \"\",\n workspaceId: \"\",\n date: new Date(0).toISOString(),\n actorId: \"platform-deploy-bridge\",\n actorName: \"Platform Deploy Bridge\",\n actorType: \"internal-system\",\n source: \"step-function\",\n };\n for (const id of Object.values(PLATFORM_ROLE_IDS)) {\n try {\n await getRoleByIdOperation({ context: probeContext, id });\n } catch (err) {\n if (err instanceof NotFoundError) {\n throw new Error(\n `seed-demo-data pre-flight: control-plane Role \"${id}\" is missing. ` +\n \"Ensure seed-system-data has run on this environment before retrying.\",\n );\n }\n throw err;\n }\n }\n};\n\n/**\n * Build the resource body for one demo Tenant. Carries the two\n * identifiers per scope decision #6: the demo-scenario URN and the\n * canonical OpenHI resource URN (ADR 2026-03-12-01).\n */\nconst tenantResourceBody = (\n spec: (typeof DEMO_TENANT_SPECS)[number],\n): Record<string, unknown> => ({\n name: spec.tenantName,\n active: true,\n identifier: [\n demoScenarioIdentifier(spec.scenario, \"tenant\"),\n openhiResourceIdentifier({\n tenantId: spec.tenantId,\n workspaceId: \"\",\n resourceType: \"Tenant\",\n id: spec.tenantId,\n }),\n ],\n});\n\nconst workspaceResourceBody = (\n spec: (typeof DEMO_TENANT_SPECS)[number],\n workspace: (typeof DEMO_TENANT_SPECS)[number][\"workspaces\"][number],\n): Record<string, unknown> => ({\n name: workspace.name,\n active: true,\n identifier: [\n demoScenarioIdentifier(spec.scenario, workspace.roleSuffix),\n openhiResourceIdentifier({\n tenantId: spec.tenantId,\n workspaceId: \"\",\n resourceType: \"Workspace\",\n id: workspace.id,\n }),\n ],\n tenant: { reference: `Tenant/${spec.tenantId}`, type: \"Tenant\" },\n});\n\nconst membershipResourceBody = (\n spec: (typeof DEMO_TENANT_SPECS)[number],\n user: DemoDevUser,\n membershipId: string,\n): Record<string, unknown> => ({\n identifier: [\n demoScenarioIdentifier(spec.scenario, `membership-${user.id}`),\n openhiResourceIdentifier({\n tenantId: spec.tenantId,\n workspaceId: \"\",\n resourceType: \"Membership\",\n id: membershipId,\n }),\n ],\n user: { reference: `User/${user.id}`, type: \"User\" },\n tenant: { reference: `Tenant/${spec.tenantId}`, type: \"Tenant\" },\n period: DEMO_PERIOD,\n});\n\nconst roleAssignmentResourceBody = (\n scenario: string,\n tenantId: string,\n user: DemoDevUser,\n roleCode: PlatformRoleCode,\n roleAssignmentId: string,\n): Record<string, unknown> => ({\n identifier: [\n demoScenarioIdentifier(scenario, `roleassignment-${user.id}-${roleCode}`),\n openhiResourceIdentifier({\n tenantId,\n workspaceId: \"\",\n resourceType: \"RoleAssignment\",\n id: roleAssignmentId,\n }),\n ],\n user: { reference: `User/${user.id}`, type: \"User\" },\n role: { reference: `Role/${idForRoleCode(roleCode)}`, type: \"Role\" },\n tenant: { reference: `Tenant/${tenantId}`, type: \"Tenant\" },\n period: DEMO_PERIOD,\n});\n\n/** Build the FHIR User resource body for a seeded dev user. */\nconst userResourceBody = (\n user: DemoDevUser,\n cognitoSub: string,\n): Record<string, unknown> => ({\n resourceType: \"User\",\n id: user.id,\n name: [{ text: user.email }],\n status: \"active\",\n cognitoSub,\n currentTenant: { reference: `Tenant/${PLACEHOLDER_TENANT_ID}` },\n currentWorkspace: { reference: `Workspace/${PLACEHOLDER_WORKSPACE_ID}` },\n});\n\n/**\n * Idempotent User upsert. The User entity is non-tenant-isolated, so\n * the put is unconditional — the entity's PK is `USER#ID#<id>` and\n * supplying the same id re-asserts the same row.\n */\nconst upsertUser = async (\n context: OpenHiContext,\n user: DemoDevUser,\n cognitoSub: string,\n): Promise<void> => {\n const service = getDynamoControlService();\n const resource = userResourceBody(user, cognitoSub);\n const summary = JSON.stringify(extractSummary(resource as FhirResourceLike));\n await service.entities.user\n .put({\n id: user.id,\n cognitoSub,\n resource: JSON.stringify(resource),\n summary,\n vid: \"1\",\n lastUpdated: context.date ?? new Date().toISOString(),\n })\n .go();\n};\n\n/**\n * Phase 3 helper: upsert one workspace's data-plane FHIR resources\n * (Patient/Practitioner/Observation/Encounter/Account). Parents are\n * written before children that reference them so direct `Resource/<id>`\n * references resolve on read paths that follow them — Patient first,\n * then Practitioner, then Observation/Encounter/Account which may\n * carry `subject: Patient/...` references.\n *\n * Every create operation's `body.id` is supplied from the fixture, so\n * re-fires after dedup-TTL expiry upsert the same record (ElectroDB's\n * `put` is unconditional — same composite key overwrites the prior\n * row).\n *\n * Each individual create is wrapped via {@link tryRun}: a failed\n * Patient does not skip the remaining Patients or the downstream\n * Practitioner/Observation/Encounter/Account writes in this workspace,\n * and a failure here does not propagate up to skip the next workspace\n * in the outer loop. Downstream resources that reference a failed\n * parent (`subject: Patient/<id>`) will likely fail too — that is\n * fine, they are attempted, the failures recorded, and the next\n * deploy upserts them once the parent lands.\n */\nconst seedWorkspaceDataPlane = async (\n baseContext: OpenHiContext,\n group: DemoWorkspaceDataPlaneFixtures,\n failures: Array<SeedFailure>,\n): Promise<void> => {\n const workspaceContext: OpenHiContext = {\n ...baseContext,\n tenantId: group.tenantId,\n workspaceId: group.workspaceId,\n };\n const scope = `${group.tenantId}/${group.workspaceId}`;\n for (const patient of group.patients) {\n await tryRun(failures, \"phase-3\", scope, \"Patient\", patient.id ?? \"\", () =>\n createPatientOperation({\n context: workspaceContext,\n body: patient,\n }),\n );\n }\n for (const practitioner of group.practitioners) {\n await tryRun(\n failures,\n \"phase-3\",\n scope,\n \"Practitioner\",\n practitioner.id ?? \"\",\n () =>\n createPractitionerOperation({\n context: workspaceContext,\n body: practitioner,\n }),\n );\n }\n for (const observation of group.observations) {\n await tryRun(\n failures,\n \"phase-3\",\n scope,\n \"Observation\",\n observation.id ?? \"\",\n () =>\n createObservationOperation({\n context: workspaceContext,\n body: observation,\n }),\n );\n }\n for (const encounter of group.encounters) {\n await tryRun(\n failures,\n \"phase-3\",\n scope,\n \"Encounter\",\n encounter.id ?? \"\",\n () =>\n createEncounterOperation({\n context: workspaceContext,\n body: encounter,\n }),\n );\n }\n for (const account of group.accounts) {\n await tryRun(failures, \"phase-3\", scope, \"Account\", account.id ?? \"\", () =>\n createAccountOperation({\n context: workspaceContext,\n body: account,\n }),\n );\n }\n};\n\n/**\n * Upsert the full demo-data graph. Walks each spec in\n * {@link DEMO_TENANT_SPECS}: Tenant → Workspaces. Then per dev user:\n * Cognito user → DynamoDB User → per-tenant Membership +\n * `tenant-admin` RoleAssignment → platform-scoped `system-admin`\n * RoleAssignment. Finally walks {@link DEMO_DATA_PLANE_FIXTURES} and\n * upserts the OPS-009 v1 FHIR resource set (Patient, Practitioner,\n * Observation, Encounter, Account) into each demo workspace. Every\n * put is keyed by a deterministic stable id so re-runs after\n * dedup-TTL expiry upsert the same records.\n *\n * Self-healing-on-every-deploy contract: every individual upsert\n * across all three phases is wrapped via {@link tryRun}. A single\n * item's failure (transient AWS error, write-time constraint\n * violation, etc.) is collected into a per-call accumulator and\n * does not skip the remaining items in its phase. After all phases\n * run, collected failures are aggregate-thrown as a single error so\n * EventBridge still routes the workflow into its failure-detection\n * path (DLQ + CloudWatch alarm) and the outer `runSeedDemoData`\n * records `markFailed` on the dedup row. Because every put is keyed\n * by a deterministic stable id, the next deploy re-attempts every\n * item — failed items eventually heal, successful items overwrite\n * themselves with the same body.\n *\n * Exported so the seeder test file can exercise it directly against\n * a mocked DynamoControlService; the production handler reaches it\n * through {@link SeedDemoDataDependencies.seedDemoGraph}.\n */\nexport const seedDemoGraph = async (params: {\n baseContext: OpenHiContext;\n devUsers: ReadonlyArray<DemoDevUser>;\n cognito: CognitoProvisioner;\n}): Promise<void> => {\n const { baseContext, devUsers, cognito } = params;\n const failures: Array<SeedFailure> = [];\n\n // Phase 1: Tenants + Workspaces (no Memberships / RoleAssignments\n // yet — those need the per-user Cognito sub).\n //\n // Each tenant and each workspace is wrapped individually. A failed\n // tenant create does NOT skip its workspaces — the tenant may\n // already exist from a prior deploy (the put is unconditional, so\n // a duplicate is a no-op; we treat all errors as recoverable here\n // and let the workspace writes proceed). A failed workspace does\n // not skip the next workspace under the same tenant or any\n // subsequent tenant.\n for (const spec of DEMO_TENANT_SPECS) {\n const tenantContext: OpenHiContext = {\n ...baseContext,\n tenantId: spec.tenantId,\n };\n\n await tryRun(\n failures,\n \"phase-1\",\n spec.tenantId,\n \"Tenant\",\n spec.tenantId,\n () =>\n createTenantOperation({\n context: tenantContext,\n body: { id: spec.tenantId, resource: tenantResourceBody(spec) },\n }),\n );\n\n for (const workspace of spec.workspaces) {\n await tryRun(\n failures,\n \"phase-1\",\n spec.tenantId,\n \"Workspace\",\n workspace.id,\n () =>\n createWorkspaceOperation({\n context: tenantContext,\n body: {\n id: workspace.id,\n resource: workspaceResourceBody(spec, workspace),\n },\n }),\n );\n }\n }\n\n // Phase 2: per-dev-user records. The Cognito provisioner is the\n // only step that can fail in a way EventBridge can usefully retry —\n // it runs first because every subsequent write needs the\n // `cognitoSub` it returns. If `ensureUser` throws, skip the whole\n // user (we have no sub to write into the User row).\n //\n // For each individual call inside the per-user block we use\n // {@link tryRun} so a Membership failure in tenant 3 does not skip\n // the Membership + RAs in tenant 4 for the same user, and the\n // platform-scoped RA is attempted last regardless of any earlier\n // per-tenant failure.\n //\n // `upsertUser` is wrapped via tryRun BUT we do NOT short-circuit\n // the per-tenant writes on its failure. The User row carries\n // `cognitoSub` for JWT-claim resolution; the Memberships and\n // RoleAssignments only reference the User by stable id. A previous\n // deploy may have already written the User row with the correct\n // sub. Attempting the per-tenant writes lets the next deploy heal\n // any partial state.\n for (const user of devUsers) {\n let cognitoSub: string;\n try {\n cognitoSub = await cognito.ensureUser(user.email);\n } catch (err) {\n failures.push({\n phase: \"phase-2\",\n scope: user.id,\n resourceType: \"CognitoUser\",\n resourceId: user.email,\n error: err,\n });\n continue;\n }\n\n await tryRun(failures, \"phase-2\", user.id, \"User\", user.id, () =>\n upsertUser(baseContext, user, cognitoSub),\n );\n\n for (const spec of DEMO_TENANT_SPECS) {\n const tenantContext: OpenHiContext = {\n ...baseContext,\n tenantId: spec.tenantId,\n };\n const userScope = `${user.id}@${spec.tenantId}`;\n\n const membershipId = demoMembershipId(user.id, spec.tenantId);\n await tryRun(\n failures,\n \"phase-2\",\n userScope,\n \"Membership\",\n membershipId,\n () =>\n createMembershipOperation({\n context: tenantContext,\n body: {\n id: membershipId,\n resource: membershipResourceBody(spec, user, membershipId),\n },\n }),\n );\n\n for (const roleCode of demoRolesForUserInTenant(user, spec.tenantId)) {\n const raId = demoRoleAssignmentId(user.id, spec.tenantId, roleCode);\n await tryRun(\n failures,\n \"phase-2\",\n userScope,\n \"RoleAssignment\",\n raId,\n () =>\n createRoleAssignmentOperation({\n context: tenantContext,\n body: {\n id: raId,\n resource: roleAssignmentResourceBody(\n spec.scenario,\n spec.tenantId,\n user,\n roleCode,\n raId,\n ),\n },\n }),\n );\n }\n }\n\n // Platform-scoped system-admin RoleAssignment. The sentinel\n // tenantId is PLATFORM_SCOPE_TENANT_ID — there is no real Tenant\n // to point at, so the operation runs with an OpenHiContext whose\n // tenantId is the sentinel. The write-time tenant-membership\n // constraint short-circuits for this sentinel so no Membership\n // prerequisite is required.\n const platformContext: OpenHiContext = {\n ...baseContext,\n tenantId: PLATFORM_SCOPE_TENANT_ID,\n };\n const platformRoleCode = PLATFORM_ROLE_CODE.SYSTEM_ADMIN;\n const platformRaId = demoRoleAssignmentId(\n user.id,\n PLATFORM_SCOPE_TENANT_ID,\n platformRoleCode,\n );\n await tryRun(\n failures,\n \"phase-2\",\n `${user.id}@${PLATFORM_SCOPE_TENANT_ID}`,\n \"RoleAssignment\",\n platformRaId,\n () =>\n createRoleAssignmentOperation({\n context: platformContext,\n body: {\n id: platformRaId,\n resource: roleAssignmentResourceBody(\n \"platform\",\n PLATFORM_SCOPE_TENANT_ID,\n user,\n platformRoleCode,\n platformRaId,\n ),\n },\n }),\n );\n }\n\n // Phase 3: data-plane FHIR resources (OPS-009 v1 set) per demo\n // workspace. Runs after the control-plane phases so the Tenants\n // and Workspaces those resources implicitly belong to already\n // exist by the time we write into them. The placeholder tenant\n // carries no data-plane fixtures.\n //\n // `seedWorkspaceDataPlane` already wraps each individual create\n // via tryRun; we wrap the helper call itself in an outer\n // try/catch as defence-in-depth so an unexpected throw from the\n // helper (programmer error, OOM, etc.) does not skip the next\n // workspace.\n for (const group of DEMO_DATA_PLANE_FIXTURES) {\n try {\n await seedWorkspaceDataPlane(baseContext, group, failures);\n } catch (err) {\n failures.push({\n phase: \"phase-3\",\n scope: `${group.tenantId}/${group.workspaceId}`,\n resourceType: \"Workspace\",\n resourceId: group.workspaceId,\n error: err,\n });\n }\n }\n\n if (failures.length > 0) {\n throw aggregateFailureError(failures);\n }\n};\n\n/**\n * Test-visible orchestrator. The production `handler` calls this with\n * real dependencies and the hardcoded {@link DEV_USERS} list; unit\n * tests inject fakes and pass the dev-user list directly.\n */\nexport const runSeedDemoData = async (\n event: SeedDemoDataEvent,\n deps: SeedDemoDataDependencies,\n devUsers: ReadonlyArray<DemoDevUser>,\n): Promise<void> => {\n const parsed = parseWorkflowEvent(event, PlatformSystemDataSeededV1);\n\n const recordResult = await deps.dedupClient.recordIfAbsent({\n consumerName: SEED_DEMO_DATA_CONSUMER_NAME,\n eventId: parsed.dedupKey.eventId,\n attempt: parsed.dedupKey.attempt,\n });\n if (!recordResult.recorded) {\n return;\n }\n\n const baseContext: OpenHiContext = {\n tenantId: \"\",\n workspaceId: \"\",\n date: parsed.envelope.occurredAt,\n actorId: \"platform-deploy-bridge\",\n actorName: \"Platform Deploy Bridge\",\n actorType: \"internal-system\",\n source: \"step-function\",\n };\n\n try {\n await deps.verifyRoles();\n await deps.seedDemoGraph({\n baseContext,\n devUsers,\n cognito: deps.cognito,\n });\n } catch (err) {\n // Mark the dedup row failed so the replay tooling (TR-016 follow-up)\n // can re-publish the originating event with a fresh attempt. The\n // re-throw keeps EventBridge's failure-detection path intact — the\n // event ends up in the DLQ + the workflow Lambda's failure\n // CloudWatch alarm fires.\n await deps.dedupClient.markFailed({\n consumerName: SEED_DEMO_DATA_CONSUMER_NAME,\n eventId: parsed.dedupKey.eventId,\n attempt: parsed.dedupKey.attempt,\n reason: errorMessage(err),\n });\n throw err;\n }\n};\n\n/**\n * SSM parameter-path prefix that hosts every seeded dev user's\n * password. The full path for a single user is\n * `${SEED_USER_PASSWORD_PARAMETER_PREFIX}<email_safe>/password`\n * where `<email_safe>` is `<user>_at_<domain>` (see\n * {@link emailToSsmPath}). The trailing `/password` segment leaves\n * room for additional per-user parameters under the same email\n * prefix in future phases without renaming the existing entries.\n */\nexport const SEED_USER_PASSWORD_PARAMETER_PREFIX = \"/openhi/seed/users/\";\n\n/**\n * SSM Parameter Store path validation regex. Names must be 1-1011\n * characters, may include alphanumerics plus `_`, `.`, `-`, and\n * `/`. We enforce a stricter subset here — alphanumerics, hyphen,\n * underscore, and period only — because the path is constructed by\n * substituting `@` → `_at_` and any other special character would\n * indicate an email that should have been rejected upstream.\n */\nconst SSM_PATH_SEGMENT = /^[A-Za-z0-9_.-]+$/;\n\n/**\n * Map an email address to its canonical SSM parameter path. The\n * `@` separator is replaced with the literal sentinel `_at_` so\n * the resulting path is a single SSM-legal name. Throws when the\n * email is empty, missing exactly one `@`, or contains characters\n * that would produce an invalid SSM path.\n *\n * Example: `alice@codedrifters.com` →\n * `/openhi/seed/users/alice_at_codedrifters.com/password`.\n */\nexport const emailToSsmPath = (email: string): string => {\n if (typeof email !== \"string\" || email.length === 0) {\n throw new Error(\n `emailToSsmPath: email must be a non-empty string (received \"${String(email)}\").`,\n );\n }\n const atIdx = email.indexOf(\"@\");\n if (atIdx === -1 || atIdx !== email.lastIndexOf(\"@\")) {\n throw new Error(\n `emailToSsmPath: email \"${email}\" must contain exactly one \"@\" character.`,\n );\n }\n const localPart = email.slice(0, atIdx);\n const domainPart = email.slice(atIdx + 1);\n if (localPart.length === 0 || domainPart.length === 0) {\n throw new Error(\n `emailToSsmPath: email \"${email}\" must have a non-empty local-part and domain.`,\n );\n }\n if (!SSM_PATH_SEGMENT.test(localPart) || !SSM_PATH_SEGMENT.test(domainPart)) {\n throw new Error(\n `emailToSsmPath: email \"${email}\" contains characters that would produce ` +\n \"an invalid SSM parameter path (only A-Z, a-z, 0-9, '.', '-', and '_' are allowed).\",\n );\n }\n return `${SEED_USER_PASSWORD_PARAMETER_PREFIX}${localPart}_at_${domainPart}/password`;\n};\n\n/**\n * Module-scoped SSM client. Lambda containers reuse the same\n * `SSMClient` instance across invocations so the TLS connection\n * + credential-resolver state warms once per container. Mirrors\n * the `CognitoIdentityProviderClient` / `DynamoDBClient` reuse\n * pattern at the bottom of this file.\n */\nlet cachedSsmClient: SSMClient | undefined;\n\nconst getSsmClient = (): SSMClient => {\n if (!cachedSsmClient) {\n cachedSsmClient = new SSMClient({});\n }\n return cachedSsmClient;\n};\n\n/**\n * Test seam: reset the module-scoped SSM client cache. Unit tests\n * that swap in different mocks across `it` blocks call this in\n * `beforeEach` so each test gets a fresh client instance.\n */\nexport const __resetSsmClientForTests = (): void => {\n cachedSsmClient = undefined;\n};\n\n/**\n * Read a seeded dev user's password from SSM Parameter Store. The\n * parameter is expected to be a `SecureString` provisioned out of\n * band by an operator (see the runbook in phase 3 of #1249). On\n * `ParameterNotFound`, the error message includes the exact\n * expected path so the operator can copy-paste-fix.\n */\nexport const fetchSeedUserPassword = async (email: string): Promise<string> => {\n const path = emailToSsmPath(email);\n const client = getSsmClient();\n try {\n const result = await client.send(\n new GetParameterCommand({ Name: path, WithDecryption: true }),\n );\n const value = result.Parameter?.Value;\n if (typeof value !== \"string\" || value.length === 0) {\n throw new Error(\n `fetchSeedUserPassword: SSM parameter \"${path}\" returned an empty value.`,\n );\n }\n return value;\n } catch (err) {\n if (err instanceof ParameterNotFound) {\n throw new Error(\n `fetchSeedUserPassword: SSM parameter \"${path}\" not found. ` +\n `Provision a SecureString at \"${path}\" with the dev user's password before re-running seed-demo-data.`,\n );\n }\n throw err;\n }\n};\n\n/**\n * Production Cognito provisioner backed by the AWS SDK. Reads the\n * user-pool id from the env var the lambda construct injects.\n *\n * Idempotency contract:\n * - On first invocation, calls `AdminCreateUser` (with\n * `MessageAction: SUPPRESS` so no invitation email fires) then\n * `AdminSetUserPassword` (permanent, from the SSM-sourced\n * value). Returns the new user's sub.\n * - On subsequent invocations, `AdminCreateUser` throws\n * `UsernameExistsException`; the provisioner catches it, calls\n * `AdminGetUser` to read the existing user's sub, and **also\n * re-applies the current SSM-sourced password** via\n * `AdminSetUserPassword`. This is the rotation seam: operators\n * update the SSM SecureString value and re-publish the seed\n * event to push a fresh password down to Cognito.\n *\n * The SSM password is fetched once per email up-front so the new-\n * user and rotation branches share the same value and at most one\n * `GetParameter` call lands per `ensureUser` invocation.\n */\nexport const productionCognitoProvisioner = (): CognitoProvisioner => {\n const client = new CognitoIdentityProviderClient({});\n const userPoolId = process.env[SEED_DEMO_DATA_USER_POOL_ID_ENV_VAR];\n if (!userPoolId || userPoolId.trim() === \"\") {\n throw new Error(\n `${SEED_DEMO_DATA_USER_POOL_ID_ENV_VAR} is not set; the seed-demo-data Lambda ` +\n \"cannot provision Cognito users without a user-pool id.\",\n );\n }\n const subFromAttributes = (\n attrs: ReadonlyArray<AttributeType> | undefined,\n ): string | undefined => {\n for (const attr of attrs ?? []) {\n if (attr.Name === \"sub\" && typeof attr.Value === \"string\") {\n return attr.Value;\n }\n }\n return undefined;\n };\n const setPassword = async (\n email: string,\n password: string,\n ): Promise<void> => {\n await client.send(\n new AdminSetUserPasswordCommand({\n UserPoolId: userPoolId,\n Username: email,\n Password: password,\n Permanent: true,\n }),\n );\n };\n return {\n ensureUser: async (email: string): Promise<string> => {\n // Fetch the SSM-sourced password up-front so both the\n // new-user path and the rotation path consume the same\n // value with a single `GetParameter` call.\n const password = await fetchSeedUserPassword(email);\n try {\n const created = await client.send(\n new AdminCreateUserCommand({\n UserPoolId: userPoolId,\n Username: email,\n MessageAction: \"SUPPRESS\",\n UserAttributes: [\n { Name: \"email\", Value: email },\n { Name: \"email_verified\", Value: \"true\" },\n ],\n }),\n );\n await setPassword(email, password);\n const sub = subFromAttributes(created.User?.Attributes);\n if (!sub) {\n throw new Error(\n `AdminCreateUser response for \"${email}\" did not carry a sub attribute.`,\n );\n }\n return sub;\n } catch (err) {\n if (err instanceof UsernameExistsException) {\n // User already exists — re-apply the current SSM-sourced\n // password so operator rotations propagate, then read the\n // existing sub. AdminSetUserPassword on an existing user\n // overwrites the credential without affecting the sub.\n await setPassword(email, password);\n const got = await client.send(\n new AdminGetUserCommand({\n UserPoolId: userPoolId,\n Username: email,\n }),\n );\n const sub = subFromAttributes(got.UserAttributes);\n if (!sub) {\n throw new Error(\n `AdminGetUser response for \"${email}\" did not carry a sub attribute.`,\n );\n }\n return sub;\n }\n throw err;\n }\n },\n };\n};\n\nconst productionDependencies = (): SeedDemoDataDependencies => {\n const dynamodb = new DynamoDBClient({});\n const cognito = productionCognitoProvisioner();\n return {\n dedupClient: workflowDedupClient(dynamodb),\n verifyRoles: verifySystemRolesExist,\n seedDemoGraph,\n cognito,\n };\n};\n\nexport const handler = async (event: SeedDemoDataEvent): Promise<void> =>\n runSeedDemoData(event, productionDependencies(), DEV_USERS);\n","import { PLATFORM_ROLE_CODE, type PlatformRoleCode } from \"@openhi/types\";\nimport { PlatformSystemDataSeededV1 } from \"@openhi/workflows\";\nimport { PLATFORM_SCOPE_TENANT_ID } from \"../../../data/operations/control/membership-constraints/platform-scope-tenant-id\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/constructs/workflows/control-plane/seed-demo-data/events.md\n */\n\n/**\n * Stable logical name this workflow registers with the shared\n * `WorkflowDedupTable` (TR-015). Used in both the construct grant\n * (`workflowDedupTable.grantConsumer(lambda, SEED_DEMO_DATA_CONSUMER_NAME)`)\n * and the handler's runtime `recordIfAbsent` call — keep them aligned by\n * importing this constant in both places.\n */\nexport const SEED_DEMO_DATA_CONSUMER_NAME = \"seed-demo-data\";\n\n/** FHIR `Identifier.system` for the demo-scenario URN scheme. */\nexport const DEMO_URN_SYSTEM = \"urn:openhi:demo\";\n\n/**\n * FHIR `Identifier.system` for the canonical OpenHI resource URN\n * (ADR 2026-03-12-01). The value form is\n * `urn:ohi:<tenantId>:<workspaceId>:<resourceType>:<id>`; empty\n * workspaceId means the resource has tenant-wide scope (or is itself\n * the workspace identity, in the Workspace case).\n */\nexport const OPENHI_RESOURCE_URN_SYSTEM = \"http://openhi.org/\";\n\n/**\n * Period stamped on every demo Membership and RoleAssignment. Fixed\n * start so re-runs produce byte-identical bodies (decision #4); no\n * end so demo memberships are open-ended.\n */\nexport const DEMO_PERIOD = { start: \"2026-01-01T00:00:00Z\" } as const;\n\n/**\n * Sentinel `tenantId` used on every dev user's `system-admin`\n * RoleAssignment. A `system-admin` RA is platform-scoped (it spans\n * every tenant), but the RoleAssignment entity requires a tenantId on\n * its key for sharding — there is no real tenant to point at.\n *\n * The canonical definition lives in\n * `data/operations/control/membership-constraints/platform-scope-tenant-id.ts`\n * so the write-time tenant-membership constraint can short-circuit\n * the sentinel without the data layer importing from the workflow.\n * Re-exported here so existing imports that resolve through\n * `seed-demo-data/events` keep working.\n */\nexport { PLATFORM_SCOPE_TENANT_ID };\n\n/** Placeholder Tenant id seeded by the workflow as the dev-user `currentTenant`. */\nexport const PLACEHOLDER_TENANT_ID = \"placeholder-tenant-id\";\n\n/** Placeholder Workspace id seeded by the workflow as the dev-user `currentWorkspace`. */\nexport const PLACEHOLDER_WORKSPACE_ID = \"placeholder-workspace-id\";\n\n/**\n * Dev-user descriptor. Every entry produces:\n * - one Cognito user (idempotent create-then-skip),\n * - one DynamoDB User record (id = `dev-<email-local-part>`),\n * - four Memberships (placeholder + the three demo tenants),\n * - four `tenant-admin` RoleAssignments (one per tenant the user\n * belongs to),\n * - one `system-admin` RoleAssignment scoped to {@link PLATFORM_SCOPE_TENANT_ID}.\n */\nexport interface DemoDevUser {\n /** Stable DynamoDB User id. */\n readonly id: string;\n /** Email used as the Cognito `Username` and as the seed for the password algorithm. */\n readonly email: string;\n}\n\n/**\n * Hardcoded dev-user roster. Adding a new developer is a one-line\n * change here plus a re-deploy. The list intentionally lives in-source\n * (not behind an env-var seam) so the IAM grant in\n * `seed-demo-data-lambda.ts` can enumerate per-user PKs at synth time.\n */\nexport const DEV_USERS: ReadonlyArray<DemoDevUser> = [\n { id: \"dev-russell\", email: \"russell@codedrifters.com\" },\n { id: \"dev-cameron\", email: \"cameron@codedrifters.com\" },\n { id: \"dev-neelima\", email: \"neelima@codedrifters.com\" },\n { id: \"dev-garon\", email: \"garon@codedrifters.com\" },\n { id: \"dev-dave\", email: \"dave@codedrifters.com\" },\n { id: \"dev-drew\", email: \"drew@codedrifters.com\" },\n { id: \"dev-jessica\", email: \"jessica@codedrifters.com\" },\n { id: \"dev-jared\", email: \"jared@codedrifters.com\" },\n { id: \"dev-goddess\", email: \"goddess@codedrifters.com\" },\n // Dedicated end-to-end test principal for admin-console Playwright\n // specs (issue #1275). Reuses the standard DEV_USERS plumbing\n // (Cognito user + DynamoDB User + per-tenant Memberships +\n // tenant-admin RAs + platform-scoped system-admin RA) and the\n // existing SSM-sourced password convention from #1249 — the\n // operator provisions the SecureString at\n // /openhi/seed/users/e2e-admin-console_at_codedrifters.com/password\n // out of band, and the seeded Cognito user picks it up via\n // AdminSetUserPassword on every seed run.\n { id: \"dev-e2e-admin-console\", email: \"e2e-admin-console@codedrifters.com\" },\n];\n\n/**\n * A single workspace inside a demo tenant. The mixed tenant has two\n * workspaces (wound-care and primary-care sub-workspaces); the other\n * two tenants have one each.\n */\nexport interface DemoWorkspaceSpec {\n /** Stable id (DynamoDB record id; also drives the canonical OHI URN). */\n readonly id: string;\n /** FHIR `Workspace.name`. */\n readonly name: string;\n /**\n * Role suffix used in the demo URN value (`<scenario>:<roleSuffix>`).\n * `workspace` for single-workspace tenants, `workspace-<sub>` for the\n * mixed tenant.\n */\n readonly roleSuffix: string;\n}\n\n/**\n * One demo tenant + the workspaces it owns. Re-exported via {@link\n * DEMO_TENANT_SPECS} as the canonical list; iterate that constant in\n * the handler and the IAM-grant builder so the value sets agree.\n */\nexport interface DemoTenantSpec {\n /**\n * Scenario slug — `placeholder`, `demo-wound-care`, `demo-primary-care`,\n * `demo-mixed`. The placeholder tenant's slug is `placeholder`; the\n * three demo tenants use `demo-*` slugs.\n */\n readonly scenario: string;\n /** Stable id (DynamoDB record id; also drives the canonical OHI URN). */\n readonly tenantId: string;\n /** FHIR `Tenant.name`. */\n readonly tenantName: string;\n /** Workspaces owned by this tenant. */\n readonly workspaces: ReadonlyArray<DemoWorkspaceSpec>;\n}\n\n/**\n * The full demo-tenant graph. Four entries: the placeholder tenant the\n * JWT-claim fallback resolves to, plus the three v1 demo scenarios\n * (OPS-009 §\"v1 scenarios\"):\n *\n * 0. Placeholder tenant — dereferences the JWT-claim fallback in\n * `pre-token-generation.handler.ts` and acts as every dev user's\n * `currentTenant`/`currentWorkspace` so Post-Confirmation skips\n * default provisioning when a seeded User signs in.\n * 1. Single-workspace wound-care tenant.\n * 2. Single-workspace primary-care tenant.\n * 3. Two-workspace mixed tenant — exercises the cross-workspace\n * isolation flow that single-workspace tenants cannot.\n */\nexport const DEMO_TENANT_SPECS: ReadonlyArray<DemoTenantSpec> = [\n {\n scenario: \"placeholder\",\n tenantId: PLACEHOLDER_TENANT_ID,\n tenantName: \"OpenHI Placeholder Tenant\",\n workspaces: [\n {\n id: PLACEHOLDER_WORKSPACE_ID,\n name: \"OpenHI Placeholder Workspace\",\n roleSuffix: \"workspace\",\n },\n ],\n },\n {\n scenario: \"demo-wound-care\",\n tenantId: \"demo-wound-care-tenant\",\n tenantName: \"Cedarbrook Wound Healing Institute\",\n workspaces: [\n {\n id: \"demo-wound-care-workspace\",\n name: \"Cedarbrook Outpatient Wound Clinic\",\n roleSuffix: \"workspace\",\n },\n ],\n },\n {\n scenario: \"demo-primary-care\",\n tenantId: \"demo-primary-care-tenant\",\n tenantName: \"Maple Ridge Family Medicine\",\n workspaces: [\n {\n id: \"demo-primary-care-workspace\",\n name: \"Maple Ridge Main Street Office\",\n roleSuffix: \"workspace\",\n },\n ],\n },\n {\n scenario: \"demo-mixed\",\n tenantId: \"demo-mixed-tenant\",\n tenantName: \"Northbridge Health Network\",\n workspaces: [\n {\n id: \"demo-mixed-workspace-wound-care\",\n name: \"Northbridge Wound Care Center\",\n roleSuffix: \"workspace-wound-care\",\n },\n {\n id: \"demo-mixed-workspace-primary-care\",\n name: \"Northbridge Family Practice\",\n roleSuffix: \"workspace-primary-care\",\n },\n ],\n },\n];\n\n/** Stable Membership id derived from `(devUserId, tenantId)`. */\nexport const demoMembershipId = (devUserId: string, tenantId: string): string =>\n `demo-membership-${devUserId}-${tenantId}`;\n\n/**\n * Stable RoleAssignment id derived from `(devUserId, tenantId, roleCode)`.\n * Each (user, tenant, role) tuple maps to exactly one record — re-runs\n * upsert the same id.\n */\nexport const demoRoleAssignmentId = (\n devUserId: string,\n tenantId: string,\n roleCode: PlatformRoleCode,\n): string => `demo-roleassignment-${devUserId}-${tenantId}-${roleCode}`;\n\n/**\n * Demo-scenario FHIR `Identifier` entry — `urn:openhi:demo:<scenario>:<role>`.\n */\nexport const demoScenarioIdentifier = (\n scenario: string,\n roleSuffix: string,\n): { system: string; value: string } => ({\n system: DEMO_URN_SYSTEM,\n value: `${scenario}:${roleSuffix}`,\n});\n\n/**\n * Canonical OpenHI resource FHIR `Identifier` entry per ADR\n * 2026-03-12-01. `workspaceId` is empty for both Tenant resources and\n * Workspace resources — for a Tenant, the resource is tenant-scoped\n * with no workspace context; for a Workspace, the resource IS the\n * workspace identity rather than living inside one.\n */\nexport const openhiResourceIdentifier = (params: {\n tenantId: string;\n workspaceId: string;\n resourceType: string;\n id: string;\n}): { use: string; system: string; value: string } => ({\n use: \"unversioned\",\n system: OPENHI_RESOURCE_URN_SYSTEM,\n value: `urn:ohi:${params.tenantId}:${params.workspaceId}:${params.resourceType}:${params.id}`,\n});\n\n/**\n * Roles every dev user holds in every tenant they belong to. Per scope\n * decision Q3, every dev user is `tenant-admin` in every tenant — there\n * is no per-(user, tenant) variance to drive from.\n */\nexport const demoRolesForUserInTenant = (\n _user: DemoDevUser,\n _tenantId: string,\n): ReadonlyArray<PlatformRoleCode> => {\n void _user;\n void _tenantId;\n return [PLATFORM_ROLE_CODE.TENANT_ADMIN];\n};\n\n/**\n * The trigger this workflow subscribes to on the control event bus.\n * The `seed-system-data` workflow publishes\n * `platform.system-data-seeded.v1` after it has finished re-asserting\n * the platform-singleton Role records; on every fire this workflow\n * re-asserts the demo-tenant graph.\n *\n * The indirection (subscribing to `system-data-seeded` rather than to\n * the raw `platform.deployment-completed.v1` event) enforces a strict\n * happens-before edge between the system-data seed and the demo-data\n * seed. Without it, both workflows would fire in parallel from the\n * same deploy event and seed-demo-data's pre-flight Role check would\n * race seed-system-data's puts — a race that EventBridge retries\n * resolve, but only after firing the failure alarm at least once on a\n * fresh environment's first deploy.\n *\n * Re-exported from `@openhi/workflows` for symmetry with the handler's\n * import — keep the construct + handler reading from the same registry\n * entry so a rename upstream surfaces at both call sites.\n */\nexport { PlatformSystemDataSeededV1 };\n","/**\n * Sentinel `tenantId` used on platform-scoped `RoleAssignment` records.\n * A platform-scoped RA (e.g. `system-admin`) spans every tenant, but\n * the `RoleAssignment` entity requires a `tenantId` on its key for\n * sharding — there is no real tenant to point at. The `\"platform\"`\n * literal is a reserved value that never matches a real `Tenant.id`\n * and signals \"this RA scopes across all tenants\".\n *\n * The constant lives in the data layer so both the\n * {@link assertUserHasTenantMembershipOperation} write-time constraint\n * and the seed-demo-data workflow can read it without the constraint\n * helper having to reach back into the workflow package — which would\n * create a backwards data-layer-to-workflow dependency. The\n * `workflows/control-plane/seed-demo-data/events.ts` module re-exports\n * the constant under the same name for back-compat with existing\n * imports that point at the workflow's barrel.\n *\n * Renaming this constant is a wire-format break — the seed-demo-data\n * handler emits `RoleAssignment` records keyed on this value, and the\n * in-band records written under it become unreachable if the sentinel\n * changes.\n */\nexport const PLATFORM_SCOPE_TENANT_ID = \"platform\";\n","import type {\n Account,\n Encounter,\n Observation,\n Patient,\n Practitioner,\n} from \"@openhi/types\";\nimport {\n DEMO_TENANT_SPECS,\n PLACEHOLDER_TENANT_ID,\n demoScenarioIdentifier,\n openhiResourceIdentifier,\n} from \"./events\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/constructs/workflows/control-plane/seed-demo-data/data-plane-fixtures.md\n *\n * Hand-authored FHIR data-plane fixture bodies the `seed-demo-data`\n * workflow upserts into the data store on every non-prod deploy.\n * Mirrors the OPS-009 v1 resource set: Patient, Practitioner,\n * Observation, Encounter, Account.\n *\n * Ids are deterministic — re-fires of the workflow upsert the same\n * records, satisfying the workflow's idempotency contract (no\n * duplicates) and letting the IAM grant in `seed-demo-data-lambda.ts`\n * enumerate exact-match `dynamodb:LeadingKeys` rather than a wildcard.\n *\n * The placeholder tenant carries no data-plane fixtures — only the\n * three real demo tenants (wound-care, primary-care, mixed) get\n * Patient/Practitioner/Observation/Encounter/Account records. The\n * placeholder tenant exists solely as a routing target for the\n * Cognito pre-token-generation fallback and never holds clinical\n * data.\n */\n\n/**\n * Logical group of FHIR resources owned by a single (tenant, workspace)\n * pair. The workflow walks `DEMO_DATA_PLANE_FIXTURES` and writes every\n * entry against the matching workspace's `OpenHiContext`.\n */\nexport interface DemoWorkspaceDataPlaneFixtures {\n readonly tenantId: string;\n readonly workspaceId: string;\n /**\n * Scenario slug used in the demo-URN identifier — mirrors the\n * `DemoTenantSpec.scenario` value for the parent tenant. For the\n * mixed tenant both workspaces share the `demo-mixed` scenario.\n */\n readonly scenario: string;\n readonly patients: ReadonlyArray<Patient>;\n readonly practitioners: ReadonlyArray<Practitioner>;\n readonly observations: ReadonlyArray<Observation>;\n readonly encounters: ReadonlyArray<Encounter>;\n readonly accounts: ReadonlyArray<Account>;\n}\n\n/**\n * Map a tenant scenario to a `(roleSuffix, tenantId, workspaceId)`\n * triple plus the demo + OHI identifiers. Keeps the per-resource\n * builders compact below — they call this once per body to stamp the\n * two-identifier pair that matches the control-plane pattern.\n */\nconst fixtureIdentifiers = (\n scenario: string,\n tenantId: string,\n workspaceId: string,\n resourceType: string,\n id: string,\n roleSuffix: string,\n) => [\n demoScenarioIdentifier(scenario, roleSuffix),\n openhiResourceIdentifier({\n tenantId,\n workspaceId,\n resourceType,\n id,\n }),\n];\n\nconst buildWoundCareFixtures = (\n scenario: string,\n tenantId: string,\n workspaceId: string,\n idPrefix: string,\n): DemoWorkspaceDataPlaneFixtures => ({\n tenantId,\n workspaceId,\n scenario,\n patients: [\n {\n resourceType: \"Patient\",\n id: `${idPrefix}-patient-1`,\n identifier: fixtureIdentifiers(\n scenario,\n tenantId,\n workspaceId,\n \"Patient\",\n `${idPrefix}-patient-1`,\n `patient-1`,\n ),\n active: true,\n name: [{ family: \"Carter\", given: [\"Eleanor\"], use: \"official\" }],\n gender: \"female\",\n birthDate: \"1952-04-18\",\n },\n {\n resourceType: \"Patient\",\n id: `${idPrefix}-patient-2`,\n identifier: fixtureIdentifiers(\n scenario,\n tenantId,\n workspaceId,\n \"Patient\",\n `${idPrefix}-patient-2`,\n `patient-2`,\n ),\n active: true,\n name: [{ family: \"Nguyen\", given: [\"Hao\"], use: \"official\" }],\n gender: \"male\",\n birthDate: \"1968-11-02\",\n },\n ],\n practitioners: [\n {\n resourceType: \"Practitioner\",\n id: `${idPrefix}-practitioner-1`,\n identifier: fixtureIdentifiers(\n scenario,\n tenantId,\n workspaceId,\n \"Practitioner\",\n `${idPrefix}-practitioner-1`,\n `practitioner-1`,\n ),\n active: true,\n name: [{ family: \"Reyes\", given: [\"Maria\"], prefix: [\"Dr.\"] }],\n gender: \"female\",\n },\n {\n resourceType: \"Practitioner\",\n id: `${idPrefix}-practitioner-2`,\n identifier: fixtureIdentifiers(\n scenario,\n tenantId,\n workspaceId,\n \"Practitioner\",\n `${idPrefix}-practitioner-2`,\n `practitioner-2`,\n ),\n active: true,\n name: [{ family: \"Okafor\", given: [\"Chinedu\"], prefix: [\"Dr.\"] }],\n gender: \"male\",\n },\n ],\n observations: [\n {\n resourceType: \"Observation\",\n id: `${idPrefix}-observation-1`,\n identifier: fixtureIdentifiers(\n scenario,\n tenantId,\n workspaceId,\n \"Observation\",\n `${idPrefix}-observation-1`,\n `observation-1`,\n ),\n status: \"final\",\n code: {\n coding: [\n {\n system: \"http://loinc.org\",\n code: \"39135-9\",\n display: \"Wound size\",\n },\n ],\n },\n subject: { reference: `Patient/${idPrefix}-patient-1` },\n valueString: \"3.2cm x 2.1cm\",\n },\n {\n resourceType: \"Observation\",\n id: `${idPrefix}-observation-2`,\n identifier: fixtureIdentifiers(\n scenario,\n tenantId,\n workspaceId,\n \"Observation\",\n `${idPrefix}-observation-2`,\n `observation-2`,\n ),\n status: \"final\",\n code: {\n coding: [\n {\n system: \"http://loinc.org\",\n code: \"72287-2\",\n display: \"Wound exudate amount\",\n },\n ],\n },\n subject: { reference: `Patient/${idPrefix}-patient-2` },\n valueString: \"moderate\",\n },\n ],\n encounters: [\n {\n resourceType: \"Encounter\",\n id: `${idPrefix}-encounter-1`,\n identifier: fixtureIdentifiers(\n scenario,\n tenantId,\n workspaceId,\n \"Encounter\",\n `${idPrefix}-encounter-1`,\n `encounter-1`,\n ),\n status: \"finished\",\n class: {\n system: \"http://terminology.hl7.org/CodeSystem/v3-ActCode\",\n code: \"AMB\",\n display: \"ambulatory\",\n },\n subject: { reference: `Patient/${idPrefix}-patient-1` },\n },\n {\n resourceType: \"Encounter\",\n id: `${idPrefix}-encounter-2`,\n identifier: fixtureIdentifiers(\n scenario,\n tenantId,\n workspaceId,\n \"Encounter\",\n `${idPrefix}-encounter-2`,\n `encounter-2`,\n ),\n status: \"finished\",\n class: {\n system: \"http://terminology.hl7.org/CodeSystem/v3-ActCode\",\n code: \"AMB\",\n display: \"ambulatory\",\n },\n subject: { reference: `Patient/${idPrefix}-patient-2` },\n },\n ],\n accounts: [\n {\n resourceType: \"Account\",\n id: `${idPrefix}-account-1`,\n identifier: fixtureIdentifiers(\n scenario,\n tenantId,\n workspaceId,\n \"Account\",\n `${idPrefix}-account-1`,\n `account-1`,\n ),\n status: \"active\",\n name: \"Wound-care self-pay account\",\n subject: [{ reference: `Patient/${idPrefix}-patient-1` }],\n },\n ],\n});\n\nconst buildPrimaryCareFixtures = (\n scenario: string,\n tenantId: string,\n workspaceId: string,\n idPrefix: string,\n): DemoWorkspaceDataPlaneFixtures => ({\n tenantId,\n workspaceId,\n scenario,\n patients: [\n {\n resourceType: \"Patient\",\n id: `${idPrefix}-patient-1`,\n identifier: fixtureIdentifiers(\n scenario,\n tenantId,\n workspaceId,\n \"Patient\",\n `${idPrefix}-patient-1`,\n `patient-1`,\n ),\n active: true,\n name: [{ family: \"Bennett\", given: [\"Sophia\"], use: \"official\" }],\n gender: \"female\",\n birthDate: \"1985-06-09\",\n },\n {\n resourceType: \"Patient\",\n id: `${idPrefix}-patient-2`,\n identifier: fixtureIdentifiers(\n scenario,\n tenantId,\n workspaceId,\n \"Patient\",\n `${idPrefix}-patient-2`,\n `patient-2`,\n ),\n active: true,\n name: [{ family: \"Patel\", given: [\"Arjun\"], use: \"official\" }],\n gender: \"male\",\n birthDate: \"1979-02-21\",\n },\n ],\n practitioners: [\n {\n resourceType: \"Practitioner\",\n id: `${idPrefix}-practitioner-1`,\n identifier: fixtureIdentifiers(\n scenario,\n tenantId,\n workspaceId,\n \"Practitioner\",\n `${idPrefix}-practitioner-1`,\n `practitioner-1`,\n ),\n active: true,\n name: [{ family: \"Lin\", given: [\"Wei\"], prefix: [\"Dr.\"] }],\n gender: \"female\",\n },\n {\n resourceType: \"Practitioner\",\n id: `${idPrefix}-practitioner-2`,\n identifier: fixtureIdentifiers(\n scenario,\n tenantId,\n workspaceId,\n \"Practitioner\",\n `${idPrefix}-practitioner-2`,\n `practitioner-2`,\n ),\n active: true,\n name: [{ family: \"Kowalski\", given: [\"Piotr\"], prefix: [\"Dr.\"] }],\n gender: \"male\",\n },\n ],\n observations: [\n {\n resourceType: \"Observation\",\n id: `${idPrefix}-observation-1`,\n identifier: fixtureIdentifiers(\n scenario,\n tenantId,\n workspaceId,\n \"Observation\",\n `${idPrefix}-observation-1`,\n `observation-1`,\n ),\n status: \"final\",\n code: {\n coding: [\n {\n system: \"http://loinc.org\",\n code: \"8480-6\",\n display: \"Systolic blood pressure\",\n },\n ],\n },\n subject: { reference: `Patient/${idPrefix}-patient-1` },\n valueQuantity: { value: 122, unit: \"mm[Hg]\" },\n },\n {\n resourceType: \"Observation\",\n id: `${idPrefix}-observation-2`,\n identifier: fixtureIdentifiers(\n scenario,\n tenantId,\n workspaceId,\n \"Observation\",\n `${idPrefix}-observation-2`,\n `observation-2`,\n ),\n status: \"final\",\n code: {\n coding: [\n {\n system: \"http://loinc.org\",\n code: \"8462-4\",\n display: \"Diastolic blood pressure\",\n },\n ],\n },\n subject: { reference: `Patient/${idPrefix}-patient-2` },\n valueQuantity: { value: 78, unit: \"mm[Hg]\" },\n },\n ],\n encounters: [\n {\n resourceType: \"Encounter\",\n id: `${idPrefix}-encounter-1`,\n identifier: fixtureIdentifiers(\n scenario,\n tenantId,\n workspaceId,\n \"Encounter\",\n `${idPrefix}-encounter-1`,\n `encounter-1`,\n ),\n status: \"finished\",\n class: {\n system: \"http://terminology.hl7.org/CodeSystem/v3-ActCode\",\n code: \"AMB\",\n display: \"ambulatory\",\n },\n subject: { reference: `Patient/${idPrefix}-patient-1` },\n },\n {\n resourceType: \"Encounter\",\n id: `${idPrefix}-encounter-2`,\n identifier: fixtureIdentifiers(\n scenario,\n tenantId,\n workspaceId,\n \"Encounter\",\n `${idPrefix}-encounter-2`,\n `encounter-2`,\n ),\n status: \"in-progress\",\n class: {\n system: \"http://terminology.hl7.org/CodeSystem/v3-ActCode\",\n code: \"AMB\",\n display: \"ambulatory\",\n },\n subject: { reference: `Patient/${idPrefix}-patient-2` },\n },\n ],\n accounts: [\n {\n resourceType: \"Account\",\n id: `${idPrefix}-account-1`,\n identifier: fixtureIdentifiers(\n scenario,\n tenantId,\n workspaceId,\n \"Account\",\n `${idPrefix}-account-1`,\n `account-1`,\n ),\n status: \"active\",\n name: \"Primary-care insurance account\",\n subject: [{ reference: `Patient/${idPrefix}-patient-1` }],\n },\n ],\n});\n\n/**\n * Per-workspace fixtures the data-plane phase writes on every fire.\n * The placeholder tenant carries no fixtures. The mixed tenant carries\n * one fixture group per workspace; the two single-workspace tenants\n * carry one each. Total: 4 fixture groups × ≈ 9 resources = ~36\n * data-plane records.\n *\n * Ids embed the tenant + workspace slug so they remain unambiguous\n * across the four workspaces (the FHIR resource id is the only thing\n * that survives into the partition key, so a duplicate id across\n * workspaces would still collide on read paths that scan-by-id).\n */\nexport const DEMO_DATA_PLANE_FIXTURES: ReadonlyArray<DemoWorkspaceDataPlaneFixtures> =\n [\n buildWoundCareFixtures(\n \"demo-wound-care\",\n \"demo-wound-care-tenant\",\n \"demo-wound-care-workspace\",\n \"demo-wound-care\",\n ),\n buildPrimaryCareFixtures(\n \"demo-primary-care\",\n \"demo-primary-care-tenant\",\n \"demo-primary-care-workspace\",\n \"demo-primary-care\",\n ),\n buildWoundCareFixtures(\n \"demo-mixed\",\n \"demo-mixed-tenant\",\n \"demo-mixed-workspace-wound-care\",\n \"demo-mixed-wound-care\",\n ),\n buildPrimaryCareFixtures(\n \"demo-mixed\",\n \"demo-mixed-tenant\",\n \"demo-mixed-workspace-primary-care\",\n \"demo-mixed-primary-care\",\n ),\n ];\n\n/**\n * Regression guard: the fixture groups must each be tied to a Tenant +\n * Workspace combination that exists in {@link DEMO_TENANT_SPECS}.\n * Imported `DEMO_TENANT_SPECS` and `PLACEHOLDER_TENANT_ID` keep the\n * guard self-contained — no test plumbing required.\n */\nconst _validateFixturesAgainstTenantSpecs = (): void => {\n for (const group of DEMO_DATA_PLANE_FIXTURES) {\n if (group.tenantId === PLACEHOLDER_TENANT_ID) {\n throw new Error(\n \"The placeholder tenant must not carry data-plane fixtures.\",\n );\n }\n const tenant = DEMO_TENANT_SPECS.find((s) => s.tenantId === group.tenantId);\n if (!tenant) {\n throw new Error(\n `Fixture references unknown tenantId \"${group.tenantId}\". ` +\n \"Add a matching entry to DEMO_TENANT_SPECS first.\",\n );\n }\n const workspace = tenant.workspaces.find(\n (ws) => ws.id === group.workspaceId,\n );\n if (!workspace) {\n throw new Error(\n `Fixture references unknown workspaceId \"${group.workspaceId}\" ` +\n `for tenant \"${group.tenantId}\".`,\n );\n }\n }\n};\n_validateFixturesAgainstTenantSpecs();\n","import { Service } from \"electrodb\";\nimport { defaultTableName, dynamoClient } from \"./dynamo-client\";\nimport { ConfigurationEntity } from \"./entities/control/configuration-entity\";\nimport { ConfigurationUserProjectionEntity } from \"./entities/control/configuration-user-projection-entity\";\nimport { ConfigurationWorkspaceProjectionEntity } from \"./entities/control/configuration-workspace-projection-entity\";\nimport { MembershipEntity } from \"./entities/control/membership-entity\";\nimport { MembershipUserProjectionEntity } from \"./entities/control/membership-user-projection-entity\";\nimport { MembershipWorkspaceProjectionEntity } from \"./entities/control/membership-workspace-projection-entity\";\nimport { RoleEntity } from \"./entities/control/role-entity\";\nimport { RoleAssignmentEntity } from \"./entities/control/roleassignment-entity\";\nimport { RoleAssignmentUserProjectionEntity } from \"./entities/control/roleassignment-user-projection-entity\";\nimport { RoleAssignmentWorkspaceProjectionEntity } from \"./entities/control/roleassignment-workspace-projection-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 configurationUserProjection: ConfigurationUserProjectionEntity,\n configurationWorkspaceProjection: ConfigurationWorkspaceProjectionEntity,\n membership: MembershipEntity,\n membershipUserProjection: MembershipUserProjectionEntity,\n membershipWorkspaceProjection: MembershipWorkspaceProjectionEntity,\n role: RoleEntity,\n roleAssignment: RoleAssignmentEntity,\n roleAssignmentUserProjection: RoleAssignmentUserProjectionEntity,\n roleAssignmentWorkspaceProjection: RoleAssignmentWorkspaceProjectionEntity,\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 *\n * `transaction` exposes ElectroDB's `service.transaction.write` /\n * `service.transaction.get` builders so the operations-layer multi-write\n * helper (#1010, ADR-018) can compose `TransactWriteItems` across the\n * control-plane entities.\n */\nexport const DynamoControlService = {\n entities: controlPlaneService.entities,\n transaction: controlPlaneService.transaction,\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 transaction: service.transaction,\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, normalizeLabel } 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/**\n * Extract a roleId from a RoleAssignment resource payload. Looks first at\n * a flat top-level `roleId` string, then at a FHIR-style `role.reference`\n * (e.g. `Role/<id>`). Returns `undefined` when neither shape is present\n * or the field is malformed — callers fall back to the generic GSI1SK\n * derivation in that case so a single bad write never blocks an entity put.\n */\nfunction extractRoleId(resource: Record<string, unknown>): string | undefined {\n const flat = resource.roleId;\n if (typeof flat === \"string\" && flat.length > 0) return flat;\n\n const role = resource.role;\n if (role && typeof role === \"object\") {\n const reference = (role as { reference?: unknown }).reference;\n if (typeof reference === \"string\" && reference.length > 0) {\n const slash = reference.lastIndexOf(\"/\");\n const tail = slash >= 0 ? reference.slice(slash + 1) : reference;\n if (tail.length > 0) return tail;\n }\n }\n return undefined;\n}\n\n/**\n * RoleAssignment-specific GSI1 sort-key attribute (ADR-018 pattern #8 —\n * \"users with a specific role in a tenant, sorted by user name\").\n *\n * Composes the canonical-row GSI1SK as the discriminator-first shape\n * `<roleId>#<normalizedUserName>#<id>` so a GSI1 query partitioned on\n * the tenant can `begins_with('<roleId>#')` to enumerate every user\n * assigned to a given role, sorted by user name.\n *\n * - `<roleId>` is read from a flat `resource.roleId` field, falling back\n * to the slug after the final `/` in `resource.role.reference` (the\n * FHIR Reference shape). Sorting on `roleId` rather than the role's\n * display name means a Role rename does not cascade onto this index\n * (TR-024 / ADR-018 § Implementation Notes).\n * - `<normalizedUserName>` is `normalizeLabel(denormalizedUserName)` —\n * the top-level denormalized field promoted in #1009 (TR-024 rule 3:\n * canonical-record symmetry).\n *\n * Falls back to `gsi1skAttribute`'s `<lastUpdated>#<id>` shape when\n * either component is missing or malformed, so pre-TR-024 rows and\n * malformed payloads still produce a valid sort key.\n *\n * Not `required` because the value is derived via `watch`/`set`.\n *\n * @see ADR-018 § Access Pattern Coverage — pattern #8\n * @see TR-024 — Denormalized display-name attributes\n */\nexport const roleAssignmentGsi1skAttribute = {\n type: \"string\" as const,\n watch: [\"resource\", \"denormalizedUserName\", \"lastUpdated\", \"id\"] as const,\n set: (\n _val?: string,\n item?: {\n resource?: string;\n denormalizedUserName?: string;\n lastUpdated?: string;\n id?: string;\n },\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\n const roleId = extractRoleId(parsed as Record<string, unknown>);\n if (roleId === undefined) return fallback;\n\n const denormalizedUserName =\n typeof item.denormalizedUserName === \"string\"\n ? item.denormalizedUserName\n : \"\";\n const normalizedUserName =\n denormalizedUserName.length > 0\n ? normalizeLabel(denormalizedUserName)\n : \"\";\n if (normalizedUserName.length === 0) return fallback;\n\n return `${roleId}#${normalizedUserName}#${id}`;\n },\n};\n\n/**\n * Membership-specific GSI1 sort-key attribute (ADR-018 pattern #1 —\n * \"users in a tenant, sorted by user name\").\n *\n * Composes the canonical-row GSI1SK as `<normalizedUserName>#<id>` so a\n * GSI1 query partitioned on the tenant range-scans by user-name prefix\n * and returns memberships sorted alphabetically by user name. No role\n * discriminator goes in front — pattern #1 is user-name-first.\n *\n * - `<normalizedUserName>` is `normalizeLabel(denormalizedUserName)` —\n * the top-level denormalized field promoted in #1009 (TR-024 rule 3:\n * canonical-record symmetry).\n *\n * Falls back to `gsi1skAttribute`'s `<lastUpdated>#<id>` shape when\n * `denormalizedUserName` is missing, so pre-TR-024 rows and malformed\n * payloads still produce a valid sort key.\n *\n * Not `required` because the value is derived via `watch`/`set`.\n *\n * @see ADR-018 § Access Pattern Coverage — pattern #1\n * @see TR-024 — Denormalized display-name attributes\n */\nexport const membershipGsi1skAttribute = {\n type: \"string\" as const,\n watch: [\"denormalizedUserName\", \"lastUpdated\", \"id\"] as const,\n set: (\n _val?: string,\n item?: {\n denormalizedUserName?: string;\n lastUpdated?: string;\n id?: string;\n },\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 const denormalizedUserName =\n typeof item?.denormalizedUserName === \"string\"\n ? item.denormalizedUserName\n : \"\";\n const normalizedUserName =\n denormalizedUserName.length > 0\n ? normalizeLabel(denormalizedUserName)\n : \"\";\n if (normalizedUserName.length === 0) {\n return fallback;\n }\n\n return `${normalizedUserName}#${id}`;\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\";\n\n/**\n * Configuration user-projection entity (single-table store, no GSI).\n *\n * **ADR-018 adjacency-list projection — pattern #10 (user-scope half).**\n * For every user-scoped Configuration write the operations-layer\n * multi-write helper writes one projection row under the user partition\n * so the user-rooted access pattern #10 is served by a single\n * base-table `Query` with no GSI hop:\n *\n * | Pattern | When | PK | SK |\n * |---|---|---|---|\n * | #10 user-scope | Configuration is user-scoped (`userId !== \"-\"`) | `USER#ID#<userId>` | `CONFIGURATION#<normalizedConfigName>#<configurationId>` |\n *\n * `<normalizedConfigName>` derives from Configuration's `key` attribute\n * (the canonical name dimension — Configuration carries no `displayName`\n * per TR-024 § Open Item #5, so `key` is the natural sort source). The\n * SK shape is operation-owned: the operations-layer projection writer\n * composes the SK string via `buildConfigurationUserProjectionSk` and\n * supplies it on the `sk` attribute. This entity stores the SK verbatim —\n * no `watch`/derived computation here — so the SK grammar (and any\n * future revision) lives in one place: the operations layer.\n *\n * Projection attribute set per ADR-018 § Projection attribute set and\n * the implementation guide § 2: `summary`, `vid`, `lastUpdated` (so\n * `Query(PK = USER#ID#<userId>, SK begins_with 'CONFIGURATION#')` is\n * self-sufficient — no BatchGet hop to the canonical record), plus the\n * projection-discriminating fields (`configurationId`, `userId`,\n * `tenantId`, `scope`).\n *\n * **Cross-tenant partition.** Unlike Membership/RoleAssignment-workspace\n * partitions, the Configuration user-projection's PK carries no tenant\n * prefix — a user's user-scoped Configurations are cross-tenant by\n * design (a user may carry preferences that follow them across tenant\n * memberships). This mirrors the RoleAssignment user-projection partition.\n *\n * **No GSI projection.** Per ADR-018 § Decision, cross-cutting reads\n * are served by the main-table partition `USER#ID#<userId>`; the\n * GSI1/GSI2 catalog is unchanged. Tenant-scoped Configurations\n * continue to use the canonical GSI1 path (ADR-011) unchanged.\n *\n * @see ADR-018 § Access Pattern Coverage (#10 — user-scope half)\n * @see .state/adr-018-implementation-guide.md § 1 (SK grammar) and § 2 (attribute set)\n * @see .claude/rules/data-layer-layout.md — projection writers live in operations, not here\n */\nexport const ConfigurationUserProjectionEntity = new Entity({\n model: {\n entity: \"configurationUserProjection\",\n service: \"control\",\n version: \"01\",\n },\n attributes: {\n /**\n * User partition discriminator. Renders as `USER#ID#<userId>` on the\n * base-table PK. Always required — the projection has no meaning\n * outside a user partition.\n */\n userId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Pre-composed sort key — built by the operations-layer projection\n * writer via `buildConfigurationUserProjectionSk`. The entity stores\n * the value verbatim so the SK grammar (pattern #10 user-scope) is\n * owned by the operations layer, not duplicated here.\n */\n sk: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Configuration canonical-record id. Stored as a discriminating\n * field so consumers can hydrate the canonical row via the\n * Configuration get-by-id operation when the projection's `summary`\n * is insufficient.\n */\n configurationId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Tenant the Configuration is associated with. The canonical row\n * keys off `(tenantId, workspaceId, userId, roleId)`; the projection\n * carries `tenantId` so consumers reconstructing the canonical PK\n * have the tenant segment without a hop.\n */\n tenantId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Scope marker. Always `\"user\"` on this projection — recorded\n * explicitly so future scope-bearing projections (workspace,\n * tenant, role) can share filter semantics in a unified\n * cross-projection list query if one ever lands.\n */\n scope: {\n type: \"string\" as const,\n required: true,\n default: \"user\",\n },\n /**\n * Configuration's `key` attribute (config category, e.g. endpoints,\n * branding, display). Mirrored from the canonical row so consumers\n * reading the projection get the natural display label without a\n * BatchGet hop. Doubles as the source of `<normalizedConfigName>` in\n * the SK.\n */\n displayName: {\n type: \"string\" as const,\n required: false,\n },\n /**\n * Summary projection (key display fields as JSON string) — mirrored\n * from the canonical Configuration row so user-partition queries do\n * not need a BatchGet hop.\n */\n summary: {\n type: \"string\" as const,\n required: true,\n },\n /** Version id mirrored from the canonical Configuration row. */\n vid: {\n type: \"string\" as const,\n required: true,\n },\n /** Last-updated timestamp mirrored from the canonical Configuration row. */\n lastUpdated: {\n type: \"string\" as const,\n required: true,\n },\n },\n indexes: {\n /**\n * Base table: PK = USER#ID#\\<userId\\>, SK = operation-supplied. A\n * single `Query(PK = USER#ID#<userId>, SK begins_with 'CONFIGURATION#')`\n * returns the user's user-scoped Configurations sorted by\n * `<normalizedConfigName>` (then `<configurationId>` as the\n * tiebreaker).\n */\n record: {\n pk: {\n field: \"PK\",\n composite: [\"userId\"],\n template: \"USER#ID#${userId}\",\n },\n sk: {\n field: \"SK\",\n casing: \"none\" as const,\n composite: [\"sk\"],\n template: \"${sk}\",\n },\n },\n },\n});\n","import { Entity } from \"electrodb\";\n\n/**\n * Configuration workspace-projection entity (single-table store, no GSI).\n *\n * **ADR-018 adjacency-list projection — pattern #10 (workspace-scope half).**\n * For every workspace-scoped Configuration the operations-layer\n * multi-write helper writes one projection row under the workspace\n * partition so the workspace-rooted access pattern #10 is served by a\n * single base-table `Query` with no GSI hop:\n *\n * | Pattern | When | PK | SK |\n * |---|---|---|---|\n * | #10 workspace-scope | Configuration is workspace-scoped (`workspaceId !== \"-\"`, `userId === \"-\"`) | `TID#<tenantId>#WORKSPACE#ID#<workspaceId>` | `CONFIGURATION#<normalizedConfigName>#<configurationId>` |\n *\n * The PK co-locates with the canonical Workspace record\n * (`SK = CURRENT`) and the Membership / RoleAssignment workspace-\n * projections (patterns #2, #9), so an admin workspace dashboard can\n * hydrate workspace metadata + member projections + role-assignment\n * projections + workspace-scoped Configurations in a single `Query`.\n *\n * `<normalizedConfigName>` derives from Configuration's `key` attribute\n * (the canonical name dimension — Configuration carries no `displayName`\n * per TR-024 § Open Item #5, so `key` is the natural sort source). The\n * SK shape is operation-owned: the operations-layer projection writer\n * composes the SK string via `buildConfigurationWorkspaceProjectionSk`\n * and supplies it on the `sk` attribute. This entity stores the SK\n * verbatim — no `watch`/derived computation here — so the SK grammar\n * (and any future revision) lives in one place: the operations layer.\n *\n * Projection attribute set per ADR-018 § Projection attribute set and\n * the implementation guide § 2: `summary`, `vid`, `lastUpdated` (so\n * `Query(PK = TID#<tenantId>#WORKSPACE#ID#<workspaceId>, SK begins_with 'CONFIGURATION#')`\n * is self-sufficient — no BatchGet hop to the canonical record), plus\n * the projection-discriminating fields (`configurationId`, `workspaceId`,\n * `tenantId`, `scope`).\n *\n * **Tenant-prefixed partition.** Unlike the Configuration user-\n * projection (whose PK is `USER#ID#<userId>` with no tenant prefix —\n * a user's user-scoped Configurations are cross-tenant by design),\n * the workspace-projection PK carries the tenant prefix because\n * Workspaces are tenant-scoped per ADR-011. This mirrors the\n * Membership / RoleAssignment workspace-projection partitions.\n *\n * **No GSI projection.** Per ADR-018 § Decision, cross-cutting reads\n * are served by the main-table partition\n * `TID#<tenantId>#WORKSPACE#ID#<workspaceId>`; the GSI1/GSI2 catalog\n * is unchanged. Tenant-scoped Configurations continue to use the\n * canonical GSI1 path (ADR-011) unchanged.\n *\n * @see ADR-018 § Access Pattern Coverage (#10 — workspace-scope half)\n * @see .state/adr-018-implementation-guide.md § 1 (SK grammar) and § 2 (attribute set)\n * @see .claude/rules/data-layer-layout.md — projection writers live in operations, not here\n */\nexport const ConfigurationWorkspaceProjectionEntity = new Entity({\n model: {\n entity: \"configurationWorkspaceProjection\",\n service: \"control\",\n version: \"01\",\n },\n attributes: {\n /**\n * Tenant the workspace belongs to. Renders as the leading segment\n * of the base-table PK. Always required — the workspace partition\n * is tenant-scoped per ADR-011.\n */\n tenantId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Workspace partition discriminator. Renders as the trailing\n * segment of the base-table PK\n * (`TID#<tenantId>#WORKSPACE#ID#<workspaceId>`). Always required —\n * the projection has no meaning outside a workspace partition.\n */\n workspaceId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Pre-composed sort key — built by the operations-layer projection\n * writer via `buildConfigurationWorkspaceProjectionSk`. The entity\n * stores the value verbatim so the SK grammar (pattern #10\n * workspace-scope) is owned by the operations layer, not\n * duplicated here.\n */\n sk: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Configuration canonical-record id. Stored as a discriminating\n * field so consumers can hydrate the canonical row via the\n * Configuration get-by-id operation when the projection's `summary`\n * is insufficient.\n */\n configurationId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Scope marker. Always `\"workspace\"` on this projection — recorded\n * explicitly so future scope-bearing projections (user, tenant,\n * role) can share filter semantics in a unified cross-projection\n * list query if one ever lands.\n */\n scope: {\n type: \"string\" as const,\n required: true,\n default: \"workspace\",\n },\n /**\n * Configuration's `key` attribute (config category, e.g. endpoints,\n * branding, display). Mirrored from the canonical row so consumers\n * reading the projection get the natural display label without a\n * BatchGet hop. Doubles as the source of `<normalizedConfigName>`\n * in the SK.\n */\n displayName: {\n type: \"string\" as const,\n required: false,\n },\n /**\n * Summary projection (key display fields as JSON string) — mirrored\n * from the canonical Configuration row so workspace-partition\n * queries do not need a BatchGet hop.\n */\n summary: {\n type: \"string\" as const,\n required: true,\n },\n /** Version id mirrored from the canonical Configuration row. */\n vid: {\n type: \"string\" as const,\n required: true,\n },\n /** Last-updated timestamp mirrored from the canonical Configuration row. */\n lastUpdated: {\n type: \"string\" as const,\n required: true,\n },\n },\n indexes: {\n /**\n * Base table: PK = TID#<tenantId>#WORKSPACE#ID#<workspaceId>,\n * SK = operation-supplied. A single\n * `Query(PK = TID#<tenantId>#WORKSPACE#ID#<workspaceId>, SK begins_with 'CONFIGURATION#')`\n * returns the workspace's workspace-scoped Configurations sorted by\n * `<normalizedConfigName>` (then `<configurationId>` as the\n * tiebreaker).\n */\n record: {\n pk: {\n field: \"PK\",\n composite: [\"tenantId\", \"workspaceId\"],\n template: \"TID#${tenantId}#WORKSPACE#ID#${workspaceId}\",\n },\n sk: {\n field: \"SK\",\n casing: \"none\" as const,\n composite: [\"sk\"],\n template: \"${sk}\",\n },\n },\n },\n});\n","import { Entity } from \"electrodb\";\nimport {\n gsi1ShardAttribute,\n membershipGsi1skAttribute,\n} 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 /**\n * Derived GSI1 sort key — `<normalizedUserName>#<id>` per ADR-018\n * pattern #1 so a GSI1 query partitioned on the tenant range-scans\n * by user-name prefix and returns memberships sorted by user name.\n * Falls back to `<lastUpdated>#<id>` when `denormalizedUserName`\n * is missing.\n */\n gsi1sk: membershipGsi1skAttribute,\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 * Denormalized `linked-data-identity` Reference (e.g. `Practitioner/abc`).\n * Populated from the FHIR extension on the Membership resource at write\n * time so future GSIs can index data-plane identity lookups without\n * deserializing the full resource JSON. See ADR 2026-03-13-02 §6.\n */\n linkedDataIdentityRef: {\n type: \"string\" as const,\n required: false,\n },\n /**\n * Denormalized display name of the linked Tenant, captured at row\n * last-write time. Promoted to a top-level attribute so the ADR-018\n * adjacency-list projection SKs (pattern #3 — `MEMBERSHIP#TENANT#<normalizedTenantName>#…`)\n * can be composed from a top-level field instead of digging into the\n * `resource` JSON. Optional on the schema so pre-TR-024 rows do not\n * break; the operations-layer multi-write helper (#1010) makes the\n * field load-bearing at write time per TR-024 rule 2 (write-time\n * source = canonical Tenant.displayName).\n * @see TR-024 — Denormalized display-name attributes\n */\n denormalizedTenantName: {\n type: \"string\" as const,\n required: false,\n },\n /**\n * Denormalized display name of the linked User, captured at row\n * last-write time. Promoted to a top-level attribute so the ADR-018\n * adjacency-list canonical-record GSI1SK (pattern #1 —\n * `<normalizedUserName>#<id>`) and workspace-projection SK (pattern #2)\n * can be composed from a top-level field. Optional on the schema so\n * pre-TR-024 rows do not break; the operations-layer multi-write helper\n * (#1010) makes the field load-bearing at write time per TR-024 rule 2\n * (write-time source = canonical User.displayName).\n * @see TR-024 — Denormalized display-name attributes\n */\n denormalizedUserName: {\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 `membershipGsi1skAttribute` — composes\n * `<normalizedUserName>#<id>` per ADR-018 pattern #1 (users in a\n * tenant, sorted by user name); falls back to `<lastUpdated>#<id>`\n * when `denormalizedUserName` is missing. `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#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\";\n\n/**\n * Membership user-projection entity (single-table store, no GSI).\n *\n * **ADR-018 adjacency-list projection.** For every Membership write the\n * operations-layer multi-write helper writes one of two projection rows\n * under the user partition so the user-rooted access patterns #3 and #4\n * are served by a single base-table `Query` with no GSI hop:\n *\n * | Pattern | When | PK | SK |\n * |---|---|---|---|\n * | #3 — tenant sub-lane | `workspaceId` absent | `USER#ID#<userId>` | `MEMBERSHIP#TENANT#<normalizedTenantName>#TID#<tenantId>#<id>` |\n * | #4 — workspace sub-lane | `workspaceId` set | `USER#ID#<userId>` | `MEMBERSHIP#WORKSPACE#TID#<tenantId>#<normalizedWorkspaceName>#WID#<workspaceId>#<id>` |\n *\n * Both shapes share the user-partition `PK = USER#ID#<userId>`. The SK\n * shape is operation-owned: the operations-layer projection writer\n * composes the SK string via the `buildMembershipUserProjectionSk*`\n * helpers and supplies it on the `sk` attribute. This entity stores the\n * SK verbatim — no `watch`/derived computation here — so the SK grammar\n * (and any future revision) lives in one place: the operations layer.\n *\n * Projection attribute set per ADR-018 § Projection attribute set and\n * the implementation guide § 2: `summary`, `vid`, `lastUpdated` (so\n * `Query(PK = USER#ID#<userId>, SK begins_with 'MEMBERSHIP#')` is\n * self-sufficient — no BatchGet hop to the canonical record), plus the\n * projection-discriminating fields (`tenantId`, `userId`, `workspaceId?`,\n * `membershipId`) and TR-024 denormalized display names\n * (`denormalizedTenantName`, `denormalizedUserName`,\n * `denormalizedWorkspaceName?`).\n *\n * **No GSI projection.** Per ADR-018 § Decision, cross-cutting reads\n * are served by the main-table partition `USER#ID#<userId>`; the\n * GSI1/GSI2 catalog is unchanged.\n *\n * @see ADR-018 § Access Pattern Coverage (#3, #4)\n * @see .state/adr-018-implementation-guide.md § 1 (SK grammar) and § 2 (attribute set)\n * @see .claude/rules/data-layer-layout.md — projection writers live in operations, not here\n */\nexport const MembershipUserProjectionEntity = new Entity({\n model: {\n entity: \"membershipUserProjection\",\n service: \"control\",\n version: \"01\",\n },\n attributes: {\n /**\n * User partition discriminator. Renders as `USER#ID#<userId>` on the\n * base-table PK. Always required — the projection has no meaning\n * outside a user partition.\n */\n userId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Pre-composed sort key — built by the operations-layer projection\n * writer via `buildMembershipUserProjectionSk*` helpers. The entity\n * stores the value verbatim so the SK grammar (patterns #3 and #4)\n * is owned by the operations layer, not duplicated here.\n */\n sk: {\n type: \"string\" as const,\n required: true,\n },\n /** Tenant in which the membership applies. Always required. */\n tenantId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Workspace the membership scopes to. Present iff the projection\n * row is a pattern-#4 workspace sub-lane row; absent for pattern-#3\n * tenant sub-lane rows.\n */\n workspaceId: {\n type: \"string\" as const,\n required: false,\n },\n /**\n * Membership canonical-record id. Stored as a discriminating field\n * so consumers can hydrate the canonical row via\n * `MembershipEntity.get({ tenantId, id: membershipId })` when the\n * projection's `summary` is insufficient.\n */\n membershipId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Summary projection (key display fields as JSON string: id,\n * displayName, status) — mirrored from the canonical Membership row\n * so user-partition queries do not need a BatchGet hop.\n */\n summary: {\n type: \"string\" as const,\n required: true,\n },\n /** Version id mirrored from the canonical Membership row. */\n vid: {\n type: \"string\" as const,\n required: true,\n },\n /** Last-updated timestamp mirrored from the canonical Membership row. */\n lastUpdated: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Denormalized Tenant display name — required to compose pattern-#3\n * SK (`MEMBERSHIP#TENANT#<normalizedTenantName>#…`). Optional on the\n * schema because pre-TR-024 rows may not carry a display name; the\n * operations layer falls back gracefully when missing.\n */\n denormalizedTenantName: {\n type: \"string\" as const,\n required: false,\n },\n /**\n * Denormalized User display name — mirrored from the canonical\n * Membership row per TR-024 rule 3 (canonical-record symmetry).\n * Carried on the projection so consumers can render the user's\n * display name without a hop to the User record.\n */\n denormalizedUserName: {\n type: \"string\" as const,\n required: false,\n },\n /**\n * Denormalized Workspace display name — required to compose\n * pattern-#4 SK (`MEMBERSHIP#WORKSPACE#TID#<tenantId>#<normalizedWorkspaceName>#…`).\n * Optional on the schema (TR-024 § Open Item #4 defers a formal\n * Workspace-rename cascade); the operations layer falls back to a\n * sentinel when missing so the SK still has a valid shape.\n */\n denormalizedWorkspaceName: {\n type: \"string\" as const,\n required: false,\n },\n },\n indexes: {\n /**\n * Base table: PK = USER#ID#\\<userId\\>, SK = operation-supplied.\n * Both pattern #3 and pattern #4 use this same index — the SK string\n * encodes the lane discriminator (`MEMBERSHIP#TENANT#…` vs\n * `MEMBERSHIP#WORKSPACE#…`) so a single\n * `Query(PK = USER#ID#<userId>, SK begins_with 'MEMBERSHIP#')`\n * returns both lanes interleaved.\n */\n record: {\n pk: {\n field: \"PK\",\n composite: [\"userId\"],\n template: \"USER#ID#${userId}\",\n },\n sk: {\n field: \"SK\",\n casing: \"none\" as const,\n composite: [\"sk\"],\n template: \"${sk}\",\n },\n },\n },\n});\n","import { Entity } from \"electrodb\";\n\n/**\n * Membership workspace-projection entity (single-table store, no GSI).\n *\n * **ADR-018 adjacency-list projection.** For every workspace-scoped\n * Membership the operations-layer multi-write helper writes one\n * projection row under the workspace partition so the workspace-rooted\n * access pattern #2 is served by a single base-table `Query` with no\n * GSI hop:\n *\n * | Pattern | When | PK | SK |\n * |---|---|---|---|\n * | #2 — users in a workspace | `workspaceId` set | `TID#<tenantId>#WORKSPACE#ID#<workspaceId>` | `MEMBERSHIP#<normalizedUserName>#USER#<userId>#<id>` |\n *\n * The PK co-locates with the canonical Workspace record\n * (`SK = CURRENT`) so a single `Query(PK = TID#<tenantId>#WORKSPACE#ID#<workspaceId>)`\n * returns workspace metadata + every member projection in one round\n * trip. The SK shape is operation-owned: the operations-layer\n * projection writer composes the SK string via the\n * `buildMembershipWorkspaceProjectionSk` helper and supplies it on the\n * `sk` attribute. This entity stores the SK verbatim — no\n * `watch`/derived computation here — so the SK grammar lives in one\n * place: the operations layer.\n *\n * Projection attribute set per ADR-018 § Projection attribute set and\n * the implementation guide § 2: `summary`, `vid`, `lastUpdated` (so\n * `Query(PK = TID#<tenantId>#WORKSPACE#ID#<workspaceId>, SK begins_with 'MEMBERSHIP#')`\n * is self-sufficient — no BatchGet hop to the canonical record), plus\n * the projection-discriminating fields (`tenantId`, `workspaceId`,\n * `userId`, `membershipId`) and TR-024 denormalized user display name\n * (`denormalizedUserName`).\n *\n * **No GSI projection.** Per ADR-018 § Decision, cross-cutting reads\n * are served by the main-table partition\n * `TID#<tenantId>#WORKSPACE#ID#<workspaceId>`; the GSI1/GSI2 catalog\n * is unchanged.\n *\n * @see ADR-018 § Access Pattern Coverage (#2)\n * @see .state/adr-018-implementation-guide.md § 1 (SK grammar) and § 2 (attribute set)\n * @see .claude/rules/data-layer-layout.md — projection writers live in operations, not here\n */\nexport const MembershipWorkspaceProjectionEntity = new Entity({\n model: {\n entity: \"membershipWorkspaceProjection\",\n service: \"control\",\n version: \"01\",\n },\n attributes: {\n /**\n * Tenant the workspace belongs to. Renders as the leading segment\n * of the base-table PK. Always required — the workspace partition\n * is tenant-scoped per ADR-011.\n */\n tenantId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Workspace partition discriminator. Renders as the trailing\n * segment of the base-table PK\n * (`TID#<tenantId>#WORKSPACE#ID#<workspaceId>`). Always required —\n * the projection has no meaning outside a workspace partition.\n */\n workspaceId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Pre-composed sort key — built by the operations-layer projection\n * writer via `buildMembershipWorkspaceProjectionSk`. The entity\n * stores the value verbatim so the SK grammar (pattern #2) is\n * owned by the operations layer, not duplicated here.\n */\n sk: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * User the membership links. Stored as a discriminating field so\n * consumers can hydrate the canonical User row via\n * `UserEntity.get({ id: userId, sk: \"CURRENT\" })` when the\n * projection's `summary` is insufficient.\n */\n userId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Membership canonical-record id. Stored as a discriminating field\n * so consumers can hydrate the canonical row via\n * `MembershipEntity.get({ tenantId, id: membershipId })` when the\n * projection's `summary` is insufficient.\n */\n membershipId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Summary projection (key display fields as JSON string: id,\n * displayName, status) — mirrored from the canonical Membership row\n * so workspace-partition queries do not need a BatchGet hop.\n */\n summary: {\n type: \"string\" as const,\n required: true,\n },\n /** Version id mirrored from the canonical Membership row. */\n vid: {\n type: \"string\" as const,\n required: true,\n },\n /** Last-updated timestamp mirrored from the canonical Membership row. */\n lastUpdated: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Denormalized User display name — required to compose the\n * pattern-#2 SK (`MEMBERSHIP#<normalizedUserName>#…`). Optional on\n * the schema because pre-TR-024 rows may not carry a display name;\n * the operations layer falls back to a sentinel when missing so\n * the SK still has a valid shape. The TR-023 rename-cascade\n * pipeline rewrites the SK on a User rename.\n */\n denormalizedUserName: {\n type: \"string\" as const,\n required: false,\n },\n },\n indexes: {\n /**\n * Base table: PK = TID#<tenantId>#WORKSPACE#ID#<workspaceId>,\n * SK = operation-supplied. Pattern #2 uses this index — the SK\n * encodes the entity-type prefix (`MEMBERSHIP#…`) so a\n * `Query(PK = TID#<tenantId>#WORKSPACE#ID#<workspaceId>, SK begins_with 'MEMBERSHIP#')`\n * returns every member projection for the workspace in normalized-\n * user-name sort order.\n */\n record: {\n pk: {\n field: \"PK\",\n composite: [\"tenantId\", \"workspaceId\"],\n template: \"TID#${tenantId}#WORKSPACE#ID#${workspaceId}\",\n },\n sk: {\n field: \"SK\",\n casing: \"none\" as const,\n composite: [\"sk\"],\n template: \"${sk}\",\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 {\n gsi1ShardAttribute,\n roleAssignmentGsi1skAttribute,\n} 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 /**\n * Derived GSI1 sort key — discriminator-first\n * `<roleId>#<normalizedUserName>#<id>` per ADR-018 pattern #8 so a\n * GSI1 query partitioned on the tenant can `begins_with('<roleId>#')`\n * to enumerate every user assigned to a given role, sorted by user\n * name. Falls back to `<lastUpdated>#<id>` when either component is\n * missing.\n */\n gsi1sk: roleAssignmentGsi1skAttribute,\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 * Denormalized display name of the linked Tenant, captured at row\n * last-write time. Promoted to a top-level attribute so the ADR-018\n * adjacency-list user-projection SK (pattern #5 —\n * `ROLEASSIGNMENT#TENANT#<normalizedRoleName>#<roleId>#TID#<tenantId>#<id>`)\n * can be composed from a top-level field instead of digging into the\n * `resource` JSON. Optional on the schema so pre-TR-024 rows do not\n * break; the operations-layer multi-write helper (#1010) makes the\n * field load-bearing at write time per TR-024 rule 2 (write-time\n * source = canonical Tenant.displayName).\n * @see TR-024 — Denormalized display-name attributes\n */\n denormalizedTenantName: {\n type: \"string\" as const,\n required: false,\n },\n /**\n * Denormalized display name of the linked User, captured at row\n * last-write time. Promoted to a top-level attribute so the ADR-018\n * adjacency-list canonical-record GSI1SK (pattern #8 —\n * `<roleId>#<normalizedUserName>#<id>`) and workspace-projection SK\n * (pattern #9) can be composed from a top-level field. Optional on\n * the schema so pre-TR-024 rows do not break; the operations-layer\n * multi-write helper (#1010) makes the field load-bearing at write\n * time per TR-024 rule 2 (write-time source = canonical\n * User.displayName).\n * @see TR-024 — Denormalized display-name attributes\n */\n denormalizedUserName: {\n type: \"string\" as const,\n required: false,\n },\n /**\n * Denormalized display name of the linked Role, captured at row\n * last-write time. Promoted to a top-level attribute so the ADR-018\n * adjacency-list user-projection SK (pattern #5 —\n * `ROLEASSIGNMENT#TENANT#<normalizedRoleName>#…`) can be composed from\n * a top-level field. Optional on the schema so pre-TR-024 rows do not\n * break; the operations-layer multi-write helper (#1010) makes the\n * field load-bearing at write time per TR-024 rule 2 (write-time\n * source = canonical Role.displayName).\n * @see TR-024 — Denormalized display-name attributes\n */\n denormalizedRoleName: {\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 `roleAssignmentGsi1skAttribute` — composes the\n * discriminator-first `<roleId>#<normalizedUserName>#<id>` shape per\n * ADR-018 pattern #8 (users with a specific role in a tenant, sorted\n * by user name); falls back to `<lastUpdated>#<id>` when either\n * component is missing. `casing: \"none\"` preserves the normalized\n * 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\";\n\n/**\n * RoleAssignment user-projection entity (single-table store, no GSI).\n *\n * **ADR-018 adjacency-list projection.** For every RoleAssignment write\n * the operations-layer multi-write helper writes one projection row\n * under the user partition so the user-rooted access pattern #5 is\n * served by a single base-table `Query` with no GSI hop. The SK encodes\n * a tenant-vs-workspace discriminator sub-prefix so both sub-lanes share\n * the user partition:\n *\n * | Sub-lane | When | PK | SK |\n * |---|---|---|---|\n * | tenant-level | `workspaceId` absent | `USER#ID#<userId>` | `ROLEASSIGNMENT#TENANT#<normalizedRoleName>#<roleId>#TID#<tenantId>#<id>` |\n * | workspace-level | `workspaceId` set | `USER#ID#<userId>` | `ROLEASSIGNMENT#WORKSPACE#<normalizedRoleName>#<roleId>#TID#<tenantId>#WID#<workspaceId>#<id>` |\n *\n * The SK shape is operation-owned: the operations-layer projection\n * writer composes the SK string via the\n * `buildRoleAssignmentUserProjectionSk*` helpers and supplies it on the\n * `sk` attribute. This entity stores the SK verbatim — no\n * `watch`/derived computation here — so the SK grammar (and any future\n * revision) lives in one place: the operations layer.\n *\n * Projection attribute set per ADR-018 § Projection attribute set and\n * the implementation guide § 2: `summary`, `vid`, `lastUpdated` (so\n * `Query(PK = USER#ID#<userId>, SK begins_with 'ROLEASSIGNMENT#')` is\n * self-sufficient — no BatchGet hop to the canonical record), plus the\n * projection-discriminating fields (`tenantId`, `roleId`,\n * `roleAssignmentId`, `userId`, `workspaceId?`) and TR-024 denormalized\n * display names (`denormalizedTenantName`, `denormalizedUserName`,\n * `denormalizedRoleName`).\n *\n * **No GSI projection.** Per ADR-018 § Decision, cross-cutting reads\n * are served by the main-table partition `USER#ID#<userId>`; the\n * GSI1/GSI2 catalog is unchanged.\n *\n * @see ADR-018 § Access Pattern Coverage (#5)\n * @see .state/adr-018-implementation-guide.md § 1 (SK grammar) and § 2 (attribute set)\n * @see .claude/rules/data-layer-layout.md — projection writers live in operations, not here\n */\nexport const RoleAssignmentUserProjectionEntity = new Entity({\n model: {\n entity: \"roleAssignmentUserProjection\",\n service: \"control\",\n version: \"01\",\n },\n attributes: {\n /**\n * User partition discriminator. Renders as `USER#ID#<userId>` on the\n * base-table PK. Always required — the projection has no meaning\n * outside a user partition.\n */\n userId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Pre-composed sort key — built by the operations-layer projection\n * writer via `buildRoleAssignmentUserProjectionSk*` helpers. The\n * entity stores the value verbatim so the SK grammar (tenant-lane\n * vs workspace-lane) is owned by the operations layer, not\n * duplicated here.\n */\n sk: {\n type: \"string\" as const,\n required: true,\n },\n /** Tenant in which the role assignment applies. Always required. */\n tenantId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Workspace the role assignment scopes to. Present iff the\n * projection row is the workspace-level sub-lane; absent for\n * tenant-level sub-lane rows.\n */\n workspaceId: {\n type: \"string\" as const,\n required: false,\n },\n /**\n * Role the assignment grants. Stored as a discriminating field so\n * `Query(PK = USER#ID#<userId>, SK begins_with 'ROLEASSIGNMENT#…')`\n * results carry the role id without a hop to the canonical row.\n */\n roleId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * RoleAssignment canonical-record id. Stored as a discriminating\n * field so consumers can hydrate the canonical row via\n * `RoleAssignmentEntity.get({ tenantId, id: roleAssignmentId })`\n * when the projection's `summary` is insufficient.\n */\n roleAssignmentId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Summary projection (key display fields as JSON string: id,\n * displayName, status) — mirrored from the canonical RoleAssignment\n * row so user-partition queries do not need a BatchGet hop.\n */\n summary: {\n type: \"string\" as const,\n required: true,\n },\n /** Version id mirrored from the canonical RoleAssignment row. */\n vid: {\n type: \"string\" as const,\n required: true,\n },\n /** Last-updated timestamp mirrored from the canonical RoleAssignment row. */\n lastUpdated: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Denormalized Tenant display name — mirrored from the canonical\n * RoleAssignment row per TR-024 rule 3 (canonical-record symmetry).\n * Optional on the schema because pre-TR-024 rows may not carry a\n * display name; the operations layer falls back gracefully when\n * missing.\n */\n denormalizedTenantName: {\n type: \"string\" as const,\n required: false,\n },\n /**\n * Denormalized User display name — mirrored from the canonical\n * RoleAssignment row per TR-024 rule 3 (canonical-record symmetry).\n * Carried on the projection so consumers can render the user's\n * display name without a hop to the User record.\n */\n denormalizedUserName: {\n type: \"string\" as const,\n required: false,\n },\n /**\n * Denormalized Role display name — required to compose the SK's\n * `<normalizedRoleName>` segment. Optional on the schema (pre-TR-024\n * rows fall back to a sentinel) but expected to be present at write\n * time per TR-024 rule 2 (write-time source =\n * canonical Role.displayName).\n */\n denormalizedRoleName: {\n type: \"string\" as const,\n required: false,\n },\n },\n indexes: {\n /**\n * Base table: PK = USER#ID#\\<userId\\>, SK = operation-supplied. Both\n * sub-lanes (tenant-level and workspace-level) use this same index —\n * the SK string encodes the lane discriminator\n * (`ROLEASSIGNMENT#TENANT#…` vs `ROLEASSIGNMENT#WORKSPACE#…`) so a\n * single `Query(PK = USER#ID#<userId>, SK begins_with 'ROLEASSIGNMENT#')`\n * returns both lanes interleaved.\n */\n record: {\n pk: {\n field: \"PK\",\n composite: [\"userId\"],\n template: \"USER#ID#${userId}\",\n },\n sk: {\n field: \"SK\",\n casing: \"none\" as const,\n composite: [\"sk\"],\n template: \"${sk}\",\n },\n },\n },\n});\n","import { Entity } from \"electrodb\";\n\n/**\n * RoleAssignment workspace-projection entity (single-table store, no GSI).\n *\n * **ADR-018 adjacency-list projection.** For every workspace-scoped\n * RoleAssignment the operations-layer multi-write helper writes one\n * projection row under the workspace partition so the workspace-rooted\n * access pattern #9 is served by a single base-table `Query` with no\n * GSI hop:\n *\n * | Pattern | When | PK | SK |\n * |---|---|---|---|\n * | #9 — users with a specific role in a workspace | `workspaceId` set | `TID#<tenantId>#WORKSPACE#ID#<workspaceId>` | `ROLEASSIGNMENT#<roleId>#<normalizedUserName>#USER#<userId>#<id>` |\n *\n * The SK is **discriminator-first** on the raw `<roleId>` (mirroring the\n * canonical GSI1SK from pattern #8): role id discriminates first so a\n * `begins_with('ROLEASSIGNMENT#<roleId>#')` filter returns every user\n * assigned to that role in the workspace, sorted alphabetically by\n * normalized user name. Omitting the `<roleId>#` segment\n * (`begins_with('ROLEASSIGNMENT#')`) returns every role assignment in\n * the workspace interleaved.\n *\n * The PK co-locates with the canonical Workspace record (`SK = CURRENT`)\n * and the Membership workspace-projection rows (pattern #2) so a single\n * `Query(PK = TID#<tenantId>#WORKSPACE#ID#<workspaceId>)` returns\n * workspace metadata + every member projection + every role-assignment\n * projection in one round trip — the admin workspace-dashboard read shape.\n *\n * The SK shape is operation-owned: the operations-layer projection\n * writer composes the SK string via the\n * `buildRoleAssignmentWorkspaceProjectionSk` helper and supplies it on\n * the `sk` attribute. This entity stores the SK verbatim — no\n * `watch`/derived computation here — so the SK grammar lives in one\n * place: the operations layer.\n *\n * Projection attribute set per ADR-018 § Projection attribute set and\n * the implementation guide § 2: `summary`, `vid`, `lastUpdated` (so\n * `Query(PK = TID#<tenantId>#WORKSPACE#ID#<workspaceId>, SK begins_with 'ROLEASSIGNMENT#')`\n * is self-sufficient — no BatchGet hop to the canonical record), plus\n * the projection-discriminating fields (`tenantId`, `workspaceId`,\n * `roleId`, `roleAssignmentId`, `userId`) and TR-024 denormalized\n * display names (`denormalizedUserName`, `denormalizedRoleName`).\n *\n * **Rename-cascade interaction (TR-023, Phase 6).** The SK uses the\n * raw `<roleId>` (rename-stable) for the discriminator and\n * `<normalizedUserName>` for the secondary sort. A Role rename does NOT\n * rewrite this SK; a User rename DOES (cascaded by the rename pipeline).\n *\n * **No GSI projection.** Per ADR-018 § Decision, cross-cutting reads\n * are served by the main-table partition\n * `TID#<tenantId>#WORKSPACE#ID#<workspaceId>`; the GSI1/GSI2 catalog\n * is unchanged.\n *\n * @see ADR-018 § Access Pattern Coverage (#9)\n * @see .state/adr-018-implementation-guide.md § 1 (SK grammar) and § 2 (attribute set)\n * @see .claude/rules/data-layer-layout.md — projection writers live in operations, not here\n */\nexport const RoleAssignmentWorkspaceProjectionEntity = new Entity({\n model: {\n entity: \"roleAssignmentWorkspaceProjection\",\n service: \"control\",\n version: \"01\",\n },\n attributes: {\n /**\n * Tenant the workspace belongs to. Renders as the leading segment\n * of the base-table PK. Always required — the workspace partition\n * is tenant-scoped per ADR-011.\n */\n tenantId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Workspace partition discriminator. Renders as the trailing\n * segment of the base-table PK\n * (`TID#<tenantId>#WORKSPACE#ID#<workspaceId>`). Always required —\n * the projection has no meaning outside a workspace partition.\n */\n workspaceId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Pre-composed sort key — built by the operations-layer projection\n * writer via `buildRoleAssignmentWorkspaceProjectionSk`. The entity\n * stores the value verbatim so the SK grammar (pattern #9) is\n * owned by the operations layer, not duplicated here.\n */\n sk: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * User the role assignment grants the role to. Stored as a\n * discriminating field so consumers can hydrate the canonical User\n * row via `UserEntity.get({ id: userId, sk: \"CURRENT\" })` when the\n * projection's `summary` is insufficient.\n */\n userId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Role the assignment grants. Stored as a discriminating field —\n * also rendered into the SK as the discriminator-first segment so\n * `begins_with('ROLEASSIGNMENT#<roleId>#')` filters one role.\n */\n roleId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * RoleAssignment canonical-record id. Stored as a discriminating\n * field so consumers can hydrate the canonical row via\n * `RoleAssignmentEntity.get({ tenantId, id: roleAssignmentId })`\n * when the projection's `summary` is insufficient.\n */\n roleAssignmentId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Summary projection (key display fields as JSON string: id,\n * displayName, status) — mirrored from the canonical RoleAssignment\n * row so workspace-partition queries do not need a BatchGet hop.\n */\n summary: {\n type: \"string\" as const,\n required: true,\n },\n /** Version id mirrored from the canonical RoleAssignment row. */\n vid: {\n type: \"string\" as const,\n required: true,\n },\n /** Last-updated timestamp mirrored from the canonical RoleAssignment row. */\n lastUpdated: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Denormalized User display name — required to compose the\n * pattern-#9 SK (`ROLEASSIGNMENT#<roleId>#<normalizedUserName>#…`).\n * Optional on the schema because pre-TR-024 rows may not carry a\n * display name; the operations layer falls back to a sentinel when\n * missing so the SK still has a valid shape. The TR-023 rename-\n * cascade pipeline rewrites the SK on a User rename.\n */\n denormalizedUserName: {\n type: \"string\" as const,\n required: false,\n },\n /**\n * Denormalized Role display name — mirrored from the canonical\n * RoleAssignment row per TR-024 rule 3 (canonical-record symmetry).\n * Carried on the projection so consumers can render the role's\n * display name without a hop to the Role record. Not part of the\n * SK (pattern #9 sorts on `<normalizedUserName>`, not role name) —\n * a Role rename does NOT rewrite this SK.\n */\n denormalizedRoleName: {\n type: \"string\" as const,\n required: false,\n },\n },\n indexes: {\n /**\n * Base table: PK = TID#<tenantId>#WORKSPACE#ID#<workspaceId>,\n * SK = operation-supplied. Pattern #9 uses this index — the SK\n * encodes the entity-type prefix and discriminator-first roleId\n * (`ROLEASSIGNMENT#<roleId>#…`) so\n * `Query(PK = TID#<tenantId>#WORKSPACE#ID#<workspaceId>, SK begins_with 'ROLEASSIGNMENT#<roleId>#')`\n * returns every user-assignment for that role in the workspace, sorted\n * by normalized user name.\n */\n record: {\n pk: {\n field: \"PK\",\n composite: [\"tenantId\", \"workspaceId\"],\n template: \"TID#${tenantId}#WORKSPACE#ID#${workspaceId}\",\n },\n sk: {\n field: \"SK\",\n casing: \"none\" as const,\n composite: [\"sk\"],\n template: \"${sk}\",\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 /**\n * TR-022 / ADR-018 lifecycle state for the cascade pipeline.\n *\n * - `active` (or undefined) — normal, readable state.\n * - `deleting` — intermediate state set synchronously by the\n * hard-delete API entry point. The owning-delete cascade state\n * machine fans out from this transition (DynamoDB stream →\n * `control-plane.owning-delete.v1` → Step Functions). Readers MUST\n * short-circuit on `deleting` so partial cascades stay invisible.\n * - `deleted-failed` — terminal failure state set by the cascade\n * finalize Lambda when the cascade run fails irrecoverably.\n * Operators recover by re-running the cascade or by direct\n * intervention.\n *\n * The cascade finalize step deletes the canonical record conditional\n * on `lifecycleState = \"deleting\"`; on replay the conditional check\n * fails and the finalize step treats that as a no-op success.\n */\n lifecycleState: {\n type: [\"active\", \"deleting\", \"deleted-failed\"] 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 /**\n * TR-022 / ADR-018 lifecycle state for the cascade pipeline.\n *\n * - `active` (or undefined) — normal, readable state.\n * - `deleting` — intermediate state set synchronously by the\n * hard-delete API entry point. The owning-delete cascade state\n * machine fans out from this transition (DynamoDB stream →\n * `control-plane.owning-delete.v1` → Step Functions). Readers MUST\n * short-circuit on `deleting` so partial cascades stay invisible.\n * - `deleted-failed` — terminal failure state set by the cascade\n * finalize Lambda when the cascade run fails irrecoverably.\n * Operators recover by re-running the cascade or by direct\n * intervention.\n *\n * The cascade finalize step deletes the canonical record conditional\n * on `lifecycleState = \"deleting\"`; on replay the conditional check\n * fails and the finalize step treats that as a no-op success.\n */\n lifecycleState: {\n type: [\"active\", \"deleting\", \"deleted-failed\"] 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","/**\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/** Thrown when the caller is authenticated but not authorized for the requested action. */\nexport class ForbiddenError extends DomainError {\n constructor(\n message: string,\n options?: { cause?: unknown; details?: unknown },\n ) {\n super(message, \"FORBIDDEN\", 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 if (err instanceof ForbiddenError) return 403;\n return null;\n}\n","import {\n assertLinkedDataIdentityCardinality,\n extractSummary,\n type Extension,\n type FhirResourceLike,\n LinkedDataIdentityCardinalityError,\n} from \"@openhi/types\";\nimport {\n buildMembershipUserProjectionItem,\n extractReferenceSlug,\n} from \"./membership-user-projection\";\nimport { buildMembershipWorkspaceProjectionItem } from \"./membership-workspace-projection\";\nimport { getDynamoControlService } from \"../../../dynamo/dynamo-control-service\";\nimport { ValidationError } from \"../../../errors\";\nimport { OpenHiContext } from \"../../../openhi-context\";\nimport { extractDenormalizedReferenceDisplay } from \"../denormalized-display-names\";\nimport { assertWorkspaceInTenantOperation } from \"../membership-constraints/assert-workspace-in-tenant-operation\";\nimport {\n executeMultiWrite,\n type MultiWriteTriple,\n} from \"../multi-write-operation\";\n\nexport interface MembershipCreateParams {\n context: OpenHiContext;\n body: { id?: string; resource?: Record<string, unknown> | string };\n tableName?: string;\n}\n\nexport interface MembershipCreateResult {\n id: string;\n resource: { resourceType: string; id: string; [key: string]: unknown };\n meta: { lastUpdated: string; versionId: string };\n}\n\nexport async function createMembershipOperation(\n params: MembershipCreateParams,\n): Promise<MembershipCreateResult> {\n const { context, body, tableName } = params;\n const service = getDynamoControlService(tableName);\n\n const id = body.id ?? `membership-${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: \"Membership\", id, ...parsedResource };\n\n let linkedDataIdentityRef: string | undefined;\n try {\n const ext = assertLinkedDataIdentityCardinality(\n resource as { extension?: Array<Extension> },\n );\n linkedDataIdentityRef = ext?.valueReference?.reference;\n } catch (e) {\n if (e instanceof LinkedDataIdentityCardinalityError) {\n throw new ValidationError(e.message, { cause: e });\n }\n throw e;\n }\n\n // TR-024 denormalized display-name attributes. The authoritative\n // write-time source per TR-024 rule 2 is the canonical Tenant / User\n // record's `displayName`. Until the carrier-record-lookup pass lands\n // (#1010 follow-up), the foundational fallback (#1009) reads the\n // FHIR Reference.display values supplied on the resource so the\n // adjacency-list projection writer here can compose SKs from\n // top-level attributes.\n const resourceRecord = resource as Record<string, unknown>;\n const denormalizedTenantName = extractDenormalizedReferenceDisplay(\n resourceRecord,\n \"tenant\",\n );\n const denormalizedUserName = extractDenormalizedReferenceDisplay(\n resourceRecord,\n \"user\",\n );\n const denormalizedWorkspaceName = extractDenormalizedReferenceDisplay(\n resourceRecord,\n \"workspace\",\n );\n\n const summary = JSON.stringify(extractSummary(resource as FhirResourceLike));\n\n // ADR-018 patterns #2 / #3 / #4 — user- and workspace-partition\n // projection rows. The projection's discriminating fields come from\n // the same FHIR Reference shape the canonical row reads, so the\n // canonical and projection writes always agree on the underlying\n // user / workspace identifiers. Missing identifiers (no user\n // reference at all) skip the user-projection; tenant-scoped\n // Memberships (no workspaceId) skip the workspace-projection — the\n // canonical row still lands either way.\n const userIdFromResource = extractReferenceSlug(resourceRecord, \"user\");\n const workspaceIdFromResource = extractReferenceSlug(\n resourceRecord,\n \"workspace\",\n );\n\n // ADR 2026-03-13-02 § 2 Consequences/Negative — when the resource\n // names a workspace, that workspace must belong to the referenced\n // tenant. Prefer the resource's `tenant.reference` (the issue's\n // \"referenced tenant\" wording) and fall back to the context tenant\n // when the body omits the reference. The check fires before any\n // write so the constraint is enforced atomically with respect to\n // the canonical row.\n if (workspaceIdFromResource !== undefined) {\n const tenantIdFromResource = extractReferenceSlug(resourceRecord, \"tenant\");\n const referencedTenantId = tenantIdFromResource ?? context.tenantId;\n await assertWorkspaceInTenantOperation({\n tenantId: referencedTenantId,\n workspaceId: workspaceIdFromResource,\n tableName,\n });\n }\n\n const userProjectionItem =\n userIdFromResource !== undefined\n ? buildMembershipUserProjectionItem({\n tenantId: context.tenantId,\n userId: userIdFromResource,\n workspaceId: workspaceIdFromResource,\n membershipId: id,\n summary,\n vid,\n lastUpdated,\n denormalizedTenantName,\n denormalizedUserName,\n denormalizedWorkspaceName,\n })\n : undefined;\n\n const workspaceProjectionItem =\n userIdFromResource !== undefined && workspaceIdFromResource !== undefined\n ? buildMembershipWorkspaceProjectionItem({\n tenantId: context.tenantId,\n workspaceId: workspaceIdFromResource,\n userId: userIdFromResource,\n membershipId: id,\n summary,\n vid,\n lastUpdated,\n denormalizedUserName,\n })\n : undefined;\n\n const canonicalItem = {\n tenantId: context.tenantId,\n id,\n resource: JSON.stringify(resource),\n summary,\n vid,\n lastUpdated,\n linkedDataIdentityRef,\n denormalizedTenantName,\n denormalizedUserName,\n };\n\n const triples: Array<MultiWriteTriple> = [\n { entity: \"membership\", action: \"put\", item: canonicalItem },\n ];\n if (userProjectionItem) {\n triples.push({\n entity: \"membershipUserProjection\",\n action: \"put\",\n item: userProjectionItem as unknown as Record<string, unknown>,\n });\n }\n if (workspaceProjectionItem) {\n triples.push({\n entity: \"membershipWorkspaceProjection\",\n action: \"put\",\n item: workspaceProjectionItem as unknown as Record<string, unknown>,\n });\n }\n\n await executeMultiWrite({ service, triples });\n\n return {\n id,\n resource,\n meta: { lastUpdated, versionId: vid },\n };\n}\n","/**\n * Membership user-projection composer.\n *\n * Owns the SK grammar for ADR-018 patterns #3 and #4 and assembles the\n * projection-row payloads consumed by the membership create / update /\n * delete operations. The {@link MembershipUserProjectionEntity} stores\n * the SK verbatim — the grammar lives here so the operations layer is\n * the single source of truth for projection-row shape (per\n * `.claude/rules/data-layer-layout.md`).\n *\n * SK grammar:\n *\n * - **Pattern #3** (tenant sub-lane, `workspaceId` absent):\n * `MEMBERSHIP#TENANT#<normalizedTenantName>#TID#<tenantId>#<membershipId>`\n * - **Pattern #4** (workspace sub-lane, `workspaceId` set):\n * `MEMBERSHIP#WORKSPACE#TID#<tenantId>#<normalizedWorkspaceName>#WID#<workspaceId>#<membershipId>`\n *\n * Both patterns share the user partition `PK = USER#ID#<userId>` so\n * `Query(PK = USER#ID#<userId>, SK begins_with 'MEMBERSHIP#')` returns\n * both lanes interleaved.\n *\n * @see ADR-018 § Access Pattern Coverage (patterns #3 and #4)\n * @see .state/adr-018-implementation-guide.md § 1 (SK grammar) and § 2 (attribute set)\n */\n\nimport { normalizeLabel } from \"@openhi/types\";\n\n/**\n * Sentinel rendered into the SK when the source display name is missing\n * or empty. Keeps the SK shape stable so a `begins_with` prefix query\n * still matches the row; the rename-cascade pipeline (TR-023) will\n * rewrite the SK once the carrier display name lands. Matches the\n * `gsi1skAttribute` defensive posture — a missing source field never\n * produces a malformed key.\n */\nconst MISSING_NAME_SENTINEL = \"-\";\n\n/** Inputs to compose a Membership user-projection row. */\nexport interface MembershipUserProjectionInput {\n readonly tenantId: string;\n readonly userId: string;\n readonly workspaceId?: string;\n readonly membershipId: string;\n readonly summary: string;\n readonly vid: string;\n readonly lastUpdated: string;\n readonly denormalizedTenantName?: string;\n readonly denormalizedUserName?: string;\n readonly denormalizedWorkspaceName?: string;\n}\n\n/** A projection-row payload ready for `multi-write` consumption. */\nexport interface MembershipUserProjectionItem {\n readonly userId: string;\n readonly sk: string;\n readonly tenantId: string;\n readonly workspaceId?: string;\n readonly membershipId: string;\n readonly summary: string;\n readonly vid: string;\n readonly lastUpdated: string;\n readonly denormalizedTenantName?: string;\n readonly denormalizedUserName?: string;\n readonly denormalizedWorkspaceName?: string;\n}\n\n/**\n * Compose the SK for ADR-018 pattern #3 (tenant sub-lane). The\n * `<normalizedTenantName>` segment sorts memberships alphabetically by\n * tenant name within the user's partition. Missing `denormalizedTenantName`\n * falls back to {@link MISSING_NAME_SENTINEL} so the SK shape stays valid\n * pre-rename-cascade.\n */\nexport function buildMembershipUserProjectionSkTenantLane(params: {\n readonly tenantId: string;\n readonly membershipId: string;\n readonly denormalizedTenantName?: string;\n}): string {\n const normalizedTenantName =\n typeof params.denormalizedTenantName === \"string\" &&\n params.denormalizedTenantName.length > 0\n ? normalizeLabel(params.denormalizedTenantName)\n : MISSING_NAME_SENTINEL;\n return `MEMBERSHIP#TENANT#${normalizedTenantName}#TID#${params.tenantId}#${params.membershipId}`;\n}\n\n/**\n * Compose the SK for ADR-018 pattern #4 (workspace sub-lane). `tenantId`\n * appears before `<normalizedWorkspaceName>` so a\n * `begins_with('MEMBERSHIP#WORKSPACE#TID#<tenantId>#')` query filters\n * by one tenant. Missing `denormalizedWorkspaceName` falls back to\n * {@link MISSING_NAME_SENTINEL}.\n */\nexport function buildMembershipUserProjectionSkWorkspaceLane(params: {\n readonly tenantId: string;\n readonly workspaceId: string;\n readonly membershipId: string;\n readonly denormalizedWorkspaceName?: string;\n}): string {\n const normalizedWorkspaceName =\n typeof params.denormalizedWorkspaceName === \"string\" &&\n params.denormalizedWorkspaceName.length > 0\n ? normalizeLabel(params.denormalizedWorkspaceName)\n : MISSING_NAME_SENTINEL;\n return `MEMBERSHIP#WORKSPACE#TID#${params.tenantId}#${normalizedWorkspaceName}#WID#${params.workspaceId}#${params.membershipId}`;\n}\n\n/**\n * Builds the projection item for the access lane implied by the input.\n * Pattern #3 when `workspaceId` is absent or empty; pattern #4 otherwise.\n * Returns `undefined` when `userId` is missing — a Membership without a\n * linked user cannot project onto the user partition.\n */\nexport function buildMembershipUserProjectionItem(\n input: MembershipUserProjectionInput,\n): MembershipUserProjectionItem | undefined {\n if (!input.userId || input.userId.length === 0) {\n return undefined;\n }\n const hasWorkspace =\n typeof input.workspaceId === \"string\" && input.workspaceId.length > 0;\n const sk = hasWorkspace\n ? buildMembershipUserProjectionSkWorkspaceLane({\n tenantId: input.tenantId,\n workspaceId: input.workspaceId as string,\n membershipId: input.membershipId,\n denormalizedWorkspaceName: input.denormalizedWorkspaceName,\n })\n : buildMembershipUserProjectionSkTenantLane({\n tenantId: input.tenantId,\n membershipId: input.membershipId,\n denormalizedTenantName: input.denormalizedTenantName,\n });\n return {\n userId: input.userId,\n sk,\n tenantId: input.tenantId,\n workspaceId: hasWorkspace ? input.workspaceId : undefined,\n membershipId: input.membershipId,\n summary: input.summary,\n vid: input.vid,\n lastUpdated: input.lastUpdated,\n denormalizedTenantName: input.denormalizedTenantName,\n denormalizedUserName: input.denormalizedUserName,\n denormalizedWorkspaceName: hasWorkspace\n ? input.denormalizedWorkspaceName\n : undefined,\n };\n}\n\n/**\n * Extracts a FHIR `Reference` slug — the segment after the final `/`.\n * Returns `undefined` when the reference is missing or malformed so\n * callers fall back gracefully (matches the defensive posture in\n * `extractRoleId` / `extractDenormalizedReferenceDisplay`).\n */\nexport function extractReferenceSlug(\n resource: Record<string, unknown>,\n fieldName: string,\n): string | undefined {\n const field = resource[fieldName];\n if (!field || typeof field !== \"object\") {\n return undefined;\n }\n const reference = (field as { reference?: unknown }).reference;\n if (typeof reference !== \"string\" || reference.length === 0) {\n return undefined;\n }\n const slash = reference.lastIndexOf(\"/\");\n const tail = slash >= 0 ? reference.slice(slash + 1) : reference;\n return tail.length > 0 ? tail : undefined;\n}\n","/**\n * Membership workspace-projection composer.\n *\n * Owns the SK grammar for ADR-018 pattern #2 and assembles the\n * projection-row payload consumed by the membership create / update /\n * delete operations. The {@link MembershipWorkspaceProjectionEntity}\n * stores the SK verbatim — the grammar lives here so the operations\n * layer is the single source of truth for projection-row shape (per\n * `.claude/rules/data-layer-layout.md`).\n *\n * SK grammar:\n *\n * - **Pattern #2** (users in a workspace, sorted by user name —\n * workspace-scoped Memberships only):\n * `MEMBERSHIP#<normalizedUserName>#USER#<userId>#<membershipId>`\n *\n * The projection co-locates with the canonical Workspace record under\n * `PK = TID#<tenantId>#WORKSPACE#ID#<workspaceId>` so\n * `Query(PK = TID#<tenantId>#WORKSPACE#ID#<workspaceId>, SK begins_with 'MEMBERSHIP#')`\n * returns workspace metadata + every member projection in one round\n * trip. Tenant-scoped Memberships (no `workspaceId`) skip this\n * projection entirely.\n *\n * @see ADR-018 § Access Pattern Coverage (pattern #2)\n * @see .state/adr-018-implementation-guide.md § 1 (SK grammar) and § 2 (attribute set)\n */\n\nimport { normalizeLabel } from \"@openhi/types\";\n\n/**\n * Sentinel rendered into the SK when the source display name is missing\n * or empty. Keeps the SK shape stable so a `begins_with` prefix query\n * still matches the row; the rename-cascade pipeline (TR-023) will\n * rewrite the SK once the carrier display name lands. Mirrors the\n * sibling user-projection composer's defensive posture — a missing\n * source field never produces a malformed key.\n */\nconst MISSING_NAME_SENTINEL = \"-\";\n\n/** Inputs to compose a Membership workspace-projection row. */\nexport interface MembershipWorkspaceProjectionInput {\n readonly tenantId: string;\n readonly workspaceId: string;\n readonly userId: string;\n readonly membershipId: string;\n readonly summary: string;\n readonly vid: string;\n readonly lastUpdated: string;\n readonly denormalizedUserName?: string;\n}\n\n/** A projection-row payload ready for `multi-write` consumption. */\nexport interface MembershipWorkspaceProjectionItem {\n readonly tenantId: string;\n readonly workspaceId: string;\n readonly sk: string;\n readonly userId: string;\n readonly membershipId: string;\n readonly summary: string;\n readonly vid: string;\n readonly lastUpdated: string;\n readonly denormalizedUserName?: string;\n}\n\n/**\n * Compose the SK for ADR-018 pattern #2. The `<normalizedUserName>`\n * segment sorts memberships alphabetically by user name within the\n * workspace partition. The trailing `USER#<userId>#<membershipId>`\n * disambiguates rows when two memberships share a normalized user name\n * (homonyms) and supports a per-user lookup via\n * `begins_with('MEMBERSHIP#<normalizedUserName>#USER#<userId>#')`.\n * Missing `denormalizedUserName` falls back to\n * {@link MISSING_NAME_SENTINEL} so the SK shape stays valid\n * pre-rename-cascade.\n */\nexport function buildMembershipWorkspaceProjectionSk(params: {\n readonly userId: string;\n readonly membershipId: string;\n readonly denormalizedUserName?: string;\n}): string {\n const normalizedUserName =\n typeof params.denormalizedUserName === \"string\" &&\n params.denormalizedUserName.length > 0\n ? normalizeLabel(params.denormalizedUserName)\n : MISSING_NAME_SENTINEL;\n return `MEMBERSHIP#${normalizedUserName}#USER#${params.userId}#${params.membershipId}`;\n}\n\n/**\n * Builds the projection item for a workspace-scoped Membership.\n * Returns `undefined` when `workspaceId` or `userId` is missing —\n * tenant-scoped Memberships (no workspaceId) skip the workspace\n * projection entirely, and a Membership without a linked user cannot\n * project onto the workspace partition.\n */\nexport function buildMembershipWorkspaceProjectionItem(\n input: MembershipWorkspaceProjectionInput,\n): MembershipWorkspaceProjectionItem | undefined {\n if (!input.workspaceId || input.workspaceId.length === 0) {\n return undefined;\n }\n if (!input.userId || input.userId.length === 0) {\n return undefined;\n }\n const sk = buildMembershipWorkspaceProjectionSk({\n userId: input.userId,\n membershipId: input.membershipId,\n denormalizedUserName: input.denormalizedUserName,\n });\n return {\n tenantId: input.tenantId,\n workspaceId: input.workspaceId,\n sk,\n userId: input.userId,\n membershipId: input.membershipId,\n summary: input.summary,\n vid: input.vid,\n lastUpdated: input.lastUpdated,\n denormalizedUserName: input.denormalizedUserName,\n };\n}\n","/**\n * Helpers that capture denormalized display-name attributes from an\n * incoming FHIR Reference on Membership and RoleAssignment resources.\n *\n * **Foundational implementation for TR-024.** ADR-018 § Implementation\n * Notes and TR-024 § Recommendation pin the authoritative write-time\n * source as the carrier entity's canonical `displayName` — i.e. the\n * operations layer reads the canonical Tenant / User / Role record\n * by id and copies its display name into the relationship's\n * `denormalized<CarrierEntity>Name` field on the same\n * `TransactWriteItems`. That contract is owned by the operations-layer\n * multi-write helper filed as #1010.\n *\n * This module is the **foundational fallback** that issue #1009 uses\n * before #1010 lands: it reads the display string a client already\n * supplies on the resource's `Reference.display` field. The fallback\n * keeps Membership / RoleAssignment write paths populating the new\n * top-level attributes today (so adjacency-list projection writers\n * downstream can rely on them) while letting #1010 own the canonical-\n * row lookup without re-plumbing the write paths.\n *\n * @see TR-024 — Denormalized display-name attributes\n * @see ADR-018 § Implementation Notes\n */\n\n/**\n * Returns the trimmed display string from `resource[fieldName].display`\n * when present and non-empty; otherwise returns `undefined`. Used by the\n * Membership and RoleAssignment create / update operations to populate\n * top-level `denormalized<CarrierEntity>Name` attributes from incoming\n * FHIR Reference fields.\n *\n * Field name maps to the FHIR field on the resource:\n * - `Membership.tenant` → `\"tenant\"`\n * - `Membership.user` → `\"user\"`\n * - `RoleAssignment.tenant` → `\"tenant\"`\n * - `RoleAssignment.user` → `\"user\"`\n * - `RoleAssignment.role` → `\"role\"`\n *\n * Guards against malformed payloads (non-object `field`, non-string\n * `display`, empty strings after trim) so a single bad write never\n * blocks an entity put — matching the same defensive posture\n * `gsi1skAttribute` takes for the `resource` JSON parse.\n */\nexport function extractDenormalizedReferenceDisplay(\n resource: Record<string, unknown>,\n fieldName: string,\n): string | undefined {\n const field = resource[fieldName];\n if (!field || typeof field !== \"object\") {\n return undefined;\n }\n const display = (field as { display?: unknown }).display;\n if (typeof display !== \"string\") {\n return undefined;\n }\n const trimmed = display.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n","import { getDynamoControlService } from \"../../../dynamo/dynamo-control-service\";\nimport { ConflictError } from \"../../../errors\";\n\n/** Inputs to {@link assertWorkspaceInTenantOperation}. */\nexport interface AssertWorkspaceInTenantParams {\n /** Tenant the workspace must belong to. */\n readonly tenantId: string;\n /** Workspace id that must exist under `tenantId`. */\n readonly workspaceId: string;\n /** Optional table-name override; resolved via env when omitted. */\n readonly tableName?: string;\n}\n\n/**\n * Throws {@link ConflictError} when no `Workspace` with id `workspaceId`\n * exists under `tenantId`.\n *\n * Implementation: a single base-table `get` against the Workspace entity\n * (`PK = TID#<tenantId>#WORKSPACE#ID#<workspaceId>, SK = CURRENT`). The\n * workspace's tenant is encoded into the PK by construction, so a hit\n * *is* the constraint check — there is no separate `managingOrganization`\n * comparison required.\n *\n * @see ADR 2026-03-13-02 § 2 — Consequences/Negative\n */\nexport async function assertWorkspaceInTenantOperation(\n params: AssertWorkspaceInTenantParams,\n): Promise<void> {\n const { tenantId, workspaceId, tableName } = params;\n const service = getDynamoControlService(tableName);\n\n const { data: item } = await service.entities.workspace\n .get({ tenantId, id: workspaceId, sk: \"CURRENT\" })\n .go();\n\n if (!item) {\n throw new ConflictError(\n `Workspace ${workspaceId} does not belong to tenant ${tenantId}; the workspace must be created in the referenced tenant before this resource can reference it.`,\n { details: { tenantId, workspaceId } },\n );\n }\n}\n","/**\n * Operations-layer multi-write helper for the control plane.\n *\n * Per ADR-018 § Implementation Notes and the ADR-018 implementation\n * guide § 3, every cross-entity mutation in the control plane (canonical\n * record + adjacency-list projections) MUST flow through this helper.\n * Lambda handlers call operations; operations call this helper; nothing\n * under `data/operations/control/` may call `service.transaction.write`\n * directly after #1010 lands.\n *\n * The helper accepts an array of `{ entity, action, item }` triples,\n * maps each one to ElectroDB's transaction-write builder, and submits\n * the batch via `TransactWriteItems` — all-or-nothing atomicity. It\n * enforces the 100-item DynamoDB transaction ceiling at the helper\n * boundary and surfaces conditional-check / transaction-conflict\n * failures as typed domain errors so REST adapters can map to the\n * right HTTP status (409 / 400 / 500).\n *\n * Idempotency belongs to the caller — every call attempts a fresh\n * `TransactWriteItems`. Callers compose conditional expressions\n * (e.g. `vid` matches, `attribute_not_exists(PK)`) per triple via\n * ElectroDB's `where` builder; the helper does not invent conditions.\n *\n * Per ADR-018 Open Item Follow-up #2 the implementation uses ElectroDB's\n * `service.transaction.write` rather than a hand-rolled\n * `TransactWriteItemsCommand`. Reasons: (a) ElectroDB derives the\n * `TransactWriteItem` payload (Item attributes, GSI keys, watch-driven\n * fields) from the entity schema — hand-rolling would duplicate the\n * watch/derive logic and silently drift on schema changes; (b) it\n * preserves the existing single-write call-site idiom\n * (`service.entities.<x>.put({...}).go()` reads almost identically to\n * `entities.<x>.put({...}).commit()` inside the txn builder), keeping\n * the operations layer ergonomic; (c) ElectroDB's `canceled` flag and\n * `ElectroValidationError` propagation give us a single typed handle on\n * cancellation-vs-validation. We can drop to raw `TransactWriteItems`\n * later if a future operation needs DDB features ElectroDB has not yet\n * surfaced.\n *\n * @see ADR-018 § Implementation Notes\n * @see .state/adr-018-implementation-guide.md § 3 — Multi-Write Helper API Contract\n * @see .claude/rules/data-layer-layout.md\n */\n\nimport type { Entity, Service } from \"electrodb\";\nimport { ConflictError, DomainError, ValidationError } from \"../../errors\";\n\n/**\n * Maximum items allowed in a single DynamoDB `TransactWriteItems`\n * call (AWS, raised from 25 → 100 on 2024-09-23). The helper enforces\n * this ceiling at the boundary so callers do not silently lose the\n * tail of an oversized batch when DDB rejects the call.\n */\nexport const TRANSACT_WRITE_ITEM_LIMIT = 100 as const;\n\n/** Supported actions on a multi-write triple. */\nexport type MultiWriteAction = \"put\" | \"create\" | \"delete\";\n\n/**\n * A single entry in a multi-write call: which entity to act on, the\n * action, and the per-action payload.\n *\n * - `put` / `create` — `item` is the full record (matches\n * `entity.put(item)` / `entity.create(item)` shape).\n * - `delete` — `item` is the key composite (matches\n * `entity.delete(key)` shape).\n *\n * `entity` is a string key into the service's `entities` map (e.g.\n * `\"membership\"`, `\"tenant\"`). Using a string key avoids leaking the\n * transaction-bound entity reference across the helper boundary —\n * ElectroDB's `service.transaction.write(fn)` only honours entity\n * references that the closure-provided `entities` argument exposes.\n */\nexport interface MultiWriteTriple<EntityKey extends string = string> {\n readonly entity: EntityKey;\n readonly action: MultiWriteAction;\n readonly item: Record<string, unknown>;\n}\n\n/** A service object exposing the ElectroDB `transaction.write` builder. */\ntype ServiceLike = Pick<\n Service<Record<string, Entity<any, any, any, any>>>,\n \"transaction\"\n>;\n\n/** Parameters for {@link executeMultiWrite}. */\nexport interface ExecuteMultiWriteParams<EntityKey extends string = string> {\n /**\n * ElectroDB `Service` (control-plane or data-plane) exposing\n * `transaction.write` and the entity set the triples reference.\n * Inject via `getDynamoControlService(tableName)` /\n * `getDynamoDataService(tableName)` — matches the service-factory\n * pattern every other operation under `data/operations/` uses.\n */\n readonly service: ServiceLike;\n /**\n * The triples to commit atomically. Order is preserved on the wire\n * (ElectroDB submits them in the same order); duplicates are not\n * de-duplicated by the helper.\n */\n readonly triples: ReadonlyArray<MultiWriteTriple<EntityKey>>;\n /** Optional idempotency token forwarded to ElectroDB. */\n readonly token?: string;\n}\n\n/** Successful multi-write result. */\nexport interface ExecuteMultiWriteResult {\n /** Number of triples committed. */\n readonly itemsWritten: number;\n /**\n * `canceled` flag returned by ElectroDB. Always `false` on the\n * success path — failures throw {@link ConflictError} or\n * {@link ValidationError}. Surfaced for completeness so callers can\n * assert on it in tests if they wish.\n */\n readonly canceled: false;\n}\n\n/**\n * Submits `triples` as a single `TransactWriteItems` via ElectroDB's\n * `service.transaction.write` builder. All-or-nothing: every triple\n * lands or none does.\n *\n * Throws:\n * - {@link ValidationError} when `triples` is empty, exceeds the\n * {@link TRANSACT_WRITE_ITEM_LIMIT}, references an entity that the\n * service does not expose, or carries an unsupported `action`.\n * - {@link ConflictError} when DynamoDB cancels the transaction\n * (e.g. `ConditionalCheckFailed`, `TransactionConflict`,\n * `ProvisionedThroughputExceeded`). The original ElectroDB error\n * (carrying `CancellationReasons`) is attached as `cause`.\n * - The original {@link DomainError} on rethrow if the caller's own\n * validation hook surfaces one (e.g. nested ValidationError).\n *\n * Note on `update` / `patch` actions: not yet supported by the triple\n * shape because ElectroDB's transaction-write builder structures them\n * as `entity.update(key).set({...}).commit()` (key + delta), which\n * does not flatten cleanly into a single `item` payload. Add a\n * separate triple variant when the first consumer needs it; today\n * every ADR-018 multi-write is a `put` (canonical + projections) or a\n * `delete` (cascade rewriter). See ADR-018 § Open Item Follow-up #2.\n */\nexport async function executeMultiWrite<EntityKey extends string = string>(\n params: ExecuteMultiWriteParams<EntityKey>,\n): Promise<ExecuteMultiWriteResult> {\n const { service, triples, token } = params;\n\n if (triples.length === 0) {\n throw new ValidationError(\n \"executeMultiWrite called with zero triples; at least one triple is required\",\n );\n }\n if (triples.length > TRANSACT_WRITE_ITEM_LIMIT) {\n throw new ValidationError(\n `executeMultiWrite received ${triples.length} triples; DynamoDB TransactWriteItems is limited to ${TRANSACT_WRITE_ITEM_LIMIT} items per call`,\n {\n details: {\n itemsRequested: triples.length,\n limit: TRANSACT_WRITE_ITEM_LIMIT,\n },\n },\n );\n }\n\n for (const [index, triple] of triples.entries()) {\n if (!triple || typeof triple !== \"object\") {\n throw new ValidationError(\n `executeMultiWrite triple at index ${index} is not an object`,\n );\n }\n if (typeof triple.entity !== \"string\" || triple.entity.length === 0) {\n throw new ValidationError(\n `executeMultiWrite triple at index ${index} is missing a non-empty 'entity' key`,\n );\n }\n if (!isSupportedAction(triple.action)) {\n throw new ValidationError(\n `executeMultiWrite triple at index ${index} has unsupported action '${String(\n triple.action,\n )}'; supported: 'put' | 'create' | 'delete'`,\n );\n }\n if (!triple.item || typeof triple.item !== \"object\") {\n throw new ValidationError(\n `executeMultiWrite triple at index ${index} is missing an 'item' payload`,\n );\n }\n }\n\n let result: { canceled: boolean; data: unknown };\n try {\n result = await service.transaction\n .write((entities: Record<string, any>) =>\n triples.map((triple, index) => {\n const transactEntity = entities[triple.entity];\n if (transactEntity === undefined) {\n throw new ValidationError(\n `executeMultiWrite triple at index ${index} references unknown entity '${triple.entity}'; ensure the service exposes it`,\n );\n }\n switch (triple.action) {\n case \"put\":\n return transactEntity.put(triple.item).commit();\n case \"create\":\n return transactEntity.create(triple.item).commit();\n case \"delete\":\n return transactEntity.delete(triple.item).commit();\n default:\n // Exhaustiveness guard; pre-flight validates this already.\n throw new ValidationError(\n `executeMultiWrite triple at index ${index} has unsupported action '${String(\n (triple as MultiWriteTriple).action,\n )}'`,\n );\n }\n }),\n )\n .go(token === undefined ? undefined : { token });\n } catch (err) {\n // Pre-flight ValidationErrors thrown inside the builder bubble\n // through unchanged so callers see a 400, not a 409.\n if (err instanceof DomainError) {\n throw err;\n }\n throw new ConflictError(buildCancellationMessage(err), {\n cause: err,\n details: extractCancellationReasons(err),\n });\n }\n\n if (result.canceled) {\n throw new ConflictError(\n \"TransactWriteItems was canceled by DynamoDB (check CancellationReasons on the cause for details)\",\n { details: { canceled: true, data: result.data } },\n );\n }\n\n return { itemsWritten: triples.length, canceled: false };\n}\n\nfunction isSupportedAction(value: unknown): value is MultiWriteAction {\n return value === \"put\" || value === \"create\" || value === \"delete\";\n}\n\nfunction buildCancellationMessage(err: unknown): string {\n if (err instanceof Error && err.message) {\n return `TransactWriteItems failed: ${err.message}`;\n }\n return \"TransactWriteItems failed (no error message available)\";\n}\n\nfunction extractCancellationReasons(err: unknown): unknown {\n if (err && typeof err === \"object\") {\n const cancellationReasons = (err as { CancellationReasons?: unknown })\n .CancellationReasons;\n if (cancellationReasons !== undefined) {\n return { CancellationReasons: cancellationReasons };\n }\n }\n return undefined;\n}\n","import { getDynamoControlService } from \"../../../dynamo/dynamo-control-service\";\nimport { NotFoundError } from \"../../../errors\";\nimport { OpenHiContext } from \"../../../openhi-context\";\n\nexport interface RoleGetByIdParams {\n context: OpenHiContext;\n id: string;\n tableName?: string;\n}\n\nexport interface RoleGetByIdResult {\n id: string;\n resource: { resourceType: string; id: string; [key: string]: unknown };\n}\n\nexport async function getRoleByIdOperation(\n params: RoleGetByIdParams,\n): Promise<RoleGetByIdResult> {\n const { id, tableName } = params;\n const service = getDynamoControlService(tableName);\n\n const response = await service.entities.role.get({ id, sk: \"CURRENT\" }).go();\n\n const item = response.data;\n if (!item) {\n throw new NotFoundError(`Role not found: ${id}`);\n }\n\n const parsedResource = JSON.parse(item.resource) as Record<string, unknown>;\n\n return {\n id,\n resource: { resourceType: \"Role\", id, ...parsedResource },\n };\n}\n","import { extractSummary, type FhirResourceLike } from \"@openhi/types\";\nimport {\n buildRoleAssignmentUserProjectionItem,\n extractReferenceSlug,\n} from \"./roleassignment-user-projection\";\nimport { buildRoleAssignmentWorkspaceProjectionItem } from \"./roleassignment-workspace-projection\";\nimport { getDynamoControlService } from \"../../../dynamo/dynamo-control-service\";\nimport { OpenHiContext } from \"../../../openhi-context\";\nimport { extractDenormalizedReferenceDisplay } from \"../denormalized-display-names\";\nimport { assertUserHasTenantMembershipOperation } from \"../membership-constraints/assert-user-has-tenant-membership-operation\";\nimport { assertWorkspaceInTenantOperation } from \"../membership-constraints/assert-workspace-in-tenant-operation\";\nimport {\n executeMultiWrite,\n type MultiWriteTriple,\n} from \"../multi-write-operation\";\n\nexport interface RoleAssignmentCreateParams {\n context: OpenHiContext;\n body: { id?: string; resource?: Record<string, unknown> | string };\n tableName?: string;\n}\n\nexport interface RoleAssignmentCreateResult {\n id: string;\n resource: { resourceType: string; id: string; [key: string]: unknown };\n meta: { lastUpdated: string; versionId: string };\n}\n\nexport async function createRoleAssignmentOperation(\n params: RoleAssignmentCreateParams,\n): Promise<RoleAssignmentCreateResult> {\n const { context, body, tableName } = params;\n const service = getDynamoControlService(tableName);\n\n const id = body.id ?? `roleassignment-${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: \"RoleAssignment\", id, ...parsedResource };\n\n // TR-024 denormalized display-name attributes. The authoritative\n // write-time source per TR-024 rule 2 is the canonical Tenant / User /\n // Role record's `displayName`. Until the carrier-record-lookup pass\n // lands (#1010 follow-up), the foundational fallback (#1009) reads\n // the FHIR Reference.display values supplied on the resource so the\n // adjacency-list projection writer here can compose SKs from\n // top-level attributes.\n const resourceRecord = resource as Record<string, unknown>;\n const denormalizedTenantName = extractDenormalizedReferenceDisplay(\n resourceRecord,\n \"tenant\",\n );\n const denormalizedUserName = extractDenormalizedReferenceDisplay(\n resourceRecord,\n \"user\",\n );\n const denormalizedRoleName = extractDenormalizedReferenceDisplay(\n resourceRecord,\n \"role\",\n );\n\n const summary = JSON.stringify(extractSummary(resource as FhirResourceLike));\n\n // ADR-018 patterns #5 / #9 — user- and workspace-partition projection\n // rows. The projection's discriminating fields come from the same\n // FHIR Reference shape the canonical row reads, so the canonical and\n // projection writes always agree on the underlying user / role /\n // workspace identifiers. Missing user or role references skip the\n // user-projection; tenant-scoped RoleAssignments (no workspaceId)\n // skip the workspace-projection — the canonical row still lands\n // either way.\n const userIdFromResource = extractReferenceSlug(resourceRecord, \"user\");\n const roleIdFromResource = extractReferenceSlug(resourceRecord, \"role\");\n const workspaceIdFromResource = extractReferenceSlug(\n resourceRecord,\n \"workspace\",\n );\n\n // ADR 2026-03-13-02 § 2 Consequences/Negative — a RoleAssignment may\n // only be created when the referenced user already holds a\n // tenant-level Membership in the referenced tenant, and (when\n // workspace-scoped) that workspace must belong to the same tenant.\n // Prefer the resource's `tenant.reference` (the issue's \"referenced\n // tenant\" wording) and fall back to the context tenant when the\n // body omits the reference. Constraints fire before any write so\n // the rejection is atomic with respect to the canonical row.\n if (userIdFromResource !== undefined) {\n const tenantIdFromResource = extractReferenceSlug(resourceRecord, \"tenant\");\n const referencedTenantId = tenantIdFromResource ?? context.tenantId;\n await assertUserHasTenantMembershipOperation({\n userId: userIdFromResource,\n tenantId: referencedTenantId,\n tableName,\n });\n if (workspaceIdFromResource !== undefined) {\n await assertWorkspaceInTenantOperation({\n tenantId: referencedTenantId,\n workspaceId: workspaceIdFromResource,\n tableName,\n });\n }\n }\n\n const userProjectionItem =\n userIdFromResource !== undefined && roleIdFromResource !== undefined\n ? buildRoleAssignmentUserProjectionItem({\n tenantId: context.tenantId,\n userId: userIdFromResource,\n workspaceId: workspaceIdFromResource,\n roleId: roleIdFromResource,\n roleAssignmentId: id,\n summary,\n vid,\n lastUpdated,\n denormalizedTenantName,\n denormalizedUserName,\n denormalizedRoleName,\n })\n : undefined;\n\n const workspaceProjectionItem =\n userIdFromResource !== undefined &&\n roleIdFromResource !== undefined &&\n workspaceIdFromResource !== undefined\n ? buildRoleAssignmentWorkspaceProjectionItem({\n tenantId: context.tenantId,\n workspaceId: workspaceIdFromResource,\n userId: userIdFromResource,\n roleId: roleIdFromResource,\n roleAssignmentId: id,\n summary,\n vid,\n lastUpdated,\n denormalizedUserName,\n denormalizedRoleName,\n })\n : undefined;\n\n const canonicalItem = {\n tenantId: context.tenantId,\n id,\n resource: JSON.stringify(resource),\n summary,\n vid,\n lastUpdated,\n denormalizedTenantName,\n denormalizedUserName,\n denormalizedRoleName,\n };\n\n const triples: Array<MultiWriteTriple> = [\n { entity: \"roleAssignment\", action: \"put\", item: canonicalItem },\n ];\n if (userProjectionItem) {\n triples.push({\n entity: \"roleAssignmentUserProjection\",\n action: \"put\",\n item: userProjectionItem as unknown as Record<string, unknown>,\n });\n }\n if (workspaceProjectionItem) {\n triples.push({\n entity: \"roleAssignmentWorkspaceProjection\",\n action: \"put\",\n item: workspaceProjectionItem as unknown as Record<string, unknown>,\n });\n }\n\n await executeMultiWrite({ service, triples });\n\n return {\n id,\n resource,\n meta: { lastUpdated, versionId: vid },\n };\n}\n","/**\n * RoleAssignment user-projection composer.\n *\n * Owns the SK grammar for ADR-018 pattern #5 and assembles the\n * projection-row payload consumed by the role-assignment create /\n * update / delete operations. The\n * {@link RoleAssignmentUserProjectionEntity} stores the SK verbatim —\n * the grammar lives here so the operations layer is the single source\n * of truth for projection-row shape (per\n * `.claude/rules/data-layer-layout.md`).\n *\n * SK grammar:\n *\n * - **tenant-level sub-lane** (`workspaceId` absent):\n * `ROLEASSIGNMENT#TENANT#<normalizedRoleName>#<roleId>#TID#<tenantId>#<roleAssignmentId>`\n * - **workspace-level sub-lane** (`workspaceId` set):\n * `ROLEASSIGNMENT#WORKSPACE#<normalizedRoleName>#<roleId>#TID#<tenantId>#WID#<workspaceId>#<roleAssignmentId>`\n *\n * Both sub-lanes share the user partition `PK = USER#ID#<userId>` so\n * `Query(PK = USER#ID#<userId>, SK begins_with 'ROLEASSIGNMENT#')`\n * returns both sub-lanes interleaved with TENANT preceding WORKSPACE\n * lexicographically.\n *\n * @see ADR-018 § Access Pattern Coverage (pattern #5)\n * @see .state/adr-018-implementation-guide.md § 1 (SK grammar) and § 2 (attribute set)\n */\n\nimport { normalizeLabel } from \"@openhi/types\";\n\n/**\n * Sentinel rendered into the SK when the source display name is missing\n * or empty. Keeps the SK shape stable so a `begins_with` prefix query\n * still matches the row; the rename-cascade pipeline (TR-023) will\n * rewrite the SK once the carrier display name lands. Matches the\n * defensive posture in `membership-user-projection` — a missing source\n * field never produces a malformed key.\n */\nconst MISSING_NAME_SENTINEL = \"-\";\n\n/** Inputs to compose a RoleAssignment user-projection row. */\nexport interface RoleAssignmentUserProjectionInput {\n readonly tenantId: string;\n readonly userId: string;\n readonly workspaceId?: string;\n readonly roleId: string;\n readonly roleAssignmentId: string;\n readonly summary: string;\n readonly vid: string;\n readonly lastUpdated: string;\n readonly denormalizedTenantName?: string;\n readonly denormalizedUserName?: string;\n readonly denormalizedRoleName?: string;\n}\n\n/** A projection-row payload ready for `multi-write` consumption. */\nexport interface RoleAssignmentUserProjectionItem {\n readonly userId: string;\n readonly sk: string;\n readonly tenantId: string;\n readonly workspaceId?: string;\n readonly roleId: string;\n readonly roleAssignmentId: string;\n readonly summary: string;\n readonly vid: string;\n readonly lastUpdated: string;\n readonly denormalizedTenantName?: string;\n readonly denormalizedUserName?: string;\n readonly denormalizedRoleName?: string;\n}\n\n/**\n * Compose the SK for ADR-018 pattern #5 — tenant-level sub-lane. The\n * `<normalizedRoleName>` segment sorts assignments alphabetically by\n * role name within the user's partition; `<roleId>` discriminates\n * rename-stable. Missing `denormalizedRoleName` falls back to\n * {@link MISSING_NAME_SENTINEL} so the SK shape stays valid\n * pre-rename-cascade.\n */\nexport function buildRoleAssignmentUserProjectionSkTenantLane(params: {\n readonly tenantId: string;\n readonly roleId: string;\n readonly roleAssignmentId: string;\n readonly denormalizedRoleName?: string;\n}): string {\n const normalizedRoleName =\n typeof params.denormalizedRoleName === \"string\" &&\n params.denormalizedRoleName.length > 0\n ? normalizeLabel(params.denormalizedRoleName)\n : MISSING_NAME_SENTINEL;\n return `ROLEASSIGNMENT#TENANT#${normalizedRoleName}#${params.roleId}#TID#${params.tenantId}#${params.roleAssignmentId}`;\n}\n\n/**\n * Compose the SK for ADR-018 pattern #5 — workspace-level sub-lane.\n * Same `<normalizedRoleName>#<roleId>` sort discriminator as the tenant\n * sub-lane; the trailing segments narrow the partition to a single\n * tenant + workspace. Missing `denormalizedRoleName` falls back to\n * {@link MISSING_NAME_SENTINEL}.\n */\nexport function buildRoleAssignmentUserProjectionSkWorkspaceLane(params: {\n readonly tenantId: string;\n readonly workspaceId: string;\n readonly roleId: string;\n readonly roleAssignmentId: string;\n readonly denormalizedRoleName?: string;\n}): string {\n const normalizedRoleName =\n typeof params.denormalizedRoleName === \"string\" &&\n params.denormalizedRoleName.length > 0\n ? normalizeLabel(params.denormalizedRoleName)\n : MISSING_NAME_SENTINEL;\n return `ROLEASSIGNMENT#WORKSPACE#${normalizedRoleName}#${params.roleId}#TID#${params.tenantId}#WID#${params.workspaceId}#${params.roleAssignmentId}`;\n}\n\n/**\n * Builds the projection item for the access lane implied by the input.\n * Tenant-level sub-lane when `workspaceId` is absent or empty;\n * workspace-level sub-lane otherwise. Returns `undefined` when `userId`\n * or `roleId` is missing — without either the projection cannot land\n * under a user partition or be sorted by role name.\n */\nexport function buildRoleAssignmentUserProjectionItem(\n input: RoleAssignmentUserProjectionInput,\n): RoleAssignmentUserProjectionItem | undefined {\n if (!input.userId || input.userId.length === 0) {\n return undefined;\n }\n if (!input.roleId || input.roleId.length === 0) {\n return undefined;\n }\n const hasWorkspace =\n typeof input.workspaceId === \"string\" && input.workspaceId.length > 0;\n const sk = hasWorkspace\n ? buildRoleAssignmentUserProjectionSkWorkspaceLane({\n tenantId: input.tenantId,\n workspaceId: input.workspaceId as string,\n roleId: input.roleId,\n roleAssignmentId: input.roleAssignmentId,\n denormalizedRoleName: input.denormalizedRoleName,\n })\n : buildRoleAssignmentUserProjectionSkTenantLane({\n tenantId: input.tenantId,\n roleId: input.roleId,\n roleAssignmentId: input.roleAssignmentId,\n denormalizedRoleName: input.denormalizedRoleName,\n });\n return {\n userId: input.userId,\n sk,\n tenantId: input.tenantId,\n workspaceId: hasWorkspace ? input.workspaceId : undefined,\n roleId: input.roleId,\n roleAssignmentId: input.roleAssignmentId,\n summary: input.summary,\n vid: input.vid,\n lastUpdated: input.lastUpdated,\n denormalizedTenantName: input.denormalizedTenantName,\n denormalizedUserName: input.denormalizedUserName,\n denormalizedRoleName: input.denormalizedRoleName,\n };\n}\n\n/**\n * Extracts a FHIR `Reference` slug — the segment after the final `/`.\n * Returns `undefined` when the reference is missing or malformed so\n * callers fall back gracefully (matches the defensive posture in\n * `extractRoleId` / `extractDenormalizedReferenceDisplay`).\n */\nexport function extractReferenceSlug(\n resource: Record<string, unknown>,\n fieldName: string,\n): string | undefined {\n const field = resource[fieldName];\n if (!field || typeof field !== \"object\") {\n return undefined;\n }\n const reference = (field as { reference?: unknown }).reference;\n if (typeof reference !== \"string\" || reference.length === 0) {\n return undefined;\n }\n const slash = reference.lastIndexOf(\"/\");\n const tail = slash >= 0 ? reference.slice(slash + 1) : reference;\n return tail.length > 0 ? tail : undefined;\n}\n","/**\n * RoleAssignment workspace-projection composer.\n *\n * Owns the SK grammar for ADR-018 pattern #9 and assembles the\n * projection-row payload consumed by the role-assignment create /\n * update / delete operations. The\n * {@link RoleAssignmentWorkspaceProjectionEntity} stores the SK\n * verbatim — the grammar lives here so the operations layer is the\n * single source of truth for projection-row shape (per\n * `.claude/rules/data-layer-layout.md`).\n *\n * SK grammar:\n *\n * - **Pattern #9** (users with a specific role in a workspace, sorted\n * by user name — workspace-scoped RoleAssignments only):\n * `ROLEASSIGNMENT#<roleId>#<normalizedUserName>#USER#<userId>#<roleAssignmentId>`\n *\n * The SK is **discriminator-first** on the raw `<roleId>` (mirroring\n * the canonical GSI1SK from pattern #8). Role id discriminates first so\n * a `begins_with('ROLEASSIGNMENT#<roleId>#')` filter returns every user\n * assigned to that role in the workspace, sorted alphabetically by\n * normalized user name. The trailing `USER#<userId>#<roleAssignmentId>`\n * disambiguates rows when two assignments share a normalized user name\n * (homonyms) and supports a per-user lookup via\n * `begins_with('ROLEASSIGNMENT#<roleId>#<normalizedUserName>#USER#<userId>#')`.\n *\n * The projection co-locates with the canonical Workspace record (and\n * the Membership workspace-projection rows from pattern #2) under\n * `PK = TID#<tenantId>#WORKSPACE#ID#<workspaceId>` so\n * `Query(PK = TID#<tenantId>#WORKSPACE#ID#<workspaceId>)` returns\n * workspace metadata + every member projection + every role-assignment\n * projection in one round trip. Tenant-scoped RoleAssignments (no\n * `workspaceId`) skip this projection entirely.\n *\n * **Rename-cascade interaction (TR-023, Phase 6).** The SK uses the\n * raw `<roleId>` (rename-stable) for the discriminator and\n * `<normalizedUserName>` for the secondary sort. A Role rename does\n * NOT rewrite this SK; a User rename DOES (cascaded by the rename\n * pipeline).\n *\n * @see ADR-018 § Access Pattern Coverage (pattern #9)\n * @see .state/adr-018-implementation-guide.md § 1 (SK grammar) and § 2 (attribute set)\n */\n\nimport { normalizeLabel } from \"@openhi/types\";\n\n/**\n * Sentinel rendered into the SK when the source user display name is\n * missing or empty. Keeps the SK shape stable so a `begins_with` prefix\n * query still matches the row; the rename-cascade pipeline (TR-023)\n * will rewrite the SK once the carrier display name lands. Mirrors the\n * sibling projection composers' defensive posture — a missing source\n * field never produces a malformed key.\n */\nconst MISSING_NAME_SENTINEL = \"-\";\n\n/** Inputs to compose a RoleAssignment workspace-projection row. */\nexport interface RoleAssignmentWorkspaceProjectionInput {\n readonly tenantId: string;\n readonly workspaceId: string;\n readonly userId: string;\n readonly roleId: string;\n readonly roleAssignmentId: string;\n readonly summary: string;\n readonly vid: string;\n readonly lastUpdated: string;\n readonly denormalizedUserName?: string;\n readonly denormalizedRoleName?: string;\n}\n\n/** A projection-row payload ready for `multi-write` consumption. */\nexport interface RoleAssignmentWorkspaceProjectionItem {\n readonly tenantId: string;\n readonly workspaceId: string;\n readonly sk: string;\n readonly userId: string;\n readonly roleId: string;\n readonly roleAssignmentId: string;\n readonly summary: string;\n readonly vid: string;\n readonly lastUpdated: string;\n readonly denormalizedUserName?: string;\n readonly denormalizedRoleName?: string;\n}\n\n/**\n * Compose the SK for ADR-018 pattern #9. The discriminator-first\n * `<roleId>` segment (raw, NOT normalized — matches the canonical\n * GSI1SK from pattern #8) lets `begins_with('ROLEASSIGNMENT#<roleId>#')`\n * filter one role. The `<normalizedUserName>` segment sorts assignments\n * alphabetically by user name within that role. The trailing\n * `USER#<userId>#<roleAssignmentId>` disambiguates homonyms and\n * supports a per-user lookup via\n * `begins_with('ROLEASSIGNMENT#<roleId>#<normalizedUserName>#USER#<userId>#')`.\n * Missing `denormalizedUserName` falls back to\n * {@link MISSING_NAME_SENTINEL} so the SK shape stays valid\n * pre-rename-cascade.\n */\nexport function buildRoleAssignmentWorkspaceProjectionSk(params: {\n readonly roleId: string;\n readonly userId: string;\n readonly roleAssignmentId: string;\n readonly denormalizedUserName?: string;\n}): string {\n const normalizedUserName =\n typeof params.denormalizedUserName === \"string\" &&\n params.denormalizedUserName.length > 0\n ? normalizeLabel(params.denormalizedUserName)\n : MISSING_NAME_SENTINEL;\n return `ROLEASSIGNMENT#${params.roleId}#${normalizedUserName}#USER#${params.userId}#${params.roleAssignmentId}`;\n}\n\n/**\n * Builds the projection item for a workspace-scoped RoleAssignment.\n * Returns `undefined` when `workspaceId`, `userId`, or `roleId` is\n * missing — tenant-scoped RoleAssignments (no workspaceId) skip the\n * workspace projection entirely; a RoleAssignment without a linked\n * user or role cannot project onto the workspace partition under the\n * pattern-#9 SK shape.\n */\nexport function buildRoleAssignmentWorkspaceProjectionItem(\n input: RoleAssignmentWorkspaceProjectionInput,\n): RoleAssignmentWorkspaceProjectionItem | undefined {\n if (!input.workspaceId || input.workspaceId.length === 0) {\n return undefined;\n }\n if (!input.userId || input.userId.length === 0) {\n return undefined;\n }\n if (!input.roleId || input.roleId.length === 0) {\n return undefined;\n }\n const sk = buildRoleAssignmentWorkspaceProjectionSk({\n roleId: input.roleId,\n userId: input.userId,\n roleAssignmentId: input.roleAssignmentId,\n denormalizedUserName: input.denormalizedUserName,\n });\n return {\n tenantId: input.tenantId,\n workspaceId: input.workspaceId,\n sk,\n userId: input.userId,\n roleId: input.roleId,\n roleAssignmentId: input.roleAssignmentId,\n summary: input.summary,\n vid: input.vid,\n lastUpdated: input.lastUpdated,\n denormalizedUserName: input.denormalizedUserName,\n denormalizedRoleName: input.denormalizedRoleName,\n };\n}\n","import { PLATFORM_SCOPE_TENANT_ID } from \"./platform-scope-tenant-id\";\nimport { getDynamoControlService } from \"../../../dynamo/dynamo-control-service\";\nimport { ConflictError } from \"../../../errors\";\n\n/**\n * SK prefix for the tenant-level Membership sub-lane (ADR-018 pattern #3).\n *\n * Tenant-level Memberships project under the user partition with\n * `SK = MEMBERSHIP#TENANT#<normalizedTenantName>#TID#<tenantId>#<membershipId>`.\n * Because the `<tenantId>` segment appears *after* `<normalizedTenantName>`,\n * a `begins_with` filter cannot narrow to a single tenant — we read every\n * tenant-lane row for the user and filter on the projection-row's\n * `tenantId` attribute in memory.\n */\nconst TENANT_LANE_SK_PREFIX = \"MEMBERSHIP#TENANT#\";\n\n/** Inputs to {@link assertUserHasTenantMembershipOperation}. */\nexport interface AssertUserHasTenantMembershipParams {\n /** The user that must already be a member of `tenantId`. */\n readonly userId: string;\n /** The tenant the user must hold a tenant-level Membership in. */\n readonly tenantId: string;\n /** Optional table-name override; resolved via env when omitted. */\n readonly tableName?: string;\n}\n\n/**\n * Throws {@link ConflictError} when `userId` has no tenant-level\n * `Membership` in `tenantId`.\n *\n * Implementation: queries the ADR-018 user-partition projection\n * (`MembershipUserProjectionEntity`) under\n * `PK = USER#ID#<userId>, SK begins_with 'MEMBERSHIP#TENANT#'` — a single\n * strongly-consistent base-table query with no GSI hop — and filters the\n * returned rows for `tenantId` in memory.\n *\n * The filter cannot be expressed as an additional `begins_with` because\n * the projection SK encodes `<normalizedTenantName>` *before* `<tenantId>`\n * (`MEMBERSHIP#TENANT#<normalizedTenantName>#TID#<tenantId>#<id>`). The\n * scan cost is bounded by the user's tenant-membership fan-out, which is\n * small by construction.\n *\n * @see ADR 2026-03-13-02 § 2 — Consequences/Negative\n * @see ADR-018 § Access Pattern Coverage (pattern #3)\n */\nexport async function assertUserHasTenantMembershipOperation(\n params: AssertUserHasTenantMembershipParams,\n): Promise<void> {\n const { userId, tenantId, tableName } = params;\n\n // The platform-scope sentinel is not a real tenant — it is a\n // reserved `tenantId` value used on platform-scoped RoleAssignments\n // (e.g. `system-admin`). No `Membership` is ever created under it,\n // and a Membership there would have no semantic meaning. Skip the\n // tenant-membership constraint so platform-scoped RAs can be\n // created without requiring an impossible-to-create prerequisite\n // Membership row.\n if (tenantId === PLATFORM_SCOPE_TENANT_ID) {\n return;\n }\n\n const service = getDynamoControlService(tableName);\n\n const result = await service.entities.membershipUserProjection.query\n .record({ userId })\n .begins({ sk: TENANT_LANE_SK_PREFIX })\n .go();\n\n const matched = (result.data ?? []).some((row) => row.tenantId === tenantId);\n if (!matched) {\n throw new ConflictError(\n `User ${userId} has no tenant-level Membership in tenant ${tenantId}; a Membership must exist before a RoleAssignment can be created.`,\n { details: { userId, tenantId } },\n );\n }\n}\n","import { extractSummary, type FhirResourceLike } from \"@openhi/types\";\nimport { getDynamoControlService } from \"../../../dynamo/dynamo-control-service\";\nimport type { OpenHiContext } from \"../../../openhi-context\";\n\nexport interface CreateTenantParams {\n context: OpenHiContext;\n body: {\n id?: string;\n resource?: Record<string, unknown> | string;\n };\n tableName?: string;\n}\n\nexport interface CreateTenantResult {\n id: string;\n resource: Record<string, unknown>;\n meta: { lastUpdated: string; versionId: string };\n}\n\n/**\n * Creates a Tenant. Generates an id if not provided.\n */\nexport async function createTenantOperation(\n params: CreateTenantParams,\n): Promise<CreateTenantResult> {\n const { context, body, tableName } = params;\n const service = getDynamoControlService(tableName);\n\n const id = body.id ?? `tenant-${Date.now()}`;\n const lastUpdated = context.date;\n const vid =\n lastUpdated.replace(/[-:T.Z]/g, \"\").slice(0, 12) || Date.now().toString(36);\n\n const parsedResource =\n typeof body.resource === \"string\"\n ? (JSON.parse(body.resource) as Record<string, unknown>)\n : (body.resource ?? {});\n\n const resource = { resourceType: \"Tenant\", id, ...parsedResource };\n const summary = JSON.stringify(extractSummary(resource as FhirResourceLike));\n\n await service.entities.tenant\n .put({\n tenantId: id,\n id,\n resource: JSON.stringify(resource),\n summary,\n vid,\n lastUpdated,\n })\n .go();\n\n return { id, resource, meta: { lastUpdated, versionId: vid } };\n}\n","import { extractSummary, type FhirResourceLike } from \"@openhi/types\";\nimport { getDynamoControlService } from \"../../../dynamo/dynamo-control-service\";\nimport type { OpenHiContext } from \"../../../openhi-context\";\nimport { provisionOrganizationForWorkspaceOperation } from \"../../data/organization/organization-provision-for-workspace-operation\";\n\nexport interface CreateWorkspaceParams {\n context: OpenHiContext;\n body: {\n id?: string;\n resource?: Record<string, unknown> | string;\n };\n tableName?: string;\n}\n\nexport interface CreateWorkspaceResult {\n id: string;\n resource: Record<string, unknown>;\n meta: { lastUpdated: string; versionId: string };\n}\n\n/**\n * Creates a Workspace scoped to the context tenant. Generates an id if not provided.\n */\nexport async function createWorkspaceOperation(\n params: CreateWorkspaceParams,\n): Promise<CreateWorkspaceResult> {\n const { context, body, tableName } = params;\n const { tenantId } = context;\n const service = getDynamoControlService(tableName);\n\n const id = body.id ?? `workspace-${Date.now()}`;\n const lastUpdated = context.date;\n const vid =\n lastUpdated.replace(/[-:T.Z]/g, \"\").slice(0, 12) || Date.now().toString(36);\n\n const parsedResource =\n typeof body.resource === \"string\"\n ? (JSON.parse(body.resource) as Record<string, unknown>)\n : (body.resource ?? {});\n\n const resource = { resourceType: \"Workspace\", id, ...parsedResource };\n const summary = JSON.stringify(extractSummary(resource as FhirResourceLike));\n\n await service.entities.workspace\n .put({\n tenantId,\n id,\n resource: JSON.stringify(resource),\n summary,\n vid,\n lastUpdated,\n })\n .go();\n\n const workspaceName =\n typeof parsedResource.name === \"string\" ? parsedResource.name : undefined;\n await provisionOrganizationForWorkspaceOperation({\n context,\n workspaceId: id,\n workspaceName,\n tableName,\n });\n\n return { id, resource, meta: { lastUpdated, versionId: vid } };\n}\n","import { Service } from \"electrodb\";\nimport { defaultTableName, dynamoClient } from \"./dynamo-client\";\nimport { AccountEntity } from \"./entities/data/account-entity\";\nimport { ActivityDefinitionEntity } from \"./entities/data/activity-definition-entity\";\nimport { AdverseEventEntity } from \"./entities/data/adverse-event-entity\";\nimport { AllergyIntoleranceEntity } from \"./entities/data/allergy-intolerance-entity\";\nimport { AppointmentEntity } from \"./entities/data/appointment-entity\";\nimport { AppointmentResponseEntity } from \"./entities/data/appointment-response-entity\";\nimport { AuditEventEntity } from \"./entities/data/audit-event-entity\";\nimport { BasicEntity } from \"./entities/data/basic-entity\";\nimport { BiologicallyDerivedProductEntity } from \"./entities/data/biologically-derived-product-entity\";\nimport { BodyStructureEntity } from \"./entities/data/body-structure-entity\";\nimport { CapabilityStatementEntity } from \"./entities/data/capability-statement-entity\";\nimport { CarePlanEntity } from \"./entities/data/care-plan-entity\";\nimport { CareTeamEntity } from \"./entities/data/care-team-entity\";\nimport { CatalogEntryEntity } from \"./entities/data/catalog-entry-entity\";\nimport { ChargeItemDefinitionEntity } from \"./entities/data/charge-item-definition-entity\";\nimport { ChargeItemEntity } from \"./entities/data/charge-item-entity\";\nimport { ClaimEntity } from \"./entities/data/claim-entity\";\nimport { ClaimResponseEntity } from \"./entities/data/claim-response-entity\";\nimport { ClinicalImpressionEntity } from \"./entities/data/clinical-impression-entity\";\nimport { CodeSystemEntity } from \"./entities/data/code-system-entity\";\nimport { CommunicationEntity } from \"./entities/data/communication-entity\";\nimport { CommunicationRequestEntity } from \"./entities/data/communication-request-entity\";\nimport { CompartmentDefinitionEntity } from \"./entities/data/compartment-definition-entity\";\nimport { CompositionEntity } from \"./entities/data/composition-entity\";\nimport { ConceptMapEntity } from \"./entities/data/concept-map-entity\";\nimport { ConditionEntity } from \"./entities/data/condition-entity\";\nimport { ConsentEntity } from \"./entities/data/consent-entity\";\nimport { ContractEntity } from \"./entities/data/contract-entity\";\nimport { CoverageEligibilityRequestEntity } from \"./entities/data/coverage-eligibility-request-entity\";\nimport { CoverageEligibilityResponseEntity } from \"./entities/data/coverage-eligibility-response-entity\";\nimport { CoverageEntity } from \"./entities/data/coverage-entity\";\nimport { DetectedIssueEntity } from \"./entities/data/detected-issue-entity\";\nimport { DeviceDefinitionEntity } from \"./entities/data/device-definition-entity\";\nimport { DeviceEntity } from \"./entities/data/device-entity\";\nimport { DeviceMetricEntity } from \"./entities/data/device-metric-entity\";\nimport { DeviceRequestEntity } from \"./entities/data/device-request-entity\";\nimport { DeviceUseStatementEntity } from \"./entities/data/device-use-statement-entity\";\nimport { DiagnosticReportEntity } from \"./entities/data/diagnostic-report-entity\";\nimport { DocumentManifestEntity } from \"./entities/data/document-manifest-entity\";\nimport { DocumentReferenceEntity } from \"./entities/data/document-reference-entity\";\nimport { EffectEvidenceSynthesisEntity } from \"./entities/data/effect-evidence-synthesis-entity\";\nimport { EncounterEntity } from \"./entities/data/encounter-entity\";\nimport { EndpointEntity } from \"./entities/data/endpoint-entity\";\nimport { EnrollmentRequestEntity } from \"./entities/data/enrollment-request-entity\";\nimport { EnrollmentResponseEntity } from \"./entities/data/enrollment-response-entity\";\nimport { EpisodeOfCareEntity } from \"./entities/data/episode-of-care-entity\";\nimport { EventDefinitionEntity } from \"./entities/data/event-definition-entity\";\nimport { EvidenceEntity } from \"./entities/data/evidence-entity\";\nimport { EvidenceVariableEntity } from \"./entities/data/evidence-variable-entity\";\nimport { ExampleScenarioEntity } from \"./entities/data/example-scenario-entity\";\nimport { ExplanationOfBenefitEntity } from \"./entities/data/explanation-of-benefit-entity\";\nimport { FamilyMemberHistoryEntity } from \"./entities/data/family-member-history-entity\";\nimport { FlagEntity } from \"./entities/data/flag-entity\";\nimport { GoalEntity } from \"./entities/data/goal-entity\";\nimport { GraphDefinitionEntity } from \"./entities/data/graph-definition-entity\";\nimport { GroupEntity } from \"./entities/data/group-entity\";\nimport { GuidanceResponseEntity } from \"./entities/data/guidance-response-entity\";\nimport { HealthcareServiceEntity } from \"./entities/data/healthcare-service-entity\";\nimport { ImagingStudyEntity } from \"./entities/data/imaging-study-entity\";\nimport { ImmunizationEntity } from \"./entities/data/immunization-entity\";\nimport { ImmunizationEvaluationEntity } from \"./entities/data/immunization-evaluation-entity\";\nimport { ImmunizationRecommendationEntity } from \"./entities/data/immunization-recommendation-entity\";\nimport { ImplementationGuideEntity } from \"./entities/data/implementation-guide-entity\";\nimport { InsurancePlanEntity } from \"./entities/data/insurance-plan-entity\";\nimport { InvoiceEntity } from \"./entities/data/invoice-entity\";\nimport { LibraryEntity } from \"./entities/data/library-entity\";\nimport { LinkageEntity } from \"./entities/data/linkage-entity\";\nimport { ListEntity } from \"./entities/data/list-entity\";\nimport { LocationEntity } from \"./entities/data/location-entity\";\nimport { MeasureEntity } from \"./entities/data/measure-entity\";\nimport { MeasureReportEntity } from \"./entities/data/measure-report-entity\";\nimport { MediaEntity } from \"./entities/data/media-entity\";\nimport { MedicationAdministrationEntity } from \"./entities/data/medication-administration-entity\";\nimport { MedicationDispenseEntity } from \"./entities/data/medication-dispense-entity\";\nimport { MedicationEntity } from \"./entities/data/medication-entity\";\nimport { MedicationKnowledgeEntity } from \"./entities/data/medication-knowledge-entity\";\nimport { MedicationRequestEntity } from \"./entities/data/medication-request-entity\";\nimport { MedicationStatementEntity } from \"./entities/data/medication-statement-entity\";\nimport { MedicinalProductAuthorizationEntity } from \"./entities/data/medicinal-product-authorization-entity\";\nimport { MedicinalProductContraindicationEntity } from \"./entities/data/medicinal-product-contraindication-entity\";\nimport { MedicinalProductEntity } from \"./entities/data/medicinal-product-entity\";\nimport { MedicinalProductIndicationEntity } from \"./entities/data/medicinal-product-indication-entity\";\nimport { MedicinalProductIngredientEntity } from \"./entities/data/medicinal-product-ingredient-entity\";\nimport { MedicinalProductInteractionEntity } from \"./entities/data/medicinal-product-interaction-entity\";\nimport { MedicinalProductManufacturedEntity } from \"./entities/data/medicinal-product-manufactured-entity\";\nimport { MedicinalProductPackagedEntity } from \"./entities/data/medicinal-product-packaged-entity\";\nimport { MedicinalProductPharmaceuticalEntity } from \"./entities/data/medicinal-product-pharmaceutical-entity\";\nimport { MedicinalProductUndesirableEffectEntity } from \"./entities/data/medicinal-product-undesirable-effect-entity\";\nimport { MessageDefinitionEntity } from \"./entities/data/message-definition-entity\";\nimport { MessageHeaderEntity } from \"./entities/data/message-header-entity\";\nimport { MolecularSequenceEntity } from \"./entities/data/molecular-sequence-entity\";\nimport { NamingSystemEntity } from \"./entities/data/naming-system-entity\";\nimport { NutritionOrderEntity } from \"./entities/data/nutrition-order-entity\";\nimport { ObservationDefinitionEntity } from \"./entities/data/observation-definition-entity\";\nimport { ObservationEntity } from \"./entities/data/observation-entity\";\nimport { OperationDefinitionEntity } from \"./entities/data/operation-definition-entity\";\nimport { OrganizationAffiliationEntity } from \"./entities/data/organization-affiliation-entity\";\nimport { OrganizationEntity } from \"./entities/data/organization-entity\";\nimport { PatientEntity } from \"./entities/data/patient-entity\";\nimport { PaymentNoticeEntity } from \"./entities/data/payment-notice-entity\";\nimport { PaymentReconciliationEntity } from \"./entities/data/payment-reconciliation-entity\";\nimport { PersonEntity } from \"./entities/data/person-entity\";\nimport { PlanDefinitionEntity } from \"./entities/data/plan-definition-entity\";\nimport { PractitionerEntity } from \"./entities/data/practitioner-entity\";\nimport { PractitionerRoleEntity } from \"./entities/data/practitioner-role-entity\";\nimport { ProcedureEntity } from \"./entities/data/procedure-entity\";\nimport { ProvenanceEntity } from \"./entities/data/provenance-entity\";\nimport { QuestionnaireEntity } from \"./entities/data/questionnaire-entity\";\nimport { QuestionnaireResponseEntity } from \"./entities/data/questionnaire-response-entity\";\nimport { RelatedPersonEntity } from \"./entities/data/related-person-entity\";\nimport { RequestGroupEntity } from \"./entities/data/request-group-entity\";\nimport { ResearchDefinitionEntity } from \"./entities/data/research-definition-entity\";\nimport { ResearchElementDefinitionEntity } from \"./entities/data/research-element-definition-entity\";\nimport { ResearchStudyEntity } from \"./entities/data/research-study-entity\";\nimport { ResearchSubjectEntity } from \"./entities/data/research-subject-entity\";\nimport { RiskAssessmentEntity } from \"./entities/data/risk-assessment-entity\";\nimport { RiskEvidenceSynthesisEntity } from \"./entities/data/risk-evidence-synthesis-entity\";\nimport { ScheduleEntity } from \"./entities/data/schedule-entity\";\nimport { SearchParameterEntity } from \"./entities/data/search-parameter-entity\";\nimport { ServiceRequestEntity } from \"./entities/data/service-request-entity\";\nimport { SlotEntity } from \"./entities/data/slot-entity\";\nimport { SpecimenDefinitionEntity } from \"./entities/data/specimen-definition-entity\";\nimport { SpecimenEntity } from \"./entities/data/specimen-entity\";\nimport { StructureDefinitionEntity } from \"./entities/data/structure-definition-entity\";\nimport { StructureMapEntity } from \"./entities/data/structure-map-entity\";\nimport { SubscriptionEntity } from \"./entities/data/subscription-entity\";\nimport { SubstanceEntity } from \"./entities/data/substance-entity\";\nimport { SubstanceNucleicAcidEntity } from \"./entities/data/substance-nucleic-acid-entity\";\nimport { SubstancePolymerEntity } from \"./entities/data/substance-polymer-entity\";\nimport { SubstanceProteinEntity } from \"./entities/data/substance-protein-entity\";\nimport { SubstanceReferenceInformationEntity } from \"./entities/data/substance-reference-information-entity\";\nimport { SubstanceSourceMaterialEntity } from \"./entities/data/substance-source-material-entity\";\nimport { SubstanceSpecificationEntity } from \"./entities/data/substance-specification-entity\";\nimport { SupplyDeliveryEntity } from \"./entities/data/supply-delivery-entity\";\nimport { SupplyRequestEntity } from \"./entities/data/supply-request-entity\";\nimport { TaskEntity } from \"./entities/data/task-entity\";\nimport { TerminologyCapabilitiesEntity } from \"./entities/data/terminology-capabilities-entity\";\nimport { TestReportEntity } from \"./entities/data/test-report-entity\";\nimport { TestScriptEntity } from \"./entities/data/test-script-entity\";\nimport { ValueSetEntity } from \"./entities/data/value-set-entity\";\nimport { VerificationResultEntity } from \"./entities/data/verification-result-entity\";\nimport { VisionPrescriptionEntity } from \"./entities/data/vision-prescription-entity\";\n\n/**\n * Data-plane entities only (service \"data\"). Same table as control plane; use\n * DynamoControlService for control-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 dataPlaneEntities = {\n account: AccountEntity,\n activitydefinition: ActivityDefinitionEntity,\n adverseevent: AdverseEventEntity,\n allergyintolerance: AllergyIntoleranceEntity,\n appointment: AppointmentEntity,\n appointmentresponse: AppointmentResponseEntity,\n auditevent: AuditEventEntity,\n basic: BasicEntity,\n biologicallyderivedproduct: BiologicallyDerivedProductEntity,\n bodystructure: BodyStructureEntity,\n capabilitystatement: CapabilityStatementEntity,\n careplan: CarePlanEntity,\n careteam: CareTeamEntity,\n catalogentry: CatalogEntryEntity,\n codesystem: CodeSystemEntity,\n chargeitem: ChargeItemEntity,\n chargeitemdefinition: ChargeItemDefinitionEntity,\n claim: ClaimEntity,\n claimresponse: ClaimResponseEntity,\n clinicalimpression: ClinicalImpressionEntity,\n communication: CommunicationEntity,\n communicationrequest: CommunicationRequestEntity,\n compartmentdefinition: CompartmentDefinitionEntity,\n composition: CompositionEntity,\n conceptmap: ConceptMapEntity,\n condition: ConditionEntity,\n consent: ConsentEntity,\n contract: ContractEntity,\n coverage: CoverageEntity,\n coverageeligibilityrequest: CoverageEligibilityRequestEntity,\n coverageeligibilityresponse: CoverageEligibilityResponseEntity,\n detectedissue: DetectedIssueEntity,\n device: DeviceEntity,\n devicedefinition: DeviceDefinitionEntity,\n devicemetric: DeviceMetricEntity,\n devicerequest: DeviceRequestEntity,\n deviceusestatement: DeviceUseStatementEntity,\n diagnosticreport: DiagnosticReportEntity,\n documentmanifest: DocumentManifestEntity,\n documentreference: DocumentReferenceEntity,\n effectevidencesynthesis: EffectEvidenceSynthesisEntity,\n encounter: EncounterEntity,\n examplescenario: ExampleScenarioEntity,\n endpoint: EndpointEntity,\n enrollmentrequest: EnrollmentRequestEntity,\n enrollmentresponse: EnrollmentResponseEntity,\n episodeofcare: EpisodeOfCareEntity,\n eventdefinition: EventDefinitionEntity,\n evidence: EvidenceEntity,\n evidencevariable: EvidenceVariableEntity,\n explanationofbenefit: ExplanationOfBenefitEntity,\n familymemberhistory: FamilyMemberHistoryEntity,\n flag: FlagEntity,\n goal: GoalEntity,\n graphdefinition: GraphDefinitionEntity,\n group: GroupEntity,\n guidanceresponse: GuidanceResponseEntity,\n healthcareservice: HealthcareServiceEntity,\n immunization: ImmunizationEntity,\n immunizationevaluation: ImmunizationEvaluationEntity,\n immunizationrecommendation: ImmunizationRecommendationEntity,\n imagingstudy: ImagingStudyEntity,\n implementationguide: ImplementationGuideEntity,\n insuranceplan: InsurancePlanEntity,\n invoice: InvoiceEntity,\n library: LibraryEntity,\n linkage: LinkageEntity,\n list: ListEntity,\n location: LocationEntity,\n medication: MedicationEntity,\n medicationadministration: MedicationAdministrationEntity,\n medicationdispense: MedicationDispenseEntity,\n medicationknowledge: MedicationKnowledgeEntity,\n medicationrequest: MedicationRequestEntity,\n medicationstatement: MedicationStatementEntity,\n medicinalproduct: MedicinalProductEntity,\n medicinalproductauthorization: MedicinalProductAuthorizationEntity,\n medicinalproductcontraindication: MedicinalProductContraindicationEntity,\n medicinalproductingredient: MedicinalProductIngredientEntity,\n medicinalproductindication: MedicinalProductIndicationEntity,\n medicinalproductinteraction: MedicinalProductInteractionEntity,\n medicinalproductmanufactured: MedicinalProductManufacturedEntity,\n medicinalproductpackaged: MedicinalProductPackagedEntity,\n medicinalproductpharmaceutical: MedicinalProductPharmaceuticalEntity,\n medicinalproductundesirableeffect: MedicinalProductUndesirableEffectEntity,\n media: MediaEntity,\n measure: MeasureEntity,\n measurereport: MeasureReportEntity,\n messagedefinition: MessageDefinitionEntity,\n messageheader: MessageHeaderEntity,\n molecularsequence: MolecularSequenceEntity,\n namingsystem: NamingSystemEntity,\n nutritionorder: NutritionOrderEntity,\n observation: ObservationEntity,\n observationdefinition: ObservationDefinitionEntity,\n operationdefinition: OperationDefinitionEntity,\n organization: OrganizationEntity,\n organizationaffiliation: OrganizationAffiliationEntity,\n patient: PatientEntity,\n paymentnotice: PaymentNoticeEntity,\n paymentreconciliation: PaymentReconciliationEntity,\n person: PersonEntity,\n plandefinition: PlanDefinitionEntity,\n practitioner: PractitionerEntity,\n practitionerrole: PractitionerRoleEntity,\n procedure: ProcedureEntity,\n provenance: ProvenanceEntity,\n questionnaire: QuestionnaireEntity,\n questionnaireresponse: QuestionnaireResponseEntity,\n requestgroup: RequestGroupEntity,\n relatedperson: RelatedPersonEntity,\n researchdefinition: ResearchDefinitionEntity,\n researchelementdefinition: ResearchElementDefinitionEntity,\n researchstudy: ResearchStudyEntity,\n researchsubject: ResearchSubjectEntity,\n riskassessment: RiskAssessmentEntity,\n riskevidencesynthesis: RiskEvidenceSynthesisEntity,\n schedule: ScheduleEntity,\n searchparameter: SearchParameterEntity,\n servicerequest: ServiceRequestEntity,\n specimen: SpecimenEntity,\n specimendefinition: SpecimenDefinitionEntity,\n structuredefinition: StructureDefinitionEntity,\n structuremap: StructureMapEntity,\n substance: SubstanceEntity,\n substancenucleicacid: SubstanceNucleicAcidEntity,\n substancepolymer: SubstancePolymerEntity,\n substanceprotein: SubstanceProteinEntity,\n substancereferenceinformation: SubstanceReferenceInformationEntity,\n substancespecification: SubstanceSpecificationEntity,\n substancesourcematerial: SubstanceSourceMaterialEntity,\n subscription: SubscriptionEntity,\n terminologycapabilities: TerminologyCapabilitiesEntity,\n testreport: TestReportEntity,\n testscript: TestScriptEntity,\n valueset: ValueSetEntity,\n supplydelivery: SupplyDeliveryEntity,\n supplyrequest: SupplyRequestEntity,\n slot: SlotEntity,\n task: TaskEntity,\n visionprescription: VisionPrescriptionEntity,\n verificationresult: VerificationResultEntity,\n};\n\nconst dataPlaneService = new Service(dataPlaneEntities, {\n table: defaultTableName,\n client: dynamoClient,\n});\n\n/**\n * Data-plane service: entities for the data store (FHIR and related). Both data-plane\n * and control-plane entities share the base table (PK, SK) and the unified GSI1 (sharded\n * resource-type list per ADR-011). Same physical table.\n */\nexport const DynamoDataService = {\n entities: dataPlaneService.entities,\n transaction: dataPlaneService.transaction,\n};\n\nexport type DynamoDataServiceType = typeof DynamoDataService;\n\n/**\n * Returns the data-plane service. Table name is resolved from tableName (optional override),\n * then DYNAMO_TABLE_NAME, then \"jesttesttable\".\n */\nexport function getDynamoDataService(\n tableName?: string,\n): DynamoDataServiceType {\n const resolved = tableName ?? defaultTableName;\n const service = new Service(dataPlaneEntities, {\n table: resolved,\n client: dynamoClient,\n });\n return {\n entities: service.entities,\n transaction: service.transaction,\n };\n}\n","import { Entity } from \"electrodb\";\nimport { computeShard } from \"../shard\";\n\n/**\n * Shared attributes for all data-plane FHIR entities (tenant-isolated, single-table store).\n * Used by all data-plane entities (Account, Patient, Encounter, Practitioner, etc.).\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/entity-standards.md\n */\nexport const dataEntityAttributes = {\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 tenantId: {\n type: \"string\" as const,\n required: true,\n },\n workspaceId: {\n type: \"string\" as const,\n required: true,\n },\n /** FHIR Resource.id; logical id in URL and PK. */\n id: {\n type: \"string\" as const,\n required: true,\n },\n /** FHIR resource 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 of the FHIR resource as a JSON string (uncompressed). Populated on every\n * write via `extractSummary(resource)` so GSI projections can surface list/lookup data without\n * reading the compressed `resource` blob. Kept uncompressed because the summary is small and\n * must be fast to retrieve without encode/decode overhead.\n *\n * @see sites/www-docs/content/architecture/adr/2026-04-17-02-fhir-summary-projection-for-gsi-access-patterns.md\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 /**\n * Shard index segment for the GSI1 partition key. Computed deterministically from `id`\n * via `computeShard` so updates always land on the same shard. Stored as a string because\n * it appears as a literal segment in the GSI1 PK template; the underlying value is 0..3.\n * Not `required` because the value is derived via `watch`/`set`; ElectroDB's required-field\n * check runs before watch propagation, so callers must not fail validation on a derived field.\n *\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md — GSI1 (sharded)\n */\n gsi1Shard: {\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 * GSI1 sort key. Written as the index's SK verbatim so list endpoints can\n * use `BEGINS_WITH` for prefix queries (e.g. `?name=Sm` against Patient).\n * Computed at write time via `extractSortKey(resource)` per DR-004:\n * - Labeled types (LABEL_PATHS): `<normalizedLabel>#<id>`\n * - Unlabeled types: `<ISO-8601 lastUpdated>#<id>`\n * The factory deliberately does not derive this from `lastUpdated`/`id`\n * — that would lock every type into the unlabeled fallback and defeat\n * label-based BEGINS_WITH on labeled types.\n *\n * @see openhi-planning DR-004\n */\n gsi1sk: {\n type: \"string\" as const,\n required: true,\n },\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\n/** Data-plane entity names (model.entity and key segment). Single source of truth for allowed values. Keys are UPPER_SNAKE for consistency. */\nexport const DATA_ENTITY_NAMES = {\n ACCOUNT: \"account\",\n ACTIVITY_DEFINITION: \"activitydefinition\",\n ADVERSE_EVENT: \"adverseevent\",\n ALLERGY_INTOLERANCE: \"allergyintolerance\",\n APPOINTMENT: \"appointment\",\n APPOINTMENT_RESPONSE: \"appointmentresponse\",\n AUDIT_EVENT: \"auditevent\",\n BASIC: \"basic\",\n BIOLOGICALLY_DERIVED_PRODUCT: \"biologicallyderivedproduct\",\n BODY_STRUCTURE: \"bodystructure\",\n CAPABILITY_STATEMENT: \"capabilitystatement\",\n CARE_PLAN: \"careplan\",\n CARE_TEAM: \"careteam\",\n CATALOG_ENTRY: \"catalogentry\",\n CODE_SYSTEM: \"codesystem\",\n COMPARTMENT_DEFINITION: \"compartmentdefinition\",\n CONCEPT_MAP: \"conceptmap\",\n CHARGE_ITEM: \"chargeitem\",\n CHARGE_ITEM_DEFINITION: \"chargeitemdefinition\",\n CLAIM: \"claim\",\n CLAIM_RESPONSE: \"claimresponse\",\n CLINICAL_IMPRESSION: \"clinicalimpression\",\n COMMUNICATION: \"communication\",\n COMMUNICATION_REQUEST: \"communicationrequest\",\n COMPOSITION: \"composition\",\n CONDITION: \"condition\",\n CONSENT: \"consent\",\n CONTRACT: \"contract\",\n COVERAGE: \"coverage\",\n COVERAGE_ELIGIBILITY_REQUEST: \"coverageeligibilityrequest\",\n COVERAGE_ELIGIBILITY_RESPONSE: \"coverageeligibilityresponse\",\n DETECTED_ISSUE: \"detectedissue\",\n DEVICE: \"device\",\n DEVICE_DEFINITION: \"devicedefinition\",\n DEVICE_METRIC: \"devicemetric\",\n DEVICE_REQUEST: \"devicerequest\",\n DEVICE_USE_STATEMENT: \"deviceusestatement\",\n DIAGNOSTIC_REPORT: \"diagnosticreport\",\n DOCUMENT_MANIFEST: \"documentmanifest\",\n DOCUMENT_REFERENCE: \"documentreference\",\n EFFECT_EVIDENCE_SYNTHESIS: \"effectevidencesynthesis\",\n ENCOUNTER: \"encounter\",\n ENDPOINT: \"endpoint\",\n ENROLLMENT_REQUEST: \"enrollmentrequest\",\n ENROLLMENT_RESPONSE: \"enrollmentresponse\",\n EPISODE_OF_CARE: \"episodeofcare\",\n EVENT_DEFINITION: \"eventdefinition\",\n EVIDENCE: \"evidence\",\n EVIDENCE_VARIABLE: \"evidencevariable\",\n EXAMPLE_SCENARIO: \"examplescenario\",\n EXPLANATION_OF_BENEFIT: \"explanationofbenefit\",\n FAMILY_MEMBER_HISTORY: \"familymemberhistory\",\n FLAG: \"flag\",\n GOAL: \"goal\",\n GRAPH_DEFINITION: \"graphdefinition\",\n GROUP: \"group\",\n GUIDANCE_RESPONSE: \"guidanceresponse\",\n HEALTHCARE_SERVICE: \"healthcareservice\",\n IMAGING_STUDY: \"imagingstudy\",\n IMPLEMENTATION_GUIDE: \"implementationguide\",\n IMMUNIZATION: \"immunization\",\n IMMUNIZATION_EVALUATION: \"immunizationevaluation\",\n IMMUNIZATION_RECOMMENDATION: \"immunizationrecommendation\",\n INSURANCE_PLAN: \"insuranceplan\",\n INVOICE: \"invoice\",\n LIBRARY: \"library\",\n LINKAGE: \"linkage\",\n LIST: \"list\",\n LOCATION: \"location\",\n MEASURE: \"measure\",\n MEASURE_REPORT: \"measurereport\",\n MEDIA: \"media\",\n MEDICATION: \"medication\",\n MEDICATION_ADMINISTRATION: \"medicationadministration\",\n MEDICATION_DISPENSE: \"medicationdispense\",\n MEDICATION_KNOWLEDGE: \"medicationknowledge\",\n MEDICATION_REQUEST: \"medicationrequest\",\n MEDICATION_STATEMENT: \"medicationstatement\",\n MEDICINAL_PRODUCT: \"medicinalproduct\",\n MEDICINAL_PRODUCT_AUTHORIZATION: \"medicinalproductauthorization\",\n MEDICINAL_PRODUCT_CONTRAINDICATION: \"medicinalproductcontraindication\",\n MEDICINAL_PRODUCT_INGREDIENT: \"medicinalproductingredient\",\n MEDICINAL_PRODUCT_INDICATION: \"medicinalproductindication\",\n MEDICINAL_PRODUCT_INTERACTION: \"medicinalproductinteraction\",\n MEDICINAL_PRODUCT_MANUFACTURED: \"medicinalproductmanufactured\",\n MEDICINAL_PRODUCT_PACKAGED: \"medicinalproductpackaged\",\n MEDICINAL_PRODUCT_PHARMACEUTICAL: \"medicinalproductpharmaceutical\",\n MEDICINAL_PRODUCT_UNDESIRABLE_EFFECT: \"medicinalproductundesirableeffect\",\n MESSAGE_DEFINITION: \"messagedefinition\",\n MESSAGE_HEADER: \"messageheader\",\n MOLECULAR_SEQUENCE: \"molecularsequence\",\n NAMING_SYSTEM: \"namingsystem\",\n NUTRITION_ORDER: \"nutritionorder\",\n OBSERVATION: \"observation\",\n OBSERVATION_DEFINITION: \"observationdefinition\",\n OPERATION_DEFINITION: \"operationdefinition\",\n ORGANIZATION: \"organization\",\n ORGANIZATION_AFFILIATION: \"organizationaffiliation\",\n PATIENT: \"patient\",\n PAYMENT_NOTICE: \"paymentnotice\",\n PAYMENT_RECONCILIATION: \"paymentreconciliation\",\n PERSON: \"person\",\n PLAN_DEFINITION: \"plandefinition\",\n PRACTITIONER: \"practitioner\",\n PRACTITIONER_ROLE: \"practitionerrole\",\n PROCEDURE: \"procedure\",\n PROVENANCE: \"provenance\",\n QUESTIONNAIRE: \"questionnaire\",\n QUESTIONNAIRE_RESPONSE: \"questionnaireresponse\",\n RELATED_PERSON: \"relatedperson\",\n REQUEST_GROUP: \"requestgroup\",\n RESEARCH_DEFINITION: \"researchdefinition\",\n RESEARCH_ELEMENT_DEFINITION: \"researchelementdefinition\",\n RESEARCH_STUDY: \"researchstudy\",\n RESEARCH_SUBJECT: \"researchsubject\",\n SEARCH_PARAMETER: \"searchparameter\",\n RISK_ASSESSMENT: \"riskassessment\",\n RISK_EVIDENCE_SYNTHESIS: \"riskevidencesynthesis\",\n SCHEDULE: \"schedule\",\n SERVICE_REQUEST: \"servicerequest\",\n SLOT: \"slot\",\n SPECIMEN: \"specimen\",\n SPECIMEN_DEFINITION: \"specimendefinition\",\n STRUCTURE_DEFINITION: \"structuredefinition\",\n STRUCTURE_MAP: \"structuremap\",\n SUBSTANCE: \"substance\",\n SUBSTANCE_NUCLEIC_ACID: \"substancenucleicacid\",\n SUBSTANCE_POLYMER: \"substancepolymer\",\n SUBSTANCE_PROTEIN: \"substanceprotein\",\n SUBSTANCE_REFERENCE_INFORMATION: \"substancereferenceinformation\",\n SUBSTANCE_SPECIFICATION: \"substancespecification\",\n SUBSTANCE_SOURCE_MATERIAL: \"substancesourcematerial\",\n SUBSCRIPTION: \"subscription\",\n TERMINOLOGY_CAPABILITIES: \"terminologycapabilities\",\n TEST_REPORT: \"testreport\",\n TEST_SCRIPT: \"testscript\",\n VALUE_SET: \"valueset\",\n SUPPLY_DELIVERY: \"supplydelivery\",\n SUPPLY_REQUEST: \"supplyrequest\",\n TASK: \"task\",\n VERIFICATION_RESULT: \"verificationresult\",\n VISION_PRESCRIPTION: \"visionprescription\",\n} as const;\n\n/** Data-plane entity name (model.entity and key segment). */\nexport type DataEntityName =\n (typeof DATA_ENTITY_NAMES)[keyof typeof DATA_ENTITY_NAMES];\n\n/**\n * Creates an ElectroDB Entity for a data-plane FHIR resource with the common model, attributes,\n * base-table index, and GSI1 (Unified Sharded List per ADR-011 / DR-004) for list-by-type-in-workspace.\n *\n * GSI1 PK shape: `TID#<tid>#WID#<wid>#RT#<resourceTypeLabel>#SHARD#<n>` where `n = computeShard(id)`\n * (4-way fixed sharding). GSI1 SK shape: `<lastUpdated>#<id>` — the unlabeled fallback per DR-004.\n * Labeled sort keys (e.g. `<normalizedLabel>#<id>` for Patient/Practitioner/etc.) ride on top of\n * this contract through the writer's `extractSortKey(resource)` integration; this factory wires the\n * index, attribute, and the deterministic shard derivation. PK template uses resourceTypeLabel as a\n * literal so each entity instance binds its own type segment.\n *\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md — GSI1\n * @see sites/www-docs/content/architecture/adr/ — ADR-011, DR-004\n */\nexport function createDataEntity(\n entity: DataEntityName,\n resourceTypeLabel: string,\n) {\n return new Entity({\n model: {\n entity,\n service: \"data\",\n version: \"01\",\n },\n attributes: dataEntityAttributes,\n indexes: {\n /** Base table: PK, SK (data store key names). PK is built from tenantId, workspaceId, id. */\n record: {\n pk: {\n field: \"PK\",\n composite: [\"tenantId\", \"workspaceId\", \"id\"],\n template: `TID#\\${tenantId}#WID#\\${workspaceId}#RT#${resourceTypeLabel}#ID#\\${id}`,\n },\n sk: {\n field: \"SK\",\n composite: [\"sk\"],\n },\n },\n /**\n * GSI1 — Unified Sharded List: list all resources of this type in a workspace; reads fan\n * out across the four shards and merge by SK. SK is the writer-supplied `gsi1sk` verbatim\n * (per DR-004) so labeled types serve `BEGINS_WITH` prefix queries on the natural label.\n * `casing: \"none\"` is required on the SK because the writer (`extractSortKey`) already\n * applies DR-004 normalization — ElectroDB's default lowercasing would mangle the\n * ISO-8601 unlabeled fallback (`T`/`Z` → `t`/`z`).\n */\n gsi1: {\n index: \"GSI1\",\n pk: {\n field: \"GSI1PK\",\n composite: [\"tenantId\", \"workspaceId\", \"gsi1Shard\"],\n template: `TID#\\${tenantId}#WID#\\${workspaceId}#RT#${resourceTypeLabel}#SHARD#\\${gsi1Shard}`,\n },\n sk: {\n field: \"GSI1SK\",\n casing: \"none\" as const,\n composite: [\"gsi1sk\"],\n template: `\\${gsi1sk}`,\n },\n },\n },\n });\n}\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Account data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Account#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const AccountEntity = createDataEntity(\"account\", \"Account\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ActivityDefinition data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ActivityDefinition#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ActivityDefinitionEntity = createDataEntity(\n \"activitydefinition\",\n \"ActivityDefinition\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * AdverseEvent data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#AdverseEvent#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const AdverseEventEntity = createDataEntity(\n \"adverseevent\",\n \"AdverseEvent\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * AllergyIntolerance data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#AllergyIntolerance#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const AllergyIntoleranceEntity = createDataEntity(\n \"allergyintolerance\",\n \"AllergyIntolerance\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Appointment data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Appointment#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const AppointmentEntity = createDataEntity(\"appointment\", \"Appointment\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * AppointmentResponse data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#AppointmentResponse#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const AppointmentResponseEntity = createDataEntity(\n \"appointmentresponse\",\n \"AppointmentResponse\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * AuditEvent data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#AuditEvent#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const AuditEventEntity = createDataEntity(\"auditevent\", \"AuditEvent\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Basic data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Basic#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const BasicEntity = createDataEntity(\"basic\", \"Basic\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * BiologicallyDerivedProduct data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#BiologicallyDerivedProduct#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const BiologicallyDerivedProductEntity = createDataEntity(\n \"biologicallyderivedproduct\",\n \"BiologicallyDerivedProduct\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * BodyStructure data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#BodyStructure#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const BodyStructureEntity = createDataEntity(\n \"bodystructure\",\n \"BodyStructure\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * CapabilityStatement data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#CapabilityStatement#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const CapabilityStatementEntity = createDataEntity(\n \"capabilitystatement\",\n \"CapabilityStatement\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * CarePlan data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#CarePlan#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const CarePlanEntity = createDataEntity(\"careplan\", \"CarePlan\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * CareTeam data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#CareTeam#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const CareTeamEntity = createDataEntity(\"careteam\", \"CareTeam\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * CatalogEntry data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#CatalogEntry#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const CatalogEntryEntity = createDataEntity(\n \"catalogentry\",\n \"CatalogEntry\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ChargeItemDefinition data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ChargeItemDefinition#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ChargeItemDefinitionEntity = createDataEntity(\n \"chargeitemdefinition\",\n \"ChargeItemDefinition\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ChargeItem data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ChargeItem#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ChargeItemEntity = createDataEntity(\"chargeitem\", \"ChargeItem\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Claim data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Claim#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ClaimEntity = createDataEntity(\"claim\", \"Claim\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ClaimResponse data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ClaimResponse#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ClaimResponseEntity = createDataEntity(\n \"claimresponse\",\n \"ClaimResponse\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ClinicalImpression data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ClinicalImpression#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ClinicalImpressionEntity = createDataEntity(\n \"clinicalimpression\",\n \"ClinicalImpression\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * CodeSystem data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#CodeSystem#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const CodeSystemEntity = createDataEntity(\"codesystem\", \"CodeSystem\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Communication data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Communication#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const CommunicationEntity = createDataEntity(\n \"communication\",\n \"Communication\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * CommunicationRequest data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#CommunicationRequest#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const CommunicationRequestEntity = createDataEntity(\n \"communicationrequest\",\n \"CommunicationRequest\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * CompartmentDefinition data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#CompartmentDefinition#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const CompartmentDefinitionEntity = createDataEntity(\n \"compartmentdefinition\",\n \"CompartmentDefinition\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Composition data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Composition#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const CompositionEntity = createDataEntity(\"composition\", \"Composition\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ConceptMap data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ConceptMap#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ConceptMapEntity = createDataEntity(\"conceptmap\", \"ConceptMap\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Condition data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Condition#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ConditionEntity = createDataEntity(\"condition\", \"Condition\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Consent data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Consent#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ConsentEntity = createDataEntity(\"consent\", \"Consent\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Contract data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Contract#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ContractEntity = createDataEntity(\"contract\", \"Contract\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * CoverageEligibilityRequest data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#CoverageEligibilityRequest#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const CoverageEligibilityRequestEntity = createDataEntity(\n \"coverageeligibilityrequest\",\n \"CoverageEligibilityRequest\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * CoverageEligibilityResponse data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#CoverageEligibilityResponse#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const CoverageEligibilityResponseEntity = createDataEntity(\n \"coverageeligibilityresponse\",\n \"CoverageEligibilityResponse\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Coverage data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Coverage#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const CoverageEntity = createDataEntity(\"coverage\", \"Coverage\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * DetectedIssue data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#DetectedIssue#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const DetectedIssueEntity = createDataEntity(\n \"detectedissue\",\n \"DetectedIssue\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * DeviceDefinition data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#DeviceDefinition#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const DeviceDefinitionEntity = createDataEntity(\n \"devicedefinition\",\n \"DeviceDefinition\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Device data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Device#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const DeviceEntity = createDataEntity(\"device\", \"Device\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * DeviceMetric data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#DeviceMetric#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const DeviceMetricEntity = createDataEntity(\n \"devicemetric\",\n \"DeviceMetric\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * DeviceRequest data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#DeviceRequest#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const DeviceRequestEntity = createDataEntity(\n \"devicerequest\",\n \"DeviceRequest\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * DeviceUseStatement data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#DeviceUseStatement#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const DeviceUseStatementEntity = createDataEntity(\n \"deviceusestatement\",\n \"DeviceUseStatement\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * DiagnosticReport data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#DiagnosticReport#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const DiagnosticReportEntity = createDataEntity(\n \"diagnosticreport\",\n \"DiagnosticReport\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * DocumentManifest data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#DocumentManifest#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const DocumentManifestEntity = createDataEntity(\n \"documentmanifest\",\n \"DocumentManifest\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * DocumentReference data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#DocumentReference#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const DocumentReferenceEntity = createDataEntity(\n \"documentreference\",\n \"DocumentReference\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * EffectEvidenceSynthesis data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#EffectEvidenceSynthesis#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const EffectEvidenceSynthesisEntity = createDataEntity(\n \"effectevidencesynthesis\",\n \"EffectEvidenceSynthesis\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Encounter data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Encounter#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with Patient and other domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\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/entities/encounter.md\n */\nexport const EncounterEntity = createDataEntity(\"encounter\", \"Encounter\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Endpoint data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Endpoint#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const EndpointEntity = createDataEntity(\"endpoint\", \"Endpoint\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * EnrollmentRequest data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#EnrollmentRequest#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const EnrollmentRequestEntity = createDataEntity(\n \"enrollmentrequest\",\n \"EnrollmentRequest\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * EnrollmentResponse data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#EnrollmentResponse#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const EnrollmentResponseEntity = createDataEntity(\n \"enrollmentresponse\",\n \"EnrollmentResponse\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * EpisodeOfCare data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#EpisodeOfCare#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const EpisodeOfCareEntity = createDataEntity(\n \"episodeofcare\",\n \"EpisodeOfCare\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * EventDefinition data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#EventDefinition#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const EventDefinitionEntity = createDataEntity(\n \"eventdefinition\",\n \"EventDefinition\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Evidence data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Evidence#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const EvidenceEntity = createDataEntity(\"evidence\", \"Evidence\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * EvidenceVariable data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#EvidenceVariable#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const EvidenceVariableEntity = createDataEntity(\n \"evidencevariable\",\n \"EvidenceVariable\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ExampleScenario data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ExampleScenario#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ExampleScenarioEntity = createDataEntity(\n \"examplescenario\",\n \"ExampleScenario\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ExplanationOfBenefit data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ExplanationOfBenefit#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ExplanationOfBenefitEntity = createDataEntity(\n \"explanationofbenefit\",\n \"ExplanationOfBenefit\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * FamilyMemberHistory data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#FamilyMemberHistory#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const FamilyMemberHistoryEntity = createDataEntity(\n \"familymemberhistory\",\n \"FamilyMemberHistory\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Flag data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Flag#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const FlagEntity = createDataEntity(\"flag\", \"Flag\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Goal data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Goal#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const GoalEntity = createDataEntity(\"goal\", \"Goal\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * GraphDefinition data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#GraphDefinition#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const GraphDefinitionEntity = createDataEntity(\n \"graphdefinition\",\n \"GraphDefinition\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Group data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Group#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const GroupEntity = createDataEntity(\"group\", \"Group\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * GuidanceResponse data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#GuidanceResponse#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const GuidanceResponseEntity = createDataEntity(\n \"guidanceresponse\",\n \"GuidanceResponse\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * HealthcareService data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#HealthcareService#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const HealthcareServiceEntity = createDataEntity(\n \"healthcareservice\",\n \"HealthcareService\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ImagingStudy data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ImagingStudy#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ImagingStudyEntity = createDataEntity(\n \"imagingstudy\",\n \"ImagingStudy\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Immunization data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Immunization#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ImmunizationEntity = createDataEntity(\n \"immunization\",\n \"Immunization\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ImmunizationEvaluation data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ImmunizationEvaluation#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ImmunizationEvaluationEntity = createDataEntity(\n \"immunizationevaluation\",\n \"ImmunizationEvaluation\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ImmunizationRecommendation data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ImmunizationRecommendation#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ImmunizationRecommendationEntity = createDataEntity(\n \"immunizationrecommendation\",\n \"ImmunizationRecommendation\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ImplementationGuide data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ImplementationGuide#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ImplementationGuideEntity = createDataEntity(\n \"implementationguide\",\n \"ImplementationGuide\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * InsurancePlan data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#InsurancePlan#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const InsurancePlanEntity = createDataEntity(\n \"insuranceplan\",\n \"InsurancePlan\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Invoice data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Invoice#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const InvoiceEntity = createDataEntity(\"invoice\", \"Invoice\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Library data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Library#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const LibraryEntity = createDataEntity(\"library\", \"Library\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Linkage data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Linkage#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const LinkageEntity = createDataEntity(\"linkage\", \"Linkage\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * List data-store entity based on FHIR R4 (single-table store).\n * Represents the FHIR List resource (curated list of items).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#List#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ListEntity = createDataEntity(\"list\", \"List\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Location data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Location#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const LocationEntity = createDataEntity(\"location\", \"Location\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Measure data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Measure#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MeasureEntity = createDataEntity(\"measure\", \"Measure\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MeasureReport data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MeasureReport#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MeasureReportEntity = createDataEntity(\n \"measurereport\",\n \"MeasureReport\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Media data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Media#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MediaEntity = createDataEntity(\"media\", \"Media\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MedicationAdministration data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MedicationAdministration#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MedicationAdministrationEntity = createDataEntity(\n \"medicationadministration\",\n \"MedicationAdministration\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MedicationDispense data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MedicationDispense#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MedicationDispenseEntity = createDataEntity(\n \"medicationdispense\",\n \"MedicationDispense\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Medication data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Medication#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MedicationEntity = createDataEntity(\"medication\", \"Medication\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MedicationKnowledge data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MedicationKnowledge#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MedicationKnowledgeEntity = createDataEntity(\n \"medicationknowledge\",\n \"MedicationKnowledge\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MedicationRequest data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MedicationRequest#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MedicationRequestEntity = createDataEntity(\n \"medicationrequest\",\n \"MedicationRequest\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MedicationStatement data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MedicationStatement#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MedicationStatementEntity = createDataEntity(\n \"medicationstatement\",\n \"MedicationStatement\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MedicinalProductAuthorization data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MedicinalProductAuthorization#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MedicinalProductAuthorizationEntity = createDataEntity(\n \"medicinalproductauthorization\",\n \"MedicinalProductAuthorization\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MedicinalProductContraindication data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MedicinalProductContraindication#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MedicinalProductContraindicationEntity = createDataEntity(\n \"medicinalproductcontraindication\",\n \"MedicinalProductContraindication\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MedicinalProduct data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MedicinalProduct#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MedicinalProductEntity = createDataEntity(\n \"medicinalproduct\",\n \"MedicinalProduct\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MedicinalProductIndication data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MedicinalProductIndication#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MedicinalProductIndicationEntity = createDataEntity(\n \"medicinalproductindication\",\n \"MedicinalProductIndication\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MedicinalProductIngredient data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MedicinalProductIngredient#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MedicinalProductIngredientEntity = createDataEntity(\n \"medicinalproductingredient\",\n \"MedicinalProductIngredient\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MedicinalProductInteraction data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MedicinalProductInteraction#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MedicinalProductInteractionEntity = createDataEntity(\n \"medicinalproductinteraction\",\n \"MedicinalProductInteraction\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MedicinalProductManufactured data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MedicinalProductManufactured#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MedicinalProductManufacturedEntity = createDataEntity(\n \"medicinalproductmanufactured\",\n \"MedicinalProductManufactured\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MedicinalProductPackaged data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MedicinalProductPackaged#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MedicinalProductPackagedEntity = createDataEntity(\n \"medicinalproductpackaged\",\n \"MedicinalProductPackaged\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MedicinalProductPharmaceutical data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MedicinalProductPharmaceutical#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MedicinalProductPharmaceuticalEntity = createDataEntity(\n \"medicinalproductpharmaceutical\",\n \"MedicinalProductPharmaceutical\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MedicinalProductUndesirableEffect data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MedicinalProductUndesirableEffect#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MedicinalProductUndesirableEffectEntity = createDataEntity(\n \"medicinalproductundesirableeffect\",\n \"MedicinalProductUndesirableEffect\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MessageDefinition data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MessageDefinition#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MessageDefinitionEntity = createDataEntity(\n \"messagedefinition\",\n \"MessageDefinition\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MessageHeader data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MessageHeader#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MessageHeaderEntity = createDataEntity(\n \"messageheader\",\n \"MessageHeader\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MolecularSequence data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MolecularSequence#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MolecularSequenceEntity = createDataEntity(\n \"molecularsequence\",\n \"MolecularSequence\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * NamingSystem data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#NamingSystem#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const NamingSystemEntity = createDataEntity(\n \"namingsystem\",\n \"NamingSystem\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * NutritionOrder data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#NutritionOrder#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const NutritionOrderEntity = createDataEntity(\n \"nutritionorder\",\n \"NutritionOrder\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ObservationDefinition data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ObservationDefinition#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ObservationDefinitionEntity = createDataEntity(\n \"observationdefinition\",\n \"ObservationDefinition\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Observation data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Observation#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ObservationEntity = createDataEntity(\"observation\", \"Observation\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * OperationDefinition data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#OperationDefinition#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const OperationDefinitionEntity = createDataEntity(\n \"operationdefinition\",\n \"OperationDefinition\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * OrganizationAffiliation data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#OrganizationAffiliation#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const OrganizationAffiliationEntity = createDataEntity(\n \"organizationaffiliation\",\n \"OrganizationAffiliation\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Organization data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Organization#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const OrganizationEntity = createDataEntity(\n \"organization\",\n \"Organization\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Patient data-store entity based on FHIR (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Patient#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) are documented in the Data-Store Entity Standards (FHIR).\n * Audit is in FHIR resource meta (meta.extension), not item attributes. See entity-standards.md.\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/patient.md\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const PatientEntity = createDataEntity(\"patient\", \"Patient\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * PaymentNotice data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#PaymentNotice#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const PaymentNoticeEntity = createDataEntity(\n \"paymentnotice\",\n \"PaymentNotice\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * PaymentReconciliation data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#PaymentReconciliation#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const PaymentReconciliationEntity = createDataEntity(\n \"paymentreconciliation\",\n \"PaymentReconciliation\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Person data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Person#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const PersonEntity = createDataEntity(\"person\", \"Person\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * PlanDefinition data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#PlanDefinition#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const PlanDefinitionEntity = createDataEntity(\n \"plandefinition\",\n \"PlanDefinition\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Practitioner data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Practitioner#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with Patient, Encounter, and entity standards.\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/practitioner.md\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const PractitionerEntity = createDataEntity(\n \"practitioner\",\n \"Practitioner\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * PractitionerRole data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#PractitionerRole#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const PractitionerRoleEntity = createDataEntity(\n \"practitionerrole\",\n \"PractitionerRole\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Procedure data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Procedure#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ProcedureEntity = createDataEntity(\"procedure\", \"Procedure\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Provenance data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Provenance#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ProvenanceEntity = createDataEntity(\"provenance\", \"Provenance\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Questionnaire data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Questionnaire#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const QuestionnaireEntity = createDataEntity(\n \"questionnaire\",\n \"Questionnaire\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * QuestionnaireResponse data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#QuestionnaireResponse#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const QuestionnaireResponseEntity = createDataEntity(\n \"questionnaireresponse\",\n \"QuestionnaireResponse\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * RelatedPerson data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#RelatedPerson#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const RelatedPersonEntity = createDataEntity(\n \"relatedperson\",\n \"RelatedPerson\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * RequestGroup data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#RequestGroup#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const RequestGroupEntity = createDataEntity(\n \"requestgroup\",\n \"RequestGroup\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ResearchDefinition data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ResearchDefinition#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ResearchDefinitionEntity = createDataEntity(\n \"researchdefinition\",\n \"ResearchDefinition\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ResearchElementDefinition data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ResearchElementDefinition#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ResearchElementDefinitionEntity = createDataEntity(\n \"researchelementdefinition\",\n \"ResearchElementDefinition\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ResearchStudy data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ResearchStudy#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ResearchStudyEntity = createDataEntity(\n \"researchstudy\",\n \"ResearchStudy\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ResearchSubject data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ResearchSubject#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ResearchSubjectEntity = createDataEntity(\n \"researchsubject\",\n \"ResearchSubject\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * RiskAssessment data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#RiskAssessment#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const RiskAssessmentEntity = createDataEntity(\n \"riskassessment\",\n \"RiskAssessment\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * RiskEvidenceSynthesis data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#RiskEvidenceSynthesis#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const RiskEvidenceSynthesisEntity = createDataEntity(\n \"riskevidencesynthesis\",\n \"RiskEvidenceSynthesis\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Schedule data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Schedule#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ScheduleEntity = createDataEntity(\"schedule\", \"Schedule\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * SearchParameter data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#SearchParameter#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const SearchParameterEntity = createDataEntity(\n \"searchparameter\",\n \"SearchParameter\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ServiceRequest data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ServiceRequest#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ServiceRequestEntity = createDataEntity(\n \"servicerequest\",\n \"ServiceRequest\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Slot data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Slot#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const SlotEntity = createDataEntity(\"slot\", \"Slot\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * SpecimenDefinition data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#SpecimenDefinition#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const SpecimenDefinitionEntity = createDataEntity(\n \"specimendefinition\",\n \"SpecimenDefinition\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Specimen data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Specimen#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const SpecimenEntity = createDataEntity(\"specimen\", \"Specimen\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * StructureDefinition data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#StructureDefinition#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const StructureDefinitionEntity = createDataEntity(\n \"structuredefinition\",\n \"StructureDefinition\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * StructureMap data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#StructureMap#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const StructureMapEntity = createDataEntity(\n \"structuremap\",\n \"StructureMap\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Subscription data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Subscription#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const SubscriptionEntity = createDataEntity(\n \"subscription\",\n \"Subscription\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Substance data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Substance#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const SubstanceEntity = createDataEntity(\"substance\", \"Substance\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * SubstanceNucleicAcid data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#SubstanceNucleicAcid#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const SubstanceNucleicAcidEntity = createDataEntity(\n \"substancenucleicacid\",\n \"SubstanceNucleicAcid\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * SubstancePolymer data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#SubstancePolymer#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const SubstancePolymerEntity = createDataEntity(\n \"substancepolymer\",\n \"SubstancePolymer\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * SubstanceProtein data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#SubstanceProtein#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const SubstanceProteinEntity = createDataEntity(\n \"substanceprotein\",\n \"SubstanceProtein\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * SubstanceReferenceInformation data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#SubstanceReferenceInformation#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const SubstanceReferenceInformationEntity = createDataEntity(\n \"substancereferenceinformation\",\n \"SubstanceReferenceInformation\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * SubstanceSourceMaterial data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#SubstanceSourceMaterial#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const SubstanceSourceMaterialEntity = createDataEntity(\n \"substancesourcematerial\",\n \"SubstanceSourceMaterial\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * SubstanceSpecification data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#SubstanceSpecification#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const SubstanceSpecificationEntity = createDataEntity(\n \"substancespecification\",\n \"SubstanceSpecification\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * SupplyDelivery data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#SupplyDelivery#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const SupplyDeliveryEntity = createDataEntity(\n \"supplydelivery\",\n \"SupplyDelivery\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * SupplyRequest data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#SupplyRequest#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const SupplyRequestEntity = createDataEntity(\n \"supplyrequest\",\n \"SupplyRequest\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Task data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Task#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const TaskEntity = createDataEntity(\"task\", \"Task\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * TerminologyCapabilities data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#TerminologyCapabilities#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const TerminologyCapabilitiesEntity = createDataEntity(\n \"terminologycapabilities\",\n \"TerminologyCapabilities\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * TestReport data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#TestReport#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const TestReportEntity = createDataEntity(\"testreport\", \"TestReport\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * TestScript data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#TestScript#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const TestScriptEntity = createDataEntity(\"testscript\", \"TestScript\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ValueSet data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ValueSet#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ValueSetEntity = createDataEntity(\"valueset\", \"ValueSet\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * VerificationResult data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#VerificationResult#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const VerificationResultEntity = createDataEntity(\n \"verificationresult\",\n \"VerificationResult\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * VisionPrescription data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#VisionPrescription#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const VisionPrescriptionEntity = createDataEntity(\n \"visionprescription\",\n \"VisionPrescription\",\n);\n","import { extractSortKey, extractSummary } from \"@openhi/types\";\nimport type { Meta, FhirResourceLike } from \"@openhi/types\";\nimport { compressResource, decompressResource } from \"../../lib/compression\";\nimport { mergeAuditIntoMeta, type MetaWithExtensions } from \"../audit-meta\";\nimport { SHARD_COUNT } from \"../dynamo/shard\";\nimport { NotFoundError } from \"../errors\";\nimport type { OpenHiContext } from \"../openhi-context\";\n\n/**\n * Sort key for the current record version. Matches Dynamo record index SK default.\n * Use this in get/update/delete (and create where applicable) for data-plane entities.\n */\nexport const DATA_ENTITY_SK = \"CURRENT\" as const;\n\n/** Base params for data-entity operations: context and optional table override. */\nexport interface BaseDataEntityParams {\n context: OpenHiContext;\n /** Optional table name override; resolved by data service from DYNAMO_TABLE_NAME when omitted. */\n tableName?: string;\n}\n\n/** Params for get-by-id and delete (context + id + optional tableName). */\nexport interface GetByIdParams extends BaseDataEntityParams {\n id: string;\n}\n\n/**\n * Mode for list operations introduced by #853 to back FHIR `_summary` opt-ins.\n *\n * - `full` (default): GSI1 fan-out → BatchGet hydration → full FHIR resource per entry.\n * - `summary`: GSI1 fan-out only; the `summary` JSON projected onto GSI1 is parsed and used\n * as `resource` per entry. Skips BatchGet entirely — that's the cost win the FHIR spec\n * intends `_summary=true` to deliver.\n * - `count`: GSI1 fan-out only; entries are dropped, only `total` is populated. Routes\n * should pass `total` into `buildSearchsetBundle({ mode: \"count\", total })`.\n *\n * `_elements` is implemented at the route layer as `full` mode + post-hydration pruning,\n * since per-element pruning has to happen after decompression and is FHIR-spec-defined\n * (always retain root-level mandatories — see `prune-resource-by-elements.ts`).\n */\nexport type ListOperationMode = \"full\" | \"summary\" | \"count\";\n\n/** Params for list (context + optional tableName + optional mode for #853 `_summary`). */\nexport interface ListParams extends BaseDataEntityParams {\n /** Defaults to `\"full\"` (current behavior); routes pass other modes for `_summary` opt-ins. */\n mode?: ListOperationMode;\n}\n\n/** Result for create / get-by-id / update: single resource. */\nexport interface SingleResourceResult<T> {\n id: string;\n resource: T;\n}\n\n/** Entry shape for list results. */\nexport interface ListEntry<T> {\n id: string;\n resource: T;\n}\n\n/**\n * Result for list: entries array plus total count.\n *\n * - For `mode === \"full\"` and `mode === \"summary\"`, `total === entries.length`.\n * - For `mode === \"count\"`, `entries` is empty and `total` is the GSI1 fan-out count.\n *\n * Splitting `total` from `entries.length` lets count-mode routes report a true count\n * while skipping any per-entry work.\n */\nexport interface ListResult<T> {\n entries: Array<ListEntry<T>>;\n total: number;\n}\n\n/** Minimal entity shape for get (used by getDataEntityById). */\ninterface EntityWithGet {\n get(params: {\n tenantId: string;\n workspaceId: string;\n id: string;\n sk: string;\n }): { go(): Promise<{ data: { id: string; resource: string } | null }> };\n}\n\n/** Minimal entity shape for delete (used by deleteDataEntityById). */\ninterface EntityWithDelete {\n delete(params: {\n tenantId: string;\n workspaceId: string;\n id: string;\n sk: string;\n }): { go(): Promise<unknown> };\n}\n\n/**\n * Minimal entity shape for list via GSI1 + BatchGet hydration (used by listDataEntitiesByWorkspace).\n * GSI1 is sharded per ADR-011, so listing fans out to each shard and concatenates ids; the\n * `resource` attribute is NOT projected onto GSI1 (per the summary projection in\n * `dynamo-db-data-store.ts`), so the second phase BatchGets the base table for full items.\n *\n * GSI1 INCLUDE projection (per `dynamo-db-data-store.ts`) carries `summary`, `vid`, `lastUpdated`,\n * `createdDate`, `modifiedDate`, `createdById`, `modifiedById` alongside the key attributes.\n * `summary` is what `mode: \"summary\"` returns to the caller without hitting the base table.\n */\ninterface DataEntityWithListAndBatchGet {\n query: {\n gsi1(params: {\n tenantId: string;\n workspaceId: string;\n gsi1Shard: string;\n }): {\n go(): Promise<{\n data: Array<{\n id: string;\n summary?: string;\n vid?: string;\n lastUpdated?: string;\n createdDate?: string;\n modifiedDate?: string;\n createdById?: string;\n modifiedById?: string;\n }> | null;\n }>;\n };\n };\n get(\n keys: Array<{\n tenantId: string;\n workspaceId: string;\n id: string;\n sk: string;\n }>,\n ): {\n go(): Promise<{\n data: Array<{ id: string; resource: string }>;\n unprocessed: Array<{\n tenantId: string;\n workspaceId: string;\n id: string;\n sk: string;\n }>;\n }>;\n };\n}\n\n/** Minimal entity shape for put (used by createDataEntityRecord). */\ninterface EntityWithPut {\n put(attrs: {\n sk: string;\n tenantId: string;\n workspaceId: string;\n id: string;\n resource: string;\n summary: string;\n vid: string;\n lastUpdated: string;\n gsi1sk: string;\n }): { go(): Promise<unknown> };\n}\n\n/** Minimal entity shape for patch (used by updateDataEntityById). */\ninterface EntityWithPatch {\n get(params: {\n tenantId: string;\n workspaceId: string;\n id: string;\n sk: string;\n }): { go(): Promise<{ data: { id: string; resource: string } | null }> };\n patch(params: {\n tenantId: string;\n workspaceId: string;\n id: string;\n sk: string;\n }): {\n set(attrs: {\n resource: string;\n summary: string;\n lastUpdated: string;\n gsi1sk: string;\n }): {\n go(): Promise<unknown>;\n };\n };\n}\n\n/**\n * Get a single data-entity record by id. Decompresses and parses resource; throws NotFoundError if missing.\n * Use from get-by-id operations with the appropriate entity and resource type.\n */\nexport async function getDataEntityById<T>(\n entity: EntityWithGet,\n tenantId: string,\n workspaceId: string,\n id: string,\n resourceLabel: string,\n): Promise<SingleResourceResult<T>> {\n const result = await entity\n .get({\n tenantId,\n workspaceId,\n id,\n sk: DATA_ENTITY_SK,\n })\n .go();\n\n if (!result.data) {\n throw new NotFoundError(`${resourceLabel} ${id} not found`, {\n details: { id },\n });\n }\n\n const parsed = JSON.parse(decompressResource(result.data.resource)) as T & {\n id?: string;\n };\n return {\n id: result.data.id,\n resource: { ...parsed, id: result.data.id } as T,\n };\n}\n\n/**\n * Delete a data-entity record by id. Idempotent (no-op if not found).\n * Use from delete operations with the appropriate entity.\n */\nexport async function deleteDataEntityById(\n entity: EntityWithDelete,\n tenantId: string,\n workspaceId: string,\n id: string,\n): Promise<void> {\n await entity\n .delete({\n tenantId,\n workspaceId,\n id,\n sk: DATA_ENTITY_SK,\n })\n .go();\n}\n\n/** Maximum total attempts (initial + retries) when hydrating list ids via BatchGet. */\nconst BATCH_GET_MAX_ATTEMPTS = 3;\n/** Base backoff in milliseconds applied to BatchGet retries; doubles each attempt. */\nconst BATCH_GET_BASE_BACKOFF_MS = 50;\n\n/** Minimal entity shape for BatchGet hydration on the base table; chunks of 100 are handled by ElectroDB. */\ninterface EntityWithBatchGet<TKey, TItem> {\n get(keys: TKey[]): {\n go(): Promise<{ data: TItem[]; unprocessed: TKey[] }>;\n };\n}\n\n/**\n * BatchGet wrapper that retries `UnprocessedKeys` with exponential backoff. ElectroDB chunks the\n * input keys into groups of 100 internally, but does not retry unprocessed keys — DynamoDB can\n * return some keys unprocessed under throttling or partial failure, and the caller must reissue\n * them. Throws after `BATCH_GET_MAX_ATTEMPTS` if any keys remain unprocessed; intended for list\n * hydration (#854) where partial results would silently truncate the response.\n */\nexport async function batchGetWithRetry<TKey, TItem>(\n entity: EntityWithBatchGet<TKey, TItem>,\n keys: TKey[],\n): Promise<TItem[]> {\n if (keys.length === 0) return [];\n\n const collected: TItem[] = [];\n let pending = keys;\n let attempt = 0;\n\n while (pending.length > 0) {\n if (attempt > 0) {\n await new Promise((resolve) =>\n setTimeout(resolve, BATCH_GET_BASE_BACKOFF_MS * 2 ** (attempt - 1)),\n );\n }\n attempt++;\n const result = await entity.get(pending).go();\n collected.push(...result.data);\n const unprocessed = result.unprocessed ?? [];\n if (unprocessed.length === 0) break;\n if (attempt >= BATCH_GET_MAX_ATTEMPTS) {\n throw new Error(\n `BatchGet exhausted retries: ${unprocessed.length} key(s) still unprocessed after ${BATCH_GET_MAX_ATTEMPTS} attempt(s)`,\n );\n }\n pending = unprocessed;\n }\n\n return collected;\n}\n\n/** GSI1 index item shape — what a sharded `gsi1.query().go()` returns per row. */\nexport interface ShardedListIndexItem {\n id: string;\n summary?: string;\n}\n\n/** Hooks that adapt a generic mode-dispatching list to a specific entity's hydration and entry shape. */\nexport interface DispatchListModeHooks<TItem, TEntry> {\n /** Hydrate the base table for the given ids (typically `batchGetWithRetry(entity, keys)`). */\n hydrate: (orderedIds: string[]) => Promise<TItem[]>;\n /** Extract the canonical id from a hydrated item so it can be matched back to the GSI1 order. */\n getId: (item: TItem) => string;\n /** Build the result entry for `mode === \"full\"` from a hydrated base-table item. */\n buildEntry: (id: string, item: TItem) => TEntry;\n /** Build the result entry for `mode === \"summary\"` from the parsed GSI1 `summary` JSON. */\n buildSummaryEntry: (\n id: string,\n parsedSummary: Record<string, unknown>,\n ) => TEntry;\n}\n\n/**\n * Mode dispatcher shared by data-plane and control-plane list operations (#853).\n *\n * Given pre-fetched `shardResults` from a sharded GSI1 fan-out, returns either:\n * - `mode === \"count\"` — `{ entries: [], total }` where total is the sum of shard row counts.\n * - `mode === \"summary\"` — entries built from each shard row's parsed `summary` JSON; rows with\n * missing or unparseable `summary` are dropped.\n * - `mode === \"full\"` — calls `hydrate(orderedIds)` (typically a BatchGet) and builds entries\n * from hydrated items in per-shard GSI1 sort order; missing items are dropped.\n *\n * Lives here (alongside `listDataEntitiesByWorkspace`) because the same dispatch logic is needed\n * by every list operation that backs a FHIR list/search endpoint, including the seven\n * control-plane peers (User, Role, Tenant, Workspace, Membership, RoleAssignment, Configuration).\n */\nexport async function dispatchListMode<TItem, TEntry>(\n mode: ListOperationMode,\n shardResults: Array<{ data: Array<ShardedListIndexItem> | null }>,\n hooks: DispatchListModeHooks<TItem, TEntry>,\n): Promise<{ entries: TEntry[]; total: number }> {\n if (mode === \"count\") {\n let total = 0;\n for (const shardResult of shardResults) {\n total += (shardResult.data ?? []).length;\n }\n return { entries: [], total };\n }\n\n if (mode === \"summary\") {\n const entries: TEntry[] = [];\n for (const shardResult of shardResults) {\n for (const item of shardResult.data ?? []) {\n if (typeof item.summary !== \"string\") continue;\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(item.summary) as Record<string, unknown>;\n } catch {\n continue;\n }\n entries.push(hooks.buildSummaryEntry(item.id, parsed));\n }\n }\n return { entries, total: entries.length };\n }\n\n const orderedIds: string[] = [];\n for (const shardResult of shardResults) {\n for (const item of shardResult.data ?? []) {\n orderedIds.push(item.id);\n }\n }\n\n if (orderedIds.length === 0) return { entries: [], total: 0 };\n\n const items = await hooks.hydrate(orderedIds);\n const byId = new Map(items.map((item) => [hooks.getId(item), item]));\n\n const entries: TEntry[] = [];\n for (const id of orderedIds) {\n const item = byId.get(id);\n if (!item) continue;\n entries.push(hooks.buildEntry(id, item));\n }\n\n return { entries, total: entries.length };\n}\n\n/**\n * List data-entity records in a workspace via GSI1.\n *\n * `mode` (default `\"full\"`) selects the read shape — see `dispatchListMode`. The data-plane\n * binding here adds the four-shard fan-out (per ADR-011) and the BatchGet hydration with\n * decompression for `mode === \"full\"`. K-way merge by `gsi1sk` is intentionally NOT done here\n * — full server-side natural sort lands with the FHIR list-endpoint plumbing that adds\n * pagination tokens.\n */\nexport async function listDataEntitiesByWorkspace<T>(\n entity: DataEntityWithListAndBatchGet,\n tenantId: string,\n workspaceId: string,\n mode: ListOperationMode = \"full\",\n): Promise<ListResult<T>> {\n const shardResults = await Promise.all(\n Array.from({ length: SHARD_COUNT }, (_, shard) =>\n entity.query\n .gsi1({ tenantId, workspaceId, gsi1Shard: String(shard) })\n .go(),\n ),\n );\n\n return dispatchListMode<{ id: string; resource: string }, ListEntry<T>>(\n mode,\n shardResults,\n {\n hydrate: (orderedIds) =>\n batchGetWithRetry(\n entity,\n orderedIds.map((id) => ({\n tenantId,\n workspaceId,\n id,\n sk: DATA_ENTITY_SK,\n })),\n ),\n getId: (item) => item.id,\n buildEntry: (id, item) => {\n const parsed = JSON.parse(decompressResource(item.resource)) as T & {\n id?: string;\n };\n return { id, resource: { ...parsed, id } as T };\n },\n buildSummaryEntry: (id, parsed) => ({\n id,\n resource: { ...parsed, id } as T,\n }),\n },\n );\n}\n\n/**\n * Create a data-entity record with put. Computes vid from lastUpdated (from resource meta or fallback).\n * Use from create operations (e.g. Practitioner, Encounter) that build the resource with audit in meta.\n */\nexport async function createDataEntityRecord<T>(\n entity: EntityWithPut,\n tenantId: string,\n workspaceId: string,\n id: string,\n resourceWithAudit: T & { meta?: { lastUpdated?: string } },\n fallbackDate: string,\n): Promise<SingleResourceResult<T>> {\n const lastUpdated =\n resourceWithAudit.meta?.lastUpdated ??\n fallbackDate ??\n new Date().toISOString();\n const vid =\n lastUpdated.replace(/[-:T.Z]/g, \"\").slice(0, 12) || Date.now().toString(36);\n\n const resourceLike = resourceWithAudit as unknown as FhirResourceLike;\n const summary = JSON.stringify(extractSummary(resourceLike));\n const gsi1sk = extractSortKey(resourceLike);\n\n await entity\n .put({\n sk: DATA_ENTITY_SK,\n tenantId,\n workspaceId,\n id,\n resource: compressResource(JSON.stringify(resourceWithAudit)),\n summary,\n vid,\n lastUpdated,\n gsi1sk,\n })\n .go();\n\n return {\n id,\n resource: resourceWithAudit as T,\n };\n}\n\n/**\n * Build an updated resource with audit in meta for use with updateDataEntityById.\n * Parses existing resource string for existing meta, merges body with id/resourceType/meta (versionId \"2\"),\n * then merges modified audit (modifiedDate, modifiedById, modifiedByName) into meta.\n * Use from update operations (Patient, Encounter, Practitioner) to avoid duplicating this logic.\n */\nexport function buildUpdatedResourceWithAudit<T extends { meta?: Meta }>(\n body: T,\n id: string,\n date: string,\n actorId: string,\n actorName: string,\n existingResourceStr: string,\n resourceType: string,\n): {\n resource: T & { id: string; meta: MetaWithExtensions };\n lastUpdated: string;\n} {\n const existingMeta: MetaWithExtensions | undefined = (\n JSON.parse(existingResourceStr) as { meta?: MetaWithExtensions }\n ).meta;\n\n const bodyWithMeta = body as T & { id?: string; meta?: Meta };\n const resourceWithVersion: T & { id: string; meta?: Meta } = {\n ...body,\n resourceType: resourceType as T[\"resourceType\"],\n id,\n meta: {\n ...(bodyWithMeta.meta ?? {}),\n lastUpdated: date,\n versionId: \"2\",\n },\n };\n\n const resourceWithAudit: T & { id: string; meta: MetaWithExtensions } = {\n ...resourceWithVersion,\n meta: mergeAuditIntoMeta(resourceWithVersion.meta ?? existingMeta, {\n modifiedDate: date,\n modifiedById: actorId,\n modifiedByName: actorName,\n }),\n };\n\n return {\n resource: resourceWithAudit,\n lastUpdated: date,\n };\n}\n\n/**\n * Update a data-entity record by id: get existing, throw if not found, then call builder with\n * decompressed existing resource string; builder returns \\{ resource, lastUpdated \\}; then patch.\n * Use from update operations with the appropriate entity and resource type.\n */\nexport async function updateDataEntityById<T>(\n entity: EntityWithPatch,\n tenantId: string,\n workspaceId: string,\n id: string,\n resourceLabel: string,\n context: OpenHiContext,\n buildPatched: (existingResourceStr: string) => {\n resource: unknown;\n lastUpdated: string;\n },\n): Promise<SingleResourceResult<T>> {\n const existing = await entity\n .get({\n tenantId,\n workspaceId,\n id,\n sk: DATA_ENTITY_SK,\n })\n .go();\n\n if (!existing.data) {\n throw new NotFoundError(`${resourceLabel} ${id} not found`, {\n details: { id },\n });\n }\n\n const existingStr = decompressResource(existing.data.resource);\n const { resource, lastUpdated } = buildPatched(existingStr);\n\n const resourceLike = resource as FhirResourceLike;\n const summary = JSON.stringify(extractSummary(resourceLike));\n const gsi1sk = extractSortKey(resourceLike);\n\n await entity\n .patch({\n tenantId,\n workspaceId,\n id,\n sk: DATA_ENTITY_SK,\n })\n .set({\n resource: compressResource(JSON.stringify(resource)),\n summary,\n lastUpdated,\n gsi1sk,\n })\n .go();\n\n return {\n id,\n resource: resource as T,\n };\n}\n","import { gzipSync, gunzipSync } from \"node:zlib\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/constructs/lib/compression.md\n */\n\n/** Envelope format version. See ADR 2026-02-15-02 (data layer compression). */\nconst ENVELOPE_VERSION = 1;\n\n/**\n * Compression algorithm identifiers supported by the envelope (string values).\n * Only algos that Node.js supports out of the box (zlib): gzip, brotli, deflate.\n * \"none\" = uncompressed payload. zstd was considered in the ADR but requires native addon/WASM.\n */\nexport const COMPRESSION_ALGOS = {\n NONE: \"none\",\n GZIP: \"gzip\",\n BROTLI: \"brotli\",\n DEFLATE: \"deflate\",\n} as const;\n\n/** Algorithm value for envelope `algo`; only gzip and none are implemented today. */\nexport type CompressionAlgo =\n (typeof COMPRESSION_ALGOS)[keyof typeof COMPRESSION_ALGOS];\n\n/** Stored value is a JSON string of this envelope. */\ninterface CompressionEnvelope {\n v: number;\n algo: string;\n payload: string;\n}\n\nfunction isEnvelope(obj: unknown): obj is CompressionEnvelope {\n return (\n typeof obj === \"object\" &&\n obj !== null &&\n \"v\" in obj &&\n \"algo\" in obj &&\n \"payload\" in obj &&\n typeof (obj as CompressionEnvelope).payload === \"string\"\n );\n}\n\n/**\n * Compresses a JSON string (e.g. serialized FHIR resource) for storage in DynamoDB.\n * Uses a versioned envelope: \\{ v, algo, payload \\} with gzip+base64 in payload.\n * Used by the data layer on write; see REST API docs (compression in data layer).\n * Optional compression: pass `{ algo: COMPRESSION_ALGOS.NONE }` to store in envelope without compressing.\n */\nexport function compressResource(\n jsonString: string,\n options?: { algo?: CompressionAlgo },\n): string {\n const algo = options?.algo ?? COMPRESSION_ALGOS.GZIP;\n if (algo === COMPRESSION_ALGOS.NONE) {\n const envelope: CompressionEnvelope = {\n v: ENVELOPE_VERSION,\n algo: COMPRESSION_ALGOS.NONE,\n payload: jsonString,\n };\n return JSON.stringify(envelope);\n }\n const buf = Buffer.from(jsonString, \"utf-8\");\n const payload = gzipSync(buf).toString(\"base64\");\n const envelope: CompressionEnvelope = {\n v: ENVELOPE_VERSION,\n algo: COMPRESSION_ALGOS.GZIP,\n payload,\n };\n return JSON.stringify(envelope);\n}\n\n/**\n * Decompresses a stored value: versioned envelope (v, algo, payload) or legacy gzip+base64 / raw.\n * If the value is not valid envelope JSON, falls back to legacy: try gzip magic on base64, else return as-is.\n */\nexport function decompressResource(compressedOrRaw: string): string {\n try {\n const parsed = JSON.parse(compressedOrRaw) as unknown;\n if (isEnvelope(parsed)) {\n if (parsed.algo === COMPRESSION_ALGOS.GZIP) {\n const buf = Buffer.from(parsed.payload, \"base64\");\n return gunzipSync(buf).toString(\"utf-8\");\n }\n if (parsed.algo === COMPRESSION_ALGOS.NONE) {\n return parsed.payload;\n }\n // Unknown algo: return payload as-is (safe fallback per ADR)\n return parsed.payload;\n }\n } catch {\n // Not valid envelope JSON — legacy path\n }\n\n // Legacy: pre-envelope gzip+base64 or raw\n try {\n const buf = Buffer.from(compressedOrRaw, \"base64\");\n if (buf.length >= 2 && buf[0] === 0x1f && buf[1] === 0x8b) {\n return gunzipSync(buf).toString(\"utf-8\");\n }\n } catch {\n // not base64 or gunzip failed\n }\n return compressedOrRaw;\n}\n","import type { Extension, Meta } from \"@openhi/types\";\n\n/**\n * Shared audit/meta helpers for FHIR resources. Used by data operations and import.\n * OpenHI audit is stored in resource meta.extension (per ADR 2026-01-13-06).\n *\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/entity-standards.md\n */\n\n/** OpenHI extension URLs for audit in resource meta (per ADR 2026-01-13-06). */\nconst OPENHI_EXT = \"http://openhi.org/fhir/StructureDefinition\";\n\n/** Meta with optional OpenHI audit extensions (created/modified by, etc.). */\nexport type MetaWithExtensions = Meta & { extension?: Array<Extension> };\n\n/** Audit fields stored in FHIR resource meta.extension. */\nexport interface AuditFields {\n createdDate?: string;\n createdById?: string;\n createdByName?: string;\n modifiedDate?: string;\n modifiedById?: string;\n modifiedByName?: string;\n deletedDate?: string;\n deletedById?: string;\n deletedByName?: string;\n}\n\n/** Audit extension entry shape (subset of Extension used by OpenHI audit). */\ntype AuditExtensionEntry = Pick<\n Extension,\n \"url\" | \"valueString\" | \"valueDateTime\"\n>;\n\n/** Builds meta.extension entries for audit; merges with existing meta. */\nexport function mergeAuditIntoMeta(\n meta: MetaWithExtensions | Record<string, unknown> | undefined,\n audit: AuditFields,\n): MetaWithExtensions {\n const existing = (meta ?? {}) as MetaWithExtensions;\n const ext: Array<AuditExtensionEntry> = [\n ...(Array.isArray(existing.extension)\n ? (existing.extension as Array<AuditExtensionEntry>)\n : []),\n ];\n const byUrl = new Map(ext.map((e) => [e.url, e]));\n function set(\n url: string,\n value: string | undefined,\n type: \"valueString\" | \"valueDateTime\",\n ) {\n if (value == null) return;\n byUrl.set(url, { url, [type]: value });\n }\n set(`${OPENHI_EXT}/created-date`, audit.createdDate, \"valueDateTime\");\n set(`${OPENHI_EXT}/created-by-id`, audit.createdById, \"valueString\");\n set(`${OPENHI_EXT}/created-by-name`, audit.createdByName, \"valueString\");\n set(`${OPENHI_EXT}/modified-date`, audit.modifiedDate, \"valueDateTime\");\n set(`${OPENHI_EXT}/modified-by-id`, audit.modifiedById, \"valueString\");\n set(`${OPENHI_EXT}/modified-by-name`, audit.modifiedByName, \"valueString\");\n set(`${OPENHI_EXT}/deleted-date`, audit.deletedDate, \"valueDateTime\");\n set(`${OPENHI_EXT}/deleted-by-id`, audit.deletedById, \"valueString\");\n set(`${OPENHI_EXT}/deleted-by-name`, audit.deletedByName, \"valueString\");\n return { ...existing, extension: Array.from(byUrl.values()) };\n}\n","import type { Organization, Reference } from \"@openhi/types\";\nimport { getDynamoDataService } from \"../../../dynamo/dynamo-data-service\";\nimport type { OpenHiContext } from \"../../../openhi-context\";\nimport {\n createDataEntityRecord,\n DATA_ENTITY_SK,\n type SingleResourceResult,\n} from \"../../data-operations-common\";\n\n/**\n * Provision the slim, id-share Organization that represents a Workspace on the data plane.\n *\n * - `Organization.id === workspaceId` (id-share with the Workspace).\n * - `name` is populated from the Workspace's name when provided.\n * - `partOf` is populated when the Workspace's Tenant has an Organization (id-share at the\n * tenant level: `Tenant.id === TenantOrganization.id`). Tenant-level provisioning is out of\n * scope for #1001 — the lookup returns `undefined` until Tenant Organizations exist.\n *\n * Idempotent: re-running with the same params overwrites the same PK with the same payload.\n *\n * @see https://github.com/codedrifters/openhi/issues/1001\n */\nexport interface ProvisionOrganizationForWorkspaceParams {\n context: OpenHiContext;\n /** Workspace id; the provisioned Organization's id equals this value. */\n workspaceId: string;\n /** Name to record on the Organization. Derived from the Workspace's `name` by the caller. */\n workspaceName?: string;\n /** Optional table name override; resolved by data service from DYNAMO_TABLE_NAME when omitted. */\n tableName?: string;\n}\n\nexport type ProvisionOrganizationForWorkspaceResult =\n SingleResourceResult<Organization>;\n\nexport async function provisionOrganizationForWorkspaceOperation(\n params: ProvisionOrganizationForWorkspaceParams,\n): Promise<ProvisionOrganizationForWorkspaceResult> {\n const { context, workspaceId, workspaceName, tableName } = params;\n const { tenantId, date } = context;\n const service = getDynamoDataService(tableName);\n\n const partOf = await resolveTenantOrganizationReference(service, tenantId);\n\n const resource: Organization = {\n resourceType: \"Organization\",\n id: workspaceId,\n ...(workspaceName !== undefined && workspaceName !== \"\"\n ? { name: workspaceName }\n : {}),\n ...(partOf !== undefined ? { partOf } : {}),\n meta: {\n lastUpdated: date,\n versionId: \"1\",\n },\n };\n\n return createDataEntityRecord<Organization>(\n service.entities.organization as Parameters<\n typeof createDataEntityRecord\n >[0],\n tenantId,\n workspaceId,\n workspaceId,\n resource,\n date,\n );\n}\n\n/**\n * Resolve the Tenant's Organization reference for `Organization.partOf`. Returns `undefined`\n * when the Tenant has no Organization yet (the default until Tenant Organization provisioning\n * is wired up in a follow-up).\n *\n * Lookup convention: the Tenant's Organization is stored at\n * `(tenantId, workspaceId=tenantId, id=tenantId)` — a self-scope key that mirrors the\n * Workspace id-share pattern one level up. This scoping convention will be ratified by the\n * Tenant Organization provisioning issue; the OrganizationEntity comment notes strict\n * isolation requires both `tenantId` and `workspaceId`, so the self-scope is the\n * simplest deterministic location.\n */\nasync function resolveTenantOrganizationReference(\n service: ReturnType<typeof getDynamoDataService>,\n tenantId: string,\n): Promise<Reference | undefined> {\n const result = await (\n service.entities.organization as {\n get(params: {\n tenantId: string;\n workspaceId: string;\n id: string;\n sk: string;\n }): { go(): Promise<{ data: unknown }> };\n }\n )\n .get({\n tenantId,\n workspaceId: tenantId,\n id: tenantId,\n sk: DATA_ENTITY_SK,\n })\n .go();\n\n if (result.data === null || result.data === undefined) {\n return undefined;\n }\n\n return { reference: `Organization/${tenantId}` };\n}\n","import type { Account, Meta } from \"@openhi/types\";\nimport { ulid } from \"ulid\";\nimport {\n mergeAuditIntoMeta,\n type MetaWithExtensions,\n} from \"../../../audit-meta\";\nimport { getDynamoDataService } from \"../../../dynamo/dynamo-data-service\";\nimport type { OpenHiContext } from \"../../../openhi-context\";\nimport {\n createDataEntityRecord,\n type SingleResourceResult,\n} from \"../../data-operations-common\";\n\n/**\n * Create an Account. Accepts FHIR-like body and OpenHI context; returns created resource.\n *\n * @see sites/www-docs/content/packages/@openhi/constructs/data/shared-data-layer-layout.md\n */\nexport interface CreateAccountParams {\n context: OpenHiContext;\n /** FHIR Account body (resourceType, id optional, meta optional). */\n body: Account;\n /** Optional table name override; resolved by data service from DYNAMO_TABLE_NAME when omitted. */\n tableName?: string;\n}\n\nexport type CreateAccountResult = SingleResourceResult<Account>;\n\n/**\n * Creates an Account. Builds put attrs with audit in meta, then ElectroDB put.\n * Throws on service/validation errors; adapters map to HTTP/GraphQL.\n */\nexport async function createAccountOperation(\n params: CreateAccountParams,\n): Promise<CreateAccountResult> {\n const { context, body, tableName } = params;\n const { tenantId, workspaceId, date, actorId, actorName } = context;\n const id = body.id ?? ulid();\n\n const meta: Meta = {\n ...(body.meta ?? {}),\n lastUpdated: date,\n versionId: \"1\",\n };\n\n const accountWithAudit: Account & {\n id: string;\n meta: MetaWithExtensions;\n } = {\n ...body,\n resourceType: \"Account\",\n id,\n meta: mergeAuditIntoMeta(meta, {\n createdDate: date,\n createdById: actorId,\n createdByName: actorName,\n modifiedDate: date,\n modifiedById: actorId,\n modifiedByName: actorName,\n }),\n };\n\n const service = getDynamoDataService(tableName);\n return createDataEntityRecord<Account>(\n service.entities.account as Parameters<typeof createDataEntityRecord>[0],\n tenantId,\n workspaceId,\n id,\n accountWithAudit,\n date,\n );\n}\n","import type { Encounter, Meta } from \"@openhi/types\";\nimport { ulid } from \"ulid\";\nimport {\n mergeAuditIntoMeta,\n type MetaWithExtensions,\n} from \"../../../audit-meta\";\nimport { getDynamoDataService } from \"../../../dynamo/dynamo-data-service\";\nimport type { OpenHiContext } from \"../../../openhi-context\";\nimport {\n createDataEntityRecord,\n type SingleResourceResult,\n} from \"../../data-operations-common\";\n\n/**\n * Create an Encounter. Accepts FHIR-like body and OpenHI context; returns created resource.\n *\n * @see sites/www-docs/content/packages/@openhi/constructs/data/shared-data-layer-layout.md\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/entities/encounter.md\n */\nexport interface CreateEncounterParams {\n context: OpenHiContext;\n /** FHIR Encounter body (resourceType, id optional, meta optional). */\n body: Encounter;\n /** Optional table name override; resolved by data service from DYNAMO_TABLE_NAME when omitted. */\n tableName?: string;\n}\n\nexport type CreateEncounterResult = SingleResourceResult<Encounter>;\n\n/**\n * Creates an Encounter. Builds put attrs with audit in meta, then ElectroDB put.\n * Throws on service/validation errors; adapters map to HTTP/GraphQL.\n */\nexport async function createEncounterOperation(\n params: CreateEncounterParams,\n): Promise<CreateEncounterResult> {\n const { context, body, tableName } = params;\n const { tenantId, workspaceId, date, actorId, actorName } = context;\n const id = body.id ?? ulid();\n\n const meta: Meta = {\n ...(body.meta ?? {}),\n lastUpdated: date,\n versionId: \"1\",\n };\n\n const encounterWithAudit: Encounter & {\n id: string;\n meta: MetaWithExtensions;\n } = {\n ...body,\n resourceType: \"Encounter\",\n id,\n meta: mergeAuditIntoMeta(meta, {\n createdDate: date,\n createdById: actorId,\n createdByName: actorName,\n modifiedDate: date,\n modifiedById: actorId,\n modifiedByName: actorName,\n }),\n };\n\n const service = getDynamoDataService(tableName);\n return createDataEntityRecord<Encounter>(\n service.entities.encounter as Parameters<typeof createDataEntityRecord>[0],\n tenantId,\n workspaceId,\n id,\n encounterWithAudit,\n date,\n );\n}\n","import type { Observation, Meta } from \"@openhi/types\";\nimport { ulid } from \"ulid\";\nimport {\n mergeAuditIntoMeta,\n type MetaWithExtensions,\n} from \"../../../audit-meta\";\nimport { getDynamoDataService } from \"../../../dynamo/dynamo-data-service\";\nimport type { OpenHiContext } from \"../../../openhi-context\";\nimport {\n createDataEntityRecord,\n type SingleResourceResult,\n} from \"../../data-operations-common\";\n\n/**\n * Create a Observation. Accepts FHIR-like body and OpenHI context; returns created resource.\n *\n * @see sites/www-docs/content/packages/@openhi/constructs/data/shared-data-layer-layout.md\n */\nexport interface CreateObservationParams {\n context: OpenHiContext;\n /** FHIR Observation body (resourceType, id optional, meta optional). */\n body: Observation;\n /** Optional table name override; resolved by data service from DYNAMO_TABLE_NAME when omitted. */\n tableName?: string;\n}\n\nexport type CreateObservationResult = SingleResourceResult<Observation>;\n\n/**\n * Creates a Observation. Builds put attrs with audit in meta, then ElectroDB put.\n * Throws on service/validation errors; adapters map to HTTP/GraphQL.\n */\nexport async function createObservationOperation(\n params: CreateObservationParams,\n): Promise<CreateObservationResult> {\n const { context, body, tableName } = params;\n const { tenantId, workspaceId, date, actorId, actorName } = context;\n const id = body.id ?? ulid();\n\n const meta: Meta = {\n ...(body.meta ?? {}),\n lastUpdated: date,\n versionId: \"1\",\n };\n\n const resourceWithAudit: Observation & {\n id: string;\n meta: MetaWithExtensions;\n } = {\n ...body,\n resourceType: \"Observation\",\n id,\n meta: mergeAuditIntoMeta(meta, {\n createdDate: date,\n createdById: actorId,\n createdByName: actorName,\n modifiedDate: date,\n modifiedById: actorId,\n modifiedByName: actorName,\n }),\n };\n\n const service = getDynamoDataService(tableName);\n return createDataEntityRecord<Observation>(\n service.entities.observation as Parameters<\n typeof createDataEntityRecord\n >[0],\n tenantId,\n workspaceId,\n id,\n resourceWithAudit,\n date,\n );\n}\n","import type { Meta, Patient } from \"@openhi/types\";\nimport { ulid } from \"ulid\";\nimport {\n mergeAuditIntoMeta,\n type MetaWithExtensions,\n} from \"../../../audit-meta\";\nimport { getDynamoDataService } from \"../../../dynamo/dynamo-data-service\";\nimport type { OpenHiContext } from \"../../../openhi-context\";\nimport {\n createDataEntityRecord,\n type SingleResourceResult,\n} from \"../../data-operations-common\";\n\n/**\n * Create a Patient. Accepts FHIR-like body and OpenHI context; returns created resource.\n *\n * @see sites/www-docs/content/packages/@openhi/constructs/data/shared-data-layer-layout.md\n * @see sites/www-docs/content/packages/@openhi/constructs/data/operations/patient/patient-create.md\n */\nexport interface CreatePatientParams {\n context: OpenHiContext;\n /** FHIR Patient body (resourceType, id optional, meta optional). */\n body: Patient;\n /** Optional table name override; resolved by data service from DYNAMO_TABLE_NAME when omitted. */\n tableName?: string;\n}\n\nexport type CreatePatientResult = SingleResourceResult<Patient>;\n\n/**\n * Creates a Patient. Builds put attrs with audit in meta, then ElectroDB put.\n * Throws on service/validation errors; adapters map to HTTP/GraphQL.\n */\nexport async function createPatientOperation(\n params: CreatePatientParams,\n): Promise<CreatePatientResult> {\n const { context, body, tableName } = params;\n const { tenantId, workspaceId, date, actorId, actorName } = context;\n const id = body.id ?? ulid();\n\n const meta: Meta = {\n ...(body.meta ?? {}),\n lastUpdated: date,\n versionId: \"1\",\n };\n\n const patientWithAudit: Patient & {\n id: string;\n meta: MetaWithExtensions;\n } = {\n ...body,\n resourceType: \"Patient\",\n id,\n meta: mergeAuditIntoMeta(meta, {\n createdDate: date,\n createdById: actorId,\n createdByName: actorName,\n modifiedDate: date,\n modifiedById: actorId,\n modifiedByName: actorName,\n }),\n };\n\n const service = getDynamoDataService(tableName);\n return createDataEntityRecord<Patient>(\n service.entities.patient as Parameters<typeof createDataEntityRecord>[0],\n tenantId,\n workspaceId,\n id,\n patientWithAudit,\n date,\n );\n}\n","import type { Meta, Practitioner } from \"@openhi/types\";\nimport { ulid } from \"ulid\";\nimport {\n mergeAuditIntoMeta,\n type MetaWithExtensions,\n} from \"../../../audit-meta\";\nimport { getDynamoDataService } from \"../../../dynamo/dynamo-data-service\";\nimport type { OpenHiContext } from \"../../../openhi-context\";\nimport {\n createDataEntityRecord,\n type SingleResourceResult,\n} from \"../../data-operations-common\";\n\n/**\n * Create a Practitioner. Accepts FHIR-like body and OpenHI context; returns created resource.\n *\n * @see sites/www-docs/content/packages/@openhi/constructs/data/shared-data-layer-layout.md\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/entities/practitioner.md\n */\nexport interface CreatePractitionerParams {\n context: OpenHiContext;\n /** FHIR Practitioner body (resourceType, id optional, meta optional). */\n body: Practitioner;\n /** Optional table name override; resolved by data service from DYNAMO_TABLE_NAME when omitted. */\n tableName?: string;\n}\n\nexport type CreatePractitionerResult = SingleResourceResult<Practitioner>;\n\n/**\n * Creates a Practitioner. Builds put attrs with audit in meta, then ElectroDB put.\n * Throws on service/validation errors; adapters map to HTTP/GraphQL.\n */\nexport async function createPractitionerOperation(\n params: CreatePractitionerParams,\n): Promise<CreatePractitionerResult> {\n const { context, body, tableName } = params;\n const { tenantId, workspaceId, date, actorId, actorName } = context;\n const id = body.id ?? ulid();\n\n const meta: Meta = {\n ...(body.meta ?? {}),\n lastUpdated: date,\n versionId: \"1\",\n };\n\n const practitionerWithAudit: Practitioner & {\n id: string;\n meta: MetaWithExtensions;\n } = {\n ...body,\n resourceType: \"Practitioner\",\n id,\n meta: mergeAuditIntoMeta(meta, {\n createdDate: date,\n createdById: actorId,\n createdByName: actorName,\n modifiedDate: date,\n modifiedById: actorId,\n modifiedByName: actorName,\n }),\n };\n\n const service = getDynamoDataService(tableName);\n return createDataEntityRecord<Practitioner>(\n service.entities.practitioner as Parameters<\n typeof createDataEntityRecord\n >[0],\n tenantId,\n workspaceId,\n id,\n practitionerWithAudit,\n date,\n );\n}\n"],"mappings":"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","names":["exports","exports","exports","exports","exports","exports","exports","exports","exports","parseWorkflowEvent","exports","exports","workflowDedupClient","exports","exports","import_client_dynamodb","import_types","import_workflows","import_electrodb","import_types","import_electrodb","import_electrodb","import_electrodb","import_electrodb","import_electrodb","import_electrodb","import_electrodb","import_electrodb","import_electrodb","import_electrodb","import_electrodb","import_electrodb","import_types","import_types","import_types","MISSING_NAME_SENTINEL","import_types","import_types","MISSING_NAME_SENTINEL","extractReferenceSlug","import_types","MISSING_NAME_SENTINEL","extractReferenceSlug","import_types","import_types","import_electrodb","import_electrodb","import_types","envelope","import_ulid","import_ulid","import_ulid","import_ulid"]}
1
+ {"version":3,"sources":["../../workflows/src/envelope-version.ts","../../workflows/src/envelope.ts","../../workflows/src/sources.ts","../../workflows/src/detail-types/registry.ts","../../workflows/src/detail-types/control-plane.ts","../../workflows/src/detail-types/platform.ts","../../workflows/src/detail-types/index.ts","../../workflows/src/publisher.ts","../../workflows/src/consumer.ts","../../workflows/src/dedup/env.ts","../../workflows/src/dedup/workflow-dedup-client.ts","../../workflows/src/dedup/index.ts","../../workflows/src/index.ts","../src/workflows/control-plane/seed-demo-data/seed-demo-data.handler.ts","../src/workflows/control-plane/seed-demo-data/events.ts","../src/data/operations/control/membership-constraints/platform-scope-tenant-id.ts","../src/workflows/control-plane/seed-demo-data/on-site-demo-facilities.ts","../src/workflows/control-plane/seed-demo-data/on-site-demo-blocks.ts","../src/workflows/control-plane/seed-demo-data/on-site-demo-facility-patients.ts","../src/workflows/control-plane/seed-demo-data/on-site-demo-home-health-patients.ts","../src/workflows/control-plane/seed-demo-data/on-site-demo-encounters.ts","../src/workflows/control-plane/seed-demo-data/on-site-demo-claims.ts","../src/workflows/control-plane/seed-demo-data/on-site-demo-directory.ts","../src/workflows/control-plane/seed-demo-data/on-site-demo-fixtures.ts","../src/workflows/control-plane/seed-demo-data/data-plane-fixtures.ts","../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/configuration-user-projection-entity.ts","../src/data/dynamo/entities/control/configuration-workspace-projection-entity.ts","../src/data/dynamo/entities/control/membership-entity.ts","../src/data/dynamo/entities/control/membership-user-projection-entity.ts","../src/data/dynamo/entities/control/membership-workspace-projection-entity.ts","../src/data/dynamo/entities/control/role-entity.ts","../src/data/dynamo/entities/control/roleassignment-entity.ts","../src/data/dynamo/entities/control/roleassignment-user-projection-entity.ts","../src/data/dynamo/entities/control/roleassignment-workspace-projection-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","../src/data/errors/domain-errors.ts","../src/data/operations/control/membership/membership-create-operation.ts","../src/data/operations/control/membership/membership-user-projection.ts","../src/data/operations/control/membership/membership-workspace-projection.ts","../src/data/operations/control/denormalized-display-names.ts","../src/data/operations/control/membership-constraints/assert-workspace-in-tenant-operation.ts","../src/data/operations/control/multi-write-operation.ts","../src/data/operations/control/role/role-get-by-id-operation.ts","../src/data/operations/control/roleassignment/roleassignment-create-operation.ts","../src/data/operations/control/roleassignment/roleassignment-user-projection.ts","../src/data/operations/control/roleassignment/roleassignment-workspace-projection.ts","../src/data/operations/control/membership-constraints/assert-user-has-tenant-membership-operation.ts","../src/data/operations/control/tenant/tenant-create-operation.ts","../src/data/operations/control/workspace/workspace-create-operation.ts","../src/data/dynamo/dynamo-data-service.ts","../src/data/dynamo/entities/data-entity-common.ts","../src/data/dynamo/entities/data/account-entity.ts","../src/data/dynamo/entities/data/activity-definition-entity.ts","../src/data/dynamo/entities/data/adverse-event-entity.ts","../src/data/dynamo/entities/data/allergy-intolerance-entity.ts","../src/data/dynamo/entities/data/appointment-entity.ts","../src/data/dynamo/entities/data/appointment-response-entity.ts","../src/data/dynamo/entities/data/audit-event-entity.ts","../src/data/dynamo/entities/data/basic-entity.ts","../src/data/dynamo/entities/data/biologically-derived-product-entity.ts","../src/data/dynamo/entities/data/body-structure-entity.ts","../src/data/dynamo/entities/data/capability-statement-entity.ts","../src/data/dynamo/entities/data/care-plan-entity.ts","../src/data/dynamo/entities/data/care-team-entity.ts","../src/data/dynamo/entities/data/catalog-entry-entity.ts","../src/data/dynamo/entities/data/charge-item-definition-entity.ts","../src/data/dynamo/entities/data/charge-item-entity.ts","../src/data/dynamo/entities/data/claim-entity.ts","../src/data/dynamo/entities/data/claim-response-entity.ts","../src/data/dynamo/entities/data/clinical-impression-entity.ts","../src/data/dynamo/entities/data/code-system-entity.ts","../src/data/dynamo/entities/data/communication-entity.ts","../src/data/dynamo/entities/data/communication-request-entity.ts","../src/data/dynamo/entities/data/compartment-definition-entity.ts","../src/data/dynamo/entities/data/composition-entity.ts","../src/data/dynamo/entities/data/concept-map-entity.ts","../src/data/dynamo/entities/data/condition-entity.ts","../src/data/dynamo/entities/data/consent-entity.ts","../src/data/dynamo/entities/data/contract-entity.ts","../src/data/dynamo/entities/data/coverage-eligibility-request-entity.ts","../src/data/dynamo/entities/data/coverage-eligibility-response-entity.ts","../src/data/dynamo/entities/data/coverage-entity.ts","../src/data/dynamo/entities/data/detected-issue-entity.ts","../src/data/dynamo/entities/data/device-definition-entity.ts","../src/data/dynamo/entities/data/device-entity.ts","../src/data/dynamo/entities/data/device-metric-entity.ts","../src/data/dynamo/entities/data/device-request-entity.ts","../src/data/dynamo/entities/data/device-use-statement-entity.ts","../src/data/dynamo/entities/data/diagnostic-report-entity.ts","../src/data/dynamo/entities/data/document-manifest-entity.ts","../src/data/dynamo/entities/data/document-reference-entity.ts","../src/data/dynamo/entities/data/effect-evidence-synthesis-entity.ts","../src/data/dynamo/entities/data/encounter-entity.ts","../src/data/dynamo/entities/data/endpoint-entity.ts","../src/data/dynamo/entities/data/enrollment-request-entity.ts","../src/data/dynamo/entities/data/enrollment-response-entity.ts","../src/data/dynamo/entities/data/episode-of-care-entity.ts","../src/data/dynamo/entities/data/event-definition-entity.ts","../src/data/dynamo/entities/data/evidence-entity.ts","../src/data/dynamo/entities/data/evidence-variable-entity.ts","../src/data/dynamo/entities/data/example-scenario-entity.ts","../src/data/dynamo/entities/data/explanation-of-benefit-entity.ts","../src/data/dynamo/entities/data/family-member-history-entity.ts","../src/data/dynamo/entities/data/flag-entity.ts","../src/data/dynamo/entities/data/goal-entity.ts","../src/data/dynamo/entities/data/graph-definition-entity.ts","../src/data/dynamo/entities/data/group-entity.ts","../src/data/dynamo/entities/data/guidance-response-entity.ts","../src/data/dynamo/entities/data/healthcare-service-entity.ts","../src/data/dynamo/entities/data/imaging-study-entity.ts","../src/data/dynamo/entities/data/immunization-entity.ts","../src/data/dynamo/entities/data/immunization-evaluation-entity.ts","../src/data/dynamo/entities/data/immunization-recommendation-entity.ts","../src/data/dynamo/entities/data/implementation-guide-entity.ts","../src/data/dynamo/entities/data/insurance-plan-entity.ts","../src/data/dynamo/entities/data/invoice-entity.ts","../src/data/dynamo/entities/data/library-entity.ts","../src/data/dynamo/entities/data/linkage-entity.ts","../src/data/dynamo/entities/data/list-entity.ts","../src/data/dynamo/entities/data/location-entity.ts","../src/data/dynamo/entities/data/measure-entity.ts","../src/data/dynamo/entities/data/measure-report-entity.ts","../src/data/dynamo/entities/data/media-entity.ts","../src/data/dynamo/entities/data/medication-administration-entity.ts","../src/data/dynamo/entities/data/medication-dispense-entity.ts","../src/data/dynamo/entities/data/medication-entity.ts","../src/data/dynamo/entities/data/medication-knowledge-entity.ts","../src/data/dynamo/entities/data/medication-request-entity.ts","../src/data/dynamo/entities/data/medication-statement-entity.ts","../src/data/dynamo/entities/data/medicinal-product-authorization-entity.ts","../src/data/dynamo/entities/data/medicinal-product-contraindication-entity.ts","../src/data/dynamo/entities/data/medicinal-product-entity.ts","../src/data/dynamo/entities/data/medicinal-product-indication-entity.ts","../src/data/dynamo/entities/data/medicinal-product-ingredient-entity.ts","../src/data/dynamo/entities/data/medicinal-product-interaction-entity.ts","../src/data/dynamo/entities/data/medicinal-product-manufactured-entity.ts","../src/data/dynamo/entities/data/medicinal-product-packaged-entity.ts","../src/data/dynamo/entities/data/medicinal-product-pharmaceutical-entity.ts","../src/data/dynamo/entities/data/medicinal-product-undesirable-effect-entity.ts","../src/data/dynamo/entities/data/message-definition-entity.ts","../src/data/dynamo/entities/data/message-header-entity.ts","../src/data/dynamo/entities/data/molecular-sequence-entity.ts","../src/data/dynamo/entities/data/naming-system-entity.ts","../src/data/dynamo/entities/data/nutrition-order-entity.ts","../src/data/dynamo/entities/data/observation-definition-entity.ts","../src/data/dynamo/entities/data/observation-entity.ts","../src/data/dynamo/entities/data/operation-definition-entity.ts","../src/data/dynamo/entities/data/organization-affiliation-entity.ts","../src/data/dynamo/entities/data/organization-entity.ts","../src/data/dynamo/entities/data/patient-entity.ts","../src/data/dynamo/entities/data/payment-notice-entity.ts","../src/data/dynamo/entities/data/payment-reconciliation-entity.ts","../src/data/dynamo/entities/data/person-entity.ts","../src/data/dynamo/entities/data/plan-definition-entity.ts","../src/data/dynamo/entities/data/practitioner-entity.ts","../src/data/dynamo/entities/data/practitioner-role-entity.ts","../src/data/dynamo/entities/data/procedure-entity.ts","../src/data/dynamo/entities/data/provenance-entity.ts","../src/data/dynamo/entities/data/questionnaire-entity.ts","../src/data/dynamo/entities/data/questionnaire-response-entity.ts","../src/data/dynamo/entities/data/related-person-entity.ts","../src/data/dynamo/entities/data/request-group-entity.ts","../src/data/dynamo/entities/data/research-definition-entity.ts","../src/data/dynamo/entities/data/research-element-definition-entity.ts","../src/data/dynamo/entities/data/research-study-entity.ts","../src/data/dynamo/entities/data/research-subject-entity.ts","../src/data/dynamo/entities/data/risk-assessment-entity.ts","../src/data/dynamo/entities/data/risk-evidence-synthesis-entity.ts","../src/data/dynamo/entities/data/schedule-entity.ts","../src/data/dynamo/entities/data/search-parameter-entity.ts","../src/data/dynamo/entities/data/service-request-entity.ts","../src/data/dynamo/entities/data/slot-entity.ts","../src/data/dynamo/entities/data/specimen-definition-entity.ts","../src/data/dynamo/entities/data/specimen-entity.ts","../src/data/dynamo/entities/data/structure-definition-entity.ts","../src/data/dynamo/entities/data/structure-map-entity.ts","../src/data/dynamo/entities/data/subscription-entity.ts","../src/data/dynamo/entities/data/substance-entity.ts","../src/data/dynamo/entities/data/substance-nucleic-acid-entity.ts","../src/data/dynamo/entities/data/substance-polymer-entity.ts","../src/data/dynamo/entities/data/substance-protein-entity.ts","../src/data/dynamo/entities/data/substance-reference-information-entity.ts","../src/data/dynamo/entities/data/substance-source-material-entity.ts","../src/data/dynamo/entities/data/substance-specification-entity.ts","../src/data/dynamo/entities/data/supply-delivery-entity.ts","../src/data/dynamo/entities/data/supply-request-entity.ts","../src/data/dynamo/entities/data/task-entity.ts","../src/data/dynamo/entities/data/terminology-capabilities-entity.ts","../src/data/dynamo/entities/data/test-report-entity.ts","../src/data/dynamo/entities/data/test-script-entity.ts","../src/data/dynamo/entities/data/value-set-entity.ts","../src/data/dynamo/entities/data/verification-result-entity.ts","../src/data/dynamo/entities/data/vision-prescription-entity.ts","../src/data/operations/data-operations-common.ts","../src/lib/compression.ts","../src/data/audit-meta.ts","../src/data/operations/data/organization/organization-provision-for-workspace-operation.ts","../src/data/operations/data/account/account-create-operation.ts","../src/data/operations/data/appointment/appointment-create-operation.ts","../src/data/operations/data/claim/claim-create-operation.ts","../src/data/operations/data/condition/condition-create-operation.ts","../src/data/operations/data/coverage/coverage-create-operation.ts","../src/data/operations/data/encounter/encounter-create-operation.ts","../src/data/operations/data/location/location-create-operation.ts","../src/data/operations/data/observation/observation-create-operation.ts","../src/data/operations/data/organization/organization-create-operation.ts","../src/data/operations/data/patient/patient-create-operation.ts","../src/data/operations/data/paymentnotice/paymentnotice-create-operation.ts","../src/data/operations/data/practitioner/practitioner-create-operation.ts","../src/data/operations/data/procedure/procedure-create-operation.ts"],"sourcesContent":["/**\n * Envelope version pinned by the publisher SDK on every emitted envelope.\n *\n * Shape is `\"<major>.<minor>\"` per TR-016 §Open Items #3 (P1).\n * Additive optional fields bump the minor; breaking changes bump the\n * major and require a documented overlap window in the consumer SDK.\n */\nexport const ENVELOPE_VERSION = \"1.0\";\n\nconst ENVELOPE_VERSION_PATTERN = /^\\d+\\.\\d+$/;\n\n/**\n * Lowest envelope major version this SDK's consumer parser accepts.\n *\n * Bump this when a deprecated major reaches end-of-life and the\n * overlap window closes.\n */\nconst MIN_SUPPORTED_MAJOR = 1;\n\n/**\n * Highest envelope major version this SDK's consumer parser accepts.\n *\n * Bump this in lockstep with `ENVELOPE_VERSION` whenever a new major\n * ships; the consumer always supports its own publish major.\n */\nconst MAX_SUPPORTED_MAJOR = 1;\n\n/**\n * Return `true` when `version` is shaped `<major>.<minor>` and its\n * major lies within `[MIN_SUPPORTED_MAJOR, MAX_SUPPORTED_MAJOR]`.\n */\nexport function isSupportedEnvelopeVersion(version: string): boolean {\n if (!ENVELOPE_VERSION_PATTERN.test(version)) {\n return false;\n }\n const major = Number.parseInt(version.split(\".\")[0], 10);\n return major >= MIN_SUPPORTED_MAJOR && major <= MAX_SUPPORTED_MAJOR;\n}\n","import type { OhiJwtClaims } from \"@openhi/types\";\n\n/**\n * Discriminated-union actor field per ADR-016 §Decision #3.\n *\n * User-initiated workflows project the four ADR-014 JWT claims (with\n * `ohi_tid` / `ohi_wid` required — a workflow event without a tenant\n * + workspace context belongs to the `system` variant); bootstrap\n * workflows run before a User exists and carry the bootstrap-role\n * name instead. The `system` value is free-form pending the\n * onboarding-bootstrap IAM role TR (TR-016 §Open Items #4).\n */\nexport type WorkflowActor = WorkflowUserActor | WorkflowSystemActor;\n\n/** User-actor variant — required projection of the ADR-014 JWT claims. */\nexport interface WorkflowUserActor {\n readonly ohi_tid: string;\n readonly ohi_wid: string;\n readonly ohi_uid: string;\n readonly ohi_uname: string;\n}\n\n/** Bootstrap-actor variant — carries the bootstrap-role name. */\nexport interface WorkflowSystemActor {\n readonly system: string;\n}\n\n/**\n * Type guard for the user-actor variant.\n */\nexport function isWorkflowUserActor(\n actor: WorkflowActor,\n): actor is WorkflowUserActor {\n return (actor as WorkflowUserActor).ohi_uid !== undefined;\n}\n\n/**\n * Type guard for the system-actor variant.\n */\nexport function isWorkflowSystemActor(\n actor: WorkflowActor,\n): actor is WorkflowSystemActor {\n return (actor as WorkflowSystemActor).system !== undefined;\n}\n\n/**\n * Standard workflow event envelope per ADR-016 §Decision #3 / TR-016.\n *\n * The generic `TPayload` parameter narrows the per-workflow payload.\n *\n * Field naming note: the payload lives under `payload` (not `detail`)\n * deliberately. EventBridge's outer event already has its own `detail`\n * field that carries this whole envelope; nesting another `detail`\n * inside it produced double-`detail` paths in rule patterns\n * (`detail.detail.<x>`) that consistently bit consumers writing\n * filters. The unambiguous name is worth the rename.\n */\nexport interface WorkflowEvent<TPayload = Record<string, unknown>> {\n /** Per-event UUID. Dedup keys on `(eventId, attempt)`. */\n readonly eventId: string;\n /** 1-indexed delivery attempt. */\n readonly attempt: number;\n /** Originating cross-plane chain identifier. */\n readonly correlationId: string;\n /** Immediate predecessor event id, or null for a chain origin. */\n readonly causationId: string | null;\n /** Discriminated actor — JWT-claim projection or bootstrap-role marker. */\n readonly actor: WorkflowActor;\n /** ISO-8601 timestamp marking when the envelope was constructed. */\n readonly occurredAt: string;\n /** Semver-shaped envelope version (e.g. `\"1.0\"`). */\n readonly envelopeVersion: string;\n /** Per-workflow payload narrowed by the generic parameter. */\n readonly payload: TPayload;\n}\n\n/**\n * Promote a raw `OhiJwtClaims` projection to a fully-required\n * `WorkflowUserActor`.\n *\n * Throws `MissingActorContextError` when `ohi_tid` or `ohi_wid` is\n * absent — those claims are optional on the JWT but required on the\n * workflow user-actor.\n */\nexport function workflowUserActorFromClaims(\n claims: OhiJwtClaims,\n): WorkflowUserActor {\n if (claims.ohi_tid === undefined || claims.ohi_wid === undefined) {\n throw new MissingActorContextError(\n \"workflowUserActorFromClaims: ohi_tid and ohi_wid are required on the workflow user-actor; the caller's JWT is missing one or both. Use a system-actor for pre-provisioning bootstrap workflows.\",\n );\n }\n return {\n ohi_tid: claims.ohi_tid,\n ohi_wid: claims.ohi_wid,\n ohi_uid: claims.ohi_uid,\n ohi_uname: claims.ohi_uname,\n };\n}\n\n/** Thrown when JWT claims lack a field required by the workflow user-actor. */\nexport class MissingActorContextError extends Error {\n /** @param message - human-readable description of the missing claim. */\n constructor(message: string) {\n super(message);\n this.name = \"MissingActorContextError\";\n }\n}\n","/**\n * Per-bus `Source` constants for the three OpenHI EventBridge buses.\n *\n * Every workflow event carries one of these values in its EventBridge\n * `Source` field. Bus selection follows ADR-016 §Decision #1.\n *\n * @see https://github.com/codedrifters/openhi-planning/blob/main/docs/src/content/docs/requirements/architectural-decisions/ADR-016-workflow-boundary-strategy.md\n */\n\n/** Source for control-plane workflow events (Tenant / Workspace / User / Membership / Role / RoleAssignment / Configuration). */\nexport const OPENHI_CONTROL_SOURCE = \"openhi.control\" as const;\n\n/** Source for data-plane workflow events (committed writes to the FHIR data store). */\nexport const OPENHI_DATA_SOURCE = \"openhi.data\" as const;\n\n/** Source for ops-plane workflow events (platform telemetry, deployments, build events). */\nexport const OPENHI_OPS_SOURCE = \"openhi.ops\" as const;\n\n/**\n * Discriminated union over the three OpenHI EventBridge sources.\n *\n * A publisher that passes any other string for the EventBridge `Source`\n * field is rejected at compile time.\n */\nexport type OpenHiSource =\n | typeof OPENHI_CONTROL_SOURCE\n | typeof OPENHI_DATA_SOURCE\n | typeof OPENHI_OPS_SOURCE;\n\n/**\n * Default EventBridge bus name for each OpenHI source.\n *\n * Deployments may override per-source via\n * `PublisherOptions.busNameByPlane`.\n */\nexport const DEFAULT_BUS_NAME_BY_SOURCE: Record<OpenHiSource, string> = {\n [OPENHI_CONTROL_SOURCE]: \"openhi-control-event-bus\",\n [OPENHI_DATA_SOURCE]: \"openhi-data-event-bus\",\n [OPENHI_OPS_SOURCE]: \"openhi-ops-event-bus\",\n};\n","import type { OpenHiSource } from \"../sources\";\n\n/**\n * One entry in the workflow detail-type registry.\n *\n * Each registered detail-type binds a typed `detail` payload to:\n * - the EventBridge `Source` (and therefore the bus) it ships on,\n * - the `detail-type` string consumers subscribe to,\n * - per-event metadata (`crossPlane`, `dedupRequired`) read by\n * downstream tooling (AsyncAPI generator, placement matrix).\n *\n * The `_detail` property is a phantom marker type only — never\n * read, never written, never instantiated. It carries the\n * compile-time TDetail through the entry so callers of\n * `publishWorkflowEvent` / `parseWorkflowEvent` see the typed\n * payload at the call site.\n */\nexport interface WorkflowDetailTypeEntry<TDetail> {\n /** Versioned detail-type string, e.g. `tenant.onboarded.v1`. */\n readonly detailType: string;\n /** The bus this detail-type ships on (compile-time enforced). */\n readonly source: OpenHiSource;\n /** Phantom marker carrying the payload shape. */\n readonly _detail?: TDetail;\n /** Marks events that cross plane boundaries (placement-matrix metadata). */\n readonly crossPlane?: boolean;\n /** Marks events that retryable consumers MUST dedupe on. */\n readonly dedupRequired?: boolean;\n}\n\n/**\n * Declare a registry entry with type inference.\n *\n * Call sites:\n *\n * ```ts\n * export const TenantOnboardedV1 = defineDetailType<TenantOnboardedV1Detail>({\n * detailType: \"tenant.onboarded.v1\",\n * source: OPENHI_CONTROL_SOURCE,\n * dedupRequired: true,\n * });\n * ```\n *\n * Detail-type strings follow `<area>.<event>.<version>` (TR-016 §Open\n * Items #2). The conformance regex below is the platform-wide format.\n */\nexport function defineDetailType<TDetail>(\n entry: Omit<WorkflowDetailTypeEntry<TDetail>, \"_detail\">,\n): WorkflowDetailTypeEntry<TDetail> {\n if (!isWellFormedDetailType(entry.detailType)) {\n throw new InvalidDetailTypeRegistrationError(\n `Detail-type \"${entry.detailType}\" does not match the platform-wide format <area>.<event>.v<integer>. See TR-016 §Open Items #2.`,\n );\n }\n return entry;\n}\n\n/**\n * Pattern enforced on every registered detail-type:\n * `<area>.<event>.v<integer>` where each segment is lowercase\n * alphanumeric with optional dashes.\n *\n * Multi-level areas (e.g. `fhir.audit-event.recorded.v1`) are\n * intentionally not yet allowed; TR-016 §Open Items #2 defers that.\n */\nconst DETAIL_TYPE_PATTERN =\n /^[a-z0-9]+(?:-[a-z0-9]+)*\\.[a-z0-9]+(?:-[a-z0-9]+)*\\.v\\d+$/;\n\n/** Return `true` when `detailType` matches the platform-wide format. */\nexport function isWellFormedDetailType(detailType: string): boolean {\n return DETAIL_TYPE_PATTERN.test(detailType);\n}\n\n/** Thrown by `defineDetailType` when the supplied string violates the format. */\nexport class InvalidDetailTypeRegistrationError extends Error {\n /** @param message - human-readable description of the violation. */\n constructor(message: string) {\n super(message);\n this.name = \"InvalidDetailTypeRegistrationError\";\n }\n}\n","import { OPENHI_DATA_SOURCE, OPENHI_OPS_SOURCE } from \"../sources\";\nimport { defineDetailType } from \"./registry\";\n\n/**\n * Owning-entity types covered by the TR-022 hard-delete cascade.\n * The cascade pipeline today targets {@link OWNING_ENTITY_TYPE.Workspace}\n * and {@link OWNING_ENTITY_TYPE.User} — the two owning entities whose\n * deletion orphans adjacency-list projections under their partition.\n * Tenant hard-delete is intentionally out of scope (it cascades a much\n * wider graph and is handled outside this pipeline).\n */\nexport const OWNING_ENTITY_TYPE = {\n Workspace: \"Workspace\",\n User: \"User\",\n} as const;\n/** Union of the values of {@link OWNING_ENTITY_TYPE}. */\nexport type OwningEntityType =\n (typeof OWNING_ENTITY_TYPE)[keyof typeof OWNING_ENTITY_TYPE];\n\n/**\n * Payload (`detail.payload`) of `control-plane.owning-delete.v1` —\n * published on the `openhi.data` data event bus when the Firehose\n * transform Lambda observes a stream record showing\n * `lifecycleState: active → deleting` on a canonical Workspace or\n * User record. The owning-delete cascade state machine subscribes to\n * this detail-type.\n *\n * The full EventBridge `detail` carries this payload nested inside a\n * `WorkflowEvent<ControlPlaneOwningDeleteV1Detail>` envelope per\n * ADR-016 standard envelope shape — `eventId`, `attempt`,\n * `correlationId`, `causationId`, `actor`, `occurredAt` live on the\n * envelope, not on this payload.\n *\n * @see .state/adr-018-implementation-guide.md section 4 (TR-022 Hard-Delete-Cascade Contract)\n */\nexport interface ControlPlaneOwningDeleteV1Detail {\n readonly ownerType: OwningEntityType;\n readonly ownerId: string;\n /** Present for Workspace owners; absent for User (cross-tenant identity). */\n readonly tenantId?: string;\n}\n\n/**\n * Registry entry for `control-plane.owning-delete.v1`.\n *\n * The platform-wide detail-type format\n * (`<area>.<event>.v<integer>` enforced by `isWellFormedDetailType`)\n * does not allow the bare `ControlPlaneOwningDelete` shape the\n * ADR-018 implementation guide pseudocode uses; the registered string\n * is the format-compliant equivalent. The EventBridge rule pattern on\n * the cascade state machine matches this exact string.\n *\n * `dedupRequired: true` — the cascade state machine MUST dedupe on\n * `(eventId, attempt)` via `WorkflowDedupClient` so EventBridge retries\n * (which the data event bus delivers at-least-once) never start two\n * concurrent cascades on the same owning entity.\n */\nexport const ControlPlaneOwningDeleteV1 =\n defineDetailType<ControlPlaneOwningDeleteV1Detail>({\n detailType: \"control-plane.owning-delete.v1\",\n source: OPENHI_DATA_SOURCE,\n dedupRequired: true,\n });\n\n/**\n * Payload of `control-plane.owning-delete-complete.v1` — terminal\n * event published on the `openhi.ops` ops event bus when the cascade\n * state machine has successfully deleted every child projection and\n * the canonical owning record itself. Observability sinks subscribe\n * to this event to confirm cascade completion and emit metrics.\n *\n * @see .state/adr-018-implementation-guide.md section 4 (Terminal events on EventBridge)\n */\nexport interface ControlPlaneOwningDeleteCompleteV1Detail {\n readonly ownerType: OwningEntityType;\n readonly ownerId: string;\n readonly tenantId?: string;\n /** Number of `TransactWriteItems` chunks the cascade issued. */\n readonly chunkCount: number;\n /** Total number of projection rows removed by the cascade. */\n readonly projectionsRemoved: number;\n /** Wall-clock duration of the cascade, in milliseconds. */\n readonly durationMs: number;\n /** ISO-8601 UTC timestamp of cascade completion. */\n readonly completedAt: string;\n}\n\n/** Registry entry for `control-plane.owning-delete-complete.v1`. */\nexport const ControlPlaneOwningDeleteCompleteV1 =\n defineDetailType<ControlPlaneOwningDeleteCompleteV1Detail>({\n detailType: \"control-plane.owning-delete-complete.v1\",\n source: OPENHI_OPS_SOURCE,\n dedupRequired: true,\n });\n\n/**\n * Payload of `control-plane.owning-delete-failed.v1` — terminal event\n * published on the `openhi.ops` ops event bus when the cascade state\n * machine fails irrecoverably. The canonical owning record is left at\n * `lifecycleState = \"deleted-failed\"` for operator-driven recovery;\n * alerting subscribers fan out to oncall.\n *\n * @see .state/adr-018-implementation-guide.md section 4 (Terminal events on EventBridge)\n */\nexport interface ControlPlaneOwningDeleteFailedV1Detail {\n readonly ownerType: OwningEntityType;\n readonly ownerId: string;\n readonly tenantId?: string;\n /** Step Functions execution ARN — operators dereference for root cause. */\n readonly executionArn: string;\n readonly chunkCount: number;\n /** Last opaque cursor the state machine successfully processed, or null. */\n readonly lastProcessedCursor: string | null;\n /** Short failure cause string from the Step Functions Catch block. */\n readonly failureCause: string;\n readonly failedAt: string;\n}\n\n/** Registry entry for `control-plane.owning-delete-failed.v1`. */\nexport const ControlPlaneOwningDeleteFailedV1 =\n defineDetailType<ControlPlaneOwningDeleteFailedV1Detail>({\n detailType: \"control-plane.owning-delete-failed.v1\",\n source: OPENHI_OPS_SOURCE,\n dedupRequired: true,\n });\n\n/**\n * Renamable entity types covered by the TR-023 rename cascade.\n *\n * Per ADR-018 only the three carrier entities whose display name is\n * denormalized onto Membership / RoleAssignment projections trigger a\n * cascade — Tenant, User, Role. A Workspace rename is intentionally\n * **not** in scope: Workspace's display name is denormalized onto the\n * Membership user-projection workspace sub-lane, but TR-024 § Open Item\n * #4 defers a formal Workspace-rename cascade — the SK falls back to a\n * sentinel until a future TR commits the contract.\n */\nexport const RENAMABLE_ENTITY_TYPE = {\n Tenant: \"Tenant\",\n User: \"User\",\n Role: \"Role\",\n} as const;\n/** Union of the values of {@link RENAMABLE_ENTITY_TYPE}. */\nexport type RenamableEntityType =\n (typeof RENAMABLE_ENTITY_TYPE)[keyof typeof RENAMABLE_ENTITY_TYPE];\n\n/**\n * Payload (`detail.payload`) of `control-plane.rename.v1` — published\n * on the `openhi.data` data event bus when the Firehose transform\n * Lambda observes a stream record showing a display-name change on a\n * canonical Tenant, User, or Role record. The rename-cascade state\n * machine subscribes to this detail-type.\n *\n * The full EventBridge `detail` carries this payload nested inside a\n * `WorkflowEvent<ControlPlaneRenameV1Detail>` envelope per ADR-016\n * standard envelope shape — `eventId`, `attempt`, `correlationId`,\n * `causationId`, `actor`, `occurredAt` live on the envelope, not on\n * this payload.\n *\n * The platform-wide detail-type format\n * (`<area>.<event>.v<integer>` enforced by `isWellFormedDetailType`)\n * does not allow the bare `ControlPlaneRename` shape the ADR-018\n * implementation guide pseudocode uses; the registered string is the\n * format-compliant equivalent (mirroring the\n * `control-plane.owning-delete.v1` naming).\n *\n * @see .state/adr-018-implementation-guide.md section 5 (TR-023 Rename-Cascade Consumer Contract)\n */\nexport interface ControlPlaneRenameV1Detail {\n readonly entityType: RenamableEntityType;\n readonly entityId: string;\n /** Present for User and Role; absent for Tenant (Tenant is the partition root). */\n readonly tenantId?: string;\n readonly oldName: string;\n readonly newName: string;\n /** Pre-computed via `extractLabel` so consumers do not re-normalize. */\n readonly oldNormalizedName: string;\n readonly newNormalizedName: string;\n}\n\n/**\n * Registry entry for `control-plane.rename.v1`.\n *\n * `dedupRequired: true` — the cascade state machine MUST dedupe on\n * `(eventId, attempt)` via `WorkflowDedupClient` so EventBridge retries\n * (which the data event bus delivers at-least-once) never start two\n * concurrent cascades on the same rename.\n */\nexport const ControlPlaneRenameV1 =\n defineDetailType<ControlPlaneRenameV1Detail>({\n detailType: \"control-plane.rename.v1\",\n source: OPENHI_DATA_SOURCE,\n dedupRequired: true,\n });\n\n/**\n * Payload of `control-plane.rename-complete.v1` — terminal event\n * published on the `openhi.ops` ops event bus when the cascade state\n * machine has successfully rewritten every affected projection row.\n * UI clients subscribe so they can refresh stale list views.\n *\n * @see .state/adr-018-implementation-guide.md section 5\n */\nexport interface ControlPlaneRenameCompleteV1Detail {\n readonly entityType: RenamableEntityType;\n readonly entityId: string;\n readonly tenantId?: string;\n readonly newName: string;\n /** Number of `TransactWriteItems` chunks the cascade issued. */\n readonly chunkCount: number;\n /** Total number of projection rows rewritten by the cascade. */\n readonly itemsRewritten: number;\n /** Wall-clock duration of the cascade, in milliseconds. */\n readonly durationMs: number;\n /** ISO-8601 UTC timestamp of cascade completion. */\n readonly completedAt: string;\n}\n\n/** Registry entry for `control-plane.rename-complete.v1`. */\nexport const ControlPlaneRenameCompleteV1 =\n defineDetailType<ControlPlaneRenameCompleteV1Detail>({\n detailType: \"control-plane.rename-complete.v1\",\n source: OPENHI_OPS_SOURCE,\n dedupRequired: true,\n });\n\n/**\n * Payload of `control-plane.rename-failed.v1` — terminal event\n * published on the `openhi.ops` ops event bus when the cascade state\n * machine fails irrecoverably. Alerting subscribers fan out to oncall.\n *\n * @see .state/adr-018-implementation-guide.md section 5\n */\nexport interface ControlPlaneRenameFailedV1Detail {\n readonly entityType: RenamableEntityType;\n readonly entityId: string;\n readonly tenantId?: string;\n /** Step Functions execution ARN — operators dereference for root cause. */\n readonly executionArn: string;\n readonly chunkCount: number;\n /** Short failure cause string from the Step Functions Catch block. */\n readonly failureCause: string;\n readonly failedAt: string;\n}\n\n/** Registry entry for `control-plane.rename-failed.v1`. */\nexport const ControlPlaneRenameFailedV1 =\n defineDetailType<ControlPlaneRenameFailedV1Detail>({\n detailType: \"control-plane.rename-failed.v1\",\n source: OPENHI_OPS_SOURCE,\n dedupRequired: true,\n });\n","import { OPENHI_CONTROL_SOURCE } from \"../sources\";\nimport { defineDetailType } from \"./registry\";\n\n/**\n * `detail` payload for `platform.deployment-completed.v1`.\n *\n * Projected by the platform-deploy bridge from a CloudFormation\n * `Stack Status Change` event (`CREATE_COMPLETE` / `UPDATE_COMPLETE`)\n * on a tagged OpenHI platform stack. Downstream control-plane\n * workflows (e.g. seed-system-roles, seed-demo-data) subscribe\n * to this detail-type on the control event bus.\n */\nexport interface PlatformDeploymentCompletedV1Detail {\n /** CloudFormation stack name (`AWS::CloudFormation::Stack` `StackName`). */\n readonly stackName: string;\n /** Full CloudFormation stack ARN. */\n readonly stackId: string;\n /** AWS region the stack deployed into (e.g. `us-east-1`). */\n readonly region: string;\n /** 12-digit AWS account id the stack deployed into. */\n readonly accountId: string;\n /** Terminal stack status that triggered the bridge. */\n readonly status: \"CREATE_COMPLETE\" | \"UPDATE_COMPLETE\";\n /** Free-form reason text from CloudFormation; absent on most events. */\n readonly statusReason?: string;\n /**\n * Projected subset of stack tags. The bridge resolves tags via\n * `cloudformation:DescribeStacks` because the source EventBridge\n * event omits them.\n */\n readonly stackTags: ReadonlyArray<{\n readonly key: string;\n readonly value: string;\n }>;\n /** ISO-8601 timestamp from the source EventBridge `time` field. */\n readonly cloudformationEventTime: string;\n}\n\n/**\n * Registry entry for `platform.deployment-completed.v1`.\n *\n * Published on the control event bus (`OPENHI_CONTROL_SOURCE`) per\n * the workflow placement matrix (codedrifters/openhi#953 row 4):\n * the AWS-native source is the ops-plane default bus, but the bridge\n * republishes onto the control bus because the downstream consumers\n * are control-plane workflows.\n *\n * `dedupRequired: true` — at-least-once redelivery from EventBridge\n * means retryable consumers MUST dedupe on `(eventId, attempt)` via\n * `WorkflowDedupClient`.\n */\nexport const PlatformDeploymentCompletedV1 =\n defineDetailType<PlatformDeploymentCompletedV1Detail>({\n detailType: \"platform.deployment-completed.v1\",\n source: OPENHI_CONTROL_SOURCE,\n dedupRequired: true,\n });\n\n/**\n * `detail` payload for `platform.system-data-seeded.v1`.\n *\n * Published by the `seed-system-data` workflow after it has\n * idempotently re-asserted every platform-singleton control-plane\n * record (today: the three canonical Roles; future: additional system\n * data) on the back of a `platform.deployment-completed.v1` event.\n *\n * Downstream control-plane workflows that depend on the\n * platform-singleton records existing — `seed-demo-data`, for\n * example — subscribe to this detail-type instead of the raw\n * deploy-completion event so the dependency is enforced by a\n * happens-before edge rather than by EventBridge retry timing.\n */\nexport interface PlatformSystemDataSeededV1Detail {\n /**\n * EventBridge `eventId` of the originating\n * `platform.deployment-completed.v1` event that triggered the\n * system-data seeding. Propagated for correlation in logs and\n * downstream causation chains.\n */\n readonly sourceEventId: string;\n /**\n * Full CloudFormation stack ARN of the deploy that triggered the\n * system-data seeding. Mirrors the field on the originating\n * `PlatformDeploymentCompletedV1Detail`; downstream consumers can\n * filter by stack-id prefix without re-reading the source event.\n */\n readonly sourceStackId: string;\n /**\n * Number of platform-singleton records re-asserted on this run.\n * Useful for sanity checks and observability — divergence between\n * deploys signals either a generator-emitted catalog change or a\n * partial-failure recovery from the replay tooling.\n */\n readonly seededRecordCount: number;\n}\n\n/**\n * Registry entry for `platform.system-data-seeded.v1`.\n *\n * Published onto the control event bus (`OPENHI_CONTROL_SOURCE`).\n * `dedupRequired: true` — downstream consumers MUST dedup on\n * `(eventId, attempt)` via `WorkflowDedupClient`, same as every other\n * retryable consumer.\n */\nexport const PlatformSystemDataSeededV1 =\n defineDetailType<PlatformSystemDataSeededV1Detail>({\n detailType: \"platform.system-data-seeded.v1\",\n source: OPENHI_CONTROL_SOURCE,\n dedupRequired: true,\n });\n","export * from \"./control-plane\";\nexport * from \"./platform\";\nexport * from \"./registry\";\n","import { randomUUID } from \"node:crypto\";\nimport {\n EventBridgeClient,\n PutEventsCommand,\n} from \"@aws-sdk/client-eventbridge\";\n\nimport type { WorkflowDetailTypeEntry } from \"./detail-types/registry\";\nimport type { WorkflowActor, WorkflowEvent } from \"./envelope\";\nimport { ENVELOPE_VERSION } from \"./envelope-version\";\nimport { DEFAULT_BUS_NAME_BY_SOURCE, type OpenHiSource } from \"./sources\";\n\n/**\n * Caller-supplied envelope context the publisher consumes.\n *\n * The actor is required on every publish — pre-provisioning bootstrap\n * workflows pass a `{ system: <role-name> }` actor.\n *\n * `correlationId` and `causationId` propagate from an upstream event\n * when this publisher is consuming-then-publishing; pass them through\n * verbatim from the inbound envelope's fields. Both are optional;\n * when omitted the publisher treats the publish as a chain origin\n * (`correlationId` = fresh UUID, `causationId` = null).\n */\nexport interface PublishContext {\n readonly actor: WorkflowActor;\n readonly correlationId?: string;\n readonly causationId?: string | null;\n}\n\n/**\n * Per-call output of a successful publish.\n */\nexport interface PublishResult {\n readonly eventId: string;\n}\n\n/**\n * Publisher overrides applied to every call against a single client.\n *\n * `eventIdGenerator`, `correlationIdGenerator`, and `now` are\n * test-only seams; production callers omit them and the publisher\n * uses `crypto.randomUUID()` and `new Date()`.\n */\nexport interface PublisherOptions {\n /** Override the default bus name for one or more sources. */\n readonly busNameByPlane?: Partial<Record<OpenHiSource, string>>;\n /** Test seam — supply a deterministic UUID generator for `eventId`. */\n readonly eventIdGenerator?: () => string;\n /** Test seam — supply a deterministic UUID generator for new `correlationId` values. */\n readonly correlationIdGenerator?: () => string;\n /** Test seam — supply a deterministic clock for `occurredAt`. */\n readonly now?: () => Date;\n}\n\n/**\n * Tree-shaped publisher client per ADR-016 Recommendation.\n *\n * The `publish` primitive accepts any registered detail-type and\n * returns a typed `PublishResult`. Downstream tree shaping\n * (`client.<bus>.<area>.<event>.publish(payload, ctx)`) is built from\n * the detail-type registry once entries are registered; until then,\n * callers invoke `client.publish(entry, payload, ctx)` directly.\n */\nexport interface WorkflowsClient {\n /**\n * Construct a workflow envelope around `payload` and publish it to\n * the EventBridge bus configured for `entry.source`.\n */\n publish<TPayload>(\n entry: WorkflowDetailTypeEntry<TPayload>,\n payload: TPayload,\n ctx: PublishContext,\n ): Promise<PublishResult>;\n}\n\n/**\n * Factory that returns a `WorkflowsClient` bound to a single\n * `EventBridgeClient`.\n */\nexport function workflowsClient(\n bridge: EventBridgeClient,\n options: PublisherOptions = {},\n): WorkflowsClient {\n return {\n publish: (entry, payload, ctx) =>\n publishWorkflowEvent(bridge, entry, payload, ctx, options),\n };\n}\n\n/**\n * Construct a workflow envelope and publish it via\n * `EventBridge.PutEvents`.\n *\n * Exposed as a stand-alone function for callers that prefer the\n * primitive over the `WorkflowsClient` indirection.\n */\nexport async function publishWorkflowEvent<TPayload>(\n bridge: EventBridgeClient,\n entry: WorkflowDetailTypeEntry<TPayload>,\n payload: TPayload,\n ctx: PublishContext,\n options: PublisherOptions = {},\n): Promise<PublishResult> {\n const eventIdGenerator = options.eventIdGenerator ?? (() => randomUUID());\n const correlationIdGenerator =\n options.correlationIdGenerator ?? (() => randomUUID());\n const now = options.now ?? (() => new Date());\n\n const envelope: WorkflowEvent<TPayload> = {\n eventId: eventIdGenerator(),\n attempt: 1,\n correlationId: ctx.correlationId ?? correlationIdGenerator(),\n causationId: ctx.causationId ?? null,\n actor: ctx.actor,\n occurredAt: now().toISOString(),\n envelopeVersion: ENVELOPE_VERSION,\n payload,\n };\n\n const busName =\n options.busNameByPlane?.[entry.source] ??\n DEFAULT_BUS_NAME_BY_SOURCE[entry.source];\n\n const result = await bridge.send(\n new PutEventsCommand({\n Entries: [\n {\n EventBusName: busName,\n Source: entry.source,\n DetailType: entry.detailType,\n Detail: JSON.stringify(envelope),\n },\n ],\n }),\n );\n\n if ((result.FailedEntryCount ?? 0) > 0) {\n const first = result.Entries?.[0];\n throw new WorkflowPublishError(\n `EventBridge rejected ${entry.detailType} publish on bus ${busName}: ${first?.ErrorCode ?? \"unknown\"} — ${first?.ErrorMessage ?? \"no error message\"}`,\n );\n }\n\n return { eventId: envelope.eventId };\n}\n\n/** Thrown when EventBridge rejects a `PutEvents` entry. */\nexport class WorkflowPublishError extends Error {\n /** @param message - human-readable description of the failed publish. */\n constructor(message: string) {\n super(message);\n this.name = \"WorkflowPublishError\";\n }\n}\n","import type { WorkflowDetailTypeEntry } from \"./detail-types/registry\";\nimport type { WorkflowEvent } from \"./envelope\";\nimport { isSupportedEnvelopeVersion } from \"./envelope-version\";\n\n/**\n * Structural shape of the EventBridge event objects this SDK's\n * consumer parses.\n *\n * Matches `@types/aws-lambda`'s `EventBridgeEvent<string, unknown>`\n * by structural compatibility without requiring callers to import\n * that types package — consumers may pass either an\n * `EventBridgeEvent` from `aws-lambda` or any record-shaped object\n * carrying the same keys.\n */\nexport interface EventBridgeEventLike {\n readonly source: string;\n readonly \"detail-type\": string;\n readonly detail: unknown;\n}\n\n/**\n * The `(eventId, attempt)` tuple every retryable consumer hands to\n * the `WorkflowDedupTable` client.\n */\nexport interface DedupKey {\n readonly eventId: string;\n readonly attempt: number;\n}\n\n/**\n * Output of `parseWorkflowEvent` — the validated envelope plus the\n * dedup tuple.\n */\nexport interface ParsedWorkflowEvent<TPayload> {\n readonly envelope: WorkflowEvent<TPayload>;\n readonly dedupKey: DedupKey;\n}\n\n/**\n * Parse an EventBridge event into a typed envelope and surface the\n * `(eventId, attempt)` tuple the dedup-table client consumes.\n *\n * Validates:\n * - `event.source` matches `expected.source`\n * - `event[\"detail-type\"]` matches `expected.detailType`\n * - the envelope's `envelopeVersion` is within the SDK's supported range\n * - every required envelope field is present and well-shaped\n */\nexport function parseWorkflowEvent<TPayload>(\n event: EventBridgeEventLike,\n expected: WorkflowDetailTypeEntry<TPayload>,\n): ParsedWorkflowEvent<TPayload> {\n if (event.source !== expected.source) {\n throw new InvalidWorkflowEventError(\n `EventBridge source \"${event.source}\" does not match expected detail-type's source \"${expected.source}\".`,\n );\n }\n\n if (event[\"detail-type\"] !== expected.detailType) {\n throw new InvalidWorkflowEventError(\n `EventBridge detail-type \"${event[\"detail-type\"]}\" does not match expected \"${expected.detailType}\".`,\n );\n }\n\n const candidate = asEnvelopeCandidate(event.detail);\n\n if (!isSupportedEnvelopeVersion(candidate.envelopeVersion)) {\n throw new UnsupportedEnvelopeVersionError(\n `Envelope version \"${candidate.envelopeVersion}\" is outside the SDK's supported range.`,\n );\n }\n\n const envelope: WorkflowEvent<TPayload> = {\n eventId: candidate.eventId,\n attempt: candidate.attempt,\n correlationId: candidate.correlationId,\n causationId: candidate.causationId,\n actor: candidate.actor,\n occurredAt: candidate.occurredAt,\n envelopeVersion: candidate.envelopeVersion,\n payload: candidate.payload as TPayload,\n };\n\n return {\n envelope,\n dedupKey: { eventId: envelope.eventId, attempt: envelope.attempt },\n };\n}\n\n/**\n * Validate that the EventBridge `detail` (which carries the workflow\n * envelope) has every required field with a plausible type. Returns a\n * typed `WorkflowEvent<unknown>` so the caller can narrow `payload`\n * once routing has succeeded.\n */\nfunction asEnvelopeCandidate(detail: unknown): WorkflowEvent<unknown> {\n if (detail === null || typeof detail !== \"object\") {\n throw new InvalidWorkflowEventError(\n \"EventBridge detail is not a non-null object.\",\n );\n }\n\n const obj = detail as Record<string, unknown>;\n\n assertString(obj, \"eventId\");\n assertPositiveInteger(obj, \"attempt\");\n assertString(obj, \"correlationId\");\n assertCausationId(obj);\n assertActor(obj);\n assertString(obj, \"occurredAt\");\n assertString(obj, \"envelopeVersion\");\n\n if (!(\"payload\" in obj)) {\n throw new InvalidWorkflowEventError(\n \"Envelope is missing required field: payload.\",\n );\n }\n\n return obj as unknown as WorkflowEvent<unknown>;\n}\n\nfunction assertString(\n obj: Record<string, unknown>,\n field: string,\n): asserts obj is Record<string, unknown> & Record<typeof field, string> {\n const value = obj[field];\n if (typeof value !== \"string\" || value.length === 0) {\n throw new InvalidWorkflowEventError(\n `Envelope field \"${field}\" must be a non-empty string.`,\n );\n }\n}\n\nfunction assertPositiveInteger(\n obj: Record<string, unknown>,\n field: string,\n): void {\n const value = obj[field];\n if (typeof value !== \"number\" || !Number.isInteger(value) || value < 1) {\n throw new InvalidWorkflowEventError(\n `Envelope field \"${field}\" must be a 1-indexed integer.`,\n );\n }\n}\n\nfunction assertCausationId(obj: Record<string, unknown>): void {\n if (!(\"causationId\" in obj)) {\n throw new InvalidWorkflowEventError(\n \"Envelope is missing required field: causationId.\",\n );\n }\n const value = obj.causationId;\n if (value !== null && (typeof value !== \"string\" || value.length === 0)) {\n throw new InvalidWorkflowEventError(\n 'Envelope field \"causationId\" must be a non-empty string or null.',\n );\n }\n}\n\nfunction assertActor(obj: Record<string, unknown>): void {\n const actor = obj.actor;\n if (actor === null || typeof actor !== \"object\") {\n throw new InvalidWorkflowEventError(\n 'Envelope field \"actor\" must be an object.',\n );\n }\n const actorObj = actor as Record<string, unknown>;\n const isUserActor =\n typeof actorObj.ohi_uid === \"string\" &&\n typeof actorObj.ohi_uname === \"string\" &&\n typeof actorObj.ohi_tid === \"string\" &&\n typeof actorObj.ohi_wid === \"string\";\n const isSystemActor = typeof actorObj.system === \"string\";\n if (!isUserActor && !isSystemActor) {\n throw new InvalidWorkflowEventError(\n 'Envelope field \"actor\" must be either a user-actor (ohi_tid, ohi_wid, ohi_uid, ohi_uname) or a system-actor ({ system: string }).',\n );\n }\n}\n\n/** Thrown when the event does not match the expected detail-type entry. */\nexport class InvalidWorkflowEventError extends Error {\n /** @param message - human-readable description of the validation failure. */\n constructor(message: string) {\n super(message);\n this.name = \"InvalidWorkflowEventError\";\n }\n}\n\n/** Thrown when the envelope version is outside the SDK's supported range. */\nexport class UnsupportedEnvelopeVersionError extends Error {\n /** @param message - human-readable description of the unsupported version. */\n constructor(message: string) {\n super(message);\n this.name = \"UnsupportedEnvelopeVersionError\";\n }\n}\n","/**\n * Environment-variable name the construct's `grantConsumer` integration\n * injects into a consumer Lambda; the runtime `WorkflowDedupClient`\n * reads it to discover the shared dedup table without a prop or import.\n *\n * The constant is the single cross-package contract between\n * `@openhi/constructs` (which emits the env var) and `@openhi/workflows`\n * (which consumes it). Renaming or removing it is a breaking change.\n */\nexport const WORKFLOW_DEDUP_TABLE_NAME_ENV_VAR =\n \"OPENHI_WORKFLOW_DEDUP_TABLE_NAME\";\n\n/** Default TTL for dedup rows: 14 days, expressed in seconds (per TR-015). */\nexport const WORKFLOW_DEDUP_DEFAULT_TTL_SECONDS = 14 * 24 * 60 * 60;\n\n/** Maximum length of a `consumerName` (per TR-015). */\nexport const WORKFLOW_DEDUP_MAX_CONSUMER_NAME_LENGTH = 64;\n","import {\n ConditionalCheckFailedException,\n DynamoDBClient,\n PutItemCommand,\n UpdateItemCommand,\n} from \"@aws-sdk/client-dynamodb\";\n\nimport {\n WORKFLOW_DEDUP_DEFAULT_TTL_SECONDS,\n WORKFLOW_DEDUP_MAX_CONSUMER_NAME_LENGTH,\n WORKFLOW_DEDUP_TABLE_NAME_ENV_VAR,\n} from \"./env\";\n\n/**\n * Inputs to `recordIfAbsent`.\n *\n * `eventId` and `attempt` are the dedup tuple every retryable\n * consumer derives from the standard envelope (see `parseWorkflowEvent`\n * and the `DedupKey` type); call sites typically spread the dedupKey\n * directly alongside the consumer name.\n */\nexport interface RecordIfAbsentInput {\n /** Stable logical name of the consumer. At most 64 chars; no whitespace. */\n readonly consumerName: string;\n /** Per-event UUID from the standard envelope. */\n readonly eventId: string;\n /** 1-indexed delivery attempt from the standard envelope. */\n readonly attempt: number;\n /** Override the 14-day default TTL. Must be a positive integer. */\n readonly ttlSeconds?: number;\n}\n\n/**\n * Result shape per TR-015. `recorded` is true on first delivery and\n * false on a duplicate; on a duplicate `alreadyProcessed` is also\n * true so callers can pattern-match without re-checking the boolean.\n */\nexport type RecordIfAbsentResult =\n | { readonly recorded: true }\n | { readonly recorded: false; readonly alreadyProcessed: true };\n\n/**\n * Inputs to `markFailed`.\n *\n * Updates the existing dedup row with `failed: true`, `failureReason`,\n * `failedAt` so the replay tooling (TR-016 follow-up) can re-publish\n * the originating event with a fresh `attempt`.\n */\nexport interface MarkFailedInput {\n /** Stable logical name of the consumer. */\n readonly consumerName: string;\n /** Per-event UUID. */\n readonly eventId: string;\n /** 1-indexed delivery attempt. */\n readonly attempt: number;\n /** Short string describing why the consumer gave up. */\n readonly reason: string;\n}\n\n/**\n * Runtime SDK every retryable workflow consumer calls before\n * performing its side-effect. See TR-015 for the contract.\n */\nexport interface WorkflowDedupClient {\n /**\n * Conditionally record a dedup token for the supplied consumer name\n * and dedup tuple. See `RecordIfAbsentResult` for the return shape.\n */\n recordIfAbsent(input: RecordIfAbsentInput): Promise<RecordIfAbsentResult>;\n /**\n * Mark the existing dedup row as permanently failed. Fire-and-forget\n * semantics for the caller; unexpected DynamoDB errors propagate.\n */\n markFailed(input: MarkFailedInput): Promise<void>;\n}\n\n/** Options shared by the factory and the standalone primitives. */\nexport interface WorkflowDedupClientOptions {\n /**\n * Table name. Defaults to `process.env[WORKFLOW_DEDUP_TABLE_NAME_ENV_VAR]`\n * (populated by the `WorkflowDedupTable` construct's `grantConsumer`).\n */\n readonly tableName?: string;\n /** Override the 14-day default TTL for every `recordIfAbsent` call. */\n readonly defaultTtlSeconds?: number;\n /** Test seam — deterministic clock for `recordedAt` / `expiresAt`. */\n readonly now?: () => Date;\n}\n\n/** Factory that returns a `WorkflowDedupClient` bound to a single DynamoDB client. */\nexport function workflowDedupClient(\n dynamodb: DynamoDBClient,\n options: WorkflowDedupClientOptions = {},\n): WorkflowDedupClient {\n return {\n recordIfAbsent: (input) => recordIfAbsent(dynamodb, input, options),\n markFailed: (input) => markFailed(dynamodb, input, options),\n };\n}\n\n/**\n * Standalone primitive — exposed for callers that prefer it over the\n * `WorkflowDedupClient` indirection.\n */\nexport async function recordIfAbsent(\n dynamodb: DynamoDBClient,\n input: RecordIfAbsentInput,\n options: WorkflowDedupClientOptions = {},\n): Promise<RecordIfAbsentResult> {\n assertConsumerName(input.consumerName);\n assertPositiveInteger(input.attempt, \"attempt\");\n const ttlSeconds =\n input.ttlSeconds ??\n options.defaultTtlSeconds ??\n WORKFLOW_DEDUP_DEFAULT_TTL_SECONDS;\n if (!Number.isInteger(ttlSeconds) || ttlSeconds <= 0) {\n throw new WorkflowDedupInvalidInputError(\n `ttlSeconds must be a positive integer; got ${ttlSeconds}.`,\n );\n }\n\n const tableName = resolveTableName(options.tableName);\n const now = (options.now ?? defaultNow)();\n const sk = encodeSortKey(input.eventId, input.attempt);\n const expiresAt = Math.floor(now.getTime() / 1000) + ttlSeconds;\n\n try {\n await dynamodb.send(\n new PutItemCommand({\n TableName: tableName,\n Item: {\n consumerName: { S: input.consumerName },\n sk: { S: sk },\n eventId: { S: input.eventId },\n attempt: { N: String(input.attempt) },\n recordedAt: { S: now.toISOString() },\n expiresAt: { N: String(expiresAt) },\n },\n ConditionExpression:\n \"attribute_not_exists(consumerName) AND attribute_not_exists(sk)\",\n }),\n );\n return { recorded: true };\n } catch (err) {\n if (err instanceof ConditionalCheckFailedException) {\n return { recorded: false, alreadyProcessed: true };\n }\n throw err;\n }\n}\n\n/** Standalone primitive — flips `failed: true` on an existing dedup row. */\nexport async function markFailed(\n dynamodb: DynamoDBClient,\n input: MarkFailedInput,\n options: WorkflowDedupClientOptions = {},\n): Promise<void> {\n assertConsumerName(input.consumerName);\n assertPositiveInteger(input.attempt, \"attempt\");\n if (input.reason.length === 0) {\n throw new WorkflowDedupInvalidInputError(\"reason must be non-empty.\");\n }\n\n const tableName = resolveTableName(options.tableName);\n const now = (options.now ?? defaultNow)();\n const sk = encodeSortKey(input.eventId, input.attempt);\n\n await dynamodb.send(\n new UpdateItemCommand({\n TableName: tableName,\n Key: {\n consumerName: { S: input.consumerName },\n sk: { S: sk },\n },\n UpdateExpression:\n \"SET #failed = :failed, #failureReason = :reason, #failedAt = :failedAt\",\n ExpressionAttributeNames: {\n \"#failed\": \"failed\",\n \"#failureReason\": \"failureReason\",\n \"#failedAt\": \"failedAt\",\n },\n ExpressionAttributeValues: {\n \":failed\": { BOOL: true },\n \":reason\": { S: input.reason },\n \":failedAt\": { S: now.toISOString() },\n },\n }),\n );\n}\n\n/** Compose the composite sort key per the TR-015 encoding. */\nexport function encodeSortKey(eventId: string, attempt: number): string {\n if (eventId.length === 0) {\n throw new WorkflowDedupInvalidInputError(\"eventId must be non-empty.\");\n }\n return `${eventId}#${attempt}`;\n}\n\nfunction resolveTableName(explicit?: string): string {\n const name = explicit ?? process.env[WORKFLOW_DEDUP_TABLE_NAME_ENV_VAR];\n if (!name) {\n throw new WorkflowDedupTableNameMissingError(\n `Workflow dedup table name not set. Pass options.tableName or set ${WORKFLOW_DEDUP_TABLE_NAME_ENV_VAR}.`,\n );\n }\n return name;\n}\n\nfunction assertConsumerName(consumerName: string): void {\n if (consumerName.length === 0) {\n throw new WorkflowDedupInvalidInputError(\"consumerName must be non-empty.\");\n }\n if (consumerName.length > WORKFLOW_DEDUP_MAX_CONSUMER_NAME_LENGTH) {\n throw new WorkflowDedupInvalidInputError(\n `consumerName must be ≤${WORKFLOW_DEDUP_MAX_CONSUMER_NAME_LENGTH} chars; got ${consumerName.length}.`,\n );\n }\n if (/\\s/.test(consumerName)) {\n throw new WorkflowDedupInvalidInputError(\n \"consumerName must not contain whitespace.\",\n );\n }\n}\n\nfunction assertPositiveInteger(value: number, field: string): void {\n if (!Number.isInteger(value) || value < 1) {\n throw new WorkflowDedupInvalidInputError(\n `${field} must be a 1-indexed integer; got ${value}.`,\n );\n }\n}\n\nfunction defaultNow(): Date {\n return new Date();\n}\n\n/** Thrown when the dedup table name cannot be resolved. */\nexport class WorkflowDedupTableNameMissingError extends Error {\n /** @param message - human-readable description. */\n constructor(message: string) {\n super(message);\n this.name = \"WorkflowDedupTableNameMissingError\";\n }\n}\n\n/** Thrown when an input violates a TR-015 invariant. */\nexport class WorkflowDedupInvalidInputError extends Error {\n /** @param message - human-readable description. */\n constructor(message: string) {\n super(message);\n this.name = \"WorkflowDedupInvalidInputError\";\n }\n}\n","export {\n WORKFLOW_DEDUP_DEFAULT_TTL_SECONDS,\n WORKFLOW_DEDUP_MAX_CONSUMER_NAME_LENGTH,\n WORKFLOW_DEDUP_TABLE_NAME_ENV_VAR,\n} from \"./env\";\nexport {\n WorkflowDedupInvalidInputError,\n WorkflowDedupTableNameMissingError,\n encodeSortKey,\n markFailed,\n recordIfAbsent,\n workflowDedupClient,\n} from \"./workflow-dedup-client\";\nexport type {\n MarkFailedInput,\n RecordIfAbsentInput,\n RecordIfAbsentResult,\n WorkflowDedupClient,\n WorkflowDedupClientOptions,\n} from \"./workflow-dedup-client\";\n","export {\n ENVELOPE_VERSION,\n isSupportedEnvelopeVersion,\n} from \"./envelope-version\";\nexport {\n MissingActorContextError,\n isWorkflowSystemActor,\n isWorkflowUserActor,\n workflowUserActorFromClaims,\n} from \"./envelope\";\nexport type {\n WorkflowActor,\n WorkflowEvent,\n WorkflowSystemActor,\n WorkflowUserActor,\n} from \"./envelope\";\nexport {\n DEFAULT_BUS_NAME_BY_SOURCE,\n OPENHI_CONTROL_SOURCE,\n OPENHI_DATA_SOURCE,\n OPENHI_OPS_SOURCE,\n} from \"./sources\";\nexport type { OpenHiSource } from \"./sources\";\nexport {\n ControlPlaneOwningDeleteCompleteV1,\n ControlPlaneOwningDeleteFailedV1,\n ControlPlaneOwningDeleteV1,\n ControlPlaneRenameCompleteV1,\n ControlPlaneRenameFailedV1,\n ControlPlaneRenameV1,\n InvalidDetailTypeRegistrationError,\n OWNING_ENTITY_TYPE,\n PlatformDeploymentCompletedV1,\n PlatformSystemDataSeededV1,\n RENAMABLE_ENTITY_TYPE,\n defineDetailType,\n isWellFormedDetailType,\n} from \"./detail-types\";\nexport type {\n ControlPlaneOwningDeleteCompleteV1Detail,\n ControlPlaneOwningDeleteFailedV1Detail,\n ControlPlaneOwningDeleteV1Detail,\n ControlPlaneRenameCompleteV1Detail,\n ControlPlaneRenameFailedV1Detail,\n ControlPlaneRenameV1Detail,\n OwningEntityType,\n PlatformDeploymentCompletedV1Detail,\n PlatformSystemDataSeededV1Detail,\n RenamableEntityType,\n WorkflowDetailTypeEntry,\n} from \"./detail-types\";\nexport {\n WorkflowPublishError,\n publishWorkflowEvent,\n workflowsClient,\n} from \"./publisher\";\nexport type {\n PublishContext,\n PublishResult,\n PublisherOptions,\n WorkflowsClient,\n} from \"./publisher\";\nexport {\n InvalidWorkflowEventError,\n UnsupportedEnvelopeVersionError,\n parseWorkflowEvent,\n} from \"./consumer\";\nexport type {\n DedupKey,\n EventBridgeEventLike,\n ParsedWorkflowEvent,\n} from \"./consumer\";\nexport {\n WORKFLOW_DEDUP_DEFAULT_TTL_SECONDS,\n WORKFLOW_DEDUP_MAX_CONSUMER_NAME_LENGTH,\n WORKFLOW_DEDUP_TABLE_NAME_ENV_VAR,\n WorkflowDedupInvalidInputError,\n WorkflowDedupTableNameMissingError,\n encodeSortKey,\n markFailed,\n recordIfAbsent,\n workflowDedupClient,\n} from \"./dedup\";\nexport type {\n MarkFailedInput,\n RecordIfAbsentInput,\n RecordIfAbsentResult,\n WorkflowDedupClient,\n WorkflowDedupClientOptions,\n} from \"./dedup\";\n","import {\n AdminCreateUserCommand,\n AdminGetUserCommand,\n AdminSetUserPasswordCommand,\n CognitoIdentityProviderClient,\n UsernameExistsException,\n type AttributeType,\n} from \"@aws-sdk/client-cognito-identity-provider\";\nimport { DynamoDBClient } from \"@aws-sdk/client-dynamodb\";\nimport {\n GetParameterCommand,\n ParameterNotFound,\n SSMClient,\n} from \"@aws-sdk/client-ssm\";\nimport {\n PLATFORM_ROLE_CODE,\n PLATFORM_ROLE_CONCEPTS,\n PLATFORM_ROLE_IDS,\n extractSummary,\n type PlatformRoleCode,\n type FhirResourceLike,\n} from \"@openhi/types\";\nimport {\n parseWorkflowEvent,\n workflowDedupClient,\n type WorkflowDedupClient,\n} from \"@openhi/workflows\";\nimport type { EventBridgeEvent } from \"aws-lambda\";\nimport {\n DEMO_DATA_PLANE_FIXTURES,\n type DemoWorkspaceDataPlaneFixtures,\n} from \"./data-plane-fixtures\";\nimport {\n DEMO_PERIOD,\n DEMO_TENANT_SPECS,\n DEV_USERS,\n ON_SITE_DEMO_TENANT_ID,\n ON_SITE_DEMO_WORKSPACE_ID,\n PLATFORM_SCOPE_TENANT_ID,\n PlatformSystemDataSeededV1,\n SEED_DEMO_DATA_CONSUMER_NAME,\n demoMembershipId,\n demoRoleAssignmentId,\n demoRolesForUserInTenant,\n demoScenarioIdentifier,\n openhiResourceIdentifier,\n type DemoDevUser,\n} from \"./events\";\nimport { getDynamoControlService } from \"../../../data/dynamo/dynamo-control-service\";\nimport { NotFoundError } from \"../../../data/errors\";\nimport type { OpenHiContext } from \"../../../data/openhi-context\";\nimport { createMembershipOperation } from \"../../../data/operations/control/membership/membership-create-operation\";\nimport { getRoleByIdOperation } from \"../../../data/operations/control/role/role-get-by-id-operation\";\nimport { createRoleAssignmentOperation } from \"../../../data/operations/control/roleassignment/roleassignment-create-operation\";\nimport { createTenantOperation } from \"../../../data/operations/control/tenant/tenant-create-operation\";\nimport { createWorkspaceOperation } from \"../../../data/operations/control/workspace/workspace-create-operation\";\nimport { createAccountOperation } from \"../../../data/operations/data/account/account-create-operation\";\nimport { createAppointmentOperation } from \"../../../data/operations/data/appointment/appointment-create-operation\";\nimport { createClaimOperation } from \"../../../data/operations/data/claim/claim-create-operation\";\nimport { createConditionOperation } from \"../../../data/operations/data/condition/condition-create-operation\";\nimport { createCoverageOperation } from \"../../../data/operations/data/coverage/coverage-create-operation\";\nimport { createEncounterOperation } from \"../../../data/operations/data/encounter/encounter-create-operation\";\nimport { createLocationOperation } from \"../../../data/operations/data/location/location-create-operation\";\nimport { createObservationOperation } from \"../../../data/operations/data/observation/observation-create-operation\";\nimport { createOrganizationOperation } from \"../../../data/operations/data/organization/organization-create-operation\";\nimport { createPatientOperation } from \"../../../data/operations/data/patient/patient-create-operation\";\nimport { createPaymentNoticeOperation } from \"../../../data/operations/data/paymentnotice/paymentnotice-create-operation\";\nimport { createPractitionerOperation } from \"../../../data/operations/data/practitioner/practitioner-create-operation\";\nimport { createProcedureOperation } from \"../../../data/operations/data/procedure/procedure-create-operation\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/constructs/workflows/control-plane/seed-demo-data/seed-demo-data-handler.md\n *\n * EventBridge workflow handler invoked once per platform-deploy event\n * on the control event bus. Pre-flight verifies that\n * `seed-system-data` has already seeded the canonical Role records,\n * then idempotently re-asserts the demo-data graph: the placeholder\n * Tenant + Workspace, the three demo tenants + their workspaces, and\n * for each entry in {@link DEV_USERS} a Cognito user, a DynamoDB User,\n * 4 Memberships, 4 `tenant-admin` RoleAssignments, plus 1\n * platform-scoped `system-admin` RoleAssignment.\n */\n\ntype SeedDemoDataEvent = EventBridgeEvent<\n \"platform.system-data-seeded.v1\",\n unknown\n>;\n\n/** Env var the lambda construct injects with the Cognito User Pool ID. */\nexport const SEED_DEMO_DATA_USER_POOL_ID_ENV_VAR =\n \"SEED_DEMO_DATA_USER_POOL_ID\";\n\n/** Inputs the handler needs to provision Cognito users for every dev. */\nexport interface CognitoProvisioner {\n /**\n * Ensure a Cognito user exists for `email`. Returns the user's\n * `sub`. Implementations MUST be idempotent: a second invocation\n * for the same email returns the existing user's sub without\n * resetting its password or touching any attribute.\n */\n readonly ensureUser: (email: string) => Promise<string>;\n}\n\n/**\n * Dependency seam for tests. The factory mirrors the production\n * arrangement: a real DynamoDB client + the real `workflowDedupClient`\n * factory bound to the `OPENHI_WORKFLOW_DEDUP_TABLE_NAME` env var the\n * construct injects via `grantConsumer`.\n */\nexport interface SeedDemoDataDependencies {\n readonly dedupClient: WorkflowDedupClient;\n /**\n * Reads every id in `PLATFORM_ROLE_IDS`. Throws when any Role\n * record is missing — that means `seed-system-data` has not yet\n * run on this environment, and emitting demo RoleAssignments that\n * reference non-existent Roles would produce orphaned records.\n */\n readonly verifyRoles: () => Promise<void>;\n /**\n * Upserts every Tenant + Workspace in {@link DEMO_TENANT_SPECS},\n * plus per-dev-user Cognito users, DynamoDB User records,\n * Memberships, and RoleAssignments.\n */\n readonly seedDemoGraph: (params: {\n readonly baseContext: OpenHiContext;\n readonly devUsers: ReadonlyArray<DemoDevUser>;\n readonly cognito: CognitoProvisioner;\n }) => Promise<void>;\n /** Cognito provisioner threaded into `seedDemoGraph`. */\n readonly cognito: CognitoProvisioner;\n}\n\nconst errorMessage = (err: unknown): string => {\n if (err instanceof Error) {\n return err.message;\n }\n return String(err);\n};\n\n/**\n * Structured per-item failure record collected during {@link seedDemoGraph}.\n * Every individual upsert in Phases 1-3 is wrapped so a single item's\n * failure (transient AWS error, write-time constraint violation, etc.)\n * does not skip the rest of its phase. After all phases run, the\n * collected failures are aggregate-thrown so EventBridge still routes\n * the workflow into its failure-detection path (DLQ + CloudWatch\n * alarm) and the outer `runSeedDemoData` records `markFailed` on the\n * dedup row.\n *\n * @see sites/www-docs/content/packages/@openhi/constructs/workflows/control-plane/seed-demo-data/index.md\n */\ntype SeedPhase = \"phase-1\" | \"phase-2\" | \"phase-3\";\n\ninterface SeedFailure {\n readonly phase: SeedPhase;\n /**\n * Short human label identifying where the failure happened\n * (e.g. tenant id, workspace id, user id). Used purely to enrich\n * the aggregate-throw message; no machine reads it.\n */\n readonly scope: string;\n readonly resourceType: string;\n readonly resourceId: string;\n readonly error: unknown;\n}\n\n/**\n * Wrap a single upsert call. On success, returns `true`. On failure,\n * pushes a structured {@link SeedFailure} onto `failures` and returns\n * `false` — the caller can use the boolean to decide whether to skip\n * downstream writes that strictly depend on this one. Most call sites\n * ignore the boolean (per-item isolation: the next item is attempted\n * regardless of this one's outcome).\n *\n * The wrapped function's return value is discarded; only the success/\n * failure signal is propagated. Callers that need the operation's\n * result (e.g. the `cognitoSub` from `cognito.ensureUser`) must hoist\n * the call out of `tryRun` and handle the failure inline.\n */\nconst tryRun = async (\n failures: Array<SeedFailure>,\n phase: SeedPhase,\n scope: string,\n resourceType: string,\n resourceId: string,\n fn: () => Promise<unknown>,\n): Promise<boolean> => {\n try {\n await fn();\n return true;\n } catch (err) {\n failures.push({ phase, scope, resourceType, resourceId, error: err });\n return false;\n }\n};\n\n/**\n * Format collected failures into a single Error suitable for the\n * outer `markFailed` reason and CloudWatch alarm payload. Lists every\n * failure as `<phase> <scope>/<resourceType>/<resourceId>: <message>`\n * joined by `; ` so a single CloudWatch line carries the full picture.\n */\nconst aggregateFailureError = (failures: ReadonlyArray<SeedFailure>): Error => {\n const summary = failures\n .map(\n (f) =>\n `${f.phase} ${f.scope}/${f.resourceType}/${f.resourceId}: ${errorMessage(\n f.error,\n )}`,\n )\n .join(\"; \");\n return new Error(\n `seed-demo-data: ${failures.length} item(s) failed across phases: ${summary}`,\n );\n};\n\n/**\n * Map a role code back to its canonical stable id from\n * `PLATFORM_ROLE_IDS`. Mirrors the lookup in\n * `seed-system-data.handler.ts` — the generator emits `_IDS` and\n * `_CONCEPTS` in lockstep, so a single SCREAMING_SNAKE key resolves\n * both projections.\n */\nconst idForRoleCode = (code: PlatformRoleCode): string => {\n for (const key of Object.keys(PLATFORM_ROLE_IDS) as Array<\n keyof typeof PLATFORM_ROLE_IDS\n >) {\n if (PLATFORM_ROLE_CONCEPTS[key].code === code) {\n return PLATFORM_ROLE_IDS[key];\n }\n }\n throw new Error(`No id mapping for role code \"${code}\".`);\n};\n\n/**\n * Pre-flight Role check. Iterates every id in\n * `PLATFORM_ROLE_IDS` and reads the record. If any read returns\n * not-found, this throws and `markFailed`'s the dedup row — the\n * replay tooling can retry once `seed-system-data` has populated the\n * Roles.\n */\nconst verifySystemRolesExist = async (): Promise<void> => {\n const probeContext: OpenHiContext = {\n tenantId: \"\",\n workspaceId: \"\",\n date: new Date(0).toISOString(),\n actorId: \"platform-deploy-bridge\",\n actorName: \"Platform Deploy Bridge\",\n actorType: \"internal-system\",\n source: \"step-function\",\n };\n for (const id of Object.values(PLATFORM_ROLE_IDS)) {\n try {\n await getRoleByIdOperation({ context: probeContext, id });\n } catch (err) {\n if (err instanceof NotFoundError) {\n throw new Error(\n `seed-demo-data pre-flight: control-plane Role \"${id}\" is missing. ` +\n \"Ensure seed-system-data has run on this environment before retrying.\",\n );\n }\n throw err;\n }\n }\n};\n\n/**\n * Build the resource body for one demo Tenant. Carries the two\n * identifiers per scope decision #6: the demo-scenario URN and the\n * canonical OpenHI resource URN (ADR 2026-03-12-01).\n */\nconst tenantResourceBody = (\n spec: (typeof DEMO_TENANT_SPECS)[number],\n): Record<string, unknown> => ({\n name: spec.tenantName,\n active: true,\n identifier: [\n demoScenarioIdentifier(spec.scenario, \"tenant\"),\n openhiResourceIdentifier({\n tenantId: spec.tenantId,\n workspaceId: \"\",\n resourceType: \"Tenant\",\n id: spec.tenantId,\n }),\n ],\n});\n\nconst workspaceResourceBody = (\n spec: (typeof DEMO_TENANT_SPECS)[number],\n workspace: (typeof DEMO_TENANT_SPECS)[number][\"workspaces\"][number],\n): Record<string, unknown> => ({\n name: workspace.name,\n active: true,\n identifier: [\n demoScenarioIdentifier(spec.scenario, workspace.roleSuffix),\n openhiResourceIdentifier({\n tenantId: spec.tenantId,\n workspaceId: \"\",\n resourceType: \"Workspace\",\n id: workspace.id,\n }),\n ],\n tenant: { reference: `Tenant/${spec.tenantId}`, type: \"Tenant\" },\n});\n\nconst membershipResourceBody = (\n spec: (typeof DEMO_TENANT_SPECS)[number],\n user: DemoDevUser,\n membershipId: string,\n): Record<string, unknown> => ({\n identifier: [\n demoScenarioIdentifier(spec.scenario, `membership-${user.id}`),\n openhiResourceIdentifier({\n tenantId: spec.tenantId,\n workspaceId: \"\",\n resourceType: \"Membership\",\n id: membershipId,\n }),\n ],\n user: { reference: `User/${user.id}`, type: \"User\" },\n tenant: { reference: `Tenant/${spec.tenantId}`, type: \"Tenant\" },\n period: DEMO_PERIOD,\n});\n\nconst roleAssignmentResourceBody = (\n scenario: string,\n tenantId: string,\n user: DemoDevUser,\n roleCode: PlatformRoleCode,\n roleAssignmentId: string,\n): Record<string, unknown> => ({\n identifier: [\n demoScenarioIdentifier(scenario, `roleassignment-${user.id}-${roleCode}`),\n openhiResourceIdentifier({\n tenantId,\n workspaceId: \"\",\n resourceType: \"RoleAssignment\",\n id: roleAssignmentId,\n }),\n ],\n user: { reference: `User/${user.id}`, type: \"User\" },\n role: { reference: `Role/${idForRoleCode(roleCode)}`, type: \"Role\" },\n tenant: { reference: `Tenant/${tenantId}`, type: \"Tenant\" },\n period: DEMO_PERIOD,\n});\n\n/**\n * Build the FHIR User resource body for a seeded dev user.\n *\n * `currentTenant`/`currentWorkspace` point at the on-site demo\n * tenant (#1301), not the placeholder. The placeholder remains\n * seeded as a structural sentinel for the JWT-claim fallback in\n * `pre-token-generation.handler.ts`, but no seeded User references\n * it on its current* pointers — UAT testers land on\n * `On-Site Medical — Demo` on first sign-in.\n */\nconst userResourceBody = (\n user: DemoDevUser,\n cognitoSub: string,\n): Record<string, unknown> => ({\n resourceType: \"User\",\n id: user.id,\n name: [\n {\n text: `${user.firstName} ${user.lastName}`,\n given: [user.firstName],\n family: user.lastName,\n },\n ],\n telecom: [{ system: \"email\", value: user.email }],\n status: \"active\",\n cognitoSub,\n currentTenant: { reference: `Tenant/${ON_SITE_DEMO_TENANT_ID}` },\n currentWorkspace: { reference: `Workspace/${ON_SITE_DEMO_WORKSPACE_ID}` },\n});\n\n/**\n * Idempotent User upsert. The User entity is non-tenant-isolated, so\n * the put is unconditional — the entity's PK is `USER#ID#<id>` and\n * supplying the same id re-asserts the same row.\n */\nconst upsertUser = async (\n context: OpenHiContext,\n user: DemoDevUser,\n cognitoSub: string,\n): Promise<void> => {\n const service = getDynamoControlService();\n const resource = userResourceBody(user, cognitoSub);\n const summary = JSON.stringify(extractSummary(resource as FhirResourceLike));\n await service.entities.user\n .put({\n id: user.id,\n cognitoSub,\n resource: JSON.stringify(resource),\n summary,\n vid: \"1\",\n lastUpdated: context.date ?? new Date().toISOString(),\n })\n .go();\n};\n\n/**\n * Phase 3 helper: upsert one workspace's data-plane FHIR resources\n * (Patient/Practitioner/Observation/Encounter/Account). Parents are\n * written before children that reference them so direct `Resource/<id>`\n * references resolve on read paths that follow them — Patient first,\n * then Practitioner, then Observation/Encounter/Account which may\n * carry `subject: Patient/...` references.\n *\n * Every create operation's `body.id` is supplied from the fixture, so\n * re-fires after dedup-TTL expiry upsert the same record (ElectroDB's\n * `put` is unconditional — same composite key overwrites the prior\n * row).\n *\n * Each individual create is wrapped via {@link tryRun}: a failed\n * Patient does not skip the remaining Patients or the downstream\n * Practitioner/Observation/Encounter/Account writes in this workspace,\n * and a failure here does not propagate up to skip the next workspace\n * in the outer loop. Downstream resources that reference a failed\n * parent (`subject: Patient/<id>`) will likely fail too — that is\n * fine, they are attempted, the failures recorded, and the next\n * deploy upserts them once the parent lands.\n */\nconst seedWorkspaceDataPlane = async (\n baseContext: OpenHiContext,\n group: DemoWorkspaceDataPlaneFixtures,\n failures: Array<SeedFailure>,\n): Promise<void> => {\n const workspaceContext: OpenHiContext = {\n ...baseContext,\n tenantId: group.tenantId,\n workspaceId: group.workspaceId,\n };\n const scope = `${group.tenantId}/${group.workspaceId}`;\n // Locations land first — block Appointments reference them via\n // `participant.actor.reference = \"Location/<id>\"`. Practitioners\n // are written separately in the existing loop below; their\n // ordering relative to Locations is immaterial.\n for (const location of group.locations ?? []) {\n await tryRun(\n failures,\n \"phase-3\",\n scope,\n \"Location\",\n location.id ?? \"\",\n () =>\n createLocationOperation({\n context: workspaceContext,\n body: location,\n }),\n );\n }\n // Directory Organizations (#1308) — DME suppliers and insurance\n // payor contacts. Standalone records (no inbound references from\n // the rest of the fixture graph) so they can land anywhere in\n // phase 3; we put them next to Locations so the directory data\n // is grouped together in the dispatch order.\n for (const organization of group.organizations ?? []) {\n await tryRun(\n failures,\n \"phase-3\",\n scope,\n \"Organization\",\n organization.id ?? \"\",\n () =>\n createOrganizationOperation({\n context: workspaceContext,\n body: organization,\n }),\n );\n }\n const patients = group.buildPatients ? group.buildPatients() : group.patients;\n for (const patient of patients) {\n await tryRun(failures, \"phase-3\", scope, \"Patient\", patient.id ?? \"\", () =>\n createPatientOperation({\n context: workspaceContext,\n body: patient,\n }),\n );\n }\n // Coverages (#1304) reference their `beneficiary` via\n // `Patient/<id>`, so write them immediately after the Patient\n // loop so the parent rows exist before the Coverage write\n // lands on read paths that follow the reference.\n const coverages = group.buildCoverages\n ? group.buildCoverages()\n : (group.coverages ?? []);\n for (const coverage of coverages) {\n await tryRun(\n failures,\n \"phase-3\",\n scope,\n \"Coverage\",\n coverage.id ?? \"\",\n () =>\n createCoverageOperation({\n context: workspaceContext,\n body: coverage,\n }),\n );\n }\n for (const practitioner of group.practitioners) {\n await tryRun(\n failures,\n \"phase-3\",\n scope,\n \"Practitioner\",\n practitioner.id ?? \"\",\n () =>\n createPractitionerOperation({\n context: workspaceContext,\n body: practitioner,\n }),\n );\n }\n // Conditions (wounds — #1306) land before Encounters and\n // Observations so the wound-exam Observation's `focus` reference\n // and the wound-debridement Procedure's `reasonReference` resolve\n // cleanly on read paths.\n const conditions = group.buildConditions\n ? group.buildConditions(baseContext)\n : (group.conditions ?? []);\n for (const condition of conditions) {\n await tryRun(\n failures,\n \"phase-3\",\n scope,\n \"Condition\",\n condition.id ?? \"\",\n () =>\n createConditionOperation({\n context: workspaceContext,\n body: condition,\n }),\n );\n }\n // Encounters (#1306) reference Patients (subject), Practitioners\n // (participant), Locations (location), Appointments (appointment).\n // All of those have already been written above so the references\n // resolve cleanly. Encounters land before Observations and\n // Procedures because both reference the encounter via `encounter`.\n const encounters = group.buildEncounters\n ? group.buildEncounters(baseContext)\n : group.encounters;\n for (const encounter of encounters) {\n await tryRun(\n failures,\n \"phase-3\",\n scope,\n \"Encounter\",\n encounter.id ?? \"\",\n () =>\n createEncounterOperation({\n context: workspaceContext,\n body: encounter,\n }),\n );\n }\n // Observations may reference Encounters (#1306 wound-exam panels)\n // and Conditions (focus = wound). Both have already been written\n // above.\n const observations = group.buildObservations\n ? group.buildObservations(baseContext)\n : group.observations;\n for (const observation of observations) {\n await tryRun(\n failures,\n \"phase-3\",\n scope,\n \"Observation\",\n observation.id ?? \"\",\n () =>\n createObservationOperation({\n context: workspaceContext,\n body: observation,\n }),\n );\n }\n // Procedures (#1306) reference Patients (subject), Encounters\n // (encounter), and Conditions (reasonReference). Land last in\n // the clinical-data tier so every parent reference resolves.\n const procedures = group.buildProcedures\n ? group.buildProcedures(baseContext)\n : (group.procedures ?? []);\n for (const procedure of procedures) {\n await tryRun(\n failures,\n \"phase-3\",\n scope,\n \"Procedure\",\n procedure.id ?? \"\",\n () =>\n createProcedureOperation({\n context: workspaceContext,\n body: procedure,\n }),\n );\n }\n // Claims (#1307) reference Patients (patient), Encounters\n // (item[].encounter), and Coverages (insurance[].coverage).\n // All three are already written above so the references\n // resolve cleanly on read paths. PaymentNotices land\n // immediately after Claims and reference them by id.\n const claims = group.buildClaims ? group.buildClaims(baseContext) : [];\n for (const claim of claims) {\n await tryRun(failures, \"phase-3\", scope, \"Claim\", claim.id ?? \"\", () =>\n createClaimOperation({\n context: workspaceContext,\n body: claim,\n }),\n );\n }\n const paymentNotices = group.buildPaymentNotices\n ? group.buildPaymentNotices(baseContext)\n : [];\n for (const paymentNotice of paymentNotices) {\n await tryRun(\n failures,\n \"phase-3\",\n scope,\n \"PaymentNotice\",\n paymentNotice.id ?? \"\",\n () =>\n createPaymentNoticeOperation({\n context: workspaceContext,\n body: paymentNotice,\n }),\n );\n }\n for (const account of group.accounts) {\n await tryRun(failures, \"phase-3\", scope, \"Account\", account.id ?? \"\", () =>\n createAccountOperation({\n context: workspaceContext,\n body: account,\n }),\n );\n }\n // Block-style Appointments land last because they reference both\n // Practitioners (doctor + scribe — written above) and Locations\n // (written first). Each occurrence is wrapped via tryRun so a\n // single failed week does not skip the rest of the recurrence\n // window or the next block template.\n const appointments = group.buildAppointments\n ? group.buildAppointments(baseContext)\n : [];\n for (const appointment of appointments) {\n await tryRun(\n failures,\n \"phase-3\",\n scope,\n \"Appointment\",\n appointment.id ?? \"\",\n () =>\n createAppointmentOperation({\n context: workspaceContext,\n body: appointment,\n }),\n );\n }\n};\n\n/**\n * Upsert the full demo-data graph. Walks each spec in\n * {@link DEMO_TENANT_SPECS}: Tenant → Workspaces. Then per dev user:\n * Cognito user → DynamoDB User → per-tenant Membership +\n * `tenant-admin` RoleAssignment → platform-scoped `system-admin`\n * RoleAssignment. Finally walks {@link DEMO_DATA_PLANE_FIXTURES} and\n * upserts the OPS-009 v1 FHIR resource set (Patient, Practitioner,\n * Observation, Encounter, Account) into each demo workspace. Every\n * put is keyed by a deterministic stable id so re-runs after\n * dedup-TTL expiry upsert the same records.\n *\n * Self-healing-on-every-deploy contract: every individual upsert\n * across all three phases is wrapped via {@link tryRun}. A single\n * item's failure (transient AWS error, write-time constraint\n * violation, etc.) is collected into a per-call accumulator and\n * does not skip the remaining items in its phase. After all phases\n * run, collected failures are aggregate-thrown as a single error so\n * EventBridge still routes the workflow into its failure-detection\n * path (DLQ + CloudWatch alarm) and the outer `runSeedDemoData`\n * records `markFailed` on the dedup row. Because every put is keyed\n * by a deterministic stable id, the next deploy re-attempts every\n * item — failed items eventually heal, successful items overwrite\n * themselves with the same body.\n *\n * Exported so the seeder test file can exercise it directly against\n * a mocked DynamoControlService; the production handler reaches it\n * through {@link SeedDemoDataDependencies.seedDemoGraph}.\n */\nexport const seedDemoGraph = async (params: {\n baseContext: OpenHiContext;\n devUsers: ReadonlyArray<DemoDevUser>;\n cognito: CognitoProvisioner;\n}): Promise<void> => {\n const { baseContext, devUsers, cognito } = params;\n const failures: Array<SeedFailure> = [];\n\n // Phase 1: Tenants + Workspaces (no Memberships / RoleAssignments\n // yet — those need the per-user Cognito sub).\n //\n // Each tenant and each workspace is wrapped individually. A failed\n // tenant create does NOT skip its workspaces — the tenant may\n // already exist from a prior deploy (the put is unconditional, so\n // a duplicate is a no-op; we treat all errors as recoverable here\n // and let the workspace writes proceed). A failed workspace does\n // not skip the next workspace under the same tenant or any\n // subsequent tenant.\n for (const spec of DEMO_TENANT_SPECS) {\n const tenantContext: OpenHiContext = {\n ...baseContext,\n tenantId: spec.tenantId,\n };\n\n await tryRun(\n failures,\n \"phase-1\",\n spec.tenantId,\n \"Tenant\",\n spec.tenantId,\n () =>\n createTenantOperation({\n context: tenantContext,\n body: { id: spec.tenantId, resource: tenantResourceBody(spec) },\n }),\n );\n\n for (const workspace of spec.workspaces) {\n await tryRun(\n failures,\n \"phase-1\",\n spec.tenantId,\n \"Workspace\",\n workspace.id,\n () =>\n createWorkspaceOperation({\n context: tenantContext,\n body: {\n id: workspace.id,\n resource: workspaceResourceBody(spec, workspace),\n },\n }),\n );\n }\n }\n\n // Phase 2: per-dev-user records. The Cognito provisioner is the\n // only step that can fail in a way EventBridge can usefully retry —\n // it runs first because every subsequent write needs the\n // `cognitoSub` it returns. If `ensureUser` throws, skip the whole\n // user (we have no sub to write into the User row).\n //\n // For each individual call inside the per-user block we use\n // {@link tryRun} so a Membership failure in tenant 3 does not skip\n // the Membership + RAs in tenant 4 for the same user, and the\n // platform-scoped RA is attempted last regardless of any earlier\n // per-tenant failure.\n //\n // `upsertUser` is wrapped via tryRun BUT we do NOT short-circuit\n // the per-tenant writes on its failure. The User row carries\n // `cognitoSub` for JWT-claim resolution; the Memberships and\n // RoleAssignments only reference the User by stable id. A previous\n // deploy may have already written the User row with the correct\n // sub. Attempting the per-tenant writes lets the next deploy heal\n // any partial state.\n for (const user of devUsers) {\n let cognitoSub: string;\n try {\n cognitoSub = await cognito.ensureUser(user.email);\n } catch (err) {\n failures.push({\n phase: \"phase-2\",\n scope: user.id,\n resourceType: \"CognitoUser\",\n resourceId: user.email,\n error: err,\n });\n continue;\n }\n\n await tryRun(failures, \"phase-2\", user.id, \"User\", user.id, () =>\n upsertUser(baseContext, user, cognitoSub),\n );\n\n for (const spec of DEMO_TENANT_SPECS) {\n const tenantContext: OpenHiContext = {\n ...baseContext,\n tenantId: spec.tenantId,\n };\n const userScope = `${user.id}@${spec.tenantId}`;\n\n const membershipId = demoMembershipId(user.id, spec.tenantId);\n await tryRun(\n failures,\n \"phase-2\",\n userScope,\n \"Membership\",\n membershipId,\n () =>\n createMembershipOperation({\n context: tenantContext,\n body: {\n id: membershipId,\n resource: membershipResourceBody(spec, user, membershipId),\n },\n }),\n );\n\n for (const roleCode of demoRolesForUserInTenant(user, spec.tenantId)) {\n const raId = demoRoleAssignmentId(user.id, spec.tenantId, roleCode);\n await tryRun(\n failures,\n \"phase-2\",\n userScope,\n \"RoleAssignment\",\n raId,\n () =>\n createRoleAssignmentOperation({\n context: tenantContext,\n body: {\n id: raId,\n resource: roleAssignmentResourceBody(\n spec.scenario,\n spec.tenantId,\n user,\n roleCode,\n raId,\n ),\n },\n }),\n );\n }\n }\n\n // Platform-scoped system-admin RoleAssignment. The sentinel\n // tenantId is PLATFORM_SCOPE_TENANT_ID — there is no real Tenant\n // to point at, so the operation runs with an OpenHiContext whose\n // tenantId is the sentinel. The write-time tenant-membership\n // constraint short-circuits for this sentinel so no Membership\n // prerequisite is required.\n const platformContext: OpenHiContext = {\n ...baseContext,\n tenantId: PLATFORM_SCOPE_TENANT_ID,\n };\n const platformRoleCode = PLATFORM_ROLE_CODE.SYSTEM_ADMIN;\n const platformRaId = demoRoleAssignmentId(\n user.id,\n PLATFORM_SCOPE_TENANT_ID,\n platformRoleCode,\n );\n await tryRun(\n failures,\n \"phase-2\",\n `${user.id}@${PLATFORM_SCOPE_TENANT_ID}`,\n \"RoleAssignment\",\n platformRaId,\n () =>\n createRoleAssignmentOperation({\n context: platformContext,\n body: {\n id: platformRaId,\n resource: roleAssignmentResourceBody(\n \"platform\",\n PLATFORM_SCOPE_TENANT_ID,\n user,\n platformRoleCode,\n platformRaId,\n ),\n },\n }),\n );\n }\n\n // Phase 3: data-plane FHIR resources (OPS-009 v1 set) per demo\n // workspace. Runs after the control-plane phases so the Tenants\n // and Workspaces those resources implicitly belong to already\n // exist by the time we write into them. The placeholder tenant\n // carries no data-plane fixtures.\n //\n // `seedWorkspaceDataPlane` already wraps each individual create\n // via tryRun; we wrap the helper call itself in an outer\n // try/catch as defence-in-depth so an unexpected throw from the\n // helper (programmer error, OOM, etc.) does not skip the next\n // workspace.\n for (const group of DEMO_DATA_PLANE_FIXTURES) {\n try {\n await seedWorkspaceDataPlane(baseContext, group, failures);\n } catch (err) {\n failures.push({\n phase: \"phase-3\",\n scope: `${group.tenantId}/${group.workspaceId}`,\n resourceType: \"Workspace\",\n resourceId: group.workspaceId,\n error: err,\n });\n }\n }\n\n if (failures.length > 0) {\n throw aggregateFailureError(failures);\n }\n};\n\n/**\n * Test-visible orchestrator. The production `handler` calls this with\n * real dependencies and the hardcoded {@link DEV_USERS} list; unit\n * tests inject fakes and pass the dev-user list directly.\n */\nexport const runSeedDemoData = async (\n event: SeedDemoDataEvent,\n deps: SeedDemoDataDependencies,\n devUsers: ReadonlyArray<DemoDevUser>,\n): Promise<void> => {\n const parsed = parseWorkflowEvent(event, PlatformSystemDataSeededV1);\n\n const recordResult = await deps.dedupClient.recordIfAbsent({\n consumerName: SEED_DEMO_DATA_CONSUMER_NAME,\n eventId: parsed.dedupKey.eventId,\n attempt: parsed.dedupKey.attempt,\n });\n if (!recordResult.recorded) {\n return;\n }\n\n const baseContext: OpenHiContext = {\n tenantId: \"\",\n workspaceId: \"\",\n date: parsed.envelope.occurredAt,\n actorId: \"platform-deploy-bridge\",\n actorName: \"Platform Deploy Bridge\",\n actorType: \"internal-system\",\n source: \"step-function\",\n };\n\n try {\n await deps.verifyRoles();\n await deps.seedDemoGraph({\n baseContext,\n devUsers,\n cognito: deps.cognito,\n });\n } catch (err) {\n // Mark the dedup row failed so the replay tooling (TR-016 follow-up)\n // can re-publish the originating event with a fresh attempt. The\n // re-throw keeps EventBridge's failure-detection path intact — the\n // event ends up in the DLQ + the workflow Lambda's failure\n // CloudWatch alarm fires.\n await deps.dedupClient.markFailed({\n consumerName: SEED_DEMO_DATA_CONSUMER_NAME,\n eventId: parsed.dedupKey.eventId,\n attempt: parsed.dedupKey.attempt,\n reason: errorMessage(err),\n });\n throw err;\n }\n};\n\n/**\n * SSM parameter-path prefix that hosts every seeded dev user's\n * password. The full path for a single user is\n * `${SEED_USER_PASSWORD_PARAMETER_PREFIX}<email_safe>/password`\n * where `<email_safe>` is `<user>_at_<domain>` (see\n * {@link emailToSsmPath}). The trailing `/password` segment leaves\n * room for additional per-user parameters under the same email\n * prefix in future phases without renaming the existing entries.\n */\nexport const SEED_USER_PASSWORD_PARAMETER_PREFIX = \"/openhi/seed/users/\";\n\n/**\n * SSM Parameter Store path validation regex. Names must be 1-1011\n * characters, may include alphanumerics plus `_`, `.`, `-`, and\n * `/`. We enforce a stricter subset here — alphanumerics, hyphen,\n * underscore, and period only — because the path is constructed by\n * substituting `@` → `_at_` and any other special character would\n * indicate an email that should have been rejected upstream.\n */\nconst SSM_PATH_SEGMENT = /^[A-Za-z0-9_.-]+$/;\n\n/**\n * Map an email address to its canonical SSM parameter path. The\n * `@` separator is replaced with the literal sentinel `_at_` so\n * the resulting path is a single SSM-legal name. Throws when the\n * email is empty, missing exactly one `@`, or contains characters\n * that would produce an invalid SSM path.\n *\n * Example: `alice@codedrifters.com` →\n * `/openhi/seed/users/alice_at_codedrifters.com/password`.\n */\nexport const emailToSsmPath = (email: string): string => {\n if (typeof email !== \"string\" || email.length === 0) {\n throw new Error(\n `emailToSsmPath: email must be a non-empty string (received \"${String(email)}\").`,\n );\n }\n const atIdx = email.indexOf(\"@\");\n if (atIdx === -1 || atIdx !== email.lastIndexOf(\"@\")) {\n throw new Error(\n `emailToSsmPath: email \"${email}\" must contain exactly one \"@\" character.`,\n );\n }\n const localPart = email.slice(0, atIdx);\n const domainPart = email.slice(atIdx + 1);\n if (localPart.length === 0 || domainPart.length === 0) {\n throw new Error(\n `emailToSsmPath: email \"${email}\" must have a non-empty local-part and domain.`,\n );\n }\n if (!SSM_PATH_SEGMENT.test(localPart) || !SSM_PATH_SEGMENT.test(domainPart)) {\n throw new Error(\n `emailToSsmPath: email \"${email}\" contains characters that would produce ` +\n \"an invalid SSM parameter path (only A-Z, a-z, 0-9, '.', '-', and '_' are allowed).\",\n );\n }\n return `${SEED_USER_PASSWORD_PARAMETER_PREFIX}${localPart}_at_${domainPart}/password`;\n};\n\n/**\n * Module-scoped SSM client. Lambda containers reuse the same\n * `SSMClient` instance across invocations so the TLS connection\n * + credential-resolver state warms once per container. Mirrors\n * the `CognitoIdentityProviderClient` / `DynamoDBClient` reuse\n * pattern at the bottom of this file.\n */\nlet cachedSsmClient: SSMClient | undefined;\n\nconst getSsmClient = (): SSMClient => {\n if (!cachedSsmClient) {\n cachedSsmClient = new SSMClient({});\n }\n return cachedSsmClient;\n};\n\n/**\n * Test seam: reset the module-scoped SSM client cache. Unit tests\n * that swap in different mocks across `it` blocks call this in\n * `beforeEach` so each test gets a fresh client instance.\n */\nexport const __resetSsmClientForTests = (): void => {\n cachedSsmClient = undefined;\n};\n\n/**\n * Read a seeded dev user's password from SSM Parameter Store. The\n * parameter is expected to be a `SecureString` provisioned out of\n * band by an operator (see the runbook in phase 3 of #1249). On\n * `ParameterNotFound`, the error message includes the exact\n * expected path so the operator can copy-paste-fix.\n */\nexport const fetchSeedUserPassword = async (email: string): Promise<string> => {\n const path = emailToSsmPath(email);\n const client = getSsmClient();\n try {\n const result = await client.send(\n new GetParameterCommand({ Name: path, WithDecryption: true }),\n );\n const value = result.Parameter?.Value;\n if (typeof value !== \"string\" || value.length === 0) {\n throw new Error(\n `fetchSeedUserPassword: SSM parameter \"${path}\" returned an empty value.`,\n );\n }\n return value;\n } catch (err) {\n if (err instanceof ParameterNotFound) {\n throw new Error(\n `fetchSeedUserPassword: SSM parameter \"${path}\" not found. ` +\n `Provision a SecureString at \"${path}\" with the dev user's password before re-running seed-demo-data.`,\n );\n }\n throw err;\n }\n};\n\n/**\n * Production Cognito provisioner backed by the AWS SDK. Reads the\n * user-pool id from the env var the lambda construct injects.\n *\n * Idempotency contract:\n * - On first invocation, calls `AdminCreateUser` (with\n * `MessageAction: SUPPRESS` so no invitation email fires) then\n * `AdminSetUserPassword` (permanent, from the SSM-sourced\n * value). Returns the new user's sub.\n * - On subsequent invocations, `AdminCreateUser` throws\n * `UsernameExistsException`; the provisioner catches it, calls\n * `AdminGetUser` to read the existing user's sub, and **also\n * re-applies the current SSM-sourced password** via\n * `AdminSetUserPassword`. This is the rotation seam: operators\n * update the SSM SecureString value and re-publish the seed\n * event to push a fresh password down to Cognito.\n *\n * The SSM password is fetched once per email up-front so the new-\n * user and rotation branches share the same value and at most one\n * `GetParameter` call lands per `ensureUser` invocation.\n */\nexport const productionCognitoProvisioner = (): CognitoProvisioner => {\n const client = new CognitoIdentityProviderClient({});\n const userPoolId = process.env[SEED_DEMO_DATA_USER_POOL_ID_ENV_VAR];\n if (!userPoolId || userPoolId.trim() === \"\") {\n throw new Error(\n `${SEED_DEMO_DATA_USER_POOL_ID_ENV_VAR} is not set; the seed-demo-data Lambda ` +\n \"cannot provision Cognito users without a user-pool id.\",\n );\n }\n const subFromAttributes = (\n attrs: ReadonlyArray<AttributeType> | undefined,\n ): string | undefined => {\n for (const attr of attrs ?? []) {\n if (attr.Name === \"sub\" && typeof attr.Value === \"string\") {\n return attr.Value;\n }\n }\n return undefined;\n };\n const setPassword = async (\n email: string,\n password: string,\n ): Promise<void> => {\n await client.send(\n new AdminSetUserPasswordCommand({\n UserPoolId: userPoolId,\n Username: email,\n Password: password,\n Permanent: true,\n }),\n );\n };\n return {\n ensureUser: async (email: string): Promise<string> => {\n // Fetch the SSM-sourced password up-front so both the\n // new-user path and the rotation path consume the same\n // value with a single `GetParameter` call.\n const password = await fetchSeedUserPassword(email);\n try {\n const created = await client.send(\n new AdminCreateUserCommand({\n UserPoolId: userPoolId,\n Username: email,\n MessageAction: \"SUPPRESS\",\n UserAttributes: [\n { Name: \"email\", Value: email },\n { Name: \"email_verified\", Value: \"true\" },\n ],\n }),\n );\n await setPassword(email, password);\n const sub = subFromAttributes(created.User?.Attributes);\n if (!sub) {\n throw new Error(\n `AdminCreateUser response for \"${email}\" did not carry a sub attribute.`,\n );\n }\n return sub;\n } catch (err) {\n if (err instanceof UsernameExistsException) {\n // User already exists — re-apply the current SSM-sourced\n // password so operator rotations propagate, then read the\n // existing sub. AdminSetUserPassword on an existing user\n // overwrites the credential without affecting the sub.\n await setPassword(email, password);\n const got = await client.send(\n new AdminGetUserCommand({\n UserPoolId: userPoolId,\n Username: email,\n }),\n );\n const sub = subFromAttributes(got.UserAttributes);\n if (!sub) {\n throw new Error(\n `AdminGetUser response for \"${email}\" did not carry a sub attribute.`,\n );\n }\n return sub;\n }\n throw err;\n }\n },\n };\n};\n\nconst productionDependencies = (): SeedDemoDataDependencies => {\n const dynamodb = new DynamoDBClient({});\n const cognito = productionCognitoProvisioner();\n return {\n dedupClient: workflowDedupClient(dynamodb),\n verifyRoles: verifySystemRolesExist,\n seedDemoGraph,\n cognito,\n };\n};\n\nexport const handler = async (event: SeedDemoDataEvent): Promise<void> =>\n runSeedDemoData(event, productionDependencies(), DEV_USERS);\n","import { PLATFORM_ROLE_CODE, type PlatformRoleCode } from \"@openhi/types\";\nimport { PlatformSystemDataSeededV1 } from \"@openhi/workflows\";\nimport { PLATFORM_SCOPE_TENANT_ID } from \"../../../data/operations/control/membership-constraints/platform-scope-tenant-id\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/constructs/workflows/control-plane/seed-demo-data/events.md\n */\n\n/**\n * Stable logical name this workflow registers with the shared\n * `WorkflowDedupTable` (TR-015). Used in both the construct grant\n * (`workflowDedupTable.grantConsumer(lambda, SEED_DEMO_DATA_CONSUMER_NAME)`)\n * and the handler's runtime `recordIfAbsent` call — keep them aligned by\n * importing this constant in both places.\n */\nexport const SEED_DEMO_DATA_CONSUMER_NAME = \"seed-demo-data\";\n\n/** FHIR `Identifier.system` for the demo-scenario URN scheme. */\nexport const DEMO_URN_SYSTEM = \"urn:openhi:demo\";\n\n/**\n * FHIR `Identifier.system` for the canonical OpenHI resource URN\n * (ADR 2026-03-12-01). The value form is\n * `urn:ohi:<tenantId>:<workspaceId>:<resourceType>:<id>`; empty\n * workspaceId means the resource has tenant-wide scope (or is itself\n * the workspace identity, in the Workspace case).\n */\nexport const OPENHI_RESOURCE_URN_SYSTEM = \"http://openhi.org/\";\n\n/**\n * Period stamped on every demo Membership and RoleAssignment. Fixed\n * start so re-runs produce byte-identical bodies (decision #4); no\n * end so demo memberships are open-ended.\n */\nexport const DEMO_PERIOD = { start: \"2026-01-01T00:00:00Z\" } as const;\n\n/**\n * Sentinel `tenantId` used on every dev user's `system-admin`\n * RoleAssignment. A `system-admin` RA is platform-scoped (it spans\n * every tenant), but the RoleAssignment entity requires a tenantId on\n * its key for sharding — there is no real tenant to point at.\n *\n * The canonical definition lives in\n * `data/operations/control/membership-constraints/platform-scope-tenant-id.ts`\n * so the write-time tenant-membership constraint can short-circuit\n * the sentinel without the data layer importing from the workflow.\n * Re-exported here so existing imports that resolve through\n * `seed-demo-data/events` keep working.\n */\nexport { PLATFORM_SCOPE_TENANT_ID };\n\n/**\n * Placeholder Tenant id.\n *\n * The placeholder is a **system sentinel**, not a user-facing demo\n * tenant. It exists for two reasons:\n *\n * 1. `pre-token-generation.handler.ts` stamps this id into the\n * JWT `ohi_tid` claim when a User cannot be resolved (no\n * DynamoDB record, missing `currentTenant`/`currentWorkspace`,\n * etc.) so the token still satisfies `openHiContextMiddleware`\n * and downstream APIs return a deterministic 403 instead of\n * crashing on a missing claim.\n * 2. The seed workflow re-asserts a Tenant + Workspace record at\n * these ids so the JWT fallback dereferences to a real DynamoDB\n * row (avoids dangling references on read paths that follow\n * `Tenant/placeholder-tenant-id`).\n *\n * Dev users' `currentTenant`/`currentWorkspace` no longer point here\n * (issue #1301) — they point at the on-site demo tenant below. The\n * placeholder records remain seeded purely as a structural sentinel.\n */\nexport const PLACEHOLDER_TENANT_ID = \"placeholder-tenant-id\";\n\n/** Placeholder Workspace id. See {@link PLACEHOLDER_TENANT_ID}. */\nexport const PLACEHOLDER_WORKSPACE_ID = \"placeholder-workspace-id\";\n\n/**\n * Stable Tenant id for the on-site-medical UAT demo tenant\n * (issue #1301). Downstream demo-data tickets (#1302 providers,\n * #1303 facilities, #1304 patients/encounters, etc.) import this\n * constant to attach their fixture resources without re-discovering\n * the tenant.\n *\n * This is the tenant every seeded dev user lands on at sign-in\n * (`currentTenant` on the seeded User resource). UAT testers see\n * \"On-Site Medical — Demo\" in the Tenant Switcher on first sign-in.\n */\nexport const ON_SITE_DEMO_TENANT_ID = \"on-site-demo-tenant\";\n\n/**\n * Stable Workspace id under {@link ON_SITE_DEMO_TENANT_ID}. Single\n * workspace for v1 UAT; workspace topology (per business line vs\n * per jurisdiction) is deferred pending an ADR (#1301 design note).\n */\nexport const ON_SITE_DEMO_WORKSPACE_ID = \"on-site-demo-workspace\";\n\n/**\n * Dev-user descriptor. Every entry produces:\n * - one Cognito user (idempotent create-then-skip),\n * - one DynamoDB User record (id = `dev-<email-local-part>`),\n * - five Memberships (placeholder + on-site demo + three demo tenants),\n * - five `tenant-admin` RoleAssignments (one per tenant the user\n * belongs to),\n * - one `system-admin` RoleAssignment scoped to {@link PLATFORM_SCOPE_TENANT_ID}.\n */\nexport interface DemoDevUser {\n /** Stable DynamoDB User id. */\n readonly id: string;\n /** Email used as the Cognito `Username` and as the seed for the password algorithm. */\n readonly email: string;\n /** Given name, populated on the seeded User FHIR resource as `name[0].given[0]`. */\n readonly firstName: string;\n /** Family name, populated on the seeded User FHIR resource as `name[0].family`. */\n readonly lastName: string;\n}\n\n/**\n * Hardcoded dev-user roster. Adding a new developer is a one-line\n * change here plus a re-deploy. The list intentionally lives in-source\n * (not behind an env-var seam) so the IAM grant in\n * `seed-demo-data-lambda.ts` can enumerate per-user PKs at synth time.\n */\nexport const DEV_USERS: ReadonlyArray<DemoDevUser> = [\n {\n id: \"dev-russell\",\n email: \"russell@codedrifters.com\",\n firstName: \"Russell\",\n lastName: \"Ingram\",\n },\n {\n id: \"dev-cameron\",\n email: \"cameron@codedrifters.com\",\n firstName: \"Cameron\",\n lastName: \"Childress\",\n },\n {\n id: \"dev-neelima\",\n email: \"neelima@codedrifters.com\",\n firstName: \"Neelima\",\n lastName: \"Ramaraju\",\n },\n {\n id: \"dev-garon\",\n email: \"garon@codedrifters.com\",\n firstName: \"Garon\",\n lastName: \"Bailey\",\n },\n {\n id: \"dev-dave\",\n email: \"dave@codedrifters.com\",\n firstName: \"Dave\",\n lastName: \"Finlay\",\n },\n {\n id: \"dev-drew\",\n email: \"drew@codedrifters.com\",\n firstName: \"Drew\",\n lastName: \"Morris\",\n },\n {\n id: \"dev-jessica\",\n email: \"jessica@codedrifters.com\",\n firstName: \"Jessica\",\n lastName: \"Branks\",\n },\n {\n id: \"dev-jared\",\n email: \"jared@codedrifters.com\",\n firstName: \"Jared\",\n lastName: \"Trotter\",\n },\n {\n id: \"dev-goddess\",\n email: \"goddess@codedrifters.com\",\n firstName: \"Goddess\",\n lastName: \"Culberson\",\n },\n // Dedicated end-to-end test principal for admin-console Playwright\n // specs (issue #1275). Reuses the standard DEV_USERS plumbing\n // (Cognito user + DynamoDB User + per-tenant Memberships +\n // tenant-admin RAs + platform-scoped system-admin RA) and the\n // existing SSM-sourced password convention from #1249 — the\n // operator provisions the SecureString at\n // /openhi/seed/users/e2e-admin-console_at_codedrifters.com/password\n // out of band, and the seeded Cognito user picks it up via\n // AdminSetUserPassword on every seed run.\n {\n id: \"dev-e2e-admin-console\",\n email: \"e2e-admin-console@codedrifters.com\",\n firstName: \"E2E\",\n lastName: \"AdminConsole\",\n },\n];\n\n/**\n * A single workspace inside a demo tenant. The mixed tenant has two\n * workspaces (wound-care and primary-care sub-workspaces); every\n * other tenant (placeholder, on-site demo, wound-care, primary-care)\n * has exactly one.\n */\nexport interface DemoWorkspaceSpec {\n /** Stable id (DynamoDB record id; also drives the canonical OHI URN). */\n readonly id: string;\n /** FHIR `Workspace.name`. */\n readonly name: string;\n /**\n * Role suffix used in the demo URN value (`<scenario>:<roleSuffix>`).\n * `workspace` for single-workspace tenants, `workspace-<sub>` for the\n * mixed tenant.\n */\n readonly roleSuffix: string;\n}\n\n/**\n * One demo tenant + the workspaces it owns. Re-exported via {@link\n * DEMO_TENANT_SPECS} as the canonical list; iterate that constant in\n * the handler and the IAM-grant builder so the value sets agree.\n */\nexport interface DemoTenantSpec {\n /**\n * Scenario slug — `placeholder`, `on-site-demo`, `demo-wound-care`,\n * `demo-primary-care`, `demo-mixed`. The placeholder tenant uses\n * `placeholder`; the on-site UAT demo tenant uses `on-site-demo`\n * (#1301); the three demo tenants use `demo-*` slugs.\n */\n readonly scenario: string;\n /** Stable id (DynamoDB record id; also drives the canonical OHI URN). */\n readonly tenantId: string;\n /** FHIR `Tenant.name`. */\n readonly tenantName: string;\n /** Workspaces owned by this tenant. */\n readonly workspaces: ReadonlyArray<DemoWorkspaceSpec>;\n}\n\n/**\n * The full demo-tenant graph. Five entries: the placeholder tenant\n * the JWT-claim fallback resolves to, the on-site-medical UAT demo\n * tenant every dev user lands on at sign-in (#1301), and the three\n * v1 demo scenarios (OPS-009 §\"v1 scenarios\"):\n *\n * 0. Placeholder tenant — dereferences the JWT-claim fallback in\n * `pre-token-generation.handler.ts`. Carries no user-facing\n * content; exists purely so the JWT fallback resolves to a real\n * DynamoDB row instead of dangling.\n * 1. On-site-medical UAT demo tenant — every seeded dev user's\n * `currentTenant`/`currentWorkspace`. Downstream demo-data\n * tickets (providers, facilities, patients) attach to this\n * tenant via {@link ON_SITE_DEMO_TENANT_ID}.\n * 2. Single-workspace wound-care tenant.\n * 3. Single-workspace primary-care tenant.\n * 4. Two-workspace mixed tenant — exercises the cross-workspace\n * isolation flow that single-workspace tenants cannot.\n */\nexport const DEMO_TENANT_SPECS: ReadonlyArray<DemoTenantSpec> = [\n {\n scenario: \"placeholder\",\n tenantId: PLACEHOLDER_TENANT_ID,\n tenantName: \"OpenHI Placeholder Tenant\",\n workspaces: [\n {\n id: PLACEHOLDER_WORKSPACE_ID,\n name: \"OpenHI Placeholder Workspace\",\n roleSuffix: \"workspace\",\n },\n ],\n },\n {\n scenario: \"on-site-demo\",\n tenantId: ON_SITE_DEMO_TENANT_ID,\n tenantName: \"On-Site Medical — Demo\",\n workspaces: [\n {\n id: ON_SITE_DEMO_WORKSPACE_ID,\n name: \"On-Site Medical — Primary Workspace\",\n roleSuffix: \"workspace\",\n },\n ],\n },\n {\n scenario: \"demo-wound-care\",\n tenantId: \"demo-wound-care-tenant\",\n tenantName: \"Cedarbrook Wound Healing Institute\",\n workspaces: [\n {\n id: \"demo-wound-care-workspace\",\n name: \"Cedarbrook Outpatient Wound Clinic\",\n roleSuffix: \"workspace\",\n },\n ],\n },\n {\n scenario: \"demo-primary-care\",\n tenantId: \"demo-primary-care-tenant\",\n tenantName: \"Maple Ridge Family Medicine\",\n workspaces: [\n {\n id: \"demo-primary-care-workspace\",\n name: \"Maple Ridge Main Street Office\",\n roleSuffix: \"workspace\",\n },\n ],\n },\n {\n scenario: \"demo-mixed\",\n tenantId: \"demo-mixed-tenant\",\n tenantName: \"Northbridge Health Network\",\n workspaces: [\n {\n id: \"demo-mixed-workspace-wound-care\",\n name: \"Northbridge Wound Care Center\",\n roleSuffix: \"workspace-wound-care\",\n },\n {\n id: \"demo-mixed-workspace-primary-care\",\n name: \"Northbridge Family Practice\",\n roleSuffix: \"workspace-primary-care\",\n },\n ],\n },\n];\n\n/** Stable Membership id derived from `(devUserId, tenantId)`. */\nexport const demoMembershipId = (devUserId: string, tenantId: string): string =>\n `demo-membership-${devUserId}-${tenantId}`;\n\n/**\n * Stable RoleAssignment id derived from `(devUserId, tenantId, roleCode)`.\n * Each (user, tenant, role) tuple maps to exactly one record — re-runs\n * upsert the same id.\n */\nexport const demoRoleAssignmentId = (\n devUserId: string,\n tenantId: string,\n roleCode: PlatformRoleCode,\n): string => `demo-roleassignment-${devUserId}-${tenantId}-${roleCode}`;\n\n/**\n * Demo-scenario FHIR `Identifier` entry — `urn:openhi:demo:<scenario>:<role>`.\n */\nexport const demoScenarioIdentifier = (\n scenario: string,\n roleSuffix: string,\n): { system: string; value: string } => ({\n system: DEMO_URN_SYSTEM,\n value: `${scenario}:${roleSuffix}`,\n});\n\n/**\n * Canonical OpenHI resource FHIR `Identifier` entry per ADR\n * 2026-03-12-01. `workspaceId` is empty for both Tenant resources and\n * Workspace resources — for a Tenant, the resource is tenant-scoped\n * with no workspace context; for a Workspace, the resource IS the\n * workspace identity rather than living inside one.\n */\nexport const openhiResourceIdentifier = (params: {\n tenantId: string;\n workspaceId: string;\n resourceType: string;\n id: string;\n}): { use: string; system: string; value: string } => ({\n use: \"unversioned\",\n system: OPENHI_RESOURCE_URN_SYSTEM,\n value: `urn:ohi:${params.tenantId}:${params.workspaceId}:${params.resourceType}:${params.id}`,\n});\n\n/**\n * Roles every dev user holds in every tenant they belong to. Per scope\n * decision Q3, every dev user is `tenant-admin` in every tenant — there\n * is no per-(user, tenant) variance to drive from.\n */\nexport const demoRolesForUserInTenant = (\n _user: DemoDevUser,\n _tenantId: string,\n): ReadonlyArray<PlatformRoleCode> => {\n void _user;\n void _tenantId;\n return [PLATFORM_ROLE_CODE.TENANT_ADMIN];\n};\n\n/**\n * The trigger this workflow subscribes to on the control event bus.\n * The `seed-system-data` workflow publishes\n * `platform.system-data-seeded.v1` after it has finished re-asserting\n * the platform-singleton Role records; on every fire this workflow\n * re-asserts the demo-tenant graph.\n *\n * The indirection (subscribing to `system-data-seeded` rather than to\n * the raw `platform.deployment-completed.v1` event) enforces a strict\n * happens-before edge between the system-data seed and the demo-data\n * seed. Without it, both workflows would fire in parallel from the\n * same deploy event and seed-demo-data's pre-flight Role check would\n * race seed-system-data's puts — a race that EventBridge retries\n * resolve, but only after firing the failure alarm at least once on a\n * fresh environment's first deploy.\n *\n * Re-exported from `@openhi/workflows` for symmetry with the handler's\n * import — keep the construct + handler reading from the same registry\n * entry so a rename upstream surfaces at both call sites.\n */\nexport { PlatformSystemDataSeededV1 };\n","/**\n * Sentinel `tenantId` used on platform-scoped `RoleAssignment` records.\n * A platform-scoped RA (e.g. `system-admin`) spans every tenant, but\n * the `RoleAssignment` entity requires a `tenantId` on its key for\n * sharding — there is no real tenant to point at. The `\"platform\"`\n * literal is a reserved value that never matches a real `Tenant.id`\n * and signals \"this RA scopes across all tenants\".\n *\n * The constant lives in the data layer so both the\n * {@link assertUserHasTenantMembershipOperation} write-time constraint\n * and the seed-demo-data workflow can read it without the constraint\n * helper having to reach back into the workflow package — which would\n * create a backwards data-layer-to-workflow dependency. The\n * `workflows/control-plane/seed-demo-data/events.ts` module re-exports\n * the constant under the same name for back-compat with existing\n * imports that point at the workflow's barrel.\n *\n * Renaming this constant is a wire-format break — the seed-demo-data\n * handler emits `RoleAssignment` records keyed on this value, and the\n * in-band records written under it become unreachable if the sentinel\n * changes.\n */\nexport const PLATFORM_SCOPE_TENANT_ID = \"platform\";\n","import type { Location } from \"@openhi/types\";\nimport {\n ON_SITE_DEMO_TENANT_ID,\n ON_SITE_DEMO_WORKSPACE_ID,\n demoScenarioIdentifier,\n openhiResourceIdentifier,\n} from \"./events\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/constructs/workflows/control-plane/seed-demo-data/on-site-demo-facilities.md\n *\n * Hand-authored Facility (FHIR Location) fixtures the\n * `seed-demo-data` workflow upserts into the on-site-medical UAT\n * demo tenant ({@link ON_SITE_DEMO_TENANT_ID} +\n * {@link ON_SITE_DEMO_WORKSPACE_ID}) on every non-prod deploy\n * (issue #1303).\n *\n * Three facilities — UAT testers exercise the calendar's \"View by\n * facility\" filter and the home-health vs facility-visit\n * routing. The on-site `AdminLocationFormPage` reads:\n * - `name`\n * - `type[0].text` — `\"facility\"` (drives the\n * classification dropdown)\n * - `address.line/city/state/postalCode/country`\n * - `telecom` (phone + email + optional fax)\n * - `status` (`\"active\"`)\n *\n * Director-of-nursing is not a first-class FHIR R4 `Location`\n * field. We denormalize it as an `extension` (single root\n * extension with three sub-extensions: `name`, `phone`,\n * `email`) under the established on-site URL convention\n * (`https://on-site-medical.app/fhir/StructureDefinition/*`) so a\n * later on-site UI iteration can pick it up without a schema\n * change.\n *\n * Ids are deterministic — re-fires upsert the same records,\n * matching the workflow's idempotency contract.\n */\n\n/**\n * Root extension URL stamped on every facility Location for the\n * director-of-nursing contact. The root extension carries three\n * sub-extensions (`name`, `phone`, `email`) — none of FHIR R4's\n * shipped extensions cover this exact triple, so we publish a\n * local URL under the on-site convention.\n */\nexport const DIRECTOR_OF_NURSING_EXTENSION_URL =\n \"https://on-site-medical.app/fhir/StructureDefinition/director-of-nursing\";\n\n/** Sub-extension URL: director-of-nursing display name. */\nexport const DIRECTOR_OF_NURSING_NAME_EXTENSION_URL = \"name\";\n\n/** Sub-extension URL: director-of-nursing phone (E.164). */\nexport const DIRECTOR_OF_NURSING_PHONE_EXTENSION_URL = \"phone\";\n\n/** Sub-extension URL: director-of-nursing email. */\nexport const DIRECTOR_OF_NURSING_EMAIL_EXTENSION_URL = \"email\";\n\ninterface FacilitySpec {\n readonly id: string;\n readonly name: string;\n readonly phone: string;\n readonly email: string;\n readonly addressLine: string;\n readonly addressCity: string;\n readonly addressState: string;\n readonly addressPostalCode: string;\n readonly directorOfNursingName: string;\n readonly directorOfNursingPhone: string;\n readonly directorOfNursingEmail: string;\n}\n\nconst ON_SITE_SCENARIO = \"on-site-demo\";\n\n/**\n * Three demo facilities. Names and addresses use real-world\n * neighbourhood references in the Atlanta metro to match the\n * convention established in `on-site-demo-fixtures.ts` (commit\n * 1535f710) — no fictional or sci-fi names.\n */\nconst FACILITY_SPECS: ReadonlyArray<FacilitySpec> = [\n {\n id: \"on-site-demo-facility-001\",\n name: \"Druid Hills Skilled Nursing\",\n phone: \"+14045550301\",\n email: \"frontdesk@druidhills.on-site-demo.example.com\",\n addressLine: \"1455 Clifton Road NE\",\n addressCity: \"Atlanta\",\n addressState: \"GA\",\n addressPostalCode: \"30322\",\n directorOfNursingName: \"Patricia Lambert, RN\",\n directorOfNursingPhone: \"+14045550311\",\n directorOfNursingEmail: \"p.lambert@druidhills.on-site-demo.example.com\",\n },\n {\n id: \"on-site-demo-facility-002\",\n name: \"Buckhead Rehabilitation Center\",\n phone: \"+14045550302\",\n email: \"frontdesk@buckhead.on-site-demo.example.com\",\n addressLine: \"3193 Howell Mill Road NW\",\n addressCity: \"Atlanta\",\n addressState: \"GA\",\n addressPostalCode: \"30327\",\n directorOfNursingName: \"Karen Whitfield, RN\",\n directorOfNursingPhone: \"+14045550312\",\n directorOfNursingEmail: \"k.whitfield@buckhead.on-site-demo.example.com\",\n },\n {\n id: \"on-site-demo-facility-003\",\n name: \"Decatur Senior Living\",\n phone: \"+14045550303\",\n email: \"frontdesk@decatur.on-site-demo.example.com\",\n addressLine: \"920 Church Street\",\n addressCity: \"Decatur\",\n addressState: \"GA\",\n addressPostalCode: \"30030\",\n directorOfNursingName: \"Monique Beaumont, RN\",\n directorOfNursingPhone: \"+14045550313\",\n directorOfNursingEmail: \"m.beaumont@decatur.on-site-demo.example.com\",\n },\n];\n\nconst buildIdentifierPair = (\n locationId: string,\n roleSuffix: string,\n): Location[\"identifier\"] => [\n demoScenarioIdentifier(ON_SITE_SCENARIO, roleSuffix),\n openhiResourceIdentifier({\n tenantId: ON_SITE_DEMO_TENANT_ID,\n workspaceId: ON_SITE_DEMO_WORKSPACE_ID,\n resourceType: \"Location\",\n id: locationId,\n }),\n];\n\nconst buildFacilityResource = (spec: FacilitySpec): Location => ({\n resourceType: \"Location\",\n id: spec.id,\n status: \"active\",\n name: spec.name,\n identifier: buildIdentifierPair(spec.id, `facility-${spec.id}`),\n type: [{ text: \"facility\" }],\n telecom: [\n { system: \"phone\", value: spec.phone, use: \"work\" },\n { system: \"email\", value: spec.email, use: \"work\" },\n ],\n address: {\n use: \"work\",\n line: [spec.addressLine],\n city: spec.addressCity,\n state: spec.addressState,\n postalCode: spec.addressPostalCode,\n country: \"US\",\n },\n extension: [\n {\n url: DIRECTOR_OF_NURSING_EXTENSION_URL,\n extension: [\n {\n url: DIRECTOR_OF_NURSING_NAME_EXTENSION_URL,\n valueString: spec.directorOfNursingName,\n },\n {\n url: DIRECTOR_OF_NURSING_PHONE_EXTENSION_URL,\n valueString: spec.directorOfNursingPhone,\n },\n {\n url: DIRECTOR_OF_NURSING_EMAIL_EXTENSION_URL,\n valueString: spec.directorOfNursingEmail,\n },\n ],\n },\n ],\n});\n\n/** Demo facilities seeded into the on-site UAT demo workspace. */\nexport const ON_SITE_DEMO_FACILITIES: ReadonlyArray<Location> =\n FACILITY_SPECS.map(buildFacilityResource);\n\n/** Stable facility ids in dispatch order. Re-exported for downstream tickets. */\nexport const ON_SITE_DEMO_FACILITY_IDS: ReadonlyArray<string> =\n FACILITY_SPECS.map((f) => f.id);\n","import type { Appointment } from \"@openhi/types\";\nimport {\n ON_SITE_DEMO_TENANT_ID,\n ON_SITE_DEMO_WORKSPACE_ID,\n demoScenarioIdentifier,\n openhiResourceIdentifier,\n} from \"./events\";\nimport { ON_SITE_DEMO_FACILITY_IDS } from \"./on-site-demo-facilities\";\nimport {\n ON_SITE_DEMO_DOCTOR_IDS,\n ON_SITE_DEMO_SCRIBE_IDS,\n} from \"./on-site-demo-fixtures\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/constructs/workflows/control-plane/seed-demo-data/on-site-demo-blocks.md\n *\n * Hand-authored weekly scheduling block fixtures the\n * `seed-demo-data` workflow upserts into the on-site-medical UAT\n * demo tenant ({@link ON_SITE_DEMO_TENANT_ID} +\n * {@link ON_SITE_DEMO_WORKSPACE_ID}) on every non-prod deploy\n * (issue #1303).\n *\n * Modelling choice: blocks are represented as FHIR\n * `Appointment` resources with `appointmentType.code = \"block\"`\n * (matching the on-site app's `isBlockAppointment` helper at\n * `sites/app-ehr/src/types/appointment.ts`). The on-site\n * calendar reads `Appointment` records, not `Schedule`/`Slot`\n * resources, so seeding `Appointment`s is the path that\n * actually renders something for UAT testers. Each block is\n * \"recurring weekly\" — we materialize that as a window of\n * concrete weekly occurrences anchored to the week containing\n * the seeder's `baseContext.date`, so blocks always show up at\n * a useful position relative to \"today\" on the demo schedule.\n *\n * Topology — issue #1303 design:\n * - Facility 1 (Druid Hills Skilled Nursing) — TWO weekly\n * blocks: Tuesday + Thursday (the high-volume facility).\n * - Facility 2 (Buckhead Rehabilitation Center) — one\n * weekly block on Wednesday.\n * - Facility 3 (Decatur Senior Living) — one weekly block\n * on Monday.\n *\n * Each block is assigned one doctor and one scribe from the\n * demo provider pool (#1302). Doctors are distributed so no\n * single doctor covers all four blocks. Capacities accommodate\n * 12-20 patients each (the upstream patient-distribution\n * ticket #1304 reads {@link ON_SITE_DEMO_BLOCK_CAPACITY_EXTENSION_URL}\n * to spread patients across blocks).\n */\n\n/**\n * Extension URL stamped on every block Appointment carrying the\n * block's intended capacity (number of patients the block can\n * accommodate). FHIR Appointment has no first-class capacity\n * field, so we publish a local URL under the on-site\n * convention.\n */\nexport const ON_SITE_DEMO_BLOCK_CAPACITY_EXTENSION_URL =\n \"https://on-site-medical.app/fhir/StructureDefinition/block-capacity\";\n\n/** Coding system the on-site app expects on Appointment.appointmentType. */\nexport const ON_SITE_APPOINTMENT_TYPE_SYSTEM =\n \"https://onsite-medical.org/appointment-type\";\n\n/**\n * Weeks of past occurrences materialized per block. Past\n * occurrences let UAT testers exercise \"history\" views without\n * waiting through time.\n */\nexport const BLOCK_OCCURRENCE_WEEKS_PAST = 4;\n\n/**\n * Weeks of future occurrences materialized per block. Future\n * occurrences cover the calendar's default \"month ahead\"\n * window plus room for testers to navigate forward.\n */\nexport const BLOCK_OCCURRENCE_WEEKS_FUTURE = 8;\n\n/**\n * Total weekly occurrences materialized per block template\n * (past + current week + future). Re-fires with the same\n * `baseContext.date` produce byte-identical occurrence ids.\n */\nexport const BLOCK_OCCURRENCES_PER_TEMPLATE =\n BLOCK_OCCURRENCE_WEEKS_PAST + 1 + BLOCK_OCCURRENCE_WEEKS_FUTURE;\n\n/**\n * ISO day-of-week index used by {@link BlockTemplate.dayOfWeek}.\n * 1 = Monday, ..., 7 = Sunday (matches ISO 8601 / FHIR usage).\n */\nexport type IsoDayOfWeek = 1 | 2 | 3 | 4 | 5 | 6 | 7;\n\ninterface BlockTemplate {\n /** Stable block-template id. Drives every occurrence's id prefix. */\n readonly id: string;\n /** Facility (Location) the block runs in. */\n readonly facilityId: string;\n /** Display name surfaced in calendar tooltips and event popovers. */\n readonly displayName: string;\n /** ISO day-of-week (1 = Monday … 7 = Sunday). */\n readonly dayOfWeek: IsoDayOfWeek;\n /** UTC hour-of-day the block starts at (0-23). */\n readonly startHourUtc: number;\n /** UTC hour-of-day the block ends at (0-23, exclusive). */\n readonly endHourUtc: number;\n /** Doctor (Practitioner) staffing the block. */\n readonly doctorId: string;\n /** Scribe (Practitioner) staffing the block. */\n readonly scribeId: string;\n /** Patient capacity. Used by #1304's patient-distribution helper. */\n readonly capacity: number;\n}\n\n/**\n * Four block templates across three facilities — the 2+1+1\n * pattern from #1303. Doctors are distributed: doctor-001 takes\n * one Druid Hills block, doctor-002 takes the other (so the\n * \"high-volume facility\" surfaces two distinct providers in the\n * calendar). Buckhead gets doctor-003; Decatur gets doctor-004.\n * Scribes rotate across the four blocks. All assigned doctors\n * come from the home-health-eligible first-five (#1302), so\n * downstream tickets that test home-health and facility flows\n * against the same provider pool will overlap.\n */\nconst BLOCK_TEMPLATES: ReadonlyArray<BlockTemplate> = [\n {\n id: \"on-site-demo-block-001\",\n facilityId: \"on-site-demo-facility-001\", // Druid Hills\n displayName: \"Druid Hills — Tuesday rounds\",\n dayOfWeek: 2, // Tuesday\n startHourUtc: 14, // 09:00 ET (EST: 14:00 UTC; EDT: 13:00 UTC) — fixed UTC keeps demo deterministic\n endHourUtc: 18, // 4-hour block\n doctorId: \"on-site-demo-doctor-001\",\n scribeId: \"on-site-demo-scribe-001\",\n capacity: 16,\n },\n {\n id: \"on-site-demo-block-002\",\n facilityId: \"on-site-demo-facility-001\", // Druid Hills (same facility, different weekday)\n displayName: \"Druid Hills — Thursday rounds\",\n dayOfWeek: 4, // Thursday\n startHourUtc: 14,\n endHourUtc: 18,\n doctorId: \"on-site-demo-doctor-002\",\n scribeId: \"on-site-demo-scribe-002\",\n capacity: 16,\n },\n {\n id: \"on-site-demo-block-003\",\n facilityId: \"on-site-demo-facility-002\", // Buckhead\n displayName: \"Buckhead — Wednesday rounds\",\n dayOfWeek: 3, // Wednesday\n startHourUtc: 14,\n endHourUtc: 18,\n doctorId: \"on-site-demo-doctor-003\",\n scribeId: \"on-site-demo-scribe-003\",\n capacity: 14,\n },\n {\n id: \"on-site-demo-block-004\",\n facilityId: \"on-site-demo-facility-003\", // Decatur\n displayName: \"Decatur — Monday rounds\",\n dayOfWeek: 1, // Monday\n startHourUtc: 14,\n endHourUtc: 18,\n doctorId: \"on-site-demo-doctor-004\",\n scribeId: \"on-site-demo-scribe-004\",\n capacity: 12,\n },\n];\n\n/**\n * Cross-fixture reference check. Block templates reference\n * facility ids (from {@link ON_SITE_DEMO_FACILITY_IDS}), doctor\n * ids (from {@link ON_SITE_DEMO_DOCTOR_IDS}), and scribe ids\n * (from {@link ON_SITE_DEMO_SCRIBE_IDS}) defined in sibling\n * fixture files. A typo would silently produce dangling\n * references in the seeded calendar.\n *\n * The validator runs lazily — called from\n * {@link buildOnSiteDemoBlockAppointments} — rather than at\n * module load, because `on-site-demo-fixtures.ts` (where the\n * doctor / scribe ids live) imports back into this module to\n * wire {@link buildOnSiteDemoBlockAppointments} into the\n * shared `ON_SITE_DEMO_FIXTURES` group. Doing the lookup at\n * load time would race that circular import and read\n * `undefined` for the upstream id arrays.\n */\nconst validateBlockTemplateReferences = (): void => {\n const facilitySet = new Set(ON_SITE_DEMO_FACILITY_IDS);\n const doctorSet = new Set(ON_SITE_DEMO_DOCTOR_IDS);\n const scribeSet = new Set(ON_SITE_DEMO_SCRIBE_IDS);\n for (const template of BLOCK_TEMPLATES) {\n if (!facilitySet.has(template.facilityId)) {\n throw new Error(\n `Block template \"${template.id}\" references unknown facility id \"${template.facilityId}\".`,\n );\n }\n if (!doctorSet.has(template.doctorId)) {\n throw new Error(\n `Block template \"${template.id}\" references unknown doctor id \"${template.doctorId}\".`,\n );\n }\n if (!scribeSet.has(template.scribeId)) {\n throw new Error(\n `Block template \"${template.id}\" references unknown scribe id \"${template.scribeId}\".`,\n );\n }\n }\n};\n\n/** Stable block-template ids in dispatch order. Re-exported for downstream tickets. */\nexport const ON_SITE_DEMO_BLOCK_TEMPLATE_IDS: ReadonlyArray<string> =\n BLOCK_TEMPLATES.map((t) => t.id);\n\nconst ON_SITE_SCENARIO = \"on-site-demo\";\n\n/**\n * Resolve the UTC date of the Monday of the ISO week containing\n * `referenceIso`. Works in UTC so the same input string always\n * produces the same output, regardless of the host's local TZ.\n */\nconst mondayOfIsoWeekUtc = (referenceIso: string): Date => {\n const ref = new Date(referenceIso);\n if (Number.isNaN(ref.getTime())) {\n throw new Error(\n `mondayOfIsoWeekUtc: invalid reference date \"${referenceIso}\".`,\n );\n }\n // getUTCDay(): Sunday = 0, Monday = 1, ..., Saturday = 6.\n // ISO week starts on Monday — shift Sunday (0) to 7 so the\n // subtraction below lands on the previous Monday in every case.\n const utcDay = ref.getUTCDay() === 0 ? 7 : ref.getUTCDay();\n const monday = new Date(\n Date.UTC(ref.getUTCFullYear(), ref.getUTCMonth(), ref.getUTCDate()),\n );\n monday.setUTCDate(monday.getUTCDate() - (utcDay - 1));\n return monday;\n};\n\n/**\n * Stable occurrence id derived from `(templateId, weekOffset)`.\n * `weekOffset` is signed: -1 for the prior week, 0 for the\n * anchor week, +1 for the next week, etc. Stamping the signed\n * offset (rather than a sequence number) keeps the ids stable\n * across re-fires that may use different past/future windows in\n * the future.\n */\nconst occurrenceId = (templateId: string, weekOffset: number): string => {\n const sign = weekOffset >= 0 ? \"p\" : \"m\"; // p = plus, m = minus\n const magnitude = Math.abs(weekOffset).toString().padStart(2, \"0\");\n return `${templateId}-w${sign}${magnitude}`;\n};\n\nconst buildIdentifierPair = (\n appointmentId: string,\n roleSuffix: string,\n): Appointment[\"identifier\"] => [\n demoScenarioIdentifier(ON_SITE_SCENARIO, roleSuffix),\n openhiResourceIdentifier({\n tenantId: ON_SITE_DEMO_TENANT_ID,\n workspaceId: ON_SITE_DEMO_WORKSPACE_ID,\n resourceType: \"Appointment\",\n id: appointmentId,\n }),\n];\n\nconst toIsoZ = (d: Date): string =>\n // toISOString() always emits a `Z` suffix on UTC times.\n d.toISOString();\n\nconst buildOccurrenceAppointment = (\n template: BlockTemplate,\n anchorMondayUtc: Date,\n weekOffset: number,\n): Appointment => {\n // Compute the occurrence's UTC date by walking from the\n // anchor Monday: + (weekOffset * 7) days + (dayOfWeek - 1)\n // days to reach the target weekday within that week.\n const occurrenceDay = new Date(anchorMondayUtc);\n occurrenceDay.setUTCDate(\n occurrenceDay.getUTCDate() + weekOffset * 7 + (template.dayOfWeek - 1),\n );\n\n const start = new Date(occurrenceDay);\n start.setUTCHours(template.startHourUtc, 0, 0, 0);\n const end = new Date(occurrenceDay);\n end.setUTCHours(template.endHourUtc, 0, 0, 0);\n\n const id = occurrenceId(template.id, weekOffset);\n return {\n resourceType: \"Appointment\",\n id,\n status: \"booked\",\n identifier: buildIdentifierPair(id, `block-${id}`),\n appointmentType: {\n coding: [\n {\n system: ON_SITE_APPOINTMENT_TYPE_SYSTEM,\n code: \"block\",\n display: \"Block\",\n },\n ],\n text: \"Block\",\n },\n description: template.displayName,\n start: toIsoZ(start),\n end: toIsoZ(end),\n minutesDuration: (template.endHourUtc - template.startHourUtc) * 60,\n participant: [\n {\n actor: {\n reference: `Location/${template.facilityId}`,\n type: \"Location\",\n },\n status: \"accepted\",\n },\n {\n actor: {\n reference: `Practitioner/${template.doctorId}`,\n type: \"Practitioner\",\n },\n status: \"accepted\",\n },\n {\n actor: {\n reference: `Practitioner/${template.scribeId}`,\n type: \"Practitioner\",\n },\n status: \"accepted\",\n },\n ],\n extension: [\n {\n url: ON_SITE_DEMO_BLOCK_CAPACITY_EXTENSION_URL,\n valueInteger: template.capacity,\n },\n ],\n };\n};\n\n/**\n * Materialize every block template's weekly occurrences,\n * anchored to the Monday of the ISO week containing\n * `referenceIso` (typically `baseContext.date`). Each template\n * produces {@link BLOCK_OCCURRENCES_PER_TEMPLATE} appointments:\n * `BLOCK_OCCURRENCE_WEEKS_PAST` past weeks, the current week,\n * and `BLOCK_OCCURRENCE_WEEKS_FUTURE` future weeks. With the\n * default window of 4 + 1 + 8 = 13 occurrences per template ×\n * 4 templates, the seeder writes 52 block Appointments per\n * fire.\n *\n * Idempotency: ids are derived from `(templateId, weekOffset)`,\n * not from a wall-clock timestamp, so re-fires of the seeder\n * with the same `referenceIso` upsert the same Appointment\n * records (no duplicates). A re-fire with a different\n * `referenceIso` (e.g., the deploy event days later) writes a\n * new set of occurrences and leaves prior weeks' records as\n * orphaned past history — that is acceptable for UAT.\n */\nexport const buildOnSiteDemoBlockAppointments = (\n referenceIso: string,\n): ReadonlyArray<Appointment> => {\n validateBlockTemplateReferences();\n const anchorMonday = mondayOfIsoWeekUtc(referenceIso);\n const out: Array<Appointment> = [];\n for (const template of BLOCK_TEMPLATES) {\n for (\n let weekOffset = -BLOCK_OCCURRENCE_WEEKS_PAST;\n weekOffset <= BLOCK_OCCURRENCE_WEEKS_FUTURE;\n weekOffset += 1\n ) {\n out.push(buildOccurrenceAppointment(template, anchorMonday, weekOffset));\n }\n }\n return out;\n};\n\n/**\n * Stable per-template (doctor, scribe) pair for the on-site\n * block schedule. Downstream tickets (e.g., the patient-\n * distribution helper in #1304) call this to look up which\n * provider pair staffs a given block without re-reading the\n * block-template list.\n */\nexport const findOnSiteDemoBlockTemplate = (\n templateId: string,\n):\n | {\n readonly id: string;\n readonly facilityId: string;\n readonly displayName: string;\n readonly doctorId: string;\n readonly scribeId: string;\n readonly capacity: number;\n readonly dayOfWeek: IsoDayOfWeek;\n }\n | undefined => {\n const t = BLOCK_TEMPLATES.find((tt) => tt.id === templateId);\n if (!t) {\n return undefined;\n }\n return {\n id: t.id,\n facilityId: t.facilityId,\n displayName: t.displayName,\n doctorId: t.doctorId,\n scribeId: t.scribeId,\n capacity: t.capacity,\n dayOfWeek: t.dayOfWeek,\n };\n};\n","import type { Coverage, Patient } from \"@openhi/types\";\nimport {\n ON_SITE_DEMO_TENANT_ID,\n ON_SITE_DEMO_WORKSPACE_ID,\n demoScenarioIdentifier,\n openhiResourceIdentifier,\n} from \"./events\";\nimport {\n ON_SITE_DEMO_BLOCK_TEMPLATE_IDS,\n findOnSiteDemoBlockTemplate,\n} from \"./on-site-demo-blocks\";\nimport { ON_SITE_DEMO_FACILITY_IDS } from \"./on-site-demo-facilities\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/constructs/workflows/control-plane/seed-demo-data/on-site-demo-facility-patients.md\n *\n * Hand-authored facility Patient + Coverage fixtures the\n * `seed-demo-data` workflow upserts into the on-site-medical UAT\n * demo tenant ({@link ON_SITE_DEMO_TENANT_ID} +\n * {@link ON_SITE_DEMO_WORKSPACE_ID}) on every non-prod deploy\n * (issue #1304).\n *\n * Topology — issue #1304 design:\n * - 4 blocks (#1303) × per-block patient count (16 + 14 + 18 +\n * 12 = 60 scheduled patients). No patient appears in more\n * than one block.\n * - Plus 6 intake-complete-not-yet-scheduled patients (2 per\n * facility — small subset that exercises the \"new intake,\n * not yet on a calendar\" UI state). Total: 66 Patients.\n * - Every patient is assigned `care-context = facility` via\n * the on-site `patient-default-care-setting` /\n * `patient-default-care-location` extension pair\n * (`sites/app-ehr/src/types/fhir-extensions/patient.ts`). The\n * UI distinguishes facility vs home-health patients by\n * reading those extensions, so seeding them is the path that\n * actually surfaces the patient under the right \"Patient\n * Type\" column in the on-site EHR.\n *\n * Insurance:\n * - Every patient gets a primary Coverage with\n * `status: \"active\"` and a verification date stamped on the\n * coverage body via the on-site `coverage-verification-date`\n * extension.\n * - A subset (~40%) gets a secondary Coverage.\n * - Payor mix: commercial / Medicare / Medicare Advantage.\n * - QMB is a Medicare-only program (real-world constraint); the\n * QMB extension only attaches to Medicare-primary patients.\n * - ~20% of patients carry the `patient-hospice-status`\n * extension on the Patient resource (CMS hospice billing\n * status — separate from QMB).\n *\n * Modelling choice — block assignment. The seeder also records\n * which block template a patient is assigned to so downstream\n * tickets (#1306 — encounters per scheduled patient per block\n * occurrence) can fan out without re-deriving the mapping.\n * Encounters are NOT created here; this ticket only attaches the\n * block reference via an extension on the Patient body. Intake-\n * only patients omit the extension entirely.\n *\n * Ids are deterministic — re-fires upsert the same records,\n * matching the workflow's idempotency contract. Adding,\n * renaming, or moving a patient is a one-line edit here plus a\n * redeploy.\n */\n\n/**\n * Extension URL stamped on the Patient body when the patient's\n * default care setting is facility-based (mirrors the on-site\n * EHR's `EXT_PATIENT_DEFAULT_CARE_SETTING` constant at\n * `sites/app-ehr/src/types/fhir-extensions/patient.ts`).\n */\nexport const PATIENT_DEFAULT_CARE_SETTING_EXTENSION_URL =\n \"https://on-site-medical.app/fhir/StructureDefinition/patient-default-care-setting\";\n\n/**\n * Extension URL stamped on the Patient body when the patient's\n * default care setting is `facility`, carrying the Location id\n * (mirrors the on-site EHR's `EXT_PATIENT_DEFAULT_CARE_LOCATION`\n * constant).\n */\nexport const PATIENT_DEFAULT_CARE_LOCATION_EXTENSION_URL =\n \"https://on-site-medical.app/fhir/StructureDefinition/patient-default-care-location\";\n\n/** Extension URL: patient residency admission date (facility-only). */\nexport const PATIENT_RESIDENCY_ADMISSION_DATE_EXTENSION_URL =\n \"https://on-site-medical.app/fhir/StructureDefinition/patient-residency-admission-date\";\n\n/** Extension URL: patient residency room number (facility-only). */\nexport const PATIENT_RESIDENCY_ROOM_EXTENSION_URL =\n \"https://on-site-medical.app/fhir/StructureDefinition/patient-residency-room\";\n\n/**\n * Extension URL stamped on the Patient body recording which\n * weekly scheduling block template the patient is assigned to\n * (#1303 + #1304). Downstream tickets (#1306 — encounters per\n * block occurrence) read this to fan out per-occurrence\n * Encounter records. Intake-only patients (no block yet) omit\n * the extension entirely.\n */\nexport const PATIENT_ASSIGNED_BLOCK_TEMPLATE_EXTENSION_URL =\n \"https://on-site-medical.app/fhir/StructureDefinition/patient-assigned-block-template\";\n\n/**\n * Root extension URL stamped on the Patient body recording the\n * patient's hospice status (CMS hospice billing flag). Carries\n * three sub-extensions (`status`, `effectiveDate`,\n * `terminationDate`) mirroring the on-site Medicare form's\n * hospice fields at\n * `sites/app-ehr/src/fixtures/medicareForm.ts`. Only ~20% of\n * patients carry this extension; the absence of the extension\n * means the patient is not in hospice.\n */\nexport const PATIENT_HOSPICE_STATUS_EXTENSION_URL =\n \"https://on-site-medical.app/fhir/StructureDefinition/patient-hospice-status\";\n\n/** Sub-extension URL under {@link PATIENT_HOSPICE_STATUS_EXTENSION_URL}. */\nexport const HOSPICE_STATUS_VALUE_SUB_EXTENSION_URL = \"status\";\n\n/** Sub-extension URL under {@link PATIENT_HOSPICE_STATUS_EXTENSION_URL}. */\nexport const HOSPICE_EFFECTIVE_DATE_SUB_EXTENSION_URL = \"effectiveDate\";\n\n/**\n * Extension URL stamped on every primary Coverage body recording\n * the most-recent verification timestamp. The on-site\n * `VerificationHistoryTable` displays verification rows from this\n * value (and from the Coverage's audit history downstream). The\n * value is an ISO 8601 instant in UTC.\n */\nexport const COVERAGE_VERIFICATION_DATE_EXTENSION_URL =\n \"https://on-site-medical.app/fhir/StructureDefinition/coverage-verification-date\";\n\n/**\n * Root extension URL stamped on a Medicare-primary Coverage\n * recording the QMB (Qualified Medicare Beneficiary) status.\n * Carries `status` + `effectiveDate` sub-extensions mirroring\n * the on-site Medicare form (`sites/app-ehr/src/fixtures/medicareForm.ts`).\n * QMB only attaches to Medicare-primary patients — it is a\n * Medicare program and is invalid on commercial-primary or\n * Medicare-Advantage-primary coverages.\n */\nexport const COVERAGE_QMB_STATUS_EXTENSION_URL =\n \"https://on-site-medical.app/fhir/StructureDefinition/coverage-qmb-status\";\n\n/** Sub-extension URL under {@link COVERAGE_QMB_STATUS_EXTENSION_URL}. */\nexport const QMB_STATUS_VALUE_SUB_EXTENSION_URL = \"status\";\n\n/** Sub-extension URL under {@link COVERAGE_QMB_STATUS_EXTENSION_URL}. */\nexport const QMB_EFFECTIVE_DATE_SUB_EXTENSION_URL = \"effectiveDate\";\n\n/**\n * Payor codes the on-site app reads from Coverage.type.coding[0].\n * The values mirror the labels used in the on-site Medicare and\n * insurance forms. `medicare-advantage` is intentionally distinct\n * from `medicare` — Medicare Advantage is a private-plan layer on\n * top of Medicare and bills through different payor pathways.\n */\nexport const COVERAGE_PAYOR_TYPE_SYSTEM =\n \"https://on-site-medical.app/fhir/CodeSystem/coverage-payor-type\";\n\n/** Payor type values written to {@link COVERAGE_PAYOR_TYPE_SYSTEM}. */\nexport const PAYOR_TYPE_COMMERCIAL = \"commercial\";\n\n/** Payor type values written to {@link COVERAGE_PAYOR_TYPE_SYSTEM}. */\nexport const PAYOR_TYPE_MEDICARE = \"medicare\";\n\n/** Payor type values written to {@link COVERAGE_PAYOR_TYPE_SYSTEM}. */\nexport const PAYOR_TYPE_MEDICARE_ADVANTAGE = \"medicare-advantage\";\n\n/**\n * Per-block patient counts. Four blocks (#1303), each filled with\n * 12-20 unique patients per AC. Counts are locked in here so\n * tests can assert exact totals against the same number the\n * generator uses. Total scheduled patients across all blocks:\n * 16 + 14 + 18 + 12 = 60.\n *\n * Order matches `ON_SITE_DEMO_BLOCK_TEMPLATE_IDS` (block-001\n * → block-004).\n */\nconst PATIENTS_PER_BLOCK: ReadonlyArray<{\n readonly blockTemplateId: string;\n readonly count: number;\n}> = [\n { blockTemplateId: \"on-site-demo-block-001\", count: 16 },\n { blockTemplateId: \"on-site-demo-block-002\", count: 14 },\n { blockTemplateId: \"on-site-demo-block-003\", count: 18 },\n { blockTemplateId: \"on-site-demo-block-004\", count: 12 },\n];\n\n/**\n * Intake-complete-not-yet-scheduled patients per facility. Small\n * subset (2 per facility × 3 facilities = 6 total) — exercises\n * the on-site UI state \"patient has been intaken at a facility\n * but has not yet been added to a weekly block\".\n */\nconst INTAKE_ONLY_PATIENTS_PER_FACILITY = 2;\n\ntype PayorType =\n | typeof PAYOR_TYPE_COMMERCIAL\n | typeof PAYOR_TYPE_MEDICARE\n | typeof PAYOR_TYPE_MEDICARE_ADVANTAGE;\n\n/**\n * Payor catalogue used to stamp realistic carrier names on each\n * primary / secondary Coverage. Each entry pairs the on-site\n * payor-type code with a human-readable display name surfaced in\n * the insurance card.\n */\nconst PRIMARY_PAYOR_OPTIONS: ReadonlyArray<{\n readonly type: PayorType;\n readonly display: string;\n}> = [\n { type: PAYOR_TYPE_COMMERCIAL, display: \"Aetna PPO\" },\n { type: PAYOR_TYPE_COMMERCIAL, display: \"Blue Cross Blue Shield of Georgia\" },\n { type: PAYOR_TYPE_COMMERCIAL, display: \"UnitedHealthcare Choice Plus\" },\n { type: PAYOR_TYPE_COMMERCIAL, display: \"Cigna OAP\" },\n { type: PAYOR_TYPE_MEDICARE, display: \"Medicare Part B\" },\n { type: PAYOR_TYPE_MEDICARE_ADVANTAGE, display: \"Humana Medicare Advantage\" },\n {\n type: PAYOR_TYPE_MEDICARE_ADVANTAGE,\n display: \"Wellcare by Allwell HMO\",\n },\n];\n\n/**\n * Secondary-coverage payors. Secondary policies on facility\n * patients are typically supplemental Medicare (\"Medigap\") plans\n * or smaller commercial gap policies — distinct from the primary\n * carrier catalogue so realistic combinations show up in the UI.\n */\nconst SECONDARY_PAYOR_OPTIONS: ReadonlyArray<{\n readonly display: string;\n}> = [\n { display: \"AARP Medigap Plan G\" },\n { display: \"Mutual of Omaha Medicare Supplement\" },\n { display: \"Cigna Supplemental Health\" },\n { display: \"AFLAC Supplemental\" },\n];\n\n/**\n * Real-looking facility-patient last names. Same convention as\n * the providers / scribes (#1302) — common American family\n * names, no fictional / sci-fi names. The list is intentionally\n * larger than the number of seeded patients so future tickets\n * can grow the roster without rotating already-deployed ids.\n */\nconst PATIENT_LAST_NAMES: ReadonlyArray<string> = [\n \"Anderson\",\n \"Bennett\",\n \"Brennan\",\n \"Carter\",\n \"Chen\",\n \"Coleman\",\n \"Cooper\",\n \"Davis\",\n \"Diaz\",\n \"Edwards\",\n \"Fisher\",\n \"Foster\",\n \"Garcia\",\n \"Garrett\",\n \"Gonzalez\",\n \"Graham\",\n \"Greene\",\n \"Hall\",\n \"Harper\",\n \"Harris\",\n \"Hayes\",\n \"Hernandez\",\n \"Holloway\",\n \"Hughes\",\n \"Jackson\",\n \"Jenkins\",\n \"Johnson\",\n \"Jones\",\n \"Kelly\",\n \"Kim\",\n \"Lambert\",\n \"Lawson\",\n \"Lee\",\n \"Lopez\",\n \"Marshall\",\n \"Martin\",\n \"Mason\",\n \"McKenzie\",\n \"Mendez\",\n \"Miller\",\n \"Mitchell\",\n \"Moore\",\n \"Morgan\",\n \"Morris\",\n \"Murphy\",\n \"Nguyen\",\n \"Nichols\",\n \"Norton\",\n \"O'Brien\",\n \"Ortiz\",\n \"Owens\",\n \"Park\",\n \"Patel\",\n \"Pearson\",\n \"Perez\",\n \"Phillips\",\n \"Porter\",\n \"Powell\",\n \"Ramirez\",\n \"Reed\",\n \"Reyes\",\n \"Robinson\",\n \"Rodriguez\",\n \"Russell\",\n \"Sanders\",\n \"Schultz\",\n \"Singh\",\n \"Stewart\",\n \"Sullivan\",\n \"Tanaka\",\n \"Taylor\",\n \"Thompson\",\n \"Torres\",\n \"Walker\",\n \"Wallace\",\n \"Watson\",\n \"Webb\",\n \"Williams\",\n \"Wilson\",\n \"Wong\",\n \"Wright\",\n];\n\n/**\n * First-name pool. Roughly balanced between traditionally-male\n * and traditionally-female names; the `gender` field is derived\n * deterministically from the index so re-fires assign the same\n * person consistent gender.\n */\nconst PATIENT_FIRST_NAMES: ReadonlyArray<{\n readonly name: string;\n readonly gender: \"male\" | \"female\";\n}> = [\n { name: \"Margaret\", gender: \"female\" },\n { name: \"Robert\", gender: \"male\" },\n { name: \"Dorothy\", gender: \"female\" },\n { name: \"William\", gender: \"male\" },\n { name: \"Helen\", gender: \"female\" },\n { name: \"Charles\", gender: \"male\" },\n { name: \"Patricia\", gender: \"female\" },\n { name: \"Richard\", gender: \"male\" },\n { name: \"Barbara\", gender: \"female\" },\n { name: \"James\", gender: \"male\" },\n { name: \"Linda\", gender: \"female\" },\n { name: \"George\", gender: \"male\" },\n { name: \"Mary\", gender: \"female\" },\n { name: \"Joseph\", gender: \"male\" },\n { name: \"Elizabeth\", gender: \"female\" },\n { name: \"Thomas\", gender: \"male\" },\n { name: \"Susan\", gender: \"female\" },\n { name: \"Frank\", gender: \"male\" },\n { name: \"Ruth\", gender: \"female\" },\n { name: \"Walter\", gender: \"male\" },\n { name: \"Carol\", gender: \"female\" },\n { name: \"Donald\", gender: \"male\" },\n { name: \"Janet\", gender: \"female\" },\n { name: \"Harold\", gender: \"male\" },\n { name: \"Joan\", gender: \"female\" },\n { name: \"Edward\", gender: \"male\" },\n { name: \"Nancy\", gender: \"female\" },\n { name: \"Henry\", gender: \"male\" },\n { name: \"Betty\", gender: \"female\" },\n { name: \"Arthur\", gender: \"male\" },\n];\n\nconst ON_SITE_SCENARIO = \"on-site-demo\";\n\n/**\n * Anchor date used when materialising deterministic timestamps\n * (birth dates, verification dates, admission dates). Fixed so\n * re-fires of the seeder against the same `baseContext.date`\n * produce byte-identical Patient + Coverage bodies. Chosen to\n * sit a year before the demo \"today\" so admission dates look\n * recent.\n */\nconst PATIENT_ANCHOR_DATE = \"2026-05-01T00:00:00Z\";\n\n/**\n * Per-patient deterministic seed object. The generator below\n * walks `PATIENTS_PER_BLOCK` and an intake-only pass to produce\n * one of these per Patient/Coverage pair.\n */\ninterface FacilityPatientSpec {\n /** Stable Patient id (also drives the demo URN identifier). */\n readonly id: string;\n /** Sequence ordinal — drives deterministic name/payor selection. */\n readonly index: number;\n /** Facility (Location) the patient is admitted to. */\n readonly facilityId: string;\n /**\n * Block template id the patient is scheduled into, or\n * `undefined` for the intake-only subset.\n */\n readonly blockTemplateId: string | undefined;\n}\n\nconst padIndex = (n: number): string => n.toString().padStart(3, \"0\");\n\n/**\n * Derive a deterministic birthDate offset from the anchor date.\n * Spreads patients across a roughly 30-year band centred on\n * \"elderly-ish\" (the on-site facility-patient population skews\n * older). Result is a `YYYY-MM-DD` FHIR `date`.\n */\nconst deterministicBirthDate = (index: number): string => {\n // Spread across 1935..1965 deterministically — older skew.\n const baseYear = 1935;\n const yearSpan = 30;\n const year = baseYear + (index % yearSpan);\n const month = ((index * 7) % 12) + 1;\n // Use 1-28 to avoid month-length edge cases.\n const day = ((index * 11) % 28) + 1;\n const mm = month.toString().padStart(2, \"0\");\n const dd = day.toString().padStart(2, \"0\");\n return `${year}-${mm}-${dd}`;\n};\n\n/**\n * Derive a deterministic verification date inside the 30 days\n * preceding the anchor date. Result is an ISO 8601 instant in\n * UTC.\n */\nconst deterministicVerificationDate = (index: number): string => {\n // Day offset 1..30 prior to the anchor.\n const dayOffset = (index % 30) + 1;\n const anchor = new Date(PATIENT_ANCHOR_DATE);\n const verifyAt = new Date(anchor);\n verifyAt.setUTCDate(verifyAt.getUTCDate() - dayOffset);\n return verifyAt.toISOString();\n};\n\n/**\n * Derive a deterministic admission date inside the year\n * preceding the anchor date. Result is a `YYYY-MM-DD` FHIR\n * `date`.\n */\nconst deterministicAdmissionDate = (index: number): string => {\n const dayOffset = ((index * 13) % 365) + 1;\n const anchor = new Date(PATIENT_ANCHOR_DATE);\n const admitAt = new Date(anchor);\n admitAt.setUTCDate(admitAt.getUTCDate() - dayOffset);\n return admitAt.toISOString().slice(0, 10);\n};\n\n/**\n * Deterministic phone in the same +1-404-555 demo block as the\n * providers (#1302). Patient phones occupy the 0400 prefix to\n * avoid collisions with provider / facility ranges.\n */\nconst deterministicPhone = (index: number): string => {\n const last4 = (400 + index).toString().padStart(4, \"0\");\n return `+1404555${last4}`;\n};\n\nconst deterministicEmail = (\n firstName: string,\n lastName: string,\n index: number,\n): string => {\n const local = `${firstName}.${lastName}.${padIndex(index)}`\n .toLowerCase()\n .replace(/[^a-z0-9.]/g, \"\");\n return `${local}@on-site-demo.example.com`;\n};\n\nconst FACILITY_STREET_NAMES: ReadonlyArray<string> = [\n \"Peachtree Street NE\",\n \"Ponce de Leon Avenue\",\n \"Piedmont Avenue\",\n \"Howell Mill Road NW\",\n \"Northside Drive NW\",\n \"Edgewood Avenue SE\",\n \"Spring Street NW\",\n \"Clifton Road NE\",\n];\n\nconst deterministicAddressLine = (index: number): string => {\n const houseNumber = 100 + index * 7;\n const streetIndex = index % FACILITY_STREET_NAMES.length;\n return `${houseNumber} ${FACILITY_STREET_NAMES[streetIndex]}`;\n};\n\n/**\n * Derive primary payor type from the patient index so the mix\n * across all patients is deterministic and balanced. Roughly:\n * - ~40% commercial\n * - ~30% Medicare\n * - ~30% Medicare Advantage\n */\nconst deterministicPrimaryPayor = (\n index: number,\n): { readonly type: PayorType; readonly display: string } => {\n // 0..9 % 10 — 0,1,2,3 = commercial; 4,5,6 = Medicare; 7,8,9 = Medicare Advantage.\n const bucket = index % 10;\n if (bucket <= 3) {\n return PRIMARY_PAYOR_OPTIONS[bucket % 4]; // commercial entries are first 4\n }\n if (bucket <= 6) {\n return PRIMARY_PAYOR_OPTIONS[4]; // Medicare Part B\n }\n // Two Medicare Advantage entries follow.\n return PRIMARY_PAYOR_OPTIONS[5 + ((bucket - 7) % 2)];\n};\n\n/**\n * Whether the patient gets a secondary Coverage. Targets ~40%\n * of patients (every other-third, roughly), giving the AC's\n * \"subset has secondary insurance\" with the right magnitude.\n */\nconst hasSecondaryCoverage = (index: number): boolean => {\n // Approx 40% — every index whose value mod 5 is 0, 1.\n return index % 5 < 2;\n};\n\n/**\n * Whether QMB attaches to this patient. QMB is Medicare-only —\n * the caller MUST short-circuit on payor type before consulting\n * this function. Within Medicare-primary patients, ~50% carry\n * QMB so it shows up clearly in UAT.\n */\nconst hasQmbStatus = (index: number): boolean => {\n return index % 2 === 0;\n};\n\n/**\n * Whether the patient is flagged as hospice (CMS billing flag).\n * Targets ~20% of patients per AC.\n */\nconst isHospicePatient = (index: number): boolean => {\n // Every 5th patient — exactly 20%.\n return index % 5 === 0;\n};\n\nconst buildIdentifierPair = (\n patientId: string,\n roleSuffix: string,\n): Patient[\"identifier\"] => [\n demoScenarioIdentifier(ON_SITE_SCENARIO, roleSuffix),\n openhiResourceIdentifier({\n tenantId: ON_SITE_DEMO_TENANT_ID,\n workspaceId: ON_SITE_DEMO_WORKSPACE_ID,\n resourceType: \"Patient\",\n id: patientId,\n }),\n];\n\nconst buildCoverageIdentifierPair = (\n coverageId: string,\n roleSuffix: string,\n): Coverage[\"identifier\"] => [\n demoScenarioIdentifier(ON_SITE_SCENARIO, roleSuffix),\n openhiResourceIdentifier({\n tenantId: ON_SITE_DEMO_TENANT_ID,\n workspaceId: ON_SITE_DEMO_WORKSPACE_ID,\n resourceType: \"Coverage\",\n id: coverageId,\n }),\n];\n\n/**\n * Build the Patient resource for one facility-patient spec.\n * Stamps the care-context extensions, optional block reference,\n * optional hospice extension, and the standard demographic\n * fields the on-site Demographics / Contacts / Care Context\n * cards read.\n */\nconst buildFacilityPatientResource = (spec: FacilityPatientSpec): Patient => {\n const firstNameEntry =\n PATIENT_FIRST_NAMES[spec.index % PATIENT_FIRST_NAMES.length];\n const lastName =\n PATIENT_LAST_NAMES[(spec.index * 3) % PATIENT_LAST_NAMES.length];\n const fullText = `${firstNameEntry.name} ${lastName}`;\n const admissionDate = deterministicAdmissionDate(spec.index);\n const blockExtension = spec.blockTemplateId\n ? [\n {\n url: PATIENT_ASSIGNED_BLOCK_TEMPLATE_EXTENSION_URL,\n valueString: spec.blockTemplateId,\n },\n ]\n : [];\n const hospiceExtension = isHospicePatient(spec.index)\n ? [\n {\n url: PATIENT_HOSPICE_STATUS_EXTENSION_URL,\n extension: [\n {\n url: HOSPICE_STATUS_VALUE_SUB_EXTENSION_URL,\n valueCode: \"in_hospice\",\n },\n {\n url: HOSPICE_EFFECTIVE_DATE_SUB_EXTENSION_URL,\n valueDate: admissionDate,\n },\n ],\n },\n ]\n : [];\n return {\n resourceType: \"Patient\",\n id: spec.id,\n active: true,\n identifier: buildIdentifierPair(spec.id, `patient-${spec.id}`),\n name: [\n {\n use: \"official\",\n text: fullText,\n given: [firstNameEntry.name],\n family: lastName,\n },\n ],\n gender: firstNameEntry.gender,\n birthDate: deterministicBirthDate(spec.index),\n telecom: [\n {\n system: \"phone\",\n value: deterministicPhone(spec.index),\n use: \"home\",\n },\n {\n system: \"email\",\n value: deterministicEmail(firstNameEntry.name, lastName, spec.index),\n use: \"home\",\n },\n ],\n address: [\n {\n use: \"home\",\n line: [deterministicAddressLine(spec.index)],\n city: \"Atlanta\",\n state: \"GA\",\n postalCode: \"30303\",\n country: \"US\",\n },\n ],\n extension: [\n {\n url: PATIENT_DEFAULT_CARE_SETTING_EXTENSION_URL,\n valueCode: \"facility\",\n },\n {\n url: PATIENT_DEFAULT_CARE_LOCATION_EXTENSION_URL,\n valueReference: { reference: `Location/${spec.facilityId}` },\n },\n {\n url: PATIENT_RESIDENCY_ADMISSION_DATE_EXTENSION_URL,\n valueDate: admissionDate,\n },\n {\n url: PATIENT_RESIDENCY_ROOM_EXTENSION_URL,\n // Pad to 3 digits so room numbers look like 100..600.\n valueString: `${100 + (spec.index % 500)}`,\n },\n ...blockExtension,\n ...hospiceExtension,\n ],\n };\n};\n\n/**\n * Build the primary Coverage resource for one facility-patient\n * spec. Every primary Coverage carries:\n * - status = active\n * - beneficiary reference back to the Patient\n * - payor type (commercial / medicare / medicare-advantage)\n * with a `display` name surfaced in the insurance card\n * - coverage-verification-date extension\n * - QMB extension when the patient is Medicare-primary AND\n * {@link hasQmbStatus} returns true.\n */\nconst buildPrimaryCoverageResource = (spec: FacilityPatientSpec): Coverage => {\n const id = `${spec.id}-coverage-primary`;\n const payor = deterministicPrimaryPayor(spec.index);\n const verificationDate = deterministicVerificationDate(spec.index);\n const isMedicarePrimary = payor.type === PAYOR_TYPE_MEDICARE;\n const qmbExtension =\n isMedicarePrimary && hasQmbStatus(spec.index)\n ? [\n {\n url: COVERAGE_QMB_STATUS_EXTENSION_URL,\n extension: [\n {\n url: QMB_STATUS_VALUE_SUB_EXTENSION_URL,\n valueCode: \"active\",\n },\n {\n url: QMB_EFFECTIVE_DATE_SUB_EXTENSION_URL,\n valueDate: deterministicAdmissionDate(spec.index),\n },\n ],\n },\n ]\n : [];\n return {\n resourceType: \"Coverage\",\n id,\n status: \"active\",\n identifier: buildCoverageIdentifierPair(id, `coverage-primary-${spec.id}`),\n beneficiary: { reference: `Patient/${spec.id}`, type: \"Patient\" },\n subscriber: { reference: `Patient/${spec.id}`, type: \"Patient\" },\n subscriberId: `MBR-${padIndex(spec.index)}-PRI`,\n relationship: { text: \"self\" },\n payor: [\n {\n display: payor.display,\n },\n ],\n type: {\n coding: [\n {\n system: COVERAGE_PAYOR_TYPE_SYSTEM,\n code: payor.type,\n display: payor.display,\n },\n ],\n text: payor.display,\n },\n order: 1,\n extension: [\n {\n url: COVERAGE_VERIFICATION_DATE_EXTENSION_URL,\n valueDateTime: verificationDate,\n },\n ...qmbExtension,\n ],\n };\n};\n\n/**\n * Build the secondary Coverage resource when {@link hasSecondaryCoverage}\n * returns true. Returns `undefined` otherwise so callers can spread\n * the result safely.\n */\nconst buildSecondaryCoverageResource = (\n spec: FacilityPatientSpec,\n): Coverage | undefined => {\n if (!hasSecondaryCoverage(spec.index)) {\n return undefined;\n }\n const id = `${spec.id}-coverage-secondary`;\n const payor =\n SECONDARY_PAYOR_OPTIONS[spec.index % SECONDARY_PAYOR_OPTIONS.length];\n const verificationDate = deterministicVerificationDate(spec.index);\n return {\n resourceType: \"Coverage\",\n id,\n status: \"active\",\n identifier: buildCoverageIdentifierPair(\n id,\n `coverage-secondary-${spec.id}`,\n ),\n beneficiary: { reference: `Patient/${spec.id}`, type: \"Patient\" },\n subscriber: { reference: `Patient/${spec.id}`, type: \"Patient\" },\n subscriberId: `MBR-${padIndex(spec.index)}-SEC`,\n relationship: { text: \"self\" },\n payor: [\n {\n display: payor.display,\n },\n ],\n type: {\n text: payor.display,\n },\n order: 2,\n extension: [\n {\n url: COVERAGE_VERIFICATION_DATE_EXTENSION_URL,\n valueDateTime: verificationDate,\n },\n ],\n };\n};\n\n/**\n * Materialise every facility-patient spec — scheduled patients\n * from `PATIENTS_PER_BLOCK` plus the intake-only patients per\n * facility. Walks the blocks first (so scheduled patients land\n * at lower ids than intake-only patients) and consumes a single\n * monotonically-incrementing sequence ordinal across both\n * passes. The ordinal is what drives every deterministic field\n * (name, birthDate, payor mix, hospice / QMB flags, etc.), so\n * the implementation guarantees stable bodies across re-fires.\n */\nconst buildAllFacilityPatientSpecs = (): ReadonlyArray<FacilityPatientSpec> => {\n validateBlockReferences();\n const specs: Array<FacilityPatientSpec> = [];\n let nextIndex = 0;\n // Scheduled patients — one block at a time.\n for (const { blockTemplateId, count } of PATIENTS_PER_BLOCK) {\n const template = findOnSiteDemoBlockTemplate(blockTemplateId);\n if (!template) {\n throw new Error(\n `Block template \"${blockTemplateId}\" not found while seeding facility patients.`,\n );\n }\n for (let i = 0; i < count; i += 1) {\n const index = nextIndex;\n specs.push({\n id: `on-site-demo-facility-patient-${padIndex(index + 1)}`,\n index,\n facilityId: template.facilityId,\n blockTemplateId,\n });\n nextIndex += 1;\n }\n }\n // Intake-only patients — 2 per facility (id, 3 facilities).\n for (const facilityId of ON_SITE_DEMO_FACILITY_IDS) {\n for (let i = 0; i < INTAKE_ONLY_PATIENTS_PER_FACILITY; i += 1) {\n const index = nextIndex;\n specs.push({\n id: `on-site-demo-facility-patient-${padIndex(index + 1)}`,\n index,\n facilityId,\n blockTemplateId: undefined,\n });\n nextIndex += 1;\n }\n }\n return specs;\n};\n\n/**\n * Cross-fixture reference check. Facility-patient specs reference\n * block-template ids (from {@link ON_SITE_DEMO_BLOCK_TEMPLATE_IDS})\n * and facility ids (from {@link ON_SITE_DEMO_FACILITY_IDS}). A\n * typo here would silently produce dangling references in the\n * seeded patient bodies.\n *\n * The validator runs lazily on first call to\n * {@link buildAllFacilityPatientSpecs} rather than at module load —\n * mirrors the `on-site-demo-blocks.ts` precedent so circular\n * imports between the patient/block/facility fixtures resolve\n * cleanly.\n */\nconst validateBlockReferences = (): void => {\n const blockSet = new Set(ON_SITE_DEMO_BLOCK_TEMPLATE_IDS);\n for (const entry of PATIENTS_PER_BLOCK) {\n if (!blockSet.has(entry.blockTemplateId)) {\n throw new Error(\n `Facility-patient generator references unknown block template id \"${entry.blockTemplateId}\".`,\n );\n }\n }\n};\n\n/**\n * Lazy cache for the spec list. Computed on first call so the\n * top-level module load does not read\n * {@link ON_SITE_DEMO_BLOCK_TEMPLATE_IDS} while the block module\n * is still mid-evaluation (the same TDZ pitfall the block\n * module's `validateBlockTemplateReferences` documents). Every\n * exported helper routes through {@link getFacilityPatientSpecs}\n * so the lazy contract is observed at every entry point — the\n * seeder calls {@link buildOnSiteDemoFacilityPatients} /\n * {@link buildOnSiteDemoFacilityCoverages} from inside the\n * fixture group, by which point both block + facility modules\n * have finished top-level evaluation.\n */\nlet cachedSpecs: ReadonlyArray<FacilityPatientSpec> | undefined;\nconst getFacilityPatientSpecs = (): ReadonlyArray<FacilityPatientSpec> => {\n if (!cachedSpecs) {\n cachedSpecs = buildAllFacilityPatientSpecs();\n }\n return cachedSpecs;\n};\n\n/**\n * Lazily materialize the facility-patient Patient resources\n * seeded into the on-site UAT demo workspace. Called by the\n * fixture group when the seeder iterates `group.patients`.\n */\nexport const buildOnSiteDemoFacilityPatients = (): ReadonlyArray<Patient> =>\n getFacilityPatientSpecs().map(buildFacilityPatientResource);\n\n/**\n * Lazily materialize the facility-patient Coverage resources\n * (primary + optional secondary) for the on-site UAT demo\n * workspace. Called by the fixture group when the seeder\n * iterates `group.coverages`.\n */\nexport const buildOnSiteDemoFacilityCoverages = (): ReadonlyArray<Coverage> => {\n const out: Array<Coverage> = [];\n for (const spec of getFacilityPatientSpecs()) {\n out.push(buildPrimaryCoverageResource(spec));\n const secondary = buildSecondaryCoverageResource(spec);\n if (secondary) {\n out.push(secondary);\n }\n }\n return out;\n};\n\n/**\n * Stable facility-patient ids in dispatch order. Lazy — call\n * this from downstream tickets (e.g. #1306 — encounters per\n * scheduled patient per block occurrence) instead of capturing\n * the array at module load.\n */\nexport const onSiteDemoFacilityPatientIds = (): ReadonlyArray<string> =>\n getFacilityPatientSpecs().map((s) => s.id);\n\n/**\n * Subset of {@link onSiteDemoFacilityPatientIds} whose patients\n * are scheduled into a weekly block. Excludes the intake-only\n * subset. Order matches `PATIENTS_PER_BLOCK` (all block-001\n * patients first, then block-002, etc.).\n */\nexport const onSiteDemoScheduledFacilityPatientIds =\n (): ReadonlyArray<string> =>\n getFacilityPatientSpecs()\n .filter((s) => s.blockTemplateId !== undefined)\n .map((s) => s.id);\n\n/**\n * Subset of {@link onSiteDemoFacilityPatientIds} whose patients\n * are intake-complete but not yet on a schedule. These patients\n * have a facility assignment but no block reference and no\n * Encounter records (downstream tickets must respect that\n * absence).\n */\nexport const onSiteDemoIntakeOnlyFacilityPatientIds =\n (): ReadonlyArray<string> =>\n getFacilityPatientSpecs()\n .filter((s) => s.blockTemplateId === undefined)\n .map((s) => s.id);\n\n/**\n * Look up the block template a facility patient is scheduled\n * into, or `undefined` for intake-only patients.\n */\nexport const findOnSiteDemoFacilityPatientBlock = (\n patientId: string,\n): string | undefined => {\n const spec = getFacilityPatientSpecs().find((s) => s.id === patientId);\n return spec?.blockTemplateId;\n};\n\n/**\n * List facility patients scheduled into a given block template\n * id. Downstream tickets (encounters, scribe assignments) call\n * this to fan out per-block work without re-deriving the\n * mapping.\n */\nexport const facilityPatientsForBlock = (\n blockTemplateId: string,\n): ReadonlyArray<string> =>\n getFacilityPatientSpecs()\n .filter((s) => s.blockTemplateId === blockTemplateId)\n .map((s) => s.id);\n","import type { Coverage, Patient } from \"@openhi/types\";\nimport {\n ON_SITE_DEMO_TENANT_ID,\n ON_SITE_DEMO_WORKSPACE_ID,\n demoScenarioIdentifier,\n openhiResourceIdentifier,\n} from \"./events\";\nimport {\n COVERAGE_PAYOR_TYPE_SYSTEM,\n COVERAGE_QMB_STATUS_EXTENSION_URL,\n COVERAGE_VERIFICATION_DATE_EXTENSION_URL,\n HOSPICE_EFFECTIVE_DATE_SUB_EXTENSION_URL,\n HOSPICE_STATUS_VALUE_SUB_EXTENSION_URL,\n PATIENT_DEFAULT_CARE_SETTING_EXTENSION_URL,\n PATIENT_HOSPICE_STATUS_EXTENSION_URL,\n PAYOR_TYPE_COMMERCIAL,\n PAYOR_TYPE_MEDICARE,\n PAYOR_TYPE_MEDICARE_ADVANTAGE,\n QMB_EFFECTIVE_DATE_SUB_EXTENSION_URL,\n QMB_STATUS_VALUE_SUB_EXTENSION_URL,\n} from \"./on-site-demo-facility-patients\";\nimport { homeHealthEligibleDoctors } from \"./on-site-demo-fixtures\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/constructs/workflows/control-plane/seed-demo-data/on-site-demo-home-health-patients.md\n *\n * Hand-authored home-health Patient + Coverage fixtures the\n * `seed-demo-data` workflow upserts into the on-site-medical UAT\n * demo tenant ({@link ON_SITE_DEMO_TENANT_ID} +\n * {@link ON_SITE_DEMO_WORKSPACE_ID}) on every non-prod deploy\n * (issue #1305).\n *\n * Topology — issue #1305 design:\n * - 20 home-health patients total. None are assigned to a\n * facility — `patient-default-care-setting` is `home`\n * (mirrors the on-site EHR's `LocationClassification = \"home\"`\n * at `sites/app-ehr/src/utils/patient/patientDefaultCareSetting.ts`),\n * and the `patient-default-care-location` extension is\n * intentionally omitted (home patients have no Location\n * reference).\n * - 17 patients are scheduled to a home-health-eligible doctor\n * (see {@link homeHealthEligibleDoctors}) with a recurring\n * visit cadence. Doctor assignment is a deterministic\n * round-robin over the 5 home-health-eligible doctors.\n * - 3 patients are intake-complete-but-not-yet-scheduled —\n * they carry a home address + care-context = home but have\n * no provider assignment and no visit cadence (the on-site\n * UI state for a brand-new home-health intake that hasn't\n * been put on the calendar yet).\n *\n * Insurance is identical to the facility-patient rules (#1304):\n * - Every patient gets a primary Coverage with\n * `status: \"active\"` and a verification date.\n * - A subset (~40%) gets a secondary Coverage.\n * - Payor mix: commercial / Medicare / Medicare Advantage.\n * - QMB only attaches to Medicare-primary patients.\n * - ~20% of patients carry the `patient-hospice-status`\n * extension on the Patient resource.\n *\n * Modelling choice — visit cadence. On-site has no formal\n * home-health visit cadence schema today (the `REPEAT_OPTIONS`\n * at `sites/app-ehr/src/features/calendar/components/eventPopoverUtils.ts`\n * are calendar-level recurrences, not patient-level cadences).\n * Each scheduled home-health patient therefore carries a simple\n * `home-health-visit-cadence-days` valueInteger extension with\n * a value drawn from the set 7 / 14 / 28 — weekly / bi-weekly /\n * monthly — distributed deterministically across the roster so\n * the UAT tenant exercises all three cadences. Intake-only\n * patients omit the extension entirely.\n *\n * Modelling choice — provider assignment. The home-health\n * analogue of the facility-patient's block reference is a\n * `patient-assigned-home-health-provider` `valueReference`\n * pointing at `Practitioner/<doctor-id>`. Downstream tickets\n * (#1306 — encounters) read this reference to fan out per-\n * patient visit Encounters. Intake-only patients omit the\n * extension (no provider yet → no encounters).\n *\n * Ids are deterministic — re-fires upsert the same records,\n * matching the workflow's idempotency contract. Adding,\n * renaming, or moving a patient is a one-line edit here plus a\n * redeploy.\n */\n\n/**\n * Extension URL stamped on a home-health Patient body recording\n * the {@link Practitioner} id of the home-health-eligible doctor\n * the patient is currently scheduled with. Carries a\n * `valueReference` shaped `{ reference: \"Practitioner/<id>\" }`.\n * Intake-only patients omit this extension.\n */\nexport const PATIENT_ASSIGNED_HOME_HEALTH_PROVIDER_EXTENSION_URL =\n \"https://on-site-medical.app/fhir/StructureDefinition/patient-assigned-home-health-provider\";\n\n/**\n * Extension URL stamped on a home-health Patient body recording\n * the patient's recurring visit cadence in days. The value is a\n * `valueInteger` drawn from {@link HOME_HEALTH_VISIT_CADENCE_OPTIONS}\n * — weekly (7), bi-weekly (14), or monthly (28). On-site has no\n * formal cadence schema today, so this denormalised extension\n * captures the visit interval directly on the Patient body until\n * the on-site team picks a permanent shape. Intake-only patients\n * omit this extension.\n */\nexport const HOME_HEALTH_VISIT_CADENCE_DAYS_EXTENSION_URL =\n \"https://on-site-medical.app/fhir/StructureDefinition/home-health-visit-cadence-days\";\n\n/**\n * Allowed visit-cadence day values. Roughly weekly / bi-weekly /\n * monthly — enough variation for UAT to exercise distinct\n * cadences in the calendar without modelling every possible\n * interval.\n */\nexport const HOME_HEALTH_VISIT_CADENCE_OPTIONS: ReadonlyArray<number> = [\n 7, 14, 28,\n];\n\n/** Number of scheduled home-health patients (provider + cadence assigned). */\nconst SCHEDULED_HOME_HEALTH_PATIENTS = 17;\n\n/** Number of intake-complete-but-not-yet-scheduled home-health patients. */\nconst INTAKE_ONLY_HOME_HEALTH_PATIENTS = 3;\n\n/** Total home-health patients seeded. */\nexport const TOTAL_HOME_HEALTH_PATIENTS: number =\n SCHEDULED_HOME_HEALTH_PATIENTS + INTAKE_ONLY_HOME_HEALTH_PATIENTS;\n\ntype PayorType =\n | typeof PAYOR_TYPE_COMMERCIAL\n | typeof PAYOR_TYPE_MEDICARE\n | typeof PAYOR_TYPE_MEDICARE_ADVANTAGE;\n\n/**\n * Payor catalogue used to stamp realistic carrier names on each\n * primary / secondary Coverage. Same mix as facility patients\n * (#1304) so the insurance UI shows the same distribution across\n * both populations.\n */\nconst PRIMARY_PAYOR_OPTIONS: ReadonlyArray<{\n readonly type: PayorType;\n readonly display: string;\n}> = [\n { type: PAYOR_TYPE_COMMERCIAL, display: \"Aetna PPO\" },\n { type: PAYOR_TYPE_COMMERCIAL, display: \"Blue Cross Blue Shield of Georgia\" },\n { type: PAYOR_TYPE_COMMERCIAL, display: \"UnitedHealthcare Choice Plus\" },\n { type: PAYOR_TYPE_COMMERCIAL, display: \"Cigna OAP\" },\n { type: PAYOR_TYPE_MEDICARE, display: \"Medicare Part B\" },\n { type: PAYOR_TYPE_MEDICARE_ADVANTAGE, display: \"Humana Medicare Advantage\" },\n {\n type: PAYOR_TYPE_MEDICARE_ADVANTAGE,\n display: \"Wellcare by Allwell HMO\",\n },\n];\n\n/** Secondary-coverage payors (Medigap + supplemental commercial). */\nconst SECONDARY_PAYOR_OPTIONS: ReadonlyArray<{\n readonly display: string;\n}> = [\n { display: \"AARP Medigap Plan G\" },\n { display: \"Mutual of Omaha Medicare Supplement\" },\n { display: \"Cigna Supplemental Health\" },\n { display: \"AFLAC Supplemental\" },\n];\n\n/**\n * Real-looking home-health patient last names. Same convention\n * as the facility patients (#1304) — common American family\n * names with no overlap on the facility roster's first 20 names\n * so the demo workspace shows visibly distinct people across\n * both populations.\n */\nconst PATIENT_LAST_NAMES: ReadonlyArray<string> = [\n \"Acosta\",\n \"Barnett\",\n \"Bryant\",\n \"Castillo\",\n \"Conway\",\n \"Delgado\",\n \"Eldridge\",\n \"Fitzgerald\",\n \"Garza\",\n \"Hicks\",\n \"Ingram\",\n \"Jensen\",\n \"Klein\",\n \"Larson\",\n \"McCarthy\",\n \"Nash\",\n \"O'Connor\",\n \"Pierce\",\n \"Quintana\",\n \"Reilly\",\n \"Salazar\",\n \"Tate\",\n \"Underwood\",\n \"Vega\",\n \"Whitaker\",\n];\n\n/**\n * First-name pool — distinct from the facility roster's pool so\n * the two populations look visibly different in the on-site UI.\n * Roughly balanced between traditionally-male and traditionally-\n * female names.\n */\nconst PATIENT_FIRST_NAMES: ReadonlyArray<{\n readonly name: string;\n readonly gender: \"male\" | \"female\";\n}> = [\n { name: \"Eleanor\", gender: \"female\" },\n { name: \"Albert\", gender: \"male\" },\n { name: \"Florence\", gender: \"female\" },\n { name: \"Bernard\", gender: \"male\" },\n { name: \"Marjorie\", gender: \"female\" },\n { name: \"Stanley\", gender: \"male\" },\n { name: \"Gladys\", gender: \"female\" },\n { name: \"Norman\", gender: \"male\" },\n { name: \"Pauline\", gender: \"female\" },\n { name: \"Raymond\", gender: \"male\" },\n { name: \"Lillian\", gender: \"female\" },\n { name: \"Howard\", gender: \"male\" },\n { name: \"Mildred\", gender: \"female\" },\n { name: \"Russell\", gender: \"male\" },\n { name: \"Frances\", gender: \"female\" },\n { name: \"Eugene\", gender: \"male\" },\n { name: \"Bernice\", gender: \"female\" },\n { name: \"Leonard\", gender: \"male\" },\n { name: \"Eileen\", gender: \"female\" },\n { name: \"Clifford\", gender: \"male\" },\n];\n\nconst ON_SITE_SCENARIO = \"on-site-demo\";\n\n/**\n * Anchor date used when materialising deterministic timestamps\n * (birth dates, verification dates). Same anchor as the facility\n * patients so re-fires across both populations share a single\n * snapshot.\n */\nconst PATIENT_ANCHOR_DATE = \"2026-05-01T00:00:00Z\";\n\n/**\n * Per-patient deterministic seed object. The generator walks a\n * scheduled pass followed by an intake-only pass and produces\n * one of these per Patient/Coverage pair.\n */\ninterface HomeHealthPatientSpec {\n /** Stable Patient id (also drives the demo URN identifier). */\n readonly id: string;\n /** Sequence ordinal — drives deterministic name/payor selection. */\n readonly index: number;\n /**\n * Practitioner id of the home-health-eligible doctor the\n * patient is scheduled with, or `undefined` for the intake-\n * only subset.\n */\n readonly providerId: string | undefined;\n /**\n * Visit cadence in days (7 / 14 / 28), or `undefined` for the\n * intake-only subset.\n */\n readonly visitCadenceDays: number | undefined;\n}\n\nconst padIndex = (n: number): string => n.toString().padStart(3, \"0\");\n\n/**\n * Derive a deterministic birthDate offset from the anchor date.\n * Spreads patients across a roughly 25-year band centred on\n * elderly-skewing — home-health populations skew older than the\n * average adult.\n */\nconst deterministicBirthDate = (index: number): string => {\n // Spread across 1932..1957 deterministically — older skew.\n const baseYear = 1932;\n const yearSpan = 25;\n const year = baseYear + (index % yearSpan);\n const month = ((index * 7) % 12) + 1;\n // Use 1-28 to avoid month-length edge cases.\n const day = ((index * 11) % 28) + 1;\n const mm = month.toString().padStart(2, \"0\");\n const dd = day.toString().padStart(2, \"0\");\n return `${year}-${mm}-${dd}`;\n};\n\n/**\n * Derive a deterministic verification date inside the 30 days\n * preceding the anchor date. Result is an ISO 8601 instant in\n * UTC.\n */\nconst deterministicVerificationDate = (index: number): string => {\n // Day offset 1..30 prior to the anchor.\n const dayOffset = (index % 30) + 1;\n const anchor = new Date(PATIENT_ANCHOR_DATE);\n const verifyAt = new Date(anchor);\n verifyAt.setUTCDate(verifyAt.getUTCDate() - dayOffset);\n return verifyAt.toISOString();\n};\n\n/**\n * Derive a deterministic effective date inside the year\n * preceding the anchor date. Used for hospice / QMB effective\n * dates. Result is a `YYYY-MM-DD` FHIR `date`.\n */\nconst deterministicEffectiveDate = (index: number): string => {\n const dayOffset = ((index * 13) % 365) + 1;\n const anchor = new Date(PATIENT_ANCHOR_DATE);\n const eff = new Date(anchor);\n eff.setUTCDate(eff.getUTCDate() - dayOffset);\n return eff.toISOString().slice(0, 10);\n};\n\n/**\n * Deterministic phone in the +1-404-555 demo block. Home-health\n * patient phones occupy the 0600 prefix to avoid collisions with\n * facility-patient (0400), provider (0100), and scribe (0200)\n * ranges.\n */\nconst deterministicPhone = (index: number): string => {\n const last4 = (600 + index).toString().padStart(4, \"0\");\n return `+1404555${last4}`;\n};\n\nconst deterministicEmail = (\n firstName: string,\n lastName: string,\n index: number,\n): string => {\n const local = `${firstName}.${lastName}.${padIndex(index)}`\n .toLowerCase()\n .replace(/[^a-z0-9.]/g, \"\");\n return `${local}@on-site-demo.example.com`;\n};\n\n/**\n * Street names used to build deterministic home addresses.\n * Distinct from the facility-patient address pool so the two\n * populations look visibly different in the on-site UI.\n */\nconst HOME_STREET_NAMES: ReadonlyArray<string> = [\n \"Briarcliff Road NE\",\n \"Cheshire Bridge Road\",\n \"Dekalb Avenue NE\",\n \"Lavista Road\",\n \"Memorial Drive SE\",\n \"Moreland Avenue NE\",\n \"North Decatur Road\",\n \"Roswell Road\",\n \"Virginia Avenue NE\",\n \"West Paces Ferry Road\",\n];\n\nconst deterministicAddressLine = (index: number): string => {\n const houseNumber = 200 + index * 11;\n const streetIndex = index % HOME_STREET_NAMES.length;\n return `${houseNumber} ${HOME_STREET_NAMES[streetIndex]}`;\n};\n\n/**\n * Atlanta-area ZIP codes — varied so the UAT roster does not\n * cluster on a single ZIP. Distinct enough to look realistic\n * without modelling actual street-to-ZIP lookups.\n */\nconst HOME_POSTAL_CODES: ReadonlyArray<string> = [\n \"30306\",\n \"30307\",\n \"30324\",\n \"30329\",\n \"30033\",\n \"30030\",\n \"30342\",\n \"30327\",\n \"30319\",\n \"30305\",\n];\n\nconst deterministicPostalCode = (index: number): string =>\n HOME_POSTAL_CODES[index % HOME_POSTAL_CODES.length];\n\n/**\n * Derive primary payor type from the patient index. Same mix as\n * the facility-patient generator so the two populations exercise\n * comparable insurance distributions.\n */\nconst deterministicPrimaryPayor = (\n index: number,\n): { readonly type: PayorType; readonly display: string } => {\n const bucket = index % 10;\n if (bucket <= 3) {\n return PRIMARY_PAYOR_OPTIONS[bucket % 4]; // commercial entries are first 4\n }\n if (bucket <= 6) {\n return PRIMARY_PAYOR_OPTIONS[4]; // Medicare Part B\n }\n return PRIMARY_PAYOR_OPTIONS[5 + ((bucket - 7) % 2)];\n};\n\n/** Whether the patient gets a secondary Coverage. Targets ~40%. */\nconst hasSecondaryCoverage = (index: number): boolean => {\n return index % 5 < 2;\n};\n\n/**\n * Whether QMB attaches to this patient. The caller MUST short-\n * circuit on payor type before consulting this function — QMB is\n * Medicare-only.\n */\nconst hasQmbStatus = (index: number): boolean => {\n return index % 2 === 0;\n};\n\n/** Whether the patient is flagged as hospice. Targets ~20%. */\nconst isHospicePatient = (index: number): boolean => {\n return index % 5 === 0;\n};\n\n/**\n * Deterministic visit-cadence selection over the index — walks\n * {@link HOME_HEALTH_VISIT_CADENCE_OPTIONS} so the seeded roster\n * exercises weekly, bi-weekly, and monthly cadences in roughly\n * equal proportions.\n */\nconst deterministicVisitCadenceDays = (index: number): number =>\n HOME_HEALTH_VISIT_CADENCE_OPTIONS[\n index % HOME_HEALTH_VISIT_CADENCE_OPTIONS.length\n ];\n\nconst buildIdentifierPair = (\n patientId: string,\n roleSuffix: string,\n): Patient[\"identifier\"] => [\n demoScenarioIdentifier(ON_SITE_SCENARIO, roleSuffix),\n openhiResourceIdentifier({\n tenantId: ON_SITE_DEMO_TENANT_ID,\n workspaceId: ON_SITE_DEMO_WORKSPACE_ID,\n resourceType: \"Patient\",\n id: patientId,\n }),\n];\n\nconst buildCoverageIdentifierPair = (\n coverageId: string,\n roleSuffix: string,\n): Coverage[\"identifier\"] => [\n demoScenarioIdentifier(ON_SITE_SCENARIO, roleSuffix),\n openhiResourceIdentifier({\n tenantId: ON_SITE_DEMO_TENANT_ID,\n workspaceId: ON_SITE_DEMO_WORKSPACE_ID,\n resourceType: \"Coverage\",\n id: coverageId,\n }),\n];\n\n/**\n * Build the Patient resource for one home-health-patient spec.\n * Stamps `care-context = home` (no Location reference — home\n * patients have no facility), optional provider + cadence\n * extensions, optional hospice extension, and the standard\n * demographic fields the on-site Demographics / Contacts / Care\n * Context cards read on a home-health patient.\n */\nconst buildHomeHealthPatientResource = (\n spec: HomeHealthPatientSpec,\n): Patient => {\n const firstNameEntry =\n PATIENT_FIRST_NAMES[spec.index % PATIENT_FIRST_NAMES.length];\n const lastName =\n PATIENT_LAST_NAMES[(spec.index * 3) % PATIENT_LAST_NAMES.length];\n const fullText = `${firstNameEntry.name} ${lastName}`;\n const effectiveDate = deterministicEffectiveDate(spec.index);\n const providerExtension = spec.providerId\n ? [\n {\n url: PATIENT_ASSIGNED_HOME_HEALTH_PROVIDER_EXTENSION_URL,\n valueReference: {\n reference: `Practitioner/${spec.providerId}`,\n type: \"Practitioner\",\n },\n },\n ]\n : [];\n const cadenceExtension =\n typeof spec.visitCadenceDays === \"number\"\n ? [\n {\n url: HOME_HEALTH_VISIT_CADENCE_DAYS_EXTENSION_URL,\n valueInteger: spec.visitCadenceDays,\n },\n ]\n : [];\n const hospiceExtension = isHospicePatient(spec.index)\n ? [\n {\n url: PATIENT_HOSPICE_STATUS_EXTENSION_URL,\n extension: [\n {\n url: HOSPICE_STATUS_VALUE_SUB_EXTENSION_URL,\n valueCode: \"in_hospice\",\n },\n {\n url: HOSPICE_EFFECTIVE_DATE_SUB_EXTENSION_URL,\n valueDate: effectiveDate,\n },\n ],\n },\n ]\n : [];\n return {\n resourceType: \"Patient\",\n id: spec.id,\n active: true,\n identifier: buildIdentifierPair(spec.id, `patient-${spec.id}`),\n name: [\n {\n use: \"official\",\n text: fullText,\n given: [firstNameEntry.name],\n family: lastName,\n },\n ],\n gender: firstNameEntry.gender,\n birthDate: deterministicBirthDate(spec.index),\n telecom: [\n {\n system: \"phone\",\n value: deterministicPhone(spec.index),\n use: \"home\",\n },\n {\n system: \"email\",\n value: deterministicEmail(firstNameEntry.name, lastName, spec.index),\n use: \"home\",\n },\n ],\n address: [\n {\n use: \"home\",\n line: [deterministicAddressLine(spec.index)],\n city: \"Atlanta\",\n state: \"GA\",\n postalCode: deterministicPostalCode(spec.index),\n country: \"US\",\n },\n ],\n extension: [\n {\n url: PATIENT_DEFAULT_CARE_SETTING_EXTENSION_URL,\n valueCode: \"home\",\n },\n // No `patient-default-care-location` extension — home-health\n // patients have no facility Location reference (mirrors the\n // on-site `buildDefaultCareSettingExtensions` helper, which\n // only emits the location extension when setting === \"facility\").\n ...providerExtension,\n ...cadenceExtension,\n ...hospiceExtension,\n ],\n };\n};\n\n/**\n * Build the primary Coverage resource for one home-health-patient\n * spec. Same shape and rules as the facility-patient primary\n * Coverage (#1304) — active status, beneficiary reference, payor\n * type, verification-date extension, and a QMB extension only on\n * Medicare-primary patients (subject to {@link hasQmbStatus}).\n */\nconst buildPrimaryCoverageResource = (\n spec: HomeHealthPatientSpec,\n): Coverage => {\n const id = `${spec.id}-coverage-primary`;\n const payor = deterministicPrimaryPayor(spec.index);\n const verificationDate = deterministicVerificationDate(spec.index);\n const isMedicarePrimary = payor.type === PAYOR_TYPE_MEDICARE;\n const qmbExtension =\n isMedicarePrimary && hasQmbStatus(spec.index)\n ? [\n {\n url: COVERAGE_QMB_STATUS_EXTENSION_URL,\n extension: [\n {\n url: QMB_STATUS_VALUE_SUB_EXTENSION_URL,\n valueCode: \"active\",\n },\n {\n url: QMB_EFFECTIVE_DATE_SUB_EXTENSION_URL,\n valueDate: deterministicEffectiveDate(spec.index),\n },\n ],\n },\n ]\n : [];\n return {\n resourceType: \"Coverage\",\n id,\n status: \"active\",\n identifier: buildCoverageIdentifierPair(id, `coverage-primary-${spec.id}`),\n beneficiary: { reference: `Patient/${spec.id}`, type: \"Patient\" },\n subscriber: { reference: `Patient/${spec.id}`, type: \"Patient\" },\n subscriberId: `MBR-HH-${padIndex(spec.index)}-PRI`,\n relationship: { text: \"self\" },\n payor: [\n {\n display: payor.display,\n },\n ],\n type: {\n coding: [\n {\n system: COVERAGE_PAYOR_TYPE_SYSTEM,\n code: payor.type,\n display: payor.display,\n },\n ],\n text: payor.display,\n },\n order: 1,\n extension: [\n {\n url: COVERAGE_VERIFICATION_DATE_EXTENSION_URL,\n valueDateTime: verificationDate,\n },\n ...qmbExtension,\n ],\n };\n};\n\n/**\n * Build the secondary Coverage resource when\n * {@link hasSecondaryCoverage} returns true; otherwise\n * `undefined`.\n */\nconst buildSecondaryCoverageResource = (\n spec: HomeHealthPatientSpec,\n): Coverage | undefined => {\n if (!hasSecondaryCoverage(spec.index)) {\n return undefined;\n }\n const id = `${spec.id}-coverage-secondary`;\n const payor =\n SECONDARY_PAYOR_OPTIONS[spec.index % SECONDARY_PAYOR_OPTIONS.length];\n const verificationDate = deterministicVerificationDate(spec.index);\n return {\n resourceType: \"Coverage\",\n id,\n status: \"active\",\n identifier: buildCoverageIdentifierPair(\n id,\n `coverage-secondary-${spec.id}`,\n ),\n beneficiary: { reference: `Patient/${spec.id}`, type: \"Patient\" },\n subscriber: { reference: `Patient/${spec.id}`, type: \"Patient\" },\n subscriberId: `MBR-HH-${padIndex(spec.index)}-SEC`,\n relationship: { text: \"self\" },\n payor: [\n {\n display: payor.display,\n },\n ],\n type: {\n text: payor.display,\n },\n order: 2,\n extension: [\n {\n url: COVERAGE_VERIFICATION_DATE_EXTENSION_URL,\n valueDateTime: verificationDate,\n },\n ],\n };\n};\n\n/**\n * Materialise every home-health-patient spec — scheduled\n * patients first (so they land at lower ids than intake-only\n * patients), each assigned to a home-health-eligible doctor via\n * a deterministic round-robin over {@link homeHealthEligibleDoctors},\n * followed by the intake-only subset with no provider /\n * cadence. The single monotonically-incrementing sequence\n * ordinal drives every deterministic field (name, birthDate,\n * payor mix, hospice / QMB flags, cadence), so the\n * implementation guarantees stable bodies across re-fires.\n *\n * Validation: at least one home-health-eligible doctor must\n * exist; otherwise no provider can be assigned to the scheduled\n * subset and the whole fixture is meaningless. We throw at build\n * time rather than emit patients with dangling Practitioner\n * references.\n */\nconst buildAllHomeHealthPatientSpecs =\n (): ReadonlyArray<HomeHealthPatientSpec> => {\n const eligibleDoctors = homeHealthEligibleDoctors();\n if (eligibleDoctors.length === 0) {\n throw new Error(\n \"No home-health-eligible doctors found — cannot seed home-health patients.\",\n );\n }\n const specs: Array<HomeHealthPatientSpec> = [];\n // Scheduled patients — round-robin over the eligible doctors.\n for (let i = 0; i < SCHEDULED_HOME_HEALTH_PATIENTS; i += 1) {\n const index = i;\n const providerId = eligibleDoctors[i % eligibleDoctors.length].id;\n if (!providerId) {\n throw new Error(\n \"Home-health-eligible doctor is missing an id; cannot seed.\",\n );\n }\n specs.push({\n id: `on-site-demo-home-health-patient-${padIndex(index + 1)}`,\n index,\n providerId,\n visitCadenceDays: deterministicVisitCadenceDays(index),\n });\n }\n // Intake-only patients — no provider, no cadence.\n for (let i = 0; i < INTAKE_ONLY_HOME_HEALTH_PATIENTS; i += 1) {\n const index = SCHEDULED_HOME_HEALTH_PATIENTS + i;\n specs.push({\n id: `on-site-demo-home-health-patient-${padIndex(index + 1)}`,\n index,\n providerId: undefined,\n visitCadenceDays: undefined,\n });\n }\n return specs;\n };\n\n/**\n * Lazy cache for the spec list. Computed on first call so the\n * top-level module load does not consult\n * {@link homeHealthEligibleDoctors} while the fixtures module is\n * still mid-evaluation (the same TDZ pitfall the facility-\n * patient module documents). Every exported helper routes\n * through this getter.\n */\nlet cachedSpecs: ReadonlyArray<HomeHealthPatientSpec> | undefined;\nconst getHomeHealthPatientSpecs = (): ReadonlyArray<HomeHealthPatientSpec> => {\n if (!cachedSpecs) {\n cachedSpecs = buildAllHomeHealthPatientSpecs();\n }\n return cachedSpecs;\n};\n\n/**\n * Lazily materialize the home-health Patient resources seeded\n * into the on-site UAT demo workspace. Called by the fixture\n * group when the seeder iterates `group.buildPatients()`.\n */\nexport const buildOnSiteDemoHomeHealthPatients = (): ReadonlyArray<Patient> =>\n getHomeHealthPatientSpecs().map(buildHomeHealthPatientResource);\n\n/**\n * Lazily materialize the home-health Coverage resources\n * (primary + optional secondary) for the on-site UAT demo\n * workspace.\n */\nexport const buildOnSiteDemoHomeHealthCoverages =\n (): ReadonlyArray<Coverage> => {\n const out: Array<Coverage> = [];\n for (const spec of getHomeHealthPatientSpecs()) {\n out.push(buildPrimaryCoverageResource(spec));\n const secondary = buildSecondaryCoverageResource(spec);\n if (secondary) {\n out.push(secondary);\n }\n }\n return out;\n };\n\n/**\n * Stable home-health-patient ids in dispatch order. Lazy — call\n * this from downstream tickets (e.g. #1306 — encounters per\n * scheduled home-health visit) instead of capturing the array\n * at module load.\n */\nexport const onSiteDemoHomeHealthPatientIds = (): ReadonlyArray<string> =>\n getHomeHealthPatientSpecs().map((s) => s.id);\n\n/**\n * Subset of {@link onSiteDemoHomeHealthPatientIds} whose\n * patients are scheduled with a home-health-eligible provider +\n * visit cadence. Excludes the intake-only subset.\n */\nexport const onSiteDemoScheduledHomeHealthPatientIds =\n (): ReadonlyArray<string> =>\n getHomeHealthPatientSpecs()\n .filter((s) => s.providerId !== undefined)\n .map((s) => s.id);\n\n/**\n * Subset of {@link onSiteDemoHomeHealthPatientIds} whose\n * patients are intake-complete but not yet on a schedule. These\n * patients carry a home address + care-context = home but no\n * provider, no cadence, and (per #1306) no Encounter records.\n */\nexport const onSiteDemoIntakeOnlyHomeHealthPatientIds =\n (): ReadonlyArray<string> =>\n getHomeHealthPatientSpecs()\n .filter((s) => s.providerId === undefined)\n .map((s) => s.id);\n\n/**\n * Look up the home-health-eligible provider assigned to a given\n * home-health patient, or `undefined` for intake-only patients.\n * Downstream tickets (encounters per scheduled visit) call this\n * to fan out per-patient encounter records.\n */\nexport const findOnSiteDemoHomeHealthPatientProvider = (\n patientId: string,\n): string | undefined => {\n const spec = getHomeHealthPatientSpecs().find((s) => s.id === patientId);\n return spec?.providerId;\n};\n\n/**\n * Look up the visit cadence (in days) for a given home-health\n * patient, or `undefined` for intake-only patients.\n */\nexport const findOnSiteDemoHomeHealthPatientVisitCadenceDays = (\n patientId: string,\n): number | undefined => {\n const spec = getHomeHealthPatientSpecs().find((s) => s.id === patientId);\n return spec?.visitCadenceDays;\n};\n","import type {\n Condition,\n Encounter,\n Observation,\n Procedure,\n} from \"@openhi/types\";\nimport {\n ON_SITE_DEMO_TENANT_ID,\n ON_SITE_DEMO_WORKSPACE_ID,\n demoScenarioIdentifier,\n openhiResourceIdentifier,\n} from \"./events\";\nimport {\n BLOCK_OCCURRENCE_WEEKS_PAST,\n findOnSiteDemoBlockTemplate,\n} from \"./on-site-demo-blocks\";\nimport {\n facilityPatientsForBlock,\n onSiteDemoScheduledFacilityPatientIds,\n} from \"./on-site-demo-facility-patients\";\nimport {\n findOnSiteDemoHomeHealthPatientProvider,\n findOnSiteDemoHomeHealthPatientVisitCadenceDays,\n onSiteDemoScheduledHomeHealthPatientIds,\n} from \"./on-site-demo-home-health-patients\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/constructs/workflows/control-plane/seed-demo-data/on-site-demo-encounters.md\n *\n * Historical Encounter + wound-Condition + wound-exam Observation +\n * wound-debridement Procedure fixtures the `seed-demo-data` workflow\n * upserts into the on-site-medical UAT demo tenant\n * ({@link ON_SITE_DEMO_TENANT_ID} + {@link ON_SITE_DEMO_WORKSPACE_ID})\n * on every non-prod deploy (issue #1306).\n *\n * Topology — issue #1306 design:\n * - Brand-new intake patients (6 facility intake-only + 3 home\n * intake-only) get **no** encounters. They carry intake +\n * insurance only.\n * - Scheduled facility patients (60 patients across 4 blocks) get\n * one Encounter per past block occurrence their block ran on\n * (the `BLOCK_OCCURRENCE_WEEKS_PAST` window = 4 past weeks).\n * Authored by the block's doctor + scribe, dated to that\n * occurrence's date.\n * - Scheduled home-health patients (17 patients) get one Encounter\n * per past visit at their cadence, stepping back from the\n * reference date. With cadence 14 days and 4 past visits, the\n * dates land at -14, -28, -42, -56 days. Authored by the\n * assigned home-health provider.\n * - ~70% of scheduled patients carry a \"current wound\" — one\n * {@link Condition} per patient with `category.text = \"wound\"`\n * plus a deterministic lower-extremity body site and wound type.\n * Every encounter for that patient records a wound-exam\n * {@link Observation} (LOINC panel 39135-9) whose components\n * show progression — length / width / depth shrink (healing) or\n * grow (worsening) across encounters depending on a\n * deterministic per-patient trajectory.\n * - ~25% of wound-bearing patients get one wound-debridement\n * {@link Procedure} on the most-recent wound encounter, using a\n * CPT code from the on-site EHR's\n * `PRESET_PROCEDURES` catalogue (e.g. 97597 Sharp Debridement).\n *\n * Modelling choices:\n * - Encounter `class` follows the on-site EHR's\n * `ENCOUNTER_CLASS_BY_LOCATION` map at\n * `sites/app-ehr/src/types/encounter.ts` — facility encounters\n * carry `code: \"IMP\", display: \"Facility\"`; home-health\n * encounters carry `code: \"HH\", display: \"Home Health\"`. The\n * `system` matches the v3 ActCode URL the on-site EHR reads.\n * - Wound is encoded as a FHIR {@link Condition} with\n * `category: [{ text: \"wound\" }]` (mirroring the on-site\n * `mapWoundFormToCondition` helper at\n * `sites/app-ehr/src/pages/visit/encounter/components/AddWoundDialog/woundFormMapping.ts`).\n * Wound exams are encoded as a single panel Observation per\n * encounter (LOINC 39135-9), with components for length /\n * width / depth — matching the on-site `buildWoundExamObservation`\n * mapper at `sites/app-ehr/src/features/wounds/mappers/woundExamMappers.ts`.\n * - Procedure carries a CPT code on `code.coding[0]` with system\n * `http://www.ama-assn.org/go/cpt` (the on-site EHR's\n * `CPT_SYSTEM` constant). `reasonReference` points at the wound\n * Condition; `encounter` points at the encounter the procedure\n * was performed during.\n *\n * Ids are deterministic — re-fires upsert the same records,\n * matching the workflow's idempotency contract.\n */\n\n/** FHIR v3 ActEncounter coding system, used on `Encounter.class`. */\nexport const ENCOUNTER_CLASS_SYSTEM =\n \"http://terminology.hl7.org/CodeSystem/v3-ActCode\";\n\n/** Encounter class coding for facility encounters (on-site `ENCOUNTER_CLASS_BY_LOCATION.facility`). */\nexport const ENCOUNTER_CLASS_FACILITY = {\n system: ENCOUNTER_CLASS_SYSTEM,\n code: \"IMP\",\n display: \"Facility\",\n} as const;\n\n/** Encounter class coding for home-health encounters (on-site `ENCOUNTER_CLASS_BY_LOCATION.home`). */\nexport const ENCOUNTER_CLASS_HOME_HEALTH = {\n system: ENCOUNTER_CLASS_SYSTEM,\n code: \"HH\",\n display: \"Home Health\",\n} as const;\n\n/** LOINC system URL used on Observation.code.coding entries. */\nexport const LOINC_SYSTEM = \"http://loinc.org\";\n\n/** SNOMED CT system URL used on Condition.code / bodySite coding entries. */\nexport const SNOMED_SYSTEM = \"http://snomed.info/sct\";\n\n/** CPT coding system used on Procedure.code (matches on-site `CPT_SYSTEM`). */\nexport const CPT_SYSTEM = \"http://www.ama-assn.org/go/cpt\";\n\n/**\n * LOINC panel code for the wound assessment panel (matches on-site\n * `WOUND_EXAM_PANEL_CODE` at\n * `sites/app-ehr/src/features/wounds/types/woundExamCodes.ts`).\n */\nexport const WOUND_EXAM_PANEL_CODE = \"39135-9\";\n\n/** Display for {@link WOUND_EXAM_PANEL_CODE}. */\nexport const WOUND_EXAM_PANEL_DISPLAY = \"Wound assessment panel\";\n\n/** LOINC component code for wound length (cm). */\nexport const WOUND_LENGTH_CODE = \"39126-8\";\n\n/** LOINC component code for wound width (cm). */\nexport const WOUND_WIDTH_CODE = \"39125-0\";\n\n/** LOINC component code for wound depth (cm). */\nexport const WOUND_DEPTH_CODE = \"39127-6\";\n\n/** LOINC component code for wound status (declining / stagnant / improving). */\nexport const WOUND_STATUS_CODE = \"72311-4\";\n\n/**\n * Hl7 condition-clinical system URL used on Condition.clinicalStatus.\n */\nexport const CONDITION_CLINICAL_STATUS_SYSTEM =\n \"http://terminology.hl7.org/CodeSystem/condition-clinical\";\n\n/**\n * Number of past home-health visits materialized per scheduled\n * home-health patient. Matches {@link BLOCK_OCCURRENCE_WEEKS_PAST}\n * so the facility and home-health populations carry comparable\n * history depths (~4 historical encounters per scheduled patient).\n */\nexport const HOME_HEALTH_VISITS_PAST = 4;\n\n/** Percentage threshold (0..100) of scheduled patients who have a current wound. */\nconst WOUND_BEARING_PATIENT_THRESHOLD = 70;\n\n/**\n * Percentage threshold (0..100) of wound-bearing patients who get a\n * debridement Procedure on their most-recent wound encounter.\n */\nconst WOUND_PROCEDURE_PATIENT_THRESHOLD = 25;\n\n/**\n * SNOMED-coded wound types stamped on the wound Condition's\n * `code.coding`. Five entries so the seeded roster shows visible\n * variety across patients. Codes are real SNOMED CT concepts under\n * the wound parent (13924000) the on-site app filters under.\n */\nconst WOUND_TYPE_OPTIONS: ReadonlyArray<{\n readonly code: string;\n readonly display: string;\n}> = [\n { code: \"421076008\", display: \"Pressure ulcer\" },\n { code: \"402863003\", display: \"Venous stasis ulcer\" },\n { code: \"371087003\", display: \"Diabetic foot ulcer\" },\n { code: \"262528002\", display: \"Arterial ulcer of lower extremity\" },\n { code: \"283682007\", display: \"Traumatic wound of lower extremity\" },\n];\n\n/**\n * Lower-extremity body sites stamped on the wound Condition's\n * `bodySite[0].coding`. All SNOMED-coded under the Lower Extremity\n * parent (61685007) the on-site app filters under.\n */\nconst WOUND_BODY_SITE_OPTIONS: ReadonlyArray<{\n readonly code: string;\n readonly display: string;\n}> = [\n { code: \"118473006\", display: \"Left lower limb\" },\n { code: \"32153003\", display: \"Left foot\" },\n { code: \"239043009\", display: \"Left heel\" },\n { code: \"61685007\", display: \"Lower limb\" },\n { code: \"118474000\", display: \"Right lower limb\" },\n { code: \"78791008\", display: \"Right foot\" },\n { code: \"239044003\", display: \"Right heel\" },\n];\n\n/**\n * Wound-debridement CPT presets the on-site EHR exposes via\n * `PRESET_PROCEDURES`. The seeder rotates through this list when\n * stamping a procedure on a wound encounter so the UAT roster\n * shows visible CPT-code variety.\n */\nconst WOUND_DEBRIDEMENT_PRESETS: ReadonlyArray<{\n readonly id: string;\n readonly display: string;\n readonly cptCode: string;\n}> = [\n { id: \"sharp-debridement\", display: \"Sharp Debridement\", cptCode: \"97597\" },\n {\n id: \"enzymatic-debridement\",\n display: \"Enzymatic Debridement\",\n cptCode: \"97602\",\n },\n { id: \"wound-irrigation\", display: \"Wound Irrigation\", cptCode: \"97605\" },\n {\n id: \"skin-substitute\",\n display: \"Skin Substitute Application\",\n cptCode: \"15271\",\n },\n];\n\nconst ON_SITE_SCENARIO = \"on-site-demo\";\n\nconst padIndex = (n: number): string => n.toString().padStart(3, \"0\");\n\n/**\n * Hash a string to a non-negative integer. Used to derive\n * deterministic per-patient selections (wound type, body site,\n * trajectory) from the patient id so re-fires produce identical\n * choices.\n */\nconst hashString = (input: string): number => {\n let h = 0;\n for (let i = 0; i < input.length; i += 1) {\n // eslint-disable-next-line no-bitwise\n h = (h * 31 + input.charCodeAt(i)) | 0;\n }\n return Math.abs(h);\n};\n\n/**\n * Whether a given patient carries a current wound. Targets\n * {@link WOUND_BEARING_PATIENT_THRESHOLD}% across the scheduled\n * roster. The decision is deterministic on the patient id.\n */\nconst isWoundBearingPatient = (patientId: string): boolean =>\n hashString(`${patientId}:wound-bearing`) % 100 <\n WOUND_BEARING_PATIENT_THRESHOLD;\n\n/**\n * Whether a wound-bearing patient gets a debridement Procedure\n * stamped on their most-recent wound encounter. Targets\n * {@link WOUND_PROCEDURE_PATIENT_THRESHOLD}% of wound-bearing\n * patients.\n */\nconst getsWoundProcedure = (patientId: string): boolean =>\n hashString(`${patientId}:procedure`) % 100 <\n WOUND_PROCEDURE_PATIENT_THRESHOLD;\n\n/**\n * Per-patient wound trajectory — either `healing` (size shrinks)\n * or `worsening` (size grows). Roughly 60/40 split so both states\n * appear visibly in the UAT roster.\n */\ntype WoundTrajectory = \"healing\" | \"worsening\";\n\nconst getWoundTrajectory = (patientId: string): WoundTrajectory =>\n hashString(`${patientId}:trajectory`) % 5 < 3 ? \"healing\" : \"worsening\";\n\n/**\n * Deterministic wound-type selection for a patient. Pulls from\n * {@link WOUND_TYPE_OPTIONS} so the seeded roster exercises every\n * type listed.\n */\nconst getWoundType = (\n patientId: string,\n): { readonly code: string; readonly display: string } =>\n WOUND_TYPE_OPTIONS[\n hashString(`${patientId}:type`) % WOUND_TYPE_OPTIONS.length\n ];\n\n/**\n * Deterministic lower-extremity body-site selection for a patient.\n */\nconst getWoundBodySite = (\n patientId: string,\n): { readonly code: string; readonly display: string } =>\n WOUND_BODY_SITE_OPTIONS[\n hashString(`${patientId}:bodysite`) % WOUND_BODY_SITE_OPTIONS.length\n ];\n\n/**\n * Deterministic CPT-preset selection for a patient who gets a\n * procedure stamped on their most-recent wound encounter.\n */\nconst getWoundProcedurePreset = (\n patientId: string,\n): {\n readonly id: string;\n readonly display: string;\n readonly cptCode: string;\n} =>\n WOUND_DEBRIDEMENT_PRESETS[\n hashString(`${patientId}:cpt`) % WOUND_DEBRIDEMENT_PRESETS.length\n ];\n\n/**\n * Stable wound-Condition id for a patient. The id is the patient\n * id suffixed with `-wound-001` — one wound per patient suffices\n * for UAT.\n */\nexport const woundConditionIdForPatient = (patientId: string): string =>\n `${patientId}-wound-001`;\n\nconst buildIdentifierPair = (\n resourceType: string,\n resourceId: string,\n roleSuffix: string,\n): Encounter[\"identifier\"] => [\n demoScenarioIdentifier(ON_SITE_SCENARIO, roleSuffix),\n openhiResourceIdentifier({\n tenantId: ON_SITE_DEMO_TENANT_ID,\n workspaceId: ON_SITE_DEMO_WORKSPACE_ID,\n resourceType,\n id: resourceId,\n }),\n];\n\n/**\n * Compute the UTC midnight Monday of the ISO week containing\n * `referenceIso`. Mirrors the block-occurrence anchor logic in\n * {@link buildOnSiteDemoBlockAppointments} so encounter dates align\n * exactly with their block occurrence.\n */\nconst mondayOfIsoWeekUtc = (referenceIso: string): Date => {\n const ref = new Date(referenceIso);\n if (Number.isNaN(ref.getTime())) {\n throw new Error(\n `mondayOfIsoWeekUtc: invalid reference date \"${referenceIso}\".`,\n );\n }\n const utcDay = ref.getUTCDay() === 0 ? 7 : ref.getUTCDay();\n const monday = new Date(\n Date.UTC(ref.getUTCFullYear(), ref.getUTCMonth(), ref.getUTCDate()),\n );\n monday.setUTCDate(monday.getUTCDate() - (utcDay - 1));\n return monday;\n};\n\nconst toIsoZ = (d: Date): string => d.toISOString();\n\ninterface EncounterSpec {\n readonly id: string;\n readonly patientId: string;\n readonly sequence: number;\n readonly totalEncounters: number;\n readonly periodStart: string;\n readonly periodEnd: string;\n readonly doctorId: string;\n readonly scribeId: string | undefined;\n readonly classCoding:\n | typeof ENCOUNTER_CLASS_FACILITY\n | typeof ENCOUNTER_CLASS_HOME_HEALTH;\n /** Optional facility Location id (facility encounters only). */\n readonly facilityId: string | undefined;\n /** Optional block-occurrence Appointment id (facility encounters only). */\n readonly appointmentId: string | undefined;\n}\n\n/**\n * Walk the past `BLOCK_OCCURRENCE_WEEKS_PAST` block occurrences for\n * each scheduled facility patient's block. One encounter per past\n * occurrence, authored by the block's doctor + scribe, dated to\n * that occurrence's start/end. Mirrors the occurrence-id format\n * used in {@link buildOnSiteDemoBlockAppointments}.\n */\nconst buildFacilityEncounterSpecs = (\n referenceIso: string,\n): ReadonlyArray<EncounterSpec> => {\n const anchorMonday = mondayOfIsoWeekUtc(referenceIso);\n const out: Array<EncounterSpec> = [];\n for (const patientId of onSiteDemoScheduledFacilityPatientIds()) {\n // We need the patient's block to find doctor + scribe + dayOfWeek.\n // Walk the block-template list once and check membership.\n const block = findBlockForPatient(patientId);\n if (!block) {\n continue;\n }\n const total = BLOCK_OCCURRENCE_WEEKS_PAST;\n for (let i = 0; i < total; i += 1) {\n // weekOffset walks -N .. -1 (oldest first), so sequence 1 is\n // the earliest historical encounter.\n const weekOffset = -(BLOCK_OCCURRENCE_WEEKS_PAST - i);\n const occurrenceDay = new Date(anchorMonday);\n occurrenceDay.setUTCDate(\n occurrenceDay.getUTCDate() + weekOffset * 7 + (block.dayOfWeek - 1),\n );\n const start = new Date(occurrenceDay);\n start.setUTCHours(14, 0, 0, 0);\n const end = new Date(occurrenceDay);\n end.setUTCHours(18, 0, 0, 0);\n\n const sign = \"m\"; // past only\n const magnitude = Math.abs(weekOffset).toString().padStart(2, \"0\");\n const appointmentId = `${block.id}-w${sign}${magnitude}`;\n\n out.push({\n id: `${patientId}-encounter-${padIndex(i + 1)}`,\n patientId,\n sequence: i + 1,\n totalEncounters: total,\n periodStart: toIsoZ(start),\n periodEnd: toIsoZ(end),\n doctorId: block.doctorId,\n scribeId: block.scribeId,\n classCoding: ENCOUNTER_CLASS_FACILITY,\n facilityId: block.facilityId,\n appointmentId,\n });\n }\n }\n return out;\n};\n\n/**\n * Cached patient-id → block-template lookup. Walks every block\n * once and inverts the per-block patient list. Lazy so the helper\n * does not consult {@link findOnSiteDemoBlockTemplate} at module\n * load time (the on-site fixtures + block modules import each\n * other circularly).\n */\nlet patientToBlockCache:\n | Map<string, ReturnType<typeof findOnSiteDemoBlockTemplate>>\n | undefined;\nconst findBlockForPatient = (\n patientId: string,\n): ReturnType<typeof findOnSiteDemoBlockTemplate> => {\n if (!patientToBlockCache) {\n const cache = new Map<\n string,\n ReturnType<typeof findOnSiteDemoBlockTemplate>\n >();\n // Walk the scheduled-patient list once: for each patient, scan\n // the four block templates and find the one that lists it.\n const scheduledIds = new Set(onSiteDemoScheduledFacilityPatientIds());\n const blockIds = [\n \"on-site-demo-block-001\",\n \"on-site-demo-block-002\",\n \"on-site-demo-block-003\",\n \"on-site-demo-block-004\",\n ];\n for (const blockId of blockIds) {\n const block = findOnSiteDemoBlockTemplate(blockId);\n if (!block) {\n continue;\n }\n for (const pid of facilityPatientsForBlock(blockId)) {\n if (scheduledIds.has(pid)) {\n cache.set(pid, block);\n }\n }\n }\n patientToBlockCache = cache;\n }\n return patientToBlockCache.get(patientId);\n};\n\n/**\n * Walk the past {@link HOME_HEALTH_VISITS_PAST} visits for each\n * scheduled home-health patient. Visits step back from the\n * reference date at the patient's cadence (7 / 14 / 28 days).\n * Each encounter is authored by the patient's assigned\n * home-health provider; no scribe (home-health is a single-\n * provider visit in the on-site EHR model).\n */\nconst buildHomeHealthEncounterSpecs = (\n referenceIso: string,\n): ReadonlyArray<EncounterSpec> => {\n const reference = new Date(referenceIso);\n if (Number.isNaN(reference.getTime())) {\n throw new Error(\n `buildHomeHealthEncounterSpecs: invalid reference date \"${referenceIso}\".`,\n );\n }\n const out: Array<EncounterSpec> = [];\n for (const patientId of onSiteDemoScheduledHomeHealthPatientIds()) {\n const providerId = findOnSiteDemoHomeHealthPatientProvider(patientId);\n const cadenceDays =\n findOnSiteDemoHomeHealthPatientVisitCadenceDays(patientId);\n if (!providerId || typeof cadenceDays !== \"number\") {\n continue;\n }\n const total = HOME_HEALTH_VISITS_PAST;\n for (let i = 0; i < total; i += 1) {\n // visit -N is oldest; visit -1 is most recent. We index\n // `i` from 0..N-1 with i=0 = oldest, i=N-1 = most recent so\n // sequence 1 is the earliest historical encounter (matches\n // the facility ordering above).\n const visitsBack = total - i;\n const visitDay = new Date(reference);\n visitDay.setUTCDate(visitDay.getUTCDate() - visitsBack * cadenceDays);\n const start = new Date(visitDay);\n start.setUTCHours(14, 0, 0, 0);\n const end = new Date(visitDay);\n end.setUTCHours(15, 0, 0, 0); // home visits are ~1 hour\n out.push({\n id: `${patientId}-encounter-${padIndex(i + 1)}`,\n patientId,\n sequence: i + 1,\n totalEncounters: total,\n periodStart: toIsoZ(start),\n periodEnd: toIsoZ(end),\n doctorId: providerId,\n scribeId: undefined,\n classCoding: ENCOUNTER_CLASS_HOME_HEALTH,\n facilityId: undefined,\n appointmentId: undefined,\n });\n }\n }\n return out;\n};\n\nconst buildEncounterResource = (spec: EncounterSpec): Encounter => {\n const participant: NonNullable<Encounter[\"participant\"]> = [\n {\n individual: {\n reference: `Practitioner/${spec.doctorId}`,\n type: \"Practitioner\",\n },\n },\n ];\n if (spec.scribeId) {\n participant.push({\n individual: {\n reference: `Practitioner/${spec.scribeId}`,\n type: \"Practitioner\",\n },\n });\n }\n const encounter: Encounter = {\n resourceType: \"Encounter\",\n id: spec.id,\n identifier: buildIdentifierPair(\n \"Encounter\",\n spec.id,\n `encounter-${spec.id}`,\n ),\n status: \"finished\",\n class: { ...spec.classCoding },\n subject: { reference: `Patient/${spec.patientId}`, type: \"Patient\" },\n period: { start: spec.periodStart, end: spec.periodEnd },\n participant,\n };\n if (spec.facilityId) {\n encounter.location = [\n {\n location: {\n reference: `Location/${spec.facilityId}`,\n type: \"Location\",\n },\n },\n ];\n }\n if (spec.appointmentId) {\n encounter.appointment = [\n {\n reference: `Appointment/${spec.appointmentId}`,\n type: \"Appointment\",\n },\n ];\n }\n return encounter;\n};\n\n/**\n * Build the wound Condition for one patient. Recorded once per\n * patient at the date of the patient's earliest encounter (the\n * wound is present on the first visit). Subsequent wound exams\n * reference this Condition via `Observation.focus`.\n */\nconst buildWoundConditionResource = (\n patientId: string,\n firstEncounterStart: string,\n): Condition => {\n const woundType = getWoundType(patientId);\n const bodySite = getWoundBodySite(patientId);\n const id = woundConditionIdForPatient(patientId);\n return {\n resourceType: \"Condition\",\n id,\n identifier: buildIdentifierPair(\"Condition\", id, `wound-${patientId}`),\n clinicalStatus: {\n coding: [\n {\n system: CONDITION_CLINICAL_STATUS_SYSTEM,\n code: \"active\",\n display: \"Active\",\n },\n ],\n },\n category: [{ text: \"wound\" }],\n code: {\n text: woundType.display,\n coding: [\n {\n system: SNOMED_SYSTEM,\n code: woundType.code,\n display: woundType.display,\n },\n ],\n },\n bodySite: [\n {\n coding: [\n {\n system: SNOMED_SYSTEM,\n code: bodySite.code,\n display: bodySite.display,\n },\n ],\n text: bodySite.display,\n },\n ],\n subject: { reference: `Patient/${patientId}`, type: \"Patient\" },\n onsetDateTime: firstEncounterStart,\n recordedDate: firstEncounterStart,\n } as Condition;\n};\n\n/**\n * Wound size at a given encounter sequence. Baseline is the\n * patient's \"starting\" size; the trajectory shifts it across\n * encounters. Result is in centimetres for length / width and\n * millimetres-deep for depth, but emitted as a cm Quantity so the\n * on-site UI's quantity-rendering matches.\n */\nconst woundSizeAtSequence = (\n patientId: string,\n sequence: number,\n totalEncounters: number,\n): {\n readonly length: number;\n readonly width: number;\n readonly depth: number;\n readonly status: \"improving\" | \"stagnant\" | \"declining\";\n} => {\n // Baseline length 4..7 cm, width 3..5 cm, depth 0.3..0.8 cm.\n const baseLength = 4 + (hashString(`${patientId}:length`) % 4); // 4..7\n const baseWidth = 3 + (hashString(`${patientId}:width`) % 3); // 3..5\n const baseDepthTenths = 3 + (hashString(`${patientId}:depth`) % 6); // 0.3..0.8 cm\n const trajectory = getWoundTrajectory(patientId);\n // Progress fraction: encounter 1 = 0 (baseline), encounter N = 1.\n const denom = Math.max(1, totalEncounters - 1);\n const progress = (sequence - 1) / denom;\n const sign = trajectory === \"healing\" ? -1 : 1;\n // Healing shrinks linearly by up to ~40% across the encounter\n // window; worsening grows linearly by up to ~30%.\n const shrinkOrGrow = trajectory === \"healing\" ? 0.4 : 0.3;\n const length = +(baseLength * (1 + sign * shrinkOrGrow * progress)).toFixed(\n 1,\n );\n const width = +(baseWidth * (1 + sign * shrinkOrGrow * progress)).toFixed(1);\n const depth = +(\n (baseDepthTenths / 10) *\n (1 + sign * shrinkOrGrow * progress)\n ).toFixed(2);\n const status =\n trajectory === \"healing\" && sequence > 1\n ? \"improving\"\n : trajectory === \"worsening\" && sequence > 1\n ? \"declining\"\n : \"stagnant\";\n return { length, width, depth, status };\n};\n\n/**\n * Build the wound-exam Observation for one encounter on a\n * wound-bearing patient. Mirrors the on-site\n * `buildWoundExamObservation` mapper: panel-coded with LOINC\n * 39135-9, `focus` references the wound Condition, `encounter`\n * references the encounter, components carry length / width /\n * depth / status.\n */\nconst buildWoundExamObservation = (\n patientId: string,\n encounterId: string,\n sequence: number,\n totalEncounters: number,\n effectiveDateTime: string,\n): Observation => {\n const size = woundSizeAtSequence(patientId, sequence, totalEncounters);\n const woundConditionId = woundConditionIdForPatient(patientId);\n const id = `${encounterId}-wound-exam`;\n return {\n resourceType: \"Observation\",\n id,\n identifier: buildIdentifierPair(\n \"Observation\",\n id,\n `wound-exam-${encounterId}`,\n ),\n status: \"final\",\n code: {\n coding: [\n {\n system: LOINC_SYSTEM,\n code: WOUND_EXAM_PANEL_CODE,\n display: WOUND_EXAM_PANEL_DISPLAY,\n },\n ],\n },\n subject: { reference: `Patient/${patientId}`, type: \"Patient\" },\n encounter: { reference: `Encounter/${encounterId}`, type: \"Encounter\" },\n focus: [\n {\n reference: `Condition/${woundConditionId}`,\n type: \"Condition\",\n },\n ],\n effectiveDateTime,\n component: [\n {\n code: {\n coding: [\n {\n system: LOINC_SYSTEM,\n code: WOUND_LENGTH_CODE,\n display: \"Length\",\n },\n ],\n },\n valueQuantity: { value: size.length, unit: \"cm\" },\n },\n {\n code: {\n coding: [\n { system: LOINC_SYSTEM, code: WOUND_WIDTH_CODE, display: \"Width\" },\n ],\n },\n valueQuantity: { value: size.width, unit: \"cm\" },\n },\n {\n code: {\n coding: [\n { system: LOINC_SYSTEM, code: WOUND_DEPTH_CODE, display: \"Depth\" },\n ],\n },\n valueQuantity: { value: size.depth, unit: \"cm\" },\n },\n {\n code: {\n coding: [\n {\n system: LOINC_SYSTEM,\n code: WOUND_STATUS_CODE,\n display: \"Status\",\n },\n ],\n },\n valueCodeableConcept: {\n coding: [{ code: size.status, display: size.status }],\n },\n },\n ],\n };\n};\n\n/**\n * Build the wound-debridement Procedure for one patient on their\n * most-recent wound encounter. Carries a CPT code in\n * `code.coding[0]`, references the wound Condition via\n * `reasonReference`, and the encounter via `encounter`.\n */\nconst buildWoundProcedureResource = (\n patientId: string,\n encounterId: string,\n performedDateTime: string,\n): Procedure => {\n const preset = getWoundProcedurePreset(patientId);\n const woundConditionId = woundConditionIdForPatient(patientId);\n const id = `${encounterId}-procedure`;\n return {\n resourceType: \"Procedure\",\n id,\n identifier: buildIdentifierPair(\n \"Procedure\",\n id,\n `procedure-${encounterId}`,\n ),\n status: \"completed\",\n code: {\n text: preset.display,\n coding: [\n {\n system: CPT_SYSTEM,\n code: preset.cptCode,\n display: preset.display,\n },\n ],\n },\n subject: { reference: `Patient/${patientId}`, type: \"Patient\" },\n encounter: { reference: `Encounter/${encounterId}`, type: \"Encounter\" },\n reasonReference: [\n {\n reference: `Condition/${woundConditionId}`,\n type: \"Condition\",\n },\n ],\n performedDateTime,\n } as Procedure;\n};\n\n/**\n * Cached encounter specs per reference-date. Computed once per\n * unique reference ISO so re-fires of the seeder against the same\n * `baseContext.date` produce byte-identical encounter ids.\n */\nconst encounterSpecsCache = new Map<string, ReadonlyArray<EncounterSpec>>();\nconst getAllEncounterSpecs = (\n referenceIso: string,\n): ReadonlyArray<EncounterSpec> => {\n const cached = encounterSpecsCache.get(referenceIso);\n if (cached) {\n return cached;\n }\n const all = [\n ...buildFacilityEncounterSpecs(referenceIso),\n ...buildHomeHealthEncounterSpecs(referenceIso),\n ];\n encounterSpecsCache.set(referenceIso, all);\n return all;\n};\n\n/**\n * Test seam — clear the spec cache between test invocations so\n * stale state from a prior seed run does not leak into the next.\n * Not part of the public API contract.\n */\nexport const __resetOnSiteDemoEncounterCachesForTests = (): void => {\n encounterSpecsCache.clear();\n patientToBlockCache = undefined;\n};\n\n/**\n * Materialize every Encounter resource for the on-site UAT demo\n * workspace. Scheduled facility patients fan out over the past 4\n * block occurrences; scheduled home-health patients fan out over\n * the past {@link HOME_HEALTH_VISITS_PAST} cadence visits. Intake-\n * only patients contribute zero encounters.\n */\nexport const buildOnSiteDemoEncounters = (\n referenceIso: string,\n): ReadonlyArray<Encounter> =>\n getAllEncounterSpecs(referenceIso).map(buildEncounterResource);\n\n/**\n * Materialize every wound {@link Condition} resource for the\n * on-site UAT demo workspace. One Condition per wound-bearing\n * patient, dated to that patient's earliest encounter.\n */\nexport const buildOnSiteDemoWoundConditions = (\n referenceIso: string,\n): ReadonlyArray<Condition> => {\n const specs = getAllEncounterSpecs(referenceIso);\n // Group by patient and find each patient's earliest encounter.\n const firstByPatient = new Map<string, string>();\n for (const spec of specs) {\n if (!isWoundBearingPatient(spec.patientId)) {\n continue;\n }\n const existing = firstByPatient.get(spec.patientId);\n if (!existing || spec.periodStart < existing) {\n firstByPatient.set(spec.patientId, spec.periodStart);\n }\n }\n const out: Array<Condition> = [];\n for (const [patientId, firstStart] of firstByPatient.entries()) {\n out.push(buildWoundConditionResource(patientId, firstStart));\n }\n return out;\n};\n\n/**\n * Materialize every wound-exam {@link Observation} for the on-site\n * UAT demo workspace. One per encounter on a wound-bearing\n * patient, with progressing length / width / depth components.\n */\nexport const buildOnSiteDemoWoundObservations = (\n referenceIso: string,\n): ReadonlyArray<Observation> => {\n const specs = getAllEncounterSpecs(referenceIso);\n const out: Array<Observation> = [];\n for (const spec of specs) {\n if (!isWoundBearingPatient(spec.patientId)) {\n continue;\n }\n out.push(\n buildWoundExamObservation(\n spec.patientId,\n spec.id,\n spec.sequence,\n spec.totalEncounters,\n spec.periodStart,\n ),\n );\n }\n return out;\n};\n\n/**\n * Materialize every wound-debridement {@link Procedure} for the\n * on-site UAT demo workspace. One per qualifying wound-bearing\n * patient, on their most-recent encounter, with a real CPT code.\n */\nexport const buildOnSiteDemoWoundProcedures = (\n referenceIso: string,\n): ReadonlyArray<Procedure> => {\n const specs = getAllEncounterSpecs(referenceIso);\n // For each patient, pick the most-recent encounter (highest\n // sequence). Procedures only land on patients who both have a\n // wound and pass {@link getsWoundProcedure}.\n const lastByPatient = new Map<string, EncounterSpec>();\n for (const spec of specs) {\n if (!isWoundBearingPatient(spec.patientId)) {\n continue;\n }\n if (!getsWoundProcedure(spec.patientId)) {\n continue;\n }\n const existing = lastByPatient.get(spec.patientId);\n if (!existing || spec.sequence > existing.sequence) {\n lastByPatient.set(spec.patientId, spec);\n }\n }\n const out: Array<Procedure> = [];\n for (const spec of lastByPatient.values()) {\n out.push(\n buildWoundProcedureResource(spec.patientId, spec.id, spec.periodStart),\n );\n }\n return out;\n};\n\n/**\n * Stable list of every Encounter id seeded for the on-site UAT\n * demo workspace, anchored to `referenceIso`. Downstream tickets\n * (e.g. #1307 — claims walking each historical encounter) read\n * this to fan out per-encounter work without re-deriving the\n * mapping.\n */\nexport const onSiteDemoEncounterIds = (\n referenceIso: string,\n): ReadonlyArray<string> => getAllEncounterSpecs(referenceIso).map((s) => s.id);\n\n/**\n * Encounters scoped to a single patient, ordered earliest first.\n * Returns the empty array for intake-only patients (no\n * encounters) and for unknown patient ids.\n */\nexport const onSiteDemoEncountersForPatient = (\n patientId: string,\n referenceIso: string,\n): ReadonlyArray<string> =>\n getAllEncounterSpecs(referenceIso)\n .filter((s) => s.patientId === patientId)\n .map((s) => s.id);\n\n/**\n * Public projection of an encounter's seed metadata. Downstream\n * tickets (e.g. #1307 — claims walking each historical encounter)\n * read this instead of re-parsing the encounter id string.\n */\nexport interface OnSiteDemoEncounterMetadata {\n /** Stable Encounter id. */\n readonly id: string;\n /** Patient the encounter is authored against. */\n readonly patientId: string;\n /** 1-based sequence ordinal within the patient's encounter list (1 = earliest). */\n readonly sequence: number;\n /** Total encounters seeded for this patient. */\n readonly totalEncounters: number;\n /** ISO 8601 start instant the encounter is dated to. */\n readonly periodStart: string;\n /** Whether this encounter carries a wound-debridement Procedure. */\n readonly hasWoundProcedure: boolean;\n}\n\n/**\n * Materialize every encounter's seed metadata for the on-site UAT\n * demo workspace. Order matches {@link onSiteDemoEncounterIds}.\n * The `hasWoundProcedure` flag is `true` only on the patient's\n * most-recent encounter when {@link onSiteDemoWoundProcedurePatientIds}\n * lists that patient — mirroring the procedure-attachment rule in\n * {@link buildOnSiteDemoWoundProcedures}.\n */\nexport const onSiteDemoEncounterMetadata = (\n referenceIso: string,\n): ReadonlyArray<OnSiteDemoEncounterMetadata> => {\n const specs = getAllEncounterSpecs(referenceIso);\n // Determine each patient's most-recent encounter id so we can\n // flag the procedure-bearing encounter without re-deriving the\n // hash.\n const lastEncounterByPatient = new Map<string, string>();\n for (const spec of specs) {\n const existing = lastEncounterByPatient.get(spec.patientId);\n if (!existing) {\n lastEncounterByPatient.set(spec.patientId, spec.id);\n continue;\n }\n // Specs are appended in sequence order per patient.\n if (spec.sequence > specs.find((s) => s.id === existing)!.sequence) {\n lastEncounterByPatient.set(spec.patientId, spec.id);\n }\n }\n const procedurePatients = new Set(onSiteDemoWoundProcedurePatientIds());\n return specs.map((spec) => ({\n id: spec.id,\n patientId: spec.patientId,\n sequence: spec.sequence,\n totalEncounters: spec.totalEncounters,\n periodStart: spec.periodStart,\n hasWoundProcedure:\n procedurePatients.has(spec.patientId) &&\n lastEncounterByPatient.get(spec.patientId) === spec.id,\n }));\n};\n\n/**\n * Subset of patients (facility + home-health) the seeder flags as\n * carrying a current wound. Exported so tests and downstream\n * tickets can assert wound-coverage targets without re-deriving\n * the hash. Order matches the input list of scheduled patients.\n */\nexport const onSiteDemoWoundBearingPatientIds = (): ReadonlyArray<string> => {\n const out: Array<string> = [];\n for (const id of onSiteDemoScheduledFacilityPatientIds()) {\n if (isWoundBearingPatient(id)) {\n out.push(id);\n }\n }\n for (const id of onSiteDemoScheduledHomeHealthPatientIds()) {\n if (isWoundBearingPatient(id)) {\n out.push(id);\n }\n }\n return out;\n};\n\n/**\n * Subset of {@link onSiteDemoWoundBearingPatientIds} whose patients\n * also get a CPT-coded debridement Procedure on their most-recent\n * encounter.\n */\nexport const onSiteDemoWoundProcedurePatientIds = (): ReadonlyArray<string> =>\n onSiteDemoWoundBearingPatientIds().filter((id) => getsWoundProcedure(id));\n","import type { Claim, Coverage, Money, PaymentNotice } from \"@openhi/types\";\nimport {\n ON_SITE_DEMO_TENANT_ID,\n ON_SITE_DEMO_WORKSPACE_ID,\n demoScenarioIdentifier,\n openhiResourceIdentifier,\n} from \"./events\";\nimport {\n CPT_SYSTEM,\n onSiteDemoEncounterMetadata,\n type OnSiteDemoEncounterMetadata,\n} from \"./on-site-demo-encounters\";\nimport { buildOnSiteDemoFacilityCoverages } from \"./on-site-demo-facility-patients\";\nimport { buildOnSiteDemoHomeHealthCoverages } from \"./on-site-demo-home-health-patients\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/constructs/workflows/control-plane/seed-demo-data/on-site-demo-claims.md\n *\n * Hand-authored Claim + PaymentNotice fixtures the `seed-demo-data`\n * workflow upserts into the on-site-medical UAT demo tenant\n * ({@link ON_SITE_DEMO_TENANT_ID} + {@link ON_SITE_DEMO_WORKSPACE_ID})\n * on every non-prod deploy (issue #1307).\n *\n * Topology — issue #1307 design:\n * - For each historical encounter (#1306), decide deterministically\n * whether the visit is billed or explicitly unbilled. The unbilled\n * decision is recorded by the *absence* of a Claim resource on\n * that encounter id; the on-site UI can derive \"unbilled\" by\n * listing claims and finding no match for an encounter.\n * - Billed encounters get exactly one {@link Claim} resource keyed\n * `<encounter-id>-claim`. The Claim carries:\n * - `status: \"active\"` (FHIR R4 enum only has\n * `active|cancelled|draft|entered-in-error`, none of which\n * encode our domain workflow status — see\n * {@link CLAIM_WORKFLOW_STATUS_EXTENSION_URL}).\n * - `claim-workflow-status` extension carrying the domain\n * status: `submitted` / `accepted` / `rejected` /\n * `reworked` / `resubmitted`.\n * - `insurance[0].coverage` referencing the patient's primary\n * {@link Coverage} (which is what carries the actual payor).\n * - `item[]` carrying one line: a wound-debridement CPT for\n * encounters that have a procedure (#1306), otherwise an\n * E/M visit code (99213/99214/99215) chosen deterministically.\n * - `total` denormalised from the single line item's `net`.\n * - Accepted claims get a {@link PaymentNotice} resource keyed\n * `<encounter-id>-payment` whose `paymentStatus` CodeableConcept\n * carries the domain payment status: `partial` / `full` /\n * `write-off`. Submitted / rejected / reworked / resubmitted\n * claims do not emit a PaymentNotice — the \"in flux\" subset is\n * specifically every `submitted` claim with no PaymentNotice.\n *\n * Modelling choices:\n * - **Single Claim per encounter** (not a chain). The \"reworked\"\n * status implies history (original rejected → resubmitted),\n * denormalised onto the same Claim via the\n * `claim-workflow-status` extension. On-site's current UI\n * (`sites/app-ehr/src/pages/patient/tabs/insurance/ClaimsTable.tsx`)\n * shows a single status badge per claim and does not need a\n * chain to render correctly.\n * - **PaymentNotice over a denormalised payment summary** —\n * PaymentNotice operations already exist in the data layer\n * (`packages/@openhi/constructs/src/data/operations/data/paymentnotice/`),\n * so we lean on real FHIR resources rather than adding a new\n * extension schema.\n * - **Domain status as an extension** — FHIR R4 `Claim.status`\n * does not include the workflow-status concepts the demo\n * needs, and stamping a non-standard string onto the enum\n * would fail the zod schema. The extension approach mirrors\n * how on-site already encodes domain state on other\n * resources (hospice status, QMB status, care-context, etc.).\n *\n * Distribution targets — chosen so all 5 workflow statuses plus\n * unbilled appear in the demo data, with payment-status variety\n * on the accepted bucket and a meaningful \"in flux\" submitted\n * bucket:\n * - ~15% of encounters are unbilled (no Claim)\n * - ~20% of claims are submitted (no PaymentNotice — \"in flux\")\n * - ~45% of claims are accepted (with PaymentNotice)\n * - ~40% of accepted: partial payment\n * - ~40% of accepted: full payment\n * - ~20% of accepted: write-off\n * - ~10% of claims are rejected\n * - ~15% of claims are reworked\n * - ~10% of claims are resubmitted\n *\n * Ids are deterministic — re-fires upsert the same records,\n * matching the workflow's idempotency contract.\n */\n\n/**\n * Extension URL stamped on every seeded Claim recording the\n * domain workflow status — submitted / accepted / rejected /\n * reworked / resubmitted. FHIR R4 `Claim.status` only carries\n * the lifecycle states `active|cancelled|draft|entered-in-error`,\n * so the demo's workflow status sits on this extension instead\n * of squeezing into the base enum.\n */\nexport const CLAIM_WORKFLOW_STATUS_EXTENSION_URL =\n \"https://on-site-medical.app/fhir/StructureDefinition/claim-workflow-status\";\n\n/** Sub-extension under {@link CLAIM_WORKFLOW_STATUS_EXTENSION_URL}. */\nexport const CLAIM_WORKFLOW_STATUS_VALUE_SUB_EXTENSION_URL = \"status\";\n\n/** Sub-extension under {@link CLAIM_WORKFLOW_STATUS_EXTENSION_URL}. */\nexport const CLAIM_WORKFLOW_STATUS_LAST_TRANSITION_SUB_EXTENSION_URL =\n \"lastTransition\";\n\n/**\n * Domain workflow status values written to\n * {@link CLAIM_WORKFLOW_STATUS_EXTENSION_URL}.\n */\nexport const CLAIM_WORKFLOW_STATUS = {\n SUBMITTED: \"submitted\",\n ACCEPTED: \"accepted\",\n REJECTED: \"rejected\",\n REWORKED: \"reworked\",\n RESUBMITTED: \"resubmitted\",\n} as const;\nexport type ClaimWorkflowStatus =\n (typeof CLAIM_WORKFLOW_STATUS)[keyof typeof CLAIM_WORKFLOW_STATUS];\n\n/**\n * Domain payment status values written to\n * {@link PaymentNotice.paymentStatus} on accepted claims.\n */\nexport const PAYMENT_STATUS = {\n PARTIAL: \"partial\",\n FULL: \"full\",\n WRITE_OFF: \"write-off\",\n} as const;\nexport type PaymentStatus =\n (typeof PAYMENT_STATUS)[keyof typeof PAYMENT_STATUS];\n\n/** CodeSystem URL stamped on the {@link PaymentNotice.paymentStatus} coding. */\nexport const PAYMENT_STATUS_SYSTEM =\n \"https://on-site-medical.app/fhir/CodeSystem/payment-status\";\n\n/**\n * E/M visit codes used on non-procedure encounters. Mirrors the\n * 99213 / 99214 / 99215 progression on-site uses elsewhere for\n * visit complexity. Real CPT codes.\n */\nconst EM_VISIT_CODES: ReadonlyArray<{\n readonly code: string;\n readonly display: string;\n readonly amount: number;\n}> = [\n {\n code: \"99213\",\n display: \"Office visit, established patient, low\",\n amount: 110,\n },\n {\n code: \"99214\",\n display: \"Office visit, established patient, moderate\",\n amount: 165,\n },\n {\n code: \"99215\",\n display: \"Office visit, established patient, high\",\n amount: 220,\n },\n];\n\n/**\n * Wound-debridement CPT codes that may land on procedure-bearing\n * encounters (mirrors {@link WOUND_DEBRIDEMENT_PRESETS} in\n * `on-site-demo-encounters.ts`). Amounts are realistic Medicare\n * allowed-amount ballpark figures so the seeded `Claim.total`\n * looks plausible.\n */\nconst PROCEDURE_CPT_AMOUNTS: Readonly<\n Record<string, { display: string; amount: number }>\n> = {\n \"97597\": { display: \"Sharp Debridement\", amount: 145 },\n \"97602\": { display: \"Enzymatic Debridement\", amount: 95 },\n \"97605\": { display: \"Wound Irrigation (NPWT)\", amount: 175 },\n \"15271\": { display: \"Skin Substitute Application\", amount: 410 },\n};\n\nconst ON_SITE_SCENARIO = \"on-site-demo\";\n\n/**\n * Hash a string to a non-negative integer. Mirrors the hashing\n * in {@link on-site-demo-encounters.ts} so per-encounter\n * decisions are stable across re-fires.\n */\nconst hashString = (input: string): number => {\n let h = 0;\n for (let i = 0; i < input.length; i += 1) {\n // eslint-disable-next-line no-bitwise\n h = (h * 31 + input.charCodeAt(i)) | 0;\n }\n return Math.abs(h);\n};\n\n/** Probability buckets (0..99 % 100) for the unbilled / status / payment cuts. */\nconst UNBILLED_BUCKET_THRESHOLD = 15;\nconst SUBMITTED_BUCKET_THRESHOLD = 35; // 15..34 = submitted (~20%)\nconst ACCEPTED_BUCKET_THRESHOLD = 80; // 35..79 = accepted (~45%)\nconst REJECTED_BUCKET_THRESHOLD = 90; // 80..89 = rejected (~10%)\nconst REWORKED_BUCKET_THRESHOLD = 100; // 90..99 = reworked (~10%) — resubmitted comes from another lane\n\n/**\n * Decide whether an encounter is billed at all. Targets ~15%\n * unbilled across the deck so the on-site UI has a non-trivial\n * \"no claim\" subset to render.\n */\nconst isEncounterUnbilled = (encounterId: string): boolean =>\n hashString(`${encounterId}:billed`) % 100 < UNBILLED_BUCKET_THRESHOLD;\n\n/**\n * Determine the workflow status for a billed encounter. The\n * distribution targets defined at the top of this module guarantee\n * every status appears in the seeded set.\n */\nconst workflowStatusForEncounter = (\n encounterId: string,\n): ClaimWorkflowStatus => {\n const bucket = hashString(`${encounterId}:status`) % 100;\n if (bucket < SUBMITTED_BUCKET_THRESHOLD - UNBILLED_BUCKET_THRESHOLD) {\n return CLAIM_WORKFLOW_STATUS.SUBMITTED;\n }\n if (bucket < ACCEPTED_BUCKET_THRESHOLD - UNBILLED_BUCKET_THRESHOLD) {\n return CLAIM_WORKFLOW_STATUS.ACCEPTED;\n }\n if (bucket < REJECTED_BUCKET_THRESHOLD - UNBILLED_BUCKET_THRESHOLD) {\n return CLAIM_WORKFLOW_STATUS.REJECTED;\n }\n if (bucket < REWORKED_BUCKET_THRESHOLD - UNBILLED_BUCKET_THRESHOLD) {\n return CLAIM_WORKFLOW_STATUS.REWORKED;\n }\n // Tail bucket — resubmitted.\n return CLAIM_WORKFLOW_STATUS.RESUBMITTED;\n};\n\n/**\n * Decide the payment status for an accepted claim. Caller MUST\n * short-circuit on workflow status — non-accepted claims have no\n * PaymentNotice.\n */\nconst paymentStatusForEncounter = (encounterId: string): PaymentStatus => {\n const bucket = hashString(`${encounterId}:payment`) % 10;\n if (bucket < 4) {\n return PAYMENT_STATUS.PARTIAL;\n }\n if (bucket < 8) {\n return PAYMENT_STATUS.FULL;\n }\n return PAYMENT_STATUS.WRITE_OFF;\n};\n\n/**\n * Build the deterministic patient → primary Coverage map. Walks\n * the seeded Coverage list (facility + home-health) once and\n * picks each Coverage with `order: 1`. Cached after first call.\n */\nlet cachedPrimaryCoverageByPatient: Map<string, Coverage> | undefined;\nconst getPrimaryCoverageByPatient = (): Map<string, Coverage> => {\n if (!cachedPrimaryCoverageByPatient) {\n const map = new Map<string, Coverage>();\n const allCoverages = [\n ...buildOnSiteDemoFacilityCoverages(),\n ...buildOnSiteDemoHomeHealthCoverages(),\n ];\n for (const cov of allCoverages) {\n if (cov.order !== 1) {\n continue;\n }\n const ref = cov.beneficiary.reference;\n if (typeof ref !== \"string\") {\n continue;\n }\n const patientId = ref.replace(/^Patient\\//, \"\");\n map.set(patientId, cov);\n }\n cachedPrimaryCoverageByPatient = map;\n }\n return cachedPrimaryCoverageByPatient;\n};\n\n/**\n * Test seam — clear caches between test invocations so stale\n * state from a prior seed run does not leak into the next.\n */\nexport const __resetOnSiteDemoClaimCachesForTests = (): void => {\n cachedPrimaryCoverageByPatient = undefined;\n};\n\nconst buildIdentifierPair = (\n resourceType: string,\n resourceId: string,\n roleSuffix: string,\n): Array<{\n system?: string;\n value?: string;\n}> =>\n [\n demoScenarioIdentifier(ON_SITE_SCENARIO, roleSuffix),\n openhiResourceIdentifier({\n tenantId: ON_SITE_DEMO_TENANT_ID,\n workspaceId: ON_SITE_DEMO_WORKSPACE_ID,\n resourceType,\n id: resourceId,\n }),\n ] as Array<{ system?: string; value?: string }>;\n\n/** Deterministic E/M code selection for non-procedure encounters. */\nconst emCodeForEncounter = (\n encounterId: string,\n): {\n readonly code: string;\n readonly display: string;\n readonly amount: number;\n} => EM_VISIT_CODES[hashString(`${encounterId}:em`) % EM_VISIT_CODES.length];\n\n/**\n * Pull the wound-debridement CPT code for a procedure-bearing\n * encounter. Falls back to 99213 if a CPT cannot be resolved\n * (shouldn't happen — the metadata flag is set by the same\n * procedure-builder that uses these CPTs).\n */\nconst cptForProcedureEncounter = (\n encounterId: string,\n): {\n readonly code: string;\n readonly display: string;\n readonly amount: number;\n} => {\n const cptKeys = Object.keys(PROCEDURE_CPT_AMOUNTS);\n const code =\n cptKeys[hashString(`${encounterId}:procedure-cpt`) % cptKeys.length];\n const entry = PROCEDURE_CPT_AMOUNTS[code];\n if (!entry) {\n return EM_VISIT_CODES[0];\n }\n return { code, display: entry.display, amount: entry.amount };\n};\n\n/** Build the `Money` resource for a USD-denominated amount. */\nconst usdMoney = (amount: number): Money => ({\n value: +amount.toFixed(2),\n currency: \"USD\",\n});\n\n/**\n * Build the Claim resource for one billed encounter. Carries the\n * workflow-status extension, insurance reference back to the\n * patient's primary Coverage, and a single line item.\n */\nconst buildClaimResource = (\n meta: OnSiteDemoEncounterMetadata,\n status: ClaimWorkflowStatus,\n primaryCoverageId: string,\n insurerDisplay: string,\n): Claim => {\n const claimId = `${meta.id}-claim`;\n const line = meta.hasWoundProcedure\n ? cptForProcedureEncounter(meta.id)\n : emCodeForEncounter(meta.id);\n const total = usdMoney(line.amount);\n const lastTransition = meta.periodStart; // domain-history anchor\n return {\n resourceType: \"Claim\",\n id: claimId,\n identifier: buildIdentifierPair(\"Claim\", claimId, `claim-${meta.id}`),\n status: \"active\",\n type: {\n coding: [\n {\n system: \"http://terminology.hl7.org/CodeSystem/claim-type\",\n code: \"professional\",\n display: \"Professional\",\n },\n ],\n text: \"Professional\",\n },\n use: \"claim\",\n patient: { reference: `Patient/${meta.patientId}`, type: \"Patient\" },\n created: meta.periodStart,\n insurer: { display: insurerDisplay },\n provider: { reference: `Patient/${meta.patientId}`, type: \"Patient\" },\n priority: {\n coding: [\n {\n system: \"http://terminology.hl7.org/CodeSystem/processpriority\",\n code: \"normal\",\n display: \"Normal\",\n },\n ],\n text: \"Normal\",\n },\n insurance: [\n {\n sequence: 1,\n focal: true,\n coverage: {\n reference: `Coverage/${primaryCoverageId}`,\n type: \"Coverage\",\n },\n },\n ],\n item: [\n {\n sequence: 1,\n productOrService: {\n coding: [\n { system: CPT_SYSTEM, code: line.code, display: line.display },\n ],\n text: line.display,\n },\n servicedDate: meta.periodStart.slice(0, 10),\n unitPrice: total,\n net: total,\n encounter: [{ reference: `Encounter/${meta.id}`, type: \"Encounter\" }],\n },\n ],\n total,\n extension: [\n {\n url: CLAIM_WORKFLOW_STATUS_EXTENSION_URL,\n extension: [\n {\n url: CLAIM_WORKFLOW_STATUS_VALUE_SUB_EXTENSION_URL,\n valueCode: status,\n },\n {\n url: CLAIM_WORKFLOW_STATUS_LAST_TRANSITION_SUB_EXTENSION_URL,\n valueDateTime: lastTransition,\n },\n ],\n },\n ],\n } as Claim;\n};\n\n/**\n * Build the PaymentNotice resource for an accepted claim. Carries\n * the domain payment status on the `paymentStatus` CodeableConcept.\n * Partial payments emit a smaller `amount` than the claim total;\n * full payments mirror the total; write-offs emit a zero `amount`\n * (the contractual adjustment closes the balance to zero without\n * actual cash changing hands).\n */\nconst buildPaymentNoticeResource = (\n meta: OnSiteDemoEncounterMetadata,\n status: PaymentStatus,\n claimId: string,\n totalCharged: Money,\n insurerDisplay: string,\n): PaymentNotice => {\n const paymentId = `${meta.id}-payment`;\n const charged = totalCharged.value ?? 0;\n let paid: number;\n if (status === PAYMENT_STATUS.FULL) {\n paid = charged;\n } else if (status === PAYMENT_STATUS.PARTIAL) {\n // 40..70% of the claim total — deterministic on the encounter id.\n const fraction = 0.4 + (hashString(`${meta.id}:partial`) % 31) / 100;\n paid = +(charged * fraction).toFixed(2);\n } else {\n paid = 0;\n }\n return {\n resourceType: \"PaymentNotice\",\n id: paymentId,\n identifier: buildIdentifierPair(\n \"PaymentNotice\",\n paymentId,\n `payment-${meta.id}`,\n ),\n status: \"active\",\n request: { reference: `Claim/${claimId}`, type: \"Claim\" },\n created: meta.periodStart,\n // FHIR R4 PaymentNotice.payment is Reference(PaymentReconciliation).\n // Demo seeding does not produce PaymentReconciliation resources;\n // we point at the Claim so the reference is at least resolvable on\n // read paths. The `request` field above is the FHIR-correct link\n // from PaymentNotice back to the originating Claim.\n payment: { reference: `Claim/${claimId}`, type: \"Claim\" },\n paymentDate: meta.periodStart.slice(0, 10),\n recipient: { display: insurerDisplay },\n amount: usdMoney(paid),\n paymentStatus: {\n coding: [\n {\n system: PAYMENT_STATUS_SYSTEM,\n code: status,\n display: status,\n },\n ],\n text: status,\n },\n } as PaymentNotice;\n};\n\n/**\n * Resolve the insurer display name from a Coverage resource. The\n * primary-Coverage builder stamps the payor display on\n * `payor[0].display`; fall back to `type.text` if missing.\n */\nconst insurerDisplayForCoverage = (cov: Coverage): string => {\n const payor = cov.payor?.[0];\n if (payor && typeof payor.display === \"string\" && payor.display.length > 0) {\n return payor.display;\n }\n if (typeof cov.type?.text === \"string\" && cov.type.text.length > 0) {\n return cov.type.text;\n }\n return \"Unknown Insurer\";\n};\n\n/**\n * Materialise every Claim resource for the on-site UAT demo\n * workspace. Walks every historical encounter (#1306); skips the\n * ~15% flagged as unbilled. Returns an empty array if no\n * encounter metadata is available (intake-only deployments).\n */\nexport const buildOnSiteDemoClaims = (\n referenceIso: string,\n): ReadonlyArray<Claim> => {\n const primaryByPatient = getPrimaryCoverageByPatient();\n const out: Array<Claim> = [];\n for (const meta of onSiteDemoEncounterMetadata(referenceIso)) {\n if (isEncounterUnbilled(meta.id)) {\n continue;\n }\n const coverage = primaryByPatient.get(meta.patientId);\n if (!coverage || !coverage.id) {\n // Patient with no primary Coverage — skip. Shouldn't\n // happen in the seeded fixture but the guard keeps the\n // builder defensive.\n continue;\n }\n const status = workflowStatusForEncounter(meta.id);\n out.push(\n buildClaimResource(\n meta,\n status,\n coverage.id,\n insurerDisplayForCoverage(coverage),\n ),\n );\n }\n return out;\n};\n\n/**\n * Materialise every PaymentNotice resource for the on-site UAT\n * demo workspace. One per `accepted` Claim (no PaymentNotice on\n * submitted / rejected / reworked / resubmitted — submitted-with-\n * no-payment is the \"in flux\" subset the AC asks for).\n */\nexport const buildOnSiteDemoPaymentNotices = (\n referenceIso: string,\n): ReadonlyArray<PaymentNotice> => {\n const primaryByPatient = getPrimaryCoverageByPatient();\n const out: Array<PaymentNotice> = [];\n for (const meta of onSiteDemoEncounterMetadata(referenceIso)) {\n if (isEncounterUnbilled(meta.id)) {\n continue;\n }\n const status = workflowStatusForEncounter(meta.id);\n if (status !== CLAIM_WORKFLOW_STATUS.ACCEPTED) {\n continue;\n }\n const coverage = primaryByPatient.get(meta.patientId);\n if (!coverage || !coverage.id) {\n continue;\n }\n const paymentStatus = paymentStatusForEncounter(meta.id);\n const line = meta.hasWoundProcedure\n ? cptForProcedureEncounter(meta.id)\n : emCodeForEncounter(meta.id);\n const total = usdMoney(line.amount);\n const claimId = `${meta.id}-claim`;\n out.push(\n buildPaymentNoticeResource(\n meta,\n paymentStatus,\n claimId,\n total,\n insurerDisplayForCoverage(coverage),\n ),\n );\n }\n return out;\n};\n\n/**\n * Stable list of every Claim id seeded for the on-site UAT demo\n * workspace, anchored to `referenceIso`. Order matches the\n * underlying encounter list. Downstream tickets (#1308 — billing\n * directory, etc.) read this to fan out per-claim work.\n */\nexport const onSiteDemoClaimIds = (\n referenceIso: string,\n): ReadonlyArray<string> =>\n buildOnSiteDemoClaims(referenceIso).map((c) => c.id ?? \"\");\n\n/**\n * Stable list of every PaymentNotice id seeded for the on-site\n * UAT demo workspace, anchored to `referenceIso`.\n */\nexport const onSiteDemoPaymentNoticeIds = (\n referenceIso: string,\n): ReadonlyArray<string> =>\n buildOnSiteDemoPaymentNotices(referenceIso).map((p) => p.id ?? \"\");\n\n/**\n * Encounter ids the seeder flags as unbilled (no Claim emitted).\n * Exposed so tests and downstream tickets can assert the\n * unbilled cut without re-deriving the hash.\n */\nexport const onSiteDemoUnbilledEncounterIds = (\n referenceIso: string,\n): ReadonlyArray<string> =>\n onSiteDemoEncounterMetadata(referenceIso)\n .filter((m) => isEncounterUnbilled(m.id))\n .map((m) => m.id);\n\n/**\n * Encounter ids the seeder flags as billed (one Claim emitted per\n * id). Exposed so tests and downstream tickets can fan out per\n * billed encounter without re-deriving the hash.\n */\nexport const onSiteDemoBilledEncounterIds = (\n referenceIso: string,\n): ReadonlyArray<string> =>\n onSiteDemoEncounterMetadata(referenceIso)\n .filter((m) => !isEncounterUnbilled(m.id))\n .map((m) => m.id);\n","import type { Organization, Practitioner_Qualification } from \"@openhi/types\";\nimport {\n ON_SITE_DEMO_TENANT_ID,\n ON_SITE_DEMO_WORKSPACE_ID,\n demoScenarioIdentifier,\n openhiResourceIdentifier,\n} from \"./events\";\n\n/**\n * Hand-authored directory (\"address book\") fixtures the\n * `seed-demo-data` workflow upserts into the on-site-medical UAT\n * demo tenant ({@link ON_SITE_DEMO_TENANT_ID} +\n * {@link ON_SITE_DEMO_WORKSPACE_ID}) on every non-prod deploy\n * (issue #1308). Three categories live here:\n *\n * - **DME suppliers** — FHIR {@link Organization} resources with\n * `type[0]` carrying both the standard FHIR org-type code (`prov`)\n * and a domain category code ({@link DME_SUPPLIER_CATEGORY_CODE})\n * so the on-site directory UI can filter by category without\n * re-parsing the body. Each carries phone, email, address, and a\n * primary `contact[0]` (FHIR Organization.contact).\n * - **Insurance payors** — FHIR {@link Organization} resources with\n * `type[0]` carrying the standard FHIR `pay` (Payer) code plus a\n * payor-type sub-category (`commercial`, `medicare`,\n * `medicare-advantage`) on a second coding.\n * - **Provider per-state credentialing** — FHIR `qualification[]`\n * entries appended onto the existing on-site doctors (#1302).\n * Each carries a license identifier, a CodeableConcept code text\n * `\"Medical License\"`, a `period` (issue + expiration), an\n * `issuer.display` set to the state medical board name, and a\n * credentialing extension (state code + status). Doctors stay a\n * single FHIR Practitioner resource each — credentialing is a\n * repeating field on the existing record.\n *\n * Facilities (#1303) are NOT duplicated here — the existing\n * {@link Location} fixtures already carry the name / phone / email /\n * director-of-nursing fields the directory UI renders. The directory\n * page reads facilities from the existing Location list and reads\n * the categories below from the Organization + Practitioner pools.\n *\n * Ids are deterministic — re-fires upsert the same records, matching\n * the workflow's idempotency contract.\n */\n\nconst ON_SITE_SCENARIO = \"on-site-demo\";\n\n/**\n * FHIR `Organization.type[0].coding.system` for the standard\n * organization-type valueset. Carrying the standard coding alongside\n * the domain category keeps the bodies interoperable.\n */\nexport const FHIR_ORGANIZATION_TYPE_SYSTEM =\n \"http://terminology.hl7.org/CodeSystem/organization-type\";\n\n/**\n * On-site domain category system for directory categorisation —\n * separates `dme-supplier` from `insurance-payor` so the directory\n * UI's category filter can match a single coding without parsing\n * the FHIR-standard `prov` / `pay` codes.\n */\nexport const ON_SITE_DIRECTORY_CATEGORY_SYSTEM =\n \"https://on-site-medical.app/fhir/CodeSystem/directory-category\";\n\n/** Domain category code stamped on every DME-supplier Organization. */\nexport const DME_SUPPLIER_CATEGORY_CODE = \"dme-supplier\";\n\n/** Domain category code stamped on every insurance-payor Organization. */\nexport const INSURANCE_PAYOR_CATEGORY_CODE = \"insurance-payor\";\n\n/**\n * Sub-category coding system stamped on the payor Organization's\n * `type[1]` so the directory UI can group payors by plan family\n * (commercial / Medicare / Medicare Advantage) without re-parsing\n * the display name. Mirrors the\n * {@link COVERAGE_PAYOR_TYPE_SYSTEM} convention used on Coverage\n * resources in #1304.\n */\nexport const INSURANCE_PAYOR_PLAN_TYPE_SYSTEM =\n \"https://on-site-medical.app/fhir/CodeSystem/payor-plan-type\";\n\n/** Commercial plan payor (Aetna, Cigna, UnitedHealthcare, etc.). */\nexport const PAYOR_PLAN_TYPE_COMMERCIAL = \"commercial\";\n\n/** Traditional Medicare (FFS) — single payor. */\nexport const PAYOR_PLAN_TYPE_MEDICARE = \"medicare\";\n\n/** Medicare Advantage plan payor (Humana MA, Anthem MA, etc.). */\nexport const PAYOR_PLAN_TYPE_MEDICARE_ADVANTAGE = \"medicare-advantage\";\n\n/** Union of the three plan-type codes a payor Organization may carry. */\nexport type PayorPlanType =\n | typeof PAYOR_PLAN_TYPE_COMMERCIAL\n | typeof PAYOR_PLAN_TYPE_MEDICARE\n | typeof PAYOR_PLAN_TYPE_MEDICARE_ADVANTAGE;\n\n/**\n * Root extension URL stamped on each `qualification[]` entry recording\n * the per-state credentialing context (state code + status). FHIR R4\n * `Practitioner_Qualification` carries `identifier`, `code`, `period`,\n * and `issuer` natively but has no `status` field; the extension fills\n * that gap without forking the schema.\n */\nexport const PRACTITIONER_CREDENTIALING_EXTENSION_URL =\n \"https://on-site-medical.app/fhir/StructureDefinition/practitioner-credentialing\";\n\n/** Sub-extension under {@link PRACTITIONER_CREDENTIALING_EXTENSION_URL}. */\nexport const PRACTITIONER_CREDENTIALING_STATE_SUB_EXTENSION_URL = \"state\";\n\n/** Sub-extension under {@link PRACTITIONER_CREDENTIALING_EXTENSION_URL}. */\nexport const PRACTITIONER_CREDENTIALING_STATUS_SUB_EXTENSION_URL = \"status\";\n\n/**\n * Credentialing status values. Mirrors the wound-care industry\n * convention — credentialing is either active (license current and in\n * good standing), suspended (under board action), or expired (lapsed\n * past expiration date).\n */\nexport const CREDENTIALING_STATUS = {\n ACTIVE: \"active\",\n SUSPENDED: \"suspended\",\n EXPIRED: \"expired\",\n} as const;\nexport type CredentialingStatus =\n (typeof CREDENTIALING_STATUS)[keyof typeof CREDENTIALING_STATUS];\n\n/**\n * FHIR `Identifier.system` for a US state medical license. Uses the\n * on-site-medical URL prefix so the identifier round-trips through\n * the on-site directory UI without colliding with the NPI system.\n */\nexport const STATE_MEDICAL_LICENSE_SYSTEM =\n \"https://on-site-medical.app/fhir/sid/state-medical-license\";\n\ninterface DmeSupplierSpec {\n readonly id: string;\n readonly name: string;\n readonly phone: string;\n readonly email: string;\n readonly addressLine: string;\n readonly addressCity: string;\n readonly addressState: string;\n readonly addressPostalCode: string;\n readonly contactName: string;\n readonly contactPhone: string;\n readonly contactEmail: string;\n}\n\n/**\n * DME (Durable Medical Equipment) supplier directory entries. Names\n * are real, publicly-known DME companies — using their actual names\n * keeps the demo realistic for UAT while the phone / email / address\n * fields all point at the `on-site-demo.example.com` sentinel domain\n * so no real outreach can happen by accident. 13 entries: enough to\n * exercise the directory UI's pagination + filtering without\n * over-engineering.\n */\nconst DME_SUPPLIER_SPECS: ReadonlyArray<DmeSupplierSpec> = [\n {\n id: \"on-site-demo-dme-supplier-001\",\n name: \"Apria Healthcare\",\n phone: \"+18004554111\",\n email: \"orders@apria.on-site-demo.example.com\",\n addressLine: \"12230 El Camino Real\",\n addressCity: \"San Diego\",\n addressState: \"CA\",\n addressPostalCode: \"92130\",\n contactName: \"Marcus Whitfield\",\n contactPhone: \"+18004554112\",\n contactEmail: \"m.whitfield@apria.on-site-demo.example.com\",\n },\n {\n id: \"on-site-demo-dme-supplier-002\",\n name: \"Lincare Holdings\",\n phone: \"+17275301700\",\n email: \"intake@lincare.on-site-demo.example.com\",\n addressLine: \"19387 US Highway 19 North\",\n addressCity: \"Clearwater\",\n addressState: \"FL\",\n addressPostalCode: \"33764\",\n contactName: \"Rachel Donovan\",\n contactPhone: \"+17275301701\",\n contactEmail: \"r.donovan@lincare.on-site-demo.example.com\",\n },\n {\n id: \"on-site-demo-dme-supplier-003\",\n name: \"AdaptHealth\",\n phone: \"+16104840700\",\n email: \"referrals@adapthealth.on-site-demo.example.com\",\n addressLine: \"220 West Germantown Pike\",\n addressCity: \"Plymouth Meeting\",\n addressState: \"PA\",\n addressPostalCode: \"19462\",\n contactName: \"Brian Calloway\",\n contactPhone: \"+16104840701\",\n contactEmail: \"b.calloway@adapthealth.on-site-demo.example.com\",\n },\n {\n id: \"on-site-demo-dme-supplier-004\",\n name: \"Rotech Healthcare\",\n phone: \"+14072629230\",\n email: \"support@rotech.on-site-demo.example.com\",\n addressLine: \"3600 Vineland Road\",\n addressCity: \"Orlando\",\n addressState: \"FL\",\n addressPostalCode: \"32811\",\n contactName: \"Elena Marsh\",\n contactPhone: \"+14072629231\",\n contactEmail: \"e.marsh@rotech.on-site-demo.example.com\",\n },\n {\n id: \"on-site-demo-dme-supplier-005\",\n name: \"Byram Healthcare\",\n phone: \"+18004220606\",\n email: \"orders@byram.on-site-demo.example.com\",\n addressLine: \"120 Bloomingdale Road\",\n addressCity: \"White Plains\",\n addressState: \"NY\",\n addressPostalCode: \"10605\",\n contactName: \"Thomas Pritchard\",\n contactPhone: \"+18004220607\",\n contactEmail: \"t.pritchard@byram.on-site-demo.example.com\",\n },\n {\n id: \"on-site-demo-dme-supplier-006\",\n name: \"Medline Industries\",\n phone: \"+18476434400\",\n email: \"wound-care@medline.on-site-demo.example.com\",\n addressLine: \"Three Lakes Drive\",\n addressCity: \"Northfield\",\n addressState: \"IL\",\n addressPostalCode: \"60093\",\n contactName: \"Jacqueline Vance\",\n contactPhone: \"+18476434401\",\n contactEmail: \"j.vance@medline.on-site-demo.example.com\",\n },\n {\n id: \"on-site-demo-dme-supplier-007\",\n name: \"McKesson Medical-Surgical\",\n phone: \"+18044703300\",\n email: \"service@mckesson-ms.on-site-demo.example.com\",\n addressLine: \"9954 Mayland Drive\",\n addressCity: \"Richmond\",\n addressState: \"VA\",\n addressPostalCode: \"23233\",\n contactName: \"Andre Holloway\",\n contactPhone: \"+18044703301\",\n contactEmail: \"a.holloway@mckesson-ms.on-site-demo.example.com\",\n },\n {\n id: \"on-site-demo-dme-supplier-008\",\n name: \"Cardinal Health at-Home Solutions\",\n phone: \"+16147573030\",\n email: \"home@cardinal.on-site-demo.example.com\",\n addressLine: \"7000 Cardinal Place\",\n addressCity: \"Dublin\",\n addressState: \"OH\",\n addressPostalCode: \"43017\",\n contactName: \"Naomi Sutherland\",\n contactPhone: \"+16147573031\",\n contactEmail: \"n.sutherland@cardinal.on-site-demo.example.com\",\n },\n {\n id: \"on-site-demo-dme-supplier-009\",\n name: \"Edgepark Medical Supplies\",\n phone: \"+18003217828\",\n email: \"orders@edgepark.on-site-demo.example.com\",\n addressLine: \"1810 Summit Commerce Park\",\n addressCity: \"Twinsburg\",\n addressState: \"OH\",\n addressPostalCode: \"44087\",\n contactName: \"Derek Ashford\",\n contactPhone: \"+18003217829\",\n contactEmail: \"d.ashford@edgepark.on-site-demo.example.com\",\n },\n {\n id: \"on-site-demo-dme-supplier-010\",\n name: \"Numotion\",\n phone: \"+18006240498\",\n email: \"intake@numotion.on-site-demo.example.com\",\n addressLine: \"5117 W Terrace Drive\",\n addressCity: \"Brentwood\",\n addressState: \"TN\",\n addressPostalCode: \"37027\",\n contactName: \"Sienna Lockhart\",\n contactPhone: \"+18006240499\",\n contactEmail: \"s.lockhart@numotion.on-site-demo.example.com\",\n },\n {\n id: \"on-site-demo-dme-supplier-011\",\n name: \"Pride Mobility\",\n phone: \"+18008003636\",\n email: \"service@pridemobility.on-site-demo.example.com\",\n addressLine: \"182 Susquehanna Avenue\",\n addressCity: \"Exeter\",\n addressState: \"PA\",\n addressPostalCode: \"18643\",\n contactName: \"Vincent Marlowe\",\n contactPhone: \"+18008003637\",\n contactEmail: \"v.marlowe@pridemobility.on-site-demo.example.com\",\n },\n {\n id: \"on-site-demo-dme-supplier-012\",\n name: \"Hollister Wound Care\",\n phone: \"+18003234060\",\n email: \"wound@hollister.on-site-demo.example.com\",\n addressLine: \"2000 Hollister Drive\",\n addressCity: \"Libertyville\",\n addressState: \"IL\",\n addressPostalCode: \"60048\",\n contactName: \"Priscilla Hawthorne\",\n contactPhone: \"+18003234061\",\n contactEmail: \"p.hawthorne@hollister.on-site-demo.example.com\",\n },\n {\n id: \"on-site-demo-dme-supplier-013\",\n name: \"Smith & Nephew Advanced Wound Management\",\n phone: \"+18008765556\",\n email: \"wound@smith-nephew.on-site-demo.example.com\",\n addressLine: \"5600 Clearfork Main Street\",\n addressCity: \"Fort Worth\",\n addressState: \"TX\",\n addressPostalCode: \"76109\",\n contactName: \"Gregory Eastland\",\n contactPhone: \"+18008765557\",\n contactEmail: \"g.eastland@smith-nephew.on-site-demo.example.com\",\n },\n];\n\ninterface InsurancePayorSpec {\n readonly id: string;\n readonly name: string;\n readonly planType: PayorPlanType;\n readonly phone: string;\n readonly email: string;\n readonly addressLine: string;\n readonly addressCity: string;\n readonly addressState: string;\n readonly addressPostalCode: string;\n readonly contactName: string;\n readonly contactPhone: string;\n readonly contactEmail: string;\n}\n\n/**\n * Insurance payor directory entries. Mirrors the payor mix the\n * Coverage fixtures (#1304 / #1305) already distribute across the\n * patient pool (commercial / Medicare / Medicare Advantage). Real\n * payor names with on-site-demo.example.com sentinel domains for\n * contacts. 8 entries — enough to exercise the directory UI's filter\n * by plan type with multiple options per family.\n */\nconst INSURANCE_PAYOR_SPECS: ReadonlyArray<InsurancePayorSpec> = [\n {\n id: \"on-site-demo-insurance-payor-001\",\n name: \"Aetna\",\n planType: PAYOR_PLAN_TYPE_COMMERCIAL,\n phone: \"+18008721414\",\n email: \"provider-services@aetna.on-site-demo.example.com\",\n addressLine: \"151 Farmington Avenue\",\n addressCity: \"Hartford\",\n addressState: \"CT\",\n addressPostalCode: \"06156\",\n contactName: \"Stephanie Wakefield\",\n contactPhone: \"+18008721415\",\n contactEmail: \"s.wakefield@aetna.on-site-demo.example.com\",\n },\n {\n id: \"on-site-demo-insurance-payor-002\",\n name: \"Cigna Healthcare\",\n planType: PAYOR_PLAN_TYPE_COMMERCIAL,\n phone: \"+18002442488\",\n email: \"provider-services@cigna.on-site-demo.example.com\",\n addressLine: \"900 Cottage Grove Road\",\n addressCity: \"Bloomfield\",\n addressState: \"CT\",\n addressPostalCode: \"06002\",\n contactName: \"Howard Greenberg\",\n contactPhone: \"+18002442489\",\n contactEmail: \"h.greenberg@cigna.on-site-demo.example.com\",\n },\n {\n id: \"on-site-demo-insurance-payor-003\",\n name: \"UnitedHealthcare\",\n planType: PAYOR_PLAN_TYPE_COMMERCIAL,\n phone: \"+18778425539\",\n email: \"provider-services@uhc.on-site-demo.example.com\",\n addressLine: \"9900 Bren Road East\",\n addressCity: \"Minnetonka\",\n addressState: \"MN\",\n addressPostalCode: \"55343\",\n contactName: \"Cassandra Bellamy\",\n contactPhone: \"+18778425540\",\n contactEmail: \"c.bellamy@uhc.on-site-demo.example.com\",\n },\n {\n id: \"on-site-demo-insurance-payor-004\",\n name: \"Anthem Blue Cross Blue Shield\",\n planType: PAYOR_PLAN_TYPE_COMMERCIAL,\n phone: \"+18004504000\",\n email: \"provider-services@anthem.on-site-demo.example.com\",\n addressLine: \"220 Virginia Avenue\",\n addressCity: \"Indianapolis\",\n addressState: \"IN\",\n addressPostalCode: \"46204\",\n contactName: \"Maurice Pendleton\",\n contactPhone: \"+18004504001\",\n contactEmail: \"m.pendleton@anthem.on-site-demo.example.com\",\n },\n {\n id: \"on-site-demo-insurance-payor-005\",\n name: \"CMS — Medicare\",\n planType: PAYOR_PLAN_TYPE_MEDICARE,\n phone: \"+18006334227\",\n email: \"provider-services@cms.on-site-demo.example.com\",\n addressLine: \"7500 Security Boulevard\",\n addressCity: \"Baltimore\",\n addressState: \"MD\",\n addressPostalCode: \"21244\",\n contactName: \"Theresa Kavanagh\",\n contactPhone: \"+18006334228\",\n contactEmail: \"t.kavanagh@cms.on-site-demo.example.com\",\n },\n {\n id: \"on-site-demo-insurance-payor-006\",\n name: \"Humana Medicare Advantage\",\n planType: PAYOR_PLAN_TYPE_MEDICARE_ADVANTAGE,\n phone: \"+18004574708\",\n email: \"provider-services@humana.on-site-demo.example.com\",\n addressLine: \"500 West Main Street\",\n addressCity: \"Louisville\",\n addressState: \"KY\",\n addressPostalCode: \"40202\",\n contactName: \"Lawrence Whitmore\",\n contactPhone: \"+18004574709\",\n contactEmail: \"l.whitmore@humana.on-site-demo.example.com\",\n },\n {\n id: \"on-site-demo-insurance-payor-007\",\n name: \"Wellcare by Centene\",\n planType: PAYOR_PLAN_TYPE_MEDICARE_ADVANTAGE,\n phone: \"+18886353224\",\n email: \"provider-services@wellcare.on-site-demo.example.com\",\n addressLine: \"8735 Henderson Road\",\n addressCity: \"Tampa\",\n addressState: \"FL\",\n addressPostalCode: \"33634\",\n contactName: \"Yolanda Caldwell\",\n contactPhone: \"+18886353225\",\n contactEmail: \"y.caldwell@wellcare.on-site-demo.example.com\",\n },\n {\n id: \"on-site-demo-insurance-payor-008\",\n name: \"Kaiser Permanente\",\n planType: PAYOR_PLAN_TYPE_COMMERCIAL,\n phone: \"+18004646000\",\n email: \"provider-services@kaiser.on-site-demo.example.com\",\n addressLine: \"1 Kaiser Plaza\",\n addressCity: \"Oakland\",\n addressState: \"CA\",\n addressPostalCode: \"94612\",\n contactName: \"Bradford Tennyson\",\n contactPhone: \"+18004646001\",\n contactEmail: \"b.tennyson@kaiser.on-site-demo.example.com\",\n },\n];\n\nconst buildOrganizationIdentifierPair = (\n organizationId: string,\n roleSuffix: string,\n): Organization[\"identifier\"] => [\n demoScenarioIdentifier(ON_SITE_SCENARIO, roleSuffix),\n openhiResourceIdentifier({\n tenantId: ON_SITE_DEMO_TENANT_ID,\n workspaceId: ON_SITE_DEMO_WORKSPACE_ID,\n resourceType: \"Organization\",\n id: organizationId,\n }),\n];\n\nconst buildDmeSupplierResource = (spec: DmeSupplierSpec): Organization => ({\n resourceType: \"Organization\",\n id: spec.id,\n active: true,\n identifier: buildOrganizationIdentifierPair(\n spec.id,\n `dme-supplier-${spec.id}`,\n ),\n name: spec.name,\n type: [\n {\n coding: [\n {\n system: FHIR_ORGANIZATION_TYPE_SYSTEM,\n code: \"prov\",\n display: \"Healthcare Provider\",\n },\n {\n system: ON_SITE_DIRECTORY_CATEGORY_SYSTEM,\n code: DME_SUPPLIER_CATEGORY_CODE,\n display: \"DME Supplier\",\n },\n ],\n text: \"DME Supplier\",\n },\n ],\n telecom: [\n { system: \"phone\", value: spec.phone, use: \"work\" },\n { system: \"email\", value: spec.email, use: \"work\" },\n ],\n address: [\n {\n use: \"work\",\n line: [spec.addressLine],\n city: spec.addressCity,\n state: spec.addressState,\n postalCode: spec.addressPostalCode,\n country: \"US\",\n },\n ],\n contact: [\n {\n purpose: { text: \"Primary Contact\" },\n name: {\n text: spec.contactName,\n given: [spec.contactName.split(\" \")[0] ?? spec.contactName],\n family: spec.contactName.split(\" \").slice(-1)[0] ?? spec.contactName,\n },\n telecom: [\n { system: \"phone\", value: spec.contactPhone, use: \"work\" },\n { system: \"email\", value: spec.contactEmail, use: \"work\" },\n ],\n },\n ],\n});\n\nconst planTypeDisplayLabel = (planType: PayorPlanType): string => {\n if (planType === PAYOR_PLAN_TYPE_COMMERCIAL) {\n return \"Commercial\";\n }\n if (planType === PAYOR_PLAN_TYPE_MEDICARE) {\n return \"Medicare\";\n }\n return \"Medicare Advantage\";\n};\n\nconst buildInsurancePayorResource = (\n spec: InsurancePayorSpec,\n): Organization => ({\n resourceType: \"Organization\",\n id: spec.id,\n active: true,\n identifier: buildOrganizationIdentifierPair(\n spec.id,\n `insurance-payor-${spec.id}`,\n ),\n name: spec.name,\n type: [\n {\n coding: [\n {\n system: FHIR_ORGANIZATION_TYPE_SYSTEM,\n code: \"pay\",\n display: \"Payer\",\n },\n {\n system: ON_SITE_DIRECTORY_CATEGORY_SYSTEM,\n code: INSURANCE_PAYOR_CATEGORY_CODE,\n display: \"Insurance Payor\",\n },\n {\n system: INSURANCE_PAYOR_PLAN_TYPE_SYSTEM,\n code: spec.planType,\n display: planTypeDisplayLabel(spec.planType),\n },\n ],\n text: planTypeDisplayLabel(spec.planType),\n },\n ],\n telecom: [\n { system: \"phone\", value: spec.phone, use: \"work\" },\n { system: \"email\", value: spec.email, use: \"work\" },\n ],\n address: [\n {\n use: \"work\",\n line: [spec.addressLine],\n city: spec.addressCity,\n state: spec.addressState,\n postalCode: spec.addressPostalCode,\n country: \"US\",\n },\n ],\n contact: [\n {\n purpose: { text: \"Provider Services\" },\n name: {\n text: spec.contactName,\n given: [spec.contactName.split(\" \")[0] ?? spec.contactName],\n family: spec.contactName.split(\" \").slice(-1)[0] ?? spec.contactName,\n },\n telecom: [\n { system: \"phone\", value: spec.contactPhone, use: \"work\" },\n { system: \"email\", value: spec.contactEmail, use: \"work\" },\n ],\n },\n ],\n});\n\n/** Demo DME-supplier Organizations seeded into the on-site UAT workspace. */\nexport const ON_SITE_DEMO_DME_SUPPLIERS: ReadonlyArray<Organization> =\n DME_SUPPLIER_SPECS.map(buildDmeSupplierResource);\n\n/** Demo insurance-payor Organizations seeded into the on-site UAT workspace. */\nexport const ON_SITE_DEMO_INSURANCE_PAYORS: ReadonlyArray<Organization> =\n INSURANCE_PAYOR_SPECS.map(buildInsurancePayorResource);\n\n/** Stable DME-supplier ids in dispatch order. */\nexport const onSiteDemoDmeSupplierIds = (): ReadonlyArray<string> =>\n DME_SUPPLIER_SPECS.map((s) => s.id);\n\n/** Stable insurance-payor ids in dispatch order. */\nexport const onSiteDemoInsurancePayorIds = (): ReadonlyArray<string> =>\n INSURANCE_PAYOR_SPECS.map((s) => s.id);\n\n/**\n * The full directory Organization pool seeded into the on-site UAT\n * workspace — DME suppliers followed by insurance payors. The seeder\n * walks this in order via `buildOrganizations`.\n */\nexport const ON_SITE_DEMO_DIRECTORY_ORGANIZATIONS: ReadonlyArray<Organization> =\n [...ON_SITE_DEMO_DME_SUPPLIERS, ...ON_SITE_DEMO_INSURANCE_PAYORS];\n\n/**\n * Per-state credentialing spec for one license. The doctor specs in\n * `on-site-demo-fixtures.ts` carry a small array of these and the\n * build helper below converts each into a FHIR\n * `Practitioner_Qualification` entry appended after the \"Physician\"\n * qualification.\n */\nexport interface PractitionerCredentialingSpec {\n /** Two-letter USPS state code (GA, AL, TN, …). */\n readonly state: string;\n /** State medical board display label used for `issuer.display`. */\n readonly stateBoardDisplay: string;\n /** Opaque license number (real format varies by state). */\n readonly licenseNumber: string;\n /** ISO date the license was issued. */\n readonly issued: string;\n /** ISO date the license expires (after-end-of-period if expired). */\n readonly expires: string;\n readonly status: CredentialingStatus;\n}\n\n/**\n * Per-doctor map of state-licensure entries. Each on-site doctor has\n * a primary license in Georgia plus 0-2 neighbouring-state licenses,\n * mirroring the regional wound-care practice pattern (a wound-care\n * provider commonly carries credentials in 2-3 adjacent states).\n * Three doctors carry a non-`active` license to give the on-site UI\n * a credentialing-status badge variety:\n * - doctor-007's Florida license is `suspended`\n * - doctor-009's Tennessee license is `expired`\n * - doctor-010 has only one license (Georgia) — illustrates a\n * single-state credentialing case\n */\nconst PRACTITIONER_CREDENTIALING_BY_DOCTOR: Readonly<\n Record<string, ReadonlyArray<PractitionerCredentialingSpec>>\n> = {\n \"on-site-demo-doctor-001\": [\n {\n state: \"GA\",\n stateBoardDisplay: \"Georgia Composite Medical Board\",\n licenseNumber: \"GA-MD-082431\",\n issued: \"2014-06-12\",\n expires: \"2027-06-30\",\n status: CREDENTIALING_STATUS.ACTIVE,\n },\n {\n state: \"AL\",\n stateBoardDisplay: \"Alabama Board of Medical Examiners\",\n licenseNumber: \"AL-MD-MD031298\",\n issued: \"2016-04-02\",\n expires: \"2026-12-31\",\n status: CREDENTIALING_STATUS.ACTIVE,\n },\n {\n state: \"TN\",\n stateBoardDisplay: \"Tennessee Board of Medical Examiners\",\n licenseNumber: \"TN-MD-MD51227\",\n issued: \"2017-09-21\",\n expires: \"2026-09-30\",\n status: CREDENTIALING_STATUS.ACTIVE,\n },\n ],\n \"on-site-demo-doctor-002\": [\n {\n state: \"GA\",\n stateBoardDisplay: \"Georgia Composite Medical Board\",\n licenseNumber: \"GA-MD-076120\",\n issued: \"2012-08-04\",\n expires: \"2027-08-31\",\n status: CREDENTIALING_STATUS.ACTIVE,\n },\n {\n state: \"FL\",\n stateBoardDisplay: \"Florida Board of Medicine\",\n licenseNumber: \"FL-MD-ME128443\",\n issued: \"2018-02-18\",\n expires: \"2026-02-28\",\n status: CREDENTIALING_STATUS.ACTIVE,\n },\n ],\n \"on-site-demo-doctor-003\": [\n {\n state: \"GA\",\n stateBoardDisplay: \"Georgia Composite Medical Board\",\n licenseNumber: \"GA-MD-091047\",\n issued: \"2015-11-22\",\n expires: \"2027-11-30\",\n status: CREDENTIALING_STATUS.ACTIVE,\n },\n {\n state: \"SC\",\n stateBoardDisplay: \"South Carolina Board of Medical Examiners\",\n licenseNumber: \"SC-MD-32788\",\n issued: \"2019-05-10\",\n expires: \"2027-05-31\",\n status: CREDENTIALING_STATUS.ACTIVE,\n },\n ],\n \"on-site-demo-doctor-004\": [\n {\n state: \"GA\",\n stateBoardDisplay: \"Georgia Composite Medical Board\",\n licenseNumber: \"GA-MD-064118\",\n issued: \"2009-07-14\",\n expires: \"2027-07-31\",\n status: CREDENTIALING_STATUS.ACTIVE,\n },\n {\n state: \"NC\",\n stateBoardDisplay: \"North Carolina Medical Board\",\n licenseNumber: \"NC-MD-2014-00892\",\n issued: \"2014-03-08\",\n expires: \"2027-03-31\",\n status: CREDENTIALING_STATUS.ACTIVE,\n },\n ],\n \"on-site-demo-doctor-005\": [\n {\n state: \"GA\",\n stateBoardDisplay: \"Georgia Composite Medical Board\",\n licenseNumber: \"GA-MD-098712\",\n issued: \"2017-01-19\",\n expires: \"2027-01-31\",\n status: CREDENTIALING_STATUS.ACTIVE,\n },\n {\n state: \"AL\",\n stateBoardDisplay: \"Alabama Board of Medical Examiners\",\n licenseNumber: \"AL-MD-MD040115\",\n issued: \"2020-06-30\",\n expires: \"2026-06-30\",\n status: CREDENTIALING_STATUS.ACTIVE,\n },\n ],\n \"on-site-demo-doctor-006\": [\n {\n state: \"GA\",\n stateBoardDisplay: \"Georgia Composite Medical Board\",\n licenseNumber: \"GA-MD-052901\",\n issued: \"2004-09-02\",\n expires: \"2027-09-30\",\n status: CREDENTIALING_STATUS.ACTIVE,\n },\n {\n state: \"TN\",\n stateBoardDisplay: \"Tennessee Board of Medical Examiners\",\n licenseNumber: \"TN-MD-MD43091\",\n issued: \"2011-05-15\",\n expires: \"2027-05-31\",\n status: CREDENTIALING_STATUS.ACTIVE,\n },\n ],\n \"on-site-demo-doctor-007\": [\n {\n state: \"GA\",\n stateBoardDisplay: \"Georgia Composite Medical Board\",\n licenseNumber: \"GA-MD-073445\",\n issued: \"2013-04-27\",\n expires: \"2027-04-30\",\n status: CREDENTIALING_STATUS.ACTIVE,\n },\n {\n state: \"FL\",\n stateBoardDisplay: \"Florida Board of Medicine\",\n licenseNumber: \"FL-MD-ME119001\",\n issued: \"2015-12-12\",\n expires: \"2026-12-31\",\n status: CREDENTIALING_STATUS.SUSPENDED,\n },\n ],\n \"on-site-demo-doctor-008\": [\n {\n state: \"GA\",\n stateBoardDisplay: \"Georgia Composite Medical Board\",\n licenseNumber: \"GA-MD-101203\",\n issued: \"2018-08-09\",\n expires: \"2027-08-31\",\n status: CREDENTIALING_STATUS.ACTIVE,\n },\n {\n state: \"SC\",\n stateBoardDisplay: \"South Carolina Board of Medical Examiners\",\n licenseNumber: \"SC-MD-35112\",\n issued: \"2021-02-01\",\n expires: \"2027-02-28\",\n status: CREDENTIALING_STATUS.ACTIVE,\n },\n ],\n \"on-site-demo-doctor-009\": [\n {\n state: \"GA\",\n stateBoardDisplay: \"Georgia Composite Medical Board\",\n licenseNumber: \"GA-MD-061887\",\n issued: \"2010-11-30\",\n expires: \"2026-11-30\",\n status: CREDENTIALING_STATUS.ACTIVE,\n },\n {\n state: \"TN\",\n stateBoardDisplay: \"Tennessee Board of Medical Examiners\",\n licenseNumber: \"TN-MD-MD38712\",\n issued: \"2012-06-04\",\n expires: \"2024-06-30\",\n status: CREDENTIALING_STATUS.EXPIRED,\n },\n ],\n \"on-site-demo-doctor-010\": [\n {\n state: \"GA\",\n stateBoardDisplay: \"Georgia Composite Medical Board\",\n licenseNumber: \"GA-MD-108901\",\n issued: \"2020-03-15\",\n expires: \"2027-03-31\",\n status: CREDENTIALING_STATUS.ACTIVE,\n },\n ],\n};\n\n/**\n * Lookup helper: per-state credentialing entries for one doctor. Returns\n * an empty array if the practitioner id is not a seeded on-site doctor.\n */\nexport const practitionerCredentialingForDoctor = (\n practitionerId: string,\n): ReadonlyArray<PractitionerCredentialingSpec> =>\n PRACTITIONER_CREDENTIALING_BY_DOCTOR[practitionerId] ?? [];\n\n/**\n * Lookup helper: per-state credentialing entry for a specific\n * (practitionerId, stateCode) pair. Returns `undefined` when the pair\n * has no credentialing entry — the on-site UI can render this as\n * \"not credentialed in <state>\" without inspecting the full list.\n */\nexport const practitionerCredentialingForState = (\n practitionerId: string,\n stateCode: string,\n): PractitionerCredentialingSpec | undefined =>\n practitionerCredentialingForDoctor(practitionerId).find(\n (entry) => entry.state === stateCode,\n );\n\n/**\n * Build the FHIR `qualification[]` entries representing per-state\n * credentialing for one doctor. The on-site demo doctor builder\n * appends these after the base \"Physician\" qualification so the\n * resulting Practitioner.qualification array carries:\n * - [0] role label (`{text: \"Physician\"}`)\n * - [1..N] per-state licenses (one entry per state in the\n * credentialing map for this doctor)\n *\n * Each license entry's identifier is keyed under\n * {@link STATE_MEDICAL_LICENSE_SYSTEM} so the on-site UI can pluck the\n * license number without parsing the issuer display.\n */\nexport const buildCredentialingQualifications = (\n practitionerId: string,\n): ReadonlyArray<Practitioner_Qualification> =>\n practitionerCredentialingForDoctor(practitionerId).map((cred) => ({\n identifier: [\n {\n system: STATE_MEDICAL_LICENSE_SYSTEM,\n value: cred.licenseNumber,\n },\n ],\n code: {\n text: \"Medical License\",\n },\n period: {\n start: cred.issued,\n end: cred.expires,\n },\n issuer: {\n display: cred.stateBoardDisplay,\n },\n extension: [\n {\n url: PRACTITIONER_CREDENTIALING_EXTENSION_URL,\n extension: [\n {\n url: PRACTITIONER_CREDENTIALING_STATE_SUB_EXTENSION_URL,\n valueCode: cred.state,\n },\n {\n url: PRACTITIONER_CREDENTIALING_STATUS_SUB_EXTENSION_URL,\n valueCode: cred.status,\n },\n ],\n },\n ],\n }));\n","import type { Practitioner } from \"@openhi/types\";\nimport type { DemoWorkspaceDataPlaneFixtures } from \"./data-plane-fixtures\";\nimport {\n ON_SITE_DEMO_TENANT_ID,\n ON_SITE_DEMO_WORKSPACE_ID,\n demoScenarioIdentifier,\n openhiResourceIdentifier,\n} from \"./events\";\nimport { buildOnSiteDemoBlockAppointments } from \"./on-site-demo-blocks\";\nimport {\n buildOnSiteDemoClaims,\n buildOnSiteDemoPaymentNotices,\n} from \"./on-site-demo-claims\";\nimport {\n ON_SITE_DEMO_DIRECTORY_ORGANIZATIONS,\n buildCredentialingQualifications,\n} from \"./on-site-demo-directory\";\nimport {\n buildOnSiteDemoEncounters,\n buildOnSiteDemoWoundConditions,\n buildOnSiteDemoWoundObservations,\n buildOnSiteDemoWoundProcedures,\n} from \"./on-site-demo-encounters\";\nimport { ON_SITE_DEMO_FACILITIES } from \"./on-site-demo-facilities\";\nimport {\n buildOnSiteDemoFacilityCoverages,\n buildOnSiteDemoFacilityPatients,\n} from \"./on-site-demo-facility-patients\";\nimport {\n buildOnSiteDemoHomeHealthCoverages,\n buildOnSiteDemoHomeHealthPatients,\n} from \"./on-site-demo-home-health-patients\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/constructs/workflows/control-plane/seed-demo-data/on-site-demo-fixtures.md\n *\n * Hand-authored Practitioner fixtures the `seed-demo-data` workflow\n * upserts into the on-site-medical UAT demo tenant\n * ({@link ON_SITE_DEMO_TENANT_ID} + {@link ON_SITE_DEMO_WORKSPACE_ID})\n * on every non-prod deploy. Issue #1302 — the on-site repo's facility\n * blocks, home-health visits, and encounter records need a realistic\n * pool of doctors and scribes to reference.\n *\n * Two sets are seeded:\n * - {@link ON_SITE_DEMO_DOCTORS} — ten Practitioners with\n * `qualification[0].code.text = \"Physician\"`. The first five carry\n * a `home-health-eligible` boolean extension set to `true` so the\n * on-site UI can filter the home-health-eligible subset for\n * home-visit scheduling.\n * - {@link ON_SITE_DEMO_SCRIBES} — five Practitioners with\n * `qualification[0].code.text = \"Scribe\"`. Scribes share the\n * Practitioner resource shape with doctors so the on-site\n * practitioner CRUD form can edit both without a new resource\n * type; the `qualification` value distinguishes the role.\n *\n * Field set matches what the on-site provider form expects today\n * (`sites/app-ehr/src/pages/admin/AdminPractitionerFormPage.tsx`):\n * - `name[0]` — given + family + text\n * - `qualification[0].code.text` — role label\n * - `active`\n * - `gender`, `birthDate`\n * - `telecom[]` — phone (E.164) + email\n * - `identifier[0]` — NPI (US national provider identifier)\n * - `address[0]` — line / city / state / postalCode / country\n * - `extension[]` — home-health-eligible boolean (doctors only)\n *\n * Ids are deterministic — re-fires upsert the same records, matching\n * the workflow's idempotency contract. Adding or renaming a Practitioner\n * is a one-line edit here plus a redeploy.\n */\n\n/** FHIR `Identifier.system` for the US NPI (National Provider Identifier). */\nexport const US_NPI_SYSTEM = \"http://hl7.org/fhir/sid/us-npi\";\n\n/**\n * Extension URL stamped on a Practitioner body when the practitioner\n * is approved to take home-health visits. Mirrors the on-site repo's\n * convention (`https://on-site-medical.app/fhir/StructureDefinition/*`)\n * — the on-site UI can pick this extension up directly without a\n * schema change. Boolean `valueBoolean: true` means eligible.\n */\nexport const HOME_HEALTH_ELIGIBLE_EXTENSION_URL =\n \"https://on-site-medical.app/fhir/StructureDefinition/home-health-eligible\";\n\n/** Practitioner.qualification code-text for a physician (matches on-site form). */\nexport const PRACTITIONER_ROLE_PHYSICIAN = \"Physician\";\n\n/** Practitioner.qualification code-text for a scribe. */\nexport const PRACTITIONER_ROLE_SCRIBE = \"Scribe\";\n\n/**\n * Single source of doctor descriptors. The build helper expands each\n * entry into a fully-shaped Practitioner resource with stable id +\n * identifiers + extension when applicable.\n */\ninterface DoctorSpec {\n readonly id: string;\n readonly firstName: string;\n readonly lastName: string;\n readonly suffix?: string;\n readonly gender: \"male\" | \"female\";\n readonly birthDate: string;\n readonly phone: string;\n readonly email: string;\n readonly npi: string;\n readonly addressLine: string;\n readonly addressCity: string;\n readonly addressState: string;\n readonly addressPostalCode: string;\n /** Whether this doctor is approved for home-health visits. */\n readonly homeHealthEligible: boolean;\n}\n\ninterface ScribeSpec {\n readonly id: string;\n readonly firstName: string;\n readonly lastName: string;\n readonly gender: \"male\" | \"female\";\n readonly birthDate: string;\n readonly phone: string;\n readonly email: string;\n /**\n * Scribes typically do not carry an NPI (they are not licensed\n * billable providers). The seeded scribes use the on-site internal\n * staff-id system instead of an NPI so the identifier field is\n * still populated for the on-site UI's identifier column.\n */\n readonly staffId: string;\n readonly addressLine: string;\n readonly addressCity: string;\n readonly addressState: string;\n readonly addressPostalCode: string;\n}\n\n/** FHIR `Identifier.system` for internal on-site staff ids (non-NPI). */\nexport const ON_SITE_STAFF_ID_SYSTEM =\n \"https://on-site-medical.app/fhir/sid/staff-id\";\n\n/**\n * Ten demo doctors. Names mirror the real-team-last-name convention\n * established in commits 68610281 / 1d2eceae — common American given\n * and family names, no fictional or sci-fi names. The first five\n * carry `homeHealthEligible: true`; the remaining five are\n * facility-only.\n */\nconst DOCTOR_SPECS: ReadonlyArray<DoctorSpec> = [\n {\n id: \"on-site-demo-doctor-001\",\n firstName: \"Sarah\",\n lastName: \"Patel\",\n suffix: \"MD\",\n gender: \"female\",\n birthDate: \"1978-03-14\",\n phone: \"+14045550101\",\n email: \"sarah.patel@on-site-demo.example.com\",\n npi: \"1003000001\",\n addressLine: \"120 Peachtree Street NE\",\n addressCity: \"Atlanta\",\n addressState: \"GA\",\n addressPostalCode: \"30303\",\n homeHealthEligible: true,\n },\n {\n id: \"on-site-demo-doctor-002\",\n firstName: \"Michael\",\n lastName: \"Brennan\",\n suffix: \"DO\",\n gender: \"male\",\n birthDate: \"1972-08-22\",\n phone: \"+14045550102\",\n email: \"michael.brennan@on-site-demo.example.com\",\n npi: \"1003000002\",\n addressLine: \"300 Ponce de Leon Avenue\",\n addressCity: \"Atlanta\",\n addressState: \"GA\",\n addressPostalCode: \"30308\",\n homeHealthEligible: true,\n },\n {\n id: \"on-site-demo-doctor-003\",\n firstName: \"Linda\",\n lastName: \"Nguyen\",\n suffix: \"MD\",\n gender: \"female\",\n birthDate: \"1981-11-05\",\n phone: \"+14045550103\",\n email: \"linda.nguyen@on-site-demo.example.com\",\n npi: \"1003000003\",\n addressLine: \"75 Piedmont Avenue\",\n addressCity: \"Atlanta\",\n addressState: \"GA\",\n addressPostalCode: \"30303\",\n homeHealthEligible: true,\n },\n {\n id: \"on-site-demo-doctor-004\",\n firstName: \"James\",\n lastName: \"Ortiz\",\n suffix: \"MD\",\n gender: \"male\",\n birthDate: \"1969-04-30\",\n phone: \"+14045550104\",\n email: \"james.ortiz@on-site-demo.example.com\",\n npi: \"1003000004\",\n addressLine: \"1825 Howell Mill Road\",\n addressCity: \"Atlanta\",\n addressState: \"GA\",\n addressPostalCode: \"30318\",\n homeHealthEligible: true,\n },\n {\n id: \"on-site-demo-doctor-005\",\n firstName: \"Olivia\",\n lastName: \"Carter\",\n suffix: \"MD\",\n gender: \"female\",\n birthDate: \"1985-07-19\",\n phone: \"+14045550105\",\n email: \"olivia.carter@on-site-demo.example.com\",\n npi: \"1003000005\",\n addressLine: \"999 Peachtree Street NE\",\n addressCity: \"Atlanta\",\n addressState: \"GA\",\n addressPostalCode: \"30309\",\n homeHealthEligible: true,\n },\n {\n id: \"on-site-demo-doctor-006\",\n firstName: \"David\",\n lastName: \"Sullivan\",\n suffix: \"MD\",\n gender: \"male\",\n birthDate: \"1965-12-02\",\n phone: \"+14045550106\",\n email: \"david.sullivan@on-site-demo.example.com\",\n npi: \"1003000006\",\n addressLine: \"550 Pharr Road\",\n addressCity: \"Atlanta\",\n addressState: \"GA\",\n addressPostalCode: \"30305\",\n homeHealthEligible: false,\n },\n {\n id: \"on-site-demo-doctor-007\",\n firstName: \"Maria\",\n lastName: \"Hernandez\",\n suffix: \"MD\",\n gender: \"female\",\n birthDate: \"1976-06-11\",\n phone: \"+14045550107\",\n email: \"maria.hernandez@on-site-demo.example.com\",\n npi: \"1003000007\",\n addressLine: \"2200 Northside Drive NW\",\n addressCity: \"Atlanta\",\n addressState: \"GA\",\n addressPostalCode: \"30318\",\n homeHealthEligible: false,\n },\n {\n id: \"on-site-demo-doctor-008\",\n firstName: \"Robert\",\n lastName: \"Kim\",\n suffix: \"DO\",\n gender: \"male\",\n birthDate: \"1983-02-27\",\n phone: \"+14045550108\",\n email: \"robert.kim@on-site-demo.example.com\",\n npi: \"1003000008\",\n addressLine: \"400 West Peachtree Street\",\n addressCity: \"Atlanta\",\n addressState: \"GA\",\n addressPostalCode: \"30308\",\n homeHealthEligible: false,\n },\n {\n id: \"on-site-demo-doctor-009\",\n firstName: \"Jennifer\",\n lastName: \"Williams\",\n suffix: \"MD\",\n gender: \"female\",\n birthDate: \"1970-10-16\",\n phone: \"+14045550109\",\n email: \"jennifer.williams@on-site-demo.example.com\",\n npi: \"1003000009\",\n addressLine: \"1364 Clifton Road NE\",\n addressCity: \"Atlanta\",\n addressState: \"GA\",\n addressPostalCode: \"30322\",\n homeHealthEligible: false,\n },\n {\n id: \"on-site-demo-doctor-010\",\n firstName: \"Thomas\",\n lastName: \"Anderson\",\n suffix: \"MD\",\n gender: \"male\",\n birthDate: \"1988-09-08\",\n phone: \"+14045550110\",\n email: \"thomas.anderson@on-site-demo.example.com\",\n npi: \"1003000010\",\n addressLine: \"1900 The Exchange SE\",\n addressCity: \"Atlanta\",\n addressState: \"GA\",\n addressPostalCode: \"30339\",\n homeHealthEligible: false,\n },\n];\n\n/**\n * Five demo scribes. Scribes assist providers with documentation;\n * they do not bill independently and therefore do not carry an NPI.\n * Each scribe gets an internal on-site staff id so the on-site UI's\n * identifier column is populated.\n */\nconst SCRIBE_SPECS: ReadonlyArray<ScribeSpec> = [\n {\n id: \"on-site-demo-scribe-001\",\n firstName: \"Emily\",\n lastName: \"Reed\",\n gender: \"female\",\n birthDate: \"1995-01-23\",\n phone: \"+14045550201\",\n email: \"emily.reed@on-site-demo.example.com\",\n staffId: \"SCR-0001\",\n addressLine: \"240 Edgewood Avenue SE\",\n addressCity: \"Atlanta\",\n addressState: \"GA\",\n addressPostalCode: \"30303\",\n },\n {\n id: \"on-site-demo-scribe-002\",\n firstName: \"Daniel\",\n lastName: \"Foster\",\n gender: \"male\",\n birthDate: \"1993-05-17\",\n phone: \"+14045550202\",\n email: \"daniel.foster@on-site-demo.example.com\",\n staffId: \"SCR-0002\",\n addressLine: \"780 Boulevard SE\",\n addressCity: \"Atlanta\",\n addressState: \"GA\",\n addressPostalCode: \"30312\",\n },\n {\n id: \"on-site-demo-scribe-003\",\n firstName: \"Ashley\",\n lastName: \"Garrett\",\n gender: \"female\",\n birthDate: \"1997-11-29\",\n phone: \"+14045550203\",\n email: \"ashley.garrett@on-site-demo.example.com\",\n staffId: \"SCR-0003\",\n addressLine: \"55 Allen Plaza\",\n addressCity: \"Atlanta\",\n addressState: \"GA\",\n addressPostalCode: \"30308\",\n },\n {\n id: \"on-site-demo-scribe-004\",\n firstName: \"Brandon\",\n lastName: \"Murray\",\n gender: \"male\",\n birthDate: \"1991-07-04\",\n phone: \"+14045550204\",\n email: \"brandon.murray@on-site-demo.example.com\",\n staffId: \"SCR-0004\",\n addressLine: \"1100 Spring Street NW\",\n addressCity: \"Atlanta\",\n addressState: \"GA\",\n addressPostalCode: \"30309\",\n },\n {\n id: \"on-site-demo-scribe-005\",\n firstName: \"Sofia\",\n lastName: \"Bennett\",\n gender: \"female\",\n birthDate: \"1999-03-12\",\n phone: \"+14045550205\",\n email: \"sofia.bennett@on-site-demo.example.com\",\n staffId: \"SCR-0005\",\n addressLine: \"165 Courtland Street NE\",\n addressCity: \"Atlanta\",\n addressState: \"GA\",\n addressPostalCode: \"30303\",\n },\n];\n\nconst ON_SITE_SCENARIO = \"on-site-demo\";\n\n/** Build the shared identifier pair (demo-URN + canonical OHI URN). */\nconst buildIdentifierPair = (\n practitionerId: string,\n roleSuffix: string,\n): Practitioner[\"identifier\"] => [\n demoScenarioIdentifier(ON_SITE_SCENARIO, roleSuffix),\n openhiResourceIdentifier({\n tenantId: ON_SITE_DEMO_TENANT_ID,\n workspaceId: ON_SITE_DEMO_WORKSPACE_ID,\n resourceType: \"Practitioner\",\n id: practitionerId,\n }),\n];\n\nconst buildDoctorResource = (spec: DoctorSpec): Practitioner => {\n const fullText = `${spec.firstName} ${spec.lastName}${spec.suffix ? `, ${spec.suffix}` : \"\"}`;\n const baseIdentifiers = buildIdentifierPair(\n spec.id,\n `practitioner-${spec.id}`,\n );\n return {\n resourceType: \"Practitioner\",\n id: spec.id,\n active: true,\n identifier: [\n ...(baseIdentifiers ?? []),\n {\n system: US_NPI_SYSTEM,\n value: spec.npi,\n },\n ],\n name: [\n {\n use: \"official\",\n text: fullText,\n given: [spec.firstName],\n family: spec.lastName,\n prefix: [\"Dr.\"],\n ...(spec.suffix ? { suffix: [spec.suffix] } : {}),\n },\n ],\n gender: spec.gender,\n birthDate: spec.birthDate,\n telecom: [\n { system: \"phone\", value: spec.phone, use: \"work\" },\n { system: \"email\", value: spec.email, use: \"work\" },\n ],\n address: [\n {\n use: \"work\",\n line: [spec.addressLine],\n city: spec.addressCity,\n state: spec.addressState,\n postalCode: spec.addressPostalCode,\n country: \"US\",\n },\n ],\n qualification: [\n {\n code: {\n text: PRACTITIONER_ROLE_PHYSICIAN,\n },\n },\n // Per-state credentialing entries appended after the role\n // label (#1308). Each on-site doctor carries 1-3 state\n // licenses with status / period / issuer fields populated\n // for the directory UI's credentialing column.\n ...buildCredentialingQualifications(spec.id),\n ],\n ...(spec.homeHealthEligible\n ? {\n extension: [\n {\n url: HOME_HEALTH_ELIGIBLE_EXTENSION_URL,\n valueBoolean: true,\n },\n ],\n }\n : {}),\n };\n};\n\nconst buildScribeResource = (spec: ScribeSpec): Practitioner => {\n const fullText = `${spec.firstName} ${spec.lastName}`;\n const baseIdentifiers = buildIdentifierPair(\n spec.id,\n `practitioner-${spec.id}`,\n );\n return {\n resourceType: \"Practitioner\",\n id: spec.id,\n active: true,\n identifier: [\n ...(baseIdentifiers ?? []),\n {\n system: ON_SITE_STAFF_ID_SYSTEM,\n value: spec.staffId,\n },\n ],\n name: [\n {\n use: \"official\",\n text: fullText,\n given: [spec.firstName],\n family: spec.lastName,\n },\n ],\n gender: spec.gender,\n birthDate: spec.birthDate,\n telecom: [\n { system: \"phone\", value: spec.phone, use: \"work\" },\n { system: \"email\", value: spec.email, use: \"work\" },\n ],\n address: [\n {\n use: \"work\",\n line: [spec.addressLine],\n city: spec.addressCity,\n state: spec.addressState,\n postalCode: spec.addressPostalCode,\n country: \"US\",\n },\n ],\n qualification: [\n {\n code: {\n text: PRACTITIONER_ROLE_SCRIBE,\n },\n },\n ],\n };\n};\n\n/** Demo doctors seeded into the on-site UAT demo workspace. */\nexport const ON_SITE_DEMO_DOCTORS: ReadonlyArray<Practitioner> =\n DOCTOR_SPECS.map(buildDoctorResource);\n\n/** Demo scribes seeded into the on-site UAT demo workspace. */\nexport const ON_SITE_DEMO_SCRIBES: ReadonlyArray<Practitioner> =\n SCRIBE_SPECS.map(buildScribeResource);\n\n/** Stable doctor ids in dispatch order. Re-exported for downstream tickets. */\nexport const ON_SITE_DEMO_DOCTOR_IDS: ReadonlyArray<string> = DOCTOR_SPECS.map(\n (d) => d.id,\n);\n\n/** Stable scribe ids in dispatch order. Re-exported for downstream tickets. */\nexport const ON_SITE_DEMO_SCRIBE_IDS: ReadonlyArray<string> = SCRIBE_SPECS.map(\n (s) => s.id,\n);\n\n/**\n * Subset of {@link ON_SITE_DEMO_DOCTORS} flagged as home-health-eligible\n * (via the {@link HOME_HEALTH_ELIGIBLE_EXTENSION_URL} extension on the\n * Practitioner body). Downstream tickets (home-health visit scheduling,\n * facility-block fixtures) use this helper to attach realistic providers\n * to home-visit-only encounters without re-reading the extension list.\n */\nexport const homeHealthEligibleDoctors = (): ReadonlyArray<Practitioner> =>\n ON_SITE_DEMO_DOCTORS.filter((p) =>\n (p.extension ?? []).some(\n (ext) =>\n ext.url === HOME_HEALTH_ELIGIBLE_EXTENSION_URL &&\n ext.valueBoolean === true,\n ),\n );\n\n/**\n * Fixture group the seeder writes into the on-site UAT demo workspace.\n * Carries practitioners (doctors + scribes — #1302), facilities\n * (#1303), recurring weekly block Appointments (#1303), facility\n * patients + their insurance Coverages (#1304), home-health\n * patients + their insurance Coverages (#1305), historical\n * encounters / wounds / wound observations / wound debridement\n * procedures (#1306), and claims + payment notices tied to those\n * encounters (#1307). Accounts for this tenant are owned by later\n * tickets.\n *\n * `buildAppointments` is dynamic so the recurring block occurrences\n * anchor to the ISO week containing the seeder's `baseContext.date`\n * — re-fires on the same date produce byte-identical Appointment ids,\n * and re-fires on a later date roll the window forward without\n * duplicating prior weeks' records.\n */\nexport const ON_SITE_DEMO_FIXTURES: DemoWorkspaceDataPlaneFixtures = {\n tenantId: ON_SITE_DEMO_TENANT_ID,\n workspaceId: ON_SITE_DEMO_WORKSPACE_ID,\n scenario: ON_SITE_SCENARIO,\n // Patients + Coverages are materialised lazily via the\n // `buildPatients` / `buildCoverages` hooks below. Module-level\n // arrays would force a TDZ on the cross-module imports between\n // `on-site-demo-fixtures.ts`, `on-site-demo-blocks.ts`, and\n // `on-site-demo-facility-patients.ts`.\n patients: [],\n practitioners: [...ON_SITE_DEMO_DOCTORS, ...ON_SITE_DEMO_SCRIBES],\n observations: [],\n encounters: [],\n accounts: [],\n locations: [...ON_SITE_DEMO_FACILITIES],\n organizations: [...ON_SITE_DEMO_DIRECTORY_ORGANIZATIONS],\n buildPatients: () => [\n ...buildOnSiteDemoFacilityPatients(),\n ...buildOnSiteDemoHomeHealthPatients(),\n ],\n buildCoverages: () => [\n ...buildOnSiteDemoFacilityCoverages(),\n ...buildOnSiteDemoHomeHealthCoverages(),\n ],\n buildAppointments: (baseContext) =>\n buildOnSiteDemoBlockAppointments(\n baseContext.date ?? new Date().toISOString(),\n ),\n buildConditions: (baseContext) =>\n buildOnSiteDemoWoundConditions(\n baseContext.date ?? new Date().toISOString(),\n ),\n buildEncounters: (baseContext) =>\n buildOnSiteDemoEncounters(baseContext.date ?? new Date().toISOString()),\n buildObservations: (baseContext) =>\n buildOnSiteDemoWoundObservations(\n baseContext.date ?? new Date().toISOString(),\n ),\n buildProcedures: (baseContext) =>\n buildOnSiteDemoWoundProcedures(\n baseContext.date ?? new Date().toISOString(),\n ),\n buildClaims: (baseContext) =>\n buildOnSiteDemoClaims(baseContext.date ?? new Date().toISOString()),\n buildPaymentNotices: (baseContext) =>\n buildOnSiteDemoPaymentNotices(baseContext.date ?? new Date().toISOString()),\n};\n","import type {\n Account,\n Appointment,\n Claim,\n Condition,\n Coverage,\n Encounter,\n Location,\n Observation,\n Organization,\n Patient,\n PaymentNotice,\n Practitioner,\n Procedure,\n} from \"@openhi/types\";\nimport {\n DEMO_TENANT_SPECS,\n PLACEHOLDER_TENANT_ID,\n demoScenarioIdentifier,\n openhiResourceIdentifier,\n} from \"./events\";\nimport { ON_SITE_DEMO_FIXTURES } from \"./on-site-demo-fixtures\";\nimport type { OpenHiContext } from \"../../../data/openhi-context\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/constructs/workflows/control-plane/seed-demo-data/data-plane-fixtures.md\n *\n * Hand-authored FHIR data-plane fixture bodies the `seed-demo-data`\n * workflow upserts into the data store on every non-prod deploy.\n * Mirrors the OPS-009 v1 resource set: Patient, Practitioner,\n * Observation, Encounter, Account.\n *\n * Ids are deterministic — re-fires of the workflow upsert the same\n * records, satisfying the workflow's idempotency contract (no\n * duplicates) and letting the IAM grant in `seed-demo-data-lambda.ts`\n * enumerate exact-match `dynamodb:LeadingKeys` rather than a wildcard.\n *\n * The placeholder tenant carries no data-plane fixtures — only the\n * three real demo tenants (wound-care, primary-care, mixed) get\n * Patient/Practitioner/Observation/Encounter/Account records. The\n * placeholder tenant exists solely as a routing target for the\n * Cognito pre-token-generation fallback and never holds clinical\n * data.\n */\n\n/**\n * Logical group of FHIR resources owned by a single (tenant, workspace)\n * pair. The workflow walks `DEMO_DATA_PLANE_FIXTURES` and writes every\n * entry against the matching workspace's `OpenHiContext`.\n */\nexport interface DemoWorkspaceDataPlaneFixtures {\n readonly tenantId: string;\n readonly workspaceId: string;\n /**\n * Scenario slug used in the demo-URN identifier — mirrors the\n * `DemoTenantSpec.scenario` value for the parent tenant. For the\n * mixed tenant both workspaces share the `demo-mixed` scenario.\n */\n readonly scenario: string;\n readonly patients: ReadonlyArray<Patient>;\n readonly practitioners: ReadonlyArray<Practitioner>;\n readonly observations: ReadonlyArray<Observation>;\n readonly encounters: ReadonlyArray<Encounter>;\n readonly accounts: ReadonlyArray<Account>;\n /**\n * Facility (FHIR Location) fixtures. Optional — only the\n * on-site UAT demo workspace seeds facilities (#1303). Defaults\n * to the empty array when omitted.\n */\n readonly locations?: ReadonlyArray<Location>;\n /**\n * Directory Organization fixtures (#1308). Optional — only the\n * on-site UAT demo workspace seeds Organizations today. Covers\n * DME suppliers and insurance payor contacts; defaults to the\n * empty array when omitted.\n */\n readonly organizations?: ReadonlyArray<Organization>;\n /**\n * Insurance Coverage fixtures (#1304). Optional — only the\n * on-site UAT demo workspace seeds Coverages today. Defaults to\n * the empty array when omitted. Coverages reference their\n * `beneficiary` Patient via `Patient/<id>`, so the seeder writes\n * Coverages after Patients in the same workspace pass.\n */\n readonly coverages?: ReadonlyArray<Coverage>;\n /**\n * Optional dynamic Patient builder. Resolved by the seeder at\n * write time so per-tenant fixtures that depend on other\n * fixture modules (cross-module references between blocks +\n * facilities + facility patients) can be evaluated lazily,\n * avoiding the TDZ that hits when one fixture module reads a\n * top-level const from another mid-cycle. When set, the seeder\n * iterates `buildPatients()` instead of `patients`.\n */\n readonly buildPatients?: () => ReadonlyArray<Patient>;\n /**\n * Optional dynamic Coverage builder. Same lazy-evaluation\n * contract as {@link buildPatients}.\n */\n readonly buildCoverages?: () => ReadonlyArray<Coverage>;\n /**\n * Optional dynamic Appointment builder. Resolved by the seeder\n * with `baseContext` so block-style Appointments can anchor\n * their recurrence to the current ISO week (#1303 — block\n * Appointments must show up at a useful position on the demo\n * calendar relative to \"today\"). When omitted, no Appointments\n * are written for this workspace.\n */\n readonly buildAppointments?: (\n baseContext: OpenHiContext,\n ) => ReadonlyArray<Appointment>;\n /**\n * Optional static wound / problem Condition fixtures (#1306).\n * Wound Conditions reference their Patient via `subject` and\n * sit upstream of wound-exam Observations (which reference the\n * Condition via `focus`) and wound Procedures (which reference\n * the Condition via `reasonReference`). The seeder writes\n * Conditions immediately after Patients so the reference chain\n * resolves cleanly on read paths.\n */\n readonly conditions?: ReadonlyArray<Condition>;\n /**\n * Optional static Procedure fixtures (#1306). Procedures\n * reference their Encounter via `encounter`, their wound\n * Condition via `reasonReference[0]`, and their Patient via\n * `subject`. Written after Encounters and Conditions so the\n * reference chain resolves cleanly on read paths.\n */\n readonly procedures?: ReadonlyArray<Procedure>;\n /**\n * Optional dynamic Condition builder. Same lazy-evaluation\n * contract as {@link buildPatients} — used so the on-site\n * encounter fixtures can anchor wound Conditions to the same\n * `baseContext.date` window the encounter dates are derived\n * from.\n */\n readonly buildConditions?: (\n baseContext: OpenHiContext,\n ) => ReadonlyArray<Condition>;\n /**\n * Optional dynamic Encounter builder. Same lazy-evaluation\n * contract as {@link buildPatients} — encounter dates depend on\n * `baseContext.date` (past block occurrences for facility\n * patients, past visit cadence for home-health patients).\n */\n readonly buildEncounters?: (\n baseContext: OpenHiContext,\n ) => ReadonlyArray<Encounter>;\n /**\n * Optional dynamic Observation builder. Same lazy-evaluation\n * contract as {@link buildPatients} — wound-exam Observations\n * reference encounters that depend on `baseContext.date`.\n */\n readonly buildObservations?: (\n baseContext: OpenHiContext,\n ) => ReadonlyArray<Observation>;\n /**\n * Optional dynamic Procedure builder. Same lazy-evaluation\n * contract as {@link buildPatients} — wound Procedures\n * reference encounters that depend on `baseContext.date`.\n */\n readonly buildProcedures?: (\n baseContext: OpenHiContext,\n ) => ReadonlyArray<Procedure>;\n /**\n * Optional dynamic Claim builder (#1307). Claims reference\n * the encounter they bill via `item[].encounter`, the\n * patient's primary Coverage via `insurance[0].coverage`, and\n * therefore depend on the encounter + coverage builders above.\n * Written after Procedures so every reference chain resolves\n * cleanly on read paths.\n */\n readonly buildClaims?: (baseContext: OpenHiContext) => ReadonlyArray<Claim>;\n /**\n * Optional dynamic PaymentNotice builder (#1307). One\n * PaymentNotice per accepted Claim; references the Claim via\n * `request` + `payment`. Written after Claims.\n */\n readonly buildPaymentNotices?: (\n baseContext: OpenHiContext,\n ) => ReadonlyArray<PaymentNotice>;\n}\n\n/**\n * Map a tenant scenario to a `(roleSuffix, tenantId, workspaceId)`\n * triple plus the demo + OHI identifiers. Keeps the per-resource\n * builders compact below — they call this once per body to stamp the\n * two-identifier pair that matches the control-plane pattern.\n */\nconst fixtureIdentifiers = (\n scenario: string,\n tenantId: string,\n workspaceId: string,\n resourceType: string,\n id: string,\n roleSuffix: string,\n) => [\n demoScenarioIdentifier(scenario, roleSuffix),\n openhiResourceIdentifier({\n tenantId,\n workspaceId,\n resourceType,\n id,\n }),\n];\n\nconst buildWoundCareFixtures = (\n scenario: string,\n tenantId: string,\n workspaceId: string,\n idPrefix: string,\n): DemoWorkspaceDataPlaneFixtures => ({\n tenantId,\n workspaceId,\n scenario,\n patients: [\n {\n resourceType: \"Patient\",\n id: `${idPrefix}-patient-1`,\n identifier: fixtureIdentifiers(\n scenario,\n tenantId,\n workspaceId,\n \"Patient\",\n `${idPrefix}-patient-1`,\n `patient-1`,\n ),\n active: true,\n name: [{ family: \"Carter\", given: [\"Eleanor\"], use: \"official\" }],\n gender: \"female\",\n birthDate: \"1952-04-18\",\n },\n {\n resourceType: \"Patient\",\n id: `${idPrefix}-patient-2`,\n identifier: fixtureIdentifiers(\n scenario,\n tenantId,\n workspaceId,\n \"Patient\",\n `${idPrefix}-patient-2`,\n `patient-2`,\n ),\n active: true,\n name: [{ family: \"Nguyen\", given: [\"Hao\"], use: \"official\" }],\n gender: \"male\",\n birthDate: \"1968-11-02\",\n },\n ],\n practitioners: [\n {\n resourceType: \"Practitioner\",\n id: `${idPrefix}-practitioner-1`,\n identifier: fixtureIdentifiers(\n scenario,\n tenantId,\n workspaceId,\n \"Practitioner\",\n `${idPrefix}-practitioner-1`,\n `practitioner-1`,\n ),\n active: true,\n name: [{ family: \"Reyes\", given: [\"Maria\"], prefix: [\"Dr.\"] }],\n gender: \"female\",\n },\n {\n resourceType: \"Practitioner\",\n id: `${idPrefix}-practitioner-2`,\n identifier: fixtureIdentifiers(\n scenario,\n tenantId,\n workspaceId,\n \"Practitioner\",\n `${idPrefix}-practitioner-2`,\n `practitioner-2`,\n ),\n active: true,\n name: [{ family: \"Okafor\", given: [\"Chinedu\"], prefix: [\"Dr.\"] }],\n gender: \"male\",\n },\n ],\n observations: [\n {\n resourceType: \"Observation\",\n id: `${idPrefix}-observation-1`,\n identifier: fixtureIdentifiers(\n scenario,\n tenantId,\n workspaceId,\n \"Observation\",\n `${idPrefix}-observation-1`,\n `observation-1`,\n ),\n status: \"final\",\n code: {\n coding: [\n {\n system: \"http://loinc.org\",\n code: \"39135-9\",\n display: \"Wound size\",\n },\n ],\n },\n subject: { reference: `Patient/${idPrefix}-patient-1` },\n valueString: \"3.2cm x 2.1cm\",\n },\n {\n resourceType: \"Observation\",\n id: `${idPrefix}-observation-2`,\n identifier: fixtureIdentifiers(\n scenario,\n tenantId,\n workspaceId,\n \"Observation\",\n `${idPrefix}-observation-2`,\n `observation-2`,\n ),\n status: \"final\",\n code: {\n coding: [\n {\n system: \"http://loinc.org\",\n code: \"72287-2\",\n display: \"Wound exudate amount\",\n },\n ],\n },\n subject: { reference: `Patient/${idPrefix}-patient-2` },\n valueString: \"moderate\",\n },\n ],\n encounters: [\n {\n resourceType: \"Encounter\",\n id: `${idPrefix}-encounter-1`,\n identifier: fixtureIdentifiers(\n scenario,\n tenantId,\n workspaceId,\n \"Encounter\",\n `${idPrefix}-encounter-1`,\n `encounter-1`,\n ),\n status: \"finished\",\n class: {\n system: \"http://terminology.hl7.org/CodeSystem/v3-ActCode\",\n code: \"AMB\",\n display: \"ambulatory\",\n },\n subject: { reference: `Patient/${idPrefix}-patient-1` },\n },\n {\n resourceType: \"Encounter\",\n id: `${idPrefix}-encounter-2`,\n identifier: fixtureIdentifiers(\n scenario,\n tenantId,\n workspaceId,\n \"Encounter\",\n `${idPrefix}-encounter-2`,\n `encounter-2`,\n ),\n status: \"finished\",\n class: {\n system: \"http://terminology.hl7.org/CodeSystem/v3-ActCode\",\n code: \"AMB\",\n display: \"ambulatory\",\n },\n subject: { reference: `Patient/${idPrefix}-patient-2` },\n },\n ],\n accounts: [\n {\n resourceType: \"Account\",\n id: `${idPrefix}-account-1`,\n identifier: fixtureIdentifiers(\n scenario,\n tenantId,\n workspaceId,\n \"Account\",\n `${idPrefix}-account-1`,\n `account-1`,\n ),\n status: \"active\",\n name: \"Wound-care self-pay account\",\n subject: [{ reference: `Patient/${idPrefix}-patient-1` }],\n },\n ],\n});\n\nconst buildPrimaryCareFixtures = (\n scenario: string,\n tenantId: string,\n workspaceId: string,\n idPrefix: string,\n): DemoWorkspaceDataPlaneFixtures => ({\n tenantId,\n workspaceId,\n scenario,\n patients: [\n {\n resourceType: \"Patient\",\n id: `${idPrefix}-patient-1`,\n identifier: fixtureIdentifiers(\n scenario,\n tenantId,\n workspaceId,\n \"Patient\",\n `${idPrefix}-patient-1`,\n `patient-1`,\n ),\n active: true,\n name: [{ family: \"Bennett\", given: [\"Sophia\"], use: \"official\" }],\n gender: \"female\",\n birthDate: \"1985-06-09\",\n },\n {\n resourceType: \"Patient\",\n id: `${idPrefix}-patient-2`,\n identifier: fixtureIdentifiers(\n scenario,\n tenantId,\n workspaceId,\n \"Patient\",\n `${idPrefix}-patient-2`,\n `patient-2`,\n ),\n active: true,\n name: [{ family: \"Patel\", given: [\"Arjun\"], use: \"official\" }],\n gender: \"male\",\n birthDate: \"1979-02-21\",\n },\n ],\n practitioners: [\n {\n resourceType: \"Practitioner\",\n id: `${idPrefix}-practitioner-1`,\n identifier: fixtureIdentifiers(\n scenario,\n tenantId,\n workspaceId,\n \"Practitioner\",\n `${idPrefix}-practitioner-1`,\n `practitioner-1`,\n ),\n active: true,\n name: [{ family: \"Lin\", given: [\"Wei\"], prefix: [\"Dr.\"] }],\n gender: \"female\",\n },\n {\n resourceType: \"Practitioner\",\n id: `${idPrefix}-practitioner-2`,\n identifier: fixtureIdentifiers(\n scenario,\n tenantId,\n workspaceId,\n \"Practitioner\",\n `${idPrefix}-practitioner-2`,\n `practitioner-2`,\n ),\n active: true,\n name: [{ family: \"Kowalski\", given: [\"Piotr\"], prefix: [\"Dr.\"] }],\n gender: \"male\",\n },\n ],\n observations: [\n {\n resourceType: \"Observation\",\n id: `${idPrefix}-observation-1`,\n identifier: fixtureIdentifiers(\n scenario,\n tenantId,\n workspaceId,\n \"Observation\",\n `${idPrefix}-observation-1`,\n `observation-1`,\n ),\n status: \"final\",\n code: {\n coding: [\n {\n system: \"http://loinc.org\",\n code: \"8480-6\",\n display: \"Systolic blood pressure\",\n },\n ],\n },\n subject: { reference: `Patient/${idPrefix}-patient-1` },\n valueQuantity: { value: 122, unit: \"mm[Hg]\" },\n },\n {\n resourceType: \"Observation\",\n id: `${idPrefix}-observation-2`,\n identifier: fixtureIdentifiers(\n scenario,\n tenantId,\n workspaceId,\n \"Observation\",\n `${idPrefix}-observation-2`,\n `observation-2`,\n ),\n status: \"final\",\n code: {\n coding: [\n {\n system: \"http://loinc.org\",\n code: \"8462-4\",\n display: \"Diastolic blood pressure\",\n },\n ],\n },\n subject: { reference: `Patient/${idPrefix}-patient-2` },\n valueQuantity: { value: 78, unit: \"mm[Hg]\" },\n },\n ],\n encounters: [\n {\n resourceType: \"Encounter\",\n id: `${idPrefix}-encounter-1`,\n identifier: fixtureIdentifiers(\n scenario,\n tenantId,\n workspaceId,\n \"Encounter\",\n `${idPrefix}-encounter-1`,\n `encounter-1`,\n ),\n status: \"finished\",\n class: {\n system: \"http://terminology.hl7.org/CodeSystem/v3-ActCode\",\n code: \"AMB\",\n display: \"ambulatory\",\n },\n subject: { reference: `Patient/${idPrefix}-patient-1` },\n },\n {\n resourceType: \"Encounter\",\n id: `${idPrefix}-encounter-2`,\n identifier: fixtureIdentifiers(\n scenario,\n tenantId,\n workspaceId,\n \"Encounter\",\n `${idPrefix}-encounter-2`,\n `encounter-2`,\n ),\n status: \"in-progress\",\n class: {\n system: \"http://terminology.hl7.org/CodeSystem/v3-ActCode\",\n code: \"AMB\",\n display: \"ambulatory\",\n },\n subject: { reference: `Patient/${idPrefix}-patient-2` },\n },\n ],\n accounts: [\n {\n resourceType: \"Account\",\n id: `${idPrefix}-account-1`,\n identifier: fixtureIdentifiers(\n scenario,\n tenantId,\n workspaceId,\n \"Account\",\n `${idPrefix}-account-1`,\n `account-1`,\n ),\n status: \"active\",\n name: \"Primary-care insurance account\",\n subject: [{ reference: `Patient/${idPrefix}-patient-1` }],\n },\n ],\n});\n\n/**\n * Per-workspace fixtures the data-plane phase writes on every fire.\n * The placeholder tenant carries no fixtures. The mixed tenant carries\n * one fixture group per workspace; the two single-workspace tenants\n * carry one each. Total: 4 fixture groups × ≈ 9 resources = ~36\n * data-plane records.\n *\n * Ids embed the tenant + workspace slug so they remain unambiguous\n * across the four workspaces (the FHIR resource id is the only thing\n * that survives into the partition key, so a duplicate id across\n * workspaces would still collide on read paths that scan-by-id).\n */\nexport const DEMO_DATA_PLANE_FIXTURES: ReadonlyArray<DemoWorkspaceDataPlaneFixtures> =\n [\n // On-site-medical UAT demo workspace — practitioners only (issue\n // #1302). Patients, encounters, and other data-plane resources for\n // this tenant land in later tickets.\n ON_SITE_DEMO_FIXTURES,\n buildWoundCareFixtures(\n \"demo-wound-care\",\n \"demo-wound-care-tenant\",\n \"demo-wound-care-workspace\",\n \"demo-wound-care\",\n ),\n buildPrimaryCareFixtures(\n \"demo-primary-care\",\n \"demo-primary-care-tenant\",\n \"demo-primary-care-workspace\",\n \"demo-primary-care\",\n ),\n buildWoundCareFixtures(\n \"demo-mixed\",\n \"demo-mixed-tenant\",\n \"demo-mixed-workspace-wound-care\",\n \"demo-mixed-wound-care\",\n ),\n buildPrimaryCareFixtures(\n \"demo-mixed\",\n \"demo-mixed-tenant\",\n \"demo-mixed-workspace-primary-care\",\n \"demo-mixed-primary-care\",\n ),\n ];\n\n/**\n * Regression guard: the fixture groups must each be tied to a Tenant +\n * Workspace combination that exists in {@link DEMO_TENANT_SPECS}.\n * Imported `DEMO_TENANT_SPECS` and `PLACEHOLDER_TENANT_ID` keep the\n * guard self-contained — no test plumbing required.\n */\nconst _validateFixturesAgainstTenantSpecs = (): void => {\n for (const group of DEMO_DATA_PLANE_FIXTURES) {\n if (group.tenantId === PLACEHOLDER_TENANT_ID) {\n throw new Error(\n \"The placeholder tenant must not carry data-plane fixtures.\",\n );\n }\n const tenant = DEMO_TENANT_SPECS.find((s) => s.tenantId === group.tenantId);\n if (!tenant) {\n throw new Error(\n `Fixture references unknown tenantId \"${group.tenantId}\". ` +\n \"Add a matching entry to DEMO_TENANT_SPECS first.\",\n );\n }\n const workspace = tenant.workspaces.find(\n (ws) => ws.id === group.workspaceId,\n );\n if (!workspace) {\n throw new Error(\n `Fixture references unknown workspaceId \"${group.workspaceId}\" ` +\n `for tenant \"${group.tenantId}\".`,\n );\n }\n }\n};\n_validateFixturesAgainstTenantSpecs();\n","import { Service } from \"electrodb\";\nimport { defaultTableName, dynamoClient } from \"./dynamo-client\";\nimport { ConfigurationEntity } from \"./entities/control/configuration-entity\";\nimport { ConfigurationUserProjectionEntity } from \"./entities/control/configuration-user-projection-entity\";\nimport { ConfigurationWorkspaceProjectionEntity } from \"./entities/control/configuration-workspace-projection-entity\";\nimport { MembershipEntity } from \"./entities/control/membership-entity\";\nimport { MembershipUserProjectionEntity } from \"./entities/control/membership-user-projection-entity\";\nimport { MembershipWorkspaceProjectionEntity } from \"./entities/control/membership-workspace-projection-entity\";\nimport { RoleEntity } from \"./entities/control/role-entity\";\nimport { RoleAssignmentEntity } from \"./entities/control/roleassignment-entity\";\nimport { RoleAssignmentUserProjectionEntity } from \"./entities/control/roleassignment-user-projection-entity\";\nimport { RoleAssignmentWorkspaceProjectionEntity } from \"./entities/control/roleassignment-workspace-projection-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 configurationUserProjection: ConfigurationUserProjectionEntity,\n configurationWorkspaceProjection: ConfigurationWorkspaceProjectionEntity,\n membership: MembershipEntity,\n membershipUserProjection: MembershipUserProjectionEntity,\n membershipWorkspaceProjection: MembershipWorkspaceProjectionEntity,\n role: RoleEntity,\n roleAssignment: RoleAssignmentEntity,\n roleAssignmentUserProjection: RoleAssignmentUserProjectionEntity,\n roleAssignmentWorkspaceProjection: RoleAssignmentWorkspaceProjectionEntity,\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 *\n * `transaction` exposes ElectroDB's `service.transaction.write` /\n * `service.transaction.get` builders so the operations-layer multi-write\n * helper (#1010, ADR-018) can compose `TransactWriteItems` across the\n * control-plane entities.\n */\nexport const DynamoControlService = {\n entities: controlPlaneService.entities,\n transaction: controlPlaneService.transaction,\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 transaction: service.transaction,\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, normalizeLabel } 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/**\n * Extract a roleId from a RoleAssignment resource payload. Looks first at\n * a flat top-level `roleId` string, then at a FHIR-style `role.reference`\n * (e.g. `Role/<id>`). Returns `undefined` when neither shape is present\n * or the field is malformed — callers fall back to the generic GSI1SK\n * derivation in that case so a single bad write never blocks an entity put.\n */\nfunction extractRoleId(resource: Record<string, unknown>): string | undefined {\n const flat = resource.roleId;\n if (typeof flat === \"string\" && flat.length > 0) return flat;\n\n const role = resource.role;\n if (role && typeof role === \"object\") {\n const reference = (role as { reference?: unknown }).reference;\n if (typeof reference === \"string\" && reference.length > 0) {\n const slash = reference.lastIndexOf(\"/\");\n const tail = slash >= 0 ? reference.slice(slash + 1) : reference;\n if (tail.length > 0) return tail;\n }\n }\n return undefined;\n}\n\n/**\n * RoleAssignment-specific GSI1 sort-key attribute (ADR-018 pattern #8 —\n * \"users with a specific role in a tenant, sorted by user name\").\n *\n * Composes the canonical-row GSI1SK as the discriminator-first shape\n * `<roleId>#<normalizedUserName>#<id>` so a GSI1 query partitioned on\n * the tenant can `begins_with('<roleId>#')` to enumerate every user\n * assigned to a given role, sorted by user name.\n *\n * - `<roleId>` is read from a flat `resource.roleId` field, falling back\n * to the slug after the final `/` in `resource.role.reference` (the\n * FHIR Reference shape). Sorting on `roleId` rather than the role's\n * display name means a Role rename does not cascade onto this index\n * (TR-024 / ADR-018 § Implementation Notes).\n * - `<normalizedUserName>` is `normalizeLabel(denormalizedUserName)` —\n * the top-level denormalized field promoted in #1009 (TR-024 rule 3:\n * canonical-record symmetry).\n *\n * Falls back to `gsi1skAttribute`'s `<lastUpdated>#<id>` shape when\n * either component is missing or malformed, so pre-TR-024 rows and\n * malformed payloads still produce a valid sort key.\n *\n * Not `required` because the value is derived via `watch`/`set`.\n *\n * @see ADR-018 § Access Pattern Coverage — pattern #8\n * @see TR-024 — Denormalized display-name attributes\n */\nexport const roleAssignmentGsi1skAttribute = {\n type: \"string\" as const,\n watch: [\"resource\", \"denormalizedUserName\", \"lastUpdated\", \"id\"] as const,\n set: (\n _val?: string,\n item?: {\n resource?: string;\n denormalizedUserName?: string;\n lastUpdated?: string;\n id?: string;\n },\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\n const roleId = extractRoleId(parsed as Record<string, unknown>);\n if (roleId === undefined) return fallback;\n\n const denormalizedUserName =\n typeof item.denormalizedUserName === \"string\"\n ? item.denormalizedUserName\n : \"\";\n const normalizedUserName =\n denormalizedUserName.length > 0\n ? normalizeLabel(denormalizedUserName)\n : \"\";\n if (normalizedUserName.length === 0) return fallback;\n\n return `${roleId}#${normalizedUserName}#${id}`;\n },\n};\n\n/**\n * Membership-specific GSI1 sort-key attribute (ADR-018 pattern #1 —\n * \"users in a tenant, sorted by user name\").\n *\n * Composes the canonical-row GSI1SK as `<normalizedUserName>#<id>` so a\n * GSI1 query partitioned on the tenant range-scans by user-name prefix\n * and returns memberships sorted alphabetically by user name. No role\n * discriminator goes in front — pattern #1 is user-name-first.\n *\n * - `<normalizedUserName>` is `normalizeLabel(denormalizedUserName)` —\n * the top-level denormalized field promoted in #1009 (TR-024 rule 3:\n * canonical-record symmetry).\n *\n * Falls back to `gsi1skAttribute`'s `<lastUpdated>#<id>` shape when\n * `denormalizedUserName` is missing, so pre-TR-024 rows and malformed\n * payloads still produce a valid sort key.\n *\n * Not `required` because the value is derived via `watch`/`set`.\n *\n * @see ADR-018 § Access Pattern Coverage — pattern #1\n * @see TR-024 — Denormalized display-name attributes\n */\nexport const membershipGsi1skAttribute = {\n type: \"string\" as const,\n watch: [\"denormalizedUserName\", \"lastUpdated\", \"id\"] as const,\n set: (\n _val?: string,\n item?: {\n denormalizedUserName?: string;\n lastUpdated?: string;\n id?: string;\n },\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 const denormalizedUserName =\n typeof item?.denormalizedUserName === \"string\"\n ? item.denormalizedUserName\n : \"\";\n const normalizedUserName =\n denormalizedUserName.length > 0\n ? normalizeLabel(denormalizedUserName)\n : \"\";\n if (normalizedUserName.length === 0) {\n return fallback;\n }\n\n return `${normalizedUserName}#${id}`;\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\";\n\n/**\n * Configuration user-projection entity (single-table store, no GSI).\n *\n * **ADR-018 adjacency-list projection — pattern #10 (user-scope half).**\n * For every user-scoped Configuration write the operations-layer\n * multi-write helper writes one projection row under the user partition\n * so the user-rooted access pattern #10 is served by a single\n * base-table `Query` with no GSI hop:\n *\n * | Pattern | When | PK | SK |\n * |---|---|---|---|\n * | #10 user-scope | Configuration is user-scoped (`userId !== \"-\"`) | `USER#ID#<userId>` | `CONFIGURATION#<normalizedConfigName>#<configurationId>` |\n *\n * `<normalizedConfigName>` derives from Configuration's `key` attribute\n * (the canonical name dimension — Configuration carries no `displayName`\n * per TR-024 § Open Item #5, so `key` is the natural sort source). The\n * SK shape is operation-owned: the operations-layer projection writer\n * composes the SK string via `buildConfigurationUserProjectionSk` and\n * supplies it on the `sk` attribute. This entity stores the SK verbatim —\n * no `watch`/derived computation here — so the SK grammar (and any\n * future revision) lives in one place: the operations layer.\n *\n * Projection attribute set per ADR-018 § Projection attribute set and\n * the implementation guide § 2: `summary`, `vid`, `lastUpdated` (so\n * `Query(PK = USER#ID#<userId>, SK begins_with 'CONFIGURATION#')` is\n * self-sufficient — no BatchGet hop to the canonical record), plus the\n * projection-discriminating fields (`configurationId`, `userId`,\n * `tenantId`, `scope`).\n *\n * **Cross-tenant partition.** Unlike Membership/RoleAssignment-workspace\n * partitions, the Configuration user-projection's PK carries no tenant\n * prefix — a user's user-scoped Configurations are cross-tenant by\n * design (a user may carry preferences that follow them across tenant\n * memberships). This mirrors the RoleAssignment user-projection partition.\n *\n * **No GSI projection.** Per ADR-018 § Decision, cross-cutting reads\n * are served by the main-table partition `USER#ID#<userId>`; the\n * GSI1/GSI2 catalog is unchanged. Tenant-scoped Configurations\n * continue to use the canonical GSI1 path (ADR-011) unchanged.\n *\n * @see ADR-018 § Access Pattern Coverage (#10 — user-scope half)\n * @see .state/adr-018-implementation-guide.md § 1 (SK grammar) and § 2 (attribute set)\n * @see .claude/rules/data-layer-layout.md — projection writers live in operations, not here\n */\nexport const ConfigurationUserProjectionEntity = new Entity({\n model: {\n entity: \"configurationUserProjection\",\n service: \"control\",\n version: \"01\",\n },\n attributes: {\n /**\n * User partition discriminator. Renders as `USER#ID#<userId>` on the\n * base-table PK. Always required — the projection has no meaning\n * outside a user partition.\n */\n userId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Pre-composed sort key — built by the operations-layer projection\n * writer via `buildConfigurationUserProjectionSk`. The entity stores\n * the value verbatim so the SK grammar (pattern #10 user-scope) is\n * owned by the operations layer, not duplicated here.\n */\n sk: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Configuration canonical-record id. Stored as a discriminating\n * field so consumers can hydrate the canonical row via the\n * Configuration get-by-id operation when the projection's `summary`\n * is insufficient.\n */\n configurationId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Tenant the Configuration is associated with. The canonical row\n * keys off `(tenantId, workspaceId, userId, roleId)`; the projection\n * carries `tenantId` so consumers reconstructing the canonical PK\n * have the tenant segment without a hop.\n */\n tenantId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Scope marker. Always `\"user\"` on this projection — recorded\n * explicitly so future scope-bearing projections (workspace,\n * tenant, role) can share filter semantics in a unified\n * cross-projection list query if one ever lands.\n */\n scope: {\n type: \"string\" as const,\n required: true,\n default: \"user\",\n },\n /**\n * Configuration's `key` attribute (config category, e.g. endpoints,\n * branding, display). Mirrored from the canonical row so consumers\n * reading the projection get the natural display label without a\n * BatchGet hop. Doubles as the source of `<normalizedConfigName>` in\n * the SK.\n */\n displayName: {\n type: \"string\" as const,\n required: false,\n },\n /**\n * Summary projection (key display fields as JSON string) — mirrored\n * from the canonical Configuration row so user-partition queries do\n * not need a BatchGet hop.\n */\n summary: {\n type: \"string\" as const,\n required: true,\n },\n /** Version id mirrored from the canonical Configuration row. */\n vid: {\n type: \"string\" as const,\n required: true,\n },\n /** Last-updated timestamp mirrored from the canonical Configuration row. */\n lastUpdated: {\n type: \"string\" as const,\n required: true,\n },\n },\n indexes: {\n /**\n * Base table: PK = USER#ID#\\<userId\\>, SK = operation-supplied. A\n * single `Query(PK = USER#ID#<userId>, SK begins_with 'CONFIGURATION#')`\n * returns the user's user-scoped Configurations sorted by\n * `<normalizedConfigName>` (then `<configurationId>` as the\n * tiebreaker).\n */\n record: {\n pk: {\n field: \"PK\",\n composite: [\"userId\"],\n template: \"USER#ID#${userId}\",\n },\n sk: {\n field: \"SK\",\n casing: \"none\" as const,\n composite: [\"sk\"],\n template: \"${sk}\",\n },\n },\n },\n});\n","import { Entity } from \"electrodb\";\n\n/**\n * Configuration workspace-projection entity (single-table store, no GSI).\n *\n * **ADR-018 adjacency-list projection — pattern #10 (workspace-scope half).**\n * For every workspace-scoped Configuration the operations-layer\n * multi-write helper writes one projection row under the workspace\n * partition so the workspace-rooted access pattern #10 is served by a\n * single base-table `Query` with no GSI hop:\n *\n * | Pattern | When | PK | SK |\n * |---|---|---|---|\n * | #10 workspace-scope | Configuration is workspace-scoped (`workspaceId !== \"-\"`, `userId === \"-\"`) | `TID#<tenantId>#WORKSPACE#ID#<workspaceId>` | `CONFIGURATION#<normalizedConfigName>#<configurationId>` |\n *\n * The PK co-locates with the canonical Workspace record\n * (`SK = CURRENT`) and the Membership / RoleAssignment workspace-\n * projections (patterns #2, #9), so an admin workspace dashboard can\n * hydrate workspace metadata + member projections + role-assignment\n * projections + workspace-scoped Configurations in a single `Query`.\n *\n * `<normalizedConfigName>` derives from Configuration's `key` attribute\n * (the canonical name dimension — Configuration carries no `displayName`\n * per TR-024 § Open Item #5, so `key` is the natural sort source). The\n * SK shape is operation-owned: the operations-layer projection writer\n * composes the SK string via `buildConfigurationWorkspaceProjectionSk`\n * and supplies it on the `sk` attribute. This entity stores the SK\n * verbatim — no `watch`/derived computation here — so the SK grammar\n * (and any future revision) lives in one place: the operations layer.\n *\n * Projection attribute set per ADR-018 § Projection attribute set and\n * the implementation guide § 2: `summary`, `vid`, `lastUpdated` (so\n * `Query(PK = TID#<tenantId>#WORKSPACE#ID#<workspaceId>, SK begins_with 'CONFIGURATION#')`\n * is self-sufficient — no BatchGet hop to the canonical record), plus\n * the projection-discriminating fields (`configurationId`, `workspaceId`,\n * `tenantId`, `scope`).\n *\n * **Tenant-prefixed partition.** Unlike the Configuration user-\n * projection (whose PK is `USER#ID#<userId>` with no tenant prefix —\n * a user's user-scoped Configurations are cross-tenant by design),\n * the workspace-projection PK carries the tenant prefix because\n * Workspaces are tenant-scoped per ADR-011. This mirrors the\n * Membership / RoleAssignment workspace-projection partitions.\n *\n * **No GSI projection.** Per ADR-018 § Decision, cross-cutting reads\n * are served by the main-table partition\n * `TID#<tenantId>#WORKSPACE#ID#<workspaceId>`; the GSI1/GSI2 catalog\n * is unchanged. Tenant-scoped Configurations continue to use the\n * canonical GSI1 path (ADR-011) unchanged.\n *\n * @see ADR-018 § Access Pattern Coverage (#10 — workspace-scope half)\n * @see .state/adr-018-implementation-guide.md § 1 (SK grammar) and § 2 (attribute set)\n * @see .claude/rules/data-layer-layout.md — projection writers live in operations, not here\n */\nexport const ConfigurationWorkspaceProjectionEntity = new Entity({\n model: {\n entity: \"configurationWorkspaceProjection\",\n service: \"control\",\n version: \"01\",\n },\n attributes: {\n /**\n * Tenant the workspace belongs to. Renders as the leading segment\n * of the base-table PK. Always required — the workspace partition\n * is tenant-scoped per ADR-011.\n */\n tenantId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Workspace partition discriminator. Renders as the trailing\n * segment of the base-table PK\n * (`TID#<tenantId>#WORKSPACE#ID#<workspaceId>`). Always required —\n * the projection has no meaning outside a workspace partition.\n */\n workspaceId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Pre-composed sort key — built by the operations-layer projection\n * writer via `buildConfigurationWorkspaceProjectionSk`. The entity\n * stores the value verbatim so the SK grammar (pattern #10\n * workspace-scope) is owned by the operations layer, not\n * duplicated here.\n */\n sk: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Configuration canonical-record id. Stored as a discriminating\n * field so consumers can hydrate the canonical row via the\n * Configuration get-by-id operation when the projection's `summary`\n * is insufficient.\n */\n configurationId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Scope marker. Always `\"workspace\"` on this projection — recorded\n * explicitly so future scope-bearing projections (user, tenant,\n * role) can share filter semantics in a unified cross-projection\n * list query if one ever lands.\n */\n scope: {\n type: \"string\" as const,\n required: true,\n default: \"workspace\",\n },\n /**\n * Configuration's `key` attribute (config category, e.g. endpoints,\n * branding, display). Mirrored from the canonical row so consumers\n * reading the projection get the natural display label without a\n * BatchGet hop. Doubles as the source of `<normalizedConfigName>`\n * in the SK.\n */\n displayName: {\n type: \"string\" as const,\n required: false,\n },\n /**\n * Summary projection (key display fields as JSON string) — mirrored\n * from the canonical Configuration row so workspace-partition\n * queries do not need a BatchGet hop.\n */\n summary: {\n type: \"string\" as const,\n required: true,\n },\n /** Version id mirrored from the canonical Configuration row. */\n vid: {\n type: \"string\" as const,\n required: true,\n },\n /** Last-updated timestamp mirrored from the canonical Configuration row. */\n lastUpdated: {\n type: \"string\" as const,\n required: true,\n },\n },\n indexes: {\n /**\n * Base table: PK = TID#<tenantId>#WORKSPACE#ID#<workspaceId>,\n * SK = operation-supplied. A single\n * `Query(PK = TID#<tenantId>#WORKSPACE#ID#<workspaceId>, SK begins_with 'CONFIGURATION#')`\n * returns the workspace's workspace-scoped Configurations sorted by\n * `<normalizedConfigName>` (then `<configurationId>` as the\n * tiebreaker).\n */\n record: {\n pk: {\n field: \"PK\",\n composite: [\"tenantId\", \"workspaceId\"],\n template: \"TID#${tenantId}#WORKSPACE#ID#${workspaceId}\",\n },\n sk: {\n field: \"SK\",\n casing: \"none\" as const,\n composite: [\"sk\"],\n template: \"${sk}\",\n },\n },\n },\n});\n","import { Entity } from \"electrodb\";\nimport {\n gsi1ShardAttribute,\n membershipGsi1skAttribute,\n} 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 /**\n * Derived GSI1 sort key — `<normalizedUserName>#<id>` per ADR-018\n * pattern #1 so a GSI1 query partitioned on the tenant range-scans\n * by user-name prefix and returns memberships sorted by user name.\n * Falls back to `<lastUpdated>#<id>` when `denormalizedUserName`\n * is missing.\n */\n gsi1sk: membershipGsi1skAttribute,\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 * Denormalized `linked-data-identity` Reference (e.g. `Practitioner/abc`).\n * Populated from the FHIR extension on the Membership resource at write\n * time so future GSIs can index data-plane identity lookups without\n * deserializing the full resource JSON. See ADR 2026-03-13-02 §6.\n */\n linkedDataIdentityRef: {\n type: \"string\" as const,\n required: false,\n },\n /**\n * Denormalized display name of the linked Tenant, captured at row\n * last-write time. Promoted to a top-level attribute so the ADR-018\n * adjacency-list projection SKs (pattern #3 — `MEMBERSHIP#TENANT#<normalizedTenantName>#…`)\n * can be composed from a top-level field instead of digging into the\n * `resource` JSON. Optional on the schema so pre-TR-024 rows do not\n * break; the operations-layer multi-write helper (#1010) makes the\n * field load-bearing at write time per TR-024 rule 2 (write-time\n * source = canonical Tenant.displayName).\n * @see TR-024 — Denormalized display-name attributes\n */\n denormalizedTenantName: {\n type: \"string\" as const,\n required: false,\n },\n /**\n * Denormalized display name of the linked User, captured at row\n * last-write time. Promoted to a top-level attribute so the ADR-018\n * adjacency-list canonical-record GSI1SK (pattern #1 —\n * `<normalizedUserName>#<id>`) and workspace-projection SK (pattern #2)\n * can be composed from a top-level field. Optional on the schema so\n * pre-TR-024 rows do not break; the operations-layer multi-write helper\n * (#1010) makes the field load-bearing at write time per TR-024 rule 2\n * (write-time source = canonical User.displayName).\n * @see TR-024 — Denormalized display-name attributes\n */\n denormalizedUserName: {\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 `membershipGsi1skAttribute` — composes\n * `<normalizedUserName>#<id>` per ADR-018 pattern #1 (users in a\n * tenant, sorted by user name); falls back to `<lastUpdated>#<id>`\n * when `denormalizedUserName` is missing. `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#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\";\n\n/**\n * Membership user-projection entity (single-table store, no GSI).\n *\n * **ADR-018 adjacency-list projection.** For every Membership write the\n * operations-layer multi-write helper writes one of two projection rows\n * under the user partition so the user-rooted access patterns #3 and #4\n * are served by a single base-table `Query` with no GSI hop:\n *\n * | Pattern | When | PK | SK |\n * |---|---|---|---|\n * | #3 — tenant sub-lane | `workspaceId` absent | `USER#ID#<userId>` | `MEMBERSHIP#TENANT#<normalizedTenantName>#TID#<tenantId>#<id>` |\n * | #4 — workspace sub-lane | `workspaceId` set | `USER#ID#<userId>` | `MEMBERSHIP#WORKSPACE#TID#<tenantId>#<normalizedWorkspaceName>#WID#<workspaceId>#<id>` |\n *\n * Both shapes share the user-partition `PK = USER#ID#<userId>`. The SK\n * shape is operation-owned: the operations-layer projection writer\n * composes the SK string via the `buildMembershipUserProjectionSk*`\n * helpers and supplies it on the `sk` attribute. This entity stores the\n * SK verbatim — no `watch`/derived computation here — so the SK grammar\n * (and any future revision) lives in one place: the operations layer.\n *\n * Projection attribute set per ADR-018 § Projection attribute set and\n * the implementation guide § 2: `summary`, `vid`, `lastUpdated` (so\n * `Query(PK = USER#ID#<userId>, SK begins_with 'MEMBERSHIP#')` is\n * self-sufficient — no BatchGet hop to the canonical record), plus the\n * projection-discriminating fields (`tenantId`, `userId`, `workspaceId?`,\n * `membershipId`) and TR-024 denormalized display names\n * (`denormalizedTenantName`, `denormalizedUserName`,\n * `denormalizedWorkspaceName?`).\n *\n * **No GSI projection.** Per ADR-018 § Decision, cross-cutting reads\n * are served by the main-table partition `USER#ID#<userId>`; the\n * GSI1/GSI2 catalog is unchanged.\n *\n * @see ADR-018 § Access Pattern Coverage (#3, #4)\n * @see .state/adr-018-implementation-guide.md § 1 (SK grammar) and § 2 (attribute set)\n * @see .claude/rules/data-layer-layout.md — projection writers live in operations, not here\n */\nexport const MembershipUserProjectionEntity = new Entity({\n model: {\n entity: \"membershipUserProjection\",\n service: \"control\",\n version: \"01\",\n },\n attributes: {\n /**\n * User partition discriminator. Renders as `USER#ID#<userId>` on the\n * base-table PK. Always required — the projection has no meaning\n * outside a user partition.\n */\n userId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Pre-composed sort key — built by the operations-layer projection\n * writer via `buildMembershipUserProjectionSk*` helpers. The entity\n * stores the value verbatim so the SK grammar (patterns #3 and #4)\n * is owned by the operations layer, not duplicated here.\n */\n sk: {\n type: \"string\" as const,\n required: true,\n },\n /** Tenant in which the membership applies. Always required. */\n tenantId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Workspace the membership scopes to. Present iff the projection\n * row is a pattern-#4 workspace sub-lane row; absent for pattern-#3\n * tenant sub-lane rows.\n */\n workspaceId: {\n type: \"string\" as const,\n required: false,\n },\n /**\n * Membership canonical-record id. Stored as a discriminating field\n * so consumers can hydrate the canonical row via\n * `MembershipEntity.get({ tenantId, id: membershipId })` when the\n * projection's `summary` is insufficient.\n */\n membershipId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Summary projection (key display fields as JSON string: id,\n * displayName, status) — mirrored from the canonical Membership row\n * so user-partition queries do not need a BatchGet hop.\n */\n summary: {\n type: \"string\" as const,\n required: true,\n },\n /** Version id mirrored from the canonical Membership row. */\n vid: {\n type: \"string\" as const,\n required: true,\n },\n /** Last-updated timestamp mirrored from the canonical Membership row. */\n lastUpdated: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Denormalized Tenant display name — required to compose pattern-#3\n * SK (`MEMBERSHIP#TENANT#<normalizedTenantName>#…`). Optional on the\n * schema because pre-TR-024 rows may not carry a display name; the\n * operations layer falls back gracefully when missing.\n */\n denormalizedTenantName: {\n type: \"string\" as const,\n required: false,\n },\n /**\n * Denormalized User display name — mirrored from the canonical\n * Membership row per TR-024 rule 3 (canonical-record symmetry).\n * Carried on the projection so consumers can render the user's\n * display name without a hop to the User record.\n */\n denormalizedUserName: {\n type: \"string\" as const,\n required: false,\n },\n /**\n * Denormalized Workspace display name — required to compose\n * pattern-#4 SK (`MEMBERSHIP#WORKSPACE#TID#<tenantId>#<normalizedWorkspaceName>#…`).\n * Optional on the schema (TR-024 § Open Item #4 defers a formal\n * Workspace-rename cascade); the operations layer falls back to a\n * sentinel when missing so the SK still has a valid shape.\n */\n denormalizedWorkspaceName: {\n type: \"string\" as const,\n required: false,\n },\n },\n indexes: {\n /**\n * Base table: PK = USER#ID#\\<userId\\>, SK = operation-supplied.\n * Both pattern #3 and pattern #4 use this same index — the SK string\n * encodes the lane discriminator (`MEMBERSHIP#TENANT#…` vs\n * `MEMBERSHIP#WORKSPACE#…`) so a single\n * `Query(PK = USER#ID#<userId>, SK begins_with 'MEMBERSHIP#')`\n * returns both lanes interleaved.\n */\n record: {\n pk: {\n field: \"PK\",\n composite: [\"userId\"],\n template: \"USER#ID#${userId}\",\n },\n sk: {\n field: \"SK\",\n casing: \"none\" as const,\n composite: [\"sk\"],\n template: \"${sk}\",\n },\n },\n },\n});\n","import { Entity } from \"electrodb\";\n\n/**\n * Membership workspace-projection entity (single-table store, no GSI).\n *\n * **ADR-018 adjacency-list projection.** For every workspace-scoped\n * Membership the operations-layer multi-write helper writes one\n * projection row under the workspace partition so the workspace-rooted\n * access pattern #2 is served by a single base-table `Query` with no\n * GSI hop:\n *\n * | Pattern | When | PK | SK |\n * |---|---|---|---|\n * | #2 — users in a workspace | `workspaceId` set | `TID#<tenantId>#WORKSPACE#ID#<workspaceId>` | `MEMBERSHIP#<normalizedUserName>#USER#<userId>#<id>` |\n *\n * The PK co-locates with the canonical Workspace record\n * (`SK = CURRENT`) so a single `Query(PK = TID#<tenantId>#WORKSPACE#ID#<workspaceId>)`\n * returns workspace metadata + every member projection in one round\n * trip. The SK shape is operation-owned: the operations-layer\n * projection writer composes the SK string via the\n * `buildMembershipWorkspaceProjectionSk` helper and supplies it on the\n * `sk` attribute. This entity stores the SK verbatim — no\n * `watch`/derived computation here — so the SK grammar lives in one\n * place: the operations layer.\n *\n * Projection attribute set per ADR-018 § Projection attribute set and\n * the implementation guide § 2: `summary`, `vid`, `lastUpdated` (so\n * `Query(PK = TID#<tenantId>#WORKSPACE#ID#<workspaceId>, SK begins_with 'MEMBERSHIP#')`\n * is self-sufficient — no BatchGet hop to the canonical record), plus\n * the projection-discriminating fields (`tenantId`, `workspaceId`,\n * `userId`, `membershipId`) and TR-024 denormalized user display name\n * (`denormalizedUserName`).\n *\n * **No GSI projection.** Per ADR-018 § Decision, cross-cutting reads\n * are served by the main-table partition\n * `TID#<tenantId>#WORKSPACE#ID#<workspaceId>`; the GSI1/GSI2 catalog\n * is unchanged.\n *\n * @see ADR-018 § Access Pattern Coverage (#2)\n * @see .state/adr-018-implementation-guide.md § 1 (SK grammar) and § 2 (attribute set)\n * @see .claude/rules/data-layer-layout.md — projection writers live in operations, not here\n */\nexport const MembershipWorkspaceProjectionEntity = new Entity({\n model: {\n entity: \"membershipWorkspaceProjection\",\n service: \"control\",\n version: \"01\",\n },\n attributes: {\n /**\n * Tenant the workspace belongs to. Renders as the leading segment\n * of the base-table PK. Always required — the workspace partition\n * is tenant-scoped per ADR-011.\n */\n tenantId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Workspace partition discriminator. Renders as the trailing\n * segment of the base-table PK\n * (`TID#<tenantId>#WORKSPACE#ID#<workspaceId>`). Always required —\n * the projection has no meaning outside a workspace partition.\n */\n workspaceId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Pre-composed sort key — built by the operations-layer projection\n * writer via `buildMembershipWorkspaceProjectionSk`. The entity\n * stores the value verbatim so the SK grammar (pattern #2) is\n * owned by the operations layer, not duplicated here.\n */\n sk: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * User the membership links. Stored as a discriminating field so\n * consumers can hydrate the canonical User row via\n * `UserEntity.get({ id: userId, sk: \"CURRENT\" })` when the\n * projection's `summary` is insufficient.\n */\n userId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Membership canonical-record id. Stored as a discriminating field\n * so consumers can hydrate the canonical row via\n * `MembershipEntity.get({ tenantId, id: membershipId })` when the\n * projection's `summary` is insufficient.\n */\n membershipId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Summary projection (key display fields as JSON string: id,\n * displayName, status) — mirrored from the canonical Membership row\n * so workspace-partition queries do not need a BatchGet hop.\n */\n summary: {\n type: \"string\" as const,\n required: true,\n },\n /** Version id mirrored from the canonical Membership row. */\n vid: {\n type: \"string\" as const,\n required: true,\n },\n /** Last-updated timestamp mirrored from the canonical Membership row. */\n lastUpdated: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Denormalized User display name — required to compose the\n * pattern-#2 SK (`MEMBERSHIP#<normalizedUserName>#…`). Optional on\n * the schema because pre-TR-024 rows may not carry a display name;\n * the operations layer falls back to a sentinel when missing so\n * the SK still has a valid shape. The TR-023 rename-cascade\n * pipeline rewrites the SK on a User rename.\n */\n denormalizedUserName: {\n type: \"string\" as const,\n required: false,\n },\n },\n indexes: {\n /**\n * Base table: PK = TID#<tenantId>#WORKSPACE#ID#<workspaceId>,\n * SK = operation-supplied. Pattern #2 uses this index — the SK\n * encodes the entity-type prefix (`MEMBERSHIP#…`) so a\n * `Query(PK = TID#<tenantId>#WORKSPACE#ID#<workspaceId>, SK begins_with 'MEMBERSHIP#')`\n * returns every member projection for the workspace in normalized-\n * user-name sort order.\n */\n record: {\n pk: {\n field: \"PK\",\n composite: [\"tenantId\", \"workspaceId\"],\n template: \"TID#${tenantId}#WORKSPACE#ID#${workspaceId}\",\n },\n sk: {\n field: \"SK\",\n casing: \"none\" as const,\n composite: [\"sk\"],\n template: \"${sk}\",\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 {\n gsi1ShardAttribute,\n roleAssignmentGsi1skAttribute,\n} 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 /**\n * Derived GSI1 sort key — discriminator-first\n * `<roleId>#<normalizedUserName>#<id>` per ADR-018 pattern #8 so a\n * GSI1 query partitioned on the tenant can `begins_with('<roleId>#')`\n * to enumerate every user assigned to a given role, sorted by user\n * name. Falls back to `<lastUpdated>#<id>` when either component is\n * missing.\n */\n gsi1sk: roleAssignmentGsi1skAttribute,\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 * Denormalized display name of the linked Tenant, captured at row\n * last-write time. Promoted to a top-level attribute so the ADR-018\n * adjacency-list user-projection SK (pattern #5 —\n * `ROLEASSIGNMENT#TENANT#<normalizedRoleName>#<roleId>#TID#<tenantId>#<id>`)\n * can be composed from a top-level field instead of digging into the\n * `resource` JSON. Optional on the schema so pre-TR-024 rows do not\n * break; the operations-layer multi-write helper (#1010) makes the\n * field load-bearing at write time per TR-024 rule 2 (write-time\n * source = canonical Tenant.displayName).\n * @see TR-024 — Denormalized display-name attributes\n */\n denormalizedTenantName: {\n type: \"string\" as const,\n required: false,\n },\n /**\n * Denormalized display name of the linked User, captured at row\n * last-write time. Promoted to a top-level attribute so the ADR-018\n * adjacency-list canonical-record GSI1SK (pattern #8 —\n * `<roleId>#<normalizedUserName>#<id>`) and workspace-projection SK\n * (pattern #9) can be composed from a top-level field. Optional on\n * the schema so pre-TR-024 rows do not break; the operations-layer\n * multi-write helper (#1010) makes the field load-bearing at write\n * time per TR-024 rule 2 (write-time source = canonical\n * User.displayName).\n * @see TR-024 — Denormalized display-name attributes\n */\n denormalizedUserName: {\n type: \"string\" as const,\n required: false,\n },\n /**\n * Denormalized display name of the linked Role, captured at row\n * last-write time. Promoted to a top-level attribute so the ADR-018\n * adjacency-list user-projection SK (pattern #5 —\n * `ROLEASSIGNMENT#TENANT#<normalizedRoleName>#…`) can be composed from\n * a top-level field. Optional on the schema so pre-TR-024 rows do not\n * break; the operations-layer multi-write helper (#1010) makes the\n * field load-bearing at write time per TR-024 rule 2 (write-time\n * source = canonical Role.displayName).\n * @see TR-024 — Denormalized display-name attributes\n */\n denormalizedRoleName: {\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 `roleAssignmentGsi1skAttribute` — composes the\n * discriminator-first `<roleId>#<normalizedUserName>#<id>` shape per\n * ADR-018 pattern #8 (users with a specific role in a tenant, sorted\n * by user name); falls back to `<lastUpdated>#<id>` when either\n * component is missing. `casing: \"none\"` preserves the normalized\n * 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\";\n\n/**\n * RoleAssignment user-projection entity (single-table store, no GSI).\n *\n * **ADR-018 adjacency-list projection.** For every RoleAssignment write\n * the operations-layer multi-write helper writes one projection row\n * under the user partition so the user-rooted access pattern #5 is\n * served by a single base-table `Query` with no GSI hop. The SK encodes\n * a tenant-vs-workspace discriminator sub-prefix so both sub-lanes share\n * the user partition:\n *\n * | Sub-lane | When | PK | SK |\n * |---|---|---|---|\n * | tenant-level | `workspaceId` absent | `USER#ID#<userId>` | `ROLEASSIGNMENT#TENANT#<normalizedRoleName>#<roleId>#TID#<tenantId>#<id>` |\n * | workspace-level | `workspaceId` set | `USER#ID#<userId>` | `ROLEASSIGNMENT#WORKSPACE#<normalizedRoleName>#<roleId>#TID#<tenantId>#WID#<workspaceId>#<id>` |\n *\n * The SK shape is operation-owned: the operations-layer projection\n * writer composes the SK string via the\n * `buildRoleAssignmentUserProjectionSk*` helpers and supplies it on the\n * `sk` attribute. This entity stores the SK verbatim — no\n * `watch`/derived computation here — so the SK grammar (and any future\n * revision) lives in one place: the operations layer.\n *\n * Projection attribute set per ADR-018 § Projection attribute set and\n * the implementation guide § 2: `summary`, `vid`, `lastUpdated` (so\n * `Query(PK = USER#ID#<userId>, SK begins_with 'ROLEASSIGNMENT#')` is\n * self-sufficient — no BatchGet hop to the canonical record), plus the\n * projection-discriminating fields (`tenantId`, `roleId`,\n * `roleAssignmentId`, `userId`, `workspaceId?`) and TR-024 denormalized\n * display names (`denormalizedTenantName`, `denormalizedUserName`,\n * `denormalizedRoleName`).\n *\n * **No GSI projection.** Per ADR-018 § Decision, cross-cutting reads\n * are served by the main-table partition `USER#ID#<userId>`; the\n * GSI1/GSI2 catalog is unchanged.\n *\n * @see ADR-018 § Access Pattern Coverage (#5)\n * @see .state/adr-018-implementation-guide.md § 1 (SK grammar) and § 2 (attribute set)\n * @see .claude/rules/data-layer-layout.md — projection writers live in operations, not here\n */\nexport const RoleAssignmentUserProjectionEntity = new Entity({\n model: {\n entity: \"roleAssignmentUserProjection\",\n service: \"control\",\n version: \"01\",\n },\n attributes: {\n /**\n * User partition discriminator. Renders as `USER#ID#<userId>` on the\n * base-table PK. Always required — the projection has no meaning\n * outside a user partition.\n */\n userId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Pre-composed sort key — built by the operations-layer projection\n * writer via `buildRoleAssignmentUserProjectionSk*` helpers. The\n * entity stores the value verbatim so the SK grammar (tenant-lane\n * vs workspace-lane) is owned by the operations layer, not\n * duplicated here.\n */\n sk: {\n type: \"string\" as const,\n required: true,\n },\n /** Tenant in which the role assignment applies. Always required. */\n tenantId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Workspace the role assignment scopes to. Present iff the\n * projection row is the workspace-level sub-lane; absent for\n * tenant-level sub-lane rows.\n */\n workspaceId: {\n type: \"string\" as const,\n required: false,\n },\n /**\n * Role the assignment grants. Stored as a discriminating field so\n * `Query(PK = USER#ID#<userId>, SK begins_with 'ROLEASSIGNMENT#…')`\n * results carry the role id without a hop to the canonical row.\n */\n roleId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * RoleAssignment canonical-record id. Stored as a discriminating\n * field so consumers can hydrate the canonical row via\n * `RoleAssignmentEntity.get({ tenantId, id: roleAssignmentId })`\n * when the projection's `summary` is insufficient.\n */\n roleAssignmentId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Summary projection (key display fields as JSON string: id,\n * displayName, status) — mirrored from the canonical RoleAssignment\n * row so user-partition queries do not need a BatchGet hop.\n */\n summary: {\n type: \"string\" as const,\n required: true,\n },\n /** Version id mirrored from the canonical RoleAssignment row. */\n vid: {\n type: \"string\" as const,\n required: true,\n },\n /** Last-updated timestamp mirrored from the canonical RoleAssignment row. */\n lastUpdated: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Denormalized Tenant display name — mirrored from the canonical\n * RoleAssignment row per TR-024 rule 3 (canonical-record symmetry).\n * Optional on the schema because pre-TR-024 rows may not carry a\n * display name; the operations layer falls back gracefully when\n * missing.\n */\n denormalizedTenantName: {\n type: \"string\" as const,\n required: false,\n },\n /**\n * Denormalized User display name — mirrored from the canonical\n * RoleAssignment row per TR-024 rule 3 (canonical-record symmetry).\n * Carried on the projection so consumers can render the user's\n * display name without a hop to the User record.\n */\n denormalizedUserName: {\n type: \"string\" as const,\n required: false,\n },\n /**\n * Denormalized Role display name — required to compose the SK's\n * `<normalizedRoleName>` segment. Optional on the schema (pre-TR-024\n * rows fall back to a sentinel) but expected to be present at write\n * time per TR-024 rule 2 (write-time source =\n * canonical Role.displayName).\n */\n denormalizedRoleName: {\n type: \"string\" as const,\n required: false,\n },\n },\n indexes: {\n /**\n * Base table: PK = USER#ID#\\<userId\\>, SK = operation-supplied. Both\n * sub-lanes (tenant-level and workspace-level) use this same index —\n * the SK string encodes the lane discriminator\n * (`ROLEASSIGNMENT#TENANT#…` vs `ROLEASSIGNMENT#WORKSPACE#…`) so a\n * single `Query(PK = USER#ID#<userId>, SK begins_with 'ROLEASSIGNMENT#')`\n * returns both lanes interleaved.\n */\n record: {\n pk: {\n field: \"PK\",\n composite: [\"userId\"],\n template: \"USER#ID#${userId}\",\n },\n sk: {\n field: \"SK\",\n casing: \"none\" as const,\n composite: [\"sk\"],\n template: \"${sk}\",\n },\n },\n },\n});\n","import { Entity } from \"electrodb\";\n\n/**\n * RoleAssignment workspace-projection entity (single-table store, no GSI).\n *\n * **ADR-018 adjacency-list projection.** For every workspace-scoped\n * RoleAssignment the operations-layer multi-write helper writes one\n * projection row under the workspace partition so the workspace-rooted\n * access pattern #9 is served by a single base-table `Query` with no\n * GSI hop:\n *\n * | Pattern | When | PK | SK |\n * |---|---|---|---|\n * | #9 — users with a specific role in a workspace | `workspaceId` set | `TID#<tenantId>#WORKSPACE#ID#<workspaceId>` | `ROLEASSIGNMENT#<roleId>#<normalizedUserName>#USER#<userId>#<id>` |\n *\n * The SK is **discriminator-first** on the raw `<roleId>` (mirroring the\n * canonical GSI1SK from pattern #8): role id discriminates first so a\n * `begins_with('ROLEASSIGNMENT#<roleId>#')` filter returns every user\n * assigned to that role in the workspace, sorted alphabetically by\n * normalized user name. Omitting the `<roleId>#` segment\n * (`begins_with('ROLEASSIGNMENT#')`) returns every role assignment in\n * the workspace interleaved.\n *\n * The PK co-locates with the canonical Workspace record (`SK = CURRENT`)\n * and the Membership workspace-projection rows (pattern #2) so a single\n * `Query(PK = TID#<tenantId>#WORKSPACE#ID#<workspaceId>)` returns\n * workspace metadata + every member projection + every role-assignment\n * projection in one round trip — the admin workspace-dashboard read shape.\n *\n * The SK shape is operation-owned: the operations-layer projection\n * writer composes the SK string via the\n * `buildRoleAssignmentWorkspaceProjectionSk` helper and supplies it on\n * the `sk` attribute. This entity stores the SK verbatim — no\n * `watch`/derived computation here — so the SK grammar lives in one\n * place: the operations layer.\n *\n * Projection attribute set per ADR-018 § Projection attribute set and\n * the implementation guide § 2: `summary`, `vid`, `lastUpdated` (so\n * `Query(PK = TID#<tenantId>#WORKSPACE#ID#<workspaceId>, SK begins_with 'ROLEASSIGNMENT#')`\n * is self-sufficient — no BatchGet hop to the canonical record), plus\n * the projection-discriminating fields (`tenantId`, `workspaceId`,\n * `roleId`, `roleAssignmentId`, `userId`) and TR-024 denormalized\n * display names (`denormalizedUserName`, `denormalizedRoleName`).\n *\n * **Rename-cascade interaction (TR-023, Phase 6).** The SK uses the\n * raw `<roleId>` (rename-stable) for the discriminator and\n * `<normalizedUserName>` for the secondary sort. A Role rename does NOT\n * rewrite this SK; a User rename DOES (cascaded by the rename pipeline).\n *\n * **No GSI projection.** Per ADR-018 § Decision, cross-cutting reads\n * are served by the main-table partition\n * `TID#<tenantId>#WORKSPACE#ID#<workspaceId>`; the GSI1/GSI2 catalog\n * is unchanged.\n *\n * @see ADR-018 § Access Pattern Coverage (#9)\n * @see .state/adr-018-implementation-guide.md § 1 (SK grammar) and § 2 (attribute set)\n * @see .claude/rules/data-layer-layout.md — projection writers live in operations, not here\n */\nexport const RoleAssignmentWorkspaceProjectionEntity = new Entity({\n model: {\n entity: \"roleAssignmentWorkspaceProjection\",\n service: \"control\",\n version: \"01\",\n },\n attributes: {\n /**\n * Tenant the workspace belongs to. Renders as the leading segment\n * of the base-table PK. Always required — the workspace partition\n * is tenant-scoped per ADR-011.\n */\n tenantId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Workspace partition discriminator. Renders as the trailing\n * segment of the base-table PK\n * (`TID#<tenantId>#WORKSPACE#ID#<workspaceId>`). Always required —\n * the projection has no meaning outside a workspace partition.\n */\n workspaceId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Pre-composed sort key — built by the operations-layer projection\n * writer via `buildRoleAssignmentWorkspaceProjectionSk`. The entity\n * stores the value verbatim so the SK grammar (pattern #9) is\n * owned by the operations layer, not duplicated here.\n */\n sk: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * User the role assignment grants the role to. Stored as a\n * discriminating field so consumers can hydrate the canonical User\n * row via `UserEntity.get({ id: userId, sk: \"CURRENT\" })` when the\n * projection's `summary` is insufficient.\n */\n userId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Role the assignment grants. Stored as a discriminating field —\n * also rendered into the SK as the discriminator-first segment so\n * `begins_with('ROLEASSIGNMENT#<roleId>#')` filters one role.\n */\n roleId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * RoleAssignment canonical-record id. Stored as a discriminating\n * field so consumers can hydrate the canonical row via\n * `RoleAssignmentEntity.get({ tenantId, id: roleAssignmentId })`\n * when the projection's `summary` is insufficient.\n */\n roleAssignmentId: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Summary projection (key display fields as JSON string: id,\n * displayName, status) — mirrored from the canonical RoleAssignment\n * row so workspace-partition queries do not need a BatchGet hop.\n */\n summary: {\n type: \"string\" as const,\n required: true,\n },\n /** Version id mirrored from the canonical RoleAssignment row. */\n vid: {\n type: \"string\" as const,\n required: true,\n },\n /** Last-updated timestamp mirrored from the canonical RoleAssignment row. */\n lastUpdated: {\n type: \"string\" as const,\n required: true,\n },\n /**\n * Denormalized User display name — required to compose the\n * pattern-#9 SK (`ROLEASSIGNMENT#<roleId>#<normalizedUserName>#…`).\n * Optional on the schema because pre-TR-024 rows may not carry a\n * display name; the operations layer falls back to a sentinel when\n * missing so the SK still has a valid shape. The TR-023 rename-\n * cascade pipeline rewrites the SK on a User rename.\n */\n denormalizedUserName: {\n type: \"string\" as const,\n required: false,\n },\n /**\n * Denormalized Role display name — mirrored from the canonical\n * RoleAssignment row per TR-024 rule 3 (canonical-record symmetry).\n * Carried on the projection so consumers can render the role's\n * display name without a hop to the Role record. Not part of the\n * SK (pattern #9 sorts on `<normalizedUserName>`, not role name) —\n * a Role rename does NOT rewrite this SK.\n */\n denormalizedRoleName: {\n type: \"string\" as const,\n required: false,\n },\n },\n indexes: {\n /**\n * Base table: PK = TID#<tenantId>#WORKSPACE#ID#<workspaceId>,\n * SK = operation-supplied. Pattern #9 uses this index — the SK\n * encodes the entity-type prefix and discriminator-first roleId\n * (`ROLEASSIGNMENT#<roleId>#…`) so\n * `Query(PK = TID#<tenantId>#WORKSPACE#ID#<workspaceId>, SK begins_with 'ROLEASSIGNMENT#<roleId>#')`\n * returns every user-assignment for that role in the workspace, sorted\n * by normalized user name.\n */\n record: {\n pk: {\n field: \"PK\",\n composite: [\"tenantId\", \"workspaceId\"],\n template: \"TID#${tenantId}#WORKSPACE#ID#${workspaceId}\",\n },\n sk: {\n field: \"SK\",\n casing: \"none\" as const,\n composite: [\"sk\"],\n template: \"${sk}\",\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 /**\n * TR-022 / ADR-018 lifecycle state for the cascade pipeline.\n *\n * - `active` (or undefined) — normal, readable state.\n * - `deleting` — intermediate state set synchronously by the\n * hard-delete API entry point. The owning-delete cascade state\n * machine fans out from this transition (DynamoDB stream →\n * `control-plane.owning-delete.v1` → Step Functions). Readers MUST\n * short-circuit on `deleting` so partial cascades stay invisible.\n * - `deleted-failed` — terminal failure state set by the cascade\n * finalize Lambda when the cascade run fails irrecoverably.\n * Operators recover by re-running the cascade or by direct\n * intervention.\n *\n * The cascade finalize step deletes the canonical record conditional\n * on `lifecycleState = \"deleting\"`; on replay the conditional check\n * fails and the finalize step treats that as a no-op success.\n */\n lifecycleState: {\n type: [\"active\", \"deleting\", \"deleted-failed\"] 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 /**\n * TR-022 / ADR-018 lifecycle state for the cascade pipeline.\n *\n * - `active` (or undefined) — normal, readable state.\n * - `deleting` — intermediate state set synchronously by the\n * hard-delete API entry point. The owning-delete cascade state\n * machine fans out from this transition (DynamoDB stream →\n * `control-plane.owning-delete.v1` → Step Functions). Readers MUST\n * short-circuit on `deleting` so partial cascades stay invisible.\n * - `deleted-failed` — terminal failure state set by the cascade\n * finalize Lambda when the cascade run fails irrecoverably.\n * Operators recover by re-running the cascade or by direct\n * intervention.\n *\n * The cascade finalize step deletes the canonical record conditional\n * on `lifecycleState = \"deleting\"`; on replay the conditional check\n * fails and the finalize step treats that as a no-op success.\n */\n lifecycleState: {\n type: [\"active\", \"deleting\", \"deleted-failed\"] 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","/**\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/** Thrown when the caller is authenticated but not authorized for the requested action. */\nexport class ForbiddenError extends DomainError {\n constructor(\n message: string,\n options?: { cause?: unknown; details?: unknown },\n ) {\n super(message, \"FORBIDDEN\", 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 if (err instanceof ForbiddenError) return 403;\n return null;\n}\n","import {\n assertLinkedDataIdentityCardinality,\n extractSummary,\n type Extension,\n type FhirResourceLike,\n LinkedDataIdentityCardinalityError,\n} from \"@openhi/types\";\nimport {\n buildMembershipUserProjectionItem,\n extractReferenceSlug,\n} from \"./membership-user-projection\";\nimport { buildMembershipWorkspaceProjectionItem } from \"./membership-workspace-projection\";\nimport { getDynamoControlService } from \"../../../dynamo/dynamo-control-service\";\nimport { ValidationError } from \"../../../errors\";\nimport { OpenHiContext } from \"../../../openhi-context\";\nimport { extractDenormalizedReferenceDisplay } from \"../denormalized-display-names\";\nimport { assertWorkspaceInTenantOperation } from \"../membership-constraints/assert-workspace-in-tenant-operation\";\nimport {\n executeMultiWrite,\n type MultiWriteTriple,\n} from \"../multi-write-operation\";\n\nexport interface MembershipCreateParams {\n context: OpenHiContext;\n body: { id?: string; resource?: Record<string, unknown> | string };\n tableName?: string;\n}\n\nexport interface MembershipCreateResult {\n id: string;\n resource: { resourceType: string; id: string; [key: string]: unknown };\n meta: { lastUpdated: string; versionId: string };\n}\n\nexport async function createMembershipOperation(\n params: MembershipCreateParams,\n): Promise<MembershipCreateResult> {\n const { context, body, tableName } = params;\n const service = getDynamoControlService(tableName);\n\n const id = body.id ?? `membership-${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: \"Membership\", id, ...parsedResource };\n\n let linkedDataIdentityRef: string | undefined;\n try {\n const ext = assertLinkedDataIdentityCardinality(\n resource as { extension?: Array<Extension> },\n );\n linkedDataIdentityRef = ext?.valueReference?.reference;\n } catch (e) {\n if (e instanceof LinkedDataIdentityCardinalityError) {\n throw new ValidationError(e.message, { cause: e });\n }\n throw e;\n }\n\n // TR-024 denormalized display-name attributes. The authoritative\n // write-time source per TR-024 rule 2 is the canonical Tenant / User\n // record's `displayName`. Until the carrier-record-lookup pass lands\n // (#1010 follow-up), the foundational fallback (#1009) reads the\n // FHIR Reference.display values supplied on the resource so the\n // adjacency-list projection writer here can compose SKs from\n // top-level attributes.\n const resourceRecord = resource as Record<string, unknown>;\n const denormalizedTenantName = extractDenormalizedReferenceDisplay(\n resourceRecord,\n \"tenant\",\n );\n const denormalizedUserName = extractDenormalizedReferenceDisplay(\n resourceRecord,\n \"user\",\n );\n const denormalizedWorkspaceName = extractDenormalizedReferenceDisplay(\n resourceRecord,\n \"workspace\",\n );\n\n const summary = JSON.stringify(extractSummary(resource as FhirResourceLike));\n\n // ADR-018 patterns #2 / #3 / #4 — user- and workspace-partition\n // projection rows. The projection's discriminating fields come from\n // the same FHIR Reference shape the canonical row reads, so the\n // canonical and projection writes always agree on the underlying\n // user / workspace identifiers. Missing identifiers (no user\n // reference at all) skip the user-projection; tenant-scoped\n // Memberships (no workspaceId) skip the workspace-projection — the\n // canonical row still lands either way.\n const userIdFromResource = extractReferenceSlug(resourceRecord, \"user\");\n const workspaceIdFromResource = extractReferenceSlug(\n resourceRecord,\n \"workspace\",\n );\n\n // ADR 2026-03-13-02 § 2 Consequences/Negative — when the resource\n // names a workspace, that workspace must belong to the referenced\n // tenant. Prefer the resource's `tenant.reference` (the issue's\n // \"referenced tenant\" wording) and fall back to the context tenant\n // when the body omits the reference. The check fires before any\n // write so the constraint is enforced atomically with respect to\n // the canonical row.\n if (workspaceIdFromResource !== undefined) {\n const tenantIdFromResource = extractReferenceSlug(resourceRecord, \"tenant\");\n const referencedTenantId = tenantIdFromResource ?? context.tenantId;\n await assertWorkspaceInTenantOperation({\n tenantId: referencedTenantId,\n workspaceId: workspaceIdFromResource,\n tableName,\n });\n }\n\n const userProjectionItem =\n userIdFromResource !== undefined\n ? buildMembershipUserProjectionItem({\n tenantId: context.tenantId,\n userId: userIdFromResource,\n workspaceId: workspaceIdFromResource,\n membershipId: id,\n summary,\n vid,\n lastUpdated,\n denormalizedTenantName,\n denormalizedUserName,\n denormalizedWorkspaceName,\n })\n : undefined;\n\n const workspaceProjectionItem =\n userIdFromResource !== undefined && workspaceIdFromResource !== undefined\n ? buildMembershipWorkspaceProjectionItem({\n tenantId: context.tenantId,\n workspaceId: workspaceIdFromResource,\n userId: userIdFromResource,\n membershipId: id,\n summary,\n vid,\n lastUpdated,\n denormalizedUserName,\n })\n : undefined;\n\n const canonicalItem = {\n tenantId: context.tenantId,\n id,\n resource: JSON.stringify(resource),\n summary,\n vid,\n lastUpdated,\n linkedDataIdentityRef,\n denormalizedTenantName,\n denormalizedUserName,\n };\n\n const triples: Array<MultiWriteTriple> = [\n { entity: \"membership\", action: \"put\", item: canonicalItem },\n ];\n if (userProjectionItem) {\n triples.push({\n entity: \"membershipUserProjection\",\n action: \"put\",\n item: userProjectionItem as unknown as Record<string, unknown>,\n });\n }\n if (workspaceProjectionItem) {\n triples.push({\n entity: \"membershipWorkspaceProjection\",\n action: \"put\",\n item: workspaceProjectionItem as unknown as Record<string, unknown>,\n });\n }\n\n await executeMultiWrite({ service, triples });\n\n return {\n id,\n resource,\n meta: { lastUpdated, versionId: vid },\n };\n}\n","/**\n * Membership user-projection composer.\n *\n * Owns the SK grammar for ADR-018 patterns #3 and #4 and assembles the\n * projection-row payloads consumed by the membership create / update /\n * delete operations. The {@link MembershipUserProjectionEntity} stores\n * the SK verbatim — the grammar lives here so the operations layer is\n * the single source of truth for projection-row shape (per\n * `.claude/rules/data-layer-layout.md`).\n *\n * SK grammar:\n *\n * - **Pattern #3** (tenant sub-lane, `workspaceId` absent):\n * `MEMBERSHIP#TENANT#<normalizedTenantName>#TID#<tenantId>#<membershipId>`\n * - **Pattern #4** (workspace sub-lane, `workspaceId` set):\n * `MEMBERSHIP#WORKSPACE#TID#<tenantId>#<normalizedWorkspaceName>#WID#<workspaceId>#<membershipId>`\n *\n * Both patterns share the user partition `PK = USER#ID#<userId>` so\n * `Query(PK = USER#ID#<userId>, SK begins_with 'MEMBERSHIP#')` returns\n * both lanes interleaved.\n *\n * @see ADR-018 § Access Pattern Coverage (patterns #3 and #4)\n * @see .state/adr-018-implementation-guide.md § 1 (SK grammar) and § 2 (attribute set)\n */\n\nimport { normalizeLabel } from \"@openhi/types\";\n\n/**\n * Sentinel rendered into the SK when the source display name is missing\n * or empty. Keeps the SK shape stable so a `begins_with` prefix query\n * still matches the row; the rename-cascade pipeline (TR-023) will\n * rewrite the SK once the carrier display name lands. Matches the\n * `gsi1skAttribute` defensive posture — a missing source field never\n * produces a malformed key.\n */\nconst MISSING_NAME_SENTINEL = \"-\";\n\n/** Inputs to compose a Membership user-projection row. */\nexport interface MembershipUserProjectionInput {\n readonly tenantId: string;\n readonly userId: string;\n readonly workspaceId?: string;\n readonly membershipId: string;\n readonly summary: string;\n readonly vid: string;\n readonly lastUpdated: string;\n readonly denormalizedTenantName?: string;\n readonly denormalizedUserName?: string;\n readonly denormalizedWorkspaceName?: string;\n}\n\n/** A projection-row payload ready for `multi-write` consumption. */\nexport interface MembershipUserProjectionItem {\n readonly userId: string;\n readonly sk: string;\n readonly tenantId: string;\n readonly workspaceId?: string;\n readonly membershipId: string;\n readonly summary: string;\n readonly vid: string;\n readonly lastUpdated: string;\n readonly denormalizedTenantName?: string;\n readonly denormalizedUserName?: string;\n readonly denormalizedWorkspaceName?: string;\n}\n\n/**\n * Compose the SK for ADR-018 pattern #3 (tenant sub-lane). The\n * `<normalizedTenantName>` segment sorts memberships alphabetically by\n * tenant name within the user's partition. Missing `denormalizedTenantName`\n * falls back to {@link MISSING_NAME_SENTINEL} so the SK shape stays valid\n * pre-rename-cascade.\n */\nexport function buildMembershipUserProjectionSkTenantLane(params: {\n readonly tenantId: string;\n readonly membershipId: string;\n readonly denormalizedTenantName?: string;\n}): string {\n const normalizedTenantName =\n typeof params.denormalizedTenantName === \"string\" &&\n params.denormalizedTenantName.length > 0\n ? normalizeLabel(params.denormalizedTenantName)\n : MISSING_NAME_SENTINEL;\n return `MEMBERSHIP#TENANT#${normalizedTenantName}#TID#${params.tenantId}#${params.membershipId}`;\n}\n\n/**\n * Compose the SK for ADR-018 pattern #4 (workspace sub-lane). `tenantId`\n * appears before `<normalizedWorkspaceName>` so a\n * `begins_with('MEMBERSHIP#WORKSPACE#TID#<tenantId>#')` query filters\n * by one tenant. Missing `denormalizedWorkspaceName` falls back to\n * {@link MISSING_NAME_SENTINEL}.\n */\nexport function buildMembershipUserProjectionSkWorkspaceLane(params: {\n readonly tenantId: string;\n readonly workspaceId: string;\n readonly membershipId: string;\n readonly denormalizedWorkspaceName?: string;\n}): string {\n const normalizedWorkspaceName =\n typeof params.denormalizedWorkspaceName === \"string\" &&\n params.denormalizedWorkspaceName.length > 0\n ? normalizeLabel(params.denormalizedWorkspaceName)\n : MISSING_NAME_SENTINEL;\n return `MEMBERSHIP#WORKSPACE#TID#${params.tenantId}#${normalizedWorkspaceName}#WID#${params.workspaceId}#${params.membershipId}`;\n}\n\n/**\n * Builds the projection item for the access lane implied by the input.\n * Pattern #3 when `workspaceId` is absent or empty; pattern #4 otherwise.\n * Returns `undefined` when `userId` is missing — a Membership without a\n * linked user cannot project onto the user partition.\n */\nexport function buildMembershipUserProjectionItem(\n input: MembershipUserProjectionInput,\n): MembershipUserProjectionItem | undefined {\n if (!input.userId || input.userId.length === 0) {\n return undefined;\n }\n const hasWorkspace =\n typeof input.workspaceId === \"string\" && input.workspaceId.length > 0;\n const sk = hasWorkspace\n ? buildMembershipUserProjectionSkWorkspaceLane({\n tenantId: input.tenantId,\n workspaceId: input.workspaceId as string,\n membershipId: input.membershipId,\n denormalizedWorkspaceName: input.denormalizedWorkspaceName,\n })\n : buildMembershipUserProjectionSkTenantLane({\n tenantId: input.tenantId,\n membershipId: input.membershipId,\n denormalizedTenantName: input.denormalizedTenantName,\n });\n return {\n userId: input.userId,\n sk,\n tenantId: input.tenantId,\n workspaceId: hasWorkspace ? input.workspaceId : undefined,\n membershipId: input.membershipId,\n summary: input.summary,\n vid: input.vid,\n lastUpdated: input.lastUpdated,\n denormalizedTenantName: input.denormalizedTenantName,\n denormalizedUserName: input.denormalizedUserName,\n denormalizedWorkspaceName: hasWorkspace\n ? input.denormalizedWorkspaceName\n : undefined,\n };\n}\n\n/**\n * Extracts a FHIR `Reference` slug — the segment after the final `/`.\n * Returns `undefined` when the reference is missing or malformed so\n * callers fall back gracefully (matches the defensive posture in\n * `extractRoleId` / `extractDenormalizedReferenceDisplay`).\n */\nexport function extractReferenceSlug(\n resource: Record<string, unknown>,\n fieldName: string,\n): string | undefined {\n const field = resource[fieldName];\n if (!field || typeof field !== \"object\") {\n return undefined;\n }\n const reference = (field as { reference?: unknown }).reference;\n if (typeof reference !== \"string\" || reference.length === 0) {\n return undefined;\n }\n const slash = reference.lastIndexOf(\"/\");\n const tail = slash >= 0 ? reference.slice(slash + 1) : reference;\n return tail.length > 0 ? tail : undefined;\n}\n","/**\n * Membership workspace-projection composer.\n *\n * Owns the SK grammar for ADR-018 pattern #2 and assembles the\n * projection-row payload consumed by the membership create / update /\n * delete operations. The {@link MembershipWorkspaceProjectionEntity}\n * stores the SK verbatim — the grammar lives here so the operations\n * layer is the single source of truth for projection-row shape (per\n * `.claude/rules/data-layer-layout.md`).\n *\n * SK grammar:\n *\n * - **Pattern #2** (users in a workspace, sorted by user name —\n * workspace-scoped Memberships only):\n * `MEMBERSHIP#<normalizedUserName>#USER#<userId>#<membershipId>`\n *\n * The projection co-locates with the canonical Workspace record under\n * `PK = TID#<tenantId>#WORKSPACE#ID#<workspaceId>` so\n * `Query(PK = TID#<tenantId>#WORKSPACE#ID#<workspaceId>, SK begins_with 'MEMBERSHIP#')`\n * returns workspace metadata + every member projection in one round\n * trip. Tenant-scoped Memberships (no `workspaceId`) skip this\n * projection entirely.\n *\n * @see ADR-018 § Access Pattern Coverage (pattern #2)\n * @see .state/adr-018-implementation-guide.md § 1 (SK grammar) and § 2 (attribute set)\n */\n\nimport { normalizeLabel } from \"@openhi/types\";\n\n/**\n * Sentinel rendered into the SK when the source display name is missing\n * or empty. Keeps the SK shape stable so a `begins_with` prefix query\n * still matches the row; the rename-cascade pipeline (TR-023) will\n * rewrite the SK once the carrier display name lands. Mirrors the\n * sibling user-projection composer's defensive posture — a missing\n * source field never produces a malformed key.\n */\nconst MISSING_NAME_SENTINEL = \"-\";\n\n/** Inputs to compose a Membership workspace-projection row. */\nexport interface MembershipWorkspaceProjectionInput {\n readonly tenantId: string;\n readonly workspaceId: string;\n readonly userId: string;\n readonly membershipId: string;\n readonly summary: string;\n readonly vid: string;\n readonly lastUpdated: string;\n readonly denormalizedUserName?: string;\n}\n\n/** A projection-row payload ready for `multi-write` consumption. */\nexport interface MembershipWorkspaceProjectionItem {\n readonly tenantId: string;\n readonly workspaceId: string;\n readonly sk: string;\n readonly userId: string;\n readonly membershipId: string;\n readonly summary: string;\n readonly vid: string;\n readonly lastUpdated: string;\n readonly denormalizedUserName?: string;\n}\n\n/**\n * Compose the SK for ADR-018 pattern #2. The `<normalizedUserName>`\n * segment sorts memberships alphabetically by user name within the\n * workspace partition. The trailing `USER#<userId>#<membershipId>`\n * disambiguates rows when two memberships share a normalized user name\n * (homonyms) and supports a per-user lookup via\n * `begins_with('MEMBERSHIP#<normalizedUserName>#USER#<userId>#')`.\n * Missing `denormalizedUserName` falls back to\n * {@link MISSING_NAME_SENTINEL} so the SK shape stays valid\n * pre-rename-cascade.\n */\nexport function buildMembershipWorkspaceProjectionSk(params: {\n readonly userId: string;\n readonly membershipId: string;\n readonly denormalizedUserName?: string;\n}): string {\n const normalizedUserName =\n typeof params.denormalizedUserName === \"string\" &&\n params.denormalizedUserName.length > 0\n ? normalizeLabel(params.denormalizedUserName)\n : MISSING_NAME_SENTINEL;\n return `MEMBERSHIP#${normalizedUserName}#USER#${params.userId}#${params.membershipId}`;\n}\n\n/**\n * Builds the projection item for a workspace-scoped Membership.\n * Returns `undefined` when `workspaceId` or `userId` is missing —\n * tenant-scoped Memberships (no workspaceId) skip the workspace\n * projection entirely, and a Membership without a linked user cannot\n * project onto the workspace partition.\n */\nexport function buildMembershipWorkspaceProjectionItem(\n input: MembershipWorkspaceProjectionInput,\n): MembershipWorkspaceProjectionItem | undefined {\n if (!input.workspaceId || input.workspaceId.length === 0) {\n return undefined;\n }\n if (!input.userId || input.userId.length === 0) {\n return undefined;\n }\n const sk = buildMembershipWorkspaceProjectionSk({\n userId: input.userId,\n membershipId: input.membershipId,\n denormalizedUserName: input.denormalizedUserName,\n });\n return {\n tenantId: input.tenantId,\n workspaceId: input.workspaceId,\n sk,\n userId: input.userId,\n membershipId: input.membershipId,\n summary: input.summary,\n vid: input.vid,\n lastUpdated: input.lastUpdated,\n denormalizedUserName: input.denormalizedUserName,\n };\n}\n","/**\n * Helpers that capture denormalized display-name attributes from an\n * incoming FHIR Reference on Membership and RoleAssignment resources.\n *\n * **Foundational implementation for TR-024.** ADR-018 § Implementation\n * Notes and TR-024 § Recommendation pin the authoritative write-time\n * source as the carrier entity's canonical `displayName` — i.e. the\n * operations layer reads the canonical Tenant / User / Role record\n * by id and copies its display name into the relationship's\n * `denormalized<CarrierEntity>Name` field on the same\n * `TransactWriteItems`. That contract is owned by the operations-layer\n * multi-write helper filed as #1010.\n *\n * This module is the **foundational fallback** that issue #1009 uses\n * before #1010 lands: it reads the display string a client already\n * supplies on the resource's `Reference.display` field. The fallback\n * keeps Membership / RoleAssignment write paths populating the new\n * top-level attributes today (so adjacency-list projection writers\n * downstream can rely on them) while letting #1010 own the canonical-\n * row lookup without re-plumbing the write paths.\n *\n * @see TR-024 — Denormalized display-name attributes\n * @see ADR-018 § Implementation Notes\n */\n\n/**\n * Returns the trimmed display string from `resource[fieldName].display`\n * when present and non-empty; otherwise returns `undefined`. Used by the\n * Membership and RoleAssignment create / update operations to populate\n * top-level `denormalized<CarrierEntity>Name` attributes from incoming\n * FHIR Reference fields.\n *\n * Field name maps to the FHIR field on the resource:\n * - `Membership.tenant` → `\"tenant\"`\n * - `Membership.user` → `\"user\"`\n * - `RoleAssignment.tenant` → `\"tenant\"`\n * - `RoleAssignment.user` → `\"user\"`\n * - `RoleAssignment.role` → `\"role\"`\n *\n * Guards against malformed payloads (non-object `field`, non-string\n * `display`, empty strings after trim) so a single bad write never\n * blocks an entity put — matching the same defensive posture\n * `gsi1skAttribute` takes for the `resource` JSON parse.\n */\nexport function extractDenormalizedReferenceDisplay(\n resource: Record<string, unknown>,\n fieldName: string,\n): string | undefined {\n const field = resource[fieldName];\n if (!field || typeof field !== \"object\") {\n return undefined;\n }\n const display = (field as { display?: unknown }).display;\n if (typeof display !== \"string\") {\n return undefined;\n }\n const trimmed = display.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n","import { getDynamoControlService } from \"../../../dynamo/dynamo-control-service\";\nimport { ConflictError } from \"../../../errors\";\n\n/** Inputs to {@link assertWorkspaceInTenantOperation}. */\nexport interface AssertWorkspaceInTenantParams {\n /** Tenant the workspace must belong to. */\n readonly tenantId: string;\n /** Workspace id that must exist under `tenantId`. */\n readonly workspaceId: string;\n /** Optional table-name override; resolved via env when omitted. */\n readonly tableName?: string;\n}\n\n/**\n * Throws {@link ConflictError} when no `Workspace` with id `workspaceId`\n * exists under `tenantId`.\n *\n * Implementation: a single base-table `get` against the Workspace entity\n * (`PK = TID#<tenantId>#WORKSPACE#ID#<workspaceId>, SK = CURRENT`). The\n * workspace's tenant is encoded into the PK by construction, so a hit\n * *is* the constraint check — there is no separate `managingOrganization`\n * comparison required.\n *\n * @see ADR 2026-03-13-02 § 2 — Consequences/Negative\n */\nexport async function assertWorkspaceInTenantOperation(\n params: AssertWorkspaceInTenantParams,\n): Promise<void> {\n const { tenantId, workspaceId, tableName } = params;\n const service = getDynamoControlService(tableName);\n\n const { data: item } = await service.entities.workspace\n .get({ tenantId, id: workspaceId, sk: \"CURRENT\" })\n .go();\n\n if (!item) {\n throw new ConflictError(\n `Workspace ${workspaceId} does not belong to tenant ${tenantId}; the workspace must be created in the referenced tenant before this resource can reference it.`,\n { details: { tenantId, workspaceId } },\n );\n }\n}\n","/**\n * Operations-layer multi-write helper for the control plane.\n *\n * Per ADR-018 § Implementation Notes and the ADR-018 implementation\n * guide § 3, every cross-entity mutation in the control plane (canonical\n * record + adjacency-list projections) MUST flow through this helper.\n * Lambda handlers call operations; operations call this helper; nothing\n * under `data/operations/control/` may call `service.transaction.write`\n * directly after #1010 lands.\n *\n * The helper accepts an array of `{ entity, action, item }` triples,\n * maps each one to ElectroDB's transaction-write builder, and submits\n * the batch via `TransactWriteItems` — all-or-nothing atomicity. It\n * enforces the 100-item DynamoDB transaction ceiling at the helper\n * boundary and surfaces conditional-check / transaction-conflict\n * failures as typed domain errors so REST adapters can map to the\n * right HTTP status (409 / 400 / 500).\n *\n * Idempotency belongs to the caller — every call attempts a fresh\n * `TransactWriteItems`. Callers compose conditional expressions\n * (e.g. `vid` matches, `attribute_not_exists(PK)`) per triple via\n * ElectroDB's `where` builder; the helper does not invent conditions.\n *\n * Per ADR-018 Open Item Follow-up #2 the implementation uses ElectroDB's\n * `service.transaction.write` rather than a hand-rolled\n * `TransactWriteItemsCommand`. Reasons: (a) ElectroDB derives the\n * `TransactWriteItem` payload (Item attributes, GSI keys, watch-driven\n * fields) from the entity schema — hand-rolling would duplicate the\n * watch/derive logic and silently drift on schema changes; (b) it\n * preserves the existing single-write call-site idiom\n * (`service.entities.<x>.put({...}).go()` reads almost identically to\n * `entities.<x>.put({...}).commit()` inside the txn builder), keeping\n * the operations layer ergonomic; (c) ElectroDB's `canceled` flag and\n * `ElectroValidationError` propagation give us a single typed handle on\n * cancellation-vs-validation. We can drop to raw `TransactWriteItems`\n * later if a future operation needs DDB features ElectroDB has not yet\n * surfaced.\n *\n * @see ADR-018 § Implementation Notes\n * @see .state/adr-018-implementation-guide.md § 3 — Multi-Write Helper API Contract\n * @see .claude/rules/data-layer-layout.md\n */\n\nimport type { Entity, Service } from \"electrodb\";\nimport { ConflictError, DomainError, ValidationError } from \"../../errors\";\n\n/**\n * Maximum items allowed in a single DynamoDB `TransactWriteItems`\n * call (AWS, raised from 25 → 100 on 2024-09-23). The helper enforces\n * this ceiling at the boundary so callers do not silently lose the\n * tail of an oversized batch when DDB rejects the call.\n */\nexport const TRANSACT_WRITE_ITEM_LIMIT = 100 as const;\n\n/** Supported actions on a multi-write triple. */\nexport type MultiWriteAction = \"put\" | \"create\" | \"delete\";\n\n/**\n * A single entry in a multi-write call: which entity to act on, the\n * action, and the per-action payload.\n *\n * - `put` / `create` — `item` is the full record (matches\n * `entity.put(item)` / `entity.create(item)` shape).\n * - `delete` — `item` is the key composite (matches\n * `entity.delete(key)` shape).\n *\n * `entity` is a string key into the service's `entities` map (e.g.\n * `\"membership\"`, `\"tenant\"`). Using a string key avoids leaking the\n * transaction-bound entity reference across the helper boundary —\n * ElectroDB's `service.transaction.write(fn)` only honours entity\n * references that the closure-provided `entities` argument exposes.\n */\nexport interface MultiWriteTriple<EntityKey extends string = string> {\n readonly entity: EntityKey;\n readonly action: MultiWriteAction;\n readonly item: Record<string, unknown>;\n}\n\n/** A service object exposing the ElectroDB `transaction.write` builder. */\ntype ServiceLike = Pick<\n Service<Record<string, Entity<any, any, any, any>>>,\n \"transaction\"\n>;\n\n/** Parameters for {@link executeMultiWrite}. */\nexport interface ExecuteMultiWriteParams<EntityKey extends string = string> {\n /**\n * ElectroDB `Service` (control-plane or data-plane) exposing\n * `transaction.write` and the entity set the triples reference.\n * Inject via `getDynamoControlService(tableName)` /\n * `getDynamoDataService(tableName)` — matches the service-factory\n * pattern every other operation under `data/operations/` uses.\n */\n readonly service: ServiceLike;\n /**\n * The triples to commit atomically. Order is preserved on the wire\n * (ElectroDB submits them in the same order); duplicates are not\n * de-duplicated by the helper.\n */\n readonly triples: ReadonlyArray<MultiWriteTriple<EntityKey>>;\n /** Optional idempotency token forwarded to ElectroDB. */\n readonly token?: string;\n}\n\n/** Successful multi-write result. */\nexport interface ExecuteMultiWriteResult {\n /** Number of triples committed. */\n readonly itemsWritten: number;\n /**\n * `canceled` flag returned by ElectroDB. Always `false` on the\n * success path — failures throw {@link ConflictError} or\n * {@link ValidationError}. Surfaced for completeness so callers can\n * assert on it in tests if they wish.\n */\n readonly canceled: false;\n}\n\n/**\n * Submits `triples` as a single `TransactWriteItems` via ElectroDB's\n * `service.transaction.write` builder. All-or-nothing: every triple\n * lands or none does.\n *\n * Throws:\n * - {@link ValidationError} when `triples` is empty, exceeds the\n * {@link TRANSACT_WRITE_ITEM_LIMIT}, references an entity that the\n * service does not expose, or carries an unsupported `action`.\n * - {@link ConflictError} when DynamoDB cancels the transaction\n * (e.g. `ConditionalCheckFailed`, `TransactionConflict`,\n * `ProvisionedThroughputExceeded`). The original ElectroDB error\n * (carrying `CancellationReasons`) is attached as `cause`.\n * - The original {@link DomainError} on rethrow if the caller's own\n * validation hook surfaces one (e.g. nested ValidationError).\n *\n * Note on `update` / `patch` actions: not yet supported by the triple\n * shape because ElectroDB's transaction-write builder structures them\n * as `entity.update(key).set({...}).commit()` (key + delta), which\n * does not flatten cleanly into a single `item` payload. Add a\n * separate triple variant when the first consumer needs it; today\n * every ADR-018 multi-write is a `put` (canonical + projections) or a\n * `delete` (cascade rewriter). See ADR-018 § Open Item Follow-up #2.\n */\nexport async function executeMultiWrite<EntityKey extends string = string>(\n params: ExecuteMultiWriteParams<EntityKey>,\n): Promise<ExecuteMultiWriteResult> {\n const { service, triples, token } = params;\n\n if (triples.length === 0) {\n throw new ValidationError(\n \"executeMultiWrite called with zero triples; at least one triple is required\",\n );\n }\n if (triples.length > TRANSACT_WRITE_ITEM_LIMIT) {\n throw new ValidationError(\n `executeMultiWrite received ${triples.length} triples; DynamoDB TransactWriteItems is limited to ${TRANSACT_WRITE_ITEM_LIMIT} items per call`,\n {\n details: {\n itemsRequested: triples.length,\n limit: TRANSACT_WRITE_ITEM_LIMIT,\n },\n },\n );\n }\n\n for (const [index, triple] of triples.entries()) {\n if (!triple || typeof triple !== \"object\") {\n throw new ValidationError(\n `executeMultiWrite triple at index ${index} is not an object`,\n );\n }\n if (typeof triple.entity !== \"string\" || triple.entity.length === 0) {\n throw new ValidationError(\n `executeMultiWrite triple at index ${index} is missing a non-empty 'entity' key`,\n );\n }\n if (!isSupportedAction(triple.action)) {\n throw new ValidationError(\n `executeMultiWrite triple at index ${index} has unsupported action '${String(\n triple.action,\n )}'; supported: 'put' | 'create' | 'delete'`,\n );\n }\n if (!triple.item || typeof triple.item !== \"object\") {\n throw new ValidationError(\n `executeMultiWrite triple at index ${index} is missing an 'item' payload`,\n );\n }\n }\n\n let result: { canceled: boolean; data: unknown };\n try {\n result = await service.transaction\n .write((entities: Record<string, any>) =>\n triples.map((triple, index) => {\n const transactEntity = entities[triple.entity];\n if (transactEntity === undefined) {\n throw new ValidationError(\n `executeMultiWrite triple at index ${index} references unknown entity '${triple.entity}'; ensure the service exposes it`,\n );\n }\n switch (triple.action) {\n case \"put\":\n return transactEntity.put(triple.item).commit();\n case \"create\":\n return transactEntity.create(triple.item).commit();\n case \"delete\":\n return transactEntity.delete(triple.item).commit();\n default:\n // Exhaustiveness guard; pre-flight validates this already.\n throw new ValidationError(\n `executeMultiWrite triple at index ${index} has unsupported action '${String(\n (triple as MultiWriteTriple).action,\n )}'`,\n );\n }\n }),\n )\n .go(token === undefined ? undefined : { token });\n } catch (err) {\n // Pre-flight ValidationErrors thrown inside the builder bubble\n // through unchanged so callers see a 400, not a 409.\n if (err instanceof DomainError) {\n throw err;\n }\n throw new ConflictError(buildCancellationMessage(err), {\n cause: err,\n details: extractCancellationReasons(err),\n });\n }\n\n if (result.canceled) {\n throw new ConflictError(\n \"TransactWriteItems was canceled by DynamoDB (check CancellationReasons on the cause for details)\",\n { details: { canceled: true, data: result.data } },\n );\n }\n\n return { itemsWritten: triples.length, canceled: false };\n}\n\nfunction isSupportedAction(value: unknown): value is MultiWriteAction {\n return value === \"put\" || value === \"create\" || value === \"delete\";\n}\n\nfunction buildCancellationMessage(err: unknown): string {\n if (err instanceof Error && err.message) {\n return `TransactWriteItems failed: ${err.message}`;\n }\n return \"TransactWriteItems failed (no error message available)\";\n}\n\nfunction extractCancellationReasons(err: unknown): unknown {\n if (err && typeof err === \"object\") {\n const cancellationReasons = (err as { CancellationReasons?: unknown })\n .CancellationReasons;\n if (cancellationReasons !== undefined) {\n return { CancellationReasons: cancellationReasons };\n }\n }\n return undefined;\n}\n","import { getDynamoControlService } from \"../../../dynamo/dynamo-control-service\";\nimport { NotFoundError } from \"../../../errors\";\nimport { OpenHiContext } from \"../../../openhi-context\";\n\nexport interface RoleGetByIdParams {\n context: OpenHiContext;\n id: string;\n tableName?: string;\n}\n\nexport interface RoleGetByIdResult {\n id: string;\n resource: { resourceType: string; id: string; [key: string]: unknown };\n}\n\nexport async function getRoleByIdOperation(\n params: RoleGetByIdParams,\n): Promise<RoleGetByIdResult> {\n const { id, tableName } = params;\n const service = getDynamoControlService(tableName);\n\n const response = await service.entities.role.get({ id, sk: \"CURRENT\" }).go();\n\n const item = response.data;\n if (!item) {\n throw new NotFoundError(`Role not found: ${id}`);\n }\n\n const parsedResource = JSON.parse(item.resource) as Record<string, unknown>;\n\n return {\n id,\n resource: { resourceType: \"Role\", id, ...parsedResource },\n };\n}\n","import { extractSummary, type FhirResourceLike } from \"@openhi/types\";\nimport {\n buildRoleAssignmentUserProjectionItem,\n extractReferenceSlug,\n} from \"./roleassignment-user-projection\";\nimport { buildRoleAssignmentWorkspaceProjectionItem } from \"./roleassignment-workspace-projection\";\nimport { getDynamoControlService } from \"../../../dynamo/dynamo-control-service\";\nimport { OpenHiContext } from \"../../../openhi-context\";\nimport { extractDenormalizedReferenceDisplay } from \"../denormalized-display-names\";\nimport { assertUserHasTenantMembershipOperation } from \"../membership-constraints/assert-user-has-tenant-membership-operation\";\nimport { assertWorkspaceInTenantOperation } from \"../membership-constraints/assert-workspace-in-tenant-operation\";\nimport {\n executeMultiWrite,\n type MultiWriteTriple,\n} from \"../multi-write-operation\";\n\nexport interface RoleAssignmentCreateParams {\n context: OpenHiContext;\n body: { id?: string; resource?: Record<string, unknown> | string };\n tableName?: string;\n}\n\nexport interface RoleAssignmentCreateResult {\n id: string;\n resource: { resourceType: string; id: string; [key: string]: unknown };\n meta: { lastUpdated: string; versionId: string };\n}\n\nexport async function createRoleAssignmentOperation(\n params: RoleAssignmentCreateParams,\n): Promise<RoleAssignmentCreateResult> {\n const { context, body, tableName } = params;\n const service = getDynamoControlService(tableName);\n\n const id = body.id ?? `roleassignment-${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: \"RoleAssignment\", id, ...parsedResource };\n\n // TR-024 denormalized display-name attributes. The authoritative\n // write-time source per TR-024 rule 2 is the canonical Tenant / User /\n // Role record's `displayName`. Until the carrier-record-lookup pass\n // lands (#1010 follow-up), the foundational fallback (#1009) reads\n // the FHIR Reference.display values supplied on the resource so the\n // adjacency-list projection writer here can compose SKs from\n // top-level attributes.\n const resourceRecord = resource as Record<string, unknown>;\n const denormalizedTenantName = extractDenormalizedReferenceDisplay(\n resourceRecord,\n \"tenant\",\n );\n const denormalizedUserName = extractDenormalizedReferenceDisplay(\n resourceRecord,\n \"user\",\n );\n const denormalizedRoleName = extractDenormalizedReferenceDisplay(\n resourceRecord,\n \"role\",\n );\n\n const summary = JSON.stringify(extractSummary(resource as FhirResourceLike));\n\n // ADR-018 patterns #5 / #9 — user- and workspace-partition projection\n // rows. The projection's discriminating fields come from the same\n // FHIR Reference shape the canonical row reads, so the canonical and\n // projection writes always agree on the underlying user / role /\n // workspace identifiers. Missing user or role references skip the\n // user-projection; tenant-scoped RoleAssignments (no workspaceId)\n // skip the workspace-projection — the canonical row still lands\n // either way.\n const userIdFromResource = extractReferenceSlug(resourceRecord, \"user\");\n const roleIdFromResource = extractReferenceSlug(resourceRecord, \"role\");\n const workspaceIdFromResource = extractReferenceSlug(\n resourceRecord,\n \"workspace\",\n );\n\n // ADR 2026-03-13-02 § 2 Consequences/Negative — a RoleAssignment may\n // only be created when the referenced user already holds a\n // tenant-level Membership in the referenced tenant, and (when\n // workspace-scoped) that workspace must belong to the same tenant.\n // Prefer the resource's `tenant.reference` (the issue's \"referenced\n // tenant\" wording) and fall back to the context tenant when the\n // body omits the reference. Constraints fire before any write so\n // the rejection is atomic with respect to the canonical row.\n if (userIdFromResource !== undefined) {\n const tenantIdFromResource = extractReferenceSlug(resourceRecord, \"tenant\");\n const referencedTenantId = tenantIdFromResource ?? context.tenantId;\n await assertUserHasTenantMembershipOperation({\n userId: userIdFromResource,\n tenantId: referencedTenantId,\n tableName,\n });\n if (workspaceIdFromResource !== undefined) {\n await assertWorkspaceInTenantOperation({\n tenantId: referencedTenantId,\n workspaceId: workspaceIdFromResource,\n tableName,\n });\n }\n }\n\n const userProjectionItem =\n userIdFromResource !== undefined && roleIdFromResource !== undefined\n ? buildRoleAssignmentUserProjectionItem({\n tenantId: context.tenantId,\n userId: userIdFromResource,\n workspaceId: workspaceIdFromResource,\n roleId: roleIdFromResource,\n roleAssignmentId: id,\n summary,\n vid,\n lastUpdated,\n denormalizedTenantName,\n denormalizedUserName,\n denormalizedRoleName,\n })\n : undefined;\n\n const workspaceProjectionItem =\n userIdFromResource !== undefined &&\n roleIdFromResource !== undefined &&\n workspaceIdFromResource !== undefined\n ? buildRoleAssignmentWorkspaceProjectionItem({\n tenantId: context.tenantId,\n workspaceId: workspaceIdFromResource,\n userId: userIdFromResource,\n roleId: roleIdFromResource,\n roleAssignmentId: id,\n summary,\n vid,\n lastUpdated,\n denormalizedUserName,\n denormalizedRoleName,\n })\n : undefined;\n\n const canonicalItem = {\n tenantId: context.tenantId,\n id,\n resource: JSON.stringify(resource),\n summary,\n vid,\n lastUpdated,\n denormalizedTenantName,\n denormalizedUserName,\n denormalizedRoleName,\n };\n\n const triples: Array<MultiWriteTriple> = [\n { entity: \"roleAssignment\", action: \"put\", item: canonicalItem },\n ];\n if (userProjectionItem) {\n triples.push({\n entity: \"roleAssignmentUserProjection\",\n action: \"put\",\n item: userProjectionItem as unknown as Record<string, unknown>,\n });\n }\n if (workspaceProjectionItem) {\n triples.push({\n entity: \"roleAssignmentWorkspaceProjection\",\n action: \"put\",\n item: workspaceProjectionItem as unknown as Record<string, unknown>,\n });\n }\n\n await executeMultiWrite({ service, triples });\n\n return {\n id,\n resource,\n meta: { lastUpdated, versionId: vid },\n };\n}\n","/**\n * RoleAssignment user-projection composer.\n *\n * Owns the SK grammar for ADR-018 pattern #5 and assembles the\n * projection-row payload consumed by the role-assignment create /\n * update / delete operations. The\n * {@link RoleAssignmentUserProjectionEntity} stores the SK verbatim —\n * the grammar lives here so the operations layer is the single source\n * of truth for projection-row shape (per\n * `.claude/rules/data-layer-layout.md`).\n *\n * SK grammar:\n *\n * - **tenant-level sub-lane** (`workspaceId` absent):\n * `ROLEASSIGNMENT#TENANT#<normalizedRoleName>#<roleId>#TID#<tenantId>#<roleAssignmentId>`\n * - **workspace-level sub-lane** (`workspaceId` set):\n * `ROLEASSIGNMENT#WORKSPACE#<normalizedRoleName>#<roleId>#TID#<tenantId>#WID#<workspaceId>#<roleAssignmentId>`\n *\n * Both sub-lanes share the user partition `PK = USER#ID#<userId>` so\n * `Query(PK = USER#ID#<userId>, SK begins_with 'ROLEASSIGNMENT#')`\n * returns both sub-lanes interleaved with TENANT preceding WORKSPACE\n * lexicographically.\n *\n * @see ADR-018 § Access Pattern Coverage (pattern #5)\n * @see .state/adr-018-implementation-guide.md § 1 (SK grammar) and § 2 (attribute set)\n */\n\nimport { normalizeLabel } from \"@openhi/types\";\n\n/**\n * Sentinel rendered into the SK when the source display name is missing\n * or empty. Keeps the SK shape stable so a `begins_with` prefix query\n * still matches the row; the rename-cascade pipeline (TR-023) will\n * rewrite the SK once the carrier display name lands. Matches the\n * defensive posture in `membership-user-projection` — a missing source\n * field never produces a malformed key.\n */\nconst MISSING_NAME_SENTINEL = \"-\";\n\n/** Inputs to compose a RoleAssignment user-projection row. */\nexport interface RoleAssignmentUserProjectionInput {\n readonly tenantId: string;\n readonly userId: string;\n readonly workspaceId?: string;\n readonly roleId: string;\n readonly roleAssignmentId: string;\n readonly summary: string;\n readonly vid: string;\n readonly lastUpdated: string;\n readonly denormalizedTenantName?: string;\n readonly denormalizedUserName?: string;\n readonly denormalizedRoleName?: string;\n}\n\n/** A projection-row payload ready for `multi-write` consumption. */\nexport interface RoleAssignmentUserProjectionItem {\n readonly userId: string;\n readonly sk: string;\n readonly tenantId: string;\n readonly workspaceId?: string;\n readonly roleId: string;\n readonly roleAssignmentId: string;\n readonly summary: string;\n readonly vid: string;\n readonly lastUpdated: string;\n readonly denormalizedTenantName?: string;\n readonly denormalizedUserName?: string;\n readonly denormalizedRoleName?: string;\n}\n\n/**\n * Compose the SK for ADR-018 pattern #5 — tenant-level sub-lane. The\n * `<normalizedRoleName>` segment sorts assignments alphabetically by\n * role name within the user's partition; `<roleId>` discriminates\n * rename-stable. Missing `denormalizedRoleName` falls back to\n * {@link MISSING_NAME_SENTINEL} so the SK shape stays valid\n * pre-rename-cascade.\n */\nexport function buildRoleAssignmentUserProjectionSkTenantLane(params: {\n readonly tenantId: string;\n readonly roleId: string;\n readonly roleAssignmentId: string;\n readonly denormalizedRoleName?: string;\n}): string {\n const normalizedRoleName =\n typeof params.denormalizedRoleName === \"string\" &&\n params.denormalizedRoleName.length > 0\n ? normalizeLabel(params.denormalizedRoleName)\n : MISSING_NAME_SENTINEL;\n return `ROLEASSIGNMENT#TENANT#${normalizedRoleName}#${params.roleId}#TID#${params.tenantId}#${params.roleAssignmentId}`;\n}\n\n/**\n * Compose the SK for ADR-018 pattern #5 — workspace-level sub-lane.\n * Same `<normalizedRoleName>#<roleId>` sort discriminator as the tenant\n * sub-lane; the trailing segments narrow the partition to a single\n * tenant + workspace. Missing `denormalizedRoleName` falls back to\n * {@link MISSING_NAME_SENTINEL}.\n */\nexport function buildRoleAssignmentUserProjectionSkWorkspaceLane(params: {\n readonly tenantId: string;\n readonly workspaceId: string;\n readonly roleId: string;\n readonly roleAssignmentId: string;\n readonly denormalizedRoleName?: string;\n}): string {\n const normalizedRoleName =\n typeof params.denormalizedRoleName === \"string\" &&\n params.denormalizedRoleName.length > 0\n ? normalizeLabel(params.denormalizedRoleName)\n : MISSING_NAME_SENTINEL;\n return `ROLEASSIGNMENT#WORKSPACE#${normalizedRoleName}#${params.roleId}#TID#${params.tenantId}#WID#${params.workspaceId}#${params.roleAssignmentId}`;\n}\n\n/**\n * Builds the projection item for the access lane implied by the input.\n * Tenant-level sub-lane when `workspaceId` is absent or empty;\n * workspace-level sub-lane otherwise. Returns `undefined` when `userId`\n * or `roleId` is missing — without either the projection cannot land\n * under a user partition or be sorted by role name.\n */\nexport function buildRoleAssignmentUserProjectionItem(\n input: RoleAssignmentUserProjectionInput,\n): RoleAssignmentUserProjectionItem | undefined {\n if (!input.userId || input.userId.length === 0) {\n return undefined;\n }\n if (!input.roleId || input.roleId.length === 0) {\n return undefined;\n }\n const hasWorkspace =\n typeof input.workspaceId === \"string\" && input.workspaceId.length > 0;\n const sk = hasWorkspace\n ? buildRoleAssignmentUserProjectionSkWorkspaceLane({\n tenantId: input.tenantId,\n workspaceId: input.workspaceId as string,\n roleId: input.roleId,\n roleAssignmentId: input.roleAssignmentId,\n denormalizedRoleName: input.denormalizedRoleName,\n })\n : buildRoleAssignmentUserProjectionSkTenantLane({\n tenantId: input.tenantId,\n roleId: input.roleId,\n roleAssignmentId: input.roleAssignmentId,\n denormalizedRoleName: input.denormalizedRoleName,\n });\n return {\n userId: input.userId,\n sk,\n tenantId: input.tenantId,\n workspaceId: hasWorkspace ? input.workspaceId : undefined,\n roleId: input.roleId,\n roleAssignmentId: input.roleAssignmentId,\n summary: input.summary,\n vid: input.vid,\n lastUpdated: input.lastUpdated,\n denormalizedTenantName: input.denormalizedTenantName,\n denormalizedUserName: input.denormalizedUserName,\n denormalizedRoleName: input.denormalizedRoleName,\n };\n}\n\n/**\n * Extracts a FHIR `Reference` slug — the segment after the final `/`.\n * Returns `undefined` when the reference is missing or malformed so\n * callers fall back gracefully (matches the defensive posture in\n * `extractRoleId` / `extractDenormalizedReferenceDisplay`).\n */\nexport function extractReferenceSlug(\n resource: Record<string, unknown>,\n fieldName: string,\n): string | undefined {\n const field = resource[fieldName];\n if (!field || typeof field !== \"object\") {\n return undefined;\n }\n const reference = (field as { reference?: unknown }).reference;\n if (typeof reference !== \"string\" || reference.length === 0) {\n return undefined;\n }\n const slash = reference.lastIndexOf(\"/\");\n const tail = slash >= 0 ? reference.slice(slash + 1) : reference;\n return tail.length > 0 ? tail : undefined;\n}\n","/**\n * RoleAssignment workspace-projection composer.\n *\n * Owns the SK grammar for ADR-018 pattern #9 and assembles the\n * projection-row payload consumed by the role-assignment create /\n * update / delete operations. The\n * {@link RoleAssignmentWorkspaceProjectionEntity} stores the SK\n * verbatim — the grammar lives here so the operations layer is the\n * single source of truth for projection-row shape (per\n * `.claude/rules/data-layer-layout.md`).\n *\n * SK grammar:\n *\n * - **Pattern #9** (users with a specific role in a workspace, sorted\n * by user name — workspace-scoped RoleAssignments only):\n * `ROLEASSIGNMENT#<roleId>#<normalizedUserName>#USER#<userId>#<roleAssignmentId>`\n *\n * The SK is **discriminator-first** on the raw `<roleId>` (mirroring\n * the canonical GSI1SK from pattern #8). Role id discriminates first so\n * a `begins_with('ROLEASSIGNMENT#<roleId>#')` filter returns every user\n * assigned to that role in the workspace, sorted alphabetically by\n * normalized user name. The trailing `USER#<userId>#<roleAssignmentId>`\n * disambiguates rows when two assignments share a normalized user name\n * (homonyms) and supports a per-user lookup via\n * `begins_with('ROLEASSIGNMENT#<roleId>#<normalizedUserName>#USER#<userId>#')`.\n *\n * The projection co-locates with the canonical Workspace record (and\n * the Membership workspace-projection rows from pattern #2) under\n * `PK = TID#<tenantId>#WORKSPACE#ID#<workspaceId>` so\n * `Query(PK = TID#<tenantId>#WORKSPACE#ID#<workspaceId>)` returns\n * workspace metadata + every member projection + every role-assignment\n * projection in one round trip. Tenant-scoped RoleAssignments (no\n * `workspaceId`) skip this projection entirely.\n *\n * **Rename-cascade interaction (TR-023, Phase 6).** The SK uses the\n * raw `<roleId>` (rename-stable) for the discriminator and\n * `<normalizedUserName>` for the secondary sort. A Role rename does\n * NOT rewrite this SK; a User rename DOES (cascaded by the rename\n * pipeline).\n *\n * @see ADR-018 § Access Pattern Coverage (pattern #9)\n * @see .state/adr-018-implementation-guide.md § 1 (SK grammar) and § 2 (attribute set)\n */\n\nimport { normalizeLabel } from \"@openhi/types\";\n\n/**\n * Sentinel rendered into the SK when the source user display name is\n * missing or empty. Keeps the SK shape stable so a `begins_with` prefix\n * query still matches the row; the rename-cascade pipeline (TR-023)\n * will rewrite the SK once the carrier display name lands. Mirrors the\n * sibling projection composers' defensive posture — a missing source\n * field never produces a malformed key.\n */\nconst MISSING_NAME_SENTINEL = \"-\";\n\n/** Inputs to compose a RoleAssignment workspace-projection row. */\nexport interface RoleAssignmentWorkspaceProjectionInput {\n readonly tenantId: string;\n readonly workspaceId: string;\n readonly userId: string;\n readonly roleId: string;\n readonly roleAssignmentId: string;\n readonly summary: string;\n readonly vid: string;\n readonly lastUpdated: string;\n readonly denormalizedUserName?: string;\n readonly denormalizedRoleName?: string;\n}\n\n/** A projection-row payload ready for `multi-write` consumption. */\nexport interface RoleAssignmentWorkspaceProjectionItem {\n readonly tenantId: string;\n readonly workspaceId: string;\n readonly sk: string;\n readonly userId: string;\n readonly roleId: string;\n readonly roleAssignmentId: string;\n readonly summary: string;\n readonly vid: string;\n readonly lastUpdated: string;\n readonly denormalizedUserName?: string;\n readonly denormalizedRoleName?: string;\n}\n\n/**\n * Compose the SK for ADR-018 pattern #9. The discriminator-first\n * `<roleId>` segment (raw, NOT normalized — matches the canonical\n * GSI1SK from pattern #8) lets `begins_with('ROLEASSIGNMENT#<roleId>#')`\n * filter one role. The `<normalizedUserName>` segment sorts assignments\n * alphabetically by user name within that role. The trailing\n * `USER#<userId>#<roleAssignmentId>` disambiguates homonyms and\n * supports a per-user lookup via\n * `begins_with('ROLEASSIGNMENT#<roleId>#<normalizedUserName>#USER#<userId>#')`.\n * Missing `denormalizedUserName` falls back to\n * {@link MISSING_NAME_SENTINEL} so the SK shape stays valid\n * pre-rename-cascade.\n */\nexport function buildRoleAssignmentWorkspaceProjectionSk(params: {\n readonly roleId: string;\n readonly userId: string;\n readonly roleAssignmentId: string;\n readonly denormalizedUserName?: string;\n}): string {\n const normalizedUserName =\n typeof params.denormalizedUserName === \"string\" &&\n params.denormalizedUserName.length > 0\n ? normalizeLabel(params.denormalizedUserName)\n : MISSING_NAME_SENTINEL;\n return `ROLEASSIGNMENT#${params.roleId}#${normalizedUserName}#USER#${params.userId}#${params.roleAssignmentId}`;\n}\n\n/**\n * Builds the projection item for a workspace-scoped RoleAssignment.\n * Returns `undefined` when `workspaceId`, `userId`, or `roleId` is\n * missing — tenant-scoped RoleAssignments (no workspaceId) skip the\n * workspace projection entirely; a RoleAssignment without a linked\n * user or role cannot project onto the workspace partition under the\n * pattern-#9 SK shape.\n */\nexport function buildRoleAssignmentWorkspaceProjectionItem(\n input: RoleAssignmentWorkspaceProjectionInput,\n): RoleAssignmentWorkspaceProjectionItem | undefined {\n if (!input.workspaceId || input.workspaceId.length === 0) {\n return undefined;\n }\n if (!input.userId || input.userId.length === 0) {\n return undefined;\n }\n if (!input.roleId || input.roleId.length === 0) {\n return undefined;\n }\n const sk = buildRoleAssignmentWorkspaceProjectionSk({\n roleId: input.roleId,\n userId: input.userId,\n roleAssignmentId: input.roleAssignmentId,\n denormalizedUserName: input.denormalizedUserName,\n });\n return {\n tenantId: input.tenantId,\n workspaceId: input.workspaceId,\n sk,\n userId: input.userId,\n roleId: input.roleId,\n roleAssignmentId: input.roleAssignmentId,\n summary: input.summary,\n vid: input.vid,\n lastUpdated: input.lastUpdated,\n denormalizedUserName: input.denormalizedUserName,\n denormalizedRoleName: input.denormalizedRoleName,\n };\n}\n","import { PLATFORM_SCOPE_TENANT_ID } from \"./platform-scope-tenant-id\";\nimport { getDynamoControlService } from \"../../../dynamo/dynamo-control-service\";\nimport { ConflictError } from \"../../../errors\";\n\n/**\n * SK prefix for the tenant-level Membership sub-lane (ADR-018 pattern #3).\n *\n * Tenant-level Memberships project under the user partition with\n * `SK = MEMBERSHIP#TENANT#<normalizedTenantName>#TID#<tenantId>#<membershipId>`.\n * Because the `<tenantId>` segment appears *after* `<normalizedTenantName>`,\n * a `begins_with` filter cannot narrow to a single tenant — we read every\n * tenant-lane row for the user and filter on the projection-row's\n * `tenantId` attribute in memory.\n */\nconst TENANT_LANE_SK_PREFIX = \"MEMBERSHIP#TENANT#\";\n\n/** Inputs to {@link assertUserHasTenantMembershipOperation}. */\nexport interface AssertUserHasTenantMembershipParams {\n /** The user that must already be a member of `tenantId`. */\n readonly userId: string;\n /** The tenant the user must hold a tenant-level Membership in. */\n readonly tenantId: string;\n /** Optional table-name override; resolved via env when omitted. */\n readonly tableName?: string;\n}\n\n/**\n * Throws {@link ConflictError} when `userId` has no tenant-level\n * `Membership` in `tenantId`.\n *\n * Implementation: queries the ADR-018 user-partition projection\n * (`MembershipUserProjectionEntity`) under\n * `PK = USER#ID#<userId>, SK begins_with 'MEMBERSHIP#TENANT#'` — a single\n * strongly-consistent base-table query with no GSI hop — and filters the\n * returned rows for `tenantId` in memory.\n *\n * The filter cannot be expressed as an additional `begins_with` because\n * the projection SK encodes `<normalizedTenantName>` *before* `<tenantId>`\n * (`MEMBERSHIP#TENANT#<normalizedTenantName>#TID#<tenantId>#<id>`). The\n * scan cost is bounded by the user's tenant-membership fan-out, which is\n * small by construction.\n *\n * @see ADR 2026-03-13-02 § 2 — Consequences/Negative\n * @see ADR-018 § Access Pattern Coverage (pattern #3)\n */\nexport async function assertUserHasTenantMembershipOperation(\n params: AssertUserHasTenantMembershipParams,\n): Promise<void> {\n const { userId, tenantId, tableName } = params;\n\n // The platform-scope sentinel is not a real tenant — it is a\n // reserved `tenantId` value used on platform-scoped RoleAssignments\n // (e.g. `system-admin`). No `Membership` is ever created under it,\n // and a Membership there would have no semantic meaning. Skip the\n // tenant-membership constraint so platform-scoped RAs can be\n // created without requiring an impossible-to-create prerequisite\n // Membership row.\n if (tenantId === PLATFORM_SCOPE_TENANT_ID) {\n return;\n }\n\n const service = getDynamoControlService(tableName);\n\n const result = await service.entities.membershipUserProjection.query\n .record({ userId })\n .begins({ sk: TENANT_LANE_SK_PREFIX })\n .go();\n\n const matched = (result.data ?? []).some((row) => row.tenantId === tenantId);\n if (!matched) {\n throw new ConflictError(\n `User ${userId} has no tenant-level Membership in tenant ${tenantId}; a Membership must exist before a RoleAssignment can be created.`,\n { details: { userId, tenantId } },\n );\n }\n}\n","import { extractSummary, type FhirResourceLike } from \"@openhi/types\";\nimport { getDynamoControlService } from \"../../../dynamo/dynamo-control-service\";\nimport type { OpenHiContext } from \"../../../openhi-context\";\n\nexport interface CreateTenantParams {\n context: OpenHiContext;\n body: {\n id?: string;\n resource?: Record<string, unknown> | string;\n };\n tableName?: string;\n}\n\nexport interface CreateTenantResult {\n id: string;\n resource: Record<string, unknown>;\n meta: { lastUpdated: string; versionId: string };\n}\n\n/**\n * Creates a Tenant. Generates an id if not provided.\n */\nexport async function createTenantOperation(\n params: CreateTenantParams,\n): Promise<CreateTenantResult> {\n const { context, body, tableName } = params;\n const service = getDynamoControlService(tableName);\n\n const id = body.id ?? `tenant-${Date.now()}`;\n const lastUpdated = context.date;\n const vid =\n lastUpdated.replace(/[-:T.Z]/g, \"\").slice(0, 12) || Date.now().toString(36);\n\n const parsedResource =\n typeof body.resource === \"string\"\n ? (JSON.parse(body.resource) as Record<string, unknown>)\n : (body.resource ?? {});\n\n const resource = { resourceType: \"Tenant\", id, ...parsedResource };\n const summary = JSON.stringify(extractSummary(resource as FhirResourceLike));\n\n await service.entities.tenant\n .put({\n tenantId: id,\n id,\n resource: JSON.stringify(resource),\n summary,\n vid,\n lastUpdated,\n })\n .go();\n\n return { id, resource, meta: { lastUpdated, versionId: vid } };\n}\n","import { extractSummary, type FhirResourceLike } from \"@openhi/types\";\nimport { getDynamoControlService } from \"../../../dynamo/dynamo-control-service\";\nimport type { OpenHiContext } from \"../../../openhi-context\";\nimport { provisionOrganizationForWorkspaceOperation } from \"../../data/organization/organization-provision-for-workspace-operation\";\n\nexport interface CreateWorkspaceParams {\n context: OpenHiContext;\n body: {\n id?: string;\n resource?: Record<string, unknown> | string;\n };\n tableName?: string;\n}\n\nexport interface CreateWorkspaceResult {\n id: string;\n resource: Record<string, unknown>;\n meta: { lastUpdated: string; versionId: string };\n}\n\n/**\n * Creates a Workspace scoped to the context tenant. Generates an id if not provided.\n */\nexport async function createWorkspaceOperation(\n params: CreateWorkspaceParams,\n): Promise<CreateWorkspaceResult> {\n const { context, body, tableName } = params;\n const { tenantId } = context;\n const service = getDynamoControlService(tableName);\n\n const id = body.id ?? `workspace-${Date.now()}`;\n const lastUpdated = context.date;\n const vid =\n lastUpdated.replace(/[-:T.Z]/g, \"\").slice(0, 12) || Date.now().toString(36);\n\n const parsedResource =\n typeof body.resource === \"string\"\n ? (JSON.parse(body.resource) as Record<string, unknown>)\n : (body.resource ?? {});\n\n const resource = { resourceType: \"Workspace\", id, ...parsedResource };\n const summary = JSON.stringify(extractSummary(resource as FhirResourceLike));\n\n await service.entities.workspace\n .put({\n tenantId,\n id,\n resource: JSON.stringify(resource),\n summary,\n vid,\n lastUpdated,\n })\n .go();\n\n const workspaceName =\n typeof parsedResource.name === \"string\" ? parsedResource.name : undefined;\n await provisionOrganizationForWorkspaceOperation({\n context,\n workspaceId: id,\n workspaceName,\n tableName,\n });\n\n return { id, resource, meta: { lastUpdated, versionId: vid } };\n}\n","import { Service } from \"electrodb\";\nimport { defaultTableName, dynamoClient } from \"./dynamo-client\";\nimport { AccountEntity } from \"./entities/data/account-entity\";\nimport { ActivityDefinitionEntity } from \"./entities/data/activity-definition-entity\";\nimport { AdverseEventEntity } from \"./entities/data/adverse-event-entity\";\nimport { AllergyIntoleranceEntity } from \"./entities/data/allergy-intolerance-entity\";\nimport { AppointmentEntity } from \"./entities/data/appointment-entity\";\nimport { AppointmentResponseEntity } from \"./entities/data/appointment-response-entity\";\nimport { AuditEventEntity } from \"./entities/data/audit-event-entity\";\nimport { BasicEntity } from \"./entities/data/basic-entity\";\nimport { BiologicallyDerivedProductEntity } from \"./entities/data/biologically-derived-product-entity\";\nimport { BodyStructureEntity } from \"./entities/data/body-structure-entity\";\nimport { CapabilityStatementEntity } from \"./entities/data/capability-statement-entity\";\nimport { CarePlanEntity } from \"./entities/data/care-plan-entity\";\nimport { CareTeamEntity } from \"./entities/data/care-team-entity\";\nimport { CatalogEntryEntity } from \"./entities/data/catalog-entry-entity\";\nimport { ChargeItemDefinitionEntity } from \"./entities/data/charge-item-definition-entity\";\nimport { ChargeItemEntity } from \"./entities/data/charge-item-entity\";\nimport { ClaimEntity } from \"./entities/data/claim-entity\";\nimport { ClaimResponseEntity } from \"./entities/data/claim-response-entity\";\nimport { ClinicalImpressionEntity } from \"./entities/data/clinical-impression-entity\";\nimport { CodeSystemEntity } from \"./entities/data/code-system-entity\";\nimport { CommunicationEntity } from \"./entities/data/communication-entity\";\nimport { CommunicationRequestEntity } from \"./entities/data/communication-request-entity\";\nimport { CompartmentDefinitionEntity } from \"./entities/data/compartment-definition-entity\";\nimport { CompositionEntity } from \"./entities/data/composition-entity\";\nimport { ConceptMapEntity } from \"./entities/data/concept-map-entity\";\nimport { ConditionEntity } from \"./entities/data/condition-entity\";\nimport { ConsentEntity } from \"./entities/data/consent-entity\";\nimport { ContractEntity } from \"./entities/data/contract-entity\";\nimport { CoverageEligibilityRequestEntity } from \"./entities/data/coverage-eligibility-request-entity\";\nimport { CoverageEligibilityResponseEntity } from \"./entities/data/coverage-eligibility-response-entity\";\nimport { CoverageEntity } from \"./entities/data/coverage-entity\";\nimport { DetectedIssueEntity } from \"./entities/data/detected-issue-entity\";\nimport { DeviceDefinitionEntity } from \"./entities/data/device-definition-entity\";\nimport { DeviceEntity } from \"./entities/data/device-entity\";\nimport { DeviceMetricEntity } from \"./entities/data/device-metric-entity\";\nimport { DeviceRequestEntity } from \"./entities/data/device-request-entity\";\nimport { DeviceUseStatementEntity } from \"./entities/data/device-use-statement-entity\";\nimport { DiagnosticReportEntity } from \"./entities/data/diagnostic-report-entity\";\nimport { DocumentManifestEntity } from \"./entities/data/document-manifest-entity\";\nimport { DocumentReferenceEntity } from \"./entities/data/document-reference-entity\";\nimport { EffectEvidenceSynthesisEntity } from \"./entities/data/effect-evidence-synthesis-entity\";\nimport { EncounterEntity } from \"./entities/data/encounter-entity\";\nimport { EndpointEntity } from \"./entities/data/endpoint-entity\";\nimport { EnrollmentRequestEntity } from \"./entities/data/enrollment-request-entity\";\nimport { EnrollmentResponseEntity } from \"./entities/data/enrollment-response-entity\";\nimport { EpisodeOfCareEntity } from \"./entities/data/episode-of-care-entity\";\nimport { EventDefinitionEntity } from \"./entities/data/event-definition-entity\";\nimport { EvidenceEntity } from \"./entities/data/evidence-entity\";\nimport { EvidenceVariableEntity } from \"./entities/data/evidence-variable-entity\";\nimport { ExampleScenarioEntity } from \"./entities/data/example-scenario-entity\";\nimport { ExplanationOfBenefitEntity } from \"./entities/data/explanation-of-benefit-entity\";\nimport { FamilyMemberHistoryEntity } from \"./entities/data/family-member-history-entity\";\nimport { FlagEntity } from \"./entities/data/flag-entity\";\nimport { GoalEntity } from \"./entities/data/goal-entity\";\nimport { GraphDefinitionEntity } from \"./entities/data/graph-definition-entity\";\nimport { GroupEntity } from \"./entities/data/group-entity\";\nimport { GuidanceResponseEntity } from \"./entities/data/guidance-response-entity\";\nimport { HealthcareServiceEntity } from \"./entities/data/healthcare-service-entity\";\nimport { ImagingStudyEntity } from \"./entities/data/imaging-study-entity\";\nimport { ImmunizationEntity } from \"./entities/data/immunization-entity\";\nimport { ImmunizationEvaluationEntity } from \"./entities/data/immunization-evaluation-entity\";\nimport { ImmunizationRecommendationEntity } from \"./entities/data/immunization-recommendation-entity\";\nimport { ImplementationGuideEntity } from \"./entities/data/implementation-guide-entity\";\nimport { InsurancePlanEntity } from \"./entities/data/insurance-plan-entity\";\nimport { InvoiceEntity } from \"./entities/data/invoice-entity\";\nimport { LibraryEntity } from \"./entities/data/library-entity\";\nimport { LinkageEntity } from \"./entities/data/linkage-entity\";\nimport { ListEntity } from \"./entities/data/list-entity\";\nimport { LocationEntity } from \"./entities/data/location-entity\";\nimport { MeasureEntity } from \"./entities/data/measure-entity\";\nimport { MeasureReportEntity } from \"./entities/data/measure-report-entity\";\nimport { MediaEntity } from \"./entities/data/media-entity\";\nimport { MedicationAdministrationEntity } from \"./entities/data/medication-administration-entity\";\nimport { MedicationDispenseEntity } from \"./entities/data/medication-dispense-entity\";\nimport { MedicationEntity } from \"./entities/data/medication-entity\";\nimport { MedicationKnowledgeEntity } from \"./entities/data/medication-knowledge-entity\";\nimport { MedicationRequestEntity } from \"./entities/data/medication-request-entity\";\nimport { MedicationStatementEntity } from \"./entities/data/medication-statement-entity\";\nimport { MedicinalProductAuthorizationEntity } from \"./entities/data/medicinal-product-authorization-entity\";\nimport { MedicinalProductContraindicationEntity } from \"./entities/data/medicinal-product-contraindication-entity\";\nimport { MedicinalProductEntity } from \"./entities/data/medicinal-product-entity\";\nimport { MedicinalProductIndicationEntity } from \"./entities/data/medicinal-product-indication-entity\";\nimport { MedicinalProductIngredientEntity } from \"./entities/data/medicinal-product-ingredient-entity\";\nimport { MedicinalProductInteractionEntity } from \"./entities/data/medicinal-product-interaction-entity\";\nimport { MedicinalProductManufacturedEntity } from \"./entities/data/medicinal-product-manufactured-entity\";\nimport { MedicinalProductPackagedEntity } from \"./entities/data/medicinal-product-packaged-entity\";\nimport { MedicinalProductPharmaceuticalEntity } from \"./entities/data/medicinal-product-pharmaceutical-entity\";\nimport { MedicinalProductUndesirableEffectEntity } from \"./entities/data/medicinal-product-undesirable-effect-entity\";\nimport { MessageDefinitionEntity } from \"./entities/data/message-definition-entity\";\nimport { MessageHeaderEntity } from \"./entities/data/message-header-entity\";\nimport { MolecularSequenceEntity } from \"./entities/data/molecular-sequence-entity\";\nimport { NamingSystemEntity } from \"./entities/data/naming-system-entity\";\nimport { NutritionOrderEntity } from \"./entities/data/nutrition-order-entity\";\nimport { ObservationDefinitionEntity } from \"./entities/data/observation-definition-entity\";\nimport { ObservationEntity } from \"./entities/data/observation-entity\";\nimport { OperationDefinitionEntity } from \"./entities/data/operation-definition-entity\";\nimport { OrganizationAffiliationEntity } from \"./entities/data/organization-affiliation-entity\";\nimport { OrganizationEntity } from \"./entities/data/organization-entity\";\nimport { PatientEntity } from \"./entities/data/patient-entity\";\nimport { PaymentNoticeEntity } from \"./entities/data/payment-notice-entity\";\nimport { PaymentReconciliationEntity } from \"./entities/data/payment-reconciliation-entity\";\nimport { PersonEntity } from \"./entities/data/person-entity\";\nimport { PlanDefinitionEntity } from \"./entities/data/plan-definition-entity\";\nimport { PractitionerEntity } from \"./entities/data/practitioner-entity\";\nimport { PractitionerRoleEntity } from \"./entities/data/practitioner-role-entity\";\nimport { ProcedureEntity } from \"./entities/data/procedure-entity\";\nimport { ProvenanceEntity } from \"./entities/data/provenance-entity\";\nimport { QuestionnaireEntity } from \"./entities/data/questionnaire-entity\";\nimport { QuestionnaireResponseEntity } from \"./entities/data/questionnaire-response-entity\";\nimport { RelatedPersonEntity } from \"./entities/data/related-person-entity\";\nimport { RequestGroupEntity } from \"./entities/data/request-group-entity\";\nimport { ResearchDefinitionEntity } from \"./entities/data/research-definition-entity\";\nimport { ResearchElementDefinitionEntity } from \"./entities/data/research-element-definition-entity\";\nimport { ResearchStudyEntity } from \"./entities/data/research-study-entity\";\nimport { ResearchSubjectEntity } from \"./entities/data/research-subject-entity\";\nimport { RiskAssessmentEntity } from \"./entities/data/risk-assessment-entity\";\nimport { RiskEvidenceSynthesisEntity } from \"./entities/data/risk-evidence-synthesis-entity\";\nimport { ScheduleEntity } from \"./entities/data/schedule-entity\";\nimport { SearchParameterEntity } from \"./entities/data/search-parameter-entity\";\nimport { ServiceRequestEntity } from \"./entities/data/service-request-entity\";\nimport { SlotEntity } from \"./entities/data/slot-entity\";\nimport { SpecimenDefinitionEntity } from \"./entities/data/specimen-definition-entity\";\nimport { SpecimenEntity } from \"./entities/data/specimen-entity\";\nimport { StructureDefinitionEntity } from \"./entities/data/structure-definition-entity\";\nimport { StructureMapEntity } from \"./entities/data/structure-map-entity\";\nimport { SubscriptionEntity } from \"./entities/data/subscription-entity\";\nimport { SubstanceEntity } from \"./entities/data/substance-entity\";\nimport { SubstanceNucleicAcidEntity } from \"./entities/data/substance-nucleic-acid-entity\";\nimport { SubstancePolymerEntity } from \"./entities/data/substance-polymer-entity\";\nimport { SubstanceProteinEntity } from \"./entities/data/substance-protein-entity\";\nimport { SubstanceReferenceInformationEntity } from \"./entities/data/substance-reference-information-entity\";\nimport { SubstanceSourceMaterialEntity } from \"./entities/data/substance-source-material-entity\";\nimport { SubstanceSpecificationEntity } from \"./entities/data/substance-specification-entity\";\nimport { SupplyDeliveryEntity } from \"./entities/data/supply-delivery-entity\";\nimport { SupplyRequestEntity } from \"./entities/data/supply-request-entity\";\nimport { TaskEntity } from \"./entities/data/task-entity\";\nimport { TerminologyCapabilitiesEntity } from \"./entities/data/terminology-capabilities-entity\";\nimport { TestReportEntity } from \"./entities/data/test-report-entity\";\nimport { TestScriptEntity } from \"./entities/data/test-script-entity\";\nimport { ValueSetEntity } from \"./entities/data/value-set-entity\";\nimport { VerificationResultEntity } from \"./entities/data/verification-result-entity\";\nimport { VisionPrescriptionEntity } from \"./entities/data/vision-prescription-entity\";\n\n/**\n * Data-plane entities only (service \"data\"). Same table as control plane; use\n * DynamoControlService for control-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 dataPlaneEntities = {\n account: AccountEntity,\n activitydefinition: ActivityDefinitionEntity,\n adverseevent: AdverseEventEntity,\n allergyintolerance: AllergyIntoleranceEntity,\n appointment: AppointmentEntity,\n appointmentresponse: AppointmentResponseEntity,\n auditevent: AuditEventEntity,\n basic: BasicEntity,\n biologicallyderivedproduct: BiologicallyDerivedProductEntity,\n bodystructure: BodyStructureEntity,\n capabilitystatement: CapabilityStatementEntity,\n careplan: CarePlanEntity,\n careteam: CareTeamEntity,\n catalogentry: CatalogEntryEntity,\n codesystem: CodeSystemEntity,\n chargeitem: ChargeItemEntity,\n chargeitemdefinition: ChargeItemDefinitionEntity,\n claim: ClaimEntity,\n claimresponse: ClaimResponseEntity,\n clinicalimpression: ClinicalImpressionEntity,\n communication: CommunicationEntity,\n communicationrequest: CommunicationRequestEntity,\n compartmentdefinition: CompartmentDefinitionEntity,\n composition: CompositionEntity,\n conceptmap: ConceptMapEntity,\n condition: ConditionEntity,\n consent: ConsentEntity,\n contract: ContractEntity,\n coverage: CoverageEntity,\n coverageeligibilityrequest: CoverageEligibilityRequestEntity,\n coverageeligibilityresponse: CoverageEligibilityResponseEntity,\n detectedissue: DetectedIssueEntity,\n device: DeviceEntity,\n devicedefinition: DeviceDefinitionEntity,\n devicemetric: DeviceMetricEntity,\n devicerequest: DeviceRequestEntity,\n deviceusestatement: DeviceUseStatementEntity,\n diagnosticreport: DiagnosticReportEntity,\n documentmanifest: DocumentManifestEntity,\n documentreference: DocumentReferenceEntity,\n effectevidencesynthesis: EffectEvidenceSynthesisEntity,\n encounter: EncounterEntity,\n examplescenario: ExampleScenarioEntity,\n endpoint: EndpointEntity,\n enrollmentrequest: EnrollmentRequestEntity,\n enrollmentresponse: EnrollmentResponseEntity,\n episodeofcare: EpisodeOfCareEntity,\n eventdefinition: EventDefinitionEntity,\n evidence: EvidenceEntity,\n evidencevariable: EvidenceVariableEntity,\n explanationofbenefit: ExplanationOfBenefitEntity,\n familymemberhistory: FamilyMemberHistoryEntity,\n flag: FlagEntity,\n goal: GoalEntity,\n graphdefinition: GraphDefinitionEntity,\n group: GroupEntity,\n guidanceresponse: GuidanceResponseEntity,\n healthcareservice: HealthcareServiceEntity,\n immunization: ImmunizationEntity,\n immunizationevaluation: ImmunizationEvaluationEntity,\n immunizationrecommendation: ImmunizationRecommendationEntity,\n imagingstudy: ImagingStudyEntity,\n implementationguide: ImplementationGuideEntity,\n insuranceplan: InsurancePlanEntity,\n invoice: InvoiceEntity,\n library: LibraryEntity,\n linkage: LinkageEntity,\n list: ListEntity,\n location: LocationEntity,\n medication: MedicationEntity,\n medicationadministration: MedicationAdministrationEntity,\n medicationdispense: MedicationDispenseEntity,\n medicationknowledge: MedicationKnowledgeEntity,\n medicationrequest: MedicationRequestEntity,\n medicationstatement: MedicationStatementEntity,\n medicinalproduct: MedicinalProductEntity,\n medicinalproductauthorization: MedicinalProductAuthorizationEntity,\n medicinalproductcontraindication: MedicinalProductContraindicationEntity,\n medicinalproductingredient: MedicinalProductIngredientEntity,\n medicinalproductindication: MedicinalProductIndicationEntity,\n medicinalproductinteraction: MedicinalProductInteractionEntity,\n medicinalproductmanufactured: MedicinalProductManufacturedEntity,\n medicinalproductpackaged: MedicinalProductPackagedEntity,\n medicinalproductpharmaceutical: MedicinalProductPharmaceuticalEntity,\n medicinalproductundesirableeffect: MedicinalProductUndesirableEffectEntity,\n media: MediaEntity,\n measure: MeasureEntity,\n measurereport: MeasureReportEntity,\n messagedefinition: MessageDefinitionEntity,\n messageheader: MessageHeaderEntity,\n molecularsequence: MolecularSequenceEntity,\n namingsystem: NamingSystemEntity,\n nutritionorder: NutritionOrderEntity,\n observation: ObservationEntity,\n observationdefinition: ObservationDefinitionEntity,\n operationdefinition: OperationDefinitionEntity,\n organization: OrganizationEntity,\n organizationaffiliation: OrganizationAffiliationEntity,\n patient: PatientEntity,\n paymentnotice: PaymentNoticeEntity,\n paymentreconciliation: PaymentReconciliationEntity,\n person: PersonEntity,\n plandefinition: PlanDefinitionEntity,\n practitioner: PractitionerEntity,\n practitionerrole: PractitionerRoleEntity,\n procedure: ProcedureEntity,\n provenance: ProvenanceEntity,\n questionnaire: QuestionnaireEntity,\n questionnaireresponse: QuestionnaireResponseEntity,\n requestgroup: RequestGroupEntity,\n relatedperson: RelatedPersonEntity,\n researchdefinition: ResearchDefinitionEntity,\n researchelementdefinition: ResearchElementDefinitionEntity,\n researchstudy: ResearchStudyEntity,\n researchsubject: ResearchSubjectEntity,\n riskassessment: RiskAssessmentEntity,\n riskevidencesynthesis: RiskEvidenceSynthesisEntity,\n schedule: ScheduleEntity,\n searchparameter: SearchParameterEntity,\n servicerequest: ServiceRequestEntity,\n specimen: SpecimenEntity,\n specimendefinition: SpecimenDefinitionEntity,\n structuredefinition: StructureDefinitionEntity,\n structuremap: StructureMapEntity,\n substance: SubstanceEntity,\n substancenucleicacid: SubstanceNucleicAcidEntity,\n substancepolymer: SubstancePolymerEntity,\n substanceprotein: SubstanceProteinEntity,\n substancereferenceinformation: SubstanceReferenceInformationEntity,\n substancespecification: SubstanceSpecificationEntity,\n substancesourcematerial: SubstanceSourceMaterialEntity,\n subscription: SubscriptionEntity,\n terminologycapabilities: TerminologyCapabilitiesEntity,\n testreport: TestReportEntity,\n testscript: TestScriptEntity,\n valueset: ValueSetEntity,\n supplydelivery: SupplyDeliveryEntity,\n supplyrequest: SupplyRequestEntity,\n slot: SlotEntity,\n task: TaskEntity,\n visionprescription: VisionPrescriptionEntity,\n verificationresult: VerificationResultEntity,\n};\n\nconst dataPlaneService = new Service(dataPlaneEntities, {\n table: defaultTableName,\n client: dynamoClient,\n});\n\n/**\n * Data-plane service: entities for the data store (FHIR and related). Both data-plane\n * and control-plane entities share the base table (PK, SK) and the unified GSI1 (sharded\n * resource-type list per ADR-011). Same physical table.\n */\nexport const DynamoDataService = {\n entities: dataPlaneService.entities,\n transaction: dataPlaneService.transaction,\n};\n\nexport type DynamoDataServiceType = typeof DynamoDataService;\n\n/**\n * Returns the data-plane service. Table name is resolved from tableName (optional override),\n * then DYNAMO_TABLE_NAME, then \"jesttesttable\".\n */\nexport function getDynamoDataService(\n tableName?: string,\n): DynamoDataServiceType {\n const resolved = tableName ?? defaultTableName;\n const service = new Service(dataPlaneEntities, {\n table: resolved,\n client: dynamoClient,\n });\n return {\n entities: service.entities,\n transaction: service.transaction,\n };\n}\n","import { Entity } from \"electrodb\";\nimport { computeShard } from \"../shard\";\n\n/**\n * Shared attributes for all data-plane FHIR entities (tenant-isolated, single-table store).\n * Used by all data-plane entities (Account, Patient, Encounter, Practitioner, etc.).\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/entity-standards.md\n */\nexport const dataEntityAttributes = {\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 tenantId: {\n type: \"string\" as const,\n required: true,\n },\n workspaceId: {\n type: \"string\" as const,\n required: true,\n },\n /** FHIR Resource.id; logical id in URL and PK. */\n id: {\n type: \"string\" as const,\n required: true,\n },\n /** FHIR resource 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 of the FHIR resource as a JSON string (uncompressed). Populated on every\n * write via `extractSummary(resource)` so GSI projections can surface list/lookup data without\n * reading the compressed `resource` blob. Kept uncompressed because the summary is small and\n * must be fast to retrieve without encode/decode overhead.\n *\n * @see sites/www-docs/content/architecture/adr/2026-04-17-02-fhir-summary-projection-for-gsi-access-patterns.md\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 /**\n * Shard index segment for the GSI1 partition key. Computed deterministically from `id`\n * via `computeShard` so updates always land on the same shard. Stored as a string because\n * it appears as a literal segment in the GSI1 PK template; the underlying value is 0..3.\n * Not `required` because the value is derived via `watch`/`set`; ElectroDB's required-field\n * check runs before watch propagation, so callers must not fail validation on a derived field.\n *\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md — GSI1 (sharded)\n */\n gsi1Shard: {\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 * GSI1 sort key. Written as the index's SK verbatim so list endpoints can\n * use `BEGINS_WITH` for prefix queries (e.g. `?name=Sm` against Patient).\n * Computed at write time via `extractSortKey(resource)` per DR-004:\n * - Labeled types (LABEL_PATHS): `<normalizedLabel>#<id>`\n * - Unlabeled types: `<ISO-8601 lastUpdated>#<id>`\n * The factory deliberately does not derive this from `lastUpdated`/`id`\n * — that would lock every type into the unlabeled fallback and defeat\n * label-based BEGINS_WITH on labeled types.\n *\n * @see openhi-planning DR-004\n */\n gsi1sk: {\n type: \"string\" as const,\n required: true,\n },\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\n/** Data-plane entity names (model.entity and key segment). Single source of truth for allowed values. Keys are UPPER_SNAKE for consistency. */\nexport const DATA_ENTITY_NAMES = {\n ACCOUNT: \"account\",\n ACTIVITY_DEFINITION: \"activitydefinition\",\n ADVERSE_EVENT: \"adverseevent\",\n ALLERGY_INTOLERANCE: \"allergyintolerance\",\n APPOINTMENT: \"appointment\",\n APPOINTMENT_RESPONSE: \"appointmentresponse\",\n AUDIT_EVENT: \"auditevent\",\n BASIC: \"basic\",\n BIOLOGICALLY_DERIVED_PRODUCT: \"biologicallyderivedproduct\",\n BODY_STRUCTURE: \"bodystructure\",\n CAPABILITY_STATEMENT: \"capabilitystatement\",\n CARE_PLAN: \"careplan\",\n CARE_TEAM: \"careteam\",\n CATALOG_ENTRY: \"catalogentry\",\n CODE_SYSTEM: \"codesystem\",\n COMPARTMENT_DEFINITION: \"compartmentdefinition\",\n CONCEPT_MAP: \"conceptmap\",\n CHARGE_ITEM: \"chargeitem\",\n CHARGE_ITEM_DEFINITION: \"chargeitemdefinition\",\n CLAIM: \"claim\",\n CLAIM_RESPONSE: \"claimresponse\",\n CLINICAL_IMPRESSION: \"clinicalimpression\",\n COMMUNICATION: \"communication\",\n COMMUNICATION_REQUEST: \"communicationrequest\",\n COMPOSITION: \"composition\",\n CONDITION: \"condition\",\n CONSENT: \"consent\",\n CONTRACT: \"contract\",\n COVERAGE: \"coverage\",\n COVERAGE_ELIGIBILITY_REQUEST: \"coverageeligibilityrequest\",\n COVERAGE_ELIGIBILITY_RESPONSE: \"coverageeligibilityresponse\",\n DETECTED_ISSUE: \"detectedissue\",\n DEVICE: \"device\",\n DEVICE_DEFINITION: \"devicedefinition\",\n DEVICE_METRIC: \"devicemetric\",\n DEVICE_REQUEST: \"devicerequest\",\n DEVICE_USE_STATEMENT: \"deviceusestatement\",\n DIAGNOSTIC_REPORT: \"diagnosticreport\",\n DOCUMENT_MANIFEST: \"documentmanifest\",\n DOCUMENT_REFERENCE: \"documentreference\",\n EFFECT_EVIDENCE_SYNTHESIS: \"effectevidencesynthesis\",\n ENCOUNTER: \"encounter\",\n ENDPOINT: \"endpoint\",\n ENROLLMENT_REQUEST: \"enrollmentrequest\",\n ENROLLMENT_RESPONSE: \"enrollmentresponse\",\n EPISODE_OF_CARE: \"episodeofcare\",\n EVENT_DEFINITION: \"eventdefinition\",\n EVIDENCE: \"evidence\",\n EVIDENCE_VARIABLE: \"evidencevariable\",\n EXAMPLE_SCENARIO: \"examplescenario\",\n EXPLANATION_OF_BENEFIT: \"explanationofbenefit\",\n FAMILY_MEMBER_HISTORY: \"familymemberhistory\",\n FLAG: \"flag\",\n GOAL: \"goal\",\n GRAPH_DEFINITION: \"graphdefinition\",\n GROUP: \"group\",\n GUIDANCE_RESPONSE: \"guidanceresponse\",\n HEALTHCARE_SERVICE: \"healthcareservice\",\n IMAGING_STUDY: \"imagingstudy\",\n IMPLEMENTATION_GUIDE: \"implementationguide\",\n IMMUNIZATION: \"immunization\",\n IMMUNIZATION_EVALUATION: \"immunizationevaluation\",\n IMMUNIZATION_RECOMMENDATION: \"immunizationrecommendation\",\n INSURANCE_PLAN: \"insuranceplan\",\n INVOICE: \"invoice\",\n LIBRARY: \"library\",\n LINKAGE: \"linkage\",\n LIST: \"list\",\n LOCATION: \"location\",\n MEASURE: \"measure\",\n MEASURE_REPORT: \"measurereport\",\n MEDIA: \"media\",\n MEDICATION: \"medication\",\n MEDICATION_ADMINISTRATION: \"medicationadministration\",\n MEDICATION_DISPENSE: \"medicationdispense\",\n MEDICATION_KNOWLEDGE: \"medicationknowledge\",\n MEDICATION_REQUEST: \"medicationrequest\",\n MEDICATION_STATEMENT: \"medicationstatement\",\n MEDICINAL_PRODUCT: \"medicinalproduct\",\n MEDICINAL_PRODUCT_AUTHORIZATION: \"medicinalproductauthorization\",\n MEDICINAL_PRODUCT_CONTRAINDICATION: \"medicinalproductcontraindication\",\n MEDICINAL_PRODUCT_INGREDIENT: \"medicinalproductingredient\",\n MEDICINAL_PRODUCT_INDICATION: \"medicinalproductindication\",\n MEDICINAL_PRODUCT_INTERACTION: \"medicinalproductinteraction\",\n MEDICINAL_PRODUCT_MANUFACTURED: \"medicinalproductmanufactured\",\n MEDICINAL_PRODUCT_PACKAGED: \"medicinalproductpackaged\",\n MEDICINAL_PRODUCT_PHARMACEUTICAL: \"medicinalproductpharmaceutical\",\n MEDICINAL_PRODUCT_UNDESIRABLE_EFFECT: \"medicinalproductundesirableeffect\",\n MESSAGE_DEFINITION: \"messagedefinition\",\n MESSAGE_HEADER: \"messageheader\",\n MOLECULAR_SEQUENCE: \"molecularsequence\",\n NAMING_SYSTEM: \"namingsystem\",\n NUTRITION_ORDER: \"nutritionorder\",\n OBSERVATION: \"observation\",\n OBSERVATION_DEFINITION: \"observationdefinition\",\n OPERATION_DEFINITION: \"operationdefinition\",\n ORGANIZATION: \"organization\",\n ORGANIZATION_AFFILIATION: \"organizationaffiliation\",\n PATIENT: \"patient\",\n PAYMENT_NOTICE: \"paymentnotice\",\n PAYMENT_RECONCILIATION: \"paymentreconciliation\",\n PERSON: \"person\",\n PLAN_DEFINITION: \"plandefinition\",\n PRACTITIONER: \"practitioner\",\n PRACTITIONER_ROLE: \"practitionerrole\",\n PROCEDURE: \"procedure\",\n PROVENANCE: \"provenance\",\n QUESTIONNAIRE: \"questionnaire\",\n QUESTIONNAIRE_RESPONSE: \"questionnaireresponse\",\n RELATED_PERSON: \"relatedperson\",\n REQUEST_GROUP: \"requestgroup\",\n RESEARCH_DEFINITION: \"researchdefinition\",\n RESEARCH_ELEMENT_DEFINITION: \"researchelementdefinition\",\n RESEARCH_STUDY: \"researchstudy\",\n RESEARCH_SUBJECT: \"researchsubject\",\n SEARCH_PARAMETER: \"searchparameter\",\n RISK_ASSESSMENT: \"riskassessment\",\n RISK_EVIDENCE_SYNTHESIS: \"riskevidencesynthesis\",\n SCHEDULE: \"schedule\",\n SERVICE_REQUEST: \"servicerequest\",\n SLOT: \"slot\",\n SPECIMEN: \"specimen\",\n SPECIMEN_DEFINITION: \"specimendefinition\",\n STRUCTURE_DEFINITION: \"structuredefinition\",\n STRUCTURE_MAP: \"structuremap\",\n SUBSTANCE: \"substance\",\n SUBSTANCE_NUCLEIC_ACID: \"substancenucleicacid\",\n SUBSTANCE_POLYMER: \"substancepolymer\",\n SUBSTANCE_PROTEIN: \"substanceprotein\",\n SUBSTANCE_REFERENCE_INFORMATION: \"substancereferenceinformation\",\n SUBSTANCE_SPECIFICATION: \"substancespecification\",\n SUBSTANCE_SOURCE_MATERIAL: \"substancesourcematerial\",\n SUBSCRIPTION: \"subscription\",\n TERMINOLOGY_CAPABILITIES: \"terminologycapabilities\",\n TEST_REPORT: \"testreport\",\n TEST_SCRIPT: \"testscript\",\n VALUE_SET: \"valueset\",\n SUPPLY_DELIVERY: \"supplydelivery\",\n SUPPLY_REQUEST: \"supplyrequest\",\n TASK: \"task\",\n VERIFICATION_RESULT: \"verificationresult\",\n VISION_PRESCRIPTION: \"visionprescription\",\n} as const;\n\n/** Data-plane entity name (model.entity and key segment). */\nexport type DataEntityName =\n (typeof DATA_ENTITY_NAMES)[keyof typeof DATA_ENTITY_NAMES];\n\n/**\n * Creates an ElectroDB Entity for a data-plane FHIR resource with the common model, attributes,\n * base-table index, and GSI1 (Unified Sharded List per ADR-011 / DR-004) for list-by-type-in-workspace.\n *\n * GSI1 PK shape: `TID#<tid>#WID#<wid>#RT#<resourceTypeLabel>#SHARD#<n>` where `n = computeShard(id)`\n * (4-way fixed sharding). GSI1 SK shape: `<lastUpdated>#<id>` — the unlabeled fallback per DR-004.\n * Labeled sort keys (e.g. `<normalizedLabel>#<id>` for Patient/Practitioner/etc.) ride on top of\n * this contract through the writer's `extractSortKey(resource)` integration; this factory wires the\n * index, attribute, and the deterministic shard derivation. PK template uses resourceTypeLabel as a\n * literal so each entity instance binds its own type segment.\n *\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md — GSI1\n * @see sites/www-docs/content/architecture/adr/ — ADR-011, DR-004\n */\nexport function createDataEntity(\n entity: DataEntityName,\n resourceTypeLabel: string,\n) {\n return new Entity({\n model: {\n entity,\n service: \"data\",\n version: \"01\",\n },\n attributes: dataEntityAttributes,\n indexes: {\n /** Base table: PK, SK (data store key names). PK is built from tenantId, workspaceId, id. */\n record: {\n pk: {\n field: \"PK\",\n composite: [\"tenantId\", \"workspaceId\", \"id\"],\n template: `TID#\\${tenantId}#WID#\\${workspaceId}#RT#${resourceTypeLabel}#ID#\\${id}`,\n },\n sk: {\n field: \"SK\",\n composite: [\"sk\"],\n },\n },\n /**\n * GSI1 — Unified Sharded List: list all resources of this type in a workspace; reads fan\n * out across the four shards and merge by SK. SK is the writer-supplied `gsi1sk` verbatim\n * (per DR-004) so labeled types serve `BEGINS_WITH` prefix queries on the natural label.\n * `casing: \"none\"` is required on the SK because the writer (`extractSortKey`) already\n * applies DR-004 normalization — ElectroDB's default lowercasing would mangle the\n * ISO-8601 unlabeled fallback (`T`/`Z` → `t`/`z`).\n */\n gsi1: {\n index: \"GSI1\",\n pk: {\n field: \"GSI1PK\",\n composite: [\"tenantId\", \"workspaceId\", \"gsi1Shard\"],\n template: `TID#\\${tenantId}#WID#\\${workspaceId}#RT#${resourceTypeLabel}#SHARD#\\${gsi1Shard}`,\n },\n sk: {\n field: \"GSI1SK\",\n casing: \"none\" as const,\n composite: [\"gsi1sk\"],\n template: `\\${gsi1sk}`,\n },\n },\n },\n });\n}\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Account data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Account#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const AccountEntity = createDataEntity(\"account\", \"Account\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ActivityDefinition data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ActivityDefinition#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ActivityDefinitionEntity = createDataEntity(\n \"activitydefinition\",\n \"ActivityDefinition\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * AdverseEvent data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#AdverseEvent#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const AdverseEventEntity = createDataEntity(\n \"adverseevent\",\n \"AdverseEvent\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * AllergyIntolerance data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#AllergyIntolerance#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const AllergyIntoleranceEntity = createDataEntity(\n \"allergyintolerance\",\n \"AllergyIntolerance\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Appointment data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Appointment#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const AppointmentEntity = createDataEntity(\"appointment\", \"Appointment\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * AppointmentResponse data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#AppointmentResponse#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const AppointmentResponseEntity = createDataEntity(\n \"appointmentresponse\",\n \"AppointmentResponse\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * AuditEvent data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#AuditEvent#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const AuditEventEntity = createDataEntity(\"auditevent\", \"AuditEvent\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Basic data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Basic#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const BasicEntity = createDataEntity(\"basic\", \"Basic\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * BiologicallyDerivedProduct data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#BiologicallyDerivedProduct#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const BiologicallyDerivedProductEntity = createDataEntity(\n \"biologicallyderivedproduct\",\n \"BiologicallyDerivedProduct\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * BodyStructure data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#BodyStructure#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const BodyStructureEntity = createDataEntity(\n \"bodystructure\",\n \"BodyStructure\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * CapabilityStatement data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#CapabilityStatement#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const CapabilityStatementEntity = createDataEntity(\n \"capabilitystatement\",\n \"CapabilityStatement\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * CarePlan data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#CarePlan#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const CarePlanEntity = createDataEntity(\"careplan\", \"CarePlan\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * CareTeam data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#CareTeam#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const CareTeamEntity = createDataEntity(\"careteam\", \"CareTeam\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * CatalogEntry data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#CatalogEntry#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const CatalogEntryEntity = createDataEntity(\n \"catalogentry\",\n \"CatalogEntry\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ChargeItemDefinition data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ChargeItemDefinition#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ChargeItemDefinitionEntity = createDataEntity(\n \"chargeitemdefinition\",\n \"ChargeItemDefinition\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ChargeItem data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ChargeItem#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ChargeItemEntity = createDataEntity(\"chargeitem\", \"ChargeItem\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Claim data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Claim#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ClaimEntity = createDataEntity(\"claim\", \"Claim\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ClaimResponse data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ClaimResponse#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ClaimResponseEntity = createDataEntity(\n \"claimresponse\",\n \"ClaimResponse\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ClinicalImpression data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ClinicalImpression#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ClinicalImpressionEntity = createDataEntity(\n \"clinicalimpression\",\n \"ClinicalImpression\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * CodeSystem data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#CodeSystem#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const CodeSystemEntity = createDataEntity(\"codesystem\", \"CodeSystem\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Communication data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Communication#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const CommunicationEntity = createDataEntity(\n \"communication\",\n \"Communication\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * CommunicationRequest data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#CommunicationRequest#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const CommunicationRequestEntity = createDataEntity(\n \"communicationrequest\",\n \"CommunicationRequest\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * CompartmentDefinition data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#CompartmentDefinition#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const CompartmentDefinitionEntity = createDataEntity(\n \"compartmentdefinition\",\n \"CompartmentDefinition\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Composition data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Composition#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const CompositionEntity = createDataEntity(\"composition\", \"Composition\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ConceptMap data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ConceptMap#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ConceptMapEntity = createDataEntity(\"conceptmap\", \"ConceptMap\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Condition data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Condition#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ConditionEntity = createDataEntity(\"condition\", \"Condition\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Consent data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Consent#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ConsentEntity = createDataEntity(\"consent\", \"Consent\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Contract data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Contract#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ContractEntity = createDataEntity(\"contract\", \"Contract\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * CoverageEligibilityRequest data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#CoverageEligibilityRequest#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const CoverageEligibilityRequestEntity = createDataEntity(\n \"coverageeligibilityrequest\",\n \"CoverageEligibilityRequest\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * CoverageEligibilityResponse data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#CoverageEligibilityResponse#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const CoverageEligibilityResponseEntity = createDataEntity(\n \"coverageeligibilityresponse\",\n \"CoverageEligibilityResponse\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Coverage data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Coverage#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const CoverageEntity = createDataEntity(\"coverage\", \"Coverage\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * DetectedIssue data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#DetectedIssue#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const DetectedIssueEntity = createDataEntity(\n \"detectedissue\",\n \"DetectedIssue\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * DeviceDefinition data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#DeviceDefinition#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const DeviceDefinitionEntity = createDataEntity(\n \"devicedefinition\",\n \"DeviceDefinition\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Device data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Device#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const DeviceEntity = createDataEntity(\"device\", \"Device\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * DeviceMetric data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#DeviceMetric#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const DeviceMetricEntity = createDataEntity(\n \"devicemetric\",\n \"DeviceMetric\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * DeviceRequest data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#DeviceRequest#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const DeviceRequestEntity = createDataEntity(\n \"devicerequest\",\n \"DeviceRequest\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * DeviceUseStatement data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#DeviceUseStatement#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const DeviceUseStatementEntity = createDataEntity(\n \"deviceusestatement\",\n \"DeviceUseStatement\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * DiagnosticReport data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#DiagnosticReport#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const DiagnosticReportEntity = createDataEntity(\n \"diagnosticreport\",\n \"DiagnosticReport\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * DocumentManifest data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#DocumentManifest#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const DocumentManifestEntity = createDataEntity(\n \"documentmanifest\",\n \"DocumentManifest\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * DocumentReference data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#DocumentReference#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const DocumentReferenceEntity = createDataEntity(\n \"documentreference\",\n \"DocumentReference\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * EffectEvidenceSynthesis data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#EffectEvidenceSynthesis#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const EffectEvidenceSynthesisEntity = createDataEntity(\n \"effectevidencesynthesis\",\n \"EffectEvidenceSynthesis\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Encounter data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Encounter#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with Patient and other domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\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/entities/encounter.md\n */\nexport const EncounterEntity = createDataEntity(\"encounter\", \"Encounter\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Endpoint data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Endpoint#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const EndpointEntity = createDataEntity(\"endpoint\", \"Endpoint\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * EnrollmentRequest data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#EnrollmentRequest#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const EnrollmentRequestEntity = createDataEntity(\n \"enrollmentrequest\",\n \"EnrollmentRequest\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * EnrollmentResponse data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#EnrollmentResponse#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const EnrollmentResponseEntity = createDataEntity(\n \"enrollmentresponse\",\n \"EnrollmentResponse\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * EpisodeOfCare data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#EpisodeOfCare#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const EpisodeOfCareEntity = createDataEntity(\n \"episodeofcare\",\n \"EpisodeOfCare\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * EventDefinition data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#EventDefinition#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const EventDefinitionEntity = createDataEntity(\n \"eventdefinition\",\n \"EventDefinition\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Evidence data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Evidence#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const EvidenceEntity = createDataEntity(\"evidence\", \"Evidence\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * EvidenceVariable data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#EvidenceVariable#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const EvidenceVariableEntity = createDataEntity(\n \"evidencevariable\",\n \"EvidenceVariable\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ExampleScenario data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ExampleScenario#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ExampleScenarioEntity = createDataEntity(\n \"examplescenario\",\n \"ExampleScenario\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ExplanationOfBenefit data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ExplanationOfBenefit#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ExplanationOfBenefitEntity = createDataEntity(\n \"explanationofbenefit\",\n \"ExplanationOfBenefit\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * FamilyMemberHistory data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#FamilyMemberHistory#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const FamilyMemberHistoryEntity = createDataEntity(\n \"familymemberhistory\",\n \"FamilyMemberHistory\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Flag data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Flag#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const FlagEntity = createDataEntity(\"flag\", \"Flag\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Goal data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Goal#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const GoalEntity = createDataEntity(\"goal\", \"Goal\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * GraphDefinition data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#GraphDefinition#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const GraphDefinitionEntity = createDataEntity(\n \"graphdefinition\",\n \"GraphDefinition\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Group data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Group#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const GroupEntity = createDataEntity(\"group\", \"Group\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * GuidanceResponse data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#GuidanceResponse#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const GuidanceResponseEntity = createDataEntity(\n \"guidanceresponse\",\n \"GuidanceResponse\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * HealthcareService data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#HealthcareService#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const HealthcareServiceEntity = createDataEntity(\n \"healthcareservice\",\n \"HealthcareService\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ImagingStudy data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ImagingStudy#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ImagingStudyEntity = createDataEntity(\n \"imagingstudy\",\n \"ImagingStudy\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Immunization data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Immunization#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ImmunizationEntity = createDataEntity(\n \"immunization\",\n \"Immunization\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ImmunizationEvaluation data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ImmunizationEvaluation#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ImmunizationEvaluationEntity = createDataEntity(\n \"immunizationevaluation\",\n \"ImmunizationEvaluation\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ImmunizationRecommendation data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ImmunizationRecommendation#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ImmunizationRecommendationEntity = createDataEntity(\n \"immunizationrecommendation\",\n \"ImmunizationRecommendation\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ImplementationGuide data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ImplementationGuide#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ImplementationGuideEntity = createDataEntity(\n \"implementationguide\",\n \"ImplementationGuide\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * InsurancePlan data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#InsurancePlan#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const InsurancePlanEntity = createDataEntity(\n \"insuranceplan\",\n \"InsurancePlan\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Invoice data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Invoice#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const InvoiceEntity = createDataEntity(\"invoice\", \"Invoice\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Library data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Library#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const LibraryEntity = createDataEntity(\"library\", \"Library\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Linkage data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Linkage#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const LinkageEntity = createDataEntity(\"linkage\", \"Linkage\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * List data-store entity based on FHIR R4 (single-table store).\n * Represents the FHIR List resource (curated list of items).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#List#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ListEntity = createDataEntity(\"list\", \"List\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Location data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Location#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const LocationEntity = createDataEntity(\"location\", \"Location\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Measure data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Measure#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MeasureEntity = createDataEntity(\"measure\", \"Measure\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MeasureReport data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MeasureReport#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MeasureReportEntity = createDataEntity(\n \"measurereport\",\n \"MeasureReport\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Media data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Media#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MediaEntity = createDataEntity(\"media\", \"Media\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MedicationAdministration data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MedicationAdministration#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MedicationAdministrationEntity = createDataEntity(\n \"medicationadministration\",\n \"MedicationAdministration\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MedicationDispense data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MedicationDispense#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MedicationDispenseEntity = createDataEntity(\n \"medicationdispense\",\n \"MedicationDispense\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Medication data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Medication#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MedicationEntity = createDataEntity(\"medication\", \"Medication\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MedicationKnowledge data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MedicationKnowledge#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MedicationKnowledgeEntity = createDataEntity(\n \"medicationknowledge\",\n \"MedicationKnowledge\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MedicationRequest data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MedicationRequest#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MedicationRequestEntity = createDataEntity(\n \"medicationrequest\",\n \"MedicationRequest\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MedicationStatement data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MedicationStatement#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MedicationStatementEntity = createDataEntity(\n \"medicationstatement\",\n \"MedicationStatement\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MedicinalProductAuthorization data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MedicinalProductAuthorization#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MedicinalProductAuthorizationEntity = createDataEntity(\n \"medicinalproductauthorization\",\n \"MedicinalProductAuthorization\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MedicinalProductContraindication data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MedicinalProductContraindication#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MedicinalProductContraindicationEntity = createDataEntity(\n \"medicinalproductcontraindication\",\n \"MedicinalProductContraindication\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MedicinalProduct data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MedicinalProduct#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MedicinalProductEntity = createDataEntity(\n \"medicinalproduct\",\n \"MedicinalProduct\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MedicinalProductIndication data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MedicinalProductIndication#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MedicinalProductIndicationEntity = createDataEntity(\n \"medicinalproductindication\",\n \"MedicinalProductIndication\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MedicinalProductIngredient data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MedicinalProductIngredient#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MedicinalProductIngredientEntity = createDataEntity(\n \"medicinalproductingredient\",\n \"MedicinalProductIngredient\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MedicinalProductInteraction data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MedicinalProductInteraction#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MedicinalProductInteractionEntity = createDataEntity(\n \"medicinalproductinteraction\",\n \"MedicinalProductInteraction\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MedicinalProductManufactured data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MedicinalProductManufactured#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MedicinalProductManufacturedEntity = createDataEntity(\n \"medicinalproductmanufactured\",\n \"MedicinalProductManufactured\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MedicinalProductPackaged data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MedicinalProductPackaged#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MedicinalProductPackagedEntity = createDataEntity(\n \"medicinalproductpackaged\",\n \"MedicinalProductPackaged\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MedicinalProductPharmaceutical data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MedicinalProductPharmaceutical#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MedicinalProductPharmaceuticalEntity = createDataEntity(\n \"medicinalproductpharmaceutical\",\n \"MedicinalProductPharmaceutical\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MedicinalProductUndesirableEffect data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MedicinalProductUndesirableEffect#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MedicinalProductUndesirableEffectEntity = createDataEntity(\n \"medicinalproductundesirableeffect\",\n \"MedicinalProductUndesirableEffect\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MessageDefinition data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MessageDefinition#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MessageDefinitionEntity = createDataEntity(\n \"messagedefinition\",\n \"MessageDefinition\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MessageHeader data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MessageHeader#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MessageHeaderEntity = createDataEntity(\n \"messageheader\",\n \"MessageHeader\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * MolecularSequence data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#MolecularSequence#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const MolecularSequenceEntity = createDataEntity(\n \"molecularsequence\",\n \"MolecularSequence\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * NamingSystem data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#NamingSystem#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const NamingSystemEntity = createDataEntity(\n \"namingsystem\",\n \"NamingSystem\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * NutritionOrder data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#NutritionOrder#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const NutritionOrderEntity = createDataEntity(\n \"nutritionorder\",\n \"NutritionOrder\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ObservationDefinition data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ObservationDefinition#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ObservationDefinitionEntity = createDataEntity(\n \"observationdefinition\",\n \"ObservationDefinition\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Observation data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Observation#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ObservationEntity = createDataEntity(\"observation\", \"Observation\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * OperationDefinition data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#OperationDefinition#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const OperationDefinitionEntity = createDataEntity(\n \"operationdefinition\",\n \"OperationDefinition\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * OrganizationAffiliation data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#OrganizationAffiliation#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const OrganizationAffiliationEntity = createDataEntity(\n \"organizationaffiliation\",\n \"OrganizationAffiliation\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Organization data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Organization#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const OrganizationEntity = createDataEntity(\n \"organization\",\n \"Organization\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Patient data-store entity based on FHIR (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Patient#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) are documented in the Data-Store Entity Standards (FHIR).\n * Audit is in FHIR resource meta (meta.extension), not item attributes. See entity-standards.md.\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/patient.md\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const PatientEntity = createDataEntity(\"patient\", \"Patient\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * PaymentNotice data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#PaymentNotice#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const PaymentNoticeEntity = createDataEntity(\n \"paymentnotice\",\n \"PaymentNotice\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * PaymentReconciliation data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#PaymentReconciliation#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const PaymentReconciliationEntity = createDataEntity(\n \"paymentreconciliation\",\n \"PaymentReconciliation\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Person data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Person#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const PersonEntity = createDataEntity(\"person\", \"Person\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * PlanDefinition data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#PlanDefinition#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const PlanDefinitionEntity = createDataEntity(\n \"plandefinition\",\n \"PlanDefinition\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Practitioner data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Practitioner#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with Patient, Encounter, and entity standards.\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/practitioner.md\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const PractitionerEntity = createDataEntity(\n \"practitioner\",\n \"Practitioner\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * PractitionerRole data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#PractitionerRole#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const PractitionerRoleEntity = createDataEntity(\n \"practitionerrole\",\n \"PractitionerRole\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Procedure data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Procedure#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ProcedureEntity = createDataEntity(\"procedure\", \"Procedure\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Provenance data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Provenance#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ProvenanceEntity = createDataEntity(\"provenance\", \"Provenance\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Questionnaire data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Questionnaire#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const QuestionnaireEntity = createDataEntity(\n \"questionnaire\",\n \"Questionnaire\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * QuestionnaireResponse data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#QuestionnaireResponse#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const QuestionnaireResponseEntity = createDataEntity(\n \"questionnaireresponse\",\n \"QuestionnaireResponse\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * RelatedPerson data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#RelatedPerson#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const RelatedPersonEntity = createDataEntity(\n \"relatedperson\",\n \"RelatedPerson\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * RequestGroup data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#RequestGroup#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const RequestGroupEntity = createDataEntity(\n \"requestgroup\",\n \"RequestGroup\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ResearchDefinition data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ResearchDefinition#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ResearchDefinitionEntity = createDataEntity(\n \"researchdefinition\",\n \"ResearchDefinition\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ResearchElementDefinition data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ResearchElementDefinition#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ResearchElementDefinitionEntity = createDataEntity(\n \"researchelementdefinition\",\n \"ResearchElementDefinition\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ResearchStudy data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ResearchStudy#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ResearchStudyEntity = createDataEntity(\n \"researchstudy\",\n \"ResearchStudy\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ResearchSubject data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ResearchSubject#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ResearchSubjectEntity = createDataEntity(\n \"researchsubject\",\n \"ResearchSubject\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * RiskAssessment data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#RiskAssessment#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const RiskAssessmentEntity = createDataEntity(\n \"riskassessment\",\n \"RiskAssessment\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * RiskEvidenceSynthesis data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#RiskEvidenceSynthesis#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const RiskEvidenceSynthesisEntity = createDataEntity(\n \"riskevidencesynthesis\",\n \"RiskEvidenceSynthesis\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Schedule data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Schedule#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ScheduleEntity = createDataEntity(\"schedule\", \"Schedule\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * SearchParameter data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#SearchParameter#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const SearchParameterEntity = createDataEntity(\n \"searchparameter\",\n \"SearchParameter\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ServiceRequest data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ServiceRequest#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ServiceRequestEntity = createDataEntity(\n \"servicerequest\",\n \"ServiceRequest\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Slot data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Slot#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const SlotEntity = createDataEntity(\"slot\", \"Slot\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * SpecimenDefinition data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#SpecimenDefinition#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const SpecimenDefinitionEntity = createDataEntity(\n \"specimendefinition\",\n \"SpecimenDefinition\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Specimen data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Specimen#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const SpecimenEntity = createDataEntity(\"specimen\", \"Specimen\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * StructureDefinition data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#StructureDefinition#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const StructureDefinitionEntity = createDataEntity(\n \"structuredefinition\",\n \"StructureDefinition\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * StructureMap data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#StructureMap#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const StructureMapEntity = createDataEntity(\n \"structuremap\",\n \"StructureMap\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Subscription data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Subscription#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const SubscriptionEntity = createDataEntity(\n \"subscription\",\n \"Subscription\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Substance data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Substance#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const SubstanceEntity = createDataEntity(\"substance\", \"Substance\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * SubstanceNucleicAcid data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#SubstanceNucleicAcid#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const SubstanceNucleicAcidEntity = createDataEntity(\n \"substancenucleicacid\",\n \"SubstanceNucleicAcid\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * SubstancePolymer data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#SubstancePolymer#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const SubstancePolymerEntity = createDataEntity(\n \"substancepolymer\",\n \"SubstancePolymer\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * SubstanceProtein data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#SubstanceProtein#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const SubstanceProteinEntity = createDataEntity(\n \"substanceprotein\",\n \"SubstanceProtein\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * SubstanceReferenceInformation data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#SubstanceReferenceInformation#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const SubstanceReferenceInformationEntity = createDataEntity(\n \"substancereferenceinformation\",\n \"SubstanceReferenceInformation\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * SubstanceSourceMaterial data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#SubstanceSourceMaterial#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const SubstanceSourceMaterialEntity = createDataEntity(\n \"substancesourcematerial\",\n \"SubstanceSourceMaterial\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * SubstanceSpecification data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#SubstanceSpecification#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const SubstanceSpecificationEntity = createDataEntity(\n \"substancespecification\",\n \"SubstanceSpecification\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * SupplyDelivery data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#SupplyDelivery#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const SupplyDeliveryEntity = createDataEntity(\n \"supplydelivery\",\n \"SupplyDelivery\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * SupplyRequest data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#SupplyRequest#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const SupplyRequestEntity = createDataEntity(\n \"supplyrequest\",\n \"SupplyRequest\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * Task data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#Task#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const TaskEntity = createDataEntity(\"task\", \"Task\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * TerminologyCapabilities data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#TerminologyCapabilities#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const TerminologyCapabilitiesEntity = createDataEntity(\n \"terminologycapabilities\",\n \"TerminologyCapabilities\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * TestReport data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#TestReport#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const TestReportEntity = createDataEntity(\"testreport\", \"TestReport\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * TestScript data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#TestScript#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const TestScriptEntity = createDataEntity(\"testscript\", \"TestScript\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * ValueSet data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#ValueSet#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const ValueSetEntity = createDataEntity(\"valueset\", \"ValueSet\");\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * VerificationResult data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#VerificationResult#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const VerificationResultEntity = createDataEntity(\n \"verificationresult\",\n \"VerificationResult\",\n);\n","import { createDataEntity } from \"../data-entity-common\";\n\n/**\n * VisionPrescription data-store entity based on FHIR R4 (single-table store).\n *\n * **Classification (ADR 2026-03-03-01):** Tenant-isolated, data plane. Strict isolation: tenantId and\n * workspaceId are required (no defaults, no sentinels). No crossover between tenants or workspaces.\n *\n * Key structure: PK = TID#<tenantId>#WID#<workspaceId>#RT#VisionPrescription#ID#<id>, SK = CURRENT.\n * Standard attributes (FHIR source and entity purpose) align with other data-plane domain resources.\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/entity-standards.md — Standard attributes (all FHIR domain resources)\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/single-table-design.md\n */\nexport const VisionPrescriptionEntity = createDataEntity(\n \"visionprescription\",\n \"VisionPrescription\",\n);\n","import { extractSortKey, extractSummary } from \"@openhi/types\";\nimport type { Meta, FhirResourceLike } from \"@openhi/types\";\nimport { compressResource, decompressResource } from \"../../lib/compression\";\nimport { mergeAuditIntoMeta, type MetaWithExtensions } from \"../audit-meta\";\nimport { SHARD_COUNT } from \"../dynamo/shard\";\nimport { NotFoundError } from \"../errors\";\nimport type { OpenHiContext } from \"../openhi-context\";\n\n/**\n * Sort key for the current record version. Matches Dynamo record index SK default.\n * Use this in get/update/delete (and create where applicable) for data-plane entities.\n */\nexport const DATA_ENTITY_SK = \"CURRENT\" as const;\n\n/** Base params for data-entity operations: context and optional table override. */\nexport interface BaseDataEntityParams {\n context: OpenHiContext;\n /** Optional table name override; resolved by data service from DYNAMO_TABLE_NAME when omitted. */\n tableName?: string;\n}\n\n/** Params for get-by-id and delete (context + id + optional tableName). */\nexport interface GetByIdParams extends BaseDataEntityParams {\n id: string;\n}\n\n/**\n * Mode for list operations introduced by #853 to back FHIR `_summary` opt-ins.\n *\n * - `full` (default): GSI1 fan-out → BatchGet hydration → full FHIR resource per entry.\n * - `summary`: GSI1 fan-out only; the `summary` JSON projected onto GSI1 is parsed and used\n * as `resource` per entry. Skips BatchGet entirely — that's the cost win the FHIR spec\n * intends `_summary=true` to deliver.\n * - `count`: GSI1 fan-out only; entries are dropped, only `total` is populated. Routes\n * should pass `total` into `buildSearchsetBundle({ mode: \"count\", total })`.\n *\n * `_elements` is implemented at the route layer as `full` mode + post-hydration pruning,\n * since per-element pruning has to happen after decompression and is FHIR-spec-defined\n * (always retain root-level mandatories — see `prune-resource-by-elements.ts`).\n */\nexport type ListOperationMode = \"full\" | \"summary\" | \"count\";\n\n/** Params for list (context + optional tableName + optional mode for #853 `_summary`). */\nexport interface ListParams extends BaseDataEntityParams {\n /** Defaults to `\"full\"` (current behavior); routes pass other modes for `_summary` opt-ins. */\n mode?: ListOperationMode;\n}\n\n/** Result for create / get-by-id / update: single resource. */\nexport interface SingleResourceResult<T> {\n id: string;\n resource: T;\n}\n\n/** Entry shape for list results. */\nexport interface ListEntry<T> {\n id: string;\n resource: T;\n}\n\n/**\n * Result for list: entries array plus total count.\n *\n * - For `mode === \"full\"` and `mode === \"summary\"`, `total === entries.length`.\n * - For `mode === \"count\"`, `entries` is empty and `total` is the GSI1 fan-out count.\n *\n * Splitting `total` from `entries.length` lets count-mode routes report a true count\n * while skipping any per-entry work.\n */\nexport interface ListResult<T> {\n entries: Array<ListEntry<T>>;\n total: number;\n}\n\n/** Minimal entity shape for get (used by getDataEntityById). */\ninterface EntityWithGet {\n get(params: {\n tenantId: string;\n workspaceId: string;\n id: string;\n sk: string;\n }): { go(): Promise<{ data: { id: string; resource: string } | null }> };\n}\n\n/** Minimal entity shape for delete (used by deleteDataEntityById). */\ninterface EntityWithDelete {\n delete(params: {\n tenantId: string;\n workspaceId: string;\n id: string;\n sk: string;\n }): { go(): Promise<unknown> };\n}\n\n/**\n * Minimal entity shape for list via GSI1 + BatchGet hydration (used by listDataEntitiesByWorkspace).\n * GSI1 is sharded per ADR-011, so listing fans out to each shard and concatenates ids; the\n * `resource` attribute is NOT projected onto GSI1 (per the summary projection in\n * `dynamo-db-data-store.ts`), so the second phase BatchGets the base table for full items.\n *\n * GSI1 INCLUDE projection (per `dynamo-db-data-store.ts`) carries `summary`, `vid`, `lastUpdated`,\n * `createdDate`, `modifiedDate`, `createdById`, `modifiedById` alongside the key attributes.\n * `summary` is what `mode: \"summary\"` returns to the caller without hitting the base table.\n */\ninterface DataEntityWithListAndBatchGet {\n query: {\n gsi1(params: {\n tenantId: string;\n workspaceId: string;\n gsi1Shard: string;\n }): {\n go(): Promise<{\n data: Array<{\n id: string;\n summary?: string;\n vid?: string;\n lastUpdated?: string;\n createdDate?: string;\n modifiedDate?: string;\n createdById?: string;\n modifiedById?: string;\n }> | null;\n }>;\n };\n };\n get(\n keys: Array<{\n tenantId: string;\n workspaceId: string;\n id: string;\n sk: string;\n }>,\n ): {\n go(): Promise<{\n data: Array<{ id: string; resource: string }>;\n unprocessed: Array<{\n tenantId: string;\n workspaceId: string;\n id: string;\n sk: string;\n }>;\n }>;\n };\n}\n\n/** Minimal entity shape for put (used by createDataEntityRecord). */\ninterface EntityWithPut {\n put(attrs: {\n sk: string;\n tenantId: string;\n workspaceId: string;\n id: string;\n resource: string;\n summary: string;\n vid: string;\n lastUpdated: string;\n gsi1sk: string;\n }): { go(): Promise<unknown> };\n}\n\n/** Minimal entity shape for patch (used by updateDataEntityById). */\ninterface EntityWithPatch {\n get(params: {\n tenantId: string;\n workspaceId: string;\n id: string;\n sk: string;\n }): { go(): Promise<{ data: { id: string; resource: string } | null }> };\n patch(params: {\n tenantId: string;\n workspaceId: string;\n id: string;\n sk: string;\n }): {\n set(attrs: {\n resource: string;\n summary: string;\n lastUpdated: string;\n gsi1sk: string;\n }): {\n go(): Promise<unknown>;\n };\n };\n}\n\n/**\n * Get a single data-entity record by id. Decompresses and parses resource; throws NotFoundError if missing.\n * Use from get-by-id operations with the appropriate entity and resource type.\n */\nexport async function getDataEntityById<T>(\n entity: EntityWithGet,\n tenantId: string,\n workspaceId: string,\n id: string,\n resourceLabel: string,\n): Promise<SingleResourceResult<T>> {\n const result = await entity\n .get({\n tenantId,\n workspaceId,\n id,\n sk: DATA_ENTITY_SK,\n })\n .go();\n\n if (!result.data) {\n throw new NotFoundError(`${resourceLabel} ${id} not found`, {\n details: { id },\n });\n }\n\n const parsed = JSON.parse(decompressResource(result.data.resource)) as T & {\n id?: string;\n };\n return {\n id: result.data.id,\n resource: { ...parsed, id: result.data.id } as T,\n };\n}\n\n/**\n * Delete a data-entity record by id. Idempotent (no-op if not found).\n * Use from delete operations with the appropriate entity.\n */\nexport async function deleteDataEntityById(\n entity: EntityWithDelete,\n tenantId: string,\n workspaceId: string,\n id: string,\n): Promise<void> {\n await entity\n .delete({\n tenantId,\n workspaceId,\n id,\n sk: DATA_ENTITY_SK,\n })\n .go();\n}\n\n/** Maximum total attempts (initial + retries) when hydrating list ids via BatchGet. */\nconst BATCH_GET_MAX_ATTEMPTS = 3;\n/** Base backoff in milliseconds applied to BatchGet retries; doubles each attempt. */\nconst BATCH_GET_BASE_BACKOFF_MS = 50;\n\n/** Minimal entity shape for BatchGet hydration on the base table; chunks of 100 are handled by ElectroDB. */\ninterface EntityWithBatchGet<TKey, TItem> {\n get(keys: TKey[]): {\n go(): Promise<{ data: TItem[]; unprocessed: TKey[] }>;\n };\n}\n\n/**\n * BatchGet wrapper that retries `UnprocessedKeys` with exponential backoff. ElectroDB chunks the\n * input keys into groups of 100 internally, but does not retry unprocessed keys — DynamoDB can\n * return some keys unprocessed under throttling or partial failure, and the caller must reissue\n * them. Throws after `BATCH_GET_MAX_ATTEMPTS` if any keys remain unprocessed; intended for list\n * hydration (#854) where partial results would silently truncate the response.\n */\nexport async function batchGetWithRetry<TKey, TItem>(\n entity: EntityWithBatchGet<TKey, TItem>,\n keys: TKey[],\n): Promise<TItem[]> {\n if (keys.length === 0) return [];\n\n const collected: TItem[] = [];\n let pending = keys;\n let attempt = 0;\n\n while (pending.length > 0) {\n if (attempt > 0) {\n await new Promise((resolve) =>\n setTimeout(resolve, BATCH_GET_BASE_BACKOFF_MS * 2 ** (attempt - 1)),\n );\n }\n attempt++;\n const result = await entity.get(pending).go();\n collected.push(...result.data);\n const unprocessed = result.unprocessed ?? [];\n if (unprocessed.length === 0) break;\n if (attempt >= BATCH_GET_MAX_ATTEMPTS) {\n throw new Error(\n `BatchGet exhausted retries: ${unprocessed.length} key(s) still unprocessed after ${BATCH_GET_MAX_ATTEMPTS} attempt(s)`,\n );\n }\n pending = unprocessed;\n }\n\n return collected;\n}\n\n/** GSI1 index item shape — what a sharded `gsi1.query().go()` returns per row. */\nexport interface ShardedListIndexItem {\n id: string;\n summary?: string;\n}\n\n/** Hooks that adapt a generic mode-dispatching list to a specific entity's hydration and entry shape. */\nexport interface DispatchListModeHooks<TItem, TEntry> {\n /** Hydrate the base table for the given ids (typically `batchGetWithRetry(entity, keys)`). */\n hydrate: (orderedIds: string[]) => Promise<TItem[]>;\n /** Extract the canonical id from a hydrated item so it can be matched back to the GSI1 order. */\n getId: (item: TItem) => string;\n /** Build the result entry for `mode === \"full\"` from a hydrated base-table item. */\n buildEntry: (id: string, item: TItem) => TEntry;\n /** Build the result entry for `mode === \"summary\"` from the parsed GSI1 `summary` JSON. */\n buildSummaryEntry: (\n id: string,\n parsedSummary: Record<string, unknown>,\n ) => TEntry;\n}\n\n/**\n * Mode dispatcher shared by data-plane and control-plane list operations (#853).\n *\n * Given pre-fetched `shardResults` from a sharded GSI1 fan-out, returns either:\n * - `mode === \"count\"` — `{ entries: [], total }` where total is the sum of shard row counts.\n * - `mode === \"summary\"` — entries built from each shard row's parsed `summary` JSON; rows with\n * missing or unparseable `summary` are dropped.\n * - `mode === \"full\"` — calls `hydrate(orderedIds)` (typically a BatchGet) and builds entries\n * from hydrated items in per-shard GSI1 sort order; missing items are dropped.\n *\n * Lives here (alongside `listDataEntitiesByWorkspace`) because the same dispatch logic is needed\n * by every list operation that backs a FHIR list/search endpoint, including the seven\n * control-plane peers (User, Role, Tenant, Workspace, Membership, RoleAssignment, Configuration).\n */\nexport async function dispatchListMode<TItem, TEntry>(\n mode: ListOperationMode,\n shardResults: Array<{ data: Array<ShardedListIndexItem> | null }>,\n hooks: DispatchListModeHooks<TItem, TEntry>,\n): Promise<{ entries: TEntry[]; total: number }> {\n if (mode === \"count\") {\n let total = 0;\n for (const shardResult of shardResults) {\n total += (shardResult.data ?? []).length;\n }\n return { entries: [], total };\n }\n\n if (mode === \"summary\") {\n const entries: TEntry[] = [];\n for (const shardResult of shardResults) {\n for (const item of shardResult.data ?? []) {\n if (typeof item.summary !== \"string\") continue;\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(item.summary) as Record<string, unknown>;\n } catch {\n continue;\n }\n entries.push(hooks.buildSummaryEntry(item.id, parsed));\n }\n }\n return { entries, total: entries.length };\n }\n\n const orderedIds: string[] = [];\n for (const shardResult of shardResults) {\n for (const item of shardResult.data ?? []) {\n orderedIds.push(item.id);\n }\n }\n\n if (orderedIds.length === 0) return { entries: [], total: 0 };\n\n const items = await hooks.hydrate(orderedIds);\n const byId = new Map(items.map((item) => [hooks.getId(item), item]));\n\n const entries: TEntry[] = [];\n for (const id of orderedIds) {\n const item = byId.get(id);\n if (!item) continue;\n entries.push(hooks.buildEntry(id, item));\n }\n\n return { entries, total: entries.length };\n}\n\n/**\n * List data-entity records in a workspace via GSI1.\n *\n * `mode` (default `\"full\"`) selects the read shape — see `dispatchListMode`. The data-plane\n * binding here adds the four-shard fan-out (per ADR-011) and the BatchGet hydration with\n * decompression for `mode === \"full\"`. K-way merge by `gsi1sk` is intentionally NOT done here\n * — full server-side natural sort lands with the FHIR list-endpoint plumbing that adds\n * pagination tokens.\n */\nexport async function listDataEntitiesByWorkspace<T>(\n entity: DataEntityWithListAndBatchGet,\n tenantId: string,\n workspaceId: string,\n mode: ListOperationMode = \"full\",\n): Promise<ListResult<T>> {\n const shardResults = await Promise.all(\n Array.from({ length: SHARD_COUNT }, (_, shard) =>\n entity.query\n .gsi1({ tenantId, workspaceId, gsi1Shard: String(shard) })\n .go(),\n ),\n );\n\n return dispatchListMode<{ id: string; resource: string }, ListEntry<T>>(\n mode,\n shardResults,\n {\n hydrate: (orderedIds) =>\n batchGetWithRetry(\n entity,\n orderedIds.map((id) => ({\n tenantId,\n workspaceId,\n id,\n sk: DATA_ENTITY_SK,\n })),\n ),\n getId: (item) => item.id,\n buildEntry: (id, item) => {\n const parsed = JSON.parse(decompressResource(item.resource)) as T & {\n id?: string;\n };\n return { id, resource: { ...parsed, id } as T };\n },\n buildSummaryEntry: (id, parsed) => ({\n id,\n resource: { ...parsed, id } as T,\n }),\n },\n );\n}\n\n/**\n * Create a data-entity record with put. Computes vid from lastUpdated (from resource meta or fallback).\n * Use from create operations (e.g. Practitioner, Encounter) that build the resource with audit in meta.\n */\nexport async function createDataEntityRecord<T>(\n entity: EntityWithPut,\n tenantId: string,\n workspaceId: string,\n id: string,\n resourceWithAudit: T & { meta?: { lastUpdated?: string } },\n fallbackDate: string,\n): Promise<SingleResourceResult<T>> {\n const lastUpdated =\n resourceWithAudit.meta?.lastUpdated ??\n fallbackDate ??\n new Date().toISOString();\n const vid =\n lastUpdated.replace(/[-:T.Z]/g, \"\").slice(0, 12) || Date.now().toString(36);\n\n const resourceLike = resourceWithAudit as unknown as FhirResourceLike;\n const summary = JSON.stringify(extractSummary(resourceLike));\n const gsi1sk = extractSortKey(resourceLike);\n\n await entity\n .put({\n sk: DATA_ENTITY_SK,\n tenantId,\n workspaceId,\n id,\n resource: compressResource(JSON.stringify(resourceWithAudit)),\n summary,\n vid,\n lastUpdated,\n gsi1sk,\n })\n .go();\n\n return {\n id,\n resource: resourceWithAudit as T,\n };\n}\n\n/**\n * Build an updated resource with audit in meta for use with updateDataEntityById.\n * Parses existing resource string for existing meta, merges body with id/resourceType/meta (versionId \"2\"),\n * then merges modified audit (modifiedDate, modifiedById, modifiedByName) into meta.\n * Use from update operations (Patient, Encounter, Practitioner) to avoid duplicating this logic.\n */\nexport function buildUpdatedResourceWithAudit<T extends { meta?: Meta }>(\n body: T,\n id: string,\n date: string,\n actorId: string,\n actorName: string,\n existingResourceStr: string,\n resourceType: string,\n): {\n resource: T & { id: string; meta: MetaWithExtensions };\n lastUpdated: string;\n} {\n const existingMeta: MetaWithExtensions | undefined = (\n JSON.parse(existingResourceStr) as { meta?: MetaWithExtensions }\n ).meta;\n\n const bodyWithMeta = body as T & { id?: string; meta?: Meta };\n const resourceWithVersion: T & { id: string; meta?: Meta } = {\n ...body,\n resourceType: resourceType as T[\"resourceType\"],\n id,\n meta: {\n ...(bodyWithMeta.meta ?? {}),\n lastUpdated: date,\n versionId: \"2\",\n },\n };\n\n const resourceWithAudit: T & { id: string; meta: MetaWithExtensions } = {\n ...resourceWithVersion,\n meta: mergeAuditIntoMeta(resourceWithVersion.meta ?? existingMeta, {\n modifiedDate: date,\n modifiedById: actorId,\n modifiedByName: actorName,\n }),\n };\n\n return {\n resource: resourceWithAudit,\n lastUpdated: date,\n };\n}\n\n/**\n * Update a data-entity record by id: get existing, throw if not found, then call builder with\n * decompressed existing resource string; builder returns \\{ resource, lastUpdated \\}; then patch.\n * Use from update operations with the appropriate entity and resource type.\n */\nexport async function updateDataEntityById<T>(\n entity: EntityWithPatch,\n tenantId: string,\n workspaceId: string,\n id: string,\n resourceLabel: string,\n context: OpenHiContext,\n buildPatched: (existingResourceStr: string) => {\n resource: unknown;\n lastUpdated: string;\n },\n): Promise<SingleResourceResult<T>> {\n const existing = await entity\n .get({\n tenantId,\n workspaceId,\n id,\n sk: DATA_ENTITY_SK,\n })\n .go();\n\n if (!existing.data) {\n throw new NotFoundError(`${resourceLabel} ${id} not found`, {\n details: { id },\n });\n }\n\n const existingStr = decompressResource(existing.data.resource);\n const { resource, lastUpdated } = buildPatched(existingStr);\n\n const resourceLike = resource as FhirResourceLike;\n const summary = JSON.stringify(extractSummary(resourceLike));\n const gsi1sk = extractSortKey(resourceLike);\n\n await entity\n .patch({\n tenantId,\n workspaceId,\n id,\n sk: DATA_ENTITY_SK,\n })\n .set({\n resource: compressResource(JSON.stringify(resource)),\n summary,\n lastUpdated,\n gsi1sk,\n })\n .go();\n\n return {\n id,\n resource: resource as T,\n };\n}\n","import { gzipSync, gunzipSync } from \"node:zlib\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/constructs/lib/compression.md\n */\n\n/** Envelope format version. See ADR 2026-02-15-02 (data layer compression). */\nconst ENVELOPE_VERSION = 1;\n\n/**\n * Compression algorithm identifiers supported by the envelope (string values).\n * Only algos that Node.js supports out of the box (zlib): gzip, brotli, deflate.\n * \"none\" = uncompressed payload. zstd was considered in the ADR but requires native addon/WASM.\n */\nexport const COMPRESSION_ALGOS = {\n NONE: \"none\",\n GZIP: \"gzip\",\n BROTLI: \"brotli\",\n DEFLATE: \"deflate\",\n} as const;\n\n/** Algorithm value for envelope `algo`; only gzip and none are implemented today. */\nexport type CompressionAlgo =\n (typeof COMPRESSION_ALGOS)[keyof typeof COMPRESSION_ALGOS];\n\n/** Stored value is a JSON string of this envelope. */\ninterface CompressionEnvelope {\n v: number;\n algo: string;\n payload: string;\n}\n\nfunction isEnvelope(obj: unknown): obj is CompressionEnvelope {\n return (\n typeof obj === \"object\" &&\n obj !== null &&\n \"v\" in obj &&\n \"algo\" in obj &&\n \"payload\" in obj &&\n typeof (obj as CompressionEnvelope).payload === \"string\"\n );\n}\n\n/**\n * Compresses a JSON string (e.g. serialized FHIR resource) for storage in DynamoDB.\n * Uses a versioned envelope: \\{ v, algo, payload \\} with gzip+base64 in payload.\n * Used by the data layer on write; see REST API docs (compression in data layer).\n * Optional compression: pass `{ algo: COMPRESSION_ALGOS.NONE }` to store in envelope without compressing.\n */\nexport function compressResource(\n jsonString: string,\n options?: { algo?: CompressionAlgo },\n): string {\n const algo = options?.algo ?? COMPRESSION_ALGOS.GZIP;\n if (algo === COMPRESSION_ALGOS.NONE) {\n const envelope: CompressionEnvelope = {\n v: ENVELOPE_VERSION,\n algo: COMPRESSION_ALGOS.NONE,\n payload: jsonString,\n };\n return JSON.stringify(envelope);\n }\n const buf = Buffer.from(jsonString, \"utf-8\");\n const payload = gzipSync(buf).toString(\"base64\");\n const envelope: CompressionEnvelope = {\n v: ENVELOPE_VERSION,\n algo: COMPRESSION_ALGOS.GZIP,\n payload,\n };\n return JSON.stringify(envelope);\n}\n\n/**\n * Decompresses a stored value: versioned envelope (v, algo, payload) or legacy gzip+base64 / raw.\n * If the value is not valid envelope JSON, falls back to legacy: try gzip magic on base64, else return as-is.\n */\nexport function decompressResource(compressedOrRaw: string): string {\n try {\n const parsed = JSON.parse(compressedOrRaw) as unknown;\n if (isEnvelope(parsed)) {\n if (parsed.algo === COMPRESSION_ALGOS.GZIP) {\n const buf = Buffer.from(parsed.payload, \"base64\");\n return gunzipSync(buf).toString(\"utf-8\");\n }\n if (parsed.algo === COMPRESSION_ALGOS.NONE) {\n return parsed.payload;\n }\n // Unknown algo: return payload as-is (safe fallback per ADR)\n return parsed.payload;\n }\n } catch {\n // Not valid envelope JSON — legacy path\n }\n\n // Legacy: pre-envelope gzip+base64 or raw\n try {\n const buf = Buffer.from(compressedOrRaw, \"base64\");\n if (buf.length >= 2 && buf[0] === 0x1f && buf[1] === 0x8b) {\n return gunzipSync(buf).toString(\"utf-8\");\n }\n } catch {\n // not base64 or gunzip failed\n }\n return compressedOrRaw;\n}\n","import type { Extension, Meta } from \"@openhi/types\";\n\n/**\n * Shared audit/meta helpers for FHIR resources. Used by data operations and import.\n * OpenHI audit is stored in resource meta.extension (per ADR 2026-01-13-06).\n *\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/entity-standards.md\n */\n\n/** OpenHI extension URLs for audit in resource meta (per ADR 2026-01-13-06). */\nconst OPENHI_EXT = \"http://openhi.org/fhir/StructureDefinition\";\n\n/** Meta with optional OpenHI audit extensions (created/modified by, etc.). */\nexport type MetaWithExtensions = Meta & { extension?: Array<Extension> };\n\n/** Audit fields stored in FHIR resource meta.extension. */\nexport interface AuditFields {\n createdDate?: string;\n createdById?: string;\n createdByName?: string;\n modifiedDate?: string;\n modifiedById?: string;\n modifiedByName?: string;\n deletedDate?: string;\n deletedById?: string;\n deletedByName?: string;\n}\n\n/** Audit extension entry shape (subset of Extension used by OpenHI audit). */\ntype AuditExtensionEntry = Pick<\n Extension,\n \"url\" | \"valueString\" | \"valueDateTime\"\n>;\n\n/** Builds meta.extension entries for audit; merges with existing meta. */\nexport function mergeAuditIntoMeta(\n meta: MetaWithExtensions | Record<string, unknown> | undefined,\n audit: AuditFields,\n): MetaWithExtensions {\n const existing = (meta ?? {}) as MetaWithExtensions;\n const ext: Array<AuditExtensionEntry> = [\n ...(Array.isArray(existing.extension)\n ? (existing.extension as Array<AuditExtensionEntry>)\n : []),\n ];\n const byUrl = new Map(ext.map((e) => [e.url, e]));\n function set(\n url: string,\n value: string | undefined,\n type: \"valueString\" | \"valueDateTime\",\n ) {\n if (value == null) return;\n byUrl.set(url, { url, [type]: value });\n }\n set(`${OPENHI_EXT}/created-date`, audit.createdDate, \"valueDateTime\");\n set(`${OPENHI_EXT}/created-by-id`, audit.createdById, \"valueString\");\n set(`${OPENHI_EXT}/created-by-name`, audit.createdByName, \"valueString\");\n set(`${OPENHI_EXT}/modified-date`, audit.modifiedDate, \"valueDateTime\");\n set(`${OPENHI_EXT}/modified-by-id`, audit.modifiedById, \"valueString\");\n set(`${OPENHI_EXT}/modified-by-name`, audit.modifiedByName, \"valueString\");\n set(`${OPENHI_EXT}/deleted-date`, audit.deletedDate, \"valueDateTime\");\n set(`${OPENHI_EXT}/deleted-by-id`, audit.deletedById, \"valueString\");\n set(`${OPENHI_EXT}/deleted-by-name`, audit.deletedByName, \"valueString\");\n return { ...existing, extension: Array.from(byUrl.values()) };\n}\n","import type { Organization, Reference } from \"@openhi/types\";\nimport { getDynamoDataService } from \"../../../dynamo/dynamo-data-service\";\nimport type { OpenHiContext } from \"../../../openhi-context\";\nimport {\n createDataEntityRecord,\n DATA_ENTITY_SK,\n type SingleResourceResult,\n} from \"../../data-operations-common\";\n\n/**\n * Provision the slim, id-share Organization that represents a Workspace on the data plane.\n *\n * - `Organization.id === workspaceId` (id-share with the Workspace).\n * - `name` is populated from the Workspace's name when provided.\n * - `partOf` is populated when the Workspace's Tenant has an Organization (id-share at the\n * tenant level: `Tenant.id === TenantOrganization.id`). Tenant-level provisioning is out of\n * scope for #1001 — the lookup returns `undefined` until Tenant Organizations exist.\n *\n * Idempotent: re-running with the same params overwrites the same PK with the same payload.\n *\n * @see https://github.com/codedrifters/openhi/issues/1001\n */\nexport interface ProvisionOrganizationForWorkspaceParams {\n context: OpenHiContext;\n /** Workspace id; the provisioned Organization's id equals this value. */\n workspaceId: string;\n /** Name to record on the Organization. Derived from the Workspace's `name` by the caller. */\n workspaceName?: string;\n /** Optional table name override; resolved by data service from DYNAMO_TABLE_NAME when omitted. */\n tableName?: string;\n}\n\nexport type ProvisionOrganizationForWorkspaceResult =\n SingleResourceResult<Organization>;\n\nexport async function provisionOrganizationForWorkspaceOperation(\n params: ProvisionOrganizationForWorkspaceParams,\n): Promise<ProvisionOrganizationForWorkspaceResult> {\n const { context, workspaceId, workspaceName, tableName } = params;\n const { tenantId, date } = context;\n const service = getDynamoDataService(tableName);\n\n const partOf = await resolveTenantOrganizationReference(service, tenantId);\n\n const resource: Organization = {\n resourceType: \"Organization\",\n id: workspaceId,\n ...(workspaceName !== undefined && workspaceName !== \"\"\n ? { name: workspaceName }\n : {}),\n ...(partOf !== undefined ? { partOf } : {}),\n meta: {\n lastUpdated: date,\n versionId: \"1\",\n },\n };\n\n return createDataEntityRecord<Organization>(\n service.entities.organization as Parameters<\n typeof createDataEntityRecord\n >[0],\n tenantId,\n workspaceId,\n workspaceId,\n resource,\n date,\n );\n}\n\n/**\n * Resolve the Tenant's Organization reference for `Organization.partOf`. Returns `undefined`\n * when the Tenant has no Organization yet (the default until Tenant Organization provisioning\n * is wired up in a follow-up).\n *\n * Lookup convention: the Tenant's Organization is stored at\n * `(tenantId, workspaceId=tenantId, id=tenantId)` — a self-scope key that mirrors the\n * Workspace id-share pattern one level up. This scoping convention will be ratified by the\n * Tenant Organization provisioning issue; the OrganizationEntity comment notes strict\n * isolation requires both `tenantId` and `workspaceId`, so the self-scope is the\n * simplest deterministic location.\n */\nasync function resolveTenantOrganizationReference(\n service: ReturnType<typeof getDynamoDataService>,\n tenantId: string,\n): Promise<Reference | undefined> {\n const result = await (\n service.entities.organization as {\n get(params: {\n tenantId: string;\n workspaceId: string;\n id: string;\n sk: string;\n }): { go(): Promise<{ data: unknown }> };\n }\n )\n .get({\n tenantId,\n workspaceId: tenantId,\n id: tenantId,\n sk: DATA_ENTITY_SK,\n })\n .go();\n\n if (result.data === null || result.data === undefined) {\n return undefined;\n }\n\n return { reference: `Organization/${tenantId}` };\n}\n","import type { Account, Meta } from \"@openhi/types\";\nimport { ulid } from \"ulid\";\nimport {\n mergeAuditIntoMeta,\n type MetaWithExtensions,\n} from \"../../../audit-meta\";\nimport { getDynamoDataService } from \"../../../dynamo/dynamo-data-service\";\nimport type { OpenHiContext } from \"../../../openhi-context\";\nimport {\n createDataEntityRecord,\n type SingleResourceResult,\n} from \"../../data-operations-common\";\n\n/**\n * Create an Account. Accepts FHIR-like body and OpenHI context; returns created resource.\n *\n * @see sites/www-docs/content/packages/@openhi/constructs/data/shared-data-layer-layout.md\n */\nexport interface CreateAccountParams {\n context: OpenHiContext;\n /** FHIR Account body (resourceType, id optional, meta optional). */\n body: Account;\n /** Optional table name override; resolved by data service from DYNAMO_TABLE_NAME when omitted. */\n tableName?: string;\n}\n\nexport type CreateAccountResult = SingleResourceResult<Account>;\n\n/**\n * Creates an Account. Builds put attrs with audit in meta, then ElectroDB put.\n * Throws on service/validation errors; adapters map to HTTP/GraphQL.\n */\nexport async function createAccountOperation(\n params: CreateAccountParams,\n): Promise<CreateAccountResult> {\n const { context, body, tableName } = params;\n const { tenantId, workspaceId, date, actorId, actorName } = context;\n const id = body.id ?? ulid();\n\n const meta: Meta = {\n ...(body.meta ?? {}),\n lastUpdated: date,\n versionId: \"1\",\n };\n\n const accountWithAudit: Account & {\n id: string;\n meta: MetaWithExtensions;\n } = {\n ...body,\n resourceType: \"Account\",\n id,\n meta: mergeAuditIntoMeta(meta, {\n createdDate: date,\n createdById: actorId,\n createdByName: actorName,\n modifiedDate: date,\n modifiedById: actorId,\n modifiedByName: actorName,\n }),\n };\n\n const service = getDynamoDataService(tableName);\n return createDataEntityRecord<Account>(\n service.entities.account as Parameters<typeof createDataEntityRecord>[0],\n tenantId,\n workspaceId,\n id,\n accountWithAudit,\n date,\n );\n}\n","import type { Appointment, Meta } from \"@openhi/types\";\nimport { ulid } from \"ulid\";\nimport {\n mergeAuditIntoMeta,\n type MetaWithExtensions,\n} from \"../../../audit-meta\";\nimport { getDynamoDataService } from \"../../../dynamo/dynamo-data-service\";\nimport type { OpenHiContext } from \"../../../openhi-context\";\nimport {\n createDataEntityRecord,\n type SingleResourceResult,\n} from \"../../data-operations-common\";\n\n/**\n * Create a Appointment. Accepts FHIR-like body and OpenHI context; returns created resource.\n *\n * @see sites/www-docs/content/packages/@openhi/constructs/data/shared-data-layer-layout.md\n */\nexport interface CreateAppointmentParams {\n context: OpenHiContext;\n /** FHIR Appointment body (resourceType, id optional, meta optional). */\n body: Appointment;\n /** Optional table name override; resolved by data service from DYNAMO_TABLE_NAME when omitted. */\n tableName?: string;\n}\n\nexport type CreateAppointmentResult = SingleResourceResult<Appointment>;\n\n/**\n * Creates a Appointment. Builds put attrs with audit in meta, then ElectroDB put.\n * Throws on service/validation errors; adapters map to HTTP/GraphQL.\n */\nexport async function createAppointmentOperation(\n params: CreateAppointmentParams,\n): Promise<CreateAppointmentResult> {\n const { context, body, tableName } = params;\n const { tenantId, workspaceId, date, actorId, actorName } = context;\n const id = body.id ?? ulid();\n\n const meta: Meta = {\n ...(body.meta ?? {}),\n lastUpdated: date,\n versionId: \"1\",\n };\n\n const resourceWithAudit: Appointment & {\n id: string;\n meta: MetaWithExtensions;\n } = {\n ...body,\n resourceType: \"Appointment\",\n id,\n meta: mergeAuditIntoMeta(meta, {\n createdDate: date,\n createdById: actorId,\n createdByName: actorName,\n modifiedDate: date,\n modifiedById: actorId,\n modifiedByName: actorName,\n }),\n };\n\n const service = getDynamoDataService(tableName);\n return createDataEntityRecord<Appointment>(\n service.entities.appointment as Parameters<\n typeof createDataEntityRecord\n >[0],\n tenantId,\n workspaceId,\n id,\n resourceWithAudit,\n date,\n );\n}\n","import type { Claim, Meta } from \"@openhi/types\";\nimport { ulid } from \"ulid\";\nimport {\n mergeAuditIntoMeta,\n type MetaWithExtensions,\n} from \"../../../audit-meta\";\nimport { getDynamoDataService } from \"../../../dynamo/dynamo-data-service\";\nimport type { OpenHiContext } from \"../../../openhi-context\";\nimport {\n createDataEntityRecord,\n type SingleResourceResult,\n} from \"../../data-operations-common\";\n\n/**\n * Create a Claim. Accepts FHIR-like body and OpenHI context; returns created resource.\n *\n * @see sites/www-docs/content/packages/@openhi/constructs/data/shared-data-layer-layout.md\n */\nexport interface CreateClaimParams {\n context: OpenHiContext;\n /** FHIR Claim body (resourceType, id optional, meta optional). */\n body: Claim;\n /** Optional table name override; resolved by data service from DYNAMO_TABLE_NAME when omitted. */\n tableName?: string;\n}\n\nexport type CreateClaimResult = SingleResourceResult<Claim>;\n\n/**\n * Creates a Claim. Builds put attrs with audit in meta, then ElectroDB put.\n * Throws on service/validation errors; adapters map to HTTP/GraphQL.\n */\nexport async function createClaimOperation(\n params: CreateClaimParams,\n): Promise<CreateClaimResult> {\n const { context, body, tableName } = params;\n const { tenantId, workspaceId, date, actorId, actorName } = context;\n const id = body.id ?? ulid();\n\n const meta: Meta = {\n ...(body.meta ?? {}),\n lastUpdated: date,\n versionId: \"1\",\n };\n\n const resourceWithAudit: Claim & {\n id: string;\n meta: MetaWithExtensions;\n } = {\n ...body,\n resourceType: \"Claim\",\n id,\n meta: mergeAuditIntoMeta(meta, {\n createdDate: date,\n createdById: actorId,\n createdByName: actorName,\n modifiedDate: date,\n modifiedById: actorId,\n modifiedByName: actorName,\n }),\n };\n\n const service = getDynamoDataService(tableName);\n return createDataEntityRecord<Claim>(\n service.entities.claim as Parameters<typeof createDataEntityRecord>[0],\n tenantId,\n workspaceId,\n id,\n resourceWithAudit,\n date,\n );\n}\n","import type { Condition, Meta } from \"@openhi/types\";\nimport { ulid } from \"ulid\";\nimport {\n mergeAuditIntoMeta,\n type MetaWithExtensions,\n} from \"../../../audit-meta\";\nimport { getDynamoDataService } from \"../../../dynamo/dynamo-data-service\";\nimport type { OpenHiContext } from \"../../../openhi-context\";\nimport {\n createDataEntityRecord,\n type SingleResourceResult,\n} from \"../../data-operations-common\";\n\n/**\n * Create a Condition. Accepts FHIR-like body and OpenHI context; returns created resource.\n *\n * @see sites/www-docs/content/packages/@openhi/constructs/data/shared-data-layer-layout.md\n */\nexport interface CreateConditionParams {\n context: OpenHiContext;\n /** FHIR Condition body (resourceType, id optional, meta optional). */\n body: Condition;\n /** Optional table name override; resolved by data service from DYNAMO_TABLE_NAME when omitted. */\n tableName?: string;\n}\n\nexport type CreateConditionResult = SingleResourceResult<Condition>;\n\n/**\n * Creates a Condition. Builds put attrs with audit in meta, then ElectroDB put.\n * Throws on service/validation errors; adapters map to HTTP/GraphQL.\n */\nexport async function createConditionOperation(\n params: CreateConditionParams,\n): Promise<CreateConditionResult> {\n const { context, body, tableName } = params;\n const { tenantId, workspaceId, date, actorId, actorName } = context;\n const id = body.id ?? ulid();\n\n const meta: Meta = {\n ...(body.meta ?? {}),\n lastUpdated: date,\n versionId: \"1\",\n };\n\n const resourceWithAudit: Condition & {\n id: string;\n meta: MetaWithExtensions;\n } = {\n ...body,\n resourceType: \"Condition\",\n id,\n meta: mergeAuditIntoMeta(meta, {\n createdDate: date,\n createdById: actorId,\n createdByName: actorName,\n modifiedDate: date,\n modifiedById: actorId,\n modifiedByName: actorName,\n }),\n };\n\n const service = getDynamoDataService(tableName);\n return createDataEntityRecord<Condition>(\n service.entities.condition as Parameters<typeof createDataEntityRecord>[0],\n tenantId,\n workspaceId,\n id,\n resourceWithAudit,\n date,\n );\n}\n","import type { Coverage, Meta } from \"@openhi/types\";\nimport { ulid } from \"ulid\";\nimport {\n mergeAuditIntoMeta,\n type MetaWithExtensions,\n} from \"../../../audit-meta\";\nimport { getDynamoDataService } from \"../../../dynamo/dynamo-data-service\";\nimport type { OpenHiContext } from \"../../../openhi-context\";\nimport {\n createDataEntityRecord,\n type SingleResourceResult,\n} from \"../../data-operations-common\";\n\n/**\n * Create a Coverage. Accepts FHIR-like body and OpenHI context; returns created resource.\n *\n * @see sites/www-docs/content/packages/@openhi/constructs/data/shared-data-layer-layout.md\n */\nexport interface CreateCoverageParams {\n context: OpenHiContext;\n /** FHIR Coverage body (resourceType, id optional, meta optional). */\n body: Coverage;\n /** Optional table name override; resolved by data service from DYNAMO_TABLE_NAME when omitted. */\n tableName?: string;\n}\n\nexport type CreateCoverageResult = SingleResourceResult<Coverage>;\n\n/**\n * Creates a Coverage. Builds put attrs with audit in meta, then ElectroDB put.\n * Throws on service/validation errors; adapters map to HTTP/GraphQL.\n */\nexport async function createCoverageOperation(\n params: CreateCoverageParams,\n): Promise<CreateCoverageResult> {\n const { context, body, tableName } = params;\n const { tenantId, workspaceId, date, actorId, actorName } = context;\n const id = body.id ?? ulid();\n\n const meta: Meta = {\n ...(body.meta ?? {}),\n lastUpdated: date,\n versionId: \"1\",\n };\n\n const resourceWithAudit: Coverage & {\n id: string;\n meta: MetaWithExtensions;\n } = {\n ...body,\n resourceType: \"Coverage\",\n id,\n meta: mergeAuditIntoMeta(meta, {\n createdDate: date,\n createdById: actorId,\n createdByName: actorName,\n modifiedDate: date,\n modifiedById: actorId,\n modifiedByName: actorName,\n }),\n };\n\n const service = getDynamoDataService(tableName);\n return createDataEntityRecord<Coverage>(\n service.entities.coverage as Parameters<typeof createDataEntityRecord>[0],\n tenantId,\n workspaceId,\n id,\n resourceWithAudit,\n date,\n );\n}\n","import type { Encounter, Meta } from \"@openhi/types\";\nimport { ulid } from \"ulid\";\nimport {\n mergeAuditIntoMeta,\n type MetaWithExtensions,\n} from \"../../../audit-meta\";\nimport { getDynamoDataService } from \"../../../dynamo/dynamo-data-service\";\nimport type { OpenHiContext } from \"../../../openhi-context\";\nimport {\n createDataEntityRecord,\n type SingleResourceResult,\n} from \"../../data-operations-common\";\n\n/**\n * Create an Encounter. Accepts FHIR-like body and OpenHI context; returns created resource.\n *\n * @see sites/www-docs/content/packages/@openhi/constructs/data/shared-data-layer-layout.md\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/entities/encounter.md\n */\nexport interface CreateEncounterParams {\n context: OpenHiContext;\n /** FHIR Encounter body (resourceType, id optional, meta optional). */\n body: Encounter;\n /** Optional table name override; resolved by data service from DYNAMO_TABLE_NAME when omitted. */\n tableName?: string;\n}\n\nexport type CreateEncounterResult = SingleResourceResult<Encounter>;\n\n/**\n * Creates an Encounter. Builds put attrs with audit in meta, then ElectroDB put.\n * Throws on service/validation errors; adapters map to HTTP/GraphQL.\n */\nexport async function createEncounterOperation(\n params: CreateEncounterParams,\n): Promise<CreateEncounterResult> {\n const { context, body, tableName } = params;\n const { tenantId, workspaceId, date, actorId, actorName } = context;\n const id = body.id ?? ulid();\n\n const meta: Meta = {\n ...(body.meta ?? {}),\n lastUpdated: date,\n versionId: \"1\",\n };\n\n const encounterWithAudit: Encounter & {\n id: string;\n meta: MetaWithExtensions;\n } = {\n ...body,\n resourceType: \"Encounter\",\n id,\n meta: mergeAuditIntoMeta(meta, {\n createdDate: date,\n createdById: actorId,\n createdByName: actorName,\n modifiedDate: date,\n modifiedById: actorId,\n modifiedByName: actorName,\n }),\n };\n\n const service = getDynamoDataService(tableName);\n return createDataEntityRecord<Encounter>(\n service.entities.encounter as Parameters<typeof createDataEntityRecord>[0],\n tenantId,\n workspaceId,\n id,\n encounterWithAudit,\n date,\n );\n}\n","import type { Location, Meta } from \"@openhi/types\";\nimport { ulid } from \"ulid\";\nimport {\n mergeAuditIntoMeta,\n type MetaWithExtensions,\n} from \"../../../audit-meta\";\nimport { getDynamoDataService } from \"../../../dynamo/dynamo-data-service\";\nimport type { OpenHiContext } from \"../../../openhi-context\";\nimport {\n createDataEntityRecord,\n type SingleResourceResult,\n} from \"../../data-operations-common\";\n\n/**\n * Create a Location. Accepts FHIR-like body and OpenHI context; returns created resource.\n *\n * @see sites/www-docs/content/packages/@openhi/constructs/data/shared-data-layer-layout.md\n */\nexport interface CreateLocationParams {\n context: OpenHiContext;\n /** FHIR Location body (resourceType, id optional, meta optional). */\n body: Location;\n /** Optional table name override; resolved by data service from DYNAMO_TABLE_NAME when omitted. */\n tableName?: string;\n}\n\nexport type CreateLocationResult = SingleResourceResult<Location>;\n\n/**\n * Creates a Location. Builds put attrs with audit in meta, then ElectroDB put.\n * Throws on service/validation errors; adapters map to HTTP/GraphQL.\n */\nexport async function createLocationOperation(\n params: CreateLocationParams,\n): Promise<CreateLocationResult> {\n const { context, body, tableName } = params;\n const { tenantId, workspaceId, date, actorId, actorName } = context;\n const id = body.id ?? ulid();\n\n const meta: Meta = {\n ...(body.meta ?? {}),\n lastUpdated: date,\n versionId: \"1\",\n };\n\n const resourceWithAudit: Location & {\n id: string;\n meta: MetaWithExtensions;\n } = {\n ...body,\n resourceType: \"Location\",\n id,\n meta: mergeAuditIntoMeta(meta, {\n createdDate: date,\n createdById: actorId,\n createdByName: actorName,\n modifiedDate: date,\n modifiedById: actorId,\n modifiedByName: actorName,\n }),\n };\n\n const service = getDynamoDataService(tableName);\n return createDataEntityRecord<Location>(\n service.entities.location as Parameters<typeof createDataEntityRecord>[0],\n tenantId,\n workspaceId,\n id,\n resourceWithAudit,\n date,\n );\n}\n","import type { Observation, Meta } from \"@openhi/types\";\nimport { ulid } from \"ulid\";\nimport {\n mergeAuditIntoMeta,\n type MetaWithExtensions,\n} from \"../../../audit-meta\";\nimport { getDynamoDataService } from \"../../../dynamo/dynamo-data-service\";\nimport type { OpenHiContext } from \"../../../openhi-context\";\nimport {\n createDataEntityRecord,\n type SingleResourceResult,\n} from \"../../data-operations-common\";\n\n/**\n * Create a Observation. Accepts FHIR-like body and OpenHI context; returns created resource.\n *\n * @see sites/www-docs/content/packages/@openhi/constructs/data/shared-data-layer-layout.md\n */\nexport interface CreateObservationParams {\n context: OpenHiContext;\n /** FHIR Observation body (resourceType, id optional, meta optional). */\n body: Observation;\n /** Optional table name override; resolved by data service from DYNAMO_TABLE_NAME when omitted. */\n tableName?: string;\n}\n\nexport type CreateObservationResult = SingleResourceResult<Observation>;\n\n/**\n * Creates a Observation. Builds put attrs with audit in meta, then ElectroDB put.\n * Throws on service/validation errors; adapters map to HTTP/GraphQL.\n */\nexport async function createObservationOperation(\n params: CreateObservationParams,\n): Promise<CreateObservationResult> {\n const { context, body, tableName } = params;\n const { tenantId, workspaceId, date, actorId, actorName } = context;\n const id = body.id ?? ulid();\n\n const meta: Meta = {\n ...(body.meta ?? {}),\n lastUpdated: date,\n versionId: \"1\",\n };\n\n const resourceWithAudit: Observation & {\n id: string;\n meta: MetaWithExtensions;\n } = {\n ...body,\n resourceType: \"Observation\",\n id,\n meta: mergeAuditIntoMeta(meta, {\n createdDate: date,\n createdById: actorId,\n createdByName: actorName,\n modifiedDate: date,\n modifiedById: actorId,\n modifiedByName: actorName,\n }),\n };\n\n const service = getDynamoDataService(tableName);\n return createDataEntityRecord<Observation>(\n service.entities.observation as Parameters<\n typeof createDataEntityRecord\n >[0],\n tenantId,\n workspaceId,\n id,\n resourceWithAudit,\n date,\n );\n}\n","import type { Organization, Meta } from \"@openhi/types\";\nimport { ulid } from \"ulid\";\nimport {\n mergeAuditIntoMeta,\n type MetaWithExtensions,\n} from \"../../../audit-meta\";\nimport { getDynamoDataService } from \"../../../dynamo/dynamo-data-service\";\nimport type { OpenHiContext } from \"../../../openhi-context\";\nimport {\n createDataEntityRecord,\n type SingleResourceResult,\n} from \"../../data-operations-common\";\n\n/**\n * Create a Organization. Accepts FHIR-like body and OpenHI context; returns created resource.\n *\n * @see sites/www-docs/content/packages/@openhi/constructs/data/shared-data-layer-layout.md\n */\nexport interface CreateOrganizationParams {\n context: OpenHiContext;\n /** FHIR Organization body (resourceType, id optional, meta optional). */\n body: Organization;\n /** Optional table name override; resolved by data service from DYNAMO_TABLE_NAME when omitted. */\n tableName?: string;\n}\n\nexport type CreateOrganizationResult = SingleResourceResult<Organization>;\n\n/**\n * Creates a Organization. Builds put attrs with audit in meta, then ElectroDB put.\n * Throws on service/validation errors; adapters map to HTTP/GraphQL.\n */\nexport async function createOrganizationOperation(\n params: CreateOrganizationParams,\n): Promise<CreateOrganizationResult> {\n const { context, body, tableName } = params;\n const { tenantId, workspaceId, date, actorId, actorName } = context;\n const id = body.id ?? ulid();\n\n const meta: Meta = {\n ...(body.meta ?? {}),\n lastUpdated: date,\n versionId: \"1\",\n };\n\n const resourceWithAudit: Organization & {\n id: string;\n meta: MetaWithExtensions;\n } = {\n ...body,\n resourceType: \"Organization\",\n id,\n meta: mergeAuditIntoMeta(meta, {\n createdDate: date,\n createdById: actorId,\n createdByName: actorName,\n modifiedDate: date,\n modifiedById: actorId,\n modifiedByName: actorName,\n }),\n };\n\n const service = getDynamoDataService(tableName);\n return createDataEntityRecord<Organization>(\n service.entities.organization as Parameters<\n typeof createDataEntityRecord\n >[0],\n tenantId,\n workspaceId,\n id,\n resourceWithAudit,\n date,\n );\n}\n","import type { Meta, Patient } from \"@openhi/types\";\nimport { ulid } from \"ulid\";\nimport {\n mergeAuditIntoMeta,\n type MetaWithExtensions,\n} from \"../../../audit-meta\";\nimport { getDynamoDataService } from \"../../../dynamo/dynamo-data-service\";\nimport type { OpenHiContext } from \"../../../openhi-context\";\nimport {\n createDataEntityRecord,\n type SingleResourceResult,\n} from \"../../data-operations-common\";\n\n/**\n * Create a Patient. Accepts FHIR-like body and OpenHI context; returns created resource.\n *\n * @see sites/www-docs/content/packages/@openhi/constructs/data/shared-data-layer-layout.md\n * @see sites/www-docs/content/packages/@openhi/constructs/data/operations/patient/patient-create.md\n */\nexport interface CreatePatientParams {\n context: OpenHiContext;\n /** FHIR Patient body (resourceType, id optional, meta optional). */\n body: Patient;\n /** Optional table name override; resolved by data service from DYNAMO_TABLE_NAME when omitted. */\n tableName?: string;\n}\n\nexport type CreatePatientResult = SingleResourceResult<Patient>;\n\n/**\n * Creates a Patient. Builds put attrs with audit in meta, then ElectroDB put.\n * Throws on service/validation errors; adapters map to HTTP/GraphQL.\n */\nexport async function createPatientOperation(\n params: CreatePatientParams,\n): Promise<CreatePatientResult> {\n const { context, body, tableName } = params;\n const { tenantId, workspaceId, date, actorId, actorName } = context;\n const id = body.id ?? ulid();\n\n const meta: Meta = {\n ...(body.meta ?? {}),\n lastUpdated: date,\n versionId: \"1\",\n };\n\n const patientWithAudit: Patient & {\n id: string;\n meta: MetaWithExtensions;\n } = {\n ...body,\n resourceType: \"Patient\",\n id,\n meta: mergeAuditIntoMeta(meta, {\n createdDate: date,\n createdById: actorId,\n createdByName: actorName,\n modifiedDate: date,\n modifiedById: actorId,\n modifiedByName: actorName,\n }),\n };\n\n const service = getDynamoDataService(tableName);\n return createDataEntityRecord<Patient>(\n service.entities.patient as Parameters<typeof createDataEntityRecord>[0],\n tenantId,\n workspaceId,\n id,\n patientWithAudit,\n date,\n );\n}\n","import type { PaymentNotice, Meta } from \"@openhi/types\";\nimport { ulid } from \"ulid\";\nimport {\n mergeAuditIntoMeta,\n type MetaWithExtensions,\n} from \"../../../audit-meta\";\nimport { getDynamoDataService } from \"../../../dynamo/dynamo-data-service\";\nimport type { OpenHiContext } from \"../../../openhi-context\";\nimport {\n createDataEntityRecord,\n type SingleResourceResult,\n} from \"../../data-operations-common\";\n\n/**\n * Create a PaymentNotice. Accepts FHIR-like body and OpenHI context; returns created resource.\n *\n * @see sites/www-docs/content/packages/@openhi/constructs/data/shared-data-layer-layout.md\n */\nexport interface CreatePaymentNoticeParams {\n context: OpenHiContext;\n /** FHIR PaymentNotice body (resourceType, id optional, meta optional). */\n body: PaymentNotice;\n /** Optional table name override; resolved by data service from DYNAMO_TABLE_NAME when omitted. */\n tableName?: string;\n}\n\nexport type CreatePaymentNoticeResult = SingleResourceResult<PaymentNotice>;\n\n/**\n * Creates a PaymentNotice. Builds put attrs with audit in meta, then ElectroDB put.\n * Throws on service/validation errors; adapters map to HTTP/GraphQL.\n */\nexport async function createPaymentNoticeOperation(\n params: CreatePaymentNoticeParams,\n): Promise<CreatePaymentNoticeResult> {\n const { context, body, tableName } = params;\n const { tenantId, workspaceId, date, actorId, actorName } = context;\n const id = body.id ?? ulid();\n\n const meta: Meta = {\n ...(body.meta ?? {}),\n lastUpdated: date,\n versionId: \"1\",\n };\n\n const resourceWithAudit: PaymentNotice & {\n id: string;\n meta: MetaWithExtensions;\n } = {\n ...body,\n resourceType: \"PaymentNotice\",\n id,\n meta: mergeAuditIntoMeta(meta, {\n createdDate: date,\n createdById: actorId,\n createdByName: actorName,\n modifiedDate: date,\n modifiedById: actorId,\n modifiedByName: actorName,\n }),\n };\n\n const service = getDynamoDataService(tableName);\n return createDataEntityRecord<PaymentNotice>(\n service.entities.paymentnotice as Parameters<\n typeof createDataEntityRecord\n >[0],\n tenantId,\n workspaceId,\n id,\n resourceWithAudit,\n date,\n );\n}\n","import type { Meta, Practitioner } from \"@openhi/types\";\nimport { ulid } from \"ulid\";\nimport {\n mergeAuditIntoMeta,\n type MetaWithExtensions,\n} from \"../../../audit-meta\";\nimport { getDynamoDataService } from \"../../../dynamo/dynamo-data-service\";\nimport type { OpenHiContext } from \"../../../openhi-context\";\nimport {\n createDataEntityRecord,\n type SingleResourceResult,\n} from \"../../data-operations-common\";\n\n/**\n * Create a Practitioner. Accepts FHIR-like body and OpenHI context; returns created resource.\n *\n * @see sites/www-docs/content/packages/@openhi/constructs/data/shared-data-layer-layout.md\n * @see sites/www-docs/content/packages/@openhi/constructs/data/dynamo/entities/practitioner.md\n */\nexport interface CreatePractitionerParams {\n context: OpenHiContext;\n /** FHIR Practitioner body (resourceType, id optional, meta optional). */\n body: Practitioner;\n /** Optional table name override; resolved by data service from DYNAMO_TABLE_NAME when omitted. */\n tableName?: string;\n}\n\nexport type CreatePractitionerResult = SingleResourceResult<Practitioner>;\n\n/**\n * Creates a Practitioner. Builds put attrs with audit in meta, then ElectroDB put.\n * Throws on service/validation errors; adapters map to HTTP/GraphQL.\n */\nexport async function createPractitionerOperation(\n params: CreatePractitionerParams,\n): Promise<CreatePractitionerResult> {\n const { context, body, tableName } = params;\n const { tenantId, workspaceId, date, actorId, actorName } = context;\n const id = body.id ?? ulid();\n\n const meta: Meta = {\n ...(body.meta ?? {}),\n lastUpdated: date,\n versionId: \"1\",\n };\n\n const practitionerWithAudit: Practitioner & {\n id: string;\n meta: MetaWithExtensions;\n } = {\n ...body,\n resourceType: \"Practitioner\",\n id,\n meta: mergeAuditIntoMeta(meta, {\n createdDate: date,\n createdById: actorId,\n createdByName: actorName,\n modifiedDate: date,\n modifiedById: actorId,\n modifiedByName: actorName,\n }),\n };\n\n const service = getDynamoDataService(tableName);\n return createDataEntityRecord<Practitioner>(\n service.entities.practitioner as Parameters<\n typeof createDataEntityRecord\n >[0],\n tenantId,\n workspaceId,\n id,\n practitionerWithAudit,\n date,\n );\n}\n","import type { Procedure, Meta } from \"@openhi/types\";\nimport { ulid } from \"ulid\";\nimport {\n mergeAuditIntoMeta,\n type MetaWithExtensions,\n} from \"../../../audit-meta\";\nimport { getDynamoDataService } from \"../../../dynamo/dynamo-data-service\";\nimport type { OpenHiContext } from \"../../../openhi-context\";\nimport {\n createDataEntityRecord,\n type SingleResourceResult,\n} from \"../../data-operations-common\";\n\n/**\n * Create a Procedure. Accepts FHIR-like body and OpenHI context; returns created resource.\n *\n * @see sites/www-docs/content/packages/@openhi/constructs/data/shared-data-layer-layout.md\n */\nexport interface CreateProcedureParams {\n context: OpenHiContext;\n /** FHIR Procedure body (resourceType, id optional, meta optional). */\n body: Procedure;\n /** Optional table name override; resolved by data service from DYNAMO_TABLE_NAME when omitted. */\n tableName?: string;\n}\n\nexport type CreateProcedureResult = SingleResourceResult<Procedure>;\n\n/**\n * Creates a Procedure. Builds put attrs with audit in meta, then ElectroDB put.\n * Throws on service/validation errors; adapters map to HTTP/GraphQL.\n */\nexport async function createProcedureOperation(\n params: CreateProcedureParams,\n): Promise<CreateProcedureResult> {\n const { context, body, tableName } = params;\n const { tenantId, workspaceId, date, actorId, actorName } = context;\n const id = body.id ?? ulid();\n\n const meta: Meta = {\n ...(body.meta ?? {}),\n lastUpdated: date,\n versionId: \"1\",\n };\n\n const resourceWithAudit: Procedure & {\n id: string;\n meta: MetaWithExtensions;\n } = {\n ...body,\n resourceType: \"Procedure\",\n id,\n meta: mergeAuditIntoMeta(meta, {\n createdDate: date,\n createdById: actorId,\n createdByName: actorName,\n modifiedDate: date,\n modifiedById: actorId,\n modifiedByName: actorName,\n }),\n };\n\n const service = getDynamoDataService(tableName);\n return createDataEntityRecord<Procedure>(\n service.entities.procedure as Parameters<typeof createDataEntityRecord>[0],\n tenantId,\n workspaceId,\n id,\n resourceWithAudit,\n date,\n );\n}\n"],"mappings":"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","names":["exports","exports","exports","exports","exports","exports","exports","exports","exports","parseWorkflowEvent","exports","exports","workflowDedupClient","exports","exports","import_client_dynamodb","import_types","import_workflows","ON_SITE_SCENARIO","buildIdentifierPair","ON_SITE_SCENARIO","buildIdentifierPair","PRIMARY_PAYOR_OPTIONS","SECONDARY_PAYOR_OPTIONS","PATIENT_LAST_NAMES","PATIENT_FIRST_NAMES","ON_SITE_SCENARIO","PATIENT_ANCHOR_DATE","padIndex","deterministicBirthDate","deterministicVerificationDate","deterministicPhone","deterministicEmail","deterministicAddressLine","deterministicPrimaryPayor","hasSecondaryCoverage","hasQmbStatus","isHospicePatient","buildIdentifierPair","buildCoverageIdentifierPair","buildPrimaryCoverageResource","buildSecondaryCoverageResource","cachedSpecs","ON_SITE_SCENARIO","padIndex","buildIdentifierPair","mondayOfIsoWeekUtc","toIsoZ","ON_SITE_SCENARIO","hashString","buildIdentifierPair","ON_SITE_SCENARIO","hashString","ON_SITE_SCENARIO","ON_SITE_SCENARIO","buildIdentifierPair","import_electrodb","import_types","import_electrodb","import_electrodb","import_electrodb","import_electrodb","import_electrodb","import_electrodb","import_electrodb","import_electrodb","import_electrodb","import_electrodb","import_electrodb","import_electrodb","import_types","import_types","import_types","MISSING_NAME_SENTINEL","import_types","import_types","MISSING_NAME_SENTINEL","extractReferenceSlug","import_types","MISSING_NAME_SENTINEL","extractReferenceSlug","import_types","import_types","import_electrodb","import_electrodb","import_types","envelope","import_ulid","import_ulid","import_ulid","import_ulid","import_ulid","import_ulid","import_ulid","import_ulid","import_ulid","import_ulid","import_ulid","import_ulid"]}