SCOPE.md still said TEN-WP-0008 was "ready, not done" two paragraphs above its own table listing staged promotion as shipped, and its list of finished workplans omitted 0008 and 0011. All twelve workplans are finished; say so once. .claude/rules/architecture.md still described `guardrail/` as a reserved, unimplemented namespace and the production store as TBD. Guardrails shipped in TEN-WP-0006/0007 and PostgreSQL became the production store in TEN-WP-0009. Also corrects the live-lookup caller to `access-engine`, matching SCOPE.md and the boundary contract. No behaviour change; 287 tests pass unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HHwvAEQfmzLHtrFGhXtVjq Assistant: claude-code Assistant-Model: opus Assistant-Process: 823014@bnt-lap001 Assistant-Session: 2a0786b1-efea-4c38-959b-6e86a493f259
7 KiB
SCOPE
Lightweight boundary for agents and contributors. Full contract:
net-kingdom/canon/standards/tenant-engine-boundary-contract_v0.1.md. Aspirational role:INTENT.md. Layer declaration: Engine / PIP (INTENT.mdfrontmatter;TEN-DEC-2026-001).
One-liner
Canonical PIP of tenant-as-an-entity facts for NetKingdom: existence, lifecycle, onboarding grouping, capability roles, plan/subscription assignment, and guardrail ceilings.
Core Idea
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. |
In Scope
- Tenant records: identifier, lifecycle (
active/retired), current onboarding grouping (ADR-0013). Grouping is mutable through an audited reclassification, not by renamingtenant_id. - Capability role grants/revocations:
PLTF/IAM/VEN/CUS(ADR-0014), audited, mostly plan-linked. - Plan/subscription assignment, referenced by
adaptive-pricingplan id. - Guardrail/quota policy: spend / entity-count / action-count ceilings,
resolved as a total function of grouping, plan, override, and lifecycle.
Seeded key:
spend.monthly.trialdefaults to zero. - Cache-read API for
key-cape(token-issuance-timetenant_rolesclaim source):GET /tenants/{id}/roles. - Live-lookup API for
access-engine(high-stakes,aal2-class decisions):GET /tenants/{id}/roles/live. Store unavailability returns503, never200plus 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.
Out of Scope
- Identity, authentication, MFA, token issuance —
key-cape/Keycloak. - Authorization decisions —
access-engineis the PDP;tenant-engineis a data source it queries, never the other way around. - Approval objects and approval lifecycle —
approval-engine. Contested inTEN-DEC-2026-001; this repo will not grow one. - Users, profiles, memberships —
user-engine.tenant_idis 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. - 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.
- Irreversible operational decisions without human approval.
- Direct Tooling-layer clients — Staff and agents reach tenant facts through this Engine, not past it.
Current State
Production service, not a bootstrap. Workplans TEN-WP-0001 through
TEN-WP-0011 are all finished: they shipped the domain model, the three
boundary-contract APIs, the flex-auth write authorizer, lifecycle,
guardrails, PostgreSQL as the production store, mutable grouping,
staged-promotion onboarding, and the security-layer conformance surfaces.
No workplan in this repo is currently open.
| 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/base/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 | yes (declared) | TEN-WP-0008; railiance/app.toml; live pin recorded as previous_stable. Helm CLI apply is a railiance-bootstrap gap (RAIL-BS-IN-0001). |
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) |
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.
Getting Oriented
- Start with:
INTENT.md - Working companion:
net-kingdom/SECURITY-COMPANION.md - Statute:
net-kingdom/canon/standards/security-layer-model_v0.7.md - 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 - Layer declaration:
decisions/decisions.mdTEN-DEC-2026-001 - Review:
history/2026-08-29-security-layer-intent-scope-review.md - Evolution workplan:
workplans/TEN-WP-0011-security-layer-conformance.md - flex-auth write-authorization integration:
docs/flex-auth-integration.md - Guardrail contract:
docs/tenant-guardrail-policy.md - Lifecycle contract:
docs/tenant-lifecycle-api.md - Agent instructions:
AGENTS.md,CLAUDE.md - Workplans:
workplans/