first commit
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
# `qwerty` — QWERTY keyboard adjacency graph
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## Purpose
|
||||
|
||||
Encodes the physical adjacency of keys on a standard US QWERTY layout so
|
||||
the `keyboardMatch` matcher can recognise spatial walks like `qwerty`,
|
||||
`asdf`, and `1qaz2wsx`. The graph drives the keyboard-walk guess estimate
|
||||
in Wheeler 2016 section 4.5. The encoding mirrors the upstream zxcvbn
|
||||
reference implementation's `adjacency_graphs.coffee`.
|
||||
|
||||
## Features
|
||||
|
||||
- Complete coverage of the alphanumeric, symbol, and shifted-symbol rows
|
||||
- Adjacency slots in zxcvbn's canonical order (left, top-left, top-right,
|
||||
right, bottom-right, bottom-left)
|
||||
- Each slot encodes both the unshifted and shifted character at that key
|
||||
- Frozen at module load — safe against accidental mutation
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { QWERTY_GRAPH } from "@suaveplan/password-strength/graphs/qwerty";
|
||||
|
||||
console.log(QWERTY_GRAPH.q); // [null, "1!", "2@", "wW", "aA", null]
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import { keyboardMatch } from "@suaveplan/password-strength/matchers/keyboard";
|
||||
import { QWERTY_GRAPH } from "@suaveplan/password-strength/graphs/qwerty";
|
||||
import { DVORAK_GRAPH } from "@suaveplan/password-strength/graphs/dvorak";
|
||||
|
||||
const matches = keyboardMatch("qwerty", {
|
||||
graphs: { qwerty: QWERTY_GRAPH, dvorak: DVORAK_GRAPH },
|
||||
});
|
||||
console.log(matches);
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `QWERTY_GRAPH: KeyboardGraph` — frozen `Record<string, ReadonlyArray<string | null>>`
|
||||
mapping each key to its six adjacency slots.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The matcher checks both characters of each slot when classifying a key
|
||||
press: matching against the second character flags the press as
|
||||
shift-required (`shiftedCount += 1`). Slots that point off the edge of the
|
||||
keyboard are `null`. The graph deliberately preserves the upstream slot
|
||||
order so callers porting from `zxcvbn` consume the same data layout.
|
||||
|
||||
## Additional Implementation Notes
|
||||
|
||||
The implementation follows the canonical zxcvbn algorithm from Wheeler 2016 with
|
||||
the suaveplan-style additions described in the package proposal: structured error
|
||||
codes via the `defineCodes` registry, Zod boundaries at every public entry
|
||||
point, OTel histograms and counters keyed to low-cardinality attributes, and
|
||||
a strict input-length guard at 200 characters. Consumers integrate with their
|
||||
existing observability stack by installing a meter provider before importing
|
||||
the package, and with their i18n stack via the `MessageResolver` callback type
|
||||
declared in `@suaveplan/types`. The bundled data tables are intentionally
|
||||
small to keep the package bundle compact; production deployments should swap
|
||||
in fuller frequency-ranked tables via `loadDictionaries`. The default English
|
||||
dictionary set is a frozen `DictionarySet` that the matcher never mutates;
|
||||
caller-supplied dictionaries override defaults by name.
|
||||
Reference in New Issue
Block a user