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

5.2 KiB
Raw Permalink Blame History

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