Plan guardrail production rollout (TEN-WP-0007)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
e5c106186d
commit
9f1e58a797
1 changed files with 145 additions and 0 deletions
145
workplans/TEN-WP-0007-guardrail-production-rollout.md
Normal file
145
workplans/TEN-WP-0007-guardrail-production-rollout.md
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
---
|
||||
id: TEN-WP-0007
|
||||
type: workplan
|
||||
title: "Production rollout of the guardrail surface"
|
||||
domain: infotech
|
||||
repo: tenant-engine
|
||||
status: ready
|
||||
owner: claude
|
||||
topic_slug: tenant-guardrails
|
||||
created: "2026-08-16"
|
||||
updated: "2026-08-16"
|
||||
depends_on:
|
||||
- TEN-WP-0006
|
||||
unblocks: []
|
||||
---
|
||||
|
||||
# TEN-WP-0007 - Guardrail production rollout
|
||||
|
||||
TEN-WP-0006 deliberately left production rollout out of scope. The operator has
|
||||
now authorized proceeding, so this workplan carries the deploy that TEN-WP-0006
|
||||
would not.
|
||||
|
||||
## Sequencing (agreed with flex-auth, FLEX-WP-0014)
|
||||
|
||||
1. **flex-auth first** — CI image from the nine-action commit, pin
|
||||
`flex-auth-tenant-engine`.
|
||||
2. **tenant-engine second** — pin the guardrail image.
|
||||
3. **Joint live verification** against a disposable tenant.
|
||||
|
||||
flex-auth goes first on purpose. If we pin first, the guardrail surface is live
|
||||
but every call denies with `write_denied` — a state indistinguishable from a
|
||||
broken deployment to anyone reading logs. Their step landing first makes each
|
||||
step independently observable.
|
||||
|
||||
## What is already true
|
||||
|
||||
- Source revision `e5c1061` on `main`, TEN-WP-0006 finished, 231 tests passing.
|
||||
- flex-auth's nine-action package is verified **in source** (17/17 Rego tests,
|
||||
23/23 fixtures, end-to-end against our unmodified `FlexAuthWriteAuthorizer`).
|
||||
- Production flex-auth serves the **seven**-action image
|
||||
`@sha256:9320df39…` — the four-action regression is resolved, but the
|
||||
guardrail actions are not in that image.
|
||||
- Production tenant-engine still runs the TEN-WP-0005 lifecycle image.
|
||||
|
||||
## T01 - Confirm the CI image and its digest
|
||||
|
||||
```task
|
||||
id: TEN-WP-0007-T01
|
||||
status: todo
|
||||
priority: high
|
||||
```
|
||||
|
||||
`src/**` is a trigger path in `.forgejo/workflows/image.yaml` and the guardrail
|
||||
commits are pushed, so CI should have built an image for `main-e5c1061`.
|
||||
Confirm it exists and record the immutable digest.
|
||||
|
||||
Blocked from this workstation: no registry credentials. Needs a shell with
|
||||
forge access, or the digest relayed by whoever has one.
|
||||
|
||||
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`).
|
||||
|
||||
## T02 - Wait for the flex-auth nine-action pin
|
||||
|
||||
```task
|
||||
id: TEN-WP-0007-T02
|
||||
status: wait
|
||||
priority: high
|
||||
```
|
||||
|
||||
Waiting on FLEX-WP-0014 step 1. Two things to collect when it lands:
|
||||
|
||||
- the new flex-auth image digest;
|
||||
- confirmation that the **seven pre-existing actions still allow** after the
|
||||
pin. The last regression surfaced as a silent rollback, and lifecycle
|
||||
authority is what user-engine is already shipping against — a second silent
|
||||
rollback would break a live consumer, not just this workplan.
|
||||
|
||||
Done when guardrail checks return allow instead of `deny unknown_action`
|
||||
against the live decision surface.
|
||||
|
||||
## T03 - Apply the migration and pin the tenant-engine image
|
||||
|
||||
```task
|
||||
id: TEN-WP-0007-T03
|
||||
status: wait
|
||||
priority: high
|
||||
```
|
||||
|
||||
The guardrail schema change is two new tables created by the same
|
||||
`CREATE TABLE IF NOT EXISTS` script fresh and existing databases both take, so
|
||||
the migration is forward-only and idempotent and needs no separate step. What
|
||||
it does need is evidence that the existing SQLite database on the PVC survives
|
||||
it with tenants, grants, and plans untouched.
|
||||
|
||||
Rollback is `kubectl -n tenant-engine rollout undo`; last-known-good is the
|
||||
TEN-WP-0005 lifecycle digest
|
||||
`@sha256:08be0b1dcdc65575592b7be665c28e09a82316ea3d4c9b551ccb753f25360612`.
|
||||
Rolling back is safe in one direction only: the new tables are additive and the
|
||||
old image ignores them, but any override written while the new image is live
|
||||
stops being enforced on rollback. Nothing reads guardrails yet, so today that
|
||||
is inert — record it before that stops being true.
|
||||
|
||||
Blocked from this workstation: `kubectl` returns `Unauthorized`. This is an
|
||||
operator step.
|
||||
|
||||
Done when the deployment is pinned to the T01 digest and the pre-existing
|
||||
tenants are intact.
|
||||
|
||||
## T04 - Live verification and consumer confirmation
|
||||
|
||||
```task
|
||||
id: TEN-WP-0007-T04
|
||||
status: wait
|
||||
priority: high
|
||||
```
|
||||
|
||||
Against a disposable tenant, in the TEN-WP-0005-T05 evidence style:
|
||||
|
||||
- guardrail read returns the grouping default with provenance `grouping`;
|
||||
- a `trial` tenant reads a **zero** spend ceiling — the ADR-0013 mandate, and
|
||||
the one thing here that is enforceable with no meter;
|
||||
- override set → read reflects it with provenance `override`;
|
||||
- override cleared → falls back to the grouping default;
|
||||
- `actor=ops` denied on both read and write;
|
||||
- `flex-auth` allowed on read, denied on write (`action_not_granted`);
|
||||
- retired tenant still reads, clamps to floor, loosening refused;
|
||||
- idempotent replay returns the original result unchanged.
|
||||
|
||||
Then confirm to flex-auth from our side — they verified the decision surface,
|
||||
not our endpoints in production, and TEN-WP-0005 established that those are
|
||||
different claims.
|
||||
|
||||
Done when live evidence is recorded here and the confirmation is sent.
|
||||
|
||||
## Out of scope
|
||||
|
||||
- **Metering.** Still unowned by any repo. The guardrail read stays
|
||||
ceiling-only until canon names a meter.
|
||||
- **The plan-derived layer.** `adaptive-pricing` exposes no plan-derived
|
||||
ceilings; the precedence layer exists and is tested but has no feed.
|
||||
- **Grouping ceiling values.** The non-`trial` defaults are conservative
|
||||
opening numbers pending product sign-off. Rolling out does not ratify them —
|
||||
they are config, changeable without a deploy.
|
||||
Loading…
Add table
Add a link
Reference in a new issue