Skip to main content

Parivar — Data Model & Schema Reference

Companion to the Technical Architecture blueprint. Authoritative source for tables, columns, enums, and relationships in the NestJS + Postgres rebuild.

This document is reconstructed from the live-database exports (database_enums.csv, database_constraints.csv) and the entity-relationship diagram (Parivar_ERD.mmd), cross-checked against the role-based API reference and the implementation guides. Where the older API reference disagreed with the live schema, the live schema wins and the discrepancy is flagged with ⚠️.

Scope note: only application tables are documented. Supabase-internal schemas (auth.*, storage.*, realtime, vault) are replaced wholesale in the rebuild — see §9.


1. How the data model maps to the rebuild

ConcernCurrent (Supabase)Rebuild (NestJS + Postgres)
Schema ownershippublic schema + Supabase-managed auth/storageSingle app-owned Postgres; one ORM schema (Prisma or TypeORM)
Identity tableauth.users (Supabase)Own users table (or external IdP) + profiles 1:1
EnumsPostgres enum typesKeep as Postgres enums or ORM-level enums + check constraints
FKs / cascadesAs listed in §8Preserve every FK; make cascade/SET NULL explicit per §8
Soft deletedeleted_at, is_disabled, is_active, status columnsSame columns; enforce in repository base query (global scope)
Auditcustomer_activity_log, location_audit_log, assessment_versions, visit_eventsKeep; consider an append-only audit module

🔁 Migration note. In Supabase the client queried public.* directly under RLS. In the rebuild no table is client-reachable; every read/write goes through a NestJS service. The ownership columns below (user_id, client_user_id, nurse_id, parent_id, created_by) stop being RLS predicates and become explicit where clauses in services.


2. Domain map (table inventory)

41 application tables, grouped into nine bounded contexts. Each maps to the NestJS module noted.

DomainTablesModule
Identity & Accessprofiles, user_roles, otp_verifications, staff_applications, customer_admin_details, nurses, doctors, reactivation_requestsAuthModule, UsersModule, NurseModule, DoctorModule
Patientsparents, parent_health_info, parent_emergency_contacts, admission_formsParentsModule
Visits & Schedulingvisits, visit_events, nurse_working_hours, nurse_leave_requests, monthly_contractsVisitsModule, NurseModule
Clinicalassessments, assessment_versions, first_visit_assessments, wound_care_forms, clinical_modules, email_notificationsClinicalModule
Escalations & Safetyescalations, sos_alerts, nurse_locations, location_audit_logEscalationsModule, NurseModule, AlertsModule
Hospital Coordinationhospital_requests, escort_tasksHospitalModule
Communicationconversations, conversation_participants, messages, voice_messages, notifications, admin_alertsNotificationsModule, PariAIModule, AlertsModule
Nurse Operationsnurse_certifications, nurse_document_signatures, nurse_preferences, nurse_bank_details, didit_webhook_eventsNurseModule
Billing & Referralssubscription_plans, subscriptions, payments, withdrawal_requests, referral_accounts, referrals, referral_commissions, referral_settings, referral_wallet_transactions, customer_activity_logBillingModule, ReferralsModule

3. Enumerated types (application domain)

These are the real enum values from database_enums.csv. Use them verbatim — several differ from the older API reference.

EnumValuesUsed by
app_rolecustomer, nurse, admin, doctoruser_roles.role, RBAC guards
visit_statuspending_admin_assignment, assigned_to_nurse, in_progress, completed, cancelled, report_submitted, approvedvisits.status
visit_typeroutine, follow_upvisits.visit_type
escalation_typedoctor_review, urgent_health, medication_issue, fall_risk, hospital_support, family_followup, admin_supportescalations.escalation_type
escalation_statusopen, under_review, actioned, closedescalations.status
escalation_severitylow, medium, high, criticalescalations.severity, admin_alerts.severity
general_conditionnormal, weak, dizzy, other, stable, improving, deteriorating, criticalassessments.general_condition
blood_sugar_typefasting, randomassessments.blood_sugar_type, first_visit_assessments.blood_sugar_type
appetite_statusnormal, reduced, poorfirst-visit / clinical intake

⚠️ Discrepancy vs. the old API reference.

  • visit_type is routine / follow_up — not regular / first_assessment / on_demand. "First visit" is determined by the absence of a first_visit_assessments row for the parent (see Clinical Reporting doc §2), not by a visit_type. On-demand bookings are a billing path, not an enum value.
  • escalation_type is the seven clinical categories above — not clinical / safety / logistical.
  • escalation_status is open → under_review → actioned → closed — not open → in_review → resolved.
  • general_condition is a richer set than the old stable/improving/deteriorating/critical.

Update DTOs, validators, and any UI dropdowns to these values.

Supabase-internal enums to drop: aal_level, factor_status, factor_type, code_challenge_method, oauth_*, one_time_token_type, equality_op, buckettype, request_status, action are Supabase/Postgres system types and have no place in the rebuilt app schema (their concerns are handled by the Auth module, object storage, and framework layers).


4. Identity & Access

profiles — 1:1 with the auth user

Primary user record. user_id is unique and FKs the auth identity.

ColumnTypeNotes
iduuid PK
user_iduuid FK→users, uniqueAuth identity
nametext
emailtext
phonetext
is_disabledboolMaster disable flag (see Account Lifecycle doc)
disabled_attimestamptz
disabled_reasontexte.g. self_deactivation
review_request_countintReactivation requests counter

user_roles — role assignment (1:many)

Unique on (user_id, role). A user may hold multiple roles. RBAC reads from here.

ColumnTypeNotes
iduuid PK
user_iduuid FK→profiles
roleapp_rolecustomer / nurse / admin / doctor

nurses — workforce record

Unique on email and user_id. Scoping key for most nurse data (nurses.user_id = auth.uid()).

ColumnTypeNotes
iduuid PKReferenced as nurse_id everywhere
user_iduuid FK→profiles, unique
nametext
emailtext, unique
statustexte.g. available, on_visit, deactivated
is_activebool
deactivated_attimestamptz

doctors — clinical-oversight record

Unique on user_id. PK id referenced as doctor_id.

staff_applications — nurse/doctor onboarding

Unique on email and user_id. Application + KYC pipeline source; supports a reactivation application type (Account Lifecycle doc §7).

customer_admin_details — admin-managed customer metadata

Unique on user_id.

otp_verifications — login/2FA codes

6-digit code, 10-min TTL, max 5/email/hour (move rate-limit to Redis — see Architecture doc).

reactivation_requests — disabled-user review requests

Tracks user_id, email, status (pending/approved), created_at. Enforces the 3-requests-per-7-days rule.


5. Patients

parents — the patient (elder in Nepal)

Owned by a customer via user_id. Soft-deleted via deleted_at.

ColumnTypeNotes
iduuid PKparent_id everywhere
user_iduuid FK→profilesOwning customer
nametext
ageint(ERD shows age; old ref showed date_of_birth — confirm which is stored)
relationshiptextmother/father/…
deleted_attimestamptzSoft delete

Likely additional columns from the API reference: city, landmark, lat, lng.

admission_forms — long-form intake (1:many on parent, typically 1)

FK parent_id. Holds conditions, medications, allergies (jsonb), and is_diabetic (boolean) which drives conditional blood-sugar capture in reports.

parent_health_info — structured health summary

FK parent_id, unique on parent_id (1:1).

parent_emergency_contacts — contacts (1:many)

FK parent_id.


6. Visits & Scheduling

visits — the booking + execution record

Central table. FKs parent_id, nurse_id (null until assigned). client_user_id denormalises the owning customer for scoping.

ColumnTypeNotes
iduuid PK
parent_iduuid FK→parents
nurse_iduuid FK→nursesNull until assigned
client_user_iduuidOwning customer (scoping key)
statusvisit_statusLifecycle (see §3)
visit_typevisit_typeroutine / follow_up
scheduled_datedate

Lifecycle: pending_admin_assignmentassigned_to_nursein_progressreport_submittedapproved; plus completed (ended without report) and cancelled. Admin rejection of a report sends report_submittedin_progress.

visit_events — append-only timeline

FK visit_id. One row per status transition / actor action.

nurse_working_hours — weekly availability

FK nurse_id. day_of_week (0–6), start_time < end_time.

nurse_leave_requests — leave

FK nurse_id. Full-day/partial; overlap with active visits blocked (409 LEAVE_CONFLICT). Admins may create on behalf of nurses.

monthly_contracts — recurring engagement

FK nurse_id. Recurring/contracted visit arrangement.


7. Clinical, Escalations, Hospital, Communication, Nurse Ops, Billing

The clinical tables (assessments, assessment_versions, first_visit_assessments, wound_care_forms, clinical_modules, email_notifications) carry the richest field sets and a full submission/versioning workflow — they are documented in detail in the Clinical Reporting Module companion doc. Summary here:

TableCardinalityKey columnsNotes
assessmentsper visit (regular report)visit_id, parent_id, nurse_id, approval_status, is_draft, version_countMandatory report; draft + 24h edit window
assessment_versionsper editassessment_id, nurse_id, version_number, snapshot jsonbAudit of each submit/edit
first_visit_assessmentsone per parentparent_id, nurse_id, visit_id, is_lockedComprehensive intake; lock-once
wound_care_formsmany per visitparent_id, visit_id, nurse_id, wound_typeAdditive wound records
clinical_modulesoptional per visitvisit_id, nurse_id, parent_idOptional clinical add-ons
email_notificationsper assessment eventassessment_id, parent_id, visit_idOutbound report emails log

Escalations & safety

TableFKsNotes
escalationsvisit_id, parent_id, nurse_idescalation_type (7 values), status (open→under_review→actioned→closed), severity
sos_alertsnurse_id, patient_parent_idNurse SOS with lat/lng; fans out admin email + realtime
nurse_locationsnurse_id (unique, 1 row/nurse)Live GPS; >5 min stale → admin alert
location_audit_lognurse_idHistorical GPS trail

⚠️ The old API reference's standalone incidents table is not in the live schema. Risk/safety events are modelled via escalations (fall_risk, urgent_health, etc.) and admin_alerts. Drop the incidents concept unless a new table is intentionally added.

Hospital coordination

TableFKsNotes
hospital_requestsparent_idCustomer-raised coordination request
escort_taskshospital_request_id, parent_idAdmin-managed escort task

Communication

TableFKsNotes
conversationsChat thread (PariAI + human)
conversation_participantsconversation_id, user_idUnique (conversation_id, user_id)
messagesconversation_id, voice_message_id, sender_id→profilesText + voice
voice_messagesTranscribed audio (Whisper)
notificationsrelated_visit_id, user_idPer-user in-app feed
admin_alerts7 related_* FKs (visit, admission_form, assessment, escalation, escort_task, hospital_request, parent)Deduped ops alerts; severity-tagged

Nurse operations

TableFKsNotes
nurse_certificationsnurse_idUnique (nurse_id, certification_name)
nurse_document_signaturesnurse_idUnique (nurse_id, document_type); 3 mandatory docs
nurse_preferencesnurse_idSettings
nurse_bank_detailsnurse_idConnectIPS payout details ⚠️ (old ref called this user_bank_details)
didit_webhook_eventsnurse_idKYC webhook log

Billing, payments & referrals

TableFKs / uniqueNotes
subscription_plansStripe price catalogue (stripe_price_id)
subscriptionsuser_id, stripe_price_idActive subscription per customer
paymentsuser_idPayment records
withdrawal_requestsNurse/referrer payouts
referral_accountsuser_id unique, referral_code uniqueReferral wallet summary
referralsreferrer_user_id, referred_user_id (unique)Referral edges
referral_commissionsreferral_id5% commission rows
referral_settingsCommission config
referral_wallet_transactionsuser_idWallet ledger
customer_activity_logCustomer audit trail

8. Foreign keys & referential integrity

Every FK from database_constraints.csv. Decide a delete policy per relationship (the right column is the recommended rebuild behaviour).

Child tableFK column→ ParentRecommended on-delete
parentsuser_idprofilesRESTRICT (soft-delete parent instead)
admission_formsparent_idparentsCASCADE
parent_health_infoparent_idparentsCASCADE
parent_emergency_contactsparent_idparentsCASCADE
visitsparent_idparentsRESTRICT
visitsnurse_idnursesSET NULL (reassign on nurse removal)
visit_eventsvisit_idvisitsCASCADE
assessmentsvisit_id / parent_id / nurse_idvisits / parents / nursesCASCADE (visit) / RESTRICT / SET NULL
assessment_versionsassessment_id / nurse_idassessments / nursesCASCADE / SET NULL
first_visit_assessmentsparent_id / nurse_id / visit_idparents / nurses / visitsRESTRICT / SET NULL / CASCADE
clinical_modulesvisit_id / nurse_id / parent_idvisits / nurses / parentsCASCADE / SET NULL / RESTRICT
wound_care_formsparent_id / visit_id / nurse_idparents / visits / nursesRESTRICT / CASCADE / SET NULL
email_notificationsassessment_id / parent_id / visit_idassessments / parents / visitsCASCADE
escalationsvisit_id / parent_id / nurse_idvisits / parents / nursesSET NULL / RESTRICT / SET NULL
sos_alertsnurse_id / patient_parent_idnurses / parentsSET NULL / RESTRICT
nurse_locationsnurse_idnursesCASCADE
location_audit_lognurse_idnursesCASCADE
hospital_requestsparent_idparentsRESTRICT
escort_taskshospital_request_id / parent_idhospital_requests / parentsCASCADE / RESTRICT
conversation_participantsconversation_id / user_idconversations / profilesCASCADE
messagesconversation_id / voice_message_idconversations / voice_messagesCASCADE / SET NULL
notificationsrelated_visit_id / user_idvisits / profilesSET NULL / CASCADE
admin_alertsrelated_{visit,admission_form,assessment,escalation,escort_task,hospital_request,parent}_idrespectiveSET NULL (alerts are historical)
nurse_certificationsnurse_idnursesCASCADE
nurse_document_signaturesnurse_idnursesCASCADE
referralsreferrer_user_id / referred_user_idprofilesRESTRICT
referral_commissionsreferral_idreferralsCASCADE
referral_wallet_transactionsuser_idreferral_accountsCASCADE
subscriptionsuser_id / stripe_price_idprofiles / subscription_plansRESTRICT
user_rolesuser_idprofilesCASCADE
profilesuser_idusers (auth)CASCADE

Unique constraints to preserve: profiles.user_id, nurses.email, nurses.user_id, doctors.user_id, customer_admin_details.user_id, staff_applications.email, staff_applications.user_id, referral_accounts.referral_code, referral_accounts.user_id, referrals.referred_user_id, nurse_locations.nurse_id, parent_health_info.parent_id, user_roles(user_id, role), nurse_certifications(nurse_id, certification_name), nurse_document_signatures(nurse_id, document_type), conversation_participants(conversation_id, user_id).

⚠️ The CSV lists user_roles_user_id_role_key as UNIQUE but splits it across two rows; treat it as a composite unique on (user_id, role).


9. What replaces the Supabase-managed schemas

Supabase schemaPurposeRebuild replacement
auth.*Users, sessions, OAuth, MFA, OTP tokensAuthModule: own users table + JWT (access/refresh), Passport OAuth strategies, OTP in otp_verifications + Redis throttle
storage.*Buckets/objects (reports, wound-photos, staff-documents)S3-compatible storage + StorageService with pre-signed URLs
realtimePostgres CDC channelsSocket.IO gateway emitting curated domain events
vault / secretsFunction secretsEnvironment variables / secret manager

10. Indexing & performance recommendations

Add these in the rebuild (beyond PK/unique/FK indexes):

  • visits(status), visits(nurse_id, status), visits(client_user_id), visits(scheduled_date) — dashboard and roster queries.
  • assessments(visit_id), assessments(nurse_id, is_draft), assessments(approval_status, admin_viewed) — nurse/admin report lists.
  • escalations(status, created_at desc), escalations(assigned_doctor_id) — doctor queue.
  • admin_alerts(status, severity, created_at desc) — ops dashboard.
  • nurse_locations(nurse_id) (already unique) + a TTL/cleanup job into location_audit_log.
  • notifications(user_id, created_at desc) — feed.
  • Partial index WHERE deleted_at IS NULL on soft-deletable tables (parents).

Cache hot, rarely-changing reads in Redis: app_config/feature flags, maps key, subscription status, on-call doctor lookup, and OTP/SOS/AI rate-limit counters.


End of Data Model & Schema Reference.