Module: Ksef::FA3::AttachmentChecks
Overview
Tier 1a's checks on the invoice attachment (docs/REFERENCE.md §8.7).
Mixed into ModelValidator. It exists because the attachment shipped without it and the
gap was not cosmetic: Invoice#attachment is a public constructor field that tier 1a never
looked at, so #errors raised rather than reported for two shapes — a value that is
not an Attachment at all (NoMethodError), and a U+0000 anywhere in the attachment's
nine text fields (a bare ArgumentError from libxml2, outside this gem's error
hierarchy). FieldChecks predicted the second in its own comments; the attachment simply
never reached the guard.
The contract this restores is CLAUDE.md's: #errors reports rather than raises, and
what tier 1a passes, #to_xml can serialise.
What is deliberately not checked
Cell contents against their column's Typ. A column declared dec whose cells hold
"nie liczba" is XSD-clean, silent to every tier, and stays that way — because rows are
ragged by design (§8.7), a cell cannot be reliably associated with a column at all. A
one-cell heading row belongs to no column, so the association is undecidable in general
rather than merely unimplemented. Recorded here so the next reader does not mistake it for
an oversight.
Upper cardinality bounds — 20 columns, 20 cells, 1000 rows, 1000 blocks. Tier 2 reports every one of them against the schema, and restating a bound the XSD already enforces is what DESIGN.md §7.1 forbids.
Constant Summary
Constants included from FieldChecks
FieldChecks::BUYER_ID_TEXT, FieldChecks::COLLAPSE, FieldChecks::FORBIDDEN_IN_XML, FieldChecks::LONG_TEXT, FieldChecks::SHORT_TEXT