TypeScript 里最小化 state
typescript// lib/pii-minimize.ts — redact direct identifiers before the Jev call.
// A routing decision keys off what the ticket SAYS, not who said it:
// queue "billing" does not need a name, an email, or a card number.
const PATTERNS: [RegExp, string][] = [
[/[\w.+-]+@[\w-]+\.[\w.]+/g, '[email]'],
[/\b(?:\d[ -]*?){13,16}\b/g, '[card]'],
[/\+?\d[\d\s().-]{7,}\d/g, '[phone]'],
];
// Salted FNV-1a: the same customer id maps to the same stable token, so
// decisions stay correlatable in YOUR logs while the identifier itself
// never leaves your system.
function pseudonym(value: string): string {
const input = value + (process.env.PSEUDONYM_SALT ?? '');
let h = 2166136261;
for (let i = 0; i < input.length; i++) {
h ^= input.charCodeAt(i);
h = Math.imul(h, 16777619);
}
return 'cust_' + (h >>> 0).toString(36);
}
export function minimizeState(state: string): string {
let out = state.replace(/customer[ _#]?\d+/gi, (m) => pseudonym(m));
for (const [pattern, tag] of PATTERNS) out = out.replace(pattern, tag);
return out;
}
// Usage — one line before the existing call:
// const state = minimizeState(rawTicketBody);
// await evaluate({ model: 'jev-latest', state, questions });这些正则只是示意,不是合规控制项:它们能抓住明显的直接标识符,但会漏掉上下文型 PII——写成自然语言的地址、自由文本里的健康信息。受监管的流量请上真正的检测器(如 Microsoft Presidio),或把 state 限制为结构化白名单字段,再谈信任输出。