diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 40c2e5f..fc37729 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -58,7 +58,7 @@ These rules govern every task. Any deviation must be discussed and documented as | 1.7 | [Routing skeleton (TanStack Router + role-aware guards)](./phase-1-foundation/07-routing-skeleton.md) | 🟩 | `f4a5e5b` | | 1.8 | [Logout flow](./phase-1-foundation/08-logout-flow.md) | 🟩 | `1ee339c` | | 1.9 | [Gitea CI + Dockerfile + nginx static serve](./phase-1-foundation/09-gitea-ci-and-dockerfile.md) | 🟩 | `9bd3b84` | -| 1.10 | [Compose service block in trm/deploy](./phase-1-foundation/10-deploy-compose-block.md) | ⬜ | — | +| 1.10 | [Compose service block in trm/deploy](./phase-1-foundation/10-deploy-compose-block.md) | 🟩 | trm/deploy `68ab08f` | ### Phase 2 — Live monitoring map diff --git a/.planning/phase-1-foundation/10-deploy-compose-block.md b/.planning/phase-1-foundation/10-deploy-compose-block.md index b8b1c39..07607a9 100644 --- a/.planning/phase-1-foundation/10-deploy-compose-block.md +++ b/.planning/phase-1-foundation/10-deploy-compose-block.md @@ -145,4 +145,32 @@ Add a new "Runtime config override" subsection after "First-deploy checklist": ## Done -(Filled in when the task lands.) +Cross-repo task — all changes land in `trm/deploy`: + +- **`compose.yaml`** — new `spa` service block right after `directus`. Image `git.dev.microservices.al/trm/spa:${SPA_TAG:-main}`. Internal-only (`expose: '80'`, no host publish; reverse proxy fronts it). Volume mount `${SPA_CONFIG_FILE:-./spa-config.json}:/usr/share/nginx/html/config.json:ro` for the runtime-config override. `restart: unless-stopped`. Healthcheck via `wget -qO- http://localhost/`. Replaced the old "Future services land here: react-spa" placeholder comment. +- **`spa-config.example.json`** (new, committed) — dev-default-equivalent file for stage/prod with `env: "stage"`. Operators copy → edit → `cp spa-config.example.json spa-config.json` before first deploy. +- **`.env.example`** — new "spa" section documenting `SPA_TAG` and `SPA_CONFIG_FILE`. Notes the SPA-is-internal-only design and same-origin requirement. +- **`.gitignore`** — added `spa-config.json` so per-environment configs never get committed. +- **`README.md`**: + - "Services in the stack" — moved the SPA from Planned to Currently with a one-liner about the volume-mount override. + - "Set Portainer stack environment variables" optional table — added `SPA_TAG` and `SPA_CONFIG_FILE` rows. Reframed the `DIRECTUS_CORS_*` row as "leave disabled — same-origin proxy means CORS isn't in play." + - **New step 8 — "Verify the SPA loads"** in the first-deploy checklist with the expected happy-path behaviour (redirect to `/login`, login → `/`, hard refresh survives, sign out → `/login`). + - **"Network model"** — added the spa to the no-host-publish list and rewrote the proxy paragraph to spell out the four routes the proxy must wire (`/api/*`, `/ws-business`, `/ws-live`, default → SPA). Same-origin-non-negotiable callout. + - **New "Runtime config override (SPA)" section** — copy → edit → mount workflow, when to override URLs to absolute (don't, unless cross-origin which breaks cookie auth), how to redeploy after editing. + +**Deviations from spec:** + +None significant. The spec also mentioned wanting the proxy stack to be a "sibling Portainer stack or run on the host" — that text was already in the existing README's Network model section before this task touched it; no change needed. + +**Smoke check:** `docker compose config` not run (Docker isn't installed on this machine). The yaml is hand-validated against the existing service blocks' shape — same env-var pattern, same volume-mount pattern, same healthcheck pattern. CI doesn't validate the compose file directly; Portainer will surface yaml errors on first deploy. + +**Required for first deploy** (operator action): + +1. Push the SPA's CI to `main` (1.9) so the `:main` image exists in the registry. +2. In `trm/deploy`, copy `spa-config.example.json` to `spa-config.json` and edit (`env: "stage"`, optional `googleMapsKey`, etc.). +3. Set Gitea repo secrets in `trm/spa` if not already present: `REGISTRY_USERNAME`, `REGISTRY_PASSWORD`, `PORTAINER_WEBHOOK_URL`. +4. Configure the reverse proxy with the four routes documented in the README's Network model section. The SPA needs to be reachable at the public domain root (everything under one origin). +5. Stack redeploy via Portainer. +6. Walk the first-deploy checklist's step 8 — verify the SPA loads. + +Landed in `trm/deploy` `68ab08f`.