# `l33t-table` — default substitution table ## Purpose Provides the default character → letter substitution table used by the `dictionaryMatch` matcher to recognise l33t-encoded variants of dictionary tokens (e.g. `p4ssw0rd` for `password`). The table follows Wheeler §3.1 and mirrors the `dropbox/zxcvbn` reference impl's `data/l33t_table.coffee`. The companion `inverseL33tTable` utility flips the table for the matcher's enumeration pass — given a substitute character, it returns the set of letters that character could represent. ## Features - Frozen default table covering twelve high-frequency substitutions - Inverse lookup helper for matcher enumeration - Pure data; safe to import in any tier (no runtime deps) - Caller-pluggable: `assess` accepts an alternative table via options ## Usage: Basic Example ```ts import { DEFAULT_L33T_TABLE, inverseL33tTable } from "@suaveplan/password-strength/matchers/dictionary"; const inverse = inverseL33tTable(DEFAULT_L33T_TABLE); console.log(inverse["4"]); // ["a"] console.log(inverse["1"]); // ["i", "l"] ``` ## Usage: Advanced Example ```ts import { DEFAULT_L33T_TABLE, inverseL33tTable, dictionaryMatch } from "@suaveplan/password-strength/matchers/dictionary"; const customTable = { ...DEFAULT_L33T_TABLE, a: ["4", "@", "/-\\"], }; const matches = dictionaryMatch("p4ssword", { passwords: new Map([["password", 1]]) }, customTable); console.log(matches); ``` ## API Reference - `DEFAULT_L33T_TABLE: L33tTable` — frozen default substitution map. - `inverseL33tTable(table: L33tTable): Record` — return the inverse map of substitute character → array of letters it can stand in for. ## Implementation Notes The table is intentionally conservative: every substitute character maps to real letters that appear in the breach-corpus literature. Adding more substitutions inflates the enumeration cost quadratically per password length, so callers who extend the table should benchmark against `assess_dictionary_heavy`. The frozen `Object.freeze` wrapper prevents inadvertent mutation by consumers. ## 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.