diff --git a/canon/architecture/adr-007-workplan-identity-and-repo-worker-topology.md b/canon/architecture/adr-007-workplan-identity-and-repo-worker-topology.md index 5da1407..55f8cbc 100644 --- a/canon/architecture/adr-007-workplan-identity-and-repo-worker-topology.md +++ b/canon/architecture/adr-007-workplan-identity-and-repo-worker-topology.md @@ -82,6 +82,13 @@ nothing prevents number reuse. **1. A workplan identifier is globally unique.** `PREFIX-WP-NNNN` names exactly one workplan across the entire fleet, for all time. +> **Amended 2026-08-17 by `ADR-009` decision 2.** Uniqueness and forward-only +> allocation are **namespace-scoped**, not global; global identity is the pair +> `(namespace, identifier)`, written `PREFIX-WP-NNNN@namespace` when foreign. +> Global sequential allocation would require a central coordinator — the exact +> dependency federation must survive. Everything below holds unchanged **within** +> a namespace, which is where all current work sits. + - A workplan prefix is owned by exactly one repository. No two repositories may use the same prefix. - A running number is never reused within a prefix, including after a workplan is @@ -96,8 +103,10 @@ It also inverts ADR-001 — a file carrying a hub's private key is the file holding hub state. *Target state (C2).* `state_hub_workstream_id` and `state_hub_task_id` become -**deterministic**: UUIDv5 derived from the globally unique `PREFIX-WP-NNNN` -identifier. Every instance computes the same value independently, writeback +**deterministic**: UUIDv5 derived from the workplan identifier. Per `ADR-009` +decision 3 the derivation input is the pair `(namespace, identifier)`, not the +identifier alone — deriving from the identifier alone would make two forks +holding unrelated work under the same number compute the same UUID. Every instance computes the same value independently, writeback becomes idempotent, and any number of hub instances may coexist without coordination. The field shape is unchanged, so consumers keep working; only the provenance of the value changes. diff --git a/canon/architecture/adr-009-federated-namespaces-and-reconciliation-limits.md b/canon/architecture/adr-009-federated-namespaces-and-reconciliation-limits.md new file mode 100644 index 0000000..ac4fe36 --- /dev/null +++ b/canon/architecture/adr-009-federated-namespaces-and-reconciliation-limits.md @@ -0,0 +1,172 @@ +--- +id: ADR-009 +type: architecture-decision-record +title: "Federated Namespaces, Qualified Identifiers, and the Limits of Reconciliation" +status: proposed +decided_by: Bernd Worsch +date: "2026-08-17" +tags: ["architecture", "federation", "namespace", "identity", "reconciliation", "fos", "adr-007", "adr-008"] +--- + +# ADR-009: Federated Namespaces, Qualified Identifiers, and the Limits of Reconciliation + +## Status + +Proposed. Amends `ADR-007` decision 1 and extends `ADR-008` decision 4. + +## Context + +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 +requirements, but `federated-organization-standard_v1.0` already resolves the +organizational half: + +> global coherence is achieved through policy, escalation, and shared protocols +> rather than through monolithic control (`:51`) +> +> bounded autonomy plus disciplined coordination (`:86`) + +Authority is a **policy** layer; availability is a **mechanism**. Nothing +requires the mechanism to depend on reaching the authority — the same separation +distributed version control makes, where an integration branch is privileged by +agreement rather than by any technical property. + +**One accepted decision does violate this.** `ADR-007` decision 1 requires +running numbers that are *globally* unique and allocated forward only. Global +sequential allocation requires a coordinator — precisely the central dependency +federation must survive. Two disconnected forks each allocating +`RCLUSTER-WP-0015` is not an edge case but a certainty. + +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 +to forking before the identifier scheme could express it. + +## Decision + +**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 +operate disconnected. It is the unit of sovereignty in FOS terms, and the unit of +divergence here. + +**2. Identifiers are unique within a namespace, qualified across namespaces.** +`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: + +```text +RCLUSTER-WP-0015 this namespace — the common case, unchanged +RCLUSTER-WP-0015@railiance01 a foreign namespace, explicitly qualified +``` + +Unqualified always means "in my own namespace", exactly as `main` does against +`origin/main`. A suffix keeps existing sorting, grep, and tooling working; a +prefix would break them. + +**3. Deterministic identifiers derive from the pair.** `ADR-007` decision 2 (C2) +derives UUIDv5 from `PREFIX-WP-NNNN`. Under federation the derivation input must +be `(namespace, identifier)`. Deriving from the identifier alone would make two +forks holding unrelated work under the same number compute the *same* UUID — +a collision manufactured by the fix. C2 is not yet built, so this is free now and +expensive later. + +**4. Records carry lineage.** A namespace records what it forked from and at what +point; a record forked from another namespace records its origin. Without +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-008` +decision 4: status and other mutable fields are a fold over append-only events +rather than fields to be reconciled. Reconciliation then becomes union-of-events +plus re-derivation — deterministic, order-independent, and requiring no +conflict model. This collapses the hardest part of reconciliation into the part +that was already free. + +**6. 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. 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 +do not.** Two namespaces may hold divergent plans about one production database; +they cannot hold divergent production databases. Work that acts on shared +operational infrastructure is not fork-safe and must be coordinated through the +owning namespace. + +## Reconciliation tiers, and where automation stops + +| Tier | Situation | Mechanism | Automatable | +|---|---|---|---| +| **T0 Fork** | namespace created, lineage recorded | metadata | yes | +| **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 | +| **T3 Amalgamation** | **distinct operational infrastructure**, identity, credentials, data stores, possibly distinct canon | 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 +companies far more than a version-control merge, and must be planned as such: + +- due diligence — inventory both sides, item by item; +- survivor decisions per subsystem — keep, move, replace, retire; +- migration with evidence, and decommissioning of what does not survive; +- governance integration — reconciling two bodies of canon is a human act, + never automated; +- identity, credential, and data custody consolidation. + +**T3 may legitimately end without integration.** Permanent coexistence, or +divestment, are valid outcomes. Real mergers most often fail at systems +integration; an architecture that assumes eventual convergence is lying about +its own limits. + +### Known cost + +`prj-state-hub-retirement` is a T3 reconciliation inside a *single* +organization — two hub implementations with distinct infrastructure. It required +a dedicated project repository, a 425-item disposition inventory (`SHR-INV-0001`), +staged migration with strangler adapters, and explicit retirement gates. That is +the realistic cost of T3 under the most favourable possible conditions: one +owner, one canon, one credential authority. + +Nothing in this ADR reduces that cost. It ensures the cost is **visible before** +a fork is created rather than discovered when reconciliation is attempted. + +## Consequences + +**Positive.** Disconnected operation stops requiring a coordinator for identity. +`ADR-007` decision 1's contradiction is resolved rather than tolerated. Client +instances become expressible. Reconciliation limits are stated rather than +implied. + +**Negative.** Every record gains a namespace and lineage, and tooling must learn +qualified references. The fork-boundary rule (decision 7) constrains what +disconnected work may legitimately do — deliberately. + +**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; +it needs a project repository and human judgement. + +**Amended.** `ADR-007` decision 1 — uniqueness is namespace-scoped, not global. +`ADR-007` decision 2 — derivation input becomes `(namespace, identifier)`. + +## Open question + +**What is the namespace boundary in practice?** Candidates: a fleet instance +(`railiance01`), a client deployment, or an FOS autonomous domain. FOS's +recursion ("from projects to companies to foundation-like umbrella structures") +suggests namespaces nest, which would make qualification relative rather than +absolute. Settle before implementation; the notation works either way. + +## References + +- `canon/standards/federated-organization-standard_v1.0.md` — bounded autonomy, + escalation, sovereignty by default, rebuildability +- ADR-001 — workplans originate as repo files +- ADR-007 — identifier uniqueness and derived identifiers (amended here) +- ADR-008 — hub authority, local cache, and the two kinds of hub data +- `CUST-WP-0058` — instance-per-client tenancy +- `SHR-INV-0001` — 425-item disposition inventory, T3 cost evidence