Files
brazil-swift-ops/packages/utils/src/config.ts
defiQUG 4f637ede8c Implement Phase 1a, 1b, 1c: Database, Auth, and API Endpoints
Phase 1a - Database Setup:
- Add PostgreSQL connection pooling with pg client
- Create 8 SQL migrations for all database schemas
- Implement migration execution system with tracking
- Add environment configuration for database and JWT settings

Phase 1b - Authentication & Authorization:
- Implement password hashing with bcrypt
- Create JWT token generation (access + refresh tokens)
- Implement RBAC with 5 roles (Admin, Manager, Analyst, Auditor, Viewer)
- Create auth middleware for authentication and authorization
- Add auth routes (login, register, refresh, logout, profile)

Phase 1c - API Endpoints (Full CRUD):
- Transaction endpoints with evaluation and batch processing
- Account management (treasury and subledger accounts)
- User management (admin-only)
- FX contract management
- Compliance endpoints (rules, results, thresholds)
- Reporting endpoints (summary, compliance, audit logs)
- Health check endpoints with database status

Phase 1d - Data Seeding:
- Create database seeding system with roles, permissions, users
- Add sample data (treasury accounts, FX contracts)
- Implement admin user creation from environment variables

All endpoints protected with authentication and role-based access control.
2026-01-23 18:48:59 -08:00

180 lines
6.6 KiB
TypeScript

/**
* Configuration management
* Externalizes configuration from environment variables and config files
*/
export interface AppConfig {
// Application
appName: string;
appVersion: string;
environment: 'development' | 'staging' | 'production';
port?: number;
// Institution
institutionBIC: string;
institutionName: string;
institutionCountry: string;
// Regulatory
reportingThresholdUSD: number;
amlStructuringThresholdUSD: number;
amlStructuringWindowDays: number;
// IOF Rates
iofRateInbound: number;
iofRateOutbound: number;
// FX Rates
fxRateProvider: 'hardcoded' | 'central-bank' | 'bloomberg' | 'reuters' | 'xe';
fxRateCacheTTL: number; // seconds
// Database (when implemented)
databaseUrl?: string;
databasePoolSize?: number;
// Logging
logLevel: 'debug' | 'info' | 'warn' | 'error' | 'fatal';
logFormat: 'json' | 'text';
// Security
enableAuth: boolean;
sessionSecret?: string;
jwtSecret?: string;
jwtRefreshSecret?: string;
jwtExpiryMinutes?: number;
jwtRefreshExpiryDays?: number;
// Admin credentials (for initial setup)
adminEmail?: string;
adminPassword?: string;
// BCB Reporting
bcbReportingEnabled: boolean;
bcbReportingApiUrl?: string;
bcbReportingApiKey?: string;
// Audit
auditRetentionDays: number;
auditAutoDelete: boolean;
}
/**
* Load configuration from environment variables
*/
export function loadConfig(): AppConfig {
return {
appName: process.env.APP_NAME || 'Brazil SWIFT Operations',
appVersion: process.env.APP_VERSION || '1.0.0',
environment: ((typeof process !== 'undefined' ? process.env?.NODE_ENV : undefined) as any) || 'development',
port: typeof process !== 'undefined' ? parseInt(process.env?.PORT || '3000', 10) : 3000,
institutionBIC: (typeof process !== 'undefined' ? process.env?.INSTITUTION_BIC : undefined) || 'ESTRBRRJ',
institutionName: (typeof process !== 'undefined' ? process.env?.INSTITUTION_NAME : undefined) || 'Strategy Investimentos S/A CVC',
institutionCountry: (typeof process !== 'undefined' ? process.env?.INSTITUTION_COUNTRY : undefined) || 'BR',
reportingThresholdUSD: parseFloat((typeof process !== 'undefined' ? process.env?.REPORTING_THRESHOLD_USD : undefined) || '10000'),
amlStructuringThresholdUSD: parseFloat((typeof process !== 'undefined' ? process.env?.AML_STRUCTURING_THRESHOLD_USD : undefined) || '10000'),
amlStructuringWindowDays: parseInt((typeof process !== 'undefined' ? process.env?.AML_STRUCTURING_WINDOW_DAYS : undefined) || '30', 10),
iofRateInbound: parseFloat((typeof process !== 'undefined' ? process.env?.IOF_RATE_INBOUND : undefined) || '0.0038'),
iofRateOutbound: parseFloat((typeof process !== 'undefined' ? process.env?.IOF_RATE_OUTBOUND : undefined) || '0.035'),
fxRateProvider: ((typeof process !== 'undefined' ? process.env?.FX_RATE_PROVIDER : undefined) as any) || 'hardcoded',
fxRateCacheTTL: parseInt((typeof process !== 'undefined' ? process.env?.FX_RATE_CACHE_TTL : undefined) || '3600', 10),
databaseUrl: typeof process !== 'undefined' ? process.env?.DATABASE_URL : undefined,
databasePoolSize: parseInt((typeof process !== 'undefined' ? process.env?.DATABASE_POOL_SIZE : undefined) || '10', 10),
logLevel: ((typeof process !== 'undefined' ? process.env?.LOG_LEVEL : undefined) as any) || 'info',
logFormat: ((typeof process !== 'undefined' ? process.env?.LOG_FORMAT : undefined) as any) || 'json',
enableAuth: (typeof process !== 'undefined' ? process.env?.ENABLE_AUTH : undefined) === 'true',
sessionSecret: typeof process !== 'undefined' ? process.env?.SESSION_SECRET : undefined,
jwtSecret: typeof process !== 'undefined' ? process.env?.JWT_SECRET : undefined,
jwtRefreshSecret: typeof process !== 'undefined' ? process.env?.JWT_REFRESH_SECRET : undefined,
jwtExpiryMinutes: parseInt((typeof process !== 'undefined' ? process.env?.JWT_EXPIRY_MINUTES : undefined) || '15', 10),
jwtRefreshExpiryDays: parseInt((typeof process !== 'undefined' ? process.env?.JWT_REFRESH_EXPIRY_DAYS : undefined) || '7', 10),
adminEmail: typeof process !== 'undefined' ? process.env?.ADMIN_EMAIL : undefined,
adminPassword: typeof process !== 'undefined' ? process.env?.ADMIN_PASSWORD : undefined,
bcbReportingEnabled: (typeof process !== 'undefined' ? process.env?.BCB_REPORTING_ENABLED : undefined) === 'true',
bcbReportingApiUrl: typeof process !== 'undefined' ? process.env?.BCB_REPORTING_API_URL : undefined,
bcbReportingApiKey: typeof process !== 'undefined' ? process.env?.BCB_REPORTING_API_KEY : undefined,
auditRetentionDays: parseInt((typeof process !== 'undefined' ? process.env?.AUDIT_RETENTION_DAYS : undefined) || '2555', 10), // 7 years
auditAutoDelete: (typeof process !== 'undefined' ? process.env?.AUDIT_AUTO_DELETE : undefined) === 'true',
};
}
/**
* Validate configuration
*/
export function validateConfig(config: AppConfig): { valid: boolean; errors: string[] } {
const errors: string[] = [];
if (!config.institutionBIC || config.institutionBIC.length !== 8) {
errors.push('Institution BIC must be 8 characters');
}
if (config.reportingThresholdUSD <= 0) {
errors.push('Reporting threshold must be greater than 0');
}
if (config.iofRateInbound < 0 || config.iofRateInbound > 1) {
errors.push('IOF inbound rate must be between 0 and 1');
}
if (config.iofRateOutbound < 0 || config.iofRateOutbound > 1) {
errors.push('IOF outbound rate must be between 0 and 1');
}
if (config.auditRetentionDays < 0) {
errors.push('Audit retention days must be non-negative');
}
if (config.enableAuth && !config.sessionSecret && !config.jwtSecret) {
errors.push('Authentication enabled but no session or JWT secret provided');
}
if (config.bcbReportingEnabled && !config.bcbReportingApiUrl) {
errors.push('BCB reporting enabled but no API URL provided');
}
return {
valid: errors.length === 0,
errors,
};
}
/**
* Get default configuration (for development)
*/
export function getDefaultConfig(): AppConfig {
return loadConfig();
}
// Singleton instance
let configInstance: AppConfig | null = null;
/**
* Get configuration singleton
*/
export function getConfig(): AppConfig {
if (!configInstance) {
configInstance = loadConfig();
const validation = validateConfig(configInstance);
if (!validation.valid) {
console.warn('Configuration validation errors:', validation.errors);
}
}
return configInstance;
}
/**
* Reset configuration (useful for testing)
*/
export function resetConfig(): void {
configInstance = null;
}