From 955fe339fd89c2046491e32e6d35e13e7fb18bf8 Mon Sep 17 00:00:00 2001 From: tegwick Date: Sun, 16 Aug 2026 02:19:48 +0200 Subject: [PATCH] Finish TEN-WP-0006: guardrail and quota policy Co-Authored-By: Claude Opus 5 --- .../TEN-WP-0006-guardrail-quota-policy.md | 47 ++++++++++++++++++- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/workplans/TEN-WP-0006-guardrail-quota-policy.md b/workplans/TEN-WP-0006-guardrail-quota-policy.md index 86bf688..d1daa49 100644 --- a/workplans/TEN-WP-0006-guardrail-quota-policy.md +++ b/workplans/TEN-WP-0006-guardrail-quota-policy.md @@ -4,7 +4,7 @@ type: workplan title: "Guardrail and quota policy for tenants" domain: infotech repo: tenant-engine -status: ready +status: finished owner: claude topic_slug: tenant-guardrails created: "2026-08-16" @@ -308,7 +308,7 @@ Decisions: ```task id: TEN-WP-0006-T05 -status: progress +status: done priority: medium state_hub_task_id: "92036fa3-9031-4b42-a67e-93196e236e08" ``` @@ -328,6 +328,49 @@ separate, human-authorized step; see the note below. Done when the full suite passes and the handoff is sent. +Done 2026-08-16. 231 tests pass (was 166 before this workplan; 65 new). Every +item on the coverage list is exercised: + +| Case | Where | +| --- | --- | +| every grouping's default | `test_guardrail_domain` (parametrised over `GROUPINGS`) | +| `trial` resolves to zero spend | `test_guardrail_domain`, `test_api_guardrails` | +| precedence grouping/plan/override | `test_guardrail_domain` | +| precedence is per key, not per set | `test_guardrail_domain` | +| unmapped grouping fails closed | `test_guardrail_domain` (bypasses the constructor to reach it) | +| reserved identifiers | `test_guardrail_domain` (parametrised over `RESERVED_IDENTIFIERS`) | +| guardrail read on a retired tenant | `test_guardrail_store_conformance`, `test_api_guardrails` | +| stale-version conflict | both conformance suites | +| idempotent replay | both conformance suites | +| cross-tenant authorization denial | `test_api_guardrails` | +| store outage, read **and** write path | `test_api_guardrails` | +| error redaction | `test_api_guardrails` | +| existing clients unaffected | `test_api_guardrails`, plus all 166 prior tests unchanged | + +Consumer handoff to `flex-auth`: + +| Fact | Value | +| --- | --- | +| Contract | `docs/tenant-guardrail-policy.md` | +| API version | `0.1.0` (unchanged — additive routes only) | +| Read route | `GET /tenants/{id}/guardrails?actor=` | +| Write routes | `PUT` / `DELETE /tenants/{id}/guardrails/{limit_key}` | +| Required actions | `tenant.guardrail.read`, `tenant.guardrail.set` (resource type `guardrail`) | +| Policy package | `tenant-engine.write-api.mutate` — extends the existing seven actions to nine | +| Source revision | `d1d9c9a` | +| Immutable image | **none — not built.** Production rollout is out of scope; see below | + +Two things the consumer must know, both stated plainly in the message sent: + +1. **`flex-auth` cannot use this yet.** Both actions are new, so until the + policy package carries them every check denies — correctly, but the surface + is inert in production until that lands. +2. **The read alone is not enforcement.** No repo owns metering, so a PDP can + enforce ceiling-presence semantics (is there a limit? is it zero?) but not + consumption-relative ones (has the tenant used it up?). The ADR-0013 `trial` + = zero default is fully enforceable today precisely because it needs no + meter. + ## Out of scope / explicitly deferred - **Production rollout.** Image build and cluster apply need credentials and a