generated from coulomb/repo-seed
117 lines
4.2 KiB
Python
117 lines
4.2 KiB
Python
import json
|
|
|
|
from sqlalchemy import select
|
|
from sqlalchemy.ext.asyncio import async_sessionmaker
|
|
|
|
from core_hub.migration import import_bundle, validate_bundle
|
|
from core_hub.models import Hub, MigrationRun, Widget
|
|
|
|
|
|
def minimal_bundle():
|
|
return {
|
|
"schemaVersion": "core-hub.migration.v1",
|
|
"source": "inter-hub-haskell",
|
|
"exportedAt": "2026-06-27T00:00:00Z",
|
|
"records": {
|
|
"hubs": [
|
|
{
|
|
"id": "11111111-1111-4111-8111-111111111111",
|
|
"slug": "ops-hub",
|
|
"name": "Ops Hub",
|
|
"domain": "ops.coulomb.social",
|
|
"hubKind": "domain",
|
|
"hubFamily": "vsm",
|
|
"vsmFunction": "OPS",
|
|
"vsmSystem": "1",
|
|
}
|
|
],
|
|
"hubCapabilityManifests": [
|
|
{
|
|
"id": "22222222-2222-4222-8222-222222222222",
|
|
"hubSlug": "ops-hub",
|
|
"manifestVersion": "1.0",
|
|
"status": "active",
|
|
}
|
|
],
|
|
"apiConsumers": [
|
|
{
|
|
"id": "33333333-3333-4333-8333-333333333333",
|
|
"slug": "ops-hub",
|
|
"name": "ops-hub",
|
|
"hubCapabilityManifestId": "22222222-2222-4222-8222-222222222222",
|
|
"keyPrefix": "ch_prefixonly",
|
|
}
|
|
],
|
|
"apiKeys": [
|
|
{
|
|
"id": "44444444-4444-4444-8444-444444444444",
|
|
"apiConsumerSlug": "ops-hub",
|
|
"keyPrefix": "ch_prefixonly",
|
|
"keyHash": "a" * 64,
|
|
"scopes": "framework:read hub:ops-hub:write",
|
|
}
|
|
],
|
|
"widgets": [
|
|
{
|
|
"id": "55555555-5555-4555-8555-555555555555",
|
|
"hubSlug": "ops-hub",
|
|
"name": "Readiness",
|
|
"widgetType": "ops-readiness-gate",
|
|
"capabilityRef": "ops:readiness",
|
|
"viewContext": "ops-hub/readiness",
|
|
"policyScope": "ops-registry",
|
|
}
|
|
],
|
|
"interactionEvents": [
|
|
{
|
|
"id": "66666666-6666-4666-8666-666666666666",
|
|
"widgetId": "55555555-5555-4555-8555-555555555555",
|
|
"eventType": "ops-endpoint-verified",
|
|
"metadata": {"expectedStatus": 401},
|
|
}
|
|
],
|
|
},
|
|
}
|
|
|
|
|
|
def test_validate_bundle_rejects_secret_key_material():
|
|
bundle = minimal_bundle()
|
|
bundle["records"]["apiKeys"][0]["fullKey"] = "do-not-import"
|
|
|
|
report = validate_bundle(bundle)
|
|
|
|
assert report["ok"] is False
|
|
assert any("secret-like" in error for error in report["errors"])
|
|
|
|
|
|
async def test_dry_run_reports_counts_without_writing(sqlite_engine):
|
|
sessionmaker = async_sessionmaker(sqlite_engine, expire_on_commit=False)
|
|
async with sessionmaker() as session:
|
|
report = await import_bundle(session, minimal_bundle(), dry_run=True)
|
|
|
|
assert report["ok"] is True
|
|
assert report["counts"]["hubs"]["created"] == 1
|
|
assert (await session.execute(select(Hub))).scalars().first() is None
|
|
|
|
|
|
async def test_import_bundle_persists_records_and_run_summary(sqlite_engine):
|
|
sessionmaker = async_sessionmaker(sqlite_engine, expire_on_commit=False)
|
|
async with sessionmaker() as session:
|
|
report = await import_bundle(session, minimal_bundle())
|
|
|
|
assert report["ok"] is True
|
|
assert report["migrationRunId"]
|
|
assert report["counts"]["widgets"]["created"] == 1
|
|
|
|
hub = (await session.execute(select(Hub))).scalars().one()
|
|
widget = (await session.execute(select(Widget))).scalars().one()
|
|
run = (await session.execute(select(MigrationRun))).scalars().one()
|
|
|
|
assert hub.slug == "ops-hub"
|
|
assert widget.hub_id == hub.id
|
|
assert json.loads(run.counts_json)["interactionEvents"]["created"] == 1
|
|
|
|
second = await import_bundle(session, minimal_bundle())
|
|
assert second["counts"]["hubs"]["updated"] == 1
|
|
assert second["counts"]["interactionEvents"]["updated"] == 1
|