Labels: backend, security, wave4
Complexity: 100 points
Branch: feat/be-config-validate
Prevented misconfiguration incidents by implementing comprehensive environment variable validation and secure error handling at startup.
File: src/config/env.schema.ts
- Added validation for
SUPABASE_SERVICE_ROLE_KEY(optional) - Added validation for
HORIZON_URL(optional, overrides network default) - Added validation for
STELLAR_SECRET_KEY(optional, required for payment signing) - Added validation for
STELLAR_PUBLIC_KEY(optional) - All new fields include proper Joi validation with descriptions
- Updated
EnvConfiginterface with new type definitions
File: src/common/utils/redaction.util.ts (NEW)
Created comprehensive utilities to prevent secret leakage:
redactSensitiveValues(): Redacts sensitive env vars in objectsredactValue(): Masks individual values (shows first/last 4 chars)sanitizeErrorMessage(): Removes secrets from error messages- Redacts Stellar secret keys (S + 55 chars)
- Redacts Stellar public keys (G + 55 chars)
- Redacts JWT tokens
- Redacts Supabase keys
createConfigSummary(): Safe config logging without exposing values
File: src/config/app-config.service.ts
Added typed accessors for new configuration:
supabaseServiceRoleKeyhorizonUrlstellarSecretKeystellarPublicKeyisPaymentSigningConfigured(convenience boolean)sentryDsn(was in merge conflict, now resolved)
File: src/main.ts
- Added
validateCriticalConfig()function - Validates required settings at bootstrap:
- SUPABASE_URL
- SUPABASE_ANON_KEY
- NETWORK
- Fails fast with clear error messages if critical config missing
- Logs safe configuration summary (no secrets)
- Warns if payment signing not configured
File: src/health/health.service.ts
Improved /ready endpoint to report config readiness safely:
- Checks database configuration loaded
- Validates network configuration
- Verifies Horizon configuration
- Reports payment signing capability
- All error messages sanitized (no secrets)
- Detailed status messages without exposing values
Files:
src/common/utils/redaction.util.unit.spec.ts(NEW)- Tests for all redaction utilities
- Tests for sanitization functions
- Tests for config summary generation
✅ App refuses to boot with missing critical config
✅ No secret values appear in logs or API responses
✅ Health endpoint indicates readiness safely
✅ All sensitive values redacted in error messages
Labels: Backend, Automation
Complexity: Medium (150 points)
Branch: feat/bulk-links
Support generating hundreds of unique payment links at once for payroll or bulk invoicing.
File: src/links/dto/bulk-payment-link.dto.ts (NEW)
Created comprehensive DTOs with validation:
-
BulkPaymentLinkItemDto: Single payment link item- Amount (required, validated)
- Asset (optional, defaults to XLM)
- Memo & memoType (optional)
- Username or destination (optional)
- Reference ID (optional)
- Privacy flag (optional)
- Expiration days (optional)
- Accepted assets (optional)
-
BulkPaymentLinkRequestDto: JSON request wrapper -
BulkPaymentLinkResponseItemDto: Single link response -
BulkPaymentLinkResponseDto: Bulk response with metadata
File: src/links/bulk-payment-links.service.ts (NEW)
Core business logic for bulk generation:
Features:
-
JSON Processing:
generateBulkLinks()- Validates batch size (max 500 links per request)
- Processes in batches of 50 for performance
- Parallel processing with concurrency control
- Comprehensive error reporting
-
CSV Processing:
generateFromCSV()- Parses CSV with headers
- Required "amount" column validation
- Supports all payment link fields
- Handles quoted values
- Pipe-separated acceptedAssets
-
Link Generation:
generateSingleLink()- Reuses existing LinksService for validation
- Generates unique IDs (UUID-based)
- Creates canonical format
- Builds shareable URLs
File: src/links/bulk-payment-links.controller.ts (NEW)
REST API endpoints:
-
POST
/links/bulk/generate(JSON)- Accepts array of payment link items
- Returns generated links with metadata
- Full Swagger documentation
-
POST
/links/bulk/generate/csv(CSV Upload)- Accepts CSV file upload
- Parses and validates CSV
- Returns generated links with metadata
- Uses multer for file handling
File: src/links/links.module.ts
- Added
BulkPaymentLinksController - Added
BulkPaymentLinksService - Exported service for potential reuse
File: src/links/bulk-payment-links.service.unit.spec.ts (NEW)
Extensive test coverage:
- Bulk generation success scenarios
- Empty array validation
- Max limit enforcement (500 links)
- Batch processing verification
- Partial failure handling
- CSV parsing tests
- Invalid CSV handling
- Quoted value handling
- Pipe-separated acceptedAssets parsing
✅ Successfully generates 100+ links in a single request without timeout
✅ Accepts JSON array of payment details
✅ Accepts CSV file upload
✅ Batch-processes and stores metadata efficiently
✅ Returns list of shareable links
✅ Processing time tracked and returned
- Processes in batches of 50 to prevent system overload
- Parallel processing within batches using Promise.all
- Supports up to 500 links per request
- Processing time tracked and returned in response
- Memory efficient (streams CSV parsing)
- Validation happens once at startup (no runtime overhead)
- Redaction utilities are pure functions (fast)
- Health endpoint checks are cached where appropriate
- Secret Redaction: All sensitive values masked in logs
- Error Sanitization: No secrets in error messages
- Fail-Fast: App won't start with missing critical config
- Safe Health Checks: Readiness endpoint exposes no secrets
- Input Validation: Comprehensive DTO validation for bulk links
POST /links/bulk/generate
Content-Type: application/json
{
"links": [
{
"amount": 100,
"asset": "XLM",
"username": "employee1",
"memo": "Salary March 2025"
},
{
"amount": 200,
"asset": "USDC",
"username": "employee2",
"memo": "Bonus payment"
}
]
}POST /links/bulk/generate/csv
Content-Type: multipart/form-data
File: payroll.csvCSV Format:
amount,asset,username,memo,referenceId
100,XLM,employee1,Salary March 2025,INV-001
200,USDC,employee2,Bonus payment,INV-002
150,XLM,employee3,Commission,INV-003Response:
{
"success": true,
"total": 3,
"links": [
{
"id": "link_abc123",
"canonical": "amount=100.0000000&asset=XLM&username=employee1",
"url": "https://app.quickex.to/pay?amount=100.0000000&asset=XLM&username=employee1",
"amount": "100.0000000",
"asset": "XLM",
"username": "employee1",
"referenceId": "INV-001",
"index": 0
}
],
"processingTimeMs": 245
}- ✏️
src/config/env.schema.ts- Added new env vars - ✏️
src/config/app-config.service.ts- Added accessors - ✏️
src/health/health.service.ts- Enhanced checks - ✏️
src/main.ts- Added startup validation - ✨
src/common/utils/redaction.util.ts- NEW - ✨
src/common/utils/redaction.util.unit.spec.ts- NEW
- ✨
src/links/dto/bulk-payment-link.dto.ts- NEW - ✨
src/links/bulk-payment-links.service.ts- NEW - ✨
src/links/bulk-payment-links.controller.ts- NEW - ✨
src/links/bulk-payment-links.service.unit.spec.ts- NEW - ✏️
src/links/links.module.ts- Integrated bulk links
# Config validation tests
pnpm test redaction.util.unit.spec.ts
# Bulk links tests
pnpm test bulk-payment-links.service.unit.spec.ts
# All tests
pnpm test- Remove
SUPABASE_URLfrom.env - Start server - should fail with clear error
- Check logs - no secrets should appear
- Start server
- Send POST to
/links/bulk/generatewith JSON array - Upload CSV to
/links/bulk/generate/csv - Verify response contains all generated links
- Check processing time is reasonable (< 5s for 100 links)
- Database Persistence: Store bulk link generation jobs for audit trail
- Async Processing: For very large batches (1000+ links), use job queue
- CSV Templates: Provide downloadable CSV template
- Link Expiry Notifications: Webhook when bulk links expire
- Analytics Dashboard: Track bulk link usage and redemption rates
- Rate Limiting: Add API key-based rate limits for bulk endpoint
- All code follows existing project conventions
- TypeScript strict mode enabled
- Comprehensive Swagger documentation
- No breaking changes to existing functionality
- Backward compatible with existing APIs
- All secrets properly handled and never logged