Git, CI/CD & GitOpsLXIV · AuditabilityFoundations
The deployment claim — what the record asserts and what it omits
What you'll learn
- Identify the five facts a deployment record asserts: source, build, content, target, time
- Distinguish the deployment record from the deployment event
- Recognise what a deployment record deliberately omits (effect, intent, durability)
- Apply a falsifiability test to a deployment claim
Prerequisites
Verified against Git 2.55.x teaching target; 2.40+ minimum · GitHub Actions continuous service; Aug 2026 documentation baseline · Argo CD v3.5.x teaching target; v3.0+ minimum · Flux v2.9.x · Sigstore Cosign v3.1.x · SLSA v1.2 · OCI Distribution Specification v1.1 · Git LFS v3.7.1 · Kubernetes (cross-course target) 1.36.x
A deployment record is a claim, not a fact. When a
Kubernetes Deployment carries an annotation, or when
Argo CD shows Synced Healthy, the record is asserting
facts about what was deployed. The audit question is
not “what does the record say?” - that is reading a
label. The audit question is “can the claim be
checked against independent evidence?”. A claim that
cannot be falsified is not worth recording.
The five facts
A deployment record, in whatever form (Kubernetes annotations, Argo CD status, Terraform state, Ansible logs), asserts five things:
flowchart TB
subgraph Claim["Deployment claim"]
S["Source: which repo, which commit"]
B["Build: which pipeline run, which runner"]
C["Content: which image digest, which manifest set"]
T["Target: which cluster, namespace, account"]
W["When: which timestamp, which deployer identity"]
end
S --> Out["Auditable claim"]
B --> Out
C --> Out
T --> Out
W --> Out
Source - the repository, branch, commit SHA. Build - the CI run ID and workflow revision. Content - the artefact identity, typically a container image digest. Target - the cluster, namespace, AWS account, region. When - the timestamp and the deployer identity.
A record that asserts all five is auditable on its own terms. A record that asserts three is a record with a gap, and the gap is the thing an audit will eventually need.
OWNER=acme
REPO=platform
RUN_ID=1234567890
gh run view "$RUN_ID" --repo "$OWNER/$REPO" \
--json event,headBranch,conclusion,startedAt
# returns: the event that triggered the run, the
# branch, the conclusion, the start time
The record versus the event
The record is a static piece of data that lives on the resource (an annotation, a label, a status field). The event is a moment in time at which the record was written. Records can be re-written without a new event. A controller that drifts and re-syncs creates a new event but the record may be unchanged. “When was this deployed?” has two answers: when the record was last written and when the content was originally built.
What the record deliberately omits
A deployment record is not a postmortem. It does not record: effect - whether the deploy caused an incident (the observability system records that); intent - why the change was made (the PR description and the linked ticket record that); durability - how long the deploy was live and whether it was rolled back (the audit log records that).
A team that asks the record “did this cause the outage?” is asking the wrong question. The record has no answer; the observability system does.
The falsifiability test
The audit-quality of a record is measured by one property: can the claim be checked against independent evidence? A checkable claim is falsifiable. An uncheckable claim is declarative.
Each fact has an independent check. Source - clone the repo at the SHA. Build - retrieve the pipeline run. Content - compute the digest in the registry. Target - query the cluster. When - query the controller’s reconcile log or the cloud provider’s audit log.
If a check fails, the record is wrong. If no check is possible (the record is not machine-readable), the record is not a claim. It is a declaration.
Production discipline
- Treat every record as a claim, not a fact. A record contradicted by an independent check must be investigated, not trusted.
- Do not put intent, effect, or durability in the record. These belong in the PR, the observability system, and the audit log respectively.
Cross-course references
- Ansible for Production Sysadmins - Part XXXVII (RepoArch) covers the analogous claim in an Ansible run log: the playbook, the inventory, the variables in effect.
- Terraform for Production Sysadmins - Parts IX-XII (State) cover the analogous claim in a Terraform state file: the resources, the providers, the module versions.
Quiz
Knowledge check · 4 questions
Q1. A Kubernetes Deployment carries an annotation recording the image digest, the commit SHA, the pipeline run URL, the cluster name, and the deploy timestamp. A security engineer asks why the change was made. Where is the answer?
Q2. A deployment record is not auditable on its own unless its image digest, commit SHA, and timestamp can be checked against the actual running state.
Q3. Name the five facts a deployment record asserts, and identify which two are most often missing when a team uses :latest tags and merges PRs without recorded approvals.
Q4. Investigate a deployment record that disagrees with the live cluster, and determine which is the source of truth.
A team uses Argo CD. The Application for `payments` shows `Synced Healthy` and the manifest in Git records `checkout@sha256:8a3f9d2...`. An engineer runs `kubectl get deployment checkout -n payments -o yaml` and finds the live deployment records `checkout:v3.2.7` in the container spec, with no annotation linking it to a digest. The Argo CD status says the cluster is in sync with Git. Both the Git manifest and the live resource cannot be right.
Passing score: 75%. Answers are checked in this browser.