diff --git a/README.md b/README.md new file mode 100644 index 0000000..bc7e322 --- /dev/null +++ b/README.md @@ -0,0 +1,119 @@ +# Cyclone + +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. + +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). + +## Install + +```bash +# Backend (Python 3.11+) +cd backend +python -m venv .venv +.venv/bin/pip install -e '.[dev]' + +# Frontend (Node 20+) +cd .. +npm install +``` + +## Dev + +Two terminals: + +```bash +# Terminal 1 — backend +cd backend +.venv/bin/python -m cyclone serve +# (defaults to 127.0.0.1:8000; override with CYCLONE_PORT=...; reload with CYCLONE_RELOAD=1) + +# Terminal 2 — frontend +npm run dev +# (Vite on http://localhost:5173) +``` + +Then open `http://localhost:5173`. Drop an `.txt` 837P or 835 file on the +Upload page; navigate to Claims, Remittances, Providers, or Activity to +see the parsed data. + +The frontend reads its backend URL from `VITE_API_BASE_URL` (default +empty). Create a `.env.local` at the repo root with: + +``` +VITE_API_BASE_URL=http://127.0.0.1:8000 +``` + +Without that, the UI falls back to its in-memory sample store via the +existing `data` adapter (parses are disabled). + +## Test + +```bash +# Backend +cd backend && .venv/bin/pytest + +# Frontend type-check + build +npm run typecheck +npm run build + +# Frontend unit tests (when added) +npm test +``` + +## Project layout + +``` +. +├── backend/ +│ ├── src/cyclone/ +│ │ ├── api.py # FastAPI app, GET + parse routes +│ │ ├── store.py # InMemoryStore, mappers +│ │ ├── __main__.py # `python -m cyclone serve` +│ │ ├── cli.py # click CLI +│ │ └── parsers/ # X12 tokenizer, models, validator, writers +│ └── 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_parse_persists.py +├── src/ # React + Vite + TypeScript UI +│ ├── components/ +│ │ └── ui/ # Skeleton, EmptyState, ErrorState, FilterChips, Pagination, … +│ ├── pages/ # Claims, Remittances, Providers, Activity, Upload +│ ├── hooks/ # useBatches, useClaims, useRemittances, useProviders, useActivity, useParse +│ ├── lib/ # api.ts (6 GET + parse837/parse835/health), format.ts, utils.ts +│ ├── store/ # zustand sample-data + parsed-batches store +│ └── types/ # shared TS types +├── docs/ +│ ├── reference/ # condensed 837P/835/X12/CO Medicaid notes +│ └── superpowers/plans/ # implementation plan +├── tailwind.config.js # shimmer, scan, row-flash keyframes +└── package.json +``` + +## Roadmap + +This is **sub-project 1 of 4**. The other three are not in this build: + +- **Sub-project 2 — DB + reconciliation.** Replace the in-memory store + with SQLite/Postgres; add 837P ↔ 835 reconciliation matching payouts to + original claims. +- **Sub-project 3 — More 837P/835 features.** Additional 837P validation + rules (REF*G1 enforcement, BHT06), 835 CAS deep-parsing, 999 ACK, and + 270/271 eligibility. +- **Sub-project 4 — Frontend features.** Per-claim detail drawer, batch + diff view, real-time streaming of NDJSON GET responses, advanced + filters (date range, multi-status, saved filter sets), keyboard-driven + navigation. + +## License + +No license file yet; this is internal-use software. Add a `LICENSE` file +when one is decided.