informed-decision/docs/evidence/2026-10-11-purpose-image-release/change_guard.py
tegwick e0359bcb6c Prepare purpose image release with bounded custody protocol and owner reviews
Assistant: codex
Assistant-Model: gpt-6.1-sol
Assistant-Session: 01a126e1-76f8-7643-8cf3-e93336539ade
2026-10-11 03:54:35 +02:00

68 lines
3.1 KiB
Python

"""Read-only exact Deployment and admission boundaries; no mutation authority."""
import copy
import hashlib
import json
BASE = 'forgejo.coulomb.social/coulomb/informed-decision@sha256:7f5c6cb29c9f70a026bfe30e72934274ddc69261676cf6d476f81dd32812d173'
CANDIDATE = 'forgejo.coulomb.social/coulomb/informed-decision@sha256:763c36402c8be7cc4c1bd1a61623d1aff9116d52241877425b45a7018cc0883a'
def dependency_projection(configmap, pvc):
if (configmap.get('kind') != 'ConfigMap' or configmap.get('immutable') is not True
or configmap['metadata']['namespace'] != 'informed-decision'
or configmap['metadata']['name'] != 'informed-decision-runtime-6c221878d051'
or set(configmap.get('data', {})) != {'runtime.json'}
or configmap.get('binaryData')):
raise ValueError('unexpected immutable runtime config identity')
if (pvc.get('kind') != 'PersistentVolumeClaim'
or pvc['metadata']['namespace'] != 'informed-decision'
or pvc['metadata']['name'] != 'informed-decision-data'
or pvc.get('status', {}).get('phase') != 'Bound'
or not pvc.get('spec', {}).get('volumeName')):
raise ValueError('unexpected bound PVC custody')
config = projection(configmap)
config.pop('data')
config['canonical_data_sha256'] = hashlib.sha256(json.dumps(
configmap['data'], sort_keys=True, separators=(',', ':')).encode()).hexdigest()
return {'configmap': config, 'pvc': projection(pvc), 'pvc_phase': 'Bound'}
def check_dependencies(configmap, pvc, sealed):
if dependency_projection(configmap, pvc) != sealed:
raise ValueError('runtime config or PVC identity/custody changed')
def projection(value):
value = copy.deepcopy(value)
value.pop('status', None)
for key in ('resourceVersion', 'generation', 'creationTimestamp', 'managedFields'):
value['metadata'].pop(key, None)
for key in ('kubectl.kubernetes.io/last-applied-configuration', 'deployment.kubernetes.io/revision'):
value['metadata'].get('annotations', {}).pop(key, None)
return value
def check_current(current, sealed):
if projection(current) != sealed:
raise ValueError('sealed live UID or configuration changed')
def check_admitted(admitted, sealed):
expected = copy.deepcopy(sealed)
containers = expected['spec']['template']['spec']['containers']
if len(containers) != 1 or containers[0]['name'] != 'informed-decision' or containers[0]['image'] != BASE:
raise ValueError('unexpected baseline container identity')
containers[0]['image'] = CANDIDATE
if projection(admitted) != expected:
raise ValueError('admission changed configuration beyond the sole image pin')
def transport_result(exit_code, output):
import json
try:
value = json.loads(output)
except (ValueError, TypeError):
return {'all_checks_pass': False, 'reason': 'invalid transport result'}
if exit_code != 0 or not isinstance(value, dict) or value.get('all_checks_pass') is not True:
return {'all_checks_pass': False, 'reason': 'read-only preflight refused'}
return value