Certify alpha8 production and rollback tuples

This commit is contained in:
2026-07-20 01:30:35 -07:00
parent e0c9e0db94
commit 252e5238ca
15 changed files with 1682 additions and 149 deletions

View File

@@ -32,6 +32,26 @@ module OpenCodeCompat
source_image
upstream_base
].freeze
EVIDENCE_REFERENCE_KEYS = %w[path sha256].freeze
NULLABLE_COMMIT_KEYS = %w[build_source_commit].freeze
EVIDENCE_RUNTIME_KEY_MAP = {
"custom_opencode_source_commit" => "source_commit"
}.freeze
EVIDENCE_RUNTIME_COORDINATE_KEYS = %w[
application_image
application_image_id
base_image
build_source_commit
docker_image_id
image
provenance_strength
registry_ref
reported_version
source_commit
source_image
tag_provenance
upstream_base
].freeze
def initialize(root:, manifest_path: File.join(root, "manifests/runtime-tuples.json"))
@root = File.realpath(root)
@@ -317,21 +337,23 @@ module OpenCodeCompat
end
validate_timestamp!(certified_at, "#{label} certification timestamp")
raise PromotionError, "#{label} certification requires at least one evidence file" if evidence.empty?
raise PromotionError, "#{label} certification evidence files must be unique" unless evidence.uniq == evidence
consumer_commit = tuple.fetch("consumer_commit")
normalized_evidence = evidence.map do |reference|
validate_evidence!(
reference,
consumer: consumer,
profile: profile,
consumer_commit: consumer_commit,
tuple: tuple,
status: status,
certified_at: certified_at,
tuple_fingerprint: expected_fingerprint,
label: label
)
end
evidence_paths = normalized_evidence.map { |reference| reference.fetch("path") }
unless evidence_paths.uniq == evidence_paths
raise PromotionError, "#{label} certification evidence files must be unique"
end
{
"status" => status,
@@ -347,7 +369,13 @@ module OpenCodeCompat
raise PromotionError, "#{label} tuple has invalid or stale certification metadata"
end
validate_supplied_certification!(
references = Array(certification["evidence"])
unless references.all? { |reference| structured_evidence_reference?(reference) }
raise PromotionError,
"#{label} recorded certification evidence must use hash-bound {path, sha256} references"
end
validated = validate_supplied_certification!(
certification,
consumer: consumer,
profile: profile,
@@ -355,23 +383,24 @@ module OpenCodeCompat
expected_fingerprint: expected_fingerprint,
label: label
)
unless certification["evidence"] == validated["evidence"]
raise PromotionError, "#{label} recorded certification evidence references are not canonical"
end
end
def validate_evidence!(
reference,
consumer:,
profile:,
consumer_commit:,
tuple:,
status:,
certified_at:,
tuple_fingerprint:,
label:
)
unless reference.is_a?(String) && !reference.empty?
raise PromotionError, "#{label} evidence references must be non-empty strings"
end
reference_path, expected_sha256 = evidence_reference_parts!(reference, label)
relative = Pathname.new(reference).cleanpath
relative = Pathname.new(reference_path).cleanpath
if relative.absolute? || relative.each_filename.first != "evidence"
raise PromotionError, "#{label} evidence must be a repository-relative path under evidence/"
end
@@ -383,14 +412,23 @@ module OpenCodeCompat
raise PromotionError, "#{label} evidence resolves outside evidence/"
end
document = parse_json(File.read(real_path), relative.to_s)
contents = File.binread(real_path)
actual_sha256 = "sha256:#{Digest::SHA256.hexdigest(contents)}"
if expected_sha256 && expected_sha256 != actual_sha256
raise PromotionError,
"#{label} evidence #{relative} has sha256=#{actual_sha256.inspect}; " \
"expected #{expected_sha256.inspect}"
end
document = parse_json(contents, relative.to_s)
unless document.is_a?(Hash) && document["schema_version"] == 1
raise PromotionError, "#{label} evidence #{relative} must use schema_version 1"
end
validate_immutable_fields!(document, "#{label} evidence #{relative}")
expected = {
"consumer" => consumer,
"profile" => profile,
"consumer_commit" => consumer_commit,
"consumer_commit" => tuple.fetch("consumer_commit"),
"status" => status,
"certified_at" => certified_at,
"tuple_sha256" => tuple_fingerprint
@@ -402,14 +440,20 @@ module OpenCodeCompat
"#{label} evidence #{relative} has #{key}=#{document[key].inspect}; expected #{value.inspect}"
end
relative.to_s
validate_evidence_tuple_details!(document, tuple, "#{label} evidence #{relative}")
{
"path" => relative.to_s,
"sha256" => actual_sha256
}
rescue Errno::ENOENT
raise PromotionError, "#{label} evidence does not exist: #{reference}"
raise PromotionError, "#{label} evidence does not exist: #{reference_path || reference}"
end
def validate_tuple!(tuple, label)
raise PromotionError, "#{label} tuple must be an object" unless tuple.is_a?(Hash)
validate_immutable_fields!(tuple, label)
validate_full_commit!(tuple["consumer_commit"], "#{label} consumer commit")
validate_client!(tuple["opencode_ruby"], "#{label} opencode_ruby", required: true)
validate_client!(tuple["opencode_rails"], "#{label} opencode_rails", required: false)
@@ -447,8 +491,10 @@ module OpenCodeCompat
raise PromotionError, "#{label} #{key} must be an immutable image@sha256 digest, not a tag"
end
exact_execution_coordinate = true if %w[image registry_ref].include?(key)
elsif key == "source_commit"
validate_full_commit!(value, "#{label} source commit")
elsif key.end_with?("_commit")
next if value.nil? && NULLABLE_COMMIT_KEYS.include?(key)
validate_full_commit!(value, "#{label} #{key.tr('_', ' ')}")
end
end
@@ -463,6 +509,154 @@ module OpenCodeCompat
(key.end_with?("_ref") && key != "tag_provenance")
end
def structured_evidence_reference?(reference)
reference.is_a?(Hash) && reference.keys.sort == EVIDENCE_REFERENCE_KEYS
end
def evidence_reference_parts!(reference, label)
if reference.is_a?(String)
unless !reference.empty?
raise PromotionError, "#{label} evidence references must contain a non-empty path"
end
return [reference, nil]
end
unless structured_evidence_reference?(reference)
raise PromotionError,
"#{label} evidence references must be a path string or an object containing only path and sha256"
end
path = reference["path"]
sha256 = reference["sha256"]
unless path.is_a?(String) && !path.empty?
raise PromotionError, "#{label} evidence references must contain a non-empty path"
end
unless sha256.is_a?(String) && sha256.match?(DIGEST)
raise PromotionError, "#{label} evidence reference sha256 must be an exact sha256 digest"
end
[path, sha256]
end
def validate_evidence_tuple_details!(document, tuple, label)
if document.key?("consumer_tree")
expected_tree = tuple["consumer_tree"]
unless expected_tree && document["consumer_tree"] == expected_tree
raise PromotionError,
"#{label} has consumer_tree=#{document['consumer_tree'].inspect}; " \
"expected #{expected_tree.inspect}"
end
end
validate_evidence_clients!(document["clients"], tuple, label) if document.key?("clients")
validate_evidence_runtime!(document["runtime"], tuple.fetch("runtime"), label) if document.key?("runtime")
end
def validate_evidence_clients!(clients, tuple, label)
unless clients.is_a?(Hash)
raise PromotionError, "#{label} clients must be an object"
end
%w[opencode_ruby opencode_rails].each do |client_name|
next unless clients.key?(client_name)
evidence_client = clients[client_name]
tuple_client = tuple[client_name]
if evidence_client.nil?
unless tuple_client.nil?
raise PromotionError, "#{label} #{client_name} is null but the tuple declares a client"
end
next
end
unless evidence_client.is_a?(Hash) && tuple_client.is_a?(Hash)
raise PromotionError, "#{label} #{client_name} must match the tuple client"
end
unless evidence_client["version"].is_a?(String) && !evidence_client["version"].empty?
raise PromotionError, "#{label} #{client_name} must include a non-empty version"
end
commits = %w[commit git_commit].filter_map do |key|
evidence_client[key] if evidence_client.key?(key)
end
if commits.empty?
raise PromotionError, "#{label} #{client_name} must include commit or git_commit"
end
compare_evidence_coordinate!(
evidence_client["version"],
tuple_client["version"],
"#{label} #{client_name}.version"
)
commits.each do |commit|
compare_evidence_coordinate!(commit, tuple_client["git_commit"], "#{label} #{client_name}.commit")
end
end
end
def validate_evidence_runtime!(runtime, tuple_runtime, label)
unless runtime.is_a?(Hash)
raise PromotionError, "#{label} runtime must be an object"
end
runtime.each do |key, value|
tuple_key = EVIDENCE_RUNTIME_KEY_MAP.fetch(key, key)
next unless EVIDENCE_RUNTIME_COORDINATE_KEYS.include?(tuple_key)
unless tuple_runtime.key?(tuple_key)
raise PromotionError, "#{label} runtime.#{key} is not present in the certified tuple"
end
compare_evidence_coordinate!(value, tuple_runtime[tuple_key], "#{label} runtime.#{key}")
end
end
def compare_evidence_coordinate!(actual, expected, label)
return if actual == expected
raise PromotionError, "#{label}=#{actual.inspect}; expected #{expected.inspect}"
end
def validate_immutable_fields!(value, label, path = [])
case value
when Hash
value.each do |key, child|
field_path = path + [key]
field_label = "#{label} #{field_path.join('.')}"
if key == "commit" || key.end_with?("_commit") || key == "head_sha" || key.end_with?("_head_sha")
unless child.nil? && NULLABLE_COMMIT_KEYS.include?(key)
validate_full_commit!(child, field_label)
end
elsif key == "tree" || key.end_with?("_tree")
validate_full_oid!(child, field_label)
elsif key == "annotated_tag_object" || key.end_with?("_tag_object")
validate_full_oid!(child, field_label)
elsif digest_field?(key)
unless child.is_a?(String) && child.match?(DIGEST)
raise PromotionError, "#{field_label} must be an exact sha256 digest"
end
end
validate_immutable_fields!(child, label, field_path)
end
when Array
value.each_with_index { |child, index| validate_immutable_fields!(child, label, path + [index]) }
end
end
def digest_field?(key)
key == "sha256" || key.end_with?("_sha256") ||
key == "digest" || key.end_with?("_digest") ||
key == "docker_image_id" || key.end_with?("_image_id")
end
def validate_full_oid!(value, label)
return if value.is_a?(String) && value.match?(FULL_COMMIT)
raise PromotionError, "#{label} must be a full 40-character lowercase Git object ID"
end
def validate_full_commit!(value, label)
return if value.is_a?(String) && value.match?(FULL_COMMIT)