Skip to content

Design

Accepted Rust direction

Root Loco 1.3 with Tera/DaisyUI and PostgreSQL 18 is primary. The Rails application is archived in git history. The accepted architecture below supersedes older parity and access assumptions; implementation acceptance remains pending. Historical Rails design sections below describe the reference, not requirements to reproduce its internals.

For the current Rust role checks, administration pages, platform-only NHS dm+d importer and synthetic seed limitations, see Manage People and Household Access and the roles and importer access audit. The historical person-grant model below is not the current Rust care-authority contract.

An active minor who has no effective guardian in any household may have an eligible open local guardian link restored, or a household owner or administrator may appoint a currently eligible adult participant through the dedicated recovery journey. Each appointment creates new attributable declaration authority; withdrawn and superseded declarations remain final. Recovery confirmation uses opaque latest-history and local-link snapshots plus a reason; the link snapshot rotates on activation/deactivation. The database rechecks global authority under a subject lock. The birthday rule conservatively spans UTC−12 through UTC+14, which can delay recovery for about 26 hours near adulthood.

Purpose

MedTracker records medication schedules, direct assignments, and administrations with guardrails for timing, dose limits, and stock, while preserving attributable history inside a household authorization boundary.

Architecture

  • The backend uses Ruby on Rails.
  • The frontend uses Hotwire (Turbo and Stimulus) with Phlex components.
  • Authentication uses Rodauth accounts with password, generic OIDC and passkeys. First-party mobile OAuth credentials identify the account; each household request checks current membership and person/action permission. Restricted integration credentials retain their household and scope limits.
  • Authorisation uses household memberships plus person-scoped access grants.
  • PostgreSQL stores development, test, and production data.
  • PaperTrail change history supports security and compliance evidence.

MedTracker is a modular monolith. Domain logic is enforced on the server. UI forms and pages render server-sent HTML and use Turbo Streams for updates.

The bounded-context map defines present ownership and dependency direction for Medication Administration, Medication Catalogue, Inventory, Health and Medication Safety, People and Care Delegation, Household Access, Identity, Interoperability, Audit and Compliance, and the supporting Reporting and Insights and Notifications capabilities. These are not separate services or databases. Shared Rails models and tables may act as persistence adapters for more than one context.

Phlex components are composition roots and rendering units, not the home of core medication business rules. UI code consumes domain records, value objects, presenters, and query objects rather than reimplementing supply, filtering, authorization, or administration rules.

Core Domain Records

Record Present responsibility
Person Demographic details, care capacity, and the individual whose care data is tracked
Account and User Authentication identity and the active application user linked to a person
HouseholdMembership An account's participation and role in one household
PersonAccessGrant Authority for a membership to view, record for, or manage one person
CarerRelationship Descriptive care responsibility between two people; not authority by itself
Medication Shared catalogue, administration-default, and inventory persistence record for one medicine/product
MedicationDosageOption Shared selectable dose identity, age-based and regimen administration defaults, and optional dose-specific inventory record
Schedule Date-bounded administration source supporting scheduled types and retained PRN semantics
PersonMedication Direct routine or as-needed administration source without a schedule
MedicationTake Immutable record of one completed administration from exactly one source
HealthEvent Recorded illness or suspected side effect for a person
MedicationReviewPrompt Practitioner-review state with an immutable medication-interaction evidence snapshot

Use the Glossary as the source of truth for these terms and for the distinction between care responsibility and authority.

Medication Safety Rules

Schedule and PersonMedication expose the applicable dose and timing rules. MedicationAdministration::RecordDose checks source state, stock availability, dose amount, timing restrictions, and overlapping administration rules before creating a MedicationTake. The take stores a dose snapshot and its concrete source. Persisting a valid take mutates only the selected tracked inventory source when inventory tracking is enabled and retains the selected source on the historical record. A valid take may use untracked inventory without changing a quantity. It is the sole normal creator of dose history.

Stock choices and dose submission use the same exact identity rule. The concrete inventory row remains usable without catalogue metadata. A different row requires equal, complete NHS dm+d system, product class (VMP, AMP, VMPP or AMPP) and code, plus equal default dose amounts and an explicit, equal stock unit. Those product concepts identify medicine, formulation and strength; broader VTM, trade-family and unknown catalogue concepts cannot establish a match. The inventory portable_id identifies a stock row, not a medicinal product. The medication dose_amount is an administration default, not chemical strength. Names, descriptive dose text and unit conversions never establish a match. Catalogue class semantics follow the NHS dm+d model.

MedicationAdministration::RestoreHistory restores immutable portable history without replaying stock changes. MedicationAdministration::HistoricalDataMigration repairs only legacy household and location metadata. These explicit exceptions do not provide alternative dose-recording paths.

Important timing concepts include:

  • max_daily_doses
  • min_hours_between_doses
  • dose_cycle
  • schedule-specific effective doses and dates

Person Types and Authority

Person type models care capacity:

  • adult
  • minor
  • dependent_adult

Household membership role models tenant governance:

  • owner
  • administrator
  • member

Person access level models authority over a specific person's records:

  • view
  • record
  • manage

Relationship labels describe why access may exist. They are not substitutes for an active PersonAccessGrant. Every care assignment creates or reactivates the descriptive relationship. Only an account-backed carer receives household membership and a standalone self grant; account-backed non-self delegation also coordinates relationship-owned access. Deactivating an account-backed self relationship leaves its standalone grant active. Accountless delegation, including self delegation, has no access records, so revocation only deactivates the description. Person-scoped authority comes from active grants; medication and inventory policies also recognise household owner and administrator governance and the narrow creator-owned, unlinked medication exception.

Supporting Read Models and Delivery

Reports::* and SmartInsights::* build read-only projections and derived insights from administration, inventory, health, and safety records. They own their report calculations and detector results, not the source facts.

Notifications own person preferences, subscriptions, delivery deduplication, and push transport. Reminder and stock notification jobs consume outcomes from the contexts that own administration and inventory rules.

Auditing and Compliance

Critical model changes are versioned for traceability. Security and workflow events are recorded with household, account, membership, and request context, then projected into append-only compliance evidence. Audit records observe domain outcomes; they do not own medication, inventory, or authorization decisions. See Audit Trail.

UI and Accessibility Direction

UI behavior and styling are guided by: