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

2.3 KiB

schemas/breach.schema.ts

Purpose

BreachSchema is the Zod schema mirroring the HIBP v3 Breach payload. It validates every documented field, so the rest of the package can assume a fully populated Breach value anywhere a parsed breach record flows. Defending the boundary at this layer means a server-side schema regression fails fast with a typed HIBP.MALFORMED_RESPONSE error rather than silently producing partial objects.

Features

  • Strict-required fields: missing keys throw at parse time.
  • Per-field type narrowing: PwnCount is a non-negative integer, DataClasses is string[], every Is* field is boolean.
  • Covers IsStealerLog, the v3 addition that earlier docs sometimes miss.
  • Type alias Breach is exported alongside the schema so consumer code stays single-source-of-truth.

Usage: Basic Example

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

const parsed = BreachSchema.parse(await response.json());
console.log(parsed.Name);

Usage: Advanced Example

import { BreachSchema, type Breach } from "@suaveplan/hibp";

export function partitionBreaches(items: unknown[]): {
    verified: Breach[];
    fabricated: Breach[];
} {
    const verified: Breach[] = [];
    const fabricated: Breach[] = [];
    for (const item of items) {
        const b = BreachSchema.parse(item);
        if (b.IsFabricated) fabricated.push(b);
        else verified.push(b);
    }
    return { verified, fabricated };
}

API Reference

  • BreachSchema: ZodObject — strict v3 breach shape.
  • Breach — z.infer<typeof BreachSchema> type alias.

Implementation Notes

The schema does not call .passthrough() deliberately — opting out of silent forward-compat keeps server-side schema regressions visible. If HIBP adds a new field, the integration test in breach-client.test.ts will fail loudly and we can decide whether to add it, mark it optional, or reject the response. The IsStealerLog field landed in HIBP v3 after the original spec; we include it as required because every breach record observed in production carries it, and treating it as optional would let silent regressions slip through. Consumers concerned about long-tail server inconsistencies can run the schema through .partial() themselves before parsing.