Files
skills/docs/security-stack/security/hibp/src/errors/hibp-error.md
2026-05-29 08:20:56 +01:00

2.4 KiB

errors/hibp-error.ts

Purpose

HibpError is the structured error class every failure path inside @suaveplan/hibp throws. It carries one of the seven registered HibpErrorCode values plus optional cause / context / trace-id metadata, and ships a toJSON() form that strips sensitive payloads (API keys, emails, passwords, full SHA-1 hashes) before any logger touches it.

Features

  • code field narrows on the seven-member registry, so callers can fan out on stable enumerated values rather than parse messages.
  • Inherits trace-id propagation and timestamp from SuaveplanError, keeping every error in the project wire-compatible.
  • leakClass field annotates errors thrown by assert-no-leak.ts with whether the offending value was a SHA-1, a password, or an email — without ever echoing the leaked bytes.
  • toJSON() scrubs any 40-char hex sequence and any address-shaped substring as a defence-in-depth filter, so even an unexpected interpolation cannot leak a hash or email.

Usage: Basic Example

import { HIBP_CODES, HibpError } from "@suaveplan/hibp";

try {
    /* ... */
} catch (err) {
    if (err instanceof HibpError && err.code === HIBP_CODES.RATE_LIMITED) {
        // back off
    }
}

Usage: Advanced Example

import { HibpError } from "@suaveplan/hibp";

function logSafely(err: unknown, logger: { error(s: string): void }): void {
    if (err instanceof HibpError) {
        logger.error(JSON.stringify(err.toJSON()));
    } else if (err instanceof Error) {
        logger.error(err.message);
    }
}

API Reference

  • new HibpError(code, message, options?) — options accepts cause, context, traceId, clock, and leakClass.
  • error.code: HibpErrorCode — the namespaced code string.
  • error.leakClass: "sha1" | "password" | "email" | undefined.
  • error.toJSON() — returns a stable, redacted serialization safe to hand to any logger.

Implementation Notes

The toJSON redaction is intentionally regex-based — strings that happen to resemble a SHA-1 or an email get replaced with [redacted] even if they were never deliberate. False positives here cost almost nothing; false negatives would cost the privacy contract. The constructor uses a helper to build the super-options object so that exactOptionalPropertyTypes: true doesn't reject undefined values that the parent class doesn't accept.