Verify image publication without Python and bind local managed package
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s
Build and Publish Container Image / build-and-push (push) Successful in 58s

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a140c4-354a-7823-8f0d-8f717397f786
This commit is contained in:
tegwick 2026-10-16 19:52:09 +02:00
parent 0a05383195
commit 84c78e072c
4 changed files with 121 additions and 8 deletions

View file

@ -33,17 +33,33 @@
"kid" "kid"
], ],
"proposed_catalog_workload_reference": { "proposed_catalog_workload_reference": {
"name": "flex-auth", "rapp_id": "rapp-flex-auth-secrets-engine",
"declaration_ref": "access-engine/tenancy.yaml#/workload_identity", "name": "flex-auth-secrets-engine",
"deployable": "flex-auth-secrets-engine",
"declaration_ref": "rapp-flex-auth-secrets-engine/declarations/rapp.yaml",
"declaration_commit": "d52f811ed5ec0be27c9c367e71d476125b3228be",
"exact_binding": "system:serviceaccount:flex-auth:flex-auth-secrets-engine", "exact_binding": "system:serviceaccount:flex-auth:flex-auth-secrets-engine",
"resolution": "unknown until owner custody and managed-package admission; do not mark resolvable merely from source binding" "resolution": "Local source tuple resolves draft. This is an owner-proposed catalog pointer only; actual Platform catalog/custody is unchanged and remains pending admission."
}, },
"key_created_or_admitted": false "key_created_or_admitted": false
}, },
"managed_package_limit": { "managed_package_limit": {
"rapp_declaration_ref": null, "rapp_declaration_ref": "rapp-flex-auth-secrets-engine/declarations/rapp.yaml",
"status": "Existing managed-deployable migration debt remains unknown under security-zones_v0.1 \u00a76; no matching authoritative rapp declaration was established. Existing source tenancy declaration supplies owner identity binding but cannot substitute for managed-package admission.", "status": "Canonical local package declaration now exists at exact recorded commit/hash. Repo Manager resolves the exact tuple/deployable under /home/worsch with ownership_repo access-engine and readiness draft. Existing unrelated rapp-forgejo declaration_missing remains visible. This source resolution does not claim central registration, private source access/placement, reef admission, signer custody, native deployment or independent consumer trust.",
"no_fiction": "Do not invent a rapp tuple or describe this Helm-managed Deployment as an independent operational unit to bypass the rule." "no_fiction": "Do not invent a rapp tuple or describe this Helm-managed Deployment as an independent operational unit to bypass the rule.",
"owner_selected_reference": {
"rapp_id": "rapp-flex-auth-secrets-engine",
"name": "flex-auth-secrets-engine",
"deployable": "flex-auth-secrets-engine",
"declaration_ref": "rapp-flex-auth-secrets-engine/declarations/rapp.yaml",
"declaration_commit": "d52f811ed5ec0be27c9c367e71d476125b3228be",
"declaration_tree": "d4fbad71bdc8ef870603526ccd1f53195d0322af",
"declaration_sha256": "0b722431bc5162dd86f72b15f12424e149aca8f2a8790adf2c57e8511ea73b4c",
"local_resolver_root": "/home/worsch",
"local_resolution": "resolved",
"readiness_state": "draft",
"scope": "Committed canonical local declaration and exact local source resolution only; no central/private read-placement, reef binding, custody, live deployment or consumer trust admission."
}
}, },
"unchanged_limits": [ "unchanged_limits": [
"tenancy and zones grades are unchanged", "tenancy and zones grades are unchanged",

View file

@ -0,0 +1,64 @@
"""Execute publisher against a Docker metadata fixture with no Python on PATH."""
import os
from pathlib import Path
import subprocess
import tempfile
import unittest
ROOT = Path(__file__).resolve().parents[1]
REVISION = '0a05383195213e7eaacd08388ce1d7892ce756df'
DIGEST = 'sha256:' + 'a'*64
DOCKER = '''#!/bin/bash
set -eu
if [[ "$1" == image && "$2" == inspect ]]; then
[[ "${CASE:-}" != inspect_error ]] || exit 29
if [[ "$4" == *RepoDigests* ]]; then
image=${5%:main-*}
case "${CASE:-}" in
missing) printf '%s@sha256:%064d\\n' other/repository 0 ;;
duplicate) printf '%s@%s\\n%s@%s\\n' "$image" "$DIGEST" "$image" "$DIGEST" ;;
malformed) printf '%s@sha256:BAD\\n' "$image" ;;
prefix_collision) printf '%s-extra@%s\\n' "$image" "$DIGEST" ;;
mismatch) if [[ "$image" == */access-engine ]]; then printf '%s@sha256:%064d\\n' "$image" 0; else printf '%s@%s\\n' "$image" "$DIGEST"; fi ;;
*) printf '%s@%s\\n' "$image" "$DIGEST" ;;
esac
else
if [[ "${CASE:-}" == wrong_revision ]]; then printf '%040d\\n' 0; else printf '%s\\n' "$REVISION"; fi
fi
fi
'''
class PublisherMetadataChecks(unittest.TestCase):
def invoke(self, case='', mode='legacy'):
with tempfile.TemporaryDirectory() as tmp:
docker = Path(tmp)/'docker'
docker.write_text(DOCKER)
docker.chmod(0o755)
env = {'PATH':tmp, 'CASE':case, 'REVISION':REVISION, 'DIGEST':DIGEST}
return subprocess.run(['/bin/bash',str(ROOT/'tools/publish-runtime-images.sh'),
REVISION,mode,tmp],env=env,capture_output=True,text=True)
def test_existing_bash_docker_only_runner_and_exact_receipt(self):
for mode,count in [('legacy',1),('paired',2)]:
result = self.invoke(mode=mode)
self.assertEqual(result.returncode,0,result.stderr)
self.assertIn('manifest_digest='+DIGEST,result.stdout)
self.assertIn('verified_repositories='+str(count),result.stdout)
def test_missing_duplicate_malformed_foreign_revision_and_inspect_failure_refuse(self):
for case in ('missing','duplicate','malformed','prefix_collision','wrong_revision','inspect_error'):
with self.subTest(case=case):
result = self.invoke(case)
self.assertNotEqual(result.returncode,0)
self.assertNotIn('publication mode=',result.stdout)
def test_existing_paired_digest_equality_is_preserved(self):
result = self.invoke('mismatch','paired')
self.assertNotEqual(result.returncode,0)
self.assertIn('manifest digests differ',result.stderr)
self.assertNotIn('publication mode=',result.stdout)
if __name__ == '__main__':
unittest.main()

View file

@ -27,8 +27,22 @@ done
digests=() digests=()
for image in "${images[@]}"; do for image in "${images[@]}"; do
docker pull "$image:main-$short" docker pull "$image:main-$short"
raw=$(docker image inspect --format '{{json .RepoDigests}}' "$image:main-$short") # The existing container-build runner supplies Bash and Docker, not Python.
digest=$(printf '%s' "$raw" | python3 -c 'import json,re,sys; x=json.load(sys.stdin); assert isinstance(x,list); matches=[v.removeprefix(sys.argv[1]+"@") for v in x if isinstance(v,str) and v.startswith(sys.argv[1]+"@")]; assert len(matches)==1 and re.fullmatch(r"sha256:[a-f0-9]{64}",matches[0]); print(matches[0])' "$image") # Capture inspect first so command failure is not hidden by process substitution.
raw=$(docker image inspect --format '{{range .RepoDigests}}{{println .}}{{end}}' "$image:main-$short")
digest=""
matches=0
while IFS= read -r reference; do
if [[ "$reference" == "$image@"* ]]; then
candidate=${reference#"$image@"}
[[ "$candidate" =~ ^sha256:[a-f0-9]{64}$ ]] || { echo 'invalid published registry manifest digest' >&2; exit 1; }
digest=$candidate
matches=$((matches + 1))
fi
done <<< "$raw"
[[ "$matches" == 1 ]] || { echo 'expected exactly one published repository digest' >&2; exit 1; }
actual_revision=$(docker image inspect --format '{{index .Config.Labels "org.opencontainers.image.revision"}}' "$image:main-$short")
[[ "$actual_revision" == "$revision" ]] || { echo 'published image revision differs from exact source' >&2; exit 1; }
digests+=("$digest") digests+=("$digest")
done done
if [[ "$mode" == paired && "${digests[0]}" != "${digests[1]}" ]]; then if [[ "$mode" == paired && "${digests[0]}" != "${digests[1]}" ]]; then

View file

@ -283,3 +283,22 @@ process contention/crash release, capacity/prefix/restart and ENOSPC/fsync failu
proofs are part of the owner package. No new service, live mount, deletion or proofs are part of the owner package. No new service, live mount, deletion or
custody grant; exact published successor, new PVC/PV retention/managed-package custody grant; exact published successor, new PVC/PV retention/managed-package
owner disposition and independent consumer admission remain prerequisites. owner disposition and independent consumer admission remain prerequisites.
2026-10-16 owner package extraction record: canonical local package
`rapp-flex-auth-secrets-engine` now exists at commit
`d52f811ed5ec0be27c9c367e71d476125b3228be`, tree
`d4fbad71bdc8ef870603526ccd1f53195d0322af`; authoritative declaration
`declarations/rapp.yaml` SHA256 `0b722431bc5162dd86f72b15f12424e149aca8f2a8790adf2c57e8511ea73b4c`.
Repo Manager exact local resolution under `/home/worsch` returns
`rapp-flex-auth-secrets-engine` / workload `flex-auth-secrets-engine` /
deployable `flex-auth-secrets-engine`, ownership `access-engine`, readiness
`draft`. The retained lifecycle PDP is the only rollback boundary claimed;
tenant/user/canary and retired `rapp-secrets-engine` remain excluded. Normative
focused family validation passes; existing unrelated global rapp-forgejo error
and reef projection warning remain visible. Package extraction keeps source
`2b064eee510640224274ccdc7cefceb1ae13162e` and current image
`sha256:05a03a8790c2210c48ea92391441c77ddf640d0cd32f5ec09838f5393171fcbd`
unchanged. Exact local source resolution is no central/private read-placement,
reef binding, custody, native rollout or consumer trust admission. Future signer
image/config adoption remains separate. T06 remains `progress`; no second work
item duplicates this bounded dependency.