# tools/federation-harness/docker-compose.two-gateways.yml
#
# Two-gateway federation test harness — local-only, no Portainer/Swarm needed.
#
# USAGE (manual):
#   docker compose -f tools/federation-harness/docker-compose.two-gateways.yml up -d
#   docker compose -f tools/federation-harness/docker-compose.two-gateways.yml down -v
#
# USAGE (from harness.ts):
#   const handle = await bootHarness();
#   ...
#   await tearDownHarness(handle);
#
# TOPOLOGY:
#   gateway-a  — "home" instance (Server A, the requesting side)
#     └── postgres-a  (pgvector/pg17, port 15432)
#     └── valkey-a    (port 16379)
#   gateway-b  — "work" instance (Server B, the serving side)
#     └── postgres-b  (pgvector/pg17, port 15433)
#     └── valkey-b    (port 16380)
#   step-ca    — shared CA for both gateways (port 19000)
#
# All services share the `fed-test-net` bridge network.
# Host port ranges (15432-15433, 16379-16380, 14001-14002, 19000) are chosen
# to avoid collision with the base dev stack (5433, 6380, 14242, 9000).
#
# IMAGE:
#   Pinned to the immutable digest sha256:1069117740e00ccfeba357cae38c43f3729fe5ae702740ce474f6512414d7c02
#   (sha-9f1a081, post-#491 IMG-FIX, smoke-tested locally).
#   Update this digest only after a new CI build is promoted to the registry.
#
# STEP-CA:
#   Single shared Step-CA instance. Both gateways connect to it.
#   CA volume is ephemeral per `docker compose down -v`; regenerated on next up.
#   The harness seed script provisions the CA roots cross-trust after first boot.

services:
  # ─── Shared Certificate Authority ────────────────────────────────────────────
  step-ca:
    image: smallstep/step-ca:0.27.4
    container_name: fed-harness-step-ca
    restart: unless-stopped
    ports:
      - '${STEP_CA_HOST_PORT:-19000}:9000'
    volumes:
      - step_ca_data:/home/step
      - ../../infra/step-ca/init.sh:/usr/local/bin/mosaic-step-ca-init.sh:ro
      - ../../infra/step-ca/templates:/etc/step-ca-templates:ro
      - ../../infra/step-ca/dev-password:/run/secrets/ca_password:ro
    entrypoint: ['/bin/sh', '/usr/local/bin/mosaic-step-ca-init.sh']
    networks:
      - fed-test-net
    healthcheck:
      test:
        [
          'CMD',
          'step',
          'ca',
          'health',
          '--ca-url',
          'https://localhost:9000',
          '--root',
          '/home/step/certs/root_ca.crt',
        ]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s

  # ─── Server A — Home / Requesting Gateway ────────────────────────────────────
  postgres-a:
    image: pgvector/pgvector:pg17
    container_name: fed-harness-postgres-a
    restart: unless-stopped
    ports:
      - '${PG_A_HOST_PORT:-15432}:5432'
    environment:
      POSTGRES_USER: mosaic
      POSTGRES_PASSWORD: mosaic
      POSTGRES_DB: mosaic
    volumes:
      - pg_a_data:/var/lib/postgresql/data
      - ../../infra/pg-init:/docker-entrypoint-initdb.d:ro
    networks:
      - fed-test-net
    healthcheck:
      test: ['CMD-SHELL', 'pg_isready -U mosaic']
      interval: 5s
      timeout: 3s
      retries: 5

  valkey-a:
    image: valkey/valkey:8-alpine
    container_name: fed-harness-valkey-a
    restart: unless-stopped
    ports:
      - '${VALKEY_A_HOST_PORT:-16379}:6379'
    volumes:
      - valkey_a_data:/data
    networks:
      - fed-test-net
    healthcheck:
      test: ['CMD', 'valkey-cli', 'ping']
      interval: 5s
      timeout: 3s
      retries: 5

  gateway-a:
    image: git.mosaicstack.dev/mosaicstack/stack/gateway@sha256:1069117740e00ccfeba357cae38c43f3729fe5ae702740ce474f6512414d7c02
    # Tag for human reference: sha-9f1a081 (post-#491 IMG-FIX; smoke-tested locally)
    container_name: fed-harness-gateway-a
    restart: unless-stopped
    ports:
      - '${GATEWAY_A_HOST_PORT:-14001}:3000'
    environment:
      MOSAIC_TIER: federated
      DATABASE_URL: postgres://mosaic:mosaic@postgres-a:5432/mosaic
      VALKEY_URL: redis://valkey-a:6379
      GATEWAY_PORT: '3000'
      GATEWAY_CORS_ORIGIN: 'http://localhost:14001'
      BETTER_AUTH_SECRET: harness-secret-server-a-do-not-use-in-prod
      BETTER_AUTH_URL: 'http://gateway-a:3000'
      STEP_CA_URL: 'https://step-ca:9000'
      FEDERATION_PEER_HOSTNAME: gateway-a
      # Bootstrap password for POST /api/bootstrap/setup — used by seed.ts to create
      # the first admin user. Only valid on a pristine (zero-user) database.
      # Not the same as ADMIN_API_KEY — there is no static API key in the gateway.
      ADMIN_BOOTSTRAP_PASSWORD: harness-admin-password-a
    depends_on:
      postgres-a:
        condition: service_healthy
      valkey-a:
        condition: service_healthy
      step-ca:
        condition: service_healthy
    networks:
      - fed-test-net
    healthcheck:
      test:
        [
          'CMD',
          'node',
          '-e',
          "require('http').get('http://127.0.0.1:3000/api/health', r => process.exit(r.statusCode === 200 ? 0 : 1)).on('error', () => process.exit(1))",
        ]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 60s

  # ─── Server B — Work / Serving Gateway ──────────────────────────────────────
  postgres-b:
    image: pgvector/pgvector:pg17
    container_name: fed-harness-postgres-b
    restart: unless-stopped
    ports:
      - '${PG_B_HOST_PORT:-15433}:5432'
    environment:
      POSTGRES_USER: mosaic
      POSTGRES_PASSWORD: mosaic
      POSTGRES_DB: mosaic
    volumes:
      - pg_b_data:/var/lib/postgresql/data
      - ../../infra/pg-init:/docker-entrypoint-initdb.d:ro
    networks:
      - fed-test-net
    healthcheck:
      test: ['CMD-SHELL', 'pg_isready -U mosaic']
      interval: 5s
      timeout: 3s
      retries: 5

  valkey-b:
    image: valkey/valkey:8-alpine
    container_name: fed-harness-valkey-b
    restart: unless-stopped
    ports:
      - '${VALKEY_B_HOST_PORT:-16380}:6379'
    volumes:
      - valkey_b_data:/data
    networks:
      - fed-test-net
    healthcheck:
      test: ['CMD', 'valkey-cli', 'ping']
      interval: 5s
      timeout: 3s
      retries: 5

  gateway-b:
    image: git.mosaicstack.dev/mosaicstack/stack/gateway@sha256:1069117740e00ccfeba357cae38c43f3729fe5ae702740ce474f6512414d7c02
    # Tag for human reference: sha-9f1a081 (post-#491 IMG-FIX; smoke-tested locally)
    container_name: fed-harness-gateway-b
    restart: unless-stopped
    ports:
      - '${GATEWAY_B_HOST_PORT:-14002}:3000'
    environment:
      MOSAIC_TIER: federated
      DATABASE_URL: postgres://mosaic:mosaic@postgres-b:5432/mosaic
      VALKEY_URL: redis://valkey-b:6379
      GATEWAY_PORT: '3000'
      GATEWAY_CORS_ORIGIN: 'http://localhost:14002'
      BETTER_AUTH_SECRET: harness-secret-server-b-do-not-use-in-prod
      BETTER_AUTH_URL: 'http://gateway-b:3000'
      STEP_CA_URL: 'https://step-ca:9000'
      FEDERATION_PEER_HOSTNAME: gateway-b
      # Bootstrap password for POST /api/bootstrap/setup — used by seed.ts to create
      # the first admin user. Only valid on a pristine (zero-user) database.
      # Not the same as ADMIN_API_KEY — there is no static API key in the gateway.
      ADMIN_BOOTSTRAP_PASSWORD: harness-admin-password-b
    depends_on:
      postgres-b:
        condition: service_healthy
      valkey-b:
        condition: service_healthy
      step-ca:
        condition: service_healthy
    networks:
      - fed-test-net
    healthcheck:
      test:
        [
          'CMD',
          'node',
          '-e',
          "require('http').get('http://127.0.0.1:3000/api/health', r => process.exit(r.statusCode === 200 ? 0 : 1)).on('error', () => process.exit(1))",
        ]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 60s

networks:
  fed-test-net:
    name: fed-test-net
    driver: bridge

volumes:
  step_ca_data:
    name: fed-harness-step-ca
  pg_a_data:
    name: fed-harness-pg-a
  valkey_a_data:
    name: fed-harness-valkey-a
  pg_b_data:
    name: fed-harness-pg-b
  valkey_b_data:
    name: fed-harness-valkey-b
