PMR Deep Exemplar
Patient Medical Records — 29 Noun-App AMI Schemas
Reference · Deep ExemplarThe 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
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.
| Field | Type | Required | PK | FK | Notes |
|---|---|---|---|---|---|
PrimaryProviderID | Guid | No | → Provider | Global FK; assigned PCP | |
PreferredPharmacyID | Guid | No | → Pharmacy | Global FK; default pharmacy | |
PatientID | Guid | Yes | ✓ | Primary key | |
PatientFirstNameString100 | String100 | Yes | Legal first name | ||
PatientLastNameString100 | String100 | Yes | Legal last name | ||
PatientDateOfBirthDateTimeUTC | DateTime | Yes | Date of birth | ||
PatientGenderCodeString50 | String50 | Yes | Administrative gender code | ||
PatientRaceCodeString50 | String50 | No | OMB race category code | ||
PatientEthnicityCodeString50 | String50 | No | OMB ethnicity code | ||
PatientPreferredLanguageString50 | String50 | No | ISO 639-1 language code | ||
PatientPatientSlugString200 | String200 | Yes | Opaque rotatable slug for patient portal URLs | ||
PatientSourceOrganizationID | Guid | Yes | Source org that created this row | ||
UpdatedDateTimeUTC | DateTime | Yes | Audit — last write timestamp | ||
UpdatedByUserID | Guid | Yes | → User | Audit — who last wrote | |
DeletedDateTimeUTC | DateTime | No | Audit — 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.
| Field | Type | Required | PK | FK | Notes |
|---|---|---|---|---|---|
PracticeID | Guid | No | → Practice | Global FK; primary practice affiliation | |
ProviderID | Guid | Yes | ✓ | Primary key | |
ProviderFirstNameString100 | String100 | Yes | Provider first name | ||
ProviderLastNameString100 | String100 | Yes | Provider last name | ||
ProviderNpiString50 | String50 | Yes | National Provider Identifier (10-digit) | ||
ProviderDeaNumberString50 | String50 | No | DEA registration number (for prescribers) | ||
ProviderSpecialtyCodeString50 | String50 | No | NPI taxonomy / specialty code | ||
ProviderSourceOrganizationID | Guid | Yes | Source org that created this row | ||
UpdatedDateTimeUTC | DateTime | Yes | Audit — last write timestamp | ||
UpdatedByUserID | Guid | Yes | → User | Audit — who last wrote | |
DeletedDateTimeUTC | DateTime | No | Audit — 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.
| Field | Type | Required | PK | FK | Notes |
|---|---|---|---|---|---|
PracticeID | Guid | Yes | ✓ | Primary key; also serves as OrganizationID in org-scoped tables | |
PracticePracticeNameString100 | String100 | Yes | Legal practice name | ||
PracticeTaxIdString50 | String50 | Yes | EIN / Tax ID | ||
PracticeNpiString50 | String50 | No | Organization NPI (Type 2) | ||
PracticeIsActiveBool | Bool | Yes | Practice is currently active | ||
PracticeSourceOrganizationID | Guid | Yes | Source org that created this row | ||
UpdatedDateTimeUTC | DateTime | Yes | Audit — last write timestamp | ||
UpdatedByUserID | Guid | Yes | → User | Audit — who last wrote | |
DeletedDateTimeUTC | DateTime | No | Audit — 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.
| Field | Type | Required | PK | FK | Notes |
|---|---|---|---|---|---|
PharmacyID | Guid | Yes | ✓ | Primary key | |
PharmacyPharmacyNameString100 | String100 | Yes | Pharmacy display name | ||
PharmacyNcpdpIdString50 | String50 | Yes | NCPDP Provider ID (7-digit) | ||
PharmacyPhoneNumberString50 | String50 | No | Phone number | ||
PharmacyAddressLine1String200 | String200 | No | Street address | ||
PharmacyCityString100 | String100 | No | City | ||
PharmacyStateCodeString50 | String50 | No | Two-letter US state code | ||
PharmacyZipCodeString50 | String50 | No | ZIP code | ||
PharmacySourceOrganizationID | Guid | Yes | Source org that created this row | ||
UpdatedDateTimeUTC | DateTime | Yes | Audit — last write timestamp | ||
UpdatedByUserID | Guid | Yes | → User | Audit — who last wrote | |
DeletedDateTimeUTC | DateTime | No | Audit — 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).
| Field | Type | Required | PK | FK | Notes |
|---|---|---|---|---|---|
SpecialtyID | Guid | Yes | ✓ | Primary key | |
SpecialtySpecialtyNameString100 | String100 | Yes | Display name (e.g., “Cardiology”) | ||
SpecialtySpecialtyCodeString50 | String50 | Yes | NPI taxonomy code | ||
SpecialtySourceOrganizationID | Guid | Yes | Source org that created this row | ||
UpdatedDateTimeUTC | DateTime | Yes | Audit — last write timestamp | ||
UpdatedByUserID | Guid | Yes | → User | Audit — who last wrote | |
DeletedDateTimeUTC | DateTime | No | Audit — 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.
| Field | Type | Required | PK | FK | Notes |
|---|---|---|---|---|---|
PatientID | Guid | Yes | → Patient | Global FK; patient seen | |
ProviderID | Guid | Yes | → Provider | Global FK; attending provider | |
EncounterID | Guid | Yes | ✓ | Primary key | |
EncounterLocationIDString50 | String50 | No | Room or location identifier | ||
EncounterEncounterDateTimeUTC | DateTime | Yes | Scheduled or actual encounter datetime | ||
EncounterEncounterTypeString50 | String50 | Yes | Office / Telehealth / Urgent / Procedure / Well-visit | ||
EncounterStatusString50 | String50 | Yes | Scheduled / In-progress / Completed / Cancelled / No-show | ||
EncounterReasonString200 | String200 | No | Chief complaint or visit reason | ||
OrganizationID | Guid | Yes | Audit — Cosmos partition key (org-scoped) | ||
UpdatedDateTimeUTC | DateTime | Yes | Audit — last write timestamp | ||
UpdatedByUserID | Guid | Yes | → User | Audit — who last wrote | |
DeletedDateTimeUTC | DateTime | No | Audit — 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.
| Field | Type | Required | PK | FK | Notes |
|---|---|---|---|---|---|
PatientID | Guid | Yes | → Patient | Global FK; patient who has the allergy | |
SourceInboundID | Guid | No | → ExternalInbound | FK to the inbound payload that contributed this allergy; null if manually entered | |
AllergyID | Guid | Yes | ✓ | Primary key | |
AllergyAllergenCodeString50 | String50 | Yes | RxNorm / SNOMED code for the allergen | ||
AllergyAllergenNameString100 | String100 | Yes | Display name of the allergen | ||
AllergyAllergenTypeString50 | String50 | Yes | Drug / Food / Environment / Biologic | ||
AllergyReactionString200 | String200 | No | Observed reaction (e.g., “rash”, “anaphylaxis”) | ||
AllergySeverityString50 | String50 | No | Mild / Moderate / Severe | ||
AllergyOnsetDateString50 | String50 | No | Approximate onset date or year | ||
AllergyVerificationStatusString50 | String50 | Yes | Unconfirmed / Confirmed / Refuted / Entered-in-error | ||
AllergySourceOrganizationID | Guid | Yes | Source org that contributed this clinical fact (deliberate exception to IC rule #11) | ||
UpdatedDateTimeUTC | DateTime | Yes | Audit — last write timestamp | ||
UpdatedByUserID | Guid | Yes | → User | Audit — who last wrote | |
DeletedDateTimeUTC | DateTime | No | Audit — 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.
| Field | Type | Required | PK | FK | Notes |
|---|---|---|---|---|---|
PatientID | Guid | Yes | → Patient | Global FK; patient on the medication | |
PrescribingProviderID | Guid | No | → Provider | Global FK; prescribing provider | |
SourceInboundID | Guid | No | → ExternalInbound | FK to inbound payload; null if manually entered | |
MedicationID | Guid | Yes | ✓ | Primary key | |
MedicationMedicationCodeString50 | String50 | Yes | RxNorm RxCUI | ||
MedicationMedicationNameString100 | String100 | Yes | Display name of the medication | ||
MedicationDoseString50 | String50 | No | Dose and unit (e.g., “10 mg”) | ||
MedicationRouteString50 | String50 | No | Route of administration (e.g., “oral”) | ||
MedicationFrequencyString50 | String50 | No | Dosing frequency (e.g., “BID”) | ||
MedicationStartDateDateTimeUTC | DateTime | No | Start date of therapy | ||
MedicationEndDateDateTimeUTC | DateTime | No | End date (null if active) | ||
MedicationStatusString50 | String50 | Yes | Active / Completed / Stopped / On-hold | ||
MedicationSourceOrganizationID | Guid | Yes | Source org that contributed this clinical fact (deliberate exception to IC rule #11) | ||
UpdatedDateTimeUTC | DateTime | Yes | Audit — last write timestamp | ||
UpdatedByUserID | Guid | Yes | → User | Audit — who last wrote | |
DeletedDateTimeUTC | DateTime | No | Audit — 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.
| Field | Type | Required | PK | FK | Notes |
|---|---|---|---|---|---|
PatientID | Guid | Yes | → Patient | Global FK; patient with the condition | |
SourceInboundID | Guid | No | → ExternalInbound | FK to inbound payload; null if manually entered | |
ConditionID | Guid | Yes | ✓ | Primary key | |
ConditionIcd10CodeString50 | String50 | Yes | ICD-10-CM code | ||
ConditionConditionNameString100 | String100 | Yes | Display name of the condition | ||
ConditionConditionCategoryString50 | String50 | No | Problem-list-item / Health-concern / Encounter-diagnosis | ||
ConditionClinicalStatusString50 | String50 | Yes | Active / Recurrence / Relapse / Inactive / Remission / Resolved | ||
ConditionVerificationStatusString50 | String50 | Yes | Unconfirmed / Confirmed / Refuted / Entered-in-error | ||
ConditionOnsetDateTimeUTC | DateTime | No | Estimated onset datetime | ||
ConditionAbatementDateTimeUTC | DateTime | No | When the condition resolved (null if active) | ||
ConditionSourceOrganizationID | Guid | Yes | Source org that contributed this clinical fact (deliberate exception to IC rule #11) | ||
UpdatedDateTimeUTC | DateTime | Yes | Audit — last write timestamp | ||
UpdatedByUserID | Guid | Yes | → User | Audit — who last wrote | |
DeletedDateTimeUTC | DateTime | No | Audit — 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.
| Field | Type | Required | PK | FK | Notes |
|---|---|---|---|---|---|
PatientID | Guid | Yes | → Patient | Global FK; patient who underwent surgery | |
SurgeonProviderID | Guid | No | → Provider | Global FK; surgeon | |
SourceInboundID | Guid | No | → ExternalInbound | FK to inbound payload; null if manually entered | |
SurgeryID | Guid | Yes | ✓ | Primary key | |
SurgeryProcedureCodeString50 | String50 | Yes | CPT or ICD-10-PCS procedure code | ||
SurgeryProcedureNameString100 | String100 | Yes | Display name of the procedure | ||
SurgerySurgeryDateTimeUTC | DateTime | Yes | Date/time of the surgery | ||
SurgeryFacilityNameString100 | String100 | No | Facility where surgery was performed | ||
SurgeryOutcomeString200 | String200 | No | Outcome summary | ||
SurgerySourceOrganizationID | Guid | Yes | Source org that contributed this clinical fact (deliberate exception to IC rule #11) | ||
UpdatedDateTimeUTC | DateTime | Yes | Audit — last write timestamp | ||
UpdatedByUserID | Guid | Yes | → User | Audit — who last wrote | |
DeletedDateTimeUTC | DateTime | No | Audit — 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.
| Field | Type | Required | PK | FK | Notes |
|---|---|---|---|---|---|
PatientID | Guid | Yes | → Patient | Global FK; patient whose family history this is | |
FamilyHistoryID | Guid | Yes | ✓ | Primary key | |
FamilyHistoryRelativeTypeCodeString50 | String50 | Yes | SNOMED code for the relative (FTH, MTH, SIS, etc.) | ||
FamilyHistoryConditionCodeString50 | String50 | Yes | SNOMED / ICD-10 code for the relative’s condition | ||
FamilyHistoryConditionNameString100 | String100 | Yes | Display name of the condition | ||
FamilyHistoryAgeAtOnsetInt | Int | No | Age of relative at condition onset | ||
FamilyHistoryIsDeceasedBool | Bool | No | Whether the relative is deceased | ||
FamilyHistorySourceOrganizationID | Guid | Yes | Source org that contributed this clinical fact (deliberate exception to IC rule #11) | ||
UpdatedDateTimeUTC | DateTime | Yes | Audit — last write timestamp | ||
UpdatedByUserID | Guid | Yes | → User | Audit — who last wrote | |
DeletedDateTimeUTC | DateTime | No | Audit — 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.
| Field | Type | Required | PK | FK | Notes |
|---|---|---|---|---|---|
PatientID | Guid | Yes | → Patient | Global FK; patient measured | |
EncounterID | Guid | No | → Encounter | FK to encounter; null for home entry | |
RecordedByUserID | Guid | Yes | → User | Global FK; who recorded the vital | |
VitalID | Guid | Yes | ✓ | Primary key | |
VitalVitalTypeString50 | String50 | Yes | BP-systolic / BP-diastolic / HR / Temp / Weight / Height / SpO2 / BMI | ||
VitalValueDecimal | Decimal | Yes | Numeric value | ||
VitalUnitString50 | String50 | Yes | Unit of measure (e.g., “mmHg”, “kg”) | ||
VitalRecordedDateTimeUTC | DateTime | Yes | When the vital was recorded | ||
VitalSourceOrganizationID | Guid | Yes | Source org that contributed this clinical fact (deliberate exception to IC rule #11) | ||
UpdatedDateTimeUTC | DateTime | Yes | Audit — last write timestamp | ||
UpdatedByUserID | Guid | Yes | → User | Audit — who last wrote | |
DeletedDateTimeUTC | DateTime | No | Audit — 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.
| Field | Type | Required | PK | FK | Notes |
|---|---|---|---|---|---|
PatientID | Guid | Yes | → Patient | Global FK; patient tested | |
OrderID | Guid | No | → Order | FK to the originating order | |
SourceInboundID | Guid | No | → ExternalInbound | FK to inbound payload; null if manually entered | |
LabResultID | Guid | Yes | ✓ | Primary key | |
LabResultTestCodeString50 | String50 | Yes | LOINC code for the test | ||
LabResultTestNameString100 | String100 | Yes | Display name of the test | ||
LabResultResultValueString200 | String200 | Yes | Result value (string to accommodate qualitative results) | ||
LabResultReferenceRangeString200 | String200 | No | Normal reference range | ||
LabResultAbnormalFlagString50 | String50 | No | Normal / Abnormal / Critical | ||
LabResultResultDateTimeUTC | DateTime | Yes | When the result was finalized | ||
LabResultPerformingLabString100 | String100 | No | Name of the performing laboratory | ||
LabResultSourceOrganizationID | Guid | Yes | Source org that contributed this clinical fact (deliberate exception to IC rule #11) | ||
UpdatedDateTimeUTC | DateTime | Yes | Audit — last write timestamp | ||
UpdatedByUserID | Guid | Yes | → User | Audit — who last wrote | |
DeletedDateTimeUTC | DateTime | No | Audit — 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.
| Field | Type | Required | PK | FK | Notes |
|---|---|---|---|---|---|
PatientID | Guid | Yes | → Patient | Global FK; patient imaged | |
OrderID | Guid | No | → Order | FK to the originating order | |
SourceInboundID | Guid | No | → ExternalInbound | FK to inbound payload; null if manually entered | |
ImagingID | Guid | Yes | ✓ | Primary key | |
ImagingModalityString50 | String50 | Yes | CT / MRI / X-ray / Ultrasound / PET | ||
ImagingBodyPartString100 | String100 | Yes | Body part examined | ||
ImagingStudyDateTimeUTC | DateTime | Yes | Date/time of the imaging study | ||
ImagingReportText | Text | No | Radiology report narrative | ||
ImagingFindingString200 | String200 | No | Key finding summary | ||
ImagingSourceOrganizationID | Guid | Yes | Source org that contributed this clinical fact (deliberate exception to IC rule #11) | ||
UpdatedDateTimeUTC | DateTime | Yes | Audit — last write timestamp | ||
UpdatedByUserID | Guid | Yes | → User | Audit — who last wrote | |
DeletedDateTimeUTC | DateTime | No | Audit — 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.
| Field | Type | Required | PK | FK | Notes |
|---|---|---|---|---|---|
PatientID | Guid | Yes | → Patient | Global FK; patient for whom the order is placed | |
OrderingProviderID | Guid | Yes | → Provider | Global FK; ordering provider | |
OrderID | Guid | Yes | ✓ | Primary key | |
OrderOrderTypeString50 | String50 | Yes | Lab / Imaging / Referral / Procedure | ||
OrderOrderCodeString50 | String50 | Yes | CPT / LOINC / HCPCS code | ||
OrderOrderNameString100 | String100 | Yes | Display name of the order | ||
OrderStatusString50 | String50 | Yes | Draft / Ordered / In-progress / Completed / Cancelled | ||
OrderPriorityString50 | String50 | No | Routine / Urgent / STAT | ||
OrderOrderedDateTimeUTC | DateTime | Yes | When the order was placed | ||
OrganizationID | Guid | Yes | Audit — Cosmos partition key (org-scoped) | ||
UpdatedDateTimeUTC | DateTime | Yes | Audit — last write timestamp | ||
UpdatedByUserID | Guid | Yes | → User | Audit — who last wrote | |
DeletedDateTimeUTC | DateTime | No | Audit — 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.
| Field | Type | Required | PK | FK | Notes |
|---|---|---|---|---|---|
PatientID | Guid | Yes | → Patient | Global FK; patient immunized | |
AdministeredByUserID | Guid | No | → User | Global FK; who administered | |
SourceInboundID | Guid | No | → ExternalInbound | FK to inbound payload; null if manually entered | |
ImmunizationID | Guid | Yes | ✓ | Primary key | |
ImmunizationVaccineCodeString50 | String50 | Yes | CVX code for the vaccine | ||
ImmunizationVaccineNameString100 | String100 | Yes | Display name of the vaccine | ||
ImmunizationAdministeredDateTimeUTC | DateTime | Yes | Date/time the vaccine was administered | ||
ImmunizationLotNumberString50 | String50 | No | Lot number of the vaccine | ||
ImmunizationManufacturerString100 | String100 | No | Vaccine manufacturer | ||
ImmunizationSiteString50 | String50 | No | Administration site (e.g., “left deltoid”) | ||
ImmunizationSourceOrganizationID | Guid | Yes | Source org that contributed this clinical fact (deliberate exception to IC rule #11) | ||
UpdatedDateTimeUTC | DateTime | Yes | Audit — last write timestamp | ||
UpdatedByUserID | Guid | Yes | → User | Audit — who last wrote | |
DeletedDateTimeUTC | DateTime | No | Audit — 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.
| Field | Type | Required | PK | FK | Notes |
|---|---|---|---|---|---|
PatientID | Guid | Yes | → Patient | Global FK; patient on the care plan | |
CarePlanID | Guid | Yes | ✓ | Primary key | |
CarePlanPlanTitleString100 | String100 | Yes | Human-readable plan title (e.g., “T2D Management”) | ||
CarePlanPlanCategoryString50 | String50 | Yes | Category (e.g., “Chronic-disease”, “Preventive”, “Post-surgical”) | ||
CarePlanStatusString50 | String50 | Yes | Active / Completed / Suspended / Entered-in-error | ||
CarePlanCreatedDateTimeUTC | DateTime | Yes | When the care plan was created | ||
CarePlanSourceOrganizationID | Guid | Yes | Source org that contributed this clinical fact (deliberate exception to IC rule #11) | ||
UpdatedDateTimeUTC | DateTime | Yes | Audit — last write timestamp | ||
UpdatedByUserID | Guid | Yes | → User | Audit — who last wrote | |
DeletedDateTimeUTC | DateTime | No | Audit — 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.
| Field | Type | Required | PK | FK | Notes |
|---|---|---|---|---|---|
PatientID | Guid | Yes | → Patient | Global FK; patient due for screening | |
RuleVersionID | Guid | Yes | → RuleVersion | FK to the rule version that generated this screening | |
ScreeningID | Guid | Yes | ✓ | Primary key | |
ScreeningScreeningTypeString50 | String50 | Yes | Type (e.g., “Mammogram”, “Colonoscopy”, “A1C”) | ||
ScreeningScreeningCodeString50 | String50 | Yes | Code for the screening (CPT / LOINC / HCPCS) | ||
ScreeningStatusString50 | String50 | Yes | Due / Scheduled / Completed / Overdue / Cancelled | ||
ScreeningDueDateTimeUTC | DateTime | Yes | When the screening is due | ||
ScreeningCompletedDateTimeUTC | DateTime | No | When the screening was completed (null if not yet done) | ||
ScreeningResultString200 | String200 | No | Screening result summary | ||
ScreeningSourceOrganizationID | Guid | Yes | Source org that contributed this clinical fact (deliberate exception to IC rule #11) | ||
UpdatedDateTimeUTC | DateTime | Yes | Audit — last write timestamp | ||
UpdatedByUserID | Guid | Yes | → User | Audit — who last wrote | |
DeletedDateTimeUTC | DateTime | No | Audit — 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.
| Field | Type | Required | PK | FK | Notes |
|---|---|---|---|---|---|
PatientID | Guid | Yes | → Patient | Global FK; patient to remind | |
ReminderID | Guid | Yes | ✓ | Primary key | |
ReminderCarePlanTaskIDString50 | String50 | Yes | Reference to the CarePlanTask this reminder is for | ||
ReminderOffsetCodeString50 | String50 | Yes | Traceability label: T-30 / T-14 / T-3 / T-day / T+3 / T+14 — not used for scheduling | ||
ReminderScheduledSendDateTimeUTC | DateTime | Yes | The actual moment to send; dispatcher queries on this | ||
ReminderChannelCodeString50 | String50 | Yes | sms / email / portal / workqueue | ||
ReminderStatusCodeString50 | String50 | Yes | scheduled / sent / delivered / failed / cancelled / superseded | ||
ReminderIsSentBool | Bool | Yes | Whether the reminder has been sent | ||
ReminderSentDateTimeUTC | DateTime | No | When the reminder was sent (null until sent) | ||
ReminderResponseCodeString50 | String50 | No | confirmed / declined / rescheduled / none | ||
ReminderResponseDateTimeUTC | DateTime | No | When the patient responded (null until response) | ||
OrganizationID | Guid | Yes | Audit — Cosmos partition key (org-scoped) | ||
UpdatedDateTimeUTC | DateTime | Yes | Audit — last write timestamp | ||
UpdatedByUserID | Guid | Yes | → User | Audit — who last wrote | |
DeletedDateTimeUTC | DateTime | No | Audit — 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.
| Field | Type | Required | PK | FK | Notes |
|---|---|---|---|---|---|
PatientID | Guid | Yes | → Patient | Global FK; patient the document is about | |
EncounterID | Guid | No | → Encounter | FK to encounter; null for non-encounter documents | |
AuthorUserID | Guid | Yes | → User | Global FK; author of the document | |
SourceInboundID | Guid | No | → ExternalInbound | FK to inbound payload; null if authored in-system | |
DocumentID | Guid | Yes | ✓ | Primary key | |
DocumentDocumentTypeString50 | String50 | Yes | Note / Letter / Report / Summary / Consent | ||
DocumentTitleString100 | String100 | Yes | Document title | ||
DocumentContentText | Text | Yes | Document body content | ||
DocumentCreatedDateTimeUTC | DateTime | Yes | When the document was created | ||
DocumentSourceOrganizationID | Guid | Yes | Source org that contributed this clinical fact (deliberate exception to IC rule #11) | ||
UpdatedDateTimeUTC | DateTime | Yes | Audit — last write timestamp | ||
UpdatedByUserID | Guid | Yes | → User | Audit — who last wrote | |
DeletedDateTimeUTC | DateTime | No | Audit — 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.
| Field | Type | Required | PK | FK | Notes |
|---|---|---|---|---|---|
PatientID | Guid | Yes | → Patient | Global FK; patient referred | |
FromProviderID | Guid | Yes | → Provider | Global FK; referring provider | |
ToProviderID | Guid | No | → Provider | Global FK; target specialist | |
ToOrganizationID | Guid | No | → Organization | FK to target organization (external practice) | |
ReferralID | Guid | Yes | ✓ | Primary key | |
ReferralReferralReasonString200 | String200 | Yes | Reason for referral | ||
ReferralClinicalSummaryText | Text | No | Clinical summary for the receiving provider | ||
ReferralUrgencyString50 | String50 | No | Routine / Urgent / STAT | ||
ReferralStatusString50 | String50 | Yes | Draft / Sent / Accepted / Rejected / Completed / Cancelled | ||
ReferralReferralTypeString50 | String50 | No | Internal / External | ||
ReferralNpiTargetString50 | String50 | No | NPI of the target specialist | ||
ReferralDirectAddressString200 | String200 | No | Direct address for secure messaging | ||
ReferralFhirServiceRequestIDString50 | String50 | No | FHIR ServiceRequest resource ID for interop | ||
OrganizationID | Guid | Yes | Audit — Cosmos partition key (org-scoped) | ||
UpdatedDateTimeUTC | DateTime | Yes | Audit — last write timestamp | ||
UpdatedByUserID | Guid | Yes | → User | Audit — who last wrote | |
DeletedDateTimeUTC | DateTime | No | Audit — 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.
| Field | Type | Required | PK | FK | Notes |
|---|---|---|---|---|---|
PatientID | Guid | Yes | → Patient | Global FK; patient the message is about | |
FromUserID | Guid | Yes | → User | Global FK; sender | |
ToUserID | Guid | Yes | → User | Global FK; recipient | |
MessageID | Guid | Yes | ✓ | Primary key | |
MessageSubjectString100 | String100 | Yes | Message subject | ||
MessageBodyText | Text | Yes | Message body | ||
MessageMessageDirectionString50 | String50 | Yes | Inbound / Outbound | ||
MessageIsReadBool | Bool | Yes | Whether the recipient has read the message | ||
OrganizationID | Guid | Yes | Audit — Cosmos partition key (org-scoped) | ||
UpdatedDateTimeUTC | DateTime | Yes | Audit — last write timestamp | ||
UpdatedByUserID | Guid | Yes | → User | Audit — who last wrote | |
DeletedDateTimeUTC | DateTime | No | Audit — 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.
| Field | Type | Required | PK | FK | Notes |
|---|---|---|---|---|---|
PatientID | Guid | Yes | → Patient | Global FK; patient the payload is about | |
SourceSystemID | Guid | Yes | → ExternalSourceSystem | FK to the source system that sent this payload | |
ExternalInboundID | Guid | Yes | ✓ | Primary key | |
ExternalInboundPayloadFormatString50 | String50 | Yes | HL7v2 / FHIR-R4 / CCDA / X12 / FaxOCR / PartnerJSON | ||
ExternalInboundRawPayloadText | Text | Yes | Raw inbound payload (encrypted at rest) | ||
ExternalInboundReceivedDateTimeUTC | DateTime | Yes | When the payload was received | ||
ExternalInboundMappingVersionString50 | String50 | Yes | Version of the mapping applied | ||
ExternalInboundIsAppliedBool | Bool | Yes | Whether the mapping has been applied to clinical noun apps | ||
OrganizationID | Guid | Yes | Audit — Cosmos partition key (org-scoped) | ||
UpdatedDateTimeUTC | DateTime | Yes | Audit — last write timestamp | ||
UpdatedByUserID | Guid | Yes | → User | Audit — who last wrote | |
DeletedDateTimeUTC | DateTime | No | Audit — 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.
| Field | Type | Required | PK | FK | Notes |
|---|---|---|---|---|---|
PatientID | Guid | Yes | → Patient | Global FK; patient the payload is about | |
RecipientID | Guid | Yes | → ExternalRecipient | FK to the recipient | |
ExternalOutboundID | Guid | Yes | ✓ | Primary key | |
ExternalOutboundPayloadFormatString50 | String50 | Yes | FHIR-US-Core / CCDA / X12 / PartnerJSON | ||
ExternalOutboundRenderedPayloadText | Text | Yes | Rendered outbound payload (encrypted at rest) | ||
ExternalOutboundSentDateTimeUTC | DateTime | Yes | When the payload was sent | ||
ExternalOutboundRedactionAppliedBool | Bool | Yes | Whether any redactions were applied (42 CFR Part 2, sensitive classes) | ||
OrganizationID | Guid | Yes | Audit — Cosmos partition key (org-scoped) | ||
UpdatedDateTimeUTC | DateTime | Yes | Audit — last write timestamp | ||
UpdatedByUserID | Guid | Yes | → User | Audit — who last wrote | |
DeletedDateTimeUTC | DateTime | No | Audit — 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.
| Field | Type | Required | PK | FK | Notes |
|---|---|---|---|---|---|
ExternalSourceSystemID | Guid | Yes | ✓ | Primary key | |
ExternalSourceSystemSystemNameString100 | String100 | Yes | Display name of the source system | ||
ExternalSourceSystemSystemTypeString50 | String50 | Yes | EHR / Lab / HIE / Pharmacy / Hospital / Payer | ||
ExternalSourceSystemEndpointUrlString200 | String200 | Yes | Endpoint URL for the source system | ||
ExternalSourceSystemIsActiveBool | Bool | Yes | Whether the source system is active | ||
OrganizationID | Guid | Yes | Audit — Cosmos partition key (org-scoped) | ||
UpdatedDateTimeUTC | DateTime | Yes | Audit — last write timestamp | ||
UpdatedByUserID | Guid | Yes | → User | Audit — who last wrote | |
DeletedDateTimeUTC | DateTime | No | Audit — 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.
| Field | Type | Required | PK | FK | Notes |
|---|---|---|---|---|---|
ExternalRecipientID | Guid | Yes | ✓ | Primary key | |
ExternalRecipientRecipientNameString100 | String100 | Yes | Display name of the recipient | ||
ExternalRecipientRecipientTypeString50 | String50 | Yes | Specialist / Hospital / Payer / HIE / Pharmacy | ||
ExternalRecipientDirectAddressString200 | String200 | No | Direct secure messaging address | ||
ExternalRecipientEndpointUrlString200 | String200 | Yes | Endpoint URL for the recipient | ||
ExternalRecipientIsActiveBool | Bool | Yes | Whether the recipient is active | ||
OrganizationID | Guid | Yes | Audit — Cosmos partition key (org-scoped) | ||
UpdatedDateTimeUTC | DateTime | Yes | Audit — last write timestamp | ||
UpdatedByUserID | Guid | Yes | → User | Audit — who last wrote | |
DeletedDateTimeUTC | DateTime | No | Audit — 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.
| Field | Type | Required | PK | FK | Notes |
|---|---|---|---|---|---|
RuleVersionID | Guid | Yes | ✓ | Primary key | |
RuleVersionRuleNameString100 | String100 | Yes | Human-readable rule name (e.g., “USPSTF Mammogram 2024”) | ||
RuleVersionRuleCategoryString50 | String50 | Yes | Screening / Chronic-mgmt / Preventive / Post-surgical | ||
RuleVersionVersionString50 | String50 | Yes | Semver version (e.g., “1.2.0”) | ||
RuleVersionEffectiveDateTimeUTC | DateTime | Yes | When this rule version becomes effective | ||
RuleVersionIsActiveBool | Bool | Yes | Whether this rule version is currently active | ||
OrganizationID | Guid | Yes | Audit — Cosmos partition key (org-scoped) | ||
UpdatedDateTimeUTC | DateTime | Yes | Audit — last write timestamp | ||
UpdatedByUserID | Guid | Yes | → User | Audit — who last wrote | |
DeletedDateTimeUTC | DateTime | No | Audit — 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.
| Field | Type | Required | PK | FK | Notes |
|---|---|---|---|---|---|
PracticeID | Guid | No | → Practice | Global FK; primary practice affiliation | |
UserID | Guid | Yes | ✓ | Primary key | |
UserEmailString200 | String200 | Yes | Login email address | ||
UserDisplayNameString100 | String100 | Yes | Display name for the user | ||
UserRoleCodeString50 | String50 | Yes | Role code (physician / nurse / front-desk / admin / lab-tech / billing / system) | ||
UserIsActiveBool | Bool | Yes | Whether the user account is active | ||
UserSourceOrganizationID | Guid | Yes | Source org that created this row | ||
UpdatedDateTimeUTC | DateTime | Yes | Audit — last write timestamp | ||
UpdatedByUserID | Guid | Yes | → User | Audit — who last wrote | |
DeletedDateTimeUTC | DateTime | No | Audit — 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.
| Field | Type | Required | PK | FK | Notes |
|---|---|---|---|---|---|
UserID | Guid | Yes | → User | Global FK; who performed the action | |
AuditLogID | Guid | Yes | ✓ | Primary key | |
AuditLogEntityNameString100 | String100 | Yes | Name of the noun-app entity touched (e.g., “Allergy”, “Patient”) | ||
AuditLogEntityIDString50 | String50 | Yes | Guid of the specific row touched | ||
AuditLogActionString50 | String50 | Yes | Read / Create / Update / SoftDelete | ||
AuditLogActionDateTimeUTC | DateTime | Yes | When the action occurred | ||
AuditLogAuthorizationChainText | Text | Yes | Traceable authorization chain for the action | ||
OrganizationID | Guid | Yes | Audit — Cosmos partition key (org-scoped) | ||
UpdatedDateTimeUTC | DateTime | Yes | Audit — last write timestamp | ||
UpdatedByUserID | Guid | Yes | → User | Audit — who last wrote | |
DeletedDateTimeUTC | DateTime | No | Audit — 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
| Tier | Source | Treated as | Typical entities |
|---|---|---|---|
| Tier 0 | Unverified inbound | Provisional — not yet reviewed or mapped | ExternalInbound rows before mapping; raw patient self-report before clinician review |
| Tier 1 | Patient-attested | Working knowledge — clinician confirmation required for high-stakes fields | Patient portal contributions, patient-verified imported data |
| Tier 2 | Clinician-attested in-system | Confirmed — a credentialed user created or reviewed this in rev.health | Encounters, manually entered allergies, clinician-authored documents |
| Tier 3 | Verified by source-of-truth | Authoritative — verified by an external authoritative source | Lab feeds, pharmacy fill records, immunization registries, signed radiology reports, NCPDP directory |
(e) Conflict handling rules
- Both rows preserved. When patient says X and a pharmacy fill says Y, both rows remain in the patient’s record. We never destroy the prior value.
- Reconciliation card lands in coordinator queue. A reconciliation card is created and placed in the care coordinator’s queue. The dashboard alert lane surfaces the conflict until a clinician resolves it.
- Superseded rows are marked with reason. When a clinician resolves a conflict by choosing one value over another, the superseded row is marked with a reason code — it is not soft-deleted.
DeletedDateTimeUTCstays null; the row remains visible for audit. - Patient corrections never silently overwrite clinician-attested data. A patient “❌ this is wrong” on a clinician-attested or hospital-attested fact goes to reconciliation, not to direct edit.
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.
| Role | Level | Scope | Notes |
|---|---|---|---|
| Patient | 1 | Read on rows where PatientID = self, scoped to patient.rev.health | Verification answers create ExternalInbound rows with SourceSystem = “patient-self”. Cannot see fields flagged “do-not-release.” |
| Front desk | 51 on Patient demographics + Encounter intake; 0 on clinical | Column-scoped write on demographic and scheduling fields only | No access to clinical narrative, labs, medications, or allergies. |
| Medical assistant | 51 on Vital, Immunization, Encounter (intake); 1 read elsewhere | Write on intake-level clinical data; read-only on other clinical | Cannot sign Rx or edit problem list. |
| Nurse / Care coordinator | 51 write on most clinical noun apps; 80 on Reminder config | Write on clinical facts for assigned patients; manage reminder cadence | Cannot sign Rx. Break-glass for non-assigned patients with reason + audit. |
| Physician | 51–80 on all clinical noun apps; 90 EditAMI | Full clinical write for paneled patients; schema break authority | Break-glass for non-panel patients with reason + audit. EditAMI is an org-level grant only. |
| Lab tech | 51 on LabResult, Order status; 1 on Patient | Write on lab and order status; read-only on patient demographics for matching | No access to clinical narrative. |
| Billing | 1 on Encounter, Patient insurance + demographics; 0 on clinical narrative | Read-only on billing-relevant fields | No access to clinical notes, lab results, or allergy list. |
| Referring specialist (external) | Time-boxed token-scoped read | Read on a specific Document or Imaging row; write back via ExternalInbound | Token expires; no broader grant. |
| Practice admin | 100 on User, Practice, RuleVersion; 0 on clinical unless dual role | Full admin on operational config; no clinical access by default | Separation of duty. Must be granted a separate clinical role for clinical access. |
| System / code-gen / standardizer | Service principal | Writes to ExternalInbound / ExternalOutbound; proposes patches against clinical noun apps | All 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.
| Field | Type | Required | PK | FK | Notes |
|---|---|---|---|---|---|
ReminderID | Guid | Yes | → Reminder | FK to the parent reminder | |
ReminderAttemptID | Guid | Yes | ✓ | Primary key | |
ReminderAttemptAttemptDateTimeUTC | DateTime | Yes | When this attempt was made | ||
ReminderAttemptChannelCodeString50 | String50 | Yes | sms / email / portal / workqueue | ||
ReminderAttemptIsSuccessBool | Bool | Yes | Whether the attempt succeeded | ||
ReminderAttemptProviderResponseCodeString50 | String50 | No | Response code from the channel provider (e.g., Twilio SID, SMTP response) | ||
ReminderAttemptErrorMessageString200 | String200 | No | Error message if the attempt failed | ||
OrganizationID | Guid | Yes | Audit — Cosmos partition key (org-scoped) | ||
UpdatedDateTimeUTC | DateTime | Yes | Audit — last write timestamp | ||
UpdatedByUserID | Guid | Yes | → User | Audit — who last wrote | |
DeletedDateTimeUTC | DateTime | No | Audit — 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:
| Offset | Meaning | Purpose |
|---|---|---|
T-30 | 30 days before due | Early nudge; schedule appointment |
T-14 | 14 days before due | Follow-up nudge if no action |
T-3 | 3 days before due | Urgent reminder; act now |
T-day | Day of due date | Day-of reminder |
T+3 | 3 days after due | Overdue notice |
T+14 | 14 days after due | No-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:
- Marks prior
Reminderrows for that task withStatusCode = “superseded”. - Keeps superseded rows for audit —
DeletedDateTimeUTCstays null. - 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.
| Aspect | v1.0.0 (before) | v1.1.0 (after) |
|---|---|---|
| New field | — | OnsetDateString50 (String50, Required=No) |
| Migration | — | Backward-compatible ALTER TABLE ADD COLUMN; no new DB needed. Existing rows have OnsetDateString = null. |
| Existing rows | Unaffected | Continue to function; OnsetDateString50 is nullable |
| API contract | No change | New 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.
| Aspect | v1.1.0 (before) | v2.0.0 (after) |
|---|---|---|
OnsetDateString50 | String50, Required=No | Renamed to OnsetDateTimeUTC; DateTime, Required=Yes |
| Migration | — | New 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 rows | Nullable, free-text | Must have a valid DateTime; requires data remediation effort |
| API contract | Optional string field | Required DateTime field; clients must update |
| EditAMI gate | Not required for 1.1.0 | Required 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.