Engineering Gap
ApiKey.key column in Prisma schema (line 387) stores API keys in plaintext with comment: "legacy plaintext column. New keys should use keyHash". Guard at app/backend/src/common/guards/api-key.guard.ts line 48 accepts both keyHash and key in OR clause. Database breach permanently compromises all stored keys.
Codebase Evidence
app/backend/prisma/schema.prisma lines 385-387: keyHash, keyPreview (proper), and key (legacy plaintext)
app/backend/src/common/guards/api-key.guard.ts line 48: OR: [{ keyHash: apiKeyHash }, { key: apiKey }]
app/backend/prisma/seed.ts: likely seeds with plaintext key column
Risk Profile
Current Risk
Database breach exposes all plaintext API keys. Attacker gains full API access as those roles.
Business Impact
Complete API compromise. Unauthorized aid disbursement. Permanent key rotation required.
Remediation Strategy
Write migration: hash all non-null key values into keyHash, set keyPreview, nullify key. Drop key column. Remove plaintext OR branch from guard. Update seed script.
Success Conditions
Change Surface
Files: prisma/schema.prisma, api-key.guard.ts, prisma/seed.ts, all e2e tests
Security Review
Eliminates plaintext secret storage. Proper SHA-256 hashing. Significant security improvement.
Completion Checklist
Engineering Gap
ApiKey.keycolumn in Prisma schema (line 387) stores API keys in plaintext with comment: "legacy plaintext column. New keys should use keyHash". Guard atapp/backend/src/common/guards/api-key.guard.tsline 48 accepts bothkeyHashandkeyin OR clause. Database breach permanently compromises all stored keys.Codebase Evidence
app/backend/prisma/schema.prismalines 385-387:keyHash,keyPreview(proper), andkey(legacy plaintext)app/backend/src/common/guards/api-key.guard.tsline 48:OR: [{ keyHash: apiKeyHash }, { key: apiKey }]app/backend/prisma/seed.ts: likely seeds with plaintext key columnRisk Profile
Current Risk
Database breach exposes all plaintext API keys. Attacker gains full API access as those roles.
Business Impact
Complete API compromise. Unauthorized aid disbursement. Permanent key rotation required.
Remediation Strategy
Write migration: hash all non-null
keyvalues intokeyHash, setkeyPreview, nullifykey. Dropkeycolumn. Remove plaintext OR branch from guard. Update seed script.Success Conditions
keycolumn removedChange Surface
Files:
prisma/schema.prisma,api-key.guard.ts,prisma/seed.ts, all e2e testsSecurity Review
Eliminates plaintext secret storage. Proper SHA-256 hashing. Significant security improvement.
Completion Checklist