docs: rewrite README — skinny packages, supply chain, cloud providers, accurate counts
All checks were successful
CI / skinny-install (aco) (push) Successful in 49s
CI / skinny-install (api) (push) Successful in 29s
CI / skinny-install (bcda) (push) Successful in 23s
CI / skinny-install (bib) (push) Successful in 35s
CI / skinny-install (bls) (push) Successful in 20s
CI / skinny-install (ccw) (push) Successful in 24s
CI / skinny-install (cli) (push) Successful in 27s
CI / skinny-install (cms) (push) Successful in 24s
CI / skinny-install (conf) (push) Successful in 26s
CI / skinny-install (pfs) (push) Successful in 26s
CI / skinny-install (rex) (push) Successful in 24s
CI / lint-test (push) Successful in 5m49s
Deploy / build-scan-report (push) Successful in 3m5s

This commit is contained in:
kert
2026-03-24 17:42:03 -04:00
parent 85ce5e719d
commit 0a57e9b78f

116
README.md
View File

@@ -2,7 +2,7 @@
![coverage](assets/icons/coverage.svg) ![coverage](assets/icons/coverage.svg)
Healthcare analytics platform on self-hosted infrastructure. Replaces dbt SQL models with narwhals DataFrame-agnostic expression functions, backed by DuckDB locally and Iceberg/Trino in the lakehouse. 22 services, 13 data pipelines, 11,931 tests at 99% coverage. Healthcare analytics platform on self-hosted infrastructure. Replaces dbt SQL models with narwhals DataFrame-agnostic expression functions, backed by DuckDB locally and Iceberg/Trino in the lakehouse. 22 services, 13 data pipelines, 11,955 tests at 99% coverage.
## Quick start ## Quick start
@@ -12,7 +12,6 @@ ROOT_KEY=$(openssl rand -hex 32)
cat > .env <<EOF cat > .env <<EOF
DOMAIN=homelab.fhirworx.io DOMAIN=homelab.fhirworx.io
HOST_IP=192.168.1.192 HOST_IP=192.168.1.192
WOODPECKER_ADMIN=kert
EOF EOF
# 2. Start core services and bootstrap credentials # 2. Start core services and bootstrap credentials
@@ -26,6 +25,20 @@ docker compose up -d
curl -s http://localhost:8000/health | python3 -m json.tool curl -s http://localhost:8000/health | python3 -m json.tool
``` ```
## Installation
The package supports skinny installs — install only the modules you need:
```bash
pip install stack[aco] # ACO analytics only
pip install stack[bib] # bibliography only
pip install stack[cli] # CLI (pulls aco + api + bib)
pip install stack[all] # everything
pip install stack[aco,aws] # ACO analytics with AWS storage
```
11 modules available as optional extras: `conf`, `aco`, `api`, `bcda`, `bib`, `bls`, `ccw`, `cli`, `cms`, `pfs`, `rex`. Cloud providers: `aws`, `gcp`, `azure`. Aggregates: `all`, `lake`.
## Services ## Services
All services route through Traefik at `*.homelab.fhirworx.io`. All services route through Traefik at `*.homelab.fhirworx.io`.
@@ -36,7 +49,6 @@ All services route through Traefik at `*.homelab.fhirworx.io`.
| Notebooks | `notebooks.homelab.fhirworx.io` | Marimo notebooks (GPU-accelerated) | | Notebooks | `notebooks.homelab.fhirworx.io` | Marimo notebooks (GPU-accelerated) |
| Docs | `docs.homelab.fhirworx.io` | Docusaurus — API reference + CMS bibliography | | Docs | `docs.homelab.fhirworx.io` | Docusaurus — API reference + CMS bibliography |
| Gitea | `gitea.homelab.fhirworx.io` | Git server, container registry, LFS | | Gitea | `gitea.homelab.fhirworx.io` | Git server, container registry, LFS |
| Woodpecker CI | `ci.homelab.fhirworx.io` | CI/CD pipelines |
| Zotero | `zotero.homelab.fhirworx.io` | Reference manager (KasmVNC desktop) | | Zotero | `zotero.homelab.fhirworx.io` | Reference manager (KasmVNC desktop) |
| Dashboard | `homelab.fhirworx.io` | Service launcher | | Dashboard | `homelab.fhirworx.io` | Service launcher |
| RustFS | `s3.homelab.fhirworx.io` | S3-compatible object storage | | RustFS | `s3.homelab.fhirworx.io` | S3-compatible object storage |
@@ -54,20 +66,20 @@ All services route through Traefik at `*.homelab.fhirworx.io`.
``` ```
CCLF/BCDA/CMS data CCLF/BCDA/CMS data
│ |
▼ v
src/aco/express/ narwhals expressions (DataFrame-agnostic) src/aco/express/ narwhals expressions (DataFrame-agnostic)
│ |
▼ v
src/aco/pipe/ pipeline runner with schema validation src/aco/pipe/ pipeline runner with schema validation
│ |
▼ v
DuckDB (local) ──or── Iceberg + Trino (lakehouse) DuckDB (local) --or-- Iceberg + Trino (lakehouse) --or-- Databricks
│ |
▼ v
src/api/ FastAPI (health, runs, bib) src/api/ FastAPI (health, runs, bib)
│ |
▼ v
notebooks/ Marimo interactive analysis notebooks/ Marimo interactive analysis
``` ```
@@ -101,10 +113,11 @@ All services route through Traefik at `*.homelab.fhirworx.io`.
- `cfg` — attribute access (`cfg.db.aco`) - `cfg` — attribute access (`cfg.db.aco`)
- `path("db.aco")` — absolute path resolution relative to repo root - `path("db.aco")` — absolute path resolution relative to repo root
- `context()` — environment switching (local/lake/databricks/trino) - `context()` — environment switching (local/lake/databricks/trino/aws/gcp/azure)
- `secret("api.secret", "STACK_API_SECRET")` — env var with config fallback - `secret("api.secret", "STACK_API_SECRET")` — env var with config fallback
- `storage.get_filesystem()` — multi-cloud storage abstraction (S3/GCS/ABFS/local)
Override context at runtime: `STACK_CONTEXT=lake`. Override context at runtime: `STACK_CONTEXT=lake` (or `aws`, `gcp`, `azure`).
### Bibliography ### Bibliography
@@ -137,19 +150,13 @@ uv run python dev/scripts/gen_config.py --check # verify (used in CI)
uv run python dev/scripts/gen_config.py --backend github # one-off override uv run python dev/scripts/gen_config.py --backend github # one-off override
``` ```
The generator: The generator reads image definitions from `stack.toml [images]`, dispatches to the active backend emitter (`dev/scripts/backends/{backend}.py`), writes workflow YAML, and auto-removes stale workflows from inactive backend directories.
1. Reads image definitions from `stack.toml [images]`
2. Dispatches to the active backend emitter (`dev/scripts/backends/{backend}.py`)
3. Writes workflow YAML files to the correct directory
4. Auto-removes stale workflows from inactive backend directories
Each backend has its own `[ci.{backend}]` config section in `stack.toml` with runner labels, registry endpoints, and authentication settings. ### Workflows
### Pipelines Seven workflows generated per backend:
Six workflows generated per backend: | Workflow | Trigger | What it does |
| Pipeline | Trigger | What it does |
|----------|---------|--------------| |----------|---------|--------------|
| `ci.yml` | Push/PR | Ruff lint + format, pytest (99% coverage), gen_config --check, skinny-install matrix | | `ci.yml` | Push/PR | Ruff lint + format, pytest (99% coverage), gen_config --check, skinny-install matrix |
| `deploy.yml` | Push to main | Build 5 images, Trivy scan, vuln reporting | | `deploy.yml` | Push to main | Build 5 images, Trivy scan, vuln reporting |
@@ -157,6 +164,7 @@ Six workflows generated per backend:
| `rebuild-all.yml` | Manual | Full rebuild + scan + deploy | | `rebuild-all.yml` | Manual | Full rebuild + scan + deploy |
| `infra-ci.yml` | Path-filtered push | Hadolint Dockerfiles, dry-run builds | | `infra-ci.yml` | Path-filtered push | Hadolint Dockerfiles, dry-run builds |
| `release.yml` | Tag (`v*`) | `uv build` + release | | `release.yml` | Tag (`v*`) | `uv build` + release |
| `pkg-supply-chain.yml` | Daily / push | Package inventory, mirror sync, drift detection, vuln scan |
### Secret mapping ### Secret mapping
@@ -168,26 +176,27 @@ Six workflows generated per backend:
### Image tagging ### Image tagging
Images are tagged with the short commit SHA (8 chars): Images are tagged with the short commit SHA (8 chars). Compose resolves via `${COMMIT_SHA:-latest}` from `.env`. Custom images: `api`, `notebooks`, `zotero`, `docs`, `mc`.
```
fhirworx/api:22ebc46e
fhirworx/notebooks:a4a2dcb0
fhirworx/docs:a4a2dcb0
```
Compose resolves via `${COMMIT_SHA:-latest}` from `.env`. Custom images: `api`, `notebooks`, `zotero`, `docs`, `mc`.
### Vulnerability management ### Vulnerability management
The `harden.yml` pipeline rebuilds all images with `--no-cache` to pick up OS patches, runs Trivy scans, and auto-files or auto-closes Gitea issues via `api.diag.vuln`. The `harden.yml` pipeline rebuilds all images with `--no-cache` to pick up OS patches, runs Trivy scans, and auto-files or auto-closes Gitea issues via `api.diag.vuln`.
### Package supply chain
Daily automated pipeline (`pkg-supply-chain.yml`) that:
1. Scans Dockerfiles, pyproject.toml, and CI workflows for all package dependencies
2. Syncs packages to the Gitea package registry (local mirror)
3. Detects drift between manifest and mirror
4. Runs Trivy vulnerability scans on dependencies
5. Auto-creates Gitea issues for missing packages and CVEs
## Credential management ## Credential management
All 19 service credentials derive from a single 256-bit root key via HKDF-SHA256. No passwords stored in `.env` — they regenerate deterministically from root key + commit SHA on each deploy. All 19 service credentials derive from a single 256-bit root key via HKDF-SHA256. No passwords stored in `.env` — they regenerate deterministically from root key + commit SHA on each deploy.
``` ```
ROOT_KEY + commit_sha → HKDF-SHA256 → all credentials → .env + backends ROOT_KEY + commit_sha -> HKDF-SHA256 -> all credentials -> .env + backends
``` ```
| Tier | Salt | Rotates | | Tier | Salt | Rotates |
@@ -214,7 +223,7 @@ ROOT_KEY=$KEY uv run python -m api.auth derive $COMMIT_SHA --redact
| `storage` | internal | PostgreSQL, RustFS | | `storage` | internal | PostgreSQL, RustFS |
| `data` | internal | Nessie, Trino, Polaris | | `data` | internal | Nessie, Trino, Polaris |
| `observability` | internal | Grafana, Prometheus, Jaeger, Loki | | `observability` | internal | Grafana, Prometheus, Jaeger, Loki |
| `ci` | external | Woodpecker, Gitea, RustFS | | `ci` | external | Gitea, Act Runner, RustFS |
## Design system ## Design system
@@ -231,6 +240,29 @@ Theme: **loch** (deep-navy). Traefik's `inject-loch` middleware rewrites HTML to
Query via Trino CLI, JDBC, Web UI, PyIceberg, or DuckDB+PyArrow. Query via Trino CLI, JDBC, Web UI, PyIceberg, or DuckDB+PyArrow.
### Cloud deployment
The platform runs on self-hosted Docker Compose by default. Cloud provider guides in `cloud/`:
| Provider | Storage | Catalog | Compute | Context |
|----------|---------|---------|---------|---------|
| Self-hosted | RustFS (S3) | Nessie / Polaris | Docker Compose | `local` / `lake` |
| AWS | S3 | Glue | ECS / EKS | `aws` |
| GCP | GCS | BigQuery | Cloud Run / GKE | `gcp` |
| Azure | ABFS | Unity Catalog | Container Apps / AKS | `azure` |
| Databricks | DBFS | Unity Catalog | Databricks Jobs | `databricks` |
Switch with `STACK_CONTEXT=aws` or edit `stack.toml [context] active`.
## Databricks
Databricks Asset Bundle (`databricks.yml`) is auto-generated from the pipeline registry. 13 pipeline tasks with dependency ordering, 3 targets (dev/staging/prod), daily schedule.
```bash
uv run python dev/scripts/gen_config.py --dab-sql # generate SQL + DDL (~4 min)
databricks bundle deploy -t dev # deploy to Databricks
```
## Project layout ## Project layout
``` ```
@@ -257,16 +289,20 @@ stack/
│ ├── prometheus/ Metrics collection │ ├── prometheus/ Metrics collection
│ ├── loki/ Log aggregation │ ├── loki/ Log aggregation
│ └── ... coredns, nginx, trino, polaris, rustfs, act-runner, gitea │ └── ... coredns, nginx, trino, polaris, rustfs, act-runner, gitea
├── assets/ Branding and styles ├── assets/ Branding, styles, generated artifacts
│ ├── css/ Per-service CSS (dashboard, gitea, marimo, woodpecker) │ ├── css/ Per-service CSS (dashboard, gitea, marimo, woodpecker)
│ ├── icons/ Favicons, logos, SVGs │ ├── icons/ Favicons, logos, coverage badge
│ └── nature.py Nature-conformant chart palette │ └── nature.py Nature-conformant chart palette
├── cloud/ Cloud provider deployment guides ├── cloud/ Cloud provider deployment guides
│ ├── self-hosted/ Docker Compose (default) │ ├── self-hosted/ Docker Compose (default)
│ ├── aws/ S3, RDS, Glue, ECS │ ├── aws/ S3, RDS, Glue, ECS
│ ├── gcp/ GCS, Cloud SQL, BigQuery, Cloud Run │ ├── gcp/ GCS, Cloud SQL, BigQuery, Cloud Run
│ └── azure/ ABFS, Azure SQL, Unity Catalog, Container Apps │ └── azure/ ABFS, Azure SQL, Unity Catalog, Container Apps
├── dev/ Dev tooling (scripts, hooks, seeds) ├── dev/ Dev tooling
│ ├── scripts/ Code generators, bootstrap, supply chain tools
│ ├── hooks/ Git pre-commit hook
│ ├── seeds/ Reference data (BCDA samples, CMS docs)
│ └── pipelines/ CI-agnostic pipeline specs
├── tests/ 11,955 tests at 99% coverage ├── tests/ 11,955 tests at 99% coverage
├── notebooks/ Marimo notebooks ├── notebooks/ Marimo notebooks
├── docs/ Docusaurus site ├── docs/ Docusaurus site