/** * How expensive a password hash is, and why that differs under test. * * bcrypt's cost is exponential: each step doubles the work. Twelve is the right * number for real passwords and the wrong one for a test suite that registers * around thirty-five customers and asserts nothing about any of their hashes. * `bcryptjs` is a pure-JS implementation, so it pays that cost several times * over compared with a native build, and the integration suite spent most of * its wall clock there. On a loaded runner that pushed * adminInventory.integration.test.ts past its twenty-second timeout, which read * as a foreign key violation somewhere else entirely — see #242. * * Deliberately not configurable. * ------------------------------ * An environment variable here would be a way to weaken password hashing in * production by misconfiguration, and nothing needs to tune this. The only way * to reach the cheap cost is NODE_ENV=test, which a deployed container would * also announce loudly by refusing to serve the built frontend — app.ts gates * static file serving on the same value. A setting that quietly degrades a * security property should be unreachable rather than merely warned about, * which is the same reasoning that made DEMO_MODE strict. */ /** What real passwords are hashed with, everywhere that is not a test run. */ export const PRODUCTION_ROUNDS = 12; /** * What tests hash with. 2^8 = 256 times less work than production. * * Four is bcrypt's own floor, so this is as cheap as the algorithm allows. It * is a fine number for a suite whose passwords are fixtures; it would be a * serious defect anywhere a real one is stored. */ export const TEST_ROUNDS = 4; /** * The cost for an environment, from NODE_ENV. * * Pure and exported for its test: this is the whole of the policy, and the * failure it guards against is silent. Only the exact string 'test' earns the * cheap cost — an unset NODE_ENV, or anything else, gets the strong one, so the * dangerous direction requires saying so explicitly. */ export function hashRoundsFor(nodeEnv: string | undefined): number { return nodeEnv === 'test' ? TEST_ROUNDS : PRODUCTION_ROUNDS; } /** Resolved once at import: NODE_ENV does not change while the process runs. */ export const PASSWORD_HASH_ROUNDS = hashRoundsFor(process.env.NODE_ENV);