@openhi/constructs 0.0.162 → 0.0.163

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/lib/{chunk-WOTU36P3.mjs → chunk-WFTDH2NM.mjs} +3 -2
  2. package/lib/chunk-WFTDH2NM.mjs.map +1 -0
  3. package/lib/{chunk-MLFMW5IF.mjs → chunk-XHG4SODS.mjs} +9 -5
  4. package/lib/chunk-XHG4SODS.mjs.map +1 -0
  5. package/lib/{chunk-7TRO2STL.mjs → chunk-ZODGX37H.mjs} +543 -46
  6. package/lib/chunk-ZODGX37H.mjs.map +1 -0
  7. package/lib/{events-TG654e7L.d.mts → events-dO9nxnPa.d.mts} +89 -4
  8. package/lib/{events-TG654e7L.d.ts → events-dO9nxnPa.d.ts} +89 -4
  9. package/lib/index.d.mts +1 -1
  10. package/lib/index.d.ts +90 -5
  11. package/lib/index.js +335 -52
  12. package/lib/index.js.map +1 -1
  13. package/lib/index.mjs +46 -2
  14. package/lib/index.mjs.map +1 -1
  15. package/lib/pre-token-generation.handler.js +1 -0
  16. package/lib/pre-token-generation.handler.js.map +1 -1
  17. package/lib/pre-token-generation.handler.mjs +1 -1
  18. package/lib/provision-default-workspace.handler.js +9 -4
  19. package/lib/provision-default-workspace.handler.js.map +1 -1
  20. package/lib/provision-default-workspace.handler.mjs +2 -2
  21. package/lib/rest-api-lambda.handler.js +292 -287
  22. package/lib/rest-api-lambda.handler.js.map +1 -1
  23. package/lib/rest-api-lambda.handler.mjs +2 -2
  24. package/lib/seed-demo-data.handler.d.mts +4 -2
  25. package/lib/seed-demo-data.handler.d.ts +4 -2
  26. package/lib/seed-demo-data.handler.js +553 -74
  27. package/lib/seed-demo-data.handler.js.map +1 -1
  28. package/lib/seed-demo-data.handler.mjs +2 -2
  29. package/package.json +3 -3
  30. package/lib/chunk-7TRO2STL.mjs.map +0 -1
  31. package/lib/chunk-MLFMW5IF.mjs.map +0 -1
  32. package/lib/chunk-WOTU36P3.mjs.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/workflows/control-plane/seed-demo-data/seed-demo-data.handler.ts","../src/workflows/control-plane/seed-demo-data/events.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"],"sourcesContent":["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","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"],"mappings":"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","names":["import_workflows","PLATFORM_ROLE_CODE","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","ON_SITE_SCENARIO","buildIdentifierPair","PLATFORM_ROLE_CODE"]}