feat(security): field encryption AES-256-GCM + random IV (at-rest)

- common/crypto/crypto.util.ts: encrypt/decrypt (GCM, random 96-bit IV), format v1:base64(iv|tag|ct)
- EncryptedTransformer applied to users.name + drivers.vehicle_plate (auto, no service change)
- blindIndex (HMAC) helper for future searchable-field encryption (phone)
- tolerant decrypt for legacy plaintext → no migration needed (varchar holds base64)
- ENCRYPTION_KEY env + boot warning if unset; docs/16-encryption.md
- fixes Siro's documented CBC+fixed-IV flaw

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-16 19:24:27 +03:00
co-authored by Claude Opus 4.8
parent bb6a7bc7ec
commit f3383c3cf8
6 changed files with 114 additions and 2 deletions
+7
View File
@@ -29,6 +29,13 @@ async function bootstrap() {
.build();
SwaggerModule.setup('api/docs', app, SwaggerModule.createDocument(app, swagger));
if (!process.env.ENCRYPTION_KEY) {
Logger.warn(
'ENCRYPTION_KEY غير مضبوط — يُستخدم مفتاح تطوير غير آمن. اضبطه للإنتاج (openssl rand -hex 32).',
'Security',
);
}
const port = cfg.get<number>('apiPort') ?? 4010;
await app.listen(port, '0.0.0.0');
Logger.log(`Tripz API on :${port} (docs at /api/docs)`, 'Bootstrap');