feat: interim identifier registrar (RMGR-WP-0005-T01)
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.
This commit is contained in:
parent
0dde030ae3
commit
f509da5606
5 changed files with 90 additions and 2 deletions
|
|
@ -33,3 +33,24 @@ rmgr prefix-uniqueness --root ..
|
|||
Registry: [`config/workplan-prefix-registry.yaml`](../config/workplan-prefix-registry.yaml).
|
||||
|
||||
Work: `RMGR-WP-0004-T01`, `RMGR-WP-0004-T08`.
|
||||
|
||||
## Identifier registrar (interim)
|
||||
|
||||
Until UUIDv5 derivation lands (`RMGR-WP-0005-T03`), only the registrar
|
||||
instance may mint `state_hub_workstream_id` / `state_hub_task_id` into
|
||||
files (`ADR-007` decision 2). Other hubs may read and project; they must
|
||||
not write new hub primary keys into git.
|
||||
|
||||
| Signal | Registrar? |
|
||||
| --- | --- |
|
||||
| `STATEHUB_REGISTRAR=1` / `true` / `yes` / `on` | yes |
|
||||
| `STATEHUB_REGISTRAR=0` / `false` / `no` / `off` | no |
|
||||
| env unset, hostname starts with `railiance` | yes |
|
||||
| env unset, any other hostname | no |
|
||||
|
||||
Accepted cost: new workplan/task registration requires connectivity to
|
||||
the registrar. Disconnected work cannot register until T03. Implementation:
|
||||
`repo_manager.registrar.is_identifier_registrar`; consumed by
|
||||
`statehub fix-consistency` C-06 / C-11 / C-32.
|
||||
|
||||
Work: `RMGR-WP-0005-T01`.
|
||||
|
|
|
|||
30
src/repo_manager/registrar.py
Normal file
30
src/repo_manager/registrar.py
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
"""Interim single-writer for hub identifiers (ADR-007 decision 2).
|
||||
|
||||
Until deterministic derivation (RMGR-WP-0005-T03) ships, exactly one
|
||||
instance may mint ``state_hub_workstream_id`` / ``state_hub_task_id``
|
||||
into repository files. Other instances may read and project; they must
|
||||
not write new hub primary keys into git-tracked files.
|
||||
|
||||
The registrar is the automated production instance (hostname prefix
|
||||
``railiance``). Override with ``STATEHUB_REGISTRAR=1`` or ``=0``.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import socket
|
||||
|
||||
_TRUE = frozenset({"1", "true", "yes", "on"})
|
||||
_FALSE = frozenset({"0", "false", "no", "off"})
|
||||
REGISTRAR_HOST_PREFIX = "railiance"
|
||||
|
||||
|
||||
def is_identifier_registrar(*, hostname: str | None = None) -> bool:
|
||||
"""Return True if this process may mint hub IDs into repository files."""
|
||||
raw = os.environ.get("STATEHUB_REGISTRAR", "").strip().lower()
|
||||
if raw in _TRUE:
|
||||
return True
|
||||
if raw in _FALSE:
|
||||
return False
|
||||
host = (hostname if hostname is not None else socket.gethostname()).strip().lower()
|
||||
return host.startswith(REGISTRAR_HOST_PREFIX)
|
||||
25
tests/test_registrar.py
Normal file
25
tests/test_registrar.py
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
from repo_manager.registrar import is_identifier_registrar
|
||||
|
||||
|
||||
def test_env_true_wins_over_hostname(monkeypatch):
|
||||
monkeypatch.setenv("STATEHUB_REGISTRAR", "1")
|
||||
assert is_identifier_registrar(hostname="bnt-lap001") is True
|
||||
|
||||
|
||||
def test_env_false_wins_over_production_hostname(monkeypatch):
|
||||
monkeypatch.setenv("STATEHUB_REGISTRAR", "0")
|
||||
assert is_identifier_registrar(hostname="railiance") is False
|
||||
|
||||
|
||||
def test_hostname_prefix_when_env_unset(monkeypatch):
|
||||
monkeypatch.delenv("STATEHUB_REGISTRAR", raising=False)
|
||||
assert is_identifier_registrar(hostname="railiance") is True
|
||||
assert is_identifier_registrar(hostname="railiance-prod") is True
|
||||
assert is_identifier_registrar(hostname="bnt-lap001") is False
|
||||
|
||||
|
||||
def test_env_aliases(monkeypatch):
|
||||
monkeypatch.setenv("STATEHUB_REGISTRAR", "yes")
|
||||
assert is_identifier_registrar(hostname="other") is True
|
||||
monkeypatch.setenv("STATEHUB_REGISTRAR", "off")
|
||||
assert is_identifier_registrar(hostname="railiance") is False
|
||||
|
|
@ -170,7 +170,7 @@ flavor-blind template silently re-breaks conformant repos.
|
|||
|
||||
```task
|
||||
id: RMGR-WP-0004-T05
|
||||
status: todo
|
||||
status: done
|
||||
priority: medium
|
||||
state_hub_task_id: "8402b8b6-2a1e-4236-b27d-d50b6161a176"
|
||||
```
|
||||
|
|
@ -192,6 +192,12 @@ Follow the dual-run strangler pattern already proven in `RMGR-WP-0002` and
|
|||
points at `rmgr scaffold`. T03 is done. Cutover / inventory move can start
|
||||
alongside `STATE-WP-0080-T02`.
|
||||
|
||||
**Result (2026-08-18):** Cutover is live via `STATE-WP-0080-T02`: project
|
||||
flavor delegates to `rmgr scaffold` (or registers only when `GOAL.md`
|
||||
exists); durable repos keep hub templating until `STATE-WP-0080-T04`
|
||||
deletes it. Inventory `caller:custodian-cli` is already `move` →
|
||||
`repo-manager`. Coordination remains `SHR-WP-0001`.
|
||||
|
||||
## Add compatibility and regression tests
|
||||
|
||||
```task
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ model; a file carrying a hub's private key is the file holding hub state.
|
|||
|
||||
```task
|
||||
id: RMGR-WP-0005-T01
|
||||
status: todo
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "b57a6882-280d-4f0a-9c73-899843dfc3d3"
|
||||
```
|
||||
|
|
@ -69,6 +69,12 @@ workstation hubs are rebuildable caches (`ADR-010` decision 2).
|
|||
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
|
||||
|
||||
```task
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue