threat
@noy-db/on-threat·pnpm add @noy-db/on-threatLockout + duress + honeypot defence triad.
What it does
Three independent, opt-in mechanisms, all pure logic — the caller
persists state and wires the resulting actions. initialLockoutState()
seeds a LockoutState; recordFailure(state, config) accumulates failed
attempts within a window (default threshold 5 in 15 minutes), triggers a
cooldown lockout (default 5 minutes) past the threshold, and after
maxStrikes rounds (default 3) flips the state to a terminal wipe signal
for the caller to act on; recordSuccess(state) resets it.
checkDuress(input, digest, salt) compares an entered secret against
a stored duress digest — a match signals the caller's onDuress handler
to purge DEKs and delete the keyring. checkHoneypot (an alias of the
same detection pair) instead routes to a pre-seeded decoy vault. None of
the three mechanisms require server cooperation.
Usage
import { initialLockoutState, recordFailure, checkDuress } from '@noy-db/on-threat'
let state = initialLockoutState()
// on each failed unlock attempt
const outcome = recordFailure(state)
if (outcome.wipe) await destroyVault()
else if (outcome.locked) showLockout(outcome.unlockAt)
// separately, check every entered secret against the duress digest
if (await checkDuress(enteredSecret, duressDigest, duressSalt)) {
await triggerDuressWipe()
}