# Deployment Architecture

## Single published port

Production Docker Compose (`compose.yml`) publishes **exactly one** host port: `edge` (Nginx), mapped via `APP_HTTPS_PORT` (default `443`). No other service (`api`, `worker`, `postgres`, `redis`) defines a Compose `ports:` mapping — they are reachable only over the internal `travel` bridge network via their service DNS names. `scripts/verify-compose-invariants.mjs` (wired into `pnpm test:compose`) fails the build if this invariant regresses.

## TLS

The edge container listens on container port 443 only and requires a certificate and private key mounted at the paths configured by `TLS_CERT_FILE`/`TLS_KEY_FILE` (bind-mounted read-only to `/run/tls/tls.crt` and `/run/tls/tls.key`). There is no port-80 fallback in this phase.

## Internal reachability

- PostgreSQL and Redis are not reachable from the host through Compose-published ports; only containers on the `travel` network can reach them.
- The API is not reachable from the host directly; all external traffic reaches it through `edge`'s `/api/` and `/health/` proxy locations.
- The worker process has neither `ports` nor `expose` — it accepts no inbound traffic at all.
- Outbound egress from `api` and `worker` (e.g. to Mistral, web research, SMTP providers in later phases) remains allowed.

## Image tags

TeamCity supplies immutable `IMAGE_TAG` values (see `scripts/teamcity/build-images.sh`); `latest`/floating tags are refused. `REGISTRY` and `IMAGE_TAG` together select the exact image digest-equivalent tag deployed to a host.

## TeamCity wiring

| TeamCity stage        | Repository entry point          |
|------------------------|----------------------------------|
| Validate               | `scripts/teamcity/validate.sh`  |
| Build + Push           | `scripts/teamcity/build-images.sh` |
| Deploy over SSH        | `scripts/teamcity/deploy.sh`    |
| Post-deploy smoke      | `scripts/teamcity/smoke.sh`     |
| Rollback               | `scripts/teamcity/rollback.sh`  |

The existing TeamCity project configures these as command-line/SSH build steps; all deployment logic stays in version control, not in TeamCity step configuration.
