Regulatory basis¶
Scope of this document
This page explains the regulatory reasoning behind the system's design. It is not legal or regulatory advice, and this system is not a medical device, not a clinical decision support product, and not in clinical use.
The design constraint that shaped the architecture¶
The 21st Century Cures Act §3060 excludes certain clinical decision support (CDS) software from the medical device definition, and the FDA's Clinical Decision Support Software guidance (September 2022) interprets it. Non-device CDS must, among other criteria, enable the user to independently review the basis for its output rather than relying primarily on it, and must not acquire, process or analyze a medical image or signal.
That criterion is why:
- every clinical claim carries a citation, and coverage is measured and
enforced in
guardrails/citation_check.pyrather than requested in a prompt (docs/architecture/decisions/D-A3-1-the-sandwich-has-two-independent-halves.md); - citations point at real public-domain pages a patient can actually open
(
docs/architecture/decisions/D-A3-4-citations-are-real-and-that-is-free.md) — a citation that cannot be independently reviewed satisfies nothing; - reference ranges are quoted rather than interpreted (
store/models.py::ReferenceRange); - the answer shows which record rows it read (
schemas/answer.py::Claim.evidence_refs); - the system directs to care rather than characterising urgency
(
guardrails/templates.py) — it never says "you are having a heart attack", it says "seek emergency care now".
Citation coverage is therefore not a quality metric here. It is a design constraint traceable to a named criterion, and being able to point at the code that enforces it is a stronger position than any amount of domain vocabulary.
HIPAA minimum necessary — 45 CFR 164.502(b)¶
The minimum-necessary standard requires limiting use, disclosure and request of protected health information to what is reasonably necessary for the purpose. Two controls implement this directly, not as a prompt instruction:
- Refusals short-circuit before retrieval. Any non-
allowpre-flight decision bindsregistry.education_only_scope(), from which every patient-scoped tool is absent (tools/registry.py,docs/architecture/decisions/D-A3-6-publication-is-deterministic-and-refusals-short-circuit.md). A refused or escalated question never reaches a patient record. - Row caps.
ScopedToolExecutorclamps everylimitargument to the scope'srow_capregardless of what the model requests (tools/scoping.py), so a run cannot pull more of the record than the scope allows.
HIPAA Safe Harbor de-identification — 45 CFR 164.514(b)¶
Safe Harbor lists 18 identifier categories that must be removed for data to be considered de-identified. This system never reaches that question in the first place: every patient record is generated by Synthea (Apache-2.0), a synthetic-patient-population simulator. There is no real or re-identifiable individual behind any record this system reads, and there is no configuration path to point it at real data.
ONC information blocking / 21st Century Cures Act Final Rule¶
The Cures Act Final Rule (45 CFR Part 171) establishes that patients are entitled to their own electronic health information without unreasonable delay or interference. This is the regulatory reason a patient-facing record-access assistant exists as a category at all — the system's base tier (record lookup, lab and medication education) is squarely inside what the rule intends patients to be able to get.
Section 1557 language access — 42 U.S.C. §18116 / 45 CFR Part 92¶
The ACA §1557 language-access requirements
require meaningful access for people with limited English proficiency. This
is why a non-English question is not silently answered badly: canonical case
16 detects the question's language (guardrails/language.py) and responds
with a stated limitation in English plus a route to the care team
(guardrails/templates.py::language_limitation_template), rather than either
guessing at a translation or refusing outright. base does not yet answer in
Spanish; that is an honest, disclosed limitation, not a silent failure, and
full language support is deferred to Stage 2 (docs/PLAN.md §7 Stretch).
The crisis path — 988 Suicide & Crisis Lifeline¶
A self-harm red flag routes to a dedicated crisis path
(guardrails/templates.py::crisis_template), distinct from the medical
emergency path in both resource and wording (docs/PLAN.md §4.4):
the 988 Suicide & Crisis Lifeline is available
24/7 by call or text, and is named explicitly rather than folded into a
generic "seek care" message.
Red-flag rules, cited rule by rule¶
Every escalation rule cites a real, public-domain patient-facing source, and
the build fails if an escalation rule is added without one
(data/generate_policy_rules.py::validate):
| Category | Rules | Source |
|---|---|---|
| Cardiac | rf-cardiac-chest-pain, rf-cardiac-radiating, rf-cardiac-associated |
MedlinePlus — Heart Attack |
| Stroke | rf-stroke-face-arm-speech, rf-stroke-sudden-neuro |
MedlinePlus — Stroke |
| Anaphylaxis | rf-anaphylaxis |
MedlinePlus — Anaphylaxis |
| Self-harm | rf-self-harm |
MedlinePlus — Suicide and Suicidal Thoughts, 988 |
The scope rules (dosing, medication change, diagnosis requests, out-of-domain questions, interaction and symptom-management questions) carry no citation, and deliberately so: they are boundaries this project set, not clinical findings, and that distinction is worth keeping visible in the table rather than dressing a design choice up as evidence.
Education-source terms, verified before the pipeline was written¶
The plan required these to be checked against the primary sources rather than assumed, because the whole citation argument above rests on them.
| Service | Terms | Rate limit |
|---|---|---|
| MedlinePlus Connect | Free; no API key, no registration. Linking to and displaying returned data is permitted; copying MedlinePlus pages is not. NLM recommends caching for 12–24 hours | 100 requests/minute per IP |
| MedlinePlus Web service | Free of charge; no registration or licensing | 85 requests/minute per IP |
| RxNav / RxNorm | Free; no licence needed. RxClass/SNOMED CT is not used, so its Affiliate licence does not apply | 20 requests/second per IP |
So the education cache is a build artifact, not a corpus: it holds only the
fields the service returns — title, URL, summary, attribution — with a retrieval
timestamp and a TTL inside NLM's recommended window. It is never committed and
the application never mirrors a MedlinePlus page. Attribution appears in
NOTICE.md, including RxNav's required verbatim statement.
The LOINC terminology table is deliberately not a dependency, so its licence agreement never applies. Synthea's observations already carry LOINC codes and MedlinePlus Connect accepts a code directly; codes pass through, the table is never downloaded or redistributed.
Two disclosures made deliberately¶
No clinician has reviewed the safety rules. Every emergency red-flag rule is derived from a published patient-facing source and cites it by URL, so no rule rests on the author's own clinical judgement. But no clinician reviewed the resulting table. Stating that plainly is the honest position; an uncited table reviewed informally would be worse than a cited one reviewed by nobody.
The reference ranges are illustrative. data/lab_reference_ranges.csv is
adult-general and cited to published sources. It is not any laboratory's own
reference intervals, and real ranges vary by assay, method, age and sex.