You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
sims-hq/packages/auth/src/lockout.ts

39 lines
1.0 KiB
TypeScript

/**
* Brute-force lockout as a pure reducer so POS and back office share the exact
* policy and it is testable without a clock. Attempts are audit-logged by the
* caller (I7: every mutation audit-logged in the same transaction).
*/
export interface LockoutPolicy {
maxFailures: number
lockMs: number
}
export const DEFAULT_LOCKOUT: LockoutPolicy = { maxFailures: 5, lockMs: 60_000 }
export interface LockoutState {
failures: number
lockedUntilMs?: number
}
export const FRESH_LOCKOUT: LockoutState = { failures: 0 }
export function isLocked(state: LockoutState, nowMs: number): boolean {
return state.lockedUntilMs !== undefined && nowMs < state.lockedUntilMs
}
export function recordFailure(
state: LockoutState,
nowMs: number,
policy: LockoutPolicy = DEFAULT_LOCKOUT,
): LockoutState {
const failures = state.failures + 1
if (failures >= policy.maxFailures) {
return { failures, lockedUntilMs: nowMs + policy.lockMs }
}
return { failures }
}
export function recordSuccess(): LockoutState {
return FRESH_LOCKOUT
}