Files
skills/docs/security-stack/security/password-generator/src/charsets/charsets.md
2026-05-29 08:20:56 +01:00

3.5 KiB
Raw Blame History

charsets

(no submodules)

Purpose

Defines the canonical character-class constants used by every generator in the package — LOWERCASE, UPPERCASE, DIGITS, SYMBOLS, plus the curated AMBIGUOUS and LOOKALIKES sets that callers subtract to avoid characters confusable in fixed-width fonts. Exposing each class as a frozen ReadonlySet<string> lets callers compose custom unions (new Set([...LOWERCASE, ...DIGITS])) without depending on any private representation.

The buildEffectiveCharset(opts) helper merges the enabled classes and subtracts opts.exclude to produce the deduplicated string array a generator can index into via randomInt. The four built-in classes are pairwise disjoint by construction, so insertion-order union is enough to deduplicate — adding a Set-tracked check would be dead code.

Features

  • Frozen ReadonlySet<string> for each class — safe to share across modules.
  • AMBIGUOUS (0Ol1I) and LOOKALIKES curated by frequency of human misreads.
  • SYMBOLS drawn from the OWASP-recommended printable range; excludes shell-quoting hazards (backtick, backslash, whitespace).
  • buildEffectiveCharset(opts) accepts string / array / Set exclusions.

Usage: Basic Example

import {
 AMBIGUOUS,
 buildEffectiveCharset,
} from "@suaveplan/password-generator";

const charset = buildEffectiveCharset({ exclude: AMBIGUOUS });

Usage: Advanced Example

import {
 DIGITS,
 LOWERCASE,
 UPPERCASE,
 buildEffectiveCharset,
} from "@suaveplan/password-generator";

// Hex charset only (digits + a-f) via two passes
const hexLower = [
 ...buildEffectiveCharset({ uppercase: false, symbols: false }),
].filter((c) => DIGITS.has(c) || "abcdef".includes(c));

// "Vault-friendly" passwords: drop ambiguous + shell-hostile chars
const safe = buildEffectiveCharset({ exclude: "0Ol1I`\\\"' " });
const charset = safe.filter((c) => !UPPERCASE.has(c) || LOWERCASE.has(c.toLowerCase()));

API Reference

Constants

  • LOWERCASE: ReadonlySet<string> — a–z (26 entries).
  • UPPERCASE: ReadonlySet<string> — A–Z (26 entries).
  • DIGITS: ReadonlySet<string> — 0–9 (10 entries).
  • SYMBOLS: ReadonlySet<string> — !@#$%^&*()-_=+[]{};:,.<>/? (25 entries).
  • AMBIGUOUS: ReadonlySet<string> — 0Ol1I.
  • LOOKALIKES: ReadonlySet<string> — 0OQ1lI5S2Z8B.

buildEffectiveCharset(opts?: CharsetOptions): string[]

Builds the deduplicated union of enabled classes minus opts.exclude. Returns a fresh array on every call; insertion order is lowercase → uppercase → digits → symbols.

  • lowercase / uppercase / digits / symbols — each defaults to true.
  • exclude — string (per-character), readonly string[], or ReadonlySet<string>; defaults to none.

Implementation Notes

Every set is frozen at module load via Object.freeze, which only freezes the Set object itself (not the underlying internal storage). The intent is to surface accidental .add / .delete calls at call sites; consumers who need to add or remove characters must clone the set first.

SYMBOLS intentionally omits whitespace, the backslash, double-quote, and backtick. Those characters routinely break shell interpolations and CSV exports; including them would force every caller to filter them out before interpolating the generated password into a deployment script. Callers who want them can compose new Set([...SYMBOLS, "\\\""]) themselves — the omission is conservative-by-default but trivially reversible.