Rule pack changelog
- 110 rules
- 97 rules mirror ZATCA's published Schematron, covering 96 of its 242 rule codes
- 151 measured fixtures
- Rule pack
2.2.0
The rule pack versions and what each one added, group by group, from the published validation rules. The version and the coverage figures above are read from the built pack; nothing on this page is typed.
What each version added
Dated prose, one entry per day the pack changed, with representative rule pages linked. The full list of rules is on the rules index.
When ZATCA publishes a new SDK, Mutabiq re-runs its fixture set and the coverage count against the files the release ships, and records the result on the changelog within fourteen days.
- Business rules - integrity constraints (BR)2 rules
- KSA - business rules (BR-KSA)36 rules
- Business rules - Code lists (BR-CL)3 rules
- Business rules - conditions (BR-CO)9 rules
- Business rules - VAT standard and reduced rate (BR-S)4 rules
- Business rules - Decimals (BR-DEC)13 rules
- Business rules - Exempted from VAT (BR-E)4 rules
- Business rules - Not subject to VAT (BR-OO)6 rules
- Business rules - Exempted from VAT (BR-KSA)1 rule
- Business rules - Not subject to VAT (BR-KSA)1 rule
- Business rules - VAT zero rate (BR-KSA)1 rule
- KSA - code list (BR-KSA-CL)4 rules
- KSA - formats (BR-KSA-84)1 rule
- KSA - decimals rules (BR-KSA-DEC)4 rules
- KSA - EN16931 (BR-KSA-EN16931)2 rules
- KSA - formats (BR-KSA-F)2 rules
- Business rules - VAT zero rate (BR-Z)4 rules
2.2.0
Rule pack 2.2.0 is dated 2026-10-15 and is the pack this site runs. It still reads ZATCA’s SDK 3.4.8, the same validation rule files 2.1.0 and 2.0.0 read, and it carries 110 rules: the rules it adds each mirror an assertion 3.4.8 carries that no earlier pack had mirrored. The minor version moved because rules were added, as the pack’s versioning policy says it must. No fixture that existed before this release changed its verdict: every assertion added is a warning in 3.4.8, and a warning does not by itself turn the verdict to Not passed — except MTB-BR-45, an error, which ZATCA’s tool rejects a document on and which was added for the fixtures built to measure that.
Added: MTB-BR-S-08, MTB-BR-Z-08, MTB-BR-E-08, MTB-BR-KSA-83, MTB-BR-KSA-25, MTB-BR-45. MTB-BR-S-08, MTB-BR-Z-08 and MTB-BR-E-08 tie a standard-rated, zero-rated or exempt VAT breakdown’s taxable amount to the sum of its own line amounts, less document allowances, plus document charges, exactly — the check BR-O-08 already made for the out-of-scope group, which 3.4.8 extends to the other categories (the earlier SDK carried no such rule for them). The standard-rated rule adds every standard-rated breakdown under the same tax total before comparing, so an invoice with a standard-rate group and a reduced-rate group is judged on their sum; ZATCA’s own tool was measured on such a document and accepts it. MTB-BR-KSA-83 reports an exemption reason code on a zero-rated, exempt or out-of-scope breakdown that has no reason text, or a blank text, beside it; the part of ZATCA’s rule that would check the text against the published list is disabled in the files ZATCA ships, so no list is checked. MTB-BR-KSA-25 reports a simplified invoice for private education or private healthcare — every reason code VATEX-SA-EDU or VATEX-SA-HEA — that does not name the buyer; ZATCA’s tool was measured not to apply it to a simplified invoice with no reason code at all, and the rule follows the tool. MTB-BR-45 reports a VAT breakdown entry with no taxable amount element at all: the XML schema allows the omission, ZATCA’s rule files flag it as an error and ZATCA’s tool was measured to reject such a document, so this rule is the release’s only error.
Changed: the explanation under MTB-BR-KSA-49 now says in so many words that these codes are for a supply to the citizen, and that whether an invoice addressed to an insurer, an employer or another payer qualifies for them is a question for your tax adviser, and points to MTB-BR-KSA-25 for the buyer name on a simplified invoice; and the explanation under MTB-BR-O-08 no longer says the out-of-scope group is the only group checked this way.
2.1.0
Rule pack 2.1.0 is dated 2026-09-29 and was the pack this site ran until 2.2.0 replaced it on 2026-10-15. It still reads ZATCA’s SDK 3.4.8, the same validation rule files 2.0.0 read, and it carried the same rules as 2.0.0: what it adds sits in the archive reader, beside MTB-BATCH-00, outside the count this page prints, because those rules read the files of an upload together rather than a single document, which nothing in ZATCA’s published rule set does. The minor version moved because rules were added, as the pack’s versioning policy says it must.
Added: MTB-BATCH-01 and MTB-BATCH-02, the invoice chain across the files uploaded together in a ZIP. Both read the archive’s members under the same seller VAT registration number, ordered by invoice counter value (KSA-16). MTB-BATCH-01 reports a member whose previous invoice hash (KSA-13) is not the hash the member before it, by counter, carries in its own QR code — the hash the issuing device wrote for it; Mutabiq computes no hash, and compares the values the documents already carry. MTB-BATCH-02 reports a counter value that more than a single member of the same seller carries. Both are warnings, and a warning does not by itself turn the verdict to Not passed: no published assertion reads documents together, so what the Fatoora platform does with a broken chain is not something Mutabiq can measure. And a hash mismatch or a repeated counter across files from different devices is expected: the counter and the chain belong to each device separately, so a seller’s devices exported together will interleave, and the explanation of each finding says so. The clearest reading is an archive per device. Neither rule mirrors a published assertion, so, like MTB-PIH-01 and the QR group, they have no page under the rules index.
Changed: MTB-BR-DEC-23, the line net amount’s decimal places, reports every failing line, each at its own position, where it reported the first and left the reader to find the rest — the same move the line-level rules made in 1.1.0. Its neighbours BR-DEC-24 and BR-DEC-25 were retired in 2.0.0 and have nothing to report per line. No fixture’s verdict moved.
2.0.0
Rule pack 2.0.0 is dated 2026-09-27 and was the pack this site ran until 2.1.0 replaced it on 2026-09-29. It reads ZATCA’s SDK 3.4.8 — the validation rule files dated 2025-12-01 (the KSA file) and 2025-09-02 (the EN file) — where every earlier pack read SDK 3.0.8. The major version moved because the source the pack mirrors changed, not because Mutabiq’s own checks did: the same document can pass under 1.1.0 and fail under 2.0.0, or the reverse, with nothing in it changed, because ZATCA’s own checker changed what it asks. A report names the pack that judged it and, beside it, the SDK that pack reads.
The pack holds 110 rules, fewer than before this release: 18 were retired, because SDK 3.4.8 no longer carries the assertion they mirrored or can no longer reach it — MTB-BR-CL-KSA-13, MTB-BR-DEC-24, MTB-BR-DEC-25, MTB-BR-E-10, MTB-BR-KSA-41, MTB-BR-KSA-45, MTB-BR-KSA-46, MTB-BR-KSA-50, MTB-BR-KSA-CL-05, MTB-BR-KSA-CL-70, MTB-BR-KSA-DEC-05, MTB-BR-KSA-F-02, MTB-BR-O-02, MTB-BR-O-05, MTB-BR-O-10, MTB-BR-O-11, MTB-BR-O-12, MTB-BR-O-13 — and their pages stay at the same addresses, marked retired, for the reports that still name them. Added, each mirroring an assertion 3.4.8 carries that 3.0.8 did not or that no earlier rule had mirrored: MTB-BR-CL-01, MTB-BR-CO-12, MTB-BR-KSA-11, MTB-BR-KSA-18, MTB-BR-KSA-23, MTB-BR-KSA-24, MTB-BR-KSA-49, MTB-BR-KSA-53, MTB-BR-KSA-68, MTB-BR-KSA-70, MTB-BR-KSA-84, MTB-BR-KSA-CL-02, MTB-BR-KSA-EN16931-02.
Severities follow 3.4.8’s own flags, and 3.4.8 flags as a warning much of what 3.0.8 flagged as an error, so a large part of the rules the pack keeps now report a WARNING where the earlier packs reported an ERROR; the report’s badge and each rule’s explanation say which, and a warning does not by itself turn the verdict to Not passed. Ceilings moved with the files: the QR code may now be twice as long as before (MTB-BR-CL-KSA-14), and the exemption reason codes are checked per VAT category, with the codes 3.4.8 added — VATEX-SA-DUTYFREE and VATEX-SA-ROYALDECREE among them — accepted where 3.0.8 refused them (MTB-BR-KSA-CL-04). And 3.4.8 pins the standard VAT rate, which no earlier file did (MTB-BR-KSA-84).
Coverage is stated as before, from the generated index: 97 of the pack’s rules mirror a code in 3.4.8’s rule files. Those files also carry codes that no rule mirrors yet; Mutabiq does not run those checks, and nothing on this site claims them.
1.1.0
Rule pack 1.1.0 is dated 2026-09-27 and was the pack this site ran until 2.0.0 replaced it later the same day. It added no rule. It was the number the pack had needed since 2026-09-10: 1.0.0 was minted early that day, and later the same day #38 added the rounding-and-decimals group — the 13 rules of the CEN decimals category, and MTB-BR-KSA-DEC-01, MTB-BR-KSA-DEC-04 and MTB-BR-KSA-DEC-05 — without moving the version, so from #38 until 1.1.0 a report stamped 1.0.0 was produced by the larger rule set. The pack’s versioning is now written down: any rule added, removed or changed in severity moves the minor version; a rule whose guard changes without changing what it reports moves the patch version and is named here.
Changes ship with 1.1.0 that the policy would have required on their own. MTB-XSD-00 — the finding Mutabiq reports about itself when the schema check could not run — is now an error, so a report whose structural check did not run reads Not passed rather than Passed; its explanation is unchanged and still says the check did not run, not that the invoice is wrong. And the line-level rules — MTB-BR-KSA-50, MTB-BR-KSA-51, MTB-BR-KSA-52, MTB-BR-KSA-DEC-03, MTB-BR-KSA-DEC-04 and MTB-BR-KSA-DEC-05 — report every failing line, each at its own position, where they reported the first and left the reader to find the rest.
2026-09-10, after launch (#38), under the 1.0.0 label. The rounding-and-decimals group, all of it: amounts and rates have published ceilings on their decimal places, counted over the serialised digits rather than the value. The CEN decimals category holds 13 rules and the KSA decimals category 4, as read from the generated index, the KSA category also holding the rate and line-VAT ceilings that had shipped earlier with their neighbouring groups; representative pages are a VAT amount in the document currency (MTB-BR-DEC-13), a line net amount (MTB-BR-DEC-23) and an item net price (MTB-BR-KSA-DEC-05). No rule in this group imposes a rounding mode: the stylesheets count digits and say nothing about how a value was rounded, and so does Mutabiq.
1.0.0
Rule pack 1.0.0 is the first published pack, dated 2026-09-10. It named the rules assembled on the days below and not the rounding-and-decimals group, which #38 added later that day; 1.1.0 above says why the version did not move then. It was assembled from the vendored validation stylesheets the Zakat, Tax and Customs Authority (ZATCA) ships with its SDK, group by group. A rule that mirrors a published assertion carries that assertion’s code in its id — MTB-BR-KSA-33 for BR-KSA-33 — so a reader can search ZATCA’s own output for the code Mutabiq printed, and the rules index headlines each rule by that code; the few that mirror no single assertion — the structural, schema, previous-invoice-hash and QR rules — carry Mutabiq’s own prefix.
2026-09-08. The invoice type code and transaction code, already in the pack when the plan was written, were joined by the identifier group: the seller’s and the buyer’s VAT registration number in the published shape (MTB-BR-KSA-40, MTB-BR-KSA-44) and the scheme an identification is declared under (MTB-BR-KSA-08). The same day shipped part of the dates-and-currency group — the issue date’s width and the currency code list (MTB-BR-CL-03), a date in the future (MTB-BR-KSA-04) and the issue time’s width (MTB-BR-KSA-CL-70) — and all of the document-arithmetic group: the sum of the lines (MTB-BR-CO-10), the VAT total against its breakdown (MTB-BR-CO-14) and the total with VAT against the total before it (MTB-BR-CO-15). The credit note’s reference to the invoice it corrects (MTB-BR-KSA-56) closed the same day; the type code element itself (MTB-BR-04) was among the rules already registered when the plan was written and carries no date of its own. The QR group was registered the same day: those rules decode the QR payload and compare it with the document, and they have no page here, for the reason given below.
2026-09-09. The line-arithmetic group: a simplified invoice’s line VAT against its net and rate (MTB-BR-KSA-50), its line amount with VAT (MTB-BR-KSA-51) and a negative price (MTB-BR-KSA-F-04). The VAT category and rate group, in a pair of batches the same day: a standard-rated breakdown’s VAT against its base and rate (MTB-BR-S-09), a zero-rated line’s rate (MTB-BR-Z-05), an exempt breakdown’s reason (MTB-BR-E-10) and an out-of-scope breakdown standing alone (MTB-BR-O-11), with the published exemption reason codes and texts (MTB-BR-KSA-CL-04). The allowance-and-charge group (MTB-BR-KSA-F-02, MTB-BR-KSA-EN16931-06). The invoice counter’s presence and its digits (MTB-BR-KSA-33, MTB-BR-KSA-34). The previous invoice hash’s presence, media type and length (MTB-BR-KSA-61, MTB-BR-KSA-26, MTB-BR-CL-KSA-13), beside a shape check on the hash, MTB-PIH-01, that has no page for the reason below. The mandatory-field group, as a batch: the seller’s address (MTB-BR-KSA-09), a Saudi buyer’s address (MTB-BR-KSA-63) and the buyer’s name (MTB-BR-KSA-42). The same day removed MTB-VAT-01, an advisory that the standard rate was not the expected figure; it mirrored nothing, and nothing replaces it.
Before 1.0.0
The placeholder version 0.0.0 existed only as a database seed and published nothing.
What the pack deliberately does not do
- Until rule pack 2.0.0 no rule pinned the standard VAT rate to any number: neither of the stylesheets in ZATCA’s SDK 3.0.8 did, and MTB-VAT-01, which advised on the rate, was removed on 2026-09-09 for that reason. ZATCA’s SDK 3.4.8 does pin it — BR-KSA-84 accepts only the rates ZATCA lists for the standard-rated category — and since 2.0.0 MTB-BR-KSA-84 reports any other rate as an error.
- The QR group and the previous-invoice-hash shape check mirror no Schematron clause: no published assertion decodes the QR payload, and the hash’s shape comes from the XML Implementation Standard rather than from the stylesheets. They are registered rules and they report, but there is no clause for a page to quote, so they have no page under the rules index.
- Severities are the published flags. A rule is ERROR where the assertion it mirrors is flagged as an error, and WARNING only where the stylesheet itself says warning, which is the seller-address rule MTB-BR-KSA-09. Where a rule mirrors no clause, ERROR is used only where a clause elsewhere or a measured SDK run shows ZATCA refusing the document: a QR payload that disagrees with the document is WARNING, the hash shape is WARNING, and the tags ZATCA itself issues are INFO. The exception is Mutabiq’s own: MTB-XSD-00, reported when the schema check itself could not run, is ERROR since 1.1.0, so that a document that was not checked is never reported as passed.
- The pack’s rules read a single document. Since 2.1.0 the archive reader also compares, across the files uploaded together, each document’s counter and previous invoice hash with the document before it, as warnings only; a rule that needs a document outside the upload, the counter’s history beyond it, or a certificate is deferred rather than approximated.