feat(eligibility): API-first 270/271 eligibility waterfall (Stedi client, payer route map, document-hash verified artifacts)#147
Conversation
…ent, payer route map, document-hash verified artifacts) The API tier of the dental eligibility offer: where a payer exposes a sanctioned real-time 270/271 route through a clearinghouse API, the check hits that route first and compiled portal replay becomes the fallback. - eligibility/client.py: StediEligibilityClient against Stedi's documented JSON endpoint (Authorization: Key header, tradingPartnerServiceId / subscriber / encounter.serviceTypeCodes request, benefitsInformation + AAA-error response). Normalized EligibilityResult with the raw 271 retained byte-exact plus its SHA-256 wire digest. parse_271 fails CLOSED: malformed or signal-free responses are indeterminate, never a guessed benefits answer. Secret-isolated auth per the effect kit convention (env-var references only; construction fails loud). - eligibility/waterfall.py + payer_routes.yaml: the committed per-payer capability map (payer -> api | portal | excluded) and the resolver the fulfillment loop calls, so route choice is reviewed data, not code. Six confirmed dental payers route api-first; Availity is excluded + portal_banned with the sanctioned-API conversion path documented; unknown payers default to portal. Fallback rule is explicit: a 270 is an idempotent READ so no-answer API attempts fall through safely (the opposite of ApiActuator's write-path HALT), except banned portals which land in the practice queue. - eligibility/artifact.py: results land in the same practice-local artifact set as portal replay (eligibility_results.csv row + byte-exact 271_<digest16>.json) and are certified by the document-hash verifier (record_written + sha256 field_equals against the wire digest) -- effect verification is source-agnostic. - docs/ELIGIBILITY_API_WATERFALL.md: honest proof labels (contract-proven vs live-proven), practice-held account / click-through BAA model, per-check cost, activation steps, backup clearinghouse. Contract-proven against faithful fakes of Stedi's documented shapes (including their published dental mock catalog); an env-gated live smoke test (STEDI_API_KEY, test mode, mock checks are free) graduates the mocked path to live-proven. Purely additive: no existing file modified, no new dependencies (httpx and PyYAML are already core), nothing on the replay hot path. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Holding this PR in draft after independent review. The API-first eligibility thesis is sound, but this exact implementation is a contract spike rather than a safe production fulfillment path. Before it can return to ready:
Current CI is green and the code appears MIT-compatible; the hold is about silent-wrong-answer, PHI, effect-verification, and fulfillment completeness—not general code quality. |
|
Status refresh (2026-07-19): the MIT-only release boundary is restored, so the remaining hold is the production contract described above. This stays a useful API-first spike but not a merge candidate until exact payer routing, benefit/time/network interpretation, error taxonomy, atomic normalized/raw artifacts, PHI retention/egress, and >=3 effect-oracled integration trials are implemented on current released main. The staff-first attended path and UI execution layer remain the launch critical path; this PR should integrate with them if resumed, not become a parallel fulfillment runtime. |
What
The API-first eligibility spike for the dental offer: a working EDI 270/271 eligibility-check path through a clearinghouse API (Stedi), integrated as a flow-idiomatic component with effect verification — so eligibility checks hit the sanctioned API route where one exists and portal replay becomes the fallback.
New package
openadapt_flow/eligibility/(import-light, not on the replay hot path; no new dependencies — httpx and PyYAML are already core):client.py—StediEligibilityClientagainst Stedi's documented real-time 270/271 JSON endpoint (Authorization: Keyheader,tradingPartnerServiceId/subscriber/encounter.serviceTypeCodesrequest,benefitsInformation/AAA-error response). NormalizedEligibilityResult(active/inactive, plan name, copay/coinsurance/deductible/OOP-max where present) with the raw 271 retained plus its SHA-256 wire digest.parse_271fails closed: a malformed or signal-free response isindeterminate, never a guessed benefits answer. Secret-isolated auth per the effect kit's convention (env-var references viaAuthReforSTEDI_API_KEY; construction fails loud when absent; the key never enters results, reasons, or artifacts).waterfall.py+payer_routes.yaml— the waterfall seam: a committed per-payer capability map (payer →api|portal|excluded) andresolve_route/run_waterfallso the fulfillment loop picks the route automatically. The six confirmed-covered dental payers route api-first; Availity isexcluded+portal_banned(scraping contractually barred) with the sanctioned-API conversion path documented; unknown payers default honestly toportal. Fallback rule is explicit: a 270 is an idempotent read, so a no-answer API attempt may fall through to the portal tier — the opposite of the write-pathApiActuator's HALT rule — except when the portal is banned, in which case the check lands in the practice queue.artifact.py— the API result lands in the same practice-local results artifact set as a portal replay (appendedeligibility_results.csvrow + the raw 271 written byte-exact as271_<digest16>.json) and is certified by the kit'sdocument-hashverifier: exactly one raw-271 document (record_written) whose bytes hash to the wire digest (field_equalsonsha256). The CSV row carries the digest, so every benefits answer traces to the exact 271 that produced it. Effect verification is source-agnostic — the halt-instead-of-guess wedge governs the artifact whether a portal, an API, or a human produced it.docs/ELIGIBILITY_API_WATERFALL.md— the waterfall design, the practice-held-account/click-through-BAA deployment model, per-check cost ($0.30 tapering to $0.08, mocks free), practice activation steps, the ADA weak-tail caveat, and the documented backup clearinghouse (pVerify; Availity Essentials API for Availity-locked payers).Honest proof status
Contract-proven, not live-proven. The client is built against Stedi's public docs (fetched 2026-07-18, including their published dental mock catalog — Ameritas / Anthem / Cigna / MetLife / UHC Dental, service type code 35). CI proves parsing, fail-closed behavior, routing, secret isolation, and the artifact write+verify roundtrip against faithful local fakes of those documented shapes. A live smoke test (
tests/test_eligibility_live_stedi.py) runs Stedi's own dental mock end-to-end and is env-gated onSTEDI_API_KEYwith a precise skip reason — Stedi's test mode is self-serve and mock checks are free, so the first run with a real test key graduates the mocked path to live-proven. Only doc-verified payer IDs are committed (cigna_dental: 62308, from Stedi's own mock catalog); all others are null withverified: falseand resolved from Stedi's payer directory at enrollment.Tests
34 new tests (33 run + 1 env-gated live skip): documented-shape fakes for active/inactive/AAA-42/AAA-75/AAA-43/payer-not-supported/malformed (fail-closed), request-shape and
Authorization: Keyheader assertions viahttpx.MockTransport, missing-env fails loud, secret never serialized, registry contents + alias/case-insensitive resolution + malformed-registry fail-loud, waterfall fallback rules (including portal-banned → queue and portal-route-needs-no-key), artifact write+verify roundtrip, tamper → REFUTED, duplicate write refused.ruff check,ruff format --check,mypy, and the full non-e2e unit suite are green locally. Frozen lanes untouched — the diff is purely additive (no existing file modified).🤖 Generated with Claude Code