# SEC-002 ingress and Compose verification Date: 2026-08-02 Status: `VERIFIED LOCALLY`; operator Traefik and production checks remain. ## Implemented boundary - Production automation explicitly selects `docker-compose.yml`; the auto-loaded override was replaced by explicitly selected `docker-compose.dev.yml`. - Base Compose retains the frontend's production compatibility port 3000 because the operator-owned reverse proxy still targets that host port. Backend, ai-service, and bundled Ollama remain unpublished; development additionally exposes backend 5202 and profile-scoped Ollama 11434. - Nginx and backend communicate over an internal dedicated CIDR; the backend accepts exactly one forwarded hop only from that CIDR. - Nginx derives its application server name from `APP_PUBLIC_BASE_URL`, rejects other Hosts except `/health`, and preserves Traefik's replaced proto/client headers rather than substituting internal HTTP. - Deploy preflight requires and validates the canonical origin and dedicated proxy CIDR. CI post-deploy commands use the production Compose file explicitly. ## Commands and results | Command/check | Result | |---|---| | focused `ExternalOriginTests` including proxy config | Pass; 14/14 | | full backend Release suite | Pass; 476/476 | | frontend `npm run build` | Pass; Next production build and TypeScript | | production and dev `docker compose ... config --quiet` | Pass | | parsed Compose assertion including `bundled-ollama` | Pass; production ports absent; dev 3000/5202/11434; internal CIDR aligned | | normalized `bash -n deploy/deploy.sh` | Pass | | `bash -n job-tracker-ui/configure-nginx-origin.sh` | Pass | | mounted nginx template `nginx -t` using already-installed local frontend image | Pass | | ephemeral origin substitution with canonical host/port then `nginx -t` | Pass | | ephemeral substitution with credential-bearing origin | Rejected as expected | | `git diff --check` | Pass; line-ending conversion warnings only | No image was pulled and no production or persistent service was changed. Ephemeral Docker validation containers were removed automatically. ## Limitations and production gates - No Traefik configuration exists in this repository. Production verification proved it still targets host port 3000, so that compatibility ingress remains. Migrate Traefik onto `jobtracker_shared`, verify its exact `Host()` rule/TLS/header handling, then remove the host port in a coordinated release. - `WEB_PROXY_SUBNET` must be chosen after production Docker-network inventory. Deploys recover a missing value from a uniquely labelled existing Compose `web_proxy` network. On its first creation, the documented `172.31.250.0/29` candidate is accepted only after a complete Docker network inventory proves it does not overlap; unreadable or overlapping inventory remains fail-closed. - Host firewall and `docker ps`/published-port state are unverified. - The exact `nginx:1.29.8-alpine` base image was not installed locally. Syntax was checked with the existing local nginx frontend image; approved CI must build the pinned Dockerfile. - A complete local proxy/browser smoke was not run because rebuilding the pinned container would require an unavailable base image/package access. No browser claim is made. - Rollback is a normal application-version rollback plus the previous `.env`; do not reintroduce the deleted auto-loaded override or published production ports. If the new CIDR overlaps, roll back before replacement and select a non-overlapping CIDR.