state-hub/tests/test_repository_alias_routing.py
tegwick 2e2ae1e5d0
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Build and Publish Multi-Context Image / build-and-push (push) Successful in 25s
feat: make repository reads alias-aware
Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a049a4-ee9f-78e1-9d66-2cb0f9bea3e3
2026-08-29 10:47:51 +02:00

292 lines
11 KiB
Python

from __future__ import annotations
from datetime import datetime, timezone
import pytest
from sqlalchemy import func, select
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker
from api.models.agent_message import AgentMessage
from api.models.fabric_graph import FabricGraphImport, FabricGraphNode
from api.models.interface_change import InterfaceChange
from api.models.managed_repo import ManagedRepo
from api.models.repository_rename import RepositorySlug
from tests.conftest import (
create_test_domain,
create_test_repo,
create_test_workplan,
)
async def _rename_in_state_hub(test_engine, repo_id: str) -> None:
factory = async_sessionmaker(test_engine, class_=AsyncSession, expire_on_commit=False)
async with factory() as session:
repo = await session.get(ManagedRepo, repo_id)
old = (
await session.execute(
select(RepositorySlug).where(RepositorySlug.slug == "flex-auth")
)
).scalar_one()
old.kind = "alias"
old.protected = True
repo.slug = "access-engine"
repo.name = "Access Engine"
session.add(
RepositorySlug(
repo_id=repo.id,
slug="access-engine",
kind="canonical",
protected=True,
)
)
await session.commit()
@pytest.mark.asyncio
async def test_alias_lookup_dispatch_bindings_and_external_staleness(
client, test_engine
):
domain = await create_test_domain(client)
repo = await create_test_repo(client, domain_slug=domain["slug"], slug="flex-auth")
workplan = await create_test_workplan(
client,
repo_id=repo["id"],
slug="FLEX-WP-0001",
title="Security stack migration",
)
task = await client.post(
"/tasks/",
json={
"workplan_id": workplan["id"],
"title": "Preserve identity",
"status": "todo",
"priority": "high",
},
)
assert task.status_code == 201, task.text
await _rename_in_state_hub(test_engine, repo["id"])
factory = async_sessionmaker(test_engine, class_=AsyncSession, expire_on_commit=False)
async with factory() as session:
change = InterfaceChange(
repo_id=repo["id"],
interface_type="rest_api",
change_type="breaking",
title="Historical consumer notice",
description="Recorded before cutover",
affected_paths=["/authorize"],
affected_repo_slugs=["flex-auth"],
status="published",
published_at=datetime.now(timezone.utc),
author="pytest",
)
import_run = FabricGraphImport(
source_repo_slug="railiance-fabric",
content_hash="a" * 64,
graph_json={},
validation_status="valid",
is_latest=True,
)
session.add_all([change, import_run])
await session.flush()
session.add(
FabricGraphNode(
import_id=import_run.id,
source_repo_slug="railiance-fabric",
graph_id="repo:flex-auth",
kind="repository",
name="Flex Auth",
repo_slug="flex-auth",
domain_slug="infotech",
lifecycle="active",
)
)
await session.commit()
old_lookup = await client.get("/repos/flex-auth")
new_lookup = await client.get("/repos/access-engine")
assert old_lookup.status_code == new_lookup.status_code == 200
assert old_lookup.json()["id"] == new_lookup.json()["id"] == repo["id"]
assert old_lookup.json()["requested_slug"] == "flex-auth"
assert old_lookup.json()["canonical_slug"] == "access-engine"
assert old_lookup.json()["slug_status"] == "alias"
assert old_lookup.json()["aliases"] == ["flex-auth"]
assert new_lookup.json()["slug_status"] == "canonical"
assert old_lookup.json()["stale_external_references"] == [
{
"owner": "railiance-fabric",
"surface": "fabric_graph_nodes",
"field": "repo_slug",
"value": "flex-auth",
"count": 1,
"status": "stale",
"handoff": "owner update or re-ingest required",
}
]
dispatch = await client.get("/repos/access-engine/dispatch")
assert dispatch.status_code == 200, dispatch.text
assert dispatch.json()["repo_slug"] == "access-engine"
assert dispatch.json()["pending_interface_changes"][0]["title"] == change.title
bound = await client.get(f"/workplans/{workplan['id']}")
assert bound.status_code == 200
assert bound.json()["id"] == workplan["id"]
assert bound.json()["repo_id"] == repo["id"]
bound_task = await client.get(f"/tasks/{task.json()['id']}")
assert bound_task.status_code == 200
assert bound_task.json()["id"] == task.json()["id"]
@pytest.mark.asyncio
async def test_message_history_is_immutable_and_old_slug_write_replays_once(
client, test_engine
):
domain = await create_test_domain(client)
repo = await create_test_repo(client, domain_slug=domain["slug"], slug="flex-auth")
await _rename_in_state_hub(test_engine, repo["id"])
factory = async_sessionmaker(test_engine, class_=AsyncSession, expire_on_commit=False)
async with factory() as session:
historical = AgentMessage(
from_agent="security-review",
to_agent="flex-auth",
subject="Before cutover",
body="Historical recipient must not be rewritten",
)
session.add(historical)
await session.commit()
historical_id = historical.id
history = await client.get("/messages/", params={"to_agent": "access-engine"})
assert history.status_code == 200
assert [item["id"] for item in history.json()] == [str(historical_id)]
assert history.json()[0]["to_agent"] == "flex-auth"
payload = {
"from_agent": "flex-auth",
"to_agent": "flex-auth",
"subject": "Queued during cutover",
"body": "Replay exactly once",
}
headers = {"Idempotency-Key": "repo-rename-old-slug-message"}
first = await client.post("/messages/", json=payload, headers=headers)
replay = await client.post("/messages/", json=payload, headers=headers)
assert first.status_code == replay.status_code == 201
assert first.json()["id"] == replay.json()["id"]
assert first.json()["from_agent"] == "access-engine"
assert first.json()["to_agent"] == "access-engine"
async with factory() as session:
assert await session.scalar(
select(func.count())
.select_from(AgentMessage)
.where(AgentMessage.subject == "Queued during cutover")
) == 1
unchanged = await session.get(AgentMessage, historical_id)
assert unchanged.to_agent == "flex-auth"
@pytest.mark.asyncio
async def test_alias_aware_interface_catalog_sbom_and_telemetry_reads(
client, test_engine
):
domain = await create_test_domain(client)
repo = await create_test_repo(client, domain_slug=domain["slug"], slug="flex-auth")
await _rename_in_state_hub(test_engine, repo["id"])
interface = await client.post(
"/interface-changes/",
json={
"repo_slug": "flex-auth",
"interface_type": "rest_api",
"change_type": "additive",
"title": "Canonical write",
"description": "New references use the current slug",
"affected_repo_slugs": ["flex-auth"],
},
)
assert interface.status_code == 201, interface.text
assert interface.json()["repo_slug"] == "access-engine"
assert interface.json()["affected_repo_slugs"] == ["access-engine"]
affected = await client.get(
"/interface-changes/", params={"affected_repo": "flex-auth"}
)
assert [item["id"] for item in affected.json()] == [interface.json()["id"]]
goal = await client.post(
"/repo-goals/",
json={
"repo_id": repo["id"],
"title": "Preserve authorization continuity",
"description": "Keep Net Kingdom consumers online",
},
)
assert goal.status_code == 201, goal.text
goals = await client.get("/repo-goals/", params={"repo_slug": "flex-auth"})
assert [item["id"] for item in goals.json()] == [goal.json()["id"]]
assert goals.json()[0]["repo_slug"] == "access-engine"
capability = await client.post(
"/capability-catalog/",
json={
"domain": "infotech",
"repo_slug": "flex-auth",
"capability_type": "authorization",
"title": "Policy decisions",
"description": "Net Kingdom authorization",
"keywords": ["authorize"],
},
)
assert capability.status_code == 201, capability.text
catalog = await client.get(
"/capability-catalog/", params={"repo_slug": "access-engine"}
)
assert [item["id"] for item in catalog.json()] == [capability.json()["id"]]
assert catalog.json()[0]["repo_slug"] == "access-engine"
service = await client.post(
"/services/catalog",
json={
"slug": "access-engine-api",
"name": "Access Engine API",
"hosting_type": "self_hosted",
"development_type": "first_party",
"first_party": {"repo_slug": "flex-auth", "owning_domain": "infotech"},
"self_hosted": {},
},
)
assert service.status_code == 201, service.text
services = await client.get("/services/catalog", params={"repo_slug": "flex-auth"})
assert [item["id"] for item in services.json()] == [service.json()["id"]]
ingested = await client.post(
"/sbom/ingest/",
json={
"repo_slug": "flex-auth",
"entries": [
{
"package_name": "opa",
"package_version": "1.0",
"ecosystem": "go",
}
],
},
)
assert ingested.status_code == 200, ingested.text
assert ingested.json()["repo_slug"] == "access-engine"
sbom = await client.get("/sbom/flex-auth")
assert sbom.status_code == 200
assert sbom.json()["repo_slug"] == "access-engine"
event = await client.post(
"/token-events/",
json={"repo_id": repo["id"], "tokens_in": 12, "tokens_out": 3},
)
assert event.status_code == 201, event.text
summary = await client.get(
"/token-events/by-repo/", params={"repo_slug": "flex-auth"}
)
assert summary.status_code == 200
assert len(summary.json()) == 1
assert summary.json()[0]["repo_slug"] == "access-engine"
assert summary.json()[0]["tokens_total"] == 15