Fix validation of fiscal codes with non-contiguous omocodia substitutions - #10
Open
MFranceschi6 wants to merge 1 commit into
Open
Fix validation of fiscal codes with non-contiguous omocodia substitutions#10MFranceschi6 wants to merge 1 commit into
MFranceschi6 wants to merge 1 commit into
Conversation
Decoding enforced right-to-left contiguous substitutions, but codes exist where any subset of the seven numeric positions is substituted. Such codes failed validation despite a valid checksum, matching what the Agenzia delle Entrate considers valid. - drop the contiguity requirement in originalFiscalCode - restore digits by position instead of lastIndex(of:), which corrupted codes when the substitution letter also appeared in the place-of-birth code or checksum - validate the checksum in isValid against the passed value: it was compared against the recomputed checksum of the decoded code, rejecting every omocodia variant
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Spritz.isValidrejects real fiscal codes issued by the Agenzia delle Entrate when the omocodia substitutions are not contiguous starting from the rightmost digit (e.g. position 13 substituted while position 14 still holds a digit). We hit this in production with a code the Agenzia delle Entrate verification service confirms as valid.While reproducing it, two more issues surfaced in the omocodia handling:
originalFiscalCode(from:)enforced right-to-left contiguous substitutions. The progressive pattern is how new omocode variants are generated, but it is not a validity constraint: codes with any subset of the seven numeric positions substituted exist and are accepted by the Agenzia delle Entrate (each numeric position is independently[0-9LMNPQRSTUV], guarded by the checksum).characters.lastIndex(of:), which searches the whole code. When the substitution letter also appears later in the code (first letter of the place-of-birth code, or the checksum letter), the wrong character was replaced, corrupting the decoded code.isValidcompared mismatched checksums for every omocode variant: the expected checksum was computed on the value as passed, but compared against the recomputed checksum of the decoded original code. As a result,isValidreturnedfalsefor any omocodia variant, contiguous ones included (e.g.MRCMLD92C42D96VG, whichoriginalFiscalCodeitself decodes correctly).Fix
originalFiscalCode(from:)now restores digits by their known positions (6, 7, 9, 10, 12, 13, 14), accepting any combination of substituted positions. The checksum pre-check and the omocodia-letter mapping still reject malformed codes (e.g.SFAFRS92C02ZN2ZW, which carries a valid checksum but a letter outside the omocodia alphabet).isValidvalidates the checksum against the passed value itself.Behavioral note:
SFAFRS92C02ZN2VJ, previously treated as corrupted because of the non-contiguity rule, is a well-formed omocode (valid checksum, valid substitution letters) and now decodes toSFAFRS92C02Z229F. The corresponding test expectation moved accordingly.Tests
All fiscal codes in the new tests are synthetic (built on the classic fictional
RSSMRA...data), no real personal data is included:RSSMRA90A01H5L1H— non-contiguous substitution (position 13 substituted, 14 not), mirrors the production case; decodes toRSSMRA90A01H501W.RSSMRA90A0MM002M— the substituted letterMalso appears as the first letter of the municipality code and as the checksum; guards the positional replacement againstlastIndex-style regressions.MRCMLD92C42D96VG— contiguous omocode now accepted byisValid, covering the checksum-comparison fix.Full suite passes: 67 tests, 0 failures.