/** * FNV-1a 52-bit hash — fast, non-cryptographic. * * WARNING: Do NOT use for cache keys derived from attacker-controlled input. * Use sha256Hex() instead for any server-side cache key with user input. * Retained for client-side non-security contexts (e.g. vector-db dedup). */ export function hashString(input: string): string { let h = 0xcbf29ce484222325n; const FNV_PRIME = 0x100000001b3n; const MASK_52 = (1n << 52n) - 1n; for (let i = 0; i < input.length; i++) { h ^= BigInt(input.charCodeAt(i)); h = (h * FNV_PRIME) & MASK_52; } return Number(h).toString(36); } /** * SHA-256 hex digest via Web Crypto (available in Edge/Vercel/Node 18+). * Use for all server-side cache keys derived from user-controlled input. */ export async function sha256Hex(input: string): Promise { const buf = await crypto.subtle.digest( 'SHA-256', new TextEncoder().encode(input), ); return Array.from(new Uint8Array(buf)) .map(b => b.toString(16).padStart(2, '0')) .join(''); }