the-custodian/canon/architecture/adr-008-multi-tenancy-model.md

35 lines
1.4 KiB
Markdown
Raw Normal View History

ADR-008: multi-tenancy model — four planes, one isolation ladder (proposed) The estate has built multi-tenancy across five documents that each cover a slice and do not compose. This records the whole model and names what is missing. Core framing: multi-tenancy here is four orthogonal planes — identity, authorization, data isolation, placement — not one property. Identity and authorization are ratified and solid. Data isolation is stated but unverified. Placement is owned by nobody and is precedent-by-accident. Three findings that motivated the draft: - R0 -> R1 -> R2 does not improve tenant isolation at all. Those rungs buy consumer isolation and capacity. Only R3 makes the tenant boundary structural. A plan tier selling R2 as isolation would be false. - No fleet mechanism verifies that any consumer actually enforces the tenant boundary it is obliged to enforce. A missing WHERE tenant_id would be a cross-tenant breach that no probe fails and no log shows as an error. Highest-severity gap; needs an appointed owner. - platform-pg holds roughly six consumers (100 max_connections, 14 each) and memory likely binds before connections do. Two are provisioned. The runway is shorter than the ladder implies. Also reconciles two already-ratified and contradictory defaults: instance-per-client for business apps, pooled for platform services, with no rule for telling a new service which it is. Proposed, not ratified. Carries a ratification path so it does not join the shared-platform-relational-storage draft in limbo. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 11:26:07 +02:00
---
id: ADR-008
type: architecture-decision-record
title: "Multi-Tenancy Framework — relocated to NetKingdom"
status: superseded
ADR-008: multi-tenancy model — four planes, one isolation ladder (proposed) The estate has built multi-tenancy across five documents that each cover a slice and do not compose. This records the whole model and names what is missing. Core framing: multi-tenancy here is four orthogonal planes — identity, authorization, data isolation, placement — not one property. Identity and authorization are ratified and solid. Data isolation is stated but unverified. Placement is owned by nobody and is precedent-by-accident. Three findings that motivated the draft: - R0 -> R1 -> R2 does not improve tenant isolation at all. Those rungs buy consumer isolation and capacity. Only R3 makes the tenant boundary structural. A plan tier selling R2 as isolation would be false. - No fleet mechanism verifies that any consumer actually enforces the tenant boundary it is obliged to enforce. A missing WHERE tenant_id would be a cross-tenant breach that no probe fails and no log shows as an error. Highest-severity gap; needs an appointed owner. - platform-pg holds roughly six consumers (100 max_connections, 14 each) and memory likely binds before connections do. Two are provisioned. The runway is shorter than the ladder implies. Also reconciles two already-ratified and contradictory defaults: instance-per-client for business apps, pooled for platform services, with no rule for telling a new service which it is. Proposed, not ratified. Carries a ratification path so it does not join the shared-platform-relational-storage draft in limbo. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 11:26:07 +02:00
decided_by: Bernd Worsch
date: "2026-08-17"
---
# ADR-008 — relocated
ADR-008: multi-tenancy model — four planes, one isolation ladder (proposed) The estate has built multi-tenancy across five documents that each cover a slice and do not compose. This records the whole model and names what is missing. Core framing: multi-tenancy here is four orthogonal planes — identity, authorization, data isolation, placement — not one property. Identity and authorization are ratified and solid. Data isolation is stated but unverified. Placement is owned by nobody and is precedent-by-accident. Three findings that motivated the draft: - R0 -> R1 -> R2 does not improve tenant isolation at all. Those rungs buy consumer isolation and capacity. Only R3 makes the tenant boundary structural. A plan tier selling R2 as isolation would be false. - No fleet mechanism verifies that any consumer actually enforces the tenant boundary it is obliged to enforce. A missing WHERE tenant_id would be a cross-tenant breach that no probe fails and no log shows as an error. Highest-severity gap; needs an appointed owner. - platform-pg holds roughly six consumers (100 max_connections, 14 each) and memory likely binds before connections do. Two are provisioned. The runway is shorter than the ladder implies. Also reconciles two already-ratified and contradictory defaults: instance-per-client for business apps, pooled for platform services, with no rule for telling a new service which it is. Proposed, not ratified. Carries a ratification path so it does not join the shared-platform-relational-storage draft in limbo. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 11:26:07 +02:00
Drafts 14 of the multi-tenancy framework were written here. On 2026-08-17 the
operator determined that multi-tenancy is part of the IT-security framework
NetKingdom provides, so the framework belongs in NetKingdom canon beside the
IAM Profile and the tenant-engine boundary contract.
ADR-008: multi-tenancy model — four planes, one isolation ladder (proposed) The estate has built multi-tenancy across five documents that each cover a slice and do not compose. This records the whole model and names what is missing. Core framing: multi-tenancy here is four orthogonal planes — identity, authorization, data isolation, placement — not one property. Identity and authorization are ratified and solid. Data isolation is stated but unverified. Placement is owned by nobody and is precedent-by-accident. Three findings that motivated the draft: - R0 -> R1 -> R2 does not improve tenant isolation at all. Those rungs buy consumer isolation and capacity. Only R3 makes the tenant boundary structural. A plan tier selling R2 as isolation would be false. - No fleet mechanism verifies that any consumer actually enforces the tenant boundary it is obliged to enforce. A missing WHERE tenant_id would be a cross-tenant breach that no probe fails and no log shows as an error. Highest-severity gap; needs an appointed owner. - platform-pg holds roughly six consumers (100 max_connections, 14 each) and memory likely binds before connections do. Two are provisioned. The runway is shorter than the ladder implies. Also reconciles two already-ratified and contradictory defaults: instance-per-client for business apps, pooled for platform services, with no rule for telling a new service which it is. Proposed, not ratified. Carries a ratification path so it does not join the shared-platform-relational-storage draft in limbo. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 11:26:07 +02:00
**It now lives at `net-kingdom/canon/standards/tenancy-posture_v0.1.md`.**
ADR-008 draft-2: reframe from fixed model to graduated framework Draft-1 proposed one model of multi-tenancy with fixed characteristics. Rejected: the estate needs a framework that can hold several situations at once, including repos that do not separate tenants rigorously today and must be developed toward doing so. What changed: - Every plane now carries an ordered ladder (I0-I3, A0-A3, E0-E4, P0-P4), not just placement. A service is a posture vector, not a verdict. - D3 reversed. Draft-1 forbade RLS as a control that "looks like a database guarantee without being one". The observation was right, the conclusion wrong: RLS is E3, materially stronger than E2, and the actual error was calling E3 by E4's name. Platform enforcement is now the direction of travel and an obligation on the platform, not only on consumers. - New governing rule: conformance is accuracy, not altitude. Declaring E0 is conformant; concealing it is not. Overclaiming is the only violation. - Fixed a flaw of draft-1's own making: R0 "shared tables, tenant column" was an enforcement state mislabelled as placement. Removed; P ladder renumbered. - Added methodology (analyze/establish/improve/guard) and per-level evidence artifacts. Guarding checks a service against its own declaration, which is what makes the verification problem tractable at all. - D7 softened per operator: tiers carry minimum levels internally, marketing language stays free, the constraint is on evidence not vocabulary. One hard line kept: "another tenant cannot reach your data" requires E4. Ratification now also tests the framework — each reviewing repo publishes its posture vector, and if a repo cannot express itself in these ladders the ladders are wrong, not the repo. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 12:20:49 +02:00
Two things changed on relocation:
ADR-008 draft-4: apply the eight amendments the gap research forced R4 now has a mechanism. It splits into horizon-elapsed (wait out a window somebody else's retention set - available to all, proves little) and key-destroyed (encrypt per entity, destroy the key, immediate). A service must name which route it uses. The regulatory position is stated rather than implied: DPAs have accepted key destruction as erasure where physical deletion is disproportionate, under conditions, and the EDPB has not formally endorsed it. Section 11.4 now says a service may make that claim but not in language implying a regulator blessed it. Overclaiming here would be worse than anywhere else in the document. Third coupling recorded: shredding a single tenant's data needs the application to encrypt under a per-tenant key before writing, so the top of the retention ladder is an enforcement-plane capability. Reaching R4 is not a retention project. The noisy-neighbour artifact was replaced. It had required proof that a saturating consumer does not breach another's allowance, which shared infrastructure cannot provide - an artifact that can only fail, or passes by being run gently, is an overclaim in the costume of evidence. It now measures: baseline, saturation run, proof the controls bind, recorded degradation. Generalised as decision 13.4. The connection ceiling is reframed. Seven consumers each politely inside a 14-connection allowance still exhaust the instance, so the number is the aggregate noisy-neighbour bound, and our per-consumer governance guards the other shape entirely. Also: quota transparency as a disclosure obligation (10.2) - a consumer learning its statement timeout by hitting it in production is our failure, not theirs; and two new open questions - crypto-shredding an audit trail destroys what audit-core exists to hold, and we have no QoS vocabulary despite a latency-critical consumer sharing an instance with a batch one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 14:49:00 +02:00
1. The five dimensions were renamed from **planes** to **axes**. NetKingdom's
accepted `platform-identity-security-architecture` already uses *plane* for
a trust and deployment layer (bootstrap / platform control / tenant), and
two senses of one word in one canon is a concept-ownership collision.
2. The opening claim that the estate "has never written down what it is
building" was corrected. That architecture document has described the trust
and tenant model since 2026-07-23. What was actually missing is a way to say
how far a given service has got.
ADR-008 draft-3: corrections, plane R, and a name Renamed to Tenancy Posture. Four Planes stopped being true and a name that encodes a count breaks every time the framework grows; the posture vector is the durable centre. Corrections from the research digests: - E3 no longer claims the application cannot route around it. Any session can re-SET the GUC, so E3 is decisive against a forgotten predicate and useless against SQL injection or a compromised process. Replaced the claim with a threat-model table. Draft-2 was overclaiming in exactly the way section 6 prohibits, which is the correction I most wanted made before review. - E3 layers on E2 rather than replacing it; claiming E3 now requires the E2 artifact too, because E3 alone fails open under injection. - The GUC is set transaction-locally, not at pool checkout, and the scaling section's pooling claim was backwards: SET LOCAL is what makes E3 safe under a pooler; statement-level pooling is what leaks. - Placement is a default plus per-tenant exceptions. One P level per service could not express the isolation tiers section 11 already sells. Added plane R for retention and erasure, implementing the rapp-postgres ADR-0002 interface: N-day retention defaulting to 30, a published erasure horizon, and dataset sweeps whose policy the consumer owns. R exists because deleting a row does not remove it from yesterday's backup, and the estate had never written that down. Also: A4 for a standard PDP interface now that AuthZEN is Final; evidence split into mechanical and adversarial, since a green CI run is not E2 evidence; the tenant boundary named as OWASP API1; and section 14 recording the structure-not-tooling stance. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 14:33:50 +02:00
This stub remains so that the ADR-008 identifier resolves rather than
dangling. It is not a second copy and must not be edited as one.
ADR-008: multi-tenancy model — four planes, one isolation ladder (proposed) The estate has built multi-tenancy across five documents that each cover a slice and do not compose. This records the whole model and names what is missing. Core framing: multi-tenancy here is four orthogonal planes — identity, authorization, data isolation, placement — not one property. Identity and authorization are ratified and solid. Data isolation is stated but unverified. Placement is owned by nobody and is precedent-by-accident. Three findings that motivated the draft: - R0 -> R1 -> R2 does not improve tenant isolation at all. Those rungs buy consumer isolation and capacity. Only R3 makes the tenant boundary structural. A plan tier selling R2 as isolation would be false. - No fleet mechanism verifies that any consumer actually enforces the tenant boundary it is obliged to enforce. A missing WHERE tenant_id would be a cross-tenant breach that no probe fails and no log shows as an error. Highest-severity gap; needs an appointed owner. - platform-pg holds roughly six consumers (100 max_connections, 14 each) and memory likely binds before connections do. Two are provisioned. The runway is shorter than the ladder implies. Also reconciles two already-ratified and contradictory defaults: instance-per-client for business apps, pooled for platform services, with no rule for telling a new service which it is. Proposed, not ratified. Carries a ratification path so it does not join the shared-platform-relational-storage draft in limbo. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 11:26:07 +02:00
The publication renderer that lived in `tools/` moved to `policy-nexus`, which
owns publication.