Files
Ty 5a210c47b0 docs(m3): reconcile the remaining docs with the settled design
Docs written before this thread still carried the three-source copy model and
the Call 2 fields it implied.

- REQUIREMENTS.md REVIEW-10: title and short description are deterministic; the
  description comes from the model or the server.
- CREATE.md: primary category declared before Call 2; deterministic copy; the
  prompt revision interface; the slug; auth row in out-of-scope.
- API.md: infer-content inputs and result are the long description only.
- UAT-PRACTICE.md: the walk no longer tells the owner to leave copy for
  templates.
- README.md: the deploy section duplicated docs/DEPLOYMENT.md and
  deploy/INVENTORY.md; it now points at them.
- DEPLOYMENT.md: the prompt seed is stated per METADATA-105.

Both gates pass.
2026-09-19 13:17:37 -07:00

113 lines
5.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Deployment
Role: ops. This is the canonical runbook for getting a build from a working tree to a live
dev/test host. `deploy/INVENTORY.md` is the only source for what runs where (hosts, ports,
container names). `docs/UAT-PRACTICE.md` is the human walk once the app is up; this doc is what
makes it up.
## 1. Topology
| Node | Role | Reach |
|---|---|---|
| Ty dev box (Windows) | code, git push to Gitea. No Docker CLI. | LAN + Tailscale |
| Gitea (`gitea.vps1.afterthedemo.com`) | source of truth for the repo. SSH port closed; HTTPS only. | Tailscale |
| `ubudual5060` (UAT host, LAN `192.168.1.202`, Tailscale `100.64.0.9`) | builds and runs Docker images for UAT. | LAN + Tailscale |
The dev box never builds images. The UAT host pulls source from Gitea and builds locally.
Do not install Docker on the dev box to work around this; the pull-build path is the plan.
## 2. Access (already provisioned; do not re-do)
- Dev box → UAT host: `ssh ubudual5060` (key `~/.ssh/ubudual5060`, wired in `~/.ssh/config`).
Unattended, passphrase-less.
- UAT host → Gitea: HTTPS with a read-only token named `5060-pull`, stored in
`~/.git-credentials` on the host. The host clones/pulls with the plain HTTPS URL;
no key material in the repo.
- Deploy checkout on the UAT host: `~/slab-deploy` (branch `main`).
The pre-existing `~/SlabUploader` on that host is a stale work clone — do not use it.
If access is broken, fix it here before touching compose. Do not commit credentials to the repo.
## 3. Build and deploy (M3)
Precondition: the M3 scaffold exists on the branch being deployed — `frontend/Dockerfile`,
`backend/Dockerfile`, and `deploy/.env` on the host. `main` currently
has `frontend/Dockerfile` only; `backend/` lands with M3 implementation.
Prompts live in SQLite with all revisions, seeded from the text in `docs/contracts/PROMPTS.md` §6 on
first run; no prompt files ship with the image (`METADATA-105`).
1. Push the branch to Gitea from the dev box.
2. On the UAT host:
```
cd ~/slab-deploy
git fetch origin && git checkout <branch> && git pull
cp deploy/.env.example deploy/.env && chmod 600 deploy/.env # first time only
docker compose -f deploy/docker-compose.yml --env-file deploy/.env build
docker compose -f deploy/docker-compose.yml --env-file deploy/.env up -d
```
3. Verify with the smoke checks in §5.
### `.env` values
Generate on the UAT host, never in the repo:
- `SLAB_AES_KEY` — `openssl rand -base64 32`
- `WOO_BASE_URL` — the store, `https://` only. FastAPI refuses `http://` at startup.
- `APP_HOSTNAME` — from `deploy/INVENTORY.md`.
- `FRONTEND_PORT` / `FASTAPI_PORT` — see the port override below.
Woo Application Password and inference keys are not in `.env`; they are entered in the app's
Settings and stored AES-GCM encrypted in the app's SQLite.
### Port binding for the dev-test environment
`deploy/docker-compose.yml` binds `127.0.0.1` only (Caddy is the TLS edge in the full stack).
The dev-test environment is reached directly on a port from the project block
`10880`–`10889` (per `deploy/INVENTORY.md`) and **must be reachable from any machine on
`192.168.1.0/24`**, so the deploy must override the port bindings to `0.0.0.0`
(compose override file or `ports:` edit scoped to this deploy). Never bind `:10880`
(Ty's local Node/SvelteKit) or Ty's `:18080`.
M3 takes over port `10881` from the M2 container (`slabuploader-m2-overnight`),
per the replace-prior-container rule in `deploy/INVENTORY.md`.
Remove the M2 container when the M3 one is healthy.
## 4. Local loop (no UAT host needed)
- Frontend: `cd frontend && npm install && npm run dev` (Vite).
- Backend: `uvicorn` from `backend/` once the M3 scaffold lands; needs the same env vars as §3.
- Tests: frontend `npm test` (Playwright config in `frontend/`); backend tests land with M3.
Use the local loop for iteration; use §3 for anything Ty must see on a phone.
## 5. Smoke checks (after every deploy)
Run from the UAT host, then from a phone on the same network (LAN or Tailscale):
1. `curl -fsS http://127.0.0.1:<frontend-port>/api/health` on the host returns ok.
2. Phone browser opens the inventory URL (`deploy/INVENTORY.md`) and the app loads.
3. `docker compose -f deploy/docker-compose.yml --env-file deploy/.env ps` shows both services
up; `docker logs` for `fastapi` shows no startup refusal (WOO_BASE_URL is `https://`).
4. `test-woo` in app Settings reports ok (store reachable, taxonomy synced).
If a check fails, the deploy is not live. Roll back per §6 before debugging on the live port.
## 6. Rollback
1. `docker compose -f deploy/docker-compose.yml --env-file deploy/.env down` on the UAT host.
2. Check out the last known-good ref in `~/slab-deploy` and re-run §3 steps 2–3.
3. Re-run §5. Volumes `slab_db` and `slab_images` persist across rollback; do not remove them
unless the data itself is the problem.
## Where each rule lives
| Rule | Source |
|---|---|
| Hosts, ports, container names | `deploy/INVENTORY.md` |
| Compose shape, env contract | `deploy/docker-compose.yml`, `deploy/.env.example` |
| UAT walk once the app is up | `docs/UAT-PRACTICE.md` |
| M3 scope and exit | `docs/MILESTONES.md`, `docs/REQUIREMENTS.md` |
| Woo auth model | `AGENTS.md`, `docs/contracts/CONTENT-WOO.md` |