TEN-WP-0007: pin guardrail image, record CI digest and flex-auth nine-action pin

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
tegwick 2026-08-16 10:02:34 +02:00
parent 4d29b8ce15
commit 611431c2b7
3 changed files with 94 additions and 3 deletions

View file

@ -15,6 +15,7 @@
| workplan | TEN-WP-0004 | finished | — | workplans/TEN-WP-0004-production-runtime.md |
| workplan | TEN-WP-0005 | finished | — | workplans/TEN-WP-0005-tenant-update-and-retirement-api.md |
| workplan | TEN-WP-0006 | finished | — | workplans/TEN-WP-0006-guardrail-quota-policy.md |
| workplan | TEN-WP-0007 | ready | — | workplans/TEN-WP-0007-guardrail-production-rollout.md |
| task | ADHOC-2026-07-24-T01 | done | — | workplans/ADHOC-2026-07-24.md |
| task | TEN-WP-0001-T01 | done | — | workplans/TEN-WP-0001-statehub-bootstrap.md |
| task | TEN-WP-0001-T02 | done | — | workplans/TEN-WP-0001-statehub-bootstrap.md |
@ -43,3 +44,7 @@
| task | TEN-WP-0006-T03 | done | — | workplans/TEN-WP-0006-guardrail-quota-policy.md |
| task | TEN-WP-0006-T04 | done | — | workplans/TEN-WP-0006-guardrail-quota-policy.md |
| task | TEN-WP-0006-T05 | done | — | workplans/TEN-WP-0006-guardrail-quota-policy.md |
| task | TEN-WP-0007-T01 | todo | — | workplans/TEN-WP-0007-guardrail-production-rollout.md |
| task | TEN-WP-0007-T02 | wait | — | workplans/TEN-WP-0007-guardrail-production-rollout.md |
| task | TEN-WP-0007-T03 | wait | — | workplans/TEN-WP-0007-guardrail-production-rollout.md |
| task | TEN-WP-0007-T04 | wait | — | workplans/TEN-WP-0007-guardrail-production-rollout.md |

View file

@ -42,7 +42,7 @@ spec:
value: /data/tenant-engine.db
- name: TENANT_ENGINE_FLEX_AUTH_URL
value: http://flex-auth-tenant-engine.flex-auth.svc.cluster.local:8080
image: forgejo.coulomb.social/coulomb/tenant-engine@sha256:08be0b1dcdc65575592b7be665c28e09a82316ea3d4c9b551ccb753f25360612
image: forgejo.coulomb.social/coulomb/tenant-engine@sha256:44ca65f3cdd5967b0124e16b6aba10bf1ac2747e1dde96cbef3dd11ae7cc9574
livenessProbe:
httpGet:
path: /health

View file

@ -12,6 +12,7 @@ updated: "2026-08-16"
depends_on:
- TEN-WP-0006
unblocks: []
state_hub_workstream_id: "9c4d1bb8-47a4-47ff-841f-e8f2ddd01b59"
---
# TEN-WP-0007 - Guardrail production rollout
@ -46,8 +47,9 @@ step independently observable.
```task
id: TEN-WP-0007-T01
status: todo
status: done
priority: high
state_hub_task_id: "2f977044-7de1-4dba-aba6-d8a4da6cdcac"
```
`src/**` is a trigger path in `.forgejo/workflows/image.yaml` and the guardrail
@ -61,12 +63,47 @@ Done when the digest is recorded here and the image is confirmed to contain
the guardrail routes (`GET /openapi.json` on the built image lists
`/tenants/{tenant_id}/guardrails`).
Done 2026-08-16. The forge API turned out to be readable without credentials,
so this was not blocked after all.
| Fact | Value |
| --- | --- |
| Immutable image | `forgejo.coulomb.social/coulomb/tenant-engine@sha256:44ca65f3cdd5967b0124e16b6aba10bf1ac2747e1dde96cbef3dd11ae7cc9574` |
| CI tag | `main-955fe33` (workflow run #2, `success`) |
| Built from | `955fe33` — "Finish TEN-WP-0006: guardrail and quota policy" |
| API version | `0.1.0` (unchanged — additive routes only) |
**Why `955fe33` and not `main` HEAD.** Three commits landed after it
(`e5c1061`, `9f1e58a`, `4d29b8c`), so the newest commit is *not* the newest
image. None of the three touches a CI trigger path — they are `WORK-RECORDS.md`,
a workplan file, and `.custodian-brief.md` — so no build was triggered and none
was needed. `955fe33` is the last commit containing source, and therefore the
correct image. Checked rather than assumed, because "latest commit" and "latest
image" diverging silently is exactly how a stale artifact ships.
`latest` resolves to the same digest, which corroborates it.
Verified by running the pulled image locally, not by trusting the tag:
```
/health {"status":"ok","version":"0.1.0"}
/tenants/{tenant_id}/guardrails GET
/tenants/{tenant_id}/guardrails/{limit_key} PUT, DELETE
```
12 paths total: the two guardrail paths plus all ten pre-existing ones
(create, role read/grant/revoke, roles/live, plan, PATCH, retire, reactivate,
health) — so the additive claim holds against the artifact, not just the diff.
Note for future runs: the image listens on **8090**, not 8000.
## T02 - Wait for the flex-auth nine-action pin
```task
id: TEN-WP-0007-T02
status: wait
status: done
priority: high
state_hub_task_id: "a5e6f0e5-0a77-4075-b0f6-8ed9bd3b5e2c"
```
Waiting on FLEX-WP-0014 step 1. Two things to collect when it lands:
@ -80,12 +117,39 @@ Waiting on FLEX-WP-0014 step 1. Two things to collect when it lands:
Done when guardrail checks return allow instead of `deny unknown_action`
against the live decision surface.
Done 2026-08-16 by flex-auth (FLEX-WP-0014 step 1).
| Fact | Value |
| --- | --- |
| flex-auth image | `@sha256:1bf060e61122693ce98359c167cc5fe8bdafc84e097e090eaa71af94d0f27cbc` |
| CI tag | `main-f304688` |
| Package | `tenant-engine.write-api.mutate` v1, **nine** actions |
| Approval | `8d1efcea-93c7-436b-a749-e5d464e94a33` |
| Rollback target | `@sha256:9320df39…` (seven actions) |
Live `/v1/check` after their pin:
```
tenant.guardrail.read actor=flex-auth allow decision:9b9e540de13cf7cf
tenant.guardrail.set actor=tenant-engine allow decision:20c82bc38501a343
tenant.guardrail.set actor=flex-auth deny action_not_granted
misspelled guardrail deny unknown_action
unknown subject deny unknown_subject
tenant.create / tenant.retire allow (still)
```
Both asks answered: **the seven pre-existing actions still allow**, so the
silent-rollback failure mode that hit TEN-WP-0005 did not recur, and
`flex-auth-user-engine` was not moved. The read/write split is real, not
nominal — `flex-auth` itself is denied the write.
## T03 - Apply the migration and pin the tenant-engine image
```task
id: TEN-WP-0007-T03
status: wait
priority: high
state_hub_task_id: "ea509a74-2030-4484-a6e0-f4543a8d394f"
```
The guardrail schema change is two new tables created by the same
@ -108,12 +172,34 @@ operator step.
Done when the deployment is pinned to the T01 digest and the pre-existing
tenants are intact.
Status 2026-08-16: **repo side done, cluster apply outstanding.**
`deploy/tenant-engine.yaml` now pins
`@sha256:44ca65f3cdd5967b0124e16b6aba10bf1ac2747e1dde96cbef3dd11ae7cc9574`
(was the TEN-WP-0005 lifecycle digest `08be0b1d…`). The manifest already
targets `flex-auth-tenant-engine.flex-auth.svc.cluster.local:8080`, which is
the deployment flex-auth just re-pinned to nine actions, so no env change is
needed.
Remaining, and it needs an operator with cluster credentials:
```bash
kubectl -n tenant-engine apply -f deploy/tenant-engine.yaml
kubectl -n tenant-engine rollout status deploy/tenant-engine
# confirm the pre-existing tenant survived the forward-only migration
kubectl -n tenant-engine exec deploy/tenant-engine -- \
curl -s localhost:8090/tenants/tenant:trial:portalcheck
```
`kubectl` returns `Unauthorized` from this workstation, so I have not applied
it and cannot verify the live result.
## T04 - Live verification and consumer confirmation
```task
id: TEN-WP-0007-T04
status: wait
priority: high
state_hub_task_id: "6e4961e2-25e4-43c4-9f39-113610306fe9"
```
Against a disposable tenant, in the TEN-WP-0005-T05 evidence style: