Bootstrap repo: State Hub registration, agent docs, TEN-WP-0001/0002
statehub register + repo-seed template scaffold (CLAUDE.md, .claude/rules/, registry/). INTENT.md and SCOPE.md rewritten from the generated stub to match net-kingdom's ratified tenant-engine-boundary-contract_v0.1.md (Purpose, Responsibility Boundary, Non-Goals). topic_slug corrected from the auto-assigned custodian default to netkingdom, matching key-cape and user-engine. TEN-WP-0001 (bootstrap) complete: files reviewed/refined, stack decided (Python 3.12 + FastAPI, matching qonto-assistant's convention), first real workplan seeded. TEN-WP-0002 drafted: service skeleton, domain model (tenant/grouping/ capability-role/plan-grant), storage layer, and the three boundary-contract API surfaces (cache-read for key-cape, live-lookup for flex-auth with an explicit fail-closed requirement, write API behind a WriteAuthorizer seam since real flex-auth integration is a declared non-goal for this pass). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
cbb8057c38
commit
9370348d54
21 changed files with 1067 additions and 0 deletions
79
workplans/TEN-WP-0001-statehub-bootstrap.md
Normal file
79
workplans/TEN-WP-0001-statehub-bootstrap.md
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
---
|
||||
id: TEN-WP-0001
|
||||
type: workplan
|
||||
title: "Bootstrap State Hub integration"
|
||||
domain: infotech
|
||||
repo: tenant-engine
|
||||
status: finished
|
||||
owner: codex
|
||||
topic_slug: netkingdom
|
||||
created: "2026-07-23"
|
||||
updated: "2026-07-23"
|
||||
---
|
||||
|
||||
# Bootstrap State Hub integration
|
||||
|
||||
Canonical owner of tenant-as-an-entity facts for NetKingdom: existence, onboarding grouping, capability roles, and plan/subscription assignment.
|
||||
|
||||
## Review Generated Integration Files
|
||||
|
||||
```task
|
||||
id: TEN-WP-0001-T01
|
||||
status: done
|
||||
priority: high
|
||||
```
|
||||
|
||||
Review `INTENT.md`, `SCOPE.md`, `AGENTS.md`, and `.custodian-brief.md`.
|
||||
Replace generated placeholders with repo-specific facts where needed.
|
||||
|
||||
**Done 2026-07-23:** `INTENT.md` and `SCOPE.md` rewritten from the generated
|
||||
stub into the full Purpose/Responsibility-Boundary/Non-Goals shape matching
|
||||
the ratified `net-kingdom/canon/standards/tenant-engine-boundary-contract_v0.1.md`
|
||||
(Ownership Model + Source-of-Truth Matrix condensed into this repo's own
|
||||
docs, not duplicated wholesale). `topic_slug` corrected from the
|
||||
auto-assigned `custodian` default to `netkingdom`, matching `key-cape` and
|
||||
`user-engine`'s convention. `.claude/rules/{repo-identity,architecture,repo-boundary,stack-and-commands}.md`
|
||||
placeholders filled in (copied from `repo-seed`, the fleet's bootstrap
|
||||
template). `AGENTS.md`/`.custodian-brief.md` left as generated — both carry
|
||||
an explicit "state-hub template sync" marker meaning they're managed by
|
||||
`fix-consistency`, not hand-edited.
|
||||
|
||||
## Verify Local Developer Workflow
|
||||
|
||||
```task
|
||||
id: TEN-WP-0001-T02
|
||||
status: done
|
||||
priority: high
|
||||
```
|
||||
|
||||
Identify the repo's install, test, lint, build, and run commands. Add or refine
|
||||
those commands in the agent instructions so future coding sessions can verify
|
||||
changes confidently.
|
||||
|
||||
**Done 2026-07-23:** Stack decided — Python 3.12 + FastAPI, matching
|
||||
`qonto-assistant`'s fleet convention for small headless services (this repo
|
||||
plays a structurally similar role: a narrow, security-adjacent API a couple
|
||||
of other services call synchronously). `make install-dev`/`test`/`lint`/`run`
|
||||
commands documented in `.claude/rules/stack-and-commands.md` ahead of the
|
||||
actual `Makefile`/`pyproject.toml`, which land in `TEN-WP-0002`.
|
||||
|
||||
## Seed First Real Workplan
|
||||
|
||||
```task
|
||||
id: TEN-WP-0001-T03
|
||||
status: done
|
||||
priority: medium
|
||||
```
|
||||
|
||||
Create the first implementation workplan for the repository's most important
|
||||
next change. After workplan file updates, run the sync locally from this repo
|
||||
checkout:
|
||||
|
||||
```bash
|
||||
statehub fix-consistency
|
||||
```
|
||||
|
||||
**Done 2026-07-23:** `TEN-WP-0002-domain-model-and-scaffold.md` created —
|
||||
service skeleton, domain model (tenant/grouping/role/plan-grant), and the
|
||||
cache-read + live-lookup APIs per the boundary contract. Registered via
|
||||
`statehub fix-consistency`.
|
||||
179
workplans/TEN-WP-0002-domain-model-and-scaffold.md
Normal file
179
workplans/TEN-WP-0002-domain-model-and-scaffold.md
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
---
|
||||
id: TEN-WP-0002
|
||||
type: workplan
|
||||
title: "Service skeleton, domain model, and the three boundary-contract APIs"
|
||||
domain: infotech
|
||||
repo: tenant-engine
|
||||
status: ready
|
||||
owner: codex
|
||||
topic_slug: netkingdom
|
||||
created: "2026-07-23"
|
||||
updated: "2026-07-23"
|
||||
---
|
||||
|
||||
# Service skeleton, domain model, and the three boundary-contract APIs
|
||||
|
||||
First real implementation workplan. Builds the tenant-engine skeleton
|
||||
against `net-kingdom/canon/standards/tenant-engine-boundary-contract_v0.1.md`:
|
||||
tenant/grouping/capability-role/plan-grant domain model, an audited grant
|
||||
trail, and the three API surfaces the contract defines — cache-read
|
||||
(`key-cape`), live-lookup (`flex-auth`), and write (grant/revoke/plan
|
||||
mutation). Guardrail/quota policy stays a reserved, unimplemented namespace
|
||||
per ADR-0014 — not in scope here.
|
||||
|
||||
**Depends on:** `net-kingdom` canon — `iam-profile_v0.3.md`,
|
||||
`tenant-engine-boundary-contract_v0.1.md`, `ADR-0013`, `ADR-0014` (all
|
||||
ratified). **Non-goals:** payment processing, pricing-model definitions
|
||||
(`adaptive-pricing`'s job), real `flex-auth` integration (the write/live
|
||||
APIs get a policy-hook interface, not a working `flex-auth` client — that's
|
||||
a follow-up once `flex-auth` has a reachable endpoint), guardrail/quota
|
||||
enforcement.
|
||||
|
||||
## Task: Service skeleton
|
||||
|
||||
```task
|
||||
id: TEN-WP-0002-T01
|
||||
status: todo
|
||||
priority: high
|
||||
```
|
||||
|
||||
Python 3.12 + FastAPI, matching `qonto-assistant`'s layout convention:
|
||||
`pyproject.toml`, `Makefile` (`install-dev`, `test`, `lint`, `run`), package
|
||||
layout separating `domain/` (pure), `store/` (persistence), `api/` (FastAPI
|
||||
routers), from day one — not refactored in later.
|
||||
|
||||
Done when: `make test` runs an empty/smoke suite; `make run` starts a bare
|
||||
FastAPI app with a `/health` endpoint.
|
||||
|
||||
## Task: Domain model — tenant, grouping, capability role, plan grant
|
||||
|
||||
```task
|
||||
id: TEN-WP-0002-T02
|
||||
status: todo
|
||||
priority: high
|
||||
```
|
||||
|
||||
Pure domain types, no framework dependency:
|
||||
|
||||
- `Tenant`: id, identifier (`tenant:<grouping>:<name>` or reserved
|
||||
`tenant:platform`/`tenant:coulomb`), grouping (ADR-0013 enum, nullable for
|
||||
the two reserved identifiers).
|
||||
- `CapabilityRole`: enum `PLTF`/`IAM`/`VEN`/`CUS`.
|
||||
- `RoleGrant`: tenant_id, role, grant_reason (`plan_assignment` /
|
||||
`manual_grant` / `platform_default`), plan_id (nullable), granted_by,
|
||||
granted_at, revoked_at (nullable), correlation_id — the audited record
|
||||
shape from the boundary contract's Tenant Role & Plan Grant Contract.
|
||||
- `PlanAssignment`: tenant_id, plan_id (references an `adaptive-pricing`
|
||||
plan id — stored as an opaque string, never resolved or duplicated
|
||||
locally), assigned_at.
|
||||
|
||||
Validation rules encoded as domain invariants, not just API-layer checks:
|
||||
|
||||
- grouping must be one of ADR-0013's twelve values, or the tenant identifier
|
||||
must be exactly `tenant:platform`/`tenant:coulomb` (grouping-less);
|
||||
- a `trial`-grouped tenant may hold any role with `grant_reason:
|
||||
platform_default` and no `plan_id` (ADR-0014) — this must be
|
||||
representable, not blocked by a plan-required constraint;
|
||||
- non-`trial` roles other than `platform_default` require a `plan_id` when
|
||||
`grant_reason: plan_assignment`;
|
||||
- revoking a grant sets `revoked_at`, never deletes the record (audit trail).
|
||||
|
||||
Done when: unit tests cover valid/invalid grouping values, the trial/
|
||||
no-plan-required exception, and grant/revoke as append-only operations.
|
||||
|
||||
## Task: Storage layer
|
||||
|
||||
```task
|
||||
id: TEN-WP-0002-T03
|
||||
status: todo
|
||||
priority: high
|
||||
```
|
||||
|
||||
In-memory store behind a `TenantStore` protocol/interface (mirrors
|
||||
`qonto_client.QontoClientProtocol`'s pattern in `qonto-assistant`), so a
|
||||
real backend can be swapped in later without touching `domain/` or `api/`.
|
||||
Every mutation emits a domain event (tenant created, role granted, role
|
||||
revoked, plan assigned) per the boundary contract's Audit Correlation
|
||||
Contract — the event bus itself can be a simple in-process list for now.
|
||||
|
||||
Done when: unit tests cover create/read/grant/revoke/assign-plan through the
|
||||
store interface, plus event emission for each mutation.
|
||||
|
||||
## Task: Cache-read API (for key-cape)
|
||||
|
||||
```task
|
||||
id: TEN-WP-0002-T04
|
||||
status: todo
|
||||
priority: high
|
||||
```
|
||||
|
||||
`GET /tenants/{tenant_id}/roles` — returns current, non-revoked capability
|
||||
roles for a tenant. This is the endpoint `key-cape` calls at token-issuance
|
||||
time to source the cached `tenant_roles` claim (IAM Profile v0.3). No
|
||||
authorization gate of its own beyond service-to-service auth (out of scope
|
||||
here — see Non-Goals); this endpoint's whole purpose is to be cheap and
|
||||
fast, per the boundary contract's performance model.
|
||||
|
||||
Done when: integration test hits the endpoint against the in-memory store
|
||||
and returns the expected role set for a seeded tenant.
|
||||
|
||||
## Task: Live-lookup API (for flex-auth) — fail closed
|
||||
|
||||
```task
|
||||
id: TEN-WP-0002-T05
|
||||
status: todo
|
||||
priority: high
|
||||
```
|
||||
|
||||
`GET /tenants/{tenant_id}/roles/live` — same data as the cache-read
|
||||
endpoint, but explicitly documented and tested as the path `flex-auth` must
|
||||
call before authorizing `aal2`-class actions. The distinction from T04 is
|
||||
operational intent (freshness guarantee, called synchronously on a
|
||||
privileged-decision path), not payload shape.
|
||||
|
||||
Per the boundary contract's performance model: **fail closed, never open**.
|
||||
If the store is unavailable, this endpoint must return an error response
|
||||
that a policy caller would treat as "deny", not a default-allow or an empty
|
||||
role list indistinguishable from "no roles granted".
|
||||
|
||||
Done when: a test simulates store unavailability and asserts the endpoint
|
||||
signals failure distinctly from "zero roles", not silently as 200 + `[]`.
|
||||
|
||||
## Task: Write API — grant, revoke, assign-plan
|
||||
|
||||
```task
|
||||
id: TEN-WP-0002-T06
|
||||
status: todo
|
||||
priority: medium
|
||||
```
|
||||
|
||||
`POST /tenants` (create), `POST /tenants/{id}/roles/grant`,
|
||||
`POST /tenants/{id}/roles/revoke`, `POST /tenants/{id}/plan` — all mutating
|
||||
endpoints from the boundary contract's Write API. Per the contract,
|
||||
`tenant-engine` does not self-authorize these writes; `flex-auth` is meant
|
||||
to gate them. Since a reachable `flex-auth` integration is explicitly a
|
||||
non-goal here, implement a `WriteAuthorizer` protocol/interface point (one
|
||||
class, default-deny stub) so every mutation already flows through a single
|
||||
seam — swapping in a real `flex-auth` client later touches one file, not
|
||||
every endpoint.
|
||||
|
||||
Done when: unit tests confirm every write endpoint calls the
|
||||
`WriteAuthorizer` seam and is denied by the default-deny stub; a
|
||||
test-only authorizer override proves the seam actually gates the mutation
|
||||
when swapped.
|
||||
|
||||
## Task: Closure review
|
||||
|
||||
```task
|
||||
id: TEN-WP-0002-T07
|
||||
status: todo
|
||||
priority: low
|
||||
```
|
||||
|
||||
Confirm T01–T06 done; run `make test`/`make lint`; verify the three API
|
||||
surfaces match the boundary contract's Ownership Model and Source-of-Truth
|
||||
Matrix with no drift. Note follow-ups: real `flex-auth` `WriteAuthorizer`
|
||||
integration, `key-cape` wiring to actually call the cache-read endpoint at
|
||||
issuance, guardrail/quota policy design (ADR-0014's reserved item), and
|
||||
Binky Hedgehog GmbH as the first real tenant record once `key-cape`'s
|
||||
`KEY-WP-0004` reaches that point. Run `statehub fix-consistency`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue