Plan tenant update and retirement APIs

This commit is contained in:
tegwick 2026-08-10 18:54:28 +02:00
parent ca05cdb172
commit 7dcccafc03
2 changed files with 139 additions and 0 deletions

View file

@ -13,6 +13,7 @@
| workplan | TEN-WP-0002 | finished | — | workplans/TEN-WP-0002-domain-model-and-scaffold.md |
| 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 | ready | — | workplans/TEN-WP-0005-tenant-update-and-retirement-api.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 |
@ -31,3 +32,8 @@
| task | TEN-WP-0004-T01 | done | — | workplans/TEN-WP-0004-production-runtime.md |
| task | TEN-WP-0004-T02 | done | — | workplans/TEN-WP-0004-production-runtime.md |
| task | TEN-WP-0004-T03 | done | — | workplans/TEN-WP-0004-production-runtime.md |
| task | TEN-WP-0005-T01 | todo | — | workplans/TEN-WP-0005-tenant-update-and-retirement-api.md |
| task | TEN-WP-0005-T02 | todo | — | workplans/TEN-WP-0005-tenant-update-and-retirement-api.md |
| task | TEN-WP-0005-T03 | todo | — | workplans/TEN-WP-0005-tenant-update-and-retirement-api.md |
| task | TEN-WP-0005-T04 | todo | — | workplans/TEN-WP-0005-tenant-update-and-retirement-api.md |
| task | TEN-WP-0005-T05 | wait | — | workplans/TEN-WP-0005-tenant-update-and-retirement-api.md |

View file

@ -0,0 +1,133 @@
---
id: TEN-WP-0005
type: workplan
title: "Tenant metadata update and reversible retirement API"
domain: infotech
repo: tenant-engine
status: ready
owner: codex
topic_slug: tenant-lifecycle
created: "2026-08-10"
updated: "2026-08-10"
depends_on:
- TEN-WP-0004
unblocks:
- USER-WP-0021
state_hub_workstream_id: "bc1bd413-381a-4aca-aded-73cb3d0af529"
---
# TEN-WP-0005 - Tenant update and retirement API
Extend tenant-engine, the canonical tenant authority, with safe metadata update
and reversible retirement operations. Tenant identifiers remain immutable.
Retirement must preserve referential integrity, grant history, plan history,
and audit correlation; it is not a hard-delete endpoint.
## T01 - Specify tenant lifecycle and HTTP contracts
```task
id: TEN-WP-0005-T01
status: todo
priority: high
state_hub_task_id: "5b7d9022-4c0f-4bc3-9f63-b268836c8efc"
```
Add an explicit tenant lifecycle (`active` and `retired`), mutable display
metadata, record version, and lifecycle timestamps to the domain contract.
Specify:
- `GET /tenants/{tenant_id}` for authoritative lifecycle and metadata reads;
- `PATCH /tenants/{tenant_id}` for allow-listed metadata changes;
- `POST /tenants/{tenant_id}/retire` for reversible retirement;
- `POST /tenants/{tenant_id}/reactivate` for controlled recovery.
Every mutation requires `Idempotency-Key`, `If-Match`, actor, reason, and
correlation ID. Tenant IDs and identifiers are immutable. Unknown fields,
empty updates, stale versions, and invalid lifecycle transitions fail closed.
Document stable response/error schemas for user-engine and other consumers.
Done when the OpenAPI contract makes concurrency, idempotency, authorization,
and lifecycle semantics unambiguous without defining a hard-delete operation.
## T02 - Implement durable lifecycle state and migration
```task
id: TEN-WP-0005-T02
status: todo
priority: high
state_hub_task_id: "3596d8f2-06cf-4bf9-bdab-00cf48a25956"
```
Extend the domain and both store implementations with display metadata,
lifecycle state, version, updated/retired/reactivated timestamps, and mutation
reason/correlation evidence. Add a forward-only PostgreSQL migration that
defaults existing tenants to active and preserves current identifiers, roles,
and plan assignments. Persist idempotency receipts so retries return the same
result across process restarts.
Done when in-memory and PostgreSQL conformance prove atomic compare-and-swap,
restart-safe idempotency, and lossless migration of existing tenants.
## T03 - Implement authorized update and lifecycle endpoints
```task
id: TEN-WP-0005-T03
status: todo
priority: high
state_hub_task_id: "083bcd28-47f4-4337-9bbe-e2f9f67cc2d1"
```
Implement the read, patch, retire, and reactivate handlers through the store
abstraction. Authorize mutations with distinct flex-auth actions:
`tenant.update`, `tenant.retire`, and `tenant.reactivate`. Return 409 for stale
versions or invalid transitions, 404 for unknown tenants, and redacted 503
responses for authority/store failures. Never reflect policy or database
details.
Retirement prevents new role grants and plan changes while retaining existing
history for audit and recovery. Reactivation does not silently restore revoked
grants or invent plan state.
Done when all lifecycle mutations are authorized, versioned, idempotent,
correlated, and provider-neutral.
## T04 - Add lifecycle security and compatibility conformance
```task
id: TEN-WP-0005-T04
status: todo
priority: high
state_hub_task_id: "b716d7bf-ef6b-4b1d-bac3-e3f716d1a0b8"
```
Cover successful update, no-op/unknown-field rejection, identifier mutation
denial, stale-version conflict, duplicate idempotency replay, conflicting-key
reuse, double retirement, reactivation, update-after-retirement denial,
role/plan mutation denial while retired, cross-tenant authorization denial,
store outage, and concurrent writers. Verify error redaction and correlation.
Prove existing create, role-read, grant/revoke, and plan clients remain
compatible.
Done when unit, API, store-conformance, PostgreSQL, and flex-auth tests pass and
the existing API behavior has no unplanned breaking change.
## T05 - Integrate and verify the production authority
```task
id: TEN-WP-0005-T05
status: wait
priority: high
state_hub_task_id: "9b21782a-1b26-4fac-81a1-06bd7e8cf70f"
```
Publish an immutable tenant-engine image, apply the migration, add the three
flex-auth actions, and roll out with rollback evidence. Exercise create,
update, retire, denied mutation while retired, reactivate, and idempotent replay
against a disposable production tenant. Hand the finalized contract to
user-engine so USER-WP-0021 can implement its platform operator UI/API without
duplicating tenant authority.
Done when production evidence confirms durable lifecycle behavior and the
consumer handoff names the immutable image, API version, and authorization
policy revision.