package config import ( "fmt" "os" "time" ) type Config struct { Env string // dev | stage | prod Addr string // listen address, e.g. ":8090" KeycloakIssuer string // e.g. http://localhost:8080/realms/breakpilot-dev DatabaseURL string // postgres DSN (unused in skeleton; in-memory store) // Keycloak Admin API — only used if KeycloakAdminURL is set. Empty // values disable the adapter and tenant-registry falls back to the // Mock (dev convenience). KeycloakAdminURL string KeycloakRealm string KeycloakClientID string KeycloakClientSecret string KeycloakTimeout time.Duration } func Load() (*Config, error) { env := getenv("APP_ENV", "dev") if env != "dev" && env != "stage" && env != "prod" { return nil, fmt.Errorf("invalid APP_ENV %q", env) } return &Config{ Env: env, // :8090 — Keycloak owns :8080 in the dev stack. Addr: getenv("ADDR", ":8090"), KeycloakIssuer: getenv("KEYCLOAK_ISSUER", "http://localhost:8080/realms/breakpilot-dev"), DatabaseURL: os.Getenv("DATABASE_URL"), KeycloakAdminURL: os.Getenv("KEYCLOAK_ADMIN_URL"), KeycloakRealm: getenv("KEYCLOAK_REALM", "breakpilot-dev"), KeycloakClientID: os.Getenv("KEYCLOAK_CLIENT_ID"), KeycloakClientSecret: os.Getenv("KEYCLOAK_CLIENT_SECRET"), KeycloakTimeout: 10 * time.Second, }, nil } func getenv(key, fallback string) string { if v := os.Getenv(key); v != "" { return v } return fallback }