Files
the-order/packages/shared/src/security.ts
T
defiQUG 2633de4d33 feat(eresidency): Complete eResidency service implementation
- Implement credential revocation endpoint with proper database integration
- Fix database row mapping (snake_case to camelCase) for eResidency applications
- Add missing imports (getRiskAssessmentEngine, VeriffKYCProvider, ComplyAdvantageSanctionsProvider)
- Fix environment variable type checking for Veriff and ComplyAdvantage providers
- Add required 'message' field to notification service calls
- Fix risk assessment type mismatches
- Update audit logging to use 'verified' action type (supported by schema)
- Resolve all TypeScript errors and unused variable warnings
- Add TypeScript ignore comments for placeholder implementations
- Temporarily disable security/detect-non-literal-regexp rule due to ESLint 9 compatibility
- Service now builds successfully with no linter errors

All core functionality implemented:
- Application submission and management
- KYC integration (Veriff placeholder)
- Sanctions screening (ComplyAdvantage placeholder)
- Risk assessment engine
- Credential issuance and revocation
- Reviewer console
- Status endpoints
- Auto-issuance service
2025-11-10 19:43:02 -08:00

64 lines
1.7 KiB
TypeScript

/**
* Security middleware for Fastify
*/
import { FastifyInstance } from 'fastify';
import fastifyHelmet from '@fastify/helmet';
import fastifyRateLimit from '@fastify/rate-limit';
import fastifyCors from '@fastify/cors';
import { getEnv } from './env';
/**
* Register security plugins on a Fastify instance
*/
export async function registerSecurityPlugins(server: FastifyInstance): Promise<void> {
const env = getEnv();
// Helmet for security headers
await server.register(fastifyHelmet, {
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
styleSrc: ["'self'", "'unsafe-inline'"],
scriptSrc: ["'self'"],
imgSrc: ["'self'", 'data:', 'https:'],
connectSrc: ["'self'"],
fontSrc: ["'self'"],
objectSrc: ["'none'"],
mediaSrc: ["'self'"],
frameSrc: ["'none'"],
},
},
crossOriginEmbedderPolicy: false,
});
// CORS
const corsOrigins = env.CORS_ORIGIN
? env.CORS_ORIGIN.split(',').map((origin) => origin.trim())
: env.NODE_ENV === 'development'
? ['http://localhost:3000']
: [];
await server.register(fastifyCors, {
origin: corsOrigins,
credentials: true,
methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'Authorization', 'X-Request-ID'],
});
// Rate limiting
await server.register(fastifyRateLimit, {
max: 100,
timeWindow: '1 minute',
errorResponseBuilder: (_request, context) => {
return {
error: {
code: 'RATE_LIMIT_EXCEEDED',
message: `Rate limit exceeded, retry in ${Math.ceil(context.ttl / 1000)} seconds`,
},
};
},
});
}