// Thin bcrypt wrapper. Cost 12 per the spec (NIST SP 800-63B-friendly). // comparePassword must never throw on a malformed hash — that path is hit // by the seeded dev user's placeholder hash and by any partially-imported // row. Throwing here would 500 on a wrong-password attempt. import bcrypt from 'bcrypt'; const COST = 12; export async function hashPassword(plain) { return bcrypt.hash(plain, COST); } export async function comparePassword(plain, hash) { try { return await bcrypt.compare(plain, hash); } catch { return false; } }