From de6c43e84c0ebfeec314618636fc23c77248e8e1 Mon Sep 17 00:00:00 2001 From: Taleef Date: Thu, 16 Jul 2026 18:50:45 -0400 Subject: [PATCH] docs(webchart): record live teatea runbook findings; fix import zip_code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Executed the teatea trial runbook end-to-end as System Owner. Two outcomes: - Client registration (runbook §§2-3) is MIE-gated: the login_trusts registry is behind the superuser-only JWT screen; WebChart "superuser" is neither the SuperUser role nor the Manage Login Trusts ACL (both set, still gated) but an MIE-issued session unlock; RFC 7591 is off; Application-Entities is DICOM not OAuth. Recorded the finding + sharpened MIE ask in the runbook §3 and the #254 answer log; §5 live evaluation is blocked behind it. - Seed contract verified live: teatea's Chart Data CSV API requires patients.zip_code (12345/12345-6789) on every row (the cause of the first validate run's 451 issues); partition MR + all patients.* columns validate. generate-webchart-import.ts now emits a synthetic demo ZIP. Docs + generator tooling only; no runtime, schema, dependency, PHI, or Outcome Status change (ADR-008). Typecheck green. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../scripts/generate-webchart-import.ts | 24 +++++--- docs/JOURNAL.md | 26 +++++++++ docs/MIE_INTEGRATION_QUESTIONS_2026-07-09.md | 21 +++++++ docs/WEBCHART_TEATEA_RUNBOOK_2026-07-16.md | 57 +++++++++++++++++++ 4 files changed, 121 insertions(+), 7 deletions(-) diff --git a/backend-ts/scripts/generate-webchart-import.ts b/backend-ts/scripts/generate-webchart-import.ts index 5d13a2c6..ef3e53f8 100644 --- a/backend-ts/scripts/generate-webchart-import.ts +++ b/backend-ts/scripts/generate-webchart-import.ts @@ -6,7 +6,7 @@ * * Emits MIE's documented Data-Migration CSV formats (verified from the `mieweb/docs` sources, * 2026-07-16 — see the generated README for source URLs and upload order): - * 01-patients.csv Chart Data CSV API (demographics; `patients.*` + `@patient_mrns.MR` headers) + * 01-patients.csv Chart Data CSV API (demographics; `patients.*` + `@patient_mrns.MR`; zip_code required) * 02-encounters.csv Clinical Encounter CSV API (office visits — the eCQM qualifying-visit IPP gate) * 03-observations.csv Observation Import (18 fixed columns; labs + vitals) * 04-injections.csv Injections CSV API (immunizations; CVX in `injections.inject_code`) @@ -192,10 +192,19 @@ function isValidDate(s: string): boolean { // emitters // --------------------------------------------------------------------------- +// A single synthetic demo ZIP for the whole cohort (Elkhart, IN — MIE's home area; clearly demo, never +// PHI). The teatea trial's Chart Data CSV API validates `patients.zip_code` against a `12345`/`12345-6789` +// regex on EVERY row and rejects the header when it is absent — verified live 2026-07-16 (the exact error +// was "Patient zip code must be formatted either 12345-6789 or 12345"; `@patient_mrns.MR` and all other +// `patients.*` columns validated). See docs/WEBCHART_TEATEA_RUNBOOK_2026-07-16.md §4. +const DEMO_ZIP = "46514"; + function patientsCsv(people: Person[]): string { - const header = "@patient_mrns.MR,patients.first_name,patients.last_name,patients.birth_date,patients.sex,patients.email"; + const header = + "@patient_mrns.MR,patients.first_name,patients.last_name,patients.birth_date,patients.sex," + + "patients.zip_code,patients.email"; const lines = people.map((p) => - row([p.mrn, p.first, p.last, `${p.birthDate} 00:00:00`, p.sex, `${p.mrn.toLowerCase()}@workwell-demo.dev`]), + row([p.mrn, p.first, p.last, `${p.birthDate} 00:00:00`, p.sex, DEMO_ZIP, `${p.mrn.toLowerCase()}@workwell-demo.dev`]), ); return [header, ...lines].join("\n") + "\n"; } @@ -308,11 +317,12 @@ Generated by \`pnpm generate:webchart-import\` (WorkWell). **Synthetic data — Tick **Verbose** on the upload form the first time; a failed-rows file can be downloaded, fixed, and re-uploaded. **Test with 2–3 rows first** (MIE's own best-practice note). -## Caveats (verify on first upload; formats sourced from the mieweb/docs repo 2026-07-16) +## Caveats (verified live against teatea 2026-07-16 via the Data-Import "Validate File" dry-run) -- \`patients.sex\` follows the documented \`patients.\` header pattern but its exact header - string was not byte-verified — if the importer rejects it, check the "Sample Demographics File" - tab of MIE's Chart Data CSV spec sheet and rename. +- **\`patients.zip_code\` is REQUIRED** and validated \`12345\`/\`12345-6789\` on every row — omitting it + fails the header ("does not match full list") AND every data row. The generator now emits a synthetic + demo ZIP. \`@patient_mrns.MR\` (partition \`MR\` — confirmed present in teatea's partition list) and all + other \`patients.*\` columns (incl. \`first_name\`/\`last_name\`/\`birth_date\`/\`sex\`/\`email\`) validated. - \`part:MR\` as \`pat_id_type\` (encounters/injections) is inferred from the documented \`part:\` id-type prefix. If rejected, re-run the failed rows with \`id:pat_id\` after looking up the chart ids, or add \`patients.extern_id1\` to 01 and use \`id:ext_id\`. diff --git a/docs/JOURNAL.md b/docs/JOURNAL.md index a34b7c44..0c16f165 100644 --- a/docs/JOURNAL.md +++ b/docs/JOURNAL.md @@ -1,5 +1,31 @@ # Journal +## 2026-07-16 — teatea runbook executed live: registration is MIE-gated, seed contract verified + +Ran the teatea trial runbook (`WEBCHART_TEATEA_RUNBOOK_2026-07-16.md`) end-to-end as System Owner. +Two decisive outcomes: + +**§§2–3 (client registration + auth probe) are blocked on MIE — proven, not assumed.** The SMART +Backend Services client registry is the `login_trusts` table, reachable only via the **superuser**-gated +JWT / Login-Trusts screen. WebChart "superuser" is **not** the SuperUser security role and **not** the +`Manage Login Trusts` ACL — both were set and the screen still returned "Super user access required"; +superuser is an MIE-issued session unlock (master password) held by MIE's internal accounts. **RFC 7591 +is off** (`/register` + `/oauth/register` return the login HTML; no `registration_endpoint`), and the +Application-Entities editor is DICOM, not an OAuth registry. A second independent research pass over the +public `mieweb/docs` sources reached the same conclusion. The sharpened MIE ask (register `workwell-backend` +with our hosted JWKS, or grant superuser + the FHIR App Editor) is now recorded in the runbook §3 and the +#254 answer log. §5 (live evaluation) is blocked behind this — nothing to read until a client exists. + +**§4 (synthetic seeding) contract verified live and the generator fixed.** teatea's Data Import → +Chart Data CSV "Validate File" dry-run established the real contract: **`patients.zip_code` is required** +(`12345`/`12345-6789`) on every row (the sole cause of the first run's 451 validation issues), partition +`MR` is valid, and all `patients.*` demographic columns validate. `scripts/generate-webchart-import.ts` +now emits a synthetic demo ZIP; typecheck green. The seed is ready to upload, but its payoff — a live FHIR +read-back — still waits on the registration above, so the actual upload + `pnpm evaluate:webchart-live` +run are deferred until MIE unblocks auth (no point seeding a population we can't yet read over FHIR). +Keypair (§1) generated and kept in `~\.workwell\` (never committed). Docs-only change here; no runtime, +schema, dependency, PHI, or Outcome Status behavior touched (ADR-008). + ## 2026-07-16 — MIE manager outage: bounded, method-safe deploy retries The WebChart stack's final deploy exposed a pre-existing failure mode in diff --git a/docs/MIE_INTEGRATION_QUESTIONS_2026-07-09.md b/docs/MIE_INTEGRATION_QUESTIONS_2026-07-09.md index 13430a99..a3f55aa8 100644 --- a/docs/MIE_INTEGRATION_QUESTIONS_2026-07-09.md +++ b/docs/MIE_INTEGRATION_QUESTIONS_2026-07-09.md @@ -227,6 +227,27 @@ what does its contract look like? confirm backend-services support on the sandbox. Details: `INTEGRATION_RESEARCH_2026-07-13.md` §1.1a. Meanwhile the transport itself is already rebuilt to the verified contract (E12 PR-2c branch; ADR-028) — only credentials stand between us and a live sandbox evaluation. +- **2026-07-16 (teatea trial — live owner walkthrough; runbook §§1–5 executed).** Ran the teatea + runbook end-to-end as System Owner. Findings: + - **A3 residual is confirmed MIE-gated (not self-serviceable on the trial).** Client registration + lives in the `login_trusts` table, reachable only via the **superuser**-gated JWT / Login-Trusts + screen. WebChart "superuser" is **not** the SuperUser security role and **not** the + `Manage Login Trusts` ACL — both were set and the screen still returned "Super user access + required." Superuser is an **MIE-issued session unlock (master password)**, held by MIE's internal + accounts only. **RFC 7591 is OFF** (`/register` + `/oauth/register` return the login HTML; no + `registration_endpoint` advertised). The Application-Entities editor is DICOM, not an OAuth + registry. **⇒ The sharpened A3 ask stands and is now unavoidable:** *MIE must either register the + `workwell-backend` backend-services client (JWKS we host) or grant our System Owner the superuser + unlock + FHIR App Editor.* Exact ask text: `WEBCHART_TEATEA_RUNBOOK_2026-07-16.md` §3 "MIE ask." + §3 auth probe + §5 live evaluation are **blocked on this** (nothing to probe/read until a client + exists). **A2/A4/A5 (pagination / rate-limit / observation representation) remain pending the live + read** — they'll be recorded the moment MIE unblocks registration. + - **B12 / seeding contract — verified live (unblocks §4 independently of auth).** teatea's Data + Import → **Chart Data CSV API** requires a well-formed **`patients.zip_code`** (`12345`/`12345-6789`) + on every row; partition **`MR`** is valid; all `patients.*` demographic columns validate. The import + generator (`pnpm generate:webchart-import`) was corrected to emit the ZIP. Observation Import keys on + observation **name**, not LOINC (as documented). So synthetic seeding is ready to run — but its payoff + (a live FHIR read-back) still waits on the A3 registration above. - **2026-07-16 (Doug meeting 2026-07-15 + teatea trial probe):** **A1 CONFIRMED** (FHIR R4 is the surface), **A3 CONFIRMED** (SMART; registration is manual + self-serviceable on the trial via `webchart.cgi?f=admin&s=jwt`), **C13 ANSWERED** (trial instance `teatea.webchartnow.com`, System diff --git a/docs/WEBCHART_TEATEA_RUNBOOK_2026-07-16.md b/docs/WEBCHART_TEATEA_RUNBOOK_2026-07-16.md index 1a4e99f9..b6795f7f 100644 --- a/docs/WEBCHART_TEATEA_RUNBOOK_2026-07-16.md +++ b/docs/WEBCHART_TEATEA_RUNBOOK_2026-07-16.md @@ -19,6 +19,25 @@ Verified facts this runbook builds on (probed 2026-07-16): - Client registration is manual, at the admin **JWT screen**: `…/webchart.cgi?f=admin&s=jwt` (it is the smart-configuration's `management_endpoint`) +> **⚠ Live-execution finding (2026-07-16) — §§2–3 are blocked on MIE; do NOT expect to self-serve.** +> A full browser walkthrough as System Owner established that client registration is **MIE-controlled**, +> not owner-serviceable on this trial (independently corroborated by a second research pass over the +> public `mieweb/docs` sources). Concretely, all of these were tried and failed: +> - `?f=admin&s=jwt` and `?f=admin&subfunc=login_trusts` → **"Super user access required."** +> - WebChart **"superuser" is NOT the "SuperUser" security role** and NOT the `Manage Login Trusts` +> ACL. Setting the account to the SuperUser role (security_role_id 12) and granting the ACL still +> gated. Per MIE docs, the Login Trusts editor lives under **"Control Panel → SuperUser"**, and +> superuser is a **session elevation requiring an MIE-issued master/unlock password** — held by +> MIE's internal accounts only (in the seeded dev DB the superuser accounts are `mie`/`cronjobs`, +> not any customer role). +> - **RFC 7591 dynamic registration is OFF**: `POST …/webchart.cgi/register` and `…/oauth/register` +> both return the HTML login shell (not JSON); smart-configuration advertises no `registration_endpoint`. +> - The **Application Entities editor is DICOM** (AE-titles), not an OAuth/FHIR client registry — dead end. +> +> **⇒ The `login_trusts` table is the only client registry, and writing it needs superuser. Steps 2–3 +> below cannot complete without MIE.** Send the sharpened ask in **"MIE ask"** (end of §3), then resume +> at §3 once MIE either registers `workwell-backend` or grants superuser + the FHIR App Editor. + --- ## 1. Generate the RS384 keypair (once, OUTSIDE the repo) @@ -87,6 +106,30 @@ never prints key/assertion/token material. Three steps: discovery → the RS384 - **invalid_client / invalid_scope** → the probe prints a targeted hint (registration/JWKS mismatch vs scope form); adjust and re-run. +### MIE ask (send this — §2 is MIE-gated, see the finding box up top) + +Because self-registration is blocked (superuser is MIE-controlled; RFC 7591 off), send MIE this +request. It resolves the §254 A3 residual either way (they register us, or they grant superuser + +the FHIR App Editor so we self-serve): + +> I am the verified System Owner of the WebChartNow trial `https://teatea.webchartnow.com/`. My +> account has the SuperUser security role and the Manage Login Trusts permission, but both +> client-registration routes return "Super user access required" (`?f=admin&s=jwt` and +> `?f=admin&subfunc=login_trusts`). Please either **(1)** grant my System Owner account SMART/FHIR +> app-registration access — the MIE-issued Super User unlock password + the FHIR App Editor — or +> **(2)** register this SMART **Backend Services** client for me: +> - Client name: `WorkWell Measure Studio` · preferred client id: `workwell-backend` +> - Grant type: `client_credentials` · token-endpoint auth: `private_key_jwt` · alg: **RS384** +> - JWKS URL: *(I will host the public JWKS at an HTTPS URL — the `webchart-teatea.pub.jwk.json` from §1)* +> - Redirect/launch URI: **none** (backend service, no browser flow) +> - Scopes: `system/*.read` (and `patient/*.rs` if supported for a backend context) +> +> Please confirm the assigned `client_id`, the pre-authorized scopes, that the token endpoint accepts +> `client_credentials` + RS384 `private_key_jwt`, and whether smart-configuration will advertise +> `client_credentials`. I will never share the private key — only the public JWKS URL. + +(I keep the private key in `~\.workwell\`; MIE only ever needs the **public** JWKS.) + ## 4. Seed the synthetic population (~30 patients) FHIR on teatea is read-scoped, so data enters through WebChart's own import tooling / UI. @@ -99,6 +142,20 @@ cd backend-ts pnpm generate:webchart-import --patients 30 --out ..\webchart-import ``` +> **✓ Live-verified 2026-07-16 (Data Import → "Validate File" dry-run on teatea).** The first validation +> pass taught us the instance's exact Chart Data contract and the generator was corrected accordingly: +> - **`patients.zip_code` is REQUIRED** and validated `12345`/`12345-6789` on **every** row — omitting it +> fails both the header ("does not match full list") and every data row. The generator now emits a +> synthetic demo ZIP (`46514`). *This was the whole cause of the first run's 451 validation issues.* +> - `@patient_mrns.MR` is correct — **`MR` is a real partition** on teatea (confirmed in the partition +> list) — and `patients.first_name/last_name/birth_date/sex/email` all validated. +> - The instance's own **Sample** (Data Import → Sample → `Sample_Chart_Data.csv`) is the authoritative +> header if a column is ever rejected; open it and match names. +> +> Always **Validate File** (non-destructive) before **Upload File** — it returns a per-row issue log and a +> "Download Failed Test Data File" button. The Data Import modal is heavy; if it fails to open, reload the +> page and reselect the row. + This emits MIE's documented Data-Migration CSV formats (verified against the `mieweb/docs` repo sources, 2026-07-16 — the rendered docs live under `docs.enterprisehealth.com/functions/system-administration/data-migration/`):