# Local dev & CI compose file. All services require an explicit --profile flag.
#
# Usage:
#   docker compose --profile dev up                → dev mode (server + search + Vite HMR)
#   docker compose --profile preview up            → local production preview (port 6005, local infra)
#   docker compose --profile production up         → CI/Fargate production (port 8080, no local infra)
#   docker compose --profile test-unit up          → lint + typecheck + unit tests (server + search)
#   docker compose --profile test-functional up    → functional tests (real DB)
#   docker compose --profile test-integration up   → integration tests (HTTP)
#   docker compose --profile test-e2e up           → E2E tests (Playwright)
#
# Prerequisites:
#   - GITHUB_NPM_TOKEN in env (for Docker builds)
#   - AWS credentials: `aws sso login` or `awsume orchard-dev`
#   - apps/server/.env and apps/client/.env populated from .env.shadow templates
#   - ECR login: `pnpm docker:login`
#
# Notes:
#   - production profile starts the app on port 8080, no local infra (expects Fargate/CI).
#   - preview profile starts preview on port 6005 + full local infra (mysql, redis, s3, migrate).
#   - test-unit profile runs lint-and-test only (no infra needed).

# ── Shared fragments ─────────────────────────────────────────────────────

x-db-env: &db-env
  CODA_DB_DRIVER: mysql
  CODA_DB_HOST: ${CODA_DB_HOST:-mysql}
  CODA_DB_PORT: ${CODA_DB_PORT:-3306}
  CODA_DB_USER: ${CODA_DB_USER:-coda_app}
  CODA_DB_PASS: ${CODA_DB_PASS:-coda_app_pass}
  CODA_DB_DATABASE: ${CODA_DB_DATABASE:-coda}

x-aws-env: &aws-env
  AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID:-}
  AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY:-}
  AWS_SESSION_TOKEN: ${AWS_SESSION_TOKEN:-}
  AWS_DEFAULT_REGION: ${AWS_DEFAULT_REGION:-us-east-1}

# Identity crypto keys shared between seed, server, and platform.
# Deterministic dev-only defaults so Docker dev "just works" without
# extra env config. Override via host env or .env at the repo root.
x-identity-env: &identity-env
  CODA_DB_IDENTITY_HMAC_SECRET: ${CODA_DB_IDENTITY_HMAC_SECRET:-a01b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b}
  CODA_DB_IDENTITY_AES_KEY: ${CODA_DB_IDENTITY_AES_KEY:-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef}

x-server-healthcheck: &server-healthcheck
  test:
    [
      "CMD-SHELL",
      'node -e "require(''http'').get(''http://localhost:8080/health'',r=>process.exit(r.statusCode===200?0:1)).on(''error'',()=>process.exit(1))"',
    ]
  interval: 10s
  timeout: 5s
  retries: 5
  start_period: 15s

x-search-healthcheck: &search-healthcheck
  test:
    [
      "CMD-SHELL",
      'node -e "require(''http'').get(''http://localhost:8081/health'',r=>process.exit(r.statusCode===200?0:1)).on(''error'',()=>process.exit(1))"',
    ]
  interval: 10s
  timeout: 5s
  retries: 10
  start_period: 600s

x-build-common: &build-common
  context: .
  secrets:
    - GITHUB_NPM_TOKEN

x-build-search: &build-search
  context: .
  dockerfile: apps/search/Dockerfile
  secrets:
    - GITHUB_NPM_TOKEN

x-build-runner: &build-runner
  context: .
  dockerfile: apps/runner/Dockerfile
  secrets:
    - GITHUB_NPM_TOKEN

x-runner-healthcheck: &runner-healthcheck
  test:
    [
      "CMD-SHELL",
      'node -e "require(''http2'').connect(''http://localhost:8082'').on(''connect'',()=>process.exit(0)).on(''error'',()=>process.exit(1))"',
    ]
  interval: 10s
  timeout: 5s
  retries: 5
  start_period: 15s

x-platform-healthcheck: &platform-healthcheck
  test:
    [
      "CMD-SHELL",
      'node -e "require(''http'').get(''http://localhost:8082/health'',r=>process.exit(r.statusCode===200?0:1)).on(''error'',()=>process.exit(1))"',
    ]
  interval: 10s
  timeout: 5s
  retries: 5
  start_period: 15s

# Resource limits mirror Terraform (terraform-infra/qa/ows-coda/):
#   App (server/production/preview): task_cpu=1024, task_memory=2048 (main.tf)
#   Search: g4dn.xlarge — 4 vCPU, 16 GB (search.tf, task_memory=4096)
#   mysql: db.t4g.medium — 2 vCPU, 4 GB (rds.tf)
#   redis: cache.t4g.micro — 2 vCPU, 0.555 GB (redis.tf)
# memswap_limit = memory on all services (Fargate/EC2 have no swap).
# Update these when Terraform instance sizes change.
x-app-limits: &app-limits
  memswap_limit: 2048M
  deploy:
    resources:
      limits:
        cpus: "1.0"
        memory: 2048M

# Production: g4dn.xlarge — 4 vCPU, 16 GB (search.tf, task_memory=4096).
# Local dev uses CPU instead of GPU for ONNX, which needs more RAM.
x-search-limits: &search-limits
  memswap_limit: 8192M
  deploy:
    resources:
      limits:
        cpus: "4.0"
        memory: 8192M

services:
  # ── Infrastructure ────────────────────────────────────────────────────────

  mysql:
    profiles:
      [
        dev,
        preview,
        test-integration,
        test-integration-release,
        test-functional,
        test-e2e,
      ]
    restart: unless-stopped
    image: mysql:8.0.36
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: coda
      MYSQL_USER: coda_app
      MYSQL_PASSWORD: coda_app_pass
    ports:
      # Host port for local tools (Sequel Ace). CI sets MYSQL_HOST_PORT=0
      # to avoid conflicts when multiple builds share a Jenkins agent.
      - "${MYSQL_HOST_PORT:-6789}:3306"
    tmpfs:
      - /var/lib/mysql:rw,noexec,nodev,nosuid,size=2g
    command:
      - --disable-log-bin
      - --skip-name-resolve
      - --innodb_doublewrite=0
      - --innodb_flush_log_at_trx_commit=2
      - --sync_binlog=0
    memswap_limit: 4096M
    deploy:
      resources:
        limits:
          cpus: "2.0"
          memory: 4096M
    healthcheck:
      test:
        [
          "CMD",
          "mysql",
          "-h",
          "127.0.0.1",
          "-uroot",
          "-proot",
          "-e",
          "SELECT 1",
        ]
      interval: 5s
      timeout: 3s
      retries: 10
      start_period: 15s

  s3:
    profiles:
      [dev, preview, test-integration, test-integration-release, test-e2e]
    restart: unless-stopped
    image: rustfs/rustfs:1.0.0-alpha.85
    ports:
      - "${S3_HOST_PORT:-9000}:9000"
      - "${S3_CONSOLE_HOST_PORT:-9001}:9001"
    environment:
      RUSTFS_ACCESS_KEY: codadev
      RUSTFS_SECRET_KEY: codadev123
    user: "0:0"
    volumes:
      - s3-data:/data
    tmpfs:
      - /logs
    memswap_limit: 512M
    deploy:
      resources:
        limits:
          cpus: "0.5"
          memory: 512M
    healthcheck:
      test: ["CMD-SHELL", "curl -sf http://localhost:9000/health"]
      interval: 5s
      timeout: 3s
      retries: 5
      start_period: 5s

  s3-init:
    profiles:
      [dev, preview, test-integration, test-integration-release, test-e2e]
    image: amazon/aws-cli:2.27.31
    depends_on:
      s3:
        condition: service_healthy
    environment:
      AWS_ACCESS_KEY_ID: codadev
      AWS_SECRET_ACCESS_KEY: codadev123
      S3_ENDPOINT: http://s3:9000
    volumes:
      - ./scripts/s3-init.sh:/s3-init.sh:ro
    entrypoint: ["sh", "/s3-init.sh"]
    memswap_limit: 256M
    deploy:
      resources:
        limits:
          cpus: "0.25"
          memory: 256M

  redis:
    profiles:
      [
        dev,
        preview,
        test-integration,
        test-integration-release,
        test-functional,
        test-e2e,
      ]
    restart: unless-stopped
    image: redis:7-alpine
    expose:
      - "6379"
    memswap_limit: 568M
    deploy:
      resources:
        limits:
          cpus: "0.5"
          memory: 568M
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 3s
      retries: 5
      start_period: 5s

  langfuse-postgres:
    profiles: [langfuse]
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: langfuse
      POSTGRES_PASSWORD: langfuse
      POSTGRES_DB: langfuse
    ports:
      - "5433:5432"
    volumes:
      - langfuse-postgres-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U langfuse"]
      interval: 5s
      timeout: 3s
      retries: 5

  langfuse-minio:
    profiles: [langfuse]
    image: minio/minio:latest
    entrypoint: sh
    command: -c 'minio server /data --console-address ":9001"'
    environment:
      MINIO_ROOT_USER: minio
      MINIO_ROOT_PASSWORD: miniominio
    ports:
      - "9100:9000"
      - "9101:9001"
    volumes:
      - langfuse-minio-data:/data
    healthcheck:
      test: ["CMD", "mc", "ready", "local"]
      interval: 5s
      timeout: 3s
      retries: 5

  langfuse-minio-init:
    profiles: [langfuse]
    image: minio/mc:latest
    depends_on:
      langfuse-minio:
        condition: service_healthy
    entrypoint: sh
    command: -c 'mc alias set local http://langfuse-minio:9000 minio miniominio && mc mb --ignore-existing local/langfuse-local-dev'

  langfuse-clickhouse:
    profiles: [langfuse]
    image: clickhouse/clickhouse-server:24.3
    ports:
      - "8123:8123"
      - "9002:9000"
    environment:
      CLICKHOUSE_USER: default
      CLICKHOUSE_PASSWORD: clickhouse
    volumes:
      - langfuse-clickhouse-data:/var/lib/clickhouse
    ulimits:
      nofile:
        soft: 262144
        hard: 262144
    healthcheck:
      test:
        [
          "CMD",
          "clickhouse-client",
          "--password",
          "clickhouse",
          "--query",
          "SELECT 1",
        ]
      interval: 5s
      timeout: 3s
      retries: 5

  langfuse-web:
    profiles: [langfuse]
    image: langfuse/langfuse:3
    depends_on:
      langfuse-postgres:
        condition: service_healthy
      langfuse-clickhouse:
        condition: service_healthy
      langfuse-minio-init:
        condition: service_completed_successfully
      redis:
        condition: service_healthy
    ports:
      - "3100:3000"
    environment:
      DATABASE_URL: postgresql://langfuse:langfuse@langfuse-postgres:5432/langfuse
      CLICKHOUSE_URL: http://langfuse-clickhouse:8123
      CLICKHOUSE_MIGRATION_URL: clickhouse://langfuse-clickhouse:9000
      CLICKHOUSE_USER: default
      CLICKHOUSE_PASSWORD: "clickhouse"
      CLICKHOUSE_CLUSTER_ENABLED: "false"
      NEXTAUTH_URL: http://localhost:3100
      NEXTAUTH_SECRET: local-dev-secret-change-in-prod
      SALT: local-dev-salt-change-in-prod
      LANGFUSE_INIT_ORG_ID: coda-local
      LANGFUSE_INIT_ORG_NAME: Coda Local
      LANGFUSE_INIT_PROJECT_ID: coda-local-project
      LANGFUSE_INIT_PROJECT_NAME: Coda
      LANGFUSE_INIT_PROJECT_PUBLIC_KEY: pk-lf-local
      LANGFUSE_INIT_PROJECT_SECRET_KEY: sk-lf-local
      LANGFUSE_INIT_USER_EMAIL: admin@coda.local
      LANGFUSE_INIT_USER_PASSWORD: admin123
      LANGFUSE_INIT_USER_NAME: Admin
      LANGFUSE_S3_EVENT_UPLOAD_ENABLED: "true"
      LANGFUSE_S3_EVENT_UPLOAD_BUCKET: "langfuse-local-dev"
      LANGFUSE_S3_EVENT_UPLOAD_REGION: "us-east-1"
      LANGFUSE_S3_EVENT_UPLOAD_ENDPOINT: "http://langfuse-minio:9000"
      LANGFUSE_S3_EVENT_UPLOAD_ACCESS_KEY_ID: "minio"
      LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY: "miniominio"
      LANGFUSE_S3_EVENT_UPLOAD_FORCE_PATH_STYLE: "true"
      REDIS_HOST: redis
      REDIS_PORT: "6379"
      HOSTNAME: 0.0.0.0
    healthcheck:
      test:
        [
          "CMD",
          "wget",
          "--no-verbose",
          "--tries=1",
          "--spider",
          "http://127.0.0.1:3000/api/public/health",
        ]
      interval: 10s
      timeout: 5s
      retries: 15
      start_period: 60s

  langfuse-worker:
    profiles: [langfuse]
    image: langfuse/langfuse:3
    depends_on:
      langfuse-web:
        condition: service_healthy
    environment:
      DATABASE_URL: postgresql://langfuse:langfuse@langfuse-postgres:5432/langfuse
      CLICKHOUSE_URL: http://langfuse-clickhouse:8123
      CLICKHOUSE_MIGRATION_URL: clickhouse://langfuse-clickhouse:9000
      CLICKHOUSE_USER: default
      CLICKHOUSE_PASSWORD: "clickhouse"
      CLICKHOUSE_CLUSTER_ENABLED: "false"
      LANGFUSE_S3_EVENT_UPLOAD_ENABLED: "true"
      LANGFUSE_S3_EVENT_UPLOAD_BUCKET: "langfuse-local-dev"
      LANGFUSE_S3_EVENT_UPLOAD_REGION: "us-east-1"
      LANGFUSE_S3_EVENT_UPLOAD_ENDPOINT: "http://langfuse-minio:9000"
      LANGFUSE_S3_EVENT_UPLOAD_ACCESS_KEY_ID: "minio"
      LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY: "miniominio"
      LANGFUSE_S3_EVENT_UPLOAD_FORCE_PATH_STYLE: "true"
      REDIS_HOST: redis
      REDIS_PORT: "6379"
      NEXTAUTH_SECRET: local-dev-secret-change-in-prod
      SALT: local-dev-salt-change-in-prod
      LANGFUSE_WORKER_HOST: 0.0.0.0
      LANGFUSE_WORKER_PORT: "3030"
    command: ["node", "packages/shared/dist/src/server/worker.js"]

  migrate:
    profiles:
      [
        dev,
        preview,
        test-integration,
        test-integration-release,
        test-functional,
        test-e2e,
      ]
    restart: "no"
    build:
      <<: *build-common
      target: migrate
    depends_on:
      mysql:
        condition: service_healthy
    environment:
      <<: [*db-env, *identity-env]
      CODA_DB_USER: root
      CODA_DB_PASS: root

  # ── API Gateway (local) ───────────────────────────────────────────────────
  # Caddy reverse proxy mirroring production API Gateway routing on port 8443.
  # Routes non-server services explicitly; everything else falls through to server.

  gateway:
    image: caddy:2-alpine
    profiles: [dev, preview]
    ports:
      - "8443:8443"
    volumes:
      - ./gateway/Caddyfile:/etc/caddy/Caddyfile:ro
    depends_on:
      server:
        condition: service_healthy

  # ── Dev services (default) ────────────────────────────────────────────────

  server:
    <<: *app-limits
    profiles: [dev, test-integration]
    build:
      <<: *build-common
      target: dev
    depends_on:
      migrate:
        condition: service_completed_successfully
      redis:
        condition: service_healthy
      s3-init:
        condition: service_completed_successfully
      platform:
        condition: service_healthy
    ports:
      - "${SERVER_HOST_PORT:-3000}:8080"
    env_file:
      - path: .env.docker.test
        required: false
      - path: apps/server/.env
        required: false
    environment:
      <<: [*db-env, *aws-env, *identity-env]
      REDIS_URL: ${REDIS_URL:-redis://redis:6379}
      PORT: "8080"
      SEARCH_URL: ${SEARCH_URL:-}
      RUNNER_URL: http://runner:8082
      PLATFORM_URL: http://platform:8082
      # Langfuse is opt-in: blank keys disable tracing. To enable, export
      # LANGFUSE_PUBLIC_KEY/LANGFUSE_SECRET_KEY and run with `--profile langfuse`.
      LANGFUSE_HOST: ${LANGFUSE_HOST:-http://langfuse-web:3000}
      LANGFUSE_PUBLIC_KEY: ${LANGFUSE_PUBLIC_KEY:-}
      LANGFUSE_SECRET_KEY: ${LANGFUSE_SECRET_KEY:-}
    volumes:
      - ./apps/server/src:/var/app/apps/server/src:delegated
      - ~/.ssh/snowflake:/home/node/.ssh/snowflake:ro
    healthcheck:
      <<: *server-healthcheck
      retries: 10
      start_period: 30s

  search:
    <<: *search-limits
    profiles: [dev]
    build:
      <<: *build-search
      target: dev
    depends_on:
      s3-init:
        condition: service_completed_successfully
    ports:
      - "${SEARCH_HOST_PORT:-8081}:8081"
    env_file:
      - path: apps/search/.env
        required: false
    environment:
      <<: *aws-env
      NODE_ENV: development
      PORT: "8081"
      SEARCH_DEVICE: cpu
      # Lightweight default: deterministic (hash-based) embeddings — no ONNX
      # model download, fast startup. Override with a HuggingFace model id
      # (e.g. SEARCH_EMBEDDING_MODEL=Xenova/...) for real semantic search.
      SEARCH_EMBEDDING_MODEL: ${SEARCH_EMBEDDING_MODEL:-deterministic/default}
      S3_ENDPOINT: http://s3:9000
      S3_SNAPSHOT_BUCKET: search-snapshots
      AWS_ACCESS_KEY_ID: codadev
      AWS_SECRET_ACCESS_KEY: codadev123
      AWS_SESSION_TOKEN: ""
      AWS_REGION: us-east-1
    volumes:
      - ./apps/search/src:/var/app/apps/search/src:delegated
      - ./apps/search/gen:/var/app/apps/search/gen:delegated
      - ~/.ssh/snowflake:/home/node/.ssh/snowflake:ro
      - search-hf-cache:/var/app/apps/search/.hf-cache
    healthcheck: *search-healthcheck

  runner:
    <<: *app-limits
    profiles: [dev]
    build:
      <<: *build-runner
      target: dev
    depends_on:
      s3-init:
        condition: service_completed_successfully
      migrate:
        condition: service_completed_successfully
    ports:
      - "${RUNNER_HOST_PORT:-8082}:8082"
    env_file:
      - path: apps/runner/.env
        required: false
    environment:
      <<: [*db-env, *aws-env]
      NODE_ENV: development
      PORT: "8082"
      REDIS_URL: ${REDIS_URL:-redis://redis:6379}
      S3_ENDPOINT: http://s3:9000
      S3_BUCKET: runner-outputs
      S3_REGION: us-east-1
    volumes:
      - ./apps/runner/src:/var/app/apps/runner/src:delegated
      - ~/.ssh/snowflake:/home/node/.ssh/snowflake:ro
    healthcheck: *runner-healthcheck

  platform:
    <<: *app-limits
    profiles: [dev, test-integration]
    build:
      <<: *build-common
      target: platform-dev
    depends_on:
      migrate:
        condition: service_completed_successfully
      redis:
        condition: service_healthy
    ports:
      - "${PLATFORM_HOST_PORT:-8083}:8082"
    env_file:
      - path: apps/platform/.env
        required: false
    environment:
      <<: [*db-env, *aws-env]
      REDIS_URL: ${REDIS_URL:-redis://redis:6379}
      PORT: "8082"
      ENVIRONMENT: dev
      NODE_ENV: dev
      SHADOW_MODE: "true"
      IDENTITY_HMAC_SECRET: ${CODA_DB_IDENTITY_HMAC_SECRET:-a01b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b}
      IDENTITY_AES_KEY: ${CODA_DB_IDENTITY_AES_KEY:-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef}
    volumes:
      - ./apps/platform/src:/var/app/apps/platform/src:delegated
    healthcheck: *platform-healthcheck

  client-dev:
    profiles: [dev]
    build:
      <<: *build-common
      target: client-dev
    depends_on:
      server:
        condition: service_healthy
      search:
        condition: service_healthy
    ports:
      - "8080:5173"
    env_file:
      - path: apps/client/.env
        required: false
    environment:
      APP_URL: http://server:8080
      DOCKER: "true"
      VITE_PORT: "5173"
      VITE_HMR_PORT: "8080"
      VITE_SEARCH_URL: http://search:8081
    volumes:
      - ./apps/client/src:/var/app/apps/client/src:delegated

  # ── Production profile (CI/Fargate — no local infra) ──────────────────────
  # Service name "production" avoids confusion with the Dockerfile "deploy"
  # target (which uses --from=client-dist for CI-provided pre-built assets).

  # DB, Redis, and downstream URLs come entirely from apps/server/.env — no
  # compose-level db-env anchor (those point at the local mysql container).
  production:
    <<: *app-limits
    profiles: [production]
    build:
      <<: *build-common
      target: deploy-local
      args:
        AUTH0_AUDIENCE: ${AUTH0_AUDIENCE:-}
        AUTH0_CLIENT_ID: ${AUTH0_CLIENT_ID:-}
        AUTH0_DOMAIN: ${AUTH0_DOMAIN:-}
        SENTRY_DSN: ${SENTRY_DSN:-}
    ports:
      - "8080:8080"
    env_file:
      - path: apps/server/.env
        required: false
    environment:
      NODE_ENV: production
      <<: *aws-env
      PORT: "8080"
    # No volume mounts — use SNOWFLAKE_READER_PRIVATE_KEY env var (PEM) like Fargate.
    healthcheck:
      <<: *server-healthcheck
      start_period: 30s

  # ── Preview profile (local production build + local infra, port 6005) ────

  preview:
    <<: *app-limits
    profiles: [preview, test-e2e]
    build:
      <<: *build-common
      target: deploy-local
      args:
        AUTH0_AUDIENCE: ${AUTH0_AUDIENCE:-}
        AUTH0_CLIENT_ID: ${AUTH0_CLIENT_ID:-}
        AUTH0_DOMAIN: ${AUTH0_DOMAIN:-}
        SENTRY_DSN: ${SENTRY_DSN:-}
    depends_on:
      migrate:
        condition: service_completed_successfully
      redis:
        condition: service_healthy
      s3-init:
        condition: service_completed_successfully
    ports:
      - "${PREVIEW_HOST_PORT:-6005}:8080"
    env_file:
      - path: apps/server/.env
        required: false
    environment:
      NODE_ENV: production
      <<: [*db-env, *aws-env]
      REDIS_URL: ${REDIS_URL:-redis://redis:6379}
      PORT: "8080"
    volumes:
      - ~/.ssh/snowflake:/home/node/.ssh/snowflake:ro
    healthcheck: *server-healthcheck

  # ── Test profiles ─────────────────────────────────────────────────────────

  lint-and-test:
    profiles: [test-unit]
    build:
      <<: *build-common
      target: lint-and-test
    environment:
      NODE_ENV: test
      ENVIRONMENT: dev
      PNPM_FILTER: "${PNPM_FILTER:-}"

  test-functional:
    profiles: [test-functional]
    build:
      <<: *build-common
      target: test-functional
    depends_on:
      migrate:
        condition: service_completed_successfully
      redis:
        condition: service_healthy
    environment:
      NODE_ENV: test
      <<: *db-env
      REDIS_URL: ${REDIS_URL:-redis://redis:6379}
      PNPM_FILTER: "${PNPM_FILTER:-}"

  test-integration:
    profiles: [test-integration]
    build:
      <<: *build-common
      target: test-integration
    depends_on:
      server:
        condition: service_healthy
    environment:
      NODE_ENV: test
      <<: *db-env
      REDIS_URL: ${REDIS_URL:-redis://redis:6379}
      SERVER_URL: http://server:8080
      PNPM_FILTER: "${PNPM_FILTER:-}"

  # TODO: test-e2e — requires a dedicated Dockerfile target with Playwright
  # and browser dependencies. Intentionally omitted to avoid silently running
  # integration tests against the preview service.

  # ── Release integration testing (CI only) ────────────────────────────
  # Uses pre-built ECR images instead of building from source. Validates
  # the exact production artifacts (pnpm deploy output, compiled JS,
  # native addon rebuilds) before deployment. Falls back to the dev-built
  # test-integration profile on PRs without release images.
  #
  # Required env vars (set by Jenkinsfile):
  #   SERVER_IMAGE   — full ECR URI for the server release image
  #   PLATFORM_IMAGE — full ECR URI for the platform release image

  server-release:
    <<: *app-limits
    profiles: [test-integration-release]
    image: ${SERVER_IMAGE}
    depends_on:
      migrate:
        condition: service_completed_successfully
      redis:
        condition: service_healthy
      s3-init:
        condition: service_completed_successfully
      platform-release:
        condition: service_healthy
    env_file:
      - path: .env.docker.test
        required: false
    environment:
      <<: [*db-env, *aws-env, *identity-env]
      REDIS_URL: ${REDIS_URL:-redis://redis:6379}
      PORT: "8080"
      DD_TRACE_ENABLED: "false"
      SEARCH_URL: ${SEARCH_URL:-}
      RUNNER_URL: ""
      PLATFORM_URL: http://platform-release:8082
    healthcheck:
      <<: *server-healthcheck
      retries: 10
      start_period: 30s

  platform-release:
    <<: *app-limits
    profiles: [test-integration-release]
    image: ${PLATFORM_IMAGE}
    depends_on:
      migrate:
        condition: service_completed_successfully
      redis:
        condition: service_healthy
    environment:
      <<: [*db-env, *aws-env]
      REDIS_URL: ${REDIS_URL:-redis://redis:6379}
      PORT: "8082"
      DD_TRACE_ENABLED: "false"
      ENVIRONMENT: test
      SHADOW_MODE: "true"
      IDENTITY_HMAC_SECRET: ${CODA_DB_IDENTITY_HMAC_SECRET:-a01b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b}
      IDENTITY_AES_KEY: ${CODA_DB_IDENTITY_AES_KEY:-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef}
    healthcheck: *platform-healthcheck

  test-integration-release:
    profiles: [test-integration-release]
    build:
      <<: *build-common
      target: test-integration
    depends_on:
      server-release:
        condition: service_healthy
    environment:
      NODE_ENV: test
      <<: *db-env
      REDIS_URL: ${REDIS_URL:-redis://redis:6379}
      SERVER_URL: http://server-release:8080
      PNPM_FILTER: "${PNPM_FILTER:-}"

volumes:
  s3-data:
  search-hf-cache:
  langfuse-postgres-data:
  langfuse-clickhouse-data:
  langfuse-minio-data:

secrets:
  GITHUB_NPM_TOKEN:
    environment: "GITHUB_NPM_TOKEN"
