# Security Center 本地部署（全 Docker）— 用于本地开发与 E2E
# 用法统一走 ./local.sh（它会带上 --env-file .env 与项目名 sc-local）
name: sc-local

services:
  mysql:
    image: public.ecr.aws/docker/library/mysql:8.0
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: ${SC_LOCAL_MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${SC_LOCAL_MYSQL_DATABASE}
      MYSQL_USER: ${SC_LOCAL_MYSQL_USER}
      MYSQL_PASSWORD: ${SC_LOCAL_MYSQL_APP_PASSWORD}
    ports:
      - "${SC_LOCAL_MYSQL_PORT}:3306"
    volumes:
      - mysql-data:/var/lib/mysql
    healthcheck:
      test: ["CMD-SHELL", "mysqladmin ping -h 127.0.0.1 -p\"${SC_LOCAL_MYSQL_ROOT_PASSWORD}\" >/dev/null 2>&1"]
      interval: 5s
      timeout: 5s
      retries: 30

  redis:
    image: public.ecr.aws/docker/library/redis:7.2
    restart: unless-stopped
    command: ["redis-server", "--requirepass", "${SC_LOCAL_REDIS_PASSWORD}"]
    ports:
      - "${SC_LOCAL_REDIS_PORT}:6379"
    volumes:
      - redis-data:/data
    healthcheck:
      test: ["CMD-SHELL", "redis-cli -a \"${SC_LOCAL_REDIS_PASSWORD}\" ping | grep -q PONG"]
      interval: 5s
      timeout: 5s
      retries: 30

  # 本地对象存储（漏洞插图上传 E2E）。默认不启动：local.sh up 仅在
  # SC_LOCAL_S3_ENABLED=true 时把 minio/minio-init 加入启动列表。
  minio:
    image: quay.io/minio/minio:latest
    restart: unless-stopped
    command: ["server", "/data", "--console-address", ":9001"]
    environment:
      MINIO_ROOT_USER: ${SC_LOCAL_MINIO_ROOT_USER:-minioadmin}
      MINIO_ROOT_PASSWORD: ${SC_LOCAL_MINIO_ROOT_PASSWORD:-minioadmin123}
    ports:
      - "${SC_LOCAL_MINIO_API_PORT:-19000}:9000"
      - "${SC_LOCAL_MINIO_CONSOLE_PORT:-19001}:9001"
    volumes:
      - minio-data:/data
    healthcheck:
      test: ["CMD-SHELL", "curl -fsS http://localhost:9000/minio/health/live > /dev/null 2>&1 || exit 1"]
      interval: 5s
      timeout: 5s
      retries: 30

  # 一次性初始化：建好 backend 用的 bucket（幂等，跑完即退出）
  minio-init:
    image: quay.io/minio/mc:latest
    restart: "no"
    depends_on:
      minio:
        condition: service_healthy
    environment:
      INIT_ROOT_USER: ${SC_LOCAL_MINIO_ROOT_USER:-minioadmin}
      INIT_ROOT_PASSWORD: ${SC_LOCAL_MINIO_ROOT_PASSWORD:-minioadmin123}
      INIT_BUCKET: ${SC_LOCAL_S3_BUCKET:-sc-vuln-uploads}
    entrypoint: >
      /bin/sh -c "mc alias set local http://minio:9000 \"$${INIT_ROOT_USER}\" \"$${INIT_ROOT_PASSWORD}\"
      && mc mb --ignore-existing \"local/$${INIT_BUCKET}\"
      && mc anonymous set download \"local/$${INIT_BUCKET}\" || true"

  backend:
    build:
      context: ../../security-center-backend
    image: sc-local-backend
    restart: unless-stopped
    environment:
      SECURITY_CENTER_APP_ENVIRONMENT: development
      SECURITY_CENTER_HTTP_HOST: 0.0.0.0
      SECURITY_CENTER_HTTP_PORT: 8080
      SECURITY_CENTER_HTTP_ALLOWED_ORIGINS: http://localhost:${SC_LOCAL_FRONTEND_PORT},http://127.0.0.1:${SC_LOCAL_FRONTEND_PORT}
      # 本地专用：免 SSO 发 admin 开发 token（E2E 取 token 用），生产必须关闭
      SECURITY_CENTER_AUTH_BYPASS_SSO: "true"
      SECURITY_CENTER_OAUTH_ENABLED: "false"
      SECURITY_CENTER_DATABASE_DSN: ${SC_LOCAL_MYSQL_USER}:${SC_LOCAL_MYSQL_APP_PASSWORD}@tcp(mysql:3306)/${SC_LOCAL_MYSQL_DATABASE}?parseTime=true
      SECURITY_CENTER_REDIS_ADDR: redis:6379
      SECURITY_CENTER_REDIS_PASSWORD: ${SC_LOCAL_REDIS_PASSWORD}
      SECURITY_CENTER_JWT_ACCESS_SECRET: ${SC_LOCAL_JWT_ACCESS_SECRET}
      SECURITY_CENTER_JWT_REFRESH_SECRET: ${SC_LOCAL_JWT_REFRESH_SECRET}
      # 附件存储（漏洞插图上传）。默认关闭保持原行为；SC_LOCAL_S3_ENABLED=true 时走本地 MinIO，
      # local.sh up 会一并拉起 minio/minio-init。endpoint 默认用 compose 内部服务名（供服务端 Head/Get/Delete），
      # 对外预签名 URL 由 PUBLIC_ENDPOINT 签成宿主机可达地址。
      SECURITY_CENTER_STORAGE_S3_ENABLED: "${SC_LOCAL_S3_ENABLED:-false}"
      SECURITY_CENTER_STORAGE_S3_BUCKET: "${SC_LOCAL_S3_BUCKET:-sc-vuln-uploads}"
      SECURITY_CENTER_STORAGE_S3_REGION: "${SC_LOCAL_S3_REGION:-us-east-1}"
      SECURITY_CENTER_STORAGE_S3_ACCESS_KEY_ID: "${SC_LOCAL_MINIO_ROOT_USER:-minioadmin}"
      SECURITY_CENTER_STORAGE_S3_SECRET_ACCESS_KEY: "${SC_LOCAL_MINIO_ROOT_PASSWORD:-minioadmin123}"
      SECURITY_CENTER_STORAGE_S3_ENDPOINT: "${SC_LOCAL_S3_ENDPOINT:-http://minio:9000}"
      # 预签名 URL 专用端点: 签名时就把 Host 签成宿主机可达地址, 浏览器/MCP 直传无需改写 URL。
      # 默认跟随 MinIO 宿主机映射端口; 服务端自身 Head/Get/Delete 仍走上面的内部 ENDPOINT。
      SECURITY_CENTER_STORAGE_S3_PUBLIC_ENDPOINT: "${SC_LOCAL_S3_PUBLIC_ENDPOINT:-http://localhost:19000}"
      SECURITY_CENTER_STORAGE_S3_USE_PATH_STYLE: "${SC_LOCAL_S3_USE_PATH_STYLE:-true}"
      SECURITY_CENTER_STORAGE_S3_UPLOAD_PREFIX: "${SC_LOCAL_S3_UPLOAD_PREFIX:-vuln-uploads}"
      # 插图查看 URL 基址（匿名 download）。本地 MinIO 容器名宿主机不可解析，
      # 用宿主机映射端口让浏览器可直接拉图；不设置则回退预签名 GET（生产路径）。
      SECURITY_CENTER_STORAGE_S3_BASE_URL: "${SC_LOCAL_S3_BASE_URL:-}"
      SECURITY_CENTER_SCAN_SCANNER_ENABLED: "false"
      # Agent 化改造（Phase 1~3）本地全开
      SECURITY_CENTER_AGENT_ENABLED: "true"
      SECURITY_CENTER_AGENT_KEY_PREFIX: sk-agent-
      SECURITY_CENTER_AGENT_ALLOW_PERMANENT_KEY: "false"
      SECURITY_CENTER_AGENT_QUOTA_ENABLED: "${SC_LOCAL_QUOTA_ENABLED:-true}"
      SECURITY_CENTER_AGENT_DEFAULT_QUOTA_RPM: "${SC_LOCAL_QUOTA_RPM:-100}"
      SECURITY_CENTER_AUDIT_RETENTION_DAYS: "90"
      # 日志级别（E2E 定位求交等 Debug 日志时设 SC_LOCAL_LOG_LEVEL=debug）
      SECURITY_CENTER_LOG_LEVEL: "${SC_LOCAL_LOG_LEVEL:-info}"
    ports:
      - "${SC_LOCAL_BACKEND_PORT}:8080"
    depends_on:
      mysql:
        condition: service_healthy
      redis:
        condition: service_healthy
    healthcheck:
      test: ["CMD-SHELL", "wget -q -O - http://localhost:8080/health > /dev/null 2>&1 || exit 1"]
      interval: 5s
      timeout: 5s
      retries: 30
      start_period: 20s

  frontend:
    profiles: ["frontend"] # 默认不启动；./local.sh up --with-frontend 才构建（首次 npm ci+build 较慢）
    build:
      context: ../../security-center-frontend
      args:
        API_PROXY_TARGET: http://backend:8080
        NEXT_PUBLIC_SSO_PROVIDER: auth0
    image: sc-local-frontend
    restart: unless-stopped
    environment:
      NEXT_PUBLIC_API_BASE_URL: /api/v1
      NEXT_PUBLIC_SSO_PROVIDER: auth0
      API_PROXY_TARGET: http://backend:8080
    ports:
      - "${SC_LOCAL_FRONTEND_PORT}:3000"
    depends_on:
      backend:
        condition: service_healthy
    healthcheck:
      # 用 127.0.0.1 而非 localhost：容器内 localhost 优先解析为 ::1，
      # 而 next standalone 仅绑 IPv4 0.0.0.0，wget 会被拒绝（backend 的 busybox 会回退 IPv4，node 镜像的不会）。
      # / 是 307 客户端跳转（静态预渲染的 NEXT_REDIRECT），/dashboard 返回真实 200。
      test: ["CMD-SHELL", "wget -q -O - http://127.0.0.1:3000/dashboard > /dev/null 2>&1 || exit 1"]
      interval: 10s
      timeout: 5s
      retries: 30
      start_period: 30s

volumes:
  mysql-data:
  redis-data:
  minio-data:
