HUB-WP-0006-T06: seed legacy topic aliases and add RM_SLICE_TOPICSPINE
- hub_core/runtime/data/legacy_topic_aliases.json: checked-in, versioned (2026-10-13.1) seed of the 16 State Hub topics from the STATE-WP-0098-T01 capture -> primary_domain facet, residual owner STATE-WP-0079, expiry 2027-03-31T23:59:59Z. Never fetched live; topic UUIDs kept verbatim. - legacy_topic_aliases.py: loader validated against the 1.0.0 legacyTopicAlias schema; per-response active/expired status; underscore slugs emitted hyphenated (1.0.0 pattern forbids '_'). - RM_SLICE_TOPICSPINE setting (off|shadow|on, default off). off keeps the navigation output unchanged (aliases []); shadow/on serve the aliases and mark responses with X-RM-Slice-Topicspine. Documented as the A5 rollback switch in docs/runtime.md. - tests/test_legacy_topic_aliases.py: seed, flag and local A5 comparison cases (C01, C02/C08, C03, C10) against fixtures. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 356991@bnt-lap001 Assistant-Session: 5d99ea69-ed55-4a1e-8d97-f4f312db247f
This commit is contained in:
parent
e8fb648f25
commit
9e4d5ba23c
10 changed files with 762 additions and 2 deletions
|
|
@ -3,6 +3,11 @@ from __future__ import annotations
|
|||
import os
|
||||
from dataclasses import dataclass
|
||||
|
||||
from hub_core.runtime.legacy_topic_aliases import (
|
||||
TOPIC_SPINE_MODES,
|
||||
normalize_topic_spine_mode,
|
||||
)
|
||||
|
||||
|
||||
def _env_bool(name: str, default: bool) -> bool:
|
||||
raw = os.getenv(name)
|
||||
|
|
@ -39,6 +44,11 @@ class RuntimeSettings:
|
|||
statehub_inbox_reads: bool = False
|
||||
statehub_inbox_agent: str = "state-hub"
|
||||
access_mode: str = "auto"
|
||||
# A5 topic-spine slice switch (HUB-WP-0006-T06). "off" (default) keeps the
|
||||
# navigation output unchanged (legacy_topic_aliases == []); "shadow" emits
|
||||
# the checked-in aliases for parity comparison only; "on" declares hub-core
|
||||
# the switched A5 read source. Rollback = set back to "off".
|
||||
rm_slice_topicspine: str = "off"
|
||||
|
||||
@property
|
||||
def enforce_access(self) -> bool:
|
||||
|
|
@ -54,6 +64,8 @@ class RuntimeSettings:
|
|||
if self.statehub_inbox_reads and (self.backend != "postgresql" or
|
||||
(not self.enforce_access and not self.api_token)):
|
||||
raise ValueError("State Hub inbox reads require PostgreSQL and operator token")
|
||||
if self.rm_slice_topicspine not in TOPIC_SPINE_MODES:
|
||||
raise ValueError("RM_SLICE_TOPICSPINE must be one of off, shadow, on")
|
||||
if self.repo_manager_timeout_seconds <= 0:
|
||||
raise ValueError("Repo Manager timeout must be positive")
|
||||
if self.repo_projection_refresh_seconds < 0:
|
||||
|
|
@ -100,6 +112,9 @@ class RuntimeSettings:
|
|||
statehub_inbox_reads=_env_bool("HUB_CORE_STATEHUB_INBOX_READS", False),
|
||||
statehub_inbox_agent=os.getenv("HUB_CORE_STATEHUB_INBOX_AGENT", "state-hub"),
|
||||
access_mode=os.getenv("HUB_CORE_ACCESS_MODE", "auto"),
|
||||
rm_slice_topicspine=normalize_topic_spine_mode(
|
||||
os.getenv("RM_SLICE_TOPICSPINE")
|
||||
),
|
||||
)
|
||||
|
||||
def readiness_checks(self, store_backend: str) -> dict[str, str]:
|
||||
|
|
@ -117,7 +132,7 @@ class RuntimeSettings:
|
|||
or bool(self.api_token)
|
||||
or store_backend == "postgresql"
|
||||
)
|
||||
return {
|
||||
checks = {
|
||||
"environment": self.environment,
|
||||
"configured_backend": self.backend,
|
||||
"active_backend": store_backend,
|
||||
|
|
@ -128,6 +143,9 @@ class RuntimeSettings:
|
|||
"v2_write_groups": ",".join(sorted(self.v2_write_groups)) or "none",
|
||||
"legacy_write_groups": ",".join(sorted(self.legacy_write_groups)) or "none",
|
||||
}
|
||||
if self.rm_slice_topicspine != "off":
|
||||
checks["rm_slice_topicspine"] = self.rm_slice_topicspine
|
||||
return checks
|
||||
|
||||
def is_ready(self, store_backend: str) -> bool:
|
||||
checks = self.readiness_checks(store_backend)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue