Layman manual
Audience: clinical and terminology authors who use the tool. No coding
knowledge assumed.
plan.pdhc is the authoring service for the PDHC platform. It is where you
design the clinical building blocks that every other service later uses to
collect, store, and act on patient data. Nothing here treats a patient — it is
a design workbench. Think of it as the "master library" of the platform:
Everything you author is versioned and identified by a stable GUID, so
downstream services always reference exactly the concept you built.
Why it matters: a PlanDefinition's thresholds flow onward to request.pdhc,
which applies them and raises data-driven alerts. A wrong unit or a wrong
threshold authored here is a patient-safety issue, not a cosmetic one. The
tool is deliberately built with guardrails (see §6) for that reason.
This is the single most important modelling rule to understand as an author.
A concept carries its own canonical unit. When you say "Systolic blood
pressure is measured in mmHg", you set that unit once, on the concept. Every
goal, threshold, activity, and transaction that refers to that concept inherits
the unit from the concept — you do not (and should not) re-type the unit on each
plan.
The plan-building forms deliberately do not offer a per-transaction unit
picker. If a stray unit does end up on a transaction or a goal target that
disagrees with the concept's own unit, the validator flags it
(W-UNIT-CONTRADICTS) so it can be corrected. Set the unit on the concept and
let everything else resolve to it — that keeps a plan automatically in sync when
terminology is later updated.
The same "resolve from the concept" principle applies to code system, concept
type, response type, and bound value set: one concept GUID resolves the whole
tree, so none of it has to be duplicated into the plan.
A typical authoring flow:
canonical_lib + canonical_refnumber, e.g. LOINC 8480-6). For codedConcepts have a status (draft by default), so you can work up a draft before
it is relied upon.
Terminology authors can bulk-load concepts from a spreadsheet. An operator runs
flask import-concepts <file.xlsx|.csv> (with an optional --dry-run to
validate without committing). Rejected rows are reported with the reason, so a
large curation batch can be cleaned up before it lands.
Access is via the platform single sign-on (SSO). Your permissions come from your
SSO account, in three levels:
| Level | Who | Can do |
|---|---|---|
| read_only | any signed-in user | browse concepts, plans, value sets, forms |
| read_write | a professional whose session includes the planning phase (or a superuser) | create/edit/delete concepts, plans, value sets, forms; use the authoring assistant |
| admin | a platform superuser | everything, including forcing a save past validation errors (audited) |
You always see the freshest version of your permissions: the tool re-checks your
session with SSO on every request, so if your access is changed or revoked
centrally it takes effect immediately — there is no stale cached copy of your
rights.
If SSO asks you to change your password, the tool sends you to the SSO
change-password page before letting you continue.
Everything you author is also published, live, as a standards-based FHIR R5
terminology service at /api/v1/. You do not have to operate this — it is how
other systems read the library you build — but it is useful to know it exists:
$expand — hand a system your value set and it returns the full$validate-code — check whether a given code is a legal answer in$lookup — look up one of your local concepts and get its$translate — translate between your local concept and itsThe practical benefit for you: the moment you curate a concept or a value set,
downstream services see the change through these operations — you are the single
source of truth for platform terminology.
plan.pdhc includes an opt-in guided-authoring assistant designed so that
someone who is not a terminology specialist can still build a correct plan. It
is two distinct layers:
A fixed set of rules, identical for every author and every path, that catches the
mistakes a novice makes. Examples of what it flags:
E-UNIT-REQUIRED)E-VALUESET-REQUIRED)E-RESPONSE-TYPE-UNKNOWN)E-DANGLING-REF)E-RANGE-INVERTED)Each issue comes back with a plain-language message telling you what is wrong.
When fail-closed enforcement is switched on, an error-level issue blocks the
save; warnings always inform but never block. (An admin can force a save past
errors, and that override is written to the audit log.)
When enabled and configured, you can describe what you want in plain language
("resting systolic blood pressure, adult") and the assistant proposes a complete,
correct concept: the right response type, unit, terminology code, and any answer
set — and it searches for an existing concept first so you don't re-create
one that already exists. It then runs the Layer-1 checker on its own proposal and
shows you the result, so it can never quietly hand you something invalid.
Important properties:
There is also a "Check openEHR export" helper that asks rosetta.pdhc whether your
concept set can be exported to openEHR, degrading quietly if that service isn't
configured.
https://plan.pdhc.seFor the API surface, deployment, and configuration, see technical.md.