Pin caller-auth digest in warn on independently rollable overlay pins
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s

The sanctioned Helm chart could not promote ADR 0004 at all, and the
emergency manifests selected enforce. That made a FLEX-WP-0011 apply
either a no-op or a global 401. First production pin is now warn, per
consumer, on CI digest sha256:138aa347… . Enforce stays a later
per-consumer flip so USER-WP-0023-T03 can close without waiting on
tenant-engine.
This commit is contained in:
tegwick 2026-08-19 12:31:08 +02:00
parent 3de72fe6f5
commit fa278674c1
22 changed files with 268 additions and 55 deletions

View file

@ -2,5 +2,5 @@ apiVersion: v2
name: flex-auth
description: Independently rollable flex-auth policy-decision Deployment (one consumer per release).
type: application
version: 0.1.0
version: 0.2.0
appVersion: "0.1.0"

View file

@ -18,3 +18,18 @@ app.kubernetes.io/name: {{ include "flex-auth.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/part-of: flex-auth
{{- end -}}
{{- define "flex-auth.callerAuth.mode" -}}
{{- $mode := "disabled" -}}
{{- if and (hasKey .Values "callerAuth") .Values.callerAuth (hasKey .Values.callerAuth "mode") .Values.callerAuth.mode -}}
{{- $mode = .Values.callerAuth.mode -}}
{{- end -}}
{{- if not (has $mode (list "disabled" "warn" "enforce")) -}}
{{- fail (printf "callerAuth.mode must be disabled, warn, or enforce; got %q" $mode) -}}
{{- end -}}
{{- $mode -}}
{{- end -}}
{{- define "flex-auth.callerAuth.enabled" -}}
{{- if has (include "flex-auth.callerAuth.mode" .) (list "warn" "enforce") -}}true{{- else -}}false{{- end -}}
{{- end -}}

View file

@ -15,6 +15,9 @@ spec:
{{- include "flex-auth.labels" . | nindent 8 }}
spec:
automountServiceAccountToken: false
{{- if eq (include "flex-auth.callerAuth.enabled" .) "true" }}
serviceAccountName: {{ include "flex-auth.name" . }}
{{- end }}
securityContext:
runAsNonRoot: true
seccompProfile:
@ -25,6 +28,15 @@ spec:
imagePullPolicy: {{ .Values.image.pullPolicy }}
args:
{{- toYaml .Values.args | nindent 12 }}
{{- if eq (include "flex-auth.callerAuth.enabled" .) "true" }}
{{- $binding := required "callerAuth.binding is required when callerAuth.mode is warn or enforce" .Values.callerAuth.binding }}
- --caller-auth-mode
- {{ include "flex-auth.callerAuth.mode" . | quote }}
- --caller-kubernetes-url
- {{ required "callerAuth.kubernetesURL is required when callerAuth.mode is warn or enforce" .Values.callerAuth.kubernetesURL | quote }}
- --caller-binding
- {{ $binding | quote }}
{{- end }}
ports:
- name: http
containerPort: {{ .Values.service.port }}
@ -46,3 +58,25 @@ spec:
drop:
- ALL
readOnlyRootFilesystem: true
{{- if eq (include "flex-auth.callerAuth.enabled" .) "true" }}
volumeMounts:
- mountPath: {{ .Values.callerAuth.reviewer.mountPath }}
name: flex-auth-reviewer
readOnly: true
{{- end }}
{{- if eq (include "flex-auth.callerAuth.enabled" .) "true" }}
volumes:
- name: flex-auth-reviewer
projected:
defaultMode: 0440
sources:
- serviceAccountToken:
audience: {{ .Values.callerAuth.reviewer.audience | quote }}
expirationSeconds: {{ .Values.callerAuth.reviewer.expirationSeconds }}
path: token
- configMap:
name: kube-root-ca.crt
items:
- key: ca.crt
path: ca.crt
{{- end }}

View file

@ -11,7 +11,16 @@ spec:
policyTypes:
- Ingress
- Egress
{{- if eq (include "flex-auth.callerAuth.enabled" .) "true" }}
egress:
- ports:
- port: 443
protocol: TCP
- port: 6443
protocol: TCP
{{- else }}
egress: []
{{- end }}
{{- if .Values.consumer.isolated }}
ingress: []
{{- else }}

View file

@ -0,0 +1,30 @@
{{- if eq (include "flex-auth.callerAuth.enabled" .) "true" }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ include "flex-auth.name" . }}-tokenreviewer
labels:
{{- include "flex-auth.labels" . | nindent 4 }}
rules:
- apiGroups:
- authentication.k8s.io
resources:
- tokenreviews
verbs:
- create
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ include "flex-auth.name" . }}-tokenreviewer
labels:
{{- include "flex-auth.labels" . | nindent 4 }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: {{ include "flex-auth.name" . }}-tokenreviewer
subjects:
- kind: ServiceAccount
name: {{ include "flex-auth.name" . }}
namespace: {{ .Release.Namespace }}
{{- end }}

View file

@ -0,0 +1,9 @@
{{- if eq (include "flex-auth.callerAuth.enabled" .) "true" }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "flex-auth.name" . }}
labels:
{{- include "flex-auth.labels" . | nindent 4 }}
automountServiceAccountToken: false
{{- end }}

View file

@ -29,6 +29,18 @@ consumer:
namespace: ""
podName: ""
# disabled keeps the image bootable without TokenReview (isolated canary).
# Production pins set warn, then enforce, independently per consumer.
callerAuth:
mode: disabled
audience: flex-auth
kubernetesURL: https://kubernetes.default.svc
binding: ""
reviewer:
mountPath: /var/run/secrets/flex-auth-reviewer
audience: https://kubernetes.default.svc
expirationSeconds: 3600
resources:
requests:
cpu: 25m

View file

@ -7,6 +7,12 @@ emergency kubectl path recovered on 2026-08-11 from live
`last-applied-configuration`, kept so a rollback does not depend on a
cluster annotation or on Helm history.
Caller authentication (FLEX-WP-0015-T02) is pinned here in **`warn`**,
matching `values/user-engine.yaml` and `values/tenant-engine.yaml`. Do not
edit these files back to `enforce` and apply them as a shortcut: that is
the hazard. Flip `callerAuth.mode` per consumer in the overlay after that
consumer's warn logs are clean, then re-render or edit only that pin.
Manifests for the two cluster-local flex-auth policy-decision services.
| File | Deployment | Consumer | Service DNS |
@ -86,10 +92,12 @@ last-known-good digest below.
| Deployment | Last-known-good digest | Policy state |
| --- | --- | --- |
| `flex-auth-tenant-engine` | `sha256:1bf060e61122693ce98359c167cc5fe8bdafc84e097e090eaa71af94d0f27cbc` | **live** — nine-action policy (FLEX-WP-0014), CI-built from `f304688` |
| `flex-auth-tenant-engine` | `sha256:138aa3471c46bca6e814691fa1e6520aedda3dffd743e6b09141ab433afdb64b` | **pin, not live** — caller-auth **warn** (FLEX-WP-0015-T02), CI `main-3de72fe` |
| `flex-auth-tenant-engine` *(live until warn promote)* | `sha256:1bf060e61122693ce98359c167cc5fe8bdafc84e097e090eaa71af94d0f27cbc` | nine-action policy (FLEX-WP-0014), CI-built from `f304688` |
| `flex-auth-tenant-engine` *(previous)* | `sha256:9320df394a642eff24da8af4a0ee8886a7bb78b0f14d8ee1deeb30ea8eeeaba7` | seven-action policy, FLEX-WP-0013 restore; guardrail actions deny `unknown_action` |
| `flex-auth-tenant-engine` *(rollback)* | `sha256:c25fc34a6cd7e64d955f8723ec70e176a583d5ae71d76280c4e2d89fba0fe0aa` | four-action policy; lifecycle actions deny `unknown_action` |
| `flex-auth-user-engine` | `sha256:1f5290376dc5fcf456dc7a785e394d8b90949dabecd1d3e856f38557149bb5f4` | **current** — FLEX-WP-0009-T04, nine fixtures (incl. registration-applicant) verified live 2026-08-16 |
| `flex-auth-user-engine` | `sha256:138aa3471c46bca6e814691fa1e6520aedda3dffd743e6b09141ab433afdb64b` | **pin, not live** — caller-auth **warn** (FLEX-WP-0015-T02), CI `main-3de72fe` |
| `flex-auth-user-engine` *(live until warn promote)* | `sha256:1f5290376dc5fcf456dc7a785e394d8b90949dabecd1d3e856f38557149bb5f4` | FLEX-WP-0009-T04, nine fixtures (incl. registration-applicant) verified live 2026-08-16 |
| `flex-auth-user-engine` *(previous)* | `sha256:a31961c45215aa6baf3bc748c6741ab703c2c8325e61aa7983a355026195e51b` | FLEX-WP-0009-T03, six fixtures verified live 2026-08-10 |
Rolling back the tenant-engine service to `c25fc34a…` restores fail-closed

View file

@ -25,12 +25,12 @@ spec:
- --policy
- /opt/flex-auth/examples/tenant-engine/policy_package.md
- --caller-auth-mode
- enforce
- warn
- --caller-kubernetes-url
- https://10.43.0.1
- --caller-binding
- tenant-engine=system:serviceaccount:tenant-engine:tenant-engine
image: forgejo.coulomb.social/coulomb/flex-auth@sha256:1bf060e61122693ce98359c167cc5fe8bdafc84e097e090eaa71af94d0f27cbc
image: forgejo.coulomb.social/coulomb/flex-auth@sha256:138aa3471c46bca6e814691fa1e6520aedda3dffd743e6b09141ab433afdb64b
livenessProbe:
httpGet:
path: /healthz

View file

@ -25,12 +25,12 @@ spec:
- --policy
- /opt/flex-auth/examples/user-engine/policy_package.md
- --caller-auth-mode
- enforce
- warn
- --caller-kubernetes-url
- https://10.43.0.1
- --caller-binding
- user-engine=system:serviceaccount:user-engine:user-engine
image: forgejo.coulomb.social/coulomb/flex-auth@sha256:1f5290376dc5fcf456dc7a785e394d8b90949dabecd1d3e856f38557149bb5f4
image: forgejo.coulomb.social/coulomb/flex-auth@sha256:138aa3471c46bca6e814691fa1e6520aedda3dffd743e6b09141ab433afdb64b
livenessProbe:
httpGet:
path: /healthz

View file

@ -38,9 +38,11 @@ cached across rotation.
Three modes support promotion: `disabled`, `warn`, and `enforce`. Warn mode
records the same authentication failures without logging credentials. It is a
bounded migration aid, not a conformant steady state. The reviewed desired
manifests select `enforce`; promotion still follows FLEX-WP-0011 and requires a
new immutable image digest plus caller rollout evidence.
bounded migration aid, not a conformant steady state. The first production pin
is `warn` on each independently rollable Deployment; `enforce` is the end
state and is flipped per consumer after that consumer's warn logs are clean.
Promotion follows FLEX-WP-0011. The two production pins must not be flipped
together: user-engine can enforce while tenant-engine stays in warn.
## Rejected alternatives

View file

@ -271,7 +271,7 @@ volunteer.
| Task | |
|---|---|
| T01 | Publish the posture vector and this review; reply to `rapp-postgres` |
| T02 | **Close the A0**: TokenReview source/desired state done; immutable promotion pending |
| T02 | **Close the A0**: TokenReview source + warn-first overlay pin done; operator promote-then-per-consumer-enforce pending |
| T03 | Deleted the unused tenant-engine live-roles adapter |
| T04 | AuthZEN endpoint — `wait`, with a written trigger |
| T05 | `make verify-posture` guards declaration/source/deployment drift |

View file

@ -45,6 +45,32 @@ $RAILIANCE rollback . --apply --approval-id <state-hub-id> --revision <helm-rev>
The canary Service is `flex-auth-canary.flex-auth.svc.cluster.local:8080`.
Production consumers keep calling their own Service names.
## Caller-auth promotion (FLEX-WP-0015-T02)
The two production pins are independently rollable. Do not flip both to
`enforce` in one apply. The first pin of digest
`sha256:138aa3471c46bca6e814691fa1e6520aedda3dffd743e6b09141ab433afdb64b`
is **warn** on each consumer.
```bash
# Warn pin (safe if a caller still sends no token)
helm upgrade --install flex-auth-user-engine charts/flex-auth \
--namespace flex-auth -f values/user-engine.yaml --wait --timeout 2m
helm upgrade --install flex-auth-tenant-engine charts/flex-auth \
--namespace flex-auth -f values/tenant-engine.yaml --wait --timeout 2m
# Confirm warn logs: "caller authentication warning:" must be absent for a
# migrated caller. user-engine is migrated; tenant-engine live status is
# unconfirmed. Isolated canary keeps callerAuth.mode=disabled.
# Then set values/user-engine.yaml callerAuth.mode: enforce and upgrade only
# that release. USER-WP-0023-T03 runs only after that flip. tenant-engine
# stays warn until its logs are clean.
```
Emergency kubectl path is also warn. Applying it in enforce is the hazard
the warn pin exists to prevent.
## Rolling a production pin
Policy is baked into the image. Do not build images on a workstation.
@ -76,8 +102,10 @@ or re-apply the last-known-good digest in `deploy/README.md`.
| Deployment | Last-known-good digest | Policy state |
| --- | --- | --- |
| `flex-auth-tenant-engine` | `sha256:1bf060e61122693ce98359c167cc5fe8bdafc84e097e090eaa71af94d0f27cbc` | **live** — nine-action policy (FLEX-WP-0014), CI-built from `f304688` |
| `flex-auth-tenant-engine` | `sha256:138aa3471c46bca6e814691fa1e6520aedda3dffd743e6b09141ab433afdb64b` | **pin, not live** — caller-auth warn (FLEX-WP-0015-T02), CI `main-3de72fe` |
| `flex-auth-tenant-engine` *(live until warn promote)* | `sha256:1bf060e61122693ce98359c167cc5fe8bdafc84e097e090eaa71af94d0f27cbc` | nine-action policy (FLEX-WP-0014), CI-built from `f304688` |
| `flex-auth-tenant-engine` *(previous)* | `sha256:9320df394a642eff24da8af4a0ee8886a7bb78b0f14d8ee1deeb30ea8eeeaba7` | seven-action policy, FLEX-WP-0013 restore |
| `flex-auth-tenant-engine` *(rollback)* | `sha256:c25fc34a6cd7e64d955f8723ec70e176a583d5ae71d76280c4e2d89fba0fe0aa` | four-action policy; lifecycle actions deny `unknown_action` |
| `flex-auth-user-engine` | `sha256:1f5290376dc5fcf456dc7a785e394d8b90949dabecd1d3e856f38557149bb5f4` | FLEX-WP-0009-T04, nine fixtures, live 2026-08-16 |
| `flex-auth-user-engine` | `sha256:138aa3471c46bca6e814691fa1e6520aedda3dffd743e6b09141ab433afdb64b` | **pin, not live** — caller-auth warn (FLEX-WP-0015-T02), CI `main-3de72fe` |
| `flex-auth-user-engine` *(live until warn promote)* | `sha256:1f5290376dc5fcf456dc7a785e394d8b90949dabecd1d3e856f38557149bb5f4` | FLEX-WP-0009-T04, nine fixtures, live 2026-08-16 |
| `flex-auth-user-engine` *(previous)* | `sha256:a31961c45215aa6baf3bc748c6741ab703c2c8325e61aa7983a355026195e51b` | FLEX-WP-0009-T03, six fixtures |

View file

@ -40,10 +40,11 @@ tenancy:
own inputs. Not a defect and not a target for movement.
A: >-
The running immutable digest still authenticates no caller, so current
remains A0. Source and reviewed desired manifests implement A2 with an
audience-scoped Kubernetes TokenReview choke point and exact
protected-system-to-ServiceAccount bindings. Promotion and a live
unbound-request probe remain under FLEX-WP-0011/FLEX-WP-0015-T02.
remains A0. Source, overlay, and reviewed desired manifests implement
A2 with an audience-scoped Kubernetes TokenReview choke point and exact
protected-system-to-ServiceAccount bindings. The first production pin
is warn, independently per consumer, under FLEX-WP-0011/FLEX-WP-0015-T02.
Current moves to A2 only after enforce and a live unbound-request probe.
E: >-
No tenant data at rest. Tenant scoping in decisions runs through one
choke point (internal/decision/engine.go normalizeRequest and the
@ -84,6 +85,7 @@ evidence:
- "internal/callerauth/auth.go"
- "internal/callerauth/auth_test.go"
- "cmd/flex-auth/main_test.go"
- "charts/flex-auth/templates/rbac.yaml"
- "deploy/caller-auth-rbac.yaml"
- "docs/adr/0004-inbound-caller-authentication.md"
deployment: "deploy/flex-auth-user-engine.yaml, deploy/flex-auth-tenant-engine.yaml"
deployment: "values/user-engine.yaml, values/tenant-engine.yaml, deploy/flex-auth-user-engine.yaml, deploy/flex-auth-tenant-engine.yaml"

View file

@ -12,4 +12,21 @@ for values in values/stage1.yaml values/stage2-canary.yaml values/stage3-product
helm template flex-auth charts/flex-auth -f "${values}" --namespace flex-auth >/dev/null
done
user_render="$(helm template flex-auth-user-engine charts/flex-auth -f values/user-engine.yaml --namespace flex-auth)"
echo "$user_render" | grep -q -- '--caller-auth-mode' || { echo "user-engine render omits caller-auth-mode" >&2; exit 1; }
echo "$user_render" | grep -A1 -- '--caller-auth-mode' | grep -q warn || { echo "user-engine first pin must be warn" >&2; exit 1; }
echo "$user_render" | grep -q tokenreviews || { echo "user-engine render omits TokenReview RBAC" >&2; exit 1; }
echo "$user_render" | grep -q flex-auth-reviewer || { echo "user-engine render omits reviewer projection" >&2; exit 1; }
tenant_render="$(helm template flex-auth-tenant-engine charts/flex-auth -f values/tenant-engine.yaml --namespace flex-auth)"
echo "$tenant_render" | grep -A1 -- '--caller-auth-mode' | grep -q warn || { echo "tenant-engine first pin must be warn" >&2; exit 1; }
echo "$tenant_render" | grep -q 'tenant-engine=system:serviceaccount:tenant-engine:tenant-engine' \
|| { echo "tenant-engine render omits its exact binding" >&2; exit 1; }
canary_render="$(helm template flex-auth-canary charts/flex-auth -f values/stage2-canary.yaml --namespace flex-auth)"
if echo "$canary_render" | grep -q tokenreviews; then
echo "isolated canary must not create TokenReview RBAC" >&2
exit 1
fi
echo "stage1 overlay render ok"

View file

@ -26,14 +26,36 @@ fail() {
exit 1
}
caller_mode_from_manifest() {
awk '
$0 ~ /--caller-auth-mode/ { getline; gsub(/^[[:space:]-]+/, ""); print; exit }
' "$1"
}
caller_mode_from_values() {
awk '
$1 == "callerAuth:" { in_block=1; next }
in_block && /^[^[:space:]#]/ { exit }
in_block && $1 == "mode:" { print $2; exit }
' "$1"
}
if grep -q 'authenticator.Authorize' "$main"; then
[[ "${declared_a:-0}" -ge 2 ]] || fail "caller authentication exists but current/implemented A is below 2"
for manifest in deploy/flex-auth-user-engine.yaml deploy/flex-auth-tenant-engine.yaml; do
grep -q -- '--caller-auth-mode' "$root/$manifest" || fail "$manifest omits caller auth mode"
grep -q 'enforce' "$root/$manifest" || fail "$manifest does not select enforce mode"
mode="$(caller_mode_from_manifest "$root/$manifest")"
[[ "$mode" == "warn" || "$mode" == "enforce" ]] || fail "$manifest caller-auth-mode is ${mode:-empty}, not warn or enforce"
grep -q -- '--caller-binding' "$root/$manifest" || fail "$manifest omits the exact system binding"
grep -q 'flex-auth-reviewer' "$root/$manifest" || fail "$manifest omits the reviewer token projection"
done
[[ -f "$root/deploy/caller-auth-rbac.yaml" ]] || fail "TokenReview RBAC manifest is absent"
grep -q 'tokenreviews' "$root/charts/flex-auth/templates/rbac.yaml" || fail "overlay TokenReview RBAC template is absent"
for values in values/user-engine.yaml values/tenant-engine.yaml; do
mode="$(caller_mode_from_values "$root/$values")"
[[ "$mode" == "warn" || "$mode" == "enforce" ]] || fail "$values callerAuth.mode is ${mode:-empty}, not warn or enforce"
grep -q 'binding:' "$root/$values" || fail "$values omits callerAuth.binding"
done
else
[[ "${declared_a:-0}" -lt 2 ]] || fail "A2 is declared without a caller-authentication choke point"
fi

View file

@ -2,7 +2,7 @@
name: flex-auth-local
image:
repository: forgejo.coulomb.social/coulomb/flex-auth
digest: sha256:1f5290376dc5fcf456dc7a785e394d8b90949dabecd1d3e856f38557149bb5f4
digest: sha256:138aa3471c46bca6e814691fa1e6520aedda3dffd743e6b09141ab433afdb64b
args:
- serve
- --addr

View file

@ -3,7 +3,7 @@
name: flex-auth-canary
image:
repository: forgejo.coulomb.social/coulomb/flex-auth
digest: sha256:1f5290376dc5fcf456dc7a785e394d8b90949dabecd1d3e856f38557149bb5f4
digest: sha256:138aa3471c46bca6e814691fa1e6520aedda3dffd743e6b09141ab433afdb64b
args:
- serve
- --addr

View file

@ -5,7 +5,7 @@
name: flex-auth-canary
image:
repository: forgejo.coulomb.social/coulomb/flex-auth
digest: sha256:1f5290376dc5fcf456dc7a785e394d8b90949dabecd1d3e856f38557149bb5f4
digest: sha256:138aa3471c46bca6e814691fa1e6520aedda3dffd743e6b09141ab433afdb64b
args:
- serve
- --addr

View file

@ -1,8 +1,10 @@
# Production pin for the tenant-engine policy service. Independently rollable.
# Warn is safe whether or not the live tenant-engine client already sends a
# token. Do not flip this pin to enforce until its warn logs are clean.
name: flex-auth-tenant-engine
image:
repository: forgejo.coulomb.social/coulomb/flex-auth
digest: sha256:1bf060e61122693ce98359c167cc5fe8bdafc84e097e090eaa71af94d0f27cbc
digest: sha256:138aa3471c46bca6e814691fa1e6520aedda3dffd743e6b09141ab433afdb64b
args:
- serve
- --addr
@ -11,6 +13,10 @@ args:
- /opt/flex-auth/examples/tenant-engine/registry_snapshot.json
- --policy
- /opt/flex-auth/examples/tenant-engine/policy_package.md
callerAuth:
mode: warn
kubernetesURL: https://10.43.0.1
binding: tenant-engine=system:serviceaccount:tenant-engine:tenant-engine
consumer:
isolated: false
namespace: tenant-engine

View file

@ -1,8 +1,10 @@
# Production pin for the user-engine policy service. Independently rollable.
# First caller-auth pin is warn (FLEX-WP-0015-T02). Flip mode to enforce only
# after warn logs are clean of unauthenticated callers for this consumer.
name: flex-auth-user-engine
image:
repository: forgejo.coulomb.social/coulomb/flex-auth
digest: sha256:1f5290376dc5fcf456dc7a785e394d8b90949dabecd1d3e856f38557149bb5f4
digest: sha256:138aa3471c46bca6e814691fa1e6520aedda3dffd743e6b09141ab433afdb64b
args:
- serve
- --addr
@ -11,6 +13,10 @@ args:
- /opt/flex-auth/examples/user-engine/registry_snapshot.json
- --policy
- /opt/flex-auth/examples/user-engine/policy_package.md
callerAuth:
mode: warn
kubernetesURL: https://10.43.0.1
binding: user-engine=system:serviceaccount:user-engine:user-engine
consumer:
isolated: false
namespace: user-engine

View file

@ -14,7 +14,7 @@ related_workplans:
- FLEX-WP-0004
- FLEX-WP-0011
created: "2026-08-17"
updated: "2026-08-18"
updated: "2026-08-19"
state_hub_workstream_id: "31846b19-c2a3-428e-950b-5985bc9146eb"
---
@ -110,38 +110,50 @@ Ship through the FLEX-WP-0011 staged-promotion path, not by direct apply.
ServiceAccount TokenReview with a separately projected reviewer identity and
exact `resource.system` → ServiceAccount bindings. Both check endpoints share
the choke point; missing/mismatched identity fails 401/403 and reviewer outage
fails 503. Unit and handler tests include the required unbound request. Desired
manifests select enforce mode and carry narrow TokenReview RBAC. The running
digest is unchanged, so `tenancy.current.A` honestly remains 0 while
`tenancy.implemented.A` is 2. Source committed as `1e1e077`.
fails 503. Unit and handler tests include the required unbound request. Source
committed as `1e1e077`.
**Remaining, in this order — the sequence is a constraint, not a preference.**
`ops-warden` ruled on rollout (2026-08-17) and `user-engine` asked for the same:
2026-08-19 overlay outcome: the sanctioned Helm chart did not render caller
auth at all, so a FLEX-WP-0011 pin of the new digest would have stayed
`disabled`. That is now wired. Desired emergency manifests and production
values select **`warn`**, not `enforce` — applying the previous enforce
manifests was the hazard. CI image `sha256:138aa3471c46bca6e814691fa1e6520aedda3dffd743e6b09141ab433afdb64b`
(`main-3de72fe`, built 2026-08-18T13:25Z) contains the TokenReview flags.
The running cluster digest is still unchanged, so `tenancy.current.A`
remains 0 while `tenancy.implemented.A` is 2.
1. Build and pin a new immutable digest carrying the caller-auth code.
2. Promote it in **`warn` mode**, not `enforce`. The reviewed desired manifests
in `deploy/` select `enforce` because that is the end state — applying them
directly is the hazard. Warn authenticates and logs failures without
rejecting, so it is safe for an unmigrated caller.
3. Confirm the warn logs are clean of unauthenticated callers. `user-engine` is
migrated and deployed as of 2026-08-18 (image `sha256:c501aeb2…`, token at
`/var/run/secrets/flex-auth-caller/token`). `tenant-engine`'s caller status
is **unconfirmed — asked 2026-08-18**; promoting `enforce` while their
client sends no token 401s every check and blocks their write paths.
`ops-warden` adopts the calling side on its own schedule.
4. Flip to `enforce`, then capture the live negative probe. `user-engine` has
the three assertions written and ready in their
`docs/flex-auth-caller-identity.md`; they deliberately have not run it,
because against an unenforced digest "no token returns 401" comes back as a
normal decision and would record as false evidence.
5. Only then may `policy.enabled` flip anywhere — `ops-warden` names that the
real deadline, and it is the same gate as FLEX-WP-0007.
**Better path than a global enforce flip.** The two production Deployments
are independently rollable (FLEX-WP-0011). USER-WP-0023-T03 only probes
`flex-auth-user-engine`. Serializing that probe on tenant-engine's caller
status would 401 tenant-engine writes if we enforced them together, and
would delay user-engine A2 evidence for no safety gain. Sequence:
**Operator gate.** Steps 14 need cluster credentials this session does not
1. Pin the caller-auth digest in overlay + emergency manifests — **done
2026-08-19**, first mode `warn` on both consumers.
2. Operator: promote each pin in warn via `helm upgrade --install
flex-auth-<consumer> charts/flex-auth --namespace flex-auth -f
values/<consumer>.yaml`. Isolated canary may boot the same digest with
caller-auth disabled. Do not `kubectl apply` an enforce manifest.
3. Confirm warn logs per consumer. `user-engine` is migrated and deployed
as of 2026-08-18 (image `sha256:c501aeb2…`, token at
`/var/run/secrets/flex-auth-caller/token`). `tenant-engine` source and
desired manifests already project that token and send it; live digest
is still unconfirmed. Warn is safe either way. `ops-warden` adopts the
calling side on its own schedule.
4. Flip **user-engine only** to `enforce` (`callerAuth.mode: enforce` in
`values/user-engine.yaml`, same digest). Then capture the live negative
probe from a user-engine pod. The three assertions are already written
in user-engine `docs/flex-auth-caller-identity.md`; they must not run
against warn, because "no token returns 401" would still be a decision.
5. Flip tenant-engine to enforce only after its warn logs are clean.
6. Only then may `policy.enabled` flip anywhere — `ops-warden` names that
the real deadline, and it is the same gate as FLEX-WP-0007.
**Operator gate.** Steps 25 need cluster credentials this session does not
have: `kubectl` returns `Unauthorized` and the context is `default`, which
`tenant-engine` documented on 2026-08-16 as indistinguishable from a
wrong-cluster KUBECONFIG. Promotion follows FLEX-WP-0011 staged promotion and
the CI image build, not a hand-built image.
wrong-cluster KUBECONFIG. Promotion follows FLEX-WP-0011 and the CI image,
not a hand-built image.
`RISK-F-0001` (risk-nexus) tracks this A0 externally. Their NetworkPolicy
question was answered 2026-08-18: both Deployments carry an ingress policy
@ -218,6 +230,7 @@ correct-looking responses, exactly like the two silent pin rollbacks the
estate has already been bitten by.
Completed 2026-08-18. `make verify-posture` checks the current/implemented
distinction, both authenticated handlers, enforce-mode desired manifests,
TokenReview RBAC, absence of a latent tenant-engine caller, and the stateless
deployment assumptions behind `R: n/a`.
distinction, both authenticated handlers, warn-or-enforce desired manifests
and overlay pins, TokenReview RBAC, absence of a latent tenant-engine caller,
and the stateless deployment assumptions behind `R: n/a`. First production
pin is warn; enforce is the end state, flipped per consumer.