fix(device-plane): activate manager from reconciled baseline

This commit is contained in:
Codex
2026-08-11 01:12:44 +03:00
parent 04ba3a9f99
commit 8defd55715
5 changed files with 322 additions and 14 deletions
+212 -8
View File
@@ -210,13 +210,29 @@ DEVICE_PLANE_FOUNDATION_ENTRIES = (
"services/device-control-core",
"services/device-gateway",
)
DEVICE_PLANE_MANAGER_CONTROL_PLANE_REL = (
DEVICE_PLANE_MANAGER_FAILED_CONTROL_PLANE_REL = (
"deployment/device-manager-control-plane-v1.json"
)
DEVICE_PLANE_MANAGER_CONTROL_PLANE_REL = (
"deployment/device-manager-control-plane-v2.json"
)
DEVICE_PLANE_MANAGER_COMPOSE_REL = "docker-compose.device-manager.yml"
DEVICE_PLANE_MANAGER_COMPOSE_SHA256 = (
"4954120aaddc999798b64c304d8cf692b79714feb727d873117bd1f3434e865e"
)
DEVICE_PLANE_MANAGER_FAILED_CONTROL_PLANE_ENTRIES = (
".dockerignore",
"package.json",
"package-lock.json",
DEVICE_PLANE_MANAGER_COMPOSE_REL,
"packages/device-protocol-contract",
"packages/arusnavi-b2-adapter",
"services/device-control-core",
"services/device-gateway/package.json",
"services/device-edge-relay/package.json",
"services/device-manager",
DEVICE_PLANE_MANAGER_FAILED_CONTROL_PLANE_REL,
)
DEVICE_PLANE_MANAGER_CONTROL_PLANE_ENTRIES = (
".dockerignore",
"package.json",
@@ -246,6 +262,20 @@ DEVICE_PLANE_MANAGER_FAILED_ARTIFACT = (
DEVICE_PLANE_MANAGER_FAILED_ARTIFACT_SHA256 = (
"50e275c1085286bcb3bb2b273aefc8bbba70f446ca2c7bd464dc745710a291a6"
)
DEVICE_PLANE_MANAGER_RECONCILIATION_PATCH_ID = (
"device-manager-control-plane-reconciliation-20260811-002"
)
DEVICE_PLANE_MANAGER_RECONCILIATION_ARTIFACT = (
"nodedc-device-plane-device-manager-control-plane-reconciliation-"
"20260811-002.tgz"
)
DEVICE_PLANE_MANAGER_RECONCILIATION_ARTIFACT_SHA256 = (
"dd86dd58e4f649db0981db5089e003caf3961356179f2abb514662351487e1e6"
)
DEVICE_PLANE_MANAGER_RECONCILIATION_APPLY_BACKUP_ID = (
"device-plane-device-manager-control-plane-reconciliation-"
"20260811-002-20260811-004839"
)
DEVICE_PLANE_MANAGER_RECONCILIATION_BACKUP_ID = (
"device-plane-device-manager-control-plane-20260810-001-"
"20260811-000321"
@@ -283,7 +313,7 @@ DEVICE_PLANE_MANAGER_RECONCILIATION_EXISTING = (
DEVICE_PLANE_MANAGER_RECONCILIATION_MISSING = (
DEVICE_PLANE_MANAGER_COMPOSE_REL,
"services/device-manager",
DEVICE_PLANE_MANAGER_CONTROL_PLANE_REL,
DEVICE_PLANE_MANAGER_FAILED_CONTROL_PLANE_REL,
)
DEVICE_PLANE_FOUNDATION_RECOVERY_REL = (
"deployment/device-plane-foundation-recovery-v1.json"
@@ -3169,6 +3199,7 @@ def allowed_payload_path(component, rel):
DEVICE_PLANE_B2_DISCOVERY_INGRESS_REL,
DEVICE_PLANE_B2_DISCOVERY_ROLLBACK_RECOVERY_REL,
DEVICE_PLANE_BACKHAUL_TARGET_REL,
DEVICE_PLANE_MANAGER_FAILED_CONTROL_PLANE_REL,
DEVICE_PLANE_MANAGER_CONTROL_PLANE_REL,
DEVICE_PLANE_MANAGER_RECONCILIATION_REL,
"packages/device-protocol-contract",
@@ -8216,6 +8247,13 @@ def load_artifact(artifact, work_dir):
entries,
):
validate_device_plane_manager_control_plane_payload(payload_dir)
if is_device_plane_manager_failed_control_plane_slice(
manifest["component"],
entries,
):
validate_device_plane_manager_failed_control_plane_payload(
payload_dir
)
if is_device_plane_manager_reconciliation_slice(
manifest["component"],
entries,
@@ -8555,14 +8593,22 @@ def reject_terminal_device_plane_foundation_artifact(manifest, sha256):
)
def reject_terminal_device_plane_manager_artifact(manifest, sha256):
def reject_terminal_device_plane_manager_artifact(
manifest,
sha256,
entries=None,
):
if (
manifest.get("id") == DEVICE_PLANE_MANAGER_FAILED_PATCH_ID
or sha256 == DEVICE_PLANE_MANAGER_FAILED_ARTIFACT_SHA256
or is_device_plane_manager_failed_control_plane_slice(
manifest.get("component"),
entries,
)
):
die(
"Device Manager control-plane 001 is terminal failed; "
"use the exact registered reconciliation successor"
"use reconciliation followed by the exact v2 activation successor"
)
@@ -8627,6 +8673,15 @@ def is_device_plane_manager_control_plane_slice(component, entries):
)
def is_device_plane_manager_failed_control_plane_slice(component, entries):
return (
component == "device-plane"
and entries is not None
and tuple(entries)
== DEVICE_PLANE_MANAGER_FAILED_CONTROL_PLANE_ENTRIES
)
def is_device_plane_manager_reconciliation_slice(component, entries):
return (
component == "device-plane"
@@ -8658,6 +8713,30 @@ def expected_platform_device_manager_public_route_descriptor():
def expected_device_plane_manager_control_plane_descriptor():
return {
"schemaVersion": (
"nodedc.device-plane.device-manager-control-plane.v2"
),
"action": "activate",
"predecessor": {
"patchId": DEVICE_PLANE_MANAGER_RECONCILIATION_PATCH_ID,
"artifactSha256": (
DEVICE_PLANE_MANAGER_RECONCILIATION_ARTIFACT_SHA256
),
"mode": "failed-control-plane-baseline-adoption",
},
"service": "device-manager",
"publicIngress": "reverse-proxy-only",
"deviceCoreManagementApi": "file-token-authenticated",
"launcherTrust": "file-token-scoped-to-device-core-handoff",
"healthGate": "bounded-container-grace+core-contract",
"commandTransport": "disabled",
"gelios": "untouched",
"rollback": "restore-reconciled-baseline",
}
def expected_device_plane_manager_failed_control_plane_descriptor():
return {
"schemaVersion": (
"nodedc.device-plane.device-manager-control-plane.v1"
@@ -8782,6 +8861,23 @@ def validate_device_plane_manager_control_plane_payload(payload_dir):
return descriptor
def validate_device_plane_manager_failed_control_plane_payload(payload_dir):
descriptor = read_strict_json(
payload_dir / DEVICE_PLANE_MANAGER_FAILED_CONTROL_PLANE_REL,
"failed Device Manager control-plane descriptor",
max_bytes=16 * 1024,
)
if (
descriptor
!= expected_device_plane_manager_failed_control_plane_descriptor()
):
die("failed Device Manager control-plane descriptor mismatch")
compose_path = payload_dir / DEVICE_PLANE_MANAGER_COMPOSE_REL
if sha256_file(compose_path) != DEVICE_PLANE_MANAGER_COMPOSE_SHA256:
die("failed Device Manager control-plane Compose mismatch")
return descriptor
def validate_device_plane_manager_reconciliation_payload(payload_dir):
descriptor = read_strict_json(
payload_dir / DEVICE_PLANE_MANAGER_RECONCILIATION_REL,
@@ -10049,7 +10145,7 @@ def validate_device_plane_manager_reconciliation_backup():
backup_dir / "missing-files.txt"
))
validate_backup_partition(
DEVICE_PLANE_MANAGER_CONTROL_PLANE_ENTRIES,
DEVICE_PLANE_MANAGER_FAILED_CONTROL_PLANE_ENTRIES,
existing,
missing,
"Device Manager reconciliation",
@@ -10090,7 +10186,10 @@ def validate_device_plane_manager_reconciled_baseline(
)
if live_source != backup_source:
die("Device Manager rollback source does not match backup")
for rel in DEVICE_PLANE_MANAGER_RECONCILIATION_MISSING:
for rel in (
*DEVICE_PLANE_MANAGER_RECONCILIATION_MISSING,
DEVICE_PLANE_MANAGER_CONTROL_PLANE_REL,
):
path = root / rel
if path.exists() or path.is_symlink():
die(
@@ -10200,7 +10299,7 @@ def validate_device_plane_manager_reconciliation_evidence(payload_dir):
or failed_manifest.get("component") != "device-plane"
or failed_manifest.get("type") != "app-overlay"
or tuple(failed_entries)
!= DEVICE_PLANE_MANAGER_CONTROL_PLANE_ENTRIES
!= DEVICE_PLANE_MANAGER_FAILED_CONTROL_PLANE_ENTRIES
):
die("Device Manager failed artifact contract mismatch")
@@ -10216,6 +10315,60 @@ def validate_device_plane_manager_reconciliation_evidence(payload_dir):
}
def validate_device_plane_manager_activation_predecessor(payload_dir):
descriptor = validate_device_plane_manager_control_plane_payload(
payload_dir
)
reconciliation_artifact = (
APPLIED_DIR / DEVICE_PLANE_MANAGER_RECONCILIATION_ARTIFACT
)
try:
artifact_stat = reconciliation_artifact.lstat()
except FileNotFoundError:
die("Device Manager reconciliation applied artifact is missing")
if (
stat.S_ISLNK(artifact_stat.st_mode)
or not stat.S_ISREG(artifact_stat.st_mode)
or sha256_file(reconciliation_artifact)
!= DEVICE_PLANE_MANAGER_RECONCILIATION_ARTIFACT_SHA256
):
die("Device Manager reconciliation applied artifact mismatch")
records = [
value
for value in load_state(STATE_FILE)
if value.get("id")
== DEVICE_PLANE_MANAGER_RECONCILIATION_PATCH_ID
]
if len(records) != 1:
die("Device Manager reconciliation applied journal count mismatch")
record = records[0]
if (
record.get("artifact")
!= DEVICE_PLANE_MANAGER_RECONCILIATION_ARTIFACT
or record.get("backup_id")
!= DEVICE_PLANE_MANAGER_RECONCILIATION_APPLY_BACKUP_ID
or record.get("component") != "device-plane"
or record.get("sha256")
!= DEVICE_PLANE_MANAGER_RECONCILIATION_ARTIFACT_SHA256
or record.get("status") != "ok"
):
die("Device Manager reconciliation applied journal mismatch")
backup_dir = validate_device_plane_manager_reconciliation_backup()
runtime = validate_device_plane_manager_reconciled_baseline(
backup_dir,
marker_installed=True,
)
return {
"mode": "reconciled-manager-forward-activation",
"descriptor": descriptor,
"reconciliationArtifact": reconciliation_artifact,
"reconciliationRecord": record,
"runtime": runtime,
}
def device_plane_service_container_ids(service):
if service not in (
*DEVICE_PLANE_RUNTIME_SERVICES,
@@ -15845,6 +15998,7 @@ def plan_artifact(artifact):
device_plane_network_publication_preflight = None
device_plane_b2_ingress_preflight = None
device_plane_b2_recovery_preflight = None
device_plane_manager_activation_preflight = None
device_plane_manager_reconciliation_preflight = None
device_plane_backhaul_preflight = None
device_plane_backhaul_vps_enrollment_preflight = None
@@ -15873,7 +16027,11 @@ def plan_artifact(artifact):
manifest, entries, payload_dir = load_artifact(artifact, Path(tmp))
reject_terminal_engine_l2_failed_artifact(manifest, sha)
reject_terminal_device_plane_foundation_artifact(manifest, sha)
reject_terminal_device_plane_manager_artifact(manifest, sha)
reject_terminal_device_plane_manager_artifact(
manifest,
sha,
entries,
)
reject_terminal_device_plane_backhaul_artifact(manifest, sha)
transition_descriptor = None
transition_preflight = None
@@ -16051,6 +16209,15 @@ def plan_artifact(artifact):
payload_dir
)
)
if is_device_plane_manager_control_plane_slice(
manifest["component"],
entries,
):
device_plane_manager_activation_preflight = (
validate_device_plane_manager_activation_predecessor(
payload_dir
)
)
if is_device_plane_manager_reconciliation_slice(
manifest["component"],
entries,
@@ -17613,6 +17780,35 @@ def plan_artifact(artifact):
)
print("device_gateway_tcp_9921=disabled:unpublished")
print("device_plane_rollback=marker-only-runtime-unchanged")
if device_plane_manager_activation_preflight is not None:
print(
"device_plane_transition="
f"{device_plane_manager_activation_preflight['mode']}"
)
print(
"device_plane_predecessor_patch="
f"{DEVICE_PLANE_MANAGER_RECONCILIATION_PATCH_ID}"
)
print(
"device_plane_predecessor_artifact_sha256="
f"{DEVICE_PLANE_MANAGER_RECONCILIATION_ARTIFACT_SHA256}"
)
print(
"device_plane_runtime_mutation="
"build+recreate:device-control-core,device-manager"
)
print(
"device_plane_runtime_services="
"preserved:device-gateway,device-postgres,"
"device-backhaul-target"
)
print("device_manager_health_gate=bounded-grace+contract")
print("device_manager_public_route=unchanged:absent")
print("device_gateway_tcp_9921=preserved:loopback-only")
print(
"device_plane_rollback="
"source+reconciled-baseline-runtime"
)
if device_plane_manager_reconciliation_preflight is not None:
print(
"device_plane_transition="
@@ -20849,6 +21045,7 @@ def apply_artifact(artifact):
reject_terminal_device_plane_manager_artifact(
manifest,
sha,
entries,
)
reject_terminal_device_plane_backhaul_artifact(
manifest,
@@ -20901,6 +21098,13 @@ def apply_artifact(artifact):
validate_device_plane_b2_discovery_rollback_recovery_evidence(
payload_dir
)
if is_device_plane_manager_control_plane_slice(
component,
entries,
):
validate_device_plane_manager_activation_predecessor(
payload_dir
)
if is_device_plane_manager_reconciliation_slice(
component,
entries,