Skip to content

Data Model

The HDS data model defines all health data items, their types, streams, and relationships.

  • Items — individual data points (body-weight, body-height, bleeding, medication, treatment, procedure, etc.)
  • Streams — hierarchical categories (body, fertility, medication, treatment, procedure, profile, …)
  • Event types — Pryv event type definitions with JSON schemas
  • Datasources — external data sources (medication, treatment, procedure databases)
  • number — numeric values with optional unit variations (kg/lb, m/ft)
  • select — single choice from options
  • checkbox — boolean (activity/plain events)
  • text — free text
  • date — date values
  • composite — nested object fields
  • datasource-search — search external datasources (medications, treatments, procedures)

Items registered at a parent stream (e.g. treatment-coded at treatment) can be reused under a descendant stream (treatment-fertility) by passing a context to the form section. forEvent() walks parent streams to resolve the original itemDef, keeping a single coded surface across multiple medical subdomains. See data-model/documentation/TREATMENT-PROCEDURE.md.

App-level qualifiers & context (what HDS deliberately does not model)

Section titled “App-level qualifiers & context (what HDS deliberately does not model)”

The root data model standardizes concepts that have cross-app machine-interoperability value. It does not try to encode every possible qualifier or circumstance on an observation — those are often specific to one application’s interpretation, and forcing them into the shared model would bloat it without a consumer that reads them.

Examples of app-level data: the situation of a symptom (e.g. pelvic pain graded by “on bowel movement”, “at ovulation”, “on a full bladder”), a lab draw’s sample context, or a “recorded from memory / date approximate” marker on a recalled history event. The measurement itself (ratio/* severity, pregnancy/detailed, a lab value) is modelled; the extra qualifier around it is the app’s.

Recommended pattern when your app needs to attach such data to an event:

  • clientData — for your app’s own structured use. This is the correct home precisely because HDS makes no interoperability claim about it: clientData is documented for app-owned, non-authoritative data (its one standardized use in the model is the related cross-reference to other events). Do not put root-model authoritative data here.
  • event.description — a short human-readable string (e.g. “pelvic pain, on bowel movement”, “prior miscarriage — date reported from memory”). This gives cross-app human visibility: any other HDS app, dashboard, or clinician view renders it, so the context isn’t lost even though it isn’t machine-structured.

Recalled history. Keep writing one event per occurrence (counts stay COUNT(events); do not revive deprecated aggregate-count items), set event.time to the intake date rather than a fabricated one, and mark it recalled via the pattern above. This maps cleanly to FHIR data-absent-reason: unknown on export.

When it should become root-model. The bar is a second application needing to machine-read the same qualifier across apps. At that point it graduates into the shared model — most likely as a coded circumstance axis in the event’s secondary streamIds (the tags/ mechanism), which keeps the measurement on its shared interoperability surface while adding the qualifier as a separate coded, multi-valued dimension. Until then, keep it app-level. (Background: site-agents #4.)

The compiled model is served at model.datasafe.dev.