Files
sase.tr/docker-compose.coolify.yml
Semih Yesilyurt 71568e2274
Some checks are pending
QA Gate (P0/P1) / Test affected app (pull_request) Waiting to run
feat(rpartstore): Renault/Dacia için RPartStore VIN-decode fallback kaynağı
rpartstore.renault.com (Renault Group bayi portalı) yeni decode kaynağı olarak
eklendi. Portal REST değil STOMP 1.2 over WebSocket konuşuyor; login Okta OIE
(IDX JSON API + PKCE), tarayıcı gerekmiyor. Sıralama Renault/Dacia için:
pcat + PL24 + emex yarışı → rpartstore → (bayrağı açıksa) Vinpin son çare.

- integrations/rpartstore: STOMP codec, Okta login, oturum (trace-id ile
  çok-mesajlı cevap eşleme), istemci (Redis'te 1 saatlik token), Renault/Dacia
  yönlendirme, RPartStore → PL24 catalog_vehicles model eşleyici (roman rakam,
  karoseri niteleyici, yanlış-pazar cezası).
- rpartstore_decodes tablosu (migration 0037) + rpartstore-decode BullMQ
  kuyruğu; worker concurrency 1 + 1 iş / 6 s limiter (portal 2 arama / 10 s).
- Günlük sert kota RPARTSTORE_DAILY_CAP (varsayılan 10, İstanbul günü):
  işlemci göndermeden önce Redis INCR ile rezervasyon yapar, aşan VIN'ler
  `capped` olur ve 24 saat sonra tekrar denenir; API kota doluysa kuyruğa
  hiç almaz. Kısa vadeli rate-limit cevabında retryAfter kadar bekleyip bir
  kez tekrar dener.
- VehiclesService.tryRpartstoreFallback: Vinpin fallback ile aynı sözleşme
  (decoding/catalogVehicle cevapları, tek başarısızlık log satırı).
- Env: RPARTSTORE_ENABLED/USER/PASS/DAILY_CAP/BROKER_URL/APP_VERSION
  (compose api+worker). Vinpin koda dokunulmadan pasif kalır (VINPIN_ENABLED).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-25 13:58:09 +03:00

319 lines
16 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
services:
api:
build:
context: .
dockerfile: Dockerfile
args:
- VITE_FARO_ENABLED=${VITE_FARO_ENABLED:-false}
- VITE_FARO_COLLECTOR_URL=${VITE_FARO_COLLECTOR_URL:-}
- VITE_POSTHOG_KEY=${VITE_POSTHOG_KEY:-}
- VITE_META_PIXEL_ID=${VITE_META_PIXEL_ID:-}
- VITE_CHATWOOT_BASE_URL=${VITE_CHATWOOT_BASE_URL:-}
- VITE_CHATWOOT_WEBSITE_TOKEN=${VITE_CHATWOOT_WEBSITE_TOKEN:-}
# Sentry browser SDK — gated on DSN presence (unset = skip init).
# VITE_* args must be build-time; runtime env won't reach the bundle.
- VITE_SENTRY_DSN=${VITE_SENTRY_DSN:-}
- VITE_SENTRY_ENVIRONMENT=${VITE_SENTRY_ENVIRONMENT:-production}
- VITE_SENTRY_RELEASE=${VITE_SENTRY_RELEASE:-}
- VITE_GOOGLE_ADS_ID=${VITE_GOOGLE_ADS_ID:-}
- VITE_GOOGLE_ADS_SIGNUP_LABEL=${VITE_GOOGLE_ADS_SIGNUP_LABEL:-}
environment:
- NODE_ENV=production
- PORT=4000
- DATABASE_URL=${DATABASE_URL}
- REDIS_HOST=sase-redis
- REDIS_PORT=6379
- REDIS_PASSWORD=${REDIS_PASSWORD}
- BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET}
- BETTER_AUTH_URL=${BETTER_AUTH_URL}
# Süper Panel ↔ Sase.tr internal admin token (X-Internal-Token header)
- INTERNAL_API_TOKEN=${INTERNAL_API_TOKEN:-}
- INTERNAL_IMPERSONATION_SECRET=${INTERNAL_IMPERSONATION_SECRET:-}
- GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID:-}
- GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET:-}
- MINIO_ENDPOINT=http://minio-global:9000
- MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY}
- MINIO_SECRET_KEY=${MINIO_SECRET_KEY}
- MINIO_BUCKET_NAME=${MINIO_BUCKET_NAME:-sase-schemas}
- MINIO_PUBLIC_URL=${MINIO_PUBLIC_URL}
- MINIO_USE_SSL=false
- CORS_ORIGIN=${CORS_ORIGIN}
- STRIPE_SECRET_KEY=${STRIPE_SECRET_KEY:-}
- STRIPE_PUBLISHABLE_KEY=${STRIPE_PUBLISHABLE_KEY:-}
- PL24_BASE_URL=${PL24_BASE_URL:-https://www.partslink24.com}
- PL24_COMPANY_CODE=${PL24_COMPANY_CODE:-}
- PL24_USERNAME=${PL24_USERNAME:-}
- PL24_PASSWORD=${PL24_PASSWORD:-}
- PL24_COMPANY_CODE_2=${PL24_COMPANY_CODE_2:-}
- PL24_USERNAME_2=${PL24_USERNAME_2:-}
- PL24_PASSWORD_2=${PL24_PASSWORD_2:-}
- PL24_PROXY_DE=${PL24_PROXY_DE:-}
- PL24_TR_DISABLED=${PL24_TR_DISABLED:-}
- PL24_BACKFILL_ENABLED=${PL24_BACKFILL_ENABLED:-}
- EMEX_USERNAME=${EMEX_USERNAME:-}
- EMEX_PASSWORD=${EMEX_PASSWORD:-}
- EMEX_USE_PROXY=${EMEX_USE_PROXY:-false}
- EMEX_PROXY_HOST=${EMEX_PROXY_HOST:-74.81.81.81}
- EMEX_PROXY_USER=${EMEX_PROXY_USER:-1726bbe361918676d44e}
- EMEX_PROXY_PASS=${EMEX_PROXY_PASS:-f11c7b6128cc86c6}
- PCAT_USE_PROXY=${PCAT_USE_PROXY:-true}
- PCAT_PROXY_HOST=${PCAT_PROXY_HOST:-gw.dataimpulse.com}
- PCAT_PROXY_USER=${PCAT_PROXY_USER:-}
- PCAT_PROXY_PASS=${PCAT_PROXY_PASS:-}
# Vinpin ePER VIN-decode fallback (flag-gated, off by default)
- VINPIN_ENABLED=${VINPIN_ENABLED:-false}
- VINPIN_URL=${VINPIN_URL:-https://login.tr.vinpin.online}
- VINPIN_USER=${VINPIN_USER:-}
- VINPIN_PASS=${VINPIN_PASS:-}
- VINPIN_WARM_DAEMON=${VINPIN_WARM_DAEMON:-false}
# Set to "false" to skip opening Rpartstore entirely during a known upstream
# Rpartstore outage → Renault decodes go straight to Dialogys (drops the
# per-decode launch-error probe + "Loading application..." stray + budget burn).
- VINPIN_RPARTSTORE_ENABLED=${VINPIN_RPARTSTORE_ENABLED:-true}
# RPartStore (Renault/Dacia) VIN-decode fallback — after pcat/PL24/emex, before Vinpin.
# Hard daily cap on searches sent to rpartstore.renault.com (default 10).
- RPARTSTORE_ENABLED=${RPARTSTORE_ENABLED:-false}
- RPARTSTORE_USER=${RPARTSTORE_USER:-}
- RPARTSTORE_PASS=${RPARTSTORE_PASS:-}
- RPARTSTORE_DAILY_CAP=${RPARTSTORE_DAILY_CAP:-10}
- RPARTSTORE_BROKER_URL=${RPARTSTORE_BROKER_URL:-wss://1po-bff.renault-edh.com/ws}
- RPARTSTORE_APP_VERSION=${RPARTSTORE_APP_VERSION:-1.34.0.6}
- POSTAL_API_URL=${POSTAL_API_URL:-}
- POSTAL_API_KEY=${POSTAL_API_KEY:-}
- POSTAL_FROM_ADDRESS=${POSTAL_FROM_ADDRESS:-noreply@sase.tr}
- POSTAL_FROM_NAME=${POSTAL_FROM_NAME:-Sase.tr}
# Novu lifecycle e-mail automation (Tailscale-only; sends via Postal)
- NOVU_API_URL=${NOVU_API_URL:-https://api.bildirim.semih.ai}
- NOVU_API_KEY=${NOVU_API_KEY:-}
- APP_PUBLIC_URL=${APP_PUBLIC_URL:-https://sase.tr}
- MAILTRACK_SECRET=${MAILTRACK_SECRET:-}
# Unsubscribe links (List-Unsubscribe header + mail footer); empty secret = mailto-only
- UNSUBSCRIBE_SECRET=${UNSUBSCRIBE_SECRET:-}
- UNSUBSCRIBE_URL_BASE=${UNSUBSCRIBE_URL_BASE:-}
- UNSUBSCRIBE_EMAIL=${UNSUBSCRIBE_EMAIL:-}
# PostHog server-side analytics (payments, subscription lifecycle, $revenue).
# Empty key → PostHogService no-ops (server-side analytics disabled).
- POSTHOG_API_KEY=${POSTHOG_API_KEY:-}
# Personal/secure key → LOCAL feature-flag evaluation (source kill switches,
# guarded decode rollout, remote config). Empty → flags fail open (inert).
- POSTHOG_PERSONAL_API_KEY=${POSTHOG_PERSONAL_API_KEY:-}
# "false" on non-prod → evaluate flags but DON'T emit analytics to prod project.
- POSTHOG_CAPTURE_ENABLED=${POSTHOG_CAPTURE_ENABLED:-}
- POSTHOG_HOST=${POSTHOG_HOST:-https://eu.i.posthog.com}
# Meta Conversions API — server-side signup tracking. Empty → CAPI no-ops.
- META_CAPI_PIXEL_ID=${META_CAPI_PIXEL_ID:-}
- META_CAPI_ACCESS_TOKEN=${META_CAPI_ACCESS_TOKEN:-}
- META_CAPI_TEST_EVENT_CODE=${META_CAPI_TEST_EVENT_CODE:-}
- OTEL_ENABLED=${OTEL_ENABLED:-false}
- OTEL_EXPORTER_OTLP_ENDPOINT=${OTEL_EXPORTER_OTLP_ENDPOINT:-}
- OTEL_EXPORTER_OTLP_HEADERS=${OTEL_EXPORTER_OTLP_HEADERS:-}
- OTEL_SERVICE_NAME=${OTEL_SERVICE_NAME:-sase-api}
- OTEL_TRACE_SAMPLE_RATE=${OTEL_TRACE_SAMPLE_RATE:-1.0}
- ML_PREDICTION_ENABLED=${ML_PREDICTION_ENABLED:-false}
# Chatwoot live-chat widget — HMAC secret for verified user identity
- CHATWOOT_HMAC_TOKEN=${CHATWOOT_HMAC_TOKEN:-}
# Local catalog-dump lookup (CategoriesService → PcatSourceDb / EmexSourceDb).
# Defaults off; when CATALOG_SOURCE_DB_ENABLED=true + URLs set, parts fetches
# hit the dump first and only fall through to live upstream on miss.
- CATALOG_SOURCE_DB_ENABLED=${CATALOG_SOURCE_DB_ENABLED:-false}
- PCAT_SOURCE_DB_URL=${PCAT_SOURCE_DB_URL:-}
- EMEX_SOURCE_DB_URL=${EMEX_SOURCE_DB_URL:-}
# Per-source kill switches. pcat default off (dump doesn't cover TR vehicles).
- EMEX_SOURCE_DB_ENABLED=${EMEX_SOURCE_DB_ENABLED:-true}
- PCAT_SOURCE_DB_ENABLED=${PCAT_SOURCE_DB_ENABLED:-false}
# Per-catalog parts-lookup allowlist (comma-separated). Empty → all
# fetchCategoryParts calls return null. See sase-emex-source-db-safety
# memory: catalog-wide bridge had 7-114x noise; only add a catalog once
# its per-vehicle bridge is wired & OEM-verified.
- EMEX_SOURCE_DB_ALLOWED_CATALOGS=${EMEX_SOURCE_DB_ALLOWED_CATALOGS:-}
# P snapshot lookup (db `td`) backing the OEM detail page. Off until
# both vars are set in Coolify; see sase-prod-db-api-access memory.
- P_DB_ENABLED=${P_DB_ENABLED:-false}
- P_DB_URL=${P_DB_URL:-}
# Tedarikçi fiyat geçmişi (takip MySQL, Tailscale 100.82.193.79). Boş →
# part-prices uçları matched:false döner, UI fiyat bölümü çizmez.
- SUPPLIER_PRICE_DB_ENABLED=${SUPPLIER_PRICE_DB_ENABLED:-false}
- SUPPLIER_PRICE_DB_URL=${SUPPLIER_PRICE_DB_URL:-}
# Central Directus CMS (Süper Panel project on Coolify). Prod and staging
# point at the SAME instance so blog content is shared across envs.
# Internal docker-network URL — both stacks join the `coolify` network.
- DIRECTUS_URL=${DIRECTUS_URL:-}
- DIRECTUS_TOKEN=${DIRECTUS_TOKEN:-}
- DIRECTUS_PROJECT=${DIRECTUS_PROJECT:-sase}
# Bearer token for POST /blog/posts/internal (Süper Panel n8n pipeline)
- BLOG_AUTOMATION_TOKEN=${BLOG_AUTOMATION_TOKEN:-}
# Catalog prefetch / backfill tuning (in-process worker lives in THIS api
# container, not worker.js). All empty → compiled-in defaults; set in Coolify
# to ramp without a code change. PL24 rate stays conservative unless rotating
# residential proxies are confirmed (upstream ban risk). See
# sase-coolify-compose-env-injection + sase-catalog-backfill memories.
- CATALOG_BACKFILL_ENABLED=${CATALOG_BACKFILL_ENABLED:-}
- PREFETCH_CONCURRENCY=${PREFETCH_CONCURRENCY:-}
- PREFETCH_RATE_MAX=${PREFETCH_RATE_MAX:-}
- PREFETCH_MAX_DEPTH=${PREFETCH_MAX_DEPTH:-}
- PREFETCH_RATE_PL24=${PREFETCH_RATE_PL24:-}
- PREFETCH_DAILY_PL24=${PREFETCH_DAILY_PL24:-}
- PREFETCH_PL24_FAST_DEPTH=${PREFETCH_PL24_FAST_DEPTH:-}
- PREFETCH_PL24_DELAY_MS=${PREFETCH_PL24_DELAY_MS:-}
- PL24_HTTP_DAILY_MAX=${PL24_HTTP_DAILY_MAX:-}
- PL24_HTTP_USER_RESERVE=${PL24_HTTP_USER_RESERVE:-}
- TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN:-}
- TELEGRAM_CHAT_ID=${TELEGRAM_CHAT_ID:-}
- PREFETCH_RATE_EMEX=${PREFETCH_RATE_EMEX:-}
- PREFETCH_RATE_PCAT=${PREFETCH_RATE_PCAT:-}
- PREFETCH_PCAT_DELAY_MS=${PREFETCH_PCAT_DELAY_MS:-}
- PREFETCH_PL24_START=${PREFETCH_PL24_START:-}
- PREFETCH_PL24_END=${PREFETCH_PL24_END:-}
- PREFETCH_NORESULT_MAX=${PREFETCH_NORESULT_MAX:-}
- PREFETCH_NORESULT_TTL_DAYS=${PREFETCH_NORESULT_TTL_DAYS:-}
- PREFETCH_COMPLETE_TTL_DAYS=${PREFETCH_COMPLETE_TTL_DAYS:-}
# VIN foto-OCR (POST /vehicles/decode/ocr): OpenRouter üzerinden vision
# modeli. Model env'leri boşsa koddaki varsayılanlar geçerli
# (google/gemini-2.5-flash + openai/gpt-5.4-nano yedek).
- OPENROUTER_API_KEY=${OPENROUTER_API_KEY:-}
- VIN_OCR_MODEL=${VIN_OCR_MODEL:-}
- VIN_OCR_FALLBACK_MODEL=${VIN_OCR_FALLBACK_MODEL:-}
depends_on:
sase-redis:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:4000/api/health"]
interval: 15s
timeout: 5s
retries: 5
start_period: 30s
labels:
- "traefik.docker.network=coolify"
expose:
- "4000"
networks:
- default
- coolify
worker:
build:
context: .
dockerfile: Dockerfile
command: ["node", "--enable-source-maps", "apps/api/dist/worker.js"]
environment:
- NODE_ENV=production
- DATABASE_URL=${DATABASE_URL}
- REDIS_HOST=sase-redis
- REDIS_PORT=6379
- REDIS_PASSWORD=${REDIS_PASSWORD}
- MINIO_ENDPOINT=http://minio-global:9000
- MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY}
- MINIO_SECRET_KEY=${MINIO_SECRET_KEY}
- MINIO_BUCKET_NAME=${MINIO_BUCKET_NAME:-sase-schemas}
- MINIO_PUBLIC_URL=${MINIO_PUBLIC_URL}
- MINIO_USE_SSL=false
- PL24_BASE_URL=${PL24_BASE_URL:-https://www.partslink24.com}
- PL24_COMPANY_CODE=${PL24_COMPANY_CODE:-}
- PL24_USERNAME=${PL24_USERNAME:-}
- PL24_PASSWORD=${PL24_PASSWORD:-}
- PL24_COMPANY_CODE_2=${PL24_COMPANY_CODE_2:-}
- PL24_USERNAME_2=${PL24_USERNAME_2:-}
- PL24_PASSWORD_2=${PL24_PASSWORD_2:-}
- PL24_PROXY_DE=${PL24_PROXY_DE:-}
- PL24_TR_DISABLED=${PL24_TR_DISABLED:-}
- PL24_BACKFILL_ENABLED=${PL24_BACKFILL_ENABLED:-}
- EMEX_USERNAME=${EMEX_USERNAME:-}
- EMEX_PASSWORD=${EMEX_PASSWORD:-}
- EMEX_USE_PROXY=${EMEX_USE_PROXY:-false}
- EMEX_PROXY_HOST=${EMEX_PROXY_HOST:-74.81.81.81}
- EMEX_PROXY_USER=${EMEX_PROXY_USER:-1726bbe361918676d44e}
- EMEX_PROXY_PASS=${EMEX_PROXY_PASS:-f11c7b6128cc86c6}
- PCAT_USE_PROXY=${PCAT_USE_PROXY:-true}
- PCAT_PROXY_HOST=${PCAT_PROXY_HOST:-gw.dataimpulse.com}
- PCAT_PROXY_USER=${PCAT_PROXY_USER:-}
- PCAT_PROXY_PASS=${PCAT_PROXY_PASS:-}
# Vinpin ePER VIN-decode fallback (worker drives the headless browser)
- VINPIN_ENABLED=${VINPIN_ENABLED:-false}
- VINPIN_URL=${VINPIN_URL:-https://login.tr.vinpin.online}
- VINPIN_USER=${VINPIN_USER:-}
- VINPIN_PASS=${VINPIN_PASS:-}
- VINPIN_WARM_DAEMON=${VINPIN_WARM_DAEMON:-false}
# Skip Rpartstore during a known upstream outage (Renault → straight to Dialogys).
- VINPIN_RPARTSTORE_ENABLED=${VINPIN_RPARTSTORE_ENABLED:-true}
# RPartStore (Renault/Dacia) VIN-decode fallback — after pcat/PL24/emex, before Vinpin.
# Hard daily cap on searches sent to rpartstore.renault.com (default 10).
- RPARTSTORE_ENABLED=${RPARTSTORE_ENABLED:-false}
- RPARTSTORE_USER=${RPARTSTORE_USER:-}
- RPARTSTORE_PASS=${RPARTSTORE_PASS:-}
- RPARTSTORE_DAILY_CAP=${RPARTSTORE_DAILY_CAP:-10}
- RPARTSTORE_BROKER_URL=${RPARTSTORE_BROKER_URL:-wss://1po-bff.renault-edh.com/ws}
- RPARTSTORE_APP_VERSION=${RPARTSTORE_APP_VERSION:-1.34.0.6}
# Novu lifecycle e-mail automation — the worker fires trial-ending + win-back
- NOVU_API_URL=${NOVU_API_URL:-https://api.bildirim.semih.ai}
- NOVU_API_KEY=${NOVU_API_KEY:-}
- APP_PUBLIC_URL=${APP_PUBLIC_URL:-https://sase.tr}
- MAILTRACK_SECRET=${MAILTRACK_SECRET:-}
# Unsubscribe links (List-Unsubscribe header + mail footer); empty secret = mailto-only
- UNSUBSCRIBE_SECRET=${UNSUBSCRIBE_SECRET:-}
- UNSUBSCRIBE_URL_BASE=${UNSUBSCRIBE_URL_BASE:-}
- UNSUBSCRIBE_EMAIL=${UNSUBSCRIBE_EMAIL:-}
# PostHog server-side analytics (payments, subscription lifecycle, $revenue).
# Empty key → PostHogService no-ops (server-side analytics disabled).
- POSTHOG_API_KEY=${POSTHOG_API_KEY:-}
# Personal/secure key → LOCAL feature-flag evaluation (source kill switches,
# guarded decode rollout, remote config). Empty → flags fail open (inert).
- POSTHOG_PERSONAL_API_KEY=${POSTHOG_PERSONAL_API_KEY:-}
# "false" on non-prod → evaluate flags but DON'T emit analytics to prod project.
- POSTHOG_CAPTURE_ENABLED=${POSTHOG_CAPTURE_ENABLED:-}
- POSTHOG_HOST=${POSTHOG_HOST:-https://eu.i.posthog.com}
# Meta Conversions API — server-side signup tracking. Empty → CAPI no-ops.
- META_CAPI_PIXEL_ID=${META_CAPI_PIXEL_ID:-}
- META_CAPI_ACCESS_TOKEN=${META_CAPI_ACCESS_TOKEN:-}
- META_CAPI_TEST_EVENT_CODE=${META_CAPI_TEST_EVENT_CODE:-}
- OTEL_ENABLED=${OTEL_ENABLED:-false}
- OTEL_EXPORTER_OTLP_ENDPOINT=${OTEL_EXPORTER_OTLP_ENDPOINT:-}
- OTEL_EXPORTER_OTLP_HEADERS=${OTEL_EXPORTER_OTLP_HEADERS:-}
- OTEL_SERVICE_NAME=${OTEL_SERVICE_NAME:-sase-worker}
- OTEL_TRACE_SAMPLE_RATE=${OTEL_TRACE_SAMPLE_RATE:-1.0}
# Local catalog-dump lookup (worker drives prefetch which uses CategoriesService).
- CATALOG_SOURCE_DB_ENABLED=${CATALOG_SOURCE_DB_ENABLED:-false}
- PCAT_SOURCE_DB_URL=${PCAT_SOURCE_DB_URL:-}
- EMEX_SOURCE_DB_URL=${EMEX_SOURCE_DB_URL:-}
# Per-source kill switches. pcat default off (dump doesn't cover TR vehicles).
- EMEX_SOURCE_DB_ENABLED=${EMEX_SOURCE_DB_ENABLED:-true}
- PCAT_SOURCE_DB_ENABLED=${PCAT_SOURCE_DB_ENABLED:-false}
# Per-catalog parts-lookup allowlist (comma-separated). Empty → all
# fetchCategoryParts calls return null. See sase-emex-source-db-safety
# memory: catalog-wide bridge had 7-114x noise; only add a catalog once
# its per-vehicle bridge is wired & OEM-verified.
- EMEX_SOURCE_DB_ALLOWED_CATALOGS=${EMEX_SOURCE_DB_ALLOWED_CATALOGS:-}
# Tedarikçi fiyat tazeleme cron'u (19:30 İstanbul) bu env'lerle çalışır;
# boşsa processor sessiz no-op.
- SUPPLIER_PRICE_DB_ENABLED=${SUPPLIER_PRICE_DB_ENABLED:-false}
- SUPPLIER_PRICE_DB_URL=${SUPPLIER_PRICE_DB_URL:-}
# Çeviri worker'ı bu anahtarı kullanıyordu ama compose'a hiç eklenmemişti
# (sase-coolify-compose-env-injection gotcha'sı): Coolify'da tanımlansa
# bile container'a ulaşmıyordu. VIN foto-OCR işiyle birlikte düzeltildi.
- OPENROUTER_API_KEY=${OPENROUTER_API_KEY:-}
depends_on:
sase-redis:
condition: service_healthy
networks:
- default
- coolify
sase-redis:
image: redis:7.4-alpine
command: redis-server --requirepass ${REDIS_PASSWORD}
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
interval: 10s
timeout: 5s
retries: 5
networks:
- default
volumes:
redis_data:
networks:
coolify:
external: true