import 'dotenv/config'; import { z } from 'zod'; const EnvSchema = z.object({ NODE_ENV: z.enum(['development', 'test', 'production']).default('development'), PORT: z.coerce.number().default(3000), DATABASE_URL: z.string().min(1), REDIS_URL: z.string().default('redis://localhost:6379'), JWT_SECRET: z.string().min(16, 'JWT_SECRET : 16 caractères minimum'), JWT_EXPIRES_IN: z.string().default('8h'), MINIO_ENDPOINT: z.string().default('localhost'), MINIO_PORT: z.coerce.number().default(9000), MINIO_USE_SSL: z.string().optional(), MINIO_ACCESS_KEY: z.string().default('siop'), MINIO_SECRET_KEY: z.string().default('siop-minio'), MINIO_BUCKET: z.string().default('siop2'), }); export type Env = z.infer; /** Validée au démarrage — l'API refuse de booter sur une config invalide. */ export function loadEnv(): Env { const parsed = EnvSchema.safeParse(process.env); if (!parsed.success) { throw new Error( `Configuration invalide :\n${parsed.error.issues .map((i) => ` - ${i.path.join('.')}: ${i.message}`) .join('\n')}`, ); } return parsed.data; } /** Lues à l'appel (et non à l'import) pour rester testables. */ export function demoModeEnabled(): boolean { return process.env.DEMO_MODE === 'true'; } /** * ADR-002, double verrou : DEMO_MODE=true en production exige l'aveu explicite * DEMO_MODE_I_KNOW=true (réservé à l'instance de démonstration publique). */ export function assertDemoModeAllowed(): void { if ( demoModeEnabled() && process.env.NODE_ENV === 'production' && process.env.DEMO_MODE_I_KNOW !== 'true' ) { throw new Error( 'DEMO_MODE=true en production sans DEMO_MODE_I_KNOW=true — démarrage refusé (ADR-002).', ); } }