# `schemas/breach.schema.ts` ## Purpose `BreachSchema` is the Zod schema mirroring the [HIBP v3 `Breach` payload](https://haveibeenpwned.com/API/v3#Breach). 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 ```ts import { BreachSchema } from "@suaveplan/hibp"; const parsed = BreachSchema.parse(await response.json()); console.log(parsed.Name); ``` ## Usage: Advanced Example ```ts 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` 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.