-
Notifications
You must be signed in to change notification settings - Fork 0
fix(at/vnr,us/rtn): align with primary sources from official documentation #110
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,8 +6,19 @@ | |
| * The check digit is computed using a weighted sum | ||
| * mod 11 over the 9 non-check digits. | ||
| * | ||
| * The 6-digit "birth date" field is not always a real | ||
| * calendar date. Sozialversicherung.at documents that | ||
| * persons with unknown date of birth are issued | ||
| * substitute values (01.01. or 01.07.), and that | ||
| * months 13, 14, etc. are issued when the daily serial | ||
| * pool for a given substitute date is exhausted. We | ||
| * therefore do not enforce a calendar-valid month here. | ||
| * The day field, however, is always within 01-31 — even | ||
| * in the documented overflow cases the day stays "01" | ||
| * — so we keep the day-bounds check. | ||
| * | ||
| * @see https://de.wikipedia.org/wiki/Sozialversicherungsnummer#%C3%96sterreich | ||
| * @see https://www.sozialversicherung.at/ | ||
| * @see https://www.sozialversicherung.at/cdscontent/?contentid=10007.820902&viewmode=content | ||
| */ | ||
|
|
||
| import type { ValidateResult, Validator } from "../types"; | ||
|
|
@@ -44,13 +55,24 @@ const validate = (value: string): ValidateResult => { | |
| ); | ||
| } | ||
|
|
||
| // Validate birth date (DDMMYY in positions 4-9) | ||
| // Per sozialversicherung.at, the 3-digit serial | ||
| // (positions 0-2) never starts with zero. | ||
| if (v[0] === "0") { | ||
|
Comment on lines
+58
to
+60
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
By removing all calendar-date checks here, checksum-valid numbers with an impossible day now pass; for example, Useful? React with 👍 / 👎.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Restored in f18e2eb. You're right — the source only documents month overflow (substitute dates and 13/14/etc. for serial exhaustion), and even in those cases the day stays "01". The 1-31 day-bounds check is back, so 1002000180 is rejected on day=00 again. CC on behalf of @jan-kubica There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
With this new guard, Useful? React with 👍 / 👎.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed in f18e2eb — generate() now builds the serial as String(randomInt(1, 9)) + randomDigits(2), so the first digit is deterministically non-zero and the CI generator roundtrip test (which was failing intermittently) is green again. CC on behalf of @jan-kubica There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The new validation rule restricts the first digit of the serial from being Please update the CC on behalf of @jan-kubica
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same fix in f18e2eb — went with String(randomInt(1, 9)) + randomDigits(2) instead of randomInt(100, 999) so the trailing two digits stay uniformly random. CC on behalf of @jan-kubica |
||
| return err( | ||
| "INVALID_COMPONENT", | ||
| "Austrian VNR serial must not start with zero", | ||
| ); | ||
| } | ||
|
|
||
| // Day (positions 4-5) is always within 01-31, even | ||
| // in the documented substitute and overflow cases | ||
| // where the month is shifted. The month is left | ||
| // unchecked per the source. | ||
| const day = Number(v.slice(4, 6)); | ||
| const month = Number(v.slice(6, 8)); | ||
| if (day < 1 || day > 31 || month < 1 || month > 12) { | ||
| if (day < 1 || day > 31) { | ||
| return err( | ||
| "INVALID_COMPONENT", | ||
| "Austrian VNR contains an invalid birth date", | ||
| "Austrian VNR day field must be within 01-31", | ||
| ); | ||
| } | ||
|
|
||
|
|
@@ -88,7 +110,9 @@ const format = (value: string): string => { | |
| /** Generate a random valid Austrian VNR. */ | ||
| const generate = (): string => { | ||
| for (;;) { | ||
| const serial = randomDigits(3); | ||
| // Serial must not start with zero (see validate). | ||
| const serial = | ||
| String(randomInt(1, 9)) + randomDigits(2); | ||
| const day = String(randomInt(1, 28)).padStart(2, "0"); | ||
| const month = String(randomInt(1, 12)).padStart(2, "0"); | ||
| const year = String(randomInt(0, 99)).padStart(2, "0"); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To ensure the new validation logic for month-13 and day-0 VNRs works correctly and doesn't regress, we should add positive test cases for valid month-13 and day-0 VNRs alongside the negative ones.
CC on behalf of @jan-kubica
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added the matching-month-13 positive test (1234011380) in f18e2eb. Did not add the matching-day-0 test — the source explicitly says day stays "01" even in substitute and overflow cases, so I restored the 1-31 day-bounds check and added a 'day-0 is invalid' negative test instead (see the parallel thread from Codex). Also added a leading-zero serial test for symmetry.
CC on behalf of @jan-kubica