approval-engine/tests/test_deploy_manifest.py
tegwick fec4eaeb1b Hold the pinned image against the repository's schema
Schema v4 gave the deployment a silent drift surface: the pinned pair is
self-consistent, migrating to 3 and serving 3, while this repository has
moved to 4. That reads as healthy, which makes it worse than an error —
the failure is the assumption that the deployment records approver
principal type.

Document v4 in storage-operations, state in the deploy runbook that the
pin predates it, and add a test that requires the statement whenever the
release record's schema version differs from this repository's. Verified
to fail when the acknowledgement is removed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HyybaE7DUXrWYrhbnESCTe

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 1275879@bnt-lap001
Assistant-Session: eb464208-f821-41b2-bc5a-a6c33d92a8ad
2026-09-09 14:38:21 +02:00

112 lines
4.5 KiB
Python

"""Mechanical checks on the deployment manifest's image pinning.
These exist because the manifest drifted in a way review did not catch: the
release was published and pinned, while three documents went on instructing an
operator to replace a placeholder that no longer existed. A pin is exactly the
kind of property a test can hold and prose cannot.
"""
from __future__ import annotations
import re
from pathlib import Path
from approval_engine.store import LATEST_SCHEMA_VERSION
ROOT = Path(__file__).resolve().parents[1]
MANIFEST = ROOT / "deploy" / "approval-engine.yaml"
RELEASE_RECORD = ROOT / "docs" / "image-scan-2026-09-06.md"
DEPLOY_README = ROOT / "deploy" / "README.md"
IMAGE_LINE = re.compile(r"^\s*image:\s*(\S+)\s*$", re.MULTILINE)
DIGEST_PIN = re.compile(r"^[^\s@]+@sha256:[0-9a-f]{64}$")
def image_refs() -> list[str]:
return IMAGE_LINE.findall(MANIFEST.read_text(encoding="utf-8"))
def test_manifest_declares_both_images():
"""The init container and the server are two references, not one."""
refs = image_refs()
assert len(refs) == 2, f"expected 2 image references, found {len(refs)}: {refs}"
def test_images_are_digest_pinned_not_tagged():
"""A tag would let the migration and the server run different code.
They share one database: the init container migrates it and the server then
serves it. A floating tag makes 'the schema the migration wrote' and 'the
schema the server expects' independently resolvable, which is the failure
the digest pin exists to prevent.
"""
for ref in image_refs():
assert DIGEST_PIN.match(ref), f"image is not digest-pinned: {ref!r}"
def test_both_images_are_identical():
"""Two different digests here is a split-brain migration waiting to happen."""
refs = image_refs()
assert len(set(refs)) == 1, f"image references differ: {sorted(set(refs))}"
def test_no_release_placeholder_remains():
"""Catches the drift that motivated this file.
A placeholder left in the manifest is caught by the digest-pin check above;
this asserts the specific token is gone so a half-applied release cannot
reintroduce it silently.
"""
text = MANIFEST.read_text(encoding="utf-8")
assert "REPLACE_WITH_RELEASE_DIGEST" not in text
def test_deploy_readme_does_not_instruct_replacing_a_pinned_placeholder():
"""The runbook and the manifest must not disagree about what is left to do.
While the manifest carries a real digest, an operator instruction to replace
a placeholder is an instruction to undo the pin.
"""
manifest = MANIFEST.read_text(encoding="utf-8")
readme = (ROOT / "deploy" / "README.md").read_text(encoding="utf-8")
if "REPLACE_WITH_RELEASE_DIGEST" not in manifest:
assert "replace `REPLACE_WITH_RELEASE_DIGEST`" not in readme
def test_pinned_image_schema_drift_is_acknowledged():
"""The pin can silently fall behind the repository's schema.
The checks above hold that migrate and serve run the *same* code. They
cannot see that both run *old* code: a v3 image migrating to 3 and serving
3 is perfectly self-consistent while this repository has moved to 4. That
reads as healthy and is the more dangerous shape, because the failure is an
assumption ("the deployment records principal_type") rather than an error.
So when the manifest still pins the artifact the release record describes,
the record's schema version must either match this repository or the
runbook must say plainly that the pin is behind. Prose alone loses that;
the test makes stating it the cheaper option.
"""
refs = image_refs()
assert refs, "no image references found"
pinned = refs[0].split("@", 1)[-1]
record = RELEASE_RECORD.read_text(encoding="utf-8")
if pinned not in record:
return # a newer artifact is pinned; this record no longer describes it
versions = {
int(v) for v in re.findall(r"LATEST_SCHEMA_VERSION\s*=\s*(\d+)", record)
}
assert len(versions) == 1, f"release record states {versions or 'no'} schema versions"
recorded = versions.pop()
if recorded == LATEST_SCHEMA_VERSION:
return
readme = DEPLOY_README.read_text(encoding="utf-8")
assert f"predates schema v{LATEST_SCHEMA_VERSION}" in readme, (
f"pinned image records schema v{recorded} while this repository is at "
f"v{LATEST_SCHEMA_VERSION}; deploy/README.md must say so explicitly "
f"(the phrase 'predates schema v{LATEST_SCHEMA_VERSION}') or the "
"manifest must be re-pinned to a newer artifact"
)