Patient Portal Service — Migration Plan
Status: populated Owner: TBD Last updated: 2026-04-18 Companion: Service Template · 03 platform-services
1. Migration Context
The patient-portal-service is a net-new service on the Ghasi-eHealth platform. There is no pre-existing portal service to migrate from. The migration plan covers:
- New tenant onboarding — provisioning portal access for existing patient populations.
- Legacy patient portal data import — for tenants transitioning from an external portal product.
- Keycloak patient realm bootstrapping.
2. New Tenant Provisioning
When a tenant activates (tenant.tenant.activated.v1 event received):
- Portal service creates default portal configuration for the tenant (feature flags, result release policy defaults, MFA enforcement policy).
- Existing patients are eligible for portal registration immediately — no bulk account creation; patients self-register.
- Module entitlement
ehr.portalmust be granted by platform operator before portal endpoints are accessible for the tenant.
3. Legacy Portal Data Import
For tenants migrating from an existing patient portal:
| Phase | Action | Notes |
|---|---|---|
| Phase 1 — Assessment | Export patient account list from legacy portal; map to Ghasi patient IDs via registration-service | Requires patientId matching via MRN or national ID |
| Phase 2 — Account creation | Bulk-create PortalAccount records for matched patients (status: pending_verification) | Admin API: POST /internal/portal/accounts/bulk |
| Phase 3 — Keycloak user migration | Create Keycloak user records in patient realm; send password-reset links | Keycloak admin API + bulk email via communication-service |
| Phase 4 — Proxy delegation import | Import existing proxy/caregiver relationships; create ProxyDelegation records via admin API | Manual review required for legal consent compliance |
| Phase 5 — Access log migration | Historical access logs from legacy portal are not migrated (new audit trail starts on platform go-live) | Document as known gap in compliance review |
4. Data Migration Tooling
Migration scripts located at: scripts/migration/patient-portal/
| Script | Purpose |
|---|---|
import-portal-accounts.ts | Bulk create PortalAccount records from CSV |
import-proxy-delegations.ts | Import proxy relationships from CSV with validation |
validate-patient-mapping.ts | Verify patientId matches between legacy portal and registration-service |
All scripts are idempotent (upsert on tenant_id + patient_id). Failed rows are logged to migration_errors.json and do not abort the batch.
5. Keycloak Patient Realm Bootstrap
Each tenant's patient realm is initialized with:
portalclient (PKCE, SMART on FHIR scopes).- MFA TOTP policy (required, not optional).
- Password policy: min 12 chars, complexity required.
- Session settings: access token 15 min, refresh 24h, refresh-token rotation enabled.
Bootstrap script: scripts/migration/patient-portal/bootstrap-patient-realm.ts
6. Rollback Plan
| Scenario | Rollback action |
|---|---|
| Bulk account import failure | Delete all accounts in pending_verification status for tenant; re-run import |
| Keycloak realm misconfiguration | Restore realm from backup snapshot; re-run bootstrap |
| Feature flag misconfiguration | Disable ehr.portal entitlement for tenant; re-configure |
Portal database migrations (Drizzle) are down-migration capable for all changes during the migration window.