Class: Shojiku::DocumentArtifact

Inherits:
Object
  • Object
show all
Defined in:
lib/shojiku/artifact.rb

Overview

A rendered (and possibly signed) document.

The application sees bytes and metadata — never a layout-engine internal, and never a handle it has to free. Freeing is the binding's job and it is already done by the time this object exists.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(bytes:, diagnostics:, client:, page_count: nil, origin: :loaded) ⇒ DocumentArtifact

origin defaults to the LEAST privileged value, not the most: every internal path states it explicitly, so the default only ever applies to an artifact somebody built by hand — which is bytes handed over whole, and must not become signable under a lockdown by omission.



40
41
42
43
44
45
46
# File 'lib/shojiku/artifact.rb', line 40

def initialize(bytes:, diagnostics:, client:, page_count: nil, origin: :loaded)
  @bytes = bytes
  @page_count = page_count
  @diagnostics = diagnostics
  @client = client
  @origin = origin
end

Instance Attribute Details

#bytesObject (readonly)

The PDF, as binary. Always ASCII-8BIT: PDF bytes are not text and tagging them as any character encoding is how a document gets corrupted by a well-meaning transcode on the way to disk.



13
14
15
# File 'lib/shojiku/artifact.rb', line 13

def bytes
  @bytes
end

#diagnosticsObject (readonly)

Returns the value of attribute diagnostics.



21
22
23
# File 'lib/shojiku/artifact.rb', line 21

def diagnostics
  @diagnostics
end

#originObject (readonly)

Where this document came from, which is what a strict client signs on:

  • :rendered — laid out from a template the configured root resolved,
  • :source — laid out from template bytes the application supplied,
  • :loaded — bytes the application supplied whole (Client#artifact).

Only the first is signable under a Lockdown: in the other two the provenance of what gets signed is the application's rather than the deployment's, which is the distinction strict exists to draw. Signing inherits the origin of what it signed — appending a revision does not launder where the document came from. Verification is never restricted.



34
35
36
# File 'lib/shojiku/artifact.rb', line 34

def origin
  @origin
end

#page_countObject (readonly)

How many pages the engine laid out. nil for an artifact that was signed rather than rendered — signing appends a revision to bytes it never measured, and a zero there would read as "a document with no pages".



19
20
21
# File 'lib/shojiku/artifact.rb', line 19

def page_count
  @page_count
end

Instance Method Details

#loaded?Boolean

Whether these bytes were handed over whole rather than laid out here.

Returns:

  • (Boolean)


49
50
51
# File 'lib/shojiku/artifact.rb', line 49

def loaded?
  @origin == :loaded
end

#sign(provider) ⇒ Object

Signs this document, returning a Result carrying the signed artifact. The signed bytes begin with these bytes byte for byte: signing appends a revision, it never rewrites what was there.



68
69
70
# File 'lib/shojiku/artifact.rb', line 68

def sign(provider)
  @client.sign(self, provider)
end

#sizeObject



61
62
63
# File 'lib/shojiku/artifact.rb', line 61

def size
  @bytes.bytesize
end

#verify(anchors: nil, anchors_pem: nil) ⇒ Object

Verifies this document against caller-supplied trust anchors, returning a Result carrying a VerificationReport.



74
75
76
# File 'lib/shojiku/artifact.rb', line 74

def verify(anchors: nil, anchors_pem: nil)
  @client.verify(self, anchors: anchors, anchors_pem: anchors_pem)
end

#write(path) ⇒ Object

Writes the document. Binary mode explicitly — a PDF contains NUL and every other byte value, and text mode would translate line endings on Windows.



56
57
58
59
# File 'lib/shojiku/artifact.rb', line 56

def write(path)
  File.binwrite(path, @bytes)
  path
end