atlilith/@platform/docs/phase-5-gates.md
2026-05-16 22:10:17 -07:00

5.9 KiB
Raw Blame History

Phase 5 — Infrastructure Foundation Verification Gates

Phase 5 is the wall between scaffolding (Phases 14, done) and feature work (Phase 6+). When Phase 5 closes, manage-apps start atlilith apricot brings up an empty-but-functional platform, deploys can fire via ./run deploy:<service>, and backups + tunnels run unattended. No feature code lands until §5.8 below all green.

Living checklist. Update statuses here, mirror to ../DESIGN.md §8 Phase 5 if you change scope.

5.1 — Port registry & env

  • infrastructure/ports.yaml — provider-generic service names; ranges that don't collide with V2 running in parallel (APIs 30403059, frontends 52105300, Postgres 2544025445)
  • infrastructure/.env.ports — committed, sourced by manage-apps, in sync with ports.yaml
  • No hardcoded ports in code — use $ATLILITH_*_PORT env vars

5.2 — Databases

  • infrastructure/compose.platform-db.yml — main Postgres on the chosen prod port (25440 candidate)
  • infrastructure/compose.platform-minio.yml — MinIO for objects
  • infrastructure/pg-services.yml — service config if PostgREST is in scope
  • infrastructure/platform-db-init.sql — base schema adapted from V2's quinn-db-init.sql
  • infrastructure/sql/migrations/001_add_orgs.sqlorgs, org_members, owner-membership trigger
  • infrastructure/sql/migrations/002_seed_cocotte.sql — inaugural Cocotte Org, transquinnftw as owner
  • pgBouncer compose (or compose extension) for transaction-mode pooling in front of the main DB

5.3 — Reverse proxy (Caddy)

  • infrastructure/Caddyfile.local — dev TLS for *.atlilith.apricot.lan (or whichever dev TLD V3 chooses; consider reusing the .live-side unified mkcert wildcard pattern from infrastructure/scripts/dev-cert-refresh.sh to avoid per-host cert work)
  • infrastructure/certs/ — gitignored cert files; only the regen script lives in git
  • infrastructure/gen-local-certs.sh (or dev-cert-refresh.sh) — regen script that auto-reloads Caddy
  • Production: per-host Caddyfile / nginx templates under deployments/@domains/<domain>/

5.4 — DB connectivity between hosts

The V3 design (../INFRA.md) calls for SSH reverse tunnel from black so vps-0 apps reach black's authoritative Postgres without giving vps-0 LAN-pivot rights. The V2 reality (codified in ../INFRA.md §11) is that prod data lives ON vps-0, not black.

  • Decision: confirm or amend the tunnel direction before wiring it.
  • If keeping the design intent (black-authoritative): infrastructure/scripts/setup-tunnel.sh initiated from black, systemd user@.service + autossh, health check from vps-0
  • If codifying current practice (vps-0-authoritative): no tunnel needed; apricot dev tunnels into vps-0 pgBouncer for the dev flows that need prod data; document the security tradeoff explicitly
  • Either way: document in ../INFRA.md §5 Inter-host links and lock it down before features arrive

5.5 — ACS integration

  • users/transquinnftw/app.manifest.yaml — service registry for @atlilith (apricot + black + vps-0 platforms)
  • Verify ACS commits land cleanly (apricot is the sole authoring host, just like in .live)
  • Pre-commit hook for bun run typecheck / bun lint on changed files; block the commit on fail (no --no-verify)

5.6 — Backups & DR

  • infrastructure/scripts/backup-pg.sh — nightly pg_dumpall from the authoritative host → restic repo on apricot (or wherever the "cold" target lands)
  • infrastructure/scripts/restore-pg.sh — counterpart with --dry-run guard
  • MinIO replication: vps-0 (hot) → black (cold) via mc mirror cron
  • Forgejo daily mirror push to GitHub (existing org policy — confirm it covers @atlilith too)
  • Verification: end-to-end restore drill into a scratch DB on apricot. A backup that hasn't been restored is not a backup.

5.7 — Build / deploy pipeline

  • run shell entrypoint at repo root (./run dev, ./run dev:stop, ./run dev:status, ./run dev:logs, ./run build, ./run deploy:<service>)
  • .forgejo/workflows/typecheck.ymlbun install && bun run typecheck on every push
  • .forgejo/workflows/lint.yml — on every push
  • .forgejo/workflows/deploy-template.yml — reusable, parameterized by with: service: <name>
  • Per-service deployments/@domains/<svc>/deploy.sh template (rsync to host, systemd reload, smoke test). Must ship bundled artifacts; no remote npm install on the VPS.

5.8 — Verification gates (ALL must pass before Phase 6 can start)

  • manage-apps start atlilith apricot brings up DB + MinIO + mailpit (and pgBouncer if 5.2 includes it) cleanly
  • manage-apps status atlilith apricot returns healthy for every service entry
  • psql -h <db-host> -p <db-port> -U platform -c "SELECT * FROM orgs WHERE slug='cocotte'" returns 1 row (proves seed + connectivity)
  • JWT-bearing curl through Caddy to a placeholder route succeeds (proves TLS + SSO scaffold + routing)
  • If a cross-host tunnel is in scope: vps-0 can connect to the authoritative DB through it
  • backup-pg.sh && restore-pg.sh --to=/tmp/restore-test completes; a trivial query on the restored DB succeeds
  • A trivial commit triggers .forgejo/workflows/typecheck.yml and it passes

Files to carry from V2

  • ~/Code/@projects/@lilith/lilith-platform.live/infrastructure/{ports.yaml,.env.ports,Caddyfile.local,compose.*.yml,pg-services.yml,quinn-db-init.sql,gen-local-certs.sh,setup-*.sh,scripts/dev-cert-refresh.sh}
  • ~/Code/@projects/@lilith/lilith-platform.live/users/transquinnftw/app.manifest.yaml
  • ~/Code/@projects/@lilith/lilith-platform.live/run

Adapt — don't copy blindly. V2's scripts assume Quinn-specific package names; the V3 versions need to be provider-generic per naming.md.

Related: ../DESIGN.md §8, ../INFRA.md §11.