generated from coulomb/repo-seed
feat: validate financial fabric graph exports
This commit is contained in:
@@ -261,6 +261,48 @@ def test_graph_export_validation_rejects_unflagged_display_edges() -> None:
|
||||
raise AssertionError("expected RegistryError for unflagged display-only edge")
|
||||
|
||||
|
||||
def test_financial_graph_export_requires_resolvable_owner() -> None:
|
||||
graph = _financial_graph()
|
||||
del graph["nodes"][0]["ownership"]
|
||||
|
||||
try:
|
||||
validate_graph_export(graph)
|
||||
except RegistryError as exc:
|
||||
assert "ownership must be an object" in exc.message
|
||||
else:
|
||||
raise AssertionError("expected RegistryError for accepted node without ownership")
|
||||
|
||||
|
||||
def test_registry_accepts_financial_graph_and_materializes_vnext_fields(tmp_path: Path) -> None:
|
||||
store = RegistryStore(tmp_path / "registry.sqlite3")
|
||||
store.init_schema()
|
||||
store.upsert_repository({"slug": "state-hub", "name": "State Hub"})
|
||||
|
||||
snapshot = store.add_snapshot(
|
||||
"state-hub",
|
||||
{
|
||||
"commit": "financial-vnext",
|
||||
"generated_at": "2026-05-24T00:00:00Z",
|
||||
"graph": _financial_graph(),
|
||||
},
|
||||
)
|
||||
graph = snapshot["graph"]
|
||||
edge = graph["edges"][0]
|
||||
|
||||
assert graph["apiVersion"] == "railiance.fabric/v1alpha2"
|
||||
assert graph["schema_version"] == "financial-fabric-v1"
|
||||
assert graph["nodes"][0]["evidence"]["review_state"] == "accepted"
|
||||
assert edge["relationship_category"] == "utility"
|
||||
assert edge["boundary"]["crosses_fabric_boundary"] is False
|
||||
assert edge["boundary"]["crosses_subfabric_boundary"] is True
|
||||
|
||||
combined = store.combined_graph()
|
||||
assert combined["apiVersion"] == "railiance.fabric/v1alpha2"
|
||||
assert combined["actors"][0]["id"] == "actor.coulomb.tenant"
|
||||
assert combined["fabrics"][1]["id"] == "subfabric.railiance.tenant.coulomb"
|
||||
assert combined["edges"][0]["relationship_category"] == "utility"
|
||||
|
||||
|
||||
def test_registry_reset_archive_and_guarded_reset(tmp_path: Path) -> None:
|
||||
store = RegistryStore(tmp_path / "registry.sqlite3")
|
||||
store.init_schema()
|
||||
@@ -426,6 +468,119 @@ def _post_json(url: str, payload: dict) -> dict:
|
||||
return json.loads(response.read())
|
||||
|
||||
|
||||
def _financial_graph() -> dict:
|
||||
return {
|
||||
"apiVersion": "railiance.fabric/v1alpha2",
|
||||
"kind": "FabricGraphExport",
|
||||
"schema_version": "financial-fabric-v1",
|
||||
"generated_at": "2026-05-24T00:00:00Z",
|
||||
"netkingdom": {
|
||||
"id": "railiance.netkingdom",
|
||||
"name": "Railiance Netkingdom",
|
||||
"king_actor_id": "actor.railiance.king",
|
||||
},
|
||||
"actors": [
|
||||
{"id": "actor.railiance.king", "kind": "FabricActor", "role": "king", "name": "Railiance King"},
|
||||
{"id": "actor.railiance.primary-lord", "kind": "FabricActor", "role": "lord", "name": "Railiance Lord"},
|
||||
{"id": "actor.coulomb.tenant", "kind": "FabricActor", "role": "tenant", "name": "Coulomb Tenant"},
|
||||
],
|
||||
"fabrics": [
|
||||
{
|
||||
"id": "fabric.railiance.primary",
|
||||
"kind": "Fabric",
|
||||
"name": "Railiance Primary Fabric",
|
||||
"netkingdom_id": "railiance.netkingdom",
|
||||
"lord_actor_id": "actor.railiance.primary-lord",
|
||||
"status": "active",
|
||||
},
|
||||
{
|
||||
"id": "subfabric.railiance.tenant.coulomb",
|
||||
"kind": "Subfabric",
|
||||
"name": "Coulomb Tenant Subfabric",
|
||||
"netkingdom_id": "railiance.netkingdom",
|
||||
"parent_fabric_id": "fabric.railiance.primary",
|
||||
"tenant_actor_id": "actor.coulomb.tenant",
|
||||
"status": "planned",
|
||||
},
|
||||
],
|
||||
"nodes": [
|
||||
{
|
||||
"id": "state-hub.http",
|
||||
"kind": "UtilityInterface",
|
||||
"name": "State Hub HTTP API",
|
||||
"repo": "state-hub",
|
||||
"domain": "custodian",
|
||||
"lifecycle": "active",
|
||||
"containment": {
|
||||
"netkingdom_id": "railiance.netkingdom",
|
||||
"fabric_id": "fabric.railiance.primary",
|
||||
"subfabric_id": None,
|
||||
"environment": "local",
|
||||
},
|
||||
"ownership": {
|
||||
"owner_actor_id": "actor.railiance.primary-lord",
|
||||
"owner_role": "lord",
|
||||
"resolution": "inherited",
|
||||
"inherited_from": "fabric.railiance.primary",
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": "coulomb.automation-client",
|
||||
"kind": "Service",
|
||||
"name": "Coulomb Automation Client",
|
||||
"repo": "coulomb-automation",
|
||||
"domain": "railiance",
|
||||
"lifecycle": "planned",
|
||||
"containment": {
|
||||
"netkingdom_id": "railiance.netkingdom",
|
||||
"fabric_id": "fabric.railiance.primary",
|
||||
"subfabric_id": "subfabric.railiance.tenant.coulomb",
|
||||
"environment": "local",
|
||||
},
|
||||
"ownership": {
|
||||
"owner_actor_id": "actor.coulomb.tenant",
|
||||
"owner_role": "tenant",
|
||||
"resolution": "explicit",
|
||||
},
|
||||
"accounting": {
|
||||
"cost_center_id": "cc.coulomb.automation",
|
||||
"allocation_model": "direct",
|
||||
},
|
||||
},
|
||||
],
|
||||
"edges": [
|
||||
{
|
||||
"id": "utility:state-hub-http:coulomb-client",
|
||||
"from": "state-hub.http",
|
||||
"to": "coulomb.automation-client",
|
||||
"type": "provides_utility_to",
|
||||
"provider": {
|
||||
"owner_actor_id": "actor.railiance.primary-lord",
|
||||
"fabric_id": "fabric.railiance.primary",
|
||||
"subfabric_id": None,
|
||||
},
|
||||
"consumer": {
|
||||
"owner_actor_id": "actor.coulomb.tenant",
|
||||
"fabric_id": "fabric.railiance.primary",
|
||||
"subfabric_id": "subfabric.railiance.tenant.coulomb",
|
||||
},
|
||||
"utility": {
|
||||
"utility_type": "coordination_api",
|
||||
"contract_id": "state-hub.http",
|
||||
"payment_schema_id": "payment.internal-tenant-access",
|
||||
"metering_basis": "unknown",
|
||||
"business_model": "tenant_utility",
|
||||
},
|
||||
"accounting": {
|
||||
"provider_profit_center_id": "pc.tenant-utilities",
|
||||
"consumer_cost_center_id": "cc.coulomb.automation",
|
||||
"allocation_model": "usage_weighted",
|
||||
},
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def _cyclonedx_bom() -> dict:
|
||||
return {
|
||||
"bomFormat": "CycloneDX",
|
||||
|
||||
Reference in New Issue
Block a user