/** * Zentrale, typsichere Konfiguration aus Umgebungsvariablen. * * Alle Werte werden beim ersten Zugriff validiert, damit Fehlkonfigurationen * sofort (und nicht erst zur Laufzeit an versteckter Stelle) auffallen. * Keine Magic Strings in der restlichen Anwendung. */ function requireEnv(name: string): string { const value = process.env[name]; if (!value || value.trim().length === 0) { throw new Error( `Umgebungsvariable ${name} ist nicht gesetzt. Bitte .env anlegen (Vorlage: .env.example).`, ); } return value.trim(); } /** Session-Secret: mindestens 32 Zeichen, sonst ist es nicht sicher. */ function requireSessionSecret(): string { const secret = requireEnv('SESSION_SECRET'); if (secret.length < 32) { throw new Error( 'SESSION_SECRET muss mindestens 32 Zeichen lang sein (z. B. crypto.randomBytes(48).toString("base64url")).', ); } return secret; } /** Liest die Konfiguration einmalig und cached das Ergebnis. */ let cachedConfig: AppConfig | undefined; export interface AppConfig { sessionSecret: string; /** Wenn false, sind neue lokale Registrierungen deaktiviert. */ allowOpenRegistration: boolean; /** MultiToolApp-Plattform: Basis-URL (JWKS-Abruf). null = SSO deaktiviert. */ hubUrl: string | null; /** Tool-Slug in der Hub-Registry (Token-`aud`). */ hubToolSlug: string | null; /** Erwarteter Token-`iss` (Hub-Basis-URL). */ hubIssuer: string | null; } export function getConfig(): AppConfig { if (cachedConfig) { return cachedConfig; } cachedConfig = { sessionSecret: requireSessionSecret(), allowOpenRegistration: (process.env.ALLOW_OPEN_REGISTRATION ?? 'true').toLowerCase() === 'true', hubUrl: process.env.HUB_URL?.trim() || null, hubToolSlug: process.env.HUB_TOOL_SLUG?.trim() || null, hubIssuer: process.env.HUB_ISSUER?.trim() || null, }; return cachedConfig; }