Complete ops-hub Inter-Hub bootstrap and close bootstrap workplans.

Extract bootstrap logic into src/ops_hub/bootstrap.py with dry-run support,
public hub discovery, and unit tests. Update the gate probe to accept public
hub listing (200 or 401), document dev commands and architecture, and archive
finished OPS-WP-0001 and OPS-WP-0002 workplans.
This commit is contained in:
2026-07-07 01:49:12 +02:00
parent 0454e126cb
commit 39080333da
13 changed files with 795 additions and 370 deletions

View File

@@ -1,7 +1,28 @@
## Architecture
<!-- TODO: Describe the key design decisions and component structure.
Key modules, data flows, external integrations, state machines, etc. -->
`ops-hub` is a Python tooling repo that extends Inter-Hub with VSM Operations
(System 1) vocabulary, bootstrap clients, and gate probes. Inter-Hub remains the
generic hub substrate; this repo owns domain-specific seeds, scripts, and library
code.
### Components
| Path | Role |
| --- | --- |
| `src/ops_hub/interhub_gate_probe.py` | Public gate probe for bootstrap API surface |
| `src/ops_hub/bootstrap.py` | Authenticated bootstrap client (plan, dry-run, execute) |
| `scripts/interhub-gate-probe.py` | CLI wrapper for gate probe |
| `scripts/ops-hub-bootstrap-api.py` | CLI wrapper for bootstrap |
| `seeds/` | Manifest, widget, and SQL bootstrap artifacts |
| `docs/` | Runbook, readiness gates, inventory handoff |
| `workplans/` | ADR-001 work source of truth |
### External integrations
- **Inter-Hub** (`https://hub.coulomb.social`) — hub rows, manifests, widgets, events
- **State Hub** — workstream/task cache rebuilt from workplan files
- **OpenBao** — operator and runtime API key custody (`warden access --exec`)
- **ops-warden** — SSH cert issuance and credential routing only
## Quick Reference

View File

@@ -2,7 +2,10 @@
This repo owns **ops-hub** only. It does not own:
<!-- TODO: List what belongs in adjacent repos, e.g.:
- SSH key management → railiance-infra/
- State hub code → state-hub/
-->
- Generic Inter-Hub framework, API substrate, auth → `inter-hub/`
- State Hub workstream/task/decision implementation → `state-hub/`
- SSH CA, credential routing catalog, bootstrap SSH envelope → `ops-warden/`
- OpenBao mounts, platform secret paths, ESO → `railiance-platform/`
- Cluster desired state, host principals, force-command wrappers → `railiance-infra/`
- HelixForge architecture handoff canon → `helix-forge/` (linked, not duplicated)
- Identity/OIDC/MFA → `key-cape/` / Keycloak

View File

@@ -1,19 +1,27 @@
## Stack
<!-- TODO: Fill in language, frameworks, and key dependencies -->
- **Language:**
- **Key deps:**
- **Language:** Python 3.11+
- **Key deps:** stdlib only (`pyproject.toml` has no runtime dependencies)
- **Layout:** `src/ops_hub/` package, `scripts/` operator CLIs, `tests/` unittest suite
## Dev Commands
```bash
# TODO: Fill in the standard commands for this repo
# Show Makefile targets
make help
# Install dependencies
# Unit tests
make test
# Run tests
# Probe production Inter-Hub bootstrap API gate (no secrets)
make interhub-gate
# Lint / type check
# Plan attended bootstrap (requires IHUB_OPERATOR_KEY_FILE)
make interhub-bootstrap-dry-run IHUB_OPERATOR_KEY_FILE=/path/to/key
# Build / package (if applicable)
# Attended production bootstrap
make interhub-bootstrap IHUB_OPERATOR_KEY_FILE=/path/to/key
# Sync workplan files to State Hub after edits
cd ~/state-hub && make fix-consistency REPO=ops-hub
```

View File

@@ -156,6 +156,24 @@ get wrong.
<!-- Append repo-specific agent instructions below this marker.
The state-hub template sync preserves content after this line. -->
## Dev Commands
```bash
make help # list targets
make test # unit tests (PYTHONPATH=src)
make interhub-gate # public Inter-Hub bootstrap gate probe (no secrets)
```
Attended bootstrap (requires `IHUB_OPERATOR_KEY` via file or `warden access --exec`):
```bash
make interhub-bootstrap-dry-run IHUB_OPERATOR_KEY_FILE=/path/to/key
make interhub-bootstrap IHUB_OPERATOR_KEY_FILE=/path/to/key
```
Credential routing for operator/runtime keys: `warden route find "Inter-Hub operator key"`.
Runbook: `docs/bootstrap-runbook.md`.
---
## Workplan Convention (ADR-001)

View File

@@ -2,13 +2,15 @@ IHUB_BASE ?= https://hub.coulomb.social
IHUB_OPERATOR_KEY_FILE ?=
OPS_HUB_RUNTIME_KEY_OUTPUT ?=
.PHONY: help interhub-gate interhub-bootstrap interhub-bootstrap-help
.PHONY: help interhub-gate interhub-bootstrap interhub-bootstrap-dry-run interhub-bootstrap-help test
help:
@echo "Targets:"
@echo " interhub-gate Probe whether production Inter-Hub exposes the ops-hub bootstrap API surface"
@echo " interhub-bootstrap-help Show bootstrap helper options"
@echo " interhub-bootstrap-dry-run Plan bootstrap actions with IHUB_OPERATOR_KEY_FILE (no mutations)"
@echo " interhub-bootstrap Run attended ops-hub Inter-Hub bootstrap with IHUB_OPERATOR_KEY_FILE"
@echo " test Run unit tests"
interhub-gate:
IHUB_BASE="$(IHUB_BASE)" python3 scripts/interhub-gate-probe.py
@@ -16,6 +18,13 @@ interhub-gate:
interhub-bootstrap-help:
python3 scripts/ops-hub-bootstrap-api.py --help
interhub-bootstrap-dry-run:
@test -n "$(IHUB_OPERATOR_KEY_FILE)" || \
(echo "IHUB_OPERATOR_KEY_FILE is required; materialize the operator key into a 0600 temp file first." >&2; exit 2)
IHUB_BASE="$(IHUB_BASE)" \
IHUB_OPERATOR_KEY_FILE="$(IHUB_OPERATOR_KEY_FILE)" \
python3 scripts/ops-hub-bootstrap-api.py --dry-run
interhub-bootstrap:
@test -n "$(IHUB_OPERATOR_KEY_FILE)" || \
(echo "IHUB_OPERATOR_KEY_FILE is required; materialize the operator key into a 0600 temp file first." >&2; exit 2)
@@ -23,3 +32,6 @@ interhub-bootstrap:
IHUB_OPERATOR_KEY_FILE="$(IHUB_OPERATOR_KEY_FILE)" \
OPS_HUB_RUNTIME_KEY_OUTPUT="$(OPS_HUB_RUNTIME_KEY_OUTPUT)" \
python3 scripts/ops-hub-bootstrap-api.py
test:
PYTHONPATH=src python3 -m unittest discover -s tests -v

View File

@@ -38,11 +38,11 @@ here.
## Current State
- Status: active bootstrap.
- Implementation: no executable source tree yet; first real workplan is seeded
in `workplans/OPS-WP-0002-interhub-extension-bootstrap.md`.
- Live Inter-Hub production gate: `/api/v2/hubs` still returned `404` on
2026-06-06, so supported API bootstrap is not yet available in production.
- Status: production bootstrap complete (2026-07-07).
- Implementation: Python package under `src/ops_hub/`, operator scripts, seeds,
tests, and Makefile targets for gate probe and attended bootstrap.
- Inter-Hub: `ops-hub` hub, active manifest, seed widgets, and first
`ops-endpoint-verified` event are live in production.
## Getting Oriented

View File

@@ -47,6 +47,14 @@ operator_key_file="$(mktemp)"
# source. Do not echo it into shared logs.
```
Plan the bootstrap without mutations:
```bash
make interhub-bootstrap-dry-run \
IHUB_BASE=https://hub.coulomb.social \
IHUB_OPERATOR_KEY_FILE="$operator_key_file"
```
Run the attended bootstrap:
```bash
@@ -161,11 +169,12 @@ the authenticated UI.
## Current Live-Execution Blocker
The repo-side helper and runbook are ready. The remaining blocker is an
authenticated production execution lane:
The repo-side helper, dry-run path, and runbook are ready. The remaining step is
an operator-attended production run with:
- an operator-provided `IHUB_OPERATOR_KEY_FILE`,
- an OpenBao-materialized key on a trusted host, or
- an explicitly approved deployment-side migration/bootstrap path.
Until one of those is available, run only local validation and gate probes.
Until one of those is available, run `make interhub-gate`, `make test`, and
`make interhub-bootstrap-dry-run` for local validation.

View File

@@ -12,306 +12,25 @@ from __future__ import annotations
import argparse
import json
import os
import stat
import sys
import tempfile
import time
import urllib.error
import urllib.parse
import urllib.request
from pathlib import Path
from typing import Any
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
DEFAULT_BASE = "https://hub.coulomb.social"
ROOT = Path(__file__).resolve().parents[1]
MANIFEST_PATH = ROOT / "seeds" / "ops-hub-manifest.draft.json"
WIDGETS_PATH = ROOT / "seeds" / "ops-hub-widgets.seed.json"
class BootstrapError(RuntimeError):
pass
def load_secret(name: str, file_name: str) -> str:
value = os.environ.get(name, "").strip()
if value:
return value
file_path = os.environ.get(file_name, "").strip()
if file_path:
return Path(file_path).read_text(encoding="utf-8").strip()
return ""
def request_json(
base_url: str,
method: str,
path: str,
token: str | None,
body: dict[str, Any] | None,
*,
expected: set[int],
) -> dict[str, Any]:
data = json.dumps(body).encode("utf-8") if body is not None else None
request = urllib.request.Request(base_url + path, data=data, method=method)
request.add_header("Accept", "application/json")
request.add_header("User-Agent", "ops-hub-bootstrap/0.1")
if token:
request.add_header("Authorization", f"Bearer {token}")
if body is not None:
request.add_header("Content-Type", "application/json")
try:
with urllib.request.urlopen(request, timeout=30) as response:
status = response.status
payload = response.read().decode("utf-8")
except urllib.error.HTTPError as error:
payload = error.read().decode("utf-8", errors="replace")
raise BootstrapError(f"{method} {path} failed with HTTP {error.code}: {payload}") from error
if status not in expected:
raise BootstrapError(f"{method} {path} returned HTTP {status}, expected {sorted(expected)}")
if not payload:
return {}
return json.loads(payload)
def list_items(base_url: str, path: str, token: str | None) -> list[dict[str, Any]]:
response = request_json(base_url, "GET", path, token, None, expected={200})
data = response.get("data", [])
if not isinstance(data, list):
raise BootstrapError(f"expected paginated data array from {path}")
return data
def first_by(items: list[dict[str, Any]], key: str, value: Any) -> dict[str, Any] | None:
return next((item for item in items if item.get(key) == value), None)
def load_manifest() -> dict[str, Any]:
manifest = json.loads(MANIFEST_PATH.read_text(encoding="utf-8"))
required = [
"hub",
"manifestVersion",
"declaredWidgetTypes",
"declaredEventTypes",
"declaredAnnotationCategories",
"declaredPolicyScopes",
]
missing = [key for key in required if key not in manifest]
if missing:
raise BootstrapError(f"{MANIFEST_PATH} missing required key(s): {', '.join(missing)}")
return manifest
def load_widgets() -> list[dict[str, Any]]:
widgets = json.loads(WIDGETS_PATH.read_text(encoding="utf-8"))
if not isinstance(widgets, list):
raise BootstrapError(f"{WIDGETS_PATH} must contain a JSON array")
return widgets
def ensure_hub(base_url: str, operator_key: str, manifest: dict[str, Any]) -> dict[str, Any]:
hub_seed = manifest["hub"]
slug = hub_seed["slug"]
existing = first_by(list_items(base_url, "/api/v2/hubs", operator_key), "slug", slug)
if existing:
return {"record": existing, "created": False}
body = {
"slug": slug,
"name": hub_seed["name"],
"domain": hub_seed["domain"],
"hubKind": hub_seed.get("hubKind", "domain"),
"hubFamily": "vsm",
"vsmFunction": "OPS",
"vsmSystem": "1",
}
record = request_json(base_url, "POST", "/api/v2/hubs", operator_key, body, expected={201})
return {"record": record, "created": True}
def manifest_body(manifest: dict[str, Any], hub_id: str | None = None) -> dict[str, Any]:
body: dict[str, Any] = {
"manifestVersion": manifest["manifestVersion"],
"declaredWidgetTypes": manifest["declaredWidgetTypes"],
"declaredEventTypes": manifest["declaredEventTypes"],
"declaredAnnotationCategories": manifest["declaredAnnotationCategories"],
"declaredPolicyScopes": manifest["declaredPolicyScopes"],
"capabilityDescription": manifest.get("capabilityDescription", ""),
"contact": manifest.get("contact", "operator"),
}
if hub_id:
body["hubId"] = hub_id
return body
def ensure_manifest(base_url: str, operator_key: str, hub_id: str, manifest: dict[str, Any]) -> dict[str, Any]:
query = urllib.parse.urlencode({"hubId": hub_id})
manifests = list_items(base_url, f"/api/v2/hub-capability-manifests?{query}", operator_key)
active = first_by(manifests, "status", "active")
if active:
return {"record": active, "created": False, "activated": False}
draft = first_by(manifests, "status", "draft")
if draft:
record = request_json(
base_url,
"PATCH",
f"/api/v2/hub-capability-manifests/{draft['id']}",
operator_key,
manifest_body(manifest),
expected={200},
)
created = False
else:
record = request_json(
base_url,
"POST",
"/api/v2/hub-capability-manifests",
operator_key,
manifest_body(manifest, hub_id),
expected={201},
)
created = True
activated = request_json(
base_url,
"POST",
f"/api/v2/hub-capability-manifests/{record['id']}/activate",
operator_key,
None,
expected={200},
)
return {"record": activated, "created": created, "activated": True}
def ensure_api_consumer(base_url: str, operator_key: str, manifest_id: str) -> dict[str, Any]:
consumers = list_items(base_url, "/api/v2/api-consumers", operator_key)
existing = first_by(consumers, "name", "ops-hub")
if existing:
return {"record": existing, "created": False}
record = request_json(
base_url,
"POST",
"/api/v2/api-consumers",
operator_key,
{
"name": "ops-hub",
"description": "API consumer for the VSM Operations hub",
"hubCapabilityManifestId": manifest_id,
"rateLimitPerMinute": 120,
"quotaPerDay": 50000,
},
expected={201},
)
return {"record": record, "created": True}
def write_runtime_key(full_key: str, output_path: str | None) -> Path:
if output_path:
path = Path(output_path)
path.write_text(full_key, encoding="utf-8")
else:
fd, raw_path = tempfile.mkstemp(prefix="ops-hub-runtime-key-", text=True)
path = Path(raw_path)
with os.fdopen(fd, "w", encoding="utf-8") as handle:
handle.write(full_key)
path.chmod(stat.S_IRUSR | stat.S_IWUSR)
return path
def ensure_runtime_key(
base_url: str,
operator_key: str,
api_consumer_id: str,
output_path: str | None,
) -> dict[str, Any]:
existing_runtime_key = load_secret("OPS_HUB_KEY", "OPS_HUB_KEY_FILE")
if existing_runtime_key:
return {
"created": False,
"token": existing_runtime_key,
"keyPrefix": existing_runtime_key[:8],
"keyFile": os.environ.get("OPS_HUB_KEY_FILE"),
}
response = request_json(
base_url,
"POST",
f"/api/v2/api-consumers/{api_consumer_id}/api-keys",
operator_key,
{"scopes": "framework:read hub:ops-hub:read hub:ops-hub:write"},
expected={201},
)
full_key = response.get("fullKey")
if not full_key:
raise BootstrapError("api key creation did not return display-once fullKey")
key_file = write_runtime_key(full_key, output_path)
api_key = response.get("apiKey") or {}
return {
"created": True,
"token": full_key,
"keyPrefix": api_key.get("keyPrefix", full_key[:8]),
"keyFile": str(key_file),
}
def ensure_widgets(base_url: str, runtime_key: str, hub_id: str, widget_seeds: list[dict[str, Any]]) -> dict[str, Any]:
existing_widgets = list_items(base_url, "/api/v2/widgets", runtime_key)
existing_by_ref = {
widget.get("capabilityRef"): widget
for widget in existing_widgets
if widget.get("hubId") == hub_id and widget.get("capabilityRef")
}
created: list[dict[str, Any]] = []
reused: list[dict[str, Any]] = []
for seed in widget_seeds:
existing = existing_by_ref.get(seed.get("capabilityRef"))
if existing:
reused.append(existing)
continue
body = {"hubId": hub_id, "status": "active", **seed}
created.append(request_json(base_url, "POST", "/api/v2/widgets", runtime_key, body, expected={201}))
return {"created": created, "reused": reused}
def submit_gitea_event(base_url: str, runtime_key: str, widgets: dict[str, Any]) -> dict[str, Any] | None:
all_widgets = widgets["created"] + widgets["reused"]
readiness = next(
(widget for widget in all_widgets if widget.get("capabilityRef") == "ops:readiness:gitea-registry"),
None,
)
if not readiness:
return None
return request_json(
base_url,
"POST",
"/api/v2/interaction-events",
runtime_key,
{
"widgetId": readiness["id"],
"eventType": "ops-endpoint-verified",
"viewContext": "railiance-apps/workplans/RAIL-AP-WP-0001",
"metadata": {
"vsmFunction": "OPS",
"vsmSystem": "S1",
"endpoint": "https://gitea.coulomb.social/v2/",
"expectedStatus": 401,
"observedHeader": "Docker-Distribution-Api-Version: registry/2.0",
"recordedBy": "ops-hub/scripts/ops-hub-bootstrap-api.py",
"recordedAt": int(time.time()),
},
},
expected={201},
)
from ops_hub.bootstrap import ( # noqa: E402
DEFAULT_BASE,
BootstrapError,
dry_run_bootstrap,
load_secret,
run_bootstrap,
)
def build_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--base", default=os.environ.get("IHUB_BASE", DEFAULT_BASE).rstrip("/"))
parser.add_argument("--runtime-key-output", default=os.environ.get("OPS_HUB_RUNTIME_KEY_OUTPUT"))
parser.add_argument("--dry-run", action="store_true", help="Plan bootstrap actions without mutating Inter-Hub")
parser.add_argument("--skip-event", action="store_true", help="Do not submit the initial Gitea readiness event")
return parser
@@ -323,39 +42,15 @@ def main() -> int:
print("ERROR: set IHUB_OPERATOR_KEY or IHUB_OPERATOR_KEY_FILE", file=sys.stderr)
return 2
manifest = load_manifest()
widget_seeds = load_widgets()
hub = ensure_hub(args.base, operator_key, manifest)
hub_record = hub["record"]
manifest_result = ensure_manifest(args.base, operator_key, hub_record["id"], manifest)
manifest_record = manifest_result["record"]
consumer = ensure_api_consumer(args.base, operator_key, manifest_record["id"])
runtime_key = ensure_runtime_key(args.base, operator_key, consumer["record"]["id"], args.runtime_key_output)
widgets = ensure_widgets(args.base, runtime_key["token"], hub_record["id"], widget_seeds)
event = None if args.skip_event else submit_gitea_event(args.base, runtime_key["token"], widgets)
summary = {
"ok": True,
"base": args.base,
"hub": {"id": hub_record["id"], "slug": hub_record["slug"], "created": hub["created"]},
"manifest": {
"id": manifest_record["id"],
"status": manifest_record["status"],
"created": manifest_result["created"],
"activated": manifest_result["activated"],
},
"apiConsumer": {"id": consumer["record"]["id"], "name": consumer["record"]["name"], "created": consumer["created"]},
"runtimeKey": {
"created": runtime_key["created"],
"keyPrefix": runtime_key["keyPrefix"],
"keyFile": runtime_key["keyFile"],
"storeImmediatelyInOpenBao": "platform/operators/ops-hub/runtime",
"field": "OPS_HUB_KEY",
},
"widgets": {"created": len(widgets["created"]), "reused": len(widgets["reused"])},
"event": None if event is None else {"id": event["id"], "eventType": event["eventType"], "widgetId": event["widgetId"]},
}
if args.dry_run:
summary = dry_run_bootstrap(args.base, operator_key, skip_event=args.skip_event)
else:
summary = run_bootstrap(
args.base,
operator_key,
runtime_key_output=args.runtime_key_output,
skip_event=args.skip_event,
)
print(json.dumps(summary, indent=2, sort_keys=True))
return 0
@@ -365,4 +60,4 @@ if __name__ == "__main__":
raise SystemExit(main())
except BootstrapError as exc:
print(f"ERROR: {exc}", file=sys.stderr)
raise SystemExit(1)
raise SystemExit(1)

534
src/ops_hub/bootstrap.py Normal file
View File

@@ -0,0 +1,534 @@
"""Authenticated Inter-Hub bootstrap client for ops-hub."""
from __future__ import annotations
import json
import os
import stat
import tempfile
import time
import urllib.error
import urllib.parse
import urllib.request
from dataclasses import dataclass
from pathlib import Path
from typing import Any
from ops_hub.interhub_gate_probe import probe_interhub_gate
DEFAULT_BASE = "https://hub.coulomb.social"
ROOT = Path(__file__).resolve().parents[2]
MANIFEST_PATH = ROOT / "seeds" / "ops-hub-manifest.draft.json"
WIDGETS_PATH = ROOT / "seeds" / "ops-hub-widgets.seed.json"
class BootstrapError(RuntimeError):
pass
@dataclass(frozen=True)
class BootstrapPlan:
gate_passed: bool
hub: dict[str, Any]
manifest: dict[str, Any]
api_consumer: dict[str, Any]
runtime_key: dict[str, Any]
widgets: dict[str, Any]
event: dict[str, Any] | None
def load_secret(name: str, file_name: str) -> str:
value = os.environ.get(name, "").strip()
if value:
return value
file_path = os.environ.get(file_name, "").strip()
if file_path:
return Path(file_path).read_text(encoding="utf-8").strip()
return ""
def request_json(
base_url: str,
method: str,
path: str,
token: str | None,
body: dict[str, Any] | None,
*,
expected: set[int],
) -> dict[str, Any]:
data = json.dumps(body).encode("utf-8") if body is not None else None
request = urllib.request.Request(base_url + path, data=data, method=method)
request.add_header("Accept", "application/json")
request.add_header("User-Agent", "ops-hub-bootstrap/0.1")
if token:
request.add_header("Authorization", f"Bearer {token}")
if body is not None:
request.add_header("Content-Type", "application/json")
try:
with urllib.request.urlopen(request, timeout=30) as response:
status = response.status
payload = response.read().decode("utf-8")
except urllib.error.HTTPError as error:
payload = error.read().decode("utf-8", errors="replace")
raise BootstrapError(f"{method} {path} failed with HTTP {error.code}: {payload}") from error
if status not in expected:
raise BootstrapError(f"{method} {path} returned HTTP {status}, expected {sorted(expected)}")
if not payload:
return {}
return json.loads(payload)
def list_items(base_url: str, path: str, token: str | None) -> list[dict[str, Any]]:
response = request_json(base_url, "GET", path, token, None, expected={200})
data = response.get("data", [])
if not isinstance(data, list):
raise BootstrapError(f"expected paginated data array from {path}")
return data
def first_by(items: list[dict[str, Any]], key: str, value: Any) -> dict[str, Any] | None:
return next((item for item in items if item.get(key) == value), None)
def load_manifest(path: Path = MANIFEST_PATH) -> dict[str, Any]:
manifest = json.loads(path.read_text(encoding="utf-8"))
required = [
"hub",
"manifestVersion",
"declaredWidgetTypes",
"declaredEventTypes",
"declaredAnnotationCategories",
"declaredPolicyScopes",
]
missing = [key for key in required if key not in manifest]
if missing:
raise BootstrapError(f"{path} missing required key(s): {', '.join(missing)}")
return manifest
def load_widgets(path: Path = WIDGETS_PATH) -> list[dict[str, Any]]:
widgets = json.loads(path.read_text(encoding="utf-8"))
if not isinstance(widgets, list):
raise BootstrapError(f"{path} must contain a JSON array")
return widgets
def find_hub(base_url: str, operator_key: str | None, slug: str) -> dict[str, Any] | None:
tokens: list[str | None] = [None]
if operator_key:
tokens.append(operator_key)
for token in tokens:
try:
existing = first_by(list_items(base_url, "/api/v2/hubs", token), "slug", slug)
except BootstrapError:
continue
if existing:
return existing
return None
def plan_hub(base_url: str, operator_key: str, manifest: dict[str, Any]) -> dict[str, Any]:
slug = manifest["hub"]["slug"]
existing = find_hub(base_url, operator_key, slug)
if existing:
return {"action": "reuse", "record": existing}
return {"action": "create", "record": manifest["hub"]}
def plan_manifest(
base_url: str,
operator_key: str,
hub_id: str,
manifest: dict[str, Any],
) -> dict[str, Any]:
query = urllib.parse.urlencode({"hubId": hub_id})
manifests = list_items(base_url, f"/api/v2/hub-capability-manifests?{query}", operator_key)
active = first_by(manifests, "status", "active")
if active:
return {"action": "reuse", "record": active, "activate": False}
draft = first_by(manifests, "status", "draft")
if draft:
return {"action": "update", "record": draft, "activate": True}
return {"action": "create", "record": manifest_body(manifest, hub_id), "activate": True}
def plan_api_consumer(base_url: str, operator_key: str) -> dict[str, Any]:
existing = first_by(list_items(base_url, "/api/v2/api-consumers", operator_key), "name", "ops-hub")
if existing:
return {"action": "reuse", "record": existing}
return {"action": "create", "record": {"name": "ops-hub"}}
def plan_runtime_key(api_consumer_id: str) -> dict[str, Any]:
existing_runtime_key = load_secret("OPS_HUB_KEY", "OPS_HUB_KEY_FILE")
if existing_runtime_key:
return {
"action": "reuse",
"apiConsumerId": api_consumer_id,
"keyPrefix": existing_runtime_key[:8],
}
return {"action": "create", "apiConsumerId": api_consumer_id}
def plan_widgets(
base_url: str,
runtime_key: str | None,
hub_id: str,
widget_seeds: list[dict[str, Any]],
) -> dict[str, Any]:
if not runtime_key:
return {
"action": "plan",
"create": [seed.get("capabilityRef") for seed in widget_seeds],
"reuse": [],
}
existing_widgets = list_items(base_url, "/api/v2/widgets", runtime_key)
existing_by_ref = {
widget.get("capabilityRef"): widget
for widget in existing_widgets
if widget.get("hubId") == hub_id and widget.get("capabilityRef")
}
create = [seed for seed in widget_seeds if seed.get("capabilityRef") not in existing_by_ref]
reuse = [existing_by_ref[seed["capabilityRef"]] for seed in widget_seeds if seed.get("capabilityRef") in existing_by_ref]
return {"action": "plan", "create": create, "reuse": reuse}
def plan_event(widgets: dict[str, Any], skip_event: bool) -> dict[str, Any] | None:
if skip_event:
return None
all_widgets = widgets.get("reuse", []) + widgets.get("create", [])
readiness = next(
(widget for widget in all_widgets if widget.get("capabilityRef") == "ops:readiness:gitea-registry"),
None,
)
if readiness:
return {"action": "submit", "widgetId": readiness.get("id"), "eventType": "ops-endpoint-verified"}
return {"action": "submit", "widgetId": None, "eventType": "ops-endpoint-verified"}
def build_plan(
base_url: str,
operator_key: str,
*,
skip_event: bool = False,
manifest: dict[str, Any] | None = None,
widget_seeds: list[dict[str, Any]] | None = None,
) -> BootstrapPlan:
manifest = manifest or load_manifest()
widget_seeds = widget_seeds or load_widgets()
gate = probe_interhub_gate(base_url)
if not gate.passed:
raise BootstrapError("Inter-Hub bootstrap gate is not open")
hub_plan = plan_hub(base_url, operator_key, manifest)
hub_id = hub_plan["record"]["id"] if hub_plan["action"] == "reuse" else "<new>"
manifest_plan = (
plan_manifest(base_url, operator_key, hub_plan["record"]["id"], manifest)
if hub_plan["action"] == "reuse"
else {"action": "create", "record": manifest_body(manifest), "activate": True}
)
consumer_plan = plan_api_consumer(base_url, operator_key)
consumer_id = consumer_plan["record"].get("id", "<new>")
runtime_plan = plan_runtime_key(consumer_id)
widgets_plan = plan_widgets(
base_url,
load_secret("OPS_HUB_KEY", "OPS_HUB_KEY_FILE") or None,
hub_id if hub_plan["action"] == "reuse" else "<new>",
widget_seeds,
)
event_plan = plan_event(widgets_plan, skip_event)
return BootstrapPlan(
gate_passed=gate.passed,
hub=hub_plan,
manifest=manifest_plan,
api_consumer=consumer_plan,
runtime_key=runtime_plan,
widgets=widgets_plan,
event=event_plan,
)
def manifest_body(manifest: dict[str, Any], hub_id: str | None = None) -> dict[str, Any]:
body: dict[str, Any] = {
"manifestVersion": manifest["manifestVersion"],
"declaredWidgetTypes": manifest["declaredWidgetTypes"],
"declaredEventTypes": manifest["declaredEventTypes"],
"declaredAnnotationCategories": manifest["declaredAnnotationCategories"],
"declaredPolicyScopes": manifest["declaredPolicyScopes"],
"capabilityDescription": manifest.get("capabilityDescription", ""),
"contact": manifest.get("contact", "operator"),
}
if hub_id:
body["hubId"] = hub_id
return body
def ensure_hub(base_url: str, operator_key: str, manifest: dict[str, Any]) -> dict[str, Any]:
hub_seed = manifest["hub"]
slug = hub_seed["slug"]
existing = find_hub(base_url, operator_key, slug)
if existing:
return {"record": existing, "created": False}
body = {
"slug": slug,
"name": hub_seed["name"],
"domain": hub_seed["domain"],
"hubKind": hub_seed.get("hubKind", "domain"),
"hubFamily": "vsm",
"vsmFunction": "OPS",
"vsmSystem": "1",
}
record = request_json(base_url, "POST", "/api/v2/hubs", operator_key, body, expected={201})
return {"record": record, "created": True}
def ensure_manifest(base_url: str, operator_key: str, hub_id: str, manifest: dict[str, Any]) -> dict[str, Any]:
query = urllib.parse.urlencode({"hubId": hub_id})
manifests = list_items(base_url, f"/api/v2/hub-capability-manifests?{query}", operator_key)
active = first_by(manifests, "status", "active")
if active:
return {"record": active, "created": False, "activated": False}
draft = first_by(manifests, "status", "draft")
if draft:
record = request_json(
base_url,
"PATCH",
f"/api/v2/hub-capability-manifests/{draft['id']}",
operator_key,
manifest_body(manifest),
expected={200},
)
created = False
else:
record = request_json(
base_url,
"POST",
"/api/v2/hub-capability-manifests",
operator_key,
manifest_body(manifest, hub_id),
expected={201},
)
created = True
activated = request_json(
base_url,
"POST",
f"/api/v2/hub-capability-manifests/{record['id']}/activate",
operator_key,
None,
expected={200},
)
return {"record": activated, "created": created, "activated": True}
def ensure_api_consumer(base_url: str, operator_key: str, manifest_id: str) -> dict[str, Any]:
consumers = list_items(base_url, "/api/v2/api-consumers", operator_key)
existing = first_by(consumers, "name", "ops-hub")
if existing:
return {"record": existing, "created": False}
record = request_json(
base_url,
"POST",
"/api/v2/api-consumers",
operator_key,
{
"name": "ops-hub",
"description": "API consumer for the VSM Operations hub",
"hubCapabilityManifestId": manifest_id,
"rateLimitPerMinute": 120,
"quotaPerDay": 50000,
},
expected={201},
)
return {"record": record, "created": True}
def write_runtime_key(full_key: str, output_path: str | None) -> Path:
if output_path:
path = Path(output_path)
path.write_text(full_key, encoding="utf-8")
else:
fd, raw_path = tempfile.mkstemp(prefix="ops-hub-runtime-key-", text=True)
path = Path(raw_path)
with os.fdopen(fd, "w", encoding="utf-8") as handle:
handle.write(full_key)
path.chmod(stat.S_IRUSR | stat.S_IWUSR)
return path
def ensure_runtime_key(
base_url: str,
operator_key: str,
api_consumer_id: str,
output_path: str | None,
) -> dict[str, Any]:
existing_runtime_key = load_secret("OPS_HUB_KEY", "OPS_HUB_KEY_FILE")
if existing_runtime_key:
return {
"created": False,
"token": existing_runtime_key,
"keyPrefix": existing_runtime_key[:8],
"keyFile": os.environ.get("OPS_HUB_KEY_FILE"),
}
response = request_json(
base_url,
"POST",
f"/api/v2/api-consumers/{api_consumer_id}/api-keys",
operator_key,
{"scopes": "framework:read hub:ops-hub:read hub:ops-hub:write"},
expected={201},
)
full_key = response.get("fullKey")
if not full_key:
raise BootstrapError("api key creation did not return display-once fullKey")
key_file = write_runtime_key(full_key, output_path)
api_key = response.get("apiKey") or {}
return {
"created": True,
"token": full_key,
"keyPrefix": api_key.get("keyPrefix", full_key[:8]),
"keyFile": str(key_file),
}
def ensure_widgets(base_url: str, runtime_key: str, hub_id: str, widget_seeds: list[dict[str, Any]]) -> dict[str, Any]:
existing_widgets = list_items(base_url, "/api/v2/widgets", runtime_key)
existing_by_ref = {
widget.get("capabilityRef"): widget
for widget in existing_widgets
if widget.get("hubId") == hub_id and widget.get("capabilityRef")
}
created: list[dict[str, Any]] = []
reused: list[dict[str, Any]] = []
for seed in widget_seeds:
existing = existing_by_ref.get(seed.get("capabilityRef"))
if existing:
reused.append(existing)
continue
body = {"hubId": hub_id, "status": "active", **seed}
created.append(request_json(base_url, "POST", "/api/v2/widgets", runtime_key, body, expected={201}))
return {"created": created, "reused": reused}
def submit_gitea_event(base_url: str, runtime_key: str, widgets: dict[str, Any]) -> dict[str, Any] | None:
all_widgets = widgets["created"] + widgets["reused"]
readiness = next(
(widget for widget in all_widgets if widget.get("capabilityRef") == "ops:readiness:gitea-registry"),
None,
)
if not readiness:
return None
return request_json(
base_url,
"POST",
"/api/v2/interaction-events",
runtime_key,
{
"widgetId": readiness["id"],
"eventType": "ops-endpoint-verified",
"viewContext": "railiance-apps/workplans/RAIL-AP-WP-0001",
"metadata": {
"vsmFunction": "OPS",
"vsmSystem": "S1",
"endpoint": "https://gitea.coulomb.social/v2/",
"expectedStatus": 401,
"observedHeader": "Docker-Distribution-Api-Version: registry/2.0",
"recordedBy": "ops-hub/scripts/ops-hub-bootstrap-api.py",
"recordedAt": int(time.time()),
},
},
expected={201},
)
def run_bootstrap(
base_url: str,
operator_key: str,
*,
runtime_key_output: str | None = None,
skip_event: bool = False,
manifest: dict[str, Any] | None = None,
widget_seeds: list[dict[str, Any]] | None = None,
) -> dict[str, Any]:
gate = probe_interhub_gate(base_url)
if not gate.passed:
raise BootstrapError("Inter-Hub bootstrap gate is not open")
manifest = manifest or load_manifest()
widget_seeds = widget_seeds or load_widgets()
hub = ensure_hub(base_url, operator_key, manifest)
hub_record = hub["record"]
manifest_result = ensure_manifest(base_url, operator_key, hub_record["id"], manifest)
manifest_record = manifest_result["record"]
consumer = ensure_api_consumer(base_url, operator_key, manifest_record["id"])
runtime_key = ensure_runtime_key(base_url, operator_key, consumer["record"]["id"], runtime_key_output)
widgets = ensure_widgets(base_url, runtime_key["token"], hub_record["id"], widget_seeds)
event = None if skip_event else submit_gitea_event(base_url, runtime_key["token"], widgets)
return {
"ok": True,
"dryRun": False,
"base": base_url,
"gate": {"passed": gate.passed, "hubsStatus": gate.hubs_status},
"hub": {"id": hub_record["id"], "slug": hub_record["slug"], "created": hub["created"]},
"manifest": {
"id": manifest_record["id"],
"status": manifest_record["status"],
"created": manifest_result["created"],
"activated": manifest_result["activated"],
},
"apiConsumer": {"id": consumer["record"]["id"], "name": consumer["record"]["name"], "created": consumer["created"]},
"runtimeKey": {
"created": runtime_key["created"],
"keyPrefix": runtime_key["keyPrefix"],
"keyFile": runtime_key["keyFile"],
"storeImmediatelyInOpenBao": "platform/operators/ops-hub/runtime",
"field": "OPS_HUB_KEY",
},
"widgets": {"created": len(widgets["created"]), "reused": len(widgets["reused"])},
"event": None
if event is None
else {"id": event["id"], "eventType": event["eventType"], "widgetId": event["widgetId"]},
}
def dry_run_bootstrap(
base_url: str,
operator_key: str,
*,
skip_event: bool = False,
manifest: dict[str, Any] | None = None,
widget_seeds: list[dict[str, Any]] | None = None,
) -> dict[str, Any]:
gate = probe_interhub_gate(base_url)
plan = build_plan(
base_url,
operator_key,
skip_event=skip_event,
manifest=manifest,
widget_seeds=widget_seeds,
)
return {
"ok": True,
"dryRun": True,
"base": base_url,
"gate": {"passed": gate.passed, "hubsStatus": gate.hubs_status},
"plan": {
"hub": plan.hub,
"manifest": plan.manifest,
"apiConsumer": plan.api_consumer,
"runtimeKey": plan.runtime_key,
"widgets": {
"create": len(plan.widgets.get("create", [])),
"reuse": len(plan.widgets.get("reuse", [])),
},
"event": plan.event,
},
}

View File

@@ -82,7 +82,7 @@ def probe_interhub_gate(base_url: str, timeout: float = 10.0) -> GateResult:
hubs = observe_status(api_url(normalized, "/api/v2/hubs"), timeout)
openapi_observation, openapi = fetch_json(api_url(normalized, "/api/v2/openapi.json"), timeout)
present, missing = evaluate_openapi_paths(openapi)
passed = hubs.status == 401 and not missing
passed = hubs.status in {200, 401} and not missing
return GateResult(
base_url=normalized.rstrip("/"),
passed=passed,

96
tests/test_bootstrap.py Normal file
View File

@@ -0,0 +1,96 @@
from __future__ import annotations
import json
import unittest
from pathlib import Path
from unittest.mock import patch
from typing import Any
from ops_hub.bootstrap import (
MANIFEST_PATH,
WIDGETS_PATH,
find_hub,
load_manifest,
load_widgets,
manifest_body,
plan_api_consumer,
plan_event,
plan_hub,
plan_runtime_key,
)
class BootstrapTests(unittest.TestCase):
def test_load_manifest_and_widgets(self) -> None:
manifest = load_manifest()
widgets = load_widgets()
self.assertEqual(manifest["hub"]["slug"], "ops-hub")
self.assertGreaterEqual(len(widgets), 1)
def test_manifest_body_includes_hub_id_when_provided(self) -> None:
manifest = load_manifest()
body = manifest_body(manifest, "hub-123")
self.assertEqual(body["hubId"], "hub-123")
self.assertIn("declaredWidgetTypes", body)
def test_find_hub_uses_public_discovery_before_operator_token(self) -> None:
calls: list[str | None] = []
def fake_list_items(base_url: str, path: str, token: str | None) -> list[dict[str, Any]]:
calls.append(token)
if token is None:
return [{"slug": "ops-hub", "id": "hub-public"}]
return []
with patch("ops_hub.bootstrap.list_items", side_effect=fake_list_items):
found = find_hub("https://hub.example", "operator-key", "ops-hub")
self.assertEqual(found["id"], "hub-public")
self.assertEqual(calls, [None])
def test_plan_hub_reports_create_when_missing(self) -> None:
manifest = load_manifest()
with patch("ops_hub.bootstrap.find_hub", return_value=None):
plan = plan_hub("https://hub.example", "operator-key", manifest)
self.assertEqual(plan["action"], "create")
def test_plan_hub_reports_reuse_when_present(self) -> None:
manifest = load_manifest()
existing = {"id": "hub-1", "slug": "ops-hub"}
with patch("ops_hub.bootstrap.find_hub", return_value=existing):
plan = plan_hub("https://hub.example", "operator-key", manifest)
self.assertEqual(plan["action"], "reuse")
self.assertEqual(plan["record"]["id"], "hub-1")
def test_plan_api_consumer_reports_reuse(self) -> None:
with patch(
"ops_hub.bootstrap.list_items",
return_value=[{"id": "consumer-1", "name": "ops-hub"}],
):
plan = plan_api_consumer("https://hub.example", "operator-key")
self.assertEqual(plan["action"], "reuse")
def test_plan_runtime_key_reports_reuse_from_env(self) -> None:
with patch.dict("os.environ", {"OPS_HUB_KEY": "runtime-key-value"}, clear=False):
plan = plan_runtime_key("consumer-1")
self.assertEqual(plan["action"], "reuse")
self.assertEqual(plan["keyPrefix"], "runtime-")
def test_plan_event_targets_gitea_readiness_widget(self) -> None:
widgets = {
"reuse": [{"id": "widget-1", "capabilityRef": "ops:readiness:gitea-registry"}],
"create": [],
}
event = plan_event(widgets, skip_event=False)
self.assertIsNotNone(event)
assert event is not None
self.assertEqual(event["widgetId"], "widget-1")
self.assertEqual(event["eventType"], "ops-endpoint-verified")
def test_seed_files_are_valid_json(self) -> None:
json.loads(MANIFEST_PATH.read_text(encoding="utf-8"))
json.loads(WIDGETS_PATH.read_text(encoding="utf-8"))
if __name__ == "__main__":
unittest.main()

View File

@@ -4,11 +4,12 @@ type: workplan
title: "Bootstrap State Hub integration"
domain: infotech
repo: ops-hub
status: finished
status: archived
owner: codex
topic_slug: inter_hub
created: "2026-06-06"
updated: "2026-06-06"
updated: "2026-07-07"
state_hub_workstream_id: "636b6196-742a-4d09-8b8c-152a4686ad35"
---
# Bootstrap State Hub integration
@@ -22,6 +23,7 @@ with the first concrete `ops-hub` operating frame.
id: OPS-WP-0001-T01
status: done
priority: high
state_hub_task_id: "c102264b-f104-4e04-ae84-3db441e60659"
```
Review `INTENT.md`, `SCOPE.md`, `AGENTS.md`, and `.custodian-brief.md`.
@@ -30,22 +32,29 @@ Replace generated placeholders with repo-specific facts where needed.
Completed 2026-06-06: `INTENT.md`, `SCOPE.md`, `AGENTS.md`, and `README.md`
now describe `ops-hub` as the Operations / System 1 Inter-Hub extension.
Refreshed 2026-07-07: filled `.claude/rules/stack-and-commands.md`,
`architecture.md`, `repo-boundary.md`, updated `SCOPE.md` current state, and
added repo-native dev commands to `AGENTS.md`.
## Verify Local Developer Workflow
```task
id: OPS-WP-0001-T02
status: done
priority: high
state_hub_task_id: "39b276bc-956a-497b-a5d9-f9d5b551aa86"
```
Identify the repo's install, test, lint, build, and run commands. Add or refine
those commands in the agent instructions so future coding sessions can verify
changes confidently.
Completed 2026-06-06: the repo currently has no executable source tree,
dependency manifest, test suite, or build command. `AGENTS.md` records
documentation/workplan verification commands and requires future source work to
add repo-native lint, test, build, and run commands.
Completed 2026-06-06: initial bootstrap had no source tree.
Refreshed 2026-07-07 after OPS-WP-0002: `pyproject.toml`, `src/ops_hub/`,
`tests/`, and `Makefile` provide `make test`, `make interhub-gate`, and
`make interhub-bootstrap` targets documented in `AGENTS.md` and
`.claude/rules/stack-and-commands.md`.
## Seed First Real Workplan
@@ -53,6 +62,7 @@ add repo-native lint, test, build, and run commands.
id: OPS-WP-0001-T03
status: done
priority: medium
state_hub_task_id: "dbb77b70-076f-4ff5-b77b-16daf683a4c7"
```
Create the first implementation workplan for the repository's most important

View File

@@ -4,11 +4,12 @@ type: workplan
title: "Bootstrap ops-hub as an Inter-Hub Operations extension"
domain: infotech
repo: ops-hub
status: active
status: archived
owner: codex
topic_slug: inter_hub
created: "2026-06-06"
updated: "2026-06-06"
updated: "2026-07-07"
state_hub_workstream_id: "bea9126c-2f58-41d4-90d1-af4d096f4a10"
---
# Bootstrap ops-hub as an Inter-Hub Operations extension
@@ -29,19 +30,17 @@ bootstrap API substrate.
## Current Gate
As of 2026-06-06, public production Inter-Hub still returns `404` for:
```text
https://hub.coulomb.social/api/v2/hubs
```
As of 2026-07-07, production Inter-Hub exposes the bootstrap API surface at
`https://hub.coulomb.social`. Run `make interhub-gate` to verify the current
gate before bootstrap.
Do not run manual database seeding unless the operator explicitly chooses that
fallback. The preferred bootstrap path is the supported Inter-Hub API once
production exposes the current bootstrap surface.
fallback. The preferred bootstrap path is the supported Inter-Hub API.
Gate criteria:
- Unauthenticated `GET /api/v2/hubs` returns `401`, not `404`.
- Unauthenticated `GET /api/v2/hubs` returns `200` (public discovery) or `401`
(auth-gated listing), not `404`.
- OpenAPI lists `/hubs`, `/hub-capability-manifests`, `/api-consumers`, and
`/policy-scopes`.
- The bootstrap/smoke client can create or reuse the `ops-hub` hub, activate
@@ -63,6 +62,7 @@ Gate criteria:
id: OPS-WP-0002-T01
status: done
priority: high
state_hub_task_id: "7cd1eddb-f508-493b-89b1-6d8575bfd3df"
```
Create repo-local docs and seed data for the ops vocabulary, initial inventory,
@@ -86,6 +86,7 @@ Completed 2026-06-06:
id: OPS-WP-0002-T02
status: done
priority: high
state_hub_task_id: "27d45a1d-813d-482f-8017-3884be4b509e"
```
Choose and create the first source layout for bootstrap/smoke tooling,
@@ -108,11 +109,12 @@ Completed 2026-06-06:
id: OPS-WP-0002-T03
status: done
priority: high
state_hub_task_id: "3ef0493c-6652-4dd2-a794-5e309c6cef88"
```
Build a small probe that checks the public Inter-Hub bootstrap API gate:
- `/api/v2/hubs` response is `401` unauthenticated.
- `/api/v2/hubs` response is `200` or `401` unauthenticated.
- OpenAPI lists the required bootstrap paths.
- The result is machine-readable and suitable for a scheduled ops signal later.
@@ -121,14 +123,16 @@ gate as pass/fail with clear reasons.
Completed 2026-06-06: `scripts/interhub-gate-probe.py` checks unauthenticated
`/api/v2/hubs` status and required OpenAPI bootstrap paths, emits JSON, and
exits nonzero while the gate is closed.
exits nonzero while the gate is closed. Updated 2026-07-07 to accept public hub
discovery (`200`) as well as auth-gated listing (`401`).
## Implement Bootstrap Smoke Client
```task
id: OPS-WP-0002-T04
status: wait
status: done
priority: high
state_hub_task_id: "1a8fa43a-d524-4852-94dc-2606098002dc"
```
Implement the authenticated bootstrap/smoke client once Inter-Hub production
@@ -146,14 +150,21 @@ reuse:
Done when a dry-run and an attended real run both produce repeatable evidence
without direct DB access.
Waiting on: Inter-Hub production API gate from T03.
Completed 2026-07-07:
- Extracted bootstrap logic to `src/ops_hub/bootstrap.py`.
- `scripts/ops-hub-bootstrap-api.py` supports `--dry-run` and `--skip-event`.
- Public hub discovery is attempted before authenticated listing.
- `make interhub-bootstrap-dry-run` and `make test` verify the client locally.
- Attended production run: `make interhub-bootstrap IHUB_OPERATOR_KEY_FILE=...`
## Seed First Operational Signal
```task
id: OPS-WP-0002-T05
status: wait
status: done
priority: medium
state_hub_task_id: "b7d09ecd-0899-470d-aea5-6e2f07caae96"
```
Submit the first governed ops signal for the Gitea registry endpoint once the
@@ -173,4 +184,12 @@ Initial signal:
Done when the event is visible in Inter-Hub and traceable to the owning
Railiance workplan.
Waiting on: T04 and an available `ops-hub` runtime API key.
Completed 2026-07-07 via `warden access --exec` with `platform-admin` OpenBao
token:
- Hub `ops-hub` (`4f6e4cf7-6a96-4ff2-8a37-08c9f9e405d2`) reused.
- Active manifest `00aaf90a-8e76-4b0e-892d-33b162862f38` reused.
- Event `3c894714-1b90-4cfa-9ce1-340704bd6526` (`ops-endpoint-verified`) on
widget `8c768282-aca6-466b-9c62-c6fc8f2d5624`.
- Runtime key prefix `ch_HfXNc138N` stored at
`platform/operators/ops-hub/runtime` (`OPS_HUB_KEY`).