This repository was archived by the owner on Oct 12, 2026. It is now read-only.
Repository navigation
feat: add PIS, voter ID, plate, combined document and PIX key - #6
Merged
Merged
Conversation
Five validators, chosen because each has a single canonical algorithm that could be checked against a reference rather than recalled. The check-digit arithmetic moves into utils/checkdigit.go. CPF, CNPJ and PIS share the same rule — a weighted sum modulo 11, with the two remainders that would need two characters folded onto zero — so it lives once instead of being copied into each new document along with its chance of getting the edge case wrong. The voter ID does not share it, and that is the interesting one. Its check digits are the remainder itself rather than eleven minus it; São Paulo and Minas Gerais outgrew the eight-digit sequence so their numbers carry thirteen digits, which means the state code has to be located from the end rather than at a fixed offset; and for those two states a remainder of zero yields 1. The first implementation of it here got all three wrong, which is why the tests below exist in the shape they do. The combined "documento" parameter accepts whichever of CPF or CNPJ the digit count describes: forms offer one field, and making the caller decide which endpoint to call defeats the point of that field. The PIX key infers its form for the same reason — a key arrives pasted into one box with nothing saying what kind it is. Every new parameter joins the one-per-request guard. Left out, each would have been a way to smuggle a second validation past it. Verification: fixed vectors published by brazilian-utils, plus a differential run of 10,000 generated numbers against reference implementations transcribed flat into the test file, plus 500 constructed-valid PIS numbers — a validator that returned false unconditionally would otherwise pass a differential test against random input.
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
Five new validators. They were chosen on one criterion: each has a single canonical algorithm that could be checked against a reference implementation, rather than recalled and hoped for. The ones that failed that test are listed at the bottom.
pistituloplacadocumentopixStructure
The check-digit arithmetic moves into
utils/checkdigit.go. CPF, CNPJ and PIS share one rule — a weighted sum modulo 11, with the two remainders that would need two characters folded onto zero — so it now lives once rather than being copied into each new document along with its chance of getting the edge case wrong.The voter ID is the interesting one
It does not share that rule, and my first implementation of it in this branch got three separate things wrong:
All three were caught by checking against brazilian-utils before writing the tests, not after. It is the reason this PR ships five validators instead of ten.
Design notes
documentoinfers CPF or CNPJ from the digit count. Forms offer a single document field; making the caller decide which endpoint to call defeats the point of that field.The PIX key infers its form for the same reason — a key arrives pasted into one box with nothing saying what kind it is. A phone key must carry
+55: a bare national number is ambiguous, and the arrangement does not accept it.Every new parameter joins
validationCount. Left out, each would have been a way to smuggle a second validation past the one-per-request guard.Verification
Three layers, because "I am fairly sure of the algorithm" is not a test:
12056874107and12056412847valid,12056412547and12081636639invalid.falseunconditionally would sail through a differential test otherwise.Plus the usual table tests for plate, document and PIX, and handler tests covering the routes and the parameter collisions.
go test ./... -racegreen;utilscoverage 72% → 81%.Deliberately not in this PR
CNH, Renavam, inscrição estadual and boleto.
CNH and Renavam have multiple published algorithm variants and I could not settle which is authoritative from the sources available. Inscrição estadual is twenty-seven different algorithms and deserves its own change. The boleto's linha digitável is well specified by FEBRABAN but mixes mod-10 and mod-11 across two different layouts, and it is large enough to review on its own.
Shipping a validator that is probably right is worse than not shipping it: a wrong answer from a validation service is more damaging than no answer, because the caller stops checking.