Add Core Hub ops evidence sink

This commit is contained in:
2026-06-27 20:34:25 +02:00
parent 18fcce87fe
commit 30043348f0
3 changed files with 364 additions and 0 deletions

View File

@@ -166,6 +166,93 @@ def test_state_hub_progress_sink_is_idempotent(monkeypatch) -> None:
assert result[0]["idempotency_key"] == idempotency_key
def test_core_hub_interaction_event_sink_posts_and_verifies_compact_event(monkeypatch) -> None:
posts: list[dict[str, Any]] = []
def fake_post(url: str, **kwargs: Any) -> DummyResponse:
assert url == "http://core-hub.test/api/v2/interaction-events"
assert kwargs["headers"]["Authorization"] == "Bearer runtime-secret"
posts.append({"url": url, **kwargs})
return DummyResponse(
{
"id": "event-1",
"eventType": "ops-endpoint-verified",
"widgetId": "widget-1",
}
)
def fake_get(url: str, **kwargs: Any) -> DummyResponse:
assert url == "http://core-hub.test/api/v2/interaction-events"
assert kwargs["headers"]["Authorization"] == "Bearer runtime-secret"
return DummyResponse({"data": [{"id": "event-1"}]})
monkeypatch.setenv("CORE_HUB_RUNTIME_TOKEN", "runtime-secret")
monkeypatch.setattr(httpx, "post", fake_post)
monkeypatch.setattr(httpx, "get", fake_get)
result = persist_ops_inventory_evidence(
_payload([
{
"type": "core-hub-interaction-event",
"core_hub_url": "http://core-hub.test",
"widget_id": "widget-1",
"event_type": "ops-endpoint-verified",
}
])
)
assert result == [
{
"type": "core-hub-interaction-event",
"status": "posted",
"event_type": "ops-endpoint-verified",
"event_id": "event-1",
"widget_id": "widget-1",
"verified": True,
"context_key": "ops_probe",
}
]
body = posts[0]["json"]
assert body["widgetId"] == "widget-1"
assert body["eventType"] == "ops-endpoint-verified"
assert body["metadata"]["activity_core_run_id"] == _run_id()
assert body["metadata"]["endpoint"]["url"] == "http://state-hub.test/health"
assert body["metadata"]["endpoint"]["widget_ref"] == "ops:endpoint:state-hub-health"
serialized = json.dumps(body, sort_keys=True)
assert "runtime-secret" not in serialized
assert "secret response body" not in serialized
assert "Authorization" not in serialized
assert "user:pass" not in serialized
assert "token=secret" not in serialized
def test_core_hub_sink_skips_cleanly_when_config_missing(monkeypatch) -> None:
monkeypatch.delenv("CORE_HUB_BASE_URL", raising=False)
monkeypatch.delenv("CORE_HUB_RUNTIME_TOKEN", raising=False)
monkeypatch.delenv("CORE_HUB_RUNTIME_TOKEN_FILE", raising=False)
monkeypatch.delenv("CORE_HUB_WIDGET_ID", raising=False)
monkeypatch.delenv("CORE_HUB_WIDGET_MAPPING", raising=False)
result = persist_ops_inventory_evidence(
_payload([{"type": "core-hub-interaction-event"}])
)
assert result == [
{
"type": "core-hub-interaction-event",
"status": "skipped",
"reason": "missing_core_hub_config",
"missing": [
"CORE_HUB_BASE_URL",
"CORE_HUB_RUNTIME_TOKEN or CORE_HUB_RUNTIME_TOKEN_FILE",
"widget_id or CORE_HUB_WIDGET_ID",
],
"context_key": "ops_probe",
}
]
def test_inter_hub_sink_skips_cleanly_when_config_missing(monkeypatch) -> None:
monkeypatch.delenv("INTER_HUB_URL", raising=False)
monkeypatch.delenv("OPS_HUB_KEY", raising=False)