2026-11-01 11:26:26 +01:00
|
|
|
# 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
|
2026-11-01 11:55:27 +01:00
|
|
|
**Evidence:** `docs/evidence/2026-11-01-compact-sitting-v14/release-candidate-checks.json` (`release_candidate` = the image in the table below)
|
2026-11-01 11:26:26 +01:00
|
|
|
|
|
|
|
|
## 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.
|
|
|
|
|
|
2026-11-01 11:55:27 +01:00
|
|
|
**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.
|
|
|
|
|
|
2026-11-01 11:26:26 +01:00
|
|
|
## 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) |
|
2026-11-01 11:55:27 +01:00
|
|
|
| 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 |
|
2026-11-01 11:26:26 +01:00
|
|
|
| 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) |
|
|
|
|
|
|
2026-11-01 11:55:27 +01:00
|
|
|
### Gate: image scan (passed)
|
2026-11-01 11:26:26 +01:00
|
|
|
|
2026-11-01 11:55:27 +01:00
|
|
|
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.
|
2026-11-01 11:26:26 +01:00
|
|
|
|
|
|
|
|
## 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 `--atomic` from owner CI
|
|
|
|
|
image `6c6dc263` (source f234d01), values `values/informed-decision-lifecycle-review.candidate.yaml`
|
|
|
|
|
(commit 941ffa6), consumer pinned v13 `31be5985`.
|
|
|
|
|
- `registry/release-units/flex-auth-informed-decision-sitting.yaml` pins the live OCI image
|
|
|
|
|
`6c6dc263…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
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
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:
|
|
|
|
|
|
2026-11-01 11:55:27 +01:00
|
|
|
- image `@sha256:6c6dc263…168e` → `@sha256:dce2ce6f1def41d162c999818caeee09dc5404331f305b0d20306fade450dd6c`
|
2026-11-01 11:26:26 +01:00
|
|
|
- `--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-audience` `flex-auth` (FLEX-WP-0038 saw this chart
|
|
|
|
|
drift). `flex-auth` is 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
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
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)
|
|
|
|
|
|
2026-11-01 11:55:27 +01:00
|
|
|
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
|
2026-11-01 11:26:26 +01:00
|
|
|
`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.
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
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:
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
["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)
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
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`
|
|
|
|
|
|
|
|
|
|
```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
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
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.yaml` to the new image
|
|
|
|
|
digest and source.
|
|
|
|
|
- Keep `values/informed-decision-lifecycle-review.candidate.yaml` as the v13 rollback
|
|
|
|
|
reference until the v14 pair has run cleanly.
|