/**
 * Constant-time string comparison (SECURITY-CRITICAL — never use `===` for secrets).
 *
 * Mirrors src/http/auth.ts in the base app: both inputs are hashed with SHA-256 to a FIXED 32
 * bytes, then compared with `crypto.timingSafeEqual`. Hashing-to-fixed-length removes the length
 * side-channel and sidesteps `timingSafeEqual`'s throw-on-length-mismatch. A missing/empty
 * candidate short-circuits to `false` before the comparator (it is not a secret-compare oracle).
 */
import { createHash, timingSafeEqual } from 'node:crypto'

export function constantTimeEqual(a: string | undefined, b: string | undefined): boolean {
  if (typeof a !== 'string' || typeof b !== 'string') return false
  if (a.length === 0 || b.length === 0) return false
  const ha = createHash('sha256').update(a, 'utf8').digest()
  const hb = createHash('sha256').update(b, 'utf8').digest()
  return timingSafeEqual(ha, hb) // both are exactly 32 bytes → never throws
}

/** Constant-time byte comparison of two equal-length buffers (false on length mismatch). */
export function constantTimeEqualBytes(a: Buffer, b: Buffer): boolean {
  if (a.length !== b.length) return false
  return timingSafeEqual(a, b)
}
