feat(device-plane): enable B2 discovery ingress

This commit is contained in:
Codex
2026-07-26 00:52:31 +03:00
parent 3c538ad98c
commit 2b1795509b
19 changed files with 2375 additions and 156 deletions
+493 -1
View File
@@ -77,6 +77,22 @@ DEVICE_PLANE_FOUNDATION_NETWORK_PUBLICATION_ENTRIES = (
*DEVICE_PLANE_FOUNDATION_ENTRIES,
DEVICE_PLANE_FOUNDATION_NETWORK_PUBLICATION_REL,
)
DEVICE_PLANE_B2_DISCOVERY_INGRESS_REL = (
"deployment/device-plane-b2-discovery-ingress-v1.json"
)
DEVICE_PLANE_B2_DISCOVERY_INGRESS_ENTRIES = (
*DEVICE_PLANE_FOUNDATION_ENTRIES,
DEVICE_PLANE_B2_DISCOVERY_INGRESS_REL,
)
DEVICE_PLANE_B2_DISCOVERY_INGRESS_PREDECESSOR_PATCH_ID = (
"device-plane-foundation-network-publication-20260725-003"
)
DEVICE_PLANE_B2_DISCOVERY_INGRESS_PREDECESSOR_ARTIFACT_SHA256 = (
"6fdd5a12c310786db1753882fc1378184fe378d2cc533633a8c73c951521b7bf"
)
DEVICE_PLANE_B2_DISCOVERY_INGRESS_COMPOSE_SHA256 = (
"50bc7842481ea73b89891a65bf243c2ecb7bbb4c093e95e3c20ddbfaa8ad6726"
)
DEVICE_PLANE_FOUNDATION_FAILED_PATCH_ID = (
"device-plane-foundation-20260725-001"
)
@@ -2865,6 +2881,7 @@ def allowed_payload_path(component, rel):
DEVICE_PLANE_POSTGRES_BOOTSTRAP_REL,
DEVICE_PLANE_FOUNDATION_RECOVERY_REL,
DEVICE_PLANE_FOUNDATION_NETWORK_PUBLICATION_REL,
DEVICE_PLANE_B2_DISCOVERY_INGRESS_REL,
"packages/device-protocol-contract",
"packages/arusnavi-b2-adapter",
"services/device-control-core",
@@ -7901,6 +7918,11 @@ def load_artifact(artifact, work_dir):
validate_device_plane_foundation_network_publication_payload(
payload_dir
)
if is_device_plane_b2_discovery_ingress_slice(
manifest["component"],
entries,
):
validate_device_plane_b2_discovery_ingress_payload(payload_dir)
if manifest["component"] == "n8n-private-extension":
validate_n8n_private_extension_release(payload_dir, entries)
if manifest["component"] == "engine":
@@ -8238,6 +8260,14 @@ def is_device_plane_foundation_network_publication_slice(component, entries):
)
def is_device_plane_b2_discovery_ingress_slice(component, entries):
return (
component == "device-plane"
and entries is not None
and tuple(entries) == DEVICE_PLANE_B2_DISCOVERY_INGRESS_ENTRIES
)
def expected_device_plane_foundation_recovery_descriptor():
return {
"schemaVersion": "nodedc.device-plane.foundation-recovery.v1",
@@ -8329,6 +8359,91 @@ def validate_device_plane_foundation_network_publication_payload(payload_dir):
return descriptor
def expected_device_plane_b2_discovery_ingress_descriptor():
return {
"schemaVersion": "nodedc.device-plane.b2-discovery-ingress.v1",
"mode": "verified-b2-discovery-only",
"predecessorPatchId": (
DEVICE_PLANE_B2_DISCOVERY_INGRESS_PREDECESSOR_PATCH_ID
),
"predecessorArtifactSha256": (
DEVICE_PLANE_B2_DISCOVERY_INGRESS_PREDECESSOR_ARTIFACT_SHA256
),
"sourceAction": "publish-verified-b2-discovery-ingress-source",
"runtimeAction": "build-and-recreate-stateless-services",
"selectedServices": [
"device-control-core",
"device-gateway",
],
"preservedServices": ["device-postgres"],
"privateNetwork": DEVICE_PLANE_PRIVATE_NETWORK,
"controlNetwork": DEVICE_PLANE_CONTROL_NETWORK,
"publishedPorts": [
"127.0.0.1:18120:18120",
"127.0.0.1:18121:18121",
"0.0.0.0:9921:9921/tcp",
],
"protocolProfile": "arusnavi.b2.internal.v1",
"framingSpecification": (
"arusnavi.internal.protocol-sheet.gid-12.v1"
),
"identityTrust": "claimed-not-ownership-proof",
"discoveryLifecycle": "quarantine",
"commandTransport": "disabled",
"gelios": "untouched",
"databaseVolume": DEVICE_PLANE_POSTGRES_VOLUME,
"rollback": "restore-source-and-predecessor-stateless-runtime",
}
def validate_device_plane_b2_discovery_ingress_payload(payload_dir):
descriptor = read_strict_json(
payload_dir / DEVICE_PLANE_B2_DISCOVERY_INGRESS_REL,
"Device Plane B2 discovery ingress descriptor",
max_bytes=16 * 1024,
)
if descriptor != expected_device_plane_b2_discovery_ingress_descriptor():
die("Device Plane B2 discovery ingress descriptor mismatch")
compose = payload_dir / "docker-compose.device-plane.yml"
if (
compose.is_symlink()
or not compose.is_file()
or sha256_file(compose)
!= DEVICE_PLANE_B2_DISCOVERY_INGRESS_COMPOSE_SHA256
):
die("Device Plane B2 discovery ingress Compose mismatch")
return descriptor
def validate_device_plane_b2_discovery_ingress_evidence(payload_dir):
descriptor = validate_device_plane_b2_discovery_ingress_payload(
payload_dir
)
if not state_has_patch_id(
DEVICE_PLANE_B2_DISCOVERY_INGRESS_PREDECESSOR_PATCH_ID
):
die("Device Plane B2 discovery ingress predecessor patch missing")
if not state_has_sha(
DEVICE_PLANE_B2_DISCOVERY_INGRESS_PREDECESSOR_ARTIFACT_SHA256
):
die("Device Plane B2 discovery ingress predecessor artifact missing")
validate_device_plane_foundation_network_publication_installed_source()
runtime = validate_device_plane_foundation_runtime(
network_publication=True
)
assert_loopback_tcp_port_closed(9921)
target_descriptor = (
component_root("device-plane")
/ DEVICE_PLANE_B2_DISCOVERY_INGRESS_REL
)
if target_descriptor.exists() or target_descriptor.is_symlink():
die("Device Plane B2 discovery ingress descriptor already installed")
return {
"mode": descriptor["mode"],
"runtime": runtime,
}
def device_plane_service_container_ids(service):
if service not in DEVICE_PLANE_RUNTIME_SERVICES:
die(f"Device Plane runtime service is not registered: {service}")
@@ -9233,6 +9348,262 @@ def validate_device_plane_foundation_runtime(network_publication=False):
return accepted
def validate_device_plane_b2_discovery_ingress_runtime(runtime_before):
validate_device_plane_runtime_secret_metadata()
before_names = device_plane_inventory_service_names(runtime_before)
if set(before_names) != set(DEVICE_PLANE_RUNTIME_SERVICES):
die("Device Plane B2 ingress predecessor inventory mismatch")
before = {
item["service"]: item
for item in runtime_before["services"]
}
contracts = {
"device-control-core": {
"image": DEVICE_PLANE_CONTROL_CORE_IMAGE,
"user": "1000:1000",
"ports": {
"18120/tcp": [{
"HostIp": "127.0.0.1",
"HostPort": "18120",
}],
},
"networks": {
DEVICE_PLANE_PRIVATE_NETWORK,
DEVICE_PLANE_CONTROL_NETWORK,
},
},
"device-gateway": {
"image": DEVICE_PLANE_GATEWAY_IMAGE,
"user": "1000:1000",
"ports": {
"18121/tcp": [{
"HostIp": "127.0.0.1",
"HostPort": "18121",
}],
"9921/tcp": [{
"HostIp": "0.0.0.0",
"HostPort": "9921",
}],
},
"networks": {
DEVICE_PLANE_PRIVATE_NETWORK,
DEVICE_PLANE_CONTROL_NETWORK,
},
},
"device-postgres": {
"image": "postgres:16-alpine",
"user": "",
"ports": {},
"networks": {DEVICE_PLANE_PRIVATE_NETWORK},
},
}
accepted = {}
containers = {}
for service, contract in contracts.items():
container_ids = device_plane_service_container_ids(service)
if len(container_ids) != 1:
die(f"Device Plane B2 ingress service count mismatch: {service}")
container = inspect_device_plane_container(container_ids[0])
containers[service] = container
state = container.get("State") or {}
config = container.get("Config") or {}
host_config = container.get("HostConfig") or {}
labels = config.get("Labels") or {}
networks = (container.get("NetworkSettings") or {}).get(
"Networks"
) or {}
actual_ports = (container.get("NetworkSettings") or {}).get(
"Ports"
) or {}
if (
state.get("Status") != "running"
or state.get("Running") is not True
or state.get("Restarting") is True
or state.get("ExitCode") != 0
or state.get("Error") not in ("", None)
or (state.get("Health") or {}).get("Status") != "healthy"
or int(container.get("RestartCount") or 0) != 0
or config.get("Image") != contract["image"]
or config.get("User", "") != contract["user"]
or (host_config.get("PortBindings") or {}) != contract["ports"]
or actual_ports != contract["ports"]
or set(networks) != contract["networks"]
or (host_config.get("RestartPolicy") or {}).get("Name")
!= "unless-stopped"
or labels.get("com.docker.compose.project")
!= "nodedc-device-plane"
or labels.get("com.docker.compose.service") != service
):
die(f"Device Plane B2 ingress runtime mismatch: {service}")
accepted[service] = {
"containerId": container.get("Id"),
"imageId": container.get("Image"),
}
if (
accepted["device-postgres"]["containerId"]
!= before["device-postgres"]["containerId"]
or accepted["device-postgres"]["imageId"]
!= before["device-postgres"]["imageId"]
):
die("Device Plane B2 ingress changed PostgreSQL generation")
for service in ("device-control-core", "device-gateway"):
if (
accepted[service]["containerId"]
== before[service]["containerId"]
or accepted[service]["imageId"] == before[service]["imageId"]
):
die(
"Device Plane B2 ingress stateless generation not replaced: "
f"{service}"
)
host_config = containers[service].get("HostConfig") or {}
if (
host_config.get("ReadonlyRootfs") is not True
or set(host_config.get("CapDrop") or ()) != {"ALL"}
or "no-new-privileges:true"
not in set(host_config.get("SecurityOpt") or ())
):
die(
"Device Plane B2 ingress hardening mismatch: "
f"{service}"
)
core_environment = container_environment(
containers["device-control-core"],
"Device Plane B2 Control Core",
)
core_required = {
"DEVICE_DISCOVERY_INGEST_ENABLED": "true",
"DEVICE_GATEWAY_CORE_TOKEN_FILE":
"/run/nodedc-secrets/gateway-core-token",
"DEVICE_IDENTIFIER_PEPPER_FILE":
"/run/nodedc-secrets/identifier-pepper",
}
if any(
core_environment.get(key) != value
for key, value in core_required.items()
):
die("Device Plane B2 Control Core environment mismatch")
gateway_environment = container_environment(
containers["device-gateway"],
"Device Plane B2 Gateway",
)
gateway_required = {
"DEVICE_GATEWAY_LISTEN_ENABLED": "true",
"DEVICE_GATEWAY_PUBLIC_INGRESS_ENABLED": "true",
"DEVICE_GATEWAY_TCP_HOST": "0.0.0.0",
"DEVICE_GATEWAY_TCP_PORT": "9921",
"DEVICE_GATEWAY_CORE_URL": "http://device-control-core:18120",
"DEVICE_GATEWAY_CORE_TOKEN_FILE":
"/run/nodedc-secrets/gateway-core-token",
"DEVICE_GATEWAY_CORE_TIMEOUT_MS": "5000",
"DEVICE_GATEWAY_MAX_BUFFERED_BYTES": "65536",
"DEVICE_GATEWAY_MAX_SESSIONS": "100",
"DEVICE_GATEWAY_MAX_SESSIONS_PER_ADDRESS": "10",
"DEVICE_GATEWAY_MAX_CONNECTIONS_PER_MINUTE_PER_ADDRESS": "30",
"DEVICE_GATEWAY_SESSION_TIMEOUT_MS": "10000",
}
if any(
gateway_environment.get(key) != value
for key, value in gateway_required.items()
):
die("Device Plane B2 Gateway environment mismatch")
for environment in (core_environment, gateway_environment):
for forbidden in (
"DEVICE_GATEWAY_CORE_TOKEN",
"DEVICE_IDENTIFIER_PEPPER",
"DEVICE_GATEWAY_COMMAND_TOKEN",
):
if forbidden in environment:
die("Device Plane B2 plaintext secret boundary mismatch")
core_mounts = {
mount.get("Destination"): mount
for mount in containers["device-control-core"].get("Mounts") or []
}
expected_core_mounts = {
"/run/nodedc-secrets/postgres-password":
DEVICE_PLANE_POSTGRES_PASSWORD_FILE,
"/run/nodedc-secrets/gateway-core-token":
DEVICE_PLANE_GATEWAY_CORE_TOKEN_FILE,
"/run/nodedc-secrets/identifier-pepper":
DEVICE_PLANE_IDENTIFIER_PEPPER_FILE,
}
if set(core_mounts) != set(expected_core_mounts):
die("Device Plane B2 Control Core mount set mismatch")
for destination, source in expected_core_mounts.items():
mount = core_mounts[destination]
if (
mount.get("Type") != "bind"
or mount.get("Source") != str(source)
or mount.get("RW") is not False
):
die("Device Plane B2 Control Core secret mount mismatch")
gateway_mounts = (
containers["device-gateway"].get("Mounts") or []
)
if (
len(gateway_mounts) != 1
or gateway_mounts[0].get("Type") != "bind"
or gateway_mounts[0].get("Source")
!= str(DEVICE_PLANE_GATEWAY_CORE_TOKEN_FILE)
or gateway_mounts[0].get("Destination")
!= "/run/nodedc-secrets/gateway-core-token"
or gateway_mounts[0].get("RW") is not False
):
die("Device Plane B2 Gateway secret mount mismatch")
postgres_mounts = containers["device-postgres"].get("Mounts") or []
postgres_secret = [
mount
for mount in postgres_mounts
if mount.get("Destination")
== "/run/nodedc-secrets/postgres-password"
]
postgres_volume = [
mount
for mount in postgres_mounts
if mount.get("Destination") == "/var/lib/postgresql/data"
]
if (
len(postgres_mounts) != 2
or len(postgres_secret) != 1
or postgres_secret[0].get("Type") != "bind"
or postgres_secret[0].get("Source")
!= str(DEVICE_PLANE_POSTGRES_PASSWORD_FILE)
or postgres_secret[0].get("RW") is not False
or len(postgres_volume) != 1
or postgres_volume[0].get("Type") != "volume"
or postgres_volume[0].get("Name")
!= DEVICE_PLANE_POSTGRES_VOLUME
or postgres_volume[0].get("RW") is not True
):
die("Device Plane B2 PostgreSQL preserved mount mismatch")
expected_private_ids = {
accepted[service]["containerId"]
for service in DEVICE_PLANE_RUNTIME_SERVICES
}
validate_device_plane_network_contract(
DEVICE_PLANE_PRIVATE_NETWORK,
internal=True,
expected_container_ids=expected_private_ids,
)
validate_device_plane_network_contract(
DEVICE_PLANE_CONTROL_NETWORK,
internal=False,
expected_container_ids={
accepted["device-control-core"]["containerId"],
accepted["device-gateway"]["containerId"],
},
)
assert_loopback_tcp_port_open(9921)
return accepted
def validate_device_plane_runtime_secret_metadata():
try:
directory_stat = DEVICE_PLANE_SECRET_DIR.lstat()
@@ -13237,6 +13608,7 @@ def plan_artifact(artifact):
l2_closed_loop_preflight = None
device_plane_foundation_recovery_preflight = None
device_plane_network_publication_preflight = None
device_plane_b2_ingress_preflight = None
device_plane_runtime_before = None
composite_provider_v4_preflight = None
provider_rotating_slot_preflight = None
@@ -13420,6 +13792,15 @@ def plan_artifact(artifact):
payload_dir
)
)
if is_device_plane_b2_discovery_ingress_slice(
manifest["component"],
entries,
):
device_plane_b2_ingress_preflight = (
validate_device_plane_b2_discovery_ingress_evidence(
payload_dir
)
)
component = manifest["component"]
root = component_root(component)
@@ -14800,7 +15181,11 @@ def plan_artifact(artifact):
f"{device_plane_postgres_plan_selection(device_plane_postgres_preflight)}"
)
print("device_postgres_volume=preserved:nodedc-device-plane-postgres-data")
print("device_gateway_public_ingress=disabled")
if device_plane_b2_ingress_preflight is not None:
print("device_gateway_public_ingress=discovery-only:tcp:9921")
print("device_control_core_discovery_ingest=enabled:authenticated")
else:
print("device_gateway_public_ingress=disabled")
print("device_gateway_command_transport=disabled")
print("gelios=untouched")
if device_plane_foundation_recovery_preflight is not None:
@@ -14875,6 +15260,46 @@ def plan_artifact(artifact):
"device_plane_rollback="
"partial-source+internal-only-stateless-runtime"
)
if device_plane_b2_ingress_preflight is not None:
print(
"device_plane_transition="
f"{device_plane_b2_ingress_preflight['mode']}"
)
print(
"device_plane_predecessor_patch="
f"{DEVICE_PLANE_B2_DISCOVERY_INGRESS_PREDECESSOR_PATCH_ID}"
)
print(
"device_plane_predecessor_artifact_sha256="
f"{DEVICE_PLANE_B2_DISCOVERY_INGRESS_PREDECESSOR_ARTIFACT_SHA256}"
)
print(
"device_plane_runtime_mutation="
"build+recreate:device-control-core,device-gateway"
)
print(
"device_plane_runtime_services="
"preserved:device-postgres"
)
print(
"device_plane_actual_ports="
"required:127.0.0.1:18120,127.0.0.1:18121,"
"0.0.0.0:9921/tcp"
)
print(
"device_gateway_framing="
"verified-read-only:"
"arusnavi.internal.protocol-sheet.gid-12.v1"
)
print(
"device_gateway_identity="
"header2-imei:claimed-not-ownership-proof"
)
print("device_gateway_discovery_lifecycle=quarantine")
print(
"device_plane_rollback="
"source+predecessor-stateless-runtime"
)
if device_plane_postgres_preflight is not None:
print(
"device_postgres_bootstrap="
@@ -16076,6 +16501,14 @@ def assert_loopback_tcp_port_closed(port):
die(f"unexpected loopback TCP listener is open: {port}")
def assert_loopback_tcp_port_open(port):
try:
connection = socket.create_connection(("127.0.0.1", port), timeout=3)
except OSError as exc:
die(f"expected loopback TCP listener is closed: {port}: {exc}")
connection.close()
def external_data_plane_healthcheck(require_managed=True):
expected_json = {
"ok": True,
@@ -16170,6 +16603,30 @@ def component_healthchecks(component, entries=None, services=None):
if component == "module-foundry":
return (module_foundry_healthcheck(),)
if component == "device-plane":
if is_device_plane_b2_discovery_ingress_slice(component, entries):
return (
{
"url": "http://127.0.0.1:18120/healthz",
"expected_json": {
"ok": True,
"service": "nodedc-device-control-core",
"database": "ready",
"discoveryIngest": "enabled",
"commandTransport": "disabled",
},
},
{
"url": "http://127.0.0.1:18121/healthz",
"expected_json": {
"ok": True,
"service": "nodedc-device-gateway",
"framing": "verified-read-only",
"tcpListener": "discovery-only",
"publicIngress": "discovery-only",
"commandTransport": "disabled",
},
},
)
selected_services = (
tuple(services)
if services is not None
@@ -16632,6 +17089,22 @@ def run_healthchecks(component, entries=None, services=None):
)
assert_loopback_tcp_port_closed(9921)
return
if is_device_plane_b2_discovery_ingress_slice(component, entries):
if tuple(services or ()) != (
"device-control-core",
"device-gateway",
):
die("Device Plane B2 discovery ingress service set mismatch")
for service in (
"device-control-core",
"device-gateway",
"device-postgres",
):
healthcheck_compose_service("device-plane", service)
for check in component_healthchecks(component, entries, services):
healthcheck_url(check)
assert_loopback_tcp_port_open(9921)
return
if component == "platform" and entries is not None and is_platform_provider_catalog_only(entries):
return
if is_engine_l2_closed_loop_slice(component, entries):
@@ -17449,6 +17922,13 @@ def apply_artifact(artifact):
validate_device_plane_foundation_network_publication_evidence(
payload_dir
)
if is_device_plane_b2_discovery_ingress_slice(
component,
entries,
):
validate_device_plane_b2_discovery_ingress_evidence(
payload_dir
)
if not root.is_dir():
if bootstrap_root:
root.mkdir(parents=True, exist_ok=True)
@@ -17830,6 +18310,18 @@ def apply_artifact(artifact):
):
die("Engine L2 closed-loop app generation was not recreated")
run_healthchecks(component, entries, services)
if is_device_plane_b2_discovery_ingress_slice(
component,
entries,
):
if device_plane_runtime_before is None:
die(
"Device Plane B2 ingress predecessor runtime "
"inventory is missing"
)
validate_device_plane_b2_discovery_ingress_runtime(
device_plane_runtime_before
)
applied_path = move_artifact(artifact, APPLIED_DIR)
append_jsonl(STATE_FILE, {