implement ops hub extension contract
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a053ff-1d6f-7fe2-ac1c-a6eb40a42a0c
This commit is contained in:
tegwick 2026-08-31 21:31:53 +02:00
parent 9bbbf2032d
commit 75f4944144
14 changed files with 662 additions and 43 deletions

View file

@ -1,17 +1,33 @@
IHUB_BASE ?= https://hub.coulomb.social IHUB_BASE ?= https://hub.coulomb.social
IHUB_OPERATOR_KEY_FILE ?= IHUB_OPERATOR_KEY_FILE ?=
OPS_HUB_RUNTIME_KEY_OUTPUT ?= OPS_HUB_RUNTIME_KEY_OUTPUT ?=
HUB_CORE_REPO ?= ../hub-core
HUB_CORE_PYTHON ?= $(HUB_CORE_REPO)/.venv/bin/python
.PHONY: help interhub-gate interhub-bootstrap interhub-bootstrap-dry-run interhub-bootstrap-help test .PHONY: help hub-extension-check hub-core-conformance interhub-gate interhub-bootstrap interhub-bootstrap-dry-run interhub-bootstrap-help test
help: help:
@echo "Targets:" @echo "Targets:"
@echo " hub-extension-check Validate the owner package against hub-core 0.1.0 schemas/catalog"
@echo " hub-core-conformance Exercise the owner package in a disposable hub-core runtime"
@echo " interhub-gate Probe whether production Inter-Hub exposes the ops-hub bootstrap API surface" @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-help Show bootstrap helper options"
@echo " interhub-bootstrap-dry-run Plan bootstrap actions with IHUB_OPERATOR_KEY_FILE (no mutations)" @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 " interhub-bootstrap Run attended ops-hub Inter-Hub bootstrap with IHUB_OPERATOR_KEY_FILE"
@echo " test Run unit tests" @echo " test Run unit tests"
hub-extension-check:
@test -x "$(HUB_CORE_PYTHON)" || \
(echo "hub-core environment missing at $(HUB_CORE_PYTHON)" >&2; exit 2)
PYTHONPATH=src "$(HUB_CORE_PYTHON)" scripts/hub-extension-check.py \
--hub-core-repo "$(HUB_CORE_REPO)"
hub-core-conformance:
@test -x "$(HUB_CORE_PYTHON)" || \
(echo "hub-core environment missing at $(HUB_CORE_PYTHON)" >&2; exit 2)
PYTHONPATH=src "$(HUB_CORE_PYTHON)" scripts/hub-core-conformance.py \
--hub-core-repo "$(HUB_CORE_REPO)"
interhub-gate: interhub-gate:
IHUB_BASE="$(IHUB_BASE)" python3 scripts/interhub-gate-probe.py IHUB_BASE="$(IHUB_BASE)" python3 scripts/interhub-gate-probe.py

View file

@ -1,7 +1,11 @@
Operations / System 1 extension for Core Hub. Operations / System 1 extension for Hub Core.
The versioned `helixforge.hub-extension` descriptor, manifest, validation, and
State Hub retirement boundary are documented in
[`docs/hub-extension.md`](docs/hub-extension.md).
`ops-hub` is the operational truth surface for environments, hosts, clusters, `ops-hub` is the operational truth surface for environments, hosts, clusters,
services, endpoints, releases, backups, incidents, risks, runbooks, readiness services, endpoints, releases, backups, incidents, risks, runbooks, readiness
gates, and migration waves. Generic hub framework work stays in `core-hub`; gates, and migration waves. Generic hub framework work stays in `hub-core`;
operations-specific extension code belongs here. Historical Haskell Inter-Hub is operations-specific extension code belongs here. Historical Haskell Inter-Hub is
`inter-hub-haskell` (retired 2026-07-08). `inter-hub-haskell` (retired 2026-07-08).

View file

@ -8,7 +8,7 @@
| Kind | ID | Status | Lane | Source | | Kind | ID | Status | Lane | Source |
| --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- |
| workplan | OPS-WP-0003 | proposed | — | workplans/OPS-WP-0003-extension-contract-alignment.md | | workplan | OPS-WP-0003 | finished | — | workplans/OPS-WP-0003-extension-contract-alignment.md |
| task | OPS-WP-0003-T01 | todo | — | workplans/OPS-WP-0003-extension-contract-alignment.md | | task | OPS-WP-0003-T01 | done | — | workplans/OPS-WP-0003-extension-contract-alignment.md |
| task | OPS-WP-0003-T02 | todo | — | workplans/OPS-WP-0003-extension-contract-alignment.md | | task | OPS-WP-0003-T02 | done | — | workplans/OPS-WP-0003-extension-contract-alignment.md |
| task | OPS-WP-0003-T03 | todo | — | workplans/OPS-WP-0003-extension-contract-alignment.md | | task | OPS-WP-0003-T03 | done | — | workplans/OPS-WP-0003-extension-contract-alignment.md |

View file

@ -1,18 +1,20 @@
# Ops Hub Bootstrap Runbook # Ops Hub Bootstrap Runbook
Date: 2026-06-17 Date: 2026-08-31
## Purpose ## Purpose
This runbook is the operator-ready path for activating `ops-hub` in production This runbook is the operator-ready path for activating `ops-hub` in production
Inter-Hub. It covers the preferred API bootstrap, key custody expectations, the Hub Core's `/api/v2` compatibility surface. It covers the preferred API
ops-warden remote execution lane, and the explicit SQL fallback. bootstrap, key custody expectations, the ops-warden remote execution lane, and
the explicit SQL fallback.
Use this when finishing `CUST-WP-0047-T05` or any later ops-hub Inter-Hub Use this when finishing `CUST-WP-0047-T05` or any later ops-hub Inter-Hub
activation task. activation task.
## Inputs ## Inputs
- Hub-extension package: `registry/hub-extension/v0.1.0/ops-hub.extension.json`
- Manifest draft: `seeds/ops-hub-manifest.draft.json` - Manifest draft: `seeds/ops-hub-manifest.draft.json`
- Widget seed: `seeds/ops-hub-widgets.seed.json` - Widget seed: `seeds/ops-hub-widgets.seed.json`
- API helper: `scripts/ops-hub-bootstrap-api.py` - API helper: `scripts/ops-hub-bootstrap-api.py`
@ -167,14 +169,21 @@ curl -s https://hub.coulomb.social/api/v2/hub-registry
Expected: `ops-hub` is visible, and the operator can see the seeded widgets in Expected: `ops-hub` is visible, and the operator can see the seeded widgets in
the authenticated UI. the authenticated UI.
## Current Live-Execution Blocker ## Authenticated rerun boundary
The repo-side helper, dry-run path, and runbook are ready. The remaining step is Ops Hub bootstrap and consumer gates passed during the hub-core candidate
an operator-attended production run with: cutover (`RAPPCOREHUB-WP-0002-T04`), and the 2026-08-31 post-cutover public
gate passes against `https://hub.coulomb.social`. There is no pending bootstrap
mutation merely to finish `OPS-WP-0003`.
- an operator-provided `IHUB_OPERATOR_KEY_FILE`, An authenticated rerun remains a high-risk attended operation because it may
- an OpenBao-materialized key on a trusted host, or create a consumer key or production records. Use it only for a real registration
- an explicitly approved deployment-side migration/bootstrap path. change, start with `warden route show inter-hub-bootstrap-ssh --json`, and
record non-secret evidence. For routine validation use:
Until one of those is available, run `make interhub-gate`, `make test`, and ```bash
`make interhub-bootstrap-dry-run` for local validation. make test
make hub-extension-check
make hub-core-conformance
make interhub-gate
```

78
docs/hub-extension.md Normal file
View file

@ -0,0 +1,78 @@
# Ops Hub extension package
Ops Hub implements the owner side of `helixforge.hub-extension` 0.1.0. Hub
Core owns and runs the framework ports; this repository owns the operations
descriptor, capability declarations, event boundary, compatibility bootstrap,
and evidence used to move service-catalog responsibility out of State Hub.
The canonical package is
`registry/hub-extension/v0.1.0/ops-hub.extension.json`. Its stable identity is
`capability.operations.ops-hub`; it also declares
`capability.operations.service-catalog` as an owner capability.
## Ownership boundary
| Surface | Owner |
| --- | --- |
| Descriptor, manifest, operational vocabulary, service-catalog records | `ops-hub` |
| `port.*` schemas, event catalog, registry and projection runtime | `hub-core` |
| Runtime and operator credentials | OpenBao/platform custody; never this package |
| State Hub compatibility routes during retirement | `state-hub` until their evidenced cutover |
Ops Hub is an aspect hub, not a second hub-core deployment. The API endpoint in
the manifest is a discovery reference to the hub-core-hosted compatibility
surface at `https://hub.coulomb.social/api/v2`.
## Events and legacy compatibility
The 0.1.0 port contract emits `ops.endpoint.verified` and consumes
`hub.progress.recorded`. The older `/api/v2` bootstrap seed uses
`ops-endpoint-verified`; hub-core's compatibility adapter retains that legacy
spelling. New port-native evidence uses the dotted catalog event and must not
silently rewrite historical events.
## Validation
```bash
make test
make hub-extension-check
make hub-core-conformance
make interhub-gate
```
`hub-extension-check` validates the owner package against hub-core's packaged
Draft 2020-12 descriptor and manifest schemas, checks every declared event
against hub-core's catalog, and emits a non-secret checksum receipt.
`hub-core-conformance` injects this repository's package into a disposable
hub-core reference runtime. Contract version 0.1.0 automates C1, C3, C4, C5,
C6, and C8 plus Tier-3 F2 and F3. C2 registry resolution, C7 raw-port policy,
C9 dependency-aware readiness, and C10 version negotiation are not automated
by the current hub-core harness and are not represented as passing.
`interhub-gate` is the safe post-cutover production check. It proves that the
hub-core-hosted `/api/v2` surface exposes the bootstrap resources without
requiring a credential or mutating production.
## Authenticated bootstrap
The existing `scripts/ops-hub-bootstrap-api.py` remains the idempotent
compatibility bootstrap client. It creates or reuses the hub, manifest, API
consumer, widgets, and verification event. Follow `docs/bootstrap-runbook.md`.
Operator and runtime keys are never arguments, logs, Git content, or extension
fields. Credential routing starts with:
```bash
warden route show inter-hub-bootstrap-ssh --json
```
The current route is high-risk and attended. A source change or public gate
does not authorize another live bootstrap mutation.
## State Hub retirement handoff
This package satisfies the receiving-side contract for `STATE-WP-0079` Wave
D1. Removing State Hub's service-catalog routes still requires a separate
caller inventory, projection/count comparison, rollback receipt, and explicit
production writer-cutover authorization. Owner readiness is not cutover proof.

View file

@ -1,15 +0,0 @@
---
repo: ops-hub
reason: >
Only a single diagnostic bootstrap-API probe script exists; the described operational-truth surface (hosts/services/incidents/runbooks) isn't implemented yet.
reviewed: "2026-07-06"
reviewed_by: claude-code
revisit: >
Revisit once the operational-truth surface has real implementation beyond the probe script.
---
# No reusable capability
This repo was reviewed for the `reuse-surface` capability registry
(REUSE-WP-0017 coverage campaign) and has no capability to register at this
time. See the `reason` field above.

View file

@ -0,0 +1,140 @@
---
id: capability.operations.ops-hub
name: Operations Hub Extension Contract
summary: Versioned hub-extension package and bootstrap client for operational truth, service-catalog records, readiness evidence, and migration gates.
owner: ops-hub
status: reviewed
domain: operations
tags:
- operations
- service-catalog
- readiness
- hub-extension
maturity:
discovery:
current: D3
target: D4
confidence: high
rationale: >
The owner boundary, versioned descriptor/manifest, hub-core ports, event
families, compatibility bootstrap, and State Hub retirement handoff are
explicit and tested.
availability:
current: A1
target: A3
confidence: high
rationale: >
The contract package and idempotent bootstrap client are available from
source; the framework runtime is hosted by hub-core rather than this repo.
external_evidence:
completeness:
level: C1
confidence: medium
basis: scope_vs_intent_and_consumer_expectations
satisfied_expectations:
- versioned extension descriptor and manifest
- hub-core schema and event-catalog validation
- disposable Tier 2/3 conformance profile
- production compatibility API public gate
broken_expectations: []
out_of_scope_expectations:
- independent framework runtime
- secret custody
reliability:
level: R1
confidence: high
basis: consumer_quality_signals
known_reliability_risks:
- authenticated re-bootstrap requires the attended high-risk access lane
discovery:
intent: >
Let hub-core host an Ops Hub extension without transferring ownership of
operational records or credentials into the framework.
includes:
- descriptor and capability manifest
- operations service-catalog declaration
- readiness evidence event boundary
- compatibility bootstrap client and public gate
excludes:
- hub-core framework implementation
- credential storage or vending
- State Hub compatibility routes after cutover
assumptions:
- hub-core remains the surviving framework runtime
use_cases:
- register Ops Hub against hub-core
- publish and project service-catalog records
- attach non-secret readiness evidence
research_memos: []
availability:
current_level: A1
target_level: A3
current_artifacts:
- registry/hub-extension/v0.1.0/ops-hub.extension.json
- scripts/ops-hub-bootstrap-api.py
- scripts/hub-extension-check.py
- scripts/hub-core-conformance.py
target_artifacts:
- policy-bound unattended registration lane
consumption_modes:
- contract package
- command-line bootstrap
relations:
depends_on:
- capability.infotech.hub-core-library
supports:
- capability.operations.service-catalog
related_to: []
evidence:
documentation:
- docs/hub-extension.md
- docs/bootstrap-runbook.md
tests:
- tests/test_extension_contract.py
- make hub-core-conformance
consumer_feedback:
- RAPPCOREHUB-WP-0002-T04
bug_reports: []
incidents: []
consumer_guidance:
recommended_for:
- registering and validating the Ops Hub extension on hub-core
- migrating State Hub service-catalog consumers to an owner-backed contract
not_recommended_for:
- treating ops-hub as another hub-core runtime
- retrieving or storing credentials
known_limitations:
- C2, C7, C9, and C10 are not automated by hub-core contract version 0.1.0
- authenticated live bootstrap requires the governed attended access lane
promotion_history:
- date: "2026-08-31"
dimension: discovery
from: D0
to: D3
rationale: Published the owner-side 0.1.0 package and conformance evidence.
author: codex
- date: "2026-08-31"
dimension: availability
from: A0
to: A1
rationale: Published source-level validation and bootstrap consumers.
author: codex
---
# Operations Hub Extension Contract
The capability is the owner-side contract package and bootstrap client. Hub
Core supplies the framework runtime; Ops Hub retains the operational vocabulary,
service-catalog model, readiness evidence, and migration-gate ownership.
The package contains no credentials. Authenticated bootstrap follows
`docs/bootstrap-runbook.md` and emits only non-secret identifiers and key
prefixes as evidence.

View file

@ -0,0 +1,76 @@
{
"descriptor": {
"contract_id": "helixforge.hub-extension",
"contract_version": "0.1.0",
"hub_slug": "ops-hub",
"display_name": "Operations Hub",
"description": "Operations aspect hub for operational truth, service-catalog records, readiness evidence, and migration gates.",
"domain": "operations",
"hub_kind": "aspect",
"status": "active",
"reuse_surface_id": "capability.operations.ops-hub",
"contract_version_min": "0.1.0",
"contract_version_max": "0.1.0",
"vsm_system": "operations",
"vsm_function": "coordination"
},
"manifest": {
"manifest_version": "0.1.0",
"schema_version": "0.1.0",
"reuse_surface_id": "capability.operations.ops-hub",
"provides": [
"capability.operations.ops-hub",
"capability.operations.service-catalog"
],
"consumes": [
"port.registry",
"port.messaging",
"port.events.interaction",
"port.projection.query",
"port.policy"
],
"events_emitted": [
"ops.endpoint.verified"
],
"events_consumed": [
"hub.progress.recorded"
],
"endpoints": [
{
"id": "api",
"discovery_key": "service.ops-hub.http"
},
{
"id": "framework-api",
"url": "https://hub.coulomb.social/api/v2"
},
{
"id": "docs",
"url": "https://forgejo.coulomb.social/coulomb/ops-hub/src/branch/main/docs/hub-extension.md"
}
],
"policy_scopes": [
"ops.catalog.read",
"ops.evidence.write"
],
"widgets": [
{
"id": "ops-overview",
"kind": "widget",
"description": "Non-secret operations overview surface."
}
],
"operator_surfaces": [
{
"id": "ops-console",
"kind": "console",
"description": "Operator-facing operations console hosted by hub-core projections."
},
{
"id": "ops-bootstrap",
"kind": "cli",
"description": "Attended, idempotent registration and compatibility bootstrap."
}
]
}
}

View file

@ -1,4 +1,20 @@
version: 1 version: 1
updated: '2026-06-16' updated: '2026-08-31'
domain: helix_forge domain: helix_forge
capabilities: [] capabilities:
- id: capability.operations.ops-hub
name: Operations Hub Extension Contract
summary: Versioned hub-extension package and bootstrap client for operational truth, service-catalog records, readiness evidence, and migration gates.
vector: D3 / A1 / C1 / R1
domain: operations
status: reviewed
owner: ops-hub
path: registry/capabilities/capability.operations.ops-hub.md
tags:
- operations
- service-catalog
- readiness
- hub-extension
consumption_modes:
- contract package
- command-line bootstrap

View file

@ -0,0 +1,35 @@
#!/usr/bin/env python3
"""Run Ops Hub's package through a disposable hub-core reference runtime."""
from __future__ import annotations
import argparse
import json
import sys
from pathlib import Path
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--hub-core-repo", type=Path, default=Path("../hub-core"))
args = parser.parse_args()
sys.path.insert(0, str(args.hub_core_repo.resolve()))
from fastapi.testclient import TestClient
from hub_core.conformance import ConformanceHarness
from hub_core.runtime.app import create_app
from hub_core.runtime.config import RuntimeSettings
from hub_core.runtime.store import InMemoryPortStore
from ops_hub.extension_contract import load_extension_package
settings = RuntimeSettings(environment="test", backend="memory", allow_ephemeral=True)
target = TestClient(create_app(settings=settings, port_store=InMemoryPortStore()))
harness = ConformanceHarness(target)
harness.package = load_extension_package()
report = harness.run()
print(json.dumps(report.to_dict(), indent=2, sort_keys=True))
return 0 if report.passed else 1
if __name__ == "__main__":
raise SystemExit(main())

View file

@ -0,0 +1,50 @@
#!/usr/bin/env python3
"""Validate the owner package against hub-core's versioned schemas."""
from __future__ import annotations
import argparse
import json
from pathlib import Path
from jsonschema import Draft202012Validator, FormatChecker
from ops_hub.extension_contract import load_extension_package, validation_receipt
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--hub-core-repo", type=Path, default=Path("../hub-core"))
args = parser.parse_args()
root = (
args.hub_core_repo
/ "hub_core"
/ "contracts"
/ "helixforge_hub_extension"
/ "v0_1_0"
)
schemas = root / "schemas"
package = load_extension_package()
for key, schema_name in (
("descriptor", "hub-descriptor.schema.json"),
("manifest", "hub-manifest.schema.json"),
):
schema = json.loads((schemas / schema_name).read_text(encoding="utf-8"))
Draft202012Validator.check_schema(schema)
Draft202012Validator(schema, format_checker=FormatChecker()).validate(package[key])
catalog = json.loads((root / "catalogs" / "event-types.json").read_text(encoding="utf-8"))
known_events = {entry["type"] for entry in catalog["event_types"]}
declared_events = set(package["manifest"]["events_emitted"])
declared_events.update(package["manifest"]["events_consumed"])
unknown = sorted(declared_events - known_events)
if unknown:
raise SystemExit("events absent from hub-core catalog: " + ", ".join(unknown))
print(json.dumps(validation_receipt(), indent=2, sort_keys=True))
return 0
if __name__ == "__main__":
raise SystemExit(main())

View file

@ -0,0 +1,102 @@
"""Ops Hub's owner-side ``helixforge.hub-extension`` package helpers."""
from __future__ import annotations
import hashlib
import json
import re
from collections.abc import Mapping, Sequence
from pathlib import Path
from typing import Any
CONTRACT_ID = "helixforge.hub-extension"
CONTRACT_VERSION = "0.1.0"
REUSE_SURFACE_ID = "capability.operations.ops-hub"
PACKAGE_PATH = (
Path(__file__).resolve().parents[2]
/ "registry"
/ "hub-extension"
/ "v0.1.0"
/ "ops-hub.extension.json"
)
_SECRET_KEY = re.compile(
r"(?:^|_)(?:api_?(?:key|token)|access_?token|auth_?token|client_?secret|"
r"credential|passwd|password|private_?key|secret)(?:$|_)",
re.IGNORECASE,
)
_SECRET_VALUE = re.compile(
r"(?:postgres(?:ql)?|mysql|mariadb|mongodb(?:\+srv)?|redis)://"
r"[^\s/:]+:[^\s/@]+@|-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----",
re.IGNORECASE,
)
def load_extension_package(path: Path = PACKAGE_PATH) -> dict[str, Any]:
return json.loads(path.read_text(encoding="utf-8"))
def package_sha256(path: Path = PACKAGE_PATH) -> str:
return hashlib.sha256(path.read_bytes()).hexdigest()
def find_secret_violations(value: Any, path: str = "$") -> list[str]:
"""Return paths with secret-shaped keys/values without returning values."""
violations: list[str] = []
if isinstance(value, Mapping):
for key, child in value.items():
child_path = f"{path}.{key}"
if _SECRET_KEY.search(str(key)):
violations.append(child_path)
violations.extend(find_secret_violations(child, child_path))
elif isinstance(value, Sequence) and not isinstance(value, (str, bytes)):
for index, child in enumerate(value):
violations.extend(find_secret_violations(child, f"{path}[{index}]"))
elif isinstance(value, str) and _SECRET_VALUE.search(value):
violations.append(path)
return violations
def validate_owner_invariants(package: Mapping[str, Any]) -> None:
descriptor = package.get("descriptor")
manifest = package.get("manifest")
if not isinstance(descriptor, Mapping) or not isinstance(manifest, Mapping):
raise ValueError("package must contain descriptor and manifest objects")
if descriptor.get("contract_id") != CONTRACT_ID:
raise ValueError("unexpected extension contract id")
if descriptor.get("contract_version") != CONTRACT_VERSION:
raise ValueError("unexpected extension contract version")
if descriptor.get("hub_slug") != "ops-hub":
raise ValueError("descriptor is not owned by ops-hub")
if descriptor.get("reuse_surface_id") != REUSE_SURFACE_ID:
raise ValueError("descriptor reuse_surface_id is not canonical")
if manifest.get("reuse_surface_id") != REUSE_SURFACE_ID:
raise ValueError("descriptor and manifest reuse_surface_id differ")
if REUSE_SURFACE_ID not in manifest.get("provides", []):
raise ValueError("manifest does not provide its canonical capability")
if "capability.operations.service-catalog" not in manifest.get("provides", []):
raise ValueError("manifest omits the service-catalog retirement handoff")
if "ops.endpoint.verified" not in manifest.get("events_emitted", []):
raise ValueError("manifest omits its governed verification event")
violations = find_secret_violations(package)
if violations:
raise ValueError("secret-like material at " + ", ".join(violations))
def validation_receipt(path: Path = PACKAGE_PATH) -> dict[str, Any]:
package = load_extension_package(path)
validate_owner_invariants(package)
return {
"ok": True,
"contract_id": CONTRACT_ID,
"contract_version": CONTRACT_VERSION,
"package": str(path),
"sha256": package_sha256(path),
"reuse_surface_id": REUSE_SURFACE_ID,
"provides": package["manifest"]["provides"],
"events_emitted": package["manifest"]["events_emitted"],
"events_consumed": package["manifest"]["events_consumed"],
"secret_violations": [],
}

View file

@ -0,0 +1,51 @@
from __future__ import annotations
import json
import unittest
from ops_hub.extension_contract import (
CONTRACT_ID,
CONTRACT_VERSION,
PACKAGE_PATH,
REUSE_SURFACE_ID,
find_secret_violations,
load_extension_package,
package_sha256,
validate_owner_invariants,
validation_receipt,
)
class ExtensionContractTests(unittest.TestCase):
def test_owner_package_is_valid_and_versioned(self) -> None:
package = load_extension_package()
validate_owner_invariants(package)
self.assertEqual(package["descriptor"]["contract_id"], CONTRACT_ID)
self.assertEqual(package["descriptor"]["contract_version"], CONTRACT_VERSION)
self.assertEqual(package["manifest"]["reuse_surface_id"], REUSE_SURFACE_ID)
def test_package_is_canonical_json_and_receipt_is_non_secret(self) -> None:
package = load_extension_package()
self.assertEqual(package, json.loads(PACKAGE_PATH.read_text(encoding="utf-8")))
receipt = validation_receipt()
self.assertTrue(receipt["ok"])
self.assertEqual(len(package_sha256()), 64)
self.assertEqual(receipt["secret_violations"], [])
def test_secret_detection_reports_paths_without_values(self) -> None:
value = {
"nested": {"api_token": "do-not-return"},
"database": "postgresql://runtime:do-not-return@example.invalid/hub",
}
self.assertEqual(find_secret_violations(value), ["$.nested.api_token", "$.database"])
def test_service_catalog_handoff_and_event_boundary_are_declared(self) -> None:
manifest = load_extension_package()["manifest"]
self.assertIn("capability.operations.service-catalog", manifest["provides"])
self.assertEqual(manifest["events_emitted"], ["ops.endpoint.verified"])
self.assertEqual(manifest["events_consumed"], ["hub.progress.recorded"])
self.assertIn("port.events.interaction", manifest["consumes"])
if __name__ == "__main__":
unittest.main()

View file

@ -4,11 +4,25 @@ type: workplan
title: "Extension contract alignment" title: "Extension contract alignment"
domain: infotech domain: infotech
repo: ops-hub repo: ops-hub
status: proposed status: finished
owner: codex owner: codex
topic_slug: infotech topic_slug: infotech
created: "2026-08-09" created: "2026-08-09"
updated: "2026-08-09" updated: "2026-08-31"
reviewed_at: "2026-08-31"
reviewed_by: codex
reviewed_against_commit: "9bbbf2032daf257d786446217bad79dc051a529c"
quality_dor: DoR-Ok
quality_dor_at: "2026-08-31"
quality_dor_by: codex
quality_dod: DoD-Ok
quality_dod_at: "2026-08-31"
quality_dod_by: codex
quality_dod_note: >-
The owner-side 0.1.0 package is versioned and federated, passes hub-core's
schemas/catalog and all eight implemented conformance checks, and the
post-cutover production compatibility gate is green. Unimplemented framework
checks are live residual HUB-WP-0009 rather than reported as passing.
parent_project: prj-state-hub-retirement parent_project: prj-state-hub-retirement
parent_workplan: SHR-WP-0001 parent_workplan: SHR-WP-0001
related: related:
@ -30,7 +44,7 @@ registration without secrets.
```task ```task
id: OPS-WP-0003-T01 id: OPS-WP-0003-T01
status: todo status: done
priority: high priority: high
state_hub_task_id: "a938b0e2-912e-5126-aa6f-d63bdeebca5d" state_hub_task_id: "a938b0e2-912e-5126-aa6f-d63bdeebca5d"
``` ```
@ -39,22 +53,50 @@ Produce hub descriptor + capability manifest referencing
`capability.infotech.ops-hub` (or current registry id), events emitted/consumed, `capability.infotech.ops-hub` (or current registry id), events emitted/consumed,
and non-secret endpoints. and non-secret endpoints.
**Completed 2026-08-31.** Published the owner-side
`helixforge.hub-extension` 0.1.0 package at
`registry/hub-extension/v0.1.0/ops-hub.extension.json`. It uses the current
hub-core fixture identity `capability.operations.ops-hub`, declares the
operations service-catalog handoff, named framework ports, emitted
`ops.endpoint.verified`, consumed `hub.progress.recorded`, and non-secret
discovery/documentation endpoints. The package checksum is
`d48bb22c88598af482a3a779b930d1269e5bd8fd9e245681e278f14c4bd064d0`.
The capability is now a reviewed federation entry (`D3 / A1 / C1 / R1`) rather
than an empty index. `docs/hub-extension.md` records that hub-core owns the
runtime while ops-hub owns operational vocabulary and records; the legacy
dash-separated event remains a compatibility spelling, not a rewrite target.
## Pass Tier 2 conformance against hub-core ## Pass Tier 2 conformance against hub-core
```task ```task
id: OPS-WP-0003-T02 id: OPS-WP-0003-T02
status: todo status: done
priority: high priority: high
state_hub_task_id: "1d1c422d-892c-5404-8d7f-a1f78c5cd87a" state_hub_task_id: "1d1c422d-892c-5404-8d7f-a1f78c5cd87a"
``` ```
When HUB-WP-0004 harness exists, run C1C10 checks; fix gaps in ops-hub. When HUB-WP-0004 harness exists, run C1C10 checks; fix gaps in ops-hub.
**Completed 2026-08-31 with framework residuals.** The owner package validates
against hub-core's packaged Draft 2020-12 descriptor/manifest schemas and event
catalog with zero secret-shaped fields. Injecting that package into a disposable
hub-core runtime passed the complete implemented profile: Tier-2 C1, C3, C4,
C5, C6, C8 and Tier-3 F2/F3 (8/8).
Hub Core contract 0.1.0 explicitly does not automate C2, C7, C9, or C10; those
cannot be fixed honestly in an extension repository. They are residual-owned by
new proposed owner workplan `HUB-WP-0009`, covering registry resolution,
raw-port configuration policy, dependency-aware readiness, version negotiation,
and any remaining tenant-isolation split. It is registered as State Hub
workplan `0d6e94f3-fd15-5f57-af41-60f0b862da5e`. The report does not count
unsupported checks as passing.
## Bootstrap dual-run on consolidated runtime ## Bootstrap dual-run on consolidated runtime
```task ```task
id: OPS-WP-0003-T03 id: OPS-WP-0003-T03
status: todo status: done
priority: high priority: high
state_hub_task_id: "947306d4-8a00-5cd6-8c6d-1f266d45055c" state_hub_task_id: "947306d4-8a00-5cd6-8c6d-1f266d45055c"
``` ```
@ -62,8 +104,23 @@ state_hub_task_id: "947306d4-8a00-5cd6-8c6d-1f266d45055c"
Verify bootstrap/smokes against hub-core-hosted `/api/v2` during CORE-WP-0010 Verify bootstrap/smokes against hub-core-hosted `/api/v2` during CORE-WP-0010
dual-run and after cutover. dual-run and after cutover.
**Completed 2026-08-31.** `RAPPCOREHUB-WP-0002-T04` records the ops-hub
consumer gate passing against the public candidate during the S1S5 dual-run.
The production cutover and exercised rollback/forward recovery repeated the
consumer gates. A fresh post-cutover `make interhub-gate` now passes against
`https://hub.coulomb.social`: `/api/v2/hubs` fails closed with 401 for an
anonymous caller, `/api/v2/openapi.json` returns 200, and all four required
bootstrap resources are present.
No new authenticated bootstrap mutation was needed or performed. The routed
Inter-Hub operator-key lane is high-risk and attended
(`inter-hub-bootstrap-ssh`); repeating a successful bootstrap merely to obtain
fresh evidence would create credentials and production records without a
functional change. Existing idempotent bootstrap behavior remains covered by
the source tests, while the current production check is non-mutating.
## Acceptance ## Acceptance
- [ ] Hub package artefacts present and versioned - [x] Hub package artefacts present and versioned
- [ ] Tier 2 conformance green (or residual-owned gaps) - [x] Tier 2 conformance green (or residual-owned gaps)
- [ ] Bootstrap works on consolidated runtime - [x] Bootstrap works on consolidated runtime