2.8 KiB
range/range.ts
(no submodules)
Purpose
RangeClient is the heart of the package — the k-anonymity Pwned
Passwords client. checkPassword(password, opts?) hashes the input,
slices the 5-hex prefix, dispatches GET https://api.pwnedpasswords.com/range/<prefix>
with the mandatory Add-Padding: true header, scans the streamed
response for a matching 35-char suffix, and returns
{ pwned, count }. It owns the strict / off framing, the NTLM mode
opt-in, the differential-privacy decoy fan-out, the AbortSignal
threading, and the OTel emission.
Features
- Mandatory
Add-Padding: trueon every fetch — including every differential-privacy decoy. - SHA-1 (default) and NTLM (caller-injected adapter) hash modes.
- Constant-time suffix compare on every parsed line.
- Streaming line parser (no
Response.text()call ever). - Differential-privacy decoy fan-out when
extraPrefixes > 0— real prefix's response is the only one consulted. - AbortSignal threaded into fetch and the streaming parser.
- OTel histograms for duration; counters for outcome, errors, throttling.
- Optional
assertOutgoingRequestSafe: trueruntime privacy gate.
Usage: Basic Example
import { RangeClient } from "@suaveplan/hibp";
const client = new RangeClient();
const { pwned, count } = await client.checkPassword("hunter2");
Usage: Advanced Example
import { RangeClient } from "@suaveplan/hibp";
const client = new RangeClient({
extraPrefixes: 3,
rng: myRng,
assertOutgoingRequestSafe: true,
strict: true,
});
const ac = new AbortController();
setTimeout(() => ac.abort(), 5_000);
const result = await client.checkPassword("hunter2", { signal: ac.signal });
API Reference
CheckPasswordOptions—mode?,signal?,extraPrefixes?.RangeClientOptions—fetchFn,clock,rng,strict,ntlmHash,extraPrefixes,assertOutgoingRequestSafe.new RangeClient(options?).client.checkPassword(password, opts?): Promise<PwnedResult>.
Implementation Notes
The class is stateless beyond its constructor options — every public
method takes the password and a per-call options bag, so a single
RangeClient instance is safe to share across a process. Error paths
funnel through the metrics emission so dashboards see counters even
for failures the caller catches and retries. The assertOutgoingRequestSafe
gate constructs a Request to feed into assertNoLeak, then re-issues
the actual fetch with the same RequestInit so the privacy check
exercises the real outgoing bytes. The NTLM adapter is required at
runtime if mode: "ntlm" is ever passed; a missing adapter surfaces as
HIBP.MALFORMED_RESPONSE because the caller has misconfigured the
client rather than the server having misbehaved.