Check the set before its members
The initial incomplete check calculates hashes only for app.py and dependency.py. When the package adds runtime.json, those hashes remain correct and drift goes unnoticed. The more complete rule first compares the exact name set and rejects the additional member. It also rejects two app.py entries and a../outside.txt name outside the allowed set. The script only reads structure and bytes from original ZIP fixtures; it neither extracts nor executes received content. This is a teaching rule for two flat names with a per-member size limit, not a secure validator for every archive. If a new file is legitimate, reconcile scope and evidence before changing expectations.
Consistency does not authenticate origin
The package with changed dependency.py fails against the original manifest. If the script also replaces the manifest with hashes of the new package, comparison passes. No signature or builder verification occurred: the bundle merely became internally consistent. The SLSA v1.2 reference describes provenance and expectation verification against configured trust, including artifact binding and builder identity. The lab implements no such process and assigns no SLSA level. During supplier receipt, identify the trusted origin of expectations, document scope and who may change it. Storing a digest beside a received package does not prove both correspond to reviewed material. These decisions remain separate from checking whether bytes match a supplied value.
Check what was actually delivered
candidate.zip passes its initial expected-digest comparison. The script deliberately substitutes the source and only then copies it to incoming.zip. The new copy fails comparison, so promoted.zip retains earlier bytes. No race between processes was executed; controlled ordering demonstrates the boundary between checking a source and copying later. A correct copy subsequently passes digest and member-set checks, and os.replace replaces the destination on the same filesystem. This local result is not a distributed transaction, establishes no crash durability and does not itself protect against another writer between checking and use. At a shared target, such access and object identity need their own mechanisms.
Accepted delivery and accepted service
Local promotion ends with runtimeAcceptanceProved=false. This is deliberate: the correct file at the target does not establish that processes loaded it, configuration is compatible or consumers obtain expected outcomes. The release plan needs activation and validation proportionate to the service. RUN should be able to locate trusted expectations, recognize rejection, preserve evidence, escalate drift and recover an identified artifact. The proposed workshop asks for that explanation in English but has not been performed by a human group. Twelve local groups passed twice; specialist review and representative exercises remain outstanding. Separate actions for inputs, manifests and delivery, with owners and checkable criteria for each gap.
python3 content/labs/release-artifacts/run.py --output /tmp/dr-release-admission.json
# Inspect selfConsistencyIsNotTrustedOrigin and checkBeforeCopyDoesNotBindDeliveredBytes.
# No SLSA verifier, signing service or production approval is implemented.A partial manifest accepts listed files and misses runtime.json; the complete rule rejects the unexpected set before promotion.
Common pitfalls
Received manifest as independent reference, hashes as signature, copying as activation or an earlier check as a guarantee of later bytes.
Related topics: Manifest coverage · RUN autonomy
Admission, trust in origin and service acceptance are distinct controls; retain evidence at each boundary and accountable decision owners.
Reference: SLSA v1.2: Build, verifying artifacts · Release management practices 2026-09; scoped GitLab GitHub CodeDeploy and EF Core documentation