From 8754983a0d23daa8f0c5eb31572593452b38e627 Mon Sep 17 00:00:00 2001 From: tegwick Date: Fri, 28 Aug 2026 21:24:50 +0200 Subject: [PATCH] docs: define repository rename identity contract Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a049a4-ee9f-78e1-9d66-2cb0f9bea3e3 --- WORK-RECORDS.md | 4 +- ...001-repository-rename-identity-contract.md | 268 ++++++++++++++++++ docs/architecture/state-hub_v0.1.md | 9 +- 3 files changed, 277 insertions(+), 4 deletions(-) create mode 100644 docs/adr/ADR-001-repository-rename-identity-contract.md diff --git a/WORK-RECORDS.md b/WORK-RECORDS.md index 49efa45..4070173 100644 --- a/WORK-RECORDS.md +++ b/WORK-RECORDS.md @@ -55,7 +55,7 @@ | workplan | STATE-WP-0082 | finished | — | workplans/STATE-WP-0082-multi-owner-review-contracts-and-receipts.md | | workplan | STATE-WP-0083 | active | — | workplans/STATE-WP-0083-forge-derived-projection-reset.md | | workplan | STATE-WP-0084 | active | — | workplans/STATE-WP-0084-forge-read-for-private-repositories.md | -| workplan | STATE-WP-0085 | ready | — | workplans/STATE-WP-0085-repository-lineage-preserving-rename.md | +| workplan | STATE-WP-0085 | active | — | workplans/STATE-WP-0085-repository-lineage-preserving-rename.md | | task | STATE-WP-ADHOC-2026-06-04-T01 | done | — | workplans/ADHOC-2026-06-04.md | | task | STATE-WP-ADHOC-2026-07-01-T01 | done | — | workplans/ADHOC-2026-07-01.md | | task | STATE-WP-ADHOC-2026-07-01-T02 | done | — | workplans/ADHOC-2026-07-01.md | @@ -321,7 +321,7 @@ | task | STATE-WP-0084-T02 | progress | — | workplans/STATE-WP-0084-forge-read-for-private-repositories.md | | task | STATE-WP-0084-T03 | progress | — | workplans/STATE-WP-0084-forge-read-for-private-repositories.md | | task | STATE-WP-0084-T04 | wait | — | workplans/STATE-WP-0084-forge-read-for-private-repositories.md | -| task | STATE-WP-0085-T01 | todo | — | workplans/STATE-WP-0085-repository-lineage-preserving-rename.md | +| task | STATE-WP-0085-T01 | done | — | workplans/STATE-WP-0085-repository-lineage-preserving-rename.md | | task | STATE-WP-0085-T02 | todo | — | workplans/STATE-WP-0085-repository-lineage-preserving-rename.md | | task | STATE-WP-0085-T03 | todo | — | workplans/STATE-WP-0085-repository-lineage-preserving-rename.md | | task | STATE-WP-0085-T04 | todo | — | workplans/STATE-WP-0085-repository-lineage-preserving-rename.md | diff --git a/docs/adr/ADR-001-repository-rename-identity-contract.md b/docs/adr/ADR-001-repository-rename-identity-contract.md new file mode 100644 index 0000000..6d02ea2 --- /dev/null +++ b/docs/adr/ADR-001-repository-rename-identity-contract.md @@ -0,0 +1,268 @@ +--- +id: STATE-ADR-001 +type: architecture-decision-record +title: "Preserve repository identity across canonical-name changes" +status: accepted +owner: state-hub +date: "2026-08-28" +deciders: + - operator + - state-hub +related: + - STATE-WP-0085 + - CUST-ADR-007 + - CUST-ADR-012 +--- + +# Preserve repository identity across canonical-name changes + +## Status and scope + +Accepted for the implementation governed by `STATE-WP-0085`. This decision +defines the State Hub compatibility contract. It does not authorize a live +Forgejo rename. + +The contract covers a repository name change within one Forgejo instance and +owner. A Forgejo owner transfer is a different identity and authorization +problem and is out of scope. A product or runtime rename is also out of scope: +module paths, binaries, packages, image names, namespaces, releases, DNS names, +environment variables, policy vocabulary, and user-facing names change only +when the target repository's migration workplan says so. + +## Context + +State Hub already anchors most durable relationships to `managed_repos.id`, but +it also exposes the current repository slug through URLs, commands, generated +files, routing keys, cached projections, and historical evidence. Treating the +slug as identity would split history when a repository is renamed. Rewriting +every occurrence would instead erase provenance and make interrupted migration +recovery unsafe. + +Forgejo is authoritative for the Git repository. State Hub is authoritative +for its repository UUID, canonical slug, protected aliases, and rename-operation +evidence. Repository files remain authoritative for work records; State Hub +continues to be their read model in accordance with `CUST-ADR-012`. + +## Decision + +A repository is identified by an immutable State Hub UUID and a verified +immutable Forge identity. Its slug, name, URL, and checkout paths are mutable +coordinates. A rename changes coordinates on the existing repository row, +retains the former slug as a protected alias, and records an idempotent phased +operation. It never registers a replacement repository. + +### Identity model + +| Element | Authority | Mutability | Rename rule | +| --- | --- | --- | --- | +| State Hub repository UUID | State Hub | Immutable | The operation is addressed by UUID; it must be identical before and after every phase. | +| Forge provider/instance | Estate configuration | Immutable in this contract | A move between instances is not a rename. | +| Forge owner | Forgejo | Immutable in this contract | Owner transfer requires a separate contract. | +| Forge repository numeric ID | Forgejo | Immutable | Preflight must verify it; any mismatch fails closed. | +| Canonical repository slug/name | Forgejo, mirrored by State Hub | Mutable | Exactly one canonical slug names the repository at a time. | +| Prior slugs | State Hub | Append-only | Retained as protected aliases; they resolve to the same UUID and cannot be claimed by another live repository. | +| Clone/web URL | Forgejo | Mutable projection | Recomputed from verified forge coordinates; never used as durable identity. | +| Local and host checkout paths | Operator/registration | Mutable projection | Re-registered after a new clone; old paths remain evidence until explicit cleanup. | +| Default branch | Forgejo/Git | Mutable outside the rename | Captured by preflight and compared before mutation; rename does not change it. | +| Expected source commit | Git | Immutable preflight assertion | Apply fails if the selected branch head has moved; a fresh preflight is required. | +| Workplan/task identifiers and Hub UUIDs | Repository files/registrar | Immutable | Preserved without re-keying. Existing prefix values remain valid. | +| Historical event/message/provenance values | Producing system | Immutable evidence | Retain the value observed at event time; resolve aliases only when a live action is requested. | + +An implementation may normalize Forge identity into dedicated tables, but the +uniqueness boundary is `(provider instance, owner, forge repository ID)`. It +must not infer or backfill the numeric repository ID from a slug, URL, checkout, +or initial Git commit. + +### Invariants + +| ID | Invariant | Required proof | +| --- | --- | --- | +| I1 | A rename uses one `managed_repos` row. | Repository-row count and UUID are unchanged. | +| I2 | Forge repository identity is unchanged. | Provider, owner, and numeric ID match the accepted preflight. | +| I3 | The selected source is unchanged at cutover. | Default branch and expected head commit match the accepted preflight. | +| I4 | Work history and telemetry retain identity. | Workplan, task, progress, decision, token, SBOM, service, DoI, and TPSC relationships still reference the same repository UUID and their baseline counts/checksums match. | +| I5 | Existing work-record identifiers are not renamed. | No identifier or filename rewrite is caused solely by the slug change. | +| I6 | The former slug remains usable as an alias. | Old and new slug resolve to the same UUID; canonical responses identify the new slug. | +| I7 | Historical evidence is not rewritten. | Stored event, message, review, contribution, raw metadata, and source-provenance values remain byte-for-byte intact. | +| I8 | Each phase is idempotent. | Repeating a completed phase with the same operation ID is a no-op returning the achieved state. | +| I9 | Every incomplete state has one safe next action. | The operation exposes its achieved phase and recovery instruction. | +| I10 | Cleanup follows verification. | No alias, checkout, route, or rollback input is removed by this operation. | + +### Slug treatment vocabulary + +Every slug-bearing surface has exactly one primary treatment: + +| Treatment | Meaning | +| --- | --- | +| `foreign-key anchored` | Durable relationship already uses the repository UUID. Preserve the row; render the current canonical slug when needed. | +| `alias-resolved` | The value requests a live lookup, route, or mutation. Accept canonical or protected alias, resolve to one UUID, then emit the canonical slug. | +| `reprojected` | Derived data is rebuilt from repository files or current coordinates after cutover. Do not hand-edit cached rows. | +| `historically retained` | The string records what a producer observed. Never rewrite it; a separate repository UUID may be added for future records. | +| `target-repo handoff` | State Hub does not own the source. Generate an explicit task for its owner and verify the result. | + +## Slug-bearing surface inventory + +This inventory is the baseline for `STATE-WP-0085`. New slug-bearing fields +must declare one of the treatments above before they are added. + +### Persistence and domain models + +| Surface | Treatment | Owner and required behavior | +| --- | --- | --- | +| `managed_repos.slug`, `name`, `remote_url`, `local_path`, `host_paths`, `git_fingerprint` | alias-resolved | State Hub updates canonical coordinates on the existing UUID. Previous slug becomes a protected alias; previous paths/URL remain operation evidence. | +| `workplans.repo_id`, `repo_goals.repo_id`, `workplan_launch_requests.repo_id` | foreign-key anchored | State Hub preserves relationships and renders the canonical slug. Repository-file bindings are reprojected. | +| `token_events.repo_id`, `sbom_snapshots.repo_id`, `sbom_entries.repo_id`, `tpsc_snapshots.repo_id`, `service_first_party.repo_id`, `doi_cache.repo_id`, `capability_catalog.repo_id` | foreign-key anchored | State Hub preserves rows and history. Cached/materialized responses use the canonical slug after invalidation. | +| `intakes.repo_id` | foreign-key anchored | State Hub preserves the relationship. `source_repo_path` remains historical provenance. | +| `contributions.repo_id` | foreign-key anchored | State Hub preserves a known local target relationship. | +| `contributions.target_repo` | historically retained | Contribution producer owns the observed string; do not rewrite past records. New live inputs resolve aliases when a matching managed repository exists. | +| `agent_messages.from_agent`, `agent_messages.to_agent` | historically retained | State Hub retains delivered envelope values. Message creation and inbox lookup are alias-resolved, so the old repository agent name continues to reach the canonical inbox. Message bodies are never rewritten. | +| `interface_changes.repo_id` | foreign-key anchored | State Hub preserves the origin repository relationship. | +| `interface_changes.affected_repo_slugs` | historically retained | State Hub retains the audience recorded at publication. New publication, pending-recipient queries, and acknowledgements resolve aliases to UUID-equivalent recipients. | +| `work_record_identifier_aliases.repo_slug` | historically retained | Registrar owns identifier provenance. A repository-name alias must not rewrite or repurpose a work-record identifier alias. | +| `review_contracts.source_repo`, `review_receipts.source_repo`, and their `source_path` values | historically retained | Review producer owns source provenance. Future records may additionally bind a repository UUID. | +| `fabric_graph_imports.source_repo_slug`, `fabric_graph_nodes.source_repo_slug`, `fabric_graph_nodes.repo_slug`, `fabric_graph_edges.source_repo_slug` | target-repo handoff | Fabric source owns these projections. Re-import from the updated source and verify lineage; State Hub does not silently rewrite them. | +| Any `source_path`, `raw_metadata`, progress payload, decision text, or event payload containing the old slug | historically retained | The producing component owns the evidence. Search results may enrich it with current canonical identity, but storage is unchanged. | + +### REST API and serialization + +| Surface | Treatment | Owner and required behavior | +| --- | --- | --- | +| `/repos/{slug}` and `/repos/{slug}/paths`; repo lookup, dispatch, DoI, sync, remote-URL and fingerprint lookup responses | alias-resolved | Repositories router resolves aliases to UUID. A response includes canonical slug and whether the request used an alias; canonical links use the new slug. Mutations bind to UUID. | +| `/repo-goals?repo_slug`, `/sbom/{repo_slug}`, SBOM ingest/list filters, `/tpsc/snapshots?repo_slug` | alias-resolved | Owning routers resolve once through the repository resolver and query by UUID. | +| Capability-catalog, service-first-party, contribution, and workplan-file-binding request `repo_slug` fields | alias-resolved | Request handlers resolve old/new slug to the same UUID. Generated and response values use the canonical slug unless explicitly historical. | +| Message `from_agent`/`to_agent` creation and inbox query parameters | alias-resolved | Message router canonicalizes repository-agent routing for matching while retaining the original envelope. Non-repository agent names are unaffected. | +| Interface-change `repo_slug`, `affected_repo_slugs`, pending `origin_repo_slug`, and affected-repo filters | alias-resolved | Interface-change router resolves local repository recipients by UUID-equivalence and retains original publication evidence. | +| Fabric graph `source_repo_slug` and `repo` filters and payloads | target-repo handoff | Fabric importer accepts old evidence but refreshed canonical data comes from its source projection. | +| Review contract/receipt `source_repo` and contribution `target_repo` representations | historically retained | APIs return the recorded value and may add canonical-resolution metadata; they do not mutate history on read. | +| Repo token summaries, DoI, SBOM, TPSC, service, capability, consistency, and dispatch response slugs derived from `repo_id` | foreign-key anchored | Serializers render the canonical slug from the repository relationship. | + +### CLI, MCP, consistency, and generated files + +| Surface | Treatment | Owner and required behavior | +| --- | --- | --- | +| `statehub register`, repo update/paths/dispatch/DoI/sync commands, and repo-slug options | alias-resolved | State Hub CLI resolves existing aliases, refuses duplicate registration, and prints UUID plus canonical slug. A new checkout updates the same UUID. | +| MCP tools accepting `repo_slug` for repository updates, ADR validation, consistency, SBOM, TPSC, repo goals, dispatch, interface changes, and ad-hoc tasks | alias-resolved | MCP adapters use the same REST resolver and return canonical identity. They do not implement a second rename path. | +| `scripts/statehub_register.py` slug/path/remote/fingerprint discovery and scaffold output | alias-resolved | Registration script recognizes the Forge identity/alias before POST or PATCH and generates only canonical new material. | +| `scripts/consistency_check.py` repository lookup, host paths, file bindings, inbox queries, prefixes, and briefs | reprojected | Consistency tooling resolves aliases, reads the canonical repository files, and regenerates bindings/briefs without changing stable work-record IDs. | +| `.custodian-brief.md`, `WORK-RECORDS.md`, workplan-file bindings, repository indexes, and other generated repository-name views | reprojected | State Hub consistency projection regenerates current coordinates from canonical source and records its source revision. | +| Repository-native workplans, `AGENTS.md`, catalog/manifest files, and other source files containing the repository slug | target-repo handoff | The target repository migration workplan updates intentional live references and retains historical ones. State Hub verifies the committed source revision. | + +### Dashboard, events, edge, and external systems + +| Surface | Treatment | Owner and required behavior | +| --- | --- | --- | +| Dashboard repository list and `/repos/[slug]` route | alias-resolved | Dashboard accepts an old route, identifies alias use, and links/redirects to the canonical route without losing the UUID. | +| Dashboard domain, inbox, interface-change, TPSC, SBOM, service, and capability queries | alias-resolved | Dashboard passes either slug to the API and renders returned canonical identity. | +| Existing `org.statehub.repo.registered` events | historically retained | Event Router retains payloads. Registration is not emitted for rename. | +| New `org.statehub.repo.renamed` and rename-phase events | historically retained | State Hub emits operation ID, repository UUID, Forge identity, old/new slug, phase, actor, expected commit, and evidence reference. Events contain no credential. | +| Edge outbox `repo_slug` metadata and literal request path/body | historically retained | Edge relay preserves queued envelopes. Central alias-aware handlers replay old-slug requests against the same UUID. Rename phase mutations are never edge-queueable and require central availability. | +| Edge read-cache keys containing old/new slug | reprojected | Edge relay treats them as separate keys, invalidates repository-scoped keys on phase events, and returns canonical identity. Stale old-slug cache content must not authorize a mutation. | +| Forgejo repository name, web/clone URL, redirects, Actions variables, hooks, branch protection, packages, releases, and deploy keys | target-repo handoff | Forgejo/HelixForge operator performs and verifies the rename. Redirects are compatibility evidence, not canonical configuration. Owner transfer remains out of scope. | +| Downstream Git remotes, submodules, module/dependency references, CI consumers, image/package references, deployments, policies, credentials, fabric declarations, and documentation | target-repo handoff | Each owning repository or platform component receives a target-workplan task. Product/runtime-name changes require explicit decisions rather than following the repository slug automatically. | +| Local working copies and automation checkout paths | target-repo handoff | Operator clones the canonical URL, registers the new path against the existing UUID, verifies it, and only then removes an old checkout under a separately confirmed cleanup step. | + +## Operation and phase contract + +Every rename has an immutable operation UUID and captures: + +- State Hub repository UUID; +- Forge provider, instance, owner, and numeric repository ID; +- old and proposed canonical slug, name, URLs, and registered paths; +- default branch and expected head commit; +- preflight expiry and evidence checksum; +- actor, confirmation evidence, achieved phase, timestamps, and errors. + +Each phase is a compare-and-set transition. A caller requests one phase, not an +opaque multi-system transaction. Before changing anything, the phase handler +observes actual State Hub and Forgejo state. If the requested result is already +true for this operation, it returns success without repeating the side effect. +If reality corresponds to a later or conflicting state, it stops and reports +the observed facts. + +Live rename phase transitions are Red-lane operations. They require central +State Hub availability, an unexpired accepted preflight, explicit operator +confirmation, and the operation UUID. They are excluded from edge queued-write +allowlists. + +### Phase and interruption recovery + +| Phase | Durable truth | Allowed next phase | Safe action after interruption | +| --- | --- | --- | --- | +| `draft` | Intent exists; no identity assertion has been accepted. | `preflighted` or cancel draft | Run non-mutating preflight. It is always safe to abandon a draft. | +| `preflighted` | Forge identity, old/new availability, branch/head, baselines, effects, and expiry are recorded; no rename has occurred. | `forge-renamed` | Re-read Forgejo and State Hub. If any compare value changed, expire the preflight and run it again. Otherwise request only the Forge phase. | +| `forge-renamed` | Forgejo numeric ID now has the new name; State Hub may still expose the old canonical slug. | `statehub-rebound` or `rollback-preflight` | Verify Forge ID and commit. Prefer completing the State Hub rebind. If continuation is unsafe, first prove the old Forge slug is free, then enter rollback preflight. Do not register a new Hub repository. | +| `statehub-rebound` | Existing Hub UUID has the new canonical slug and protected old alias; Forge identity matches. | `source-synced` or `rollback-preflight` | Verify both slugs resolve to one UUID. Regenerate State Hub-owned projections and sync repository source. Alias compatibility makes pausing here safe. | +| `source-synced` | Target repository source and State Hub projections are committed at the recorded revision. | `consumers-verified` or `rollback-preflight` | Resume external handoffs from the recorded checklist. Do not assume source changes rolled out to consumers. | +| `consumers-verified` | Required consumers, routes, artifacts, deployment references, and telemetry continuity checks have evidence. | `completed` or `rollback-preflight` | Re-run final invariant checks. Complete only if no required handoff remains open. | +| `completed` | Invariants and required handoffs passed; old alias remains protected. | none in this operation | No automatic action. Optional checkout or compatibility cleanup is a separately approved target-repository task. | +| `rollback-preflight` | Desired rollback point, old-slug availability, current IDs/commits, and irreversible handoffs are recorded. | `rolled-back` or resume forward | If the old slug is unavailable or an external change is unsafe to reverse, stop and resume forward. Otherwise reverse one phase at a time, Forgejo first when its name must change. | +| `rolled-back` | Forgejo and State Hub canonical coordinates are restored and both observed slugs remain protected aliases; history is intact. | new operation only | Verify the original canonical route and consumers. Keep evidence and aliases; investigate before starting a new operation. | + +### Failure states + +| Failure code | Detection | Mutation rule | Recovery | +| --- | --- | --- | --- | +| `forge-unreachable` | Forge identity or repository cannot be read. | None. | Restore connectivity and repeat the same phase. Never infer success from a redirect or local clone. | +| `forge-identity-mismatch` | Provider, owner, or numeric ID differs from preflight. | None. | Stop for operator investigation; a new preflight cannot waive an identity mismatch without a separately reviewed migration. | +| `source-moved` | Default branch or expected head commit differs. | None. | Expire preflight and generate a new one against the intended commit. | +| `target-slug-conflict` | New slug is owned by another Forgejo or State Hub identity/alias. | None. | Choose another slug or resolve the conflicting ownership outside this operation. | +| `old-slug-unavailable` | Rollback target is no longer free. | No rollback mutation. | Continue forward or resolve ownership explicitly; do not steal or delete an alias. | +| `statehub-conflict` | Old/new slug, alias, or Forge identity resolves to multiple/different UUIDs. | None. | Repair identity data under a separate reviewed incident; preserve all evidence. | +| `forge-renamed-hub-pending` | Forge ID has new name but State Hub remains canonical on old slug. | Only `statehub-rebound` or rollback after preflight. | Verify ID/commit, then resume rebind with the same operation ID. | +| `hub-rebound-source-pending` | Hub canonical slug changed but repository projections/source are stale. | No duplicate rebind. | Resolve through either alias, then run source/projection sync for the recorded revision. | +| `consumer-verification-failed` | One or more external handoffs lack evidence or health checks fail. | Do not complete or clean up. | Keep aliases and both checkout facts; repair the named consumer or enter rollback preflight. | +| `edge-writes-pending` | Relevant outbox envelopes or unknown queued writes exist. | Preflight fails closed. | Replay/quarantine the outbox, verify idempotency against aliases, then preflight again. | +| `operation-conflict` | Another active operation targets the same UUID, Forge ID, old slug, or new slug. | None. | Finish/cancel the owning operation; only one active rename may hold the identity lock. | +| `evidence-drift` | Counts, checksums, paths, or source revision no longer match accepted evidence. | None for the requested phase. | Explain the drift and renew preflight; never silently update the accepted baseline. | + +### Retry and rollback limits + +- An idempotency key is the operation UUID plus requested phase. Reuse of the + key with different expectations is a conflict. +- A completed phase cannot be overwritten by a retry. Reconciliation may + append observed evidence and an error, but not erase prior evidence. +- Rollback is a new sequence on the same operation record and must itself pass + compare-and-set checks. It never deletes aliases, operation history, events, + or historical values. +- Before `forge-renamed`, rollback means abandoning an unexpired intent and has + no external side effect. +- After `forge-renamed`, automatic rollback is possible only while the old + Forge slug is provably available and external effects can be reversed. +- After source or consumer changes, rollback generates explicit handoffs for + irreversible or independently owned effects. It must not claim that a Forge + and Hub coordinate reversal also reversed packages, deployments, policies, + caches, or product/runtime names. + +## Consequences + +- T02 must add verified Forge identity, protected repository aliases, and an + operation journal without changing existing repository UUIDs. +- T03 must expose UUID-addressed preflight and one-phase mutation APIs with the + failure codes above. Slug convenience routes are read/resolution helpers only. +- T04 and T05 must centralize alias resolution and prove that history, + telemetry, work records, and queued-write behavior remain continuous. +- T06 must generate target-repository workplans that separate repository, + product, runtime, consumer, and cleanup decisions. +- T07 and T08 may orchestrate and rehearse the contract, but the live + `flex-auth` to `access-engine` operation remains gated by its adopted target + workplan. +- Protected aliases may accumulate. A future alias-retirement policy needs its + own evidence and decision; this rename workflow does not delete them. + +## Rejected alternatives + +| Alternative | Reason rejected | +| --- | --- | +| Delete and re-register under the new slug | Creates a second repository identity and strands foreign-key history. | +| Update only `managed_repos.slug` | Leaves routing, files, external projections, retries, and recovery undefined. | +| Mass-rewrite every old-slug string | Destroys historical provenance and cannot safely update independently owned systems. | +| Use Forgejo redirects indefinitely | Redirects do not update canonical remotes, routing, packages, policies, or deployment consumers. | +| Make repository and product/runtime rename one operation | Couples independently risky decisions and makes rollback boundaries unknowable. | +| Queue live rename phases through the edge relay | A disconnected multi-system identity mutation cannot prove current Forge identity, conflicts, or ordering. | + +## References + +- `STATE-WP-0085` — lineage-preserving repository rename workflow +- `CUST-ADR-007` — stable workplan identity and registrar authority +- `CUST-ADR-012` — Forge projection, source revision, and rebuildability +- `docs/architecture/state-hub_v0.1.md` — State Hub system context diff --git a/docs/architecture/state-hub_v0.1.md b/docs/architecture/state-hub_v0.1.md index 6ab28cb..d79762f 100644 --- a/docs/architecture/state-hub_v0.1.md +++ b/docs/architecture/state-hub_v0.1.md @@ -116,8 +116,9 @@ N/A for this stub. ## 9. Architecture Decisions -This repo has no `docs/adr/` corpus. Binding decisions live in -the-custodian and are listed on the estate map: +Estate-wide binding decisions live in the-custodian and are listed on the +estate map. Service-local implementation decisions live in `docs/adr/` and do +not supersede the estate decisions: | Estate ADR | Status | Why it binds this system | | --- | --- | --- | @@ -126,6 +127,10 @@ the-custodian and are listed on the estate map: | `CUST-ADR-007` | accepted | One writer of workplan UUIDs. | | `CUST-ADR-010` | proposed | Two kinds of hub data. | +| Local ADR | Status | Scope | +| --- | --- | --- | +| `STATE-ADR-001` | accepted | Repository identity and recovery contract for canonical-name changes. | + Do not treat a State Hub `/decisions` row as the published ADR. ---