diff --git a/canon/architecture/adr-006-canon-federation-concept-ownership.md b/canon/architecture/adr-006-canon-federation-concept-ownership.md index 49c0375..733e030 100644 --- a/canon/architecture/adr-006-canon-federation-concept-ownership.md +++ b/canon/architecture/adr-006-canon-federation-concept-ownership.md @@ -2,10 +2,9 @@ id: ADR-006 type: architecture-decision-record title: "Canon Federation and Concept Ownership Across InfoTech and Commerce" -status: accepted +status: proposed decided_by: Bernd Worsch date: "2026-08-16" -accepted: "2026-08-17" tags: ["architecture", "canon", "concept-ownership", "info-tech-canon", "commerce-canon", "identity", "orthogonality"] --- @@ -13,8 +12,8 @@ tags: ["architecture", "canon", "concept-ownership", "info-tech-canon", "commerc ## Status -Accepted 2026-08-17. All seven ownership questions are resolved (see -Resolutions); content may now move under `CFED-WP-0001`. +Proposed. Canon changes are review-gated; this ADR is the review artifact for +the identity/commerce split and must be accepted before content moves. ## Context @@ -115,13 +114,10 @@ than identity-owned definitions. `Customer` · `Vendor` · `Commercial Relationship` · `Commercial Commitment` · `Payment Instrument Reference` · `Payment Mandate` · `Pipeline Pursuit` · `Commercial Record` · `Counterparty Assurance Gradient` · `Reputation Signal` · -`Performance Evidence` · `Registry Identifier` · +`Performance Evidence` · `Adjudication Outcome` · `Registry Identifier` · `Proxy Commercial Identifier` · convenience terms `Reputation`, `Customer Account` -*Owned by `itc-evid`, the evidence model (see R3, R5, R7):* -`Evidence` · `Evidence Source` · `Adjudication Outcome` - Identifier subtypes demonstrate the intended pattern: `itc-ident` owns `Identifier`; `commerce-canon` owns `Registry Identifier` and `Proxy Commercial Identifier` as specializations of it. @@ -137,112 +133,26 @@ the canon does not push. organizational architecture, human-gated — not commercial vocabulary. If it ever moves, it becomes an InfoTechCanon organization standard, not a CommerceCanon one. -## Resolutions +## Open questions -The six collisions listed at draft time, resolved 2026-08-17. Two were settled -by evidence already present in the models rather than by argument. +These are unresolved collisions that must be settled before the affected +concepts move. They are deliberately listed rather than silently decided. -**R1 — `Scope`: owned by `itc-ident`.** There is no head-on collision: -`itc-access` owns `ResourceScope` (`:717`, "the boundary within which access -applies"), a narrower concept, not a general `Scope`. `itc-ident` owns the -general concept, keeping it with `Tenant` and `Realm` — `Tenant` is defined as -"an administrative or isolation scope", so separating it from its genus would -split a definition from the concept it depends on. `itc-access` keeps -`ResourceScope` as a refinement. - -If `landscape` or `information-space` later need general scoping, promote -`Scope` to the kernel **on that demand signal**, not pre-emptively. - -**R2 — `Assurance Level`: owned by `itc-ident`, distinct from governance -assurance.** A false collision. `itc-gov` owns `AssuranceCase` (`:1178`, a -structured argument that a claim is justified) and `AssuranceConclusion` -(`:1184`). identity's `Assurance Level` is NIST SP 800-63-4 IAL/AAL/FAL — -graded confidence metadata on credentials, bindings, and federation assertions. -They share an English word and nothing else. Both models carry a disambiguation -note, because the word will keep causing this. - -Design principle P12 ("Distinguish Assurance Dimensions") carries over: IAL, -AAL, and FAL must not be collapsed into a single "trust level" on an account. - -**R3 — `Evidence` and `Evidence Source` are a general pair, owned together, and -not by commerce.** They are not competing definitions of one concept: - -- **Evidence Source** — an addressable information container: a document, file, - or other artifact identifiable by URI. -- **Evidence** — a distinct information item, textual or descriptive, drawn from - a source: a quotation, an extracted value, a specific assertion. - -Both may carry commentary. Which evidence is captured from a source depends on -the interest being served. - -Worked example: an invoice PDF is an Evidence Source; the amount, the issuer, -and the due date are separate Evidence items within it. The common electronic- -invoicing pattern of an XML embedding inside a signed PDF is exactly this -structure — evidence pre-extracted and bound to its source so the extraction is -itself tamper-evident. - -The pair is domain-neutral (it extends to criminal, regulatory, and scientific -evidence). Commerce, identity, and governance all **use** it; none owns it. -Consequently `itc-gov` no longer owns `Evidence`; it imports it. - -**R4 — `Relationship Tuple`: owned by `itc-access`.** Already modelled there -(`:549`, under `PolicyEvaluationEntity` beside `AuthorizationRequest`, -`AuthorizationDecision`, `DecisionReason`, `EvaluationContext`). identity-canon's -own entry agrees: "Relationship tuples are not canonical identity roots. They -project from actors, accounts, memberships, and delegations into authorization -domains." `itc-ident` must not define it. - -**R5 — `Adjudication Outcome`: follows R3, owned with the evidence pair.** Not -`itc-access` `AuthorizationDecision` (a PDP allow/deny, `:907`) and not `itc-gov` -`Decision` (a governance choice point). The concept is general rather than -commercial: an arbitration award, court judgment, or regulatory consent order is -evidence in employment, licensing, or compliance disputes as much as in -commercial ones. Commerce is a consumer, not the owner. - -Structurally it is **Evidence** — the outcome asserted — sourced from an -Evidence Source such as the judgment document. - -The `assurance_tier` dimension splits accordingly: the evidence model owns a -general evidence-strength dimension; `commerce-canon` owns the -`Counterparty Assurance Gradient` as its named four-tier application of it. - -**R6 — `Community` and `Household` extend `itc-org`; `Family` is a separate -concept area.** identity-canon defines "Family Or Household" as one entry. That -conflation is rejected. - -`Community` and `Household` are collective actors and slot under `itc-org`'s -existing `CollectiveActor` (`:363`, beside `Person`, `HumanActor`, -`NonHumanActor`), honouring P4 ("Model Collective Actors Without Collapsing -Them"). - -`Family` does not. Family carries substantial structure — kinship, guardianship, -dependency, care, and legal, biological, and social parenthood — which changes -over time and is subject to interpretation. Modelling it as one more collective -actor is the specific mistake most family-oriented software makes, and it is why -such software generally models families badly. It gets its own concept area. - -Scope discipline applies: the family area is **seeded, not authored**. Record the -concept, the privacy sensitivity already flagged in identity-canon ("may have -legal implications outside the canon's scope"), and the open modelling -questions. Do not build it out inside `CFED-WP-0001`; it grows on demand signal -like any other canon content. - -**R7 — the evidence pair lives in a dedicated model, `itc-evid`.** A new -InfoTechCanon model at `infospace/models/evidence/` owns `Evidence`, -`Evidence Source`, `Adjudication Outcome`, and the general evidence-strength -dimension. - -`itc-gov`, `itc-ident`, and `commerce-canon` import it. Three named consumers -existed before the model did, which is the demand signal the canon requires. - -Rejected alternative: leaving both with `itc-gov` as incumbent owner of -`Evidence`. That is cheaper and preserves the locality of the -Policy-Control-Evidence chain pattern (`:1391`), but it would force identity and -commerce to import "governance" in order to describe an invoice line item — -mis-signalling evidence as a governance sub-topic when it is domain-neutral. - -`itc-gov` retains `AssuranceCase`, `AssuranceConclusion`, `Audit`, and the -Policy-Control-Evidence pattern, now expressed over imported evidence concepts. +1. **`Scope`.** identity-canon P3 makes it first-class; `itc-access` uses "access + scope" throughout. Does `itc-ident` own `Scope` with `itc-access` importing, + or the reverse? +2. **`Assurance Level` vs `itc-gov` `Assurance`.** Specialization or distinct + concept? `Counterparty Assurance Gradient` builds on whichever wins. +3. **`Evidence Source` vs `itc-gov` `Evidence`.** Likely an `itc-gov` + specialization rather than an identity-owned concept. +4. **`Relationship Tuple`.** A Zanzibar/OpenFGA-style authorization primitive — + plausibly `itc-access`, not `itc-ident`. +5. **`Adjudication Outcome` vs `itc-access` `AuthorizationDecision` and `itc-gov` + `Decision`.** Three candidate owners. +6. **`Community`, `Family Or Household`.** Social collectives absent from + `itc-org`, which covers enterprise structures (`Team`, `Group`, + `OrganizationalUnit`). Recommend extending `itc-org` rather than placing them + in `itc-ident`. ## Consequences 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 deleted file mode 100644 index af8c357..0000000 --- a/canon/architecture/adr-007-workplan-identity-and-repo-worker-topology.md +++ /dev/null @@ -1,206 +0,0 @@ ---- -id: ADR-007 -type: architecture-decision-record -title: "Workplan Identity Uniqueness, Single Registrar, and Repo Worker Topology" -status: accepted -decided_by: Bernd Worsch -date: "2026-08-16" -accepted: "2026-08-17" -tags: ["architecture", "workplans", "identity", "state-hub", "repo-manager", "agents", "registrar"] ---- - -# ADR-007: Workplan Identity Uniqueness, Single Registrar, and Repo Worker Topology - -## Status - -Accepted 2026-08-17. Identifier uniqueness, the registrar model, lifecycle -protection, and worker topology are settled. - -**Remediation of existing collisions (§ Migration) remains an open ruling.** It -is disruptive, touches six repositories, and no active work depends on it — all -five duplicated identifiers are `finished`. - -## Context - -On 2026-08-16, `STATE-WP-0080` was found registered **twice, in two different -databases**, with two different workplan UUIDs and two disjoint sets of task -UUIDs: - -| Registrar | Workplan UUID | Reachable at `127.0.0.1:8000` | -|---|---|---| -| Workstation hub (`make api`, local postgres) | `03f38314` | yes | -| A second instance, over a second database | `bbfce36a` | **404** | - -The second instance is *not* identifiable from the commit author. -`custodian-sync@railiance.local` is a hardcoded default git identity in -`scripts/consistency_check.py:1899` (`GIT_SYNC_USER_NAME` / -`GIT_SYNC_USER_EMAIL`), so every machine running `fix-consistency` commits under -that name. The discriminator is the timezone: sync commits appear under both -`+0000` and `+0200` (the workstation's offset), which is independent evidence of -two machines writing to one repository. - -Both write their IDs into the same git-tracked workplan file, so each sync -overwrites the other's IDs and the file flip-flops on every round trip. The same -commit (`ff909e1`, "renormalize lifecycle state [auto]") also promoted the -workplan `proposed` → `active` without human review. - -A fleet scan of 955 hub workplans (525 with parseable `PREFIX-WP-NNNN` -identifiers) found this is not an isolated incident. Two distinct identity -defects are live: - -**Prefix reuse across repositories:** - -```text -CUST-WP- → state-hub, the-custodian -RAIL-BS-WP- → railiance-bootstrap, railiance-cluster -RAILIANCE-WP- → railiance-apps, railiance-forge, railiance-platform, railiance-telemetry -``` - -`PRJ-WP-` is a latent fourth: `statehub register` derives it from the `prj-` -flavor marker, so every project repository would collide (see `RMGR-WP-0004`). - -**Running-number reuse:** - -```text -CUST-WP-0000 the-custodian ×2 -CUST-WP-0010 the-custodian ×2 -CUST-WP-0045 the-custodian ×2 -RAILIANCE-WP-0015 railiance-platform, railiance-apps -RAILIANCE-WP-0016 railiance-platform ×2, railiance-apps -``` - -`RAILIANCE-WP-0015` is actively cited in operational memory as the cnpg-backup -gate in `railiance-apps`; a second record of the same name in -`railiance-platform` makes that citation ambiguous. - -The `C-26` consistency check already flags prefix nonconformance *within* a repo -against a canonical prefix, but nothing enforces uniqueness *across* repos, and -nothing prevents number reuse. - -## Decision - -**1. A workplan identifier is globally unique.** `PREFIX-WP-NNNN` names exactly -one workplan across the entire fleet, for all time. - -- 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 - cancelled, archived, or deleted. Numbers are allocated forward only. -- Prefixes are derived from the *project or repository identity*, never from a - flavor marker or category (`PRJ-WP-` is invalid by construction). - -**2. Hub identifiers stored in repository files must be derivable, not -database-local.** The defect is structural: a database-local key is stored in a -shared artifact, so each database overwrites the other's value on every sync. -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 -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. - -This has a hard prerequisite: deterministic derivation from a **non-unique** -identifier would manufacture collisions rather than remove them. Two project -repos sharing `PRJ-WP-` would compute the same UUID for different workplans. -Decision 1 must therefore be enforced before derivation ships. - -*Interim state (A).* Until derivation lands, exactly one instance writes hub -identifiers into repository files. Other instances may read, project, and serve, -but must not mint workplan or task UUIDs into git-tracked files. The interim -registrar is the automated production instance; workstation hubs are development -read replicas. - -The interim is policy, enforced by discipline, and it has a real cost: -registration requires connectivity to the registrar, so disconnected work cannot -register. That cost is accepted only until C2 removes the need for it, at which -point the number of hub instances becomes an availability choice rather than a -correctness constraint. - -*Rejected.* Collapsing to a single shared database (workstation hubs pointing at -the production database) would also make identifiers consistent by construction, -but it eliminates offline capability — cutting directly against `STATE-WP-0068` -(offline write buffer and edge relay) — and couples all local work to tunnel -availability. - -*Ownership.* Both the interim guard and the derivation belong to `repo-manager` -under decision `747011c6`, which already places file-backed record indexing and -reconciliation there. Building either in `state-hub` would invest in a component -being retired under `STATE-WP-0079`. - -Migration scope for C2: **758 workplan files** across the fleet currently carry -these fields. - -**3. Lifecycle status is not automatically promoted.** An automated -normalization pass may report drift; it may not move a workplan from `proposed` -to `active`. `proposed` means awaiting human review, and an automation that -promotes it destroys the meaning of the review gate. - -**4. Repository manipulation is performed by a worker agent in that -repository.** This is the default topology. - -- A worker acting in repo X owns changes to repo X. -- Multiple independent top-level workers inside a single repository are an - **exception**, requiring an explicit reason, not a routine mode of operation. -- Concurrent independent writers are what turned a two-registrar bug into - repeated git divergence. - -**5. Project (`prj-`) repositories may act across their participating -repositories.** When work is governed by a project repo, its tasks may direct -changes across every repository the project names, through the project's work -agent, where that is more efficient than delegating. - -This is a deliberate, scoped exception to decision 4: the project repo already -owns cross-repo sequencing and its `SCOPE.md` names its participants, so its -authority is declared rather than ad hoc. It does not license a worker in an -arbitrary repository to reach into others. - -## Consequences - -**Positive.** Workplan identifiers become citable without qualification. -Hub IDs stop flip-flopping in git. The `proposed` status regains meaning. -Cross-repo authority becomes something a repository declares rather than -something any session assumes. - -**Negative.** Existing collisions must be remediated (see below), which is -disruptive. Workstation sessions lose the ability to register workplans directly -and must route through the registrar or a worker in the owning repo. Prefix -allocation needs a fleet-level registry, which is new machinery. - -**Enforcement.** Prefix ownership, uniqueness, and forward-only numbering are -repository standards, so they belong to Repo Manager under decision `747011c6` -(`RMGR-WP-0004`), not to a hub. Canon defines the rule; Repo Manager checks it. - -## Migration — needs a separate ruling - -Three prefixes and five identifiers are already colliding. Remediation options, -in increasing cost: - -1. **Freeze and forward-fix.** Accept existing collisions as historical, enforce - uniqueness only for new workplans. Cheapest; leaves `RAILIANCE-WP-0015` - permanently ambiguous. -2. **Renumber the live collisions only.** Fix identifiers that are still cited or - active; leave `finished`/`archived` duplicates alone. -3. **Full renaming.** Give `railiance-apps`, `railiance-forge`, - `railiance-platform`, `railiance-telemetry` distinct prefixes, likewise - `railiance-bootstrap`/`railiance-cluster` and `state-hub`'s legacy `CUST-WP-` - files. Touches six repositories and every inbound reference. - -Recommendation: **option 2**, with option 3's prefix split applied only to repos -that are still creating new workplans under a shared prefix — a shared prefix -that is still growing keeps generating new collisions, while a dormant one does -not. - -All five duplicated identifiers are currently `finished`, so no active work is -blocked by deferring this. - -## References - -- Decision `747011c6` — repository standards belong to Repo Manager -- ADR-001 — workplans originate as repo files; hub is a read model -- `RMGR-WP-0004` — repository standards conformance and governed scaffolding -- `STATE-WP-0080` — register scaffolding handoff -- Fleet scan 2026-08-16: 955 hub workplans, 525 parseable identifiers, - 3 reused prefixes, 5 reused identifiers