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>
2026-07-23 21:56:07 +02:00
# SCOPE
> Lightweight boundary for agents and contributors. Full contract:
> `net-kingdom/canon/standards/tenant-engine-boundary-contract_v0.1.md`.
2026-08-29 11:57:37 +02:00
> Aspirational role: `INTENT.md`. Layer declaration: Engine / PIP
> (`INTENT.md` frontmatter; `TEN-DEC-2026-001`).
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>
2026-07-23 21:56:07 +02:00
---
## One-liner
2026-08-29 11:57:37 +02:00
Canonical PIP of tenant-as-an-entity facts for NetKingdom: existence,
lifecycle, onboarding grouping, capability roles, plan/subscription
assignment, and guardrail ceilings.
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>
2026-07-23 21:56:07 +02:00
---
## Core Idea
2026-08-29 11:57:37 +02:00
`tenant-engine` answers "what is this tenant, what roles does it hold, what
plan is it on, and how far may it go" for two consumers: `key-cape`
(cached, at token issuance) and `access-engine` / `flex-auth` (live, for
high-stakes decisions). It never stores users, issues tokens, evaluates
approvals, or makes authorization decisions. Tenancy context is an input to
the decision, not a decision.
---
## Layer
| Key | Value |
| --- | --- |
| Layer | **Engine** |
| Role | **PIP** |
| Statute | `net-kingdom/canon/standards/security-layer-model_v0.7.md` |
| Companion | `net-kingdom/SECURITY-COMPANION.md` |
| Catalog row | tenant-as-an-entity facts (`§4` ) |
| Tooling contacts | none (`key-cape` and OpenBao are not clients of this repo) |
| Non-Tooling clients | PostgreSQL / SQLite (own store); `flex-auth` `POST /v1/check` (Engine API on the write and authorized-read path); State Hub (work records, not a runtime dependency) |
| Write path | PEP-shaped: fail-closed when `access-engine` is unset or unreachable |
| Conformance today | Declaration is in our own voice. Mechanical `layer.yaml` check, persisted decision records, published stance map, and independent evidence custody are **not** yet shipped — see the review and `TEN-WP-0011` . |
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>
2026-07-23 21:56:07 +02:00
---
## In Scope
2026-08-29 11:57:37 +02:00
- Tenant records: identifier, lifecycle (`active` / `retired` ), current
onboarding grouping (ADR-0013). Grouping is mutable through an audited
reclassification, not by renaming `tenant_id` .
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>
2026-07-23 21:56:07 +02:00
- Capability role grants/revocations: `PLTF` /`IAM` /`VEN` /`CUS` (ADR-0014),
audited, mostly plan-linked.
- Plan/subscription assignment, referenced by `adaptive-pricing` plan id.
2026-08-29 11:57:37 +02:00
- Guardrail/quota *policy* : spend / entity-count / action-count ceilings,
resolved as a total function of grouping, plan, override, and lifecycle.
Seeded key: `spend.monthly` . `trial` defaults to zero.
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>
2026-07-23 21:56:07 +02:00
- Cache-read API for `key-cape` (token-issuance-time `tenant_roles` claim
2026-08-29 11:57:37 +02:00
source): `GET /tenants/{id}/roles` .
- Live-lookup API for `access-engine` (high-stakes, `aal2` -class
decisions): `GET /tenants/{id}/roles/live` . Store unavailability returns
`503` , never `200` plus empty roles.
- Write API for create / grant / revoke / plan / metadata / retire /
reactivate / grouping / guardrail mutations, authorization-gated by
`flex-auth` . Unset or unreachable authorizer denies.
- Authoritative tenant read with ETag / If-Match / idempotency on
lifecycle and guardrail mutations.
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>
2026-07-23 21:56:07 +02:00
## Out of Scope
- Identity, authentication, MFA, token issuance — `key-cape` /Keycloak.
2026-08-29 11:57:37 +02:00
- Authorization decisions — `access-engine` is the PDP; `tenant-engine` is
a data source it queries, never the other way around.
- Approval objects and approval lifecycle — `approval-engine` . Contested
in `TEN-DEC-2026-001` ; this repo will not grow one.
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>
2026-07-23 21:56:07 +02:00
- Users, profiles, memberships — `user-engine` . `tenant_id` is the only key
shared between the two services.
- Pricing-model / plan term definitions — `adaptive-pricing` .
- Payment processing — not yet identified as owned by any repo.
- Runtime secret custody — OpenBao / `secrets-engine` .
2026-08-29 11:57:37 +02:00
- Metering / consumption counters — whoever meters the resource writes
them; this service does not observe spend.
- Rate limiting / traffic shaping — gateway concern, not `action_count` .
- Containment / actuation — unowned and held at zero estate-wide.
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>
2026-07-23 21:56:07 +02:00
- Irreversible operational decisions without human approval.
2026-08-29 11:57:37 +02:00
- Direct Tooling-layer clients — Staff and agents reach tenant facts
through this Engine, not past it.
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>
2026-07-23 21:56:07 +02:00
## Current State
2026-08-29 11:57:37 +02:00
Production service, not a bootstrap. Finished workplans `TEN-WP-0001`
through `TEN-WP-0007` , `TEN-WP-0009` , and `TEN-WP-0010` shipped the domain
model, the three boundary-contract APIs, the `flex-auth` write authorizer,
lifecycle, guardrails, PostgreSQL as the production store, and mutable
grouping. `TEN-WP-0008` (staged-promotion onboarding) is still `ready` ,
not done.
| Surface | Shipped | Notes |
| --- | --- | --- |
| Domain model + SQLite/in-memory store | yes | `TEN-WP-0002` |
| Cache-read / live-lookup / write APIs | yes | `TEN-WP-0002` |
| `flex-auth` `WriteAuthorizer` | yes | Fail-closed; `is_allowed()` returns a bool and **discards the decision envelope** |
| Production runtime | yes | `TEN-WP-0004` ; image pin in `deploy/tenant-engine.yaml` |
| Lifecycle (update / retire / reactivate) | yes | `TEN-WP-0005` ; no hard-delete |
| Guardrail policy | yes | `TEN-WP-0006` / `0007` ; `docs/tenant-guardrail-policy.md` |
| PostgreSQL production store | yes | `TEN-WP-0009` ; deploy mounts `TENANT_ENGINE_DATABASE_URL_FILE` |
| Mutable grouping | yes | `TEN-WP-0010` ; identifier segment stays historical |
| Staged promotion | **no** | `TEN-WP-0008` |
2026-08-29 13:02:51 +02:00
| Machine-readable `layer.yaml` | yes | `TEN-WP-0011-T01` ; check in `scripts/check_layer_conformance.py` |
| Persisted `authorization_decision_id` | yes | `authz_records` plus mutation event payload (`TEN-WP-0011-T02` ) |
| Published unreachable-engine stance map | yes | `pep-stance.yaml` , fail-closed, tested equal to shipped behaviour |
| Independent audit-core emission | path shipped, sender pending | Local outbox + POST `/v1/events` ; `AUDIT-IN-0002` |
| Bounded event-read interface | yes | `events_for(tenant_id)` only (`TEN-WP-0011-T05` ) |
| Claim freshness / input-class lifetime | yes | `pip-claims.yaml` (`TEN-WP-0011-T03` ) |
2026-08-29 11:57:37 +02:00
The boundary contract still labels guardrail policy "reserved, not
implemented" and still calls this repo "not a policy enforcement point".
Both sentences are stale: guardrails shipped, and the write path is
PEP-shaped even though this repo is not a PDP. Amendment is a
`net-kingdom` change, requested from `TEN-WP-0011` .
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>
2026-07-23 21:56:07 +02:00
## Getting Oriented
- Start with: `INTENT.md`
2026-08-29 11:57:37 +02:00
- Working companion: `net-kingdom/SECURITY-COMPANION.md`
- Statute: `net-kingdom/canon/standards/security-layer-model_v0.7.md`
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>
2026-07-23 21:56:07 +02:00
- Ownership contract: `net-kingdom/canon/standards/tenant-engine-boundary-contract_v0.1.md`
- Claim/carrying mechanism: `net-kingdom/canon/standards/iam-profile_v0.3.md`
2026-08-29 11:57:37 +02:00
- Layer declaration: `decisions/decisions.md` `TEN-DEC-2026-001`
- Review: `history/2026-08-29-security-layer-intent-scope-review.md`
- Evolution workplan: `workplans/TEN-WP-0011-security-layer-conformance.md`
TEN-WP-0003: FlexAuthWriteAuthorizer -- gate writes through flex-auth
flex_auth.py: CheckRequest + FlexAuthCheckClient against flex-auth's real
POST /v1/check contract (schemas/check_request.schema.json,
decision_envelope.schema.json, read directly from the flex-auth repo, not
guessed). Fail-closed by construction: only effect=="allow" authorizes;
every other effect, non-200, malformed body, or transport failure resolves
to deny, nothing raises past is_allowed().
authz.FlexAuthWriteAuthorizer implements the existing WriteAuthorizer
Protocol. Action -> resource-type mapping coordinated with FLEX-WP-0008's
planned vocabulary (both repos reference the same table).
DefaultDenyWriteAuthorizer stays the fallback when no flex-auth URL is
configured.
config.py: Settings.from_env(), mirroring qonto-assistant's pattern.
docs/flex-auth-integration.md documents the contract, fail-closed rule,
and current real state (denies everything until FLEX-WP-0008 lands).
60 tests passing. Verified live twice over real HTTP between separate
processes (not just MockTransport): a deny-returning flex-auth double
produces 403 from POST /tenants, an allow-returning one produces 201.
Also registered (not implemented) the two workplans this depends on for a
complete picture: flex-auth/FLEX-WP-0008 (protected-system registration --
what makes allow reachable) and key-cape/KEY-WP-0005 (discovered key-cape
emits none of iam-profile_v0.3.md's core claims yet, not just missing
tenant_roles -- a bigger, security-sensitive gap flagged rather than
quietly worked around).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 22:54:44 +02:00
- flex-auth write-authorization integration: `docs/flex-auth-integration.md`
2026-08-29 11:57:37 +02:00
- Guardrail contract: `docs/tenant-guardrail-policy.md`
- Lifecycle contract: `docs/tenant-lifecycle-api.md`
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>
2026-07-23 21:56:07 +02:00
- Agent instructions: `AGENTS.md` , `CLAUDE.md`
- Workplans: `workplans/`