docs + hardening: CI backend switching, README update, zotero CVEs (refs #150, #158)
Some checks failed
CI / skinny-install (aco) (push) Failing after 8s
CI / skinny-install (api) (push) Failing after 7s
CI / skinny-install (bcda) (push) Failing after 7s
CI / skinny-install (bib) (push) Failing after 7s
CI / skinny-install (bls) (push) Failing after 8s
CI / skinny-install (ccw) (push) Failing after 8s
CI / skinny-install (cli) (push) Failing after 7s
CI / skinny-install (cms) (push) Failing after 7s
CI / skinny-install (conf) (push) Failing after 8s
CI / skinny-install (pfs) (push) Failing after 8s
CI / skinny-install (rex) (push) Failing after 7s
CI / lint-test (push) Has been cancelled
Infra CI / notebooks (push) Failing after 6s
Infra CI / zotero (push) Failing after 7s
Infra CI / docs (push) Successful in 39s
Infra CI / api (push) Successful in 9s
Infra CI / mc (push) Successful in 6s
Deploy / build-scan-report (push) Has been cancelled
Some checks failed
CI / skinny-install (aco) (push) Failing after 8s
CI / skinny-install (api) (push) Failing after 7s
CI / skinny-install (bcda) (push) Failing after 7s
CI / skinny-install (bib) (push) Failing after 7s
CI / skinny-install (bls) (push) Failing after 8s
CI / skinny-install (ccw) (push) Failing after 8s
CI / skinny-install (cli) (push) Failing after 7s
CI / skinny-install (cms) (push) Failing after 7s
CI / skinny-install (conf) (push) Failing after 8s
CI / skinny-install (pfs) (push) Failing after 8s
CI / skinny-install (rex) (push) Failing after 7s
CI / lint-test (push) Has been cancelled
Infra CI / notebooks (push) Failing after 6s
Infra CI / zotero (push) Failing after 7s
Infra CI / docs (push) Successful in 39s
Infra CI / api (push) Successful in 9s
Infra CI / mc (push) Successful in 6s
Deploy / build-scan-report (push) Has been cancelled
- Add CI backend switching section to README with backend table, switch instructions, secret mapping, and workflow descriptions - Update project layout section to reflect P24 tree reorg (infra/, assets/, cloud/) - Fix stale references: styles/ → assets/, .woodpecker/ → .gitea/ - Fix gen_config.py --help to list all 3 backends (gitea|github|woodpecker) - Add dist-upgrade + CVE commentary to zotero Dockerfile; Go stdlib CVEs (CVE-2024-24790, CVE-2025-68121) are in base image static binaries — tracked by weekly harden.yml --no-cache rebuilds
This commit is contained in:
117
README.md
117
README.md
@@ -1,6 +1,6 @@
|
||||
# Stack
|
||||
|
||||

|
||||

|
||||
|
||||
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.
|
||||
|
||||
@@ -112,16 +112,59 @@ Override context at runtime: `STACK_CONTEXT=lake`.
|
||||
|
||||
## CI/CD
|
||||
|
||||
Six Woodpecker pipelines in `.woodpecker/`:
|
||||
### Backend switching
|
||||
|
||||
CI/CD workflows are auto-generated from `stack.toml` by `gen_config.py`. Three backends are supported:
|
||||
|
||||
| Backend | Workflows directory | When to use |
|
||||
|---------|---------------------|-------------|
|
||||
| `gitea` | `.gitea/workflows/` | Self-hosted Gitea instance (default) |
|
||||
| `github` | `.github/workflows/` | GitHub repos / GitHub Actions |
|
||||
| `woodpecker` | `.woodpecker/` | Woodpecker CI server |
|
||||
|
||||
Switch backends by editing `stack.toml`:
|
||||
|
||||
```toml
|
||||
[ci]
|
||||
backend = "gitea" # change to "github" or "woodpecker"
|
||||
```
|
||||
|
||||
Then regenerate:
|
||||
|
||||
```bash
|
||||
uv run python dev/scripts/gen_config.py # generate new workflows
|
||||
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
|
||||
```
|
||||
|
||||
The generator:
|
||||
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.
|
||||
|
||||
### Pipelines
|
||||
|
||||
Six workflows generated per backend:
|
||||
|
||||
| Pipeline | Trigger | What it does |
|
||||
|----------|---------|--------------|
|
||||
| `ci.yml` | Push | Ruff lint, pytest, marimo check |
|
||||
| `deploy.yml` | Push to main | Build images, Trivy scan, deploy, rotate credentials |
|
||||
| `harden.yml` | Manual/cron | Rebuild all images `--no-cache`, scan, auto-close vuln issues |
|
||||
| `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 |
|
||||
| `harden.yml` | Weekly cron / manual | Rebuild `--no-cache`, scan, auto-close/file vuln issues |
|
||||
| `rebuild-all.yml` | Manual | Full rebuild + scan + deploy |
|
||||
| `infra-ci.yml` | Push | Hadolint Dockerfiles, build validation |
|
||||
| `release.yml` | Tag | Release pipeline |
|
||||
| `infra-ci.yml` | Path-filtered push | Hadolint Dockerfiles, dry-run builds |
|
||||
| `release.yml` | Tag (`v*`) | `uv build` + release |
|
||||
|
||||
### Secret mapping
|
||||
|
||||
| Secret | Gitea | GitHub | Woodpecker |
|
||||
|--------|-------|--------|------------|
|
||||
| Registry auth | `REGISTRY_USER` + `REGISTRY_TOKEN` | `GITHUB_TOKEN` (built-in) | `registry_username` + `registry_password` |
|
||||
| Gitea API | `GITEA_TOKEN` | N/A | `gitea_token` |
|
||||
| Vuln reporting | `GITEA_TOKEN` | `GITHUB_TOKEN` | `gitea_token` |
|
||||
|
||||
### Image tagging
|
||||
|
||||
@@ -175,7 +218,7 @@ ROOT_KEY=$KEY uv run python -m api.auth derive $COMMIT_SHA --redact
|
||||
|
||||
## Design system
|
||||
|
||||
Theme: **loch** (deep-navy). Traefik's `inject-loch` middleware rewrites HTML to inject `loch.css` and the favicon. Per-service CSS in `styles/`. Altair chart theme in `styles/nature.py` (Nature-conformant, accessible palette, IBM Plex Mono headings).
|
||||
Theme: **loch** (deep-navy). Traefik's `inject-loch` middleware rewrites HTML to inject `loch.css` and the favicon. Per-service CSS in `assets/css/`. Altair chart theme in `assets/nature.py` (Nature-conformant, accessible palette, IBM Plex Mono headings).
|
||||
|
||||
## Data lakehouse
|
||||
|
||||
@@ -194,34 +237,40 @@ Query via Trino CLI, JDBC, Web UI, PyIceberg, or DuckDB+PyArrow.
|
||||
stack/
|
||||
├── compose.yml Docker Compose (22 services)
|
||||
├── stack.toml Centralised configuration
|
||||
├── pyproject.toml Python project (uv)
|
||||
├── pyproject.toml Python project (uv, optional deps per module)
|
||||
├── src/
|
||||
│ ├── aco/
|
||||
│ │ ├── express/ narwhals transformation functions (15 modules)
|
||||
│ │ ├── pipe/ pipeline runner + 13 pipeline modules
|
||||
│ │ ├── table/ table schemas with column metadata
|
||||
│ │ └── dag.py pipeline DAG
|
||||
│ ├── api/
|
||||
│ │ ├── routes/ health, pipelines, bib endpoints
|
||||
│ │ ├── auth/ HKDF credential derivation + provisioning
|
||||
│ │ └── diag/ Trivy vuln reporter
|
||||
│ ├── bib/ Zotero store, tags, metadata
|
||||
│ ├── conf/ Config loader (cfg, path, context, secret)
|
||||
│ ├── bcda/ BCDA API client
|
||||
│ ├── cms/ CMS data utilities
|
||||
│ ├── aco/ ACO analytics (express, pipe, table, lake, load)
|
||||
│ ├── api/ FastAPI server + auth + diag
|
||||
│ ├── bcda/ BCDA FHIR R4 client
|
||||
│ ├── bib/ Zotero bibliography store, tags, metadata
|
||||
│ ├── bls/ BLS data
|
||||
│ ├── ccw/ CCW data dictionary
|
||||
│ ├── cli/ CLI entry point (typer)
|
||||
│ ├── cms/ CMS public data tables
|
||||
│ ├── conf/ Config loader, storage abstraction, table base
|
||||
│ ├── pfs/ Physician Fee Schedule
|
||||
│ └── rex/ REX data processing
|
||||
├── notebooks/ Marimo notebooks (12 notebooks)
|
||||
├── tests/ 11,931 tests at 99% coverage
|
||||
├── styles/ Loch design system (CSS, favicons, nature.py)
|
||||
├── docs/ Docusaurus site (griffe → Node → nginx)
|
||||
├── .woodpecker/ CI/CD pipelines (6 pipelines)
|
||||
├── api/Dockerfile FastAPI service
|
||||
├── notebooks/Dockerfile Marimo + CUDA 12.6 + cuDF
|
||||
├── zotero/Dockerfile Zotero desktop (KasmVNC + GPU)
|
||||
├── docs/Dockerfile 3-stage: griffe → pnpm build → nginx:alpine
|
||||
├── traefik/ Reverse proxy config + loch injection
|
||||
├── data/ DuckDB, bib.sqlite, BCDA/CMS data
|
||||
│ └── rex/ REX fixed-width file processing
|
||||
├── infra/ Service configs and Dockerfiles
|
||||
│ ├── images/ All Dockerfiles (api, notebooks, zotero, docs, mc)
|
||||
│ ├── traefik/ Reverse proxy + loch CSS injection
|
||||
│ ├── grafana/ Dashboards and datasource provisioning
|
||||
│ ├── prometheus/ Metrics collection
|
||||
│ ├── loki/ Log aggregation
|
||||
│ └── ... coredns, nginx, trino, polaris, rustfs, act-runner, gitea
|
||||
├── assets/ Branding and styles
|
||||
│ ├── css/ Per-service CSS (dashboard, gitea, marimo, woodpecker)
|
||||
│ ├── icons/ Favicons, logos, SVGs
|
||||
│ └── nature.py Nature-conformant chart palette
|
||||
├── cloud/ Cloud provider deployment guides
|
||||
│ ├── self-hosted/ Docker Compose (default)
|
||||
│ ├── aws/ S3, RDS, Glue, ECS
|
||||
│ ├── gcp/ GCS, Cloud SQL, BigQuery, Cloud Run
|
||||
│ └── azure/ ABFS, Azure SQL, Unity Catalog, Container Apps
|
||||
├── dev/ Dev tooling (scripts, hooks, seeds)
|
||||
├── tests/ 11,955 tests at 99% coverage
|
||||
├── notebooks/ Marimo notebooks
|
||||
├── docs/ Docusaurus site
|
||||
├── data/ DuckDB, bib.sqlite, BCDA/CMS data (gitignored)
|
||||
└── .env Derived credentials (not in git)
|
||||
```
|
||||
|
||||
|
||||
@@ -218,7 +218,9 @@ def main() -> int:
|
||||
help="Verify files are up-to-date (exit 1 if not)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--backend", default=None, help="Override CI backend (woodpecker|github)"
|
||||
"--backend",
|
||||
default=None,
|
||||
help="Override CI backend (gitea|github|woodpecker)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--dab-sql",
|
||||
|
||||
@@ -3,8 +3,17 @@ FROM ghcr.io/selkies-project/nvidia-egl-desktop:latest
|
||||
|
||||
USER root
|
||||
|
||||
# System-level security patches — pulls latest fixes for all OS packages.
|
||||
# Go stdlib CVEs (CVE-2024-24790, CVE-2025-68121) are in static binaries
|
||||
# from the base image; they resolve when upstream rebuilds with patched Go.
|
||||
# The harden.yml weekly --no-cache rebuild ensures we track upstream fixes.
|
||||
RUN apt-get update \
|
||||
&& apt-get upgrade -y \
|
||||
&& apt-get dist-upgrade -y \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install Zotero
|
||||
RUN apt-get update && apt-get upgrade -y && apt-get install -y --no-install-recommends \
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
curl \
|
||||
ca-certificates \
|
||||
&& curl -sL https://raw.githubusercontent.com/retorquere/zotero-deb/master/install.sh | bash \
|
||||
|
||||
Reference in New Issue
Block a user