Initial Commit
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
# `sequence` — alphanumeric sequence matcher
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## Purpose
|
||||
|
||||
Detects ascending and descending runs of consecutive characters within a single
|
||||
alphabet class (lowercase letters, uppercase letters, decimal digits) per
|
||||
Wheeler §3.2. A run of `abcd` carries far less entropy than four random
|
||||
letters and the scorer needs an explicit pattern record to compute the right
|
||||
guesses count.
|
||||
|
||||
## Features
|
||||
|
||||
- Lower, upper, and digit alphabets
|
||||
- Both directions (ascending `1234`, descending `9876`)
|
||||
- Minimum length 2
|
||||
- Each match carries `sequenceSpace` (size of the alphabet) and `ascending`
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { sequenceMatch } from "@suaveplan/password-strength/matchers/sequence";
|
||||
|
||||
const matches = sequenceMatch("abcd");
|
||||
console.log(matches[0].ascending); // true
|
||||
console.log(matches[0].sequenceName); // "lower"
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import { sequenceMatch } from "@suaveplan/password-strength/matchers/sequence";
|
||||
|
||||
// Mixed runs are reported separately
|
||||
for (const m of sequenceMatch("abc987XYZ")) {
|
||||
console.log(m.token, m.sequenceName, m.ascending);
|
||||
}
|
||||
// abc lower true
|
||||
// 987 digits false
|
||||
// XYZ upper true
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `sequenceMatch(password: string): SequenceMatch[]` — return every maximal
|
||||
ascending or descending run of length ≥ 2 within a single alphabet class.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The walk is single-pass: at each index, the matcher checks the delta between
|
||||
adjacent characters; if it is `+1` or `-1` within the same alphabet, the
|
||||
matcher extends the run greedily until the delta breaks or the alphabet
|
||||
changes. Runs of length 1 are filtered out. The algorithm is `O(n)` over the
|
||||
password length and emits each maximal run exactly once.
|
||||
|
||||
## 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