feat: strengthen validator correctness and repo hygiene#77
Conversation
|
| Filename | Overview |
|---|---|
| src/types.ts | Adds ParsedBirthDate, ParsedIdentifier, ParsableValidator, and makes Validator generic over TParsed; the conditional parse property typing is correct. |
| src/cz/rc.ts | Replaces fragile (mm % 50) % 20 |
| src/sk/rc.ts | Now re-exports generate from cz/rc and adds parse, generate, and lengths to the public validator object; delegation pattern is clean. |
| src/nl/vat.ts | Removes BSN and MOD97 checksum checks in favour of purely structural validation; intentional per cited official guidance. |
| src/lv/vat.ts | Splits validation into three explicit branches (new personal 3x, entity 4/5/9, legacy personal), adds century-digit bounds check (0-2 only), and now generates both new-format personal and entity codes. |
| src/si/emso.ts | Adds future-date guard with correct local-midnight normalization and register-code restriction (50-59); both changes are source-backed. |
| src/ee/ik.ts | Restricts first digit to 1-6 (drops speculative 7/8 century values) per OECD Estonia TIN sheet. |
| src/it/codicefiscale.ts | Adds generate() and exposes parse on the public validator object; prior Math.random() coin-flip replaced with randomInt(0, 1) === 0. |
| src/eu/vat.ts | Adds generate() that delegates to each member validator's own generator; defensive guards are unreachable in practice but harmless. |
| test/parse.test.ts | Auto-discovery now uses public validator objects from src/index instead of filesystem glob; specific date/gender assertions for all changed validators are preserved. |
| scripts/oracle.ts | Removes stale oracle pairings and adds semantically correct shaped generators for cz.rc, ee.ik, bg.egn, si.emso, lv.vat, cy.vat with inline rationale comments. |
| .github/workflows/ci.yml | Adds build job running typecheck, build, and sync-exports:check; gated on trust-check and required before publish. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["lv.vat validate(v)"] --> B{"v[0]==='3' &&\nv[1] in '2'-'9'?"}
B -- yes --> C["✅ New personal code\n(syntactic only, no checksum)"]
B -- no --> D{"v[0] in\n'4','5','9'?"}
D -- yes --> E["weightedSum check\n(mod 11 = 3)"]
E -- pass --> F["✅ Entity code"]
E -- fail --> G["❌ INVALID_CHECKSUM"]
D -- no --> H["Legacy personal code\nDDMMYY + century 0-2"]
H --> I{"validateBirthDate?\ncentury ∈ 0-2?"}
I -- fail --> J["❌ INVALID_COMPONENT"]
I -- pass --> K{"checkPersonal\n(weighted sum)"}
K -- pass --> L["✅ Legacy personal"]
K -- fail --> M["❌ INVALID_CHECKSUM"]
N["cz.rc decodeMonth(mm, year, len)"] --> O{"len=10 &&\nyear≥2004?"}
O -- yes --> P["candidates: 0, 50, 20, 70"]
O -- no --> Q["candidates: 0, 50"]
P --> R["first offset where\nmm-offset ∈ 1-12"]
Q --> R
R -- none match --> S["❌ INVALID_COMPONENT"]
R -- found --> T["✅ decoded month"]
Reviews (2): Last reviewed commit: "Address bot review feedback" | Re-trigger Greptile
There was a problem hiding this comment.
🚩 Multiple oracle libraries removed as cross-validators with detailed inline rationale
The PR removes several oracle pairings: cy.vat from jsvat/valvat, lv.vat from jsvat/valvat, nl.vat from python-stdnum/jsvat/valvat, bg.egn from stdnum-js/ruby-ssn, es.vat from jsvat/valvat, cz.dic from python-stdnum/jsvat, and sk.rc from ruby-ssn. Each removal has an inline comment explaining the disagreement (e.g., Cyprus TFA ranges, Latvia post-2017 format, GRAO EGN rules). This reduces oracle coverage but the rationale cites authoritative government sources over third-party libraries. Worth auditing the specific official sources to confirm the claimed discrepancies.
Was this helpful? React with 👍 or 👎 to provide feedback.
Summary
This PR strengthens
stdnumacross four areas:parse()to a typed first-class capability in the public validator APIexamplesandgenerate()seeds and filling generator gapsWhat changed
Validator<TParsed>,ParsedBirthDate,ParsedIdentifier, andParsableValidator.parse()on the public validator object.typecheckandsync-exports:checkscripts and wired them into CI andprepublishOnly.tsdownfrom deprecatedbundle: falsetounbundle: true.examplesandgenerate()over random lucky discovery.NL#########B##format.ee.iksi.emsolv.vatcz.rc/sk.rcVerification
Passed locally:
bun run typecheckbun run lintbun testbun run sync-exports:checkcz,ee,lv,si,skFollow-up
no-non-null-assertionis still disabled. I left that as a separate cleanup because the repo still has broad postfix!usage and it deserves a focused pass rather than being mixed into this PR.