PMR Deep Exemplar

Patient Medical Records — 29 Noun-App AMI Schemas

Reference · Deep Exemplar

The patientMedicalRecords suite is a constellation of 29 noun-apps, each with its own AMI schema. Clinical facts are global — they belong to the patient and carry a SourceOrganizationID audit trail — while operational entities are org-scoped with OrganizationID. This page is the single source of truth for every schema, the provenance model, RBAC thresholds, and two fully worked examples (Reminder lifecycle and Allergy versioning).

Data classification

Clinical facts are global; operational entities are org-scoped. PHI belongs to the patient. Patient and User are GLOBAL — they have no OrganizationID. Clinical facts (Allergy, Medication, Condition, Vital, LabResult, Imaging, Immunization, Surgery, FamilyHistory, CarePlan, Screening, Document) are GLOBAL with SourceOrganizationID audit — a deliberate exception to IC hard rule #11, documented explicitly on each schema. Every authorized viewer of the patient sees the union of all contributions across all source orgs. Operational entities (Encounter, Order, Reminder, Referral, Message, ExternalInbound, ExternalOutbound, ExternalSourceSystem, ExternalRecipient, RuleVersion, AuditLog) are org-scoped — they carry OrganizationID and enforce tenant isolation via Cosmos partition-key isolation.

Global entities that are not clinical facts — Provider, Practice, Pharmacy, Specialty — also use the SourceOrganizationID audit pattern rather than OrganizationID. They are reference data shared across the platform; their identity is not partitioned by tenant.

FK relationship diagram

flowchart LR
  subgraph Global["Global entities"]
    Patient((Patient))
    Provider((Provider))
    Practice((Practice))
    Pharmacy((Pharmacy))
    Specialty((Specialty))
    User((User))
  end

  subgraph Clinical["Clinical facts (global + SourceOrganizationID)"]
    Allergy[Allergy]
    Medication[Medication]
    Condition[Condition]
    Vital[Vital]
    LabResult[LabResult]
    Imaging[Imaging]
    Immunization[Immunization]
    Surgery[Surgery]
    FamilyHistory[FamilyHistory]
    CarePlan[CarePlan]
    Screening[Screening]
    Order[Order]
    Document[Document]
    Referral[Referral]
    Message[Message]
    Encounter[Encounter]
  end

  subgraph Provenance["Provenance / Interop (org-scoped)"]
    ExternalInbound[ExternalInbound]
    ExternalOutbound[ExternalOutbound]
    ExternalSourceSystem[ExternalSourceSystem]
    ExternalRecipient[ExternalRecipient]
  end

  subgraph Operational["Operational (org-scoped)"]
    Reminder[Reminder]
    RuleVersion[RuleVersion]
    AuditLog[AuditLog]
  end

  Patient --> Allergy
  Patient --> Medication
  Patient --> Condition
  Patient --> Vital
  Patient --> LabResult
  Patient --> Imaging
  Patient --> Immunization
  Patient --> Surgery
  Patient --> FamilyHistory
  Patient --> CarePlan
  Patient --> Screening
  Patient --> Order
  Patient --> Document
  Patient --> Referral
  Patient --> Message
  Patient --> Encounter
  Patient --> ExternalInbound
  Patient --> ExternalOutbound
  Patient --> Reminder

  Provider --> Medication
  Provider --> Surgery
  Provider --> Encounter
  Provider --> Order
  Provider --> Referral
  Provider --> Practice

  Practice --> User

  Pharmacy --> Patient

  Encounter --> Vital
  Encounter --> Document

  Order --> LabResult
  Order --> Imaging

  ExternalSourceSystem --> ExternalInbound
  ExternalRecipient --> ExternalOutbound

  ExternalInbound --> Allergy
  ExternalInbound --> Medication
  ExternalInbound --> Condition
  ExternalInbound --> Surgery
  ExternalInbound --> LabResult
  ExternalInbound --> Imaging
  ExternalInbound --> Immunization
  ExternalInbound --> Document

  RuleVersion --> Screening
  RuleVersion --> Reminder

  User --> AuditLog
  User --> Message
  User --> Vital
  User --> Immunization
  User --> Document
        

Solid arrows = FK direction (child → parent reads as “child references parent”). Per IC hard rule #14, FKs are enforced by the generated API layer, not by database FK constraints. Clinical-fact entities cross the org boundary by referencing global Patient and Provider without OrganizationID partitioning — they carry SourceOrganizationID in their audit trail instead.

Patient P0

One row per patient. GLOBAL — no OrganizationID. Patient identity is not partitioned by tenant; the patient owns their own record. Uses the SourceOrganizationID pattern to record which org contributed the row.

Trust tier: 2 (clinician-attested in-system for demographics; inbound imports may be tier 0–1).

RBAC: Read ≥ 1, Write demographics ≥ 51, EditAMI ≥ 90.

Patient AMI schema
FieldTypeRequiredPKFKNotes
PrimaryProviderIDGuidNo→ ProviderGlobal FK; assigned PCP
PreferredPharmacyIDGuidNo→ PharmacyGlobal FK; default pharmacy
PatientIDGuidYesPrimary key
PatientFirstNameString100String100YesLegal first name
PatientLastNameString100String100YesLegal last name
PatientDateOfBirthDateTimeUTCDateTimeYesDate of birth
PatientGenderCodeString50String50YesAdministrative gender code
PatientRaceCodeString50String50NoOMB race category code
PatientEthnicityCodeString50String50NoOMB ethnicity code
PatientPreferredLanguageString50String50NoISO 639-1 language code
PatientPatientSlugString200String200YesOpaque rotatable slug for patient portal URLs
PatientSourceOrganizationIDGuidYesSource org that created this row
UpdatedDateTimeUTCDateTimeYesAudit — last write timestamp
UpdatedByUserIDGuidYes→ UserAudit — who last wrote
DeletedDateTimeUTCDateTimeNoAudit — soft-delete timestamp. NULL = active; non-null = deletion time.

Provider P0

One row per clinician or prescriber. GLOBAL — no OrganizationID. Provider identity spans practices; a provider may practice at multiple orgs.

Trust tier: 2 (clinician-attested in-system; NPI verified against NPPES).

RBAC: Read ≥ 1, Write ≥ 70 (practice manager), EditAMI ≥ 90.

Provider AMI schema
FieldTypeRequiredPKFKNotes
PracticeIDGuidNo→ PracticeGlobal FK; primary practice affiliation
ProviderIDGuidYesPrimary key
ProviderFirstNameString100String100YesProvider first name
ProviderLastNameString100String100YesProvider last name
ProviderNpiString50String50YesNational Provider Identifier (10-digit)
ProviderDeaNumberString50String50NoDEA registration number (for prescribers)
ProviderSpecialtyCodeString50String50NoNPI taxonomy / specialty code
ProviderSourceOrganizationIDGuidYesSource org that created this row
UpdatedDateTimeUTCDateTimeYesAudit — last write timestamp
UpdatedByUserIDGuidYes→ UserAudit — who last wrote
DeletedDateTimeUTCDateTimeNoAudit — soft-delete timestamp. NULL = active; non-null = deletion time.

Practice P0

One row per practice organization. GLOBAL — no OrganizationID. A practice is a reference entity shared across the platform; the PracticeID is the OrganizationID value used in org-scoped tables.

Trust tier: 2 (internal canonical; Tax ID and NPI verified).

RBAC: Read ≥ 1, Write ≥ 70 (practice manager), EditAMI ≥ 90.

Practice AMI schema
FieldTypeRequiredPKFKNotes
PracticeIDGuidYesPrimary key; also serves as OrganizationID in org-scoped tables
PracticePracticeNameString100String100YesLegal practice name
PracticeTaxIdString50String50YesEIN / Tax ID
PracticeNpiString50String50NoOrganization NPI (Type 2)
PracticeIsActiveBoolBoolYesPractice is currently active
PracticeSourceOrganizationIDGuidYesSource org that created this row
UpdatedDateTimeUTCDateTimeYesAudit — last write timestamp
UpdatedByUserIDGuidYes→ UserAudit — who last wrote
DeletedDateTimeUTCDateTimeNoAudit — soft-delete timestamp. NULL = active; non-null = deletion time.

Pharmacy P0

One row per pharmacy. GLOBAL — no OrganizationID. Pharmacy is a reference entity; patients and prescriptions reference it across all orgs.

Trust tier: 3 (verified by NCPDP directory — authoritative).

RBAC: Read ≥ 1, Write ≥ 70 (practice manager), EditAMI ≥ 90.

Pharmacy AMI schema
FieldTypeRequiredPKFKNotes
PharmacyIDGuidYesPrimary key
PharmacyPharmacyNameString100String100YesPharmacy display name
PharmacyNcpdpIdString50String50YesNCPDP Provider ID (7-digit)
PharmacyPhoneNumberString50String50NoPhone number
PharmacyAddressLine1String200String200NoStreet address
PharmacyCityString100String100NoCity
PharmacyStateCodeString50String50NoTwo-letter US state code
PharmacyZipCodeString50String50NoZIP code
PharmacySourceOrganizationIDGuidYesSource org that created this row
UpdatedDateTimeUTCDateTimeYesAudit — last write timestamp
UpdatedByUserIDGuidYes→ UserAudit — who last wrote
DeletedDateTimeUTCDateTimeNoAudit — soft-delete timestamp. NULL = active; non-null = deletion time.

Specialty P0

One row per medical specialty. GLOBAL — no OrganizationID. Reference lookup for provider specialty codes.

Trust tier: 3 (verified by NPI taxonomy — authoritative).

RBAC: Read ≥ 1, Write ≥ 90 (EditAMI only).

Specialty AMI schema
FieldTypeRequiredPKFKNotes
SpecialtyIDGuidYesPrimary key
SpecialtySpecialtyNameString100String100YesDisplay name (e.g., “Cardiology”)
SpecialtySpecialtyCodeString50String50YesNPI taxonomy code
SpecialtySourceOrganizationIDGuidYesSource org that created this row
UpdatedDateTimeUTCDateTimeYesAudit — last write timestamp
UpdatedByUserIDGuidYes→ UserAudit — who last wrote
DeletedDateTimeUTCDateTimeNoAudit — soft-delete timestamp. NULL = active; non-null = deletion time.

Encounter P0

One row per clinical encounter (visit). Org-scoped. Encounters are operational events owned by the practice where they occurred.

Trust tier: 2 (clinician-attested in-system — confirmed).

RBAC: Read ≥ 1, Write intake ≥ 51 (front desk, MA), Write clinical ≥ 51 (nurse, physician), EditAMI ≥ 90.

Encounter AMI schema
FieldTypeRequiredPKFKNotes
PatientIDGuidYes→ PatientGlobal FK; patient seen
ProviderIDGuidYes→ ProviderGlobal FK; attending provider
EncounterIDGuidYesPrimary key
EncounterLocationIDString50String50NoRoom or location identifier
EncounterEncounterDateTimeUTCDateTimeYesScheduled or actual encounter datetime
EncounterEncounterTypeString50String50YesOffice / Telehealth / Urgent / Procedure / Well-visit
EncounterStatusString50String50YesScheduled / In-progress / Completed / Cancelled / No-show
EncounterReasonString200String200NoChief complaint or visit reason
OrganizationIDGuidYesAudit — Cosmos partition key (org-scoped)
UpdatedDateTimeUTCDateTimeYesAudit — last write timestamp
UpdatedByUserIDGuidYes→ UserAudit — who last wrote
DeletedDateTimeUTCDateTimeNoAudit — soft-delete timestamp. NULL = active; non-null = deletion time.

Allergy P0

One row per patient allergy or intolerance. GLOBAL — clinical fact with SourceOrganizationID audit. A deliberate exception to IC hard rule #11: allergies belong to the patient and are visible across all orgs, with SourceOrganizationID recording which org contributed the data.

Trust tier: 1 (patient-attested) – 3 (verified by source-of-truth such as pharmacy fill or allergist report).

RBAC: Read ≥ 1, Write ≥ 51 (clinician), EditAMI ≥ 90.

Allergy AMI schema
FieldTypeRequiredPKFKNotes
PatientIDGuidYes→ PatientGlobal FK; patient who has the allergy
SourceInboundIDGuidNo→ ExternalInboundFK to the inbound payload that contributed this allergy; null if manually entered
AllergyIDGuidYesPrimary key
AllergyAllergenCodeString50String50YesRxNorm / SNOMED code for the allergen
AllergyAllergenNameString100String100YesDisplay name of the allergen
AllergyAllergenTypeString50String50YesDrug / Food / Environment / Biologic
AllergyReactionString200String200NoObserved reaction (e.g., “rash”, “anaphylaxis”)
AllergySeverityString50String50NoMild / Moderate / Severe
AllergyOnsetDateString50String50NoApproximate onset date or year
AllergyVerificationStatusString50String50YesUnconfirmed / Confirmed / Refuted / Entered-in-error
AllergySourceOrganizationIDGuidYesSource org that contributed this clinical fact (deliberate exception to IC rule #11)
UpdatedDateTimeUTCDateTimeYesAudit — last write timestamp
UpdatedByUserIDGuidYes→ UserAudit — who last wrote
DeletedDateTimeUTCDateTimeNoAudit — soft-delete timestamp. NULL = active; non-null = deletion time.

Medication P0

One row per active or historical medication on the patient’s med list. GLOBAL — clinical fact with SourceOrganizationID audit. Deliberate exception to IC hard rule #11; the patient owns their medication history across all prescribing orgs.

Trust tier: 1 (patient-attested) – 3 (verified by pharmacy fill or prescriber).

RBAC: Read ≥ 1, Write ≥ 51 (clinician), EditAMI ≥ 90.

Medication AMI schema
FieldTypeRequiredPKFKNotes
PatientIDGuidYes→ PatientGlobal FK; patient on the medication
PrescribingProviderIDGuidNo→ ProviderGlobal FK; prescribing provider
SourceInboundIDGuidNo→ ExternalInboundFK to inbound payload; null if manually entered
MedicationIDGuidYesPrimary key
MedicationMedicationCodeString50String50YesRxNorm RxCUI
MedicationMedicationNameString100String100YesDisplay name of the medication
MedicationDoseString50String50NoDose and unit (e.g., “10 mg”)
MedicationRouteString50String50NoRoute of administration (e.g., “oral”)
MedicationFrequencyString50String50NoDosing frequency (e.g., “BID”)
MedicationStartDateDateTimeUTCDateTimeNoStart date of therapy
MedicationEndDateDateTimeUTCDateTimeNoEnd date (null if active)
MedicationStatusString50String50YesActive / Completed / Stopped / On-hold
MedicationSourceOrganizationIDGuidYesSource org that contributed this clinical fact (deliberate exception to IC rule #11)
UpdatedDateTimeUTCDateTimeYesAudit — last write timestamp
UpdatedByUserIDGuidYes→ UserAudit — who last wrote
DeletedDateTimeUTCDateTimeNoAudit — soft-delete timestamp. NULL = active; non-null = deletion time.

Condition P0

One row per problem, diagnosis, or health concern on the patient’s problem list. GLOBAL — clinical fact with SourceOrganizationID audit. Deliberate exception to IC hard rule #11.

Trust tier: 1 (patient-attested) – 3 (verified by source-of-truth).

RBAC: Read ≥ 1, Write ≥ 51 (clinician), EditAMI ≥ 90.

Condition AMI schema
FieldTypeRequiredPKFKNotes
PatientIDGuidYes→ PatientGlobal FK; patient with the condition
SourceInboundIDGuidNo→ ExternalInboundFK to inbound payload; null if manually entered
ConditionIDGuidYesPrimary key
ConditionIcd10CodeString50String50YesICD-10-CM code
ConditionConditionNameString100String100YesDisplay name of the condition
ConditionConditionCategoryString50String50NoProblem-list-item / Health-concern / Encounter-diagnosis
ConditionClinicalStatusString50String50YesActive / Recurrence / Relapse / Inactive / Remission / Resolved
ConditionVerificationStatusString50String50YesUnconfirmed / Confirmed / Refuted / Entered-in-error
ConditionOnsetDateTimeUTCDateTimeNoEstimated onset datetime
ConditionAbatementDateTimeUTCDateTimeNoWhen the condition resolved (null if active)
ConditionSourceOrganizationIDGuidYesSource org that contributed this clinical fact (deliberate exception to IC rule #11)
UpdatedDateTimeUTCDateTimeYesAudit — last write timestamp
UpdatedByUserIDGuidYes→ UserAudit — who last wrote
DeletedDateTimeUTCDateTimeNoAudit — soft-delete timestamp. NULL = active; non-null = deletion time.

Surgery P0

One row per surgical procedure in the patient’s history. GLOBAL — clinical fact with SourceOrganizationID audit. Deliberate exception to IC hard rule #11.

Trust tier: 1 (patient-attested) – 3 (verified by surgical report).

RBAC: Read ≥ 1, Write ≥ 51 (clinician), EditAMI ≥ 90.

Surgery AMI schema
FieldTypeRequiredPKFKNotes
PatientIDGuidYes→ PatientGlobal FK; patient who underwent surgery
SurgeonProviderIDGuidNo→ ProviderGlobal FK; surgeon
SourceInboundIDGuidNo→ ExternalInboundFK to inbound payload; null if manually entered
SurgeryIDGuidYesPrimary key
SurgeryProcedureCodeString50String50YesCPT or ICD-10-PCS procedure code
SurgeryProcedureNameString100String100YesDisplay name of the procedure
SurgerySurgeryDateTimeUTCDateTimeYesDate/time of the surgery
SurgeryFacilityNameString100String100NoFacility where surgery was performed
SurgeryOutcomeString200String200NoOutcome summary
SurgerySourceOrganizationIDGuidYesSource org that contributed this clinical fact (deliberate exception to IC rule #11)
UpdatedDateTimeUTCDateTimeYesAudit — last write timestamp
UpdatedByUserIDGuidYes→ UserAudit — who last wrote
DeletedDateTimeUTCDateTimeNoAudit — soft-delete timestamp. NULL = active; non-null = deletion time.

FamilyHistory P1

One row per family-member condition on the patient’s family history. GLOBAL — clinical fact with SourceOrganizationID audit. Deliberate exception to IC hard rule #11.

Trust tier: 1 (patient-attested — working knowledge; clinician confirmation required for high-stakes fields).

RBAC: Read ≥ 1, Write ≥ 51 (clinician), EditAMI ≥ 90.

FamilyHistory AMI schema
FieldTypeRequiredPKFKNotes
PatientIDGuidYes→ PatientGlobal FK; patient whose family history this is
FamilyHistoryIDGuidYesPrimary key
FamilyHistoryRelativeTypeCodeString50String50YesSNOMED code for the relative (FTH, MTH, SIS, etc.)
FamilyHistoryConditionCodeString50String50YesSNOMED / ICD-10 code for the relative’s condition
FamilyHistoryConditionNameString100String100YesDisplay name of the condition
FamilyHistoryAgeAtOnsetIntIntNoAge of relative at condition onset
FamilyHistoryIsDeceasedBoolBoolNoWhether the relative is deceased
FamilyHistorySourceOrganizationIDGuidYesSource org that contributed this clinical fact (deliberate exception to IC rule #11)
UpdatedDateTimeUTCDateTimeYesAudit — last write timestamp
UpdatedByUserIDGuidYes→ UserAudit — who last wrote
DeletedDateTimeUTCDateTimeNoAudit — soft-delete timestamp. NULL = active; non-null = deletion time.

Vital P0

One row per vital-sign measurement. GLOBAL — clinical fact with SourceOrganizationID audit. Deliberate exception to IC hard rule #11. Home-entered and clinic-entered vitals share the same noun, distinguished by RecordedByUserID + trust tier.

Trust tier: 1 (patient home entry) – 2 (clinician-recorded in encounter).

RBAC: Read ≥ 1, Write ≥ 51 (MA, nurse), EditAMI ≥ 90.

Vital AMI schema
FieldTypeRequiredPKFKNotes
PatientIDGuidYes→ PatientGlobal FK; patient measured
EncounterIDGuidNo→ EncounterFK to encounter; null for home entry
RecordedByUserIDGuidYes→ UserGlobal FK; who recorded the vital
VitalIDGuidYesPrimary key
VitalVitalTypeString50String50YesBP-systolic / BP-diastolic / HR / Temp / Weight / Height / SpO2 / BMI
VitalValueDecimalDecimalYesNumeric value
VitalUnitString50String50YesUnit of measure (e.g., “mmHg”, “kg”)
VitalRecordedDateTimeUTCDateTimeYesWhen the vital was recorded
VitalSourceOrganizationIDGuidYesSource org that contributed this clinical fact (deliberate exception to IC rule #11)
UpdatedDateTimeUTCDateTimeYesAudit — last write timestamp
UpdatedByUserIDGuidYes→ UserAudit — who last wrote
DeletedDateTimeUTCDateTimeNoAudit — soft-delete timestamp. NULL = active; non-null = deletion time.

LabResult P0

One row per lab test result. GLOBAL — clinical fact with SourceOrganizationID audit. Deliberate exception to IC hard rule #11. Lab results are patient-owned; the performing lab may be external.

Trust tier: 3 (verified by source-of-truth — lab feed is authoritative).

RBAC: Read ≥ 1, Write ≥ 51 (lab tech, clinician), EditAMI ≥ 90.

LabResult AMI schema
FieldTypeRequiredPKFKNotes
PatientIDGuidYes→ PatientGlobal FK; patient tested
OrderIDGuidNo→ OrderFK to the originating order
SourceInboundIDGuidNo→ ExternalInboundFK to inbound payload; null if manually entered
LabResultIDGuidYesPrimary key
LabResultTestCodeString50String50YesLOINC code for the test
LabResultTestNameString100String100YesDisplay name of the test
LabResultResultValueString200String200YesResult value (string to accommodate qualitative results)
LabResultReferenceRangeString200String200NoNormal reference range
LabResultAbnormalFlagString50String50NoNormal / Abnormal / Critical
LabResultResultDateTimeUTCDateTimeYesWhen the result was finalized
LabResultPerformingLabString100String100NoName of the performing laboratory
LabResultSourceOrganizationIDGuidYesSource org that contributed this clinical fact (deliberate exception to IC rule #11)
UpdatedDateTimeUTCDateTimeYesAudit — last write timestamp
UpdatedByUserIDGuidYes→ UserAudit — who last wrote
DeletedDateTimeUTCDateTimeNoAudit — soft-delete timestamp. NULL = active; non-null = deletion time.

Imaging P0

One row per imaging study. GLOBAL — clinical fact with SourceOrganizationID audit. Deliberate exception to IC hard rule #11.

Trust tier: 3 (verified by source-of-truth — signed radiology report is authoritative).

RBAC: Read ≥ 1, Write ≥ 51 (clinician), EditAMI ≥ 90.

Imaging AMI schema
FieldTypeRequiredPKFKNotes
PatientIDGuidYes→ PatientGlobal FK; patient imaged
OrderIDGuidNo→ OrderFK to the originating order
SourceInboundIDGuidNo→ ExternalInboundFK to inbound payload; null if manually entered
ImagingIDGuidYesPrimary key
ImagingModalityString50String50YesCT / MRI / X-ray / Ultrasound / PET
ImagingBodyPartString100String100YesBody part examined
ImagingStudyDateTimeUTCDateTimeYesDate/time of the imaging study
ImagingReportTextTextNoRadiology report narrative
ImagingFindingString200String200NoKey finding summary
ImagingSourceOrganizationIDGuidYesSource org that contributed this clinical fact (deliberate exception to IC rule #11)
UpdatedDateTimeUTCDateTimeYesAudit — last write timestamp
UpdatedByUserIDGuidYes→ UserAudit — who last wrote
DeletedDateTimeUTCDateTimeNoAudit — soft-delete timestamp. NULL = active; non-null = deletion time.

Order P0

One row per clinical order (lab, imaging, referral). Org-scoped. Orders are operational events initiated by a practice.

Trust tier: 2 (clinician-attested in-system — confirmed).

RBAC: Read ≥ 1, Write ≥ 51 (clinician, lab tech for status), EditAMI ≥ 90.

Order AMI schema
FieldTypeRequiredPKFKNotes
PatientIDGuidYes→ PatientGlobal FK; patient for whom the order is placed
OrderingProviderIDGuidYes→ ProviderGlobal FK; ordering provider
OrderIDGuidYesPrimary key
OrderOrderTypeString50String50YesLab / Imaging / Referral / Procedure
OrderOrderCodeString50String50YesCPT / LOINC / HCPCS code
OrderOrderNameString100String100YesDisplay name of the order
OrderStatusString50String50YesDraft / Ordered / In-progress / Completed / Cancelled
OrderPriorityString50String50NoRoutine / Urgent / STAT
OrderOrderedDateTimeUTCDateTimeYesWhen the order was placed
OrganizationIDGuidYesAudit — Cosmos partition key (org-scoped)
UpdatedDateTimeUTCDateTimeYesAudit — last write timestamp
UpdatedByUserIDGuidYes→ UserAudit — who last wrote
DeletedDateTimeUTCDateTimeNoAudit — soft-delete timestamp. NULL = active; non-null = deletion time.

Immunization P0

One row per immunization administered or recorded. GLOBAL — clinical fact with SourceOrganizationID audit. Deliberate exception to IC hard rule #11.

Trust tier: 1 (patient-attested) – 3 (verified by immunization registry).

RBAC: Read ≥ 1, Write ≥ 51 (MA, nurse), EditAMI ≥ 90.

Immunization AMI schema
FieldTypeRequiredPKFKNotes
PatientIDGuidYes→ PatientGlobal FK; patient immunized
AdministeredByUserIDGuidNo→ UserGlobal FK; who administered
SourceInboundIDGuidNo→ ExternalInboundFK to inbound payload; null if manually entered
ImmunizationIDGuidYesPrimary key
ImmunizationVaccineCodeString50String50YesCVX code for the vaccine
ImmunizationVaccineNameString100String100YesDisplay name of the vaccine
ImmunizationAdministeredDateTimeUTCDateTimeYesDate/time the vaccine was administered
ImmunizationLotNumberString50String50NoLot number of the vaccine
ImmunizationManufacturerString100String100NoVaccine manufacturer
ImmunizationSiteString50String50NoAdministration site (e.g., “left deltoid”)
ImmunizationSourceOrganizationIDGuidYesSource org that contributed this clinical fact (deliberate exception to IC rule #11)
UpdatedDateTimeUTCDateTimeYesAudit — last write timestamp
UpdatedByUserIDGuidYes→ UserAudit — who last wrote
DeletedDateTimeUTCDateTimeNoAudit — soft-delete timestamp. NULL = active; non-null = deletion time.

CarePlan P0

One row per care plan (a named, categorized set of tasks for a patient). GLOBAL — clinical fact with SourceOrganizationID audit. Deliberate exception to IC hard rule #11. The care plan is the living, computable per-patient plan that updates itself as conditions change.

Trust tier: 2 (clinician-attested in-system; rules auto-generate, clinicians confirm or override).

RBAC: Read ≥ 1, Write ≥ 51 (nurse, physician), EditAMI ≥ 90.

CarePlan AMI schema
FieldTypeRequiredPKFKNotes
PatientIDGuidYes→ PatientGlobal FK; patient on the care plan
CarePlanIDGuidYesPrimary key
CarePlanPlanTitleString100String100YesHuman-readable plan title (e.g., “T2D Management”)
CarePlanPlanCategoryString50String50YesCategory (e.g., “Chronic-disease”, “Preventive”, “Post-surgical”)
CarePlanStatusString50String50YesActive / Completed / Suspended / Entered-in-error
CarePlanCreatedDateTimeUTCDateTimeYesWhen the care plan was created
CarePlanSourceOrganizationIDGuidYesSource org that contributed this clinical fact (deliberate exception to IC rule #11)
UpdatedDateTimeUTCDateTimeYesAudit — last write timestamp
UpdatedByUserIDGuidYes→ UserAudit — who last wrote
DeletedDateTimeUTCDateTimeNoAudit — soft-delete timestamp. NULL = active; non-null = deletion time.

Screening P1

One row per screening or preventive service due/completed for a patient. GLOBAL — clinical fact with SourceOrganizationID audit. Deliberate exception to IC hard rule #11. Each screening pins a RuleVersionID for determinism.

Trust tier: 2 (rule-generated, clinician-confirmed).

RBAC: Read ≥ 1, Write ≥ 51 (clinician), EditAMI ≥ 90.

Screening AMI schema
FieldTypeRequiredPKFKNotes
PatientIDGuidYes→ PatientGlobal FK; patient due for screening
RuleVersionIDGuidYes→ RuleVersionFK to the rule version that generated this screening
ScreeningIDGuidYesPrimary key
ScreeningScreeningTypeString50String50YesType (e.g., “Mammogram”, “Colonoscopy”, “A1C”)
ScreeningScreeningCodeString50String50YesCode for the screening (CPT / LOINC / HCPCS)
ScreeningStatusString50String50YesDue / Scheduled / Completed / Overdue / Cancelled
ScreeningDueDateTimeUTCDateTimeYesWhen the screening is due
ScreeningCompletedDateTimeUTCDateTimeNoWhen the screening was completed (null if not yet done)
ScreeningResultString200String200NoScreening result summary
ScreeningSourceOrganizationIDGuidYesSource org that contributed this clinical fact (deliberate exception to IC rule #11)
UpdatedDateTimeUTCDateTimeYesAudit — last write timestamp
UpdatedByUserIDGuidYes→ UserAudit — who last wrote
DeletedDateTimeUTCDateTimeNoAudit — soft-delete timestamp. NULL = active; non-null = deletion time.

Reminder P0

One row per concrete reminder to send. Org-scoped. Reminders are operational — they are persisted as absolute UTC datetimes and polled by the dispatcher. T-offsets are configuration only; the DB stores the computed send time, not the offset formula. See Section 6 for the full worked example.

Trust tier: 2 (clinician-attested in-system — confirmed).

RBAC: Read ≥ 1, Write ≥ 51 (nurse, care coordinator), ManageFeatures ≥ 80, EditAMI ≥ 90.

Reminder AMI schema
FieldTypeRequiredPKFKNotes
PatientIDGuidYes→ PatientGlobal FK; patient to remind
ReminderIDGuidYesPrimary key
ReminderCarePlanTaskIDString50String50YesReference to the CarePlanTask this reminder is for
ReminderOffsetCodeString50String50YesTraceability label: T-30 / T-14 / T-3 / T-day / T+3 / T+14 — not used for scheduling
ReminderScheduledSendDateTimeUTCDateTimeYesThe actual moment to send; dispatcher queries on this
ReminderChannelCodeString50String50Yessms / email / portal / workqueue
ReminderStatusCodeString50String50Yesscheduled / sent / delivered / failed / cancelled / superseded
ReminderIsSentBoolBoolYesWhether the reminder has been sent
ReminderSentDateTimeUTCDateTimeNoWhen the reminder was sent (null until sent)
ReminderResponseCodeString50String50Noconfirmed / declined / rescheduled / none
ReminderResponseDateTimeUTCDateTimeNoWhen the patient responded (null until response)
OrganizationIDGuidYesAudit — Cosmos partition key (org-scoped)
UpdatedDateTimeUTCDateTimeYesAudit — last write timestamp
UpdatedByUserIDGuidYes→ UserAudit — who last wrote
DeletedDateTimeUTCDateTimeNoAudit — soft-delete timestamp. NULL = active; non-null = deletion time.

Document P0

One row per clinical document (note, letter, report). GLOBAL — clinical fact with SourceOrganizationID audit. Deliberate exception to IC hard rule #11.

Trust tier: 2 (clinician-authored in-system) – 3 (verified by signed external report).

RBAC: Read ≥ 1, Write ≥ 51 (clinician), EditAMI ≥ 90.

Document AMI schema
FieldTypeRequiredPKFKNotes
PatientIDGuidYes→ PatientGlobal FK; patient the document is about
EncounterIDGuidNo→ EncounterFK to encounter; null for non-encounter documents
AuthorUserIDGuidYes→ UserGlobal FK; author of the document
SourceInboundIDGuidNo→ ExternalInboundFK to inbound payload; null if authored in-system
DocumentIDGuidYesPrimary key
DocumentDocumentTypeString50String50YesNote / Letter / Report / Summary / Consent
DocumentTitleString100String100YesDocument title
DocumentContentTextTextYesDocument body content
DocumentCreatedDateTimeUTCDateTimeYesWhen the document was created
DocumentSourceOrganizationIDGuidYesSource org that contributed this clinical fact (deliberate exception to IC rule #11)
UpdatedDateTimeUTCDateTimeYesAudit — last write timestamp
UpdatedByUserIDGuidYes→ UserAudit — who last wrote
DeletedDateTimeUTCDateTimeNoAudit — soft-delete timestamp. NULL = active; non-null = deletion time.

Referral P0

One row per referral. Org-scoped. Cross-references the Referrals module. Referrals are operational events initiated by a practice to send a patient to a specialist.

Trust tier: 2 (clinician-attested in-system — confirmed).

RBAC: Read ≥ 1, Write ≥ 51 (clinician), EditAMI ≥ 90.

Referral AMI schema
FieldTypeRequiredPKFKNotes
PatientIDGuidYes→ PatientGlobal FK; patient referred
FromProviderIDGuidYes→ ProviderGlobal FK; referring provider
ToProviderIDGuidNo→ ProviderGlobal FK; target specialist
ToOrganizationIDGuidNo→ OrganizationFK to target organization (external practice)
ReferralIDGuidYesPrimary key
ReferralReferralReasonString200String200YesReason for referral
ReferralClinicalSummaryTextTextNoClinical summary for the receiving provider
ReferralUrgencyString50String50NoRoutine / Urgent / STAT
ReferralStatusString50String50YesDraft / Sent / Accepted / Rejected / Completed / Cancelled
ReferralReferralTypeString50String50NoInternal / External
ReferralNpiTargetString50String50NoNPI of the target specialist
ReferralDirectAddressString200String200NoDirect address for secure messaging
ReferralFhirServiceRequestIDString50String50NoFHIR ServiceRequest resource ID for interop
OrganizationIDGuidYesAudit — Cosmos partition key (org-scoped)
UpdatedDateTimeUTCDateTimeYesAudit — last write timestamp
UpdatedByUserIDGuidYes→ UserAudit — who last wrote
DeletedDateTimeUTCDateTimeNoAudit — soft-delete timestamp. NULL = active; non-null = deletion time.

Message P1

One row per internal message between users about a patient. Org-scoped. Messages are operational communications owned by the practice.

Trust tier: 2 (internal canonical — authored by credentialed users in-system).

RBAC: Read own ≥ 1, Write ≥ 51, EditAMI ≥ 90.

Message AMI schema
FieldTypeRequiredPKFKNotes
PatientIDGuidYes→ PatientGlobal FK; patient the message is about
FromUserIDGuidYes→ UserGlobal FK; sender
ToUserIDGuidYes→ UserGlobal FK; recipient
MessageIDGuidYesPrimary key
MessageSubjectString100String100YesMessage subject
MessageBodyTextTextYesMessage body
MessageMessageDirectionString50String50YesInbound / Outbound
MessageIsReadBoolBoolYesWhether the recipient has read the message
OrganizationIDGuidYesAudit — Cosmos partition key (org-scoped)
UpdatedDateTimeUTCDateTimeYesAudit — last write timestamp
UpdatedByUserIDGuidYes→ UserAudit — who last wrote
DeletedDateTimeUTCDateTimeNoAudit — soft-delete timestamp. NULL = active; non-null = deletion time.

ExternalInbound P0

One row per external payload received (HL7v2, FHIR, CCDA, X12, fax+OCR, partner JSON). Org-scoped. Immutable once created — the canonical receipt for provenance and dispute resolution.

Trust tier: 0 (unverified inbound) until mapping and review promote child clinical-fact rows to tier 1–3.

RBAC: Read ≥ 51 (clinician, integration admin), Write system-only (service principal), EditAMI ≥ 90.

ExternalInbound AMI schema
FieldTypeRequiredPKFKNotes
PatientIDGuidYes→ PatientGlobal FK; patient the payload is about
SourceSystemIDGuidYes→ ExternalSourceSystemFK to the source system that sent this payload
ExternalInboundIDGuidYesPrimary key
ExternalInboundPayloadFormatString50String50YesHL7v2 / FHIR-R4 / CCDA / X12 / FaxOCR / PartnerJSON
ExternalInboundRawPayloadTextTextYesRaw inbound payload (encrypted at rest)
ExternalInboundReceivedDateTimeUTCDateTimeYesWhen the payload was received
ExternalInboundMappingVersionString50String50YesVersion of the mapping applied
ExternalInboundIsAppliedBoolBoolYesWhether the mapping has been applied to clinical noun apps
OrganizationIDGuidYesAudit — Cosmos partition key (org-scoped)
UpdatedDateTimeUTCDateTimeYesAudit — last write timestamp
UpdatedByUserIDGuidYes→ UserAudit — who last wrote
DeletedDateTimeUTCDateTimeNoAudit — soft-delete timestamp. NULL = active; non-null = deletion time.

ExternalOutbound P0

One row per outbound payload sent to an external recipient. Org-scoped. Immutable once created — the canonical receipt for what was sent and when, including any redactions applied.

Trust tier: 2 (rendered from clinician-attested data in-system).

RBAC: Read ≥ 51 (clinician, integration admin), Write system-only (service principal), EditAMI ≥ 90.

ExternalOutbound AMI schema
FieldTypeRequiredPKFKNotes
PatientIDGuidYes→ PatientGlobal FK; patient the payload is about
RecipientIDGuidYes→ ExternalRecipientFK to the recipient
ExternalOutboundIDGuidYesPrimary key
ExternalOutboundPayloadFormatString50String50YesFHIR-US-Core / CCDA / X12 / PartnerJSON
ExternalOutboundRenderedPayloadTextTextYesRendered outbound payload (encrypted at rest)
ExternalOutboundSentDateTimeUTCDateTimeYesWhen the payload was sent
ExternalOutboundRedactionAppliedBoolBoolYesWhether any redactions were applied (42 CFR Part 2, sensitive classes)
OrganizationIDGuidYesAudit — Cosmos partition key (org-scoped)
UpdatedDateTimeUTCDateTimeYesAudit — last write timestamp
UpdatedByUserIDGuidYes→ UserAudit — who last wrote
DeletedDateTimeUTCDateTimeNoAudit — soft-delete timestamp. NULL = active; non-null = deletion time.

ExternalSourceSystem P0

One row per external source system that sends data to rev.health. Org-scoped. Configuration entity for inbound interop.

Trust tier: N/A (configuration, not clinical data).

RBAC: Read ≥ 70 (integration admin), Write ≥ 70, EditAMI ≥ 90.

ExternalSourceSystem AMI schema
FieldTypeRequiredPKFKNotes
ExternalSourceSystemIDGuidYesPrimary key
ExternalSourceSystemSystemNameString100String100YesDisplay name of the source system
ExternalSourceSystemSystemTypeString50String50YesEHR / Lab / HIE / Pharmacy / Hospital / Payer
ExternalSourceSystemEndpointUrlString200String200YesEndpoint URL for the source system
ExternalSourceSystemIsActiveBoolBoolYesWhether the source system is active
OrganizationIDGuidYesAudit — Cosmos partition key (org-scoped)
UpdatedDateTimeUTCDateTimeYesAudit — last write timestamp
UpdatedByUserIDGuidYes→ UserAudit — who last wrote
DeletedDateTimeUTCDateTimeNoAudit — soft-delete timestamp. NULL = active; non-null = deletion time.

ExternalRecipient P0

One row per external recipient that receives data from rev.health. Org-scoped. Configuration entity for outbound interop.

Trust tier: N/A (configuration, not clinical data).

RBAC: Read ≥ 70 (integration admin), Write ≥ 70, EditAMI ≥ 90.

ExternalRecipient AMI schema
FieldTypeRequiredPKFKNotes
ExternalRecipientIDGuidYesPrimary key
ExternalRecipientRecipientNameString100String100YesDisplay name of the recipient
ExternalRecipientRecipientTypeString50String50YesSpecialist / Hospital / Payer / HIE / Pharmacy
ExternalRecipientDirectAddressString200String200NoDirect secure messaging address
ExternalRecipientEndpointUrlString200String200YesEndpoint URL for the recipient
ExternalRecipientIsActiveBoolBoolYesWhether the recipient is active
OrganizationIDGuidYesAudit — Cosmos partition key (org-scoped)
UpdatedDateTimeUTCDateTimeYesAudit — last write timestamp
UpdatedByUserIDGuidYes→ UserAudit — who last wrote
DeletedDateTimeUTCDateTimeNoAudit — soft-delete timestamp. NULL = active; non-null = deletion time.

RuleVersion P0

One row per versioned clinical rule. Org-scoped. Every CarePlanTask and Screening pins a RuleVersionID so the care plan is reproducible from inputs + rule version. Rules are their own noun-app, not inline logic.

Trust tier: N/A (configuration, not clinical data).

RBAC: Read ≥ 51, Write ≥ 80 (practice admin), EditAMI ≥ 90.

RuleVersion AMI schema
FieldTypeRequiredPKFKNotes
RuleVersionIDGuidYesPrimary key
RuleVersionRuleNameString100String100YesHuman-readable rule name (e.g., “USPSTF Mammogram 2024”)
RuleVersionRuleCategoryString50String50YesScreening / Chronic-mgmt / Preventive / Post-surgical
RuleVersionVersionString50String50YesSemver version (e.g., “1.2.0”)
RuleVersionEffectiveDateTimeUTCDateTimeYesWhen this rule version becomes effective
RuleVersionIsActiveBoolBoolYesWhether this rule version is currently active
OrganizationIDGuidYesAudit — Cosmos partition key (org-scoped)
UpdatedDateTimeUTCDateTimeYesAudit — last write timestamp
UpdatedByUserIDGuidYes→ UserAudit — who last wrote
DeletedDateTimeUTCDateTimeNoAudit — soft-delete timestamp. NULL = active; non-null = deletion time.

User P0

One row per system user (clinician, staff, admin). GLOBAL — no OrganizationID. User identity is global; a person may work across multiple practices. Uses the SourceOrganizationID audit pattern.

Trust tier: 2 (internal canonical; identity proofed via SSO + MFA).

RBAC: Read ≥ 1 (own profile), Write ≥ 70 (practice manager), Admin ≥ 100, EditAMI ≥ 90.

User AMI schema
FieldTypeRequiredPKFKNotes
PracticeIDGuidNo→ PracticeGlobal FK; primary practice affiliation
UserIDGuidYesPrimary key
UserEmailString200String200YesLogin email address
UserDisplayNameString100String100YesDisplay name for the user
UserRoleCodeString50String50YesRole code (physician / nurse / front-desk / admin / lab-tech / billing / system)
UserIsActiveBoolBoolYesWhether the user account is active
UserSourceOrganizationIDGuidYesSource org that created this row
UpdatedDateTimeUTCDateTimeYesAudit — last write timestamp
UpdatedByUserIDGuidYes→ UserAudit — who last wrote
DeletedDateTimeUTCDateTimeNoAudit — soft-delete timestamp. NULL = active; non-null = deletion time.

AuditLog P0

One row per auditable action (read or write) across all noun apps. Org-scoped. Immutable — the system appends only; no updates or deletes. Captures the authorization-chain trace for every data touch.

Trust tier: N/A (audit infrastructure, not clinical data).

RBAC: Read ≥ 70 (practice admin, compliance), Write system-only, EditAMI ≥ 90.

AuditLog AMI schema
FieldTypeRequiredPKFKNotes
UserIDGuidYes→ UserGlobal FK; who performed the action
AuditLogIDGuidYesPrimary key
AuditLogEntityNameString100String100YesName of the noun-app entity touched (e.g., “Allergy”, “Patient”)
AuditLogEntityIDString50String50YesGuid of the specific row touched
AuditLogActionString50String50YesRead / Create / Update / SoftDelete
AuditLogActionDateTimeUTCDateTimeYesWhen the action occurred
AuditLogAuthorizationChainTextTextYesTraceable authorization chain for the action
OrganizationIDGuidYesAudit — Cosmos partition key (org-scoped)
UpdatedDateTimeUTCDateTimeYesAudit — last write timestamp
UpdatedByUserIDGuidYes→ UserAudit — who last wrote
DeletedDateTimeUTCDateTimeNoAudit — soft-delete timestamp. NULL = active; non-null = deletion time.

Provenance model

The canonical record is the set of noun-app rows themselves. There is no separate canonical document. Provenance is captured by FK and trust tier on each row. Three forms of every clinical fact exist:

(a) Internal canonical provenance

Records created within rev.health by credentialed users. These rows have SourceInboundID = null (or the literal string “manual” in a metadata field) and a TrustTier of 1–2 depending on the attesting role. Editable per RBAC permission rules with full audit.

(b) External inbound provenance

Records received from external systems via ExternalInbound. One row per external payload (HL7v2, FHIR R4, CCDA, X12, fax+OCR, partner JSON). The inbound row stores the raw payload + source + format + timestamp + mapping version applied. Immutable once created. Applied clinical-fact rows carry SourceInboundID FK back to the originating payload for full traceability.

(c) External outbound provenance

Records sent to external systems via ExternalOutbound. One row per send. Stores the rendered payload + recipient + format + timestamp + hash + redactions applied. Immutable. We have exactly what we sent and when.

(d) Trust tier definitions

TierSourceTreated asTypical entities
Tier 0Unverified inboundProvisional — not yet reviewed or mappedExternalInbound rows before mapping; raw patient self-report before clinician review
Tier 1Patient-attestedWorking knowledge — clinician confirmation required for high-stakes fieldsPatient portal contributions, patient-verified imported data
Tier 2Clinician-attested in-systemConfirmed — a credentialed user created or reviewed this in rev.healthEncounters, manually entered allergies, clinician-authored documents
Tier 3Verified by source-of-truthAuthoritative — verified by an external authoritative sourceLab feeds, pharmacy fill records, immunization registries, signed radiology reports, NCPDP directory

(e) Conflict handling rules

RBAC matrix (IC 0–100 scale)

Permission checks happen client-side AND API-side every time, against the 0–100 scale, scoped per app per env per group. MFA required for any role at level ≥ 51. Field-level encryption on PHI columns. Every read and write creates an AuditLog row.

RoleLevelScopeNotes
Patient1Read on rows where PatientID = self, scoped to patient.rev.healthVerification answers create ExternalInbound rows with SourceSystem = “patient-self”. Cannot see fields flagged “do-not-release.”
Front desk51 on Patient demographics + Encounter intake; 0 on clinicalColumn-scoped write on demographic and scheduling fields onlyNo access to clinical narrative, labs, medications, or allergies.
Medical assistant51 on Vital, Immunization, Encounter (intake); 1 read elsewhereWrite on intake-level clinical data; read-only on other clinicalCannot sign Rx or edit problem list.
Nurse / Care coordinator51 write on most clinical noun apps; 80 on Reminder configWrite on clinical facts for assigned patients; manage reminder cadenceCannot sign Rx. Break-glass for non-assigned patients with reason + audit.
Physician51–80 on all clinical noun apps; 90 EditAMIFull clinical write for paneled patients; schema break authorityBreak-glass for non-panel patients with reason + audit. EditAMI is an org-level grant only.
Lab tech51 on LabResult, Order status; 1 on PatientWrite on lab and order status; read-only on patient demographics for matchingNo access to clinical narrative.
Billing1 on Encounter, Patient insurance + demographics; 0 on clinical narrativeRead-only on billing-relevant fieldsNo access to clinical notes, lab results, or allergy list.
Referring specialist (external)Time-boxed token-scoped readRead on a specific Document or Imaging row; write back via ExternalInboundToken expires; no broader grant.
Practice admin100 on User, Practice, RuleVersion; 0 on clinical unless dual roleFull admin on operational config; no clinical access by defaultSeparation of duty. Must be granted a separate clinical role for clinical access.
System / code-gen / standardizerService principalWrites to ExternalInbound / ExternalOutbound; proposes patches against clinical noun appsAll writes attributed to system-{component}-{version}. No direct clinical writes without reconciliation for tier ≥ 2 data.

Worked Reminder example (VAL-CONTENT-042)

A full end-to-end worked example of the Reminder lifecycle, from creation through dispatch, attempt, and supersession.

(a) Reminder AMI schema

See the Reminder entity above (entity #19) for the full AMI schema. Every reminder is persisted as a concrete UTC datetime row that the dispatcher polls against.

(b) ReminderAttempt AMI schema

One row per delivery attempt for a reminder. Records each attempt with outcome for retry visibility and dead-letter tracking.

ReminderAttempt AMI schema
FieldTypeRequiredPKFKNotes
ReminderIDGuidYes→ ReminderFK to the parent reminder
ReminderAttemptIDGuidYesPrimary key
ReminderAttemptAttemptDateTimeUTCDateTimeYesWhen this attempt was made
ReminderAttemptChannelCodeString50String50Yessms / email / portal / workqueue
ReminderAttemptIsSuccessBoolBoolYesWhether the attempt succeeded
ReminderAttemptProviderResponseCodeString50String50NoResponse code from the channel provider (e.g., Twilio SID, SMTP response)
ReminderAttemptErrorMessageString200String200NoError message if the attempt failed
OrganizationIDGuidYesAudit — Cosmos partition key (org-scoped)
UpdatedDateTimeUTCDateTimeYesAudit — last write timestamp
UpdatedByUserIDGuidYes→ UserAudit — who last wrote
DeletedDateTimeUTCDateTimeNoAudit — soft-delete timestamp. NULL = active; non-null = deletion time.

(c) Offset ladder

For each CarePlanTask, the system generates a ladder of concrete Reminder rows at these offsets from the task’s DueDateTimeUTC:

OffsetMeaningPurpose
T-3030 days before dueEarly nudge; schedule appointment
T-1414 days before dueFollow-up nudge if no action
T-33 days before dueUrgent reminder; act now
T-dayDay of due dateDay-of reminder
T+33 days after dueOverdue notice
T+1414 days after dueNo-show follow-up; escalation

Computation: ScheduledSendDateTimeUTC = DueDateTimeUTC + offset, normalized to patient’s preferred contact window (9am–8pm patient-local), then converted back to UTC for storage. Computed once at write time and persisted. Never re-derived implicitly.

(d) Dispatcher SQL query

SELECT * FROM Reminder
WHERE OrganizationID = @practice
  AND IsSentBool = false
  AND DeletedDateTimeUTC IS NULL
  AND StatusCode = 'scheduled'
  AND ScheduledSendDateTimeUTC <= @nowUtc
ORDER BY ScheduledSendDateTimeUTC ASC

The dispatcher runs this query on a poll interval. It is the only thing it does. No business logic lives in the dispatcher beyond dequeue + hand-off to the channel provider.

(e) Frequency cap

Max 3 attempts per patient per day across all channels. Applied at dispatcher dequeue, not at schedule time, so the underlying schedule stays intact. If a patient already has 3 attempts today, the dispatcher skips that row until the next day.

(f) Supersession logic

If CarePlanTask.DueDateTimeUTC changes (e.g., physician overrides the due date), the system:

  1. Marks prior Reminder rows for that task with StatusCode = “superseded”.
  2. Keeps superseded rows for audit — DeletedDateTimeUTC stays null.
  3. Generates a fresh ladder of Reminder rows based on the new DueDateTimeUTC.

This ensures the reminder history is always traceable, and no prior value is destroyed.

(g) Reminder lifecycle diagram

flowchart TD
  A[CarePlanTask created or updated] --> B[Generate offset ladder]
  B --> C[Create Reminder rows with ScheduledSendDateTimeUTC]
  C --> D[Dispatcher polls: ScheduledSendDateTimeUTC <= nowUtc?]
  D -- Yes --> E{Frequency cap OK?}
  E -- Yes --> F[Dequeue + dispatch via channel]
  E -- No --> G[Skip until next day]
  D -- No --> D
  F --> H[Create ReminderAttempt row]
  H --> I{IsSuccessBool?}
  I -- Yes --> J[Reminder.StatusCode = sent / delivered]
  I -- No --> K[ReminderAttempt.ErrorMessageString recorded]
  K --> L{Retry count < max?}
  L -- Yes --> D
  L -- No --> M[Dead-letter: StatusCode = failed]
  J --> N{Patient responded?}
  N -- Yes --> O[Reminder.ResponseCodeString = confirmed / declined / rescheduled]
  N -- No --> P[Next ladder rung fires]
  A2[DueDateTimeUTC changed] --> Q[Mark prior Reminders StatusCode = superseded]
  Q --> B
  O --> R[Reminder lifecycle complete]
        

Worked Allergy versioning example (VAL-CONTENT-043)

A worked example demonstrating AMI schema versioning on the Allergy entity, covering a backward-compatible feature bump (1.1.0) and an illustrative breaking change (2.0.0).

(a) Allergy 1.0.0 — initial creation

The initial schema as documented in the Allergy entity above (entity #7). This is the “before” schema. Key fields include AllergyID, PatientID, AllergenCodeString50, AllergenNameString100, AllergenTypeString50, ReactionString200, SeverityString50, VerificationStatusString50, plus the three audit fields with SourceOrganizationID pattern.

Note: OnsetDateString50 is not present in v1.0.0. The field was added in v1.1.0.

(b) Allergy 1.1.0 — feature bump (backward-compatible)

Add an optional field OnsetDateString50 to capture the approximate onset date or year of the allergy. This is a backward-compatible addition: existing rows continue to work with OnsetDateString = null.

Aspectv1.0.0 (before)v1.1.0 (after)
New fieldOnsetDateString50 (String50, Required=No)
MigrationBackward-compatible ALTER TABLE ADD COLUMN; no new DB needed. Existing rows have OnsetDateString = null.
Existing rowsUnaffectedContinue to function; OnsetDateString50 is nullable
API contractNo changeNew optional field in response; clients that don’t request it are unaffected

(c) Allergy 2.0.0 — break bump (illustrative)

Make OnsetDateString50 required and change its type from String to DateTime. This is a breaking change: existing rows with null or free-text onset values cannot satisfy the new contract.

Aspectv1.1.0 (before)v2.0.0 (after)
OnsetDateString50String50, Required=NoRenamed to OnsetDateTimeUTC; DateTime, Required=Yes
MigrationNew DB per IC rule #13. ETL from old: parse free-text onset into DateTime where possible, set sentinel value (e.g., 0001-01-01T00:00:00Z) where unparseable. 90-day grace period: both DBs live side-by-side; reads fall back to old DB for rows not yet migrated. After grace period, old DB is archived (not deleted).
Existing rowsNullable, free-textMust have a valid DateTime; requires data remediation effort
API contractOptional string fieldRequired DateTime field; clients must update
EditAMI gateNot required for 1.1.0Required for 2.0.0 — level ≥ 90 must approve any schema break (per IC hard rule #5)

This illustrates the IC versioning contract: feature bumps (minor) are additive and backward-compatible; break bumps (major) require a new database, ETL migration, a grace period, and explicit EditAMI authorization.