Minimize the state in TypeScript
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 });These are illustrative regexes, not a compliance control: they catch the obvious direct identifiers and will miss contextual PII — addresses written as prose, free-text health details. For regulated traffic, run a real detector (for example Microsoft Presidio) or restrict the state to structured, allow-listed fields before trusting the output.