diff --git a/WORK-RECORDS.md b/WORK-RECORDS.md index 6fb36f7..ff39c7c 100644 --- a/WORK-RECORDS.md +++ b/WORK-RECORDS.md @@ -14,7 +14,7 @@ | workplan | TEN-WP-0003 | finished | — | workplans/TEN-WP-0003-flex-auth-write-authorizer.md | | 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-0006 | ready | — | workplans/TEN-WP-0006-guardrail-quota-policy.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 | @@ -38,8 +38,8 @@ | task | TEN-WP-0005-T03 | done | — | workplans/TEN-WP-0005-tenant-update-and-retirement-api.md | | task | TEN-WP-0005-T04 | done | — | workplans/TEN-WP-0005-tenant-update-and-retirement-api.md | | task | TEN-WP-0005-T05 | done | — | workplans/TEN-WP-0005-tenant-update-and-retirement-api.md | -| task | TEN-WP-0006-T01 | done | — | workplans/TEN-WP-0006-guardrail-quota-policy.md | -| task | TEN-WP-0006-T02 | done | — | workplans/TEN-WP-0006-guardrail-quota-policy.md | -| 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-0006-T01 | todo | — | workplans/TEN-WP-0006-guardrail-quota-policy.md | +| task | TEN-WP-0006-T02 | todo | — | workplans/TEN-WP-0006-guardrail-quota-policy.md | +| task | TEN-WP-0006-T03 | todo | — | workplans/TEN-WP-0006-guardrail-quota-policy.md | +| task | TEN-WP-0006-T04 | todo | — | workplans/TEN-WP-0006-guardrail-quota-policy.md | +| task | TEN-WP-0006-T05 | todo | — | workplans/TEN-WP-0006-guardrail-quota-policy.md | diff --git a/workplans/TEN-WP-0007-guardrail-production-rollout.md b/workplans/TEN-WP-0007-guardrail-production-rollout.md deleted file mode 100644 index 4a42cfd..0000000 --- a/workplans/TEN-WP-0007-guardrail-production-rollout.md +++ /dev/null @@ -1,145 +0,0 @@ ---- -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.