"""Adoption and routine-promotion boundaries are checked without cluster access.""" import importlib.util from pathlib import Path import copy import pytest import yaml ROOT=Path(__file__).resolve().parents[1] def load(name): spec=importlib.util.spec_from_file_location(name,ROOT/'scripts'/f'{name}.py') mod=importlib.util.module_from_spec(spec);spec.loader.exec_module(mod);return mod def test_render_exact_reviewed_set_and_no_jobs_or_secrets(): render=load('render_gitops') assert render.render()==(ROOT/'k8s/gitops/runtime.yaml').read_text() docs=list(yaml.safe_load_all(render.render())) assert len(docs)==9 assert {d['kind'] for d in docs}=={'Deployment','ConfigMap','Service'} assert all(d['metadata']['namespace']=='activity-core' for d in docs) worker=next(d for d in docs if d['metadata']['name']=='actcore-worker') mounts=worker['spec']['template']['spec']['containers'][0]['volumeMounts'] assert any(m.get('subPath')=='entrypoint' and m['name']=='backup-verified' for m in mounts) def test_image_workflow_publishes_commit_tag_and_digest(): text=(ROOT/'.forgejo/workflows/image.yaml').read_text() assert ':latest' not in text and ':git-${REF}' in text assert '${REF}.tar.gz' in text and '--target test' in text assert 'RepoDigests' in text def test_build_inputs_are_pinned(): text=(ROOT/'Dockerfile').read_text() assert text.count('python:3.12-slim@sha256:')==2 assert 'uv==0.5.9' in text and '--frozen' in text def promotion(): from datetime import datetime,timezone before=list(yaml.safe_load_all((ROOT/'k8s/gitops/runtime.yaml').read_text())) after=copy.deepcopy(before) worker=next(d for d in after if d['metadata']['name']=='actcore-worker') container=worker['spec']['template']['spec']['containers'][0] container.update(image='forgejo.coulomb.social/coulomb/activity-core@sha256:'+'a'*64,imagePullPolicy='IfNotPresent') evidence=dict(schema_version=1,identity_admitted=True,authority='ACTIVITY-WP-0041-image-only-v1',checks='pass',review_result='pass',reviewer='independent-ci',producer='build-ci',candidate_commit='a'*40,rollback_commit='b'*40,healthy_since='2026-09-26T00:00:00Z',observed_at='2026-09-27T01:00:00Z',argo_synced=True,argo_healthy=True) return before,after,evidence,datetime(2026,9,27,1,tzinfo=timezone.utc) def test_admits_only_digest_release_after_soak(): assert load('check_gitops_promotion').validate(*promotion())['deployments']==['actcore-worker'] @pytest.mark.parametrize('key,value',[('identity_admitted',False),('checks','fail'),('reviewer','build-ci'),('healthy_since','2026-09-27T00:00:00Z'),('observed_at','2026-09-26T01:00:00Z'),('argo_healthy',False),('rollback_commit','not-a-sha')]) def test_refuses_missing_release_guards(key,value): before,after,evidence,now=promotion();evidence[key]=value with pytest.raises(ValueError):load('check_gitops_promotion').validate(before,after,evidence,now) @pytest.mark.parametrize('change',['command','resources','tag','inventory']) def test_refuses_authority_expansion(change): before,after,evidence,now=promotion() worker=next(d for d in after if d['metadata']['name']=='actcore-worker') c=worker['spec']['template']['spec']['containers'][0] if change=='command':c['command']=['sh'] elif change=='resources':c['resources']={'requests':{'cpu':'2'}} elif change=='tag':c['image']='forgejo.coulomb.social/coulomb/activity-core:latest' else:after.pop() with pytest.raises(ValueError):load('check_gitops_promotion').validate(before,after,evidence,now) def test_frontend_projection_checks_content_and_pin(tmp_path): renderer=load('render_gitops') cm=next(d for d in yaml.safe_load_all(renderer.render()) if d['metadata']['name']=='actcore-external-activity-definitions') for name,body in cm['data'].items(): if name.startswith('frontend-patterns-'): (tmp_path/name).write_text(body) renderer.verify_frontend(tmp_path) (tmp_path/'frontend-patterns-daily.md').write_text('tampered') with pytest.raises(ValueError): renderer.verify_frontend(tmp_path) def test_retention_projection_is_pinned_and_mounted(tmp_path): renderer=load('render_gitops') docs=list(yaml.safe_load_all(renderer.render())) cm=next(d for d in docs if d['metadata']['name']=='actcore-ops-service-inventory') source=tmp_path/'prune.py';source.write_text(cm['data']['forgejo_package_prune.py']) renderer.verify_platform(source) worker=next(d for d in docs if d['metadata']['name']=='actcore-worker') mounts=worker['spec']['template']['spec']['containers'][0]['volumeMounts'] assert any(m.get('subPath')=='forgejo_package_prune.py' and m['readOnly'] is True for m in mounts) source.write_text('tampered') with pytest.raises(ValueError):renderer.verify_platform(source)