feat(sp24): align CLAUDE.md + REQUIREMENTS.md + ARCHITECTURE.md with auth work + AUTH_DISABLED WARNING
Replaces every stale 'no auth' / 'no authentication' / 'no second party to authenticate' claim in the three top-level docs with the v1 posture: the auth boundary is HTTP (bcrypt + HttpOnly session cookie; first admin bootstrapped from CYCLONE_ADMIN_USERNAME + CYCLONE_ADMIN_PASSWORD env vars); the file-system posture (SQLCipher at rest, macOS Keychain) is unchanged; the threat model is still a stolen/imaged drive. Closes requirements §11 R-1 (was Open; now Closed by SP24 — auth shipped via the origin/main merge on 2026-06-23, SP24 reconciled the docs). Also: - backend/src/cyclone/__main__.py — emit WARNING when AUTH_DISABLED is True at boot so a misconfigured production deploy fails loudly - §6.1 migrations table in ARCHITECTURE.md — list 0013 (auth_users_and_ sessions) and 0014 (audit_log_user_id) with the renumbering note - §4.2 module map — add the cyclone.auth.* package - Three skills addenda: cyclone-tests (AUTH_DISABLED conftest bypass is mandatory context), cyclone-api-router (every router needs Depends(matrix_gate)), cyclone-spec (spec template threat-model is now auth-aware) This also tracks CLAUDE.md in git for the first time (was previously untracked; the SP24 doc updates are in scope for the increment). Spec: docs/superpowers/specs/2026-06-23-cyclone-auth-posture-alignment-design.md Plan: docs/superpowers/plans/2026-06-23-cyclone-auth-posture-alignment.md
This commit is contained in:
+10
-7
@@ -13,7 +13,7 @@
|
||||
|
||||
## 1. System overview
|
||||
|
||||
Cyclone is a self-hosted X12 EDI claims-management suite for a single billing office. The first deployment target is Colorado Medicaid (one operator, one trading partner). The system is local-only on purpose: the backend binds to `127.0.0.1` and has no authentication because the threat model is a stolen or imaged drive, not a remote attacker.
|
||||
Cyclone is a self-hosted X12 EDI claims-management suite for a single billing office. The first deployment target is Colorado Medicaid (one operator, one trading partner). The system is local-only on purpose: the backend binds to `127.0.0.1` and requires login (bcrypt + HttpOnly session cookie). The threat model is still a stolen or imaged drive, not a remote attacker — SQLCipher at rest and the macOS Keychain handle that. The auth boundary is the HTTP layer; the file-system posture is unchanged. The SP23 product fork changes the threat model to "remote operator on LAN."
|
||||
|
||||
Cyclone processes three X12 transaction pairs end-to-end:
|
||||
|
||||
@@ -199,8 +199,9 @@ backend/src/cyclone/
|
||||
|
||||
| Module | Responsibility |
|
||||
|---|---|
|
||||
| `__main__` | Dispatch `serve` vs CLI; honor `CYCLONE_PORT` / `CYCLONE_RELOAD` |
|
||||
| `__main__` | Dispatch `serve` vs CLI; honor `CYCLONE_PORT` / `CYCLONE_RELOAD`; emit `AUTH_DISABLED` WARNING if `cyclone.auth.deps.AUTH_DISABLED` is True at boot |
|
||||
| `api` | FastAPI app, lifespan, route includes, 999/270/271 endpoints, exception → HTTP |
|
||||
| `auth.*` | HTTP-layer login (bcrypt + HttpOnly session cookie). Submodules: `deps` (the `matrix_gate` FastAPI dependency, `AUTH_DISABLED` flag), `routes` (`/api/auth/login`, `/api/auth/logout`, `/api/auth/me`), `users`, `sessions`, `permissions` (role matrix), `bootstrap` (env-var first-admin), `cli` (`cyclone admin create-user` / `rotate-password`) |
|
||||
| `api_helpers` | Error → status code mapping, common response shapes |
|
||||
| `audit_log` | Append + verify a SHA-256 hash-chained log (SP11) |
|
||||
| `backup` | Pure crypto + file I/O for SP17 backup format |
|
||||
@@ -338,9 +339,9 @@ The client uses `fetch` + `ReadableStream` to consume the body and dispatches ea
|
||||
|
||||
## 6. Data model
|
||||
|
||||
### 6.1 Migrations 0001–0012
|
||||
### 6.1 Migrations 0001–0014
|
||||
|
||||
The schema evolves in 12 ordered SQL files under `backend/src/cyclone/migrations/`. Each file starts with `-- version: N` and is applied in order by `db_migrate.py`. There is no migration framework — `db_migrate.py` is a 30-line file that checks the `schema_version` row and applies everything newer.
|
||||
The schema evolves in ordered SQL files under `backend/src/cyclone/migrations/`. Each file starts with `-- version: N` and is applied in order by `db_migrate.py`. There is no migration framework — `db_migrate.py` is a 30-line file that checks the `schema_version` row and applies everything newer. The first 12 ship on `main`; 13 + 14 are the auth migrations that landed in `main` on 2026-06-23.
|
||||
|
||||
| # | File | What it adds |
|
||||
|---|---|---|
|
||||
@@ -356,8 +357,10 @@ The schema evolves in 12 ordered SQL files under `backend/src/cyclone/migrations
|
||||
| 10 | `0010_payer_rejected_acknowledged.sql` | `claim.payer_rejected_acknowledged_*` columns (SP14 hand-off) |
|
||||
| 11 | `0011_processed_inbound_files.sql` | `processed_inbound_files` idempotency table (SP16) |
|
||||
| 12 | `0012_backups.sql` | `db_backups` table (SP17) |
|
||||
| 13 | `0013_auth_users_and_sessions.sql` | `users` + `sessions` tables, `users.password_hash` (bcrypt) — landed 2026-06-23 |
|
||||
| 14 | `0014_audit_log_user_id.sql` | `audit_log.user_id` FK to `users.id` (forward reference to 0013) — landed 2026-06-23 |
|
||||
|
||||
A 13th (`0013_claims_unique_constraint.sql`) and 14th (`0014_409_ux.sql`) are in-flight on the `claims-unique-fix` worktree but not yet on `main`.
|
||||
The SP22 parse-then-decide migrations (drop claims UNIQUE constraint + relax PK to `(batch_id, id)`) are renumbered to 0015 + 0016 on the `claims-unique-fix` worktree so the auth migrations stay at the front of the chain; they'll keep those numbers when SP22 lands.
|
||||
|
||||
### 6.2 ERD (high level)
|
||||
|
||||
@@ -614,7 +617,7 @@ Every API error is a JSON object with `{"error": "<code>", "message": "<human>",
|
||||
| `ValidationError` (R-codes) | 422 | `validation_failed` (issues in `detail`) |
|
||||
| `FileNotFoundError` | 404 | `not_found` |
|
||||
| `ValueError` | 400 | `bad_request` |
|
||||
| `PermissionError` | 403 | `forbidden` (reserved — no auth today) |
|
||||
| `PermissionError` | 403 | `forbidden` (raised by `matrix_gate` when the role is below the endpoint's required role) |
|
||||
| (anything else) | 500 | `internal` (with a request id for log correlation) |
|
||||
|
||||
The 409-vs-422-vs-400 split is intentional: 409 for state-machine violations (the operator's input is well-formed but conflicts with current state), 422 for parse / validation, 400 for bad input shape.
|
||||
@@ -700,7 +703,7 @@ For a single operator on a single machine, the dev deployment IS the production
|
||||
|
||||
The following are explicitly NOT built in v1, by design:
|
||||
|
||||
- **Multi-user / multi-host** — no auth, no LAN-bind, no Docker, no reverse proxy. The operator is one person, the host is one machine. (SP23 fork if this changes.)
|
||||
- **Multi-user / multi-host** — login is required (single-user model today; SP23 adds RBAC). LAN-bind, Docker, reverse proxy still out of scope. (SP23 covers the LAN-bind / Docker / RBAC product fork.)
|
||||
- **Other trading partners** — only Colorado Medicaid via Gainwell is configured. The `PayerConfig` mechanism (SP9) supports adding more; the spec/plan/CLI work for that is on the backlog.
|
||||
- **837I / 837D / 834 / 820 / 275 / 278 / 276-277** — only 837P and 835 are first-class. Other transaction types are listed in [REQUIREMENTS.md §6.2](REQUIREMENTS.md) as backlog items.
|
||||
- **NPPES real-time lookup** — only local NPI checksum validation (SP20). The operator who wants real registry lookup has to wire it in later.
|
||||
|
||||
Reference in New Issue
Block a user