// Package config — env-based конфиг learning-сервиса. Стиль envStr идентичен // candidates/tasks/booking — чтобы k8s-манифесты выглядели единообразно. package config import ( "os" "strconv" ) type Config struct { ServerPort string DatabaseURL string MigrationsDir string // InternalAPIKey — общий ключ с порталом для server-to-server auth. // Portal-proxy ставит X-Internal-Key + X-User-Id; сервис верифицирует // ключ и доверяет X-User-Id (JWT уже провалидирован на портале). InternalAPIKey string // PortalURL — для in-app уведомлений (назначен курс/тест/пройден тест). // Если пусто — notify-вызовы тихо no-op'ятся, основной flow работает. PortalURL string // PublicBaseURL — внешний origin, под которым отдаются public-ссылки // для кандидатов (например, https://portal.estateliga.work). Используется // в формате URL'ей: /public/learning/test/. PublicBaseURL string // MinIO для видео-уроков. Структура та же что в telephony (records bucket), // но bucket отдельный — public-link'и читают видео через стрим-прокси. MinIOEndpoint string MinIOAccessKey string MinIOSecretKey string MinIOBucket string MinIOUseSSL bool // RedisAddr — пустой = eventbus отключён, сервис работает без публикации // событий (попадание кандидата на тест не уведомит HR в realtime). RedisAddr string RedisPassword string RedisDB int PodName string } func Load() *Config { return &Config{ ServerPort: envStr("SERVER_PORT", "3001"), DatabaseURL: envStr("DATABASE_URL", "postgres://learning:learning@localhost:5432/learning?sslmode=disable"), MigrationsDir: envStr("MIGRATIONS_DIR", "/migrations"), InternalAPIKey: envStr("INTERNAL_API_KEY", envStr("PORTAL_INTERNAL_API_KEY", "")), PortalURL: envStr("PORTAL_URL", ""), PublicBaseURL: envStr("PUBLIC_BASE_URL", ""), MinIOEndpoint: envStr("MINIO_ENDPOINT", ""), MinIOAccessKey: envStr("MINIO_ACCESS_KEY", ""), MinIOSecretKey: envStr("MINIO_SECRET_KEY", ""), MinIOBucket: envStr("MINIO_BUCKET", "learning-videos"), MinIOUseSSL: envBool("MINIO_USE_SSL", false), RedisAddr: envStr("REDIS_ADDR", ""), RedisPassword: envStr("REDIS_PASSWORD", ""), RedisDB: envInt("REDIS_DB", 0), PodName: envStr("POD_NAME", hostname()), } } func envInt(key string, def int) int { if v := os.Getenv(key); v != "" { if n, err := strconv.Atoi(v); err == nil { return n } } return def } func envBool(key string, def bool) bool { if v := os.Getenv(key); v != "" { if b, err := strconv.ParseBool(v); err == nil { return b } } return def } func envStr(key, def string) string { if v := os.Getenv(key); v != "" { return v } return def } func hostname() string { h, err := os.Hostname() if err != nil { return "unknown" } return h }