feat: finish register receiving and authority routing
Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a023c0-a0a3-7c03-b395-5a0d2757214d
This commit is contained in:
parent
6d134425df
commit
d103955217
28 changed files with 970 additions and 48 deletions
65
docs/adr-002-canonical-utc-time.md
Normal file
65
docs/adr-002-canonical-utc-time.md
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
---
|
||||
id: RMGR-ADR-002
|
||||
type: architecture-decision-record
|
||||
title: "Canonical UTC timestamps; local time only at I/O boundaries"
|
||||
status: accepted
|
||||
decided: "2026-08-21"
|
||||
deciders: ["Bernd Worsch"]
|
||||
related:
|
||||
- RMGR-WP-0008
|
||||
- RMGR-WP-0005
|
||||
- docs/observation-command-contracts_v0.1.md
|
||||
---
|
||||
|
||||
# ADR-002: Canonical UTC timestamps; local time only at I/O boundaries
|
||||
|
||||
## Status
|
||||
|
||||
**Accepted** (2026-08-21).
|
||||
|
||||
## Context
|
||||
|
||||
Repo Manager emits timestamps into repository records, indexes, mutation
|
||||
meters, events, evidence, and compatibility contracts. Host-local clocks and
|
||||
implicit calendar conversion make identical events serialize differently,
|
||||
create daylight-saving ambiguity, and make deterministic reconciliation harder.
|
||||
|
||||
Users and external systems still need local calendars, wall-clock times, and
|
||||
locale-specific formatting. Those are presentation and ingestion concerns, not
|
||||
stored identity.
|
||||
|
||||
## Decision
|
||||
|
||||
1. Every value representing an **instant** is created, stored, compared, and
|
||||
exchanged in UTC.
|
||||
2. New textual timestamps use RFC 3339/ISO 8601 with the canonical `Z` suffix.
|
||||
Readers may accept legacy explicit offsets and normalize them to UTC before
|
||||
comparison or re-emission. Naive datetimes are rejected at boundaries.
|
||||
3. Database timestamp columns use timezone-aware types and UTC values. Epoch
|
||||
values, where a foreign contract requires them, denote UTC instants.
|
||||
4. Conversion to or from a local timezone, locale, calendar, or wall-clock
|
||||
representation occurs only in UI and I/O adapters. The converted value never
|
||||
replaces the canonical instant.
|
||||
5. Inputs that omit a timezone are invalid unless the specific I/O contract
|
||||
also supplies an explicit timezone. DST gaps and folds must be resolved at
|
||||
that boundary before producing UTC.
|
||||
6. A genuine **date-only domain value**—for example a contractual due date—is
|
||||
not a timestamp and keeps its declared calendar semantics. A date derived
|
||||
from the current instant for repository metadata uses the UTC calendar date.
|
||||
7. Tests, fixtures, logs, filenames, events, and idempotency material follow the
|
||||
same rule; test convenience is not an exception.
|
||||
|
||||
## Enforcement
|
||||
|
||||
- Repo Manager timestamp creation goes through `repo_manager.time`.
|
||||
- Ruff `DTZ` and `UP` rules remain explicitly selected so naive datetime use
|
||||
and non-canonical UTC APIs fail lint even if Ruff defaults change.
|
||||
- Contract tests require UTC-aware values and canonical `Z` serialization.
|
||||
|
||||
## Consequences
|
||||
|
||||
Stored and exchanged instants are byte-stable across hosts. Ordering and
|
||||
reconciliation no longer depend on operator locale or daylight-saving rules.
|
||||
Presentation clients must retain the canonical value and treat local rendering
|
||||
as a reversible view. Legacy offset-bearing timestamps remain readable but are
|
||||
normalized when rewritten.
|
||||
52
docs/adr-003-projection-ui-ownership.md
Normal file
52
docs/adr-003-projection-ui-ownership.md
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
---
|
||||
id: RMGR-ADR-003
|
||||
type: architecture-decision-record
|
||||
title: "Projection UI ownership stays outside Repo Manager"
|
||||
status: accepted
|
||||
decided: "2026-08-21"
|
||||
deciders: ["Repo Manager and hub-core architecture"]
|
||||
related:
|
||||
- RMGR-WP-0008
|
||||
- HUB-WP-0004
|
||||
- SHR-ARCH-HUB-0001
|
||||
---
|
||||
|
||||
# ADR-003: Projection UI ownership stays outside Repo Manager
|
||||
|
||||
## Status
|
||||
|
||||
**Accepted** (2026-08-21).
|
||||
|
||||
## Context
|
||||
|
||||
The State Hub retirement inventory initially assigned slice A4's work and
|
||||
repository pages to Repo Manager because Repo Manager owns the underlying
|
||||
file-backed records. That assignment conflated authority with presentation.
|
||||
Repo Manager is a functional component with governed CLI and adapter surfaces;
|
||||
it is not a cross-repository hub or dashboard runtime.
|
||||
|
||||
The accepted `HUB-WP-0004` architecture keeps repository work authoritative in
|
||||
Git through Repo Manager and assigns projection/query and hub UI capabilities
|
||||
to hub-core and its operator clients. Building another dashboard here would
|
||||
duplicate those projections and blur the one-authority boundary.
|
||||
|
||||
## Decision
|
||||
|
||||
1. Repo Manager owns repository observation, governed file-backed mutation,
|
||||
reconciliation, indexes, and stable machine-facing contracts. It does not
|
||||
own a dashboard or general operator UI.
|
||||
2. hub-core owns cross-repository projection/query contracts and the surviving
|
||||
hub UI runtime. Ops or domain clients may render narrower views through
|
||||
those contracts.
|
||||
3. User interfaces consume Repo Manager and hub-core ports. They do not write
|
||||
repository authority or projection storage directly.
|
||||
4. State Hub retirement slice A4 is therefore a hub-core/projection-client
|
||||
replacement, not a UI migration into Repo Manager. Repo Manager's A1–A3 and
|
||||
A5 contracts remain inputs to those projections.
|
||||
|
||||
## Consequences
|
||||
|
||||
RMGR-WP-0008 does not need a dashboard deliverable. A4 route redirects and UI
|
||||
replacement remain in the retirement program's hub-core cutover work. Any
|
||||
future repository-local UI must be proposed separately and remain a client of
|
||||
the same governed contracts.
|
||||
|
|
@ -35,8 +35,18 @@ confirmed live hub-first workplans in this snapshot.
|
|||
|
||||
The 217 closed rows remain cheap historical provenance. They need not be
|
||||
reconstructed as files, but the cache-rebuild procedure must export or retain
|
||||
them before replacing the local database. Repairing the seven live bindings is
|
||||
the remaining prerequisite for T07.
|
||||
them before replacing the local database.
|
||||
|
||||
## Repair result
|
||||
|
||||
All seven bindings were submitted together to the preferred
|
||||
`PUT /workplans/index/bindings` route and the hub acknowledged
|
||||
`{"updated":7,"received":7}`. A fresh query now finds exactly 217 unbound rows:
|
||||
201 `finished`, 16 `archived`, and **zero live**. No repository file or
|
||||
lifecycle status was changed. The broad `fix-consistency --all` path was not
|
||||
used for the repair because it aborts while refreshing the brief for stale
|
||||
registered path `/home/worsch/inter-hub`; the targeted binding route avoided
|
||||
coupling this data repair to that unrelated registry defect.
|
||||
|
||||
## Reproduction
|
||||
|
||||
|
|
|
|||
40
docs/evidence/RMGR-WP-0008-sbom-cutover-2026-08-21.md
Normal file
40
docs/evidence/RMGR-WP-0008-sbom-cutover-2026-08-21.md
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
# RMGR-WP-0008 SBOM receiving and cutover evidence — 2026-08-21
|
||||
|
||||
Repo Manager now derives an SBOM snapshot from repository-owned lockfiles and
|
||||
the reviewed `sbom-tools.yaml` escape hatch. The snapshot includes source path
|
||||
and SHA-256 provenance, Git revision, canonical UTC generation time, ecosystem,
|
||||
direct/development flags, licence grouping, and direct production copyleft
|
||||
findings.
|
||||
|
||||
## Live projection reconciliation
|
||||
|
||||
The workstation State Hub held 22 historical snapshots for 18 repositories.
|
||||
For migration planning, only the newest snapshot per repository was compared
|
||||
with a fresh Repo Manager scan of its registered local path:
|
||||
|
||||
- 18 repositories scanned; 0 parse failures;
|
||||
- 9 entry counts matched exactly;
|
||||
- newest State Hub projections totalled 2,659 entries;
|
||||
- current authoritative lockfiles produce 1,565 entries.
|
||||
|
||||
The differing counts are expected evidence of source drift, not rows to copy:
|
||||
the stored snapshots date from March through July 2026, while the rescan reads
|
||||
the current checked-out lockfiles. Copying the 2,659 cached rows into repository
|
||||
records would reverse the authority boundary. Cutover therefore rebuilds each
|
||||
repository snapshot from its current lockfiles and retains the old State Hub
|
||||
snapshot ids/timestamps as historical provenance until the retirement retention
|
||||
gate permits deletion.
|
||||
|
||||
## Compatibility contract
|
||||
|
||||
State Hub's retirement adapter calls `rmgr sbom scan --path <repo> --slug
|
||||
<slug>` and receives `repo-manager.sbom-snapshot.v1` JSON. Route-level tests
|
||||
pin that invocation and response shape. The adapter is read/derive-only: it
|
||||
does not commit, push, or mutate a register file.
|
||||
|
||||
## Verification
|
||||
|
||||
- `uv run ruff check src tests`
|
||||
- focused SBOM and compatibility-adapter tests
|
||||
- live `repo-manager` scan: 39 entries, no parse errors, canonical `Z`
|
||||
timestamp, Git revision present, and no direct production copyleft finding
|
||||
|
|
@ -53,3 +53,12 @@ the database a source of repository truth.
|
|||
|
||||
This narrows the offline-buffer part of `STATE-WP-0068`; it does not authorize
|
||||
changes in repositories owned by hub-core, activity-core, ops-hub, or fin-hub.
|
||||
|
||||
## Enforced routing
|
||||
|
||||
`rmgr authority route` is the executable gate for this contract. File-derived
|
||||
records require both repository and domain context and resolve to
|
||||
`repository:<domain>/<repo>` under Repo Manager. Central and derived record
|
||||
types resolve to their one declared hub owner. Unknown types and writes whose
|
||||
claimed owner disagrees with the contract are rejected instead of falling back
|
||||
to whichever hub received the request.
|
||||
|
|
|
|||
|
|
@ -54,3 +54,22 @@ rmgr register defer --kind technical-debt --entry-id TD-001
|
|||
Mutations use the same expected-HEAD, idempotency, Git commit, optional
|
||||
push-seal, normalized-event, reindex, and dual-run-meter mechanism as workplan
|
||||
and task mutations.
|
||||
|
||||
## Derived SBOM inventory
|
||||
|
||||
SBOM is the exception to ordinary register mutation: recognised lockfiles and a
|
||||
reviewed root `sbom-tools.yaml` remain authoritative. Repo Manager derives a
|
||||
replaceable snapshot and licence/copyleft report without copying State Hub rows
|
||||
back into a new source-of-truth file.
|
||||
|
||||
```bash
|
||||
rmgr sbom scan --path . --output sbom-snapshot.json
|
||||
rmgr sbom licence-report --path .
|
||||
```
|
||||
|
||||
Detection covers `uv.lock`, `requirements.txt`, `package-lock.json`,
|
||||
`yarn.lock`, `Cargo.lock`, `go.sum`, `.terraform.lock.hcl`, Ansible requirements
|
||||
under `ansible/`, and root `sbom-tools.yaml`. Each source carries a SHA-256 and
|
||||
the snapshot carries the Git revision and canonical UTC generation timestamp.
|
||||
An output file is optional evidence, never authority, and is not overwritten
|
||||
without `--force`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue