diff --git a/err.txt b/err.txt new file mode 100644 index 0000000..a3dcf99 --- /dev/null +++ b/err.txt @@ -0,0 +1 @@ +[config] JWT_SECRET neni nastavena. Pouzivam nahodny klic platny jen do restartu containeru. Nastavte JWT_SECRET jako promennou aplikace v AppFactory. diff --git a/out.txt b/out.txt new file mode 100644 index 0000000..3105cbf --- /dev/null +++ b/out.txt @@ -0,0 +1,4 @@ +[start] csbot-prototype bezi na portu 3000 +[start] ROOT_PATH: /apps/csbot-prototype +[start] health: /apps/csbot-prototype/health, docs: /apps/csbot-prototype/docs +[req] GET /health diff --git a/src/config.ts b/src/config.ts index 6e597ab..c902381 100644 --- a/src/config.ts +++ b/src/config.ts @@ -2,19 +2,37 @@ * Konfigurace z environment variables. * AppFactory je predava containeru, viz AGENTS.md, sekce Variables a secrets. * Zadna hodnota se nehardcoduje a zadny secret se neloguje. + * + * Pravidlo: chybejici konfigurace nesmi shodit start aplikace. Container, + * ktery nenastartuje, je pro AppFactory nefunkcni sluzba. */ +import { randomBytes } from 'node:crypto'; + const isProduction = process.env.NODE_ENV === 'production'; -function requiredInProduction(name: string, fallback: string): string { - const value = process.env[name]; +/** + * Tajny klic pro podpis tokenu. + * + * Kdyz promenna chybi, NEPADAME a ani nepouzijeme klic zapsany v kodu. + * Aplikace musi nastartovat a odpovidat na /health, jinak ji AppFactory + * vyhodnoti jako nefunkcni. Misto toho se vygeneruje nahodny klic pro + * beh procesu a do logu jde hlasite varovani. + * + * Dusledek: po restartu containeru prestanou platit vydane tokeny + * a uzivatele se musi prihlasit znovu. Proto se JWT_SECRET ma nastavit + * jako promenna aplikace v AppFactory. + */ +function resolveJwtSecret(): string { + const value = process.env.JWT_SECRET; if (value && value.trim().length > 0) return value; - if (isProduction) { - // Zamerne padame pri startu - tichy fallback na dev secret by byl bezpecnostni dira. - throw new Error(`Chybi povinna promenna prostredi ${name} (NODE_ENV=production).`); - } - console.warn(`[config] ${name} neni nastavena, pouzivam DEV fallback. Nepouzivat v produkci.`); - return fallback; + + const generated = randomBytes(32).toString('base64url'); + console.warn( + '[config] JWT_SECRET neni nastavena. Pouzivam nahodny klic platny jen do restartu ' + + 'containeru. Nastavte JWT_SECRET jako promennou aplikace v AppFactory.', + ); + return generated; } /** @@ -34,7 +52,7 @@ export const config = { /** Port urcuje AppFactory sablona, vychozi 3000. Nemenit bez upravy metadat. */ port: Number(process.env.PORT ?? 3000), rootPath: normalizeRootPath(process.env.ROOT_PATH), - jwtSecret: requiredInProduction('JWT_SECRET', 'dev-only-secret-nepouzivat-v-produkci'), + jwtSecret: resolveJwtSecret(), jwtExpiresIn: process.env.JWT_EXPIRES_IN ?? '8h', /** * Povolene originy pro CORS. V nasazeni bezi web i API na stejne domene,