feat(deploy): register VPS telemetry releases

This commit is contained in:
Codex
2026-08-22 17:29:46 +03:00
parent 0438fbd80b
commit c5c4e69acb
2 changed files with 280 additions and 13 deletions
+226 -13
View File
@@ -278,6 +278,9 @@ DEVICE_PLANE_MANAGER_RELEASE_V7_REL = (
DEVICE_PLANE_MANAGER_RELEASE_V8_REL = ( DEVICE_PLANE_MANAGER_RELEASE_V8_REL = (
"deployment/device-manager-release-v8.json" "deployment/device-manager-release-v8.json"
) )
DEVICE_PLANE_MANAGER_RELEASE_V9_REL = (
"deployment/device-manager-release-v9.json"
)
DEVICE_PLANE_MANAGER_COMPOSE_REL = "docker-compose.device-manager.yml" DEVICE_PLANE_MANAGER_COMPOSE_REL = "docker-compose.device-manager.yml"
DEVICE_PLANE_EDGE_CORE_CHANNEL_BOOTSTRAP_REL = ( DEVICE_PLANE_EDGE_CORE_CHANNEL_BOOTSTRAP_REL = (
"deployment/device-edge-core-channel-bootstrap-v1.json" "deployment/device-edge-core-channel-bootstrap-v1.json"
@@ -297,6 +300,9 @@ DEVICE_PLANE_CONTROL_CORE_RELEASE_REL = (
DEVICE_PLANE_CONTROL_CORE_RELEASE_V2_REL = ( DEVICE_PLANE_CONTROL_CORE_RELEASE_V2_REL = (
"deployment/device-control-core-release-v2.json" "deployment/device-control-core-release-v2.json"
) )
DEVICE_PLANE_CONTROL_CORE_RELEASE_V3_REL = (
"deployment/device-control-core-release-v3.json"
)
DEVICE_PLANE_EDGE_CORE_CHANNEL_COMPOSE_REL = ( DEVICE_PLANE_EDGE_CORE_CHANNEL_COMPOSE_REL = (
"docker-compose.device-edge-core-channel.yml" "docker-compose.device-edge-core-channel.yml"
) )
@@ -367,6 +373,16 @@ DEVICE_PLANE_CONTROL_CORE_RELEASE_V2_ENTRIES = (
"services/device-control-core", "services/device-control-core",
DEVICE_PLANE_CONTROL_CORE_RELEASE_V2_REL, DEVICE_PLANE_CONTROL_CORE_RELEASE_V2_REL,
) )
DEVICE_PLANE_CONTROL_CORE_RELEASE_V3_ENTRIES = (
".dockerignore",
"package.json",
"package-lock.json",
"packages/device-protocol-contract",
"packages/device-edge-channel-contract",
"packages/infrastructure-telemetry-contract",
"services/device-control-core",
DEVICE_PLANE_CONTROL_CORE_RELEASE_V3_REL,
)
DEVICE_PLANE_CONTROL_CORE_RELEASE_FIRST_PREDECESSOR_PATCH_ID = ( DEVICE_PLANE_CONTROL_CORE_RELEASE_FIRST_PREDECESSOR_PATCH_ID = (
"device-edge-core-channel-upgrade-v4-20260812-023" "device-edge-core-channel-upgrade-v4-20260812-023"
) )
@@ -427,6 +443,18 @@ DEVICE_PLANE_MANAGER_RELEASE_V8_CONTROL_CORE_PREDECESSOR_PATCH_ID = (
DEVICE_PLANE_MANAGER_RELEASE_V8_CONTROL_CORE_PREDECESSOR_ARTIFACT_SHA256 = ( DEVICE_PLANE_MANAGER_RELEASE_V8_CONTROL_CORE_PREDECESSOR_ARTIFACT_SHA256 = (
"e2d062b82b022dba662522b5d6e192026ac964d78950d903295ca3cbbc95ab28" "e2d062b82b022dba662522b5d6e192026ac964d78950d903295ca3cbbc95ab28"
) )
DEVICE_PLANE_MANAGER_RELEASE_V9_PREDECESSOR_PATCH_ID = (
"device-manager-release-v8-20260822-039"
)
DEVICE_PLANE_MANAGER_RELEASE_V9_PREDECESSOR_ARTIFACT_SHA256 = (
"30a83d4c6b5c029c96c4af19fa558e0ae75e4b60bc897881457304bd17e0e465"
)
DEVICE_PLANE_MANAGER_RELEASE_V9_CONTROL_CORE_PREDECESSOR_PATCH_ID = (
"device-control-core-release-v3-20260822-040"
)
DEVICE_PLANE_MANAGER_RELEASE_V9_CONTROL_CORE_PREDECESSOR_ARTIFACT_SHA256 = (
"08448a56cdf391076f92c5242e368fd0033b420167874645eebfa1f22184ee92"
)
DEVICE_PLANE_EDGE_CORE_CHANNEL_BOOTSTRAP_PREDECESSOR_PATCH_ID = ( DEVICE_PLANE_EDGE_CORE_CHANNEL_BOOTSTRAP_PREDECESSOR_PATCH_ID = (
"device-edge-core-channel-bootstrap-20260812-018" "device-edge-core-channel-bootstrap-20260812-018"
) )
@@ -500,6 +528,9 @@ DEVICE_PLANE_MANAGER_RELEASE_V7_COMPOSE_SHA256 = (
DEVICE_PLANE_MANAGER_RELEASE_V8_COMPOSE_SHA256 = ( DEVICE_PLANE_MANAGER_RELEASE_V8_COMPOSE_SHA256 = (
DEVICE_PLANE_MANAGER_RELEASE_V6_COMPOSE_SHA256 DEVICE_PLANE_MANAGER_RELEASE_V6_COMPOSE_SHA256
) )
DEVICE_PLANE_MANAGER_RELEASE_V9_COMPOSE_SHA256 = (
DEVICE_PLANE_MANAGER_RELEASE_V8_COMPOSE_SHA256
)
DEVICE_PLANE_MANAGER_FAVICON_SHA256 = { DEVICE_PLANE_MANAGER_FAVICON_SHA256 = {
"favicon.ico": ( "favicon.ico": (
"f8933114a85646335ea5c94944f56d3cd8c48a6032016719f7905ff244ec0aa2" "f8933114a85646335ea5c94944f56d3cd8c48a6032016719f7905ff244ec0aa2"
@@ -626,6 +657,11 @@ DEVICE_PLANE_MANAGER_RELEASE_V8_ENTRIES = (
"services/device-manager", "services/device-manager",
DEVICE_PLANE_MANAGER_RELEASE_V8_REL, DEVICE_PLANE_MANAGER_RELEASE_V8_REL,
) )
DEVICE_PLANE_MANAGER_RELEASE_V9_ENTRIES = (
DEVICE_PLANE_MANAGER_COMPOSE_REL,
"services/device-manager",
DEVICE_PLANE_MANAGER_RELEASE_V9_REL,
)
DEVICE_PLANE_MANAGER_RECONCILIATION_REL = ( DEVICE_PLANE_MANAGER_RECONCILIATION_REL = (
"deployment/device-manager-control-plane-reconciliation-v1.json" "deployment/device-manager-control-plane-reconciliation-v1.json"
) )
@@ -4669,16 +4705,19 @@ def allowed_payload_path(component, rel):
DEVICE_PLANE_MANAGER_RELEASE_V6_REL, DEVICE_PLANE_MANAGER_RELEASE_V6_REL,
DEVICE_PLANE_MANAGER_RELEASE_V7_REL, DEVICE_PLANE_MANAGER_RELEASE_V7_REL,
DEVICE_PLANE_MANAGER_RELEASE_V8_REL, DEVICE_PLANE_MANAGER_RELEASE_V8_REL,
DEVICE_PLANE_MANAGER_RELEASE_V9_REL,
DEVICE_PLANE_EDGE_CORE_CHANNEL_BOOTSTRAP_REL, DEVICE_PLANE_EDGE_CORE_CHANNEL_BOOTSTRAP_REL,
DEVICE_PLANE_EDGE_CORE_CHANNEL_UPGRADE_REL, DEVICE_PLANE_EDGE_CORE_CHANNEL_UPGRADE_REL,
DEVICE_PLANE_EDGE_CORE_CHANNEL_UPGRADE_V2_REL, DEVICE_PLANE_EDGE_CORE_CHANNEL_UPGRADE_V2_REL,
DEVICE_PLANE_EDGE_CORE_CHANNEL_UPGRADE_V4_REL, DEVICE_PLANE_EDGE_CORE_CHANNEL_UPGRADE_V4_REL,
DEVICE_PLANE_CONTROL_CORE_RELEASE_REL, DEVICE_PLANE_CONTROL_CORE_RELEASE_REL,
DEVICE_PLANE_CONTROL_CORE_RELEASE_V2_REL, DEVICE_PLANE_CONTROL_CORE_RELEASE_V2_REL,
DEVICE_PLANE_CONTROL_CORE_RELEASE_V3_REL,
DEVICE_PLANE_MANAGER_RECONCILIATION_REL, DEVICE_PLANE_MANAGER_RECONCILIATION_REL,
DEVICE_PLANE_MANAGER_V2_RECONCILIATION_REL, DEVICE_PLANE_MANAGER_V2_RECONCILIATION_REL,
"packages/device-protocol-contract", "packages/device-protocol-contract",
"packages/device-edge-channel-contract", "packages/device-edge-channel-contract",
"packages/infrastructure-telemetry-contract",
"packages/arusnavi-b2-adapter", "packages/arusnavi-b2-adapter",
"services/device-control-core", "services/device-control-core",
"services/device-gateway", "services/device-gateway",
@@ -4690,6 +4729,7 @@ def allowed_payload_path(component, rel):
if rel.startswith(( if rel.startswith((
"packages/device-protocol-contract/", "packages/device-protocol-contract/",
"packages/device-edge-channel-contract/", "packages/device-edge-channel-contract/",
"packages/infrastructure-telemetry-contract/",
"packages/arusnavi-b2-adapter/", "packages/arusnavi-b2-adapter/",
"services/device-control-core/", "services/device-control-core/",
"services/device-gateway/", "services/device-gateway/",
@@ -11611,6 +11651,7 @@ def is_device_plane_manager_control_plane_slice(component, entries):
DEVICE_PLANE_MANAGER_RELEASE_V6_ENTRIES, DEVICE_PLANE_MANAGER_RELEASE_V6_ENTRIES,
DEVICE_PLANE_MANAGER_RELEASE_V7_ENTRIES, DEVICE_PLANE_MANAGER_RELEASE_V7_ENTRIES,
DEVICE_PLANE_MANAGER_RELEASE_V8_ENTRIES, DEVICE_PLANE_MANAGER_RELEASE_V8_ENTRIES,
DEVICE_PLANE_MANAGER_RELEASE_V9_ENTRIES,
) )
) )
@@ -11671,6 +11712,14 @@ def is_device_plane_manager_release_v8_slice(component, entries):
) )
def is_device_plane_manager_release_v9_slice(component, entries):
return (
component == "device-plane"
and entries is not None
and tuple(entries) == DEVICE_PLANE_MANAGER_RELEASE_V9_ENTRIES
)
def is_device_plane_manager_persistent_release_slice(component, entries): def is_device_plane_manager_persistent_release_slice(component, entries):
return ( return (
is_device_plane_manager_release_v4_slice(component, entries) is_device_plane_manager_release_v4_slice(component, entries)
@@ -11678,6 +11727,7 @@ def is_device_plane_manager_persistent_release_slice(component, entries):
or is_device_plane_manager_release_v6_slice(component, entries) or is_device_plane_manager_release_v6_slice(component, entries)
or is_device_plane_manager_release_v7_slice(component, entries) or is_device_plane_manager_release_v7_slice(component, entries)
or is_device_plane_manager_release_v8_slice(component, entries) or is_device_plane_manager_release_v8_slice(component, entries)
or is_device_plane_manager_release_v9_slice(component, entries)
) )
@@ -11736,6 +11786,7 @@ def is_device_plane_control_core_release_slice(component, entries):
and tuple(entries) in ( and tuple(entries) in (
DEVICE_PLANE_CONTROL_CORE_RELEASE_ENTRIES, DEVICE_PLANE_CONTROL_CORE_RELEASE_ENTRIES,
DEVICE_PLANE_CONTROL_CORE_RELEASE_V2_ENTRIES, DEVICE_PLANE_CONTROL_CORE_RELEASE_V2_ENTRIES,
DEVICE_PLANE_CONTROL_CORE_RELEASE_V3_ENTRIES,
) )
) )
@@ -11748,6 +11799,14 @@ def is_device_plane_control_core_release_v2_slice(component, entries):
) )
def is_device_plane_control_core_release_v3_slice(component, entries):
return (
component == "device-plane"
and entries is not None
and tuple(entries) == DEVICE_PLANE_CONTROL_CORE_RELEASE_V3_ENTRIES
)
def is_device_plane_manager_v2_control_plane_slice(component, entries): def is_device_plane_manager_v2_control_plane_slice(component, entries):
return ( return (
component == "device-plane" component == "device-plane"
@@ -11992,6 +12051,37 @@ def expected_device_plane_manager_release_v8_boundaries():
} }
def expected_device_plane_manager_release_v9_boundaries():
return {
**expected_device_plane_manager_release_v8_boundaries(),
"predecessor": {
"kind": "release",
"patchId": DEVICE_PLANE_MANAGER_RELEASE_V9_PREDECESSOR_PATCH_ID,
"artifactSha256": (
DEVICE_PLANE_MANAGER_RELEASE_V9_PREDECESSOR_ARTIFACT_SHA256
),
},
"controlCorePredecessor": {
"patchId": (
DEVICE_PLANE_MANAGER_RELEASE_V9_CONTROL_CORE_PREDECESSOR_PATCH_ID
),
"artifactSha256": (
DEVICE_PLANE_MANAGER_RELEASE_V9_CONTROL_CORE_PREDECESSOR_ARTIFACT_SHA256
),
},
"telemetryWorkspace": "mission-core-compute-module-parity-v1",
"telemetryNavigation": "full-workspace-back-navigation-v1",
"telemetryPollInterval": "three-seconds",
"telemetryFreshness": (
"fifteen-seconds-missing-stale-not-unhealthy"
),
"telemetryOntologyProjection": (
"observation-observed-property-provenance-freshness-v1"
),
"telemetryAgent": "telegraf-host-observer-v1",
}
def expected_device_plane_manager_release_boundaries(): def expected_device_plane_manager_release_boundaries():
# Compatibility name for the current release builder/tests. Immutable v1 # Compatibility name for the current release builder/tests. Immutable v1
# predecessors always use expected_device_plane_manager_release_v1_boundaries. # predecessors always use expected_device_plane_manager_release_v1_boundaries.
@@ -12238,12 +12328,12 @@ def expected_device_plane_control_core_release_descriptor(
"edgeRegistrations": "preserved", "edgeRegistrations": "preserved",
"commandTransport": ( "commandTransport": (
"typed-service-ping-v1" "typed-service-ping-v1"
if schema_version == "v2" if schema_version in ("v2", "v3")
else "disabled" else "disabled"
), ),
"gelios": ( "gelios": (
"untouched-legacy-only" "untouched-legacy-only"
if schema_version == "v2" if schema_version in ("v2", "v3")
else "untouched" else "untouched"
), ),
"preservedServices": [ "preservedServices": [
@@ -12258,7 +12348,7 @@ def expected_device_plane_control_core_release_descriptor(
), ),
"rollback": "restore-preapply-source-and-core-runtime", "rollback": "restore-preapply-source-and-core-runtime",
} }
if schema_version == "v2": if schema_version in ("v2", "v3"):
descriptor["commandCatalog"] = ( descriptor["commandCatalog"] = (
"allowlisted-adapter-typed-commands-only" "allowlisted-adapter-typed-commands-only"
) )
@@ -12266,6 +12356,24 @@ def expected_device_plane_control_core_release_descriptor(
"transient-core-memory-then-single-pinned-mtls-command-envelope-" "transient-core-memory-then-single-pinned-mtls-command-envelope-"
"to-edge-never-persisted-never-logged-never-returned" "to-edge-never-persisted-never-logged-never-returned"
) )
if schema_version == "v3":
descriptor.update({
"telemetryTransport": (
"edge-channel-host-telemetry-observed-v1"
),
"telemetryContract": (
"nodedc.infrastructure.host-telemetry.v1"
),
"telemetryStorage": (
"device-control-core-postgres-seven-day-retention"
),
"ontologyProjection": (
"observation-observed-property-provenance-freshness-v1"
),
"telemetryFreshness": (
"fifteen-seconds-missing-stale-not-unhealthy"
),
})
return descriptor return descriptor
@@ -12512,6 +12620,7 @@ def validate_device_plane_manager_release_payload_contract(
"nodedc.device-plane.device-manager-release.v6", "nodedc.device-plane.device-manager-release.v6",
"nodedc.device-plane.device-manager-release.v7", "nodedc.device-plane.device-manager-release.v7",
"nodedc.device-plane.device-manager-release.v8", "nodedc.device-plane.device-manager-release.v8",
"nodedc.device-plane.device-manager-release.v9",
): ):
required_compose.extend(( required_compose.extend((
"NODEDC_DEVICE_MANAGER_PRESENTATION_PATH: " "NODEDC_DEVICE_MANAGER_PRESENTATION_PATH: "
@@ -12702,6 +12811,24 @@ def validate_device_plane_manager_release_v8_payload(
return descriptor return descriptor
def validate_device_plane_manager_release_v9_payload(
payload_dir,
*,
expected_release_id=None,
):
descriptor = validate_device_plane_manager_release_payload_contract(
payload_dir,
descriptor_rel=DEVICE_PLANE_MANAGER_RELEASE_V9_REL,
schema_version="nodedc.device-plane.device-manager-release.v9",
boundaries=expected_device_plane_manager_release_v9_boundaries(),
compose_sha256=DEVICE_PLANE_MANAGER_RELEASE_V9_COMPOSE_SHA256,
edge_channel=False,
expected_release_id=expected_release_id,
)
validate_device_plane_manager_v6_favicon_bundle(payload_dir)
return descriptor
def validate_device_plane_manager_release_payload( def validate_device_plane_manager_release_payload(
payload_dir, payload_dir,
*, *,
@@ -12715,12 +12842,18 @@ def validate_device_plane_manager_release_payload(
v6 = payload_dir / DEVICE_PLANE_MANAGER_RELEASE_V6_REL v6 = payload_dir / DEVICE_PLANE_MANAGER_RELEASE_V6_REL
v7 = payload_dir / DEVICE_PLANE_MANAGER_RELEASE_V7_REL v7 = payload_dir / DEVICE_PLANE_MANAGER_RELEASE_V7_REL
v8 = payload_dir / DEVICE_PLANE_MANAGER_RELEASE_V8_REL v8 = payload_dir / DEVICE_PLANE_MANAGER_RELEASE_V8_REL
v9 = payload_dir / DEVICE_PLANE_MANAGER_RELEASE_V9_REL
present = [ present = [
path for path in (v1, v2, v3, v4, v5, v6, v7, v8) path for path in (v1, v2, v3, v4, v5, v6, v7, v8, v9)
if path.exists() or path.is_symlink() if path.exists() or path.is_symlink()
] ]
if len(present) != 1: if len(present) != 1:
die("Device Manager release descriptor cardinality mismatch") die("Device Manager release descriptor cardinality mismatch")
if present[0] == v9:
return validate_device_plane_manager_release_v9_payload(
payload_dir,
expected_release_id=expected_release_id,
)
if present[0] == v8: if present[0] == v8:
return validate_device_plane_manager_release_v8_payload( return validate_device_plane_manager_release_v8_payload(
payload_dir, payload_dir,
@@ -12883,10 +13016,11 @@ def validate_device_plane_control_core_release_payload(
): ):
v1 = payload_dir / DEVICE_PLANE_CONTROL_CORE_RELEASE_REL v1 = payload_dir / DEVICE_PLANE_CONTROL_CORE_RELEASE_REL
v2 = payload_dir / DEVICE_PLANE_CONTROL_CORE_RELEASE_V2_REL v2 = payload_dir / DEVICE_PLANE_CONTROL_CORE_RELEASE_V2_REL
present = [path for path in (v1, v2) if path.exists() or path.is_symlink()] v3 = payload_dir / DEVICE_PLANE_CONTROL_CORE_RELEASE_V3_REL
present = [path for path in (v1, v2, v3) if path.exists() or path.is_symlink()]
if len(present) != 1: if len(present) != 1:
die("Device Control Core release descriptor cardinality mismatch") die("Device Control Core release descriptor cardinality mismatch")
schema_version = "v2" if present[0] == v2 else "v1" schema_version = "v3" if present[0] == v3 else "v2" if present[0] == v2 else "v1"
descriptor = read_strict_json( descriptor = read_strict_json(
present[0], present[0],
"Device Control Core release descriptor", "Device Control Core release descriptor",
@@ -12928,7 +13062,7 @@ def validate_device_plane_control_core_release_payload(
if ( if (
not isinstance(release_id, str) not isinstance(release_id, str)
or not re.fullmatch( or not re.fullmatch(
r"device-control-core-release(?:-v2)?-[A-Za-z0-9._-]{1,67}", r"device-control-core-release(?:-v[23])?-[A-Za-z0-9._-]{1,67}",
release_id, release_id,
) )
or ( or (
@@ -13028,6 +13162,20 @@ def installed_device_plane_manager_compose_sha256():
v6 = root / DEVICE_PLANE_MANAGER_RELEASE_V6_REL v6 = root / DEVICE_PLANE_MANAGER_RELEASE_V6_REL
v7 = root / DEVICE_PLANE_MANAGER_RELEASE_V7_REL v7 = root / DEVICE_PLANE_MANAGER_RELEASE_V7_REL
v8 = root / DEVICE_PLANE_MANAGER_RELEASE_V8_REL v8 = root / DEVICE_PLANE_MANAGER_RELEASE_V8_REL
v9 = root / DEVICE_PLANE_MANAGER_RELEASE_V9_REL
if v9.exists() or v9.is_symlink():
descriptor = read_strict_json(
v9,
"installed Device Manager release v9 descriptor",
max_bytes=16 * 1024,
)
validate_device_plane_manager_release_descriptor(
descriptor,
schema_version="nodedc.device-plane.device-manager-release.v9",
boundaries=expected_device_plane_manager_release_v9_boundaries(),
)
return DEVICE_PLANE_MANAGER_RELEASE_V9_COMPOSE_SHA256
# A successful v2 overlay intentionally leaves the immutable v1 release # A successful v2 overlay intentionally leaves the immutable v1 release
# descriptor as predecessor evidence. Prefer the highest installed # descriptor as predecessor evidence. Prefer the highest installed
@@ -14621,6 +14769,7 @@ def validate_device_plane_manager_v3_active_baseline(descriptor):
"nodedc.device-plane.device-manager-release.v6", "nodedc.device-plane.device-manager-release.v6",
"nodedc.device-plane.device-manager-release.v7", "nodedc.device-plane.device-manager-release.v7",
"nodedc.device-plane.device-manager-release.v8", "nodedc.device-plane.device-manager-release.v8",
"nodedc.device-plane.device-manager-release.v9",
): ):
return None return None
@@ -14677,11 +14826,15 @@ def validate_device_plane_manager_v3_active_baseline(descriptor):
core_artifact, core_artifact,
Path(directory), Path(directory),
) )
core_entry_set = tuple(core_entries)
if ( if (
core_manifest.get("id") != core_reference["patchId"] core_manifest.get("id") != core_reference["patchId"]
or core_manifest.get("component") != "device-plane" or core_manifest.get("component") != "device-plane"
or core_manifest.get("type") != "app-overlay" or core_manifest.get("type") != "app-overlay"
or tuple(core_entries) != DEVICE_PLANE_CONTROL_CORE_RELEASE_V2_ENTRIES or core_entry_set not in (
DEVICE_PLANE_CONTROL_CORE_RELEASE_V2_ENTRIES,
DEVICE_PLANE_CONTROL_CORE_RELEASE_V3_ENTRIES,
)
): ):
die("Device Manager v3 Device Control Core predecessor type mismatch") die("Device Manager v3 Device Control Core predecessor type mismatch")
expected_core_descriptor = ( expected_core_descriptor = (
@@ -14690,8 +14843,13 @@ def validate_device_plane_manager_v3_active_baseline(descriptor):
expected_release_id=core_reference["patchId"], expected_release_id=core_reference["patchId"],
) )
) )
installed_core_descriptor_rel = (
DEVICE_PLANE_CONTROL_CORE_RELEASE_V3_REL
if core_entry_set == DEVICE_PLANE_CONTROL_CORE_RELEASE_V3_ENTRIES
else DEVICE_PLANE_CONTROL_CORE_RELEASE_V2_REL
)
installed_core_descriptor = read_strict_json( installed_core_descriptor = read_strict_json(
DEVICE_PLANE_ROOT / DEVICE_PLANE_CONTROL_CORE_RELEASE_V2_REL, DEVICE_PLANE_ROOT / installed_core_descriptor_rel,
"installed Device Manager v3 Device Control Core predecessor", "installed Device Manager v3 Device Control Core predecessor",
max_bytes=16 * 1024, max_bytes=16 * 1024,
) )
@@ -14699,12 +14857,12 @@ def validate_device_plane_manager_v3_active_baseline(descriptor):
die("Device Manager v3 Device Control Core predecessor is not current") die("Device Manager v3 Device Control Core predecessor is not current")
expected_core_source = collect_exact_files( expected_core_source = collect_exact_files(
core_payload, core_payload,
DEVICE_PLANE_CONTROL_CORE_RELEASE_V2_ENTRIES, core_entry_set,
"Device Manager v3 Device Control Core predecessor source", "Device Manager v3 Device Control Core predecessor source",
) )
actual_core_source = collect_exact_files( actual_core_source = collect_exact_files(
DEVICE_PLANE_ROOT, DEVICE_PLANE_ROOT,
DEVICE_PLANE_CONTROL_CORE_RELEASE_V2_ENTRIES, core_entry_set,
"installed Device Manager v3 Device Control Core predecessor source", "installed Device Manager v3 Device Control Core predecessor source",
) )
if actual_core_source != expected_core_source: if actual_core_source != expected_core_source:
@@ -14772,6 +14930,7 @@ def device_plane_manager_preserved_runtime_health_services(descriptor):
"nodedc.device-plane.device-manager-release.v6", "nodedc.device-plane.device-manager-release.v6",
"nodedc.device-plane.device-manager-release.v7", "nodedc.device-plane.device-manager-release.v7",
"nodedc.device-plane.device-manager-release.v8", "nodedc.device-plane.device-manager-release.v8",
"nodedc.device-plane.device-manager-release.v9",
): ):
return ( return (
"device-control-core", "device-control-core",
@@ -14908,6 +15067,7 @@ def validate_device_plane_manager_activation_predecessor(
DEVICE_PLANE_MANAGER_RELEASE_V6_ENTRIES, DEVICE_PLANE_MANAGER_RELEASE_V6_ENTRIES,
DEVICE_PLANE_MANAGER_RELEASE_V7_ENTRIES, DEVICE_PLANE_MANAGER_RELEASE_V7_ENTRIES,
DEVICE_PLANE_MANAGER_RELEASE_V8_ENTRIES, DEVICE_PLANE_MANAGER_RELEASE_V8_ENTRIES,
DEVICE_PLANE_MANAGER_RELEASE_V9_ENTRIES,
) )
): ):
die("Device Manager release predecessor type mismatch") die("Device Manager release predecessor type mismatch")
@@ -14932,6 +15092,8 @@ def validate_device_plane_manager_activation_predecessor(
DEVICE_PLANE_MANAGER_RELEASE_V7_REL, DEVICE_PLANE_MANAGER_RELEASE_V7_REL,
DEVICE_PLANE_MANAGER_RELEASE_V8_ENTRIES: DEVICE_PLANE_MANAGER_RELEASE_V8_ENTRIES:
DEVICE_PLANE_MANAGER_RELEASE_V8_REL, DEVICE_PLANE_MANAGER_RELEASE_V8_REL,
DEVICE_PLANE_MANAGER_RELEASE_V9_ENTRIES:
DEVICE_PLANE_MANAGER_RELEASE_V9_REL,
}.get( }.get(
tuple(predecessor_entries), tuple(predecessor_entries),
DEVICE_PLANE_MANAGER_CONTROL_PLANE_REL, DEVICE_PLANE_MANAGER_CONTROL_PLANE_REL,
@@ -15487,6 +15649,9 @@ def validate_device_plane_control_core_release_predecessor(
installed_v2_release = ( installed_v2_release = (
DEVICE_PLANE_ROOT / DEVICE_PLANE_CONTROL_CORE_RELEASE_V2_REL DEVICE_PLANE_ROOT / DEVICE_PLANE_CONTROL_CORE_RELEASE_V2_REL
) )
installed_v3_release = (
DEVICE_PLANE_ROOT / DEVICE_PLANE_CONTROL_CORE_RELEASE_V3_REL
)
with tempfile.TemporaryDirectory( with tempfile.TemporaryDirectory(
prefix="device-control-core-release-predecessor-", prefix="device-control-core-release-predecessor-",
dir=TMP_DIR, dir=TMP_DIR,
@@ -15520,6 +15685,8 @@ def validate_device_plane_control_core_release_predecessor(
or installed_v1_release.is_symlink() or installed_v1_release.is_symlink()
or installed_v2_release.exists() or installed_v2_release.exists()
or installed_v2_release.is_symlink() or installed_v2_release.is_symlink()
or installed_v3_release.exists()
or installed_v3_release.is_symlink()
): ):
die("Device Control Core first release is already installed") die("Device Control Core first release is already installed")
else: else:
@@ -15529,6 +15696,9 @@ def validate_device_plane_control_core_release_predecessor(
elif tuple(entries) == DEVICE_PLANE_CONTROL_CORE_RELEASE_V2_ENTRIES: elif tuple(entries) == DEVICE_PLANE_CONTROL_CORE_RELEASE_V2_ENTRIES:
installed_release = installed_v2_release installed_release = installed_v2_release
source_entries = DEVICE_PLANE_CONTROL_CORE_RELEASE_V2_ENTRIES source_entries = DEVICE_PLANE_CONTROL_CORE_RELEASE_V2_ENTRIES
elif tuple(entries) == DEVICE_PLANE_CONTROL_CORE_RELEASE_V3_ENTRIES:
installed_release = installed_v3_release
source_entries = DEVICE_PLANE_CONTROL_CORE_RELEASE_V3_ENTRIES
else: else:
die("Device Control Core release predecessor type mismatch") die("Device Control Core release predecessor type mismatch")
expected_installed = validate_device_plane_control_core_release_payload( expected_installed = validate_device_plane_control_core_release_payload(
@@ -17311,6 +17481,7 @@ def validate_device_manager_control_plane_runtime(
require_edge_channel = edge_descriptor.is_file() and not edge_descriptor.is_symlink() require_edge_channel = edge_descriptor.is_file() and not edge_descriptor.is_symlink()
if require_persistent_data is None: if require_persistent_data is None:
data_descriptors = ( data_descriptors = (
DEVICE_PLANE_ROOT / DEVICE_PLANE_MANAGER_RELEASE_V9_REL,
DEVICE_PLANE_ROOT / DEVICE_PLANE_MANAGER_RELEASE_V8_REL, DEVICE_PLANE_ROOT / DEVICE_PLANE_MANAGER_RELEASE_V8_REL,
DEVICE_PLANE_ROOT / DEVICE_PLANE_MANAGER_RELEASE_V7_REL, DEVICE_PLANE_ROOT / DEVICE_PLANE_MANAGER_RELEASE_V7_REL,
DEVICE_PLANE_ROOT / DEVICE_PLANE_MANAGER_RELEASE_V6_REL, DEVICE_PLANE_ROOT / DEVICE_PLANE_MANAGER_RELEASE_V6_REL,
@@ -29966,6 +30137,7 @@ def plan_artifact(artifact):
"nodedc.device-plane.device-manager-release.v6", "nodedc.device-plane.device-manager-release.v6",
"nodedc.device-plane.device-manager-release.v7", "nodedc.device-plane.device-manager-release.v7",
"nodedc.device-plane.device-manager-release.v8", "nodedc.device-plane.device-manager-release.v8",
"nodedc.device-plane.device-manager-release.v9",
) )
else "build+recreate:device-control-core,device-manager" else "build+recreate:device-control-core,device-manager"
) )
@@ -29984,6 +30156,7 @@ def plan_artifact(artifact):
"nodedc.device-plane.device-manager-release.v6", "nodedc.device-plane.device-manager-release.v6",
"nodedc.device-plane.device-manager-release.v7", "nodedc.device-plane.device-manager-release.v7",
"nodedc.device-plane.device-manager-release.v8", "nodedc.device-plane.device-manager-release.v8",
"nodedc.device-plane.device-manager-release.v9",
) )
else "preserved:device-gateway,device-postgres," else "preserved:device-gateway,device-postgres,"
"device-backhaul-target" "device-backhaul-target"
@@ -29998,6 +30171,7 @@ def plan_artifact(artifact):
"nodedc.device-plane.device-manager-release.v6", "nodedc.device-plane.device-manager-release.v6",
"nodedc.device-plane.device-manager-release.v7", "nodedc.device-plane.device-manager-release.v7",
"nodedc.device-plane.device-manager-release.v8", "nodedc.device-plane.device-manager-release.v8",
"nodedc.device-plane.device-manager-release.v9",
) )
print( print(
"device_manager_health_gate=" "device_manager_health_gate="
@@ -30022,6 +30196,7 @@ def plan_artifact(artifact):
"nodedc.device-plane.device-manager-release.v6", "nodedc.device-plane.device-manager-release.v6",
"nodedc.device-plane.device-manager-release.v7", "nodedc.device-plane.device-manager-release.v7",
"nodedc.device-plane.device-manager-release.v8", "nodedc.device-plane.device-manager-release.v8",
"nodedc.device-plane.device-manager-release.v9",
): ):
print( print(
"device_manager_overview_layout=" "device_manager_overview_layout="
@@ -30031,11 +30206,13 @@ def plan_artifact(artifact):
"nodedc.device-plane.device-manager-release.v6", "nodedc.device-plane.device-manager-release.v6",
"nodedc.device-plane.device-manager-release.v7", "nodedc.device-plane.device-manager-release.v7",
"nodedc.device-plane.device-manager-release.v8", "nodedc.device-plane.device-manager-release.v8",
"nodedc.device-plane.device-manager-release.v9",
): ):
print("device_manager_favicon_set=nodedc-adaptive-v1") print("device_manager_favicon_set=nodedc-adaptive-v1")
if manager_schema in ( if manager_schema in (
"nodedc.device-plane.device-manager-release.v7", "nodedc.device-plane.device-manager-release.v7",
"nodedc.device-plane.device-manager-release.v8", "nodedc.device-plane.device-manager-release.v8",
"nodedc.device-plane.device-manager-release.v9",
): ):
print("device_manager_command_form=aligned-control-row-v1") print("device_manager_command_form=aligned-control-row-v1")
print("device_manager_secondary_empty_text=help-text-sm-v1") print("device_manager_secondary_empty_text=help-text-sm-v1")
@@ -30050,8 +30227,9 @@ def plan_artifact(artifact):
"device_manager_host_ontology=" "device_manager_host_ontology="
"candidate-not-canonical" "candidate-not-canonical"
) )
if manager_schema == ( if manager_schema in (
"nodedc.device-plane.device-manager-release.v8" "nodedc.device-plane.device-manager-release.v8",
"nodedc.device-plane.device-manager-release.v9",
): ):
print( print(
"device_manager_infrastructure_hosts=" "device_manager_infrastructure_hosts="
@@ -30081,6 +30259,22 @@ def plan_artifact(artifact):
"device_manager_interactive_shell=" "device_manager_interactive_shell="
"disabled-pending-managed-session-boundary" "disabled-pending-managed-session-boundary"
) )
if manager_schema == (
"nodedc.device-plane.device-manager-release.v9"
):
print(
"device_manager_host_telemetry_workspace="
"mission-core-compute-module-parity-v1"
)
print(
"device_manager_host_telemetry_navigation="
"full-workspace-back-navigation-v1"
)
print("device_manager_host_telemetry_poll=three-seconds")
print(
"device_manager_host_telemetry_freshness="
"fifteen-seconds-missing-stale-not-unhealthy"
)
if device_plane_manager_activation_preflight["descriptor"].get( if device_plane_manager_activation_preflight["descriptor"].get(
"commandTransport" "commandTransport"
) == "typed-service-ping-v1": ) == "typed-service-ping-v1":
@@ -30138,6 +30332,25 @@ def plan_artifact(artifact):
"device_edge_channel_commands=" "device_edge_channel_commands="
f"{descriptor['commandTransport']}" f"{descriptor['commandTransport']}"
) )
if descriptor.get("schemaVersion") == (
"nodedc.device-plane.device-control-core-release.v3"
):
print(
"device_host_telemetry_transport="
"edge-channel-host-telemetry-observed-v1"
)
print(
"device_host_telemetry_storage="
"device-control-core-postgres-seven-day-retention"
)
print(
"device_host_telemetry_ontology="
"observation-observed-property-provenance-freshness-v1"
)
print(
"device_host_telemetry_freshness="
"fifteen-seconds-missing-stale-not-unhealthy"
)
print("device_manager=preserved:active") print("device_manager=preserved:active")
print("device_manager_public_route=unchanged:active") print("device_manager_public_route=unchanged:active")
print("device_gateway_tcp_9921=preserved:loopback-only") print("device_gateway_tcp_9921=preserved:loopback-only")
@@ -29,6 +29,60 @@ RUNNER = load_runner()
class DevicePlaneRegistryTest(unittest.TestCase): class DevicePlaneRegistryTest(unittest.TestCase):
def test_manager_v9_pins_v8_and_host_telemetry_workspace(self):
self.assertEqual(
RUNNER.DEVICE_PLANE_MANAGER_RELEASE_V9_PREDECESSOR_PATCH_ID,
"device-manager-release-v8-20260822-039",
)
self.assertEqual(
RUNNER.DEVICE_PLANE_MANAGER_RELEASE_V9_CONTROL_CORE_PREDECESSOR_PATCH_ID,
"device-control-core-release-v3-20260822-040",
)
boundaries = RUNNER.expected_device_plane_manager_release_v9_boundaries()
self.assertEqual(
boundaries["telemetryWorkspace"],
"mission-core-compute-module-parity-v1",
)
self.assertEqual(
boundaries["telemetryFreshness"],
"fifteen-seconds-missing-stale-not-unhealthy",
)
self.assertEqual(
RUNNER.component_services(
"device-plane",
RUNNER.DEVICE_PLANE_MANAGER_RELEASE_V9_ENTRIES,
),
("device-manager",),
)
def test_control_core_v3_registers_telemetry_contract_slice(self):
predecessor = {
"kind": "release",
"patchId": "device-control-core-release-v2-20260822-038",
"artifactSha256": (
"e2d062b82b022dba662522b5d6e192026ac964d78950d903295ca3cbbc95ab28"
),
}
descriptor = RUNNER.expected_device_plane_control_core_release_descriptor(
"device-control-core-release-v3-20260822-040",
predecessor,
schema_version="v3",
)
self.assertEqual(
descriptor["telemetryTransport"],
"edge-channel-host-telemetry-observed-v1",
)
self.assertEqual(
descriptor["telemetryStorage"],
"device-control-core-postgres-seven-day-retention",
)
self.assertTrue(
RUNNER.is_device_plane_control_core_release_v3_slice(
"device-plane",
RUNNER.DEVICE_PLANE_CONTROL_CORE_RELEASE_V3_ENTRIES,
)
)
def test_manager_v8_pins_production_v6_and_canonical_ontology_runtime(self): def test_manager_v8_pins_production_v6_and_canonical_ontology_runtime(self):
self.assertEqual( self.assertEqual(
RUNNER.DEVICE_PLANE_MANAGER_RELEASE_V8_PREDECESSOR_PATCH_ID, RUNNER.DEVICE_PLANE_MANAGER_RELEASE_V8_PREDECESSOR_PATCH_ID,