Skip to content

Repository files navigation

ACO Health

Apache-2.0-licensed, self-hosted first vertical slice for a single ACO. It proves a synthetic BCDA v3 NDJSON → immutable manifest → canonical claim lineage → paid-claims metrics → FastAPI → Next.js dashboard flow.

Not a production clinical or payment system. All repository fixtures are deterministic, synthetic, and non-PHI. Parts A/B paid TCOC and Part D paid spend are separate operational_estimate values—not official CMS reconciliation. The BCDA v3 synchronization adapter is contract-tested with mocked HTTP; this repository has not validated CMS sandbox or production access. No HCC score, attribution logic, or production identity provider is included.

What is included

  • FastAPI /health, database-backed /ready, and versioned /api/v1 routes.
  • SQLAlchemy 2 models tested on SQLite and configured for PostgreSQL via DATABASE_URL.
  • Immutable, SHA-256-addressed source manifests and ingestion jobs.
  • Minimal BCDA v3 NDJSON parsing for Patient, Coverage, and ExplanationOfBenefit.
  • A typed httpx BCDA v3 client for in-memory bearer caching, all/explicit runout exports, bounded polling/retries, recoverable job history, strict manifests, confined URLs, and streamed downloads that refresh authorization after a 401.
  • Durable export-run and downloaded-file lineage plus an atomic, SHA-256-addressed filesystem artifact store. The narrow store protocol is the future MinIO/S3 adapter boundary; no object-store implementation is claimed here.
  • Canonical beneficiaries, claims, and current/historical claim versions with source lineage.
  • Decimal/NUMERIC(18,2) paid amounts; UTC source/data-through timestamps.
  • Separate Parts A/B paid TCOC and Part D paid spend.
  • Permission-gated and audited beneficiary CSV; an XLSXExportAdapter protocol boundary only.
  • Minimal responsive Next.js executive dashboard.
  • Compose stack: API, web, PostgreSQL, and MinIO (raw-object-store boundary).

Development status and handoff

The first synthetic raw-to-dashboard slice and mocked BCDA v3 synchronization slice are complete. The next milestone is credential-safe live CMS sandbox validation. A new developer or agent should start with docs/HANDOFF.md, then follow the reviewed implementation plan in docs/LIVE_BCDA_SANDBOX_VALIDATION_PLAN.md. The repository must continue to state that sandbox access is unvalidated until a real run produces sanitized, dated evidence.

Local development

Prerequisites: Python 3.12+, Node 22+, npm, and Docker for the container path.

python -m venv .venv
.venv/bin/pip install -e '.[dev]'
.venv/bin/pytest
.venv/bin/ruff check .
.venv/bin/mypy

cd apps/web
npm ci
npm test
npm run lint
npm run typecheck
npm run build

Run against SQLite and load the synthetic sample:

# repository root
.venv/bin/python -m aco_health.cli fixtures/synthetic/bcda_v3.ndjson \
  --source-uri file://synthetic/bcda_v3.ndjson
.venv/bin/uvicorn aco_health.main:app --reload

# separate terminal
cd apps/web
API_INTERNAL_URL=http://localhost:8000 npm run dev

Open http://localhost:3000; API docs are at http://localhost:8000/docs.

BCDA v3 synchronization

BCDA credentials are read only from BCDA_CLIENT_ID and BCDA_CLIENT_SECRET. Keep them in an untracked local environment or secret manager. The CLI exits clearly before making a request when either is absent. It requests only Patient,Coverage,ExplanationOfBenefit, downloads and ingests them in that dependency order, and records only non-secret failure summaries—never bearer tokens or raw response bodies.

After installing the project and loading an untracked environment, start a Group all export:

aco-health-bcda-sync --scope all --since 2026-07-01T00:00:00Z

runout is never implicit:

aco-health-bcda-sync --scope runout

Recover a known job without starting another remote export:

aco-health-bcda-sync --recover-job YOUR_EXISTING_JOB_ID

The configured origin must be HTTPS (official defaults: sandbox https://sandbox.bcda.cms.gov, production https://api.bcda.cms.gov). Job and data URLs are restricted to that exact origin and the v3 /api/v3/jobs/… or /data/… paths before authorization is forwarded. Redirects are rejected. Recovered scope and _since values come only from the completed manifest's authoritative request URL; recovery rejects caller-supplied values. Files default to ./bcda-artifacts; downloads have a configurable byte limit and partial temporary files are removed on failure.

Docker Compose

Copy the non-secret template and replace every replace-* value with locally generated credentials. Compose deliberately has no credential defaults and fails configuration when a required variable is absent. Every published first-slice port binds to 127.0.0.1, including the API, dashboard, PostgreSQL, and MinIO console, while the API uses the temporary trusted-upstream header contract described below.

cp .env.example .env
# edit .env before continuing
docker compose config --quiet
docker compose up --build -d
docker compose exec api python -m aco_health.cli fixtures/synthetic/bcda_v3.ndjson \
  --source-uri s3://synthetic/bcda_v3.ndjson
# restart the server-rendered dashboard only if a browser had cached an earlier error
curl http://localhost:8000/api/v1/executive-summary

Dashboard: http://localhost:3000. MinIO console: http://localhost:9001. MinIO is provisioned as the object-store boundary but the first ingest command intentionally reads a local synthetic file—there is no fake BCDA download/OAuth implementation.

The PostgreSQL-specific raw-to-metrics integration test is guarded against non-test databases. With the Compose database running, create a disposable test database and execute it explicitly:

docker compose exec postgres sh -c 'createdb -U "$POSTGRES_USER" aco_health_test'
set -a
. ./.env
set +a
.venv/bin/pytest -m postgres apps/api/tests/test_postgres_integration.py

Stop and remove local state with docker compose down -v.

API examples

curl http://localhost:8000/api/v1/executive-summary

curl -OJ http://localhost:8000/api/v1/exports/beneficiaries.csv \
  -H 'X-Permissions: beneficiary:export' \
  -H 'X-Actor-Id: local-synthetic-reviewer'

X-Permissions/X-Actor-Id are a trusted-upstream authorization contract, not authentication. They make the permission and audit boundary executable for this slice. Do not expose the API directly in production; replace the dependency with validated identity-provider/gateway claims. Denied exports are HTTP 403; allowed exports write an audit row.

The local Compose loopback binding is a security boundary for this temporary contract. Publishing the API on a non-loopback address would expose caller-supplied authorization headers to that network and is unsupported until a validating gateway or identity provider is in front of the API.

The export contains canonical beneficiary IDs only, paid estimates, and UTC data-through time. The generic EOB provider reference is stored with role unknown; it is never inferred to be a billing or attributed provider. Geography is not derived and should be presented as Unknown until a supplied provider-location source is implemented.

Layout

  • apps/api/src/aco_health/bcda.py — source parser
  • apps/api/src/aco_health/bcda_client.py — BCDA v3 authentication and HTTP contracts
  • apps/api/src/aco_health/bcda_sync.py — durable polling, download, and ordered ingestion
  • apps/api/src/aco_health/artifacts.py — atomic filesystem storage and future-store protocol
  • apps/api/src/aco_health/cli_bcda.py — start/recovery command
  • apps/api/src/aco_health/ingestion.py — raw-to-canonical ingestion
  • apps/api/src/aco_health/models.py — manifests, jobs, canonical lineage, audit
  • apps/api/src/aco_health/metrics.py — paid metric service
  • apps/api/src/aco_health/exports.py — CSV and XLSX adapter boundary
  • apps/api/src/aco_health/main.py — presentation/API
  • apps/web/app/ — dashboard
  • fixtures/synthetic/ — non-PHI sample

Scope boundaries

Real user authentication/authorization, official beneficiary attribution, CMS MSSP HCC modeling, XLSX rendering, scheduling/distributed queues, MinIO/S3 artifact storage, and scale/load validation are deliberately unsupported. BCDA OAuth and Bulk FHIR orchestration are implemented against the documented v3 contract and tested only with synthetic mocked HTTP. No claim of actual CMS sandbox, production, or large-ACO validation is made.

License

Apache License 2.0; see LICENSE.

About

Open-source, self-hosted BCDA v3 population-health analytics foundation for a single ACO

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages