Let’s start with an uncomfortable truth: in the year 2026, a language model can write a sonnet about your MRI in 400 milliseconds, yet getting your insurer to actually approve that MRI still runs on a machine patented by Alexander Bain in 1843. We got tired of sitting through slide decks announcing that "FHIR is coming," so we wired the real HL7 DaVinci prior-authorization loop — CRD → DTR → PAS — end to end against InterSystems IRIS for Health as the clinical FHIR engine, packed all seven moving parts into a single drop-in Linux container, and made it grant a real claim in a real browser in 30 minutes flat. No cloud. No PHI. No license request. No Docker. Here is the whole story, with zero hand-waving and all the receipts.
Every healthcare interoperability conference on earth ends with the exact same ritual. Somebody dims the ballroom lights, puts up an architectural diagram with 47 pastel arrows, clears their throat, and says: "FHIR is coming."
(If you live outside health IT: FHIR — pronounced "fire" — is the modern REST/JSON standard health software uses to exchange clinical data so the players can stop speaking twelve dialects of 1980s pipe-delimited gibberish.)
Meanwhile, back in the actual clinic, a doctor orders a home blood-glucose monitor for a 69-year-old diabetic patient. What happens next is not a REST call. What happens next is that a nurse spends forty-five minutes hunting down clinical notes, logging into a payer web portal that looks like it was styled in FrontPage 98, or feeding paper into a literal fax machine while listening to smooth-jazz hold music or calling on the phone or sending the snap shot via WhatsApp.
Submit to watching PENDING → GRANTED flip in a real browser in this lab.The tragedy isn’t that nobody has written the spec to fix this. The specs have been published for years. The tragedy is that almost nobody has ever seen the whole loop running in one place. Payers build one third of it behind a VPN. EHR vendors demo another third at HIMSS. Reference implementations rot on GitHub with broken Gradle wrappers. The future is endlessly announced and almost never seen working.
So we did the one thing nobody at those committee meetings was doing: we built the smallest machine that contains the entire future of prior authorization, proved it twice, and made it a one-command download.
Run it and own the whole 7-service appliance on your local box in one command.
e.d House rule for this post: we leave nothing out, but we refuse to drown you in committee Greek. Every acronym earns its keep in plain English the moment it walks on stage, and the repo README + AGENTS.md carry every port, pin, and troubleshooting scar.
1. Why Prior Authorization Is the Canary in the Coal Mine (and Why CMS Brought a Sledgehammer)
Prior authorization is not exotic medicine. It isn’t robotic neurosurgery or AlphaFold protein folding. It is the most routine, bureaucratic, soul-crushing transaction in healthcare: "Doctor ordered X; insurer wants proof before paying for X."
And that is precisely why it is the ultimate canary for healthcare interoperability. If you can make prior authorization work as structured, real-time data between a hospital and an insurer, you can make anything work.
The federal regulator reached the same conclusion. Building on the earlier CMS-9115-F (2020) rule that kicked off the Patient Access wave, in January 2024 CMS (the Centers for Medicare & Medicaid Services) dropped the hammer with CMS-0057-F (Advancing Interoperability and Improving Prior Authorization Processes). It mandates that Medicare Advantage organizations, state Medicaid/CHIP programs, and Qualified Health Plan issuers stand up four FHIR R4 (version 4.0.1) APIs:
- Patient Access API — so patients can read their own clinical and claims data (including prior-auth decisions).
- Provider Access API — so in-network clinicians can pull the patient data they need at the point of care.
- Payer-to-Payer API — so a patient’s records and active authorizations follow them when they switch insurers.
- Prior Authorization API — so providers can query documentation rules and submit prior-auth requests electronically directly from their workflow.
The operational teeth bit in January 2026 (including mandatory specific denial reasons and public metrics); the FHIR API deadline is January 2027 for large payers (January 2028 for smaller qualifying plans). Instead of letting requests rot in a 30-day fax limbo, the rule enforces 72-hour urgent and 7-calendar-day standard turnaround windows, ~24/7 API availability, and pushes aggressively toward real-time autonomous decisions for routinely approved items.
2. The Antidote: Three Three-Letter Acronyms and One Plot Twist
When CMS wrote CMS-0057-F, they didn’t leave engineers to invent a protocol from scratch. They explicitly pointed at the HL7 DaVinci Project and three of its Implementation Guides (IGs).
Before we name the three guides, let’s set the stage with the three actors in every healthcare transaction:
- The Payer is the insurer paying the claim (Medicare Advantage, Medicaid, or commercial plan).
- The Provider is the hospital or clinic delivering the care.
- The EHR (Electronic Health Record) is the screen the doctor sits in front of to write orders and read chart notes.
Here is the first misconception almost everyone brings to the table: people assume the clever prior-auth software lives inside the hospital’s EHR. It doesn’t. The payer owns the coverage rules, the payer owns the questionnaire, and the payer owns the adjudication engine. The hospital’s system mostly asks, launches, and signs.
The entire DaVinci loop is just three handshakes — hover or tap each badge for the 10-second crib sheet: CRDCoverage Requirements Discovery — CDS Hook fired at order time: asks the payer whether prior auth or documentation is needed and returns a card on screen. → DTRDocumentation Templates and Rules — SMART on FHIR app launched from the card: renders the payer's questionnaire, evaluates CQL rules, and builds the Claim itself. → PASPrior Authorization Support — FHIR Claim/$submit endpoint: receives the structured prior-auth bundle and returns a ClaimResponse (Pending, Granted, or Denied).:
- 1. CRD — Coverage Requirements Discovery (IG): "Do I even need paperwork for this?"
The split-second a doctor selects an order in the EHR, a CDS Hook (order-sign-crd) pings the payer’s CRD server with the patient and order context. The payer evaluates its rules in real time and sends back a visual Card right on the doctor’s screen: "Documentation Required — Complete HomeBloodGlucoseMonitorOrder in DTR." - 2. DTR — Documentation Templates and Rules (IG): "Show me the exact form, and don’t make me retype the chart."
Clicking that card launches DTR — a SMART on FHIR web app that opens inside the hospital workflow behind a real OpenID Connect / OAuth 2.0 login. DTR pulls the payer’s FHIRQuestionnaire, evaluates deterministic CQL (Clinical Quality Language) rules against the patient’s record in IRIS, loads the payer’s approved code lists (value sets — nothing scarier than a curated dropdown of ICD-10/HCPCS codes), and produces a structuredQuestionnaireResponse. - 3. PAS — Prior Authorization Support (IG): "Adjudicate the claim as data, not a PDF."
The finished package is POSTed as a structured FHIRClaim(inspect the exact real JSON payload from our run here) to the payer’sClaim/$submitoperation. The payer responds immediately with a FHIRClaimResponseand flips the disposition fromPENDING→GRANTED.
Who actually builds and sends the
Claim to PAS? Everyone guesses the EHR does. Wrong. DTR — the payer’s SMART questionnaire app — builds the Claim from its own QuestionnaireResponse and POSTs Claim/$submit to PAS itself! Nothing in the EHR half even knows PAS exists. That single architectural fact is why an API-only test script can never prove the browser flow works, and why our lab ships two independent verification drivers.
3. Under the Hood: All 7 Moving Parts on One Linux Bridge
To make this real, you need two halves talking across a real network boundary:
- The Screen (`crd-request-generator` on port
:3001): HL7 DaVinci’s own mock EHR, pinned to an exact commit. Treat it as pure glass: patient tiles, order dropdowns, and a button. It holds zero patient data of its own. - The Spine (InterSystems IRIS for Health on port
:52774): The moment you click a patient tile on the screen, the browser queries a real production clinical data platform over FHIR R4. Screen and server speak the exact protocol an Epic or Oracle Health (Cerner) EHR speaks to its FHIR repository.
┌─────────────────────── your machine (or live web) ──────────────────────┐
│ Real Browser (you or Playwright e2e-browser.py — 14/14 assertions) │
└────────────────────────────────────┬──────────────────────────────────────┘
│ http://10.0.3.108:3001
▼
┌─────────── LXC guest "iris-fhir" (10.0.3.108) — self-contained ─────────┐
│ │
│ crg :3001 ───────────────────────────► CRD :8090 │
│ (Mock EHR UI · Node 22 / React) (Java / Quarkus · CDS Hooks) │
│ │ │ │
│ │ 1. SMART launch │ 2. Card: │
│ ▼ ▼ "Doc Required" │
│ Keycloak :8180 dtr :3005 │
│ (Real OIDC login: dtr / dtr-demo) (Node 22 / React 19 SMART app) │
│ │ │ │
│ └────────► 3. Signed OIDC token ───────────►│ 4. Fill form + │
│ │ builds Claim ITSELF │
│ ▼ 5. POST Claim/$submit │
│ PAS :9015 │
│ (Java / Spring Boot · 201) │
│ PENDING ──(15s)──► GRANTED │
│ │
│ ehr-shim :8080 (OAuth client_credentials) ──► IRIS for Health :52774 │
│ (Browser never holds an IRIS credential) (Native FHIR R4 over TLS) │
└───────────────────────────────────────────────────────────────────────────┘Here is the complete manifest of what runs inside that single container (`iris.service` + `davinci-stack.service`), pinned in versions.lock:
| Component | Port | Runtime / Stack | Exact Job in the Loop |
|---|---|---|---|
| IRIS for Health | 52774 (TLS)52773, 1972 |
InterSystems IRIS for Health Community 2026.2 | The clinical data platform + native FHIR R4 repository (https://10.0.3.108:52774/fhir/r4). Holds the seeded synthetic patients, answers over TLS, auto-starts via iris.service. |
ehr-shim |
8080 |
Node.js proxy | Holds the provisioned IRIS OAuth confidential client; mints a fresh client_credentials bearer token (with aud = FHIR base URL) per call and fronts IRIS TLS so the browser never touches an IRIS secret. |
CRD |
8090 |
Java / Quarkus (Temurin 17, Gradle) | CDS Hooks server (/r4/cds-services). Evaluates payer CQL rules + 65 pre-seeded value sets on order-sign-crd and returns the "Documentation Required" card. |
Keycloak |
8180 |
Keycloak 26.7.4 (JDK 21) | Identity & Access Management (`BurdenReduction` realm, 26 SMART scopes, user dtr / dtr-demo). Makes the DTR SMART launch perform a genuine OIDC redirect and login screen. |
dtr |
3005 |
Node 22 / React 19 / Express 5 | The payer’s SMART on FHIR questionnaire app: completes the OIDC handshake, renders the form with value-set dropdowns, and assembles + submits the FHIR Claim itself. |
prior-auth (PAS) |
9015 |
Java / Spring Boot 2.7 (Temurin 17) | Payer adjudication server. Accepts POST /fhir/Claim/$submit (HTTP 201), runs CQL adjudication rules, answers PENDING, and flips to GRANTED on a 15-second timer (DELAY=15000). |
crg |
3001 |
Node 22 / React (crd-request-generator) |
The clinician order-entry UI you drive from your browser. (Port 3000 is intentionally left untouched so existing host apps are never clobbered.) |
4. The Whole Run, Frame by Frame (All 9 Real-Browser Receipts)
Who is our patient? Meet Vlad Quinton (`pat013`), a 69-year-old male who — along with Bobby Tables (yes, HL7’s test-fixture authors have a sense of humor) and two friends — is 100% synthetic demo data published by HL7 and seeded into IRIS. That is what "no PHI" means here: there is zero protected health information anywhere in the repo, the container, or the screenshots.
Two honest boundaries before we click:
- The UI is a stand-in, not a full hospital EHR. It is HL7’s own order-entry harness; in production, Epic or Cerner fires the exact same CDS Hook and SMART launch.
- The order is data, not a physical glucometer.
E0607is the standard HCPCS code for a Home blood glucose monitor (`DeviceRequest`). Selecting it is the trigger that forces the system to ask the payer whether paperwork is required.
Here is the exact click-by-click walkthrough (once your LXC container is imported and running):
- Pick the patient & order (Frame 1): Open
http://10.0.3.108:3001/(default lxc host:port) → clickPATIENT SELECT→ pick thepat013tile (Vlad Quinton, 69M) → from its ownSelect a request...dropdown chooseE0607 (DeviceRequest) Home blood glucose monitor→ clickClick to select this patient. - Fire the order-time check (Frame 2): Click
SUBMIT TO CRD AND DISPLAY CARDS. CRD evaluates the payer’s CQL coverage rules against Vlad’s FHIR record in IRIS (10–20 seconds of real rule evaluation) and renders the card on screen: "Documentation Required — Complete HomeBloodGlucoseMonitorOrder in DTR." - Authenticate via SMART on FHIR (Frame 3): Click the launch button on the card. A new tab opens and redirects through Keycloak (`:8180`) for a real OpenID Connect / OAuth login. Sign in with
dtr/dtr-demo. - Render the Payer Questionnaire (Frames 4–6): DTR (`:3005`) loads the Home Blood Glucose Monitor Order questionnaire with live value-set dropdowns (e.g., "Type 2 diabetes mellitus with diabetic nephropathy — E11.21"), date pickers, and attestation checkboxes. Fill the required fields.
- The Plot Twist in Action (Frame 7): Click
PROCEED TO PRIOR AUTH. Right inside the DTR app, the UI swaps in the Prior Auth submission panel — because DTR has just assembled the formal FHIRClaimJSON itself. - Submit & Watch `PENDING` → `GRANTED` (Frames 8–9): Click
Submit. PAS (`:9015`) immediately returns HTTP 201 with dispositionPending(Frame 8). Fifteen seconds later, the payer adjudication timer completes and the browser flips toGranted(Frame 9).
Server-side, if you tail -f logs/prior-auth.log inside the container, you can watch the exact moment the fax machine dies:
POST /Claim/$submit fhir+JSON
generateAndStoreClaimResponse(c37fe4f8…/0M987654001AZ, disposition: PENDING)
generateAndStoreClaimResponse(46204484…/0M987654001AZ, disposition: GRANTED) # +15 sHere are the four headline frames from that run (click any frame to inspect full-screen):
![]() Frame 2 · CRD Card: "Documentation Required" at order sign · Enlarge |
![]() Frame 3 · SMART Launch: Real Keycloak OIDC login ( dtr / dtr-demo) · Enlarge |
![]() Frame 4 · DTR Form: Payer questionnaire + live value sets · Enlarge |
![]() Frame 9 · PAS Verdict: Pending flips to Granted in 15s · Enlarge |
e.d Want the uncut director’s reel? The automated Playwright driver (`bin/e2e-browser.py`, 14/14 assertions) captures all nine intermediate states — including the patient modal, date pickers, completed form fields, the DTR Claim-builder panel, and the initial `Pending` receipt before the 15-second flip:
![]() Frame 1: Pick pat013 + E0607 · Zoom |
![]() Frame 5: Diagnosis & dates · Zoom |
![]() Frame 6: Form complete · Zoom |
![]() Frame 7: DTR’s Claim panel · Zoom |
![]() Frame 8: HTTP 201 Pending · Zoom |
![]() Frame 9: +15s → Granted · Zoom |
5. Try It Live Right Now — Zero Install, Three Minutes
Don’t have a Linux box handy right this second? We put the exact same lab live on the public internet at https://iris-fhir.aidentech.com. No signup, no email gate, about three minutes:
- Click
PATIENT SELECT→ pick thepat013tile → from its request dropdown chooseE0607 (DeviceRequest)→ select the patient. - Click
SUBMIT TO CRD AND DISPLAY CARDS→ wait for the Documentation Required card. - Click the card’s launch link → the DTR questionnaire opens in a popup (allow popups) behind the real Keycloak login. Demo credentials:
dtr/dtr-demo(full list in the README credentials inventory). - If DTR offers a previously saved in-progress form, click
Cancelfor a fresh one, then fill the required fields. - Click
PROCEED TO PRIOR AUTH→ verify the PAS endpoint ishttps://iris-pas.aidentech.com/fhir→ clickSubmit→ clickCheck Claim Statusafter 15 seconds to watch it flip toGRANTED.
Synthetic patients only; you can’t break anything. Want the whole appliance on your own metal? Jump to Run it below.
6. Why InterSystems IRIS for Health? (And Why Not Just HAPI FHIR?)
Let’s address the elephant in the server room. Everything else in this repository is open-source HL7 DaVinci reference code. Why didn’t we just drop in an open-source FHIR server like HAPI FHIR or a mocked JSON file and call it a day?
Because HAPI FHIR is great for writing unit tests, but hospitals don’t run unit tests as their clinical spine.
The question a hospital CIO or chief architect actually loses sleep over is: "Does the enterprise clinical data platform we actually run in production behave properly under this DaVinci flow?"
InterSystems IRIS for Health is a thoroughbred commercial clinical-data platform: a native FHIR R4 repository (CRUD, search, operations, transactions), an integration engine (Health Connect for the HL7 v2, X12, and IHE feeds hospitals still depend on), and multi-model storage (objects, SQL tables, documents, and native vector search living inside one engine). It powers real hospital estates (TrakCare, HealthShare, enterprise EMPIs) and large-scale clinical AI workloads (see Stanford Health Care’s FHIR + AI deployment).
Its Community Edition is free for evaluation and development. We didn’t write a brochure about it — we provisioned it, locked it down with OAuth and TLS, seeded it, and proved it with receipts:
| The Receipt | The Verifiable Evidence |
|---|---|
| Thoroughbred FHIR R4 server over TLS | curl -sk https://10.0.3.108:52774/fhir/r4/metadata returns IRIS’s own CapabilityStatement with HTTP 200 within seconds of cold boot. |
| Production-shaped OAuth 2.0 security | An OAuth confidential client is provisioned inside the image; ehr-shim mints a short-lived client_credentials bearer token per upstream request (`aud` = FHIR base URL). The browser never holds an IRIS credential. |
| A real SMART / OIDC login, not a bypass | Clicking the CRD card triggers a real OpenID Connect redirect through Keycloak (`BurdenReduction` realm, 26 SMART scopes) before a single question renders. |
| Real seeded clinical records | Synthetic DaVinci patients (`pat013` Vlad Quinton & friends) live inside IRIS’s native FHIR repository and answer real FHIR search/read queries. |
| Ships as a self-starting appliance | Cold boot (`lxc-stop` → `lxc-start`) brings up `iris.service` and `davinci-stack.service` automatically; clean shutdowns write a clean IRIS Write Image Journal (WIJ). |
| Proven end-to-end by two independent drivers | 12/12 automated API checks (`bin/demo.sh`) and 14/14 real-Chromium Playwright checks (`bin/e2e-browser.py`) both drive claims all the way to GRANTED. |
7. Confessions of a `chrooted` Graybeard: Why We Shipped an LXC Image (and Why We Dug Up Every Trap So You Don’t Have To)

Anyone can publish a 40-step Markdown file titled "How to Build the DaVinci Stack Yourself" and wish you good luck. If you actually try to build the six upstream DaVinci repositories from scratch on a Tuesday afternoon, here is what happens to you:
- Upstream is docker-compose-shaped (and the greybeard, who grew up on
chrootenvironments, never accepted Docker as a friend... and... never will!). - Upstream toolchains have drifted:
prior-auth/Dockerfile.devstill pins Gradle 6.9 and JDK 11 against a repository whose wrapper demands Gradle 8.14.2 and JDK 17. - Upstream’s own setup guide casually notes an open bug when submitting requests locally.
And those are just the surface bumps. While building and verifying this appliance, we hit — and permanently fixed or guarded against — the gnarliest integration traps in the stack. Expand any of these boring war stories if you want to see what our scripts save you from:
War Story #1: The SIGILL Core Dump on Older Silicon (AVX / AVX2 / BMI1 / BMI2) - Yes - Some Mothers Do ’Ave ’Em!
IRIS for Health 2024.x+ is compiled with AVX, AVX2, BMI1, and BMI2 CPU instructions. Yes they live among us and chug along all in the midst of Elon’s flying car. We tested it on an older Core 2 Quad Q9650 (which only had cx16 sse2 ssse3): iris.service immediately died at boot with a hardware SIGILL core dump. No container can emulate CPU flags the host silicon lacks. So bin/lxc-import.sh checks /proc/cpuinfo in Step 1 before downloading a single byte and tells you plainly if your CPU (needs 2013+ Intel Haswell or 2017+ AMD Zen, or a VM exposing host CPU flags) can run it.
War Story #2: The Missing Trailing Slash That Lobotomized 65 Value Sets
Both upstream file stores concatenate VSAC_CACHE_DIR + filename with zero path separator. Leave off the trailing slash on VSAC_CACHE_DIR and CRD silently looks for files in the parent directory, fails to resolve any of the 65 terminology value sets, and renders questionnaires with blank dropdowns. Worse: if you seed an unexpanded ValueSet resource (`expansion.contains == 0`), the form renders with zero options. Our bin/seed-valuesets.sh pulls all 65 value sets from public tx.fhir.org using $expand, refuses to write unless contains > 0, and bin/env.sh enforces the trailing slash automatically.
War Story #3: Upstream’s embedCdsLibrary Footgun & The 260× 9p Filesystem Trap
If you run upstream’s Gradle task embedCdsLibrary, it cheerfully runs rm -rf and clones unpinned master from GitHub, destroying reproducibility. Even better: CRD wants the entire CDS-Library repo at repos/CRD/server/CDS-Library/, whereas PAS wants only the PriorAuth/ subfolder. Our bin/up.sh places both from pinned 40-character SHAs in versions.lock.
e.d Bonus scar: our original dev box sat on a 9p mount that was 260× slower for small npm/Gradle writes, and a /tmp wipe once ate the JDK toolchain — so everything now lives deterministically under runtime/ on ext4.
War Story #4: Why Custom Bridge IPs Still Keep 10.0.3.108 Bound as a Secondary Address
What if your host doesn’t use lxcbr0 (`10.0.3.1/24`) and you pass --bridge br0 --container-ip 192.168.50.108? The installer re-pins every service, drops and re-imports the Keycloak realm so redirect URIs match your new IP, and points ehr-shim at 127.0.0.1 (because IRIS’s TLS cert covers 127.0.0.1 and 10.0.3.108). Crucially, it keeps 10.0.3.108 bound as a secondary IP on eth0 inside the container — because IRIS’s internal OAuth server mints JWTs that self-reference https://10.0.3.108:52774, and dropping that secondary IP causes token validation to hang while /oauth2/token still looks healthy!
War Story #5: What We Refuse to Trim When Building the Image (Never Touch the WIJ)
To pack IRIS + 6 Java/Node services + JDK 17 + JDK 21 + Maven + prebuilt React bundles into a ~4.2 GB archive (`bin/lxc-image-build.sh`), we trim caches carefully — but we never delete IRIS’s Write Image Journal (IRIS.WIJ), journal files, journal.log, SSH keys, or /var/log directory structures. Deleting any of those drops IRIS into single-user recovery mode on next boot. And yes, we also disclose the three upstream CQL expressions (`ALTERNATIVE_THERAPY`, `RESULT_QuestionnaireAdditionalUri`, `RESULT_QuestionnairePARequestUri`) that upstream CRD doesn't pre-populate yet — which is why the browser driver types the form fields while the API driver seeds `bundle-items.json`.
Because we fought all five of those battles once and captured the victorious machine as a checksum-verified LXC container image, your entire install is three lines:
git clone https://github.com/Aidentech-com/iris-fhir.git
cd iris-fhir
sudo bash bin/lxc-import.sh githubThat’s it. The installer checks your CPU flags, disk space (≥ 15 GB), and bridge before downloading, pulls the image, verifies the SHA-256 checksum, boots the container, and waits until all six services plus IRIS report HTTP 200:
==> [9/10] Verify the stack ...
keycloak 8180 200 /realms/BurdenReduction/.well-known/openid-configuration
ehr-shim 8080 200 /fhir/r4/metadata
crd 8090 200 /r4/cds-services
prior-auth 9015 200 /fhir/metadata
dtr 3005 200 /
crg 3001 200 /
==> [10/10] Summary ...
Open http://10.0.3.108:3001/ ...Nothing runs on your lxc host machine — instead the lxc guest has it all, and that’s by design. No Node, no Java, no Gradle, no Docker daemon, no InterSystems account, no license key, no cloud signup. Thirty minutes after you start the download (almost all of it waiting on the ~4.2 GB image transfer), you are watching a claim turn GRANTED at http://10.0.3.108:3001/. (And if you are a masochist who wants to build from source without LXC, Path B — ./bin/provision.sh && ./bin/up.sh — is in the repo too.)
8. What’s In It For You? (Three Audiences, Zero Fluff)
A. If You Run Hospital IT / HIS Systems
This is your CMS-0057-F and global interoperability future (US ONC Cures Act, European EHDS, India ABDM, Saudi/GCC national FHIR exchanges) decompressed from a 300-page procurement PDF into a single afternoon:
- "What does an order-time coverage check actually look like?" → Watch the
order-sign-crdCDS Hook return the card in Frame 2. - "How does a SMART on FHIR app launch inside an EHR?" → Watch the OIDC redirect through Keycloak in Frame 3.
- "What are value sets, CQL, and payer questionnaires?" → Inspect the 65 expanded value sets and the rendered DTR form in Frame 4.
- "How does a prior-auth request reach a payer as structured data?" → Watch DTR build the
Claim, POSTClaim/$submit, and flipPENDING → GRANTEDin Frame 9.
Knowing FHIR on paper and having watched it work — with every log file under logs/*.log open in front of you — are two completely different things. This repo is the second one.
B. To the People at InterSystems — This One Is Yours to Enjoy
You build IRIS for Health and tell the market it is a high-performance FHIR engine. Here is the proof from outside: an independent, reproducible, third-party demonstration of your platform acting as the live clinical spine of the hardest regulatory workflow in US healthcare.
- A zero-friction developer on-ramp: Normally, trying IRIS for Health takes an account, an image pull, and manual FHIR/OAuth setup. Here, one command imports a pre-provisioned Community Edition instance and lets a developer watch it power a granted claim in 30 minutes.
- A miniature third-party case study: Real FHIR R4 (4.0.1) resources, TLS, OAuth confidential client, seeded clinical data — backed by the platform’s multi-model engine (records, SQL tables, documents, plus vector search ready for GenAI).
- Both halves of CMS-0057-F: InterSystems markets Payer Services for CMS-0057 compliance; this repo proves the provider side of that exact same regulation talking to an IRIS FHIR server. Put them together and you own both sides of the table.
- Community-ready: MIT-licensed orchestration, SHA-pinned, checksum-verified, and documented for both humans and AI agents. Run it, try to break it, re-verify it — and if it earns an InterSystems Developer Community feature or case-study nod, the credit is warmly appreciated.
Boundary, stated plainly: the container ships InterSystems IRIS for Health Community Edition unmodified under InterSystems’ own Community license. Nothing is patched, nothing is relicensed, and no trademark claim is made. The platform credit is InterSystems’; the proof lives on git.
C. The AI Canvas: Why This Lab Is an Agent Playground
Everyone wants to pitch "AI for Prior Authorization." Almost nobody has a realistic sandbox to test it against. This lab gives you four things AI builders desperately need:
- FHIR is the substrate clinical AI requires: Chart summarization, coding copilots, and RAG over patient records are only as good as the structured, queryable data underneath. Here you have a live IRIS FHIR R4 repository you can query right now.
- Prior auth is healthcare AI’s highest-ROI target: It is high-volume, text-heavy, and rule-documented — tailor-made for an LLM copilot that retrieves chart evidence, drafts DTR questionnaire answers, selects supporting codes, and tees up the form for a clinician’s one-click signature.
- Deterministic CQL rules are the guardrail, not the enemy: You don’t want a hallucinating LLM adjudicating medical necessity. The winning architecture is hybrid: language models draft; deterministic CQL rules and value sets adjudicate. This lab gives you both halves in one box.
- Agents need a safe tool surface (and we shipped `AGENTS.md`): Because the stack is 100% local and 100% synthetic data, an AI agent can hammer CRD, DTR, PAS, and IRIS end-to-end without touching PHI. The repo even ships
AGENTS.md— a complete autonomous agent playbook (provision → start → verify → report → stop).
9. Run It (30 Minutes to `GRANTED`)
git clone https://github.com/Aidentech-com/iris-fhir.git
cd iris-fhir
sudo bash bin/lxc-import.sh github # downloads & verifies the LXC image
# the lxc guest starts IRIS + all six services itself — nothing runs on your host
lxc-attach -n iris-fhir -- bash -c 'cd /opt/davinci-mock && bash bin/demo.sh' # 12/12 API checks
ADVERTISE_HOST=10.0.3.108 ./.venv/bin/python bin/e2e-browser.py # 14/14 real-browser checks
# open http://10.0.3.108:3001/ and click through to a GRANTED claimEverything else — the one-time host CPU/bridge check, Path B source builds, custom bridge IP re-pinning (`--bridge` / `--container-ip`), LAN mode (`ADVERTISE_HOST`), port sweep (`bin/down.sh --purge`), credentials table, and full glossary — is waiting in the GitHub README.
The FHIR future is not "coming." It is sitting in a 4.2 GB container, and you can watch it push the fax machine over and grant a claim in 30 minutes.
Sources & Citations: The 88% manual prior-authorization figure originates from the widely cited 2018 Managed Care / industry survey carried by Prior authorization (Wikipedia). The $23–31 billion annual US system cost and the weekly practice time breakdown (1.1 h physician, 13.1 h nursing, 5.6 h clerical) come from Casalino et al., Health Affairs (2009); the per-physician annual cost ($2,161–$3,430) is from Journal of the American Board of Family Medicine (2012); the ~90% faster electronic PA response figure is from the Prime Therapeutics PBM case study. All regulatory mandates, the four FHIR R4 APIs, the 2026/2027/2028 compliance dates, and the 72-hour / 7-day decision windows come directly from the CMS-0057-F Final Rule Fact Sheet.
First in our hands-on health-IT engineering series — one discipline: take a real clinical system, wire the real protocol, prove it with automated drivers, and hand you the keys. Stay tuned for the next one.









💬 Discussion