# Cognito to Healthie Form Migration — Spec ## Summary **Client-approved direction:** Healthie is the unified patient-facing and clinical workflow platform. Cognito is the migration source only. The Cognito intake form will be rebuilt in Healthie using the field mapping derived from Cognito's form definition JS. The migration mapping YAML (`Cognito_to_Healthie_Form_Mapping.yaml`) provides complete field-level detail: 80+ fields across 19 sections, with labels, Healthie input types, choices, helptext, conditional visibility rules, and page order. --- ## Migration Overview | Aspect | Cognito (Source) | Healthie (Target) | |---|---|---| | **API** | REST (one-time export) | GraphQL (queries + mutations) | | **Field IDs** | Opaque keys (`NameEntryNumber_First`) | Stable `custom_module.id` | | **Schema** | Extracted from form definition JS | Queryable at runtime | | **File Uploads** | Short-lived URL | GraphQL `expiring_url` | | **Conditional Logic** | Form JS branching | `CustomModuleCondition` | | **Ongoing Use** | Migration source only | Primary intake + daily check-ins | --- ## Healthie Form Structure (Documented) ### Form Templates (`CustomModuleForm`) Forms are built from `CustomModule` objects (individual questions/fields). A form template is queryable: ```graphql query form($id: ID) { customModuleForm(id: $id) { id name custom_modules { id hipaa_name mod_type # e.g. "text", "choice", "date", "file" label options # for choice/checkbox fields required } } } ``` **This is the key advantage:** The form schema is queryable and documented, so we can: (a) discover available fields at runtime, (b) validate our field mapping against the actual form structure during CI/CD or deployment, and (c) detect when the form changes. **Note:** explicit field-to-column mapping is still required since DB columns are hardcoded — both Cognito and Healthie need a mapping artifact (e.g., YAML). The difference is that Healthie's mapping keys (`custom_module.id`) are stable and discoverable, while Cognito's field keys (from our XLSX sample: e.g., `"NameEntryNumber_First"`) are opaque, undocumented, and unvalidated against a real webhook. ### Filled Out Forms (`FormAnswerGroup`) A submitted form is a `FormAnswerGroup`: ```graphql query getFormAnswerGroups($id: ID) { formAnswerGroup(id: $id) { id finished created_at user { id # patient identity } custom_module_form { id name } form_answers { id label answer custom_module { id mod_type required } } } } ``` **Every answer has a `custom_module.id`** — this is the stable, queryable field identifier. Unlike Cognito where we guess that `"NameEntryNumber_First"` means "first name", Healthie tells us explicitly: `custom_module.label = "First Name"`, `mod_type = "text"`. ### Onboarding Flows For multi-step intake, Healthie supports `OnboardingFlow` objects that chain multiple forms, documents, and tasks together: - `createOnboardingFlow` / `updateOnboardingFlow` / `deleteOnboardingFlow` - `OnboardingItem` objects link forms (`item_type: "Module Form"`), documents, and insurance forms - Flows can be attached to `UserGroup` (e.g., "CKM patients", "MSK patients") - Completion tracked via `CompletedOnboardingItem` ### Webhooks for Form Events Healthie emits form-related webhooks (same pointer pattern as all other events): | Event | Trigger | |---|---| | `form_answer_group.created` | `createFormAnswerGroup` — patient submits form | | `form_answer_group.updated` | Form answer modified | | `form_answer_group.locked` | Form locked for editing | | `form_answer_group.signed` | Form signed (e.g., consent) | | `form_answer_group.unlocked` | Form unlocked | | `form_answer_group.deleted` | Form deleted | | `custom_module_form.created` | New form template created | | `custom_module_form.updated` | Form template updated | | `custom_module_form.deleted` | Form template deleted | | `completed_onboarding_item.created` | Onboarding step completed | | `requested_form_completion.created` | Provider sends form to patient | The `form_answer_group.created` webhook gives us `resource_id` → we query `formAnswerGroup(id)` → get structured answers. ### Recurring Forms (Daily Check-Ins) Healthie supports recurring form completion requests: ```graphql mutation createRequestedFormCompletion($input: CreateRequestedFormInput!) { createRequestedFormCompletion(input: $input) { requestedFormCompletion { id } } } # Input: { recipient_ids, form_id, is_recurring: true, frequency: "Daily", ... } ``` This covers daily check-ins without building custom scheduling. --- ## Migration Flow Patients fill out the intake form in Healthie, which creates them as a patient in Healthie. Our Core DB tracks them in `intake_records` (pre-enrollment) until eligibility + consent + alignment are confirmed, then promotes to `beneficiaries`. If not approved, they're deactivated in Healthie but retained in `intake_records` for audit. The two-stage identity model still enforces the enrollment gate in our Core DB. ## Cognito Form Field Migration (Completed) The Cognito form definition JS has been extracted and parsed into `Cognito_to_Healthie_Form_Mapping.yaml`. This mapping was used to rebuild the intake form in Healthie. No submission data exists in Cognito to migrate — all patient intake originates from Healthie. 1. **Form field definitions** — Extracted from Cognito form definition JS (complete field data: labels, types, choices, conditional visibility, helptext, page structure) 2. **Healthie form rebuilt** — Using `Cognito_to_Healthie_Form_Mapping.yaml` as the spec 3. **Cognito decommissioned** — Once the Healthie intake form is live and validated ## Healthie Form Rebuild Checklist The `Cognito_to_Healthie_Form_Mapping.yaml` provides all field data needed to rebuild the form: - **Page order:** 21 pages (some shared, some conditional) - **Sections:** 19 sections (top-level + nested) - **Conditional visibility:** Female/Male sex branching, Vascular/Fatty Liver/Kidney conditional sections - **File uploads:** 6 file upload fields (Female health, Male health, Vascular, Fatty Liver, Kidney, Infection/Immune, Report Upload) - **Multi-select fields:** ~50 checkbox/multi-choice fields - **Single-select fields:** ~15 choice fields - **Text fields:** ~15 free-text fields (with max_length constraints) - **Boolean fields:** 2 (eligibility acknowledgment, safety screening) ## Open Items 1. **Healthie Enterprise purchase** — Waiting on sales proposal for sandbox access 2. **Form creation via API** — Need to verify `createCustomModuleForm` mutation signature in Healthie sandbox