"""OSINT Dashboard — centralized configuration (12-factor, env-driven). All infrastructure endpoints are read from the environment with container-friendly defaults. No secrets, hostnames, or cluster-specific addresses are hardcoded anywhere in the codebase. Override per environment via environment variables (docker-compose, k8s ConfigMap/Secret, or systemd): DB_USER, DB_PASSWORD, DB_HOST, DB_PORT, DB_NAME NATS_URL MINIO_ENDPOINT, MINIO_ACCESS_KEY, MINIO_SECRET_KEY, MINIO_SECURE """ from __future__ import annotations import os from urllib.parse import quote_plus # ── PostgreSQL ──────────────────────────────────────────────────────────── # Defaults assume docker-compose/k8s service names. Override for your stack. DB_USER = os.getenv("DB_USER", "osint") DB_PASSWORD = os.getenv("DB_PASSWORD", "") DB_HOST = os.getenv("DB_HOST", "postgres") DB_PORT = os.getenv("DB_PORT", "5432") DB_NAME = os.getenv("DB_NAME", "osint_data") # Async SQLAlchemy URL. Password is URL-encoded so special chars are safe. DATABASE_URL = ( f"postgresql+asyncpg://" f"{DB_USER}:{quote_plus(DB_PASSWORD)}@{DB_HOST}:{DB_PORT}/{DB_NAME}" ) # ── NATS JetStream ───────────────────────────────────────────────────────── NATS_URL = os.getenv("NATS_URL", "nats://nats:4222") # ── MinIO (document storage) ──────────────────────────────────────────────── MINIO_ENDPOINT = os.getenv("MINIO_ENDPOINT", "minio:9000") MINIO_ACCESS_KEY = os.getenv("MINIO_ACCESS_KEY", "") MINIO_SECRET_KEY = os.getenv("MINIO_SECRET_KEY", "") # "false" / "0" / "no" (case-insensitive) → plain HTTP (e.g. local compose). MINIO_SECURE = os.getenv("MINIO_SECURE", "false").lower() not in ("false", "0", "no") # ── NASA FIRMS (active fire / hotspot ingest) ─────────────────────────────── # MAP_KEY is free; obtain one at https://firms.modaps.eosdis.nasa.gov/api/map_key_info/ # and set FIRMS_MAP_KEY in .env. Until it is set, the fire ingestor logs a # warning and stays idle (no crash). FIRMS_MAP_KEY = os.getenv("FIRMS_MAP_KEY", "") # NRT VIIRS S-NPP active fire/hotspot detection (375m). FIRMS_DATASET = os.getenv("FIRMS_DATASET", "VIIRS_SNPP_NRT") # Area bounding box as "minlon,minlat,maxlon,maxlat". Default covers most of # the inhabited globe; narrow it (e.g. CONUS "-125,24,-66,50") to shrink # payloads and the Postgres write volume. FIRMS_BBOX = os.getenv("FIRMS_BBOX", "-180,-60,180,75") # Poll cadence in seconds. FIRMS NRT updates every ~5-10 min; 900 = 15 min. FIRMS_INTERVAL = int(os.getenv("FIRMS_INTERVAL", "900")) # Day range for the area-CSV request. FIRMS accepts [1..5] days of NRT # detections; the API 400s when this parameter is omitted. FIRMS_DAYS = int(os.getenv("FIRMS_DAYS", "1")) # Outbound HTTP timeout for the FIRMS CSV download. FIRMS_TIMEOUT = float(os.getenv("FIRMS_TIMEOUT", "60"))