Skip to content

fix(holidays,bank-account): add Rio de Janeiro's Corpus Christi and accept 12 digit Caixa accounts - #598

Merged
hyanmandian merged 10 commits into
claude/area-code-municipalitiesfrom
claude/sources-round-3
Sep 29, 2026
Merged

hyanmandian merged 10 commits into
claude/area-code-municipalitiesfrom
claude/sources-round-3

Conversation

@hyanmandian

Copy link
Copy Markdown
Member

What does this PR do?

Stacks on #597. It applies what the second round of the official-source investigation found against the stack.

Holidays

  • Rio de Janeiro Corpus Christi: Lei RJ nº 11.002/2025 makes Corpus Christi (Easter + 60) a feriado estadual, in force on publication. The STF upheld it in ADI 7898; the decision is unanimous and was published on 02/07/2026, with trânsito em julgado on 13/08/2026.
    • With stateCode: "RJ" it is now typed "state" from 2026 on, the same as DF and MA.
    • With includeOptional: false it still counts as a non-business day.
    • Up to 2.4.0 it was missing.
  • Goiás 2026: Decreto GO nº 10.987/2026 moved 28/10/2026 to 30/10. It is documented next to the other one-off decree dates the table does not carry.

isValidBankAccount, Caixa (104)

  • Account format: the Caixa layouts describe the account with 12 digits, "sem operação", in CNAB 400 notes NE051/NE052 and CNAB 240 note G011, with worked examples. The lib only took the older 11 digit form (operação + conta), so every 12 digit Caixa account was rejected.
  • Check digits: a 12 digit account now takes either of the two digits the Caixa defines:
    • the account's own digit, over the 12 digits (official example 000000109990 → 6);
    • the agency/account digit, over agency + account (official example 0161 + 000000109990 → 5).
  • Older form: 11 digit accounts keep the compendium rule, and their existing test cases still pass.

Official citations

  • Santander: the account digit (Débito Automático 150 v08, April 2026) matches the existing rule; its example, agency 2001 and account 01038237 with digit 7, is accepted.
  • Banco do Brasil: the agency digit (Doc5175, Anexo XI) is mathematically the same module 11 used here.
  • All three manuals are now cited as @see Official, and the docs say which rules have an official source.

Checklist

  • My commit/PR title follows Conventional Commits.
  • I added or updated tests covering this change: the RJ Corpus Christi in 2025 and 2026 (holiday and business day), and the Caixa official examples plus the "above 9 → 0" case.
  • I updated the documentation in both docs/utilities.md and docs/pt-br/utilities.md.
  • npm run check passes locally. Coverage (7783 tests), Deno, Stryker on is-valid-bank-account.ts (100%) and check:api also pass.
  • I ran npm run build:llms.
  • This change does not introduce a breaking change. It accepts accounts the official Caixa layout documents and adds a holiday a law in force creates; check:api reports no breaking change against 2.4.0.
  • This change does not add any runtime dependency.

Additional context

Sources: the Lei RJ nº 11.002/2025 text on the ALERJ site, STF ADI 7898, Decreto GO nº 10.987/2026, and the Caixa, Santander and Banco do Brasil layout manuals (links in the JSDoc).

🤖 Generated with Claude Code

https://claude.ai/code/session_01RLkm9YrtAifc6XCLFVEsdH


Generated by Claude Code

…ccept 12 digit Caixa accounts

Lei RJ nº 11.002/2025 made Corpus Christi (Easter plus 60) a feriado estadual in force on its
publication, and the STF upheld it in ADI 7898 (trânsito em julgado 13/08/2026), so with
stateCode "RJ" it is typed "state" from 2026 on, as in the Distrito Federal and Maranhão.
Goiás' 28/10/2026, moved to 30/10 by Decreto GO nº 10.987/2026, joins the one-off decree
dates the table documents without carrying.

The Caixa layouts (CNAB 400 notes NE051 and NE052, CNAB 240 note G011) describe the account
with 12 digits, "sem operação", and publish both of its check digits with worked examples.
isValidBankAccount only took the older 11 digit operação + conta form, so every 12 digit Caixa
account was rejected; it now takes either digit over a 12 digit account, and keeps the
compendium rule for 11 digits. The Santander account digit and the Banco do Brasil agency
digit, also published in each bank's manuals, match the rules already here, and all three
manuals are now cited.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLkm9YrtAifc6XCLFVEsdH
@vercel

vercel Bot commented Sep 27, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
brazilian-utils Ready Ready Preview Sep 29, 2026 3:17am UTC

@coderabbitai

coderabbitai Bot commented Sep 27, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 6ac71d5d-2f7a-4c40-a1ad-ac779e293640

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@pkg-pr-new

pkg-pr-new Bot commented Sep 27, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@brazilian-utils/brazilian-utils@598

commit: c283ec5

@github-actions

github-actions Bot commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

Tree-shaking report

✅ No size regression. 7 grew out of 187 exports.

Base Head Δ
Pre-existing exports, all imported 1895.1 KB 1895.2 KB (gzip 349.9 KB) +100 B (+0.0%)
Full import 1895.1 KB 1895.2 KB (gzip 349.9 KB) +100 B (+0.0%)
Exports 187 187 0

What changed (7)

Export Base Head Δ gzip
🟡 addBusinessDays 8.5 KB 8.6 KB +51 B (+0.6%) 3.1 KB
🟡 differenceInBusinessDays 8.4 KB 8.4 KB +51 B (+0.6%) 3.0 KB
🟡 getHolidays 7.4 KB 7.4 KB +51 B (+0.7%) 2.6 KB
🟡 isBusinessDay 7.8 KB 7.9 KB +51 B (+0.6%) 2.8 KB
🟡 isHoliday 7.7 KB 7.7 KB +51 B (+0.6%) 2.7 KB
🟡 subBusinessDays 8.6 KB 8.6 KB +51 B (+0.6%) 3.1 KB
🟡 isValidBankAccount 5.2 KB 5.3 KB +43 B (+0.8%) 2.4 KB
All exports (187)
Export Base Head Δ gzip
⚪ GetAddressInfoByCepError 112 B 112 B 0 B 124 B
⚪ GetAddressInfoByCepNotFoundError 205 B 205 B 0 B 145 B
⚪ GetAddressInfoByCepServiceError 204 B 204 B 0 B 143 B
⚪ GetAddressInfoByCepValidationError 203 B 203 B 0 B 144 B
⚪ GetCepInfoByAddressError 112 B 112 B 0 B 124 B
⚪ GetCepInfoByAddressNotFoundError 205 B 205 B 0 B 145 B
⚪ GetCepInfoByAddressValidationError 203 B 203 B 0 B 144 B
🟡 addBusinessDays 8.5 KB 8.6 KB +51 B (+0.6%) 3.1 KB
⚪ capitalize 2.4 KB 2.4 KB 0 B 1.2 KB
⚪ convertCurrencyToWords 2.0 KB 2.0 KB 0 B 1.0 KB
⚪ convertDateToWords 2.4 KB 2.4 KB 0 B 1.2 KB
⚪ convertLicensePlateToMercosul 527 B 527 B 0 B 363 B
⚪ convertNumberToWords 1.6 KB 1.6 KB 0 B 819 B
🟡 differenceInBusinessDays 8.4 KB 8.4 KB +51 B (+0.6%) 3.0 KB
⚪ formatBoleto 649 B 649 B 0 B 402 B
⚪ formatCEP 470 B 470 B 0 B 334 B
⚪ formatCNPJ 620 B 620 B 0 B 420 B
⚪ formatCPF 521 B 521 B 0 B 365 B
⚪ formatCaepf 487 B 487 B 0 B 344 B
⚪ formatCei 484 B 484 B 0 B 343 B
⚪ formatCep 470 B 470 B 0 B 334 B
⚪ formatCertidao 513 B 513 B 0 B 350 B
⚪ formatCest 474 B 474 B 0 B 337 B
⚪ formatCid10 459 B 459 B 0 B 330 B
⚪ formatCnae 474 B 474 B 0 B 340 B
⚪ formatCnh 517 B 517 B 0 B 361 B
⚪ formatCno 488 B 488 B 0 B 344 B
⚪ formatCnpj 620 B 620 B 0 B 420 B
⚪ formatCns 483 B 483 B 0 B 340 B
⚪ formatCpf 521 B 521 B 0 B 365 B
⚪ formatCurrency 985 B 985 B 0 B 592 B
⚪ formatIban 267 B 267 B 0 B 228 B
⚪ formatLegalNature 470 B 470 B 0 B 337 B
⚪ formatLicensePlate 361 B 361 B 0 B 270 B
⚪ formatNbs 462 B 462 B 0 B 334 B
⚪ formatNcm 475 B 475 B 0 B 338 B
⚪ formatNfeKey 601 B 601 B 0 B 383 B
⚪ formatPassport 187 B 187 B 0 B 174 B
⚪ formatPhone 2.6 KB 2.6 KB 0 B 1.2 KB
⚪ formatPis 521 B 521 B 0 B 365 B
⚪ formatProcessoJuridico 490 B 490 B 0 B 344 B
⚪ formatSuframa 476 B 476 B 0 B 338 B
⚪ formatVoterId 523 B 523 B 0 B 365 B
⚪ generateBoleto 1.4 KB 1.4 KB 0 B 779 B
⚪ generateCNPJ 843 B 843 B 0 B 523 B
⚪ generateCPF 628 B 628 B 0 B 423 B
⚪ generateCep 130 B 130 B 0 B 136 B
⚪ generateCnh 565 B 565 B 0 B 343 B
⚪ generateCnpj 843 B 843 B 0 B 523 B
⚪ generateCpf 628 B 628 B 0 B 423 B
⚪ generateLegalNature 5.0 KB 5.0 KB 0 B 1.6 KB
⚪ generateLicensePlate 266 B 266 B 0 B 227 B
⚪ generatePassport 226 B 226 B 0 B 191 B
⚪ generatePhone 670 B 670 B 0 B 419 B
⚪ generatePis 357 B 357 B 0 B 272 B
⚪ generatePixPayload 4.5 KB 4.5 KB 0 B 2.0 KB
⚪ generateProcessoJuridico 821 B 821 B 0 B 523 B
⚪ generateRenavam 378 B 378 B 0 B 284 B
⚪ generateSuframa 451 B 451 B 0 B 335 B
⚪ generateVoterId 852 B 852 B 0 B 551 B
⚪ getAddressInfoByCep 3.9 KB 3.9 KB 0 B 1.7 KB
⚪ getAreaCodeByMunicipalityCode 165.0 KB 165.0 KB 0 B 52.2 KB
⚪ getAreaCodeInfo 3.1 KB 3.1 KB 0 B 989 B
⚪ getAreaCodesByState 809 B 809 B 0 B 459 B
⚪ getBankByCode 37.8 KB 37.8 KB 0 B 9.2 KB
⚪ getBankByIspb 37.8 KB 37.8 KB 0 B 9.2 KB
⚪ getBanks 37.6 KB 37.6 KB 0 B 9.0 KB
⚪ getBoletoInfo 2.4 KB 2.4 KB 0 B 1.2 KB
⚪ getCbo 115.7 KB 115.7 KB 0 B 29.5 KB
⚪ getCepInfoByAddress 2.0 KB 2.0 KB 0 B 1.0 KB
⚪ getCertidaoInfo 1.0 KB 1.0 KB 0 B 594 B
⚪ getCest 115.5 KB 115.5 KB 0 B 26.1 KB
⚪ getCfop 67.6 KB 67.6 KB 0 B 6.3 KB
⚪ getCid10 988.3 KB 988.3 KB 0 B 123.6 KB
⚪ getCities 153.4 KB 153.4 KB 0 B 49.2 KB
⚪ getClassTrib 50.0 KB 50.0 KB 0 B 9.0 KB
⚪ getCnae 91.6 KB 91.6 KB 0 B 20.0 KB
⚪ getCnpjInfo 964 B 964 B 0 B 542 B
⚪ getCpfInfo 994 B 994 B 0 B 614 B
⚪ getCstIbsCbs 967 B 967 B 0 B 534 B
⚪ getFormatLicensePlate 315 B 315 B 0 B 245 B
⚪ getGtinInfo 817 B 817 B 0 B 555 B
🟡 getHolidays 7.4 KB 7.4 KB +51 B (+0.7%) 2.6 KB
⚪ getIbanInfo 752 B 752 B 0 B 494 B
⚪ getLegalNature 5.6 KB 5.6 KB 0 B 1.8 KB
⚪ getLegalNatures 5.1 KB 5.1 KB 0 B 1.6 KB
⚪ getLegalNaturesByCategory 5.6 KB 5.6 KB 0 B 1.9 KB
⚪ getMunicipalities 153.6 KB 153.6 KB 0 B 49.4 KB
⚪ getMunicipalitiesByAreaCode 167.8 KB 167.8 KB 0 B 52.8 KB
⚪ getMunicipality 154.1 KB 154.1 KB 0 B 49.7 KB
⚪ getMunicipalityByCode 153.8 KB 153.8 KB 0 B 49.5 KB
⚪ getNbs 80.6 KB 80.6 KB 0 B 13.1 KB
⚪ getNfeKeyInfo 2.2 KB 2.2 KB 0 B 1.2 KB
⚪ getNfseKeyInfo 2.4 KB 2.4 KB 0 B 1.2 KB
⚪ getPixKeyInfo 2.5 KB 2.5 KB 0 B 1.2 KB
⚪ getPixPayloadInfo 4.6 KB 4.6 KB 0 B 2.1 KB
⚪ getServiceItem 26.1 KB 26.1 KB 0 B 8.4 KB
⚪ getStateByCep 3.6 KB 3.6 KB 0 B 1.0 KB
⚪ getStateByIbgeCode 2.4 KB 2.4 KB 0 B 700 B
⚪ getStateCodeByName 2.3 KB 2.3 KB 0 B 649 B
⚪ getStateNameByCode 2.2 KB 2.2 KB 0 B 591 B
⚪ getStates 2.2 KB 2.2 KB 0 B 539 B
⚪ getTimezoneByState 737 B 737 B 0 B 327 B
🟡 isBusinessDay 7.8 KB 7.9 KB +51 B (+0.6%) 2.8 KB
🟡 isHoliday 7.7 KB 7.7 KB +51 B (+0.6%) 2.7 KB
🟡 isValidBankAccount 5.2 KB 5.3 KB +43 B (+0.8%) 2.4 KB
⚪ isValidBoleto 1.6 KB 1.6 KB 0 B 892 B
⚪ isValidCEP 163 B 163 B 0 B 163 B
⚪ isValidCNPJ 796 B 796 B 0 B 447 B
⚪ isValidCPF 500 B 500 B 0 B 334 B
⚪ isValidCaepf 782 B 782 B 0 B 479 B
⚪ isValidCbo 16.2 KB 16.2 KB 0 B 5.5 KB
⚪ isValidCei 714 B 714 B 0 B 472 B
⚪ isValidCep 163 B 163 B 0 B 163 B
⚪ isValidCertidao 758 B 758 B 0 B 462 B
⚪ isValidCest 7.6 KB 7.6 KB 0 B 2.3 KB
⚪ isValidCfop 2.8 KB 2.8 KB 0 B 1.4 KB
⚪ isValidCid10 26.2 KB 26.2 KB 0 B 6.8 KB
⚪ isValidClassTrib 1.8 KB 1.8 KB 0 B 639 B
⚪ isValidCnae 9.6 KB 9.6 KB 0 B 3.4 KB
⚪ isValidCnh 610 B 610 B 0 B 370 B
⚪ isValidCno 718 B 718 B 0 B 474 B
⚪ isValidCnpj 796 B 796 B 0 B 447 B
⚪ isValidCns 746 B 746 B 0 B 475 B
⚪ isValidCpf 500 B 500 B 0 B 334 B
⚪ isValidCreditCard 555 B 555 B 0 B 389 B
⚪ isValidCsosn 330 B 330 B 0 B 262 B
⚪ isValidCst 995 B 995 B 0 B 569 B
⚪ isValidCstIbsCbs 894 B 894 B 0 B 505 B
⚪ isValidEmail 171 B 171 B 0 B 157 B
⚪ isValidGtin 428 B 428 B 0 B 313 B
⚪ isValidIE 5.1 KB 5.1 KB 0 B 1.8 KB
⚪ isValidIban 531 B 531 B 0 B 376 B
⚪ isValidIe 5.1 KB 5.1 KB 0 B 1.8 KB
⚪ isValidLandlinePhone 717 B 717 B 0 B 463 B
⚪ isValidLegalNature 649 B 649 B 0 B 427 B
⚪ isValidLicensePlate 267 B 267 B 0 B 216 B
⚪ isValidMobilePhone 758 B 758 B 0 B 496 B
⚪ isValidNbs 8.5 KB 8.5 KB 0 B 2.3 KB
⚪ isValidNcm 82.6 KB 82.6 KB 0 B 22.8 KB
⚪ isValidNfeKey 1.6 KB 1.6 KB 0 B 954 B
⚪ isValidNfseKey 2.1 KB 2.1 KB 0 B 1.1 KB
⚪ isValidPIS 418 B 418 B 0 B 316 B
⚪ isValidPassport 197 B 197 B 0 B 186 B
⚪ isValidPhone 1.8 KB 1.8 KB 0 B 909 B
⚪ isValidPis 418 B 418 B 0 B 316 B
⚪ isValidPixKey 2.3 KB 2.3 KB 0 B 1.1 KB
⚪ isValidPixPayload 4.2 KB 4.2 KB 0 B 1.9 KB
⚪ isValidProcessoJuridico 699 B 699 B 0 B 429 B
⚪ isValidRegistroProfissional 1.2 KB 1.2 KB 0 B 724 B
⚪ isValidRenavam 516 B 516 B 0 B 356 B
⚪ isValidServiceItem 1.2 KB 1.2 KB 0 B 694 B
⚪ isValidServicePhone 706 B 706 B 0 B 372 B
⚪ isValidSuframa 590 B 590 B 0 B 411 B
⚪ isValidVin 848 B 848 B 0 B 573 B
⚪ isValidVoterId 706 B 706 B 0 B 427 B
⚪ parseBoleto 247 B 247 B 0 B 215 B
⚪ parseCaepf 199 B 199 B 0 B 183 B
⚪ parseCbo 198 B 198 B 0 B 182 B
⚪ parseCei 199 B 199 B 0 B 183 B
⚪ parseCep 198 B 198 B 0 B 182 B
⚪ parseCertidao 199 B 199 B 0 B 183 B
⚪ parseCest 198 B 198 B 0 B 182 B
⚪ parseCfop 198 B 198 B 0 B 182 B
⚪ parseCid10 177 B 177 B 0 B 170 B
⚪ parseCnae 198 B 198 B 0 B 182 B
⚪ parseCnh 199 B 199 B 0 B 183 B
⚪ parseCno 199 B 199 B 0 B 183 B
⚪ parseCnpj 298 B 298 B 0 B 240 B
⚪ parseCns 199 B 199 B 0 B 184 B
⚪ parseCpf 199 B 199 B 0 B 183 B
⚪ parseCurrency 610 B 610 B 0 B 409 B
⚪ parseIban 227 B 227 B 0 B 202 B
⚪ parseLegalNature 198 B 198 B 0 B 182 B
⚪ parseLicensePlate 177 B 177 B 0 B 170 B
⚪ parseNcm 198 B 198 B 0 B 182 B
⚪ parseNfeKey 412 B 412 B 0 B 312 B
⚪ parseNfseKey 253 B 253 B 0 B 219 B
⚪ parsePassport 177 B 177 B 0 B 169 B
⚪ parsePhone 370 B 370 B 0 B 281 B
⚪ parsePis 199 B 199 B 0 B 183 B
⚪ parseProcessoJuridico 199 B 199 B 0 B 182 B
⚪ parseSuframa 198 B 198 B 0 B 181 B
⚪ parseVoterId 199 B 199 B 0 B 183 B
⚪ removeAccents 99 B 99 B 0 B 119 B
🟡 subBusinessDays 8.6 KB 8.6 KB +51 B (+0.6%) 3.1 KB
⚪ toStandardSchema 284 B 284 B 0 B 233 B
How this is measured

Every export is imported alone into an esbuild consumer bundle (minified, tree-shaken) built from the head and from the base of this pull request; the sizes are the resulting bundles, gzip is their gzipped size. 🔴 marks a regression: a pre-existing export that grew more than 20% and more than 256 B, or the bundle importing every pre-existing export growing more than 5%. 🟡 is growth under the threshold, 🟢 a decrease, ⚪ no change, 🆕 an export that does not exist on the base (never a regression), 🗑️ an export that was removed. An intentional increase is accepted with the tree-shaking: accepted label.

@codecov

codecov Bot commented Sep 27, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (8ad95fc) to head (c283ec5).

Additional details and impacted files
@@                        Coverage Diff                        @@
##           claude/area-code-municipalities      #598   +/-   ##
=================================================================
  Coverage                           100.00%   100.00%           
=================================================================
  Files                                  227       227           
  Lines                                 2364      2367    +3     
  Branches                               706       707    +1     
=================================================================
+ Hits                                  2364      2367    +3     
Flag Coverage Δ
node 100.00% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@hyanmandian
hyanmandian added this pull request to stack #614 September 29, 2026 04:08
@hyanmandian
hyanmandian merged commit 1f82b56 into main Sep 29, 2026
30 checks passed

This branch was successfully deployed

1 active deployment
Preview — c283ec57 Deployed Sep 29, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants