- Created
PayoutMethodmodel in Prisma schema - Added encrypted fields for sensitive data:
encryptedAccountNumberencryptedRoutingNumberencryptedSwiftCodeencryptedIban
- Added non-sensitive fields:
bankNameaccountHolderNamecountrycurrencylastFourDigits(for display)
- Added soft delete support (
deletedAt) - Added relationship to
Usermodel - Added relationship to
Payoutmodel - Created database migration file
- Created
CreatePayoutMethodDtowith validation- Type validation (bank_account, wire_transfer, ach)
- Optional fields for different payout types
- Swagger/OpenAPI documentation
- Created
UpdatePayoutMethodDto- Only allows updating non-sensitive fields
- Prevents modification of encrypted data
- Created
PayoutMethodServicewith full CRUD operations - Implemented encryption/decryption using existing
EncryptionService - Key methods:
create()- Encrypts sensitive data before storagefindAll()- Returns sanitized listfindOne()- Returns sanitized single recordfindOneWithSensitiveData()- Internal use only, decrypts dataupdate()- Updates non-sensitive fieldsremove()- Soft deletesgetDefaultMethod()- Gets user's default payout method
- Data sanitization (removes encrypted fields from responses)
- Last 4 digits extraction for display
- Default method management (only one default per user)
- Created
PayoutMethodControllerwith REST endpoints - JWT authentication on all endpoints
- Swagger/OpenAPI documentation
- Endpoints:
POST /payout-methods- Create new methodGET /payout-methods- List all methodsGET /payout-methods/default- Get default methodGET /payout-methods/:id- Get specific methodPUT /payout-methods/:id- Update methodDELETE /payout-methods/:id- Delete method
- Updated
PayoutsModuleto include:PayoutMethodServicePayoutMethodControllerEncryptionModuleimport
- Exported
PayoutMethodServicefor use in other modules
- Added
ENCRYPTION_SECRETto.env.example - Documented secret generation instructions
- Added security recommendations
- Created comprehensive test suite (
payout-method.service.spec.ts) - Test coverage includes:
- Encryption/decryption
- Data sanitization
- Default method management
- Soft deletion
- Access control
- Validation
- IBAN/SWIFT support
- Error handling
- Created
FIAT_PAYOUT_SECURITY.mdwith:- Architecture overview
- Security features
- API documentation
- Environment setup
- Compliance considerations
- Future enhancements
# Generate Prisma client
npx prisma generate
# Apply migration
npx prisma migrate deploy
# Or for development
npx prisma migrate dev# Generate encryption secret
openssl rand -base64 32
# Add to .env file
ENCRYPTION_SECRET="<generated_secret>"# Run all tests
npm test
# Run specific test file
npm test -- payout-method.service.spec.ts
# Run with coverage
npm test -- --coverage- Test creating payout methods via API
- Test listing payout methods
- Test updating payout methods
- Test deleting payout methods
- Verify encryption in database
- Test default method switching
- Review encryption implementation
- Verify no sensitive data in logs
- Check API response sanitization
- Test access control (users can only access their own methods)
- Verify soft delete functionality
- Set up secure secret management (AWS Secrets Manager, Vault, etc.)
- Configure different secrets per environment
- Set up monitoring and alerting
- Document key rotation procedures
- Set up audit logging
| Criteria | Status | Notes |
|---|---|---|
| Add encrypted fields for bank account info | ✅ | All sensitive fields encrypted with AES-256-GCM |
| Create PayoutMethod model | ✅ | Full model with relationships and soft delete |
| Encrypt/decrypt in service layer | ✅ | Using existing EncryptionService |
| Secure storage | ✅ | Encrypted at rest, sanitized in responses |
| API endpoints | ✅ | Full CRUD with authentication |
| Tests | ✅ | Comprehensive test suite created |
| Documentation | ✅ | Complete security documentation |
-
Encryption at Rest
- AES-256-GCM encryption
- Unique IV per encryption
- Authenticated encryption (AEAD)
-
Data Minimization
- Only last 4 digits stored in plaintext
- Full numbers never exposed in API responses
-
Access Control
- JWT authentication required
- User isolation (can only access own methods)
-
Audit Trail
- Soft deletion preserves history
- Timestamps on all records
-
Default Management
- Automatic default switching
- Only one default per user
prisma/migrations/20260531_add_payout_method/migration.sqlsrc/payouts/dto/create-payout-method.dto.tssrc/payouts/dto/update-payout-method.dto.tssrc/payouts/payout-method.service.tssrc/payouts/payout-method.controller.tssrc/payouts/payout-method.service.spec.tsFIAT_PAYOUT_SECURITY.mdIMPLEMENTATION_CHECKLIST.md
prisma/schema.prisma- Added PayoutMethod model and relationshipssrc/payouts/payouts.module.ts- Added new service and controller.env.example- Added ENCRYPTION_SECRET
-
Set up environment:
# Generate secret openssl rand -base64 32 # Add to .env echo "ENCRYPTION_SECRET=<your_secret>" >> .env
-
Run migration:
npx prisma migrate dev
-
Start server:
npm run start:dev
-
Test API:
# Create payout method curl -X POST http://localhost:3000/payout-methods \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "type": "bank_account", "accountNumber": "1234567890", "routingNumber": "021000021", "bankName": "Chase Bank", "accountHolderName": "John Doe" }'
- Never commit
ENCRYPTION_SECRETto version control - Use different secrets for each environment
- Implement key rotation strategy for production
- Monitor and log access to sensitive data
- Regular security audits recommended
- Consider PCI DSS compliance requirements for production
For questions or issues:
- Review
FIAT_PAYOUT_SECURITY.mdfor detailed documentation - Check test files for usage examples
- Contact security team for encryption key management