docs(sp42): README.md — refresh auth/bind claim, project layout, streaming endpoints, sub-project count

This commit is contained in:
Nora
2026-07-08 23:03:45 -06:00
parent b3aec27e52
commit b0956d039c
+62 -44
View File
@@ -2,12 +2,17 @@
A self-hosted EDI claims management suite for a single billing office.
Parses 837P professional claims and 835 ERA remittances (X12 005010X222A1
and 005010X221A1), with a local-only FastAPI backend and a React UI for
browsing, filtering, and inspecting the parsed data.
and 005010X221A1), with a FastAPI backend and a React UI for browsing,
filtering, and inspecting the parsed data.
Local-only on purpose: binds to `127.0.0.1`, no auth, no internet exposure.
Built for one operator, one machine, one trading partner (Colorado
Medicaid, currently).
LAN-only by design: always binds to `0.0.0.0:8000` and requires login
(bcrypt + HttpOnly session cookie; first admin bootstrapped from
`CYCLONE_ADMIN_USERNAME` + `CYCLONE_ADMIN_PASSWORD`). Reachability is
controlled by the host firewall / compose port publishing, not by the
bind address. Built for one operator, one machine, one trading partner
(Colorado Medicaid, currently). Do not expose the published ports to
the public internet. See [SP23](docs/superpowers/specs/2026-06-22-cyclone-ubuntu-docker-deployment-design.md)
for the LAN-bind / Docker / RBAC product fork that shipped 2026-06-23.
## Install
@@ -184,13 +189,15 @@ happening — clients flip to `stalled` after 30s of total silence
### Endpoints
| Method | Path | Subscribes to | Default sort |
| ------ | -------------------------- | ------------------- | ------------------- |
| GET | `/api/claims/stream` | `claim_written` | `-submission_date` |
| GET | `/api/remittances/stream` | `remittance_written`| `-received_date` |
| GET | `/api/activity/stream` | `activity_recorded` | `-timestamp` (limit 50) |
| Method | Path | Subscribes to | Default sort |
| ------ | -------------------------- | -------------------- | ------------------- |
| GET | `/api/claims/stream` | `claim_written` | `-submission_date` |
| GET | `/api/remittances/stream` | `remittance_written` | `-received_date` |
| GET | `/api/activity/stream` | `activity_recorded` | `-timestamp` (limit 50) |
| GET | `/api/acks/stream` | `ack_received` | `-received_date` |
| GET | `/api/ta1-acks/stream` | `ta1_ack_received` | `-received_date` |
All three accept the same query params as their non-streaming
All five accept the same query params as their non-streaming
counterparts (`status`, `payer`, `date_from`, …) so a frontend can
swap a one-shot fetch for a tail with no URL surgery. Responses
are `Content-Type: application/x-ndjson`.
@@ -743,12 +750,11 @@ backup API).
.
├── backend/
│ ├── src/cyclone/
│ │ ├── api.py # FastAPI app, GET + parse routes, /api/{resource}/stream
│ │ ├── api.py # FastAPI app shell (~377 LOC post-SP36; routes live in api_routers/)
│ │ ├── api_helpers.py # NDJSON / content-negotiation / live-tail helpers
│ │ ├── pubsub.py # in-process EventBus (drop-oldest, per-kind fan-out)
│ │ ├── store.py # CycloneStore, mappers, publish-on-write
│ │ ├── db.py # SQLAlchemy engine, session factory, ORM models
│ │ ├── db_migrate.py # PRAGMA user_version migration runner
│ │ ├── db_migrate.py # PRAGMA user_version migration runner (23 migrations)
│ │ ├── db_crypto.py # optional SQLCipher encryption at rest (SP12)
│ │ ├── audit_log.py # tamper-evident hash-chained audit_log (SP11)
│ │ ├── inbox_lanes.py # rejected / payer_rejected / candidates / unmatched / done_today
@@ -756,37 +762,45 @@ backup API).
│ │ ├── inbox_state_277ca.py # 277CA STC A4/A6/A7 → payer_rejected stamp (SP10)
│ │ ├── providers.py # multi-NPI provider lookups (SP9)
│ │ ├── payers.py # payer / payer_config lookups (SP9)
│ │ ├── secrets.py # macOS Keychain-backed secret fetcher
│ │ ├── reconcile.py # pure-function 835→claim match + line-level match
│ │ ├── __main__.py # `python -m cyclone serve`
│ │ ├── cli.py # click CLI
│ │ ── parsers/ # X12 tokenizer, models, validator, writers, 277CA, 999, TA1, 270, 271
└── tests/
├── fixtures/ # co_medicaid_*.txt, minimal_*.txt
├── test_api.py # parse-837/835 round-trip
├── test_api_gets.py # 6 GET endpoints
├── test_store.py # store + mappers + iterators
├── test_api_streaming.py
├── test_api_stream_live.py # 3 live-tail endpoints + disconnect cleanup
├── test_pubsub.py # EventBus + subscribe/unsubscribe
├── test_api_parse_persists.py
├── test_db.py / test_db_crypto.py / test_db_migrate.py
├── test_audit_log.py
── test_inbox_lanes.py / test_inbox_state.py
── test_apply_277ca_rejections.py
│ ├── test_sftp_stub.py / test_sftp_paramiko.py
── test_providers_seed.py / test_payer_config_loading.py
├── src/ # React + Vite + TypeScript UI
│ │ ├── secrets.py # macOS Keychain-backed secret fetcher (4-tier: _FILE > env > Keychain > None)
│ │ ├── reconcile.py # pure-function 835→claim match + line-level match (SP31 pcn-exact)
│ │ ├── scheduler.py # inbound MFT polling scheduler (SP16, SP27 per-op timeout)
│ │ ├── edifabric.py # Edifabric /v2/x12/{read,validate} HTTP client (SP40)
│ │ ── backup.py / backup_service.py / backup_scheduler.py # SP17 encrypted backups
│ ├── __main__.py # `python -m cyclone serve` (auth bootstrap then dispatch)
├── cli.py # click CLI (15+ subcommands; see cyclone-cli skill)
├── api_routers/ # SP36 — 22 FastAPI routers + _shared.py helpers
├── auth/ # SP24 — bcrypt + sessions + matrix_gate + admin users + rate_limit
├── clearhouse/ # SftpClient + InboundFile + SftpStat
├── edi/ # filename regex/builder helpers
├── handlers/ # SP27 — per-file-type inbound parse handlers
├── parsers/ # X12 tokenizer, models, validator, writers, 277CA, 999, TA1, 270, 271
├── rebill/ # SP41 — in-window rebill pipeline (13 modules)
├── reissue/ # SP24 — offline 837P reissue workflow
├── store/ # SP21 — split CycloneStore facade (16 modules)
── submission/ # SP37 — canonical submit_file helper + recover + bulk_ingest
── tests/ # 178 pytest files (post-SP41)
│ ├── fixtures/ # 22 entries (837P / 835 / 999 / TA1 / 277CA samples + visits CSV)
── test_api_*.py # FastAPI integration via TestClient
│ ├── test_*.py # pure-unit
│ └── ...
├── src/ # React + Vite + TypeScript UI (12 pages, 84 test files)
│ ├── components/
│ │ ├── ui/ # Skeleton, EmptyState, ErrorState, FilterChips, Pagination, …
│ │ ├── ClaimDrawer/ # 12 sibling tests
│ │ ├── RemitDrawer/ # 8 sibling tests
│ │ ├── ProviderDrawer/ # right-anchored side panel
│ │ ├── AckDrawer/ # right-anchored side panel (SP28 ack-claim auto-link)
│ │ ├── inbox/ # 5-lane triage surface (SP14)
│ │ ├── drill/ # DrillStackProvider + DrillableCell + PeekModal
│ │ └── TailStatusPill.tsx # live-tail status badge + reconnect button
│ ├── pages/ # Claims, Remittances, Providers, Acks, Activity, Upload, Inbox, …
│ ├── pages/ # Dashboard, Claims, Remittances, Providers, ActivityLog,
│ │ # Upload, Reconciliation, Inbox, Acks, Batches, BatchDiff, Login
│ ├── hooks/ # useBatches, useClaims, useRemittances, useProviders, useActivity, useParse
│ │ # + useTailStream, useMergedTail (live tail)
│ ├── lib/ # api.ts, format.ts, utils.ts
# + tail-stream.ts (NDJSON parser)
│ ├── store/ # zustand sample-data + parsed-batches store
│ │ # + tail-store.ts (FIFO-capped live tail slices)
│ │ # + useTailStream, useMergedTail (live tail triplet)
│ ├── auth/ # AuthProvider, RoleGate, api client (SP24)
├── lib/ # api.ts, format.ts, utils.ts, tail-stream.ts (NDJSON parser), inbox-api.ts
│ ├── store/ # zustand useAppStore (sample data) + useTailStore (FIFO-capped live tail slices)
│ └── types/ # shared TS types
├── config/
│ └── payers.yaml # YAML-driven payer + clearhouse config (SP9)
@@ -807,11 +821,15 @@ backup API).
> 3. The per-SP spec under [`docs/superpowers/specs/`](docs/superpowers/specs/) for whatever you're touching.
> 4. The per-SP plan under [`docs/superpowers/plans/`](docs/superpowers/plans/) if you're implementing.
Sub-projects 2 through 19 are **shipped**. See the [completeness
Sub-projects 2 through 41 are **shipped** (last merged: SP41 in-window
rebill pipeline, `merge: SP41 inwindow-rebill-pipeline into main` at
`309e6c0`). See the [completeness
review](docs/reviews/2026-06-20-cyclone-completeness-review.md) for
the honest gap analysis against the industry definition of a HIPAA
clearinghouse — the short version is that the local-only,
single-operator, single-payer design contract is honored, and the
clearinghouse — the short version is that the LAN-only,
single-operator, single-payer design contract is honored (auth per
SP23, encryption at rest via SQLCipher per SP12, RBAC per SP23, audit
log per SP11), and the
items that would be needed to expand that contract (AS2/AS4, SNIP 17,
HITRUST, 276/277 status, 278 referrals, COB) are intentionally out of
scope.