audit: Tier 0 quick wins — EMAIL_REDIRECT_TO prod guard + storage routing + metadata masking
Tier 0.2: src/lib/env.ts now refuses boot when NODE_ENV=production AND EMAIL_REDIRECT_TO is set. Sendmail logs the rewrite at warn (was debug) so dev/staging windows where someone forgets to unset are immediately visible. Tier 0.6: backup_jobs.storage_path added to TABLES_WITH_STORAGE_KEYS in src/lib/storage/migrate.ts. Flipping the storage backend used to silently orphan every pg_dump artefact — last-resort recovery path is now actually portable. Tier 1.7: createAuditLog now runs metadata through maskSensitiveFields (was only applied to old/new value diffs). Portal-auth, crm-invite, hard-delete and email-accounts services were writing raw emails into this column unbounded. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -151,10 +151,21 @@ export async function sendEmail(
|
||||
...(resolvedAttachments.length > 0 ? { attachments: resolvedAttachments } : {}),
|
||||
});
|
||||
|
||||
logger.debug(
|
||||
{ messageId: info.messageId, to: effectiveTo, originalTo: requestedTo, subject, portId },
|
||||
env.EMAIL_REDIRECT_TO ? 'Email sent (redirected)' : 'Email sent',
|
||||
);
|
||||
// When EMAIL_REDIRECT_TO is set we elevate to `warn` so the dev-only
|
||||
// safety net is visible in any logger config. Prod boot already refuses
|
||||
// when both are set (see env.ts superRefine) — this catches the dev /
|
||||
// staging window where someone left it in a .env by mistake.
|
||||
if (env.EMAIL_REDIRECT_TO) {
|
||||
logger.warn(
|
||||
{ messageId: info.messageId, to: effectiveTo, originalTo: requestedTo, subject, portId },
|
||||
'Email sent (REDIRECTED via EMAIL_REDIRECT_TO — recipient overridden)',
|
||||
);
|
||||
} else {
|
||||
logger.debug(
|
||||
{ messageId: info.messageId, to: effectiveTo, originalTo: requestedTo, subject, portId },
|
||||
'Email sent',
|
||||
);
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user