feat(deploy): seal Gelios telemetry authority transition

This commit is contained in:
Codex
2026-07-22 13:06:32 +03:00
parent 4402c9ed25
commit fdda153595
4 changed files with 85 additions and 56 deletions
+54 -19
View File
@@ -242,10 +242,10 @@ ENGINE_PROVIDER_SECURITY_CATALOG_ARTIFACT_ENTRIES = (
ENGINE_PROVIDER_SECURITY_CATALOG_REL,
)
ENGINE_PROVIDER_SECURITY_CATALOG_PREDECESSOR_SHA256 = (
"30f89052b6557a2444550bd6e7eed30747b2d9b7ff3a22d079d9905fe0a04702"
"1aac712a05e55137d69eedaf363969460ffe866288e8e18e35711967ab232f39"
)
ENGINE_PROVIDER_SECURITY_CATALOG_TARGET_SHA256 = (
"992159fc457ec76ce1f45aad337604c8a72b29252d44fbccda515f0fd6ea6428"
"dd67d8b01091072a4e7be3820b9639c12f2f897ccbbd79208123564d10c1cd81"
)
ENGINE_CONTROL_PLANE_STATE_REL = "nodedc-control-plane"
ENGINE_PUBLISH_GRANT_STATE_REL = f"{ENGINE_CONTROL_PLANE_STATE_REL}/publish-grants"
@@ -3889,7 +3889,15 @@ def validate_engine_provider_security_catalog_payload(payload_dir, entries):
die("Engine provider security catalog target sha256 mismatch")
catalog = read_strict_json(catalog_path, "Engine provider security catalog")
packages = catalog.get("packages") if isinstance(catalog, dict) else None
provider = packages[0] if isinstance(packages, list) and len(packages) == 1 else None
package_ids = [item.get("id") for item in packages if isinstance(item, dict)] \
if isinstance(packages, list) else None
provider = next(
(
item for item in packages
if isinstance(item, dict) and item.get("id") == "gelios.provider.v7"
),
None,
) if isinstance(packages, list) else None
capabilities = provider.get("capabilities") if isinstance(provider, dict) else None
capability = capabilities[0] if isinstance(capabilities, list) and len(capabilities) == 1 else None
request = capability.get("request") if isinstance(capability, dict) else None
@@ -3897,13 +3905,19 @@ def validate_engine_provider_security_catalog_payload(payload_dir, entries):
publisher = provider.get("publisher") if isinstance(provider, dict) else None
if (
catalog.get("schemaVersion") != "nodedc.engine.provider-security-catalog/v1"
or package_ids != [
"gelios.provider.v1",
"gelios.provider.v4",
"gelios.provider.v5",
"moscow-department-of-transport.pmd-slow-zones.v1",
"gelios.provider.v7",
]
or not isinstance(provider, dict)
or provider.get("id") != "gelios.provider.v3"
or provider.get("version") != "3.0.0"
or provider.get("version") != "7.0.0"
or provider.get("providerId") != "gelios"
or credential != {
"authModeId": "gelios.rest-rotating-bearer.v3",
"credentialType": "httpBearerAuth",
"credentialType": "ndcProviderRotatingAccessApi",
}
or not isinstance(capability, dict)
or capability.get("id") != "gelios.units.current.read"
@@ -3911,15 +3925,18 @@ def validate_engine_provider_security_catalog_payload(payload_dir, entries):
or capability.get("status") != "implemented"
or request != {
"method": "GET",
"url": "https://api.geliospro.com/api/v1/units",
"url": (
"https://api.geliospro.com/api/v1/units?incltrip=true&inclcntrs=true"
"&inclsnsrs=true&incllsv=true"
),
}
or capability.get("dataProductIds") != ["fleet.positions.current.v2"]
or capability.get("dataProductIds") != ["fleet.positions.current.v5"]
or publisher != {
"nodeType": "n8n-nodes-ndc.ndcDataProductPublish",
"credentialType": "ndcDataProductWriterApi",
}
):
die("Engine provider security catalog v3 projection mismatch")
die("Engine provider security catalog v7 telemetry projection mismatch")
return catalog
@@ -3959,16 +3976,29 @@ def accept_engine_provider_security_catalog_runtime():
const module=await import('file:///app/server/dataProductPublishGrant/providerCatalog.js');
const catalog=await module.loadProviderSecurityCatalog();
const validation=module.validateProviderSecurityCatalog(catalog);
const provider=catalog.packages?.[0];
const provider=catalog.packages?.find((item)=>item.id==='gelios.provider.v7');
const capability=provider?.capabilities?.[0];
if(!validation.ok||provider?.id!=='gelios.provider.v3'||provider?.providerCredential?.credentialType!=='httpBearerAuth'||capability?.request?.url!=='https://api.geliospro.com/api/v1/units'||capability?.dataProductIds?.[0]!=='fleet.positions.current.v2')process.exit(2);
process.stdout.write('engine-provider-catalog:gelios.provider.v3:httpBearerAuth:fleet.positions.current.v2');
const slot='ndcProviderRotatingAccessApi';
const credential={id:'native-provider',name:'provider',nodeDcCredentialId:'provider-ref'};
const policy={kind:'httpRequest',allowedHosts:['api.geliospro.com'],requireHttps:true,disableRedirects:true};
const queryParameters={parameters:[{name:'incltrip',value:'true'},{name:'inclcntrs',value:'true'},{name:'inclsnsrs',value:'true'},{name:'incllsv',value:'true'}]};
const source={id:'units',data:{n8n:{id:'units',name:'units',type:'n8n-nodes-base.httpRequest',parameters:{method:'GET',url:'https://api.geliospro.com/api/v1/units',sendQuery:true,specifyQuery:'keypair',queryParameters},credentials:{[slot]:credential}},nodedcAgentCredentialPolicies:{[slot]:policy}}};
const publish={id:'publish',data:{n8n:{id:'publish',name:'publish',type:'n8n-nodes-ndc.ndcDataProductPublish',parameters:{dataProductId:'fleet.positions.current.v5'},credentials:{}}}};
const graph={nodes:[source,publish],edges:[{source:'units',target:'publish'}]};
const resolved=module.resolveProviderConnectionFromGraph({graph,targetNodeId:'publish',catalog});
const drift=structuredClone(graph);drift.nodes[0].data.n8n.parameters.queryParameters.parameters.pop();
const rejected=module.resolveProviderConnectionFromGraph({graph:drift,targetNodeId:'publish',catalog});
if(!validation.ok||provider?.providerCredential?.credentialType!==slot||capability?.request?.url!=='https://api.geliospro.com/api/v1/units?incltrip=true&inclcntrs=true&inclsnsrs=true&incllsv=true'||capability?.dataProductIds?.[0]!=='fleet.positions.current.v5'||!resolved.ok||resolved.descriptor?.packageId!=='gelios.provider.v7'||resolved.descriptor?.providerCredentialRef!=='provider-ref'||rejected.blockers?.join(',')!=='publish_grant_provider_request_not_exact')process.exit(2);
process.stdout.write('engine-provider-catalog:gelios.provider.v7:ndcProviderRotatingAccessApi:fleet.positions.current.v5');
""".strip(),
),
"Engine provider security catalog v3",
"Engine provider security catalog v7 telemetry",
container_id=engine_backend_container_id(),
)
expected = "engine-provider-catalog:gelios.provider.v3:httpBearerAuth:fleet.positions.current.v2"
expected = (
"engine-provider-catalog:gelios.provider.v7:"
"ndcProviderRotatingAccessApi:fleet.positions.current.v5"
)
if live != expected:
die("Engine provider security catalog live acceptance mismatch")
return {"catalog_sha256": ENGINE_PROVIDER_SECURITY_CATALOG_TARGET_SHA256, "live": live}
@@ -7951,11 +7981,14 @@ def plan_artifact(artifact):
print("node_intelligence_image=preserved")
print("n8n_l1=untouched")
if provider_catalog_preflight:
print("engine_provider_catalog_transition=gelios-rest-rotating-v3")
print("engine_provider_package=gelios.provider.v3")
print("engine_provider_credential=httpBearerAuth")
print("engine_provider_endpoint=https://api.geliospro.com/api/v1/units")
print("engine_data_product=fleet.positions.current.v2")
print("engine_provider_catalog_transition=gelios-telemetry-authority-v7")
print("engine_provider_package=gelios.provider.v7")
print("engine_provider_credential=ndcProviderRotatingAccessApi")
print(
"engine_provider_endpoint=https://api.geliospro.com/api/v1/units?"
"incltrip=true&inclcntrs=true&inclsnsrs=true&incllsv=true"
)
print("engine_data_product=fleet.positions.current.v5")
print(
"predecessor_catalog_sha256="
f"{provider_catalog_preflight['catalog_sha256']}"
@@ -7964,6 +7997,8 @@ def plan_artifact(artifact):
print(f"backend_current_barrier={provider_catalog_preflight['backend_mode']}")
print("n8n_l1=untouched")
print("engine_ui=untouched")
print("engine_databases=untouched")
print("mcp_nginx=untouched")
if composite_provider_v4_preflight:
print("engine_composite_provider_transition=exact-v3-to-v4")
print("engine_provider_package=gelios.provider.v4")