# with — FastAPI app + Postgres 17 sidecar (replaced the static-nginx
# scaffold at M0). Deploy: srv-gw deploy --project with --build

services:
  app:
    build: .
    container_name: ${PROJECT_NAME}-app
    restart: unless-stopped

    # DO NOT CHANGE - port is managed by gateway
    ports:
      - "172.17.0.1:${PORT}:3000"

    env_file:
      - .env                  # WITH_DB_URL + sidecar password
      - .supabase-export.env  # SUPABASE_DB_* (read-only source, nightly snapshot)
      - .bw-auth.env          # BW_CLIENT_ID + BW_CLIENT_SECRET (600, written by
                              # app-client-register --secret-out; never in git/chat)
      - .registry.env         # REGISTRY_SERVICE_TOKEN (600, machine-generated;
                              # satellites get a copy provisioned by the owner
                              # session — ADR #014; never in git/chat)
    environment:
      TZ: America/Vancouver   # nightly snapshot fires at 03:30 local
      APP_ENV: production     # hard-refuses the AUTH_DEV_USER stub (T-AZ-043)
      BW_AUTH: https://auth.bowden.works
      BW_APP_DOMAIN: https://with.bowden.works

    volumes:
      # Diff-harness code + output live on the host (workstream C edits the
      # extractor without a rebuild; baselines/status land in harness/out/).
      - ./harness:/app/harness
      # Nightly sidecar dumps (books backups) — host/NAS rotation reads these.
      - ./backups:/app/backups
      # PlusROI sheet export (read-only) — the nightly rebuild's second
      # source (books_source="auto" finds books-import/source; ADR #016).
      - ./books-import:/app/books-import:ro

    depends_on:
      db:
        condition: service_healthy

    healthcheck:
      test: ["CMD", "python", "-c",
             "import urllib.request; urllib.request.urlopen('http://127.0.0.1:3000/healthz', timeout=3)"]
      interval: 30s
      timeout: 5s
      start_period: 20s
      retries: 3

    networks: [default, internal]
    mem_limit: 1g

  db:
    image: postgres:17  # major-pinned — the pgdata volume is tied to it
    container_name: ${PROJECT_NAME}-db
    restart: unless-stopped

    # pg_stat_statements — query-level observability for the perf pass
    # (09-build-plan §M8). Preloaded here; the extension itself is created
    # once after this lands with:
    #   psql "$WITH_DB_URL_HOST" -c 'CREATE EXTENSION IF NOT EXISTS pg_stat_statements'
    # (see docs/PERF.md). track=all also counts nested statements.
    command:
      - "postgres"
      - "-c"
      - "shared_preload_libraries=pg_stat_statements"
      - "-c"
      - "pg_stat_statements.track=all"
      - "-c"
      - "pg_stat_statements.max=10000"

    # Host-local ONLY (psql / diff harness / backups) — never 0.0.0.0,
    # never the Docker bridge IP (04-architecture.md).
    ports:
      - "127.0.0.1:54317:5432"

    environment:
      POSTGRES_DB: with
      POSTGRES_USER: with
      POSTGRES_PASSWORD: ${WITH_DB_PASSWORD}

    volumes:
      - pgdata:/var/lib/postgresql/data

    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U with -d with"]
      interval: 5s
      timeout: 3s
      retries: 12

    # On BOTH networks: `internal` carries app<->db traffic; `default` is
    # required because Docker does not publish ports for containers attached
    # only to internal networks (the 127.0.0.1:54317 psql path would silently
    # break). `default` is project-scoped and the published port binds
    # loopback only, so nothing outside this compose project reaches the db.
    networks: [internal, default]
    mem_limit: 1g

volumes:
  pgdata:

networks:
  internal:
    internal: true
