Class: Kotoshu::Integrity::Manifest
- Inherits:
-
Object
- Object
- Kotoshu::Integrity::Manifest
- Defined in:
- lib/kotoshu/integrity/manifest.rb
Overview
Parsed view of a content repo's manifest.json.
Format (per TODO.impl/09-integrity-security.md task 1):
{
"version": 1,
"generated_at": "2026-06-25T10:00:00Z",
"resources": {
"en/spelling/index.dic": {
"size": 49568,
"sha256": "ab12...",
"language": "en",
"type": "spelling",
"license": "LGPL/MPL/GPL",
"source": "SCROLL"
}
}
}
Construction:
manifest = Manifest.parse(json_string)
manifest.fetch("en/spelling/index.dic") # => Entry or nil
manifest.verify_content!("en/spelling/index.dic", bytes) # raises on mismatch
Manifest.load(url, http:), returns nil when the manifest 404s (graceful
degradation — see module docs).
Defined Under Namespace
Classes: Entry
Instance Attribute Summary collapse
-
#entries ⇒ Object
readonly
Returns the value of attribute entries.
-
#generated_at ⇒ Object
readonly
Returns the value of attribute generated_at.
-
#version ⇒ Object
readonly
Returns the value of attribute version.
Class Method Summary collapse
-
.load(url, http: Kotoshu::Integrity::NetHTTP) ⇒ Object
Fetch and parse a manifest from a URL.
-
.parse(json) ⇒ Object
Parse a manifest JSON string.
Instance Method Summary collapse
- #empty? ⇒ Boolean
- #fetch(path) ⇒ Object
-
#initialize(entries, version: nil, generated_at: nil) ⇒ Manifest
constructor
A new instance of Manifest.
-
#verify_content!(path, content, url: nil) ⇒ Object
Verify that content for
pathmatches the manifest entry.
Constructor Details
#initialize(entries, version: nil, generated_at: nil) ⇒ Manifest
Returns a new instance of Manifest.
81 82 83 84 85 |
# File 'lib/kotoshu/integrity/manifest.rb', line 81 def initialize(entries, version: nil, generated_at: nil) @entries = entries @version = version @generated_at = generated_at end |
Instance Attribute Details
#entries ⇒ Object (readonly)
Returns the value of attribute entries.
79 80 81 |
# File 'lib/kotoshu/integrity/manifest.rb', line 79 def entries @entries end |
#generated_at ⇒ Object (readonly)
Returns the value of attribute generated_at.
79 80 81 |
# File 'lib/kotoshu/integrity/manifest.rb', line 79 def generated_at @generated_at end |
#version ⇒ Object (readonly)
Returns the value of attribute version.
79 80 81 |
# File 'lib/kotoshu/integrity/manifest.rb', line 79 def version @version end |
Class Method Details
.load(url, http: Kotoshu::Integrity::NetHTTP) ⇒ Object
Fetch and parse a manifest from a URL. Returns nil when the manifest is absent (HTTP 404/410) so callers can fall back to unverified downloads — see module docs. Any other failure (5xx, network error, parse error) raises.
72 73 74 75 76 77 |
# File 'lib/kotoshu/integrity/manifest.rb', line 72 def self.load(url, http: Kotoshu::Integrity::NetHTTP) body = http.get(url) return nil if body.nil? parse(body) end |
.parse(json) ⇒ Object
Parse a manifest JSON string. Returns an empty Manifest if the JSON is parseable but has no resources (caller treats as "no constraints").
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/kotoshu/integrity/manifest.rb', line 45 def self.parse(json) data = JSON.parse(json) entries = {} (data["resources"] || {}).each do |path, fields| entries[path] = Entry.new( path: path, sha256: fields["sha256"], size: fields["size"], language: fields["language"], type: fields["type"], license: fields["license"], source: fields["source"] ) end new(entries, version: data["version"], generated_at: data["generated_at"]) rescue JSON::ParserError => e raise Kotoshu::IntegrityError.new( "manifest", expected: "<valid JSON>", actual: "<parse error: #{e.}>" ) end |
Instance Method Details
#empty? ⇒ Boolean
91 92 93 |
# File 'lib/kotoshu/integrity/manifest.rb', line 91 def empty? @entries.empty? end |
#fetch(path) ⇒ Object
87 88 89 |
# File 'lib/kotoshu/integrity/manifest.rb', line 87 def fetch(path) @entries[path] end |
#verify_content!(path, content, url: nil) ⇒ Object
Verify that content for path matches the manifest entry.
Raises Kotoshu::IntegrityError on mismatch. No-op when the
manifest has no entry for path (returns nil — caller decides
whether to treat absence as failure in strict mode).
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/kotoshu/integrity/manifest.rb', line 99 def verify_content!(path, content, url: nil) entry = @entries[path] return nil unless entry actual = Digest::SHA256.hexdigest(content) unless actual == entry.sha256 raise Kotoshu::IntegrityError.new( path, expected: entry.sha256, actual: actual, url: url ) end true end |