From 275cd9aaec4a4ed9300ad2e0c118509b772288cc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 4 Aug 2026 15:49:00 +0000 Subject: [PATCH] Version Packages --- .changeset/neat-readme-shape.md | 20 --------------- .changeset/quiet-docs-decisions.md | 22 ---------------- CHANGELOG.md | 40 ++++++++++++++++++++++++++++++ package.json | 2 +- 4 files changed, 41 insertions(+), 43 deletions(-) delete mode 100644 .changeset/neat-readme-shape.md delete mode 100644 .changeset/quiet-docs-decisions.md diff --git a/.changeset/neat-readme-shape.md b/.changeset/neat-readme-shape.md deleted file mode 100644 index 1315edd..0000000 --- a/.changeset/neat-readme-shape.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -"naija-id": patch ---- - -Restructure the README for scanning. Documentation only — no code, no API change. - -The README had grown to 437 lines across 16 sections with no table of contents, and 69% of it was prose. The qualities it was optimised for — stating every limit plainly, never overclaiming — had made it unscannable: every honest caveat was a paragraph, and the paragraphs accumulated. `Format for display` started around line 250, so anyone asking "how do I format a phone number" scrolled past 107 lines of identifier-specific caveats first. - -Four changes: - -- **A capability table up front**, listing all 14 identifiers against their `is*` / `format*` / `generate*` / `detect()` name and whether redaction covers them by default. This is what most readers actually want, and it replaces a lot of scattered prose. Generated from the real exports, not from memory. -- **Reordered so the shape of the library comes first**: Install → capability table → Quick start → Format → Generate → Mask → Redact → per-identifier notes → integrations. Identifier-specific caveats no longer sit between a reader and the core API. -- **A table of contents.** All 10 anchors verified against the actual headings. -- **The deep reasoning moved into four collapsed `
` blocks** — 109 lines of it: why validators cannot be detectors, the redaction false-positive measurements, the NUBAN residue proof behind `inferBanks`, the voter-VIN evidence table, and the fixed-line letter guard. Nothing is deleted; it is one click away instead of in the scroll path. - -Kept in the README rather than moved to a separate file so no link can rot and nothing depends on a doc that might not be published. - -**437 → 226 lines**, with the rendered default view at ~198. Prose that explained *why* now links to `docs/design-decisions.md` instead of repeating it, so the README carries what you need to call the API and one line of caveat per identifier — the reasoning is one click away rather than in the scroll path. - -Per-identifier caveats became a table rather than six prose blocks. Every snippet was extracted and compiled against the project's own tsc, every claimed output was executed and checked, and all 9 internal and cross-file anchors were verified against real headings. diff --git a/.changeset/quiet-docs-decisions.md b/.changeset/quiet-docs-decisions.md deleted file mode 100644 index 0f6bad2..0000000 --- a/.changeset/quiet-docs-decisions.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -"naija-id": patch ---- - -Add `docs/design-decisions.md` — a published record of the decisions that are easy to reverse incorrectly. Documentation only. - -Until now, the reasoning behind the load-bearing choices lived only in JSDoc comments and commit messages. A contributor asking "why is redaction anchored on written shape rather than on the validators?" had no findable answer, and the honest answer is a measurement, not an opinion. - -Eight entries, each with the evidence it rests on: - -1. **Format only, never existence** — NUBAN's check digit is the sole real checksum. -2. **A validator cannot be a detector** — `parseX` normalizes before testing, so `isPhone("Total: NGN 8,031,234,567")` is `true`. Redaction anchors on shape and uses the validator only to veto. -3. **Confidence is evidence, not type** — measured false-positive rates per detector (100% for bare digit counts, 30% for `isPhone`, 0.4% for plate/passport). -4. **NUBAN is undetectable without a bank code** — the residue proof, and why the same fact makes `inferBanks` useful while making a silent detector dishonest. -5. **A replaced or tokenized identifier gets its own module** — the `python-stdnum` precedent (`de.idnr`/`de.stnr`, `in.aadhaar`/`in.vid`) behind Tax ID vs TIN and vNIN vs NIN. -6. **Cite a source, or leave it out** — with the full list of what that rule has excluded: prefix `0917`, Yoruba labels, Pidgin labels, plate LGA decoding, VIN hex enforcement, historic area codes. -7. **`detect()` ordering is load-bearing** — including the measured 0.09% trade behind placing fixed-line ahead of NIN. -8. **Subpaths keep the main entry small** — the bundle measurements, and the constraint that `redact.ts` must not import the bank dataset. - -Plus a sources list and the known follow-ons. Linked from `CONTRIBUTING.md`. - -`docs/` adds nothing to the published package — `files` is `["dist"]`, verified with `npm pack --dry-run`. diff --git a/CHANGELOG.md b/CHANGELOG.md index 80a5473..1aa83a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,45 @@ # naija-id +## 0.5.1 + +### Patch Changes + +- e7030ef: Restructure the README for scanning. Documentation only — no code, no API change. + + The README had grown to 437 lines across 16 sections with no table of contents, and 69% of it was prose. The qualities it was optimised for — stating every limit plainly, never overclaiming — had made it unscannable: every honest caveat was a paragraph, and the paragraphs accumulated. `Format for display` started around line 250, so anyone asking "how do I format a phone number" scrolled past 107 lines of identifier-specific caveats first. + + Four changes: + + - **A capability table up front**, listing all 14 identifiers against their `is*` / `format*` / `generate*` / `detect()` name and whether redaction covers them by default. This is what most readers actually want, and it replaces a lot of scattered prose. Generated from the real exports, not from memory. + - **Reordered so the shape of the library comes first**: Install → capability table → Quick start → Format → Generate → Mask → Redact → per-identifier notes → integrations. Identifier-specific caveats no longer sit between a reader and the core API. + - **A table of contents.** All 10 anchors verified against the actual headings. + - **The deep reasoning moved into four collapsed `
` blocks** — 109 lines of it: why validators cannot be detectors, the redaction false-positive measurements, the NUBAN residue proof behind `inferBanks`, the voter-VIN evidence table, and the fixed-line letter guard. Nothing is deleted; it is one click away instead of in the scroll path. + + Kept in the README rather than moved to a separate file so no link can rot and nothing depends on a doc that might not be published. + + **437 → 226 lines**, with the rendered default view at ~198. Prose that explained _why_ now links to `docs/design-decisions.md` instead of repeating it, so the README carries what you need to call the API and one line of caveat per identifier — the reasoning is one click away rather than in the scroll path. + + Per-identifier caveats became a table rather than six prose blocks. Every snippet was extracted and compiled against the project's own tsc, every claimed output was executed and checked, and all 9 internal and cross-file anchors were verified against real headings. + +- 162eeb0: Add `docs/design-decisions.md` — a published record of the decisions that are easy to reverse incorrectly. Documentation only. + + Until now, the reasoning behind the load-bearing choices lived only in JSDoc comments and commit messages. A contributor asking "why is redaction anchored on written shape rather than on the validators?" had no findable answer, and the honest answer is a measurement, not an opinion. + + Eight entries, each with the evidence it rests on: + + 1. **Format only, never existence** — NUBAN's check digit is the sole real checksum. + 2. **A validator cannot be a detector** — `parseX` normalizes before testing, so `isPhone("Total: NGN 8,031,234,567")` is `true`. Redaction anchors on shape and uses the validator only to veto. + 3. **Confidence is evidence, not type** — measured false-positive rates per detector (100% for bare digit counts, 30% for `isPhone`, 0.4% for plate/passport). + 4. **NUBAN is undetectable without a bank code** — the residue proof, and why the same fact makes `inferBanks` useful while making a silent detector dishonest. + 5. **A replaced or tokenized identifier gets its own module** — the `python-stdnum` precedent (`de.idnr`/`de.stnr`, `in.aadhaar`/`in.vid`) behind Tax ID vs TIN and vNIN vs NIN. + 6. **Cite a source, or leave it out** — with the full list of what that rule has excluded: prefix `0917`, Yoruba labels, Pidgin labels, plate LGA decoding, VIN hex enforcement, historic area codes. + 7. **`detect()` ordering is load-bearing** — including the measured 0.09% trade behind placing fixed-line ahead of NIN. + 8. **Subpaths keep the main entry small** — the bundle measurements, and the constraint that `redact.ts` must not import the bank dataset. + + Plus a sources list and the known follow-ons. Linked from `CONTRIBUTING.md`. + + `docs/` adds nothing to the published package — `files` is `["dist"]`, verified with `npm pack --dry-run`. + ## 0.5.0 ### Minor Changes diff --git a/package.json b/package.json index f32fdf7..757e795 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "naija-id", - "version": "0.5.0", + "version": "0.5.1", "description": "Zero-dependency validators, formatters and PII redaction for Nigerian identifiers — phone (E.164), NIN, vNIN, BVN, Tax ID, TIN, CAC, NUBAN, plate, passport, driver's licence and RSA PIN.", "keywords": [ "nigeria",