version: "3.8"

services:
  rollerlogic-api:
    image: ghcr.io/taaazzz-prog/rollerlogic-api:v1.3.68

    networks:
      - traefik-public

    volumes:
      # Contenus premium protégés (avatars + ball skins) servis UNIQUEMENT via l'API (/api/avatars/*, /api/ball-skins/*)
      # IMPORTANT: ne pas monter sur /app/public/avatars sinon ça masque les avatars de base (/avatars/base/manifest.json)
      - /var/www/rollerlogic-api/private:/app/private:ro
      # Les musiques d'ambiance
      - /var/www/rollerlogic-mobile/sons:/app/public/sons:ro

    deploy:
      replicas: 1
      placement:
        constraints:
          - node.role == manager
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
      resources:
        limits:
          cpus: "1.0"
          memory: 512M
        reservations:
          cpus: "0.25"
          memory: 128M
      update_config:
        parallelism: 1
        delay: 10s
        failure_action: rollback
        order: start-first
      labels:
        - "traefik.enable=true"
        - "traefik.swarm.network=traefik-public"

        # HTTPS router - Frontend (rollerlogic.com) - Priorité haute
        - "traefik.http.routers.rollerlogic.rule=Host(`rollerlogic.com`) || Host(`www.rollerlogic.com`)"
        - "traefik.http.routers.rollerlogic.entrypoints=websecure"
        - "traefik.http.routers.rollerlogic.tls=true"
        - "traefik.http.routers.rollerlogic.tls.certresolver=letsencrypt"
        - "traefik.http.routers.rollerlogic.service=rollerlogic"
        - "traefik.http.routers.rollerlogic.priority=100"
        - "traefik.http.routers.rollerlogic.middlewares=frontend-security-headers@swarm,frontend-maintenance-errors@swarm"

        # HTTPS router - API (api.rollerlogic.com)
        - "traefik.http.routers.rollerlogic-api.rule=Host(`api.rollerlogic.com`)"
        - "traefik.http.routers.rollerlogic-api.entrypoints=websecure"
        - "traefik.http.routers.rollerlogic-api.tls=true"
        - "traefik.http.routers.rollerlogic-api.tls.certresolver=letsencrypt"
        - "traefik.http.routers.rollerlogic-api.service=rollerlogic"
        - "traefik.http.routers.rollerlogic-api.priority=100"
        - "traefik.http.routers.rollerlogic-api.middlewares=api-security-headers@swarm"

        # HTTPS router - Stripe webhook (SANS préfixe /api)
        # Permet d'utiliser https://api.rollerlogic.com/payments/stripe/webhook
        - "traefik.http.routers.rollerlogic-api-webhook.rule=Host(`api.rollerlogic.com`) && PathPrefix(`/payments/stripe/webhook`)"
        - "traefik.http.routers.rollerlogic-api-webhook.entrypoints=websecure"
        - "traefik.http.routers.rollerlogic-api-webhook.tls=true"
        - "traefik.http.routers.rollerlogic-api-webhook.tls.certresolver=letsencrypt"
        - "traefik.http.routers.rollerlogic-api-webhook.service=rollerlogic"
        - "traefik.http.routers.rollerlogic-api-webhook.priority=200"
        - "traefik.http.routers.rollerlogic-api-webhook.middlewares=api-security-headers@swarm"

        # Security headers - Frontend
        - "traefik.http.middlewares.frontend-security-headers.headers.stsSeconds=31536000"
        - "traefik.http.middlewares.frontend-security-headers.headers.stsIncludeSubdomains=true"
        - "traefik.http.middlewares.frontend-security-headers.headers.stsPreload=true"
        - "traefik.http.middlewares.frontend-security-headers.headers.contentTypeNosniff=true"
        - "traefik.http.middlewares.frontend-security-headers.headers.referrerPolicy=strict-origin-when-cross-origin"
        - "traefik.http.middlewares.frontend-security-headers.headers.permissionsPolicy=geolocation=(), microphone=(), camera=()"
        - "traefik.http.middlewares.frontend-security-headers.headers.customFrameOptionsValue=SAMEORIGIN"

        # Maintenance fallback page (only when backend returns 503)
        - "traefik.http.middlewares.frontend-maintenance-errors.errors.status=503"
        - "traefik.http.middlewares.frontend-maintenance-errors.errors.service=rollerlogic-maintenance@swarm"
        - "traefik.http.middlewares.frontend-maintenance-errors.errors.query=/"

        # Security headers - API
        - "traefik.http.middlewares.api-security-headers.headers.stsSeconds=31536000"
        - "traefik.http.middlewares.api-security-headers.headers.stsIncludeSubdomains=true"
        - "traefik.http.middlewares.api-security-headers.headers.stsPreload=true"
        - "traefik.http.middlewares.api-security-headers.headers.contentTypeNosniff=true"
        - "traefik.http.middlewares.api-security-headers.headers.referrerPolicy=strict-origin-when-cross-origin"
        - "traefik.http.middlewares.api-security-headers.headers.permissionsPolicy=geolocation=(), microphone=(), camera=()"
        - "traefik.http.middlewares.api-security-headers.headers.customFrameOptionsValue=DENY"

        # HTTP -> HTTPS redirect (frontend)
        - "traefik.http.routers.rollerlogic-http.rule=Host(`rollerlogic.com`) || Host(`www.rollerlogic.com`)"
        - "traefik.http.routers.rollerlogic-http.entrypoints=web"
        - "traefik.http.routers.rollerlogic-http.middlewares=redirect-to-https@swarm"

        # HTTP -> HTTPS redirect (API)
        - "traefik.http.routers.rollerlogic-api-http.rule=Host(`api.rollerlogic.com`)"
        - "traefik.http.routers.rollerlogic-api-http.entrypoints=web"
        - "traefik.http.routers.rollerlogic-api-http.middlewares=redirect-to-https@swarm"

        # Service port (3000 pour Node.js)
        - "traefik.http.services.rollerlogic.loadbalancer.server.port=3000"
        - "traefik.http.services.rollerlogic.loadbalancer.healthcheck.path=/api/health"
        - "traefik.http.services.rollerlogic.loadbalancer.healthcheck.interval=30s"

    secrets:
      - rollerlogic_db_password
      - rollerlogic_jwt_secret
      - smtp_pass_v2
      - stripe_secret_key_rollerlogic_live
      - stripe_webhook_secret_rollerlogic_live
      - rollerlogic_mysql_ca

    environment:
      APP_ENV: production
      APP_URL: https://rollerlogic.com
      TZ: Europe/Paris
      ADS_ENABLED: "false"

      # Database
      DB_HOST: gb9434-001.eu.clouddb.ovh.net
      DB_PORT: "35670"
      DB_USER: Taaazzz
      DB_NAME: RollerLogic
      DB_PASSWORD_FILE: /run/secrets/rollerlogic_db_password
      DB_CONNECTION: mysql
      DB_CHARSET: utf8mb4
      DB_COLLATION: utf8mb4_unicode_ci
      DB_SSL: "true"
      DB_SSL_REJECT_UNAUTHORIZED: "true"
      DB_SSL_CA_FILE: /run/secrets/rollerlogic_mysql_ca

      # Auth
      JWT_SECRET_FILE: /run/secrets/rollerlogic_jwt_secret

      # Cookies - SameSite=none pour compatibilité mobile (Safari, etc.)
      COOKIE_SAMESITE: "none"
      COOKIE_SECURE: "true"
      # COOKIE_DOMAIN retiré pour que le cookie soit lié à l'hôte exact

      # SMTP
      SMTP_HOST: ssl0.ovh.net
      SMTP_PORT: "465"
      SMTP_SECURE: "true"
      SMTP_USER: contact@taaazzz-prog.fr
      SMTP_PASSWORD_FILE: /run/secrets/smtp_pass_v2
      SMTP_FROM_EMAIL: contact@taaazzz-prog.fr
      SMTP_FROM_NAME: "RollerLogic"

      # Stripe Payments (LIVE - Production)
      STRIPE_SECRET_KEY_FILE: /run/secrets/stripe_secret_key_rollerlogic_live
      STRIPE_WEBHOOK_SECRET_FILE: /run/secrets/stripe_webhook_secret_rollerlogic_live

  # Service de maintenance - S'affiche quand le service principal est indisponible
  rollerlogic-maintenance:
    image: ghcr.io/taaazzz-prog/rollerlogic-maintenance:v1.3.68

    networks:
      - traefik-public

    deploy:
      replicas: 1
      placement:
        constraints:
          - node.role == manager
      restart_policy:
        condition: on-failure
      resources:
        limits:
          cpus: "0.25"
          memory: 64M
        reservations:
          cpus: "0.05"
          memory: 16M
      labels:
        - "traefik.enable=true"
        - "traefik.swarm.network=traefik-public"

        # HTTPS router - Fallback Frontend (priorité basse = 1)
        - "traefik.http.routers.rollerlogic-maintenance.rule=Host(`rollerlogic.com`) || Host(`www.rollerlogic.com`)"
        - "traefik.http.routers.rollerlogic-maintenance.entrypoints=websecure"
        - "traefik.http.routers.rollerlogic-maintenance.tls=true"
        - "traefik.http.routers.rollerlogic-maintenance.tls.certresolver=letsencrypt"
        - "traefik.http.routers.rollerlogic-maintenance.service=rollerlogic-maintenance"
        - "traefik.http.routers.rollerlogic-maintenance.priority=1"

        # HTTPS router - Fallback API (priorité basse = 1)
        - "traefik.http.routers.rollerlogic-api-maintenance.rule=Host(`api.rollerlogic.com`)"
        - "traefik.http.routers.rollerlogic-api-maintenance.entrypoints=websecure"
        - "traefik.http.routers.rollerlogic-api-maintenance.tls=true"
        - "traefik.http.routers.rollerlogic-api-maintenance.tls.certresolver=letsencrypt"
        - "traefik.http.routers.rollerlogic-api-maintenance.service=rollerlogic-maintenance"
        - "traefik.http.routers.rollerlogic-api-maintenance.priority=1"

        # Service port
        - "traefik.http.services.rollerlogic-maintenance.loadbalancer.server.port=80"

  # Panel Admin - Interface d'administration sécurisée (sysop.rollerlogic.com)
  rollerlogic-admin:
    image: ghcr.io/taaazzz-prog/rollerlogic-admin:v1.3.68

    networks:
      - traefik-public

    deploy:
      replicas: 1
      placement:
        constraints:
          - node.role == manager
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
      resources:
        limits:
          cpus: "0.5"
          memory: 256M
        reservations:
          cpus: "0.1"
          memory: 64M
      update_config:
        parallelism: 1
        delay: 10s
        failure_action: rollback
        order: start-first
      labels:
        - "traefik.enable=true"
        - "traefik.swarm.network=traefik-public"

        # HTTPS router - Admin Panel (sysop.rollerlogic.com)
        - "traefik.http.routers.rollerlogic-admin.rule=Host(`sysop.rollerlogic.com`)"
        - "traefik.http.routers.rollerlogic-admin.entrypoints=websecure"
        - "traefik.http.routers.rollerlogic-admin.tls=true"
        - "traefik.http.routers.rollerlogic-admin.tls.certresolver=letsencrypt"
        - "traefik.http.routers.rollerlogic-admin.service=rollerlogic-admin"
        - "traefik.http.routers.rollerlogic-admin.priority=100"

        # Middlewares de sécurité renforcée
        - "traefik.http.routers.rollerlogic-admin.middlewares=admin-security-headers@swarm"

        # Security headers middleware (défini globalement dans Traefik ou ici)
        - "traefik.http.middlewares.admin-security-headers.headers.customFrameOptionsValue=DENY"
        - "traefik.http.middlewares.admin-security-headers.headers.contentSecurityPolicy=default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com https://fonts.googleapis.com; img-src 'self' data: https:; font-src 'self' data: https://cdnjs.cloudflare.com https://fonts.gstatic.com; connect-src 'self' https://api.rollerlogic.com; frame-ancestors 'none';"
        # Éviter les caches agressifs sur le panel (sinon on voit "l'ancienne" UI après déploiement)
        - "traefik.http.middlewares.admin-security-headers.headers.customResponseHeaders.Cache-Control=no-store"
        - "traefik.http.middlewares.admin-security-headers.headers.customResponseHeaders.Pragma=no-cache"
        - "traefik.http.middlewares.admin-security-headers.headers.customResponseHeaders.Expires=0"
        - "traefik.http.middlewares.admin-security-headers.headers.stsSeconds=31536000"
        - "traefik.http.middlewares.admin-security-headers.headers.stsIncludeSubdomains=true"
        - "traefik.http.middlewares.admin-security-headers.headers.stsPreload=true"
        - "traefik.http.middlewares.admin-security-headers.headers.contentTypeNosniff=true"
        - "traefik.http.middlewares.admin-security-headers.headers.browserXssFilter=true"
        - "traefik.http.middlewares.admin-security-headers.headers.referrerPolicy=no-referrer"
        - "traefik.http.middlewares.admin-security-headers.headers.permissionsPolicy=geolocation=(), microphone=(), camera=()"

        # HTTP -> HTTPS redirect
        - "traefik.http.routers.rollerlogic-admin-http.rule=Host(`sysop.rollerlogic.com`)"
        - "traefik.http.routers.rollerlogic-admin-http.entrypoints=web"
        - "traefik.http.routers.rollerlogic-admin-http.middlewares=redirect-to-https@swarm"

        # Service port (3000 pour serve)
        - "traefik.http.services.rollerlogic-admin.loadbalancer.server.port=3000"
        - "traefik.http.services.rollerlogic-admin.loadbalancer.healthcheck.path=/"
        - "traefik.http.services.rollerlogic-admin.loadbalancer.healthcheck.interval=30s"

networks:
  traefik-public:
    external: true

secrets:
  rollerlogic_db_password:
    external: true
  rollerlogic_jwt_secret:
    external: true
  smtp_pass_v2:
    external: true
  stripe_secret_key_rollerlogic_live:
    external: true
  stripe_webhook_secret_rollerlogic_live:
    external: true
  rollerlogic_mysql_ca:
    external: true
