docs(canon): ADR-011 draft-2 — federation as four planes with declared posture
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

Reworks federation from binary rules into the plane/ladder/posture form from
ADR-008 (Four Planes), reusing its vocabulary rather than adding a second
maturity language to the canon.

Four planes: Namespace, Autonomy, Reconciliation, Substrate, each with a
ladder. Draft-1's 'records fork, effects do not' becomes the S ladder.
Posture is declared in the repo per ADR-010 decision 4; the ecosystem's own
posture is recorded honestly as N1 U1 R1 S1.

Key additions: conformance is accuracy not altitude; an anti-overclaim rule
stating that namespace qualification is N-plane movement only and does not
make anything federation-capable, with a commercial clause for
instance-per-client claims; the reconciliation tier is now DERIVED from
participants' postures (any S3 entails T3), so rejoining cost is computable
before a fork exists rather than discovered during reconciliation; evidence
definitions per level; and guard via rmgr conform.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
codex 2026-08-18 18:24:05 +02:00
parent 1e2199ddc7
commit 47b2843df4

View file

@ -1,59 +1,134 @@
--- ---
id: ADR-011 id: ADR-011
type: architecture-decision-record type: architecture-decision-record
title: "Federated Namespaces, Qualified Identifiers, and the Limits of Reconciliation" title: "Federated Namespaces: Four Planes, Declared Posture, and the Limits of Reconciliation"
status: proposed status: proposed
decided_by: Bernd Worsch decided_by: Bernd Worsch
date: "2026-08-17" date: "2026-08-17"
tags: ["architecture", "federation", "namespace", "identity", "reconciliation", "fos", "adr-007", "adr-008"] revision: "draft-2"
tags: ["architecture", "federation", "namespace", "identity", "reconciliation", "posture", "fos", "adr-007", "adr-008", "adr-010"]
--- ---
# ADR-011: Federated Namespaces, Qualified Identifiers, and the Limits of Reconciliation # ADR-011: Federated Namespaces — Four Planes, Declared Posture, and the Limits of Reconciliation
## Status ## Status
Proposed. Amends `ADR-007` decision 1 and extends `ADR-010` decision 4. Proposed, draft-2. Amends `ADR-007` decisions 1 and 2; extends `ADR-010`
decision 4; adopts the plane/ladder/posture form and the accuracy-not-altitude
conformance rule from `ADR-008` (Multi-Tenancy Framework).
## Context ## Context
The ecosystem must be **federation-capable** — able to work without a live link The ecosystem must be **federation-capable** — able to work without a live link
to central services — and **chain-of-command efficient**. These read as opposing to central services — and **chain-of-command efficient**.
requirements, but `federated-organization-standard_v1.0` already resolves the `federated-organization-standard_v1.0` already resolves the organizational half:
organizational half:
> global coherence is achieved through policy, escalation, and shared protocols > global coherence is achieved through policy, escalation, and shared protocols
> rather than through monolithic control (`:51`) > rather than through monolithic control (`:51`)
> >
> bounded autonomy plus disciplined coordination (`:86`) > bounded autonomy plus disciplined coordination (`:86`)
Authority is a **policy** layer; availability is a **mechanism**. Nothing Authority is a **policy** layer; availability is a **mechanism**. Distributed
requires the mechanism to depend on reaching the authority — the same separation version control makes the same separation: an integration branch is privileged by
distributed version control makes, where an integration branch is privileged by agreement, never by a technical property.
agreement rather than by any technical property.
**One accepted decision does violate this.** `ADR-007` decision 1 requires **One accepted decision violates this.** `ADR-007` decision 1 requires running
running numbers that are *globally* unique and allocated forward only. Global numbers that are *globally* unique and allocated forward only. Global sequential
sequential allocation requires a coordinator — precisely the central dependency allocation requires a coordinator — precisely the central dependency federation
federation must survive. Two disconnected forks each allocating must survive. Two disconnected forks each allocating `RCLUSTER-WP-0015` is a
`RCLUSTER-WP-0015` is not an edge case but a certainty. certainty, not an edge case.
This is not hypothetical. Instance-per-client tenancy (`CUST-WP-0058`) already This is not hypothetical. Instance-per-client tenancy (`CUST-WP-0058`) already
means each client deployment is a fork of the stack; the business model committed makes every client deployment a fork of the stack; the business model committed
to forking before the identifier scheme could express it. to forking before the identifier scheme could express it.
### Why this draft changed form
Draft-1 stated federation as a set of binary rules — notably "records fork,
effects do not". That is a single verdict where a graduated declaration belongs,
and it is the same conflation `ADR-008` §03 diagnoses for multi-tenancy:
*"'Is this multi-tenant?' is treated as one question. It is four, and they are
independent."*
"Is this federation-capable?" is likewise not one question. A namespace can be
strong on identity and incapable of disconnected operation; it can operate
disconnected and have no way to reconcile afterwards. Draft-1 could not say so.
This draft reuses `ADR-008`'s vocabulary rather than inventing a parallel one.
Two competing maturity vocabularies in one canon would be its own collision.
## Decision ## Decision
**1. Records live in a namespace.** A namespace is a federated branch of the **1. Records live in a namespace.** A namespace is a federated branch of the
ecosystem — a fleet instance, a client deployment, an autonomous domain that may ecosystem — a fleet instance, a client deployment, an autonomous domain that may
operate disconnected. It is the unit of sovereignty in FOS terms, and the unit of operate disconnected. It is the unit of sovereignty in FOS terms and the unit of
divergence here. divergence here.
**2. Identifiers are unique within a namespace, qualified across namespaces.** **2. Federation is four orthogonal planes.**
`ADR-007` decision 1 is amended: uniqueness and forward-only allocation are
**namespace-scoped**, not global. Global identity is the pair
`(namespace, identifier)`.
Notation is a suffix: | Plane | Question | Vocabulary owner |
|---|---|---|
| Namespace **N** | How are records named and disambiguated across branches? | this ADR |
| Autonomy **U** | Can work proceed with no link to central services? | repo-manager |
| Reconciliation **R** | What happens when branches meet again? | repo-manager |
| Substrate **S** | Does this namespace hold independently diverging operational state? | railiance-platform |
**3. Each plane carries a ladder.** Higher is stronger, not better. The right
level is the one a namespace can evidence and its risk warrants.
```text
N0 no namespace concept; identifiers assume one global space
N1 namespace implied by deployment, never recorded
N2 namespace declared; identifiers namespace-scoped; qualification available
N3 N2 + lineage recorded, and derived identifiers keyed on (namespace, identifier)
U0 routine work requires the central service
U1 degraded read-only; writes blocked while disconnected
U2 work proceeds locally: file-derived state written to files, hub-native buffered
U3 U2 + exercised — a dated disconnection drill with evidence
R0 no defined path; divergence is unrecoverable
R1 manual, per-record comparison and hand resolution
R2 append-only events plus derived state: union and re-derive, deterministic
R3 R2 + lineage-aware; distinguishes divergence from collision automatically
S0 shares operational substrate with another namespace — cannot fork safely
S1 shared substrate, namespace-keyed
S2 dedicated substrate, no independent state divergence yet
S3 independent operational substrate with diverged state — the fork is real
```
**4. A namespace declares a posture vector**, in the repository rather than the
hub, consistent with `ADR-010` decision 4 (file-derived state) and `ADR-008`
decision 5.1.
```yaml
federation:
current: { N: 1, U: 1, R: 1, S: 1 }
target: { N: 3, U: 2, R: 2, S: 1 }
reviewed: "2026-08-18"
gap:
U: "Registration requires the registrar under ADR-007 decision 2 interim.
Lifts when derived identifiers land (RMGR-WP-0005-T03)."
```
**The ecosystem's own posture today is `N1 U1 R1 S1`** — one implied namespace,
disconnected registration blocked, reconciliation manual, substrate shared.
Declaring that is conformant. Claiming better is not.
**5. Conformance is accuracy, not altitude.** Adopted verbatim in force from
`ADR-008` §06: a namespace is conformant when its declared posture is accurate,
its target recorded, and it claims no level it cannot evidence. It is
non-conformant when it overclaims, at any altitude.
Declaring `S0` is conformant. Concealing `S0` is not. A repository may join at
any posture; it may not join silently. This matters more here than it does for
tenancy: the cost of discovering a true posture during reconciliation is the
whole difference between T2 and T3.
**6. Identifiers are unique within a namespace, qualified across.** `ADR-007`
decision 1 is amended: uniqueness and forward-only allocation are
**namespace-scoped**. Global identity is the pair `(namespace, identifier)`.
```text ```text
RCLUSTER-WP-0015 this namespace — the common case, unchanged RCLUSTER-WP-0015 this namespace — the common case, unchanged
@ -61,40 +136,77 @@ RCLUSTER-WP-0015@railiance01 a foreign namespace, explicitly qualified
``` ```
Unqualified always means "in my own namespace", exactly as `main` does against Unqualified always means "in my own namespace", exactly as `main` does against
`origin/main`. A suffix keeps existing sorting, grep, and tooling working; a `origin/main`. A suffix preserves existing sorting, grep, and tooling; a prefix
prefix would break them. would break them.
**3. Deterministic identifiers derive from the pair.** `ADR-007` decision 2 (C2) **7. Derived identifiers key on the pair.** `ADR-007` decision 2 (C2) derives
derives UUIDv5 from `PREFIX-WP-NNNN`. Under federation the derivation input must UUIDv5 from the identifier. Under federation the input must be
be `(namespace, identifier)`. Deriving from the identifier alone would make two `(namespace, identifier)`. Deriving from the identifier alone would make two
forks holding unrelated work under the same number compute the *same* UUID — forks holding unrelated work under the same number compute the *same* UUID — a
a collision manufactured by the fix. C2 is not yet built, so this is free now and collision manufactured by the fix. C2 is not yet built, so this is free now and
expensive later. expensive later.
**4. Records carry lineage.** A namespace records what it forked from and at what **8. The planes couple at their upper levels. State the coupling; do not use it
point; a record forked from another namespace records its origin. Without to argue the planes are one.**
lineage, a shared identifier is ambiguous between *the same work, diverged* and
*different work, colliding* — a distinction that cannot be reconstructed after
the fact.
**5. Mutable state is derived from an append-only log.** Extending `ADR-010` - `R3` requires `N3` — distinguishing divergence from collision requires lineage.
decision 4: status and other mutable fields are a fold over append-only events - A namespace may not sustain `U2` or above while below `R2`. Operating
rather than fields to be reconciled. Reconciliation then becomes union-of-events disconnected without deterministic reconciliation accumulates divergence that
plus re-derivation — deterministic, order-independent, and requiring no cannot later be merged. Autonomy without reconciliation is not federation; it
conflict model. This collapses the hardest part of reconciliation into the part is an unplanned fork.
that was already free. - `T3` is entailed by `S3` in any participant (decision 10).
**6. Coexistence is the normal case; merging is the exception.** The qualifier is **9. Anti-overclaim.** This is the most misusable fact in the framework, and it
primarily a **coexistence** mechanism, not merge preparation. Most forks — is the direct analogue of `ADR-008`'s `P0 → P1 → P2` warning.
client instances above all — are never intended to return. The architecture must
support permanent parallel operation as a first-class outcome, not as a failure
to reconcile.
**7. What may fork.** Canon, plans, knowledge, and records fork freely. **Effects > Adopting namespace-qualified identifiers is movement on the **N plane only**.
do not.** Two namespaces may hold divergent plans about one production database; > It buys disambiguation, citability, and coordinator-free allocation. It does
they cannot hold divergent production databases. Work that acts on shared > **not** raise autonomy, reconciliation, or substrate independence by one step.
operational infrastructure is not fork-safe and must be coordinated through the > A system at `N3 U0 R0 S0` cannot operate disconnected and cannot reconcile.
owning namespace.
No namespace may be described as "federation-capable", "independently operable",
or "able to run disconnected" on N-plane evidence alone. Such a claim requires
declared `U` and `R` levels with evidence behind them.
**Commercially**, client-facing claims about instance independence must cite the
`S` and `U` levels, never the identifier scheme. Instance-per-client tenancy is
sold on substrate independence; the qualifier does not supply it.
**10. The reconciliation tier is derived from participants' postures, not judged
after the fact.**
```text
any participant at S3 -> T3 (regardless of other planes)
all participants S<=S2 and R>=R2 -> T2 feasible
any participant below R2 -> T1 at best; manual thereafter
```
This is the practical payoff of declaring postures: the cost of rejoining is
**computable before a fork is created**, rather than discovered when
reconciliation is attempted.
**11. Coexistence is the normal case; merging is the exception.** The qualifier
is primarily a coexistence mechanism, not merge preparation. Most forks — client
instances above all — are never intended to return. Permanent parallel operation
is a first-class outcome, not a failure to reconcile.
**12. Evidence.** A claimed level requires evidence, per `ADR-008` §13.
| Level | Evidence |
|---|---|
| `N2` | namespace declared in the repo; qualified references resolve |
| `N3` | lineage fields present; a derived identifier reproduced by an independent implementation |
| `U2` | work completed with central unreachable, committed, later accepted without rework |
| `U3` | dated disconnection drill record |
| `R2` | replaying the union of events reproduces identical derived state |
| `R3` | a collision and a divergence, correctly distinguished, in test |
| `S2` / `S3` | substrate inventory naming the stateful systems and whether their state has diverged |
**13. Guard.** Declared postures regress silently. Posture is checked by the same
consistency machinery that checks repository standards (`RMGR-WP-0004-T02`,
`rmgr conform`), so a namespace that drops below its declared level is a
reported defect rather than a discovery. A regression found by guarding is a
defect; a regression declared in advance is a decision.
## Reconciliation tiers, and where automation stops ## Reconciliation tiers, and where automation stops
@ -102,11 +214,8 @@ owning namespace.
|---|---|---|---| |---|---|---|---|
| **T0 Fork** | namespace created, lineage recorded | metadata | yes | | **T0 Fork** | namespace created, lineage recorded | metadata | yes |
| **T1 Sync** | pull canon, plans, or knowledge from another namespace | append events, re-derive | largely | | **T1 Sync** | pull canon, plans, or knowledge from another namespace | append events, re-derive | largely |
| **T2 Reintegration** | fork returns; records diverged, **no independent operational infrastructure** | union events, re-derive, human-resolve genuine contradictions | partly | | **T2 Reintegration** | records diverged, no participant above `S2` | union events, re-derive, human-resolve genuine contradictions | partly |
| **T3 Amalgamation** | **distinct operational infrastructure**, identity, credentials, data stores, possibly distinct canon | governed programme — see below | **no** | | **T3 Amalgamation** | any participant at `S3` | governed programme — see below | **no** |
**The T2/T3 test is whether the fork established its own operational
infrastructure** — stateful systems with independently diverged state.
**T3 is not a merge.** It resembles the merger or acquisition of distinct **T3 is not a merge.** It resembles the merger or acquisition of distinct
companies far more than a version-control merge, and must be planned as such: companies far more than a version-control merge, and must be planned as such:
@ -120,46 +229,49 @@ companies far more than a version-control merge, and must be planned as such:
**T3 may legitimately end without integration.** Permanent coexistence, or **T3 may legitimately end without integration.** Permanent coexistence, or
divestment, are valid outcomes. Real mergers most often fail at systems divestment, are valid outcomes. Real mergers most often fail at systems
integration; an architecture that assumes eventual convergence is lying about integration; an architecture that assumes eventual convergence is lying about its
its own limits. own limits.
### Known cost ### Known cost
`prj-state-hub-retirement` is a T3 reconciliation inside a *single* `prj-state-hub-retirement` is a T3 reconciliation inside a *single*
organization — two hub implementations with distinct infrastructure. It required organization — two hub implementations, distinct infrastructure. It required a
a dedicated project repository, a 425-item disposition inventory (`SHR-INV-0001`), dedicated project repository, a 425-item disposition inventory (`SHR-INV-0001`),
staged migration with strangler adapters, and explicit retirement gates. That is staged migration with strangler adapters, and explicit retirement gates. That is
the realistic cost of T3 under the most favourable possible conditions: one the realistic cost of T3 under the most favourable conditions possible: one
owner, one canon, one credential authority. owner, one canon, one credential authority.
Nothing in this ADR reduces that cost. It ensures the cost is **visible before** Nothing here reduces that cost. Declared postures make it **visible before** a
a fork is created rather than discovered when reconciliation is attempted. fork is created rather than discovered when reconciliation is attempted.
## Consequences ## Consequences
**Positive.** Disconnected operation stops requiring a coordinator for identity. **Positive.** Disconnected operation stops requiring a coordinator for identity.
`ADR-007` decision 1's contradiction is resolved rather than tolerated. Client `ADR-007` decision 1's contradiction is resolved rather than tolerated. A
instances become expressible. Reconciliation limits are stated rather than namespace mid-journey can describe itself honestly instead of being
implied. non-conformant. Reconciliation cost becomes computable in advance. Client
instances become expressible.
**Negative.** Every record gains a namespace and lineage, and tooling must learn **Negative.** Every namespace gains a posture to declare and keep accurate, and
qualified references. The fork-boundary rule (decision 7) constrains what tooling must learn qualified references. Decision 8's coupling rule constrains
disconnected work may legitimately do — deliberately. disconnected operation to namespaces that can reconcile — deliberately.
**Deferred.** Merge machinery for T2 is **not** specified here and should not be **Deferred.** Merge machinery for T2 is **not** specified here and should not be
built until a real fork exists and needs it. T3 needs no machinery by definition; built until a real fork needs it. T3 needs no machinery by definition; it needs a
it needs a project repository and human judgement. project repository and human judgement.
**Amended.** `ADR-007` decision 1 — uniqueness is namespace-scoped, not global. **Amended.** `ADR-007` decision 1 — uniqueness is namespace-scoped.
`ADR-007` decision 2 — derivation input becomes `(namespace, identifier)`. `ADR-007` decision 2 — derivation input becomes `(namespace, identifier)`.
## Open question ## Open question
**What is the namespace boundary in practice?** Candidates: a fleet instance **What is the namespace boundary in practice?** Candidates: a fleet instance
(`railiance01`), a client deployment, or an FOS autonomous domain. FOS's (`railiance01`), a client deployment, or an FOS autonomous domain. FOS's
recursion ("from projects to companies to foundation-like umbrella structures") recursion — "from projects to companies to foundation-like umbrella structures" —
suggests namespaces nest, which would make qualification relative rather than suggests namespaces **nest**, which would make qualification relative rather than
absolute. Settle before implementation; the notation works either way. absolute, closer to DNS than to a flat handle. The notation survives either
answer, so implementation is not blocked, but the data model is unfinished until
it is settled.
## References ## References
@ -167,6 +279,9 @@ absolute. Settle before implementation; the notation works either way.
escalation, sovereignty by default, rebuildability escalation, sovereignty by default, rebuildability
- ADR-001 — workplans originate as repo files - ADR-001 — workplans originate as repo files
- ADR-007 — identifier uniqueness and derived identifiers (amended here) - ADR-007 — identifier uniqueness and derived identifiers (amended here)
- ADR-008 — Multi-Tenancy Framework; source of the plane/ladder/posture form and
the accuracy-not-altitude conformance rule
- ADR-010 — hub authority, local cache, and the two kinds of hub data - ADR-010 — hub authority, local cache, and the two kinds of hub data
- `CUST-WP-0058` — instance-per-client tenancy - `CUST-WP-0058` — instance-per-client tenancy
- `SHR-INV-0001` — 425-item disposition inventory, T3 cost evidence - `SHR-INV-0001` — 425-item disposition inventory, T3 cost evidence
- `RMGR-WP-0004-T02``rmgr conform`, the guard machinery