Candidate image forgejo.coulomb.social/coulomb/flex-auth@sha256:dce2ce6f1def41d162c999818caeee09dc5404331f305b0d20306fade450dd6c
(revision label f4c9f2b). Read-only checks: v14 and v13 policy directories
byte-identical to source, package digests 8911458f (v14) and 31be5985 (v13),
in-image validate 46/46 and 32/32, offline verify requests answer
self_approval_refused / approval_action_not_admitted on v14, Trivy
HIGH/CRITICAL = 0 (same pinned scanner). Values, twin, pin test, runbook
(scan gate passed; informed-decision side ready at RELEASE_SHA 005709a3,
image ca75f0be, carrying 80ef840) and evidence move to this digest; the
154726d2 image is superseded.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 5502@bnt-lap001
Assistant-Session: 68b3b02f-5d0f-4e71-8421-796f62e50196
11 KiB
Runbook: release compact-sitting v14 to flex-auth-informed-decision-sitting
Date prepared: 2026-11-01 (owner: access-engine / flex-auth; nothing below has been run)
Workplan: workplans/FLEX-WP-0040-bounded-execution-pdp-gate.md, FLEX-WP-0040-T07
Owner note: docs/compact-sitting-v14-present-existing.md ("Live steps")
Approval: founder, 2026-11-01, relayed by the net-kingdom coordinator
Runs: the founder, from an access-engine checkout at the commit carrying this file
Evidence: docs/evidence/2026-11-01-compact-sitting-v14/release-candidate-checks.json (release_candidate = the image in the table below)
Coordinated with informed-decision (same window)
This release is one half of a pair. informed-decision pins the policy package it
expects (policy object of its review runtime: deploy/lifecycle/service.candidate.json
runtime.json and deploy/lifecycle/admission.candidate.json) and compares the
policy_package / policy_version / policy_package_digest of every decision with
that pin. A version or digest mismatch fails closed: from the moment this upgrade
completes until the consumer pins v14, every review request is refused, and the reverse
holds if the consumer moves first. Run both in one window, this release first, the
consumer pin immediately after; roll both back together.
| before (in force) | after | |
|---|---|---|
| package | informed-decision.compact-sitting |
same |
| version | v13 |
v14 |
| package_digest | sha256:31be5985c0c1e6b0c3a039ed7310d1e94daf523a94f6d926e6e8d759d3711873 |
sha256:8911458f36f1a60598aa19592a2d752a74dffe2617fd86238407ac87bc300fde |
The consumer's approval_action context change (owner note, "Consumer change required")
is needed only for service:nk-bind-executor present-existing requests. Without it those
are refused with approval_action_not_admitted; requests for requester
informed-decision are unaffected by v14.
informed-decision's side is ready (2026-11-01, relayed by the net-kingdom coordinator):
RELEASE_SHA 005709a37228ba9e6d5a658aada0b62bf49649f5, service image
forgejo.coulomb.social/coulomb/informed-decision@sha256:ca75f0be03af0bd96a66b08d2949bdc2d16365a93ffabcd6593074b565e8f01b
(main-c228583), runbook ~/informed-decision/deploy/lifecycle/RELEASE-INFD-WP-0010-T02.md.
That image carries the approval_action change (informed-decision commit 80ef840). Its
step 3 runs "access-engine first, then informed-decision": its 3a is steps 0-2 of this
runbook, then its 3b pins v14; its rollback returns this release to revision 13.
Release candidate
| Field | Value |
|---|---|
| release / namespace | flex-auth-informed-decision-sitting / flex-auth |
| chart | charts/flex-auth (this checkout) |
| values | values/informed-decision-sitting.yaml (edited directly; twin values/access-engine/informed-decision-sitting.yaml regenerated, not deployed) |
| image | forgejo.coulomb.social/coulomb/flex-auth@sha256:dce2ce6f1def41d162c999818caeee09dc5404331f305b0d20306fade450dd6c |
| image tag / source | main-f4c9f2b, OCI revision label f4c9f2beeb92d1639eebce7d6fbef60ea3f4db81 (CI .forgejo/workflows/image.yaml, push to main); v14 policy from 2de0f86, Go 1.26.10 builder |
| policy | /opt/flex-auth/examples/informed-decision-present-existing-review/policy.md (file sha256 dcfae737…40141, package digest verified from the image) |
| registry | unchanged path /opt/flex-auth/examples/informed-decision-lifecycle-review/registry.json (byte-identical to the present-existing copy) |
Gate: image scan (passed)
The first candidate (main-2de0f86, sha256:154726d2…4776) carried four Go stdlib 1.26.7
HIGH CVEs (CVE-2026-111943, CVE-2026-78667, CVE-2026-78669, CVE-2026-97031), as does the image
in force (6c6dc263). Founder decision 2026-11-01: bump Go and rebuild. Commit f4c9f2b
moved the builder to golang:1.26.10-alpine and go.mod to go 1.26.10; nothing else changed.
The rebuilt candidate above has 0 HIGH/CRITICAL (same pinned Trivy, OS layer and both
binaries). Its v14 and v13 policy directories are byte-identical to the source, the package
digests are 8911458f…0fde (v14) and 31be5985…3711873 (v13), and in-image validate
passes 46/46 (v14) and 32/32 (v13). The 154726d2 image must not be released.
Image in force (source evidence)
values/informed-decision-sitting.yaml recorded bdac62bc… (FLEX-WP-0033 cutover,
2026-10-04) but was never promoted after FLEX-WP-0034. Source evidence says the release
runs 6c6dc263:
- FLEX-WP-0034-T02 (2026-10-05): Helm revision 13 deployed with
--atomicfrom owner CI image6c6dc263(sourcef234d01), valuesvalues/informed-decision-lifecycle-review.candidate.yaml(commit941ffa6), consumer pinned v1331be5985. registry/release-units/flex-auth-informed-decision-sitting.yamlpins the live OCI image6c6dc263…168e.- FLEX-WP-0038 (2026-10-22): a diff of the values file against live showed the sitting
release "also changes image", i.e. live is not
bdac62bc; that release was not upgraded.
So the pre-release state is expected to be: revision 13, image 6c6dc263, v13 policy at
…/informed-decision-lifecycle-review/policy.md, memory request 32Mi. Step 0 confirms it
read-only; if it differs, stop and report.
Steps
export KUBECONFIG=$HOME/.kube/config-railiance01
cd ~/access-engine # the commit carrying this runbook
REL=flex-auth-informed-decision-sitting
NS=flex-auth
0. Record the state in force (read-only)
helm -n $NS history $REL --max 5
helm -n $NS get values $REL -o yaml > /tmp/$REL.values-before.yaml
kubectl -n $NS get deploy $REL -o jsonpath='{.spec.template.spec.containers[0].image}{"\n"}{.spec.template.spec.containers[0].args}{"\n"}'
Expect: last revision deployed (13 unless something has run since), image
…@sha256:6c6dc263f4a7f6461e109e133c004c080e8e373acfead8611856c5fb3e44168e, --policy
/opt/flex-auth/examples/informed-decision-lifecycle-review/policy.md. Write down the
revision number as PREV; it is the rollback target. If the image differs, stop.
1. Server dry-run and diff (read-only)
helm -n $NS upgrade $REL charts/flex-auth -f values/informed-decision-sitting.yaml \
--dry-run=server > /tmp/$REL.dry-run.txt && echo dry-run-ok
helm template $REL charts/flex-auth -n $NS -f values/informed-decision-sitting.yaml \
| kubectl -n $NS diff -f -
Expected diff, Deployment flex-auth-informed-decision-sitting only:
- image
@sha256:6c6dc263…168e→@sha256:dce2ce6f1def41d162c999818caeee09dc5404331f305b0d20306fade450dd6c --policy…/informed-decision-lifecycle-review/policy.md→…/informed-decision-present-existing-review/policy.md- memory request
32Mi→40Mi(FLEX-WP-0038 right-sizing, already in the values file) - possibly two added args
--caller-audienceflex-auth(FLEX-WP-0038 saw this chart drift).flex-authis the binary's default, so behaviour is unchanged; the consumer's token audience is untouched. - possibly Helm-managed labels/annotations (chart version, revision).
Anything else (NetworkPolicy, RBAC, Service, caller binding, registry path, replicas) means stop and report to the owner.
2. Upgrade
helm -n $NS upgrade $REL charts/flex-auth -f values/informed-decision-sitting.yaml \
--atomic --wait --timeout 3m
kubectl -n $NS rollout status deploy/$REL --timeout=2m
--atomic reverts to PREV by itself if the pod does not become ready.
3. Pin the consumer (informed-decision, same window)
Per informed-decision's own runbook (RELEASE-INFD-WP-0010-T02.md, step 3b, RELEASE_SHA
005709a3…49f5, image ca75f0be…): set the review runtime's policy object to
informed-decision.compact-sitting / v14 /
sha256:8911458f36f1a60598aa19592a2d752a74dffe2617fd86238407ac87bc300fde and release it.
Until then review requests fail closed.
4. Verify (read-only decision checks with synthetic claims)
The service admits only the informed-decision pod and the
system:serviceaccount:informed-decision:review caller, so check through a port-forward
with a short-lived token for that ServiceAccount (the documented pattern of
docs/operator-caller-access-path.md). Both requests are synthetic and must be denied;
no approval or memo is touched.
kubectl -n $NS get deploy $REL -o jsonpath='{.spec.template.spec.containers[0].image}{"\n"}'
kubectl -n $NS logs deploy/$REL --tail=20
kubectl -n $NS port-forward svc/$REL 18080:8080 >/dev/null 2>&1 & PF=$!
sleep 2
TOKEN=$(kubectl -n informed-decision create token review --audience=flex-auth --duration=10m)
E=docs/evidence/2026-11-01-compact-sitting-v14
for f in verify-self-approval verify-missing-action; do
jq --argjson now "$(date +%s)" '.subject.attributes.assurance.at = $now' $E/$f.request.json \
| curl -s -X POST localhost:18080/v1/check -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d @- \
| jq -c --arg f $f '[$f,.effect,.reason,.provenance.policy_version,.provenance.policy_package_digest]'
done
curl -s -o /dev/null -w 'no-token http %{http_code}\n' -X POST localhost:18080/v1/check \
-H 'Content-Type: application/json' -d @$E/verify-self-approval.request.json
unset TOKEN; kill $PF
Expected:
["verify-self-approval","deny","self_approval_refused","v14","sha256:8911458f36f1a60598aa19592a2d752a74dffe2617fd86238407ac87bc300fde"]
["verify-missing-action","deny","approval_action_not_admitted","v14","sha256:8911458f36f1a60598aa19592a2d752a74dffe2617fd86238407ac87bc300fde"]
no-token http 401
(The same two requests against v13 answer unknown_class, so these reasons prove v14 is
serving. They were checked offline against the image's own check command.) Then confirm
in informed-decision that an ordinary review read for requester informed-decision
still succeeds with the v14 pin (its own check). Any other result: roll back.
5. Rollback (both halves)
helm -n $NS rollback $REL $PREV --wait --timeout 3m
kubectl -n $NS get deploy $REL -o jsonpath='{.spec.template.spec.containers[0].image}{"\n"}'
Expect image @sha256:6c6dc263f4a7f6461e109e133c004c080e8e373acfead8611856c5fb3e44168e
and the lifecycle-review policy path. Then restore informed-decision's v13 pin
(v13, sha256:31be5985c0c1e6b0c3a039ed7310d1e94daf523a94f6d926e6e8d759d3711873).
Rollback values, if helm rollback is unavailable (exact revision-13 values, kept in the
repo): values/informed-decision-lifecycle-review.candidate.yaml
image: forgejo.coulomb.social/coulomb/flex-auth@sha256:6c6dc263f4a7f6461e109e133c004c080e8e373acfead8611856c5fb3e44168e
--registry /opt/flex-auth/examples/informed-decision-lifecycle-review/registry.json
--policy /opt/flex-auth/examples/informed-decision-lifecycle-review/policy.md # v13, 31be5985…
resources.requests: cpu 5m, memory 32Mi
helm -n $NS upgrade $REL charts/flex-auth -f values/informed-decision-lifecycle-review.candidate.yaml --atomic --wait --timeout 3m
The candidate image also carries the v13 package unchanged (same path, same digest), so
reverting only --policy on the new image is a valid partial rollback if the image itself
is not the problem.
After a successful release (owner follow-up)
- Record the Helm revision and the step-4 output under
docs/evidence/2026-11-01-compact-sitting-v14/and mark FLEX-WP-0040-T07 accordingly. - Update
registry/release-units/flex-auth-informed-decision-sitting.yamlto the new image digest and source. - Keep
values/informed-decision-lifecycle-review.candidate.yamlas the v13 rollback reference until the v14 pair has run cleanly.