import { ValidationPipe } from '@nestjs/common'; import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import { GlobalExceptionFilter } from './common/filters/global-exception.filter'; import helmet from 'helmet'; async function bootstrap() { const app = await NestFactory.create(AppModule); // CORS — tillåt endast appens egen origin (sätts via ALLOWED_ORIGIN i miljövariabler) const allowedOrigin = process.env.ALLOWED_ORIGIN || 'https://recept.gynther.se'; app.enableCors({ origin: allowedOrigin, methods: ['GET', 'POST', 'PATCH', 'PUT', 'DELETE', 'OPTIONS'], allowedHeaders: ['Content-Type', 'Authorization'], credentials: true, }); // Helmet som säkerhetsbackup (CSP hanteras av Next.js/Caddy) app.use( helmet({ contentSecurityPolicy: false, crossOriginEmbedderPolicy: true, crossOriginOpenerPolicy: { policy: 'same-origin' }, crossOriginResourcePolicy: { policy: 'same-origin' }, originAgentCluster: true, referrerPolicy: { policy: 'strict-origin-when-cross-origin' }, strictTransportSecurity: { maxAge: 31536000, includeSubDomains: true, preload: true, }, xContentTypeOptions: true, xFrameOptions: { action: 'deny' }, xXssProtection: false, // Deprecated, hanteras av Caddy }), ); app.setGlobalPrefix('api'); // Registrera global exception filter app.useGlobalFilters(new GlobalExceptionFilter()); app.useGlobalPipes( new ValidationPipe({ whitelist: true, forbidNonWhitelisted: true, transform: true, }), ); await app.listen(8080, '0.0.0.0'); } bootstrap();