269 lines
25 KiB
Markdown
269 lines
25 KiB
Markdown
|
|
---
|
||
|
|
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
|