diff --git a/README.md b/README.md index 1b550d5..670bd56 100644 --- a/README.md +++ b/README.md @@ -418,6 +418,35 @@ was a one-file change (`sftp_paramiko.py` replacing `sftp_stub.py`). the `paramiko` extras aren't installed so the test suite stays green on Linux dev boxes. +## Inbound MFT Scheduler (SP16) + +The dzinesco SFTP server accepts inbound files (835 remits, 999/TA1 +acks, 271 eligibility responses, 277/277CA claim acknowledgments) that +need to be pulled on a cadence, parsed, and persisted. SP16 ships the +**operator-facing control surface** for the polling loop, even though +the actual background scheduler is still in flight: + +| Method | Path | Notes | +| ------ | --------------------------------------------- | ---------------------------------------------------------------- | +| POST | `/api/admin/scheduler/start` | Start the background MFT polling loop (idempotent). | +| POST | `/api/admin/scheduler/stop` | Stop the background loop. Waits for the current tick to finish. | +| GET | `/api/admin/scheduler/status` | Running state + last tick summary. | +| POST | `/api/admin/scheduler/tick` | Force a single poll cycle. Coalesces with an in-flight tick. | +| GET | `/api/admin/scheduler/processed-files` | Recently processed inbound files. `?status=ok|error|skipped|pending`, `?limit=` (1–500, default 50). | + +The endpoints read from a `cyclone.scheduler` module and a +`cyclone.db.ProcessedInboundFile` ORM model that are being landed +alongside SP16 — the admin router's import surface is in place, the +implementation is in progress. The control surface is forward-compatible +with the eventual scheduler: starting / stopping / ticking / listing +processed files will all work as soon as the loop lands. + +The `paramiko` SFTP client from [SP13](#sftp-wire-up-paramiko) is the +underlying transport; the scheduler reuses it to list + download files +under the inbound SFTP path, then dispatches each downloaded file to +the matching parser based on the `` token in the filename +(see [SP13 file-naming template](#sftp-wire-up-paramiko)). + ## Batches, Reconciliation, and Activity These read/write endpoints are the core operator surface for browsing @@ -474,20 +503,31 @@ backup API). . ├── backend/ │ ├── src/cyclone/ -│ │ ├── api.py # FastAPI app + parse routes; mounts api_routers/* sub-apps +│ │ ├── api.py # FastAPI app + middleware; mounts api_routers/* sub-apps │ │ ├── api_helpers.py # NDJSON / content-negotiation / live-tail helpers │ │ ├── api_routers/ # FastAPI APIRouters extracted from api.py │ │ │ ├── health.py # GET /api/health │ │ │ ├── acks.py # GET /api/acks, /api/acks/{id} │ │ │ ├── ta1_acks.py # GET /api/ta1-acks, /api/ta1-acks/{id} │ │ │ ├── activity.py # GET /api/activity, /api/activity/stream -│ │ │ ├── batches.py # GET /api/batches, /api/batches/{id}, /api/batch-diff +│ │ │ ├── batches.py # GET /api/batches, /api/batches/{id} │ │ │ ├── claims.py # GET /api/claims, /api/claims/stream, /api/claims/{id}, │ │ │ │ # /api/claims/{id}/serialize-837, /api/claims/{id}/line-reconciliation │ │ │ ├── remittances.py # GET /api/remittances, /api/remittances/stream, /api/remittances/{id} │ │ │ ├── providers.py # GET /api/providers +│ │ │ ├── inbox.py # GET /api/inbox/lanes, POST /api/inbox/* (match/dismiss/acknowledge/resubmit), +│ │ │ │ # GET /api/inbox/export.csv +│ │ │ ├── reconciliation.py # GET /api/reconciliation/unmatched, /api/batch-diff, +│ │ │ │ # POST /api/reconciliation/match, /api/reconciliation/unmatch +│ │ │ ├── eligibility.py # POST /api/eligibility/request, /api/eligibility/parse-271 │ │ │ ├── clearhouse.py # GET /api/clearhouse, POST /api/clearhouse/submit -│ │ │ └── config.py # /api/config/providers[/...], /api/config/payers[/...], /api/admin/reload-config +│ │ │ ├── config.py # /api/config/providers[/...], /api/config/payers[/...], /api/admin/reload-config +│ │ │ ├── parse_835.py # POST /api/parse-835 +│ │ │ ├── parse_837.py # POST /api/parse-837 +│ │ │ ├── parse_999.py # POST /api/parse-999 +│ │ │ ├── parse_ta1.py # POST /api/parse-ta1 +│ │ │ └── admin.py # /api/admin/audit-log[/verify], /api/admin/db/rotate-key, +│ │ │ # /api/admin/scheduler/* (SP16) │ │ ├── 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