Moteur de règles fiscales canadiennes
Un moteur de règles qui calcule l'impôt fédéral T1 et québécois TP-1, où chaque constante se retrace jusqu'à la page source dont elle provient.
L'impôt sur le revenu est du droit public. N'importe qui peut lire les paliers, et presque tous ceux qui les implémentent se trompent quelque part, parce que la faute n'est pas dans l'arithmétique. Elle est dans les constantes : un taux modifié l'an dernier, un montant qui s'éteint sur un seuil que personne n'a revérifié. Ce moteur calcule les obligations fédérales T1 et québécoises TP-1, et l'intérêt n'est pas le calcul. C'est la façon dont il apprend qu'il se trompe.
Dix-sept domaines sont implémentés sur les deux déclarations : paliers fédéraux et québécois, montants personnels de base et leur extinction, RRQ, assurance-emploi au taux réduit du Québec, RQAP, montants d'âge, de pension et pour déficience, l'abattement québécois de 16,5 pour cent, le crédit d'impôt pour solidarité, la déduction pour travailleur, le REER, les cotisations syndicales et les frais de garde, et les retenues résolues en remboursement ou en solde dû. Chaque constante n'existe qu'une fois, dans une table de paramètres datée qui porte son URL source et sa date de récupération, pour qu'aucun chiffre ne dorme en double. Une API REST expose le moteur avec des clés révocables par client.
Ce que nous avons mesuré
Une seconde implémentation a ensuite été écrite de zéro, qui n'importe jamais le moteur, bâtie en retournant chercher les sources primaires à l'ARC, à Revenu Québec et au Ministère des Finances. Une barrière différentielle confronte les deux. S'y ajoutent des tests de propriété qui ne demandent aucun oracle : monotonie, continuité aux frontières de paliers, comportement d'extinction, pureté.
À quoi ça tient
À sa première passe, l'oracle a trouvé 8 défauts confirmés, 2 au fédéral et 6 au Québec : des paliers périmés, un montant personnel de base périmé, le mauvais mécanisme pour la déduction pour travailleur, la mauvaise structure pour le crédit d'âge et de retraite, des montants pour déficience périmés sur les deux déclarations, un plafond fédéral de frais médicaux périmé, des chiffres de solidarité erronés, et un défaut d'arrondi en virgule flottante. Chacun a été revérifié contre une deuxième tournée de sources avant que le moteur ne change, et aucun ne s'est avéré être une erreur de l'oracle. Pourquoi les tests existants les avaient-ils tous manqués ? Ils avaient été transcrits à la main depuis les mêmes tables, par le même auteur, dans la même séance que le moteur. Ils prouvaient que les deux transcriptions s'accordaient. Ils ne pouvaient pas prouver que l'une ou l'autre suivait la loi.
Ce mode de panne n'a rien de propre à l'impôt. La paie, les avantages sociaux, l'assurance et les taxes de vente le partagent : une constante fausse avec laquelle tous les tests sont d'accord, parce que les tests viennent de la même source que le code. Une seconde implémentation bâtie sur les sources primaires, c'est ainsi qu'on la trouve.
PORTÉE ET LIMITES
Disons-le franchement : ceci est en pré-alpha. La validation contre un outil certifié IMPÔTNET est toujours en cours, donc ce moteur n'est pas certifié pour des décisions de production de déclaration et n'est pas offert comme tel. Il correspond à l'oracle au cent près sur les dix scénarios de référence des deux déclarations, ce qui est un énoncé sur l'accord de deux implémentations, pas sur une certification.
TECHNOLOGIES
- Python · FastAPI · Pydantic · pytest · Docker
- FastAPI
- Pydantic
- pytest
- Docker