From 76196aa39fd1dab78da9ba636e5768621347f429 Mon Sep 17 00:00:00 2001 From: tegwick Date: Sun, 16 Aug 2026 10:34:44 +0200 Subject: [PATCH] Finish TEN-WP-0007: guardrail surface live in production Co-Authored-By: Claude Opus 5 --- WORK-RECORDS.md | 4 +- ...EN-WP-0007-guardrail-production-rollout.md | 60 ++++++++++++++++++- 2 files changed, 59 insertions(+), 5 deletions(-) diff --git a/WORK-RECORDS.md b/WORK-RECORDS.md index d0f30d9..989bd99 100644 --- a/WORK-RECORDS.md +++ b/WORK-RECORDS.md @@ -44,7 +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-T01 | done | — | workplans/TEN-WP-0007-guardrail-production-rollout.md | +| task | TEN-WP-0007-T02 | done | — | 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 | diff --git a/workplans/TEN-WP-0007-guardrail-production-rollout.md b/workplans/TEN-WP-0007-guardrail-production-rollout.md index 90010d4..2129924 100644 --- a/workplans/TEN-WP-0007-guardrail-production-rollout.md +++ b/workplans/TEN-WP-0007-guardrail-production-rollout.md @@ -4,7 +4,7 @@ type: workplan title: "Production rollout of the guardrail surface" domain: infotech repo: tenant-engine -status: active +status: finished owner: claude topic_slug: tenant-guardrails created: "2026-08-16" @@ -147,7 +147,7 @@ nominal — `flex-auth` itself is denied the write. ```task id: TEN-WP-0007-T03 -status: wait +status: done priority: high state_hub_task_id: "ea509a74-2030-4484-a6e0-f4543a8d394f" ``` @@ -193,11 +193,36 @@ kubectl -n tenant-engine exec deploy/tenant-engine -- \ `kubectl` returns `Unauthorized` from this workstation, so I have not applied it and cannot verify the live result. +Done 2026-08-16. flex-auth attended the apply as operator (explicitly *not* as +an ownership claim). Deployment is `1/1` on +`@sha256:44ca65f3…`, `/health` returns `0.1.0`. + +**Correction to the rollback target recorded above.** The image actually +replaced was `@sha256:2249e8c6…85149207` — the **TEN-WP-0004** image — not the +TEN-WP-0005 lifecycle digest `08be0b1d…` this task assumed. Production had been +sitting on a pre-lifecycle image, so the lifecycle routes verified live on +2026-08-13 were *not* being served. That is a second silent rollback, parallel +to the flex-auth four-action one, and nobody had noticed because the two +failures looked identical from outside: user-engine's portal would have seen +`404` on the lifecycle routes rather than the `403` a policy denial produces. +This rollout fixed both surfaces at once, since the new image carries lifecycle +and guardrail routes together. + +So the real last-known-good ladder is: `44ca65f3…` (current, lifecycle + +guardrails) → `08be0b1d…` (lifecycle only) → `2249e8c6…` (neither). Rolling +back past `08be0b1d…` removes lifecycle authority that user-engine depends on. + +**Pre-existing tenants survived the forward-only migration:** + +- `tenant:trial:portalcheck` — `active`, version 1, untouched +- `tenant:trial:ten-wp-0005-t05` — `retired`, version 5, rename and lifecycle + history intact + ## T04 - Live verification and consumer confirmation ```task id: TEN-WP-0007-T04 -status: wait +status: done priority: high state_hub_task_id: "6e4961e2-25e4-43c4-9f39-113610306fe9" ``` @@ -220,6 +245,35 @@ different claims. Done when live evidence is recorded here and the confirmation is sent. +Done 2026-08-16. Live against production, disposable tenants +`tenant:small:ten-wp-0007-t04` (left `retired`) and +`tenant:trial:ten-wp-0007-t04` (left `active`). + +| Check | Result | +| --- | --- | +| grouping default, `actor=flex-auth` | 200 — `25000 EUR P1M`, provenance `grouping` | +| **`trial` reads zero spend** | 200 — `amount 0`, provenance `grouping` | +| read `actor=ops` | 403 | +| write `actor=flex-auth` | 403 — read/write split holds live | +| write `actor=ops` | 403 | +| set override `actor=tenant-engine` | 200 — `9000`, provenance `override`, ETag `"2"` | +| idempotent replay, same key | `Idempotent-Replay: true`, version still 2, same `change_id` | +| clear override | 200 — falls back to `25000`, provenance `grouping` | +| read while `retired` | 200 — `amount 0`, provenance `lifecycle` | +| loosen while retired | 409 `guardrail_loosening_denied` | +| tighten while retired | 200 — reduce-privilege stays available | +| unregistered key | 404 `unknown_limit_key` | + +**The ADR-0013 mandate is now enforced in production.** A `trial` tenant reads +a zero spend ceiling; before this rollout it had no ceiling at all. That is the +one guardrail that needs no meter to be meaningful, which is why it lands +first. + +Two things this run incidentally proved beyond the guardrail surface: the +lifecycle routes are serving again (the `retire` above returned 200, which the +pre-rollout image could not have done), and the `change_id` derivation holds +across a real replay rather than only in tests. + ## Out of scope - **Metering.** Still unowned by any repo. The guardrail read stays