mirror of
https://github.com/Crosstalk-Solutions/project-nomad.git
synced 2026-10-16 21:00:03 +02:00
* feat(drug-reference): offline FDA drug labels, conditions, and remedies
Adds an offline medical-reference feature with three coupled layers:
- Drug Reference: full-text search over openFDA drug-label indications,
a detail page per label, and a side-by-side single-drug comparison view.
A two-phase background pipeline downloads the openFDA label parts to the
storage volume (resumable) and ingests them into the search table.
- Conditions ("When to use what"): a curated spine of first-aid situations
that maps each situation to matching OTC drugs, each linking back to its
Drug Reference detail page.
- Curated remedies: hand-authored natural and home-remedy entries drawn from
US-government public-domain sources (NCCIH, CDC, MedlinePlus, FDA), shown
with their source links and the same safety disclaimers as the rest of the
feature.
The drug-reference and conditions layers are intentionally coupled: the drug
detail page shows the situations a drug treats, and the conditions controller
reads the same drug_labels table.
Safety surfaces ship as written. The amber SafetyBanner ("informational only,
not medical advice, not an FDA endorsement, not a drug-interaction checker, in
an emergency call emergency services") renders on the condition pages and the
search page; the detail and comparison pages carry their own "not a cross-drug
interaction checker" callout; and every page carries the openFDA CC0 source
citation and no-FDA-affiliation footer.
Wiring on this branch:
- start/routes.ts: the /drug-reference and /conditions page GETs plus their
/api/* groups.
- commands/queue/work.ts: the drug-download and drug-ingest queues, both at
concurrency 1. The two drug queues get a per-queue stall override
(lockDuration 1_800_000, maxStalledCount 3) because each part is one long
stream; every other queue keeps the existing 300000 default.
- inertia/pages/home.tsx: Drug Reference and "When to use what" tiles. The
icon and display_order are a starting point, open to change.
- types/kv_store.ts: the two drugReference.* keys the pipeline reads and writes.
- package.json: yauzl and stream-json (plus their @types), used by the ingest
job to stream the label JSON out of the downloaded zips.
The app reads the conditions and remedy data from the compiled TS constants in
app/data/; the repo-root collections/*.json files are the browseable mirrors.
The natural-remedies standalone test reads collections/natural_remedies.json to
assert the two stay in sync, so that file is also a test fixture.
The four standalone tests pass (drug_interactions, drug_ingest_status,
conditions, natural_remedies). tsc reports no errors in the feature code.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* chore(drug-reference): drop a fork-internal comment reference
* fix(drug-reference): address review — defer FULLTEXT, fallback remedies prop, strip fork refs
- migration: wrap the FULLTEXT ALTER in this.defer so it runs after the
deferred createTable (was silently swallowed, index never created)
- controller: add remedies:[] to the index() error fallback (required prop)
- strip fork-internal issue/spec references from ported comments
- tsconfig: exclude tests/standalone (node --experimental-strip-types only)
- correct the varchar(768) byte-math comment; extend remedy-spine test
* fix(drug-reference): make the interaction comparison readable at five drugs
The comparison view laid its columns out on an equal-fraction CSS grid
(repeat(N, minmax(0, 1fr))), so each added drug shrank every column; at the
five-drug maximum the FDA interaction text was squeezed into unreadable slivers.
Lay the columns out with flex instead: full-width and stacked on phones, then
fixed-width columns that scroll sideways from the sm: breakpoint up, so they
never shrink below a readable width. Theme the columns with the same palette as
the rest of the page (they were on stock gray), and give the headers a fixed
min-height so columns line up when drug names wrap.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* feat(collections): route a 'dataset' tier resource to the drug pipeline
Add an optional `type` discriminator to SpecResource ('zim' | 'dataset',
absent == 'zim'), so the tier installer can carry a DB-ingested resource
alongside ZIM files. ZimService.downloadCategoryTier branches on it: a
'dataset' resource dispatches the existing FDA download+ingest pipeline
instead of RunDownloadJob, guarded against duplicate dispatch by the drug
ingest status. Every existing manifest entry has no `type` and keeps the
exact ZIM path.
Widen InstalledResource.resource_type to include 'dataset' and exclude
dataset rows from the ZIM/map catalog-update scan (datasets aren't
filename-versioned; their freshness path is separate). No dataset rows are
written yet: the InstalledResource 'dataset' row on ingest-ready, the
manifest entry, install-gating, and the downloads-aggregator integration
are follow-up commits.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* feat(drug-reference): rework into an opt-in medicine-standard tier dataset
Reshapes the offline FDA drug reference from a built-in feature into curated
content installed by selecting the Medicine / Standard tier, per maintainer
direction.
- install-state: the ingest writes an installed_resources 'dataset' row on
ready (version = the openFDA export_date), threaded installer to download to
ingest; the tier-status math and the home-tile gate read it. Manual ingests
write no row, so install-state stays tied to the curated path.
- manifest: declare the dataset in the medicine-standard tier (runtime fetches
the remote manifest, so this also needs to land upstream).
- install-gating: the drug-reference home tiles render only when installed.
- uninstall: DrugReferenceService.uninstall() stops the two drug queues, deletes
the on-disk parts, truncates drug_labels (schema kept), clears the KV markers,
and drops the install row. Best-effort, logged, scoped to drug data only.
- downloads: the download phase reports the canonical {percent, downloadedBytes,
totalBytes} shape as one drug-data card in the Active Downloads aggregator with
cancel/remove; the heavy ingest stays in the IngestStatus surface with an
Indexing handoff on the card.
- auto-update: a daily DrugAutoUpdateJob compares the manifest export_date and
re-downloads when newer, gated on installed + no active job.
typecheck clean; the drug standalone suites pass. Three points are flagged in
code for the maintainer: the InstalledResource 'dataset' approach, the tier
home, and the export_date string format.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(downloads): keep the drug download card live across all parts
The Active Downloads card filtered to the deterministic jobId, but the
download's continuations run under auto-generated jobIds (only part 0 uses the
deterministic one). So the card tracked part 0 and then vanished while parts
2..N kept downloading. The queue is concurrency 1, so collapse to whichever
single part is in flight and report the deterministic jobId: one card tracks
aggregate progress through the whole download and cancel/remove still routes.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* feat(drug-reference): co-locate a persistent safety note with affirmative remedy guidance
Add RemedySafetyNote at the head of every natural-remedy section — the two on
Drug Reference and the one on "When to use what" — so the "informational only,
not medical advice, seek real medical care in an emergency" framing appears with
the guidance itself, not only in the page-top banner. Replaces the terse
per-section caveat with the same amber alert language as SafetyBanner.
Addresses the upstream #1040 review request that the disclaimer be unmistakable
and present wherever affirmative self-care guidance appears, not a one-time banner.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(drug-reference): fold dataset freshness into the content-auto-update path
The drug dataset auto-updated on its own daily cron that ignored the
contentAutoUpdate.* master switch, so it would refresh even with content
auto-update turned off, and it didn't ride the content-update path the way
ZIMs and maps do.
Move the export_date freshness/apply orchestration onto
DrugReferenceService.attemptAutoUpdate(), add
ContentAutoUpdateService.attemptDrugDataset() gated on the same enabled +
window config, and have the hourly ContentAutoUpdateJob drive both. Retire
the standalone DrugAutoUpdateJob. The ZIM/map attempt() path is unchanged.
Addresses the upstream #1040 request to wire the openFDA export_date check
into the content updater so the dataset updates alongside ZIMs and maps.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* feat(drug-reference): strengthen the remedy note to consult a clinician before combining with meds
Widen the affirmative-remedy safety note from "talk to a clinician before use"
to explicitly cover using a remedy AND combining one with a medication the user
already takes — the interaction case is the higher-risk path for an off-grid
user self-treating.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* feat(drug-reference): gate affirmative remedy content behind an off-by-default flag
Add drugReference.remediesEnabled (default off), independent of the tier
install. When off, the server emits no remedy data at any boundary — the
drug-reference page prop, conditions show, and the /api/conditions/drugs
situation search — and the "Natural" filter is hidden, so installing the
medicine-standard tier lights up the verbatim FDA label search and the
condition-to-OTC matching but not the hand-authored self-care and herbal
sections. No user-facing toggle: it is flipped on after a clinician content-pass.
Implements the upstream #1040 split-by-risk request: the regulated label content
ships with the tier; the authored remedy guidance stays gated until sign-off.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Jake Turner <52841588+jakeaturner@users.noreply.github.com>
427 lines
9.2 KiB
JSON
427 lines
9.2 KiB
JSON
{
|
||
"version": "2026-06-07",
|
||
"conditions": [
|
||
{
|
||
"slug": "pain",
|
||
"label": "Pain",
|
||
"category": "Pain, fever & inflammation",
|
||
"searchTerms": [
|
||
"pain",
|
||
"aches",
|
||
"minor aches",
|
||
"pain relief",
|
||
"analgesic"
|
||
]
|
||
},
|
||
{
|
||
"slug": "headache",
|
||
"label": "Headache",
|
||
"category": "Pain, fever & inflammation",
|
||
"searchTerms": [
|
||
"headache",
|
||
"migraine",
|
||
"head pain",
|
||
"tension headache"
|
||
]
|
||
},
|
||
{
|
||
"slug": "muscle-joint-pain",
|
||
"label": "Muscle & joint pain",
|
||
"category": "Pain, fever & inflammation",
|
||
"searchTerms": [
|
||
"muscular aches",
|
||
"muscle aches",
|
||
"backache",
|
||
"arthritis",
|
||
"joint pain",
|
||
"minor pain of arthritis"
|
||
]
|
||
},
|
||
{
|
||
"slug": "fever",
|
||
"label": "Fever",
|
||
"category": "Pain, fever & inflammation",
|
||
"searchTerms": [
|
||
"fever",
|
||
"reduces fever",
|
||
"fever reducer",
|
||
"temporarily reduces fever"
|
||
]
|
||
},
|
||
{
|
||
"slug": "menstrual-cramps",
|
||
"label": "Menstrual cramps",
|
||
"category": "Pain, fever & inflammation",
|
||
"searchTerms": [
|
||
"menstrual cramps",
|
||
"menstrual pain",
|
||
"period pain",
|
||
"premenstrual"
|
||
]
|
||
},
|
||
{
|
||
"slug": "cough",
|
||
"label": "Cough",
|
||
"category": "Cold, cough & allergy",
|
||
"searchTerms": [
|
||
"cough",
|
||
"cough suppressant",
|
||
"coughing",
|
||
"controls cough"
|
||
]
|
||
},
|
||
{
|
||
"slug": "nasal-congestion",
|
||
"label": "Nasal congestion",
|
||
"category": "Cold, cough & allergy",
|
||
"searchTerms": [
|
||
"nasal congestion",
|
||
"stuffy nose",
|
||
"sinus congestion",
|
||
"decongestant",
|
||
"nasal decongestant"
|
||
]
|
||
},
|
||
{
|
||
"slug": "sore-throat",
|
||
"label": "Sore throat",
|
||
"category": "Cold, cough & allergy",
|
||
"searchTerms": [
|
||
"sore throat",
|
||
"sore mouth",
|
||
"minor sore throat",
|
||
"throat pain"
|
||
]
|
||
},
|
||
{
|
||
"slug": "common-cold",
|
||
"label": "Common cold",
|
||
"category": "Cold, cough & allergy",
|
||
"searchTerms": [
|
||
"common cold",
|
||
"cold symptoms",
|
||
"cold",
|
||
"flu symptoms"
|
||
]
|
||
},
|
||
{
|
||
"slug": "allergic-reaction",
|
||
"label": "Allergies & allergic reactions",
|
||
"category": "Cold, cough & allergy",
|
||
"searchTerms": [
|
||
"allergy",
|
||
"allergic reactions",
|
||
"hay fever",
|
||
"antihistamine",
|
||
"runny nose",
|
||
"sneezing",
|
||
"itchy watery eyes"
|
||
]
|
||
},
|
||
{
|
||
"slug": "heartburn",
|
||
"label": "Heartburn",
|
||
"category": "Stomach & digestion",
|
||
"searchTerms": [
|
||
"heartburn",
|
||
"acid indigestion",
|
||
"acid reducer",
|
||
"antacid",
|
||
"sour stomach"
|
||
]
|
||
},
|
||
{
|
||
"slug": "indigestion",
|
||
"label": "Indigestion & upset stomach",
|
||
"category": "Stomach & digestion",
|
||
"searchTerms": [
|
||
"indigestion",
|
||
"upset stomach",
|
||
"gas",
|
||
"bloating",
|
||
"fullness",
|
||
"antacid"
|
||
]
|
||
},
|
||
{
|
||
"slug": "nausea-vomiting",
|
||
"label": "Nausea & vomiting",
|
||
"category": "Stomach & digestion",
|
||
"searchTerms": [
|
||
"nausea",
|
||
"vomiting",
|
||
"upset stomach associated with nausea"
|
||
]
|
||
},
|
||
{
|
||
"slug": "diarrhea",
|
||
"label": "Diarrhea",
|
||
"category": "Stomach & digestion",
|
||
"searchTerms": [
|
||
"diarrhea",
|
||
"antidiarrheal",
|
||
"loose stools",
|
||
"traveler’s diarrhea"
|
||
]
|
||
},
|
||
{
|
||
"slug": "constipation",
|
||
"label": "Constipation",
|
||
"category": "Stomach & digestion",
|
||
"searchTerms": [
|
||
"constipation",
|
||
"laxative",
|
||
"irregularity",
|
||
"occasional constipation",
|
||
"stool softener"
|
||
]
|
||
},
|
||
{
|
||
"slug": "motion-sickness",
|
||
"label": "Motion sickness",
|
||
"category": "Stomach & digestion",
|
||
"searchTerms": [
|
||
"motion sickness",
|
||
"travel sickness",
|
||
"seasickness",
|
||
"car sickness"
|
||
]
|
||
},
|
||
{
|
||
"slug": "gas",
|
||
"label": "Gas & bloating",
|
||
"category": "Stomach & digestion",
|
||
"searchTerms": [
|
||
"gas",
|
||
"bloating",
|
||
"flatulence",
|
||
"antigas",
|
||
"pressure"
|
||
]
|
||
},
|
||
{
|
||
"slug": "wounds-cuts",
|
||
"label": "Wounds & cuts",
|
||
"category": "Skin & wounds",
|
||
"searchTerms": [
|
||
"minor cuts",
|
||
"scrapes",
|
||
"wounds",
|
||
"first aid antiseptic",
|
||
"first aid to help prevent infection",
|
||
"abrasions"
|
||
]
|
||
},
|
||
{
|
||
"slug": "burns",
|
||
"label": "Burns",
|
||
"category": "Skin & wounds",
|
||
"searchTerms": [
|
||
"burns",
|
||
"minor burns",
|
||
"sunburn",
|
||
"scald",
|
||
"minor burn"
|
||
]
|
||
},
|
||
{
|
||
"slug": "insect-bites-stings",
|
||
"label": "Insect bites & stings",
|
||
"category": "Skin & wounds",
|
||
"searchTerms": [
|
||
"insect bites",
|
||
"insect stings",
|
||
"bug bites",
|
||
"bee sting",
|
||
"itching from insect bites"
|
||
]
|
||
},
|
||
{
|
||
"slug": "skin-rash-itch",
|
||
"label": "Rash & itching",
|
||
"category": "Skin & wounds",
|
||
"searchTerms": [
|
||
"itching",
|
||
"rash",
|
||
"skin irritation",
|
||
"itchy skin",
|
||
"minor skin irritations",
|
||
"eczema"
|
||
]
|
||
},
|
||
{
|
||
"slug": "poison-ivy",
|
||
"label": "Poison ivy & plant rashes",
|
||
"category": "Skin & wounds",
|
||
"searchTerms": [
|
||
"poison ivy",
|
||
"poison oak",
|
||
"poison sumac",
|
||
"rashes due to poison ivy"
|
||
]
|
||
},
|
||
{
|
||
"slug": "fungal-infection",
|
||
"label": "Athlete’s foot & ringworm",
|
||
"category": "Skin & wounds",
|
||
"searchTerms": [
|
||
"athlete’s foot",
|
||
"ringworm",
|
||
"jock itch",
|
||
"antifungal",
|
||
"fungal infection",
|
||
"tinea"
|
||
]
|
||
},
|
||
{
|
||
"slug": "dry-skin",
|
||
"label": "Dry & chapped skin",
|
||
"category": "Skin & wounds",
|
||
"searchTerms": [
|
||
"dry skin",
|
||
"chapped skin",
|
||
"chapped lips",
|
||
"skin protectant",
|
||
"cracked skin"
|
||
]
|
||
},
|
||
{
|
||
"slug": "acne",
|
||
"label": "Acne",
|
||
"category": "Skin & wounds",
|
||
"searchTerms": [
|
||
"acne",
|
||
"pimples",
|
||
"blackheads",
|
||
"acne treatment"
|
||
]
|
||
},
|
||
{
|
||
"slug": "eye-irritation",
|
||
"label": "Eye irritation & dryness",
|
||
"category": "Eyes, ears & mouth",
|
||
"searchTerms": [
|
||
"eye irritation",
|
||
"dry eyes",
|
||
"red eyes",
|
||
"eye redness",
|
||
"itchy eyes",
|
||
"lubricant eye"
|
||
]
|
||
},
|
||
{
|
||
"slug": "earache",
|
||
"label": "Earache & ear wax",
|
||
"category": "Eyes, ears & mouth",
|
||
"searchTerms": [
|
||
"earache",
|
||
"ear wax",
|
||
"earwax removal",
|
||
"ear pain",
|
||
"swimmer’s ear"
|
||
]
|
||
},
|
||
{
|
||
"slug": "canker-sores",
|
||
"label": "Canker & cold sores",
|
||
"category": "Eyes, ears & mouth",
|
||
"searchTerms": [
|
||
"canker sores",
|
||
"cold sores",
|
||
"mouth sores",
|
||
"fever blisters",
|
||
"oral pain"
|
||
]
|
||
},
|
||
{
|
||
"slug": "toothache",
|
||
"label": "Toothache",
|
||
"category": "Eyes, ears & mouth",
|
||
"searchTerms": [
|
||
"toothache",
|
||
"tooth pain",
|
||
"dental pain",
|
||
"oral analgesic"
|
||
]
|
||
},
|
||
{
|
||
"slug": "sleeplessness",
|
||
"label": "Sleeplessness",
|
||
"category": "Sleep, stress & general",
|
||
"searchTerms": [
|
||
"sleeplessness",
|
||
"insomnia",
|
||
"sleep aid",
|
||
"difficulty falling asleep",
|
||
"nighttime"
|
||
]
|
||
},
|
||
{
|
||
"slug": "dehydration",
|
||
"label": "Dehydration",
|
||
"category": "Sleep, stress & general",
|
||
"searchTerms": [
|
||
"dehydration",
|
||
"oral rehydration",
|
||
"electrolyte",
|
||
"fluid loss",
|
||
"replaces electrolytes"
|
||
]
|
||
},
|
||
{
|
||
"slug": "hemorrhoids",
|
||
"label": "Hemorrhoids",
|
||
"category": "Sleep, stress & general",
|
||
"searchTerms": [
|
||
"hemorrhoids",
|
||
"hemorrhoidal",
|
||
"anal itching",
|
||
"rectal"
|
||
]
|
||
},
|
||
{
|
||
"slug": "yeast-infection",
|
||
"label": "Vaginal yeast infection",
|
||
"category": "Infections (OTC-treatable)",
|
||
"searchTerms": [
|
||
"vaginal yeast infection",
|
||
"yeast infection",
|
||
"vaginal antifungal",
|
||
"candidiasis"
|
||
]
|
||
},
|
||
{
|
||
"slug": "pinworm",
|
||
"label": "Pinworm",
|
||
"category": "Infections (OTC-treatable)",
|
||
"searchTerms": [
|
||
"pinworm",
|
||
"pinworm infection",
|
||
"pinworm treatment"
|
||
]
|
||
},
|
||
{
|
||
"slug": "cold-sore-lip",
|
||
"label": "Chapped & sun-protected lips",
|
||
"category": "Sleep, stress & general",
|
||
"searchTerms": [
|
||
"lip protectant",
|
||
"chapped lips",
|
||
"sunburn protection lips",
|
||
"lip balm"
|
||
]
|
||
},
|
||
{
|
||
"slug": "eye-allergy",
|
||
"label": "Eye allergies",
|
||
"category": "Eyes, ears & mouth",
|
||
"searchTerms": [
|
||
"eye allergy",
|
||
"itchy eyes due to allergies",
|
||
"ocular itching",
|
||
"allergic conjunctivitis"
|
||
]
|
||
}
|
||
]
|
||
}
|