48 lines
2.1 KiB
TypeScript
48 lines
2.1 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { readFileSync } from "node:fs";
|
|
import { resolve } from "node:path";
|
|
|
|
/**
|
|
* PII-protection regression test for EmailService.
|
|
*
|
|
* The legacy `console.log` printed `{ providerSettings, alias, hasTemplateData }`
|
|
* which is borderline; we tightened it further (no full alias, only boolean).
|
|
* This test asserts we never regress to logging `to`, `subject`, `body`, or `data`.
|
|
*/
|
|
describe("EmailService PII discipline", () => {
|
|
const SOURCE = readFileSync(resolve(__dirname, "EmailService.ts"), "utf8");
|
|
|
|
it("contains no live console.* call sites", () => {
|
|
const live = SOURCE.split("\n").filter((line, idx, all) => {
|
|
if (!/console\.(log|error|warn|info|debug)\s*\(/.test(line)) return false;
|
|
const trimmed = line.trimStart();
|
|
if (trimmed.startsWith("//") || trimmed.startsWith("*")) return false;
|
|
const prev = idx > 0 ? all[idx - 1].trim() : "";
|
|
if (/eslint-disable-next-line[^\n]*no-console/.test(prev)) return false;
|
|
return true;
|
|
});
|
|
expect(live).toEqual([]);
|
|
});
|
|
|
|
it("never passes recipient address / subject / body / template-data as own logger fields", () => {
|
|
// Pattern: emailLogger.<level>({ <key>: ... }) — flag if `<key>` is one of the PII fields.
|
|
// Note: We check key positions (property keys), not value expressions like `Boolean(data)`.
|
|
const pattern = /emailLogger\.(info|warn|error|debug)\s*\(\s*\{([\s\S]*?)\}/g;
|
|
const forbiddenKeys = ["to", "subject", "body", "templateData", "recipient", "html", "text"];
|
|
let match: RegExpExecArray | null;
|
|
const offenders: string[] = [];
|
|
while ((match = pattern.exec(SOURCE)) !== null) {
|
|
const objContent = match[2];
|
|
for (const key of forbiddenKeys) {
|
|
const keyRe = new RegExp(`(^|[\\s,{])${key}\\s*:`, "m");
|
|
if (keyRe.test(objContent)) offenders.push(`key "${key}" in ${match[0].slice(0, 80)}...`);
|
|
}
|
|
}
|
|
expect(offenders, `emailLogger must not log PII fields: ${offenders.join("; ")}`).toEqual([]);
|
|
});
|
|
|
|
it("uses createScopedLogger('email')", () => {
|
|
expect(SOURCE).toMatch(/createScopedLogger\(\s*["']email["']\s*\)/);
|
|
});
|
|
});
|