Add is_identifier_registrar so only the production instance may mint hub UUIDs into repository files. Workstation hubs stay read/project caches until deterministic derivation lands. Also close RMGR-WP-0004-T05: register cutover is STATE-WP-0080-T02.
11 KiB
| id | type | title | domain | repo | status | owner | topic_slug | created | updated | parent_project | parent_workplan | related | state_hub_workstream_id | ||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| RMGR-WP-0005 | workplan | Registrar consolidation and deterministic hub identifiers | infotech | repo-manager | active | codex | infotech | 2026-08-17 | 2026-08-18 | prj-state-hub-retirement | SHR-WP-0001 |
|
7ddb5421-d960-4a3c-94b1-40b6c96abfab |
Registrar consolidation and deterministic hub identifiers
Goal
Make hub identifiers stored in repository files derivable rather than database-local, so that any number of hub instances can reconcile the same repository without overwriting each other.
Implements ADR-007 decision 2: interim single-writer (A), target deterministic
derivation (C2).
The defect
state_hub_workstream_id and state_hub_task_id are database-local primary
keys stored in a shared git artifact. Two hub instances over two databases each
mint their own value for the same workplan, and every sync overwrites the other.
Observed 2026-08-16 on STATE-WP-0080: workplan UUID 03f38314 from the
workstation hub, bbfce36a from a second instance (404 against the workstation
database), plus two disjoint sets of task UUIDs. Sync commits appear under both
+0000 and +0200 timezones, confirming two machines write to one repository.
It also inverts ADR-001. Files are meant to originate work with the hub as read
model; a file carrying a hub's private key is the file holding hub state.
Scope: 758 workplan files across the fleet currently carry these fields.
Apply the interim single-writer rule
id: RMGR-WP-0005-T01
status: done
priority: high
state_hub_task_id: "b57a6882-280d-4f0a-9c73-899843dfc3d3"
Until derivation ships, exactly one instance may write hub identifiers into
repository files. The interim registrar is the automated production instance;
workstation hubs are rebuildable caches (ADR-010 decision 2).
- Make the writeback path refuse to mint identifiers when the instance is not the registrar, rather than relying on operator discipline.
- Provide the configuration that designates the registrar, and make a non-registrar instance's read/project behaviour unchanged.
- Document the accepted cost: registration requires connectivity to the registrar, so disconnected work cannot register until T03 lands.
Interim, and deliberately so — it trades availability for correctness, and T03 removes the need for the trade.
Result (2026-08-18): repo_manager.registrar.is_identifier_registrar
(STATEHUB_REGISTRAR env, else hostname prefix railiance).
statehub fix-consistency skips C-06 / C-11 / C-32 mint+writeback when
this instance is not the registrar. Read/project checks are unchanged.
Cost documented in docs/repository-standards_v0.1.md.
Re-register identifiers minted outside the registrar
id: RMGR-WP-0005-T02
status: wait
priority: medium
state_hub_task_id: "8e679ddb-9845-457f-8672-1fd4b7455e7b"
Records minted by non-registrar instances before T01 need reconciliation. Known cases, all created 2026-08-16/17 from the workstation hub:
RMGR-WP-0004(b8b3f1e0) and its seven tasks;CFED-WP-0001(7a96da54) and its thirteen tasks, plus theprj-canon-federationrepo record (3809b0ff);STATE-WP-0080— already reconciled by hand to the second instance's IDs (bbfce36a), retained here as the worked example.
Prefer waiting for T03 where possible: once identifiers are derived, these converge without manual intervention. Re-register by hand only what blocks work before then.
Derive identifiers deterministically
id: RMGR-WP-0005-T03
status: wait
priority: high
state_hub_task_id: "28067729-498d-4f47-89bd-5b9718e999c7"
Replace minted UUIDs with UUIDv5 derived from the globally unique
PREFIX-WP-NNNN identifier (and PREFIX-WP-NNNN-TNN for tasks).
- Fix the namespace UUID and derivation input as a published contract — the value must be reproducible by any implementation, not just this one.
- Field shape is unchanged, so consumers reading
state_hub_workstream_idkeep working; only the provenance of the value changes. - Writeback becomes idempotent: two instances write identical bytes, so the flip-flop cannot recur regardless of how many hubs run.
Blocked on RMGR-WP-0004-T08. Deriving from a non-unique identifier
manufactures collisions: two repositories sharing PRJ-WP- would compute the
same UUID for different workplans. Uniqueness must be enforced first.
Migrate the fleet
id: RMGR-WP-0005-T04
status: wait
priority: high
state_hub_task_id: "503a23a9-ede1-4cf1-bd32-e9669b84ce58"
One-time pass over the 758 files carrying hub identifiers: compute the derived value, update the database to match, and write the file.
- Must be all-or-nothing per repository — a half-migrated repo has some derived and some minted identifiers and reconciles unpredictably.
- Records whose current identifier is already referenced externally (dashboards, saved queries, progress events) need a mapping table from old to derived, kept as provenance rather than discarded.
- Repositories with unresolved identifier collisions cannot migrate until
ADR-007§ Migration is ruled on; skip and report them rather than guessing.
Retire the interim rule
id: RMGR-WP-0005-T05
status: wait
priority: low
state_hub_task_id: "3946d1fc-2137-4d7b-a400-29b447ca83de"
Once derivation is live fleet-wide, remove the single-writer restriction from T01. Multiple hub instances become an availability choice rather than a correctness constraint, and disconnected registration works again.
Confirm before removal: two instances reconciling the same repository produce byte-identical writeback, and neither creates a duplicate record.
Rebuild local instances as caches
id: RMGR-WP-0005-T07
status: wait
priority: high
state_hub_task_id: "70f83359-0b61-4dc0-83b0-33f289b64e83"
Implement ADR-010 decisions 1–3: the central hub on railiance is authoritative
as a reading of the repositories; local instances become rebuildable caches.
- A cache must be discardable and reconstructable from repository files alone, with no work lost.
- Local work must not require a hub — repository files are self-describing, so reading them is sufficient for working inside a repo.
- Cache reads are advisory and must carry their staleness (
ADR-010decision 8).
Measured 2026-08-17: 955 workplans locally against 649 on the primary, 320 local-only, of which 288 are backed by files that all exist on disk. That portion of the divergence is redundant and needs no merge — only a rebuild.
Separate file-derived from hub-native data
id: RMGR-WP-0005-T08
status: wait
priority: high
state_hub_task_id: "241cf058-2f3e-4d49-8cc9-5c714be4a1cf"
Implement ADR-010 decision 4. The two kinds need opposite handling:
- File-derived (workplans, tasks, statuses, dependencies) — central derives it and must not accept pushes of it (decision 5). Offline, the git commit is the write. No conflict model: conflicts are git conflicts.
- Hub-native (progress events, decisions, inbox messages, token events) — central owns it, needs a real write path and a local append-only buffer for replay. No conflict model either: append-only merges regardless of order.
Deliverable is an explicit classification of every record type the hub holds, with its truth source and offline behaviour, so neither kind is handled by the other's rules.
Feeds a rescope of STATE-WP-0068 (offline write buffer and edge relay): under
this split most of what it buffers does not need buffering, and only the
append-only stream does. Re-examine before building further on it — this likely
reduces its scope.
Disposition the orphaned hub-first records
id: RMGR-WP-0005-T09
status: wait
priority: high
state_hub_task_id: "d40cc4a8-4280-4940-ac1d-dc1049f1b678"
28 records exist in the local instance with no backing file. They are the only
records a cache rebuild would drop, so they must be classified first
(ADR-010 § Orphan disposition):
- Broken links — a file exists but
backing_filenamewas never recorded.RMGR-WP-0004is a confirmed instance. Repair the link; no data at risk. Likely the largest class, so classify before estimating the rest. - Live hub-first records —
proposed/ready/backlogwith no file, inactivity-core,core-hub,hub-core,issue-core,ops-hub,prj-forgejo-org-refactor,railiance-enablement,railiance-infra,reef-railiance. Write a repository file or drop explicitly. These areADR-001violations and must not survive as hub-only records. - Closed hub-first records —
finished/archivedwith no file. Retain as provenance where cheap; do not reconstruct completed plans.
Blocks T07 — rebuilding the cache before this classification would discard class 2.
Note: one of these records is already labelled SPURIOUS bootstrap (statehub register collision) in repo-manager, independent corroboration of the
STATE-WP-0080 defect.
Assign one authoritative hub per record
id: RMGR-WP-0005-T10
status: wait
priority: medium
state_hub_task_id: "15f0f167-a8d0-4d5c-8576-3e93b1e8792f"
Implement ADR-010 decision 7. The retirement splits one hub into several, which
is permitted only if every record has exactly one authoritative hub, determined
by its repository and domain.
Define and enforce that mapping before the split lands. Without it the peer-database divergence this workplan exists to remove recurs at larger scale.
Coordinate with the hub-extension architecture in
prj-state-hub-retirement/architecture/; hub-core owns the hub-native side.
Protect lifecycle status from automation
id: RMGR-WP-0005-T06
status: done
priority: medium
state_hub_task_id: "d440d59c-f78e-4752-84c7-f3d5fdf7d3c3"
Implement ADR-007 decision 3: an automated normalization pass may report
lifecycle drift but may not promote a workplan from proposed to active.
proposed means awaiting human review; automated promotion destroys the gate.
Observed: commit ff909e1 ("renormalize lifecycle state [auto]") promoted
STATE-WP-0080 to active hours after it was drafted for review.
Extend the same protection to task status, where the symptom is currently
sharper: C-15 forces CFED-WP-0001-T02 back to wait on every sync
regardless of file content — reproduced three times, via file edit and via
update_task_status, with the task never holding todo. Establish which
direction wins for task status and make it consistent with ADR-001, where the
file originates work.
Result (2026-08-18): In state-hub consistency: C-23 does not
auto-promote proposed → active (report only). C-15 no longer
writebacks wait over progress/todo; file wins via C-10 (ADR-001).
C-15 remains a non-fixable warning when the DB is terminal and the file
is not.