Class: Ksef::UPO::Document
- Inherits:
-
Data
- Object
- Data
- Ksef::UPO::Document
- Defined in:
- lib/ksef/upo/document.rb
Overview
A retrieved UPO, held as the exact bytes received (docs/REFERENCE.md §12).
xml is deliberately a raw String and not a parsed document. The Ministry's XAdES
signature covers the octets, so anything that re-serialises them — even a lossless
round-trip through an XML library — risks producing a document that no longer
verifies. Parse a copy if you need to read it; archive this.
source records where the bytes came from, because the two routes have different
properties worth knowing after the fact: :storage is the unmetered pre-signed link
(§14.2), :api the metered fallback.
Instance Attribute Summary collapse
-
#published_hash ⇒ Object
readonly
Returns the value of attribute published_hash.
-
#source ⇒ Object
readonly
Returns the value of attribute source.
-
#xml ⇒ Object
readonly
Returns the value of attribute xml.
Instance Method Summary collapse
- #inspect ⇒ Object
-
#sha256 ⇒ Object
SHA-256 of the bytes held, Base64 — the same form
x-ms-meta-hashuses. - #size ⇒ Object
-
#to_s ⇒ Object
Deliberately not the document: a UPO is a few kilobytes of XML, and putting it in a log line or an exception message helps nobody.
-
#validate ⇒ Validation
Checks the document against the bundled schema — a diagnostic, never a gate (§14.3).
-
#verifiable? ⇒ Boolean
Whether there is anything to check against at all.
-
#verified? ⇒ Boolean
True only when a hash was published and the bytes match it.
- #verify! ⇒ self
-
#write(path) ⇒ Integer
Writes the bytes untouched.
Instance Attribute Details
#published_hash ⇒ Object (readonly)
Returns the value of attribute published_hash
15 16 17 |
# File 'lib/ksef/upo/document.rb', line 15 def published_hash @published_hash end |
#source ⇒ Object (readonly)
Returns the value of attribute source
15 16 17 |
# File 'lib/ksef/upo/document.rb', line 15 def source @source end |
#xml ⇒ Object (readonly)
Returns the value of attribute xml
15 16 17 |
# File 'lib/ksef/upo/document.rb', line 15 def xml @xml end |
Instance Method Details
#inspect ⇒ Object
68 69 70 71 |
# File 'lib/ksef/upo/document.rb', line 68 def inspect state = verifiable? ? verified?.to_s : "unverifiable" "#<data Ksef::UPO::Document size=#{size} source=#{source.inspect} verified=#{state}>" end |
#sha256 ⇒ Object
SHA-256 of the bytes held, Base64 — the same form x-ms-meta-hash uses.
17 |
# File 'lib/ksef/upo/document.rb', line 17 def sha256 = Ksef::Crypto::Digest.of(xml).base64 |
#size ⇒ Object
19 |
# File 'lib/ksef/upo/document.rb', line 19 def size = xml.bytesize |
#to_s ⇒ Object
Deliberately not the document: a UPO is a few kilobytes of XML, and putting it in a log line or an exception message helps nobody. DESIGN.md §4.5 forbids full invoice payloads at default log level, and the same reasoning applies here.
66 |
# File 'lib/ksef/upo/document.rb', line 66 def to_s = "#<Ksef::UPO::Document #{size} bytes from #{source}>" |
#validate ⇒ Validation
Checks the document against the bundled schema — a diagnostic, never a gate (§14.3). Archive the bytes regardless of what this says; see Validator for why there is no raising counterpart.
51 |
# File 'lib/ksef/upo/document.rb', line 51 def validate = Validator.validate(xml) |
#verifiable? ⇒ Boolean
Whether there is anything to check against at all. The pre-signed storage link
publishes x-ms-meta-hash; the metered API route publishes nothing.
Split from #verified? rather than folded into it as a third state: "no hash was published" and "the hash did not match" call for completely different responses, and a predicate that answers both with one value invites treating an unverifiable document as a corrupt one.
28 |
# File 'lib/ksef/upo/document.rb', line 28 def verifiable? = !published_hash.nil? |
#verified? ⇒ Boolean
True only when a hash was published and the bytes match it. False for an unverifiable document too — ask #verifiable? to tell the two apart.
32 |
# File 'lib/ksef/upo/document.rb', line 32 def verified? = verifiable? && sha256 == published_hash |
#verify! ⇒ self
36 37 38 39 40 41 42 43 44 |
# File 'lib/ksef/upo/document.rb', line 36 def verify! return self unless verifiable? && !verified? raise IntegrityError, "The UPO fetched from #{source} does not match the hash the server published: " \ "expected #{published_hash}, got #{sha256} over #{size} bytes. This is a corrupted " \ "transfer, not a bad request — fetch it again. Do not archive these bytes as proof " \ "of receipt (docs/REFERENCE.md §14.2)." end |
#write(path) ⇒ Integer
Writes the bytes untouched. Binary mode on purpose: this must not pick up a newline translation or a re-encode on the way to disk, or the archived file stops matching what the Ministry signed.
59 60 61 |
# File 'lib/ksef/upo/document.rb', line 59 def write(path) File.binwrite(path, xml) end |