x-worker-env: &worker-env NODE_ENV: production REDIS_HOST: ${REDIS_HOST:-didi-cache} REDIS_PORT: ${REDIS_PORT:-6379} REDIS_USERNAME: ${REDIS_USERNAME:-} REDIS_PASSWORD: ${REDIS_PASSWORD:-redis123} REDIS_DB: ${REDIS_DB:-0} RABBITMQ_HOST: ${RABBITMQ_HOST:-staging-dataLayer-rabbitmq} RABBITMQ_PORT: ${RABBITMQ_PORT:-5672} RABBITMQ_USER: ${RABBITMQ_USER:-admin} RABBITMQ_PASS: ${RABBITMQ_PASS:-rabbitmq123} RABBITMQ_VHOST: ${RABBITMQ_VHOST:-/} # Management API (for /health/all only — local mgmt always reachable # from didi-network, even when AMQP routed via cluster VIP) RABBITMQ_MGMT_URL: ${RABBITMQ_MGMT_URL:-http://staging-dataLayer-rabbitmq:15672} RABBITMQ_MGMT_USER: ${RABBITMQ_MGMT_USER:-admin} RABBITMQ_MGMT_PASS: ${RABBITMQ_MGMT_PASS:-rabbitmq123} PG_HOST: ${PG_HOST:-didi-postgres} PG_PORT: ${PG_PORT:-5432} PG_DATABASE: ${PG_DATABASE:-DIDI} PG_USER: ${PG_USER:-bos_interface} PG_PASSWORD: ${PG_PASSWORD:-interface} MINIO_ENDPOINT: ${MINIO_ENDPOINT:-staging-dataLayer-minio:9000} MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY:-minioadmin} MINIO_SECRET_KEY: ${MINIO_SECRET_KEY:-minio123} MINIO_USE_SSL: ${MINIO_USE_SSL:-false} MINIO_BUCKET: ${MINIO_BUCKET:-} # empty=local multi-bucket mode; set to 'didi-prod' on cluster MINIO_PUBLIC_ENDPOINT: ${MINIO_PUBLIC_ENDPOINT:-} # JWT verification — RS256 against Keycloak JWKS (didi-clients + didi-admins). # JWT_VERIFY_ENABLED=false disables signature checks (dev ONLY, never prod). KEYCLOAK_URL: ${KEYCLOAK_URL:-http://didi-keycloak:8080/auth} JWT_VERIFY_ENABLED: ${JWT_VERIFY_ENABLED:-true} FRAMEWORK_API_URL: http://didi-framework:3005 SYNC_API_URL: http://didi-framework:3005/api/sync-analysis PUBLIC_API_BASE_URL: ${PUBLIC_API_BASE_URL:-https://api.local:8443} INTERNAL_MEDIA_URL: ${INTERNAL_MEDIA_URL:-http://didi-agent-v3:24803} # === Lot 1 (platforma AI) — toate configurabile per deployment via .env === LLM_ROUTER_URL: ${LLM_ROUTER_URL:-http://llm.local:14011} VISION_LLM_URL: ${VISION_LLM_URL:-http://llm.local:14011} DOMAIN_CHECK_API_URL: ${DOMAIN_CHECK_API_URL:-http://domain-check-api:11000/api/v1/check/check} M17_WEB_API_URL: ${M17_WEB_API_URL:-http://websearch.local:51100} DIDI_BRAIN_URL: ${DIDI_BRAIN_URL:-http://didibrain-api:8090} # OpenTelemetry — traces export to OTel Collector → Jaeger OTEL_EXPORTER_OTLP_ENDPOINT: ${OTEL_EXPORTER_OTLP_ENDPOINT:-http://didi-otel-collector:4317} OTEL_SERVICE_NAME: ${OTEL_SERVICE_NAME:-agent-v3} # AI platform dashboard — EventSink fires a summary event per AnalysisSession # to /api/ingest/event so analyses appear in the unified Insights/History # view (module=agent_v3). Empty = sink disabled. DASHBOARD_URL: ${DASHBOARD_URL:-http://didiAI-dashboard:51300} M17_WHISPER_URL: ${M17_WHISPER_URL:-http://llm.local:54300/v1/audio/transcriptions} M17_WHISPER_TOKEN: ${M17_WHISPER_TOKEN} OPENROUTER_API_KEY: ${OPENROUTER_API_KEY} OPENAI_API_KEY: ${OPENAI_API_KEY} GROQ_API_KEY: ${GROQ_API_KEY} ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY:-} GOOGLE_API_KEY: ${GOOGLE_API_KEY:-} # STAGING_MODE: "true" → /api/v3/moderation/* permits requests without JWT # roles (legacy soft-auth, useful for local + admin-dashboard staging). Set # to "false" simultaneously with admin-dashboard cutover for strict prod role # enforcement (admin/moderator/senior_moderator only). STAGING_MODE: ${STAGING_MODE:-true} # Some internal AI services may use self-signed certificates. # Setting this lets agent-v3 + workers accept it. All other providers # (OpenRouter, Anthropic, Groq, OpenAI) have public CA-signed certs that # are still validated by the OS trust store (the flag affects rejection # logic, but a properly-signed chain still verifies cleanly). NODE_TLS_REJECT_UNAUTHORIZED: ${NODE_TLS_REJECT_UNAUTHORIZED:-0} # Forensic Features microservice (m25-m29 deepfake measurements + heatmaps). # Default ON; disable cu FORENSIC_ENABLED=false dacă serviciul nu rulează. FORENSIC_API_URL: ${FORENSIC_API_URL:-http://forensic-features-api:8080} FORENSIC_ENABLED: ${FORENSIC_ENABLED:-true} FORENSIC_TIMEOUT_MS: ${FORENSIC_TIMEOUT_MS:-180000} # BusterX video deepfake (specialized vLLM model). Opt-in. BUSTER_ENABLED: ${BUSTER_ENABLED:-false} VIDEO_ANALYSIS_URL: ${VIDEO_ANALYSIS_URL:-http://didiAI-video-api:54600} # Extractors metadata/integrity (EXIF/ELA/C2PA/video_meta/SHA256). Default ON. EXTRACTORS_ENABLED: ${EXTRACTORS_ENABLED:-true} EXTRACTORS_URL: ${EXTRACTORS_URL:-http://didiAI-extractors:54400} EXTRACTORS_TIMEOUT_MS: ${EXTRACTORS_TIMEOUT_MS:-60000} services: agent-v3: build: . container_name: didi-agent-v3 restart: unless-stopped ports: - "24803:24803" environment: <<: *worker-env AGENT_V3_HOST: "0.0.0.0" AGENT_V3_PORT: "24803" networks: - didi-network healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:24803/api/v3/health"] interval: 30s timeout: 10s start_period: 5s retries: 3 worker-media-preprocess: build: . restart: unless-stopped environment: <<: *worker-env command: ["node", "dist/worker-entrypoints/media-preprocess.js"] healthcheck: disable: true deploy: replicas: 2 networks: - didi-network worker-techniques: build: . restart: unless-stopped environment: <<: *worker-env command: ["node", "dist/worker-entrypoints/techniques.js"] healthcheck: disable: true deploy: replicas: 2 networks: - didi-network worker-ai-tampered: build: . restart: unless-stopped environment: <<: *worker-env command: ["node", "dist/worker-entrypoints/ai-tampered.js"] healthcheck: disable: true deploy: replicas: 2 networks: - didi-network worker-claims: build: . restart: unless-stopped environment: <<: *worker-env command: ["node", "dist/worker-entrypoints/claims.js"] healthcheck: disable: true deploy: replicas: 3 networks: - didi-network worker-domain: build: . restart: unless-stopped environment: <<: *worker-env command: ["node", "dist/worker-entrypoints/domain.js"] healthcheck: disable: true deploy: replicas: 2 networks: - didi-network verdict-aggregator: build: . restart: unless-stopped environment: <<: *worker-env command: ["node", "dist/worker-entrypoints/aggregator.js"] healthcheck: disable: true deploy: replicas: 2 networks: - didi-network networks: didi-network: external: true