Files
NODEDC_MISSION_CORE/tests/test_xgrids_acquisition_lifecycle.py
T

32141 lines
1.2 MiB
Plaintext

from __future__ import annotations
import asyncio
import fcntl
import hashlib
import json
import logging
import os
import subprocess
import threading
import time
from collections.abc import AsyncIterator, Callable, Iterator, Mapping
from contextlib import asynccontextmanager, contextmanager
from dataclasses import dataclass, replace
from datetime import UTC, datetime, timedelta
from itertools import count
from pathlib import Path
from types import MethodType, SimpleNamespace
from typing import Any
import pytest
from missioncore_plugin_sdk.v0alpha2 import RuntimeActionInvocation
from pydantic import SecretStr, ValidationError
import k1link.device_plugins.xgrids_k1.facade as facade_module
import k1link.host_network.wifi as host_wifi_module
from k1link.data_plane import ConsumerFrameContext, DecodedPointCloudView
from k1link.device_plugins.xgrids_k1.active_acquisition_recovery_checkpoint import (
ActiveAcquisitionRecoveryConnection,
ActiveAcquisitionRecoveryIdentity,
ActiveAcquisitionRecoveryTransportBinding,
active_acquisition_project_name_sha256,
)
from k1link.device_plugins.xgrids_k1.application_control_process_lease import (
ApplicationControlProcessLease,
)
from k1link.device_plugins.xgrids_k1.ble.runtime_arbiter import (
BleOperationHardTimeout,
BleOperationProgress,
BleRuntimeBusy,
bind_ble_runtime_owner_loop,
run_ble_operation,
wait_for_ble_runtime_idle,
)
from k1link.device_plugins.xgrids_k1.connection_supervisor import (
DEFAULT_TRANSPORT_OBSERVATION_TTL_SECONDS,
EndpointTarget,
HostPathProbeResult,
VerifiedControlEvidence,
)
from k1link.device_plugins.xgrids_k1.device_identity_pin_store import (
DeviceIdentityPinStoreCorrupt,
)
from k1link.device_plugins.xgrids_k1.facade import (
ACTION_PHYSICAL_COMMAND_REOPEN_RETIRED_RECONCILIATION,
ACTION_PHYSICAL_COMMAND_RETIRE_UNAVAILABLE,
DEFAULT_LIVE_STREAMS,
XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
AbortAcquisitionRequest,
BleScanRequest,
CameraPreviewSelectRequest,
CompatibilityAttestationRequest,
ConfiguredEndpointProbeRequest,
ConnectionVerifyRequest,
ConnectRequest,
DesiredConnectionModeRequest,
EnterApplicationWorkspaceRequest,
ForceFinishAcquisitionRequest,
OpenApplicationControlSessionRequest,
OperatorPresenceRequest,
PrepareAcquisitionRequest,
PrepareConnectionReconfigurationRequest,
ReopenRetiredPhysicalCommandReconciliationRequest,
RetireUnavailablePhysicalCommandRequest,
ShadowApplicationControlArmRequest,
StartAcquisitionRequest,
StopAcquisitionRequest,
XgridsK1CompatibilityService,
XgridsK1PluginFacade,
)
from k1link.device_plugins.xgrids_k1.network_mutation_ledger import (
NetworkConnectionMode,
NetworkMutationRecord,
NetworkStatusEvidence,
PreviousConnectionEvidence,
)
from k1link.device_plugins.xgrids_k1.network_provisioning_idempotency_journal import (
NetworkProvisioningIdempotencyConflict,
derive_request_binding_sha256,
)
from k1link.device_plugins.xgrids_k1.physical_command_coordinator import (
LedgerPhysicalCommandCoordinator,
PhysicalCommandIntentContext,
PhysicalCommandRuntimeBinding,
)
from k1link.device_plugins.xgrids_k1.physical_command_ledger import (
PHYSICAL_COMMAND_APPLICATION_SUCCESS_CODE,
PhysicalCommandApplicationResponse,
PhysicalCommandBlocked,
PhysicalCommandConnectionBinding,
PhysicalCommandIdentity,
PhysicalCommandLedgerSnapshot,
PhysicalCommandStatusEvidence,
PhysicalCommandTransitionError,
)
from k1link.device_plugins.xgrids_k1.protocol import application_session as session_module
from k1link.device_plugins.xgrids_k1.protocol.application_acceptance import (
ApplicationAcceptanceError,
)
from k1link.device_plugins.xgrids_k1.protocol.application_bootstrap import (
ApplicationControlAuthority,
LiveDeviceControlBinding,
)
from k1link.device_plugins.xgrids_k1.protocol.application_mqtt import (
ApplicationMqttDeviceStatusEvidence,
ApplicationMqttPublishEvidence,
ApplicationMqttResponseEvidence,
ApplicationMqttTransportError,
)
from k1link.device_plugins.xgrids_k1.protocol.application_publish import (
OneShotPublishEnvelope,
)
from k1link.device_plugins.xgrids_k1.protocol.application_session import (
ApplicationConnectionBinding,
ApplicationConnectionBindingLost,
InteractiveApplicationControlSession,
)
from k1link.device_plugins.xgrids_k1.protocol.modeling_control import (
MODELING_STATE_BASE,
)
from k1link.device_plugins.xgrids_k1.semantic_topology_store import (
SemanticTopologyStoreCorrupt,
)
from k1link.device_plugins.xgrids_k1.viewer.messages import StreamMessage
from k1link.host_network import HostWifiAssociationIdentityResult
from k1link.viewer.metrics import BridgeMetrics
from k1link.web.device_lifecycle import OperationJournal
from k1link.web.plugin_runtime import PluginExecutionError
ATTESTATION = CompatibilityAttestationRequest(
firmware_version="3.0.2",
topology="direct-lan",
verification="live-device-info",
)
QUICK_CONNECT_ATTESTATION = CompatibilityAttestationRequest(
firmware_version="3.0.2",
topology="device-ap",
verification="live-device-info",
)
DIRECT_CONNECT_ATTESTATION = CompatibilityAttestationRequest(
firmware_version="3.0.2",
topology="controller-hotspot",
verification="live-device-info",
)
PRIMARY_TEST_CREDENTIAL = "x" * 24
SECONDARY_TEST_CREDENTIAL = "y" * 24
PROJECT_NAME = "K1 lifecycle test"
PRIVATE_APPLICATION_AUTHORITY = "11111111-2222-3333-4444-555555555555"
DURABLE_K1_UUID = "F89438FA-55ED-85AD-EED7-734AC84746D8"
_CONNECT_INTENT_SEQUENCE = count(1)
_LIFECYCLE_INTENT_SEQUENCE = count(1)
_SYNTHETIC_SCAN_CAPTURES: dict[str, facade_module.CapturedDiscoveredDevice] = {}
@pytest.fixture(autouse=True)
def _synthetic_exact_scan_handoff(monkeypatch: pytest.MonkeyPatch) -> Iterator[None]:
"""Give facade-only lifecycle fixtures an exact selected scan object.
Scanner ownership/object handoff itself is covered in ``test_ble_scanner``.
These service tests seed the facade's scan projection directly, so mirror
that synthetic scan with one object-bound capture instead of weakening the
production admission rule to accept a UUID without a CoreBluetooth object.
"""
_SYNTHETIC_SCAN_CAPTURES.clear()
monkeypatch.setattr(
facade_module,
"_capture_network_intent_device",
lambda device_id: _SYNTHETIC_SCAN_CAPTURES.get(device_id),
)
monkeypatch.setattr(
facade_module,
"pin_connected_device_handle",
lambda *_args, **_kwargs: None,
)
yield
_SYNTHETIC_SCAN_CAPTURES.clear()
def _connect_request(**values: Any) -> ConnectRequest:
"""Give every physical network test an explicit, unique durable intent."""
values.setdefault(
"idempotency_key",
f"test-network-provision-{next(_CONNECT_INTENT_SEQUENCE)}",
)
values.setdefault("expected_mode_revision", 0)
values.setdefault("expected_discovery_generation", 0)
return ConnectRequest(**values)
def _select_connection_mode(
service: XgridsK1CompatibilityService,
connection_mode: str,
) -> int:
"""Select a process-local draft exactly as the product dropdown does."""
state = service.select_connection_mode(
DesiredConnectionModeRequest(
connection_mode=connection_mode, # type: ignore[arg-type]
expected_revision=service.state()["desired_connection_mode_revision"],
)
)
return int(state["desired_connection_mode_revision"])
def _lifecycle_intent_key(action: str) -> str:
return f"test-{action}-{next(_LIFECYCLE_INTENT_SEQUENCE)}"
def _prepare_request(**values: Any) -> PrepareAcquisitionRequest:
values.setdefault("idempotency_key", _lifecycle_intent_key("acquisition-prepare"))
values.setdefault("expected_control_session_generation", 1)
values.setdefault("expected_control_state_revision", 1)
return PrepareAcquisitionRequest(**values)
def _start_request(**values: Any) -> StartAcquisitionRequest:
values.setdefault("idempotency_key", _lifecycle_intent_key("acquisition-start"))
values.setdefault("expected_control_session_generation", 1)
values.setdefault("expected_control_state_revision", 2)
return StartAcquisitionRequest(**values)
def _stop_request(**values: Any) -> StopAcquisitionRequest:
values.setdefault("idempotency_key", _lifecycle_intent_key("acquisition-stop"))
values.setdefault("expected_control_session_generation", 1)
values.setdefault("expected_control_state_revision", 3)
return StopAcquisitionRequest(**values)
def _abort_request(**values: Any) -> AbortAcquisitionRequest:
values.setdefault("idempotency_key", _lifecycle_intent_key("acquisition-abort"))
values.setdefault("expected_control_session_generation", 1)
values.setdefault("expected_control_state_revision", 2)
return AbortAcquisitionRequest(**values)
def _force_finish_request(**values: Any) -> ForceFinishAcquisitionRequest:
values.setdefault(
"idempotency_key",
_lifecycle_intent_key("acquisition-force-finish-local"),
)
values.setdefault("operator_confirmed", True)
return ForceFinishAcquisitionRequest(**values)
def _dispatch_test_network_write(
on_write_dispatch: Callable[[dict[str, Any], str], None] | None,
) -> None:
"""Cross the same durable dispatch boundary as the production BLE helper."""
assert on_write_dispatch is not None
on_write_dispatch(
{
"mode": "WIFI_AP",
"ipv4": "192.168.56.1",
"status_code": 1,
"reserved": 0,
},
"with_response",
)
async def _reachable_control_endpoint(
target: str,
*_: object,
endpoint_probe: Callable[[str], object] | None = None,
**__: object,
) -> object:
return endpoint_probe(target) if endpoint_probe is not None else True
async def _unreachable_control_endpoint(
target: str,
*_: object,
endpoint_probe: Callable[[str], object] | None = None,
**__: object,
) -> object:
return endpoint_probe(target) if endpoint_probe is not None else False
def _direct_host_path(target_ipv4: str, **_: object) -> HostPathProbeResult:
source_ipv4 = (
"10.255.254.2"
if target_ipv4.startswith("10.")
else "192.168.56.2"
if target_ipv4.startswith("192.168.56.")
else "192.168.1.2"
)
return HostPathProbeResult(
available=True,
fingerprint=f"test-route:{target_ipv4}",
interface="test0",
source_ipv4=source_ipv4,
route_class="direct",
kernel_route_fingerprint=f"test-route:{target_ipv4}",
)
def _association_bound_direct_host_path(target_ipv4: str) -> HostPathProbeResult:
raw = _direct_host_path(target_ipv4)
assert raw.fingerprint is not None
return HostPathProbeResult(
available=True,
fingerprint=facade_module.bind_route_fingerprint_to_wifi_association(
raw.fingerprint,
DeterministicContendedAssociationProbe.proven_observation(),
),
interface=raw.interface,
source_ipv4=raw.source_ipv4,
route_class=raw.route_class,
kernel_route_fingerprint=raw.fingerprint,
)
def _tunnel_host_path(target_ipv4: str) -> HostPathProbeResult:
return HostPathProbeResult(
available=True,
fingerprint=f"test-tunnel:{target_ipv4}",
interface="utun-test",
source_ipv4="100.64.0.2",
route_class="tunnel",
)
@pytest.mark.parametrize(
("interface", "destination", "expected", "reason_code"),
[
("en0", "192.168.68.0", "direct", None),
("bridge100", "192.168.68.0", "direct", None),
("utun8", "192.168.68.0", "tunnel", "host-route-tunnel"),
("tun0", "192.168.68.0", "tunnel", "host-route-tunnel"),
("tap2", "192.168.68.0", "tunnel", "host-route-tunnel"),
("wg0", "192.168.68.0", "tunnel", "host-route-tunnel"),
("en0", "default", "default", "host-route-default"),
(
"vendor-vpn0",
"192.168.68.0",
"unknown",
"host-route-interface-unreviewed",
),
(None, "192.168.68.0", "unknown", "host-route-unclassified"),
],
)
def test_host_route_classifier_is_fail_closed_for_virtual_and_unknown_interfaces(
interface: str | None,
destination: str,
expected: str,
reason_code: str | None,
) -> None:
assert facade_module._classify_host_route(interface, destination) == ( # noqa: SLF001
expected,
reason_code,
)
class FakeHostWifiAssociationProbe:
def __init__(self, *continuity_tokens: str) -> None:
self._continuity_tokens = continuity_tokens or ("a" * 64,)
self.interfaces: list[str | None] = []
self.timeout_seconds: list[float] = []
def observe(
self,
interface_name: str | None,
*,
timeout_seconds: float = 30.0,
) -> HostWifiAssociationIdentityResult:
assert timeout_seconds > 0
self.timeout_seconds.append(timeout_seconds)
token_index = min(len(self.interfaces), len(self._continuity_tokens) - 1)
self.interfaces.append(interface_name)
return {
"schema_version": 1,
"adapter": "test-host-association",
"wifi_interface": True,
"association_state": "associated",
"evidence_quality": "bssid-only",
"continuity_proven": True,
"continuity_token": self._continuity_tokens[token_index],
"reason_code": None,
}
class DeterministicContendedAssociationProbe:
"""Real probe harness with fake lock/helper clocks and no wall-clock sleep."""
def __init__(
self,
*,
lock_wait_seconds: float,
helper_required_seconds: float,
on_first_lock_acquired: Callable[[], None] | None = None,
) -> None:
self.monotonic = 100.0
self.wall = 1_000.0
self.lock_wait_seconds = lock_wait_seconds
self.helper_required_seconds = helper_required_seconds
self.on_first_lock_acquired = on_first_lock_acquired
self.lock_timeouts: list[float] = []
self.helper_timeouts: list[float] = []
self._lock_acquisitions = 0
self._locked = False
def advance(self, seconds: float) -> None:
self.monotonic += seconds
self.wall += seconds
def acquire(self, *, timeout: float) -> bool:
self.lock_timeouts.append(timeout)
wait = self.lock_wait_seconds if self._lock_acquisitions == 0 else 0.0
self._lock_acquisitions += 1
if wait > timeout:
self.advance(timeout)
return False
self.advance(wait)
self._locked = True
if self._lock_acquisitions == 1 and self.on_first_lock_acquired is not None:
self.on_first_lock_acquired()
return True
def release(self) -> None:
assert self._locked is True
self._locked = False
def runner(
self,
argv: list[str],
**kwargs: object,
) -> subprocess.CompletedProcess[bytes]:
timeout = kwargs.get("timeout")
assert isinstance(timeout, (int, float)) and not isinstance(timeout, bool)
timeout_seconds = float(timeout)
self.helper_timeouts.append(timeout_seconds)
if self.helper_required_seconds > timeout_seconds:
self.advance(timeout_seconds)
raise subprocess.TimeoutExpired(argv, timeout_seconds)
self.advance(self.helper_required_seconds)
return subprocess.CompletedProcess(
argv,
0,
stdout=(
b'{"ok":true,"adapter":"CoreWLAN","wifi_interface":true,'
b'"association_identity":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
b'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","association_evidence":"bssid-only"}'
),
stderr=b"",
)
def build(
self,
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> host_wifi_module.HostWifiAssociationIdentityProbe:
helper_path = tmp_path / "deterministic-association-helper.swift"
helper_path.write_text("// deterministic test helper\n", encoding="utf-8")
monkeypatch.setattr(
host_wifi_module,
"time",
SimpleNamespace(monotonic=lambda: self.monotonic),
)
monkeypatch.setattr(
host_wifi_module,
"sys",
SimpleNamespace(platform="darwin"),
)
probe = host_wifi_module.HostWifiAssociationIdentityProbe(
helper_path,
runner=self.runner,
continuity_key=b"c" * 32,
monotonic_clock=lambda: self.monotonic,
wall_clock=lambda: self.wall,
)
probe._lock = self # type: ignore[assignment] # noqa: SLF001
return probe
@staticmethod
def proven_observation() -> HostWifiAssociationIdentityResult:
return {
"schema_version": 1,
"adapter": "CoreWLAN",
"wifi_interface": True,
"association_state": "associated",
"evidence_quality": "bssid-only",
"continuity_proven": True,
"continuity_token": "a" * 64,
"reason_code": None,
}
class FakeApplicationAuthorityLoader:
def __init__(self) -> None:
self.calls = 0
def load(self) -> ApplicationControlAuthority:
self.calls += 1
return ApplicationControlAuthority(openapi_key=PRIVATE_APPLICATION_AUTHORITY)
class FakeVisualizationRuntime:
def __init__(self) -> None:
self.phase = "idle"
self.source_mode = "idle"
self.source_ready = False
self.producer_generation = 0
self.pcl_frames = 0
self.start_calls: list[tuple[str, Path, float | None, str]] = []
self.stop_calls = 0
self.stop_error: Exception | None = None
self.recover_connection: Callable[[int], str] | None = None
self.recovery_requests: list[tuple[str, int]] = []
self.recovery_request_pending = False
self.recovery_state = "inactive"
self.recovery_attempt = 0
def snapshot(self) -> dict[str, Any]:
return {
"phase": self.phase,
"message": "test runtime",
"source_mode": self.source_mode,
"source_ready": self.source_ready,
"producer_generation": self.producer_generation,
"foxglove_ws_url": None,
"foxglove_viewer_url": None,
"rerun_grpc_url": None,
"viewer_settings": {},
"metrics": {
"messages_received": self.pcl_frames,
"payload_bytes": 0,
"pcl_frames": self.pcl_frames,
"pose_frames": 0,
"points_published": 0,
"last_point_count": 0,
"decode_errors": 0,
"preview_dropped": 0,
"pcl_fps": 0.0,
"pose_fps": 0.0,
"mqtt_to_publish_ms": None,
"mqtt_to_publish_p50_ms": None,
"mqtt_to_publish_p95_ms": None,
"decode_publish_ms": None,
"trajectory_poses": 0,
},
"connection_recovery": {
"state": self.recovery_state,
"attempt": self.recovery_attempt,
"reason_code": None,
"started_at_utc": None,
"elapsed_ms": None,
"recovered_at_utc": None,
"automatic_command_retry": False,
"device_write_performed": False,
"network_mutation_performed": False,
},
}
def start_live(
self,
host: str,
out_dir: Path,
*,
duration_seconds: float | None,
project_name: str,
recover_connection: Callable[[int], str] | None = None,
) -> None:
self.producer_generation += 1
self.start_calls.append((host, out_dir, duration_seconds, project_name))
self.phase = "starting_live"
self.source_mode = "live"
self.recover_connection = recover_connection
def mark_ready(self) -> None:
self.phase = "live"
self.source_ready = True
def request_connection_recovery(
self,
reason_code: str,
*,
expected_generation: int,
) -> bool:
if (
expected_generation != self.producer_generation
or self.recover_connection is None
or self.source_mode != "live"
or self.phase not in {"live", "reconnecting"}
):
return False
if self.phase == "reconnecting":
return True
self.phase = "reconnecting"
self.source_ready = False
self.recovery_state = "reconnecting"
self.recovery_requests.append((reason_code, expected_generation))
self.recovery_request_pending = True
return True
def stop(self) -> None:
self.stop_calls += 1
self.recovery_request_pending = False
if self.stop_error is not None:
raise self.stop_error
self.phase = "idle"
self.source_mode = "idle"
self.source_ready = False
self.recovery_state = "inactive"
self.recovery_attempt = 0
def close(self) -> None:
self.stop()
class FakeInteractiveControlSession:
def __init__(self, *, initial_state: str = "workspace-ready") -> None:
self.state = initial_state
self.session_generation = 1
self.state_revision = 1
self.verified_control: dict[str, object] | None = None
self.start_projects: list[str] = []
self.start_contexts: list[Any] = []
self.stop_calls = 0
self.stop_contexts: list[Any] = []
self.stop_dispatch_deadlines: list[Callable[[], bool] | None] = []
self.inspection_only = False
self.inspection_promotion_allowed = False
self.failure: dict[str, object] | None = None
self.outcome_unknown = False
self.transport_publish_attempts = 0
def snapshot(self) -> dict[str, object]:
return {
"state": self.state,
"session_generation": self.session_generation,
"state_revision": self.state_revision,
"inspection_only": self.inspection_only,
"inspection_promotion_allowed": self.inspection_promotion_allowed,
"can_open": self.state in {"idle", "completed", "closed", "failed"},
"can_enter_workspace": self.state == "connection-ready",
"can_prepare_project": self.state == "workspace-ready",
"can_start": self.state == "project-ready",
"can_stop": self.state == "scanning",
"can_confirm_standby": False,
"failure": self.failure,
"outcome_unknown": self.outcome_unknown,
"transport": {
"state": "failed" if self.state == "failed" else "ready",
"publish_attempts": self.transport_publish_attempts,
},
"verified_control": self.verified_control,
}
def open(
self,
*,
connection_binding: ApplicationConnectionBinding,
inspection_only: bool = False,
**_: object,
) -> dict[str, object]:
assert self.state == "idle"
self.verified_control = _verified_control_for_binding(connection_binding)
self.inspection_only = inspection_only
self.inspection_promotion_allowed = not inspection_only
self.state = "connection-ready"
self.state_revision += 1
return self.snapshot()
def adopt_reconciled_scanning(
self,
*,
reconciliation_id: str,
expected_session_generation: int,
expected_state_revision: int,
) -> dict[str, object]:
assert reconciliation_id
self._accept_checkpoint(
expected_session_generation=expected_session_generation,
expected_state_revision=expected_state_revision,
)
assert self.state == "connection-ready"
self.state = "scanning"
return self.snapshot()
def enter_workspace(
self,
*,
expected_session_generation: int | None = None,
expected_state_revision: int | None = None,
) -> dict[str, object]:
assert self.state == "connection-ready"
self._accept_checkpoint(
expected_session_generation=expected_session_generation,
expected_state_revision=expected_state_revision,
)
self.state = "workspace-ready"
return self.snapshot()
def _accept_checkpoint(
self,
*,
expected_session_generation: int | None,
expected_state_revision: int | None,
) -> None:
assert expected_session_generation == self.session_generation
assert expected_state_revision == self.state_revision
self.state_revision += 1
def validate_connection_binding(self) -> None:
return None
def validate_physical_reconciliation_binding(self) -> None:
return None
def open_project_prompt(
self,
*,
expected_session_generation: int | None = None,
expected_state_revision: int | None = None,
) -> dict[str, object]:
assert self.state == "workspace-ready"
self._accept_checkpoint(
expected_session_generation=expected_session_generation,
expected_state_revision=expected_state_revision,
)
self.state = "project-ready"
return self.snapshot()
def request_start(
self,
*,
project_name: str,
confirmation: object,
command_context: object,
preparation_checkpoint_observer: object | None = None,
expected_session_generation: int | None = None,
expected_state_revision: int | None = None,
) -> dict[str, object]:
del preparation_checkpoint_observer
assert confirmation is not None
assert command_context is not None
assert self.state == "project-ready"
self._accept_checkpoint(
expected_session_generation=expected_session_generation,
expected_state_revision=expected_state_revision,
)
self.start_projects.append(project_name)
self.start_contexts.append(command_context)
self.state = "scanning"
return self.snapshot()
def request_stop(
self,
*,
confirmation: object,
command_context: object,
dispatch_admission_deadline_reached: Callable[[], bool] | None = None,
expected_session_generation: int | None = None,
expected_state_revision: int | None = None,
) -> dict[str, object]:
assert confirmation is not None
assert command_context is not None
assert self.state == "scanning"
self._accept_checkpoint(
expected_session_generation=expected_session_generation,
expected_state_revision=expected_state_revision,
)
self.stop_calls += 1
self.stop_contexts.append(command_context)
self.stop_dispatch_deadlines.append(dispatch_admission_deadline_reached)
self.state = "awaiting-standby-confirmation"
return self.snapshot()
def close_prestart(
self,
*,
expected_session_generation: int | None = None,
expected_state_revision: int | None = None,
) -> dict[str, object]:
if expected_session_generation is not None or expected_state_revision is not None:
self._accept_checkpoint(
expected_session_generation=expected_session_generation,
expected_state_revision=expected_state_revision,
)
self.state = "closed"
self.verified_control = None
return self.snapshot()
def retire_for_network_change(self, **_: object) -> dict[str, object]:
if self.state not in {"idle", "completed", "closed", "failed"}:
raise RuntimeError("control session cannot be retired")
self.state = "idle"
self.verified_control = None
return self.snapshot()
def close(self) -> None:
self.state = "closed"
self.verified_control = None
PHYSICAL_ACCEPTANCE = OperatorPresenceRequest(
operator_present=True,
owner_controlled_device=True,
lixelgo_closed=True,
battery_storage_confirmed=True,
expected_physical_state_confirmed=True,
)
def _exact_start_physical_proof(
*,
operation_id: str,
acquisition_id: str,
binding: ApplicationConnectionBinding,
resolved: bool,
) -> dict[str, object]:
session_state = "scanning" if resolved else "scan_starting"
return {
"status": "resolved" if resolved else "unresolved",
"reason_code": (None if resolved else "physical-command-reconciliation-required"),
"requires_reconciliation": not resolved,
"resolved_active_recovery_required": resolved,
"reconciled_physical_state": "active" if resolved else None,
"physical_active": resolved,
"automatic_replay_allowed": False,
"record": {
"revision": 7,
"operation_id": operation_id,
"acquisition_id": acquisition_id,
"action": "start",
"stage": "resolved" if resolved else "observing",
"resolution": "start-active-observed" if resolved else None,
"publish_call_returned": True,
"qos2_completed": True,
"packet_id": 14,
"application_response": {
"operation_id": operation_id,
"action": "start",
"success": True,
},
"baseline_status": {
"control_session_id": "fake-control-session",
"host_path_epoch": binding.host_path_epoch,
"producer_generation": 1,
"session_state": "ready",
"project_bound": False,
"init_ready": False,
"mqtt_retained": False,
},
"last_status": {
"session_state": session_state,
"project_bound": resolved,
"init_ready": resolved,
"mqtt_retained": False,
"system_error_code": None,
},
"connection": {
"intent_id": binding.intent_id,
"transport_ref": binding.transport_ref,
"connection_mode": binding.connection_mode,
"target_ipv4": binding.target_ipv4,
"target_port": binding.target_port,
"host_path_epoch": binding.host_path_epoch,
"control_session_id": "fake-control-session",
"producer_generation": 1,
},
"identity": {
"vendor_device_id_sha256": "a" * 64,
"device_serial_sha256": "b" * 64,
},
"compatibility_profile_id": XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
"reconciliations": [],
},
}
def test_control_session_transport_metadata_does_not_leak_into_confirmation() -> None:
request = OpenApplicationControlSessionRequest(
operator_present=True,
owner_controlled_device=True,
lixelgo_closed=True,
battery_storage_confirmed=True,
expected_physical_state_confirmed=True,
timezone_name="Europe/Moscow",
)
assert request.confirmation() == PHYSICAL_ACCEPTANCE.confirmation()
async def _synthetic_prestart_control_bootstrap(
service: XgridsK1CompatibilityService,
*,
parent_operation_id: str | None,
connection_mode: facade_module.ConnectionMode,
inspection_only: bool = False,
) -> None:
"""Keep network lifecycle tests independent from a live MQTT/Keychain."""
supervisor = service._connection_supervisor.snapshot() # noqa: SLF001
assert supervisor.intent is not None
assert supervisor.device_network.target is not None
assert supervisor.device_network.transport_ref is not None
operation, _ = service._operations.begin( # noqa: SLF001
facade_module.ACTION_CONNECTION_CONTROL_BOOTSTRAP,
device_id=service._device_id, # noqa: SLF001
device_session_id=service._device_session_id, # noqa: SLF001
deadline_seconds=1.0,
context={
"connection_mode": connection_mode,
"parent_operation_id": parent_operation_id,
"automatic_retry": False,
},
)
service._operations.transition( # noqa: SLF001
operation.operation_id,
"running",
stage_code="mqtt-device-info",
message_code="connection.control_bootstrap.running",
)
control = FakeInteractiveControlSession(initial_state="idle")
binding = ApplicationConnectionBinding(
intent_id=supervisor.intent.intent_id,
transport_ref=supervisor.device_network.transport_ref,
host_path_epoch=supervisor.host_path.epoch,
target_ipv4=supervisor.device_network.target.ipv4,
target_port=supervisor.device_network.target.port,
connection_mode=connection_mode,
)
control.open(
connection_binding=binding,
inspection_only=inspection_only,
)
control.verified_control = _verified_control_for_binding(
binding,
logical_device_id=str(
supervisor.intent.expected_device_id or service._device_id # noqa: SLF001
),
control_session_id=(
f"fake-control-{parent_operation_id}"
if parent_operation_id is not None
else "fake-control-session"
),
)
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
service._reconcile_connection_supervisor( # noqa: SLF001
control.snapshot(),
service.runtime.snapshot(),
)
if not service._connection_supervisor.snapshot().authority.control_allowed: # noqa: SLF001
failure = facade_module.ConnectionVerificationError(
"synthetic DeviceInfo authority was not admitted",
reason_code="control-bootstrap-device-identity-unverified",
)
service._operations.transition( # noqa: SLF001
operation.operation_id,
"failed",
stage_code="device-info-failed",
message_code="connection.control_bootstrap.failed",
error={
"category": "connection",
"code": failure.reason_code,
"retryable": True,
"safe_to_retry": True,
"side_effect_status": "none",
},
)
raise failure
service._operations.transition( # noqa: SLF001
operation.operation_id,
"succeeded",
stage_code="device-info-confirmed",
message_code="connection.control_bootstrap.completed",
result={
"connection_mode": connection_mode,
"control_verified": True,
"device_write_performed": False,
"automatic_retry": False,
},
)
def service_with_fake_runtime(
tmp_path: Path,
) -> tuple[XgridsK1CompatibilityService, FakeVisualizationRuntime]:
# Durable network/idempotency records are intentionally global in the real
# runtime. Each test needs its own private store while repeated service
# construction inside one test must still exercise restart semantics.
os.environ["MISSIONCORE_DATA_DIR"] = str(tmp_path / "private-data")
os.environ["MISSIONCORE_EVIDENCE_DIR"] = str(tmp_path / "private-evidence")
os.environ["MISSIONCORE_LEGACY_SESSIONS_DIR"] = str(tmp_path / "private-legacy-sessions")
service = XgridsK1CompatibilityService(
tmp_path,
host_wifi_association_probe=FakeHostWifiAssociationProbe(),
)
runtime = FakeVisualizationRuntime()
service.runtime = runtime # type: ignore[assignment]
# The broad legacy lifecycle fixture replaces both the real application
# session and typed physical coordinator with mapping-only fakes. It has no
# durable PREPARED callback from which checkpoint v2 can be constructed.
# Keep those older tests scoped to their original lifecycle concern; the
# typed checkpoint ordering/CAS seams have dedicated integration tests.
service._active_acquisition_checkpoint_matches_current = MethodType( # type: ignore[method-assign] # noqa: SLF001
lambda _service, **_kwargs: True,
service,
)
legacy_start_operation_id: list[str | None] = [None]
def checkpoint_start_operation_id(
_service: XgridsK1CompatibilityService,
*,
local_start_operation_id: str | None,
**_kwargs: object,
) -> str | None:
if local_start_operation_id is not None:
legacy_start_operation_id[0] = local_start_operation_id
return legacy_start_operation_id[0]
service._active_acquisition_checkpoint_start_operation_id = MethodType( # type: ignore[method-assign] # noqa: SLF001
checkpoint_start_operation_id,
service,
)
service._record_active_acquisition_checkpoint_gap = MethodType( # type: ignore[method-assign] # noqa: SLF001
lambda _service, _lineage, **_kwargs: True,
service,
)
service._confirm_active_acquisition_checkpoint_rebind = MethodType( # type: ignore[method-assign] # noqa: SLF001
lambda _service, *_args, **_kwargs: True,
service,
)
service._cease_active_acquisition_checkpoint_from_physical_head = MethodType( # type: ignore[method-assign] # noqa: SLF001
lambda _service, **_kwargs: True,
service,
)
service._bootstrap_prestart_control_ready_owned = MethodType( # type: ignore[method-assign] # noqa: SLF001
_synthetic_prestart_control_bootstrap,
service,
)
return service, runtime
def test_service_owns_one_wifi_association_probe_across_monitor_recreation(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
association_probe = FakeHostWifiAssociationProbe()
constructed: list[Path] = []
def probe_factory(helper_path: Path) -> FakeHostWifiAssociationProbe:
constructed.append(helper_path)
return association_probe
monkeypatch.setattr(
facade_module,
"HostWifiAssociationIdentityProbe",
probe_factory,
)
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
service = XgridsK1CompatibilityService(tmp_path)
_seed_supervised_connection(service, target_ipv4="192.168.1.20")
first = service._sample_host_path("192.168.1.20") # noqa: SLF001
service._connection_monitor = service._new_connection_monitor() # noqa: SLF001
second = asyncio.run( # noqa: SLF001
service._monitor_host_path(EndpointTarget("192.168.1.20"))
)
assert constructed == [tmp_path / "plugins" / "xgrids-k1" / "macos" / "associate_wifi.swift"]
assert association_probe.interfaces == ["test0", "test0"]
assert first.fingerprint == second.fingerprint
@pytest.mark.parametrize(
("raw_paths", "association_tokens"),
[
(
(
_direct_host_path("192.168.1.20"),
_direct_host_path("192.168.56.20"),
),
("a" * 64, "a" * 64, "a" * 64),
),
(
(
_direct_host_path("192.168.1.20"),
_direct_host_path("192.168.1.20"),
),
("a" * 64, "a" * 64, "b" * 64),
),
],
)
def test_sync_tcp_success_cannot_cross_route_or_wifi_association_change(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
raw_paths: tuple[HostPathProbeResult, HostPathProbeResult],
association_tokens: tuple[str, str, str],
) -> None:
association_probe = FakeHostWifiAssociationProbe(*association_tokens)
service = XgridsK1CompatibilityService(
tmp_path,
host_wifi_association_probe=association_probe,
)
service.runtime = FakeVisualizationRuntime() # type: ignore[assignment]
monkeypatch.setattr(facade_module, "_inspect_host_path", lambda _target: raw_paths[0])
initial_path = service._sample_host_path("192.168.1.20") # noqa: SLF001
_seed_supervised_connection(service, host_path=initial_path)
pending_paths = iter(raw_paths)
monkeypatch.setattr(
facade_module,
"_inspect_host_path",
lambda _target: next(pending_paths),
)
monkeypatch.setattr(
facade_module,
"_control_endpoint_reachable",
lambda _target: True,
)
observation = service._probe_control_endpoint("192.168.1.20") # noqa: SLF001
supervisor = service._connection_supervisor.snapshot() # noqa: SLF001
assert observation.reachable is False
assert observation.reason_code == "host-path-changed-during-tcp-probe"
assert supervisor.host_path.fingerprint == observation.path.fingerprint
assert supervisor.endpoint.tcp_state == "unreachable"
assert supervisor.authority.control_allowed is False
assert supervisor.lease.state != "reachable"
def _seed_supervised_connection(
service: XgridsK1CompatibilityService,
*,
target_ipv4: str = "192.168.1.20",
connection_mode: facade_module.ConnectionMode = "bridge",
transport_ref: str = "test-ble-transport",
logical_device_id: str = "known-k1",
host_path: HostPathProbeResult | None = None,
endpoint_reachable: bool = True,
endpoint_reason: str | None = None,
with_control: bool = True,
) -> ApplicationConnectionBinding:
"""Install one internally consistent test-only connection evidence chain.
Older lifecycle fixtures used ``_k1_ip`` as if an address implied a live
connection. The production supervisor now deliberately requires four
independent facts: the K1-reported topology, the current host route, TCP
reachability and DeviceInfo bound to that exact intent/route epoch. Tests
that exercise already-open plugin control must seed all four explicitly;
tests for the pre-DeviceInfo state pass ``with_control=False``.
"""
intent_id = f"test-intent-{connection_mode}-{transport_ref}-{target_ipv4}"
target = EndpointTarget(target_ipv4, facade_module.CONTROL_MQTT_PORT)
attestation = {
"bridge": ATTESTATION,
"quick-connect": QUICK_CONNECT_ATTESTATION,
"direct-connect": DIRECT_CONNECT_ATTESTATION,
}[connection_mode]
service._pin_or_match_device_identity( # noqa: SLF001
transport_ref=transport_ref,
logical_device_id=logical_device_id,
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
)
service._connection_supervisor.set_intent( # noqa: SLF001
intent_id=intent_id,
requested_mode=connection_mode,
expected_device_id=logical_device_id,
)
accepted = service._connection_supervisor.observe_device_network_applied( # noqa: SLF001
intent_id=intent_id,
transport_ref=transport_ref,
connection_mode=connection_mode,
target=target,
source="ble-read-only-status",
)
assert accepted is True
host_epoch = service._connection_supervisor.observe_host_path( # noqa: SLF001
host_path or _direct_host_path(target_ipv4)
)
endpoint_accepted = service._connection_supervisor.observe_endpoint( # noqa: SLF001
target=target,
intent_id=intent_id,
host_path_epoch=host_epoch,
reachable=endpoint_reachable,
reason_code=(
None if endpoint_reachable else endpoint_reason or "test-endpoint-unreachable"
),
)
assert endpoint_accepted is True
binding = ApplicationConnectionBinding(
intent_id=intent_id,
transport_ref=transport_ref,
host_path_epoch=host_epoch,
target_ipv4=target_ipv4,
target_port=facade_module.CONTROL_MQTT_PORT,
connection_mode=connection_mode,
)
if with_control:
assert endpoint_reachable is True
control_accepted = service._connection_supervisor.observe_control_evidence( # noqa: SLF001
VerifiedControlEvidence(
intent_id=intent_id,
transport_ref=transport_ref,
host_path_epoch=host_epoch,
target=target,
connection_mode=connection_mode,
logical_device_id=logical_device_id,
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
control_session_id=f"test-control-{transport_ref}",
)
)
assert control_accepted is True
with service._lock: # noqa: SLF001
service._selected_device_id = transport_ref # noqa: SLF001
service._connection_mode = connection_mode # noqa: SLF001
service._k1_ip = target_ipv4 # noqa: SLF001
service._device_id = logical_device_id # noqa: SLF001
service._device_session_id = f"test-session-{transport_ref}" # noqa: SLF001
service._device_session_opened_at = "2026-07-20T12:00:00Z" # noqa: SLF001
service._compatibility_attestation = attestation.model_dump(mode="json") # noqa: SLF001
service._connection_lease_generation = ( # noqa: SLF001
service._connection_supervisor.snapshot().lease.generation # noqa: SLF001
)
control = service._application_control_session # noqa: SLF001
if (
with_control
and isinstance(control, FakeInteractiveControlSession)
and control.verified_control is None
):
control.verified_control = _verified_control_for_binding(
binding,
logical_device_id=logical_device_id,
)
return binding
def _verified_control_for_binding(
binding: ApplicationConnectionBinding,
*,
logical_device_id: str = "known-k1",
control_session_id: str = "fake-control-session",
control_proof_revision: int = 1,
control_proof_source: str = "correlated-application-response",
control_proof_fresh: bool = True,
producer_generation: int = 1,
) -> dict[str, object]:
return {
"logical_device_id": logical_device_id,
"compatibility_profile_id": XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
"control_session_id": control_session_id,
"source": "mqtt-device-info",
"intent_id": binding.intent_id,
"transport_ref": binding.transport_ref,
"host_path_epoch": binding.host_path_epoch,
"target_ipv4": binding.target_ipv4,
"target_port": binding.target_port,
"connection_mode": binding.connection_mode,
"producer_generation": producer_generation,
"control_proof_revision": control_proof_revision,
"control_proof_source": control_proof_source,
"control_proof_fresh": control_proof_fresh,
}
def _seed_unresolved_physical_stop_for_retirement(
service: XgridsK1CompatibilityService,
binding: ApplicationConnectionBinding,
) -> RetireUnavailablePhysicalCommandRequest:
"""Persist one accepted STOP whose READY outcome was never observed."""
identity = PhysicalCommandIdentity(
vendor_device_id_sha256=hashlib.sha256(b"retirement-vendor").hexdigest(),
device_serial_sha256=hashlib.sha256(b"retirement-serial").hexdigest(),
)
connection = PhysicalCommandConnectionBinding(
intent_id=binding.intent_id,
transport_ref=binding.transport_ref,
connection_mode=binding.connection_mode,
target_ipv4=binding.target_ipv4,
target_port=binding.target_port,
host_path_epoch=binding.host_path_epoch,
control_session_id="retirement-old-control-session",
producer_generation=11,
)
def status(
session_state: str,
*,
observed_at_utc: str,
) -> PhysicalCommandStatusEvidence:
scanning = session_state == "scanning"
return PhysicalCommandStatusEvidence(
source="live-control-session",
vendor_device_id_sha256=identity.vendor_device_id_sha256,
device_serial_sha256=identity.device_serial_sha256,
control_session_id=connection.control_session_id,
host_path_epoch=connection.host_path_epoch,
producer_generation=connection.producer_generation,
session_state=session_state, # type: ignore[arg-type]
session_state_code=302 if scanning else 300,
project_bound=scanning,
project_id_sha256=("c" * 64 if scanning else None),
init_ready=scanning,
status_message_sha256=hashlib.sha256(
f"{session_state}:{observed_at_utc}".encode()
).hexdigest(),
mqtt_retained=False,
observed_at_utc=observed_at_utc,
)
ledger = service._physical_command_ledger # noqa: SLF001
start_operation_id = "physical-start-before-operator-retirement"
stop_operation_id = "physical-stop-before-operator-retirement"
acquisition_id = "acquisition-before-operator-retirement"
ledger.prepare(
operation_id=start_operation_id,
parent_operation_id=None,
acquisition_id=acquisition_id,
action="start",
identity=identity,
connection=connection,
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
payload_sha256="d" * 64,
baseline_status=status(
"ready",
observed_at_utc="2026-08-10T16:59:00.000Z",
),
)
ledger.mark_dispatching(start_operation_id)
ledger.mark_observing(
start_operation_id,
publish_call_returned=True,
packet_id=41,
)
ledger.mark_qos2_completed(start_operation_id, packet_id=41)
ledger.record_application_response(
start_operation_id,
PhysicalCommandApplicationResponse(
operation_id=start_operation_id,
action="start",
control_session_id=connection.control_session_id,
host_path_epoch=connection.host_path_epoch,
producer_generation=connection.producer_generation,
result_code=PHYSICAL_COMMAND_APPLICATION_SUCCESS_CODE,
success=True,
payload_sha256="e" * 64,
observed_at_utc="2026-08-10T16:59:01.000Z",
),
)
ledger.record_status_observation(
start_operation_id,
status("scanning", observed_at_utc="2026-08-10T16:59:02.000Z"),
)
ledger.resolve(start_operation_id, resolution="start-active-observed")
ledger.prepare(
operation_id=stop_operation_id,
parent_operation_id=start_operation_id,
acquisition_id=acquisition_id,
action="stop",
identity=identity,
connection=connection,
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
payload_sha256="f" * 64,
baseline_status=status(
"scanning",
observed_at_utc="2026-08-10T17:00:00.000Z",
),
)
ledger.mark_dispatching(stop_operation_id)
ledger.mark_observing(
stop_operation_id,
publish_call_returned=True,
packet_id=42,
)
ledger.mark_qos2_completed(stop_operation_id, packet_id=42)
ledger.record_application_response(
stop_operation_id,
PhysicalCommandApplicationResponse(
operation_id=stop_operation_id,
action="stop",
control_session_id=connection.control_session_id,
host_path_epoch=connection.host_path_epoch,
producer_generation=connection.producer_generation,
result_code=PHYSICAL_COMMAND_APPLICATION_SUCCESS_CODE,
success=True,
payload_sha256="1" * 64,
observed_at_utc="2026-08-10T17:00:01.000Z",
),
)
record = ledger.snapshot().record
assert record is not None and record.unresolved
return RetireUnavailablePhysicalCommandRequest(
retirement_id="operator-retirement-stable-request",
expected_operation_id=record.operation_id,
expected_revision=record.revision,
expected_transport_ref=record.connection.transport_ref,
operator_confirmed=True,
reason="device-permanently-unavailable-or-replaced",
)
@pytest.mark.parametrize(
"failure_mode",
["stale-visible-checkpoint", "cross-process-ledger-race"],
)
def test_physical_retirement_checkpoint_conflict_is_http_409_without_device_io(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
failure_mode: str,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
binding = _seed_supervised_connection(
service,
transport_ref=DURABLE_K1_UUID,
connection_mode="bridge",
)
current_request = _seed_unresolved_physical_stop_for_retirement(
service,
binding,
)
request = (
current_request.model_copy(
update={
"expected_operation_id": "physical-stop-different-current-checkpoint",
}
)
if failure_mode == "stale-visible-checkpoint"
else current_request
)
before = service.state()
before_record = service._physical_command_ledger.snapshot().record # noqa: SLF001
before_operations = service._operations.snapshot() # noqa: SLF001
io_calls: list[str] = []
ledger_calls: list[str] = []
async def forbidden_async_io(*_args: object, **_kwargs: object) -> object:
io_calls.append("ble-or-wifi")
raise AssertionError("retirement checkpoint conflict must not reach device I/O")
def forbidden_sync_io(*_args: object, **_kwargs: object) -> object:
io_calls.append("mqtt-tcp-monitor")
raise AssertionError("retirement checkpoint conflict must not probe the device")
def final_ledger_cas(*_args: object, **_kwargs: object) -> object:
ledger_calls.append("retire")
if failure_mode == "cross-process-ledger-race":
raise PhysicalCommandTransitionError(
"physical command retirement used a stale record checkpoint"
)
raise AssertionError("visible stale checkpoint must fail before the ledger CAS")
monkeypatch.setattr(facade_module, "read_wifi_status_once", forbidden_async_io)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_async_io)
monkeypatch.setattr(service, "_probe_control_endpoint", forbidden_sync_io)
monkeypatch.setattr(
service._physical_command_coordinator, # noqa: SLF001
"retire_unavailable_target",
final_ledger_cas,
)
adapter = XgridsK1PluginFacade(service)
with pytest.raises(PluginExecutionError) as raised:
asyncio.run(
adapter.invoke(
RuntimeActionInvocation(
invocation_id=f"retirement-{failure_mode}",
plugin_id=adapter.plugin_id,
action_id=ACTION_PHYSICAL_COMMAND_RETIRE_UNAVAILABLE,
requested_at=datetime.now(UTC),
parameters={
**request.model_dump(mode="json"),
"expected_snapshot_runtime_id": before["snapshot_runtime_id"],
},
)
)
)
assert raised.value.http_status_code == 409
assert raised.value.reason_code == "physical-command-retirement-stale-checkpoint"
assert ledger_calls == ([] if failure_mode == "stale-visible-checkpoint" else ["retire"])
assert service._physical_command_ledger.snapshot().record == before_record # noqa: SLF001
assert service._operations.snapshot() == before_operations # noqa: SLF001
assert service._application_control_process_lease_holders == set() # noqa: SLF001
assert runtime.start_calls == []
assert runtime.stop_calls == 0
assert io_calls == []
def test_operator_retirement_is_local_only_revokes_old_authority_and_keeps_mode_draft(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
_select_connection_mode(service, "quick-connect")
_set_scanned_devices(
service,
[
{
"device_id": "retired-k1",
"name": "Original K1",
"rssi": -40,
"address": None,
"connectable": True,
"likely_k1": True,
},
{
"device_id": "replacement-k1",
"name": "Replacement K1",
"rssi": -45,
"address": None,
"connectable": True,
"likely_k1": True,
},
],
)
binding = _seed_supervised_connection(
service,
transport_ref="RETIRED-K1",
connection_mode="bridge",
)
request = _seed_unresolved_physical_stop_for_retirement(service, binding)
with service._lock: # noqa: SLF001
# CoreBluetooth UUID aliases compare case-insensitively for fencing,
# while the durable retirement CAS keeps its original exact spelling.
service._selected_device_id = "retired-k1" # noqa: SLF001
_seed_terminal_network_attempt(service)
before = service.state()
before_operations = service._operations.snapshot() # noqa: SLF001
before_generation = service._ble_discovery_generation # noqa: SLF001
before_devices = list(service._devices) # noqa: SLF001
io_calls: list[str] = []
async def forbidden_io(*_args: object, **_kwargs: object) -> object:
io_calls.append("device-or-network-io")
raise AssertionError("operator retirement must be local-only")
monkeypatch.setattr(facade_module, "read_wifi_status_once", forbidden_io)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_io)
monkeypatch.setattr(
service,
"_probe_control_endpoint",
lambda *_args, **_kwargs: io_calls.append("tcp-probe"),
)
assert before["physical_command"]["operator_retirement"]["allowed"] is True
retirement_action = before["connection_policy"]["actions"]["retire-unavailable-physical-target"]
assert retirement_action == {
"allowed": True,
"reason_codes": [],
"target_source": "durable-physical-command",
"required_transport_ref": "RETIRED-K1",
"requires_live_gatt_validation": False,
"physical_command_allowed": False,
"physical_outcome": "unknown",
"device_write_performed": False,
"automatic_retry": False,
}
assert before["connection_policy"]["recommended_action"] == (
"retire-unavailable-physical-target"
)
assert before["connection_attempt"]["safe_next_action"] == (
"retire-unavailable-physical-target"
)
result = service.retire_unavailable_physical_command(request)
physical = result["physical_command"]
assert physical["record"]["resolution"] == "operator-retired-outcome-unknown"
assert physical["operator_retirement"]["physical_outcome"] == "unknown"
assert physical["operator_retirement"]["allowed"] is False
assert result["desired_connection_mode"] == "quick-connect"
assert result["selected_device_id"] is None
assert result["k1_ip"] is None
assert result["connection_lifecycle"]["active_binding"] is None
assert result["connection_policy"]["facts"]["retired_transport_refs"] == ["RETIRED-K1"]
assert result["connection_policy"]["facts"]["eligible_fresh_transport_refs"] == [
"replacement-k1"
]
assert (
result["connection_policy"]["actions"]["retire-unavailable-physical-target"]["allowed"]
is False
)
assert result["connection_policy"]["actions"]["scan-ble"]["allowed"] is True
assert result["connection_attempt"]["safe_next_action"] == ("scan-select-connect")
supervisor = service._connection_supervisor.snapshot() # noqa: SLF001
assert supervisor.intent is not None
assert supervisor.intent.intent_id == ("physical-retirement-operator-retirement-stable-request")
assert supervisor.intent.requested_mode == "quick-connect"
assert supervisor.authority.control_allowed is False
assert service._operations.snapshot() == before_operations # noqa: SLF001
assert service._ble_discovery_generation == before_generation # noqa: SLF001
assert service._devices == before_devices # noqa: SLF001
assert runtime.start_calls == []
assert runtime.stop_calls == 0
assert io_calls == []
def test_retired_exact_fresh_candidate_reopens_locally_for_explicit_verify_only(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
binding = _seed_supervised_connection(
service,
transport_ref=DURABLE_K1_UUID,
connection_mode="bridge",
)
retirement = _seed_unresolved_physical_stop_for_retirement(service, binding)
service.retire_unavailable_physical_command(retirement)
before_operations = service._operations.snapshot() # noqa: SLF001
before_runtime_starts = list(runtime.start_calls)
before_runtime_stops = runtime.stop_calls
# A row retained from before retirement is not fresh enough to reopen it.
_set_scanned_k1(service, device_id=DURABLE_K1_UUID.lower())
stale = service.state()["physical_command"]["operator_reconciliation_reopen"]
assert stale["allowed"] is False
assert "physical-command-reconciliation-reopen-target-not-observed" in stale["reason_codes"]
with service._lock: # noqa: SLF001
service._ble_discovery_generation += 1 # noqa: SLF001
_set_scanned_k1(service, device_id=DURABLE_K1_UUID.lower())
before = service.state()
projection = before["physical_command"]["operator_reconciliation_reopen"]
assert projection == {
"allowed": True,
"reason_codes": [],
"expected_revision": retirement.expected_revision + 1,
"expected_retirement_id": retirement.retirement_id,
"expected_transport_ref": DURABLE_K1_UUID.lower(),
"expected_discovery_generation": service._ble_discovery_generation, # noqa: SLF001
"expected_desired_mode": "bridge",
"expected_desired_mode_revision": 0,
"device_io_performed": False,
"automatic_retry": False,
}
io_calls: list[str] = []
async def forbidden_async_io(*_args: object, **_kwargs: object) -> object:
io_calls.append("ble-or-wifi")
raise AssertionError("reopen must remain local-only")
def forbidden_sync_io(*_args: object, **_kwargs: object) -> object:
io_calls.append("mqtt-tcp-monitor")
raise AssertionError("reopen must remain local-only")
monkeypatch.setattr(facade_module, "read_wifi_status_once", forbidden_async_io)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_async_io)
monkeypatch.setattr(service, "_probe_control_endpoint", forbidden_sync_io)
reopen_request = ReopenRetiredPhysicalCommandReconciliationRequest(
reopening_id="reopening-explicit-fresh-row",
expected_revision=projection["expected_revision"],
expected_retirement_id=projection["expected_retirement_id"],
expected_transport_ref=projection["expected_transport_ref"],
expected_discovery_generation=projection["expected_discovery_generation"],
expected_desired_mode=projection["expected_desired_mode"],
expected_desired_mode_revision=projection["expected_desired_mode_revision"],
operator_confirmed=True,
reason="device-returned-for-explicit-reconciliation",
)
result = service.reopen_retired_physical_command_reconciliation(reopen_request)
# A lost HTTP response is retried against the durable audit, not against
# the now-consumed projection. The retry must return usable state without
# appending another reopen or reacquiring BLE/network ownership.
retried = service.reopen_retired_physical_command_reconciliation(reopen_request)
physical = result["physical_command"]
assert physical["status"] == "unresolved"
assert physical["requires_reconciliation"] is True
assert physical["record"]["stage"] == "observing"
assert physical["record"]["resolution"] is None
assert physical["record"]["operator_retirements"][0]["retirement_id"] == (
retirement.retirement_id
)
assert (
physical["record"]["operator_reconciliation_reopens"][0]["reopening_id"]
== "reopening-explicit-fresh-row"
)
assert len(retried["physical_command"]["record"]["operator_reconciliation_reopens"]) == 1
assert (
retried["connection_policy"]["actions"]["observe-fresh-device-network"]["allowed"] is True
)
assert result["snapshot_runtime_id"] == before["snapshot_runtime_id"]
assert retried["snapshot_runtime_id"] == before["snapshot_runtime_id"]
assert result["snapshot_revision"] > before["snapshot_revision"]
assert (
service._ble_discovery_generation
== projection[ # noqa: SLF001
"expected_discovery_generation"
]
)
assert result["k1_lifecycle_process_lease"] == {
"held_by_current_service": False,
"holders": [],
"process_lease_quarantined": False,
"reason_code": None,
"restart_required": False,
}
observe_action = result["connection_policy"]["actions"]["observe-fresh-device-network"]
assert observe_action["allowed"] is True
assert observe_action["required_transport_ref"] == DURABLE_K1_UUID
assert observe_action["required_connection_mode"] == "bridge"
assert result["connection_policy"]["actions"]["provision-fresh-device"]["allowed"] is False
assert result["connection_policy"]["actions"]["start-acquisition"]["allowed"] is False
assert result["connection_policy"]["actions"]["stop-acquisition"]["allowed"] is False
assert result["connection_lifecycle"]["mode_selection"]["allowed"] is False
assert result["connection_policy"]["facts"]["retired_transport_refs"] == []
assert (
DURABLE_K1_UUID.lower()
in result["connection_policy"]["facts"]["eligible_fresh_transport_refs"]
)
assert service._operations.snapshot() == before_operations # noqa: SLF001
assert runtime.start_calls == before_runtime_starts
assert runtime.stop_calls == before_runtime_stops
assert io_calls == []
@pytest.mark.parametrize("observed_session_state", ["ready", "scanning"])
def test_casefolded_reopened_uuid_uses_actual_fresh_ref_and_verify_reconciles_state(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
observed_session_state: str,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
binding = _seed_supervised_connection(
service,
transport_ref=DURABLE_K1_UUID,
connection_mode="bridge",
)
retirement = _seed_unresolved_physical_stop_for_retirement(service, binding)
service.retire_unavailable_physical_command(retirement)
# Retirement records the durable UUID exactly as originally observed. A
# later CoreBluetooth scan may return the same UUID with different case.
_set_scanned_k1(service, device_id=DURABLE_K1_UUID.lower())
with service._lock: # noqa: SLF001
service._ble_discovery_generation += 1 # noqa: SLF001
_set_scanned_k1(service, device_id=DURABLE_K1_UUID.lower())
projection = service._physical_operator_reconciliation_reopen_projection() # noqa: SLF001
reopened = service.reopen_retired_physical_command_reconciliation(
ReopenRetiredPhysicalCommandReconciliationRequest(
reopening_id="reopening-casefolded-end-to-end",
expected_revision=projection["expected_revision"],
expected_retirement_id=projection["expected_retirement_id"],
expected_transport_ref=projection["expected_transport_ref"],
expected_discovery_generation=projection["expected_discovery_generation"],
expected_desired_mode=projection["expected_desired_mode"],
expected_desired_mode_revision=projection["expected_desired_mode_revision"],
operator_confirmed=True,
reason="device-returned-for-explicit-reconciliation",
)
)
observation = reopened["connection_policy"]["actions"]["observe-fresh-device-network"]
assert observation["allowed"] is True
assert observation["required_transport_ref"] == DURABLE_K1_UUID
actual_ref = DURABLE_K1_UUID.lower()
capture = _SYNTHETIC_SCAN_CAPTURES[actual_ref]
capture_calls: list[str] = []
status_reads: list[str] = []
forbidden_mutations: list[str] = []
def capture_actual(device_id: str) -> facade_module.CapturedDiscoveredDevice | None:
capture_calls.append(device_id)
return capture if device_id == actual_ref else None
async def read_status(
device_id: str,
*,
captured_device: facade_module.CapturedDiscoveredDevice | None,
on_gatt_validated: Callable[[facade_module.CapturedDiscoveredDevice], None],
**_: object,
) -> dict[str, Any]:
status_reads.append(device_id)
assert captured_device is capture
on_gatt_validated(capture)
return _wifi_status_read("10.255.254.77", device_id=device_id)
async def forbidden_provision(*_: object, **__: object) -> object:
forbidden_mutations.append("wifi")
raise AssertionError("explicit Verify must not provision Wi-Fi")
monkeypatch.setattr(facade_module, "capture_discovered_device", capture_actual)
monkeypatch.setattr(facade_module, "read_wifi_status_once", read_status)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_provision)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(
facade_module,
"_host_route_class",
lambda _target: "direct-or-routed",
)
monkeypatch.setattr(facade_module, "_control_endpoint_reachable", lambda _target: True)
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
coordinator = service._physical_command_coordinator # noqa: SLF001
async def bootstrap_ready_proof(
bound_service: XgridsK1CompatibilityService,
*,
parent_operation_id: str | None,
connection_mode: facade_module.ConnectionMode,
inspection_only: bool = False,
) -> None:
await _synthetic_prestart_control_bootstrap(
bound_service,
parent_operation_id=parent_operation_id,
connection_mode=connection_mode,
inspection_only=inspection_only,
)
verified = bound_service._application_control_session.snapshot().get( # noqa: SLF001
"verified_control"
)
assert isinstance(verified, dict)
coordinator.application_response(
ApplicationMqttResponseEvidence(
operation_key="bootstrap:casefold:DeviceInfoRequest",
response_topic="lixel/application/response/device_info",
payload_sha256="9" * 64,
modeling_action=None,
result_code=None,
success=None,
observed_at_utc="2026-08-10T12:00:00.000Z",
)
)
coordinator.bind_control_session(
PhysicalCommandRuntimeBinding(
vendor_device_id_sha256=hashlib.sha256(b"retirement-vendor").hexdigest(),
device_serial_sha256=hashlib.sha256(b"retirement-serial").hexdigest(),
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
intent_id=str(verified["intent_id"]),
transport_ref=str(verified["transport_ref"]),
connection_mode=verified["connection_mode"], # type: ignore[arg-type]
target_ipv4=str(verified["target_ipv4"]),
target_port=int(verified["target_port"]),
host_path_epoch=int(verified["host_path_epoch"]),
control_session_id=str(verified["control_session_id"]),
producer_generation=int(verified["producer_generation"]),
)
)
coordinator.device_status(
ApplicationMqttDeviceStatusEvidence(
vendor_device_id_sha256=hashlib.sha256(b"retirement-vendor").hexdigest(),
device_serial_sha256=hashlib.sha256(b"retirement-serial").hexdigest(),
session_state=observed_session_state,
session_state_code=(
MODELING_STATE_BASE + (300 if observed_session_state == "ready" else 302)
),
project_bound=observed_session_state == "scanning",
project_id_sha256=("5" * 64 if observed_session_state == "scanning" else None),
init_ready=observed_session_state == "scanning",
status_message_sha256="8" * 64,
mqtt_retained=False,
observed_at_utc="2026-08-10T12:00:01.000Z",
)
)
bound_service._acquire_application_control_process_lease() # noqa: SLF001
service._bootstrap_prestart_control_ready_owned = MethodType( # type: ignore[method-assign] # noqa: SLF001
bootstrap_ready_proof,
service,
)
result = asyncio.run(
service.verify_connection(
ConnectionVerifyRequest(
# The frontend follows the server policy, whose durable
# physical recovery target retains the original uppercase
# spelling. Backend lookup must resolve that to the current
# lowercase advert before any native BLE call.
device_id=observation["required_transport_ref"],
source="fresh-scan",
compatibility_attestation=ATTESTATION,
operation_id="op-00000000-0000-4000-8000-000000001240",
expected_discovery_generation=projection["expected_discovery_generation"],
)
)
)
assert capture_calls == [actual_ref]
assert status_reads == [actual_ref]
assert result["selected_device_id"] == actual_ref
assert result["physical_command"]["record"]["resolution"] == (
"physical-standby-observed"
if observed_session_state == "ready"
else "physical-active-observed"
)
assert (
result["physical_command"]["record"]["operator_retirements"][0]["retired_transport_ref"]
== DURABLE_K1_UUID
)
assert (
result["physical_command"]["record"]["operator_reconciliation_reopens"][0][
"reopened_transport_ref"
]
== actual_ref
)
assert forbidden_mutations == []
assert runtime.start_calls == []
assert runtime.stop_calls == 0
if observed_session_state == "scanning":
assert result["connection_policy"]["actions"]["provision-fresh-device"]["allowed"] is False
assert result["connection_policy"]["actions"]["start-acquisition"]["allowed"] is False
assert result["application_control_session"]["can_stop"] is True
assert result["connection_policy"]["actions"]["stop-acquisition"]["allowed"] is True, (
result["connection_policy"]["actions"]["stop-acquisition"]
)
assert result["acquisition"]["result"]["recovery_only"] is True
def _retired_fresh_reopen_request(
service: XgridsK1CompatibilityService,
*,
reopening_id: str,
connection_mode: facade_module.ConnectionMode = "bridge",
) -> ReopenRetiredPhysicalCommandReconciliationRequest:
if connection_mode != "bridge":
_select_connection_mode(service, connection_mode)
binding = _seed_supervised_connection(
service,
transport_ref=DURABLE_K1_UUID,
connection_mode=connection_mode,
)
retirement = _seed_unresolved_physical_stop_for_retirement(service, binding)
service.retire_unavailable_physical_command(retirement)
with service._lock: # noqa: SLF001
service._ble_discovery_generation += 1 # noqa: SLF001
_set_scanned_k1(service, device_id=DURABLE_K1_UUID.lower())
projection = service._physical_operator_reconciliation_reopen_projection() # noqa: SLF001
assert projection["allowed"] is True
return ReopenRetiredPhysicalCommandReconciliationRequest(
reopening_id=reopening_id,
expected_revision=projection["expected_revision"],
expected_retirement_id=projection["expected_retirement_id"],
expected_transport_ref=projection["expected_transport_ref"],
expected_discovery_generation=projection["expected_discovery_generation"],
expected_desired_mode=projection["expected_desired_mode"],
expected_desired_mode_revision=projection["expected_desired_mode_revision"],
operator_confirmed=True,
reason="device-returned-for-explicit-reconciliation",
)
def test_physical_reopen_final_checkpoint_conflict_is_http_409_without_device_io(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
request = _retired_fresh_reopen_request(
service,
reopening_id="reopening-cross-process-ledger-race",
)
before = service.state()
before_record = service._physical_command_ledger.snapshot().record # noqa: SLF001
before_operations = service._operations.snapshot() # noqa: SLF001
io_calls: list[str] = []
ledger_calls: list[str] = []
async def forbidden_async_io(*_args: object, **_kwargs: object) -> object:
io_calls.append("ble-or-wifi")
raise AssertionError("reopen checkpoint conflict must not reach device I/O")
def forbidden_sync_io(*_args: object, **_kwargs: object) -> object:
io_calls.append("mqtt-tcp-monitor")
raise AssertionError("reopen checkpoint conflict must not probe the device")
def conflicting_final_cas(*_args: object, **_kwargs: object) -> object:
ledger_calls.append("reopen")
raise PhysicalCommandTransitionError(
"physical command reconciliation reopen used a stale record revision"
)
monkeypatch.setattr(facade_module, "read_wifi_status_once", forbidden_async_io)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_async_io)
monkeypatch.setattr(service, "_probe_control_endpoint", forbidden_sync_io)
monkeypatch.setattr(
service._physical_command_coordinator, # noqa: SLF001
"reopen_retired_reconciliation",
conflicting_final_cas,
)
adapter = XgridsK1PluginFacade(service)
with pytest.raises(PluginExecutionError) as raised:
asyncio.run(
adapter.invoke(
RuntimeActionInvocation(
invocation_id="reopening-cross-process-ledger-race",
plugin_id=adapter.plugin_id,
action_id=(ACTION_PHYSICAL_COMMAND_REOPEN_RETIRED_RECONCILIATION),
requested_at=datetime.now(UTC),
parameters={
**request.model_dump(mode="json"),
"expected_snapshot_runtime_id": before["snapshot_runtime_id"],
},
)
)
)
assert raised.value.http_status_code == 409
assert raised.value.reason_code == ("physical-command-reconciliation-reopen-stale-checkpoint")
assert ledger_calls == ["reopen"]
assert service._physical_command_ledger.snapshot().record == before_record # noqa: SLF001
assert service._operations.snapshot() == before_operations # noqa: SLF001
assert service._application_control_process_lease_holders == set() # noqa: SLF001
assert runtime.start_calls == []
assert runtime.stop_calls == 0
assert io_calls == []
def test_reopen_projection_rejects_a_different_local_mode_draft_without_mutation(
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
request = _retired_fresh_reopen_request(
service,
reopening_id="reopening-mode-mismatch",
)
before_record = service._physical_command_ledger.snapshot().record # noqa: SLF001
before_operations = service._operations.snapshot() # noqa: SLF001
before_generation = service._ble_discovery_generation # noqa: SLF001
switched_revision = _select_connection_mode(service, "quick-connect")
projection = service._physical_operator_reconciliation_reopen_projection() # noqa: SLF001
assert switched_revision == 1
assert projection["allowed"] is False
assert projection["reason_codes"] == ["physical-command-reconciliation-reopen-mode-mismatch"]
with pytest.raises(facade_module.NetworkProvisioningConflict) as blocked:
service.reopen_retired_physical_command_reconciliation(request)
assert blocked.value.reason_code == ("physical-command-reconciliation-reopen-mode-mismatch")
assert service._physical_command_ledger.snapshot().record == before_record # noqa: SLF001
assert service._operations.snapshot() == before_operations # noqa: SLF001
assert service._ble_discovery_generation == before_generation # noqa: SLF001
assert runtime.start_calls == []
assert runtime.stop_calls == 0
def test_reopen_rejects_desired_mode_revision_aba_without_consuming_checkpoint(
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
stale_request = _retired_fresh_reopen_request(
service,
reopening_id="reopening-mode-revision-aba",
)
before_record = service._physical_command_ledger.snapshot().record # noqa: SLF001
before_operations = service._operations.snapshot() # noqa: SLF001
_select_connection_mode(service, "quick-connect")
current_revision = _select_connection_mode(service, "bridge")
projection = service._physical_operator_reconciliation_reopen_projection() # noqa: SLF001
assert current_revision == 2
assert projection["allowed"] is True
assert projection["expected_desired_mode"] == "bridge"
assert projection["expected_desired_mode_revision"] == 2
with pytest.raises(facade_module.NetworkProvisioningConflict) as stale:
service.reopen_retired_physical_command_reconciliation(stale_request)
assert stale.value.reason_code == ("physical-command-reconciliation-reopen-stale-checkpoint")
assert service._physical_command_ledger.snapshot().record == before_record # noqa: SLF001
assert service._operations.snapshot() == before_operations # noqa: SLF001
assert runtime.start_calls == []
assert runtime.stop_calls == 0
def test_reopen_freezes_mode_draft_until_physical_observation_terminalizes(
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
request = _retired_fresh_reopen_request(
service,
reopening_id="reopening-freezes-mode-draft",
)
reopened = service.reopen_retired_physical_command_reconciliation(request)
reopened_record = service._physical_command_ledger.snapshot().record # noqa: SLF001
assert reopened["physical_command"]["requires_reconciliation"] is True
assert reopened["connection_lifecycle"]["mode_selection"]["allowed"] is False
assert (
"connection-mode-selection-physical-state-unsafe"
in reopened["connection_lifecycle"]["mode_selection"]["reason_codes"]
)
with pytest.raises(facade_module.NetworkProvisioningConflict) as blocked:
_select_connection_mode(service, "quick-connect")
assert blocked.value.reason_code == ("connection-mode-selection-physical-state-unsafe")
assert service._physical_command_ledger.snapshot().record == reopened_record # noqa: SLF001
assert service.state()["desired_connection_mode"] == "bridge"
assert service.state()["desired_connection_mode_revision"] == 0
assert runtime.start_calls == []
assert runtime.stop_calls == 0
def test_restarted_peer_can_align_only_to_pending_reopen_mode_without_io(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
owner, _ = service_with_fake_runtime(tmp_path)
request = _retired_fresh_reopen_request(
owner,
reopening_id="reopening-quick-restart-mode-alignment",
connection_mode="quick-connect",
)
owner.reopen_retired_physical_command_reconciliation(request)
restarted, restarted_runtime = service_with_fake_runtime(tmp_path)
before_record = restarted._physical_command_ledger.snapshot().record # noqa: SLF001
device_edges: list[str] = []
monkeypatch.setattr(
facade_module,
"scan",
lambda *_args, **_kwargs: device_edges.append("scan"),
)
monkeypatch.setattr(
facade_module,
"provision_wifi_once",
lambda *_args, **_kwargs: device_edges.append("network-write"),
)
before = restarted.state()
assert before["desired_connection_mode"] == "bridge"
assert before["connection_lifecycle"]["mode_selection"]["allowed"] is True
aligned = restarted.select_connection_mode(
DesiredConnectionModeRequest(
connection_mode="quick-connect",
expected_revision=before["desired_connection_mode_revision"],
)
)
assert aligned["desired_connection_mode"] == "quick-connect"
assert aligned["desired_connection_mode_revision"] == 1
assert aligned["connection_lifecycle"]["mode_selection"]["allowed"] is False
assert restarted._physical_command_ledger.snapshot().record == before_record # noqa: SLF001
assert restarted_runtime.start_calls == []
assert restarted_runtime.stop_calls == 0
assert device_edges == []
def _install_real_retirement_ready_bootstrap(
service: XgridsK1CompatibilityService,
) -> None:
"""Feed exact fresh DeviceInfo/READY evidence to the real coordinator."""
coordinator = service._physical_command_coordinator # noqa: SLF001
async def bootstrap_ready_proof(
bound_service: XgridsK1CompatibilityService,
*,
parent_operation_id: str | None,
connection_mode: facade_module.ConnectionMode,
inspection_only: bool = False,
) -> None:
await _synthetic_prestart_control_bootstrap(
bound_service,
parent_operation_id=parent_operation_id,
connection_mode=connection_mode,
inspection_only=inspection_only,
)
verified = bound_service._application_control_session.snapshot().get( # noqa: SLF001
"verified_control"
)
assert isinstance(verified, dict)
vendor_hash = hashlib.sha256(b"retirement-vendor").hexdigest()
serial_hash = hashlib.sha256(b"retirement-serial").hexdigest()
coordinator.application_response(
ApplicationMqttResponseEvidence(
operation_key="bootstrap:retirement:DeviceInfoRequest",
response_topic="lixel/application/response/device_info",
payload_sha256="7" * 64,
modeling_action=None,
result_code=None,
success=None,
observed_at_utc="2026-08-10T12:10:00.000Z",
)
)
coordinator.bind_control_session(
PhysicalCommandRuntimeBinding(
vendor_device_id_sha256=vendor_hash,
device_serial_sha256=serial_hash,
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
intent_id=str(verified["intent_id"]),
transport_ref=str(verified["transport_ref"]),
connection_mode=verified["connection_mode"], # type: ignore[arg-type]
target_ipv4=str(verified["target_ipv4"]),
target_port=int(verified["target_port"]),
host_path_epoch=int(verified["host_path_epoch"]),
control_session_id=str(verified["control_session_id"]),
producer_generation=int(verified["producer_generation"]),
)
)
coordinator.device_status(
ApplicationMqttDeviceStatusEvidence(
vendor_device_id_sha256=vendor_hash,
device_serial_sha256=serial_hash,
session_state="ready",
session_state_code=MODELING_STATE_BASE + 300,
project_bound=False,
project_id_sha256=None,
init_ready=False,
status_message_sha256="6" * 64,
mqtt_retained=False,
observed_at_utc="2026-08-10T12:10:01.000Z",
)
)
bound_service._acquire_application_control_process_lease() # noqa: SLF001
service._bootstrap_prestart_control_ready_owned = MethodType( # type: ignore[method-assign] # noqa: SLF001
bootstrap_ready_proof,
service,
)
def test_reopened_verify_network_unavailable_stays_unresolved_and_can_retry_exactly(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
reopen_request = _retired_fresh_reopen_request(
service,
reopening_id="reopening-network-unavailable-retry",
)
reopened = service.reopen_retired_physical_command_reconciliation(reopen_request)
observation = reopened["connection_policy"]["actions"]["observe-fresh-device-network"]
durable_ref = str(observation["required_transport_ref"])
actual_ref = reopen_request.expected_transport_ref
capture = _SYNTHETIC_SCAN_CAPTURES[actual_ref]
observed_addresses: list[str | None] = [None]
status_reads: list[str] = []
forbidden_mutations: list[str] = []
monkeypatch.setattr(
facade_module,
"capture_discovered_device",
lambda device_id: capture if device_id == actual_ref else None,
)
async def read_status(
device_id: str,
*,
captured_device: facade_module.CapturedDiscoveredDevice | None,
on_gatt_validated: Callable[[facade_module.CapturedDiscoveredDevice], None],
**_: object,
) -> dict[str, Any]:
status_reads.append(device_id)
assert captured_device is capture
on_gatt_validated(capture)
return _wifi_status_read(observed_addresses[0], device_id=device_id)
async def forbidden_provision(*_: object, **__: object) -> object:
forbidden_mutations.append("wifi")
raise AssertionError("network-unavailable Verify must not provision")
monkeypatch.setattr(facade_module, "read_wifi_status_once", read_status)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_provision)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(
facade_module,
"_host_route_class",
lambda _target: "direct-or-routed",
)
monkeypatch.setattr(facade_module, "_control_endpoint_reachable", lambda _target: True)
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
with pytest.raises(facade_module.ConnectionVerificationError) as unavailable:
asyncio.run(
service.verify_connection(
ConnectionVerifyRequest(
device_id=durable_ref,
source="fresh-scan",
compatibility_attestation=ATTESTATION,
operation_id="op-00000000-0000-4000-8000-000000001241",
expected_discovery_generation=(reopen_request.expected_discovery_generation),
)
)
)
assert unavailable.value.reason_code == "connection-verify-address-unavailable"
failed = service.state()
assert failed["connection_verification"]["status"] == "unreachable"
assert failed["connection_verification"]["network_reachability"] == ("unreachable")
assert failed["connection_verification"]["reason_code"] == (
"connection-verify-address-unavailable"
)
assert failed["physical_command"]["status"] == "unresolved"
assert failed["physical_command"]["requires_reconciliation"] is True
assert failed["connection_policy"]["facts"]["retired_transport_refs"] == []
assert failed["physical_command"]["operator_retirement"]["allowed"] is True
assert failed["connection_policy"]["actions"]["provision-fresh-device"]["allowed"] is False
assert failed["connection_policy"]["actions"]["start-acquisition"]["allowed"] is False
assert failed["connection_policy"]["actions"]["stop-acquisition"]["allowed"] is False
# The disconnected selector was freely editable before this exact reopen.
# The admitted reopen now freezes that mode CAS until the immediately owned
# read-only observation terminalizes, so another tab cannot strand it.
assert failed["connection_lifecycle"]["mode_selection"]["allowed"] is False
assert (
"connection-mode-selection-physical-state-unsafe"
in failed["connection_lifecycle"]["mode_selection"]["reason_codes"]
)
assert service._application_control_process_lease_holders == set() # noqa: SLF001
# Restoring the old route does not replay anything. The operator can
# explicitly run the same server-bound observation against the still-fresh
# exact candidate and reconcile READY.
observed_addresses[0] = "10.255.254.77"
_install_real_retirement_ready_bootstrap(service)
recovered = asyncio.run(
service.verify_connection(
ConnectionVerifyRequest(
device_id=durable_ref,
source="fresh-scan",
compatibility_attestation=ATTESTATION,
operation_id="op-00000000-0000-4000-8000-000000001242",
expected_discovery_generation=(reopen_request.expected_discovery_generation),
)
)
)
assert status_reads == [actual_ref, actual_ref]
assert recovered["physical_command"]["record"]["resolution"] == ("physical-standby-observed")
assert forbidden_mutations == []
assert runtime.start_calls == []
assert runtime.stop_calls == 0
@pytest.mark.parametrize(
("blocker", "reason_code"),
[
("network", "network-provision-operation-active"),
("control", "control-session-not-admissible-for-network-change"),
("lifecycle", "k1-lifecycle-process-lease-control-owned"),
("ble", "ble-runtime-busy"),
(
"nonconnectable",
"physical-command-reconciliation-reopen-target-not-connectable",
),
],
)
def test_reopen_projection_blocks_live_owners_before_durable_or_device_action(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
blocker: str,
reason_code: str,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
request = _retired_fresh_reopen_request(
service,
reopening_id=f"reopening-blocked-{blocker}",
)
before = service._physical_command_ledger.snapshot().record # noqa: SLF001
assert before is not None
native = dict(facade_module.ble_runtime_snapshot())
if blocker == "network":
service._provisioning_active = True # noqa: SLF001
elif blocker == "control":
service._application_control_session = FakeInteractiveControlSession( # type: ignore[assignment] # noqa: SLF001
initial_state="workspace-ready"
)
elif blocker == "lifecycle":
service._application_control_process_lease_holders.add("control") # noqa: SLF001
elif blocker == "ble":
native["active_operation_kind"] = "scan"
monkeypatch.setattr(facade_module, "ble_runtime_snapshot", lambda: native)
elif blocker == "nonconnectable":
service._devices[0]["connectable"] = False # noqa: SLF001
else: # pragma: no cover - exhaustive test table
raise AssertionError(blocker)
projection = service._physical_operator_reconciliation_reopen_projection() # noqa: SLF001
assert projection["allowed"] is False
assert reason_code in projection["reason_codes"]
with pytest.raises(facade_module.NetworkProvisioningConflict) as blocked:
service.reopen_retired_physical_command_reconciliation(request)
assert blocked.value.reason_code == reason_code
assert service._physical_command_ledger.snapshot().record == before # noqa: SLF001
assert runtime.start_calls == []
assert runtime.stop_calls == 0
@pytest.mark.parametrize("safe_to_retry", [False, True])
def test_reopen_uses_the_same_failed_control_admission_as_fresh_verify(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
safe_to_retry: bool,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
request = _retired_fresh_reopen_request(
service,
reopening_id=f"reopening-failed-control-{safe_to_retry}",
)
before = service._physical_command_ledger.snapshot().record # noqa: SLF001
control = FakeInteractiveControlSession(initial_state="failed")
base_snapshot = control.snapshot
def failed_snapshot() -> dict[str, object]:
return {
**base_snapshot(),
"failure": {
"safe_to_retry": safe_to_retry,
"network_change_admissible": False,
},
}
monkeypatch.setattr(control, "snapshot", failed_snapshot)
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
projection = service._physical_operator_reconciliation_reopen_projection() # noqa: SLF001
if not safe_to_retry:
assert projection["allowed"] is False
assert "control-session-not-admissible-for-network-change" in projection["reason_codes"]
with pytest.raises(facade_module.NetworkProvisioningConflict) as blocked:
service.reopen_retired_physical_command_reconciliation(request)
assert blocked.value.reason_code == ("control-session-not-admissible-for-network-change")
assert service._physical_command_ledger.snapshot().record == before # noqa: SLF001
else:
assert projection["allowed"] is True
assert runtime.start_calls == []
assert runtime.stop_calls == 0
@pytest.mark.parametrize(
("blocker", "reason_code"),
[
("supervisor", "connection-supervisor-closed"),
("idempotency-unavailable", "network-provisioning-idempotency-unavailable"),
("idempotency-corrupt", "network-provisioning-idempotency-corrupt"),
("topology-corrupt", "semantic-topology-store-corrupt"),
("identity-corrupt", "device-identity-pin-store-corrupt"),
("network-ledger-corrupt", "network-mutation-ledger-corrupt"),
("foreign-reconciliation", "reconciliation-target-not-observed"),
],
)
def test_reopen_rejects_unchanged_post_reopen_verify_blockers_before_commit(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
blocker: str,
reason_code: str,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
request = _retired_fresh_reopen_request(
service,
reopening_id=f"reopening-environment-blocked-{blocker}",
)
before = service._physical_command_ledger.snapshot().record # noqa: SLF001
if blocker == "supervisor":
monkeypatch.setattr(
service._connection_supervisor, # noqa: SLF001
"snapshot",
lambda: SimpleNamespace(closed=True),
)
elif blocker == "idempotency-unavailable":
service._network_provisioning_idempotency_journal = None # noqa: SLF001
elif blocker == "idempotency-corrupt":
monkeypatch.setattr(
service,
"_network_provisioning_idempotency_public_snapshot",
lambda: {"status": "corrupt"},
)
elif blocker == "topology-corrupt":
monkeypatch.setattr(
service,
"_semantic_topology_public_snapshot",
lambda: {"status": "corrupt"},
)
elif blocker == "identity-corrupt":
monkeypatch.setattr(
service,
"_device_identity_pin_public_snapshot",
lambda: {"status": "corrupt"},
)
elif blocker == "network-ledger-corrupt":
monkeypatch.setattr(
service._network_mutation_ledger, # noqa: SLF001
"snapshot",
lambda: SimpleNamespace(status="corrupt", record=None),
)
elif blocker == "foreign-reconciliation":
monkeypatch.setattr(
service,
"_network_provisioning_idempotency_public_snapshot",
lambda: {
"status": "blocked",
"active_operation_id": "foreign-network-operation",
"active_action": facade_module.ACTION_NETWORK_PROVISION,
"active_stage": "unresolved",
},
)
monkeypatch.setattr(
service._network_mutation_ledger, # noqa: SLF001
"snapshot",
lambda: SimpleNamespace(
status="unresolved",
record=SimpleNamespace(
operation_id="foreign-network-operation",
stage="dispatching",
resolution=None,
transport_ref="foreign-transport",
intended_mode="bridge",
),
),
)
else: # pragma: no cover - exhaustive parameter table
raise AssertionError(blocker)
projection = service._physical_operator_reconciliation_reopen_projection() # noqa: SLF001
assert projection["allowed"] is False
assert reason_code in projection["reason_codes"]
with pytest.raises(facade_module.NetworkProvisioningConflict) as blocked:
service.reopen_retired_physical_command_reconciliation(request)
assert blocked.value.reason_code == reason_code
assert service._physical_command_ledger.snapshot().record == before # noqa: SLF001
assert runtime.start_calls == []
assert runtime.stop_calls == 0
@pytest.mark.parametrize(
("audit_shape", "reason_code"),
[
(
"different-unresolved-operation",
"network-provisioning-idempotency-operation-mismatch",
),
(
"unresolved-ledger-without-idempotency",
"network-provisioning-idempotency-operation-mismatch",
),
(
"active-idempotency-without-ledger",
"network-provisioning-idempotency-ledger-mismatch",
),
(
"same-operation-prepared-prepared",
"network-provisioning-idempotency-ledger-mismatch",
),
],
)
def test_reopen_rejects_unexecutable_network_audit_pairing_before_lease_or_io(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
audit_shape: str,
reason_code: str,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
request = _retired_fresh_reopen_request(
service,
reopening_id=f"reopening-audit-blocked-{audit_shape}",
)
operation_id = f"network-audit-{audit_shape}"
if audit_shape == "different-unresolved-operation":
_seed_unresolved_network_mutation(
service,
operation_id=operation_id,
idempotency_operation_id=f"{operation_id}-other",
transport_ref=request.expected_transport_ref,
)
elif audit_shape == "unresolved-ledger-without-idempotency":
prepared = _prepare_network_mutation_for_reopen(
service,
operation_id=operation_id,
transport_ref=request.expected_transport_ref,
intended_mode="bridge",
)
service._network_mutation_ledger.mark_dispatching( # noqa: SLF001
operation_id,
expected_revision=prepared.revision,
)
elif audit_shape == "active-idempotency-without-ledger":
_begin_network_idempotency_for_reopen(
service,
operation_id=operation_id,
mark_unresolved=True,
)
elif audit_shape == "same-operation-prepared-prepared":
_prepare_network_mutation_for_reopen(
service,
operation_id=operation_id,
transport_ref=request.expected_transport_ref,
intended_mode="bridge",
)
_begin_network_idempotency_for_reopen(
service,
operation_id=operation_id,
mark_unresolved=False,
)
else: # pragma: no cover - exhaustive parameter table
raise AssertionError(audit_shape)
physical_before = service._physical_command_ledger.snapshot().record # noqa: SLF001
network_before = service._network_mutation_ledger.snapshot() # noqa: SLF001
idempotency_before = ( # noqa: SLF001
service._require_network_provisioning_idempotency_journal().snapshot()
)
operations_before = service._operations.snapshot() # noqa: SLF001
lease_calls: list[str] = []
io_calls: list[str] = []
def forbidden_lease(*_args: object, **_kwargs: object) -> None:
lease_calls.append("lease")
raise AssertionError("rejected reopen must not acquire the lifecycle lease")
async def forbidden_async_io(*_args: object, **_kwargs: object) -> object:
io_calls.append("device-io")
raise AssertionError("rejected reopen must not perform device I/O")
monkeypatch.setattr(service, "_acquire_k1_lifecycle_process_lease", forbidden_lease)
monkeypatch.setattr(facade_module, "read_wifi_status_once", forbidden_async_io)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_async_io)
monkeypatch.setattr(
service,
"_probe_control_endpoint",
lambda *_args, **_kwargs: io_calls.append("endpoint-io"),
)
projection = service._physical_operator_reconciliation_reopen_projection() # noqa: SLF001
assert projection["allowed"] is False
assert reason_code in projection["reason_codes"]
with pytest.raises(facade_module.NetworkProvisioningConflict) as blocked:
service.reopen_retired_physical_command_reconciliation(request)
assert blocked.value.reason_code == reason_code
assert service._physical_command_ledger.snapshot().record == physical_before # noqa: SLF001
assert service._network_mutation_ledger.snapshot() == network_before # noqa: SLF001
assert ( # noqa: SLF001
service._require_network_provisioning_idempotency_journal().snapshot() == idempotency_before
)
assert service._operations.snapshot() == operations_before # noqa: SLF001
assert lease_calls == []
assert io_calls == []
assert runtime.start_calls == []
assert runtime.stop_calls == 0
def test_reopen_rejects_unresolved_network_mode_conflict_before_lease_or_io(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
request = _retired_fresh_reopen_request(
service,
reopening_id="reopening-network-mode-conflict",
)
_seed_unresolved_network_mutation(
service,
operation_id="network-mode-conflict",
transport_ref=request.expected_transport_ref.upper(),
intended_mode="quick-connect",
)
physical_before = service._physical_command_ledger.snapshot().record # noqa: SLF001
network_before = service._network_mutation_ledger.snapshot() # noqa: SLF001
idempotency_before = ( # noqa: SLF001
service._require_network_provisioning_idempotency_journal().snapshot()
)
lease_calls: list[str] = []
io_calls: list[str] = []
monkeypatch.setattr(
service,
"_acquire_k1_lifecycle_process_lease",
lambda *_args, **_kwargs: lease_calls.append("lease"),
)
monkeypatch.setattr(
facade_module,
"read_wifi_status_once",
lambda *_args, **_kwargs: io_calls.append("gatt-read"),
)
monkeypatch.setattr(
facade_module,
"provision_wifi_once",
lambda *_args, **_kwargs: io_calls.append("gatt-write"),
)
projection = service._physical_operator_reconciliation_reopen_projection() # noqa: SLF001
assert projection["allowed"] is False
assert "reconciliation-target-mode-mismatch" in projection["reason_codes"]
with pytest.raises(facade_module.NetworkProvisioningConflict) as blocked:
service.reopen_retired_physical_command_reconciliation(request)
assert blocked.value.reason_code == "reconciliation-target-mode-mismatch"
assert service._physical_command_ledger.snapshot().record == physical_before # noqa: SLF001
assert service._network_mutation_ledger.snapshot() == network_before # noqa: SLF001
assert ( # noqa: SLF001
service._require_network_provisioning_idempotency_journal().snapshot() == idempotency_before
)
assert lease_calls == []
assert io_calls == []
assert runtime.start_calls == []
assert runtime.stop_calls == 0
@pytest.mark.parametrize(
"audit_shape",
[
"prepared-without-idempotency",
"prepared-with-matching-unresolved-idempotency",
"resolved-not-dispatched-with-matching-unresolved-idempotency",
"resolved-target-observed-with-matching-unresolved-idempotency",
],
)
def test_reopen_admits_network_audit_shapes_verify_can_repair_exactly(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
audit_shape: str,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
request = _retired_fresh_reopen_request(
service,
reopening_id=f"reopening-repairable-{audit_shape}",
)
operation_id = f"network-repairable-{audit_shape}"
prepared = _prepare_network_mutation_for_reopen(
service,
operation_id=operation_id,
transport_ref=request.expected_transport_ref,
# PREPARED is deterministically closed as not-dispatched before Verify
# chooses the physical recovery mode, so this difference is repairable.
intended_mode=("quick-connect" if audit_shape.startswith("prepared-") else "bridge"),
)
if "matching-unresolved-idempotency" in audit_shape:
_begin_network_idempotency_for_reopen(
service,
operation_id=operation_id,
mark_unresolved=True,
)
if audit_shape.startswith("resolved-not-dispatched"):
service._network_mutation_ledger.resolve( # noqa: SLF001
operation_id,
expected_revision=prepared.revision,
resolution="not-dispatched",
)
elif audit_shape.startswith("resolved-target-observed"):
dispatching = service._network_mutation_ledger.mark_dispatching( # noqa: SLF001
operation_id,
expected_revision=prepared.revision,
)
service._network_mutation_ledger.resolve( # noqa: SLF001
operation_id,
expected_revision=dispatching.revision,
resolution="target-observed",
observation=NetworkStatusEvidence(
mode="WIFI_CLIENT",
ipv4="192.168.68.51",
status_code=1,
reserved=0,
),
)
network_before = service._network_mutation_ledger.snapshot() # noqa: SLF001
idempotency_before = ( # noqa: SLF001
service._require_network_provisioning_idempotency_journal().snapshot()
)
io_calls: list[str] = []
monkeypatch.setattr(
facade_module,
"read_wifi_status_once",
lambda *_args, **_kwargs: io_calls.append("gatt-read"),
)
monkeypatch.setattr(
facade_module,
"provision_wifi_once",
lambda *_args, **_kwargs: io_calls.append("gatt-write"),
)
projection = service._physical_operator_reconciliation_reopen_projection() # noqa: SLF001
assert projection["allowed"] is True, projection
reopened = service.reopen_retired_physical_command_reconciliation(request)
assert reopened["physical_command"]["requires_reconciliation"] is True
assert (
reopened["connection_policy"]["actions"]["observe-fresh-device-network"]["allowed"] is True
)
assert service._network_mutation_ledger.snapshot() == network_before # noqa: SLF001
assert ( # noqa: SLF001
service._require_network_provisioning_idempotency_journal().snapshot() == idempotency_before
)
assert io_calls == []
assert runtime.start_calls == []
assert runtime.stop_calls == 0
def test_fresh_observation_requires_network_and_physical_recovery_same_target(
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_devices(
service,
[
{"device_id": "physical-k1", "connectable": True},
{"device_id": "network-k1", "connectable": True},
],
)
_seed_unresolved_network_mutation(
service,
operation_id="network-other-fresh-target",
transport_ref="network-k1",
intended_mode="bridge",
)
policy = _project_connection_policy_for_test(
service,
physical_command=_resolved_active_physical_snapshot(
transport_ref="physical-k1",
connection_mode="bridge",
),
)
observation = policy["actions"]["observe-fresh-device-network"]
assert observation["allowed"] is False
assert "reconciliation-target-physical-recovery-mismatch" in observation["reason_codes"]
assert observation["required_transport_ref"] == "physical-k1"
def test_reopen_rejects_discovery_generation_drift_before_durable_commit(
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
request = _retired_fresh_reopen_request(
service,
reopening_id="reopening-stale-discovery-generation",
)
before = service._physical_command_ledger.snapshot().record # noqa: SLF001
with service._lock: # noqa: SLF001
service._ble_discovery_generation += 1 # noqa: SLF001
_set_scanned_k1(service, device_id=DURABLE_K1_UUID.lower())
with pytest.raises(facade_module.NetworkProvisioningConflict) as stale:
service.reopen_retired_physical_command_reconciliation(request)
assert stale.value.reason_code == ("physical-command-reconciliation-reopen-stale-checkpoint")
assert service._physical_command_ledger.snapshot().record == before # noqa: SLF001
assert service._application_control_process_lease_holders == set() # noqa: SLF001
assert runtime.start_calls == []
assert runtime.stop_calls == 0
def test_reopen_two_tab_lost_response_retry_uses_one_durable_audit(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
first, _ = service_with_fake_runtime(tmp_path)
request = _retired_fresh_reopen_request(
first,
reopening_id="reopening-two-tab-lost-response",
)
second, second_runtime = service_with_fake_runtime(tmp_path)
with second._lock: # noqa: SLF001
second._ble_discovery_generation = request.expected_discovery_generation # noqa: SLF001
_set_scanned_k1(second, device_id=request.expected_transport_ref)
committed = first.reopen_retired_physical_command_reconciliation(request)
monkeypatch.setattr(
second,
"_acquire_k1_lifecycle_process_lease",
lambda *_args, **_kwargs: (_ for _ in ()).throw(
AssertionError("durable lost-response retry must not reacquire the lease")
),
)
observed = second.reopen_retired_physical_command_reconciliation(request)
assert committed["physical_command"]["status"] == "unresolved"
reopens = observed["physical_command"]["record"]["operator_reconciliation_reopens"]
assert [item["reopening_id"] for item in reopens] == ["reopening-two-tab-lost-response"]
assert (
observed["connection_policy"]["actions"]["observe-fresh-device-network"]["allowed"] is True
)
assert second_runtime.start_calls == []
assert second_runtime.stop_calls == 0
def test_reopen_quick_restart_retry_is_durable_and_does_not_require_local_draft(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
owner, _ = service_with_fake_runtime(tmp_path)
request = _retired_fresh_reopen_request(
owner,
reopening_id="reopening-quick-restart-lost-response",
connection_mode="quick-connect",
)
owner.reopen_retired_physical_command_reconciliation(request)
restarted, restarted_runtime = service_with_fake_runtime(tmp_path)
assert restarted.state()["desired_connection_mode"] == "bridge"
monkeypatch.setattr(
restarted,
"_acquire_k1_lifecycle_process_lease",
lambda *_args, **_kwargs: (_ for _ in ()).throw(
AssertionError("durable reopen retry must not reacquire the lease")
),
)
observed = restarted.reopen_retired_physical_command_reconciliation(request)
after_release = restarted.state()
assert observed["desired_connection_mode"] == "bridge"
assert after_release["connection_lifecycle"]["mode_selection"]["allowed"] is True
assert [
item["reopening_id"]
for item in observed["physical_command"]["record"]["operator_reconciliation_reopens"]
] == ["reopening-quick-restart-lost-response"]
assert restarted_runtime.start_calls == []
assert restarted_runtime.stop_calls == 0
def test_reopen_cross_process_lifecycle_owner_blocks_before_ledger_commit(
tmp_path: Path,
) -> None:
owner, _ = service_with_fake_runtime(tmp_path)
request = _retired_fresh_reopen_request(
owner,
reopening_id="reopening-cross-process-owner",
)
actor, actor_runtime = service_with_fake_runtime(tmp_path)
with actor._lock: # noqa: SLF001
actor._ble_discovery_generation = request.expected_discovery_generation # noqa: SLF001
_set_scanned_k1(actor, device_id=request.expected_transport_ref)
assert (
actor._physical_operator_reconciliation_reopen_projection()[ # noqa: SLF001
"allowed"
]
is False
)
with actor._lock: # noqa: SLF001
actor._ble_discovery_generation += 1 # noqa: SLF001
_set_scanned_k1(actor, device_id=request.expected_transport_ref)
actor_projection = actor._physical_operator_reconciliation_reopen_projection() # noqa: SLF001
assert actor_projection["allowed"] is True
actor_request = ReopenRetiredPhysicalCommandReconciliationRequest(
reopening_id=request.reopening_id,
expected_revision=actor_projection["expected_revision"],
expected_retirement_id=actor_projection["expected_retirement_id"],
expected_transport_ref=actor_projection["expected_transport_ref"],
expected_discovery_generation=actor_projection["expected_discovery_generation"],
expected_desired_mode=actor_projection["expected_desired_mode"],
expected_desired_mode_revision=actor_projection["expected_desired_mode_revision"],
operator_confirmed=True,
reason=request.reason,
)
before = actor._physical_command_ledger.snapshot().record # noqa: SLF001
owner._acquire_k1_lifecycle_process_lease("control") # noqa: SLF001
try:
with pytest.raises(facade_module.ApplicationControlProcessLeaseUnavailable):
actor.reopen_retired_physical_command_reconciliation(actor_request)
finally:
owner._release_k1_lifecycle_process_lease("control") # noqa: SLF001
assert actor._physical_command_ledger.snapshot().record == before # noqa: SLF001
assert actor._application_control_process_lease_holders == set() # noqa: SLF001
assert actor_runtime.start_calls == []
assert actor_runtime.stop_calls == 0
def test_peer_requires_a_new_scan_after_observing_shared_physical_retirement(
tmp_path: Path,
) -> None:
owner, owner_runtime = service_with_fake_runtime(tmp_path)
binding = _seed_supervised_connection(
owner,
transport_ref=DURABLE_K1_UUID,
connection_mode="bridge",
)
retirement = _seed_unresolved_physical_stop_for_retirement(owner, binding)
peer, peer_runtime = service_with_fake_runtime(tmp_path)
with peer._lock: # noqa: SLF001
peer._ble_discovery_generation += 1 # noqa: SLF001
stale_generation = peer._ble_discovery_generation # noqa: SLF001
_set_scanned_k1(peer, device_id=DURABLE_K1_UUID.lower())
owner.retire_unavailable_physical_command(retirement)
retired_before = peer._physical_command_ledger.snapshot().record # noqa: SLF001
stale = peer._physical_operator_reconciliation_reopen_projection() # noqa: SLF001
assert stale["allowed"] is False
assert "physical-command-reconciliation-reopen-target-not-observed" in stale["reason_codes"]
assert ( # noqa: SLF001
peer._physical_retirement_reopen_generation_floors[retirement.retirement_id]
== stale_generation
)
assert peer._physical_command_ledger.snapshot().record == retired_before # noqa: SLF001
with peer._lock: # noqa: SLF001
peer._ble_discovery_generation += 1 # noqa: SLF001
_set_scanned_k1(peer, device_id=DURABLE_K1_UUID.lower())
fresh = peer._physical_operator_reconciliation_reopen_projection() # noqa: SLF001
assert fresh["allowed"] is True, fresh
reopened = peer.reopen_retired_physical_command_reconciliation(
ReopenRetiredPhysicalCommandReconciliationRequest(
reopening_id="reopening-after-peer-post-retirement-scan",
expected_revision=fresh["expected_revision"],
expected_retirement_id=fresh["expected_retirement_id"],
expected_transport_ref=fresh["expected_transport_ref"],
expected_discovery_generation=fresh["expected_discovery_generation"],
expected_desired_mode=fresh["expected_desired_mode"],
expected_desired_mode_revision=fresh["expected_desired_mode_revision"],
operator_confirmed=True,
reason="device-returned-for-explicit-reconciliation",
)
)
assert reopened["physical_command"]["requires_reconciliation"] is True
assert owner_runtime.start_calls == []
assert owner_runtime.stop_calls == 0
assert peer_runtime.start_calls == []
assert peer_runtime.stop_calls == 0
def test_exact_retirement_retry_repairs_local_revocation_without_process_lease_or_io(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
binding = _seed_supervised_connection(service, transport_ref="retired-k1")
request = _seed_unresolved_physical_stop_for_retirement(service, binding)
real_revoke = service._revoke_retired_physical_target_locally # noqa: SLF001
def fail_after_durable_commit(*_args: object, **_kwargs: object) -> None:
raise RuntimeError("injected crash after ledger commit")
monkeypatch.setattr(
service,
"_revoke_retired_physical_target_locally",
fail_after_durable_commit,
)
with pytest.raises(RuntimeError, match="injected crash"):
service.retire_unavailable_physical_command(request)
committed = service._physical_command_ledger.snapshot().record # noqa: SLF001
assert committed is not None
assert committed.resolution == "operator-retired-outcome-unknown"
assert service._selected_device_id == "retired-k1" # noqa: SLF001
# A replacement backend may legitimately advance the shared ledger before
# the original browser retries its lost retirement response. The carried
# retirement audit, not the current operation, is the idempotency key.
replacement_identity = PhysicalCommandIdentity(
vendor_device_id_sha256="7" * 64,
device_serial_sha256="8" * 64,
)
replacement_connection = PhysicalCommandConnectionBinding(
intent_id="replacement-intent",
transport_ref="replacement-k1",
connection_mode="bridge",
target_ipv4="192.168.1.21",
target_port=facade_module.CONTROL_MQTT_PORT,
host_path_epoch=21,
control_session_id="replacement-control-session",
producer_generation=22,
)
replacement_status = PhysicalCommandStatusEvidence(
source="live-control-session",
vendor_device_id_sha256=replacement_identity.vendor_device_id_sha256,
device_serial_sha256=replacement_identity.device_serial_sha256,
control_session_id=replacement_connection.control_session_id,
host_path_epoch=replacement_connection.host_path_epoch,
producer_generation=replacement_connection.producer_generation,
session_state="ready",
session_state_code=300,
project_bound=False,
project_id_sha256=None,
init_ready=False,
status_message_sha256="9" * 64,
mqtt_retained=False,
observed_at_utc="2026-08-10T17:01:00.000Z",
)
replacement = service._physical_command_ledger.prepare( # noqa: SLF001
operation_id="replacement-start-after-retirement",
parent_operation_id=committed.operation_id,
acquisition_id="replacement-acquisition-after-retirement",
action="start",
identity=replacement_identity,
connection=replacement_connection,
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
payload_sha256="2" * 64,
baseline_status=replacement_status,
)
advanced = service._physical_command_ledger.resolve( # noqa: SLF001
replacement.operation_id,
resolution="not-dispatched",
)
monkeypatch.setattr(service, "_revoke_retired_physical_target_locally", real_revoke)
monkeypatch.setattr(
service,
"_acquire_k1_lifecycle_process_lease",
lambda *_args, **_kwargs: (_ for _ in ()).throw(
AssertionError("exact retry must not acquire the shared process lease")
),
)
repaired = service.retire_unavailable_physical_command(request)
persisted = service._physical_command_ledger.snapshot().record # noqa: SLF001
assert persisted == advanced
assert repaired["selected_device_id"] is None
assert repaired["connection_lifecycle"]["active_binding"] is None
def test_stale_peer_blocks_every_retired_target_contact_path_before_io(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
owner, _ = service_with_fake_runtime(tmp_path)
owner_binding = _seed_supervised_connection(owner, transport_ref="RETIRED-K1")
request = _seed_unresolved_physical_stop_for_retirement(owner, owner_binding)
stale_peer, stale_runtime = service_with_fake_runtime(tmp_path)
_set_scanned_k1(stale_peer, device_id="retired-k1")
_seed_supervised_connection(stale_peer, transport_ref="retired-k1")
connect_request = _connect_request(
device_id="retired-k1",
ssid="DCCONSTRUCTIONS",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
connection_mode="bridge",
compatibility_attestation=ATTESTATION,
)
owner.retire_unavailable_physical_command(request)
io_calls: list[str] = []
async def forbidden_async_io(*_args: object, **_kwargs: object) -> object:
io_calls.append("ble-or-network")
raise AssertionError("retired target must be rejected before I/O")
def forbidden_sync_io(*_args: object, **_kwargs: object) -> object:
io_calls.append("host-tcp-mqtt-http")
raise AssertionError("retired target must be rejected before I/O")
monkeypatch.setattr(facade_module, "read_wifi_status_once", forbidden_async_io)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_async_io)
monkeypatch.setattr(facade_module, "_control_endpoint_reachable", forbidden_sync_io)
monkeypatch.setattr(stale_peer, "_sample_host_path", forbidden_sync_io)
monkeypatch.setattr(stale_peer, "_probe_control_endpoint", forbidden_sync_io)
monkeypatch.setattr(stale_peer, "_refresh_live_lan_address", forbidden_sync_io)
monkeypatch.setattr(stale_peer.camera_preview, "select", forbidden_sync_io)
monkeypatch.setattr(
stale_peer._calibration_snapshot_reader, # noqa: SLF001
"capture",
forbidden_sync_io,
)
monkeypatch.setattr(
SecretStr,
"get_secret_value",
lambda _self: (_ for _ in ()).throw(
AssertionError("retired Connect must not unwrap the credential")
),
)
with pytest.raises(facade_module.NetworkProvisioningConflict) as connect_error:
asyncio.run(stale_peer.connect(connect_request))
assert connect_error.value.reason_code == "physical-command-target-retired"
with pytest.raises(facade_module.ConnectionVerificationError) as verify_error:
asyncio.run(
stale_peer.verify_connection(
ConnectionVerifyRequest(
device_id="retired-k1",
source="fresh-scan",
compatibility_attestation=ATTESTATION,
expected_discovery_generation=0,
)
)
)
assert verify_error.value.reason_code == "physical-command-target-retired"
with pytest.raises(facade_module.ConnectionVerificationError) as open_error:
stale_peer.open_application_control_session(
OpenApplicationControlSessionRequest(
operator_present=True,
owner_controlled_device=True,
lixelgo_closed=True,
battery_storage_confirmed=True,
expected_physical_state_confirmed=True,
timezone_name="Europe/Moscow",
)
)
assert open_error.value.reason_code == "physical-command-target-retired"
with pytest.raises(facade_module.ConfiguredEndpointProbeError) as probe_error:
asyncio.run(stale_peer.probe_configured_endpoint(ConfiguredEndpointProbeRequest()))
assert probe_error.value.reason_code == "physical-command-target-retired"
with pytest.raises(facade_module.ConnectionVerificationError) as calibration_error:
stale_peer.read_device_calibration_snapshot()
assert calibration_error.value.reason_code == "physical-command-target-retired"
assert stale_peer._connection_monitor_target() is None # noqa: SLF001
asyncio.run(stale_peer._connection_monitor.poll_once()) # noqa: SLF001
with pytest.raises(facade_module.ConnectionVerificationError):
asyncio.run(
stale_peer._monitor_control_endpoint( # noqa: SLF001
EndpointTarget("192.168.1.20", facade_module.CONTROL_MQTT_PORT)
)
)
with pytest.raises(facade_module.ConnectionVerificationError):
stale_peer.prepare_acquisition(
_prepare_request(
project_name="RETIRED01",
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
with pytest.raises(facade_module.ConnectionVerificationError):
stale_peer.start_live(
"RETIRED02",
"192.168.1.20",
None,
ATTESTATION,
)
with pytest.raises(facade_module.ConnectionVerificationError) as camera_error:
stale_peer.select_camera_preview(
CameraPreviewSelectRequest(
source_id=facade_module.DEFAULT_ACQUISITION_CAMERA_SOURCE,
device_session_id="test-session-retired-k1",
)
)
assert camera_error.value.reason_code == "physical-command-target-retired"
inspected = stale_peer.inspect_device()
assert inspected["physical_command"]["record"]["resolution"] == (
"operator-retired-outcome-unknown"
)
assert stale_runtime.start_calls == []
assert stale_runtime.stop_calls == 0
assert io_calls == []
def test_selected_camera_holds_retirement_fence_and_stale_generation_cannot_spawn(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
camera_service, _ = service_with_fake_runtime(tmp_path)
binding = _seed_supervised_connection(
camera_service,
transport_ref="retired-k1",
)
request = _seed_unresolved_physical_stop_for_retirement(
camera_service,
binding,
)
camera_service.camera_preview._ffmpeg_path = ( # noqa: SLF001
tmp_path / "synthetic-ffmpeg"
)
selected = camera_service.select_camera_preview(
CameraPreviewSelectRequest(
source_id=facade_module.DEFAULT_ACQUISITION_CAMERA_SOURCE,
device_session_id="test-session-retired-k1",
)
)
generation = selected["camera_preview"]["generation"]
assert isinstance(generation, int)
assert "camera" in ( # noqa: SLF001
camera_service._application_control_process_lease_holders # noqa: SLF001
)
retirement_service, _ = service_with_fake_runtime(tmp_path)
with pytest.raises(facade_module.ApplicationControlProcessLeaseUnavailable):
retirement_service.retire_unavailable_physical_command(request)
stopped = camera_service.stop_camera_preview(
facade_module.CameraPreviewStopRequest(
generation=generation,
device_session_id="test-session-retired-k1",
)
)
assert stopped["camera_preview"]["active_source_id"] is None
assert "camera" not in ( # noqa: SLF001
camera_service._application_control_process_lease_holders # noqa: SLF001
)
retired = retirement_service.retire_unavailable_physical_command(request)
assert retired["physical_command"]["record"]["resolution"] == (
"operator-retired-outcome-unknown"
)
popen_calls: list[str] = []
def forbidden_popen(*_args: object, **_kwargs: object) -> object:
popen_calls.append("popen")
raise AssertionError("retired stale camera generation must not spawn FFmpeg")
monkeypatch.setattr(
"k1link.device_plugins.xgrids_k1.camera.subprocess.Popen",
forbidden_popen,
)
with pytest.raises(ValueError, match="generation не активно"):
camera_service.camera_preview.open_delivery(generation)
assert popen_calls == []
def test_cancelled_target_probe_retains_retirement_fence_until_thread_finishes(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
probe_service, _ = service_with_fake_runtime(tmp_path)
binding = _seed_supervised_connection(
probe_service,
transport_ref="retired-k1",
)
request = _seed_unresolved_physical_stop_for_retirement(
probe_service,
binding,
)
retirement_service, _ = service_with_fake_runtime(tmp_path)
probe_entered = threading.Event()
release_probe = threading.Event()
def blocked_host_path(
_target: str,
*,
association_timeout_seconds: float = 30.0,
fail_closed_unproven_association: bool = False,
) -> HostPathProbeResult:
assert association_timeout_seconds == (
facade_module.CONNECTION_MONITOR_ASSOCIATION_TIMEOUT_SECONDS
)
assert fail_closed_unproven_association is True
probe_entered.set()
assert release_probe.wait(timeout=5.0)
return _direct_host_path(_target)
monkeypatch.setattr(probe_service, "_sample_host_path", blocked_host_path)
async def scenario() -> None:
target = EndpointTarget(binding.target_ipv4, binding.target_port)
probe_task = asyncio.create_task(
probe_service._monitor_host_path(target) # noqa: SLF001
)
assert await asyncio.to_thread(probe_entered.wait, 5.0)
before = retirement_service._physical_command_ledger.snapshot().record # noqa: SLF001
probe_task.cancel()
await asyncio.sleep(0)
probe_task.cancel()
await asyncio.sleep(0.01)
assert probe_task.done() is False
with pytest.raises(facade_module.ApplicationControlProcessLeaseUnavailable):
await asyncio.to_thread(
retirement_service.retire_unavailable_physical_command,
request,
)
assert (
retirement_service._physical_command_ledger.snapshot().record # noqa: SLF001
== before
)
release_probe.set()
with pytest.raises(asyncio.CancelledError):
await probe_task
retired = await asyncio.to_thread(
retirement_service.retire_unavailable_physical_command,
request,
)
assert retired["physical_command"]["record"]["resolution"] == (
"operator-retired-outcome-unknown"
)
asyncio.run(scenario())
def test_calibration_process_lease_blocks_cross_service_retirement_until_capture_finishes(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
calibration_service, _ = service_with_fake_runtime(tmp_path)
binding = _seed_supervised_connection(
calibration_service,
transport_ref="retired-k1",
)
request = _seed_unresolved_physical_stop_for_retirement(
calibration_service,
binding,
)
retirement_service, _ = service_with_fake_runtime(tmp_path)
capture_entered = threading.Event()
release_capture = threading.Event()
outcome: dict[str, object] = {}
class BlockingCalibrationReader:
def capture(self, **_kwargs: object) -> dict[str, object]:
capture_entered.set()
assert release_capture.wait(timeout=5)
return {"status": "available", "snapshot_id": "blocking-test"}
calibration_service._calibration_snapshot_reader = ( # type: ignore[assignment] # noqa: SLF001
BlockingCalibrationReader()
)
monkeypatch.setattr(
calibration_service,
"_refresh_live_lan_address",
lambda: "192.168.1.20",
)
def capture() -> None:
try:
outcome["result"] = calibration_service.read_device_calibration_snapshot()
except BaseException as exc: # pragma: no cover - asserted below
outcome["error"] = exc
worker = threading.Thread(target=capture, daemon=True)
worker.start()
assert capture_entered.wait(timeout=5)
projection = calibration_service.state()["physical_command"]["operator_retirement"]
assert projection["allowed"] is False
assert "device-calibration-read-active" in projection["reason_codes"]
before = retirement_service._physical_command_ledger.snapshot().record # noqa: SLF001
with pytest.raises(facade_module.ApplicationControlProcessLeaseUnavailable):
retirement_service.retire_unavailable_physical_command(request)
unchanged = retirement_service._physical_command_ledger.snapshot().record # noqa: SLF001
assert unchanged == before
release_capture.set()
worker.join(timeout=5)
assert not worker.is_alive()
assert "error" not in outcome
assert outcome["result"] == {
"status": "available",
"snapshot_id": "blocking-test",
}
def test_calibration_hard_timeout_retains_retirement_fence_until_ble_cleanup(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
calibration_service, _ = service_with_fake_runtime(tmp_path)
binding = _seed_supervised_connection(
calibration_service,
transport_ref="retired-k1",
)
request = _seed_unresolved_physical_stop_for_retirement(
calibration_service,
binding,
)
retirement_service, _ = service_with_fake_runtime(tmp_path)
async def scenario() -> None:
cleanup_entered = asyncio.Event()
cleanup_release = asyncio.Event()
async def detached_status_read(
_device_id: str,
**_kwargs: object,
) -> dict[str, Any]:
async def stubborn_cleanup(_progress: BleOperationProgress) -> None:
try:
await asyncio.Event().wait()
except asyncio.CancelledError:
cleanup_entered.set()
await cleanup_release.wait()
raise
return await run_ble_operation( # type: ignore[return-value]
"status-read",
hard_timeout_seconds=0.01,
operation=stubborn_cleanup,
)
runtime_loop = asyncio.get_running_loop()
bind_ble_runtime_owner_loop(runtime_loop)
with calibration_service._lock: # noqa: SLF001
calibration_service._runtime_event_loop = runtime_loop # noqa: SLF001
monkeypatch.setattr(
facade_module,
"read_wifi_status_once",
detached_status_read,
)
monkeypatch.setattr(
facade_module,
"_host_route_class",
lambda _target: "default-route",
)
with pytest.raises(RuntimeError, match="BLE status-read не завершился"):
await asyncio.to_thread(calibration_service.read_device_calibration_snapshot)
await cleanup_entered.wait()
with pytest.raises(facade_module.NetworkProvisioningConflict):
await asyncio.to_thread(
retirement_service.retire_unavailable_physical_command,
request,
)
cleanup_release.set()
assert await wait_for_ble_runtime_idle()
retired = await asyncio.to_thread(
retirement_service.retire_unavailable_physical_command,
request,
)
assert retired["physical_command"]["record"]["resolution"] == (
"operator-retired-outcome-unknown"
)
asyncio.run(scenario())
def test_operator_manual_live_retains_cross_process_fence_until_receiver_stops(
tmp_path: Path,
) -> None:
live_service, live_runtime = service_with_fake_runtime(tmp_path)
prepared = live_service.prepare_acquisition(
_prepare_request(
project_name="MANUAL01",
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
retirement_service, _ = service_with_fake_runtime(tmp_path)
binding = _seed_supervised_connection(
retirement_service,
transport_ref="retired-k1",
)
request = _seed_unresolved_physical_stop_for_retirement(
retirement_service,
binding,
)
started = live_service.start_acquisition(_start_request(acquisition_id=acquisition_id))
assert started["acquisition"]["state"] == "starting"
assert live_runtime.start_calls
assert (
live_service._operator_manual_acquisition_process_lease_id # noqa: SLF001
== acquisition_id
)
with pytest.raises(facade_module.ApplicationControlProcessLeaseUnavailable):
retirement_service.retire_unavailable_physical_command(request)
unresolved = retirement_service._physical_command_ledger.snapshot().record # noqa: SLF001
assert unresolved is not None and unresolved.unresolved
stopped = live_service.stop_acquisition(
_stop_request(
acquisition_id=acquisition_id,
mode="capture-only",
)
)
assert stopped["acquisition"]["state"] == "completed"
assert live_service._operator_manual_acquisition_process_lease_id is None # noqa: SLF001
retired = retirement_service.retire_unavailable_physical_command(request)
assert retired["physical_command"]["record"]["resolution"] == (
"operator-retired-outcome-unknown"
)
def test_ambiguous_manual_start_cleanup_keeps_retirement_fenced_until_retry(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
live_service, live_runtime = service_with_fake_runtime(tmp_path)
prepared = live_service.prepare_acquisition(
_prepare_request(
project_name="MANUALFAIL",
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
retirement_service, _ = service_with_fake_runtime(tmp_path)
binding = _seed_supervised_connection(
retirement_service,
transport_ref="retired-k1",
)
request = _seed_unresolved_physical_stop_for_retirement(
retirement_service,
binding,
)
original_start_live = live_runtime.start_live
def fail_after_receiver_start(
host: str,
out_dir: Path,
*,
duration_seconds: float | None,
project_name: str,
recover_connection: Callable[[int], str] | None = None,
) -> None:
original_start_live(
host,
out_dir,
duration_seconds=duration_seconds,
project_name=project_name,
recover_connection=recover_connection,
)
raise RuntimeError("injected receiver start failure")
monkeypatch.setattr(live_runtime, "start_live", fail_after_receiver_start)
live_runtime.stop_error = RuntimeError("injected receiver cleanup failure")
camera_arm_calls: list[Path] = []
monkeypatch.setattr(
live_service,
"_arm_camera_recording",
lambda out_dir, **_kwargs: camera_arm_calls.append(out_dir),
)
with pytest.raises(RuntimeError, match="receiver start failure"):
live_service.start_acquisition(_start_request(acquisition_id=acquisition_id))
assert live_runtime.start_calls
assert camera_arm_calls == []
assert (
live_service._operator_manual_acquisition_process_lease_id # noqa: SLF001
== acquisition_id
)
with pytest.raises(facade_module.ApplicationControlProcessLeaseUnavailable):
retirement_service.retire_unavailable_physical_command(request)
unresolved = retirement_service._physical_command_ledger.snapshot().record # noqa: SLF001
assert unresolved is not None and unresolved.unresolved
live_runtime.stop_error = None
live_service._stop_acquisition_sources( # noqa: SLF001
camera_status="failed",
camera_failure_code="cleanup-retry-after-start-failure",
)
assert live_service._operator_manual_acquisition_process_lease_id is None # noqa: SLF001
retirement_service.retire_unavailable_physical_command(request)
def test_state_snapshot_stamp_is_runtime_scoped_and_monotonic(tmp_path: Path) -> None:
service, _ = service_with_fake_runtime(tmp_path / "first-runtime")
first = service.state()
second = service.state()
replacement, _ = service_with_fake_runtime(tmp_path / "replacement-runtime")
replacement_state = replacement.state()
assert first["snapshot_runtime_id"].startswith("snapshot-runtime-")
assert first["snapshot_runtime_id"] == second["snapshot_runtime_id"]
assert first["snapshot_runtime_started_at_utc"] == (second["snapshot_runtime_started_at_utc"])
assert (
first["snapshot_runtime_started_monotonic_ns"]
== (second["snapshot_runtime_started_monotonic_ns"])
)
assert second["snapshot_revision"] == first["snapshot_revision"] + 1
assert replacement_state["snapshot_runtime_id"] != first["snapshot_runtime_id"]
assert int(replacement_state["snapshot_runtime_started_monotonic_ns"]) > int(
first["snapshot_runtime_started_monotonic_ns"]
)
assert replacement_state["snapshot_revision"] == 1
def test_runtime_start_allocator_is_strictly_increasing_for_equal_clock_ticks(
monkeypatch: pytest.MonkeyPatch,
) -> None:
with facade_module._SNAPSHOT_RUNTIME_START_LOCK: # noqa: SLF001
previous = facade_module._LAST_SNAPSHOT_RUNTIME_STARTED_MONOTONIC_NS # noqa: SLF001
facade_module._LAST_SNAPSHOT_RUNTIME_STARTED_MONOTONIC_NS = 100 # noqa: SLF001
try:
monkeypatch.setattr(facade_module.time, "monotonic_ns", lambda: 100)
first = facade_module._allocate_snapshot_runtime_started_monotonic_ns() # noqa: SLF001
second = facade_module._allocate_snapshot_runtime_started_monotonic_ns() # noqa: SLF001
assert (first, second) == ("101", "102")
finally:
with facade_module._SNAPSHOT_RUNTIME_START_LOCK: # noqa: SLF001
facade_module._LAST_SNAPSHOT_RUNTIME_STARTED_MONOTONIC_NS = max( # noqa: SLF001
previous,
102,
)
def _wifi_status_read(
ipv4: str | None,
*,
device_id: str = "test-ble-transport",
) -> dict[str, Any]:
return {
"schema_version": 1,
"profile_id": "xgrids-k1-fw3-wifi-v1",
"observed_at_utc": "2026-07-20T12:00:00Z",
"adapter": "CoreBluetooth",
"bleak_version": "test",
"device_macos_uuid": device_id,
"device_name": "XGR-K1",
"service_uuid": "00007f00-0000-1000-8000-00805f9b34fb",
"write_characteristic_uuid": "00007f01-0000-1000-8000-00805f9b34fb",
"write_characteristic_properties": ["read", "write"],
"max_write_without_response_size": 253,
"mtu_size": 256,
"status_characteristic_uuid": "00007f02-0000-1000-8000-00805f9b34fb",
"operation": "single_reviewed_wifi_status_read",
"write_performed": False,
"status": {
"value_length": 54,
"mode": "WIFI_CLIENT",
"ipv4": ipv4,
"status_code": 1,
"reserved": 0,
"trailer_hex": "",
},
}
def _durable_status_capture(
device_id: str = DURABLE_K1_UUID,
) -> facade_module.CapturedDiscoveredDevice:
return facade_module.CapturedDiscoveredDevice(
device=SimpleNamespace(address=device_id), # type: ignore[arg-type]
macos_uuid=device_id,
owner_epoch=7,
source="retrieved-durable",
)
def _ap_ready_wifi_status() -> dict[str, Any]:
return {
"value_length": 54,
"mode": "WIFI_AP",
"ipv4": "192.168.56.1",
"status_code": 1,
"reserved": 1,
"trailer_hex": "",
}
@pytest.mark.parametrize("mode", [None, "UNKNOWN", "WIFI_AP"])
def test_applied_bridge_target_requires_explicit_wifi_client_mode(
mode: str | None,
) -> None:
status = {
"mode": mode,
"ipv4": "192.168.68.52",
"status_code": 1,
"reserved": 0,
}
assert facade_module._applied_network_target("bridge", status) is None # noqa: SLF001
assert (
facade_module._applied_network_target("direct-connect", status) # noqa: SLF001
is None
)
@pytest.mark.parametrize(
("connection_mode", "baseline", "observed", "previous", "expected"),
[
(
"bridge",
NetworkStatusEvidence("WIFI_CLIENT", "192.168.68.40", 1, 0),
{"mode": "WIFI_CLIENT", "ipv4": "192.168.68.40", "status_code": 1, "reserved": 0},
None,
None,
),
(
"bridge",
NetworkStatusEvidence("WIFI_CLIENT", "192.168.68.40", 1, 0),
{"mode": "WIFI_CLIENT", "ipv4": "192.168.68.99", "status_code": 1, "reserved": 0},
None,
None,
),
(
"direct-connect",
NetworkStatusEvidence("WIFI_CLIENT", None, 1, 0),
{"mode": "WIFI_CLIENT", "ipv4": "172.20.10.2", "status_code": 1, "reserved": 0},
None,
None,
),
(
"quick-connect",
NetworkStatusEvidence("WIFI_AP", "192.168.56.1", 1, 1),
{"mode": "WIFI_AP", "ipv4": "192.168.56.1", "status_code": 2, "reserved": 1},
None,
None,
),
(
"bridge",
NetworkStatusEvidence("WIFI_AP", "192.168.56.1", 1, 1),
{"mode": "WIFI_CLIENT", "ipv4": "192.168.68.50", "status_code": 1, "reserved": 0},
None,
"192.168.68.50",
),
(
"direct-connect",
NetworkStatusEvidence("WIFI_AP", "192.168.56.1", 1, 1),
{"mode": "WIFI_CLIENT", "ipv4": "172.20.10.2", "status_code": 1, "reserved": 0},
None,
"172.20.10.2",
),
(
"quick-connect",
NetworkStatusEvidence("WIFI_CLIENT", "192.168.68.50", 1, 0),
{"mode": "WIFI_AP", "ipv4": "192.168.56.1", "status_code": 1, "reserved": 1},
None,
"192.168.56.1",
),
(
"quick-connect",
NetworkStatusEvidence("WIFI_AP", "192.168.56.1", 1, 0),
{"mode": "WIFI_AP", "ipv4": "192.168.56.1", "status_code": 1, "reserved": 1},
None,
"192.168.56.1",
),
(
"quick-connect",
NetworkStatusEvidence("WIFI_CLIENT", "192.168.68.50", 1, 0),
{"mode": "WIFI_AP", "ipv4": "192.168.56.1", "status_code": 1, "reserved": 1},
PreviousConnectionEvidence("same-k1", "quick-connect", "192.168.56.1", "old-session"),
None,
),
(
"bridge",
NetworkStatusEvidence("WIFI_AP", "192.168.56.1", 1, 1),
{"mode": "WIFI_CLIENT", "ipv4": "192.168.68.99", "status_code": 1, "reserved": 0},
PreviousConnectionEvidence("same-k1", "bridge", "192.168.68.40", "old-session"),
None,
),
(
"direct-connect",
NetworkStatusEvidence("WIFI_AP", "192.168.56.1", 1, 1),
{"mode": "WIFI_CLIENT", "ipv4": "172.20.10.2", "status_code": 1, "reserved": 0},
PreviousConnectionEvidence("same-k1", "bridge", "172.20.10.2", "old-session"),
None,
),
(
"bridge",
NetworkStatusEvidence("WIFI_AP", "192.168.56.1", 1, 1),
{"mode": "WIFI_CLIENT", "ipv4": "172.20.10.2", "status_code": 1, "reserved": 0},
PreviousConnectionEvidence("same-k1", "direct-connect", "172.20.10.2", "old-session"),
None,
),
(
"bridge",
NetworkStatusEvidence("WIFI_AP", "192.168.56.1", 1, 1),
{"mode": "WIFI_CLIENT", "ipv4": "192.168.68.50", "status_code": 1, "reserved": 0},
PreviousConnectionEvidence("other-k1", "bridge", "192.168.68.50", "old-session"),
"192.168.68.50",
),
],
)
def test_post_dispatch_target_requires_status_distinguishable_from_baseline(
connection_mode: facade_module.ConnectionMode,
baseline: NetworkStatusEvidence,
observed: dict[str, object],
previous: PreviousConnectionEvidence | None,
expected: str | None,
) -> None:
assert (
facade_module._post_dispatch_network_target( # noqa: SLF001
connection_mode,
observed,
transport_ref="same-k1",
baseline_status=baseline,
previous_connection=previous,
)
== expected
)
def test_post_dispatch_bridge_accepts_exact_fw302_network_name_when_baseline_is_same() -> None:
"""An idempotent same-network Bridge request proves the requested target."""
status = {
"mode": "WIFI_CLIENT",
"network_name": "LAB_NETWORK",
"ipv4": "192.168.68.51",
"status_code": 1,
"reserved": 0,
}
assert (
facade_module._post_dispatch_network_target( # noqa: SLF001
"bridge",
status,
transport_ref="same-k1",
baseline_status=NetworkStatusEvidence("WIFI_CLIENT", "192.168.68.51", 1, 0),
previous_connection=PreviousConnectionEvidence(
"same-k1",
"bridge",
"192.168.68.51",
"old-session",
),
expected_network_name="LAB_NETWORK",
)
== "192.168.68.51"
)
def test_post_dispatch_bridge_rejects_another_fw302_network_name() -> None:
status = {
"mode": "WIFI_CLIENT",
"network_name": "ANOTHER_NETWORK",
"ipv4": "192.168.68.51",
"status_code": 1,
"reserved": 0,
}
assert (
facade_module._post_dispatch_network_target( # noqa: SLF001
"bridge",
status,
transport_ref="same-k1",
baseline_status=NetworkStatusEvidence("WIFI_AP", "192.168.56.1", 1, 1),
expected_network_name="LAB_NETWORK",
)
is None
)
def _seed_unresolved_network_mutation(
service: XgridsK1CompatibilityService,
*,
operation_id: str = "ambiguous-operation",
idempotency_operation_id: str | None = None,
transport_ref: str = "test-ble-transport",
intended_mode: NetworkConnectionMode = "bridge",
baseline_status: NetworkStatusEvidence | None = None,
previous_connection: PreviousConnectionEvidence | None = None,
) -> dict[str, Any]:
resolved_idempotency_operation_id = idempotency_operation_id or operation_id
idempotency_key = f"test-reconciliation-{resolved_idempotency_operation_id}"
idempotency_journal = (
service._require_network_provisioning_idempotency_journal() # noqa: SLF001
)
idempotency_admission = idempotency_journal.begin(
idempotency_key=idempotency_key,
action=facade_module.ACTION_NETWORK_PROVISION,
operation_id=resolved_idempotency_operation_id,
request_binding_sha256=facade_module.derive_request_binding_sha256(
idempotency_key,
action=facade_module.ACTION_NETWORK_PROVISION,
canonical_request=b'{"test":"read-only-reconciliation"}',
),
)
ledger = service._network_mutation_ledger # noqa: SLF001
prepared = ledger.prepare(
operation_id=operation_id,
transport_ref=transport_ref,
intended_mode=intended_mode,
write_mode="with_response",
baseline_status=baseline_status
or NetworkStatusEvidence(
mode="WIFI_AP",
ipv4="192.168.56.1",
status_code=1,
reserved=1,
),
previous_connection=previous_connection,
)
idempotency_journal.mark_unresolved(
resolved_idempotency_operation_id,
expected_revision=idempotency_admission.record.revision,
)
ledger.mark_dispatching(
operation_id,
expected_revision=prepared.revision,
)
fence = service.state()["network_write_reconciliation"]
assert fence is not None
return fence
def _prepare_network_mutation_for_reopen(
service: XgridsK1CompatibilityService,
*,
operation_id: str,
transport_ref: str,
intended_mode: NetworkConnectionMode,
) -> NetworkMutationRecord:
return service._network_mutation_ledger.prepare( # noqa: SLF001
operation_id=operation_id,
transport_ref=transport_ref,
intended_mode=intended_mode,
write_mode="with_response",
baseline_status=NetworkStatusEvidence(
mode="WIFI_AP",
ipv4="192.168.56.1",
status_code=1,
reserved=1,
),
)
def _begin_network_idempotency_for_reopen(
service: XgridsK1CompatibilityService,
*,
operation_id: str,
mark_unresolved: bool,
) -> None:
idempotency_key = f"reopen-audit-{operation_id}"
journal = service._require_network_provisioning_idempotency_journal() # noqa: SLF001
admission = journal.begin(
idempotency_key=idempotency_key,
action=facade_module.ACTION_NETWORK_PROVISION,
operation_id=operation_id,
request_binding_sha256=facade_module.derive_request_binding_sha256(
idempotency_key,
action=facade_module.ACTION_NETWORK_PROVISION,
canonical_request=b'{"test":"reopen-precommit"}',
),
)
if mark_unresolved:
journal.mark_unresolved(
operation_id,
expected_revision=admission.record.revision,
)
def _seed_legacy_network_mutation_without_idempotency(
service: XgridsK1CompatibilityService,
*,
operation_id: str = "legacy-network-operation",
stage: str = "dispatching",
) -> None:
"""Create the durable shape emitted before the idempotency journal existed."""
ledger = service._network_mutation_ledger # noqa: SLF001
prepared = ledger.prepare(
operation_id=operation_id,
transport_ref="test-ble-transport",
intended_mode="bridge",
write_mode="with_response",
baseline_status=NetworkStatusEvidence(
mode="WIFI_AP",
ipv4="192.168.56.1",
status_code=1,
reserved=1,
),
)
if stage == "prepared":
return
dispatching = ledger.mark_dispatching(
operation_id,
expected_revision=prepared.revision,
)
if stage == "observing":
ledger.mark_observing(
operation_id,
expected_revision=dispatching.revision,
write_confirmed=True,
observation=NetworkStatusEvidence(
mode="WIFI_CLIENT",
ipv4="192.168.68.50",
status_code=1,
reserved=0,
),
)
elif stage != "dispatching":
raise ValueError("unsupported legacy test stage")
def _set_scanned_devices(
service: XgridsK1CompatibilityService,
devices: list[dict[str, Any]],
) -> None:
service._devices = devices # noqa: SLF001
_SYNTHETIC_SCAN_CAPTURES.clear()
_SYNTHETIC_SCAN_CAPTURES.update(
{
str(item["device_id"]): facade_module.CapturedDiscoveredDevice(
device=SimpleNamespace(address=str(item["device_id"])), # type: ignore[arg-type]
macos_uuid=str(item["device_id"]),
owner_epoch=1,
scan_generation=service._ble_discovery_generation, # noqa: SLF001
)
for item in devices
}
)
observed_monotonic = facade_module.time.monotonic()
observed_suspend_aware = facade_module.time.time()
service._ble_device_last_seen_monotonic = { # noqa: SLF001
str(item["device_id"]): observed_monotonic for item in devices
}
service._ble_device_last_seen_suspend_aware = { # noqa: SLF001
str(item["device_id"]): observed_suspend_aware for item in devices
}
def _set_scanned_k1(
service: XgridsK1CompatibilityService,
*,
device_id: str = "test-ble-transport",
) -> None:
_set_scanned_devices(
service,
[
{
"device_id": device_id,
"name": "XGR-K1",
"rssi": -44,
"address": None,
"connectable": True,
"likely_k1": True,
}
],
)
def _ble_scan_result(device_id: str) -> dict[str, Any]:
return {
"devices": [
{
"macos_uuid": device_id,
"name": "XGR-K1",
"local_name": "XGR-K1",
"rssi": -44,
"k1_name_candidate": True,
}
]
}
def _resolved_active_physical_snapshot(
*,
transport_ref: str = "k1-original",
connection_mode: str = "bridge",
) -> dict[str, object]:
return {
"status": "resolved",
"reason_code": None,
"requires_reconciliation": False,
"resolved_active_recovery_required": True,
"automatic_replay_allowed": False,
"normal_session_recovery_supported": False,
"recovery_requirement": ("explicit-read-only-deviceinfo-and-non-retained-devicestatus"),
"runtime_bound": False,
"reconciliation_ready": False,
"observed_session_state": None,
"active_operation_id": None,
"record": {
"operation_id": "persisted-start-active",
"action": "start",
"stage": "resolved",
"resolution": "start-active-observed",
"connection": {
"transport_ref": transport_ref,
"connection_mode": connection_mode,
},
"reconciliations": [],
},
}
def _pending_reopened_physical_snapshot(
*,
transport_ref: str = "k1-a",
connection_mode: str = "bridge",
) -> dict[str, object]:
"""Project a classified STOP whose retired target was reopened for Verify."""
operation_id = "pending-reopened-prepared-stop"
retirement_id = "retirement-before-pending-reopen"
return {
"status": "resolved",
"reason_code": "physical-command-reconciliation-required",
"requires_reconciliation": False,
"resolved_active_recovery_required": True,
"reopened_physical_state_recovery_required": True,
"physical_active": False,
"reconciled_physical_state": None,
"automatic_replay_allowed": False,
"normal_session_recovery_supported": False,
"recovery_requirement": "explicit-read-only-reconciliation",
"runtime_bound": False,
"active_operation_id": None,
"record": {
"operation_id": operation_id,
"acquisition_id": "pending-reopened-acquisition",
"action": "stop",
"stage": "resolved",
"resolution": "not-dispatched",
"revision": 9,
"connection": {
"transport_ref": transport_ref,
"connection_mode": connection_mode,
},
"operator_retirements": [
{
"retirement_id": retirement_id,
"retired_transport_ref": transport_ref,
"original_attempt": {"operation_id": operation_id},
}
],
"operator_reconciliation_reopens": [
{
"retirement_id": retirement_id,
"retired_record_revision": 8,
}
],
"reconciliations": [],
},
}
def test_physical_recovery_policy_pins_original_ref_and_mode_but_keeps_scan_read_only(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_devices(
service,
[
{
"device_id": "k1-original",
"name": "Original K1",
"rssi": -40,
"address": None,
"connectable": True,
"likely_k1": True,
},
{
"device_id": "k1-nearby",
"name": "Nearby K1",
"rssi": -35,
"address": None,
"connectable": True,
"likely_k1": True,
},
],
)
monkeypatch.setattr(
service._physical_command_coordinator, # noqa: SLF001
"snapshot",
lambda: _resolved_active_physical_snapshot(),
)
state = service.state()
policy = state["connection_policy"]["actions"]
assert policy["scan-ble"]["allowed"] is True
assert "physical-device-already-active" not in policy["scan-ble"]["reason_codes"]
assert policy["provision-fresh-device"]["allowed"] is False
assert "physical-device-already-active" in policy["provision-fresh-device"]["reason_codes"]
assert policy["observe-fresh-device-network"] == {
"allowed": True,
"reason_codes": [],
"target_source": "fresh-scan",
"required_transport_ref": "k1-original",
"required_connection_mode": "bridge",
"requires_live_gatt_validation": True,
"automatic_retry": False,
}
def test_physical_recovery_rejects_wrong_nearby_k1_before_topology_or_ble_io(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_devices(
service,
[
{
"device_id": "k1-original",
"name": "Original K1",
"rssi": -40,
"address": None,
"connectable": True,
"likely_k1": True,
},
{
"device_id": "k1-nearby",
"name": "Nearby K1",
"rssi": -35,
"address": None,
"connectable": True,
"likely_k1": True,
},
],
)
monkeypatch.setattr(
service._physical_command_coordinator, # noqa: SLF001
"snapshot",
lambda: _resolved_active_physical_snapshot(),
)
io_calls: list[str] = []
monkeypatch.setattr(
facade_module,
"read_wifi_status_once",
lambda *_args, **_kwargs: io_calls.append("gatt-read"),
)
monkeypatch.setattr(
service,
"_apply_read_only_device_topology",
lambda *_args, **_kwargs: io_calls.append("topology-commit"),
)
semantic_before = service._semantic_topology_public_snapshot() # noqa: SLF001
supervisor_before = service._connection_supervisor.snapshot() # noqa: SLF001
network_ledger_before = service._network_mutation_ledger.snapshot() # noqa: SLF001
with pytest.raises(facade_module.ConnectionVerificationError) as rejected:
asyncio.run(
service.verify_connection(
ConnectionVerifyRequest(
device_id="k1-nearby",
source="fresh-scan",
compatibility_attestation=ATTESTATION,
expected_discovery_generation=0,
)
)
)
assert rejected.value.reason_code == "physical-command-recovery-target-mismatch"
assert io_calls == []
assert service._semantic_topology_public_snapshot() == semantic_before # noqa: SLF001
assert service._connection_supervisor.snapshot() == supervisor_before # noqa: SLF001
assert service._network_mutation_ledger.snapshot() == network_ledger_before # noqa: SLF001
def test_connect_is_fenced_before_gatt_or_wifi_when_physical_state_is_active(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service, device_id="k1-original")
monkeypatch.setattr(
service._physical_command_coordinator, # noqa: SLF001
"snapshot",
lambda: _resolved_active_physical_snapshot(),
)
io_calls: list[str] = []
async def forbidden_network_io(*_args: object, **_kwargs: object) -> dict[str, Any]:
io_calls.append("network-io")
raise AssertionError("physical admission must fail before GATT/Wi-Fi")
monkeypatch.setattr(facade_module, "read_wifi_status_once", forbidden_network_io)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_network_io)
with pytest.raises(facade_module.NetworkProvisioningConflict) as rejected:
asyncio.run(
service.connect(
_connect_request(
device_id="k1-original",
ssid="DCCONSTRUCTIONS",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
connection_mode="bridge",
compatibility_attestation=ATTESTATION,
)
)
)
assert rejected.value.reason_code == "physical-device-already-active"
assert io_calls == []
def test_latest_scan_candidate_survives_wall_clock_age_but_requires_exact_capture(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service, device_id="k1-a")
service._ble_device_last_seen_monotonic["k1-a"] = -1.0 # noqa: SLF001
service._ble_device_last_seen_suspend_aware["k1-a"] = -1.0 # noqa: SLF001
monkeypatch.setattr(facade_module, "_capture_network_intent_device", lambda _device_id: None)
async def forbidden_write(*_: object, **__: object) -> dict[str, Any]:
raise AssertionError("a missing exact scan capture must fail before GATT write")
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_write)
state = service.state()
assert [item["device_id"] for item in state["devices"]] == ["k1-a"]
assert state["selected_device_id"] is None
assert state["device_session"] is None
assert state["connection_lifecycle"]["active_binding"] is None
assert state["connection_lifecycle"]["active_binding_key"] is None
assert state["connection_policy"]["actions"]["provision-fresh-device"]["allowed"] is True
with pytest.raises(facade_module.NetworkProvisioningConflict) as raised:
asyncio.run(
service.connect(
_connect_request(
device_id="k1-a",
ssid="lab-router",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
connection_mode="bridge",
compatibility_attestation=ATTESTATION,
)
)
)
assert raised.value.reason_code == "network-provision-candidate-not-fresh"
def test_candidate_wall_clock_age_does_not_close_an_admitted_connection_session(
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_seed_supervised_connection(service, transport_ref="k1-a")
_set_scanned_k1(service, device_id="k1-a")
service._ble_device_last_seen_monotonic["k1-a"] = -1.0 # noqa: SLF001
service._ble_device_last_seen_suspend_aware["k1-a"] = -1.0 # noqa: SLF001
state = service.state()
assert [item["device_id"] for item in state["devices"]] == ["k1-a"]
assert state["selected_device_id"] == "k1-a"
assert state["device_session"] is not None
assert state["device_session"]["connectivity"] in {"connected", "degraded"}
def test_ble_scan_lists_twenty_candidates_without_selecting_or_opening_gatt(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
low_level_calls: list[str] = []
async def twenty_candidate_scan(
_duration_seconds: float,
*,
on_admitted: Callable[[], None] | None = None,
) -> dict[str, Any]:
if on_admitted is not None:
on_admitted()
return {
"devices": [
{
"macos_uuid": f"K1-CANDIDATE-{index:02d}",
"name": f"XGR-K1-{index:02d}",
"local_name": f"XGR-K1-{index:02d}",
"rssi": -40 - index,
"k1_name_candidate": True,
}
for index in range(20)
]
}
async def forbidden_gatt(*_: object, **__: object) -> dict[str, Any]:
low_level_calls.append("gatt")
raise AssertionError("scan must not open GATT or write K1")
monkeypatch.setattr(facade_module, "scan", twenty_candidate_scan)
monkeypatch.setattr(facade_module, "read_wifi_status_once", forbidden_gatt)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_gatt)
state = asyncio.run(service.scan_ble(1.0))
assert len(state["devices"]) == 20
assert state["selected_device_id"] is None
assert state["device_session"] is None
assert state["connection_mode"] is None
assert low_level_calls == []
def _attempt_competing_scan_from_sync_boundary(
service: XgridsK1CompatibilityService,
*,
operation_id: str,
) -> object:
outcomes: list[object] = []
def worker() -> None:
try:
outcomes.append(
asyncio.run(
service.scan_ble(
BleScanRequest(
duration_seconds=1.0,
operation_id=operation_id,
)
)
)
)
except BaseException as exc:
outcomes.append(exc)
thread = threading.Thread(target=worker, daemon=True)
thread.start()
thread.join(timeout=1.0)
assert not thread.is_alive()
assert len(outcomes) == 1
return outcomes[0]
def test_explicit_new_scan_invalidates_previous_candidate_authority(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service)
async def empty_scan(
_duration_seconds: float,
*,
on_admitted: Callable[[], None] | None = None,
) -> dict[str, Any]:
assert on_admitted is not None
on_admitted()
return {"devices": []}
monkeypatch.setattr(facade_module, "scan", empty_scan)
state = asyncio.run(service.scan_ble(1.0))
assert state["devices"] == []
assert state["connection_policy"]["actions"]["provision-fresh-device"]["allowed"] is False
assert state["connection_policy"]["facts"]["fresh_transport_refs"] == []
def test_uuid_without_exact_latest_scan_capture_cannot_retire_existing_session(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service, device_id="k1-a")
service._selected_device_id = "k1-a" # noqa: SLF001
service._connection_mode = "bridge" # noqa: SLF001
service._device_session_id = "existing-session" # noqa: SLF001
service._k1_ip = "192.168.68.50" # noqa: SLF001
monkeypatch.setattr(facade_module, "_capture_network_intent_device", lambda _device_id: None)
monkeypatch.setattr(
service,
"_retire_application_control_for_network_change",
lambda: (_ for _ in ()).throw(
AssertionError("missing exact capture must fail before ownership handoff")
),
)
with pytest.raises(facade_module.NetworkProvisioningConflict) as raised:
asyncio.run(
service.connect(
_connect_request(
device_id="k1-a",
ssid="lab-router",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
connection_mode="bridge",
compatibility_attestation=ATTESTATION,
)
)
)
assert raised.value.reason_code == "network-provision-candidate-not-fresh"
assert service._selected_device_id == "k1-a" # noqa: SLF001
assert service._connection_mode == "bridge" # noqa: SLF001
assert service._device_session_id == "existing-session" # noqa: SLF001
assert service._k1_ip == "192.168.68.50" # noqa: SLF001
def test_stale_runtime_generation_cannot_revive_live_data_plane(
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
runtime.source_mode = "live"
runtime.phase = "live"
runtime.producer_generation = 2
consumed = service._observe_runtime_message( # noqa: SLF001
StreamMessage(
sequence=7,
topic="RealtimePointcloud",
payload=b"stale",
received_at_epoch_ns=1,
received_monotonic_ns=1,
source="live_mqtt",
producer_generation=1,
),
BridgeMetrics(),
)
assert consumed is True
assert service._last_live_data_monotonic is None # noqa: SLF001
assert service._last_live_data_suspend_aware is None # noqa: SLF001
assert service._last_live_data_session_id is None # noqa: SLF001
@pytest.mark.parametrize("loss_boundary", ["control", "host"])
def test_bound_live_data_session_expires_after_control_or_host_lease_loss(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
loss_boundary: str,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
binding = _seed_supervised_connection(service)
with service._lock: # noqa: SLF001
service._compatibility_attestation = ATTESTATION.model_dump(mode="json") # noqa: SLF001
runtime.source_mode = "live"
runtime.phase = "live"
monotonic_now = [100.0]
monkeypatch.setattr(facade_module.time, "monotonic", lambda: monotonic_now[0])
supervisor = service._connection_supervisor # noqa: SLF001
data_session_id = "bound-live-data-session"
assert supervisor.observe_data_plane(
intent_id=binding.intent_id,
host_path_epoch=binding.host_path_epoch,
state="healthy",
session_id=data_session_id,
)
with service._lock: # noqa: SLF001
service._last_live_data_monotonic = monotonic_now[0] # noqa: SLF001
service._last_live_data_session_id = data_session_id # noqa: SLF001
if loss_boundary == "control":
assert supervisor.observe_control_loss(
intent_id=binding.intent_id,
host_path_epoch=binding.host_path_epoch,
control_session_id="test-control-test-ble-transport",
reason_code="test-control-loss",
)
else:
supervisor.observe_host_path(
HostPathProbeResult(
available=False,
fingerprint=None,
interface=None,
source_ipv4=None,
route_class="unavailable",
reason_code="test-host-loss",
)
)
revoked = supervisor.snapshot()
assert revoked.lease.state != "reachable"
assert revoked.data_plane.state == "healthy"
assert revoked.data_plane.host_path_epoch == binding.host_path_epoch
monotonic_now[0] += facade_module.LIVE_DATA_PLANE_STALL_SECONDS + 0.01
service._reconcile_connection_supervisor( # noqa: SLF001
{"state": "unknown"},
runtime.snapshot(),
)
stalled = supervisor.snapshot()
assert stalled.data_plane.state == "stalled"
assert stalled.data_plane.reason_code == "live-data-stalled"
assert stalled.data_plane.session_id == data_session_id
assert stalled.data_plane.host_path_epoch == binding.host_path_epoch
monotonic_now[0] = 100.0 + facade_module.LIVE_DATA_PLANE_LOST_SECONDS + 0.01
service._reconcile_connection_supervisor( # noqa: SLF001
{"state": "unknown"},
runtime.snapshot(),
)
lost = supervisor.snapshot()
assert lost.data_plane.state == "lost"
assert lost.data_plane.reason_code == "live-data-lost"
assert lost.data_plane.session_id == data_session_id
assert lost.data_plane.host_path_epoch == binding.host_path_epoch
assert (
supervisor.observe_data_plane(
intent_id=binding.intent_id,
host_path_epoch=binding.host_path_epoch,
state="healthy",
session_id="new-data-session-without-current-lease",
)
is False
)
def test_bound_live_data_session_expires_across_host_suspend(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
binding = _seed_supervised_connection(service)
runtime.source_mode = "live"
runtime.phase = "live"
monotonic_now = [300.0]
suspend_aware_now = [3_000.0]
monkeypatch.setattr(facade_module.time, "monotonic", lambda: monotonic_now[0])
monkeypatch.setattr(facade_module.time, "time", lambda: suspend_aware_now[0])
supervisor = service._connection_supervisor # noqa: SLF001
data_session_id = "pre-suspend-data-session"
assert supervisor.observe_data_plane(
intent_id=binding.intent_id,
host_path_epoch=binding.host_path_epoch,
state="healthy",
session_id=data_session_id,
)
with service._lock: # noqa: SLF001
service._last_live_data_monotonic = monotonic_now[0] # noqa: SLF001
service._last_live_data_suspend_aware = suspend_aware_now[0] # noqa: SLF001
service._last_live_data_session_id = data_session_id # noqa: SLF001
supervisor.observe_host_path(
HostPathProbeResult(
available=False,
fingerprint=None,
interface=None,
source_ipv4=None,
route_class="unavailable",
reason_code="host-suspended",
)
)
suspend_aware_now[0] += facade_module.LIVE_DATA_PLANE_STALL_SECONDS + 0.01
service._reconcile_connection_supervisor( # noqa: SLF001
{"state": "unknown"},
runtime.snapshot(),
)
assert supervisor.snapshot().data_plane.state == "stalled"
suspend_aware_now[0] = 3_000.0 + facade_module.LIVE_DATA_PLANE_LOST_SECONDS + 0.01
service._reconcile_connection_supervisor( # noqa: SLF001
{"state": "unknown"},
runtime.snapshot(),
)
lost = supervisor.snapshot()
assert lost.data_plane.state == "lost"
assert lost.data_plane.reason_code == "live-data-lost"
assert lost.data_plane.host_path_epoch == binding.host_path_epoch
def test_only_exact_bound_live_data_session_can_refresh_after_lease_loss(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
binding = _seed_supervised_connection(service)
runtime.source_mode = "live"
runtime.phase = "live"
runtime.source_ready = True
runtime.producer_generation = 4
monotonic_now = [200.0]
monkeypatch.setattr(facade_module.time, "monotonic", lambda: monotonic_now[0])
def published_point_cloud(sequence: int) -> DecodedPointCloudView:
return DecodedPointCloudView(
context=ConsumerFrameContext(
sequence=sequence,
captured_at_epoch_ns=sequence,
received_monotonic_ns=sequence,
processing_started_monotonic_ns=sequence,
encoded_size_bytes=16,
live=True,
),
frame_id="map",
positions_xyz=((0.0, 0.0, 0.0),),
)
runtime.pcl_frames = 1
service._observe_published_runtime_envelope( # noqa: SLF001
published_point_cloud(1),
runtime.producer_generation,
)
supervisor = service._connection_supervisor # noqa: SLF001
bound = supervisor.snapshot().data_plane
assert bound.state == "healthy"
assert bound.session_id == "test-session-test-ble-transport"
assert bound.host_path_epoch == binding.host_path_epoch
assert supervisor.observe_control_loss(
intent_id=binding.intent_id,
host_path_epoch=binding.host_path_epoch,
control_session_id="test-control-test-ble-transport",
reason_code="test-control-loss",
)
assert supervisor.observe_data_plane(
intent_id=binding.intent_id,
host_path_epoch=binding.host_path_epoch,
state="stalled",
session_id="test-session-test-ble-transport",
reason_code="test-data-stall",
)
monotonic_now[0] += 1.0
runtime.pcl_frames = 2
service._observe_published_runtime_envelope( # noqa: SLF001
published_point_cloud(2),
runtime.producer_generation,
)
refreshed = supervisor.snapshot()
assert refreshed.data_plane.state == "healthy"
assert refreshed.data_plane.session_id == "test-session-test-ble-transport"
assert refreshed.authority.control_allowed is False
assert refreshed.authority.data_ingest_authoritative is False
with service._lock: # noqa: SLF001
service._device_session_id = "new-session-without-current-lease" # noqa: SLF001
monotonic_now[0] += 1.0
runtime.pcl_frames = 3
service._observe_published_runtime_envelope( # noqa: SLF001
published_point_cloud(3),
runtime.producer_generation,
)
rejected_new_session = supervisor.snapshot()
assert rejected_new_session.data_plane.session_id == ("test-session-test-ble-transport")
assert service._last_live_data_session_id == ( # noqa: SLF001
"test-session-test-ble-transport"
)
def test_postpublished_pcl_rolls_same_session_to_fresh_control_epoch_after_wifi_rebind(
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
binding = _seed_supervised_connection(service)
runtime.source_mode = "live"
runtime.phase = "live"
runtime.source_ready = True
runtime.producer_generation = 4
def published_point_cloud(sequence: int) -> DecodedPointCloudView:
return DecodedPointCloudView(
context=ConsumerFrameContext(
sequence=sequence,
captured_at_epoch_ns=sequence,
received_monotonic_ns=sequence,
processing_started_monotonic_ns=sequence,
encoded_size_bytes=16,
live=True,
),
frame_id="map",
positions_xyz=((0.0, 0.0, 0.0),),
)
runtime.pcl_frames = 1
service._observe_published_runtime_envelope( # noqa: SLF001
published_point_cloud(1),
runtime.producer_generation,
)
supervisor = service._connection_supervisor # noqa: SLF001
before_loss = supervisor.snapshot()
data_session_id = "test-session-test-ble-transport"
assert before_loss.host_path.epoch == binding.host_path_epoch
assert before_loss.data_plane.session_id == data_session_id
assert before_loss.data_plane.host_path_epoch == binding.host_path_epoch
supervisor.observe_host_path(
HostPathProbeResult(
available=False,
fingerprint=None,
interface=None,
source_ipv4=None,
route_class="unavailable",
reason_code="host-route-unavailable",
)
)
rebound_epoch = supervisor.observe_host_path(
HostPathProbeResult(
available=True,
fingerprint="route-after-wifi-return",
interface="test0",
source_ipv4="192.168.1.2",
route_class="direct",
kernel_route_fingerprint="route-after-wifi-return",
)
)
target = EndpointTarget(binding.target_ipv4, binding.target_port)
assert supervisor.observe_endpoint(
target=target,
intent_id=binding.intent_id,
host_path_epoch=rebound_epoch,
reachable=True,
)
assert supervisor.observe_control_evidence(
VerifiedControlEvidence(
intent_id=binding.intent_id,
transport_ref=binding.transport_ref,
host_path_epoch=rebound_epoch,
target=target,
connection_mode=binding.connection_mode,
logical_device_id="known-k1",
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
control_session_id="post-wifi-control",
control_proof_revision=2,
control_proof_source="correlated-application-response",
)
)
rebound = supervisor.snapshot()
assert rebound.host_path.epoch == rebound_epoch
assert rebound.authority.control_allowed is True
assert rebound.data_plane.session_id == data_session_id
assert rebound.data_plane.host_path_epoch == binding.host_path_epoch
assert rebound.authority.data_ingest_authoritative is False
runtime.pcl_frames = 2
service._observe_published_runtime_envelope( # noqa: SLF001
published_point_cloud(2),
runtime.producer_generation,
)
recovered = supervisor.snapshot()
assert recovered.data_plane.state == "healthy"
assert recovered.data_plane.session_id == data_session_id
assert recovered.data_plane.host_path_epoch == rebound_epoch
assert recovered.data_plane.host_path_epoch == recovered.host_path.epoch
assert recovered.authority.data_ingest_authoritative is True
def test_pose_only_traffic_cannot_refresh_point_cloud_health_during_recovery(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
binding = _seed_supervised_connection(service)
runtime.source_mode = "live"
runtime.phase = "live"
runtime.source_ready = True
runtime.producer_generation = 4
now = [100.0]
monkeypatch.setattr(facade_module.time, "monotonic", lambda: now[0])
monkeypatch.setattr(facade_module.time, "time", lambda: now[0])
def packet(sequence: int, topic: str) -> StreamMessage:
return StreamMessage(
sequence=sequence,
topic=topic,
payload=b"data-plane-evidence",
received_at_epoch_ns=sequence,
received_monotonic_ns=sequence,
source="live_mqtt",
producer_generation=4,
)
baseline = DecodedPointCloudView(
context=ConsumerFrameContext(
sequence=1,
captured_at_epoch_ns=1,
received_monotonic_ns=1,
processing_started_monotonic_ns=1,
encoded_size_bytes=16,
live=True,
),
frame_id="map",
positions_xyz=((0.0, 0.0, 0.0),),
)
runtime.pcl_frames = 1
service._observe_published_runtime_envelope( # noqa: SLF001
baseline,
runtime.producer_generation,
)
assert service._last_live_data_monotonic == 100.0 # noqa: SLF001
assert service._connection_supervisor.snapshot().data_plane.state == "healthy" # noqa: SLF001
runtime.phase = "reconnecting"
runtime.source_ready = False
runtime.recovery_state = "reconnecting"
now[0] += facade_module.LIVE_DATA_PLANE_STALL_SECONDS + 0.01
service._observe_runtime_message( # noqa: SLF001
packet(2, "lixel/application/report/lio_pose"),
BridgeMetrics(),
)
assert service._last_live_data_monotonic == 100.0 # noqa: SLF001
service._observe_runtime_message( # noqa: SLF001
packet(3, "RealtimePointcloud"),
BridgeMetrics(),
)
assert service._last_live_data_monotonic == 100.0 # noqa: SLF001
service._reconcile_connection_supervisor( # noqa: SLF001
{"state": "unknown"},
runtime.snapshot(),
)
assert service._connection_supervisor.snapshot().data_plane.state == "stalled" # noqa: SLF001
now[0] = 100.0 + facade_module.LIVE_DATA_PLANE_LOST_SECONDS + 0.01
service._observe_runtime_message( # noqa: SLF001
packet(4, "RealtimePath"),
BridgeMetrics(),
)
assert service._last_live_data_monotonic == 100.0 # noqa: SLF001
service._reconcile_connection_supervisor( # noqa: SLF001
{"state": "unknown"},
runtime.snapshot(),
)
lost = service._connection_supervisor.snapshot().data_plane # noqa: SLF001
assert lost.state == "lost"
assert lost.reason_code == "live-data-lost"
assert lost.host_path_epoch == binding.host_path_epoch
def test_new_ble_scan_generation_invalidates_old_candidates_before_io_and_on_failure(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service, device_id="old-scan-device")
async def scenario() -> None:
entered = asyncio.Event()
release = asyncio.Event()
async def failing_scan(
_duration_seconds: float,
*,
on_admitted: Callable[[], None] | None = None,
) -> dict[str, Any]:
if on_admitted is not None:
on_admitted()
entered.set()
await release.wait()
raise RuntimeError("synthetic BLE scan failure")
monkeypatch.setattr(facade_module, "scan", failing_scan)
scan_task = asyncio.create_task(service.scan_ble(6.0))
await asyncio.wait_for(entered.wait(), timeout=1.0)
assert service.state()["devices"] == []
release.set()
with pytest.raises(RuntimeError, match="synthetic BLE scan failure"):
await asyncio.wait_for(scan_task, timeout=1.0)
asyncio.run(scenario())
failed_state = service.state()
assert failed_state["devices"] == []
assert service._devices == [] # noqa: SLF001
assert service._ble_device_last_seen_monotonic == {} # noqa: SLF001
failed_operation = failed_state["last_operation"]
assert failed_operation["status"] == "failed"
assert failed_operation["error"] == {
"category": "transport",
"code": "RuntimeError",
"retryable": True,
"safe_to_retry": True,
"side_effect_status": "none",
}
def test_ble_scan_operation_id_is_exactly_once_and_request_bound(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
transport_calls = 0
async def successful_scan(
_duration_seconds: float,
*,
on_admitted: Callable[[], None] | None = None,
) -> dict[str, Any]:
nonlocal transport_calls
if on_admitted is not None:
on_admitted()
transport_calls += 1
return _ble_scan_result("exactly-once-device")
monkeypatch.setattr(facade_module, "scan", successful_scan)
operation_id = "op-00000000-0000-4000-8000-000000000001"
request = BleScanRequest(duration_seconds=6.0, operation_id=operation_id)
first = asyncio.run(service.scan_ble(request))
repeated = asyncio.run(service.scan_ble(request))
assert transport_calls == 1
assert first["devices"][0]["connectable"] is None
assert first["last_operation"]["operation_id"] == operation_id
assert repeated["last_operation"]["operation_id"] == operation_id
with pytest.raises(ValueError, match="different request"):
asyncio.run(
service.scan_ble(
BleScanRequest(
duration_seconds=7.0,
operation_id=operation_id,
)
)
)
def test_ble_scan_maps_process_runtime_busy_to_operation_journal(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service, device_id="active-scan-result")
service._operation_phase = "scanning" # noqa: SLF001
async def scenario() -> tuple[Any, dict[str, Any]]:
async def busy_scan(
_duration_seconds: float,
*,
on_admitted: Callable[[], None] | None = None,
) -> dict[str, Any]:
del on_admitted
raise BleRuntimeBusy(
active_operation_kind="status-read",
cleanup_pending=False,
)
monkeypatch.setattr(facade_module, "scan", busy_scan)
with pytest.raises(BleRuntimeBusy, match="уже выполняется"):
await service.scan_ble(6.0)
assert service._operation_phase == "scanning" # noqa: SLF001
rejected_state = service.state()
async def recovered_scan(
_duration_seconds: float,
*,
on_admitted: Callable[[], None] | None = None,
) -> dict[str, Any]:
if on_admitted is not None:
on_admitted()
return _ble_scan_result("second-generation")
monkeypatch.setattr(facade_module, "scan", recovered_scan)
recovered_state = await service.scan_ble(6.0)
return rejected_state, recovered_state
rejected_state, recovered_state = asyncio.run(scenario())
assert [item["device_id"] for item in rejected_state["devices"]] == ["active-scan-result"]
rejected_operation = rejected_state["last_operation"]
assert rejected_operation["status"] == "failed"
assert rejected_operation["stage_code"] == "busy"
assert rejected_operation["message_code"] == "discovery.scan.already_running"
assert rejected_operation["error"] == {
"category": "conflict",
"code": "ble-runtime-busy",
"retryable": True,
"safe_to_retry": True,
"side_effect_status": "none",
}
assert [item["device_id"] for item in recovered_state["devices"]] == ["second-generation"]
def test_ble_scan_does_not_block_owner_loop_on_sync_lifecycle_gate(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
gate_held = threading.Event()
release_gate = threading.Event()
def hold_sync_lifecycle_gate() -> None:
with service._acquisition_lifecycle_gate: # noqa: SLF001
gate_held.set()
release_gate.wait(timeout=2.0)
holder = threading.Thread(target=hold_sync_lifecycle_gate)
holder.start()
assert gate_held.wait(timeout=1.0)
async def admitted_scan(
_duration_seconds: float,
*,
on_admitted: Callable[[], None] | None = None,
) -> dict[str, Any]:
if on_admitted is not None:
on_admitted()
release_gate.set()
return _ble_scan_result("nonblocking-scan")
monkeypatch.setattr(facade_module, "scan", admitted_scan)
started_at = time.monotonic()
started = asyncio.run(service.scan_ble(6.0))
elapsed = time.monotonic() - started_at
holder.join(timeout=1.0)
assert not holder.is_alive()
assert elapsed < 0.5
assert [item["device_id"] for item in started["devices"]] == ["nonblocking-scan"]
def test_ble_scan_maps_hard_timeout_to_operation_journal(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
async def scenario() -> tuple[dict[str, Any], dict[str, Any]]:
async def timed_out_scan(
_duration_seconds: float,
*,
on_admitted: Callable[[], None] | None = None,
) -> dict[str, Any]:
if on_admitted is not None:
on_admitted()
raise BleOperationHardTimeout(
"scan",
BleOperationProgress(operation_stage="discovery"),
)
monkeypatch.setattr(facade_module, "scan", timed_out_scan)
with pytest.raises(BleOperationHardTimeout, match="не завершилась"):
await service.scan_ble(6.0)
assert service._operation_phase is None # noqa: SLF001
failed_state = service.state()
async def recovered_scan(
_duration_seconds: float,
*,
on_admitted: Callable[[], None] | None = None,
) -> dict[str, Any]:
if on_admitted is not None:
on_admitted()
return _ble_scan_result("after-timeout")
monkeypatch.setattr(facade_module, "scan", recovered_scan)
recovered_state = await service.scan_ble(6.0)
return failed_state, recovered_state
failed_state, recovered_state = asyncio.run(scenario())
assert failed_state["devices"] == []
failed_operation = failed_state["last_operation"]
assert failed_operation["status"] == "failed"
assert failed_operation["error"] == {
"category": "transport",
"code": "ble-discovery-timeout",
"retryable": True,
"safe_to_retry": True,
"side_effect_status": "none",
"operation_stage": "discovery",
"device_write_attempted": False,
"device_write_confirmed": False,
"host_diagnostic": {
"schema_version": "missioncore.host-failure-diagnostic/v1",
"code": "host.bluetooth.operation-timeout",
"domain": "corebluetooth",
"impact": "discovery",
"operator_action": "explicit-retry",
"automatic_retry": False,
"redacted": True,
},
}
assert [item["device_id"] for item in recovered_state["devices"]] == ["after-timeout"]
def test_cancelled_ble_scan_is_journaled_and_releases_process_gate(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
async def scenario() -> tuple[dict[str, Any], dict[str, Any]]:
transport_entered = asyncio.Event()
transport_cancelled = asyncio.Event()
async def blocked_scan(
_duration_seconds: float,
*,
on_admitted: Callable[[], None] | None = None,
) -> dict[str, Any]:
if on_admitted is not None:
on_admitted()
transport_entered.set()
try:
await asyncio.Event().wait()
except asyncio.CancelledError:
transport_cancelled.set()
raise
monkeypatch.setattr(facade_module, "scan", blocked_scan)
scan_task = asyncio.create_task(service.scan_ble(6.0))
await asyncio.wait_for(transport_entered.wait(), timeout=1.0)
scan_task.cancel()
with pytest.raises(asyncio.CancelledError):
await scan_task
assert transport_cancelled.is_set()
assert service._operation_phase is None # noqa: SLF001
cancelled_state = service.state()
async def recovered_scan(
_duration_seconds: float,
*,
on_admitted: Callable[[], None] | None = None,
) -> dict[str, Any]:
if on_admitted is not None:
on_admitted()
return _ble_scan_result("after-cancellation")
monkeypatch.setattr(facade_module, "scan", recovered_scan)
recovered_state = await service.scan_ble(6.0)
return cancelled_state, recovered_state
cancelled_state, recovered_state = asyncio.run(scenario())
assert cancelled_state["devices"] == []
cancelled_operation = cancelled_state["last_operation"]
assert cancelled_operation["status"] == "cancelled"
assert cancelled_operation["stage_code"] == "cancelled"
assert cancelled_operation["message_code"] == "discovery.scan.cancelled"
assert cancelled_operation["error"] == {
"category": "transport",
"code": "ble-discovery-cancelled",
"retryable": True,
"safe_to_retry": True,
"side_effect_status": "none",
}
assert [item["device_id"] for item in recovered_state["devices"]] == ["after-cancellation"]
def test_connect_owns_lifecycle_while_safe_preflight_rejects_a_competing_scan(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service)
mode_revision = _select_connection_mode(service, "quick-connect")
preflight_entered = threading.Event()
release_preflight = threading.Event()
def delayed_preflight(*_: object, **__: object) -> dict[str, Any]:
preflight_entered.set()
if not release_preflight.wait(timeout=1.0):
raise RuntimeError("test preflight release timed out")
return {
"schema_version": 1,
"adapter": "macOS Keychain",
"available": False,
"profile_enrolled": False,
"credential_source": "exact-firmware-profile",
}
async def replacement_scan(
_duration_seconds: float,
*,
on_admitted: Callable[[], None] | None = None,
) -> dict[str, Any]:
if on_admitted is not None:
on_admitted()
return {
"devices": [
{
"macos_uuid": "replacement-device",
"name": "XGR-NEW",
"local_name": "XGR-NEW",
"rssi": -40,
"k1_name_candidate": True,
}
]
}
@asynccontextmanager
async def forbidden_activation(
*_args: object,
**_kwargs: object,
) -> AsyncIterator[dict[str, Any]]:
raise AssertionError("changed discovery generation must stop before BLE write")
yield {}
monkeypatch.setattr(
facade_module,
"ensure_wifi_profile_from_credential_source",
delayed_preflight,
)
monkeypatch.setattr(facade_module, "scan", replacement_scan)
monkeypatch.setattr(facade_module, "device_ap_activation_session", forbidden_activation)
async def scenario() -> None:
connect_task = asyncio.create_task(
service.connect(
_connect_request(
device_id="test-ble-transport",
connection_mode="quick-connect",
compatibility_attestation=QUICK_CONNECT_ATTESTATION,
expected_mode_revision=mode_revision,
)
)
)
entered = await asyncio.wait_for(
asyncio.to_thread(preflight_entered.wait, 1.0),
timeout=1.5,
)
assert entered is True
with pytest.raises(
facade_module.BleDiscoveryUnavailable,
match="настройки Wi-Fi",
) as scan_failure:
await service.scan_ble(6.0)
assert scan_failure.value.reason_code == "ble-discovery-blocked-by-provisioning"
release_preflight.set()
with pytest.raises(facade_module.HostWifiProfileError):
await asyncio.wait_for(connect_task, timeout=1.0)
try:
asyncio.run(scenario())
finally:
release_preflight.set()
def test_provision_scan_is_rejected_after_atomic_fence_before_control_retirement(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service, device_id="k1-a")
generation_before = service._ble_discovery_generation # noqa: SLF001
scan_outcomes: list[object] = []
provision_calls = 0
async def racing_scan(
_duration_seconds: float,
*,
on_admitted: Callable[[], None] | None = None,
) -> dict[str, Any]:
assert on_admitted is not None
on_admitted()
return _ble_scan_result("racing-scan")
original_retire = service._retire_application_control_for_network_change # noqa: SLF001
def retire_with_competing_scan() -> None:
assert service._provisioning_active is True # noqa: SLF001
scan_outcomes.append(
_attempt_competing_scan_from_sync_boundary(
service,
operation_id="op-00000000-0000-4000-8000-000000000101",
)
)
original_retire()
async def fake_provision(
*_: object,
on_write_dispatch: Callable[[dict[str, Any], str], None] | None = None,
**__: object,
) -> dict[str, Any]:
nonlocal provision_calls
provision_calls += 1
assert service._provisioning_active is True # noqa: SLF001
_dispatch_test_network_write(on_write_dispatch)
return {
"started_at_utc": "2026-08-06T12:00:00Z",
"completed_at_utc": "2026-08-06T12:00:01Z",
"profile_id": "xgrids-k1-fw3-wifi-v1",
"outcome": "lan_address_observed",
"write_mode": "with_response",
"observations": [
{
"status": {
"mode": "WIFI_CLIENT",
"ipv4": "192.168.68.50",
"status_code": 1,
"reserved": 0,
}
}
],
}
monkeypatch.setattr(facade_module, "scan", racing_scan)
monkeypatch.setattr(
service,
"_retire_application_control_for_network_change",
retire_with_competing_scan,
)
monkeypatch.setattr(facade_module, "provision_wifi_once", fake_provision)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(facade_module, "_host_route_class", lambda _target: "direct-or-routed")
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
monkeypatch.setattr(facade_module, "_control_endpoint_reachable", lambda _target: True)
monkeypatch.setattr(
facade_module,
"_await_control_endpoint_reachable",
_reachable_control_endpoint,
)
connected = asyncio.run(
service.connect(
_connect_request(
device_id="k1-a",
ssid="lab-router",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
connection_mode="bridge",
compatibility_attestation=ATTESTATION,
)
)
)
assert len(scan_outcomes) == 1
scan_error = scan_outcomes[0]
assert isinstance(scan_error, facade_module.BleDiscoveryUnavailable)
assert scan_error.reason_code == "ble-discovery-blocked-by-provisioning"
assert service._ble_discovery_generation == generation_before # noqa: SLF001
assert [item["device_id"] for item in connected["devices"]] == ["k1-a"]
assert provision_calls == 1
assert connected["connection_mode"] == "bridge"
assert service._provisioning_active is False # noqa: SLF001
scan_operation = next(
item
for item in connected["operations"]
if item["operation_id"] == "op-00000000-0000-4000-8000-000000000101"
)
assert scan_operation["status"] == "failed"
assert scan_operation["error"]["code"] == "ble-discovery-blocked-by-provisioning"
def test_corrupt_identity_pin_store_fails_after_new_intent_retires_old_control(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service, device_id="k1-a")
retire_calls = 0
def corrupt_identity_lookup(_transport_ref: str) -> None:
raise DeviceIdentityPinStoreCorrupt("synthetic corrupt pin store")
def record_retirement() -> None:
nonlocal retire_calls
retire_calls += 1
async def forbidden_provision(*_: object, **__: object) -> dict[str, Any]:
raise AssertionError("identity preflight must fail before the BLE write boundary")
monkeypatch.setattr(service, "_expected_vendor_device_id", corrupt_identity_lookup)
monkeypatch.setattr(
service,
"_retire_application_control_for_network_change",
record_retirement,
)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_provision)
with pytest.raises(
DeviceIdentityPinStoreCorrupt,
match="synthetic corrupt pin store",
):
asyncio.run(
service.connect(
_connect_request(
device_id="k1-a",
ssid="lab-router",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
connection_mode="bridge",
compatibility_attestation=ATTESTATION,
)
)
)
assert retire_calls == 1
assert service._provisioning_active is False # noqa: SLF001
assert service._ble_discovery_generation == 0 # noqa: SLF001
assert [item["device_id"] for item in service.state()["devices"]] == ["k1-a"]
def test_unavailable_semantic_topology_store_fails_after_new_intent_retirement_without_write(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service, device_id="k1-a")
service._semantic_topology_store = None # noqa: SLF001
retire_calls = 0
def record_retirement() -> None:
nonlocal retire_calls
retire_calls += 1
async def forbidden_provision(*_: object, **__: object) -> dict[str, Any]:
raise AssertionError("semantic store preflight must fail before the BLE write boundary")
monkeypatch.setattr(
service,
"_retire_application_control_for_network_change",
record_retirement,
)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_provision)
with pytest.raises(
SemanticTopologyStoreCorrupt,
match="semantic topology store is unavailable",
):
asyncio.run(
service.connect(
_connect_request(
device_id="k1-a",
ssid="lab-router",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
connection_mode="bridge",
compatibility_attestation=ATTESTATION,
)
)
)
assert retire_calls == 1
assert service._provisioning_active is False # noqa: SLF001
assert service._provisioning_gate.locked() is False # noqa: SLF001
assert service._ble_discovery_generation == 0 # noqa: SLF001
assert [item["device_id"] for item in service.state()["devices"]] == ["k1-a"]
def test_verify_connection_adopts_scanned_existing_lan_without_device_write(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
# Ordinary topology adoption must still retire unrelated terminal local
# history. Only a later exact physical SCANNING reconciliation may
# materialize the bounded recovery-only STOP identity.
service._acquisition = facade_module.AcquisitionRecord( # noqa: SLF001
acquisition_id="stale-terminal-acquisition",
device_id="stale-device",
device_session_id="stale-device-session",
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
control_mode="plugin-commanded",
requested_streams=(),
target_host="192.168.68.99",
duration_seconds=None,
evidence_policy="disabled",
state="failed",
)
service._acquisition_project_name = "STALE" # noqa: SLF001
_set_scanned_k1(service)
status_reads: list[tuple[str, float, bool]] = []
async def fake_status_read(
device_id: str,
*,
timeout_seconds: float,
rediscover: bool,
**_: object,
) -> dict[str, Any]:
status_reads.append((device_id, timeout_seconds, rediscover))
return _wifi_status_read("10.255.254.77")
async def forbidden_provision(*_: object, **__: object) -> dict[str, Any]:
raise AssertionError("connection.verify must never call Wi-Fi provisioning")
monkeypatch.setattr(facade_module, "read_wifi_status_once", fake_status_read)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_provision)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(facade_module, "_host_route_class", lambda _target: "direct-or-routed")
monkeypatch.setattr(facade_module, "_control_endpoint_reachable", lambda _target: True)
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
state = asyncio.run(
service.verify_connection(
ConnectionVerifyRequest(
device_id="test-ble-transport",
compatibility_attestation=ATTESTATION,
expected_discovery_generation=0,
)
)
)
assert status_reads == [("test-ble-transport", 20.0, False)]
assert state["selected_device_id"] == "test-ble-transport"
assert state["k1_ip"] == "10.255.254.77"
assert state["connection_mode"] == "bridge"
assert state["device_ref"]["transport_alias"] == "test-ble-transport"
assert state["device_session"]["connectivity"] == "connected"
assert state["compatibility"]["attestation"]["topology"] == "direct-lan"
assert state["connection_verification"] == {
"status": "reachable",
"lease_state": "reachable",
"lease_generation": state["connection_supervisor"]["lease"]["generation"],
"endpoint_validation": "ble-wifi-status-read+mqtt-tcp-connect",
"network_reachability": "reachable",
"host_route_class": "direct-or-routed",
"address_source": "ble-wifi-status-read",
"connection_origin": "external-existing-network",
"admission_source": "connection.verify",
"address_changed": True,
"previous_address_present": False,
"write_performed": False,
"observed_at": "2026-07-20T12:00:00Z",
"reason_code": None,
"supervisor_revision": state["connection_verification"]["supervisor_revision"],
}
assert state["last_operation"]["action"] == "connection.verify"
assert state["last_operation"]["status"] == "succeeded"
assert state["last_operation"]["result"]["write_performed"] is False
assert state["last_operation"]["result"]["control_verified"] is True
assert state["connection_lifecycle"]["connection_ready"] is True
assert state["connection_lifecycle"]["active_mode"] == "bridge"
assert state["acquisition"] is None
assert service._acquisition_project_name is None # noqa: SLF001
def test_read_only_verify_scan_is_rejected_after_atomic_fence_before_admission(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service)
generation_before = service._ble_discovery_generation # noqa: SLF001
scan_outcomes: list[object] = []
admission_calls = 0
async def racing_scan(
_duration_seconds: float,
*,
on_admitted: Callable[[], None] | None = None,
) -> dict[str, Any]:
assert on_admitted is not None
on_admitted()
return _ble_scan_result("racing-scan")
async def fake_status_read(*_: object, **__: object) -> dict[str, Any]:
return _wifi_status_read("10.255.254.77")
original_retire = service._retire_application_control_for_network_change # noqa: SLF001
original_apply = service._apply_read_only_device_topology # noqa: SLF001
def retire_with_competing_scan(*, allow_terminal_failure: bool = False) -> None:
assert service._provisioning_active is True # noqa: SLF001
scan_outcomes.append(
_attempt_competing_scan_from_sync_boundary(
service,
operation_id="op-00000000-0000-4000-8000-000000000102",
)
)
original_retire(allow_terminal_failure=allow_terminal_failure)
def apply_with_fence_assertion(**kwargs: Any) -> str:
nonlocal admission_calls
admission_calls += 1
assert service._provisioning_active is True # noqa: SLF001
return original_apply(**kwargs)
monkeypatch.setattr(facade_module, "scan", racing_scan)
monkeypatch.setattr(facade_module, "read_wifi_status_once", fake_status_read)
monkeypatch.setattr(
service,
"_retire_application_control_for_network_change",
retire_with_competing_scan,
)
monkeypatch.setattr(
service,
"_apply_read_only_device_topology",
apply_with_fence_assertion,
)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(facade_module, "_host_route_class", lambda _target: "direct-or-routed")
monkeypatch.setattr(facade_module, "_control_endpoint_reachable", lambda _target: True)
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
verified = asyncio.run(
service.verify_connection(
ConnectionVerifyRequest(
device_id="test-ble-transport",
compatibility_attestation=ATTESTATION,
expected_discovery_generation=0,
)
)
)
assert len(scan_outcomes) == 1
scan_error = scan_outcomes[0]
assert isinstance(scan_error, facade_module.BleDiscoveryUnavailable)
assert scan_error.reason_code == "ble-discovery-blocked-by-provisioning"
assert service._ble_discovery_generation == generation_before # noqa: SLF001
assert [item["device_id"] for item in verified["devices"]] == ["test-ble-transport"]
assert admission_calls == 1
assert verified["connection_mode"] == "bridge"
assert verified["k1_ip"] == "10.255.254.77"
assert service._provisioning_active is False # noqa: SLF001
scan_operation = next(
item
for item in verified["operations"]
if item["operation_id"] == "op-00000000-0000-4000-8000-000000000102"
)
assert scan_operation["status"] == "failed"
assert scan_operation["error"]["code"] == "ble-discovery-blocked-by-provisioning"
def test_connection_verify_operation_id_is_exactly_once_and_request_bound(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service)
status_reads = 0
async def fake_status_read(*_: object, **__: object) -> dict[str, Any]:
nonlocal status_reads
status_reads += 1
return _wifi_status_read("10.255.254.77")
monkeypatch.setattr(facade_module, "read_wifi_status_once", fake_status_read)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(facade_module, "_host_route_class", lambda _target: "direct-or-routed")
monkeypatch.setattr(facade_module, "_control_endpoint_reachable", lambda _target: True)
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
operation_id = "op-00000000-0000-4000-8000-000000000002"
request = ConnectionVerifyRequest(
device_id="test-ble-transport",
compatibility_attestation=ATTESTATION,
operation_id=operation_id,
expected_discovery_generation=0,
)
first = asyncio.run(service.verify_connection(request))
repeated = asyncio.run(service.verify_connection(request))
assert status_reads == 1
assert first["last_operation"]["operation_id"] == operation_id
assert repeated["last_operation"]["operation_id"] == operation_id
assert first["last_operation"]["result"]["lease_state"] == "reachable"
assert first["last_operation"]["result"]["lease_generation"] == (
first["connection_supervisor"]["lease"]["generation"]
)
with pytest.raises(ValueError, match="different request"):
asyncio.run(
service.verify_connection(
ConnectionVerifyRequest(
device_id="different-k1",
compatibility_attestation=ATTESTATION,
operation_id=operation_id,
expected_discovery_generation=0,
)
)
)
def test_verify_connection_adoption_requires_current_scan_candidate(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
async def forbidden_status_read(*_: object, **__: object) -> dict[str, Any]:
raise AssertionError("an unscanned device must not be probed")
async def forbidden_provision(*_: object, **__: object) -> dict[str, Any]:
raise AssertionError("connection.verify must never call Wi-Fi provisioning")
monkeypatch.setattr(facade_module, "read_wifi_status_once", forbidden_status_read)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_provision)
with pytest.raises(
facade_module.ConnectionVerificationError,
match="свежего кандидата",
) as raised:
asyncio.run(
service.verify_connection(
ConnectionVerifyRequest(
device_id="not-in-current-scan",
compatibility_attestation=ATTESTATION,
expected_discovery_generation=0,
)
)
)
assert raised.value.reason_code == "connection-verify-candidate-not-fresh"
operation = service.state()["last_operation"]
assert operation["action"] == "connection.verify"
assert operation["status"] == "failed"
assert operation["error"] == {
"category": "connection",
"code": "connection-verify-candidate-not-fresh",
"retryable": True,
"safe_to_retry": True,
"side_effect_status": "none",
}
def test_verify_connection_timeout_is_journaled_without_device_side_effect(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
caplog: pytest.LogCaptureFixture,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service)
async def timed_out_status_read(*_: object, **__: object) -> dict[str, Any]:
failure = TimeoutError("synthetic private transport detail")
failure.operation_stage = "exact-uuid-scan" # type: ignore[attr-defined]
raise failure
monkeypatch.setattr(facade_module, "read_wifi_status_once", timed_out_status_read)
with (
caplog.at_level(logging.INFO, logger=facade_module.__name__),
pytest.raises(
facade_module.ConnectionVerificationError,
match="не завершил ожидание точного",
) as raised,
):
asyncio.run(
service.verify_connection(
ConnectionVerifyRequest(
device_id="test-ble-transport",
compatibility_attestation=ATTESTATION,
expected_discovery_generation=0,
)
)
)
assert raised.value.reason_code == "connection-verify-exact-uuid-scan-timeout"
operation = service.state()["last_operation"]
assert operation["error"] == {
"category": "connection",
"code": "connection-verify-exact-uuid-scan-timeout",
"retryable": True,
"safe_to_retry": True,
"side_effect_status": "none",
"operation_stage": "exact-uuid-scan",
}
accepted_at = datetime.fromisoformat(operation["accepted_at"])
deadline_at = datetime.fromisoformat(operation["deadline_at"])
assert (deadline_at - accepted_at).total_seconds() == (
facade_module.CONNECTION_VERIFY_HARD_TIMEOUT_SECONDS
)
failure_log = next(
record
for record in caplog.records
if getattr(record, "event_code", None) == "k1_connection_verify_failed"
)
assert failure_log.operation_stage == "exact-uuid-scan"
assert failure_log.reason_code == "connection-verify-exact-uuid-scan-timeout"
assert failure_log.failure_category == "timeout"
assert failure_log.device_write_performed is False
assert failure_log.automatic_retry is False
assert "private" not in str(operation)
assert "private" not in caplog.text
def test_connection_lease_probe_race_is_an_expected_state_conflict() -> None:
failure = facade_module._connection_verification_error( # noqa: SLF001
facade_module.ConnectionLeaseUnavailable(
"private concurrent lease mutation detail",
reason_code="connection_lease_changed_during_probe",
)
)
assert failure.reason_code == "connection-verify-lease-changed"
assert str(failure) == "Подключение K1 изменилось во время read-only проверки"
assert "private" not in str(failure)
def test_read_only_gatt_contract_is_logged_before_missing_dhcp_rejection(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
caplog: pytest.LogCaptureFixture,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service)
async def status_without_lan_address(*_: object, **__: object) -> dict[str, Any]:
return _wifi_status_read(None)
monkeypatch.setattr(
facade_module,
"read_wifi_status_once",
status_without_lan_address,
)
with (
caplog.at_level(logging.INFO, logger=facade_module.__name__),
pytest.raises(facade_module.ConnectionVerificationError) as raised,
):
asyncio.run(
service.verify_connection(
ConnectionVerifyRequest(
device_id="test-ble-transport",
compatibility_attestation=ATTESTATION,
expected_discovery_generation=0,
)
)
)
assert raised.value.reason_code == "connection-verify-address-unavailable"
contract_log = next(
record
for record in caplog.records
if getattr(record, "event_code", None) == "k1_ble_gatt_contract_observed"
)
assert contract_log.write_characteristic_properties == ["read", "write"]
assert contract_log.max_write_without_response_size == 253
assert contract_log.mtu_size == 256
assert contract_log.bridge_frame_length == 99
assert contract_log.quick_connect_frame_length == 100
assert contract_log.device_write_performed is False
assert contract_log.automatic_retry is False
assert "device_macos_uuid" not in contract_log.__dict__
assert "write_characteristic_uuid" not in contract_log.__dict__
@pytest.mark.parametrize(
("cleanup_pending", "reason_code"),
[
(False, "connection-verify-busy"),
(True, "connection-verify-cleanup-pending"),
],
)
def test_verify_connection_preserves_process_ble_busy_state(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
cleanup_pending: bool,
reason_code: str,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service)
async def busy_status_read(*_: object, **__: object) -> dict[str, Any]:
raise BleRuntimeBusy(
active_operation_kind="scan",
cleanup_pending=cleanup_pending,
)
monkeypatch.setattr(facade_module, "read_wifi_status_once", busy_status_read)
with pytest.raises(facade_module.ConnectionVerificationError) as raised:
asyncio.run(
service.verify_connection(
ConnectionVerifyRequest(
device_id="test-ble-transport",
compatibility_attestation=ATTESTATION,
expected_discovery_generation=0,
)
)
)
assert raised.value.reason_code == reason_code
operation = service.state()["last_operation"]
assert operation["error"] == {
"category": "connection",
"code": reason_code,
"retryable": True,
"safe_to_retry": True,
"side_effect_status": "none",
}
@pytest.mark.parametrize(
("ipv4", "is_local", "route_class", "endpoint_reachable", "reason_code"),
[
(None, False, "direct-or-routed", True, "connection-verify-address-unavailable"),
(
"192.168.56.1",
False,
"device-ap",
True,
"connection-verify-address-unavailable",
),
(
"10.255.254.77",
True,
"direct-or-routed",
True,
"connection-verify-local-address-conflict",
),
("10.255.254.77", False, "tunnel", True, "connection-verify-route-mismatch"),
(
"10.255.254.77",
False,
"default-route",
True,
"connection-verify-route-mismatch",
),
(
"10.255.254.77",
False,
"direct-or-routed",
False,
"connection-verify-mqtt-unreachable",
),
],
)
def test_verify_connection_adoption_fails_closed_before_establishing_lease(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
ipv4: str | None,
is_local: bool,
route_class: str,
endpoint_reachable: bool,
reason_code: str,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service)
async def fake_status_read(*_: object, **__: object) -> dict[str, Any]:
return _wifi_status_read(ipv4)
async def forbidden_provision(*_: object, **__: object) -> dict[str, Any]:
raise AssertionError("connection.verify must never call Wi-Fi provisioning")
monkeypatch.setattr(facade_module, "read_wifi_status_once", fake_status_read)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_provision)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: is_local)
monkeypatch.setattr(facade_module, "_host_route_class", lambda _target: route_class)
monkeypatch.setattr(
facade_module,
"_control_endpoint_reachable",
lambda _target: endpoint_reachable,
)
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
with pytest.raises(facade_module.ConnectionVerificationError) as raised:
asyncio.run(
service.verify_connection(
ConnectionVerifyRequest(
device_id="test-ble-transport",
compatibility_attestation=ATTESTATION,
expected_discovery_generation=0,
)
)
)
assert raised.value.reason_code == reason_code
state = service.state()
assert [item["device_id"] for item in state["devices"]] == ["test-ble-transport"]
# Fresh Bridge 7f02 evidence is provisional until route/TCP and exact
# DeviceInfo identity all succeed. Any failure before that point retires
# only the ephemeral projection, retains the fresh candidate for a later
# explicit choice, and never publishes untrusted durable topology.
assert state["selected_device_id"] is None
assert state["k1_ip"] is None
assert state["connection_mode"] is None
assert state["device_session"] is None
assert state["semantic_topology_store"]["status"] == "empty"
assert state["connection_supervisor"]["authority"]["control_allowed"] is False
assert state["connection_verification"].get("write_performed") is not True
def test_apply_owned_rescan_after_unreachable_verify_dispatches_exactly_one_write(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
device_id = "k1-verify-then-apply"
_set_scanned_k1(service, device_id=device_id)
old_capture = _SYNTHETIC_SCAN_CAPTURES[device_id]
replacement_capture = facade_module.CapturedDiscoveredDevice(
device=SimpleNamespace(address=device_id), # type: ignore[arg-type]
macos_uuid=device_id,
owner_epoch=old_capture.owner_epoch,
scan_generation=old_capture.scan_generation + 1,
)
active_capture = old_capture
invalidated_capture_ids: set[int] = set()
pinned_by_session: dict[str, facade_module.CapturedDiscoveredDevice] = {}
def exact_capture(requested_device_id: str) -> object | None:
assert requested_device_id == device_id
if id(active_capture) in invalidated_capture_ids:
return None
return active_capture
def pin_exact_capture(
capture: facade_module.CapturedDiscoveredDevice,
*,
device_session_id: str,
) -> None:
assert capture is active_capture
pinned_by_session[device_session_id] = capture
def invalidate_exact_session(
requested_device_id: str,
*,
device_session_id: str,
) -> bool:
assert requested_device_id == device_id
retired = pinned_by_session.pop(device_session_id, None)
if retired is None:
return False
invalidated_capture_ids.add(id(retired))
return True
async def status_on_unreachable_existing_network(
*_: object,
captured_device: facade_module.CapturedDiscoveredDevice | None = None,
on_gatt_validated: Callable[[facade_module.CapturedDiscoveredDevice], None] | None = None,
**__: object,
) -> dict[str, Any]:
assert captured_device is old_capture
assert on_gatt_validated is not None
on_gatt_validated(old_capture)
return _wifi_status_read("192.168.1.20", device_id=device_id)
monkeypatch.setattr(facade_module, "_capture_network_intent_device", exact_capture)
monkeypatch.setattr(facade_module, "capture_discovered_device", exact_capture)
monkeypatch.setattr(facade_module, "pin_connected_device_handle", pin_exact_capture)
monkeypatch.setattr(
facade_module,
"invalidate_connected_device_session",
invalidate_exact_session,
)
monkeypatch.setattr(
facade_module,
"read_wifi_status_once",
status_on_unreachable_existing_network,
)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(
facade_module,
"_host_route_class",
lambda _target: "direct-or-routed",
)
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
monkeypatch.setattr(
facade_module,
"_control_endpoint_reachable",
lambda _target: False,
)
with pytest.raises(facade_module.ConnectionVerificationError) as unavailable:
asyncio.run(
service.verify_connection(
ConnectionVerifyRequest(
device_id=device_id,
source="fresh-scan",
compatibility_attestation=ATTESTATION,
expected_discovery_generation=0,
)
)
)
assert unavailable.value.reason_code == "connection-verify-mqtt-unreachable"
after_verify = service.state()
assert [item["device_id"] for item in after_verify["devices"]] == [device_id]
assert after_verify["selected_device_id"] is None
assert invalidated_capture_ids == {id(old_capture)}
assert exact_capture(device_id) is None
async def apply_owned_scan(
_duration_seconds: float,
*,
on_admitted: Callable[[], None] | None = None,
) -> dict[str, Any]:
nonlocal active_capture
assert on_admitted is not None
on_admitted()
active_capture = replacement_capture
return _ble_scan_result(device_id)
monkeypatch.setattr(facade_module, "scan", apply_owned_scan)
rescanned = asyncio.run(service.scan_ble(BleScanRequest(duration_seconds=1.0)))
assert rescanned["ble_discovery_generation"] == 1
assert exact_capture(device_id) is replacement_capture
dispatched_writes: list[facade_module.CapturedDiscoveredDevice] = []
async def provision_once(
*_: object,
captured_device: facade_module.CapturedDiscoveredDevice | None = None,
on_write_dispatch: Callable[[dict[str, Any], str], None] | None = None,
**__: object,
) -> dict[str, Any]:
assert captured_device is replacement_capture
_dispatch_test_network_write(on_write_dispatch)
dispatched_writes.append(captured_device)
return {
"started_at_utc": "2026-08-11T07:00:00Z",
"completed_at_utc": "2026-08-11T07:00:01Z",
"profile_id": "xgrids-k1-fw3-wifi-v1",
"outcome": "lan_address_observed",
"write_mode": "with_response",
"baseline_status": _wifi_status_read(None)["status"],
"observations": [{"status": _wifi_status_read("192.168.1.20")["status"]}],
}
monkeypatch.setattr(facade_module, "provision_wifi_once", provision_once)
monkeypatch.setattr(
facade_module,
"_control_endpoint_reachable",
lambda _target: True,
)
monkeypatch.setattr(
facade_module,
"_await_control_endpoint_reachable",
_reachable_control_endpoint,
)
connected = asyncio.run(
service.connect(
_connect_request(
device_id=device_id,
ssid="lab-network",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
expected_discovery_generation=rescanned["ble_discovery_generation"],
)
)
)
assert dispatched_writes == [replacement_capture]
assert connected["connection_lifecycle"]["connection_ready"] is True
network_operations = [
item for item in connected["operations"] if item["action"] == "network.provision"
]
assert len(network_operations) == 1
assert network_operations[0]["status"] == "succeeded"
verify_operations = [
item for item in connected["operations"] if item["action"] == "connection.verify"
]
assert len(verify_operations) == 1
assert verify_operations[0]["status"] == "failed"
assert verify_operations[0]["error"]["side_effect_status"] == "none"
def test_connection_verify_request_requires_paired_exact_firmware_attestation() -> None:
with pytest.raises(ValidationError, match="compatibility_attestation"):
ConnectionVerifyRequest(device_id="test-ble-transport")
with pytest.raises(ValidationError, match="device_id"):
ConnectionVerifyRequest(compatibility_attestation=ATTESTATION)
with pytest.raises(ValidationError, match="3.0.2"):
ConnectionVerifyRequest(
device_id="test-ble-transport",
compatibility_attestation={
"firmware_version": "3.0.3",
"topology": "direct-lan",
"verification": "live-device-info",
},
)
with pytest.raises(ValidationError, match="expected_discovery_generation"):
ConnectionVerifyRequest(
device_id="test-ble-transport",
compatibility_attestation=ATTESTATION,
)
quick_connect = ConnectionVerifyRequest(
device_id="test-ble-transport",
compatibility_attestation=QUICK_CONNECT_ATTESTATION,
expected_discovery_generation=0,
)
assert quick_connect.compatibility_attestation == QUICK_CONNECT_ATTESTATION
def test_verify_connection_refreshes_dynamic_dhcp_address_and_rotates_session(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
service._selected_device_id = "test-ble-transport" # noqa: SLF001
service._connection_mode = "bridge" # noqa: SLF001
service._k1_ip = "10.255.254.54" # noqa: SLF001
service._device_id = "known-k1" # noqa: SLF001
service._device_session_id = "old-device-session" # noqa: SLF001
service._device_session_opened_at = "2026-07-20T10:00:00Z" # noqa: SLF001
service._device_calibration = {"status": "available"} # noqa: SLF001
service._compatibility_attestation = ATTESTATION.model_dump(mode="json") # noqa: SLF001
_set_scanned_k1(service)
async def fake_status_read(*_: object, **__: object) -> dict[str, Any]:
return _wifi_status_read("10.255.254.77")
monkeypatch.setattr(facade_module, "read_wifi_status_once", fake_status_read)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(facade_module, "_host_route_class", lambda _target: "direct-or-routed")
monkeypatch.setattr(
facade_module,
"_control_endpoint_reachable",
lambda target: target == "10.255.254.77",
)
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
state = asyncio.run(
service.verify_connection(
ConnectionVerifyRequest(
device_id="test-ble-transport",
compatibility_attestation=ATTESTATION,
expected_discovery_generation=0,
)
)
)
assert state["k1_ip"] == "10.255.254.77"
assert state["device_session"]["device_session_id"] != "old-device-session"
assert state["connection_verification"] == {
"status": "reachable",
"lease_state": "reachable",
"lease_generation": state["connection_supervisor"]["lease"]["generation"],
"endpoint_validation": "ble-wifi-status-read+mqtt-tcp-connect",
"network_reachability": "reachable",
"host_route_class": "direct-or-routed",
"address_source": "ble-wifi-status-read",
"connection_origin": "external-existing-network",
"admission_source": "connection.verify",
"address_changed": True,
"previous_address_present": True,
"write_performed": False,
"observed_at": "2026-07-20T12:00:00Z",
"reason_code": None,
"supervisor_revision": state["connection_verification"]["supervisor_revision"],
}
assert state["device_calibration"]["status"] == "unavailable"
def test_bridge_read_only_verify_never_shortcuts_fresh_ble_status(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
service._selected_device_id = "test-ble-transport" # noqa: SLF001
service._connection_mode = "bridge" # noqa: SLF001
service._k1_ip = "10.255.254.54" # noqa: SLF001
service._compatibility_attestation = ATTESTATION.model_dump(mode="json") # noqa: SLF001
service._device_id = "known-k1" # noqa: SLF001
service._device_session_id = "known-device-session" # noqa: SLF001
_set_scanned_k1(service)
_seed_supervised_connection(
service,
target_ipv4="10.255.254.54",
with_control=False,
)
service._device_session_id = "known-device-session" # noqa: SLF001
monkeypatch.setattr(facade_module, "_host_route_class", lambda _target: "direct-or-routed")
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(facade_module, "_control_endpoint_reachable", lambda _target: True)
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
status_reads: list[tuple[str, float, bool]] = []
async def exact_status_read(
device_id: str,
*,
timeout_seconds: float,
rediscover: bool,
**_: object,
) -> dict[str, Any]:
status_reads.append((device_id, timeout_seconds, rediscover))
return _wifi_status_read("10.255.254.54")
monkeypatch.setattr(facade_module, "read_wifi_status_once", exact_status_read)
state = asyncio.run(
service.verify_connection(
ConnectionVerifyRequest(
device_id="test-ble-transport",
compatibility_attestation=ATTESTATION,
expected_discovery_generation=0,
)
)
)
assert status_reads == [("test-ble-transport", 20.0, False)]
assert state["k1_ip"] == "10.255.254.54"
# A fresh exact BLE observation creates a new intent/session fence even
# when DHCP returned the same address. Similar endpoint text is not
# continuity authority.
assert state["device_session"]["device_session_id"] != "known-device-session"
assert state["connection_verification"] == {
"status": "reachable",
"lease_state": "reachable",
"lease_generation": state["connection_supervisor"]["lease"]["generation"],
"endpoint_validation": "ble-wifi-status-read+mqtt-tcp-connect",
"network_reachability": "reachable",
"host_route_class": "direct-or-routed",
"address_source": "ble-wifi-status-read",
"connection_origin": "external-existing-network",
"admission_source": "connection.verify",
"address_changed": False,
"previous_address_present": True,
"write_performed": False,
"observed_at": "2026-07-20T12:00:00Z",
"reason_code": None,
"supervisor_revision": state["connection_verification"]["supervisor_revision"],
}
assert state["last_operation"]["status"] == "succeeded"
def test_implicit_acquisition_target_uses_current_ble_dhcp_address(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
service._selected_device_id = "test-ble-transport" # noqa: SLF001
service._connection_mode = "bridge" # noqa: SLF001
service._k1_ip = "10.255.254.54" # noqa: SLF001
service._compatibility_attestation = ATTESTATION.model_dump(mode="json") # noqa: SLF001
status_loop: asyncio.AbstractEventLoop | None = None
runtime_loop: asyncio.AbstractEventLoop | None = None
async def fake_status_read(*_: object, **__: object) -> dict[str, Any]:
nonlocal status_loop
status_loop = asyncio.get_running_loop()
return _wifi_status_read("10.255.254.77")
monkeypatch.setattr(facade_module, "read_wifi_status_once", fake_status_read)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(facade_module, "_host_route_class", lambda _target: "direct-or-routed")
monkeypatch.setattr(
facade_module,
"_control_endpoint_reachable",
lambda target: target == "10.255.254.77",
)
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
async def scenario() -> dict[str, Any]:
nonlocal runtime_loop
runtime_loop = asyncio.get_running_loop()
service.bind_runtime_event_loop()
return await asyncio.to_thread(
service.prepare_acquisition,
_prepare_request(
project_name=PROJECT_NAME,
compatibility_attestation=ATTESTATION,
),
)
state = asyncio.run(scenario())
assert state["k1_ip"] == "10.255.254.77"
assert state["acquisition"]["target_host"] == "10.255.254.77"
assert status_loop is runtime_loop
def test_control_session_reuses_reachable_process_owned_connection_lease(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_seed_supervised_connection(
service,
target_ipv4="10.255.254.54",
with_control=False,
)
service._device_session_id = "known-session" # noqa: SLF001
service._compatibility_attestation = ATTESTATION.model_dump(mode="json") # noqa: SLF001
opened_hosts: list[str] = []
class FakeOpenControlSession:
def __init__(self) -> None:
self.state = "idle"
self.verified_control: dict[str, object] | None = None
def snapshot(self) -> dict[str, object]:
return {
"state": self.state,
"can_confirm_standby": False,
"verified_control": self.verified_control,
}
def open(
self,
*,
host: str,
connection_binding: ApplicationConnectionBinding,
**_: object,
) -> dict[str, object]:
opened_hosts.append(host)
self.state = "connection-ready"
self.verified_control = _verified_control_for_binding(connection_binding)
return self.snapshot()
async def forbidden_status_read(*_: object, **__: object) -> dict[str, Any]:
raise AssertionError("reachable connection lease must not reopen BLE")
service._application_control_session = FakeOpenControlSession() # type: ignore[assignment] # noqa: SLF001
monkeypatch.setattr(facade_module, "read_wifi_status_once", forbidden_status_read)
monkeypatch.setattr(facade_module, "_control_endpoint_reachable", lambda _target: True)
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
admission_generation = service._connection_supervisor.snapshot().lease.generation # noqa: SLF001
state = service.open_application_control_session(
OpenApplicationControlSessionRequest(
operator_present=True,
owner_controlled_device=True,
lixelgo_closed=True,
battery_storage_confirmed=True,
expected_physical_state_confirmed=True,
timezone_name="Europe/Moscow",
)
)
assert opened_hosts == ["10.255.254.54"]
assert state["k1_ip"] == "10.255.254.54"
assert state["connection_verification"]["lease_state"] == "reachable"
assert state["connection_verification"]["network_reachability"] == "reachable"
open_operation = next(
operation
for operation in state["operations"]
if operation["action"] == "application-control.session.open"
)
assert open_operation["status"] == "succeeded"
assert open_operation["result"] == {
"lease_generation": admission_generation,
"connection_lease_reused": True,
"recovery_performed": False,
"address_changed": False,
"device_write_performed": False,
}
service._release_application_control_process_lease() # noqa: SLF001
def test_operator_control_open_replaces_verify_inspection_with_fresh_dialogue(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
transitions: list[str] = []
class RecordingControlSession(FakeInteractiveControlSession):
def close_prestart(self, **kwargs: object) -> dict[str, object]:
transitions.append("inspection-closed")
return super().close_prestart(**kwargs)
def retire_for_network_change(self, **kwargs: object) -> dict[str, object]:
transitions.append("inspection-retired")
return super().retire_for_network_change(**kwargs)
def open(self, *, inspection_only: bool = False, **kwargs: object) -> dict[str, object]:
transitions.append(
"inspection-opened" if inspection_only else "canonical-opened"
)
self.session_generation += 1
return super().open(inspection_only=inspection_only, **kwargs)
control = RecordingControlSession(initial_state="connection-ready")
control.session_generation = 7
control.state_revision = 11
control.inspection_only = True
control.inspection_promotion_allowed = False
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
binding = _seed_supervised_connection(service)
control.verified_control = _verified_control_for_binding(binding)
service._acquire_application_control_process_lease() # noqa: SLF001
monkeypatch.setattr(facade_module, "_control_endpoint_reachable", lambda _target: True)
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
state = service.open_application_control_session(
OpenApplicationControlSessionRequest(
operator_present=True,
owner_controlled_device=True,
lixelgo_closed=True,
battery_storage_confirmed=True,
expected_physical_state_confirmed=True,
timezone_name="Europe/Moscow",
)
)
assert transitions == [
"inspection-closed",
"inspection-retired",
"canonical-opened",
]
assert state["application_control_session"]["state"] == "connection-ready"
assert state["application_control_session"]["inspection_only"] is False
assert state["application_control_session"]["session_generation"] == 8
service._release_application_control_process_lease() # noqa: SLF001
def test_reachable_connection_lease_supports_repeated_independent_control_sessions(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_seed_supervised_connection(
service,
target_ipv4="10.255.254.54",
with_control=False,
)
service._device_session_id = "known-session" # noqa: SLF001
service._compatibility_attestation = ATTESTATION.model_dump(mode="json") # noqa: SLF001
opened_hosts: list[str] = []
class FakeCompletedControlSession:
def __init__(self) -> None:
self.state = "completed"
self.verified_control: dict[str, object] | None = None
def snapshot(self) -> dict[str, object]:
return {
"state": self.state,
"can_open": True,
"can_confirm_standby": False,
"verified_control": self.verified_control,
}
def open(
self,
*,
host: str,
connection_binding: ApplicationConnectionBinding,
**_: object,
) -> dict[str, object]:
opened_hosts.append(host)
self.state = "connection-ready"
self.verified_control = _verified_control_for_binding(
connection_binding,
control_session_id=f"fake-control-session-{len(opened_hosts)}",
)
return self.snapshot()
async def forbidden_status_read(*_: object, **__: object) -> dict[str, Any]:
raise AssertionError("repeated scans must not repeat BLE or Wi-Fi setup")
service._application_control_session = FakeCompletedControlSession() # type: ignore[assignment] # noqa: SLF001
monkeypatch.setattr(facade_module, "read_wifi_status_once", forbidden_status_read)
monkeypatch.setattr(facade_module, "_control_endpoint_reachable", lambda _target: True)
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
request = OpenApplicationControlSessionRequest(
operator_present=True,
owner_controlled_device=True,
lixelgo_closed=True,
battery_storage_confirmed=True,
expected_physical_state_confirmed=True,
timezone_name="Europe/Moscow",
)
service.open_application_control_session(request)
fake_session = service._application_control_session # noqa: SLF001
fake_session.state = "completed" # type: ignore[attr-defined]
state = service.open_application_control_session(request)
assert opened_hosts == ["10.255.254.54", "10.255.254.54"]
assert state["device_session"]["device_session_id"] == "known-session"
assert (
state["connection_verification"]["lease_generation"]
== (state["connection_supervisor"]["lease"]["generation"])
)
open_operations = [
operation
for operation in state["operations"]
if operation["action"] == "application-control.session.open"
]
assert len(open_operations) == 2
assert {operation["status"] for operation in open_operations} == {"succeeded"}
assert all(
operation["result"]["connection_lease_reused"] is True for operation in open_operations
)
service._release_application_control_process_lease() # noqa: SLF001
@pytest.mark.parametrize("continuity_change", ["host-epoch", "bridge-to-quick"])
def test_old_device_info_binding_cannot_regain_authority_after_connection_change(
tmp_path: Path,
continuity_change: str,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
old_binding = _seed_supervised_connection(
service,
target_ipv4=facade_module.AP_FALLBACK_IPV4,
connection_mode="bridge",
logical_device_id="known-k1",
with_control=False,
)
old_control_snapshot = {
"state": "connection-ready",
"verified_control": _verified_control_for_binding(old_binding),
}
service._reconcile_connection_supervisor( # noqa: SLF001
old_control_snapshot,
runtime.snapshot(),
)
assert service._connection_supervisor.snapshot().authority.control_allowed is True # noqa: SLF001
target = EndpointTarget(
facade_module.AP_FALLBACK_IPV4,
facade_module.CONTROL_MQTT_PORT,
)
if continuity_change == "host-epoch":
new_epoch = service._connection_supervisor.observe_host_path( # noqa: SLF001
HostPathProbeResult(
available=True,
fingerprint="test-route-after-wifi-reassociation",
interface="test1",
source_ipv4="192.168.56.3",
route_class="direct",
)
)
current_intent = service._connection_supervisor.snapshot().intent # noqa: SLF001
assert current_intent is not None
assert service._connection_supervisor.observe_endpoint( # noqa: SLF001
target=target,
intent_id=current_intent.intent_id,
host_path_epoch=new_epoch,
reachable=True,
)
else:
new_intent_id = "test-intent-quick-after-bridge"
service._connection_supervisor.set_intent( # noqa: SLF001
intent_id=new_intent_id,
requested_mode="quick-connect",
expected_device_id="known-k1",
)
assert service._connection_supervisor.observe_device_network_applied( # noqa: SLF001
intent_id=new_intent_id,
transport_ref="test-ble-transport",
connection_mode="quick-connect",
target=target,
source="ble-post-write-status",
)
epoch = service._connection_supervisor.snapshot().host_path.epoch # noqa: SLF001
assert service._connection_supervisor.observe_endpoint( # noqa: SLF001
target=target,
intent_id=new_intent_id,
host_path_epoch=epoch,
reachable=True,
)
# The old application worker may still publish its old DeviceInfo snapshot.
# Reconciliation must compare the immutable binding, never relabel it with
# the new intent/route merely because the same TCP address answers.
service._reconcile_connection_supervisor( # noqa: SLF001
old_control_snapshot,
runtime.snapshot(),
)
supervisor = service._connection_supervisor.snapshot() # noqa: SLF001
assert supervisor.endpoint.tcp_state == "reachable"
assert supervisor.authority.control_allowed is False
assert supervisor.authority.acquisition_start_allowed is False
assert supervisor.device_identity.state != "verified"
assert supervisor.lease.state == "configured-unverified"
def test_application_command_binding_guard_rejects_changed_host_epoch(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
binding = _seed_supervised_connection(service)
monkeypatch.setattr(service, "_sample_host_path", _direct_host_path)
monkeypatch.setattr(
service._application_control_session, # noqa: SLF001
"snapshot",
lambda: {
"state": "connection-ready",
"verified_control": _verified_control_for_binding(
binding,
control_session_id="test-control-test-ble-transport",
),
},
)
service._validate_application_connection_binding(binding) # noqa: SLF001
service._connection_supervisor.observe_host_path( # noqa: SLF001
HostPathProbeResult(
available=True,
fingerprint="route-after-mac-wifi-change",
interface="test1",
source_ipv4="192.168.56.3",
route_class="direct",
)
)
with pytest.raises(ApplicationConnectionBindingLost) as caught:
service._validate_application_connection_binding(binding) # noqa: SLF001
assert caught.value.reason_code == "application-connection-binding-lost"
def test_explicit_stop_dispatch_waits_for_transient_local_lifecycle_holder(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
binding = _seed_supervised_connection(service)
monkeypatch.setattr(service, "_sample_host_path", _direct_host_path)
monkeypatch.setattr(
service._application_control_session, # noqa: SLF001
"snapshot",
lambda: {
"state": "scanning",
"verified_control": _verified_control_for_binding(binding),
},
)
assert service._k1_command_dispatch_gate.acquire(blocking=False) # noqa: SLF001
entered = threading.Event()
completed = threading.Event()
release_callbacks: list[Callable[[], None]] = []
failures: list[BaseException] = []
def acquire_stop_lease() -> None:
entered.set()
try:
release_callbacks.append(
service._acquire_application_dispatch_lease( # noqa: SLF001
binding,
lambda: False,
)
)
except BaseException as exc: # pragma: no branch - asserted below
failures.append(exc)
finally:
completed.set()
worker = threading.Thread(target=acquire_stop_lease)
worker.start()
assert entered.wait(1.0)
assert completed.wait(0.1) is False
service._k1_command_dispatch_gate.release() # noqa: SLF001
assert completed.wait(1.0)
worker.join(timeout=1.0)
assert failures == []
assert len(release_callbacks) == 1
release_callbacks[0]()
assert service._k1_command_dispatch_gate.acquire(blocking=False) # noqa: SLF001
service._k1_command_dispatch_gate.release() # noqa: SLF001
def test_explicit_stop_dispatch_contention_expires_without_crossing_publish_lease(
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
binding = _seed_supervised_connection(service)
assert service._k1_command_dispatch_gate.acquire(blocking=False) # noqa: SLF001
expired = threading.Event()
completed = threading.Event()
failures: list[BaseException] = []
def acquire_stop_lease() -> None:
try:
service._acquire_application_dispatch_lease( # noqa: SLF001
binding,
expired.is_set,
)
except BaseException as exc: # pragma: no branch - asserted below
failures.append(exc)
finally:
completed.set()
worker = threading.Thread(target=acquire_stop_lease)
worker.start()
assert completed.wait(0.1) is False
expired.set()
assert completed.wait(1.0)
worker.join(timeout=1.0)
service._k1_command_dispatch_gate.release() # noqa: SLF001
assert len(failures) == 1
assert isinstance(failures[0], ApplicationConnectionBindingLost)
assert service._k1_command_dispatch_gate.acquire(blocking=False) # noqa: SLF001
service._k1_command_dispatch_gate.release() # noqa: SLF001
def test_application_command_guard_projects_new_remote_proof_before_admission(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
binding = _seed_supervised_connection(service)
monkeypatch.setattr(service, "_sample_host_path", _direct_host_path)
control_session_id = "test-control-test-ble-transport"
monkeypatch.setattr(
service._application_control_session, # noqa: SLF001
"snapshot",
lambda: {
"state": "connection-ready",
"verified_control": _verified_control_for_binding(
binding,
control_session_id=control_session_id,
control_proof_revision=2,
control_proof_source="mqtt-heartbeat",
),
},
)
service._validate_application_connection_binding(binding) # noqa: SLF001
supervisor = service._connection_supervisor # noqa: SLF001
assert supervisor.snapshot().authority.control_allowed is True
assert supervisor._control_proof_revision == 2 # noqa: SLF001
assert supervisor._control_proof_source == "mqtt-heartbeat" # noqa: SLF001
def test_control_session_recovers_changed_bridge_address_without_wifi_write(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_seed_supervised_connection(
service,
target_ipv4="10.255.254.54",
with_control=False,
)
service._device_session_id = "old-session" # noqa: SLF001
service._compatibility_attestation = ATTESTATION.model_dump(mode="json") # noqa: SLF001
opened_hosts: list[str] = []
status_calls: list[dict[str, object]] = []
class FakeOpenControlSession:
def __init__(self) -> None:
self.state = "idle"
self.verified_control: dict[str, object] | None = None
def snapshot(self) -> dict[str, object]:
return {
"state": self.state,
"can_confirm_standby": False,
"verified_control": self.verified_control,
}
def open(
self,
*,
host: str,
connection_binding: ApplicationConnectionBinding,
**_: object,
) -> dict[str, object]:
opened_hosts.append(host)
self.state = "connection-ready"
self.verified_control = _verified_control_for_binding(connection_binding)
return self.snapshot()
async def fake_status_read(*_: object, **kwargs: object) -> dict[str, Any]:
status_calls.append(kwargs)
return _wifi_status_read("10.255.254.77")
service._application_control_session = FakeOpenControlSession() # type: ignore[assignment] # noqa: SLF001
monkeypatch.setattr(facade_module, "read_wifi_status_once", fake_status_read)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(facade_module, "_host_route_class", lambda _target: "direct-or-routed")
monkeypatch.setattr(
facade_module,
"_control_endpoint_reachable",
lambda target: target == "10.255.254.77",
)
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
async def scenario() -> dict[str, Any]:
service.bind_runtime_event_loop()
return await asyncio.to_thread(
service.open_application_control_session,
OpenApplicationControlSessionRequest(
operator_present=True,
owner_controlled_device=True,
lixelgo_closed=True,
battery_storage_confirmed=True,
expected_physical_state_confirmed=True,
timezone_name="Europe/Moscow",
),
)
state = asyncio.run(scenario())
assert status_calls == [{"timeout_seconds": 20.0, "rediscover": True}]
assert opened_hosts == ["10.255.254.77"]
assert state["k1_ip"] == "10.255.254.77"
assert state["device_session"]["device_session_id"] != "old-session"
assert state["connection_verification"]["status"] == "reachable"
assert state["connection_verification"]["write_performed"] is False
open_operation = next(
operation
for operation in state["operations"]
if operation["action"] == "application-control.session.open"
)
assert open_operation["result"]["recovery_performed"] is True
assert open_operation["result"]["address_changed"] is True
assert open_operation["result"]["device_write_performed"] is False
def test_control_session_prestart_failure_is_journaled_and_marks_lease_offline(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_seed_supervised_connection(
service,
target_ipv4="10.255.254.54",
endpoint_reachable=False,
with_control=False,
)
service._device_session_id = "known-session" # noqa: SLF001
service._compatibility_attestation = ATTESTATION.model_dump(mode="json") # noqa: SLF001
async def failed_status_read(*_: object, **__: object) -> dict[str, Any]:
raise TimeoutError("synthetic BLE recovery timeout")
monkeypatch.setattr(facade_module, "read_wifi_status_once", failed_status_read)
monkeypatch.setattr(facade_module, "_control_endpoint_reachable", lambda _target: False)
monkeypatch.setattr(facade_module, "_host_route_class", lambda _target: "direct-or-routed")
with pytest.raises(
facade_module.ConnectionLeaseUnavailable,
match="повторное чтение состояния",
):
service.open_application_control_session(
OpenApplicationControlSessionRequest(
operator_present=True,
owner_controlled_device=True,
lixelgo_closed=True,
battery_storage_confirmed=True,
expected_physical_state_confirmed=True,
timezone_name="Europe/Moscow",
)
)
state = service.state()
assert state["application_control_session"]["state"] == "idle"
assert state["device_session"]["connectivity"] == "offline"
assert state["connection_verification"]["lease_state"] == "configured-unverified"
open_operation = next(
operation
for operation in state["operations"]
if operation["action"] == "application-control.session.open"
)
assert open_operation["status"] == "failed"
assert open_operation["error"] == {
"category": "connection",
"code": "connection_lease_ble_recovery_failed",
"retryable": False,
"safe_to_retry": True,
"side_effect_status": "none",
}
def test_bridge_route_mismatch_persists_read_only_recovery_before_rejecting_control(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_seed_supervised_connection(
service,
target_ipv4="192.168.68.50",
host_path=_tunnel_host_path("192.168.68.50"),
endpoint_reachable=False,
endpoint_reason="connection_lease_host_route_mismatch",
with_control=False,
)
service._device_session_id = "known-session" # noqa: SLF001
service._compatibility_attestation = ATTESTATION.model_dump(mode="json") # noqa: SLF001
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(facade_module, "_control_endpoint_reachable", lambda _target: False)
monkeypatch.setattr(facade_module, "_host_route_class", lambda _target: "tunnel")
service._read_wifi_status_on_runtime_loop = ( # type: ignore[method-assign] # noqa: SLF001
lambda *_args, **_kwargs: _wifi_status_read("192.168.68.77")
)
with pytest.raises(
facade_module.ConnectionLeaseUnavailable,
match="другой локальной сети",
):
service.open_application_control_session(
OpenApplicationControlSessionRequest(
operator_present=True,
owner_controlled_device=True,
lixelgo_closed=True,
battery_storage_confirmed=True,
expected_physical_state_confirmed=True,
timezone_name="Europe/Moscow",
)
)
state = service.state()
assert state["k1_ip"] == "192.168.68.77"
assert state["semantic_topology_store"]["record"]["ipv4"] == "192.168.68.77"
assert state["device_session"]["device_session_id"] != "known-session"
assert state["connection_verification"]["lease_state"] == "configured-unverified"
assert state["connection_verification"]["endpoint_validation"] == "host-route"
assert state["connection_verification"]["host_route_class"] == "tunnel"
assert state["application_control_session"]["state"] == "idle"
def test_prepare_creates_provisional_device_session_and_profiled_acquisition(
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
state = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
duration_seconds=60,
compatibility_attestation=ATTESTATION,
)
)
assert runtime.start_calls == []
assert state["device_ref"]["identity_stability"] == "provisional"
assert state["device_ref"]["device_id"] != state["device_session"]["device_session_id"]
assert state["acquisition"]["state"] == "prepared"
assert state["acquisition"]["project_name"] == PROJECT_NAME
assert state["acquisition"]["mount_type"] == "handheld"
assert state["acquisition"]["gnss_mode"] == "none"
assert state["acquisition"]["compatibility_profile_id"] == (XGRIDS_K1_COMPATIBILITY_PROFILE_ID)
assert state["compatibility"]["vendor_writes_enabled"] is False
def test_project_name_is_normalized_and_control_characters_are_rejected() -> None:
request = _prepare_request(
project_name=" K1 Lab ",
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
assert request.project_name == "K1 Lab"
for invalid in (" ", "line\nbreak", "\ud800", "x" * 97):
with pytest.raises(ValidationError):
_prepare_request(
project_name=invalid,
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
def test_acquisition_is_unbounded_by_default_and_accepts_ten_hour_hint() -> None:
unbounded = _prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
ten_hours = _prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
duration_seconds=10 * 60 * 60,
compatibility_attestation=ATTESTATION,
)
assert unbounded.duration_seconds is None
assert ten_hours.duration_seconds == 36_000
def test_connection_modes_require_their_exact_topology_attestation() -> None:
with pytest.raises(ValidationError, match="idempotency_key"):
ConnectRequest(
device_id="synthetic-device",
ssid="synthetic-network",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
)
assert (
_connect_request(
device_id="synthetic-device",
connection_mode="quick-connect",
compatibility_attestation=QUICK_CONNECT_ATTESTATION,
).connection_mode
== "quick-connect"
)
assert (
_connect_request(
device_id="synthetic-device",
ssid="synthetic-network",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
connection_mode="direct-connect",
compatibility_attestation=DIRECT_CONNECT_ATTESTATION,
).connection_mode
== "direct-connect"
)
bridge = _connect_request(
device_id="synthetic-device",
ssid="synthetic-network",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
)
assert bridge.allow_host_wifi_switch is False
assert (
_connect_request(
device_id="synthetic-device",
ssid="synthetic-network",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
allow_host_wifi_switch=True,
).allow_host_wifi_switch
is True
)
with pytest.raises(ValidationError, match="valid boolean"):
_connect_request(
device_id="synthetic-device",
ssid="synthetic-network",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
allow_host_wifi_switch="yes",
)
with pytest.raises(ValidationError, match="only for Bridge"):
_connect_request(
device_id="synthetic-device",
connection_mode="quick-connect",
compatibility_attestation=QUICK_CONNECT_ATTESTATION,
allow_host_wifi_switch=True,
)
with pytest.raises(ValidationError):
_connect_request(
device_id="synthetic-device",
connection_mode="quick-connect",
compatibility_attestation=ATTESTATION,
)
with pytest.raises(ValidationError, match="host Wi-Fi profile"):
_connect_request(
device_id="synthetic-device",
ssid="synthetic-network",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
connection_mode="quick-connect",
compatibility_attestation=QUICK_CONNECT_ATTESTATION,
)
with pytest.raises(ValidationError, match="32 UTF-8 bytes"):
_connect_request(
device_id="synthetic-device",
ssid="🛰️" * 9,
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
)
with pytest.raises(ValidationError, match="64 UTF-8 bytes"):
_connect_request(
device_id="synthetic-device",
ssid="synthetic-network",
password=SecretStr("🔒" * 17),
compatibility_attestation=ATTESTATION,
)
def test_only_physically_accepted_mount_and_gnss_values_are_admitted() -> None:
with pytest.raises(ValidationError):
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
mount_type="uav", # type: ignore[arg-type]
compatibility_attestation=ATTESTATION,
)
with pytest.raises(ValidationError):
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
gnss_mode="rtk", # type: ignore[arg-type]
compatibility_attestation=ATTESTATION,
)
def test_facade_arms_bounded_shadow_lease_without_installing_publish_transport(
tmp_path: Path,
) -> None:
loader = FakeApplicationAuthorityLoader()
service = XgridsK1CompatibilityService(
tmp_path,
application_authority_loader=loader,
)
runtime = FakeVisualizationRuntime()
service.runtime = runtime # type: ignore[assignment]
service._selected_device_id = "test-ble-transport" # noqa: SLF001
service._k1_ip = "192.168.1.20" # noqa: SLF001
service._compatibility_attestation = { # noqa: SLF001
"firmware_version": "3.0.2",
"topology": "direct-lan",
"verification": "live-device-info",
"basis": "selected-profile-live-device-info-required",
"observed_at": "2026-07-18T00:00:00Z",
}
state = service.arm_application_control_shadow(
ShadowApplicationControlArmRequest(
operator_confirmed=True,
lease_seconds=60.0,
timezone_name="Europe/Moscow",
)
)
execution = state["application_control_execution"]
assert loader.calls == 1
assert execution["state"] == "armed-shadow-only"
assert execution["lease"]["authority_cached"] is True
assert execution["can_emit_requests"] is False
assert execution["live_transport_installed"] is False
assert execution["publisher"]["vendor_writes_enabled"] is False
assert execution["publisher"]["transport_calls"] == 0
assert PRIVATE_APPLICATION_AUTHORITY not in str(state)
disarmed = service.disarm_application_control_shadow()
assert disarmed["application_control_execution"]["state"] == "disarmed"
assert disarmed["application_control_execution"]["lease"] is None
def test_shadow_arm_requires_idle_connected_profile_selected_device_before_keychain_read(
tmp_path: Path,
) -> None:
loader = FakeApplicationAuthorityLoader()
service = XgridsK1CompatibilityService(
tmp_path,
application_authority_loader=loader,
)
service.runtime = FakeVisualizationRuntime() # type: ignore[assignment]
with pytest.raises(RuntimeError, match="подключите K1"):
service.arm_application_control_shadow(
ShadowApplicationControlArmRequest(
operator_confirmed=True,
timezone_name="Europe/Moscow",
)
)
assert loader.calls == 0
def test_shadow_arm_contract_requires_explicit_operator_confirmation() -> None:
with pytest.raises(ValidationError):
ShadowApplicationControlArmRequest.model_validate({"timezone_name": "Europe/Moscow"})
def test_prepare_acquisition_revokes_existing_shadow_authority_lease(tmp_path: Path) -> None:
loader = FakeApplicationAuthorityLoader()
service = XgridsK1CompatibilityService(
tmp_path,
application_authority_loader=loader,
)
service.runtime = FakeVisualizationRuntime() # type: ignore[assignment]
service._selected_device_id = "test-ble-transport" # noqa: SLF001
service._k1_ip = "192.168.1.20" # noqa: SLF001
service._compatibility_attestation = ATTESTATION.model_dump(mode="json") # noqa: SLF001
service.arm_application_control_shadow(
ShadowApplicationControlArmRequest(
operator_confirmed=True,
timezone_name="Europe/Moscow",
)
)
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
duration_seconds=60,
compatibility_attestation=ATTESTATION,
)
)
assert prepared["application_control_execution"]["state"] == "disarmed"
assert prepared["application_control_execution"]["lease"] is None
def test_operator_manual_start_is_confirmed_only_by_real_point_data(tmp_path: Path) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
duration_seconds=60,
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
starting = service.start_acquisition(_start_request(acquisition_id=acquisition_id))
assert starting["acquisition"]["state"] == "starting"
assert starting["last_operation"]["status"] == "running"
runtime.mark_ready()
awaiting = service.state()
assert awaiting["acquisition"]["state"] == "awaiting_external_start"
assert awaiting["last_operation"]["status"] == "operator_action_required"
assert len(runtime.start_calls) == 1
assert runtime.start_calls[0][3] == PROJECT_NAME
runtime.pcl_frames = 1
acquiring = service.state()
assert acquiring["acquisition"]["state"] == "acquiring"
assert acquiring["last_operation"]["status"] == "succeeded"
assert acquiring["last_operation"]["result"]["confirmation"] == "point-frame"
@pytest.mark.parametrize("proof_first", [False, True])
def test_plugin_commanded_acquisition_keeps_start_and_stop_as_explicit_actions(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
proof_first: bool,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control = FakeInteractiveControlSession()
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
binding = _seed_supervised_connection(service)
service._compatibility_attestation = ATTESTATION.model_dump(mode="json") # noqa: SLF001
prepared = service.prepare_acquisition(
_prepare_request(
project_name="TEST001",
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
assert prepared["acquisition"]["control_mode"] == "plugin-commanded"
assert control.state == "project-ready"
assert runtime.start_calls == []
with pytest.raises(ValueError, match="подтверждения присутствия"):
service.start_acquisition(_start_request(acquisition_id=acquisition_id))
assert control.start_projects == []
pre_pcl_state = service.start_acquisition(
_start_request(
acquisition_id=acquisition_id,
physical_acceptance=PHYSICAL_ACCEPTANCE,
)
)
pre_pcl_camera_streams = [
stream
for stream in pre_pcl_state["sensor_catalog"]["streams"]
if stream.get("semantic_channel_id") == "camera.preview.live"
]
assert pre_pcl_state["camera_preview"]["active_source_id"] is None
assert pre_pcl_state["camera_preview"]["delivery"] is None
assert pre_pcl_state["camera_preview"]["activation_admission"]["state"] == (
"waiting-for-first-authoritative-pcl"
)
assert all(stream["activation"]["selected"] is False for stream in pre_pcl_camera_streams)
assert all(stream["activation"]["controllable"] is False for stream in pre_pcl_camera_streams)
assert all(stream["delivery"] is None for stream in pre_pcl_camera_streams)
pre_pcl_camera = service.camera_preview.snapshot()
assert pre_pcl_camera["active_source_id"] is None
assert pre_pcl_camera["delivery"] is None
assert pre_pcl_camera["recording"]["active"] is False
assert pre_pcl_camera["recording"]["producer_alive"] is False
assert control.start_projects == ["TEST001"]
assert control.stop_calls == 0
assert control.start_projects == ["TEST001"]
start_operation_id = service._acquisition_start_operation_id # noqa: SLF001
assert isinstance(start_operation_id, str)
monkeypatch.setattr(
service,
"_active_acquisition_checkpoint_start_operation_id",
lambda **_kwargs: start_operation_id,
)
physical_proof = _exact_start_physical_proof(
operation_id=start_operation_id,
acquisition_id=acquisition_id,
binding=binding,
resolved=True,
)
runtime.mark_ready()
if proof_first:
monkeypatch.setattr(
service._physical_command_coordinator, # noqa: SLF001
"snapshot",
lambda: physical_proof,
)
proof_without_frame = service.state()
assert proof_without_frame["acquisition"]["state"] == ("awaiting_external_start")
assert proof_without_frame["last_operation"]["status"] == "running"
else:
runtime.pcl_frames = 1
frame_before_canonical_start = service.state()
assert frame_before_canonical_start["acquisition"]["state"] == ("awaiting_external_start")
assert frame_before_canonical_start["last_operation"]["status"] == "running"
monkeypatch.setattr(
service._physical_command_coordinator, # noqa: SLF001
"snapshot",
lambda: physical_proof,
)
runtime.pcl_frames = 1
acquiring = service.state()
assert acquiring["acquisition"]["state"] == "acquiring"
assert acquiring["last_operation"]["status"] == "succeeded"
assert acquiring["last_operation"]["stage_code"] == ("canonical-start-and-first-point-frame")
assert acquiring["last_operation"]["result"]["confirmation"] == (
"canonical-start-and-point-frame"
)
stopping = service.stop_acquisition(
_stop_request(
acquisition_id=acquisition_id,
mode="graceful",
physical_acceptance=PHYSICAL_ACCEPTANCE,
)
)
assert control.stop_calls == 1
assert stopping["acquisition"]["state"] == "awaiting_external_stop"
assert stopping["last_operation"]["status"] == "running"
control.state = "completed"
# This legacy mapping fixture does not let the fake request_stop replace
# the START projection with a typed durable STOP head. Bypass only its
# terminal checkpoint seam; dedicated integration tests cover real v5
# STOP proof -> checkpoint CEASED ordering.
monkeypatch.setattr(
service,
"_cease_active_acquisition_checkpoint_from_physical_head",
lambda **_kwargs: True,
)
# The production worker has also resolved the durable STOP ledger before
# publishing `completed`; this mapping-only fake still returns the old
# START document. Preserve this test's pre-checkpoint intent by omitting
# that stale mapping at the reducer boundary.
original_reconcile_acquisition = service._reconcile_acquisition # noqa: SLF001
def reconcile_legacy_completed(
runtime_snapshot: Mapping[str, Any],
camera_snapshot: Mapping[str, Any],
control_snapshot: Mapping[str, Any],
**kwargs: Any,
) -> None:
kwargs["physical_command_proof"] = None
original_reconcile_acquisition(
runtime_snapshot,
camera_snapshot,
control_snapshot,
**kwargs,
)
monkeypatch.setattr(service, "_reconcile_acquisition", reconcile_legacy_completed)
completed = service.state()
assert control.stop_calls == 1
assert completed["acquisition"]["state"] == "completed"
assert completed["acquisition"]["result"]["device_state"] == "ready"
assert completed["last_operation"]["status"] == "succeeded"
assert runtime.stop_calls == 1
assert completed["live_perception_shadow"]["active"] is False
assert completed["message"] == (
"Приём и запись завершены. K1 остановлен и готов к новому запуску."
)
def test_terminal_prepared_start_without_publish_settles_and_stops_local_capture(
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control = FakeInteractiveControlSession()
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
binding = _seed_supervised_connection(
service,
transport_ref="k1-start-zero-publish",
)
prepared = service.prepare_acquisition(
_prepare_request(
project_name="START_NONE",
host=binding.target_ipv4,
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = str(prepared["acquisition"]["acquisition_id"])
identity = PhysicalCommandIdentity(
vendor_device_id_sha256="a" * 64,
device_serial_sha256="b" * 64,
)
assert control.verified_control is not None
connection = PhysicalCommandConnectionBinding(
intent_id=binding.intent_id,
transport_ref=binding.transport_ref,
connection_mode=binding.connection_mode,
target_ipv4=binding.target_ipv4,
target_port=binding.target_port,
host_path_epoch=binding.host_path_epoch,
control_session_id=str(control.verified_control["control_session_id"]),
producer_generation=int(control.verified_control["producer_generation"]),
)
coordinator = service._physical_command_coordinator # noqa: SLF001
coordinator.application_response(
ApplicationMqttResponseEvidence(
operation_key="bootstrap:start-none:DeviceInfoRequest",
response_topic="lixel/application/response/device_info",
payload_sha256="c" * 64,
modeling_action=None,
result_code=None,
success=None,
observed_at_utc="2026-08-14T13:30:40.000Z",
)
)
coordinator.bind_control_session(
PhysicalCommandRuntimeBinding(
vendor_device_id_sha256=identity.vendor_device_id_sha256,
device_serial_sha256=identity.device_serial_sha256,
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
intent_id=connection.intent_id,
transport_ref=connection.transport_ref,
connection_mode=connection.connection_mode,
target_ipv4=connection.target_ipv4,
target_port=connection.target_port,
host_path_epoch=connection.host_path_epoch,
control_session_id=connection.control_session_id,
producer_generation=connection.producer_generation,
)
)
coordinator.device_status(
ApplicationMqttDeviceStatusEvidence(
vendor_device_id_sha256=identity.vendor_device_id_sha256,
device_serial_sha256=identity.device_serial_sha256,
session_state="ready",
session_state_code=MODELING_STATE_BASE + 300,
project_bound=False,
project_id_sha256=None,
init_ready=False,
status_message_sha256="d" * 64,
mqtt_retained=False,
observed_at_utc="2026-08-14T13:30:41.000Z",
)
)
payload = b"exact-start-zero-publish"
envelope = OneShotPublishEnvelope(
operation_key="modeling:start",
topic="lixel/application/request/modeling",
payload=payload,
payload_sha256=hashlib.sha256(payload).hexdigest(),
payload_bytes=len(payload),
qos=2,
retain=False,
)
def request_start_after_durable_prepare(**kwargs: object) -> dict[str, object]:
context = kwargs["command_context"]
observer = kwargs["preparation_checkpoint_observer"]
assert isinstance(context, PhysicalCommandIntentContext)
assert callable(observer)
coordinator.prepare(context, action="start", envelope=envelope)
observer("prepared", context, envelope)
control._accept_checkpoint( # noqa: SLF001
expected_session_generation=kwargs["expected_session_generation"], # type: ignore[arg-type]
expected_state_revision=kwargs["expected_state_revision"], # type: ignore[arg-type]
)
control.start_projects.append(str(kwargs["project_name"]))
control.start_contexts.append(context)
control.state = "start-requested"
return control.snapshot()
control.request_start = request_start_after_durable_prepare # type: ignore[method-assign]
starting = service.start_acquisition(
_start_request(
acquisition_id=acquisition_id,
physical_acceptance=PHYSICAL_ACCEPTANCE,
)
)
start_operation_id = str(starting["last_operation"]["operation_id"])
assert starting["physical_command"]["record"]["stage"] == "prepared"
assert starting["active_acquisition_recovery_checkpoint"]["state"] == "prepared"
assert runtime.source_mode == "live"
control.state = "failed"
control.state_revision += 1
control.failure = {
"reason_code": "application-connection-binding-lost",
"failed_phase": "start-requested",
"modeling_command_attempted": False,
"diagnostic_evidence_unavailable": [],
"safe_to_retry": True,
}
control.outcome_unknown = False
settled = service.state()
record = service._physical_command_ledger.snapshot().record # noqa: SLF001
checkpoint = service._active_acquisition_checkpoint.snapshot().checkpoint # type: ignore[union-attr] # noqa: SLF001
operation = service._operations.get(start_operation_id) # noqa: SLF001
assert record is not None
assert record.stage == "resolved"
assert record.resolution == "not-dispatched"
assert checkpoint is not None and checkpoint.state == "ceased"
assert settled["acquisition"]["state"] == "failed"
assert settled["acquisition"]["result"]["device_start"] == "not-dispatched"
assert settled["acquisition"]["result"]["receiver_stopped"] is True
assert operation.status == "failed"
assert operation.stage_code == "physical-start-not-dispatched"
assert operation.error is not None
assert operation.error["side_effect_status"] == "none"
assert operation.error["physical_command_sent"] is False
assert runtime.stop_calls == 1
assert runtime.source_mode == "idle"
assert service._acquisition_session_lease is None # noqa: SLF001
def test_live_prepared_start_reduction_does_not_touch_publish_fence(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
acquisition_id = "acq-live-prepared"
operation_id = "op-live-prepared"
monkeypatch.setattr(
service._physical_command_coordinator, # noqa: SLF001
"snapshot",
lambda: {
"status": "unresolved",
"record": {
"operation_id": operation_id,
"acquisition_id": acquisition_id,
"action": "start",
"stage": "prepared",
"resolution": None,
"publish_call_returned": None,
"packet_id": None,
"qos2_completed": False,
"application_response": None,
},
},
)
monkeypatch.setattr(
service._application_control_session, # noqa: SLF001
"snapshot",
lambda: {"state": "initializing", "failure": None},
)
class PublishFenceMustStayFree:
def acquire(self, *args: object, **kwargs: object) -> bool:
raise AssertionError("live START reduction touched the publish fence")
def release(self) -> None:
raise AssertionError("live START reduction released an unowned fence")
monkeypatch.setattr(
service,
"_k1_command_dispatch_gate",
PublishFenceMustStayFree(),
)
outcome = service._settle_prepared_start_worker_failure( # noqa: SLF001
acquisition_id=acquisition_id,
start_operation_id=operation_id,
)
assert outcome == "not-applicable"
def _activate_real_checkpoint_for_prepared_stop_fixture(
service: XgridsK1CompatibilityService,
*,
project_name: str,
) -> None:
"""Back the specialized retained-receiver fixture with the real v5 CAS."""
store = service._active_acquisition_checkpoint # noqa: SLF001
acquisition = service._acquisition # noqa: SLF001
out_dir = service._acquisition_out_dir # noqa: SLF001
record = service._physical_command_ledger.snapshot().record # noqa: SLF001
assert store is not None
assert acquisition is not None
assert out_dir is not None
assert record is not None and record.last_status is not None
binding = ActiveAcquisitionRecoveryTransportBinding(
runtime_instance_id=service._snapshot_runtime_id, # noqa: SLF001
intent_id=record.connection.intent_id,
transport_ref=record.connection.transport_ref,
connection_mode=record.connection.connection_mode,
target_ipv4=record.connection.target_ipv4,
target_port=record.connection.target_port,
host_path_epoch=record.connection.host_path_epoch,
control_session_id=record.connection.control_session_id,
producer_generation=record.connection.producer_generation,
logical_device_id=acquisition.device_id,
compatibility_profile_id=record.compatibility_profile_id,
vendor_device_id_sha256=record.identity.vendor_device_id_sha256,
device_serial_sha256=record.identity.device_serial_sha256,
)
prepared = store.prepare(
transition_id=f"test-retained-prepare:{record.operation_id}",
predecessor_revision=0,
acquisition_id=acquisition.acquisition_id,
original_start_operation_id=record.operation_id,
start_payload_sha256=record.payload_sha256,
identity=ActiveAcquisitionRecoveryIdentity(
logical_device_id=acquisition.device_id,
vendor_device_id_sha256=record.identity.vendor_device_id_sha256,
device_serial_sha256=record.identity.device_serial_sha256,
),
connection=ActiveAcquisitionRecoveryConnection(
transport_ref=record.connection.transport_ref,
connection_mode=record.connection.connection_mode,
target_ipv4=record.connection.target_ipv4,
target_port=record.connection.target_port,
),
compatibility_profile_id=record.compatibility_profile_id,
project_name=project_name,
project_name_wire_sha256=active_acquisition_project_name_sha256(
project_name
),
original_evidence_session_id=out_dir.name,
duration_seconds=acquisition.duration_seconds,
requested_streams=acquisition.requested_streams,
evidence_policy=acquisition.evidence_policy,
mount_type="handheld",
gnss_mode="none",
prepared_binding=binding,
)
status_proof = service._checkpoint_status_proof( # noqa: SLF001
status=record.last_status,
binding=binding,
evidence_session_id=out_dir.name,
)
store.activate(
transition_id=f"test-retained-activate:{record.operation_id}",
expected_revision=prepared.revision,
expected_acquisition_id=prepared.acquisition_id,
expected_start_operation_id=prepared.original_start_operation_id,
status_proof=status_proof,
physical_proof=service._checkpoint_physical_proof( # noqa: SLF001
record=record,
binding=binding,
checkpoint=prepared,
),
)
def _install_real_prepared_stop_dispatch_fixture(
service: XgridsK1CompatibilityService,
runtime: FakeVisualizationRuntime,
*,
confirm_first_pcl: bool = True,
) -> SimpleNamespace:
"""Install one fully confirmed START and a STOP that only durably PREPAREs."""
control = FakeInteractiveControlSession()
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
binding = _seed_supervised_connection(service, transport_ref="k1-stop-dispatch-race")
prepared = service.prepare_acquisition(
_prepare_request(
project_name="STOP_RACE",
host=binding.target_ipv4,
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = str(prepared["acquisition"]["acquisition_id"])
service.start_acquisition(
_start_request(
acquisition_id=acquisition_id,
physical_acceptance=PHYSICAL_ACCEPTANCE,
)
)
start_operation_id = service._acquisition_start_operation_id # noqa: SLF001
assert isinstance(start_operation_id, str)
identity = PhysicalCommandIdentity(
vendor_device_id_sha256="a" * 64,
device_serial_sha256="b" * 64,
)
connection = PhysicalCommandConnectionBinding(
intent_id=binding.intent_id,
transport_ref=binding.transport_ref,
connection_mode=binding.connection_mode,
target_ipv4=binding.target_ipv4,
target_port=binding.target_port,
host_path_epoch=binding.host_path_epoch,
control_session_id="fake-control-session",
producer_generation=1,
)
def status(session_state: str, observed_at_utc: str) -> PhysicalCommandStatusEvidence:
scanning = session_state == "scanning"
return PhysicalCommandStatusEvidence(
source="live-control-session",
vendor_device_id_sha256=identity.vendor_device_id_sha256,
device_serial_sha256=identity.device_serial_sha256,
control_session_id=connection.control_session_id,
host_path_epoch=connection.host_path_epoch,
producer_generation=connection.producer_generation,
session_state=session_state, # type: ignore[arg-type]
session_state_code=302 if scanning else 300,
project_bound=scanning,
project_id_sha256="c" * 64 if scanning else None,
init_ready=scanning,
status_message_sha256=hashlib.sha256(observed_at_utc.encode()).hexdigest(),
mqtt_retained=False,
observed_at_utc=observed_at_utc,
)
ledger = service._physical_command_ledger # noqa: SLF001
ledger.prepare(
operation_id=start_operation_id,
parent_operation_id=None,
acquisition_id=acquisition_id,
action="start",
identity=identity,
connection=connection,
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
payload_sha256="1" * 64,
baseline_status=status("ready", "2026-08-12T08:00:00.000Z"),
)
ledger.mark_dispatching(start_operation_id)
ledger.mark_observing(start_operation_id, publish_call_returned=True, packet_id=71)
ledger.mark_qos2_completed(start_operation_id, packet_id=71)
ledger.record_application_response(
start_operation_id,
PhysicalCommandApplicationResponse(
operation_id=start_operation_id,
action="start",
control_session_id=connection.control_session_id,
host_path_epoch=connection.host_path_epoch,
producer_generation=connection.producer_generation,
result_code=PHYSICAL_COMMAND_APPLICATION_SUCCESS_CODE,
success=True,
payload_sha256="2" * 64,
observed_at_utc="2026-08-12T08:00:01.000Z",
),
)
ledger.record_status_observation(
start_operation_id,
status("scanning", "2026-08-12T08:00:02.000Z"),
)
ledger.resolve(start_operation_id, resolution="start-active-observed")
coordinator = service._physical_command_coordinator # noqa: SLF001
coordinator.application_response(
ApplicationMqttResponseEvidence(
operation_key="bootstrap:stop-race:DeviceInfoRequest",
response_topic="lixel/application/response/device_info",
payload_sha256="3" * 64,
modeling_action=None,
result_code=None,
success=None,
observed_at_utc="2026-08-12T08:00:03.000Z",
)
)
coordinator.bind_control_session(
PhysicalCommandRuntimeBinding(
vendor_device_id_sha256=identity.vendor_device_id_sha256,
device_serial_sha256=identity.device_serial_sha256,
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
intent_id=connection.intent_id,
transport_ref=connection.transport_ref,
connection_mode=connection.connection_mode,
target_ipv4=connection.target_ipv4,
target_port=connection.target_port,
host_path_epoch=connection.host_path_epoch,
control_session_id=connection.control_session_id,
producer_generation=connection.producer_generation,
)
)
coordinator.device_status(
ApplicationMqttDeviceStatusEvidence(
vendor_device_id_sha256=identity.vendor_device_id_sha256,
device_serial_sha256=identity.device_serial_sha256,
session_state="scanning",
session_state_code=MODELING_STATE_BASE + 302,
project_bound=True,
project_id_sha256="c" * 64,
init_ready=True,
status_message_sha256="4" * 64,
mqtt_retained=False,
observed_at_utc="2026-08-12T08:00:04.000Z",
)
)
_activate_real_checkpoint_for_prepared_stop_fixture(
service,
project_name="STOP_RACE",
)
runtime.mark_ready()
runtime.pcl_frames = 1 if confirm_first_pcl else 0
assert service.state()["acquisition"]["state"] == (
"acquiring" if confirm_first_pcl else "awaiting_external_start"
)
payload = b"exact-stop-dispatch-race"
envelope = OneShotPublishEnvelope(
operation_key="modeling:stop",
topic="lixel/application/request/modeling",
payload=payload,
payload_sha256=hashlib.sha256(payload).hexdigest(),
payload_bytes=len(payload),
qos=2,
retain=False,
)
original_request_stop = control.request_stop
prepare_calls: list[str] = []
def request_stop_after_durable_prepare(**kwargs: object) -> dict[str, object]:
command_context = kwargs["command_context"]
coordinator.prepare(command_context, action="stop", envelope=envelope) # type: ignore[arg-type]
prepare_calls.append(str(command_context.operation_id)) # type: ignore[attr-defined]
result = original_request_stop(**kwargs) # type: ignore[arg-type]
control.state = "stop-requested"
return result
control.request_stop = request_stop_after_durable_prepare # type: ignore[method-assign]
stop_operation_id = "op-00000000-0000-4000-8000-000000001401"
request = _stop_request(
acquisition_id=acquisition_id,
operation_id=stop_operation_id,
idempotency_key="prepared-stop-dispatch-race",
mode="graceful",
physical_acceptance=PHYSICAL_ACCEPTANCE,
)
return SimpleNamespace(
service=service,
runtime=runtime,
control=control,
binding=binding,
coordinator=coordinator,
ledger=ledger,
identity=identity,
connection=connection,
status=status,
envelope=envelope,
request=request,
start_operation_id=start_operation_id,
stop_operation_id=stop_operation_id,
prepare_calls=prepare_calls,
)
def _observe_stop_race_route_loss(service: XgridsK1CompatibilityService) -> None:
service._connection_supervisor.observe_host_path( # noqa: SLF001
HostPathProbeResult(
available=False,
fingerprint=None,
interface=None,
source_ipv4=None,
route_class="unavailable",
reason_code="router-link-lost",
)
)
def _settle_real_prepared_stop_before_publish(
fixture: SimpleNamespace,
) -> facade_module._PreparedStopRecoveryOwner:
"""Drive the real S0 row to truthful NONE while retaining its receiver."""
fixture.control.state = "failed"
fixture.control.state_revision += 1
fixture.control.failure = {
"reason_code": "application-connection-binding-lost",
"modeling_command_attempted": False,
"safe_to_retry": False,
}
fixture.service.state()
owner = fixture.service._prepared_stop_recovery_owner # noqa: SLF001
assert isinstance(owner, facade_module._PreparedStopRecoveryOwner)
operation = fixture.service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert operation.stage_code == "physical-stop-classified-not-dispatched"
assert operation.error is not None
assert operation.error["side_effect_status"] == "none"
return owner
def _classify_real_prepared_stop(
fixture: SimpleNamespace,
owner: facade_module._PreparedStopRecoveryOwner,
*,
session_state: str,
reconciliation_id: str,
) -> dict[str, object]:
"""Install a fresh inspection binding and classify S0 with real coordinator audit."""
scanning = session_state == "scanning"
runtime_binding = PhysicalCommandRuntimeBinding(
vendor_device_id_sha256="a" * 64,
device_serial_sha256="b" * 64,
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
intent_id=fixture.binding.intent_id,
transport_ref=fixture.binding.transport_ref,
connection_mode=fixture.binding.connection_mode,
target_ipv4=fixture.binding.target_ipv4,
target_port=fixture.binding.target_port,
host_path_epoch=fixture.binding.host_path_epoch + 1,
control_session_id=f"fresh-{reconciliation_id}",
producer_generation=2,
)
fixture.coordinator.prepare_read_only_bootstrap()
fixture.coordinator.application_response(
ApplicationMqttResponseEvidence(
operation_key=f"bootstrap:{reconciliation_id}:DeviceInfoRequest",
response_topic="lixel/application/response/device_info",
payload_sha256="f" * 64,
modeling_action=None,
result_code=None,
success=None,
observed_at_utc="2026-08-12T08:00:59.000Z",
)
)
fixture.coordinator.bind_control_session(runtime_binding)
fixture.coordinator.device_status(
ApplicationMqttDeviceStatusEvidence(
vendor_device_id_sha256=runtime_binding.vendor_device_id_sha256,
device_serial_sha256=runtime_binding.device_serial_sha256,
session_state=session_state, # type: ignore[arg-type]
session_state_code=MODELING_STATE_BASE + (302 if scanning else 300),
project_bound=scanning,
project_id_sha256="c" * 64 if scanning else None,
init_ready=scanning,
status_message_sha256="e" * 64,
mqtt_retained=False,
observed_at_utc="2026-08-12T08:01:00.000Z",
)
)
return dict(
fixture.service._classify_retained_prepared_stop_owned( # noqa: SLF001
owner=owner,
reconciliation_id=reconciliation_id,
reconcile=lambda: fixture.coordinator.reconcile_unresolved(
reconciliation_id=reconciliation_id,
),
)
)
def _resolve_real_stop_ready(fixture: SimpleNamespace) -> None:
"""Advance the fixture's exact S0 to canonical durable READY without polling."""
fixture.ledger.mark_dispatching(fixture.stop_operation_id)
fixture.ledger.mark_observing(
fixture.stop_operation_id,
publish_call_returned=True,
packet_id=72,
)
fixture.ledger.mark_qos2_completed(fixture.stop_operation_id, packet_id=72)
fixture.ledger.record_application_response(
fixture.stop_operation_id,
PhysicalCommandApplicationResponse(
operation_id=fixture.stop_operation_id,
action="stop",
control_session_id=fixture.connection.control_session_id,
host_path_epoch=fixture.connection.host_path_epoch,
producer_generation=fixture.connection.producer_generation,
result_code=PHYSICAL_COMMAND_APPLICATION_SUCCESS_CODE,
success=True,
payload_sha256="5" * 64,
observed_at_utc="2026-08-12T08:00:05.000Z",
),
)
fixture.ledger.record_status_observation(
fixture.stop_operation_id,
fixture.status("ready", "2026-08-12T08:00:06.000Z"),
)
fixture.ledger.resolve(
fixture.stop_operation_id,
resolution="stop-standby-observed",
)
def test_prepared_stop_and_dispatch_gate_fence_route_loss_without_duplicate_publish(
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(service, runtime)
stopping = service.stop_acquisition(fixture.request)
prepared_record = fixture.ledger.snapshot().record
assert prepared_record is not None
assert prepared_record.operation_id == fixture.stop_operation_id
assert prepared_record.stage == "prepared"
assert service._prepared_stop_dispatch_lineage_is_current() is True # noqa: SLF001
assert stopping["selected_device_id"] == fixture.binding.transport_ref
# A route-negative state reduction lands after durable PREPARE but before
# the asynchronous worker owns the command-dispatch gate. It must not
# tear down the only topology that can execute this already accepted STOP.
for _ in range(3):
_observe_stop_race_route_loss(service)
state = service.state()
assert state["selected_device_id"] == fixture.binding.transport_ref
assert fixture.prepare_calls == [fixture.stop_operation_id]
repeated = service.stop_acquisition(fixture.request)
assert repeated["selected_device_id"] == fixture.binding.transport_ref
assert fixture.prepare_calls == [fixture.stop_operation_id]
dispatch = ApplicationMqttPublishEvidence(
operation_key="modeling:stop",
topic=fixture.envelope.topic,
payload_sha256=fixture.envelope.payload_sha256,
qos=2,
retain=False,
packet_id=None,
)
published: list[str] = []
assert service._k1_command_dispatch_gate.acquire(blocking=False) # noqa: SLF001
try:
fixture.coordinator.publish_dispatching(dispatch)
dispatching = fixture.ledger.snapshot().record
assert dispatching is not None and dispatching.stage == "dispatching"
# This is the exact mark_dispatching -> client.publish interleaving.
# The reducer sees confirmed loss but cannot cross the transport gate.
mid_dispatch = service.state()
assert mid_dispatch["selected_device_id"] == fixture.binding.transport_ref
published.append(fixture.envelope.payload_sha256)
finally:
service._k1_command_dispatch_gate.release() # noqa: SLF001
assert published == [fixture.envelope.payload_sha256]
assert fixture.prepare_calls == [fixture.stop_operation_id]
# Once the dispatch fence is released, the same genuine route loss uses
# the normal fail-closed reducer; PREPARED lineage no longer applies.
retired = service.state()
assert retired["selected_device_id"] is None
assert retired["device_session"] is None
@pytest.mark.parametrize("terminal_reason", ["control-failed", "deadline"])
def test_prepared_stop_barrier_expires_and_real_loss_retires_fail_closed(
tmp_path: Path,
terminal_reason: str,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(service, runtime)
service.stop_acquisition(fixture.request)
if terminal_reason == "control-failed":
fixture.control.state = "failed"
fixture.control.state_revision += 1
fixture.control.failure = {
"reason_code": "mqtt_network_loop_failed",
"modeling_command_attempted": False,
"safe_to_retry": False,
}
else:
operation = service._operations.get(fixture.stop_operation_id) # noqa: SLF001
operation.deadline_at = datetime.now(UTC) - timedelta(seconds=1)
for _ in range(3):
_observe_stop_race_route_loss(service)
assert service._prepared_stop_dispatch_lineage_is_current() is False # noqa: SLF001
retired = service.state()
if terminal_reason == "control-failed":
# A terminal pre-publish worker is no longer merely an expired dispatch
# barrier: it is exact NONE proof and retains the receiver/topology for
# the automatic read-only SCANNING/READY classification path.
assert retired["selected_device_id"] == fixture.binding.transport_ref
operation = service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert operation.stage_code == "physical-stop-classified-not-dispatched"
assert operation.error is not None
assert operation.error["side_effect_status"] == "none"
assert service._prepared_stop_recovery_owner is not None # noqa: SLF001
else:
# A hung nonterminal worker whose bounded operation deadline elapsed has
# no terminal NONE proof. Genuine route loss therefore retires normally.
assert retired["selected_device_id"] is None
assert fixture.ledger.snapshot().record is not None
assert fixture.ledger.snapshot().record.stage == "prepared" # type: ignore[union-attr]
assert fixture.prepare_calls == [fixture.stop_operation_id]
def test_prepared_stop_pending_worker_outranks_runtime_error_then_settles_none(
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(service, runtime)
service.stop_acquisition(fixture.request)
runtime.phase = "error"
# Local producer symptoms cannot terminalize an accepted STOP while the
# exact durable command is still PREPARED and its worker is nonterminal.
pending = service.state()
operation = service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert pending["acquisition"]["state"] == "awaiting_external_stop"
assert operation.status == "running"
assert operation.error is None
assert fixture.ledger.snapshot().record is not None
assert fixture.ledger.snapshot().record.stage == "prepared" # type: ignore[union-attr]
# The same row plus a terminal pre-publish worker is exact NONE proof.
fixture.control.state = "failed"
fixture.control.state_revision += 1
fixture.control.failure = {
"reason_code": "application-connection-binding-lost",
"modeling_command_attempted": False,
"safe_to_retry": False,
}
settled = service.state()
operation = service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert operation.status == "failed"
assert operation.stage_code == "physical-stop-classified-not-dispatched"
assert operation.error is not None
assert operation.error["side_effect_status"] == "none"
assert operation.error["physical_command_sent"] is False
assert settled["selected_device_id"] is None
def test_expired_stop_dispatch_admission_resolves_durable_no_dispatch(
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(service, runtime)
service.stop_acquisition(fixture.request)
assert len(fixture.control.stop_dispatch_deadlines) == 1
deadline_reached = fixture.control.stop_dispatch_deadlines[0]
assert deadline_reached is not None
operation = service._operations.get(fixture.stop_operation_id) # noqa: SLF001
operation.deadline_at = datetime.now(UTC) - timedelta(seconds=1)
assert deadline_reached() is True
fixture.control.state = "failed"
fixture.control.state_revision += 1
fixture.control.failure = {
"reason_code": "physical-command-dispatch-deadline-expired",
"modeling_command_attempted": True,
"stop_command_attempted": False,
"stop_publish_attempts": 0,
"diagnostic_evidence_unavailable": [],
"safe_to_retry": True,
}
fixture.control.outcome_unknown = False
fixture.control.transport_publish_attempts = 8
settled = service.state()
record = fixture.ledger.snapshot().record
assert record is not None
assert record.stage == "resolved"
assert record.resolution == "not-dispatched"
assert record.resolved_unclassified_stop_recovery_required is True
assert fixture.coordinator.snapshot()["active_operation_id"] is None
operation = service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert operation.stage_code == "physical-stop-classified-not-dispatched"
assert operation.error is not None
assert operation.error["side_effect_status"] == "none"
assert operation.error["physical_command_sent"] is False
assert operation.error["automatic_replay_allowed"] is False
assert service.camera_preview.snapshot()["recording"]["source_end_expected"] is False
assert service._prepared_stop_recovery_owner is not None # noqa: SLF001
assert settled["physical_command"]["record"]["resolution"] == "not-dispatched"
def test_abort_rejects_exact_unresolved_stop_before_any_local_cleanup(
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(service, runtime)
service.stop_acquisition(fixture.request)
before_operations = tuple(service._operations.snapshot()) # noqa: SLF001
with pytest.raises(
facade_module.LocalAcquisitionLifecycleError,
match="исход PREPARED/DISPATCHING STOP",
) as raised:
service.abort_acquisition(
_abort_request(acquisition_id=fixture.request.acquisition_id)
)
assert raised.value.reason_code == "acquisition-abort-physical-stop-unresolved"
assert tuple(service._operations.snapshot()) == before_operations # noqa: SLF001
operation = service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert operation.status == "running"
assert operation.error is None
record = fixture.ledger.snapshot().record
assert record is not None and record.stage == "prepared"
assert service._acquisition is not None # noqa: SLF001
assert service._acquisition.state == "awaiting_external_stop" # noqa: SLF001
assert service._acquisition_stop_operation_id == fixture.stop_operation_id # noqa: SLF001
assert runtime.stop_calls == 0
def test_capture_only_rejects_live_prepared_stop_before_operation_or_local_cleanup(
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(service, runtime)
service.stop_acquisition(fixture.request)
acquisition = service._acquisition # noqa: SLF001
assert acquisition is not None
before_operations = tuple(service._operations.snapshot()) # noqa: SLF001
before_acquisition = (
acquisition.state,
acquisition.state_revision,
acquisition.message_code,
acquisition.result,
)
with pytest.raises(
facade_module.LocalAcquisitionLifecycleError,
match="ещё владеет PREPARED STOP",
) as raised:
service.stop_acquisition(
_stop_request(
acquisition_id=acquisition.acquisition_id,
operation_id="op-00000000-0000-4000-8000-000000001450",
mode="capture-only",
)
)
assert raised.value.reason_code == "acquisition-stop-worker-retirement-pending"
assert tuple(service._operations.snapshot()) == before_operations # noqa: SLF001
assert fixture.control.state == "stop-requested"
record = fixture.ledger.snapshot().record
assert record is not None and record.stage == "prepared"
assert fixture.prepare_calls == [fixture.stop_operation_id]
assert (
acquisition.state,
acquisition.state_revision,
acquisition.message_code,
acquisition.result,
) == before_acquisition
assert service._acquisition_stop_operation_id == fixture.stop_operation_id # noqa: SLF001
assert runtime.stop_calls == 0
def test_capture_only_defers_terminal_prepared_stop_while_dispatch_gate_is_busy(
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(service, runtime)
service.stop_acquisition(fixture.request)
fixture.control.state = "failed"
fixture.control.failure = {
"reason_code": "application-connection-binding-lost",
"modeling_command_attempted": False,
"safe_to_retry": False,
}
before_operations = tuple(service._operations.snapshot()) # noqa: SLF001
assert service._k1_command_dispatch_gate.acquire(blocking=False) # noqa: SLF001
try:
with pytest.raises(
facade_module.LocalAcquisitionLifecycleError,
match="publish-переходом STOP",
) as raised:
service.stop_acquisition(
_stop_request(
acquisition_id=fixture.request.acquisition_id,
operation_id="op-00000000-0000-4000-8000-000000001451",
mode="capture-only",
)
)
finally:
service._k1_command_dispatch_gate.release() # noqa: SLF001
assert raised.value.reason_code == "acquisition-stop-dispatch-retirement-pending"
assert tuple(service._operations.snapshot()) == before_operations # noqa: SLF001
record = fixture.ledger.snapshot().record
assert record is not None and record.stage == "prepared"
operation = service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert operation.status == "running"
assert operation.error is None
assert fixture.prepare_calls == [fixture.stop_operation_id]
assert runtime.stop_calls == 0
def test_capture_only_settles_terminal_prepared_stop_none_before_local_cleanup(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(service, runtime)
service.stop_acquisition(fixture.request)
fixture.control.state = "failed"
fixture.control.failure = {
"reason_code": "application-connection-binding-lost",
"modeling_command_attempted": False,
"safe_to_retry": False,
}
monkeypatch.setattr(service, "_seal_acquisition_capture_clock", lambda: None)
completed = service.stop_acquisition(
_stop_request(
acquisition_id=fixture.request.acquisition_id,
operation_id="op-00000000-0000-4000-8000-000000001452",
mode="capture-only",
)
)
original_stop = service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert original_stop.status == "failed"
assert original_stop.stage_code == "physical-stop-classified-not-dispatched"
assert original_stop.error is not None
assert original_stop.error["side_effect_status"] == "none"
assert original_stop.error["physical_command_sent"] is False
local_stop = completed["last_operation"]
assert local_stop["operation_id"] == "op-00000000-0000-4000-8000-000000001452"
assert local_stop["status"] == "succeeded"
assert completed["acquisition"]["state"] == "completed"
assert completed["acquisition"]["result"]["device_stop"] == "not-sent"
record = fixture.ledger.snapshot().record
assert record is not None and record.stage == "prepared"
assert fixture.prepare_calls == [fixture.stop_operation_id]
assert fixture.control.stop_calls == 1
assert runtime.stop_calls == 1
def test_capture_only_cleanup_failure_preserves_s0_and_confirmed_start_truth(
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(
service,
runtime,
confirm_first_pcl=False,
)
service.stop_acquisition(fixture.request)
fixture.control.state = "failed"
fixture.control.failure = {
"reason_code": "application-connection-binding-lost",
"modeling_command_attempted": False,
"safe_to_retry": False,
}
runtime.stop_error = RuntimeError("synthetic capture-only cleanup timeout")
with pytest.raises(RuntimeError, match="synthetic capture-only cleanup timeout"):
service.stop_acquisition(
_stop_request(
acquisition_id=fixture.request.acquisition_id,
operation_id="op-00000000-0000-4000-8000-000000001457",
mode="capture-only",
)
)
start = service._operations.get(fixture.start_operation_id) # noqa: SLF001
original_stop = service._operations.get(fixture.stop_operation_id) # noqa: SLF001
local_stop = service._operations.get( # noqa: SLF001
"op-00000000-0000-4000-8000-000000001457"
)
assert start.status == "interrupted"
assert start.stage_code == "physical-start-active-local-retirement-before-point"
assert start.error is not None and start.error["side_effect_status"] == "succeeded"
assert original_stop.stage_code == "physical-stop-classified-not-dispatched"
assert original_stop.error is not None
assert original_stop.error["side_effect_status"] == "none"
assert local_stop.status == "failed"
assert service._acquisition_stop_operation_id == fixture.stop_operation_id # noqa: SLF001
record = fixture.ledger.snapshot().record
assert record is not None and record.stage == "prepared"
assert service._acquisition_session_lease is not None # noqa: SLF001
@pytest.mark.parametrize("stage", ["dispatching", "observing"])
def test_capture_only_preserves_postpublish_stop_unknown_before_local_cleanup(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
stage: str,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(service, runtime)
service.stop_acquisition(fixture.request)
dispatch = ApplicationMqttPublishEvidence(
operation_key="modeling:stop",
topic=fixture.envelope.topic,
payload_sha256=fixture.envelope.payload_sha256,
qos=2,
retain=False,
packet_id=None,
)
fixture.coordinator.publish_dispatching(dispatch)
if stage == "observing":
fixture.ledger.mark_observing(
fixture.stop_operation_id,
publish_call_returned=False,
packet_id=None,
)
monkeypatch.setattr(service, "_seal_acquisition_capture_clock", lambda: None)
completed = service.stop_acquisition(
_stop_request(
acquisition_id=fixture.request.acquisition_id,
operation_id=(
"op-00000000-0000-4000-8000-000000001453"
if stage == "dispatching"
else "op-00000000-0000-4000-8000-000000001454"
),
mode="capture-only",
)
)
original_stop = service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert original_stop.status == "failed"
assert original_stop.stage_code == "physical-stop-outcome-unknown-local-retirement"
assert original_stop.error is not None
assert original_stop.error["side_effect_status"] == "unknown"
assert original_stop.error["automatic_replay_allowed"] is False
assert completed["last_operation"]["status"] == "succeeded"
assert completed["acquisition"]["result"]["device_stop"] == (
"physical-outcome-unknown"
)
record = fixture.ledger.snapshot().record
assert record is not None and record.stage == stage
assert fixture.prepare_calls == [fixture.stop_operation_id]
assert fixture.control.stop_calls == 1
assert runtime.stop_calls == 1
@pytest.mark.parametrize("action", ["capture-only", "abort", "force", "reset", "close"])
def test_resolved_ready_preducer_dominates_destructive_action_and_pending_start(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
action: str,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(
service,
runtime,
confirm_first_pcl=False,
)
service.stop_acquisition(fixture.request)
_resolve_real_stop_ready(fixture)
monkeypatch.setattr(service, "_seal_acquisition_capture_clock", lambda: None)
if action == "close":
monkeypatch.setattr(service.camera_preview, "close", lambda: None)
monkeypatch.setattr(runtime, "close", runtime.stop)
before_record = fixture.ledger.snapshot().record
before_prepare_calls = list(fixture.prepare_calls)
before_operation_ids = {
item["operation_id"]
for item in service._operations.snapshot() # noqa: SLF001
}
if action == "capture-only":
result = service.stop_acquisition(
_stop_request(
acquisition_id=fixture.request.acquisition_id,
operation_id="op-00000000-0000-4000-8000-000000001455",
mode="capture-only",
)
)
assert result["acquisition"]["state"] == "completed"
elif action == "abort":
result = service.abort_acquisition(
_abort_request(
acquisition_id=fixture.request.acquisition_id,
operation_id="op-00000000-0000-4000-8000-000000001456",
)
)
assert result["acquisition"]["state"] == "completed"
elif action == "force":
with service._acquisition_lifecycle_gate: # noqa: SLF001
assert service._force_finish_active_acquisition_locally( # noqa: SLF001
reason_code="test-resolved-ready-dominance",
require_recovery=False,
)
elif action == "reset":
service.select_connection_mode(
DesiredConnectionModeRequest(
connection_mode="quick-connect",
expected_revision=service._desired_connection_mode_revision, # noqa: SLF001
reset_scenario=True,
reset_id="resolved-ready-preducer-reset-0001",
)
)
else:
service.close()
start = service._operations.get(fixture.start_operation_id) # noqa: SLF001
stop = service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert start.status == "interrupted"
assert start.stage_code == "physical-start-active-but-no-point-before-standby"
assert start.error is not None
assert start.error["side_effect_status"] == "succeeded"
assert start.error["automatic_replay_allowed"] is False
assert stop.status == "succeeded"
assert stop.stage_code == "device-standby-confirmed"
assert service._acquisition is not None # noqa: SLF001
assert service._acquisition.result is not None # noqa: SLF001
assert service._acquisition.result["device_state"] == "ready" # noqa: SLF001
assert service._acquisition.result["device_stop"] == "protocol-confirmed" # noqa: SLF001
assert fixture.ledger.snapshot().record == before_record
assert fixture.prepare_calls == before_prepare_calls
assert fixture.control.stop_calls == 1
assert runtime.stop_calls == 1
after_operation_ids = {
item["operation_id"]
for item in service._operations.snapshot() # noqa: SLF001
}
assert after_operation_ids == before_operation_ids
def test_local_force_finish_fences_prepared_stop_then_settles_none_before_cleanup(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(service, runtime)
service.stop_acquisition(fixture.request)
monkeypatch.setattr(service, "_seal_acquisition_capture_clock", lambda: None)
with service._acquisition_lifecycle_gate: # noqa: SLF001
assert service._force_finish_active_acquisition_locally( # noqa: SLF001
reason_code="test-local-retirement",
require_recovery=False,
)
operation = service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert operation.status == "failed"
assert operation.stage_code == "physical-stop-classified-not-dispatched"
assert operation.error is not None
assert operation.error["side_effect_status"] == "none"
assert operation.error["physical_command_sent"] is False
record = fixture.ledger.snapshot().record
assert record is not None and record.stage == "prepared"
assert service._acquisition is not None # noqa: SLF001
assert service._acquisition.state == "interrupted" # noqa: SLF001
assert service._acquisition.result is not None # noqa: SLF001
assert service._acquisition.result["device_stop"] == "not-sent" # noqa: SLF001
assert service._acquisition_stop_operation_id == fixture.stop_operation_id # noqa: SLF001
assert runtime.stop_calls == 1
def test_local_force_finish_preserves_confirmed_start_truth_before_first_point(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(
service,
runtime,
confirm_first_pcl=False,
)
service.stop_acquisition(fixture.request)
start_before = service._operations.get(fixture.start_operation_id) # noqa: SLF001
assert start_before.status == "running"
monkeypatch.setattr(service, "_seal_acquisition_capture_clock", lambda: None)
with service._acquisition_lifecycle_gate: # noqa: SLF001
assert service._force_finish_active_acquisition_locally( # noqa: SLF001
reason_code="test-local-retirement",
require_recovery=False,
)
start = service._operations.get(fixture.start_operation_id) # noqa: SLF001
assert start.status == "interrupted"
assert start.stage_code == "physical-start-active-local-retirement-before-point"
assert start.error is not None
assert start.error["side_effect_status"] == "succeeded"
assert start.error["automatic_replay_allowed"] is False
stop = service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert stop.stage_code == "physical-stop-classified-not-dispatched"
assert stop.error is not None and stop.error["side_effect_status"] == "none"
def test_local_force_finish_preserves_dispatching_stop_as_outcome_unknown(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(service, runtime)
service.stop_acquisition(fixture.request)
dispatch = ApplicationMqttPublishEvidence(
operation_key="modeling:stop",
topic=fixture.envelope.topic,
payload_sha256=fixture.envelope.payload_sha256,
qos=2,
retain=False,
packet_id=None,
)
assert service._k1_command_dispatch_gate.acquire(blocking=False) # noqa: SLF001
try:
fixture.coordinator.publish_dispatching(dispatch)
finally:
service._k1_command_dispatch_gate.release() # noqa: SLF001
monkeypatch.setattr(service, "_seal_acquisition_capture_clock", lambda: None)
with service._acquisition_lifecycle_gate: # noqa: SLF001
assert service._force_finish_active_acquisition_locally( # noqa: SLF001
reason_code="test-local-retirement",
require_recovery=False,
)
operation = service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert operation.status == "failed"
assert operation.stage_code == "physical-stop-outcome-unknown-local-retirement"
assert operation.error is not None
assert operation.error["side_effect_status"] == "unknown"
assert operation.error["automatic_replay_allowed"] is False
record = fixture.ledger.snapshot().record
assert record is not None and record.stage == "dispatching"
assert service._acquisition is not None # noqa: SLF001
assert service._acquisition.state == "interrupted" # noqa: SLF001
assert service._acquisition.result is not None # noqa: SLF001
assert service._acquisition.result["device_stop"] == "physical-outcome-unknown" # noqa: SLF001
assert "physical_command_sent" not in service._acquisition.result # noqa: SLF001
assert service._acquisition_stop_operation_id == fixture.stop_operation_id # noqa: SLF001
def test_local_force_finish_defers_without_mutation_while_dispatch_gate_is_owned(
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(service, runtime)
service.stop_acquisition(fixture.request)
acquisition = service._acquisition # noqa: SLF001
assert acquisition is not None
before_revision = acquisition.state_revision
before_recovery_generation = service._active_stream_recovery_generation # noqa: SLF001
assert service._k1_command_dispatch_gate.acquire(blocking=False) # noqa: SLF001
try:
with service._acquisition_lifecycle_gate, pytest.raises( # noqa: SLF001
facade_module.LocalAcquisitionLifecycleError,
match="publish-переходом STOP",
) as raised:
service._force_finish_active_acquisition_locally( # noqa: SLF001
reason_code="test-local-retirement",
require_recovery=False,
)
finally:
service._k1_command_dispatch_gate.release() # noqa: SLF001
assert raised.value.reason_code == "acquisition-stop-dispatch-retirement-pending"
operation = service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert operation.status == "running"
assert operation.error is None
record = fixture.ledger.snapshot().record
assert record is not None and record.stage == "prepared"
assert service._acquisition is acquisition # noqa: SLF001
assert acquisition.state == "awaiting_external_stop"
assert acquisition.state_revision == before_revision
assert service._acquisition_stop_operation_id == fixture.stop_operation_id # noqa: SLF001
assert ( # noqa: SLF001
service._active_stream_recovery_generation == before_recovery_generation
)
assert fixture.control.state == "stop-requested"
assert runtime.stop_calls == 0
def test_scenario_reset_fences_prepared_stop_before_local_cleanup_and_durable_retirement(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(service, runtime)
service.stop_acquisition(fixture.request)
monkeypatch.setattr(service, "_seal_acquisition_capture_clock", lambda: None)
reset = service.select_connection_mode(
DesiredConnectionModeRequest(
connection_mode="quick-connect",
expected_revision=service.state()["desired_connection_mode_revision"],
reset_scenario=True,
reset_id="prepared-stop-reset-0001",
)
)
operation = service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert operation.status == "failed"
assert operation.stage_code == "physical-stop-classified-not-dispatched"
assert operation.error is not None
assert operation.error["side_effect_status"] == "none"
record = fixture.ledger.snapshot().record
assert record is not None
assert record.operation_id == fixture.stop_operation_id
assert record.stage == "resolved"
assert record.resolution == "not-dispatched"
assert reset["connection_scenario_reset"]["physical_disposition"] == "not-dispatched"
assert reset["connection_scenario_reset"]["device_command_performed"] is False
assert reset["acquisition"]["state"] == "interrupted"
assert service._acquisition_stop_operation_id is None # noqa: SLF001
assert runtime.stop_calls == 1
def test_scenario_reset_dispatch_gate_defer_preserves_owner_then_exact_retry_converges(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(service, runtime)
service.stop_acquisition(fixture.request)
monkeypatch.setattr(service, "_seal_acquisition_capture_clock", lambda: None)
request = DesiredConnectionModeRequest(
connection_mode="quick-connect",
expected_revision=service.state()["desired_connection_mode_revision"],
reset_scenario=True,
reset_id="prepared-stop-reset-retry-0001",
)
assert service._k1_command_dispatch_gate.acquire(blocking=False) # noqa: SLF001
try:
with pytest.raises(
facade_module.LocalAcquisitionLifecycleError,
match="publish-переходом STOP",
) as raised:
service.select_connection_mode(request)
finally:
service._k1_command_dispatch_gate.release() # noqa: SLF001
assert raised.value.reason_code == "acquisition-stop-dispatch-retirement-pending"
operation = service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert operation.status == "running"
assert operation.error is None
record = fixture.ledger.snapshot().record
assert record is not None and record.stage == "prepared"
assert service._acquisition is not None # noqa: SLF001
assert service._acquisition.state == "awaiting_external_stop" # noqa: SLF001
assert service._acquisition_stop_operation_id == fixture.stop_operation_id # noqa: SLF001
assert runtime.stop_calls == 0
retried = service.select_connection_mode(request)
operation = service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert operation.stage_code == "physical-stop-classified-not-dispatched"
assert operation.error is not None
assert operation.error["side_effect_status"] == "none"
record = fixture.ledger.snapshot().record
assert record is not None and record.resolution == "not-dispatched"
assert retried["connection_scenario_reset"]["physical_disposition"] == "not-dispatched"
def test_scenario_reset_retires_dispatching_stop_as_outcome_unknown_never_cancelled(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(service, runtime)
service.stop_acquisition(fixture.request)
dispatch = ApplicationMqttPublishEvidence(
operation_key="modeling:stop",
topic=fixture.envelope.topic,
payload_sha256=fixture.envelope.payload_sha256,
qos=2,
retain=False,
packet_id=None,
)
assert service._k1_command_dispatch_gate.acquire(blocking=False) # noqa: SLF001
try:
fixture.coordinator.publish_dispatching(dispatch)
finally:
service._k1_command_dispatch_gate.release() # noqa: SLF001
monkeypatch.setattr(service, "_seal_acquisition_capture_clock", lambda: None)
reset = service.select_connection_mode(
DesiredConnectionModeRequest(
connection_mode="quick-connect",
expected_revision=service.state()["desired_connection_mode_revision"],
reset_scenario=True,
reset_id="dispatching-stop-reset-0001",
)
)
operation = service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert operation.status == "failed"
assert operation.stage_code == "physical-stop-outcome-unknown-local-retirement"
assert operation.error is not None
assert operation.error["side_effect_status"] == "unknown"
assert operation.error["automatic_replay_allowed"] is False
record = fixture.ledger.snapshot().record
assert record is not None
assert record.stage == "resolved"
assert record.resolution == "operator-retired-outcome-unknown"
assert reset["connection_scenario_reset"]["physical_disposition"] == (
"operator-retired-outcome-unknown"
)
assert service._acquisition_stop_operation_id is None # noqa: SLF001
@pytest.mark.parametrize(
("session_state", "expected_message", "expected_physical_state"),
[
(
"scanning",
"acquisition.recovery.scanning_adoption_pending",
"active",
),
(
"ready",
"acquisition.recovery.device_standby_observed",
"standby",
),
],
)
def test_retained_prepared_stop_classification_reserves_local_owner_from_durable_audit(
tmp_path: Path,
session_state: str,
expected_message: str,
expected_physical_state: str,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(service, runtime)
service.stop_acquisition(fixture.request)
owner = _settle_real_prepared_stop_before_publish(fixture)
original_acquisition = owner.acquisition
original_lease = owner.session_lease
original_out_dir = owner.out_dir
reconciled = _classify_real_prepared_stop(
fixture,
owner,
session_state=session_state,
reconciliation_id=f"test-{session_state}-retained",
)
physical = fixture.coordinator.snapshot()
assert reconciled["operation_id"] == fixture.stop_operation_id
assert reconciled["stage"] == "resolved"
assert reconciled["resolution"] == "not-dispatched"
assert physical["reconciled_physical_state"] == expected_physical_state
assert service._acquisition is original_acquisition # noqa: SLF001
assert service._acquisition_session_lease is original_lease # noqa: SLF001
assert service._acquisition_out_dir == original_out_dir # noqa: SLF001
assert service._acquisition.message_code == expected_message # noqa: SLF001
assert runtime.stop_calls == 0
assert fixture.control.stop_calls == 1
stop_operation = service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert stop_operation.stage_code == "physical-stop-classified-not-dispatched"
assert stop_operation.error is not None
assert stop_operation.error["side_effect_status"] == "none"
@pytest.mark.parametrize("session_state", ["ready", "scanning"])
def test_resolved_unclassified_stop_compatibility_classifies_without_new_command(
tmp_path: Path,
session_state: str,
) -> None:
"""A startup-resolved legacy STOP still takes the read-only classifier."""
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(service, runtime)
service.stop_acquisition(fixture.request)
_settle_real_prepared_stop_before_publish(fixture)
fixture.ledger.resolve(
fixture.stop_operation_id,
resolution="not-dispatched",
)
fixture.coordinator = LedgerPhysicalCommandCoordinator(fixture.ledger)
service._physical_command_coordinator = fixture.coordinator # noqa: SLF001
compatibility = fixture.coordinator.snapshot()
compatibility_record = compatibility["record"]
assert isinstance(compatibility_record, dict)
compatibility_revision = compatibility_record["revision"]
assert compatibility["status"] == "resolved"
assert compatibility["requires_reconciliation"] is True
assert compatibility["resolved_unclassified_stop_recovery_required"] is True
assert compatibility["reconciliation_ready"] is False
before_prepare_calls = list(fixture.prepare_calls)
before_control_stop_calls = fixture.control.stop_calls
reconciliation_id = f"test-resolved-unclassified-{session_state}"
scanning = session_state == "scanning"
runtime_binding = PhysicalCommandRuntimeBinding(
vendor_device_id_sha256="a" * 64,
device_serial_sha256="b" * 64,
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
intent_id=fixture.binding.intent_id,
transport_ref=fixture.binding.transport_ref,
connection_mode=fixture.binding.connection_mode,
target_ipv4=fixture.binding.target_ipv4,
target_port=fixture.binding.target_port,
host_path_epoch=fixture.binding.host_path_epoch + 1,
control_session_id=f"fresh-{reconciliation_id}",
producer_generation=2,
)
fixture.coordinator.prepare_read_only_bootstrap()
fixture.coordinator.application_response(
ApplicationMqttResponseEvidence(
operation_key=f"bootstrap:{reconciliation_id}:DeviceInfoRequest",
response_topic="lixel/application/response/device_info",
payload_sha256="f" * 64,
modeling_action=None,
result_code=None,
success=None,
observed_at_utc="2026-08-12T08:10:59.000Z",
)
)
fixture.coordinator.bind_control_session(runtime_binding)
fixture.coordinator.device_status(
ApplicationMqttDeviceStatusEvidence(
vendor_device_id_sha256=runtime_binding.vendor_device_id_sha256,
device_serial_sha256=runtime_binding.device_serial_sha256,
session_state=session_state, # type: ignore[arg-type]
session_state_code=MODELING_STATE_BASE + (302 if scanning else 300),
project_bound=scanning,
project_id_sha256="c" * 64 if scanning else None,
init_ready=scanning,
status_message_sha256="e" * 64,
mqtt_retained=False,
observed_at_utc="2026-08-12T08:11:00.000Z",
)
)
reconciled = fixture.coordinator.reconcile_unresolved(
reconciliation_id=reconciliation_id,
)
latest = reconciled["reconciliations"][-1]
original_attempt = latest["original_attempt"]
assert reconciled["revision"] == compatibility_revision + 1
assert reconciled["operation_id"] == fixture.stop_operation_id
assert reconciled["stage"] == "resolved"
assert reconciled["resolution"] == "not-dispatched"
assert latest["kind"] == "prepared-stop-classification"
assert latest["resolution"] == (
"physical-active-observed"
if session_state == "scanning"
else "physical-standby-observed"
)
assert original_attempt["stage"] == "resolved"
assert original_attempt["resolution"] == "not-dispatched"
assert original_attempt["publish_call_returned"] is None
assert original_attempt["packet_id"] is None
assert original_attempt["qos2_completed"] is False
physical = fixture.coordinator.snapshot()
matcher = (
service._matching_classified_prepared_stop_active # noqa: SLF001
if scanning
else service._matching_classified_prepared_stop_standby # noqa: SLF001
)
assert matcher(
physical,
acquisition_id=reconciled["acquisition_id"],
stop_operation_id=fixture.stop_operation_id,
start_operation_id=fixture.start_operation_id,
verified_control=latest["verified_binding"]["connection"],
)
assert fixture.prepare_calls == before_prepare_calls
assert fixture.control.stop_calls == before_control_stop_calls
assert runtime.stop_calls == 0
def test_retained_prepared_stop_commit_and_local_reservation_are_one_lifecycle_transaction(
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(service, runtime)
service.stop_acquisition(fixture.request)
owner = _settle_real_prepared_stop_before_publish(fixture)
fixture.coordinator.prepare_read_only_bootstrap()
fixture.coordinator.application_response(
ApplicationMqttResponseEvidence(
operation_key="bootstrap:test-atomic:DeviceInfoRequest",
response_topic="lixel/application/response/device_info",
payload_sha256="f" * 64,
modeling_action=None,
result_code=None,
success=None,
observed_at_utc="2026-08-12T08:01:59.000Z",
)
)
binding = PhysicalCommandRuntimeBinding(
vendor_device_id_sha256="a" * 64,
device_serial_sha256="b" * 64,
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
intent_id=fixture.binding.intent_id,
transport_ref=fixture.binding.transport_ref,
connection_mode=fixture.binding.connection_mode,
target_ipv4=fixture.binding.target_ipv4,
target_port=fixture.binding.target_port,
host_path_epoch=fixture.binding.host_path_epoch + 1,
control_session_id="fresh-atomic-classification",
producer_generation=2,
)
fixture.coordinator.bind_control_session(binding)
fixture.coordinator.device_status(
ApplicationMqttDeviceStatusEvidence(
vendor_device_id_sha256="a" * 64,
device_serial_sha256="b" * 64,
session_state="scanning",
session_state_code=MODELING_STATE_BASE + 302,
project_bound=True,
project_id_sha256="c" * 64,
init_ready=True,
status_message_sha256="e" * 64,
mqtt_retained=False,
observed_at_utc="2026-08-12T08:02:00.000Z",
)
)
committed = threading.Event()
allow_reservation = threading.Event()
state_finished = threading.Event()
errors: list[BaseException] = []
def reconcile_after_pause() -> dict[str, object]:
record = fixture.coordinator.reconcile_unresolved(
reconciliation_id="test-atomic-classification",
)
committed.set()
assert allow_reservation.wait(timeout=5)
return record
def classify() -> None:
try:
service._classify_retained_prepared_stop_owned( # noqa: SLF001
owner=owner,
reconciliation_id="test-atomic-classification",
reconcile=reconcile_after_pause,
)
except BaseException as exc: # pragma: no cover - assertion surface
errors.append(exc)
def poll_state() -> None:
try:
service.state()
except BaseException as exc: # pragma: no cover - assertion surface
errors.append(exc)
finally:
state_finished.set()
classify_thread = threading.Thread(target=classify)
classify_thread.start()
assert committed.wait(timeout=5)
poll_thread = threading.Thread(target=poll_state)
poll_thread.start()
assert state_finished.wait(timeout=0.05) is False
allow_reservation.set()
classify_thread.join(timeout=5)
poll_thread.join(timeout=5)
assert not errors
assert state_finished.is_set()
assert service._acquisition is owner.acquisition # noqa: SLF001
assert service._acquisition_session_lease is owner.session_lease # noqa: SLF001
assert service._acquisition.message_code == ( # noqa: SLF001
"acquisition.recovery.scanning_adoption_pending"
)
def test_exact_old_stop_retry_is_idempotent_during_scanning_adoption_pending(
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(service, runtime)
service.stop_acquisition(fixture.request)
owner = _settle_real_prepared_stop_before_publish(fixture)
_classify_real_prepared_stop(
fixture,
owner,
session_state="scanning",
reconciliation_id="test-old-s0-retry-pending",
)
before_record = fixture.ledger.snapshot().record
before_operations = tuple(service._operations.snapshot()) # noqa: SLF001
before_control_calls = fixture.control.stop_calls
before_prepare_calls = list(fixture.prepare_calls)
repeated = service.stop_acquisition(fixture.request)
assert repeated["acquisition"]["message_code"] == (
"acquisition.recovery.scanning_adoption_pending"
)
assert fixture.ledger.snapshot().record == before_record
assert tuple(service._operations.snapshot()) == before_operations # noqa: SLF001
assert fixture.control.stop_calls == before_control_calls
assert fixture.prepare_calls == before_prepare_calls
assert service._prepared_stop_recovery_owner is owner # noqa: SLF001
assert runtime.stop_calls == 0
@pytest.mark.parametrize(
"action",
["abort", "capture-only", "force", "reset", "close"],
)
def test_ready_local_projection_pending_rejects_destructive_action_without_mutation(
tmp_path: Path,
action: str,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(service, runtime)
service.stop_acquisition(fixture.request)
owner = _settle_real_prepared_stop_before_publish(fixture)
_classify_real_prepared_stop(
fixture,
owner,
session_state="ready",
reconciliation_id=f"test-ready-pending-{action}",
)
acquisition = service._acquisition # noqa: SLF001
assert acquisition is owner.acquisition
before_record = fixture.ledger.snapshot().record
before_operations = tuple(service._operations.snapshot()) # noqa: SLF001
before_state = (
acquisition.state,
acquisition.state_revision,
acquisition.message_code,
acquisition.result,
)
before_stop_pointer = service._acquisition_stop_operation_id # noqa: SLF001
before_start_pointer = service._acquisition_start_operation_id # noqa: SLF001
before_control_calls = fixture.control.stop_calls
before_prepare_calls = list(fixture.prepare_calls)
with pytest.raises(facade_module.LocalAcquisitionLifecycleError) as raised:
if action == "abort":
service.abort_acquisition(
_abort_request(acquisition_id=acquisition.acquisition_id)
)
elif action == "capture-only":
service.stop_acquisition(
_stop_request(
acquisition_id=acquisition.acquisition_id,
operation_id=f"op-ready-pending-capture-{action}",
mode="capture-only",
)
)
elif action == "force":
service.force_finish_acquisition_locally(
_force_finish_request(
acquisition_id=acquisition.acquisition_id,
expected_state_revision=acquisition.state_revision,
expected_recovery_generation=(
service._active_stream_recovery_generation # noqa: SLF001
),
)
)
elif action == "reset":
service.select_connection_mode(
DesiredConnectionModeRequest(
connection_mode="quick-connect",
expected_revision=service._desired_connection_mode_revision, # noqa: SLF001
reset_scenario=True,
reset_id="ready-pending-reset-0001",
)
)
else:
service.close()
assert raised.value.reason_code == "acquisition-prepared-stop-adoption-pending"
assert fixture.ledger.snapshot().record == before_record
assert tuple(service._operations.snapshot()) == before_operations # noqa: SLF001
assert (
acquisition.state,
acquisition.state_revision,
acquisition.message_code,
acquisition.result,
) == before_state
assert service._acquisition_stop_operation_id == before_stop_pointer # noqa: SLF001
assert service._acquisition_start_operation_id == before_start_pointer # noqa: SLF001
assert service._prepared_stop_recovery_owner is owner # noqa: SLF001
assert fixture.control.stop_calls == before_control_calls
assert fixture.prepare_calls == before_prepare_calls
assert runtime.stop_calls == 0
assert service._connection_scenario_reset_pending is None # noqa: SLF001
assert service._service_close_requested.is_set() is False # noqa: SLF001
def test_classified_scanning_adopts_same_receiver_and_allows_one_fresh_stop(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(service, runtime)
service.stop_acquisition(fixture.request)
owner = _settle_real_prepared_stop_before_publish(fixture)
reconciled = _classify_real_prepared_stop(
fixture,
owner,
session_state="scanning",
reconciliation_id="test-scanning-in-place",
)
latest = reconciled["reconciliations"][-1]
verified_binding = latest["verified_binding"]["connection"]
fixture.control.state = "scanning"
fixture.control.state_revision += 1
fixture.control.failure = None
fixture.control.verified_control = {
**dict(verified_binding),
"logical_device_id": "known-k1",
"compatibility_profile_id": XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
}
old_device_session_id = owner.acquisition.device_session_id
service._device_session_id = "fresh-in-place-device-session" # noqa: SLF001
runtime_start_calls = list(runtime.start_calls)
service._adopt_classified_prepared_stop_scanning_in_place( # noqa: SLF001
owner=owner,
reconciliation_id="test-scanning-in-place",
reconciled_record=reconciled,
)
assert service._acquisition is owner.acquisition # noqa: SLF001
assert service._acquisition_session_lease is owner.session_lease # noqa: SLF001
assert service._acquisition_out_dir == owner.out_dir # noqa: SLF001
assert service._acquisition.device_session_id != old_device_session_id # noqa: SLF001
assert service._acquisition.device_session_id == ( # noqa: SLF001
"fresh-in-place-device-session"
)
assert service._acquisition.state == "acquiring" # noqa: SLF001
assert service._acquisition_stop_operation_id is None # noqa: SLF001
assert runtime.start_calls == runtime_start_calls
# Hold the durable gap closure exactly where its fsync may block. A public
# STOP must publish priority without waiting for lifecycle ownership; once
# the store resumes, that priority prevents this already-published PCL from
# granting camera authority and the fresh STOP owns the next durable edge.
store = service._active_acquisition_checkpoint # noqa: SLF001
assert store is not None
original_rebind_active = store.rebind_active
rebind_entered = threading.Event()
release_rebind = threading.Event()
def blocked_rebind_active(**kwargs: Any) -> Any:
rebind_entered.set()
assert release_rebind.wait(timeout=2.0)
return original_rebind_active(**kwargs)
monkeypatch.setattr(store, "rebind_active", blocked_rebind_active)
camera_calls: list[str] = []
def forbidden_camera_start(*_: object, **__: object) -> dict[str, object]:
camera_calls.append("camera-start")
return service.camera_preview.snapshot()
monkeypatch.setattr(
service.camera_preview,
"activate_recording_producer",
forbidden_camera_start,
)
monkeypatch.setattr(
service.camera_preview,
"retry_recording_producer",
forbidden_camera_start,
)
frame = DecodedPointCloudView(
context=ConsumerFrameContext(
sequence=1,
captured_at_epoch_ns=1,
received_monotonic_ns=1,
processing_started_monotonic_ns=1,
encoded_size_bytes=16,
live=True,
),
frame_id="map",
positions_xyz=((0.0, 0.0, 0.0),),
)
runtime.phase = "live"
runtime.source_mode = "live"
runtime.source_ready = True
runtime.pcl_frames = 1
publish_errors: list[BaseException] = []
def publish_first_pcl() -> None:
try:
service._observe_published_runtime_envelope( # noqa: SLF001
frame,
runtime.producer_generation,
)
except BaseException as exc: # pragma: no cover - asserted below
publish_errors.append(exc)
fresh_stop_id = "op-00000000-0000-4000-8000-000000001402"
fresh_request = _stop_request(
acquisition_id=owner.lineage.acquisition_id,
operation_id=fresh_stop_id,
idempotency_key="classified-scanning-fresh-stop",
mode="graceful",
physical_acceptance=PHYSICAL_ACCEPTANCE,
expected_control_session_generation=fixture.control.session_generation,
expected_control_state_revision=fixture.control.state_revision,
)
stop_results: list[dict[str, Any]] = []
stop_errors: list[BaseException] = []
def request_fresh_stop() -> None:
try:
stop_results.append(service.stop_acquisition(fresh_request))
except BaseException as exc: # pragma: no cover - asserted below
stop_errors.append(exc)
publish_thread = threading.Thread(target=publish_first_pcl)
stop_thread = threading.Thread(target=request_fresh_stop)
publish_thread.start()
try:
assert rebind_entered.wait(timeout=2.0)
stop_thread.start()
deadline = time.monotonic() + 2.0
while time.monotonic() < deadline:
with service._lock: # noqa: SLF001
if service._camera_stop_priority_counts.get( # noqa: SLF001
owner.lineage.acquisition_id,
0,
):
break
time.sleep(0.005)
with service._lock: # noqa: SLF001
assert service._camera_stop_priority_counts.get( # noqa: SLF001
owner.lineage.acquisition_id,
0,
) == 1
assert stop_thread.is_alive()
finally:
release_rebind.set()
publish_thread.join(timeout=2.0)
if stop_thread.ident is not None:
stop_thread.join(timeout=2.0)
assert publish_thread.is_alive() is False
assert stop_thread.is_alive() is False
assert publish_errors == []
assert stop_errors == []
assert len(stop_results) == 1
fresh = stop_results[0]
assert camera_calls == []
with service._lock: # noqa: SLF001
assert service._classified_stop_rebind_pending is None # noqa: SLF001
assert service._classified_stop_rebind_inflight is None # noqa: SLF001
record = fixture.ledger.snapshot().record
assert record is not None
assert record.operation_id == fresh_stop_id
assert record.parent_operation_id == fixture.stop_operation_id
assert record.stage == "prepared"
assert fresh["acquisition"]["state"] == "awaiting_external_stop"
assert fixture.prepare_calls == [fixture.stop_operation_id, fresh_stop_id]
assert runtime.start_calls == runtime_start_calls
def test_blocked_checkpoint_fsync_starts_stop_deadline_and_expires_before_prepare(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(service, runtime)
service.stop_acquisition(fixture.request)
owner = _settle_real_prepared_stop_before_publish(fixture)
reconciled = _classify_real_prepared_stop(
fixture,
owner,
session_state="scanning",
reconciliation_id="test-scanning-stop-deadline-fsync",
)
verified_binding = reconciled["reconciliations"][-1]["verified_binding"]["connection"]
fixture.control.state = "scanning"
fixture.control.state_revision += 1
fixture.control.failure = None
fixture.control.verified_control = {
**dict(verified_binding),
"logical_device_id": "known-k1",
"compatibility_profile_id": XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
}
service._device_session_id = "fresh-stop-deadline-session" # noqa: SLF001
service._adopt_classified_prepared_stop_scanning_in_place( # noqa: SLF001
owner=owner,
reconciliation_id="test-scanning-stop-deadline-fsync",
reconciled_record=reconciled,
)
store = service._active_acquisition_checkpoint # noqa: SLF001
assert store is not None
original_rebind_active = store.rebind_active
rebind_entered = threading.Event()
release_rebind = threading.Event()
def blocked_rebind_active(**kwargs: Any) -> Any:
rebind_entered.set()
assert release_rebind.wait(timeout=3.0)
return original_rebind_active(**kwargs)
monkeypatch.setattr(store, "rebind_active", blocked_rebind_active)
frame = DecodedPointCloudView(
context=ConsumerFrameContext(
sequence=1,
captured_at_epoch_ns=1,
received_monotonic_ns=1,
processing_started_monotonic_ns=1,
encoded_size_bytes=16,
live=True,
),
frame_id="map",
positions_xyz=((0.0, 0.0, 0.0),),
)
runtime.phase = "live"
runtime.source_mode = "live"
runtime.source_ready = True
runtime.pcl_frames = 1
publish_thread = threading.Thread(
target=service._observe_published_runtime_envelope, # noqa: SLF001
kwargs={"envelope": frame, "producer_generation": runtime.producer_generation},
daemon=True,
)
publish_thread.start()
assert rebind_entered.wait(timeout=2.0)
stop_id = "op-00000000-0000-4000-8000-000000001403"
request = _stop_request(
acquisition_id=owner.lineage.acquisition_id,
operation_id=stop_id,
idempotency_key="classified-scanning-fsync-expired-stop",
mode="graceful",
deadline_seconds=1.0,
physical_acceptance=PHYSICAL_ACCEPTANCE,
expected_control_session_generation=fixture.control.session_generation,
expected_control_state_revision=fixture.control.state_revision,
)
stop_errors: list[BaseException] = []
def request_stop() -> None:
try:
service.stop_acquisition(request)
except BaseException as exc: # pragma: no cover - asserted below
stop_errors.append(exc)
stop_thread = threading.Thread(target=request_stop, daemon=True)
stop_thread.start()
try:
priority_deadline = time.monotonic() + 0.5
while time.monotonic() < priority_deadline:
operation = next(
(
item
for item in service._operations.snapshot() # noqa: SLF001
if item["operation_id"] == stop_id
),
None,
)
with service._lock: # noqa: SLF001
priority = service._camera_stop_priority_counts.get( # noqa: SLF001
owner.lineage.acquisition_id,
0,
)
if operation is not None and priority == 1:
break
time.sleep(0.005)
assert operation is not None
assert operation["status"] == "accepted"
assert priority == 1
assert fixture.prepare_calls == [fixture.stop_operation_id]
assert stop_thread.is_alive()
deadline = time.monotonic() + 2.0
while time.monotonic() < deadline and not service._operations.deadline_reached( # noqa: SLF001
stop_id
):
time.sleep(0.01)
assert service._operations.deadline_reached(stop_id) is True # noqa: SLF001
finally:
release_rebind.set()
publish_thread.join(timeout=3.0)
stop_thread.join(timeout=3.0)
assert publish_thread.is_alive() is False
assert stop_thread.is_alive() is False
assert len(stop_errors) == 1
assert getattr(stop_errors[0], "reason_code", None) == (
"physical-command-dispatch-deadline-expired"
)
operation = service._operations.get(stop_id) # noqa: SLF001
assert operation.status == "failed"
assert operation.stage_code == (
"physical-stop-dispatch-deadline-expired-before-prepare"
)
assert operation.error is not None
assert operation.error["code"] == "physical-command-dispatch-deadline-expired"
assert operation.error["side_effect_status"] == "none"
assert operation.error["physical_command_sent"] is False
assert operation.error["automatic_replay_allowed"] is False
assert fixture.prepare_calls == [fixture.stop_operation_id]
record = fixture.ledger.snapshot().record
assert record is not None
assert record.operation_id == fixture.stop_operation_id
assert record.action == "stop"
assert record.stage == "resolved"
assert fixture.control.stop_calls == 1
def test_stop_deadline_after_durable_prepare_retains_exact_no_dispatch_owner(
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(service, runtime)
original_request_stop = fixture.control.request_stop
def expire_after_durable_prepare(**kwargs: object) -> dict[str, object]:
command_context = kwargs["command_context"]
fixture.coordinator.prepare(
command_context,
action="stop",
envelope=fixture.envelope,
)
fixture.prepare_calls.append(str(command_context.operation_id))
fixture.coordinator.resolve_prepared_not_dispatched("stop")
raise ApplicationMqttTransportError(
"synthetic deadline after STOP PREPARE fsync",
reason_code="physical-command-dispatch-deadline-expired",
)
fixture.control.request_stop = expire_after_durable_prepare
try:
with pytest.raises(
ApplicationMqttTransportError,
match="synthetic deadline after STOP PREPARE fsync",
):
service.stop_acquisition(fixture.request)
finally:
fixture.control.request_stop = original_request_stop
record = fixture.ledger.snapshot().record
assert record is not None
assert record.operation_id == fixture.stop_operation_id
assert record.action == "stop"
assert record.stage == "resolved"
assert record.resolution == "not-dispatched"
assert record.publish_call_returned is None
assert record.packet_id is None
assert record.qos2_completed is False
operation = service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert operation.status == "failed"
assert operation.stage_code == "physical-stop-classified-not-dispatched"
assert operation.error is not None
assert operation.error["side_effect_status"] == "none"
assert operation.error["physical_command_sent"] is False
assert operation.error["automatic_replay_allowed"] is False
assert fixture.prepare_calls == [fixture.stop_operation_id]
with service._lock: # noqa: SLF001
acquisition = service._acquisition # noqa: SLF001
owner = service._prepared_stop_recovery_owner # noqa: SLF001
assert service._acquisition_stop_operation_id == fixture.stop_operation_id # noqa: SLF001
assert acquisition is not None
assert acquisition.state == "awaiting_external_stop"
assert owner is not None
assert owner.acquisition is acquisition
assert owner.lineage.stop_operation_id == fixture.stop_operation_id
assert service.camera_preview.snapshot()["recording"]["source_end_expected"] is False
# Exact retries observe the terminal journal identity and never prepare or
# publish another physical STOP, even after the original control socket is
# no longer admissible for a new command.
fixture.control.state = "failed"
fixture.control.state_revision += 1
fixture.control.failure = {
"reason_code": "mqtt_network_loop_failed",
"modeling_command_attempted": False,
"safe_to_retry": False,
}
fixture.control.verified_control = None
retried = service.stop_acquisition(fixture.request)
assert retried["contract_version"] == "missioncore.device-plugin-state/v1alpha2"
assert retried["selected_device_id"] == fixture.binding.transport_ref
assert retried["acquisition"]["acquisition_id"] == fixture.request.acquisition_id
assert retried["acquisition"]["state"] in {
"awaiting_external_stop",
"interrupted",
}
assert retried["last_operation"]["operation_id"] == fixture.stop_operation_id
assert retried["last_operation"]["status"] == "failed"
assert fixture.prepare_calls == [fixture.stop_operation_id]
with pytest.raises(ValueError, match="different request"):
service.stop_acquisition(
fixture.request.model_copy(
update={
"idempotency_key": fixture.request.idempotency_key,
"expected_control_state_revision": (
fixture.request.expected_control_state_revision + 1
),
}
)
)
assert fixture.prepare_calls == [fixture.stop_operation_id]
def test_corrupt_physical_snapshot_never_terminalizes_preadmitted_stop_as_none(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(service, runtime)
original_snapshot = fixture.ledger.snapshot
original_owned = service._stop_acquisition_owned # noqa: SLF001
entered_owned = threading.Event()
def reject_before_prepare(
request: StopAcquisitionRequest,
preadmitted_stop: object | None = None,
) -> dict[str, Any]:
assert preadmitted_stop is not None
entered_owned.set()
raise facade_module.LocalAcquisitionLifecycleError(
"synthetic admission rejection before physical PREPARE",
reason_code="synthetic-before-prepare",
)
monkeypatch.setattr(service, "_stop_acquisition_owned", reject_before_prepare)
monkeypatch.setattr(
fixture.ledger,
"snapshot",
lambda: PhysicalCommandLedgerSnapshot(
status="corrupt",
record=None,
reason_code="physical-command-ledger-corrupt",
),
)
fresh_request = fixture.request.model_copy(
update={
"operation_id": "op-00000000-0000-4000-8000-000000001404",
"idempotency_key": "corrupt-ledger-preadmitted-stop",
}
)
try:
with pytest.raises(
facade_module.LocalAcquisitionLifecycleError,
match="synthetic admission rejection",
):
service.stop_acquisition(fresh_request)
finally:
monkeypatch.setattr(fixture.ledger, "snapshot", original_snapshot)
monkeypatch.setattr(service, "_stop_acquisition_owned", original_owned)
assert entered_owned.is_set()
operation = service._operations.get(fresh_request.operation_id) # noqa: SLF001
assert operation.status == "accepted"
assert operation.error is None
assert fixture.prepare_calls == []
assert original_snapshot().record is not None
assert original_snapshot().record.operation_id == fixture.start_operation_id # type: ignore[union-attr]
def test_classified_ready_finishes_same_receiver_and_pins_fresh_start_binding(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(service, runtime)
service.stop_acquisition(fixture.request)
owner = _settle_real_prepared_stop_before_publish(fixture)
_classify_real_prepared_stop(
fixture,
owner,
session_state="ready",
reconciliation_id="test-ready-in-place",
)
monkeypatch.setattr(service, "_seal_acquisition_capture_clock", lambda: None)
finished = service.state()
stop_operation = service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert finished["acquisition"]["state"] == "interrupted"
assert finished["acquisition"]["result"]["read_only_recovery"] is True
assert finished["acquisition"]["result"]["device_stop"] == "not-sent"
assert finished["acquisition"]["cleanup_pending"] is False
assert stop_operation.stage_code == "physical-stop-classified-not-dispatched"
assert stop_operation.error is not None
assert stop_operation.error["side_effect_status"] == "none"
assert service._acquisition_session_lease is None # noqa: SLF001
assert service._prepared_stop_recovery_owner is None # noqa: SLF001
assert runtime.stop_calls == 1
physical = fixture.coordinator.snapshot()
assert facade_module._physical_command_prepared_stop_ready_successor_pending( # noqa: SLF001
physical
)
with pytest.raises(
facade_module.NetworkProvisioningConflict,
) as mutation:
service._require_physical_command_network_mutation_allowed() # noqa: SLF001
assert mutation.value.reason_code == "physical-command-reconciliation-required"
policy = facade_module._connection_policy_projection( # noqa: SLF001
supervisor=service._connection_supervisor.snapshot(), # noqa: SLF001
ledger=service._network_mutation_ledger.snapshot(), # noqa: SLF001
fresh_devices=[],
provisioning_active=False,
acquisition_active=False,
acquisition_cleanup_pending=False,
acquisition_state="interrupted",
runtime_active=False,
application_control_session=fixture.control.snapshot(),
physical_command=physical,
ble_runtime={
"poisoned": False,
"cleanup_pending": False,
"active_operation_kind": None,
},
lifecycle_process_lease_holders=(),
network_provisioning_idempotency={},
network_provisioning_idempotency_available=True,
semantic_topology_store={"status": "available"},
device_identity_pin_store={"status": "available"},
current_device_recovery=None,
desired_connection_mode=service._desired_connection_mode, # noqa: SLF001
active_connection_mode=service._connection_mode, # noqa: SLF001
)
assert "physical-command-reconciliation-required" not in policy["actions"][
"start-acquisition"
]["reason_codes"]
# The classified READY binding remains pinned during an ordinary
# continuation, but an explicit clean-scenario reset must abandon that
# future START ownership. After the separately requested fresh Scan, the
# exact UUID is an ordinary one-click provisioning target again.
reset = service.select_connection_mode(
DesiredConnectionModeRequest(
connection_mode="bridge",
expected_revision=finished["desired_connection_mode_revision"],
reset_scenario=True,
reset_id="classified-ready-clean-network-reset-0001",
)
)
assert reset["connection_scenario_reset"]["physical_disposition"] == (
"operator-retired-outcome-unknown"
)
reset_record = fixture.ledger.snapshot().record
assert reset_record is not None
assert reset_record.resolution == "operator-retired-outcome-unknown"
assert reset_record.original_command_outcome == "not-dispatched"
assert fixture.prepare_calls == [fixture.stop_operation_id]
with service._lock: # noqa: SLF001
service._ble_discovery_generation += 1 # noqa: SLF001
generation = service._ble_discovery_generation # noqa: SLF001
service._scenario_reset_successful_scan_generation = generation # noqa: SLF001
assert service._connection_scenario_reset is not None # noqa: SLF001
service._scenario_reset_successful_scan_reset_id = ( # noqa: SLF001
service._connection_scenario_reset["reset_id"]
)
service._connection_scenario_reset["active"] = False # noqa: SLF001
service._connection_scenario_reset[ # noqa: SLF001
"settled_by_discovery_generation"
] = generation
_set_scanned_k1(service, device_id=fixture.binding.transport_ref)
scanned = service.state()
assert scanned["connection_policy"]["facts"][
"eligible_fresh_transport_refs"
] == [fixture.binding.transport_ref]
assert scanned["connection_policy"]["actions"]["provision-fresh-device"][
"allowed"
] is True
assert scanned["connection_policy"]["actions"]["start-acquisition"][
"allowed"
] is False
writes = _install_successful_fast_ack_bridge_write(monkeypatch)
monkeypatch.setattr(
service,
"_schedule_control_bootstrap_continuation",
lambda **_kwargs: None,
)
applied = asyncio.run(
service.connect(
_connect_request(
device_id=fixture.binding.transport_ref,
ssid="classified-ready-clean-network",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
operation_id="op-00000000-0000-4000-8000-000000001405",
expected_mode_revision=scanned[
"desired_connection_mode_revision"
],
expected_discovery_generation=generation,
expected_reconfiguration_revision=scanned[
"connection_reconfiguration"
]["revision"],
)
)
)
assert writes == ["network-write"]
assert applied["connection_attempt"]["phase"] == "network_applied"
reopened = fixture.ledger.snapshot().record
assert reopened is not None
assert reopened.original_command_outcome == "not-dispatched"
assert reopened.reopened_physical_state_requires_reconciliation is True
assert len(reopened.operator_reconciliation_reopens) == 1
assert reopened.operator_reconciliation_reopens[-1].reason == (
"reset-network-intent-read-only-settlement"
)
assert fixture.prepare_calls == [fixture.stop_operation_id]
def test_classified_ready_before_first_pcl_interrupts_pending_start_without_new_edge(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(
service,
runtime,
confirm_first_pcl=False,
)
start_before = service._operations.get(fixture.start_operation_id) # noqa: SLF001
assert start_before.status == "running"
assert service._acquisition_start_operation_id == fixture.start_operation_id # noqa: SLF001
service.stop_acquisition(fixture.request)
owner = _settle_real_prepared_stop_before_publish(fixture)
_classify_real_prepared_stop(
fixture,
owner,
session_state="ready",
reconciliation_id="test-ready-before-first-pcl",
)
monkeypatch.setattr(service, "_seal_acquisition_capture_clock", lambda: None)
finished = service.state()
start = service._operations.get(fixture.start_operation_id) # noqa: SLF001
stop = service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert finished["acquisition"]["state"] == "interrupted"
assert finished["acquisition"]["result"]["device_stop"] == "not-sent"
assert start.status == "interrupted"
assert start.stage_code == "physical-start-active-but-no-point-before-standby"
assert start.error is not None
assert start.error["side_effect_status"] == "succeeded"
assert start.error["automatic_replay_allowed"] is False
assert service._acquisition_start_operation_id is None # noqa: SLF001
assert stop.stage_code == "physical-stop-classified-not-dispatched"
assert stop.error is not None
assert stop.error["side_effect_status"] == "none"
assert fixture.prepare_calls == [fixture.stop_operation_id]
assert fixture.control.stop_calls == 1
assert runtime.stop_calls == 1
@pytest.mark.parametrize("action", ["abort", "force", "reset", "close"])
def test_resolved_ready_dominates_later_local_action_without_rewriting_s0_or_pending_start(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
action: str,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(
service,
runtime,
confirm_first_pcl=False,
)
service.stop_acquisition(fixture.request)
owner = _settle_real_prepared_stop_before_publish(fixture)
_classify_real_prepared_stop(
fixture,
owner,
session_state="ready",
reconciliation_id=f"test-ready-dominates-{action}",
)
monkeypatch.setattr(service, "_seal_acquisition_capture_clock", lambda: None)
completed = service.state()
acquisition = service._acquisition # noqa: SLF001
assert acquisition is not None
assert completed["acquisition"]["state"] == "interrupted"
assert completed["acquisition"]["result"]["device_stop"] == "not-sent"
before_record = fixture.ledger.snapshot().record
before_acquisition = (
acquisition.state,
acquisition.state_revision,
acquisition.message_code,
dict(acquisition.result or {}),
)
before_operations = {
item["operation_id"]: item
for item in service._operations.snapshot() # noqa: SLF001
if item["operation_id"]
in {fixture.start_operation_id, fixture.stop_operation_id}
}
before_prepare_calls = list(fixture.prepare_calls)
before_control_stop_calls = fixture.control.stop_calls
if action == "abort":
result = service.abort_acquisition(
_abort_request(acquisition_id=acquisition.acquisition_id)
)
assert result["acquisition"]["state"] == "interrupted"
elif action == "force":
result = service.force_finish_acquisition_locally(
_force_finish_request(
acquisition_id=acquisition.acquisition_id,
expected_state_revision=acquisition.state_revision,
expected_recovery_generation=(
service._active_stream_recovery_generation # noqa: SLF001
),
)
)
assert result["acquisition"]["state"] == "interrupted"
elif action == "reset":
result = service.select_connection_mode(
DesiredConnectionModeRequest(
connection_mode="quick-connect",
expected_revision=service._desired_connection_mode_revision, # noqa: SLF001
reset_scenario=True,
reset_id="resolved-ready-reset-0001",
)
)
assert result["acquisition"]["state"] == "interrupted"
else:
service.close()
after_operations = {
item["operation_id"]: item
for item in service._operations.snapshot() # noqa: SLF001
if item["operation_id"]
in {fixture.start_operation_id, fixture.stop_operation_id}
}
after_record = fixture.ledger.snapshot().record
if action == "reset":
assert before_record is not None
assert after_record is not None
assert after_record.revision == before_record.revision + 1
assert after_record.resolution == "operator-retired-outcome-unknown"
assert after_record.original_command_outcome == "not-dispatched"
assert after_record.reconciliations == before_record.reconciliations
assert after_record.operator_retirements[-1].reason == (
"connection-scenario-reset-by-operator"
)
assert after_record.operator_retirements[-1].original_attempt.operation_id == (
before_record.operation_id
)
assert after_record.operator_retirements[-1].original_attempt.revision == (
before_record.revision
)
else:
assert after_record == before_record
assert (
acquisition.state,
acquisition.state_revision,
acquisition.message_code,
dict(acquisition.result or {}),
) == before_acquisition
assert after_operations == before_operations
assert before_operations[fixture.start_operation_id]["status"] == "interrupted"
assert before_operations[fixture.start_operation_id]["stage_code"] == (
"physical-start-active-but-no-point-before-standby"
)
assert before_operations[fixture.stop_operation_id]["stage_code"] == (
"physical-stop-classified-not-dispatched"
)
assert before_operations[fixture.stop_operation_id]["error"]["side_effect_status"] == "none"
assert fixture.prepare_calls == before_prepare_calls
assert fixture.control.stop_calls == before_control_stop_calls
@pytest.mark.parametrize("camera_outcome", ["healthy", "dead", "clean-ended"])
def test_classified_scanning_cancels_stop_eof_and_preserves_or_rearms_camera_epoch(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
camera_outcome: str,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(service, runtime)
service.stop_acquisition(fixture.request)
owner = _settle_real_prepared_stop_before_publish(fixture)
reconciled = _classify_real_prepared_stop(
fixture,
owner,
session_state="scanning",
reconciliation_id=f"test-scanning-camera-{camera_outcome}",
)
verified_binding = reconciled["reconciliations"][-1]["verified_binding"]["connection"]
fixture.control.state = "scanning"
fixture.control.state_revision += 1
fixture.control.failure = None
fixture.control.verified_control = {
**dict(verified_binding),
"logical_device_id": "known-k1",
"compatibility_profile_id": XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
}
service._device_session_id = f"fresh-camera-{camera_outcome}-session" # noqa: SLF001
# `_classify_real_prepared_stop` installs the fresh durable/control proof
# directly. Production Verify also publishes that same rotated route and
# DeviceInfo generation to the connection supervisor; mirror that portion
# here so the real camera activation admission remains exercised.
fresh_path = HostPathProbeResult(
available=True,
fingerprint=f"test-route:classified-camera:{camera_outcome}",
interface="test0",
source_ipv4="192.168.1.2",
route_class="direct",
kernel_route_fingerprint=(f"test-route:classified-camera:{camera_outcome}"),
)
fresh_host_epoch = service._connection_supervisor.observe_host_path( # noqa: SLF001
fresh_path
)
assert fresh_host_epoch == verified_binding["host_path_epoch"]
fresh_target = EndpointTarget(
str(verified_binding["target_ipv4"]),
int(verified_binding["target_port"]),
)
assert service._connection_supervisor.observe_endpoint( # noqa: SLF001
target=fresh_target,
intent_id=str(verified_binding["intent_id"]),
host_path_epoch=fresh_host_epoch,
reachable=True,
)
assert service._connection_supervisor.observe_control_evidence( # noqa: SLF001
VerifiedControlEvidence(
intent_id=str(verified_binding["intent_id"]),
transport_ref=str(verified_binding["transport_ref"]),
host_path_epoch=fresh_host_epoch,
target=fresh_target,
connection_mode=verified_binding["connection_mode"], # type: ignore[arg-type]
logical_device_id="known-k1",
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
control_session_id=str(verified_binding["control_session_id"]),
)
)
owner.out_dir.mkdir(parents=True, exist_ok=True)
initial_epoch = 5 if camera_outcome == "healthy" else None
camera_state: dict[str, object] = {
"phase": (
"streaming"
if camera_outcome == "healthy"
else "error"
if camera_outcome == "dead"
else "idle"
),
"generation": None if camera_outcome == "clean-ended" else 5,
"active_source_id": (
None
if camera_outcome == "clean-ended"
else facade_module.DEFAULT_ACQUISITION_CAMERA_SOURCE
),
# These are the real gateway shapes after producer detachment. The
# acquisition recording root stays active while both ended variants
# expose no active producer epoch. The dead case is the bounded
# pre-first-media decode failure which production admits for a fresh
# epoch; a generic source EOF must first finish its archive seal.
"recording": {
"active": True,
"session": owner.out_dir.name,
"active_epoch": initial_epoch,
"producer_alive": camera_outcome == "healthy",
"source_end_expected": False,
"committed_media_segment_count": 0,
},
"error": (
{"code": "invalid-fmp4", "message": "synthetic dead producer"}
if camera_outcome == "dead"
else None
),
}
cancel_calls: list[str] = []
select_calls: list[tuple[str, str]] = []
start_recording_calls: list[Path] = []
retry_calls: list[tuple[str, str, int, str]] = []
def snapshot_camera() -> dict[str, object]:
return {
**camera_state,
"recording": dict(camera_state["recording"]), # type: ignore[arg-type]
}
def cancel_expected_source_end() -> dict[str, object]:
cancel_calls.append("cancel")
return snapshot_camera()
def select_camera(source_id: str, target: str) -> dict[str, object]:
select_calls.append((source_id, target))
assert camera_outcome == "clean-ended"
recording = camera_state["recording"]
assert isinstance(recording, dict)
camera_state.update(
{
"phase": "connecting",
"generation": 6,
"active_source_id": source_id,
"error": None,
}
)
# A real select auto-spawns because the clean-ended gateway retained
# this acquisition's recording root.
recording.update({"active_epoch": 6, "producer_alive": True})
return snapshot_camera()
def start_recording(session_dir: Path) -> dict[str, object]:
start_recording_calls.append(session_dir)
assert session_dir == owner.out_dir
return snapshot_camera()
def retry_recording(
source_id: str,
target: str,
*,
expected_generation: int,
expected_recording_session: str,
pre_retry_fence: Callable[[Callable[[], bool]], bool],
commit_fence: Callable[[Callable[[], bool]], bool] | None = None,
committed_before_start: Callable[[dict[str, object]], None] | None = None,
) -> dict[str, object]:
retry_calls.append(
(source_id, target, expected_generation, expected_recording_session)
)
assert camera_outcome == "dead"
assert expected_generation == 5
assert expected_recording_session == owner.out_dir.name
assert pre_retry_fence(lambda: True) is True
recording = camera_state["recording"]
assert isinstance(recording, dict)
recording.update({"active_epoch": 6, "producer_alive": True})
camera_state.update(
{
"phase": "streaming",
"generation": 6,
"active_source_id": source_id,
"error": None,
}
)
assert commit_fence is not None
assert committed_before_start is not None
assert commit_fence(
lambda: committed_before_start(snapshot_camera()) is None
) is True
return snapshot_camera()
def activate_recording(
source_id: str,
target: str,
session_dir: Path,
*,
commit_fence: Callable[[Callable[[], bool]], bool],
committed_before_start: Callable[[dict[str, object]], None] | None = None,
) -> dict[str, object]:
select_camera(source_id, target)
start_recording(session_dir)
assert committed_before_start is not None
assert commit_fence(
lambda: committed_before_start(snapshot_camera()) is None
) is True
return snapshot_camera()
monkeypatch.setattr(service.camera_preview, "snapshot", snapshot_camera)
monkeypatch.setattr(
service.camera_preview,
"cancel_expected_source_end",
cancel_expected_source_end,
)
monkeypatch.setattr(service.camera_preview, "select", select_camera)
monkeypatch.setattr(service.camera_preview, "start_recording", start_recording)
monkeypatch.setattr(
service.camera_preview,
"activate_recording_producer",
activate_recording,
)
monkeypatch.setattr(
service.camera_preview,
"retry_recording_producer",
retry_recording,
)
activation_lineage = (
owner.lineage.acquisition_id,
owner.out_dir.name,
owner.runtime_producer_generation,
)
with service._lock: # noqa: SLF001
service._camera_activation_lineage = activation_lineage # noqa: SLF001
service._adopt_classified_prepared_stop_scanning_in_place( # noqa: SLF001
owner=owner,
reconciliation_id=f"test-scanning-camera-{camera_outcome}",
reconciled_record=reconciled,
)
assert cancel_calls == ["cancel"]
assert snapshot_camera()["recording"]["source_end_expected"] is False # type: ignore[index]
assert select_calls == []
assert start_recording_calls == []
assert retry_calls == []
with service._lock: # noqa: SLF001
if camera_outcome == "healthy":
assert service._camera_activation_lineage == activation_lineage # noqa: SLF001
assert service._camera_activation_retry_lineage is None # noqa: SLF001
else:
assert service._camera_activation_lineage is None # noqa: SLF001
assert service._camera_activation_retry_lineage == activation_lineage # noqa: SLF001
assert snapshot_camera()["recording"]["active_epoch"] == initial_epoch # type: ignore[index]
checkpoint_store = service._active_acquisition_checkpoint # noqa: SLF001
assert checkpoint_store is not None
pending_before_pcl = service._classified_stop_rebind_pending # noqa: SLF001
assert pending_before_pcl is not None
gap_snapshot = checkpoint_store.snapshot()
assert gap_snapshot.status == "active"
assert gap_snapshot.checkpoint is not None
assert gap_snapshot.checkpoint.last_gap_started_at_utc is not None
assert gap_snapshot.checkpoint.last_gap_recovered_at_utc is None
original_lease = service._acquisition_session_lease # noqa: SLF001
original_out_dir = service._acquisition_out_dir # noqa: SLF001
frame = DecodedPointCloudView(
context=ConsumerFrameContext(
sequence=1,
captured_at_epoch_ns=1,
received_monotonic_ns=1,
processing_started_monotonic_ns=1,
encoded_size_bytes=16,
live=True,
),
frame_id="map",
positions_xyz=((0.0, 0.0, 0.0),),
)
runtime.phase = "live"
runtime.source_mode = "live"
runtime.source_ready = True
runtime.pcl_frames = 1
stale_frame = DecodedPointCloudView(
context=ConsumerFrameContext(
sequence=2,
captured_at_epoch_ns=1,
received_monotonic_ns=1,
processing_started_monotonic_ns=1,
encoded_size_bytes=16,
live=False,
),
frame_id="map",
positions_xyz=((0.0, 0.0, 0.0),),
)
empty_frame = DecodedPointCloudView(
context=ConsumerFrameContext(
sequence=1,
captured_at_epoch_ns=1,
received_monotonic_ns=1,
processing_started_monotonic_ns=1,
encoded_size_bytes=0,
live=True,
),
frame_id="map",
positions_xyz=(),
)
service._observe_published_runtime_envelope( # noqa: SLF001
stale_frame,
runtime.producer_generation,
)
service._observe_published_runtime_envelope( # noqa: SLF001
empty_frame,
runtime.producer_generation,
)
service._observe_published_runtime_envelope( # noqa: SLF001
frame,
runtime.producer_generation + 1,
)
with service._camera_restart_commit_gate, service._lock: # noqa: SLF001
service._camera_stop_priority_counts[ # noqa: SLF001
owner.lineage.acquisition_id
] = 1
try:
assert service._promote_classified_stop_rebind_from_pcl( # noqa: SLF001
envelope=frame,
producer_generation=runtime.producer_generation,
) is False
finally:
with service._camera_restart_commit_gate, service._lock: # noqa: SLF001
service._camera_stop_priority_counts.pop( # noqa: SLF001
owner.lineage.acquisition_id,
None,
)
assert service._classified_stop_rebind_pending == pending_before_pcl # noqa: SLF001
assert service._classified_stop_rebind_inflight is None # noqa: SLF001
assert checkpoint_store.snapshot().checkpoint == gap_snapshot.checkpoint
assert select_calls == []
assert start_recording_calls == []
assert retry_calls == []
rebind_calls: list[str] = []
original_rebind_active = checkpoint_store.rebind_active
def observe_rebind_active(**kwargs: Any) -> Any:
rebind_calls.append(str(kwargs["transition_id"]))
committed = original_rebind_active(**kwargs)
if camera_outcome == "dead":
raise OSError("synthetic lost response after durable rebind")
return committed
monkeypatch.setattr(
checkpoint_store,
"rebind_active",
observe_rebind_active,
)
service._observe_published_runtime_envelope( # noqa: SLF001
frame,
runtime.producer_generation,
)
committed_snapshot = checkpoint_store.snapshot()
assert committed_snapshot.status == "active"
assert committed_snapshot.checkpoint is not None
assert committed_snapshot.checkpoint.revision == (
gap_snapshot.checkpoint.revision + 1
)
assert committed_snapshot.checkpoint.last_gap_recovered_at_utc is not None
assert rebind_calls == [pending_before_pcl.transition_id]
assert service._classified_stop_rebind_pending is None # noqa: SLF001
assert service._classified_stop_rebind_inflight is None # noqa: SLF001
assert service._acquisition_session_lease is original_lease # noqa: SLF001
assert service._acquisition_out_dir == original_out_dir # noqa: SLF001
deadline = time.monotonic() + 2.0
while (
camera_outcome != "healthy"
and not (select_calls or retry_calls)
and time.monotonic() < deadline
):
time.sleep(0.01)
service._observe_published_runtime_envelope( # noqa: SLF001
frame,
runtime.producer_generation,
)
time.sleep(0.05)
assert checkpoint_store.snapshot().checkpoint == committed_snapshot.checkpoint
assert rebind_calls == [pending_before_pcl.transition_id]
assert len(select_calls) + len(retry_calls) <= 1
if camera_outcome == "healthy":
assert select_calls == []
assert start_recording_calls == []
assert retry_calls == []
assert snapshot_camera()["recording"]["active_epoch"] == initial_epoch # type: ignore[index]
elif camera_outcome == "clean-ended":
assert select_calls == [
(
facade_module.DEFAULT_ACQUISITION_CAMERA_SOURCE,
owner.lineage.target_ipv4,
)
]
assert start_recording_calls == [owner.out_dir]
assert retry_calls == []
assert snapshot_camera()["recording"]["active_epoch"] == 6 # type: ignore[index]
else:
assert select_calls == []
assert start_recording_calls == []
assert retry_calls == [
(
facade_module.DEFAULT_ACQUISITION_CAMERA_SOURCE,
owner.lineage.target_ipv4,
5,
owner.out_dir.name,
)
]
assert snapshot_camera()["recording"]["active_epoch"] == 6 # type: ignore[index]
def test_classified_ready_cleanup_failure_retains_owner_then_retries_locally(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(service, runtime)
service.stop_acquisition(fixture.request)
owner = _settle_real_prepared_stop_before_publish(fixture)
_classify_real_prepared_stop(
fixture,
owner,
session_state="ready",
reconciliation_id="test-ready-cleanup-retry",
)
monkeypatch.setattr(service, "_seal_acquisition_capture_clock", lambda: None)
original_stop_current = service.camera_preview.stop_current
failure_pending = True
def fail_once_stop_current() -> dict[str, object]:
nonlocal failure_pending
if failure_pending:
failure_pending = False
raise RuntimeError("synthetic camera current cleanup failure")
return original_stop_current()
monkeypatch.setattr(service.camera_preview, "stop_current", fail_once_stop_current)
with pytest.raises(RuntimeError, match="synthetic camera current cleanup failure"):
service.state()
failed = service._acquisition # noqa: SLF001
assert failed is not None
assert failed.state == "failed"
assert failed.result is not None
assert failed.result["device_stop"] == "not-sent"
assert failed.result["local_cleanup_retry_pending"] is True
assert service._acquisition_session_lease is owner.session_lease # noqa: SLF001
assert service._prepared_stop_recovery_owner is owner # noqa: SLF001
assert runtime.stop_calls == 0
retried = service.state()
assert retried["acquisition"]["state"] == "failed"
assert retried["acquisition"]["cleanup_pending"] is False
assert retried["acquisition"]["result"]["device_stop"] == "not-sent"
assert retried["acquisition"]["result"]["receiver_stopped"] is True
assert "local_cleanup_retry_pending" not in retried["acquisition"]["result"]
assert retried["acquisition"]["message_code"] == (
"acquisition.recovery.local_cleanup_completed"
)
assert failed.result is not None
assert failed.result["receiver_stopped"] is True
assert "local_cleanup_retry_pending" not in failed.result
assert service._acquisition_session_lease is None # noqa: SLF001
assert service._prepared_stop_recovery_owner is None # noqa: SLF001
assert runtime.stop_calls == 1
record = fixture.ledger.snapshot().record
assert record is not None
assert record.operation_id == fixture.stop_operation_id
assert record.resolution == "not-dispatched"
assert fixture.control.stop_calls == 1
@pytest.mark.parametrize(
("failure_stage", "expected_message_code"),
[
(
"camera-process-lease",
"acquisition.recovery.camera_fence_release_failed",
),
("runtime", "acquisition.recovery.runtime_cleanup_failed"),
("capture-clock", "acquisition.recovery.capture_clock_failed"),
(
"perception-ingress",
"acquisition.recovery.perception_ingress_cleanup_failed",
),
(
"evidence-lease",
"acquisition.recovery.evidence_lease_release_failed",
),
],
)
def test_classified_ready_staged_cleanup_failure_retains_exact_owner_for_local_retry(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
failure_stage: str,
expected_message_code: str,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(service, runtime)
service.stop_acquisition(fixture.request)
owner = _settle_real_prepared_stop_before_publish(fixture)
_classify_real_prepared_stop(
fixture,
owner,
session_state="ready",
reconciliation_id=f"test-ready-{failure_stage}",
)
activation_lineage = (
owner.lineage.acquisition_id,
owner.out_dir.name,
owner.runtime_producer_generation,
)
with service._lock: # noqa: SLF001
service._live_perception_camera_binding = ( # noqa: SLF001
owner.out_dir.name,
facade_module.DEFAULT_ACQUISITION_CAMERA_SOURCE,
1,
)
service._camera_activation_lineage = activation_lineage # noqa: SLF001
service._camera_activation_retry_lineage = activation_lineage # noqa: SLF001
failure_pending = True
process_lease = None
if failure_stage == "camera-process-lease":
assert service._ensure_camera_preview_process_lease() is True # noqa: SLF001
process_lease = service._application_control_process_lease # noqa: SLF001
assert process_lease is not None
original_release = type(process_lease).release
def fail_once_process_release(candidate: object) -> object:
nonlocal failure_pending
if candidate is process_lease and failure_pending:
failure_pending = False
raise RuntimeError("synthetic camera process lease release failure")
return original_release(candidate) # type: ignore[arg-type]
monkeypatch.setattr(type(process_lease), "release", fail_once_process_release)
elif failure_stage == "runtime":
runtime.stop_error = RuntimeError("synthetic recovery runtime stop failure")
elif failure_stage == "capture-clock":
original_seal = service._seal_acquisition_capture_clock # noqa: SLF001
def fail_once_clock() -> None:
nonlocal failure_pending
if failure_pending:
failure_pending = False
raise RuntimeError("synthetic recovery capture clock failure")
original_seal()
monkeypatch.setattr(service, "_seal_acquisition_capture_clock", fail_once_clock)
elif failure_stage == "perception-ingress":
original_end_session = service.live_perception_ingress.end_session
def fail_once_ingress(session_id: str) -> None:
nonlocal failure_pending
if failure_pending:
failure_pending = False
raise RuntimeError("synthetic recovery ingress cleanup failure")
original_end_session(session_id)
monkeypatch.setattr(
service.live_perception_ingress,
"end_session",
fail_once_ingress,
)
elif failure_stage == "evidence-lease":
original_release_evidence = service._release_acquisition_session_lease # noqa: SLF001
def fail_once_evidence_release() -> None:
nonlocal failure_pending
if failure_pending:
failure_pending = False
raise RuntimeError("synthetic recovery evidence lease release failure")
original_release_evidence()
monkeypatch.setattr(
service,
"_release_acquisition_session_lease",
fail_once_evidence_release,
)
else: # pragma: no cover - exhaustive test table
raise AssertionError(failure_stage)
with pytest.raises(RuntimeError, match="synthetic"):
service.state()
failed = service._acquisition # noqa: SLF001
assert failed is owner.acquisition
assert failed.state == "failed"
assert failed.message_code == expected_message_code
assert failed.result is not None
assert failed.result["device_stop"] == "not-sent"
assert failed.result["local_cleanup_retry_pending"] is True
assert failed.result["local_cleanup_stage"] == failure_stage
assert failed.result["local_cleanup_error_code"] == "RuntimeError"
assert service._acquisition_session_lease is owner.session_lease # noqa: SLF001
assert service._prepared_stop_recovery_owner is owner # noqa: SLF001
if failure_stage == "camera-process-lease":
assert runtime.stop_calls == 0
assert service._application_control_process_lease is process_lease # noqa: SLF001
assert service._application_control_process_lease_holders == { # noqa: SLF001
"camera"
}
runtime.stop_error = None
retried = service.state()
assert retried["acquisition"]["state"] == "failed"
assert retried["acquisition"]["cleanup_pending"] is False
assert retried["acquisition"]["result"]["device_stop"] == "not-sent"
assert retried["acquisition"]["result"]["receiver_stopped"] is True
assert "local_cleanup_retry_pending" not in retried["acquisition"]["result"]
assert "local_cleanup_stage" not in retried["acquisition"]["result"]
assert retried["acquisition"]["message_code"] == (
"acquisition.recovery.local_cleanup_completed"
)
assert service._acquisition_session_lease is None # noqa: SLF001
assert service._prepared_stop_recovery_owner is None # noqa: SLF001
assert service._application_control_process_lease_holders == set() # noqa: SLF001
assert service._application_control_process_lease is None # noqa: SLF001
assert service._live_perception_camera_binding is None # noqa: SLF001
assert service._camera_activation_lineage is None # noqa: SLF001
assert service._camera_activation_retry_lineage is None # noqa: SLF001
assert fixture.control.stop_calls == 1
record = fixture.ledger.snapshot().record
assert record is not None
assert record.operation_id == fixture.stop_operation_id
assert record.resolution == "not-dispatched"
def test_classified_ready_ambiguous_process_fence_release_requires_restart(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(service, runtime)
service.stop_acquisition(fixture.request)
owner = _settle_real_prepared_stop_before_publish(fixture)
_classify_real_prepared_stop(
fixture,
owner,
session_state="ready",
reconciliation_id="test-ready-ambiguous-process-fence",
)
assert service._ensure_camera_preview_process_lease() is True # noqa: SLF001
process_lease = service._application_control_process_lease # noqa: SLF001
assert process_lease is not None
descriptor = process_lease._descriptor # noqa: SLF001
original_flock = fcntl.flock
original_close = os.close
unlock_calls = 0
close_calls = 0
def fail_unlock(candidate: int, operation: int) -> None:
nonlocal unlock_calls
if candidate == descriptor and operation == fcntl.LOCK_UN:
unlock_calls += 1
raise OSError(5, "synthetic unlock failure")
original_flock(candidate, operation)
def fail_close(candidate: int) -> None:
nonlocal close_calls
if candidate == descriptor:
close_calls += 1
raise OSError(5, "synthetic close failure")
original_close(candidate)
monkeypatch.setattr(fcntl, "flock", fail_unlock)
monkeypatch.setattr(os, "close", fail_close)
try:
with pytest.raises(
facade_module.ApplicationControlProcessLeaseReleaseAmbiguous
):
service.state()
failed = service._acquisition # noqa: SLF001
assert failed is owner.acquisition
assert failed.state == "failed"
assert failed.result is not None
assert failed.result["local_cleanup_retry_pending"] is True
assert failed.result["local_cleanup_stage"] == "camera-process-lease"
assert service._acquisition_session_lease is owner.session_lease # noqa: SLF001
assert service._prepared_stop_recovery_owner is owner # noqa: SLF001
assert runtime.stop_calls == 0
assert (unlock_calls, close_calls) == (1, 1)
quarantined = service.state()
assert quarantined["acquisition"]["cleanup_pending"] is True
assert quarantined["acquisition"]["result"][
"local_cleanup_retry_pending"
] is True
assert quarantined["k1_lifecycle_process_lease"] == {
"held_by_current_service": False,
"holders": [],
"process_lease_quarantined": True,
"reason_code": (
"application-control-process-lease-release-ambiguous"
),
"restart_required": True,
}
assert quarantined["connection_policy"]["allowed_actions"] == []
assert quarantined["connection_policy"]["recommended_action"] == (
"restart-mission-core"
)
assert (unlock_calls, close_calls) == (1, 1)
assert runtime.stop_calls == 0
with pytest.raises(
facade_module.ApplicationControlProcessLeaseUnavailable
):
service._ensure_camera_preview_process_lease() # noqa: SLF001
finally:
monkeypatch.setattr(fcntl, "flock", original_flock)
monkeypatch.setattr(os, "close", original_close)
original_flock(descriptor, fcntl.LOCK_UN)
original_close(descriptor)
def test_repeated_classified_stop_chain_preserves_pending_start_until_first_pcl(
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(
service,
runtime,
confirm_first_pcl=False,
)
start_operation = service._operations.get(fixture.start_operation_id) # noqa: SLF001
assert start_operation.status == "running"
assert service._acquisition_start_operation_id == fixture.start_operation_id # noqa: SLF001
service.stop_acquisition(fixture.request)
owner0 = _settle_real_prepared_stop_before_publish(fixture)
reconciled0 = _classify_real_prepared_stop(
fixture,
owner0,
session_state="scanning",
reconciliation_id="test-chain-s0",
)
binding0 = reconciled0["reconciliations"][-1]["verified_binding"]["connection"]
fixture.control.state = "scanning"
fixture.control.state_revision += 1
fixture.control.failure = None
fixture.control.verified_control = {
**dict(binding0),
"logical_device_id": "known-k1",
"compatibility_profile_id": XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
}
service._device_session_id = "fresh-chain-s0-session" # noqa: SLF001
service._adopt_classified_prepared_stop_scanning_in_place( # noqa: SLF001
owner=owner0,
reconciliation_id="test-chain-s0",
reconciled_record=reconciled0,
)
assert service._acquisition.state == "awaiting_external_start" # noqa: SLF001
assert service._acquisition_start_operation_id == fixture.start_operation_id # noqa: SLF001
stop1_id = "op-00000000-0000-4000-8000-000000001403"
service.stop_acquisition(
_stop_request(
acquisition_id=owner0.lineage.acquisition_id,
operation_id=stop1_id,
idempotency_key="classified-chain-s1",
mode="graceful",
physical_acceptance=PHYSICAL_ACCEPTANCE,
expected_control_session_generation=fixture.control.session_generation,
expected_control_state_revision=fixture.control.state_revision,
)
)
fixture.control.state = "failed"
fixture.control.state_revision += 1
fixture.control.failure = {
"reason_code": "application-connection-binding-lost",
"modeling_command_attempted": False,
"safe_to_retry": False,
}
service.state()
owner1 = service._prepared_stop_recovery_owner # noqa: SLF001
assert isinstance(owner1, facade_module._PreparedStopRecoveryOwner)
assert owner1.lineage.stop_operation_id == stop1_id
assert owner1.lineage.parent_physical_operation_id == fixture.stop_operation_id
assert owner1.start_operation_id == fixture.start_operation_id
reconciled1 = _classify_real_prepared_stop(
fixture,
owner1,
session_state="scanning",
reconciliation_id="test-chain-s1",
)
binding1 = reconciled1["reconciliations"][-1]["verified_binding"]["connection"]
fixture.control.state = "scanning"
fixture.control.state_revision += 1
fixture.control.failure = None
fixture.control.verified_control = {
**dict(binding1),
"logical_device_id": "known-k1",
"compatibility_profile_id": XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
}
with service._lock: # noqa: SLF001
service._selected_device_id = fixture.binding.transport_ref # noqa: SLF001
service._connection_mode = fixture.binding.connection_mode # noqa: SLF001
service._k1_ip = fixture.binding.target_ipv4 # noqa: SLF001
service._device_session_id = "fresh-chain-s1-session" # noqa: SLF001
service._adopt_classified_prepared_stop_scanning_in_place( # noqa: SLF001
owner=owner1,
reconciliation_id="test-chain-s1",
reconciled_record=reconciled1,
)
assert service._matching_start_active_confirmed( # noqa: SLF001
fixture.coordinator.snapshot(),
acquisition_id=owner1.lineage.acquisition_id,
start_operation_id=fixture.start_operation_id,
verified_control=fixture.control.verified_control,
)
repeated_s0 = service.stop_acquisition(fixture.request)
current_after_old_retry = fixture.ledger.snapshot().record
assert current_after_old_retry is not None
assert current_after_old_retry.operation_id == stop1_id
assert current_after_old_retry.stage == "resolved"
assert repeated_s0["acquisition"]["state"] == "awaiting_external_start"
assert fixture.prepare_calls == [fixture.stop_operation_id, stop1_id]
runtime.phase = "live"
runtime.source_ready = True
runtime.recovery_state = "recovered"
runtime.pcl_frames = 1
first_pcl = service.state()
start_operation = service._operations.get(fixture.start_operation_id) # noqa: SLF001
assert first_pcl["acquisition"]["state"] == "acquiring"
assert start_operation.status == "succeeded"
assert start_operation.stage_code == "canonical-start-and-first-point-frame"
assert service._acquisition_start_operation_id is None # noqa: SLF001
with service._lock: # noqa: SLF001
service._active_stream_recovery_lineage = None # noqa: SLF001
service._active_stream_recovery_state = "inactive" # noqa: SLF001
runtime.phase = "reconnecting"
runtime.source_ready = False
runtime.recovery_state = "reconnecting"
second_disconnect = service._admit_active_stream_recovery_lineage( # noqa: SLF001
runtime=runtime.snapshot(),
)
assert second_disconnect is not None
assert second_disconnect.physical_operation_id == stop1_id
assert second_disconnect.start_operation_id == fixture.start_operation_id
runtime.phase = "live"
runtime.source_ready = True
runtime.recovery_state = "recovered"
current_physical = fixture.coordinator.snapshot()
current_record = current_physical["record"]
assert isinstance(current_record, dict)
assert service._physical_active_parent_proof( # noqa: SLF001
current_physical,
acquisition_id=owner1.lineage.acquisition_id,
parent_operation_id=str(current_record["operation_id"]),
verified_control=fixture.control.verified_control,
) is not None
stop2_id = "op-00000000-0000-4000-8000-000000001404"
captured_stop2 = service._capture_prepared_stop_dispatch_lineage( # noqa: SLF001
operation_id=stop2_id,
acquisition=owner1.acquisition,
)
assert captured_stop2 is not None
service.stop_acquisition(
_stop_request(
acquisition_id=owner1.lineage.acquisition_id,
operation_id=stop2_id,
idempotency_key="classified-chain-s2",
mode="graceful",
physical_acceptance=PHYSICAL_ACCEPTANCE,
expected_control_session_generation=fixture.control.session_generation,
expected_control_state_revision=fixture.control.state_revision,
)
)
current = fixture.ledger.snapshot().record
assert current is not None
assert current.operation_id == stop2_id
assert current.parent_operation_id == stop1_id
assert current.stage == "prepared"
def test_prepared_stop_gate_defer_preserves_terminal_truth_until_settlement_and_teardown(
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(service, runtime)
service.stop_acquisition(fixture.request)
fixture.control.state = "failed"
fixture.control.state_revision += 1
fixture.control.failure = {
"reason_code": "mqtt_network_loop_failed",
"modeling_command_attempted": False,
"safe_to_retry": False,
}
# Simulate the transport owning its global dispatch fence. Both truthful
# settlement and topology retirement defer; generic reducers must not
# convert the still-PREPARED STOP to UNKNOWN in the meantime.
assert service._k1_command_dispatch_gate.acquire(blocking=False) # noqa: SLF001
try:
deferred = service.state()
finally:
service._k1_command_dispatch_gate.release() # noqa: SLF001
operation = service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert operation.status == "running"
assert operation.error is None
assert deferred["selected_device_id"] == fixture.binding.transport_ref
assert deferred["application_control_session"]["state"] == "failed"
# On the next poll, settlement happens before proven-loss retirement could
# reset the failed control owner to idle. Exact NONE instead promotes the
# retained receiver into read-only classification recovery, so teardown is
# intentionally deferred rather than discarding the live evidence owner.
settled = service.state()
operation = service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert operation.status == "failed"
assert operation.stage_code == "physical-stop-classified-not-dispatched"
assert operation.error is not None
assert operation.error["side_effect_status"] == "none"
assert operation.error["physical_command_sent"] is False
assert settled["selected_device_id"] == fixture.binding.transport_ref
assert service._prepared_stop_recovery_owner is not None # noqa: SLF001
assert settled["application_control_session"]["state"] == "failed"
def test_stop_without_exact_parent_proof_fails_before_durable_prepare(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(service, runtime)
parent = fixture.ledger.snapshot().record
assert parent is not None
original_snapshot = fixture.coordinator.snapshot
def snapshot_without_parent_identity() -> dict[str, object]:
snapshot = original_snapshot()
record = snapshot.get("record")
assert isinstance(record, dict)
snapshot["record"] = {**record, "identity": None}
return snapshot
monkeypatch.setattr(fixture.coordinator, "snapshot", snapshot_without_parent_identity)
with pytest.raises(
facade_module.LocalAcquisitionLifecycleError,
match="physical lineage",
) as raised:
service.stop_acquisition(fixture.request)
assert raised.value.reason_code == "physical-stop-parent-proof-unavailable"
assert fixture.prepare_calls == []
assert fixture.control.stop_calls == 0
current = fixture.ledger.snapshot().record
assert current is not None
assert current.operation_id == parent.operation_id
assert current.stage == "resolved"
operation = service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert operation.status == "failed"
assert operation.error is not None
assert operation.error["side_effect_status"] == "none"
@dataclass
class _ActualWorkerStopTransportSnapshot:
state: str
publish_attempts: int
def as_dict(self) -> dict[str, object]:
return {
"state": self.state,
"publish_attempts": self.publish_attempts,
"qos2_completions": 0,
"correlated_responses": 1,
"ignored_known_responses": 0,
"late_known_responses": 0,
"latest_device_session_state": "scanning",
"latest_device_project_bound": True,
"latest_device_init_ready": True,
"automatic_retry": False,
"automatic_reconnect": False,
"control_proof_revision": 1,
"control_proof_source": "correlated-application-response",
"control_proof_fresh": True,
"control_proof_age_seconds": 0.0,
}
class _ActualWorkerStopRaceTransport:
"""Fake MQTT client boundary driven by the real control-session worker."""
def __init__(self) -> None:
self.state = "new"
self.publish_attempts = 0
self.fake_client_publish_calls: list[str] = []
self.evidence_observer: object | None = None
self.dispatch_guard: Callable[[], Callable[[], None] | None] | None = None
self.before_transport_guard = threading.Event()
self.release_transport_guard = threading.Event()
self.after_mark_dispatching = threading.Event()
self.release_fake_publish = threading.Event()
def install_evidence_observer(self, observer: object) -> None:
self.evidence_observer = observer
def install_dispatch_guard(
self,
guard: Callable[[], Callable[[], None] | None],
) -> None:
self.dispatch_guard = guard
def open(self) -> _ActualWorkerStopTransportSnapshot:
self.state = "ready"
return self.snapshot()
def close(self) -> None:
self.state = "closed"
def snapshot(self) -> _ActualWorkerStopTransportSnapshot:
return _ActualWorkerStopTransportSnapshot(self.state, self.publish_attempts)
def validate_control_proof(self, _binding: LiveDeviceControlBinding) -> None:
return None
def scan_initialization_complete(self, _binding: LiveDeviceControlBinding) -> bool:
return True
def exchange_batch_once(
self,
envelopes: Any,
*,
required_response_operation_keys: Any,
) -> dict[str, bytes]:
envelope = tuple(envelopes)[0]
assert envelope.operation_key == "modeling:stop"
assert required_response_operation_keys == {"modeling:stop"}
assert self.dispatch_guard is not None
release = self.dispatch_guard()
try:
self.publish_attempts += 1
observer = self.evidence_observer
assert observer is not None
observer.publish_dispatching(
ApplicationMqttPublishEvidence(
operation_key="modeling:stop",
topic=envelope.topic,
payload_sha256=envelope.payload_sha256,
qos=envelope.qos,
retain=envelope.retain,
packet_id=None,
)
)
self.after_mark_dispatching.set()
assert self.release_fake_publish.wait(3.0)
self.fake_client_publish_calls.append(envelope.payload_sha256)
raise RuntimeError("synthetic response omitted after fake client publish")
finally:
if release is not None:
release()
class _ActualWorkerStopRaceExecutor:
def __init__(self, transport: _ActualWorkerStopRaceTransport) -> None:
self.transport = transport
self.binding = LiveDeviceControlBinding(
vendor_device_id="actual-worker-device",
device_serial="ACTUAL-WORKER-SERIAL",
software_version="3.0.2",
system_version="3.0.2",
device_model="LixelKity K1",
device_type="A4",
is_activated=True,
)
self.stage = "inspection"
def run_read_only_inspection_stage(self, _orchestrator: object) -> LiveDeviceControlBinding:
observer = self.transport.evidence_observer
assert observer is not None
observer.application_response(
ApplicationMqttResponseEvidence(
operation_key="bootstrap:1:DeviceInfoRequest",
response_topic="lixel/application/response/device_info",
payload_sha256="8" * 64,
modeling_action=None,
result_code=None,
success=None,
observed_at_utc="2026-08-12T09:00:00.000Z",
)
)
return self.binding
def wait_for_operator_checkpoint(
self,
_event: str,
observed: Callable[[], bool],
*,
reconciled_active_observed: Callable[[], bool] | None = None,
) -> None:
deadline = time.monotonic() + 3.0
while not observed():
if reconciled_active_observed is not None and reconciled_active_observed():
return None
if time.monotonic() >= deadline:
raise TimeoutError("actual worker checkpoint was not released")
threading.Event().wait(0.005)
return None
def adopt_reconciled_scanning(self, **_: object) -> None:
self.stage = "scanning"
def maintain_active_until_stop_requested(self, observed: Callable[[], bool]) -> None:
while not observed():
threading.Event().wait(0.005)
self.stage = "stop-requested"
def execute_canonical_stop(
self,
command: object,
_permit: object,
*,
dispatch_guard: Callable[[], None] | None = None,
dispatch_admission_deadline_reached: Callable[[], bool] | None = None,
) -> object:
self.transport.before_transport_guard.set()
assert self.transport.release_transport_guard.wait(3.0)
if dispatch_guard is not None:
dispatch_guard()
assert dispatch_admission_deadline_reached is not None
assert dispatch_admission_deadline_reached() is False
envelope = OneShotPublishEnvelope.from_modeling_command(command) # type: ignore[arg-type]
return self.transport.exchange_batch_once(
[envelope],
required_response_operation_keys={"modeling:stop"},
)
def maintain_post_stop_until_standby(self) -> None:
raise RuntimeError("synthetic standby omitted")
def snapshot(self) -> dict[str, object]:
return {
"dialogue_stage": self.stage,
"start_attempted": True,
"start_complete": True,
"stop_attempted": self.transport.publish_attempts > 0,
"stop_complete": False,
"automatic_retry": False,
}
def _wait_control_state(
session: InteractiveApplicationControlSession,
expected: set[str],
) -> dict[str, object]:
deadline = time.monotonic() + 3.0
while time.monotonic() < deadline:
snapshot = session.snapshot()
if str(snapshot.get("state")) in expected:
return snapshot
threading.Event().wait(0.005)
raise AssertionError(f"control did not reach {expected}: {session.snapshot()}")
def _install_actual_worker_recovered_stop_fixture(
service: XgridsK1CompatibilityService,
runtime: FakeVisualizationRuntime,
monkeypatch: pytest.MonkeyPatch,
) -> SimpleNamespace:
binding = _seed_supervised_connection(
service,
transport_ref="actual-worker-transport",
logical_device_id="actual-worker-device",
with_control=False,
)
route_available = {"value": True}
monkeypatch.setattr(
service,
"_sample_host_path",
lambda _target, **_kwargs: (
_direct_host_path(binding.target_ipv4)
if route_available["value"]
else HostPathProbeResult(
available=False,
fingerprint=None,
interface=None,
source_ipv4=None,
route_class="unavailable",
reason_code="router-link-lost",
)
),
)
identity = PhysicalCommandIdentity(
vendor_device_id_sha256=hashlib.sha256(b"actual-worker-device").hexdigest(),
device_serial_sha256=hashlib.sha256(b"ACTUAL-WORKER-SERIAL").hexdigest(),
)
old_connection = PhysicalCommandConnectionBinding(
intent_id="old-active-intent",
transport_ref=binding.transport_ref,
connection_mode=binding.connection_mode,
target_ipv4=binding.target_ipv4,
target_port=binding.target_port,
host_path_epoch=binding.host_path_epoch,
control_session_id="old-active-control",
producer_generation=1,
)
def physical_status(state: str, observed: str) -> PhysicalCommandStatusEvidence:
scanning = state == "scanning"
return PhysicalCommandStatusEvidence(
source="live-control-session",
vendor_device_id_sha256=identity.vendor_device_id_sha256,
device_serial_sha256=identity.device_serial_sha256,
control_session_id=old_connection.control_session_id,
host_path_epoch=old_connection.host_path_epoch,
producer_generation=old_connection.producer_generation,
session_state=state, # type: ignore[arg-type]
session_state_code=302 if scanning else 300,
project_bound=scanning,
project_id_sha256="a" * 64 if scanning else None,
init_ready=scanning,
status_message_sha256=hashlib.sha256(observed.encode()).hexdigest(),
mqtt_retained=False,
observed_at_utc=observed,
)
ledger = service._physical_command_ledger # noqa: SLF001
start_operation_id = "op-00000000-0000-4000-8000-000000001420"
acquisition_id = "acq-actual-worker-stop-race"
ledger.prepare(
operation_id=start_operation_id,
parent_operation_id=None,
acquisition_id=acquisition_id,
action="start",
identity=identity,
connection=old_connection,
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
payload_sha256="1" * 64,
baseline_status=physical_status("ready", "2026-08-12T09:00:01.000Z"),
)
ledger.mark_dispatching(start_operation_id)
ledger.mark_observing(start_operation_id, publish_call_returned=True, packet_id=81)
ledger.mark_qos2_completed(start_operation_id, packet_id=81)
ledger.record_application_response(
start_operation_id,
PhysicalCommandApplicationResponse(
operation_id=start_operation_id,
action="start",
control_session_id=old_connection.control_session_id,
host_path_epoch=old_connection.host_path_epoch,
producer_generation=old_connection.producer_generation,
result_code=PHYSICAL_COMMAND_APPLICATION_SUCCESS_CODE,
success=True,
payload_sha256="2" * 64,
observed_at_utc="2026-08-12T09:00:02.000Z",
),
)
ledger.record_status_observation(
start_operation_id,
physical_status("scanning", "2026-08-12T09:00:03.000Z"),
)
ledger.resolve(start_operation_id, resolution="start-active-observed")
transport = _ActualWorkerStopRaceTransport()
monkeypatch.setattr(
session_module,
"PhysicalAcceptanceDialogueExecutor",
_ActualWorkerStopRaceExecutor,
)
coordinator = service._physical_command_coordinator # noqa: SLF001
control = InteractiveApplicationControlSession(
FakeApplicationAuthorityLoader(),
transport_factory=lambda _host: transport, # type: ignore[arg-type]
connection_path_validator=service._validate_application_connection_path, # noqa: SLF001
connection_binding_validator=service._validate_application_connection_binding, # noqa: SLF001
connection_dispatch_lease=service._acquire_application_dispatch_lease, # noqa: SLF001
physical_command_coordinator=coordinator,
)
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
control.open(
host=binding.target_ipv4,
timezone_name="Europe/Moscow",
connection_binding=binding,
inspection_only=True,
)
ready = _wait_control_state(control, {"connection-ready"})
verified = ready["verified_control"]
assert isinstance(verified, dict)
coordinator.device_status(
ApplicationMqttDeviceStatusEvidence(
vendor_device_id_sha256=identity.vendor_device_id_sha256,
device_serial_sha256=identity.device_serial_sha256,
session_state="scanning",
session_state_code=MODELING_STATE_BASE + 302,
project_bound=True,
project_id_sha256="a" * 64,
init_ready=True,
status_message_sha256="3" * 64,
mqtt_retained=False,
observed_at_utc="2026-08-12T09:00:04.000Z",
)
)
reconciliation_id = "actual-worker-rebind"
reconciled = coordinator.reconcile_resolved_active(reconciliation_id=reconciliation_id)
control.adopt_reconciled_scanning(
reconciliation_id=reconciliation_id,
expected_session_generation=ready["session_generation"], # type: ignore[arg-type]
expected_state_revision=ready["state_revision"], # type: ignore[arg-type]
)
scanning = _wait_control_state(control, {"scanning"})
service._reconcile_connection_supervisor(scanning, runtime.snapshot()) # noqa: SLF001
service._materialize_recovered_physical_stop_acquisition( # noqa: SLF001
reconciliation_id=reconciliation_id,
reconciled_record=reconciled,
)
stop_operation_id = "op-00000000-0000-4000-8000-000000001421"
request = _stop_request(
acquisition_id=acquisition_id,
operation_id=stop_operation_id,
idempotency_key="actual-worker-stop-race",
mode="graceful",
physical_acceptance=PHYSICAL_ACCEPTANCE,
expected_control_session_generation=scanning["session_generation"],
expected_control_state_revision=scanning["state_revision"],
)
return SimpleNamespace(
binding=binding,
route_available=route_available,
ledger=ledger,
coordinator=coordinator,
control=control,
transport=transport,
request=request,
stop_operation_id=stop_operation_id,
)
def test_capture_only_rejects_real_worker_queued_before_prepared_dispatch(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_actual_worker_recovered_stop_fixture(
service,
runtime,
monkeypatch,
)
service.stop_acquisition(fixture.request)
assert fixture.transport.before_transport_guard.wait(3.0)
before_operations = tuple(service._operations.snapshot()) # noqa: SLF001
before_acquisition = service._acquisition # noqa: SLF001
with pytest.raises(
facade_module.LocalAcquisitionLifecycleError,
match="ещё владеет PREPARED STOP",
) as raised:
service.stop_acquisition(
_stop_request(
acquisition_id=fixture.request.acquisition_id,
operation_id="op-00000000-0000-4000-8000-000000001458",
mode="capture-only",
)
)
assert raised.value.reason_code == "acquisition-stop-worker-retirement-pending"
assert tuple(service._operations.snapshot()) == before_operations # noqa: SLF001
assert service._acquisition is before_acquisition # noqa: SLF001
assert fixture.transport.fake_client_publish_calls == []
assert fixture.transport.publish_attempts == 0
record = fixture.ledger.snapshot().record
assert record is not None and record.stage == "prepared"
operation = service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert operation.status == "running"
assert operation.error is None
assert runtime.stop_calls == 0
# Rejection performs no socket close or cancellation. The one accepted
# canonical S0 worker remains the sole owner and may cross its original
# publish edge exactly once after the test releases it.
fixture.transport.release_transport_guard.set()
assert fixture.transport.after_mark_dispatching.wait(3.0)
fixture.transport.release_fake_publish.set()
_wait_control_state(fixture.control, {"failed"})
assert len(fixture.transport.fake_client_publish_calls) == 1
assert fixture.transport.publish_attempts == 1
record = fixture.ledger.snapshot().record
assert record is not None and record.stage in {"dispatching", "observing"}
def test_actual_worker_stop_survives_both_loss_reducer_seams_and_publishes_once(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_actual_worker_recovered_stop_fixture(
service,
runtime,
monkeypatch,
)
service.stop_acquisition(fixture.request)
assert fixture.transport.before_transport_guard.wait(3.0)
supervisor = service._connection_supervisor.snapshot() # noqa: SLF001
assert supervisor.intent is not None and supervisor.device_network.target is not None
for _ in range(3):
assert service._connection_supervisor.observe_endpoint( # noqa: SLF001
target=supervisor.device_network.target,
intent_id=supervisor.intent.intent_id,
host_path_epoch=supervisor.host_path.epoch,
reachable=False,
reason_code="transient-control-port-negative",
)
retained = service.state()
assert retained["selected_device_id"] == fixture.binding.transport_ref
assert fixture.transport.fake_client_publish_calls == []
# Restore the exact control-plane proof after the synthetic transient
# endpoint negatives; the first seam tested only PREPARED lineage.
service._reconcile_connection_supervisor( # noqa: SLF001
fixture.control.snapshot(),
runtime.snapshot(),
)
refreshed = fixture.control.snapshot()
refreshed_verified = refreshed.get("verified_control")
assert isinstance(refreshed_verified, dict)
supervisor = service._connection_supervisor.snapshot() # noqa: SLF001
assert supervisor.intent is not None and supervisor.device_network.target is not None
assert service._connection_supervisor.observe_endpoint( # noqa: SLF001
target=supervisor.device_network.target,
intent_id=supervisor.intent.intent_id,
host_path_epoch=supervisor.host_path.epoch,
reachable=True,
)
assert service._connection_supervisor.observe_control_evidence( # noqa: SLF001
VerifiedControlEvidence(
intent_id=supervisor.intent.intent_id,
transport_ref=fixture.binding.transport_ref,
host_path_epoch=supervisor.host_path.epoch,
target=supervisor.device_network.target,
connection_mode=fixture.binding.connection_mode,
logical_device_id="actual-worker-device",
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
control_session_id=str(refreshed_verified["control_session_id"]),
control_proof_revision=2,
control_proof_source="correlated-application-response",
)
)
fixture.transport.release_transport_guard.set()
assert fixture.transport.after_mark_dispatching.wait(3.0)
# The real worker now owns the facade dispatch gate after mark_dispatching.
# A true route loss cannot tear topology out from under fake client.publish.
for _ in range(3):
_observe_stop_race_route_loss(service)
mid_publish = service.state()
assert mid_publish["selected_device_id"] == fixture.binding.transport_ref
assert fixture.transport.fake_client_publish_calls == []
fixture.transport.release_fake_publish.set()
failed = _wait_control_state(fixture.control, {"failed"})
assert failed["state"] == "failed"
assert len(fixture.transport.fake_client_publish_calls) == 1
assert fixture.transport.publish_attempts == 1
after_failure = service.state()
physical_record = fixture.ledger.snapshot().record
assert physical_record is not None
assert physical_record.stage in {"dispatching", "observing"}
operation = service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert operation.stage_code != "physical-stop-classified-not-dispatched"
assert operation.error is None or operation.error.get("side_effect_status") != "none"
assert after_failure["physical_command"]["record"]["stage"] in {
"dispatching",
"observing",
}
def test_actual_worker_real_route_loss_fails_before_publish_and_settles_none(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_actual_worker_recovered_stop_fixture(
service,
runtime,
monkeypatch,
)
service.stop_acquisition(fixture.request)
assert fixture.transport.before_transport_guard.wait(3.0)
fixture.route_available["value"] = False
for _ in range(3):
_observe_stop_race_route_loss(service)
retained = service.state()
assert retained["selected_device_id"] == fixture.binding.transport_ref
fixture.transport.release_transport_guard.set()
failed = _wait_control_state(fixture.control, {"failed"})
assert failed["failure"]["reason_code"] == "application-connection-binding-lost" # type: ignore[index]
assert fixture.transport.fake_client_publish_calls == []
assert fixture.transport.publish_attempts == 0
settled = service.state()
operation = service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert operation.status == "failed"
assert operation.stage_code == "physical-stop-classified-not-dispatched"
assert operation.error is not None
assert operation.error["side_effect_status"] == "none"
assert operation.error["physical_command_sent"] is False
assert settled["selected_device_id"] is None
@pytest.mark.parametrize(
("durable_start_resolved", "expected_side_effect_status"),
[(False, "unknown"), (True, "succeeded")],
)
@pytest.mark.parametrize("coincident_local_error", ["none", "camera", "runtime"])
def test_plugin_start_requires_composite_active_proof_and_fails_closed_on_control_fault(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
durable_start_resolved: bool,
expected_side_effect_status: str,
coincident_local_error: str,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control = FakeInteractiveControlSession()
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
binding = _seed_supervised_connection(service)
service._compatibility_attestation = ATTESTATION.model_dump(mode="json") # noqa: SLF001
prepared = service.prepare_acquisition(
_prepare_request(
project_name="START_GATE",
host=binding.target_ipv4,
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
pre_pcl_state = service.start_acquisition(
_start_request(
acquisition_id=acquisition_id,
physical_acceptance=PHYSICAL_ACCEPTANCE,
)
)
pre_pcl_camera_streams = [
stream
for stream in pre_pcl_state["sensor_catalog"]["streams"]
if stream.get("semantic_channel_id") == "camera.preview.live"
]
assert pre_pcl_state["camera_preview"]["active_source_id"] is None
assert pre_pcl_state["camera_preview"]["delivery"] is None
assert pre_pcl_state["camera_preview"]["activation_admission"]["state"] == (
"waiting-for-first-authoritative-pcl"
)
assert all(stream["activation"]["selected"] is False for stream in pre_pcl_camera_streams)
assert all(stream["activation"]["controllable"] is False for stream in pre_pcl_camera_streams)
start_operation_id = service._acquisition_start_operation_id # noqa: SLF001
assert isinstance(start_operation_id, str)
physical_proof = _exact_start_physical_proof(
operation_id=start_operation_id,
acquisition_id=acquisition_id,
binding=binding,
resolved=durable_start_resolved,
)
monkeypatch.setattr(
service._physical_command_coordinator, # noqa: SLF001
"snapshot",
lambda: physical_proof,
)
# The live stream can begin during SCAN_STARTING. Neither frames alone nor
# even a durable edge observed after this browser reduction is enough while
# the current canonical control owner is not SCANNING/can_stop.
control.state = "initializing"
runtime.mark_ready()
runtime.pcl_frames = 30
initializing = service.state()
assert initializing["acquisition"]["state"] == "awaiting_external_start"
assert initializing["last_operation"]["status"] == "running"
original_control_snapshot = control.snapshot
def failed_control_snapshot() -> dict[str, object]:
snapshot = original_control_snapshot()
snapshot["outcome_unknown"] = True
snapshot["failure"] = {
"code": "ApplicationControlDeviceFault",
"reason_code": "device_status_fault",
"failed_phase": "initializing",
"modeling_command_attempted": True,
"safe_to_retry": False,
}
snapshot["transport"] = {
"latest_system_error_code": 0x32040133,
"latest_system_error_state": "algorithm_error",
}
return snapshot
if coincident_local_error == "camera":
original_camera_snapshot = service.camera_preview.snapshot
def failed_camera_snapshot() -> dict[str, Any]:
return {
**original_camera_snapshot(),
"phase": "error",
"recording": {"active": True},
"error": {"code": "coincident-camera-fault"},
}
monkeypatch.setattr(service.camera_preview, "snapshot", failed_camera_snapshot)
elif coincident_local_error == "runtime":
runtime.phase = "error"
monkeypatch.setattr(control, "snapshot", failed_control_snapshot)
control.state = "failed"
failed = service.state()
start_operation = next(
operation
for operation in failed["operations"]
if operation["operation_id"] == start_operation_id
)
assert failed["acquisition"]["state"] == "failed"
assert failed["acquisition"]["cleanup_pending"] is True
assert failed["source_mode"] == "live"
assert start_operation["status"] == "failed"
assert start_operation["stage_code"] == "device-start-outcome-unknown"
assert start_operation["error"]["safe_to_retry"] is False
assert start_operation["error"]["side_effect_status"] == (expected_side_effect_status)
assert start_operation["error"]["automatic_replay_allowed"] is False
assert runtime.stop_calls == 0
assert control.stop_calls == 0
runtime.pcl_frames += 1
still_failed = service.state()
repeated_start_operation = next(
operation
for operation in still_failed["operations"]
if operation["operation_id"] == start_operation_id
)
assert still_failed["acquisition"]["state"] == "failed"
assert still_failed["acquisition"]["cleanup_pending"] is True
assert still_failed["source_mode"] == "live"
assert repeated_start_operation == start_operation
assert runtime.stop_calls == 0
assert control.stop_calls == 0
locally_stopped = service.stop_acquisition(
_stop_request(acquisition_id=acquisition_id, mode="capture-only")
)
assert locally_stopped["source_mode"] == "idle"
assert locally_stopped["acquisition"]["cleanup_pending"] is False
assert locally_stopped["last_operation"]["result"]["device_stop"] == "unknown"
assert runtime.stop_calls == 1
assert control.stop_calls == 0
@pytest.mark.parametrize(
("durable_start_resolved", "expected_side_effect_status"),
[(False, "unknown"), (True, "succeeded")],
)
@pytest.mark.parametrize("local_error", ["camera", "runtime"])
def test_plugin_start_local_failure_preserves_post_checkpoint_physical_outcome(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
durable_start_resolved: bool,
expected_side_effect_status: str,
local_error: str,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control = FakeInteractiveControlSession()
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
binding = _seed_supervised_connection(service)
service._compatibility_attestation = ATTESTATION.model_dump(mode="json") # noqa: SLF001
prepared = service.prepare_acquisition(
_prepare_request(
project_name="START_LOCAL_FAILURE",
host=binding.target_ipv4,
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
pre_pcl_state = service.start_acquisition(
_start_request(
acquisition_id=acquisition_id,
physical_acceptance=PHYSICAL_ACCEPTANCE,
)
)
pre_pcl_camera_streams = [
stream
for stream in pre_pcl_state["sensor_catalog"]["streams"]
if stream.get("semantic_channel_id") == "camera.preview.live"
]
assert pre_pcl_state["camera_preview"]["active_source_id"] is None
assert pre_pcl_state["camera_preview"]["delivery"] is None
assert pre_pcl_state["camera_preview"]["activation_admission"]["state"] == (
"waiting-for-first-authoritative-pcl"
)
assert all(stream["activation"]["selected"] is False for stream in pre_pcl_camera_streams)
assert all(stream["activation"]["controllable"] is False for stream in pre_pcl_camera_streams)
start_operation_id = service._acquisition_start_operation_id # noqa: SLF001
assert isinstance(start_operation_id, str)
physical_proof = _exact_start_physical_proof(
operation_id=start_operation_id,
acquisition_id=acquisition_id,
binding=binding,
resolved=durable_start_resolved,
)
monkeypatch.setattr(
service._physical_command_coordinator, # noqa: SLF001
"snapshot",
lambda: physical_proof,
)
runtime.mark_ready()
awaiting = service.state()
assert awaiting["acquisition"]["state"] == "awaiting_external_start"
assert awaiting["last_operation"]["status"] == "running"
if local_error == "camera":
original_camera_snapshot = service.camera_preview.snapshot
def failed_camera_snapshot() -> dict[str, Any]:
return {
**original_camera_snapshot(),
"phase": "error",
"recording": {"active": True},
"error": {"code": "camera-failed-before-local-start-acceptance"},
}
monkeypatch.setattr(service.camera_preview, "snapshot", failed_camera_snapshot)
else:
runtime.phase = "error"
failed = service.state()
start_operation = next(
operation
for operation in failed["operations"]
if operation["operation_id"] == start_operation_id
)
assert failed["acquisition"]["state"] == "failed"
assert failed["acquisition"]["cleanup_pending"] is False
assert failed["source_mode"] == "idle"
assert start_operation["status"] == "failed"
assert start_operation["stage_code"] == "runtime-failed"
assert start_operation["error"]["safe_to_retry"] is False
assert start_operation["error"]["side_effect_status"] == (expected_side_effect_status)
assert start_operation["error"]["automatic_replay_allowed"] is False
assert runtime.stop_calls == 1
assert control.stop_calls == 0
@pytest.mark.parametrize("local_failure", ["none", "cleanup", "camera"])
def test_durable_stop_ready_auto_cleans_local_receiver_after_control_loss(
tmp_path: Path,
local_failure: str,
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""A resolved exact STOP survives Wi-Fi/control retirement as completion truth."""
service, runtime = service_with_fake_runtime(tmp_path)
control = FakeInteractiveControlSession()
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
binding = _seed_supervised_connection(
service,
connection_mode="bridge",
transport_ref="k1-stop-ready",
)
control.verified_control = _verified_control_for_binding(
binding,
control_session_id="stop-ready-control",
)
prepared = service.prepare_acquisition(
_prepare_request(
project_name="STOP_READY",
host=binding.target_ipv4,
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
service.start_acquisition(
_start_request(
acquisition_id=acquisition_id,
physical_acceptance=PHYSICAL_ACCEPTANCE,
)
)
start_operation_id = service._acquisition_start_operation_id # noqa: SLF001
assert isinstance(start_operation_id, str)
identity = PhysicalCommandIdentity(
vendor_device_id_sha256="a" * 64,
device_serial_sha256="b" * 64,
)
physical_connection = PhysicalCommandConnectionBinding(
intent_id=binding.intent_id,
transport_ref=binding.transport_ref,
connection_mode="bridge",
target_ipv4=binding.target_ipv4,
target_port=binding.target_port,
host_path_epoch=binding.host_path_epoch,
control_session_id="stop-ready-control",
producer_generation=1,
)
def status(
session_state: str,
*,
observed_at_utc: str,
) -> PhysicalCommandStatusEvidence:
scanning = session_state == "scanning"
return PhysicalCommandStatusEvidence(
source="live-control-session",
vendor_device_id_sha256=identity.vendor_device_id_sha256,
device_serial_sha256=identity.device_serial_sha256,
control_session_id=physical_connection.control_session_id,
host_path_epoch=physical_connection.host_path_epoch,
producer_generation=physical_connection.producer_generation,
session_state=session_state, # type: ignore[arg-type]
session_state_code=302 if scanning else 300,
project_bound=scanning,
project_id_sha256="c" * 64 if scanning else None,
init_ready=scanning,
status_message_sha256=hashlib.sha256(
f"{session_state}:{observed_at_utc}".encode()
).hexdigest(),
mqtt_retained=False,
observed_at_utc=observed_at_utc,
)
ledger = service._physical_command_ledger # noqa: SLF001
ledger.prepare(
operation_id=start_operation_id,
parent_operation_id=None,
acquisition_id=acquisition_id,
action="start",
identity=identity,
connection=physical_connection,
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
payload_sha256="1" * 64,
baseline_status=status(
"ready",
observed_at_utc="2026-08-10T08:01:30.000Z",
),
)
ledger.mark_dispatching(start_operation_id)
ledger.mark_observing(
start_operation_id,
publish_call_returned=True,
packet_id=94,
)
ledger.mark_qos2_completed(start_operation_id, packet_id=94)
ledger.record_application_response(
start_operation_id,
PhysicalCommandApplicationResponse(
operation_id=start_operation_id,
action="start",
control_session_id=physical_connection.control_session_id,
host_path_epoch=physical_connection.host_path_epoch,
producer_generation=physical_connection.producer_generation,
result_code=PHYSICAL_COMMAND_APPLICATION_SUCCESS_CODE,
success=True,
payload_sha256="2" * 64,
observed_at_utc="2026-08-10T08:01:31.000Z",
),
)
ledger.record_status_observation(
start_operation_id,
status("scanning", observed_at_utc="2026-08-10T08:01:32.000Z"),
)
ledger.resolve(start_operation_id, resolution="start-active-observed")
runtime.mark_ready()
runtime.pcl_frames = 1
assert service.state()["acquisition"]["state"] == "acquiring"
# Match an acquisition that resumed through the exact read-only recovery
# owner before the operator requested the one canonical STOP.
active_start_record = ledger.snapshot().record
assert active_start_record is not None
recovery_lineage = facade_module._ActiveStreamRecoveryLineage( # noqa: SLF001
recovery_generation=service._active_stream_recovery_generation, # noqa: SLF001
snapshot_runtime_id=service._snapshot_runtime_id, # noqa: SLF001
acquisition_id=acquisition_id,
device_id=service._device_id, # type: ignore[arg-type] # noqa: SLF001
device_session_id=service._device_session_id, # type: ignore[arg-type] # noqa: SLF001
evidence_session_id=service._acquisition_out_dir.name, # type: ignore[union-attr] # noqa: SLF001
runtime_producer_generation=runtime.producer_generation,
start_operation_id=start_operation_id,
physical_operation_id=start_operation_id,
physical_revision=active_start_record.revision,
intent_id=binding.intent_id,
transport_ref=binding.transport_ref,
connection_mode="bridge",
target_ipv4=binding.target_ipv4,
target_port=binding.target_port,
)
with service._lock: # noqa: SLF001
service._active_stream_recovery_lineage = recovery_lineage # noqa: SLF001
service._active_stream_recovery_state = "recovered" # noqa: SLF001
service._active_stream_recovery_attempt = 7 # noqa: SLF001
runtime.recovery_state = "recovered"
runtime.recovery_attempt = 7
stop_operation_id = "op-00000000-0000-4000-8000-000000001299"
stop_request = _stop_request(
acquisition_id=acquisition_id,
operation_id=stop_operation_id,
mode="graceful",
physical_acceptance=PHYSICAL_ACCEPTANCE,
)
stopping = service.stop_acquisition(stop_request)
assert stopping["acquisition"]["state"] == "awaiting_external_stop"
assert stopping["last_operation"]["status"] == "running"
assert control.stop_calls == 1
assert runtime.source_mode == "live"
# Wi-Fi/control disappears after the one STOP request. Model the exact
# production ordering: state() begins with a pending local retirement,
# turns the completed ephemeral control owner into idle, and only then
# reduces the durable READY edge.
control.state = "completed"
service._pending_local_control_retirement = True # noqa: SLF001
ledger.prepare(
operation_id=stop_operation_id,
parent_operation_id=start_operation_id,
acquisition_id=acquisition_id,
action="stop",
identity=identity,
connection=physical_connection,
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
payload_sha256="d" * 64,
baseline_status=status(
"scanning",
observed_at_utc="2026-08-10T08:01:40.000Z",
),
)
ledger.mark_dispatching(stop_operation_id)
ledger.mark_observing(
stop_operation_id,
publish_call_returned=True,
packet_id=95,
)
ledger.mark_qos2_completed(stop_operation_id, packet_id=95)
ledger.record_application_response(
stop_operation_id,
PhysicalCommandApplicationResponse(
operation_id=stop_operation_id,
action="stop",
control_session_id=physical_connection.control_session_id,
host_path_epoch=physical_connection.host_path_epoch,
producer_generation=physical_connection.producer_generation,
result_code=PHYSICAL_COMMAND_APPLICATION_SUCCESS_CODE,
success=True,
payload_sha256="e" * 64,
observed_at_utc="2026-08-10T08:01:41.000Z",
),
)
ledger.record_status_observation(
stop_operation_id,
status("ready", observed_at_utc="2026-08-10T08:01:44.000Z"),
)
ledger.resolve(stop_operation_id, resolution="stop-standby-observed")
unintended_edges: list[str] = []
async def forbidden_device_edge(*_args: object, **_kwargs: object) -> object:
unintended_edges.append("device-or-network-io")
raise AssertionError("durable STOP READY reduction must be local-only")
monkeypatch.setattr(facade_module, "scan", forbidden_device_edge)
monkeypatch.setattr(facade_module, "read_wifi_status_once", forbidden_device_edge)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_device_edge)
if local_failure == "cleanup":
runtime.stop_error = RuntimeError("synthetic local cleanup failure after READY")
elif local_failure == "camera":
original_camera_snapshot = service.camera_preview.snapshot
def failed_camera_snapshot() -> dict[str, Any]:
snapshot = original_camera_snapshot()
return {
**snapshot,
"phase": "error",
"recording": {"active": True},
"error": {"code": "synthetic-camera-producer-failed"},
}
monkeypatch.setattr(service.camera_preview, "snapshot", failed_camera_snapshot)
completed = service.state()
operation = next(
item for item in completed["operations"] if item["operation_id"] == stop_operation_id
)
assert completed["application_control_session"]["state"] == "idle"
assert completed["physical_command"]["record"]["resolution"] == ("stop-standby-observed")
if local_failure == "cleanup":
assert completed["acquisition"]["state"] == "failed"
assert completed["acquisition"]["cleanup_pending"] is True
assert operation["status"] == "failed"
assert operation["stage_code"] == "local-finalization-failed"
assert operation["error"] == {
"category": "stream",
"code": "local-finalization-failed-after-device-standby",
"retryable": True,
"safe_to_retry": True,
"side_effect_status": "succeeded",
}
assert completed["source_mode"] == "live"
assert completed["connection_policy"]["actions"]["scan-ble"]["allowed"] is False
# Local cleanup alone is retried by polling. The physical STOP remains
# terminal and is never published again.
runtime.stop_error = None
completed = service.state()
operation = next(
item for item in completed["operations"] if item["operation_id"] == stop_operation_id
)
assert completed["acquisition"]["state"] == "failed"
assert completed["acquisition"]["cleanup_pending"] is False
assert operation["status"] == "failed"
assert operation["stage_code"] == "local-finalization-failed"
assert runtime.stop_calls == 2
elif local_failure == "camera":
assert completed["acquisition"]["state"] == "failed"
assert completed["acquisition"]["cleanup_pending"] is False
assert completed["acquisition"]["result"] == {
"receiver_stopped": True,
"device_state": "ready",
"device_stop": "protocol-confirmed",
"camera_failure_code": "synthetic-camera-producer-failed",
}
assert operation["status"] == "failed"
assert operation["stage_code"] == "local-finalization-failed"
assert operation["error"]["side_effect_status"] == "succeeded"
assert runtime.stop_calls == 1
else:
assert completed["acquisition"]["state"] == "completed"
assert completed["acquisition"]["cleanup_pending"] is False
assert completed["acquisition"]["result"] == {
"receiver_stopped": True,
"device_state": "ready",
"device_stop": "protocol-confirmed",
}
assert operation["status"] == "succeeded"
assert operation["stage_code"] == "device-standby-confirmed"
assert runtime.stop_calls == 1
assert completed["source_mode"] == "idle"
assert completed["live_perception_shadow"]["active"] is False
assert completed["connection_policy"]["actions"]["scan-ble"]["allowed"] is True
assert unintended_edges == []
assert control.stop_calls == 1
if local_failure != "cleanup":
assert completed["connection_recovery"]["state"] == "inactive"
assert completed["connection_recovery"]["automatic_read_only_rebind"] is False
assert service._active_stream_recovery_lineage is None # noqa: SLF001
# Polling the same durable proof is a pure idempotent read: no second
# local teardown and, critically, no second physical STOP.
stop_call_count = runtime.stop_calls
repeated = service.state()
repeated_operation = next(
item for item in repeated["operations"] if item["operation_id"] == stop_operation_id
)
assert repeated_operation["status"] == operation["status"]
assert repeated["acquisition"]["state"] == completed["acquisition"]["state"]
assert repeated["connection_policy"]["actions"]["scan-ble"]["allowed"] is True
assert unintended_edges == []
assert control.stop_calls == 1
assert runtime.stop_calls == stop_call_count
# A process restart retains only the resolved durable edge. There is no
# process-local receiver to recover and no physical action to replay.
restarted, restarted_runtime = service_with_fake_runtime(tmp_path)
restarted_state = restarted.state()
assert restarted_state["physical_command"]["record"]["operation_id"] == (stop_operation_id)
assert restarted_state["physical_command"]["record"]["resolution"] == ("stop-standby-observed")
assert restarted_state["acquisition"] is None
assert restarted_state["source_mode"] == "idle"
assert restarted_state["connection_policy"]["actions"]["scan-ble"]["allowed"] is True
assert restarted_runtime.stop_calls == 0
@pytest.mark.parametrize(
"mismatch",
[
"operation",
"acquisition",
"response-operation",
"retained-ready",
"bound-ready",
"initialized-ready",
"missing-qos2",
],
)
def test_durable_stop_ready_rejects_nonmatching_or_noncanonical_proof(
mismatch: str,
) -> None:
stop_operation_id = "op-00000000-0000-4000-8000-000000001399"
acquisition_id = "acquisition-stop-ready-proof"
proof: dict[str, Any] = {
"status": "resolved",
"requires_reconciliation": False,
"record": {
"operation_id": stop_operation_id,
"acquisition_id": acquisition_id,
"action": "stop",
"stage": "resolved",
"resolution": "stop-standby-observed",
"publish_call_returned": True,
"qos2_completed": True,
"packet_id": 91,
"application_response": {
"operation_id": stop_operation_id,
"action": "stop",
"success": True,
},
"last_status": {
"session_state": "ready",
"project_bound": False,
"init_ready": False,
"mqtt_retained": False,
},
},
}
record = proof["record"]
if mismatch == "operation":
record["operation_id"] = "different-stop-operation"
elif mismatch == "acquisition":
record["acquisition_id"] = "different-acquisition"
elif mismatch == "response-operation":
record["application_response"]["operation_id"] = "different-stop-operation"
elif mismatch == "retained-ready":
record["last_status"]["mqtt_retained"] = True
elif mismatch == "bound-ready":
record["last_status"]["project_bound"] = True
elif mismatch == "initialized-ready":
record["last_status"]["init_ready"] = True
elif mismatch == "missing-qos2":
record["qos2_completed"] = False
assert (
XgridsK1CompatibilityService._matching_stop_standby_confirmed( # noqa: SLF001
proof,
acquisition_id=acquisition_id,
stop_operation_id=stop_operation_id,
)
is False
)
@pytest.mark.parametrize(
"mismatch",
["operation", "acquisition", "response-operation", "response-failed", "ready", "stopping"],
)
def test_stop_timeout_matcher_rejects_wrong_lineage_or_terminal_status(
mismatch: str,
) -> None:
stop_operation_id = "op-00000000-0000-4000-8000-000000001489"
acquisition_id = "acquisition-stop-timeout-proof"
proof: dict[str, Any] = {
"status": "unresolved",
"requires_reconciliation": True,
"record": {
"operation_id": stop_operation_id,
"acquisition_id": acquisition_id,
"action": "stop",
"stage": "observing",
"resolution": None,
# An exact application response may precede or outlive the local
# QoS2 callback. Timeout cleanup is local-only in either case.
"publish_call_returned": None,
"qos2_completed": False,
"packet_id": None,
"application_response": {
"operation_id": stop_operation_id,
"action": "stop",
"success": True,
"observed_at_utc": "2026-08-10T08:10:02.000Z",
},
"last_status": None,
},
}
record = proof["record"]
if mismatch == "operation":
record["operation_id"] = "different-stop-operation"
elif mismatch == "acquisition":
record["acquisition_id"] = "different-acquisition"
elif mismatch == "response-operation":
record["application_response"]["operation_id"] = "different-stop-operation"
elif mismatch == "response-failed":
record["application_response"]["success"] = False
elif mismatch in {"ready", "stopping"}:
record["last_status"] = {
"session_state": "ready" if mismatch == "ready" else "scan_stopping"
}
assert (
XgridsK1CompatibilityService._matching_stop_response_without_terminal_status( # noqa: SLF001
proof,
acquisition_id=acquisition_id,
stop_operation_id=stop_operation_id,
)
is False
)
def test_stop_timeout_matcher_accepts_exact_response_without_qos2_callback() -> None:
stop_operation_id = "op-00000000-0000-4000-8000-000000001488"
acquisition_id = "acquisition-stop-timeout-no-qos"
proof = {
"status": "unresolved",
"requires_reconciliation": True,
"record": {
"operation_id": stop_operation_id,
"acquisition_id": acquisition_id,
"action": "stop",
"stage": "observing",
"resolution": None,
"publish_call_returned": None,
"qos2_completed": False,
"packet_id": None,
"application_response": {
"operation_id": stop_operation_id,
"action": "stop",
"success": True,
"observed_at_utc": "2026-08-10T08:10:02.000Z",
},
"last_status": None,
},
}
assert XgridsK1CompatibilityService._matching_stop_response_without_terminal_status( # noqa: SLF001
proof,
acquisition_id=acquisition_id,
stop_operation_id=stop_operation_id,
)
def _stop_response_without_terminal_status_fixture(
tmp_path: Path,
*,
qos2_completed: bool = True,
application_response: bool = True,
) -> SimpleNamespace:
clock_value = [datetime(2026, 8, 10, 8, 10, tzinfo=UTC)]
service, runtime = service_with_fake_runtime(tmp_path)
service._operations = OperationJournal(clock=lambda: clock_value[0]) # noqa: SLF001
control = FakeInteractiveControlSession()
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
binding = _seed_supervised_connection(
service,
connection_mode="bridge",
transport_ref="k1-stop-timeout",
)
control.verified_control = _verified_control_for_binding(
binding,
control_session_id="stop-timeout-control",
)
prepared = service.prepare_acquisition(
_prepare_request(
project_name="STOP_TIMEOUT",
host=binding.target_ipv4,
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
service.start_acquisition(
_start_request(
acquisition_id=acquisition_id,
physical_acceptance=PHYSICAL_ACCEPTANCE,
)
)
start_operation_id = service._acquisition_start_operation_id # noqa: SLF001
assert isinstance(start_operation_id, str)
identity = PhysicalCommandIdentity(
vendor_device_id_sha256="4" * 64,
device_serial_sha256="5" * 64,
)
physical_connection = PhysicalCommandConnectionBinding(
intent_id=binding.intent_id,
transport_ref=binding.transport_ref,
connection_mode="bridge",
target_ipv4=binding.target_ipv4,
target_port=binding.target_port,
host_path_epoch=binding.host_path_epoch,
control_session_id="stop-timeout-control",
producer_generation=1,
)
def status(
session_state: str,
*,
observed_at_utc: str,
) -> PhysicalCommandStatusEvidence:
scanning = session_state == "scanning"
return PhysicalCommandStatusEvidence(
source="live-control-session",
vendor_device_id_sha256=identity.vendor_device_id_sha256,
device_serial_sha256=identity.device_serial_sha256,
control_session_id=physical_connection.control_session_id,
host_path_epoch=physical_connection.host_path_epoch,
producer_generation=physical_connection.producer_generation,
session_state=session_state, # type: ignore[arg-type]
session_state_code=302 if scanning else 300,
project_bound=scanning,
project_id_sha256="6" * 64 if scanning else None,
init_ready=scanning,
status_message_sha256=hashlib.sha256(
f"{session_state}:{observed_at_utc}".encode()
).hexdigest(),
mqtt_retained=False,
observed_at_utc=observed_at_utc,
)
ledger = service._physical_command_ledger # noqa: SLF001
ledger.prepare(
operation_id=start_operation_id,
parent_operation_id=None,
acquisition_id=acquisition_id,
action="start",
identity=identity,
connection=physical_connection,
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
payload_sha256="7" * 64,
baseline_status=status(
"ready",
observed_at_utc="2026-08-10T08:09:55.000Z",
),
)
ledger.mark_dispatching(start_operation_id)
ledger.mark_observing(
start_operation_id,
publish_call_returned=True,
packet_id=81,
)
ledger.mark_qos2_completed(start_operation_id, packet_id=81)
ledger.record_application_response(
start_operation_id,
PhysicalCommandApplicationResponse(
operation_id=start_operation_id,
action="start",
control_session_id=physical_connection.control_session_id,
host_path_epoch=physical_connection.host_path_epoch,
producer_generation=physical_connection.producer_generation,
result_code=PHYSICAL_COMMAND_APPLICATION_SUCCESS_CODE,
success=True,
payload_sha256="8" * 64,
observed_at_utc="2026-08-10T08:09:56.000Z",
),
)
ledger.record_status_observation(
start_operation_id,
status("scanning", observed_at_utc="2026-08-10T08:09:57.000Z"),
)
ledger.resolve(start_operation_id, resolution="start-active-observed")
runtime.mark_ready()
runtime.pcl_frames = 1
assert service.state()["acquisition"]["state"] == "acquiring"
stop_operation_id = "op-00000000-0000-4000-8000-000000001499"
stop_request = _stop_request(
acquisition_id=acquisition_id,
operation_id=stop_operation_id,
deadline_seconds=10.0,
mode="graceful",
physical_acceptance=PHYSICAL_ACCEPTANCE,
)
stopping = service.stop_acquisition(stop_request)
assert stopping["acquisition"]["state"] == "awaiting_external_stop"
assert stopping["last_operation"]["status"] == "running"
ledger.prepare(
operation_id=stop_operation_id,
parent_operation_id=start_operation_id,
acquisition_id=acquisition_id,
action="stop",
identity=identity,
connection=physical_connection,
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
payload_sha256="9" * 64,
baseline_status=status(
"scanning",
observed_at_utc="2026-08-10T08:10:00.000Z",
),
)
ledger.mark_dispatching(stop_operation_id)
if qos2_completed:
ledger.mark_observing(
stop_operation_id,
publish_call_returned=True,
packet_id=82,
)
ledger.mark_qos2_completed(stop_operation_id, packet_id=82)
if application_response:
ledger.record_application_response(
stop_operation_id,
PhysicalCommandApplicationResponse(
operation_id=stop_operation_id,
action="stop",
control_session_id=physical_connection.control_session_id,
host_path_epoch=physical_connection.host_path_epoch,
producer_generation=physical_connection.producer_generation,
result_code=PHYSICAL_COMMAND_APPLICATION_SUCCESS_CODE,
success=True,
payload_sha256="a" * 64,
observed_at_utc="2026-08-10T08:10:02.000Z",
),
)
return SimpleNamespace(
service=service,
runtime=runtime,
control=control,
ledger=ledger,
clock_value=clock_value,
acquisition_id=acquisition_id,
stop_operation_id=stop_operation_id,
status=status,
)
def test_unknown_stop_retires_only_terminal_control_and_keeps_live_capture(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
fixture = _stop_response_without_terminal_status_fixture(
tmp_path,
qos2_completed=False,
application_response=False,
)
service = fixture.service
control = fixture.control
close_calls = 0
worker_retired = False
original_snapshot = control.snapshot
original_close = control.close
def terminal_snapshot() -> dict[str, object]:
snapshot = original_snapshot()
if control.state == "failed" and not worker_retired:
snapshot["can_open"] = False
return snapshot
def retire_failed_worker() -> None:
nonlocal close_calls, worker_retired
close_calls += 1
worker_retired = True
original_close()
monkeypatch.setattr(control, "snapshot", terminal_snapshot)
monkeypatch.setattr(control, "close", retire_failed_worker)
control.state = "failed"
control.outcome_unknown = True
control.failure = {
"code": "ApplicationCommandOutcomeUnknown",
"reason_code": "mqtt_response_timeout",
"stop_command_attempted": True,
"stop_publish_attempts": 1,
"safe_to_retry": False,
}
service._acquire_application_control_process_lease() # noqa: SLF001
recovered = service.state()
assert close_calls == 1
assert recovered["application_control_session"]["state"] == "idle"
assert recovered["acquisition"]["state"] == "awaiting_external_stop"
assert recovered["source_mode"] == "live"
assert recovered["physical_command"]["status"] == "unresolved"
assert recovered["physical_command"]["requires_reconciliation"] is True
assert fixture.runtime.stop_calls == 0
assert control.stop_calls == 1
assert service._application_control_process_lease_holders == set() # noqa: SLF001
@pytest.mark.parametrize("qos2_completed", [True, False])
def test_stop_success_without_terminal_status_times_out_into_local_only_recovery(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
qos2_completed: bool,
) -> None:
fixture = _stop_response_without_terminal_status_fixture(
tmp_path,
qos2_completed=qos2_completed,
)
service = fixture.service
runtime = fixture.runtime
control = fixture.control
operation = service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert operation.deadline_at is not None
fixture.clock_value[0] = operation.deadline_at - timedelta(milliseconds=1)
before_deadline = service.state()
assert before_deadline["acquisition"]["state"] == "awaiting_external_stop"
assert service._acquisition_session_lease is not None # noqa: SLF001
assert before_deadline["source_mode"] == "live"
assert before_deadline["last_operation"]["status"] == "running"
assert runtime.stop_calls == 0
assert control.stop_calls == 1
unintended_edges: list[str] = []
async def forbidden_device_edge(*_args: object, **_kwargs: object) -> object:
unintended_edges.append("device-or-network-io")
raise AssertionError("STOP timeout recovery must be local-only")
monkeypatch.setattr(facade_module, "scan", forbidden_device_edge)
monkeypatch.setattr(facade_module, "read_wifi_status_once", forbidden_device_edge)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_device_edge)
fixture.clock_value[0] = operation.deadline_at
timed_out = service.state()
timeout_operation = next(
item
for item in timed_out["operations"]
if item["operation_id"] == fixture.stop_operation_id
)
assert timed_out["application_control_session"]["state"] == "idle"
assert timed_out["acquisition"]["state"] == "failed"
assert timed_out["acquisition"]["cleanup_pending"] is False
assert timed_out["acquisition"]["message_code"] == (
"acquisition.stop.accepted_physical_outcome_unknown"
)
assert timed_out["acquisition"]["result"] == {
"receiver_stopped": True,
"device_state": "unknown",
"device_stop": "stop-accepted-physical-outcome-unknown",
"automatic_replay_allowed": False,
}
assert timeout_operation["status"] == "timed_out"
assert timeout_operation["stage_code"] == ("stop-accepted-physical-outcome-unknown")
assert timeout_operation["error"] == {
"category": "device",
"code": "stop-accepted-physical-outcome-unknown",
"retryable": False,
"safe_to_retry": False,
"side_effect_status": "unknown",
"automatic_replay_allowed": False,
}
assert timed_out["physical_command"]["status"] == "unresolved"
assert timed_out["physical_command"]["requires_reconciliation"] is True
assert timed_out["physical_command"]["record"]["resolution"] is None
assert timed_out["source_mode"] == "idle"
assert timed_out["live_perception_shadow"]["active"] is False
assert timed_out["connection_policy"]["actions"]["scan-ble"]["allowed"] is True
for action in ("provision-fresh-device", "start-acquisition", "stop-acquisition"):
assert timed_out["connection_policy"]["actions"][action]["allowed"] is False
assert unintended_edges == []
assert runtime.stop_calls == 1
assert control.stop_calls == 1
repeated = service.state()
assert repeated["acquisition"]["state"] == "failed"
assert repeated["physical_command"]["status"] == "unresolved"
assert repeated["connection_policy"]["actions"]["scan-ble"]["allowed"] is True
assert unintended_edges == []
assert runtime.stop_calls == 1
assert control.stop_calls == 1
restarted, restarted_runtime = service_with_fake_runtime(tmp_path)
restarted_state = restarted.state()
assert restarted_state["physical_command"]["status"] == "unresolved"
assert restarted_state["physical_command"]["record"]["operation_id"] == (
fixture.stop_operation_id
)
assert restarted_state["acquisition"] is None
assert restarted_state["connection_policy"]["actions"]["scan-ble"]["allowed"] is True
for action in ("provision-fresh-device", "start-acquisition", "stop-acquisition"):
assert restarted_state["connection_policy"]["actions"][action]["allowed"] is False
assert restarted_runtime.stop_calls == 0
def test_stop_timeout_local_cleanup_failure_retries_only_local_resources(
tmp_path: Path,
) -> None:
fixture = _stop_response_without_terminal_status_fixture(tmp_path)
operation = fixture.service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert operation.deadline_at is not None
fixture.clock_value[0] = operation.deadline_at
fixture.runtime.stop_error = RuntimeError("synthetic timeout cleanup failure")
failed_cleanup = fixture.service.state()
failed_operation = next(
item
for item in failed_cleanup["operations"]
if item["operation_id"] == fixture.stop_operation_id
)
assert failed_cleanup["acquisition"]["state"] == "failed"
assert failed_cleanup["acquisition"]["cleanup_pending"] is True
assert failed_cleanup["source_mode"] == "live"
assert failed_operation["status"] == "failed"
assert failed_operation["stage_code"] == ("local-cleanup-failed-after-stop-outcome-unknown")
assert failed_operation["error"]["side_effect_status"] == "unknown"
assert failed_operation["error"]["safe_to_retry"] is False
assert failed_operation["error"]["automatic_replay_allowed"] is False
assert fixture.control.stop_calls == 1
assert fixture.runtime.stop_calls == 1
fixture.runtime.stop_error = None
recovered = fixture.service.state()
assert recovered["acquisition"]["state"] == "failed"
assert recovered["acquisition"]["cleanup_pending"] is False
assert recovered["acquisition"]["result"]["receiver_stopped"] is True
assert "local_cleanup_retry_pending" not in recovered["acquisition"]["result"]
assert recovered["source_mode"] == "idle"
assert recovered["physical_command"]["status"] == "unresolved"
assert recovered["connection_policy"]["actions"]["scan-ble"]["allowed"] is True
assert fixture.control.stop_calls == 1
assert fixture.runtime.stop_calls == 2
repeated = fixture.service.state()
assert repeated["acquisition"]["cleanup_pending"] is False
assert fixture.control.stop_calls == 1
assert fixture.runtime.stop_calls == 2
def test_stop_response_preserves_precise_unknown_outcome_through_predeadline_loss(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
fixture = _stop_response_without_terminal_status_fixture(tmp_path)
operation = fixture.service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert operation.deadline_at is not None
original_snapshot = fixture.control.snapshot
def failed_control_snapshot() -> dict[str, object]:
snapshot = original_snapshot()
if fixture.control.state == "failed":
snapshot["failure"] = {
"reason_code": "mqtt_network_loop_failed",
"safe_to_retry": False,
"modeling_command_attempted": True,
}
return snapshot
monkeypatch.setattr(fixture.control, "snapshot", failed_control_snapshot)
fixture.control.state = "failed"
fixture.runtime.phase = "error"
fixture.clock_value[0] = operation.deadline_at - timedelta(milliseconds=1)
before_deadline = fixture.service.state()
stop_operation = next(
item
for item in before_deadline["operations"]
if item["operation_id"] == fixture.stop_operation_id
)
assert before_deadline["acquisition"]["state"] == "awaiting_external_stop"
assert before_deadline["acquisition"]["message_code"] == ("acquisition.stop.device_stopping")
assert stop_operation["status"] == "running"
assert before_deadline["physical_command"]["status"] == "unresolved"
assert fixture.runtime.stop_calls == 0
assert fixture.control.stop_calls == 1
fixture.clock_value[0] = operation.deadline_at
timed_out = fixture.service.state()
stop_operation = next(
item
for item in timed_out["operations"]
if item["operation_id"] == fixture.stop_operation_id
)
assert timed_out["acquisition"]["message_code"] == (
"acquisition.stop.accepted_physical_outcome_unknown"
)
assert stop_operation["status"] == "timed_out"
assert stop_operation["stage_code"] == "stop-accepted-physical-outcome-unknown"
assert timed_out["source_mode"] == "idle"
assert timed_out["physical_command"]["status"] == "unresolved"
assert fixture.runtime.stop_calls == 1
assert fixture.control.stop_calls == 1
def test_stop_ready_resolution_wins_when_it_arrives_at_timeout_deadline(
tmp_path: Path,
) -> None:
fixture = _stop_response_without_terminal_status_fixture(tmp_path)
operation = fixture.service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert operation.deadline_at is not None
fixture.clock_value[0] = operation.deadline_at
fixture.ledger.record_status_observation(
fixture.stop_operation_id,
fixture.status("ready", observed_at_utc="2026-08-10T08:10:10.000Z"),
)
fixture.ledger.resolve(
fixture.stop_operation_id,
resolution="stop-standby-observed",
)
fixture.control.state = "idle"
fixture.control.verified_control = None
completed = fixture.service.state()
completed_operation = next(
item
for item in completed["operations"]
if item["operation_id"] == fixture.stop_operation_id
)
assert completed["acquisition"]["state"] == "completed"
assert completed["acquisition"]["result"]["device_state"] == "ready"
assert completed_operation["status"] == "succeeded"
assert completed["physical_command"]["record"]["resolution"] == ("stop-standby-observed")
assert fixture.control.stop_calls == 1
assert fixture.runtime.stop_calls == 1
def test_facade_wires_one_physical_command_coordinator_into_control_session(
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
assert (
service._application_control_session._physical_command_coordinator # noqa: SLF001
is service._physical_command_coordinator # noqa: SLF001
)
physical_snapshot = service.state()["physical_command"]
assert physical_snapshot["automatic_replay_allowed"] is False
assert physical_snapshot["status"] == "empty"
@pytest.mark.parametrize(
("stage", "action", "expected_resolution"),
[
(
"prepared",
"start",
[("op-00000000-0000-4000-8000-000000000111", "not-dispatched")],
),
("prepared", "stop", []),
("dispatching", "start", []),
("observing", "start", []),
],
)
def test_facade_startup_auto_resolves_only_pre_dispatch_physical_attempt(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
stage: str,
action: str,
expected_resolution: list[tuple[str, str]],
) -> None:
operation_id = "op-00000000-0000-4000-8000-000000000111"
class StartupLedger:
def __init__(self) -> None:
self.resolutions: list[tuple[str, str]] = []
def snapshot(self) -> SimpleNamespace:
return SimpleNamespace(
status="unresolved",
record=SimpleNamespace(
operation_id=operation_id,
stage=stage,
action=action,
),
)
def resolve(self, candidate: str, *, resolution: str) -> None:
self.resolutions.append((candidate, resolution))
ledger = StartupLedger()
monkeypatch.setattr(facade_module, "PhysicalCommandLedger", lambda _root: ledger)
service = XgridsK1CompatibilityService(
tmp_path,
host_wifi_association_probe=FakeHostWifiAssociationProbe(),
)
assert service._physical_command_ledger is ledger # noqa: SLF001
assert ledger.resolutions == expected_resolution
def test_facade_physical_context_chains_stop_to_durable_start_after_transient_id_clears(
tmp_path: Path,
) -> None:
start_operation_id = "op-00000000-0000-4000-8000-000000000101"
stop_operation_id = "op-00000000-0000-4000-8000-000000000102"
service, runtime = service_with_fake_runtime(tmp_path)
control = FakeInteractiveControlSession()
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
binding = _seed_supervised_connection(service)
service._compatibility_attestation = ATTESTATION.model_dump(mode="json") # noqa: SLF001
class FacadeAdmissionLedger:
def __init__(self) -> None:
self.record: object | None = None
self.admission_calls = 0
def require_no_unresolved_attempt(self) -> None:
self.admission_calls += 1
def snapshot(self) -> SimpleNamespace:
return SimpleNamespace(record=self.record)
ledger = FacadeAdmissionLedger()
service._physical_command_ledger = ledger # type: ignore[assignment] # noqa: SLF001
prepared = service.prepare_acquisition(
_prepare_request(
project_name="TEST001",
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
service.start_acquisition(
_start_request(
acquisition_id=acquisition_id,
operation_id=start_operation_id,
physical_acceptance=PHYSICAL_ACCEPTANCE,
)
)
start_context = control.start_contexts[-1]
assert start_context.operation_id == start_operation_id
assert start_context.parent_operation_id is None
assert start_context.acquisition_id == acquisition_id
assert start_context.operator_confirmation_id is None
assert start_context.operator_confirmed_at_utc is None
ledger.record = SimpleNamespace(operation_id=start_context.operation_id)
service._physical_command_coordinator = SimpleNamespace( # type: ignore[assignment] # noqa: SLF001
snapshot=lambda: _exact_start_physical_proof(
operation_id=start_operation_id,
acquisition_id=acquisition_id,
binding=binding,
resolved=True,
)
)
runtime.mark_ready()
runtime.pcl_frames = 1
service.state()
assert service._acquisition_start_operation_id is None # noqa: SLF001
service.stop_acquisition(
_stop_request(
acquisition_id=acquisition_id,
operation_id=stop_operation_id,
mode="graceful",
physical_acceptance=PHYSICAL_ACCEPTANCE,
)
)
stop_context = control.stop_contexts[-1]
assert stop_context.operation_id == stop_operation_id
assert stop_context.parent_operation_id == start_operation_id
assert stop_context.acquisition_id == acquisition_id
assert stop_context.operator_confirmation_id is None
assert stop_context.operator_confirmed_at_utc is None
assert ledger.admission_calls == 2
def test_facade_blocks_unresolved_physical_start_before_local_receiver_side_effects(
tmp_path: Path,
) -> None:
operation_id = "op-00000000-0000-4000-8000-000000000103"
service, runtime = service_with_fake_runtime(tmp_path)
control = FakeInteractiveControlSession()
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
_seed_supervised_connection(service)
service._compatibility_attestation = ATTESTATION.model_dump(mode="json") # noqa: SLF001
class BlockedPhysicalLedger:
def require_no_unresolved_attempt(self) -> None:
raise PhysicalCommandBlocked("ambiguous previous physical edge")
service._physical_command_ledger = BlockedPhysicalLedger() # type: ignore[assignment] # noqa: SLF001
prepared = service.prepare_acquisition(
_prepare_request(
project_name="TEST001",
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
with pytest.raises(PhysicalCommandBlocked):
service.start_acquisition(
_start_request(
acquisition_id=prepared["acquisition"]["acquisition_id"],
operation_id=operation_id,
physical_acceptance=PHYSICAL_ACCEPTANCE,
)
)
assert runtime.start_calls == []
assert control.start_contexts == []
assert service._operations.get(operation_id).status == "failed" # noqa: SLF001
def test_plugin_commanded_prepare_rejects_stale_binding_before_creating_acquisition(
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
class StaleInteractiveControlSession(FakeInteractiveControlSession):
def __init__(self) -> None:
super().__init__()
self.project_prompt_calls = 0
self.close_calls = 0
def validate_connection_binding(self) -> None:
raise ApplicationConnectionBindingLost("test route changed")
def open_project_prompt(
self,
*,
expected_session_generation: int | None = None,
expected_state_revision: int | None = None,
) -> dict[str, object]:
self.project_prompt_calls += 1
return super().open_project_prompt(
expected_session_generation=expected_session_generation,
expected_state_revision=expected_state_revision,
)
def close_prestart(self) -> dict[str, object]:
self.close_calls += 1
return super().close_prestart()
control = StaleInteractiveControlSession()
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
_seed_supervised_connection(service)
service._compatibility_attestation = ATTESTATION.model_dump(mode="json") # noqa: SLF001
with pytest.raises(ApplicationConnectionBindingLost):
service.prepare_acquisition(
_prepare_request(
project_name="TEST001",
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
assert service._acquisition is None # noqa: SLF001
assert control.project_prompt_calls == 0
assert control.close_calls == 1
assert control.state == "closed"
def test_workspace_entry_rejects_stale_binding_before_releasing_checkpoint(
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
class StaleWorkspaceControlSession(FakeInteractiveControlSession):
def __init__(self) -> None:
super().__init__()
self.state = "connection-ready"
self.enter_calls = 0
self.close_calls = 0
def validate_connection_binding(self) -> None:
raise ApplicationConnectionBindingLost("test route changed")
def enter_workspace(
self,
*,
expected_session_generation: int | None = None,
expected_state_revision: int | None = None,
) -> dict[str, object]:
# Production ``InteractiveApplicationControlSession`` owns this
# command-bound guard internally. The facade must not duplicate
# it ahead of the checkpoint.
self.validate_connection_binding()
del expected_session_generation, expected_state_revision
self.enter_calls += 1
raise AssertionError("stale checkpoint must not be released")
def close_prestart(self) -> dict[str, object]:
self.close_calls += 1
return super().close_prestart()
control = StaleWorkspaceControlSession()
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
_seed_supervised_connection(service)
with pytest.raises(ApplicationConnectionBindingLost):
service.enter_application_workspace(
EnterApplicationWorkspaceRequest(
operator_confirmed=True,
expected_session_generation=1,
expected_state_revision=1,
)
)
assert control.enter_calls == 0
assert control.close_calls == 1
assert control.state == "closed"
class _BindingValidatingControlSession(FakeInteractiveControlSession):
"""Test double with the production session's command-bound guards."""
def __init__(
self,
service: XgridsK1CompatibilityService,
binding: ApplicationConnectionBinding,
) -> None:
super().__init__(initial_state="idle")
self._service = service
self._binding = binding
self.validation_calls = 0
def validate_connection_binding(self) -> None:
self.validation_calls += 1
self._service._validate_application_connection_binding(self._binding) # noqa: SLF001
def enter_workspace(
self,
*,
expected_session_generation: int | None = None,
expected_state_revision: int | None = None,
) -> dict[str, object]:
self.validate_connection_binding()
return super().enter_workspace(
expected_session_generation=expected_session_generation,
expected_state_revision=expected_state_revision,
)
def open_project_prompt(
self,
*,
expected_session_generation: int | None = None,
expected_state_revision: int | None = None,
) -> dict[str, object]:
self.validate_connection_binding()
return super().open_project_prompt(
expected_session_generation=expected_session_generation,
expected_state_revision=expected_state_revision,
)
def request_start(
self,
*,
project_name: str,
confirmation: object,
command_context: object,
preparation_checkpoint_observer: object | None = None,
expected_session_generation: int | None = None,
expected_state_revision: int | None = None,
) -> dict[str, object]:
self.validate_connection_binding()
return super().request_start(
project_name=project_name,
confirmation=confirmation,
command_context=command_context,
preparation_checkpoint_observer=preparation_checkpoint_observer,
expected_session_generation=expected_session_generation,
expected_state_revision=expected_state_revision,
)
def _install_binding_validating_ready_control(
service: XgridsK1CompatibilityService,
*,
host_path: HostPathProbeResult | None = None,
) -> tuple[
_BindingValidatingControlSession,
ApplicationConnectionBinding,
dict[str, Any],
]:
binding = _seed_supervised_connection(
service,
connection_mode="bridge",
transport_ref="ttl-bound-k1",
logical_device_id="ttl-bound-device",
host_path=host_path,
)
control = _BindingValidatingControlSession(service, binding)
control.open(connection_binding=binding)
control.verified_control = _verified_control_for_binding(
binding,
logical_device_id="ttl-bound-device",
control_session_id="test-control-ttl-bound-k1",
control_proof_revision=2,
)
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
service._reconcile_connection_supervisor( # noqa: SLF001
control.snapshot(),
service.runtime.snapshot(),
)
service._acquire_application_control_process_lease() # noqa: SLF001
state = service.state()
assert state["application_control_session"]["state"] == "connection-ready"
return control, binding, state
def test_public_commanded_workflow_refreshes_stable_route_before_ttl_reduction(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
monotonic_now = [100.0]
suspend_aware_now = [1_000.0]
supervisor = service._connection_supervisor # noqa: SLF001
supervisor._monotonic_clock = lambda: monotonic_now[0] # noqa: SLF001
supervisor._suspend_aware_clock = lambda: suspend_aware_now[0] # noqa: SLF001
control, binding, ready = _install_binding_validating_ready_control(service)
stable_path = _direct_host_path(binding.target_ipv4)
monkeypatch.setattr(service, "_sample_host_path", lambda *_args, **_kwargs: stable_path)
monkeypatch.setattr(
facade_module,
"_probe_control_endpoint_socket",
lambda _target: facade_module.TcpReachabilityProbeResult(reachable=True),
)
target = EndpointTarget(binding.target_ipv4, binding.target_port)
def advance_past_fifteen_seconds_with_fresh_endpoint() -> None:
monotonic_now[0] += 10.0
suspend_aware_now[0] += 10.0
assert supervisor.observe_endpoint(
target=target,
intent_id=binding.intent_id,
host_path_epoch=binding.host_path_epoch,
reachable=True,
)
monotonic_now[0] += 5.01
suspend_aware_now[0] += 5.01
advance_past_fifteen_seconds_with_fresh_endpoint()
polled = service.state()
assert polled["application_control_session"]["state"] == "connection-ready"
assert supervisor.snapshot().host_path.epoch == binding.host_path_epoch
workspace = service.enter_application_workspace(
EnterApplicationWorkspaceRequest(
operator_confirmed=True,
expected_session_generation=ready["application_control_session"]["session_generation"],
expected_state_revision=ready["application_control_session"]["state_revision"],
)
)
assert workspace["application_control_session"]["state"] == "workspace-ready"
assert supervisor.snapshot().host_path.epoch == binding.host_path_epoch
assert control.validation_calls == 1
# Retain a focused regression for the original 15-second reducer ordering
# even though the production silence lease now tolerates two monitor
# passes. Command-bound sampling must still precede stale reduction for
# any reviewed TTL configuration.
supervisor._observation_ttl_seconds = 15.0 # noqa: SLF001
advance_past_fifteen_seconds_with_fresh_endpoint()
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host=binding.target_ipv4,
compatibility_attestation=ATTESTATION,
expected_control_session_generation=workspace["application_control_session"][
"session_generation"
],
expected_control_state_revision=workspace["application_control_session"][
"state_revision"
],
)
)
assert prepared["application_control_session"]["state"] == "project-ready"
assert supervisor.snapshot().host_path.epoch == binding.host_path_epoch
assert control.validation_calls == 3
advance_past_fifteen_seconds_with_fresh_endpoint()
started = service.start_acquisition(
_start_request(
acquisition_id=prepared["acquisition"]["acquisition_id"],
physical_acceptance=PHYSICAL_ACCEPTANCE,
expected_control_session_generation=prepared["application_control_session"][
"session_generation"
],
expected_control_state_revision=prepared["application_control_session"][
"state_revision"
],
)
)
assert started["acquisition"]["state"] == "starting"
assert supervisor.snapshot().host_path.epoch == binding.host_path_epoch
assert supervisor.snapshot().authority.control_allowed is True
assert control.start_projects == [PROJECT_NAME]
assert control.validation_calls == 5
assert len(runtime.start_calls) == 1
def test_existing_control_open_refreshes_before_ttl_reuse_gate(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _runtime = service_with_fake_runtime(tmp_path)
monotonic_now = [100.0]
suspend_aware_now = [1_000.0]
supervisor = service._connection_supervisor # noqa: SLF001
supervisor._monotonic_clock = lambda: monotonic_now[0] # noqa: SLF001
supervisor._suspend_aware_clock = lambda: suspend_aware_now[0] # noqa: SLF001
supervisor._observation_ttl_seconds = 15.0 # noqa: SLF001
control, binding, _ready = _install_binding_validating_ready_control(service)
stable_path = _direct_host_path(binding.target_ipv4)
monkeypatch.setattr(service, "_sample_host_path", lambda *_args, **_kwargs: stable_path)
monotonic_now[0] += 10.0
suspend_aware_now[0] += 10.0
assert supervisor.observe_endpoint(
target=EndpointTarget(binding.target_ipv4, binding.target_port),
intent_id=binding.intent_id,
host_path_epoch=binding.host_path_epoch,
reachable=True,
)
monotonic_now[0] += 5.01
suspend_aware_now[0] += 5.01
def forbid_reopen_or_recovery() -> tuple[str, dict[str, Any]]:
raise AssertionError("stable existing control must not reopen or enter BLE recovery")
monkeypatch.setattr(service, "_reuse_or_recover_control_target", forbid_reopen_or_recovery)
reused = service.open_application_control_session(
OpenApplicationControlSessionRequest(
operator_present=True,
owner_controlled_device=True,
lixelgo_closed=True,
battery_storage_confirmed=True,
expected_physical_state_confirmed=True,
timezone_name="Europe/Moscow",
)
)
assert reused["application_control_session"]["state"] == "connection-ready"
assert supervisor.snapshot().host_path.epoch == binding.host_path_epoch
assert supervisor.snapshot().authority.control_allowed is True
assert control.validation_calls == 1
open_operation = next(
operation
for operation in reused["operations"]
if operation["action"] == "application-control.session.open"
)
assert open_operation["result"]["connection_lease_reused"] is True
assert open_operation["result"]["device_write_performed"] is False
def test_existing_control_bootstrap_refreshes_before_ttl_reuse_gate(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _runtime = service_with_fake_runtime(tmp_path)
monotonic_now = [100.0]
suspend_aware_now = [1_000.0]
supervisor = service._connection_supervisor # noqa: SLF001
supervisor._monotonic_clock = lambda: monotonic_now[0] # noqa: SLF001
supervisor._suspend_aware_clock = lambda: suspend_aware_now[0] # noqa: SLF001
supervisor._observation_ttl_seconds = 15.0 # noqa: SLF001
control, binding, _ready = _install_binding_validating_ready_control(service)
service._bootstrap_prestart_control_ready_owned = MethodType( # type: ignore[method-assign] # noqa: SLF001
XgridsK1CompatibilityService._bootstrap_prestart_control_ready_owned, # noqa: SLF001
service,
)
stable_path = _direct_host_path(binding.target_ipv4)
monkeypatch.setattr(service, "_sample_host_path", lambda *_args, **_kwargs: stable_path)
monotonic_now[0] += 10.0
suspend_aware_now[0] += 10.0
assert supervisor.observe_endpoint(
target=EndpointTarget(binding.target_ipv4, binding.target_port),
intent_id=binding.intent_id,
host_path_epoch=binding.host_path_epoch,
reachable=True,
)
monotonic_now[0] += 5.01
suspend_aware_now[0] += 5.01
async def forbid_retirement() -> None:
raise AssertionError("stable existing control must not be retired or reopened")
monkeypatch.setattr(
service,
"_retire_prestart_control_for_mode_transition",
forbid_retirement,
)
asyncio.run(
service._bootstrap_prestart_control_ready_owned( # noqa: SLF001
parent_operation_id=None,
connection_mode="bridge",
)
)
assert control.state == "connection-ready"
assert control.validation_calls == 1
assert supervisor.snapshot().host_path.epoch == binding.host_path_epoch
assert supervisor.snapshot().authority.control_allowed is True
bootstrap = [
operation
for operation in service._operations.snapshot() # noqa: SLF001
if operation["action"] == facade_module.ACTION_CONNECTION_CONTROL_BOOTSTRAP
]
assert len(bootstrap) == 1
assert bootstrap[0]["status"] == "succeeded"
def test_workspace_route_change_still_fails_closed_before_checkpoint(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
monotonic_now = [100.0]
suspend_aware_now = [1_000.0]
supervisor = service._connection_supervisor # noqa: SLF001
supervisor._monotonic_clock = lambda: monotonic_now[0] # noqa: SLF001
supervisor._suspend_aware_clock = lambda: suspend_aware_now[0] # noqa: SLF001
control, binding, ready = _install_binding_validating_ready_control(service)
changed_path = HostPathProbeResult(
available=True,
fingerprint="test-route:changed-before-workspace",
interface="test0",
source_ipv4="192.168.1.2",
route_class="direct",
kernel_route_fingerprint="test-route:changed-before-workspace",
)
monkeypatch.setattr(service, "_sample_host_path", lambda *_args, **_kwargs: changed_path)
with pytest.raises(ApplicationConnectionBindingLost):
service.enter_application_workspace(
EnterApplicationWorkspaceRequest(
operator_confirmed=True,
expected_session_generation=ready["application_control_session"][
"session_generation"
],
expected_state_revision=ready["application_control_session"]["state_revision"],
)
)
assert control.state == "closed"
assert supervisor.snapshot().host_path.epoch != binding.host_path_epoch
assert supervisor.snapshot().authority.control_allowed is False
assert runtime.start_calls == []
assert control.start_projects == []
def test_start_stale_endpoint_fails_before_receiver_or_device_checkpoint(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control, binding, ready = _install_binding_validating_ready_control(service)
stable_path = _direct_host_path(binding.target_ipv4)
monkeypatch.setattr(service, "_sample_host_path", lambda *_args, **_kwargs: stable_path)
workspace = service.enter_application_workspace(
EnterApplicationWorkspaceRequest(
operator_confirmed=True,
expected_session_generation=ready["application_control_session"]["session_generation"],
expected_state_revision=ready["application_control_session"]["state_revision"],
)
)
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host=binding.target_ipv4,
compatibility_attestation=ATTESTATION,
expected_control_session_generation=workspace["application_control_session"][
"session_generation"
],
expected_control_state_revision=workspace["application_control_session"][
"state_revision"
],
)
)
target = EndpointTarget(binding.target_ipv4, binding.target_port)
supervisor = service._connection_supervisor # noqa: SLF001
assert supervisor.observe_endpoint(
target=target,
intent_id=binding.intent_id,
host_path_epoch=binding.host_path_epoch,
reachable=False,
reason_code="tcp-endpoint-unreachable",
)
physical_before = service._physical_command_ledger.snapshot() # noqa: SLF001
with pytest.raises(ApplicationConnectionBindingLost):
service.start_acquisition(
_start_request(
acquisition_id=prepared["acquisition"]["acquisition_id"],
physical_acceptance=PHYSICAL_ACCEPTANCE,
expected_control_session_generation=prepared["application_control_session"][
"session_generation"
],
expected_control_state_revision=prepared["application_control_session"][
"state_revision"
],
)
)
assert prepared["acquisition"]["state"] == "prepared"
assert service._acquisition is not None # noqa: SLF001
assert service._acquisition.state == "prepared" # noqa: SLF001
assert service._physical_command_ledger.snapshot() == physical_before # noqa: SLF001
assert not any(
operation["action"] == facade_module.ACTION_ACQUISITION_START
for operation in service._operations.snapshot() # noqa: SLF001
)
assert runtime.start_calls == []
assert control.start_projects == []
def test_start_refreshes_ttl_expired_endpoint_after_project_prepare(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
monotonic_now = [100.0]
suspend_aware_now = [1_000.0]
supervisor = service._connection_supervisor # noqa: SLF001
supervisor._monotonic_clock = lambda: monotonic_now[0] # noqa: SLF001
supervisor._suspend_aware_clock = lambda: suspend_aware_now[0] # noqa: SLF001
supervisor._observation_ttl_seconds = 15.0 # noqa: SLF001
control, binding, ready = _install_binding_validating_ready_control(service)
stable_path = _direct_host_path(binding.target_ipv4)
monkeypatch.setattr(service, "_sample_host_path", lambda *_args, **_kwargs: stable_path)
workspace = service.enter_application_workspace(
EnterApplicationWorkspaceRequest(
operator_confirmed=True,
expected_session_generation=ready["application_control_session"][
"session_generation"
],
expected_state_revision=ready["application_control_session"]["state_revision"],
)
)
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host=binding.target_ipv4,
compatibility_attestation=ATTESTATION,
expected_control_session_generation=workspace["application_control_session"][
"session_generation"
],
expected_control_state_revision=workspace["application_control_session"][
"state_revision"
],
)
)
monotonic_now[0] += 15.01
suspend_aware_now[0] += 15.01
assert control.verified_control is not None
control.verified_control = {
**control.verified_control,
"control_proof_revision": 3,
}
tcp_samples: list[str] = []
monkeypatch.setattr(
facade_module,
"_probe_control_endpoint_socket",
lambda target: (
tcp_samples.append(target)
or facade_module.TcpReachabilityProbeResult(reachable=True)
),
)
started = service.start_acquisition(
_start_request(
acquisition_id=prepared["acquisition"]["acquisition_id"],
physical_acceptance=PHYSICAL_ACCEPTANCE,
expected_control_session_generation=prepared["application_control_session"][
"session_generation"
],
expected_control_state_revision=prepared["application_control_session"][
"state_revision"
],
)
)
assert started["acquisition"]["state"] == "starting"
assert tcp_samples == [binding.target_ipv4]
assert supervisor.snapshot().host_path.epoch == binding.host_path_epoch
assert supervisor.snapshot().endpoint.tcp_state == "reachable"
assert supervisor.snapshot().authority.acquisition_start_allowed is True
assert len(runtime.start_calls) == 1
assert control.start_projects == [PROJECT_NAME]
def test_start_refreshes_endpoint_before_prepared_worker_handoff_window(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
monotonic_now = [100.0]
suspend_aware_now = [1_000.0]
supervisor = service._connection_supervisor # noqa: SLF001
supervisor._monotonic_clock = lambda: monotonic_now[0] # noqa: SLF001
supervisor._suspend_aware_clock = lambda: suspend_aware_now[0] # noqa: SLF001
supervisor._observation_ttl_seconds = 15.0 # noqa: SLF001
control, binding, ready = _install_binding_validating_ready_control(service)
stable_path = _direct_host_path(binding.target_ipv4)
monkeypatch.setattr(service, "_sample_host_path", lambda *_args, **_kwargs: stable_path)
workspace = service.enter_application_workspace(
EnterApplicationWorkspaceRequest(
operator_confirmed=True,
expected_session_generation=ready["application_control_session"][
"session_generation"
],
expected_state_revision=ready["application_control_session"]["state_revision"],
)
)
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host=binding.target_ipv4,
compatibility_attestation=ATTESTATION,
expected_control_session_generation=workspace["application_control_session"][
"session_generation"
],
expected_control_state_revision=workspace["application_control_session"][
"state_revision"
],
)
)
# The endpoint is still nominally reachable, but only eleven seconds of
# its lease remain. That is insufficient for PREPARED + worker dispatch.
monotonic_now[0] += 4.01
suspend_aware_now[0] += 4.01
assert supervisor.snapshot().endpoint.tcp_state == "reachable"
tcp_samples: list[str] = []
monkeypatch.setattr(
facade_module,
"_probe_control_endpoint_socket",
lambda target: (
tcp_samples.append(target)
or facade_module.TcpReachabilityProbeResult(reachable=True)
),
)
started = service.start_acquisition(
_start_request(
acquisition_id=prepared["acquisition"]["acquisition_id"],
physical_acceptance=PHYSICAL_ACCEPTANCE,
expected_control_session_generation=prepared["application_control_session"][
"session_generation"
],
expected_control_state_revision=prepared["application_control_session"][
"state_revision"
],
)
)
assert started["acquisition"]["state"] == "starting"
assert tcp_samples == [binding.target_ipv4]
assert supervisor.endpoint_observation_has_remaining_lease(
target=EndpointTarget(binding.target_ipv4, binding.target_port),
intent_id=binding.intent_id,
host_path_epoch=binding.host_path_epoch,
minimum_remaining_seconds=facade_module.COMMAND_ENDPOINT_MIN_REMAINING_SECONDS,
)
assert len(runtime.start_calls) == 1
assert control.start_projects == [PROJECT_NAME]
def test_start_stale_control_proof_fails_before_receiver_or_device_checkpoint(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control, binding, ready = _install_binding_validating_ready_control(service)
stable_path = _direct_host_path(binding.target_ipv4)
monkeypatch.setattr(service, "_sample_host_path", lambda *_args, **_kwargs: stable_path)
workspace = service.enter_application_workspace(
EnterApplicationWorkspaceRequest(
operator_confirmed=True,
expected_session_generation=ready["application_control_session"]["session_generation"],
expected_state_revision=ready["application_control_session"]["state_revision"],
)
)
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host=binding.target_ipv4,
compatibility_attestation=ATTESTATION,
expected_control_session_generation=workspace["application_control_session"][
"session_generation"
],
expected_control_state_revision=workspace["application_control_session"][
"state_revision"
],
)
)
def reject_stale_control_proof(_control: object) -> None:
raise ApplicationConnectionBindingLost("test MQTT control proof expired")
control.validate_connection_binding = MethodType( # type: ignore[method-assign]
reject_stale_control_proof,
control,
)
physical_before = service._physical_command_ledger.snapshot() # noqa: SLF001
with pytest.raises(ApplicationConnectionBindingLost):
service.start_acquisition(
_start_request(
acquisition_id=prepared["acquisition"]["acquisition_id"],
physical_acceptance=PHYSICAL_ACCEPTANCE,
expected_control_session_generation=prepared["application_control_session"][
"session_generation"
],
expected_control_state_revision=prepared["application_control_session"][
"state_revision"
],
)
)
assert prepared["acquisition"]["state"] == "prepared"
assert service._acquisition is not None # noqa: SLF001
assert service._acquisition.state == "prepared" # noqa: SLF001
assert service._physical_command_ledger.snapshot() == physical_before # noqa: SLF001
assert not any(
operation["action"] == facade_module.ACTION_ACQUISITION_START
for operation in service._operations.snapshot() # noqa: SLF001
)
assert runtime.start_calls == []
assert control.start_projects == []
def test_next_scan_retires_stale_terminal_live_perception_ingress_before_start(
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
service.live_perception_ingress.begin_session("stale-completed-session")
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
state = service.start_acquisition(
_start_request(acquisition_id=prepared["acquisition"]["acquisition_id"])
)
assert runtime.start_calls
assert state["acquisition"]["state"] == "starting"
assert state["live_perception_shadow"]["active"] is True
assert state["live_perception_shadow"]["session_id"] != "stale-completed-session"
def test_confirmed_scanning_waits_for_first_authoritative_pcl_before_camera(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control = FakeInteractiveControlSession()
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
_seed_supervised_connection(service)
service._compatibility_attestation = ATTESTATION.model_dump(mode="json") # noqa: SLF001
prepared = service.prepare_acquisition(
_prepare_request(
project_name="TEST001",
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
pre_pcl_state = service.start_acquisition(
_start_request(
acquisition_id=acquisition_id,
physical_acceptance=PHYSICAL_ACCEPTANCE,
)
)
pre_pcl_camera_streams = [
stream
for stream in pre_pcl_state["sensor_catalog"]["streams"]
if stream.get("semantic_channel_id") == "camera.preview.live"
]
assert pre_pcl_state["camera_preview"]["active_source_id"] is None
assert pre_pcl_state["camera_preview"]["delivery"] is None
assert pre_pcl_state["camera_preview"]["activation_admission"]["state"] == (
"waiting-for-first-authoritative-pcl"
)
assert all(stream["activation"]["selected"] is False for stream in pre_pcl_camera_streams)
assert all(stream["activation"]["controllable"] is False for stream in pre_pcl_camera_streams)
out_dir = service._acquisition_out_dir # noqa: SLF001
assert out_dir is not None
out_dir.mkdir(parents=True)
events: list[tuple[str, object]] = []
activation_entered = threading.Event()
release_activation = threading.Event()
camera_state: dict[str, object] = {
"phase": "idle",
"active_source_id": None,
"recording": {"active": False},
}
def activate_recording(
source_id: str,
target: str,
session_dir: Path,
*,
commit_fence: Callable[[Callable[[], bool]], bool],
committed_before_start: Callable[[dict[str, object]], None] | None = None,
) -> dict[str, object]:
events.append(("select", (source_id, target)))
camera_state["active_source_id"] = source_id
events.append(("record", session_dir))
camera_state["recording"] = {
"active": True,
"session": session_dir.name,
"active_epoch": 1,
"producer_alive": True,
"last_segment_age_ms": 0,
"last_media_segment_age_ms": 0,
"media_ready": True,
"current_epoch": {
"generation": 1,
"init_committed": True,
"init_committed_age_ms": 0,
"first_media_committed": True,
"first_media_committed_age_ms": 0,
"committed_media_segment_count": 1,
"last_media_segment_age_ms": 0,
},
}
camera_state["phase"] = "streaming"
committed = dict(camera_state)
assert committed_before_start is not None
assert commit_fence(
lambda: committed_before_start(committed) is None
) is True
return committed
actual_camera_snapshot = service.camera_preview.snapshot()
def snapshot_camera() -> dict[str, object]:
return {
**actual_camera_snapshot,
**camera_state,
"recording": {
**actual_camera_snapshot["recording"],
**camera_state["recording"], # type: ignore[arg-type]
},
}
monkeypatch.setattr(service.camera_preview, "snapshot", snapshot_camera)
monkeypatch.setattr(
service.camera_preview,
"activate_recording_producer",
activate_recording,
)
real_activate = service._activate_default_acquisition_camera # noqa: SLF001
def gated_activate(**kwargs: object) -> bool:
activation_entered.set()
assert release_activation.wait(timeout=2.0)
return real_activate(**kwargs) # type: ignore[arg-type]
monkeypatch.setattr(service, "_activate_default_acquisition_camera", gated_activate)
runtime.mark_ready()
assert control.state == "scanning"
assert camera_state["active_source_id"] is None
assert events == []
with service._lock: # noqa: SLF001
start_operation_id = service._acquisition_start_operation_id # noqa: SLF001
assert start_operation_id is not None
binding = _seed_supervised_connection(service)
physical = _exact_start_physical_proof(
operation_id=start_operation_id,
acquisition_id=acquisition_id,
binding=binding,
resolved=True,
)
physical_snapshot_calls = 0
def snapshot_physical() -> dict[str, object]:
nonlocal physical_snapshot_calls
physical_snapshot_calls += 1
return physical
monkeypatch.setattr(
service._physical_command_coordinator, # noqa: SLF001
"snapshot",
snapshot_physical,
)
runtime.pcl_frames = 1
frame = DecodedPointCloudView(
context=ConsumerFrameContext(
sequence=1,
captured_at_epoch_ns=1,
received_monotonic_ns=1,
processing_started_monotonic_ns=1,
encoded_size_bytes=16,
live=True,
),
frame_id="map",
positions_xyz=((0.0, 0.0, 0.0),),
)
service._observe_published_runtime_envelope( # noqa: SLF001
frame,
runtime.producer_generation,
)
# The first PCL admits only the one automatic right-camera activation.
# Public manual controls stay closed until that worker proves an exact
# recording epoch, preventing a left/right selection race.
assert activation_entered.wait(timeout=2.0)
activating_state = service.state()
activating_camera_streams = [
stream
for stream in activating_state["sensor_catalog"]["streams"]
if stream.get("semantic_channel_id") == "camera.preview.live"
]
assert activating_state["camera_preview"]["activation_admission"]["state"] == "activating"
assert all(
stream["activation"]["controllable"] is False
for stream in activating_camera_streams
)
with pytest.raises(RuntimeError, match="автоматического запуска правой камеры"):
service.select_camera_preview(
CameraPreviewSelectRequest(
device_session_id=service._device_session_id, # type: ignore[arg-type] # noqa: SLF001
source_id="sensor.camera.left",
)
)
assert events == []
release_activation.set()
deadline = time.monotonic() + 2.0
while len(events) < 2 and time.monotonic() < deadline:
time.sleep(0.01)
assert events == [
("select", ("sensor.camera.right", "192.168.1.20")),
("record", out_dir),
]
assert camera_state["active_source_id"] == "sensor.camera.right"
assert camera_state["recording"] == {
"active": True,
"session": out_dir.name,
"active_epoch": 1,
"producer_alive": True,
"last_segment_age_ms": 0,
"last_media_segment_age_ms": 0,
"media_ready": True,
"current_epoch": {
"generation": 1,
"init_committed": True,
"init_committed_age_ms": 0,
"first_media_committed": True,
"first_media_committed_age_ms": 0,
"committed_media_segment_count": 1,
"last_media_segment_age_ms": 0,
},
}
assert runtime.source_mode == "live"
assert control.start_projects == ["TEST001"]
assert control.stop_calls == 0
admitted_state = service.state()
admitted_camera_streams = [
stream
for stream in admitted_state["sensor_catalog"]["streams"]
if stream.get("semantic_channel_id") == "camera.preview.live"
]
assert admitted_state["camera_preview"]["activation_admission"]["state"] == "admitted"
assert any(
stream["source_id"] == "sensor.camera.right"
and stream["activation"]["selected"] is True
and stream["activation"]["controllable"] is True
for stream in admitted_camera_streams
)
# Every later authoritative PCL for the same lineage is idempotent.
physical_snapshot_calls_before = physical_snapshot_calls
service._observe_published_runtime_envelope(frame, runtime.producer_generation) # noqa: SLF001
time.sleep(0.05)
assert len(events) == 2
assert physical_snapshot_calls == physical_snapshot_calls_before
def test_stale_post_publish_pcl_cannot_activate_camera(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control = FakeInteractiveControlSession()
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
binding = _seed_supervised_connection(service)
service._compatibility_attestation = ATTESTATION.model_dump(mode="json") # noqa: SLF001
prepared = service.prepare_acquisition(
_prepare_request(
project_name="STALEPCL001",
host=binding.target_ipv4,
compatibility_attestation=ATTESTATION,
)
)
service.start_acquisition(
_start_request(
acquisition_id=prepared["acquisition"]["acquisition_id"],
physical_acceptance=PHYSICAL_ACCEPTANCE,
)
)
runtime.mark_ready()
runtime.pcl_frames = 1
selected: list[object] = []
monkeypatch.setattr(
service.camera_preview,
"select",
lambda *_args, **_kwargs: selected.append(object()),
)
frame = DecodedPointCloudView(
context=ConsumerFrameContext(
sequence=1,
captured_at_epoch_ns=1,
received_monotonic_ns=1,
processing_started_monotonic_ns=1,
encoded_size_bytes=16,
live=True,
),
frame_id="map",
positions_xyz=((0.0, 0.0, 0.0),),
)
service._observe_published_runtime_envelope( # noqa: SLF001
frame,
runtime.producer_generation - 1,
)
with service._lock: # noqa: SLF001
service._acquisition.transition("interrupted", message_code="test.stale") # type: ignore[union-attr] # noqa: SLF001
service._observe_published_runtime_envelope(frame, runtime.producer_generation) # noqa: SLF001
time.sleep(0.05)
assert selected == []
assert service.camera_preview.snapshot()["active_source_id"] is None
def test_failed_post_pcl_camera_activation_retries_on_later_authoritative_frame(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control = FakeInteractiveControlSession()
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
binding = _seed_supervised_connection(service)
service._compatibility_attestation = ATTESTATION.model_dump(mode="json") # noqa: SLF001
prepared = service.prepare_acquisition(
_prepare_request(
project_name="RETRYPCL001",
host=binding.target_ipv4,
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
service.start_acquisition(
_start_request(
acquisition_id=acquisition_id,
physical_acceptance=PHYSICAL_ACCEPTANCE,
)
)
runtime.mark_ready()
runtime.pcl_frames = 1
with service._lock: # noqa: SLF001
start_operation_id = service._acquisition_start_operation_id # noqa: SLF001
out_dir = service._acquisition_out_dir # noqa: SLF001
assert start_operation_id is not None
assert out_dir is not None
physical = _exact_start_physical_proof(
operation_id=start_operation_id,
acquisition_id=acquisition_id,
binding=_seed_supervised_connection(service),
resolved=True,
)
monkeypatch.setattr(service._physical_command_coordinator, "snapshot", lambda: physical) # noqa: SLF001
out_dir.mkdir(parents=True)
actual_camera = service.camera_preview.snapshot()
camera_state: dict[str, object] = {
**actual_camera,
"phase": "idle",
"generation": None,
"active_source_id": None,
"recording": {
**actual_camera["recording"],
"active": False,
"session": None,
"active_epoch": None,
"producer_alive": False,
},
"error": None,
}
select_calls: list[tuple[str, str]] = []
recording_calls: list[Path] = []
retry_calls: list[tuple[str, str, int, str]] = []
def snapshot_camera() -> dict[str, object]:
return {
**camera_state,
"recording": dict(camera_state["recording"]), # type: ignore[arg-type]
}
def fail_first_activation(
source_id: str,
target: str,
session_dir: Path,
*,
commit_fence: Callable[[Callable[[], bool]], bool],
committed_before_start: Callable[[dict[str, object]], None] | None = None,
) -> dict[str, object]:
del commit_fence, committed_before_start
select_calls.append((source_id, target))
recording_calls.append(session_dir)
camera_state.update(
{
"phase": "error",
"error": {
"code": "ffmpeg-start-failed",
"message": "synthetic first local spawn failure",
},
"generation": 1,
"active_source_id": source_id,
"recording": {
**camera_state["recording"], # type: ignore[arg-type]
"active": True,
"session": session_dir.name,
"active_epoch": None,
"producer_alive": False,
},
}
)
raise RuntimeError("synthetic first local spawn failure")
def retry_recording(
source_id: str,
target: str,
*,
expected_generation: int,
expected_recording_session: str,
pre_retry_fence: Callable[[Callable[[], bool]], bool],
commit_fence: Callable[[Callable[[], bool]], bool] | None = None,
committed_before_start: Callable[[dict[str, object]], None] | None = None,
) -> dict[str, object]:
retry_calls.append(
(source_id, target, expected_generation, expected_recording_session)
)
assert camera_state["phase"] == "error"
assert camera_state["generation"] == expected_generation
assert pre_retry_fence(lambda: True) is True
recording = camera_state["recording"]
assert isinstance(recording, dict)
assert recording["session"] == expected_recording_session
camera_state.update(
{
"phase": "connecting",
"generation": expected_generation + 1,
"error": None,
"recording": {
**recording,
"active_epoch": expected_generation + 1,
"producer_alive": True,
"last_segment_age_ms": None,
"last_media_segment_age_ms": None,
"media_ready": False,
"current_epoch": {
"generation": expected_generation + 1,
"init_committed": False,
"init_committed_age_ms": None,
"first_media_committed": False,
"first_media_committed_age_ms": None,
"committed_media_segment_count": 0,
"last_media_segment_age_ms": None,
},
},
}
)
committed = snapshot_camera()
assert commit_fence is not None
assert committed_before_start is not None
assert commit_fence(
lambda: committed_before_start(committed) is None
) is True
return committed
monkeypatch.setattr(service.camera_preview, "snapshot", snapshot_camera)
monkeypatch.setattr(
service.camera_preview,
"activate_recording_producer",
fail_first_activation,
)
monkeypatch.setattr(
service.camera_preview,
"retry_recording_producer",
retry_recording,
)
frame = DecodedPointCloudView(
context=ConsumerFrameContext(
sequence=1,
captured_at_epoch_ns=1,
received_monotonic_ns=1,
processing_started_monotonic_ns=1,
encoded_size_bytes=16,
live=True,
),
frame_id="map",
positions_xyz=((0.0, 0.0, 0.0),),
)
service._observe_published_runtime_envelope(frame, runtime.producer_generation) # noqa: SLF001
deadline = time.monotonic() + 2.0
while len(recording_calls) < 1 and time.monotonic() < deadline:
time.sleep(0.01)
assert recording_calls == [out_dir]
assert select_calls == [("sensor.camera.right", binding.target_ipv4)]
# Normal UI polling between attempts must preserve PCL/Rerun and the
# scanner-owned session while this exact startup error is retryable.
provisional = service.state()
assert provisional["acquisition"]["state"] in {
"starting",
"awaiting_external_start",
"acquiring",
}
assert provisional["camera_preview"]["activation_admission"]["state"] == "activating"
assert runtime.source_mode == "live"
assert runtime.stop_calls == 0
assert control.stop_calls == 0
# Frames inside the bounded retry window cannot create a worker storm.
service._observe_published_runtime_envelope(frame, runtime.producer_generation) # noqa: SLF001
time.sleep(0.05)
assert retry_calls == []
with service._lock: # noqa: SLF001
service._camera_activation_retry_not_before_monotonic = 0.0 # noqa: SLF001
service._observe_published_runtime_envelope(frame, runtime.producer_generation) # noqa: SLF001
deadline = time.monotonic() + 2.0
while len(retry_calls) < 1 and time.monotonic() < deadline:
time.sleep(0.01)
assert retry_calls == [
(
"sensor.camera.right",
binding.target_ipv4,
1,
out_dir.name,
)
]
assert camera_state["generation"] == 2
recording = camera_state["recording"]
assert isinstance(recording, dict)
assert recording["active_epoch"] == 2
assert recording["producer_alive"] is True
with service._lock: # noqa: SLF001
assert service._camera_activation_lineage == ( # noqa: SLF001
acquisition_id,
out_dir.name,
runtime.producer_generation,
)
assert control.start_projects == ["RETRYPCL001"]
assert control.stop_calls == 0
admitted = service.state()
assert admitted["acquisition"]["state"] == "acquiring"
assert admitted["camera_preview"]["activation_admission"]["state"] == "activating"
assert admitted["camera_preview"]["recording"]["media_ready"] is False
assert admitted["connection_policy"]["actions"]["stop-acquisition"]["allowed"] is True
# The same shaped error without the exact retry claim stays terminal; the
# classifier never masks storage/archive failures or an unrelated lineage.
with service._lock: # noqa: SLF001
service._camera_activation_lineage = None # noqa: SLF001
service._camera_activation_retry_lineage = None # noqa: SLF001
monkeypatch.setattr(service, "_seal_acquisition_capture_clock", lambda: None)
camera_state.update(
{
"phase": "error",
"error": {
"code": "camera-storage-failed",
"message": "synthetic durable archive failure",
},
"recording": {
**recording,
"active_epoch": None,
"producer_alive": False,
},
}
)
terminal = service.state()
assert terminal["acquisition"]["state"] == "failed"
assert terminal["acquisition"]["result"]["camera_failure_code"] == (
"camera-storage-failed"
)
def _install_composite_active_recovery_fixture(
service: XgridsK1CompatibilityService,
runtime: FakeVisualizationRuntime,
monkeypatch: pytest.MonkeyPatch,
*,
runtime_phase: str = "reconnecting",
camera_phase: str = "error",
) -> tuple[FakeInteractiveControlSession, dict[str, object]]:
control = FakeInteractiveControlSession()
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
binding = _seed_supervised_connection(service)
prepared = service.prepare_acquisition(
_prepare_request(
project_name="RECOVERY001",
host=binding.target_ipv4,
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = str(prepared["acquisition"]["acquisition_id"])
service.start_acquisition(
_start_request(
acquisition_id=acquisition_id,
physical_acceptance=PHYSICAL_ACCEPTANCE,
)
)
with service._lock: # noqa: SLF001
acquisition = service._acquisition # noqa: SLF001
start_operation_id = service._acquisition_start_operation_id # noqa: SLF001
out_dir = service._acquisition_out_dir # noqa: SLF001
assert acquisition is not None
assert start_operation_id is not None
assert out_dir is not None
acquisition.transition("acquiring", message_code="acquisition.acquiring")
out_dir.mkdir(parents=True, exist_ok=True)
runtime.phase = runtime_phase
runtime.source_mode = "live"
runtime.source_ready = runtime_phase == "live"
runtime.recovery_state = (
"reconnecting" if runtime_phase == "reconnecting" else "inactive"
)
runtime.recovery_request_pending = runtime_phase == "reconnecting"
runtime.pcl_frames = 4
physical: dict[str, object] = {
"status": "resolved",
"reason_code": None,
"requires_reconciliation": False,
"resolved_active_recovery_required": True,
"automatic_replay_allowed": False,
"normal_session_recovery_supported": False,
"recovery_requirement": ("explicit-read-only-deviceinfo-and-non-retained-devicestatus"),
"runtime_bound": True,
"reconciliation_ready": False,
"observed_session_state": None,
"active_operation_id": None,
"record": {
"revision": 7,
"operation_id": start_operation_id,
"acquisition_id": acquisition_id,
"action": "start",
"stage": "resolved",
"resolution": "start-active-observed",
"publish_call_returned": True,
"qos2_completed": True,
"packet_id": 41,
"application_response": {
"operation_id": start_operation_id,
"action": "start",
"success": True,
},
"last_status": {
"session_state": "scanning",
"project_bound": True,
"init_ready": True,
"mqtt_retained": False,
},
"connection": {
"intent_id": binding.intent_id,
"transport_ref": binding.transport_ref,
"connection_mode": binding.connection_mode,
"target_ipv4": binding.target_ipv4,
"target_port": binding.target_port,
},
"reconciliations": [],
},
}
monkeypatch.setattr(
service._physical_command_coordinator, # noqa: SLF001
"snapshot",
lambda: physical,
)
# START operation ownership is released after the normal application
# operation settles. The broad mapping-only fixture has no real durable
# checkpoint, so preserve its immutable original START through the same
# helper seam used by production checkpoint integration.
service._active_acquisition_checkpoint_start_operation_id = MethodType( # type: ignore[method-assign] # noqa: SLF001
lambda _service, **_kwargs: start_operation_id,
service,
)
camera = service.camera_preview.snapshot()
camera.update(
{
"phase": camera_phase,
"active_source_id": facade_module.DEFAULT_ACQUISITION_CAMERA_SOURCE,
"recording": {
"active": True,
"session": out_dir.name,
"active_epoch": 1 if camera_phase == "streaming" else None,
"producer_alive": camera_phase == "streaming",
"producer_age_ms": 1_000,
"last_segment_age_ms": 0 if camera_phase == "streaming" else None,
"completed_epochs": 0 if camera_phase == "streaming" else 1,
"last_summary": None,
"source_end_expected": False,
},
"error": (
{
"code": "camera-source-ended",
"message": "synthetic Wi-Fi loss",
}
if camera_phase == "error"
else None
),
}
)
monkeypatch.setattr(service.camera_preview, "snapshot", lambda: camera)
return control, physical
def test_camera_first_short_outage_is_observational_without_browser_side_effects(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control, physical = _install_composite_active_recovery_fixture(
service,
runtime,
monkeypatch,
runtime_phase="live",
camera_phase="error",
)
start_projects_before = list(control.start_projects)
stop_calls_before = control.stop_calls
state = service.state()
recovery = state["connection_recovery"]
assert runtime.recovery_requests == []
assert runtime.recovery_request_pending is False
assert state["source_mode"] == "live"
assert recovery["state"] == "inactive"
assert recovery["automatic_read_only_rebind"] is False
assert state["acquisition"]["state"] == "acquiring"
assert state["selected_device_id"] == "test-ble-transport"
assert state["k1_ip"] == "192.168.1.20"
assert runtime.stop_calls == 0
assert control.start_projects == start_projects_before
assert control.stop_calls == stop_calls_before
assert service._physical_command_coordinator.snapshot() is physical # noqa: SLF001
def test_camera_stall_snapshot_does_not_reconnect_live_mqtt_runtime(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control, physical = _install_composite_active_recovery_fixture(
service,
runtime,
monkeypatch,
runtime_phase="live",
camera_phase="streaming",
)
camera = service.camera_preview.snapshot()
recording = camera["recording"]
assert isinstance(recording, dict)
recording["last_segment_age_ms"] = (
facade_module.ACTIVE_STREAM_CAMERA_STALL_MILLISECONDS
)
state = service.state()
assert runtime.recovery_requests == []
assert runtime.recovery_request_pending is False
assert state["source_mode"] == "live"
assert state["acquisition"]["state"] == "acquiring"
assert runtime.stop_calls == 0
assert control.stop_calls == 0
assert service._physical_command_coordinator.snapshot() is physical # noqa: SLF001
def test_backend_camera_watchdog_cas_restarts_only_camera_without_device_commands(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control, physical = _install_composite_active_recovery_fixture(
service,
runtime,
monkeypatch,
runtime_phase="live",
camera_phase="streaming",
)
camera = service.camera_preview.snapshot()
camera["generation"] = 1
recording = camera["recording"]
assert isinstance(recording, dict)
recording.update(
{
"producer_age_ms": facade_module.ACTIVE_STREAM_CAMERA_STALL_MILLISECONDS + 1,
"last_segment_age_ms": facade_module.ACTIVE_STREAM_CAMERA_STALL_MILLISECONDS + 1,
"last_media_segment_age_ms": (
facade_module.ACTIVE_STREAM_CAMERA_STALL_MILLISECONDS + 1
),
"committed_media_segment_count": 10,
"media_ready": True,
"current_epoch": {
"generation": 1,
"init_committed": True,
"init_committed_age_ms": 20_000,
"first_media_committed": True,
"first_media_committed_age_ms": 20_000,
"committed_media_segment_count": 10,
"last_media_segment_age_ms": (
facade_module.ACTIVE_STREAM_CAMERA_STALL_MILLISECONDS + 1
),
},
}
)
restart_calls: list[tuple[str, str, int, str, int | None, int]] = []
def restart(
source_id: str,
target: str,
*,
expected_generation: int,
expected_recording_session: str,
expected_active_epoch: int | None,
expected_recording_media_segment_count: int,
pre_detach_fence: Callable[[Callable[[], bool]], bool],
commit_fence: Callable[[Callable[[], bool]], bool] | None = None,
committed_before_start: Callable[[dict[str, object]], None] | None = None,
) -> dict[str, object]:
restart_calls.append(
(
source_id,
target,
expected_generation,
expected_recording_session,
expected_active_epoch,
expected_recording_media_segment_count,
)
)
assert pre_detach_fence(lambda: True) is True
camera.update(
{
"phase": "connecting",
"generation": 2,
"error": None,
"recording": {
**recording,
"active_epoch": 2,
"producer_alive": True,
"producer_age_ms": 0,
"last_segment_age_ms": None,
"last_media_segment_age_ms": None,
"media_ready": False,
"current_epoch": {
"generation": 2,
"init_committed": False,
"init_committed_age_ms": None,
"first_media_committed": False,
"first_media_committed_age_ms": None,
"committed_media_segment_count": 0,
"last_media_segment_age_ms": None,
},
},
}
)
assert commit_fence is not None
assert committed_before_start is not None
assert commit_fence(
lambda: committed_before_start(dict(camera)) is None
) is True
return dict(camera)
monkeypatch.setattr(service.camera_preview, "restart_recording_producer", restart)
start_projects_before = list(control.start_projects)
stop_calls_before = control.stop_calls
service._observe_camera_producer_stall("camera-stream-stalled", 1) # noqa: SLF001
service._observe_camera_producer_stall("camera-stream-stalled", 1) # noqa: SLF001
assert restart_calls == [
(
facade_module.DEFAULT_ACQUISITION_CAMERA_SOURCE,
"192.168.1.20",
1,
recording["session"],
1,
10,
)
]
assert runtime.phase == "live"
assert runtime.recovery_requests == []
assert control.start_projects == start_projects_before
assert control.stop_calls == stop_calls_before
assert service._physical_command_coordinator.snapshot() is physical # noqa: SLF001
assert camera["recording"]["media_ready"] is False
projected = service.state()
assert projected["connection_recovery"]["state"] == "inactive"
assert projected["connection_recovery"]["camera_recovery"] == "owned"
assert projected["connection_recovery"]["camera_media_state"] == "pending-init"
assert projected["connection_recovery"]["camera_media_ready"] is False
assert projected["connection_recovery"]["camera_epoch"]["generation"] == 2
assert projected["connection_policy"]["actions"]["stop-acquisition"]["allowed"] is True
def test_stop_priority_overtakes_blocked_camera_watchdog_candidate(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control, _physical = _install_composite_active_recovery_fixture(
service,
runtime,
monkeypatch,
runtime_phase="live",
camera_phase="streaming",
)
camera = service.camera_preview.snapshot()
camera["generation"] = 1
recording = camera["recording"]
assert isinstance(recording, dict)
recording.update(
{
"producer_age_ms": facade_module.ACTIVE_STREAM_CAMERA_STALL_MILLISECONDS + 1,
"last_segment_age_ms": facade_module.ACTIVE_STREAM_CAMERA_STALL_MILLISECONDS + 1,
"last_media_segment_age_ms": (
facade_module.ACTIVE_STREAM_CAMERA_STALL_MILLISECONDS + 1
),
"committed_media_segment_count": 10,
"media_ready": True,
"current_epoch": {
"generation": 1,
"init_committed": True,
"init_committed_age_ms": 20_000,
"first_media_committed": True,
"first_media_committed_age_ms": 20_000,
"committed_media_segment_count": 10,
"last_media_segment_age_ms": 20_000,
},
}
)
candidate_blocked = threading.Event()
release_candidate = threading.Event()
candidate_committed: list[bool] = []
def restart(
_source_id: str,
_target: str,
*,
expected_generation: int,
expected_recording_session: str,
expected_active_epoch: int | None,
expected_recording_media_segment_count: int,
pre_detach_fence: Callable[[Callable[[], bool]], bool],
commit_fence: Callable[[Callable[[], bool]], bool] | None = None,
committed_before_start: Callable[[dict[str, object]], None] | None = None,
) -> dict[str, object]:
del (
expected_generation,
expected_recording_session,
expected_active_epoch,
expected_recording_media_segment_count,
)
assert commit_fence is not None
del committed_before_start
candidate_blocked.set()
assert release_candidate.wait(3.0)
committed = commit_fence(lambda: candidate_committed.append(True) or True)
if not committed:
raise ValueError("camera recovery lineage устарела")
return dict(camera)
monkeypatch.setattr(service.camera_preview, "restart_recording_producer", restart)
stop_owned_entered = threading.Event()
def stop_owned(
_request: StopAcquisitionRequest,
_preadmitted_stop: object | None = None,
) -> dict[str, object]:
stop_owned_entered.set()
control.request_stop(
confirmation=object(),
command_context=object(),
dispatch_admission_deadline_reached=lambda: False,
expected_session_generation=control.session_generation,
expected_state_revision=control.state_revision,
)
with service._lock: # noqa: SLF001
acquisition = service._acquisition # noqa: SLF001
assert acquisition is not None
acquisition.transition(
"awaiting_external_stop",
message_code="acquisition.stop.device_stopping",
)
service._acquisition_stop_operation_id = "priority-stop" # noqa: SLF001
return {"stop": "prepared"}
monkeypatch.setattr(service, "_stop_acquisition_owned", stop_owned)
observer = threading.Thread(
target=service._observe_camera_producer_stall, # noqa: SLF001
args=("camera-stream-stalled", 1),
daemon=True,
)
observer.start()
assert candidate_blocked.wait(3.0)
request = _stop_request(
acquisition_id=None,
mode="graceful",
physical_acceptance=PHYSICAL_ACCEPTANCE,
)
stop_result: list[dict[str, object]] = []
stop_worker = threading.Thread(
target=lambda: stop_result.append(service.stop_acquisition(request)),
daemon=True,
)
stop_worker.start()
assert stop_owned_entered.wait(3.0)
stop_worker.join(3.0)
assert stop_worker.is_alive() is False
assert stop_result == [{"stop": "prepared"}]
assert control.stop_calls == 1
assert candidate_committed == []
release_candidate.set()
observer.join(3.0)
assert observer.is_alive() is False
assert candidate_committed == []
def test_stop_priority_overtakes_blocked_physical_snapshot_before_camera_commit(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
_control, physical = _install_composite_active_recovery_fixture(
service,
runtime,
monkeypatch,
runtime_phase="live",
camera_phase="streaming",
)
with service._lock: # noqa: SLF001
acquisition = service._acquisition # noqa: SLF001
out_dir = service._acquisition_out_dir # noqa: SLF001
start_operation_id = service._acquisition_start_operation_id # noqa: SLF001
assert acquisition is not None
assert out_dir is not None
assert start_operation_id is not None
snapshot_blocked = threading.Event()
release_snapshot = threading.Event()
def blocking_snapshot() -> dict[str, object]:
if threading.current_thread().name == "camera-commit-candidate":
snapshot_blocked.set()
assert release_snapshot.wait(3.0)
return physical
monkeypatch.setattr(
service._physical_command_coordinator, # noqa: SLF001
"snapshot",
blocking_snapshot,
)
camera_commit_calls: list[str] = []
camera_commit_results: list[bool] = []
camera_commit_worker = threading.Thread(
name="camera-commit-candidate",
target=lambda: camera_commit_results.append(
service._commit_camera_restart_if_still_active( # noqa: SLF001
acquisition_id=acquisition.acquisition_id,
evidence_session_id=out_dir.name,
start_operation_id=start_operation_id,
runtime_producer_generation=runtime.producer_generation,
commit=lambda: camera_commit_calls.append("commit") or True,
)
),
daemon=True,
)
camera_commit_worker.start()
assert snapshot_blocked.wait(3.0)
stop_owned_entered = threading.Event()
def stop_owned(
_request: StopAcquisitionRequest,
_preadmitted_stop: object | None = None,
) -> dict[str, object]:
assert service._camera_stop_priority_counts == { # noqa: SLF001
acquisition.acquisition_id: 1
}
stop_owned_entered.set()
with service._lock: # noqa: SLF001
acquisition.transition(
"awaiting_external_stop",
message_code="acquisition.stop.device_stopping",
)
service._acquisition_stop_operation_id = "snapshot-priority-stop" # noqa: SLF001
return {"stop": "prepared"}
monkeypatch.setattr(service, "_stop_acquisition_owned", stop_owned)
stop_result: list[dict[str, object]] = []
stop_worker = threading.Thread(
target=lambda: stop_result.append(
service.stop_acquisition(
_stop_request(
acquisition_id=None,
mode="graceful",
operator_confirmed=True,
physical_acceptance=PHYSICAL_ACCEPTANCE,
)
)
),
daemon=True,
)
stop_worker.start()
assert stop_owned_entered.wait(3.0)
stop_worker.join(3.0)
assert stop_worker.is_alive() is False
assert stop_result == [{"stop": "prepared"}]
release_snapshot.set()
camera_commit_worker.join(3.0)
assert camera_commit_worker.is_alive() is False
assert camera_commit_results == [False]
assert camera_commit_calls == []
def test_stop_priority_overtakes_blocked_initial_camera_popen(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(service, runtime)
with service._lock: # noqa: SLF001
acquisition = service._acquisition # noqa: SLF001
out_dir = service._acquisition_out_dir # noqa: SLF001
assert acquisition is not None
assert out_dir is not None
camera = service.camera_preview.snapshot()
camera.update(
{
"phase": "idle",
"generation": None,
"active_source_id": None,
"recording": {"active": False},
"error": None,
}
)
candidate_blocked = threading.Event()
release_candidate = threading.Event()
candidate_committed: list[bool] = []
def blocked_initial_popen(
_source_id: str,
_target: str,
_session_dir: Path,
*,
commit_fence: Callable[[Callable[[], bool]], bool],
committed_before_start: Callable[[dict[str, object]], None] | None = None,
) -> dict[str, object]:
del committed_before_start
candidate_blocked.set()
assert release_candidate.wait(3.0)
if not commit_fence(lambda: candidate_committed.append(True) or True):
raise ValueError("camera activation lineage устарела")
return dict(camera)
monkeypatch.setattr(
service.camera_preview,
"activate_recording_producer",
blocked_initial_popen,
)
monkeypatch.setattr(service, "_ensure_camera_preview_process_lease", lambda: False)
activation_result: list[bool] = []
activation_errors: list[BaseException] = []
def activate() -> None:
try:
activation_result.append(
service._activate_default_acquisition_camera( # noqa: SLF001
expected_acquisition_id=acquisition.acquisition_id,
expected_evidence_session_id=out_dir.name,
expected_runtime_generation=runtime.producer_generation,
)
)
except BaseException as exc:
activation_errors.append(exc)
activation = threading.Thread(
target=activate,
daemon=True,
)
activation.start()
assert candidate_blocked.wait(3.0)
stop_result: list[dict[str, object]] = []
stop_worker = threading.Thread(
target=lambda: stop_result.append(
service.stop_acquisition(
fixture.request.model_copy(update={"acquisition_id": None})
)
),
daemon=True,
)
stop_worker.start()
stop_worker.join(3.0)
assert stop_worker.is_alive() is False
assert len(stop_result) == 1
assert stop_result[0]["acquisition"]["state"] == "awaiting_external_stop"
assert fixture.control.stop_calls == 1
assert fixture.prepare_calls == [fixture.stop_operation_id]
prepared_record = fixture.ledger.snapshot().record
assert prepared_record is not None
assert prepared_record.operation_id == fixture.stop_operation_id
assert prepared_record.stage == "prepared"
release_candidate.set()
activation.join(3.0)
assert activation.is_alive() is False
assert activation_result == []
assert len(activation_errors) == 1
assert isinstance(activation_errors[0], ValueError)
assert candidate_committed == []
def test_nontransport_camera_failure_remains_terminal_without_recovery_wake(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control, physical = _install_composite_active_recovery_fixture(
service,
runtime,
monkeypatch,
runtime_phase="live",
camera_phase="streaming",
)
camera = service.camera_preview.snapshot()
camera["phase"] = "error"
camera["error"] = {
"code": "camera-artifact-write-failed",
"message": "synthetic local storage failure",
}
monkeypatch.setattr(service, "_seal_acquisition_capture_clock", lambda: None)
state = service.state()
assert runtime.recovery_requests == []
assert runtime.recovery_request_pending is False
assert state["acquisition"]["state"] == "failed"
assert state["acquisition"]["result"]["camera_failure_code"] == (
"camera-artifact-write-failed"
)
assert runtime.stop_calls == 1
assert control.stop_calls == 0
assert service._physical_command_coordinator.snapshot() is physical # noqa: SLF001
def test_host_first_recovery_does_not_mask_later_camera_artifact_failure(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control, physical = _install_composite_active_recovery_fixture(
service,
runtime,
monkeypatch,
runtime_phase="live",
camera_phase="streaming",
)
monkeypatch.setattr(service, "_seal_acquisition_capture_clock", lambda: None)
lost_path = HostPathProbeResult(
available=False,
fingerprint=None,
interface=None,
source_ipv4=None,
route_class="unavailable",
reason_code="host-route-unavailable",
)
start_projects_before = list(control.start_projects)
stop_calls_before = control.stop_calls
for _ in range(3):
service._connection_supervisor.observe_host_path(lost_path) # noqa: SLF001
reconnecting = service.state()
assert reconnecting["phase"] == "reconnecting"
assert runtime.recovery_request_pending is True
camera = service.camera_preview.snapshot()
camera["phase"] = "error"
camera["error"] = {
"code": "camera-artifact-write-failed",
"message": "synthetic local artifact failure after host loss",
}
failed = service.state()
assert failed["acquisition"]["state"] == "failed"
assert failed["acquisition"]["result"]["camera_failure_code"] == (
"camera-artifact-write-failed"
)
assert failed["source_mode"] == "idle"
assert runtime.stop_calls == 1
assert runtime.recovery_request_pending is False
assert control.start_projects == start_projects_before
assert control.stop_calls == stop_calls_before
assert service._physical_command_coordinator.snapshot() is physical # noqa: SLF001
def test_control_first_loss_freezes_topology_before_ephemeral_retirement(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control, physical = _install_composite_active_recovery_fixture(
service,
runtime,
monkeypatch,
runtime_phase="live",
camera_phase="streaming",
)
control.state = "failed"
control.failure = {
"reason_code": "mqtt_network_loop_failed",
"modeling_command_attempted": True,
"safe_to_retry": False,
}
start_projects_before = list(control.start_projects)
stop_calls_before = control.stop_calls
state = service.state()
assert runtime.recovery_requests == [
("mqtt_network_loop_failed", runtime.producer_generation),
]
assert state["phase"] == "reconnecting"
assert state["connection_recovery"]["automatic_read_only_rebind"] is True
assert state["acquisition"]["state"] == "acquiring"
assert state["selected_device_id"] == "test-ble-transport"
assert state["device_session"] is not None
assert state["k1_ip"] == "192.168.1.20"
assert runtime.stop_calls == 0
assert control.start_projects == start_projects_before
assert control.stop_calls == stop_calls_before
assert service._physical_command_coordinator.snapshot() is physical # noqa: SLF001
def test_incident_host_route_streak_wakes_recovery_before_binding_retirement(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control, _physical = _install_composite_active_recovery_fixture(
service,
runtime,
monkeypatch,
runtime_phase="live",
camera_phase="streaming",
)
lost_path = HostPathProbeResult(
available=False,
fingerprint=None,
interface=None,
source_ipv4=None,
route_class="unavailable",
reason_code="host-route-unavailable",
)
states: list[dict[str, Any]] = []
for _ in range(3):
service._connection_supervisor.observe_host_path(lost_path) # noqa: SLF001
states.append(service.state())
assert runtime.recovery_requests == [
("host-route-unavailable", runtime.producer_generation),
]
assert all(state["selected_device_id"] == "test-ble-transport" for state in states)
assert states[-1]["phase"] == "reconnecting"
assert states[-1]["connection_recovery"]["automatic_read_only_rebind"] is True
assert states[-1]["acquisition"]["state"] == "acquiring"
assert control.state == "scanning"
assert runtime.stop_calls == 0
@pytest.mark.parametrize("first_symptom", ["camera", "control"])
def test_host_camera_and_late_mqtt_loss_share_one_recovery_owner(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
first_symptom: str,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control, _physical = _install_composite_active_recovery_fixture(
service,
runtime,
monkeypatch,
runtime_phase="live",
camera_phase="error" if first_symptom == "camera" else "streaming",
)
if first_symptom == "camera":
first = service.state()
assert first["connection_recovery"]["state"] == "inactive"
assert runtime.recovery_requests == []
control.state = "failed"
control.failure = {
"reason_code": "mqtt_network_loop_failed",
"modeling_command_attempted": True,
"safe_to_retry": False,
}
else:
control.state = "failed"
control.failure = {
"reason_code": "mqtt_network_loop_failed",
"modeling_command_attempted": True,
"safe_to_retry": False,
}
first = service.state()
camera = service.camera_preview.snapshot()
camera["phase"] = "error"
camera["error"] = {
"code": "camera-source-ended",
"message": "synthetic later camera loss",
}
second = service.state()
generation = second["connection_recovery"]["generation"]
# A later Paho callback sees the already reconnecting runtime and therefore
# joins this owner; it cannot queue a second capture wake or lineage.
assert service._active_stream_recovery_admitted_for_runtime_loss() is True # noqa: SLF001
assert len(runtime.recovery_requests) == 1
assert second["connection_recovery"]["generation"] == generation
assert second["connection_recovery"]["state"] == "reconnecting"
assert second["acquisition"]["state"] == "acquiring"
assert runtime.stop_calls == 0
def test_active_stream_recovery_survives_old_control_keepalive_failure(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control, _physical = _install_composite_active_recovery_fixture(
service,
runtime,
monkeypatch,
)
admitted = service.state()
assert admitted["connection_recovery"]["state"] == "reconnecting"
with service._lock: # noqa: SLF001
assert service._active_stream_recovery_started_monotonic is not None # noqa: SLF001
service._active_stream_recovery_started_monotonic -= 60.0 # noqa: SLF001
control.state = "failed"
control.failure = {
"reason_code": "mqtt_network_loop_failed",
"modeling_command_attempted": True,
"safe_to_retry": False,
}
after_keepalive = service.state()
assert after_keepalive["phase"] == "reconnecting"
assert after_keepalive["connection_recovery"]["elapsed_ms"] >= 60_000
assert after_keepalive["connection_recovery"]["automatic_command_retry"] is False
assert after_keepalive["acquisition"]["state"] == "acquiring"
assert after_keepalive["selected_device_id"] == "test-ble-transport"
assert after_keepalive["k1_ip"] == "192.168.1.20"
assert runtime.stop_calls == 0
def test_recovered_projection_requires_a_live_ready_source_and_terminal_lease_retires_owner(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
_control, _physical = _install_composite_active_recovery_fixture(
service,
runtime,
monkeypatch,
)
reconnecting = service.state()
lineage = service._active_stream_recovery_lineage # noqa: SLF001
assert lineage is not None
assert reconnecting["connection_recovery"]["state"] == "reconnecting"
runtime.phase = "idle"
runtime.source_mode = "idle"
runtime.source_ready = False
projected_reconnecting_idle = service._active_stream_recovery_projection( # noqa: SLF001
runtime.snapshot()
)
assert projected_reconnecting_idle["state"] == "inactive"
assert projected_reconnecting_idle["automatic_read_only_rebind"] is False
assert projected_reconnecting_idle["acquisition_id"] is None
runtime.phase = "reconnecting"
runtime.source_mode = "live"
runtime.phase = "live"
runtime.source_ready = True
runtime.recovery_state = "recovered"
runtime.recovery_attempt = 7
recovered = service._active_stream_recovery_projection(runtime.snapshot()) # noqa: SLF001
assert recovered["state"] == "recovered"
assert recovered["attempt"] == 7
assert recovered["automatic_read_only_rebind"] is True
# An out-of-order runtime tail cannot publish recovered while the receiver
# is terminal. Durable physical-command history is owned by its ledger, not
# by this process-local recovery contract.
runtime.phase = "idle"
runtime.source_mode = "idle"
runtime.source_ready = False
projected_idle = service._active_stream_recovery_projection(runtime.snapshot()) # noqa: SLF001
assert projected_idle["state"] == "inactive"
assert projected_idle["automatic_read_only_rebind"] is False
assert projected_idle["acquisition_id"] is None
assert projected_idle["camera_recovery"] == "inactive"
service._release_acquisition_session_lease() # noqa: SLF001
retired = service._active_stream_recovery_projection(runtime.snapshot()) # noqa: SLF001
assert retired["state"] == "inactive"
assert retired["automatic_read_only_rebind"] is False
assert retired["acquisition_id"] is None
assert service._active_stream_recovery_lineage is None # noqa: SLF001
def test_local_force_finish_cancels_generation_and_is_idempotent_for_mode_reset(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
_control, physical = _install_composite_active_recovery_fixture(
service,
runtime,
monkeypatch,
runtime_phase="reconnecting",
camera_phase="error",
)
monkeypatch.setattr(service, "_seal_acquisition_capture_clock", lambda: None)
state = service.state()
acquisition = state["acquisition"]
recovery = state["connection_recovery"]
lineage = service._active_stream_recovery_lineage # noqa: SLF001
assert lineage is not None
assert runtime.recovery_request_pending is True
finished = service.force_finish_acquisition_locally(
_force_finish_request(
acquisition_id=acquisition["acquisition_id"],
expected_state_revision=acquisition["state_revision"],
expected_recovery_generation=recovery["generation"],
)
)
assert finished["acquisition"]["state"] == "interrupted"
assert finished["acquisition"]["result"]["device_stop"] == "not-sent"
assert finished["acquisition"]["result"]["physical_command_sent"] is False
assert finished["connection_recovery"]["state"] == "force-finished"
assert runtime.stop_calls == 1
assert runtime.recovery_request_pending is False
assert service._active_stream_recovery_lineage_is_current(lineage) is False # noqa: SLF001
assert service._physical_command_coordinator.snapshot() is physical # noqa: SLF001
with service._acquisition_lifecycle_gate: # noqa: SLF001
assert (
service._force_finish_active_acquisition_locally( # noqa: SLF001
reason_code="connection-mode-reset",
require_recovery=False,
)
is False
)
@pytest.mark.parametrize("cleanup_failure", ["runtime", "camera"])
def test_local_force_finish_cleanup_failure_is_visible_retryable_and_fences_late_success(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
cleanup_failure: str,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control, physical = _install_composite_active_recovery_fixture(
service,
runtime,
monkeypatch,
)
monkeypatch.setattr(service, "_seal_acquisition_capture_clock", lambda: None)
before = service.state()
acquisition = before["acquisition"]
recovery = before["connection_recovery"]
lineage = service._active_stream_recovery_lineage # noqa: SLF001
assert lineage is not None
start_projects_before = list(control.start_projects)
stop_calls_before = control.stop_calls
original_stop_recording = service.camera_preview.stop_recording
camera_failure_active = cleanup_failure == "camera"
def stop_recording(**kwargs: object) -> dict[str, object]:
nonlocal camera_failure_active
if camera_failure_active:
camera_failure_active = False
raise RuntimeError("synthetic camera local cleanup failure")
return original_stop_recording(**kwargs) # type: ignore[arg-type,return-value]
if cleanup_failure == "runtime":
runtime.stop_error = RuntimeError("synthetic runtime local cleanup failure")
else:
monkeypatch.setattr(service.camera_preview, "stop_recording", stop_recording)
with pytest.raises(RuntimeError, match=f"synthetic {cleanup_failure} local cleanup failure"):
service.force_finish_acquisition_locally(
_force_finish_request(
acquisition_id=acquisition["acquisition_id"],
expected_state_revision=acquisition["state_revision"],
expected_recovery_generation=recovery["generation"],
)
)
failed = service.state()
failed_operation = failed["last_operation"]
assert failed["acquisition"]["state"] == "failed"
assert failed["acquisition"]["cleanup_pending"] is True
assert failed["acquisition"]["result"]["local_force_finish"] is True
assert failed["acquisition"]["result"]["device_stop"] == "not-sent"
assert failed["acquisition"]["result"]["physical_command_sent"] is False
assert failed_operation["action"] == facade_module.ACTION_ACQUISITION_FORCE_FINISH
assert failed_operation["status"] == "failed"
assert failed_operation["stage_code"] == "local-cleanup-failed"
assert failed_operation["error"]["retryable"] is True
assert failed_operation["error"]["safe_to_retry"] is True
assert failed_operation["error"]["side_effect_status"] == "none"
assert service._active_stream_recovery_lineage_is_current(lineage) is False # noqa: SLF001
assert control.start_projects == start_projects_before
assert control.stop_calls == stop_calls_before
assert service._physical_command_coordinator.snapshot() is physical # noqa: SLF001
# The retry is local finalization only. It seals the retained evidence
# lease through the compatibility stop seam and cannot revive recovery or
# publish a physical command.
runtime.stop_error = None
recovered = service.stop()
assert recovered["acquisition"]["state"] == "failed"
assert recovered["acquisition"]["cleanup_pending"] is False
assert recovered["source_mode"] == "idle"
assert service._active_stream_recovery_lineage_is_current(lineage) is False # noqa: SLF001
assert control.start_projects == start_projects_before
assert control.stop_calls == stop_calls_before
assert service._physical_command_coordinator.snapshot() is physical # noqa: SLF001
def test_connection_mode_reset_supersedes_queued_force_finish_without_state_revival(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
_control, physical = _install_composite_active_recovery_fixture(
service,
runtime,
monkeypatch,
runtime_phase="reconnecting",
camera_phase="error",
)
monkeypatch.setattr(service, "_seal_acquisition_capture_clock", lambda: None)
queued = service.state()
queued_acquisition = queued["acquisition"]
queued_recovery = queued["connection_recovery"]
assert runtime.recovery_request_pending is True
with service._acquisition_lifecycle_gate: # noqa: SLF001
reset_finished = service._force_finish_active_acquisition_locally( # noqa: SLF001
reason_code="connection-mode-reset",
require_recovery=False,
)
assert reset_finished is True
with pytest.raises(
facade_module.LocalAcquisitionLifecycleError,
match="acquisition changed",
):
service.force_finish_acquisition_locally(
_force_finish_request(
acquisition_id=queued_acquisition["acquisition_id"],
expected_state_revision=queued_acquisition["state_revision"],
expected_recovery_generation=queued_recovery["generation"],
)
)
after = service.state()
assert after["acquisition"]["state"] == "interrupted"
assert after["connection_recovery"]["state"] == "force-finished"
assert runtime.stop_calls == 1
assert runtime.recovery_request_pending is False
assert service._physical_command_coordinator.snapshot() is physical # noqa: SLF001
def test_active_stream_recovery_scanning_resumes_same_physical_lineage_without_commands(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control, physical = _install_composite_active_recovery_fixture(
service,
runtime,
monkeypatch,
)
service.state()
lineage = service._active_stream_recovery_lineage # noqa: SLF001
assert lineage is not None
physical["reconciliation_ready"] = True
physical["observed_session_state"] = "scanning"
control.state = "connection-ready"
start_projects_before = list(control.start_projects)
stop_calls_before = control.stop_calls
reconcile_ids: list[str] = []
def reconcile_resolved_active(*, reconciliation_id: str) -> dict[str, object]:
reconcile_ids.append(reconciliation_id)
record = physical["record"]
assert isinstance(record, dict)
record["revision"] = int(record["revision"]) + 1
return record
monkeypatch.setattr(
service._physical_command_coordinator, # noqa: SLF001
"reconcile_resolved_active",
reconcile_resolved_active,
)
monkeypatch.setattr(
control,
"request_start",
lambda **_kwargs: pytest.fail("recovery must not repeat START"),
)
monkeypatch.setattr(
control,
"request_stop",
lambda **_kwargs: pytest.fail("recovery must not send STOP"),
)
decision = asyncio.run(
service._reconcile_active_stream_physical_state_owned( # noqa: SLF001
lineage,
attempt=3,
)
)
assert decision == "resume"
assert reconcile_ids == [
facade_module._active_stream_reconciliation_id( # noqa: SLF001
lineage,
attempt=3,
)
]
assert control.state == "scanning"
assert control.start_projects == start_projects_before
assert control.stop_calls == stop_calls_before
# The physical audit revision advanced before MQTT SUBACK. A failed first
# resubscribe must admit the same frozen lineage on attempt two.
assert service._admit_active_stream_recovery_lineage() is lineage # noqa: SLF001
assert (
physical["record"]
is service._physical_command_coordinator.snapshot()[ # noqa: SLF001
"record"
]
)
def test_active_stream_recovery_privacy_bridge_retains_exact_route_for_read_only_rebind(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control, physical = _install_composite_active_recovery_fixture(
service,
runtime,
monkeypatch,
)
service.state()
lineage = service._active_stream_recovery_lineage # noqa: SLF001
assert lineage is not None
supervisor = service._connection_supervisor # noqa: SLF001
baseline = supervisor.snapshot()
candidate = replace(
baseline,
device_identity=replace(baseline.device_identity, state="unverified"),
control_plane=replace(
baseline.control_plane,
state="lost",
session_id=None,
),
lease=replace(baseline.lease, state="configured-unverified"),
authority=replace(
baseline.authority,
control_allowed=False,
acquisition_start_allowed=False,
),
)
start_projects_before = list(control.start_projects)
stop_calls_before = control.stop_calls
operation_journal_before = service._operations.snapshot() # noqa: SLF001
physical_ledger_before = service._physical_command_ledger.snapshot() # noqa: SLF001
network_ledger_before = service._network_mutation_ledger.snapshot() # noqa: SLF001
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
monkeypatch.setattr(
service._host_wifi_association_probe, # noqa: SLF001
"observe",
lambda *_args, **_kwargs: {
"schema_version": 1,
"adapter": "CoreWLAN",
"wifi_interface": True,
"association_state": "unavailable",
"evidence_quality": "unavailable",
"continuity_proven": False,
"continuity_token": "d" * 64,
"reason_code": "association-identity-unavailable",
},
)
monkeypatch.setattr(
supervisor,
"association_timeout_retention_candidate",
lambda *, expected_target: (
candidate
if expected_target
== EndpointTarget(lineage.target_ipv4, lineage.target_port)
else None
),
)
sampled = service._sample_host_path(lineage.target_ipv4) # noqa: SLF001
assert sampled.available is True
assert sampled.reason_code is None
assert sampled.fingerprint == baseline.host_path.fingerprint
assert sampled.kernel_route_fingerprint == (
baseline.host_path.kernel_route_fingerprint
)
assert control.start_projects == start_projects_before
assert control.stop_calls == stop_calls_before
assert service._operations.snapshot() == operation_journal_before # noqa: SLF001
assert ( # noqa: SLF001
service._physical_command_ledger.snapshot() == physical_ledger_before
)
assert service._network_mutation_ledger.snapshot() == network_ledger_before # noqa: SLF001
assert service._physical_command_coordinator.snapshot() is physical # noqa: SLF001
def test_active_stream_control_adoption_gets_fresh_budget_after_slow_proof(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control, physical = _install_composite_active_recovery_fixture(
service,
runtime,
monkeypatch,
)
service.state()
lineage = service._active_stream_recovery_lineage # noqa: SLF001
assert lineage is not None
physical["reconciliation_ready"] = True
physical["observed_session_state"] = "scanning"
control.state = "connection-ready"
start_projects_before = list(control.start_projects)
stop_calls_before = control.stop_calls
original_adopt = control.adopt_reconciled_scanning
original_snapshot = control.snapshot
clock = [200.0]
adoption_pending = [False]
adoption_snapshots = [0]
class FacadeTimeProxy:
def monotonic(self) -> float:
return clock[0]
def __getattr__(self, name: str) -> Any:
return getattr(time, name)
def reconcile_resolved_active(*, reconciliation_id: str) -> dict[str, object]:
assert reconciliation_id
record = physical["record"]
assert isinstance(record, dict)
record["revision"] = int(record["revision"]) + 1
return record
def delayed_adopt(**kwargs: object) -> dict[str, object]:
result = original_adopt(**kwargs)
adoption_pending[0] = True
control.state = "active-recovery-requested"
clock[0] = 205.01
return result
def delayed_snapshot() -> dict[str, object]:
if adoption_pending[0]:
adoption_snapshots[0] += 1
if adoption_snapshots[0] >= 2:
control.state = "scanning"
clock[0] = 205.5
return original_snapshot()
monkeypatch.setattr(
service._physical_command_coordinator, # noqa: SLF001
"reconcile_resolved_active",
reconcile_resolved_active,
)
monkeypatch.setattr(control, "adopt_reconciled_scanning", delayed_adopt)
monkeypatch.setattr(control, "snapshot", delayed_snapshot)
monkeypatch.setattr(facade_module, "time", FacadeTimeProxy())
monkeypatch.setattr(
control,
"request_start",
lambda **_kwargs: pytest.fail("recovery must not repeat START"),
)
monkeypatch.setattr(
control,
"request_stop",
lambda **_kwargs: pytest.fail("recovery must not send STOP"),
)
decision = asyncio.run(
service._reconcile_active_stream_physical_state_owned( # noqa: SLF001
lineage,
attempt=4,
)
)
assert decision == "resume"
assert adoption_snapshots[0] >= 2
assert control.start_projects == start_projects_before
assert control.stop_calls == stop_calls_before
def test_epoch_one_to_three_rebind_namespaces_prior_acquisition_attempt_collision(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""Regress the 2026-08-12 acq-cc9f5310 Wi-Fi recovery failure."""
service, runtime = service_with_fake_runtime(tmp_path)
control, physical = _install_composite_active_recovery_fixture(
service,
runtime,
monkeypatch,
)
with service._lock: # noqa: SLF001
# Match the live process-local counter; another acquisition had
# already persisted auto-rebind:2:6 in the global ledger history.
service._active_stream_recovery_generation = 1 # noqa: SLF001
service.state()
lineage = service._active_stream_recovery_lineage # noqa: SLF001
assert lineage is not None
assert lineage.recovery_generation == 2
assert service._connection_supervisor.snapshot().host_path.epoch == 1 # noqa: SLF001
service._connection_supervisor.observe_host_path( # noqa: SLF001
HostPathProbeResult(
available=False,
fingerprint=None,
interface=None,
source_ipv4=None,
route_class="unavailable",
reason_code="host-route-unavailable",
)
)
service._connection_supervisor.observe_host_path( # noqa: SLF001
HostPathProbeResult(
available=True,
fingerprint="route-after-wifi-return",
interface="test0",
source_ipv4="192.168.1.100",
route_class="direct",
)
)
assert service._connection_supervisor.snapshot().host_path.epoch == 3 # noqa: SLF001
assert service._active_stream_recovery_lineage_is_current(lineage) is True # noqa: SLF001
physical["reconciliation_ready"] = True
physical["observed_session_state"] = "scanning"
control.state = "connection-ready"
start_projects_before = list(control.start_projects)
stop_calls_before = control.stop_calls
historical_ids = {"auto-rebind:2:6", "auto-rebind:2:7"}
reconcile_ids: list[str] = []
def reconcile_resolved_active(*, reconciliation_id: str) -> dict[str, object]:
if reconciliation_id in historical_ids:
raise facade_module.PhysicalCommandTransitionError(
"physical reconciliation id has already been used"
)
reconcile_ids.append(reconciliation_id)
record = physical["record"]
assert isinstance(record, dict)
record["revision"] = int(record["revision"]) + 1
return record
monkeypatch.setattr(
service._physical_command_coordinator, # noqa: SLF001
"reconcile_resolved_active",
reconcile_resolved_active,
)
monkeypatch.setattr(
control,
"request_start",
lambda **_kwargs: pytest.fail("recovery must not replay START"),
)
monkeypatch.setattr(
control,
"request_stop",
lambda **_kwargs: pytest.fail("recovery must not publish STOP"),
)
monkeypatch.setattr(
service,
"scan_ble",
lambda *_args, **_kwargs: pytest.fail("recovery must not touch BLE"),
)
monkeypatch.setattr(
service,
"connect",
lambda *_args, **_kwargs: pytest.fail("recovery must not mutate network state"),
)
decision = asyncio.run(
service._reconcile_active_stream_physical_state_owned( # noqa: SLF001
lineage,
attempt=6,
)
)
expected_id = facade_module._active_stream_reconciliation_id( # noqa: SLF001
lineage,
attempt=6,
)
prior_process_lineage = facade_module.dataclass_replace(
lineage,
snapshot_runtime_id="snapshot-runtime-prior-process",
acquisition_id="acq-b0cc1fe4-b934-4a98-a3e5-ecab7afd17c4",
physical_operation_id="op-prior-acquisition-start",
)
prior_process_id = facade_module._active_stream_reconciliation_id( # noqa: SLF001
prior_process_lineage,
attempt=6,
)
assert decision == "resume"
assert reconcile_ids == [expected_id]
assert expected_id not in historical_ids
assert expected_id != prior_process_id
assert expected_id == facade_module._active_stream_reconciliation_id( # noqa: SLF001
lineage,
attempt=6,
)
assert len(expected_id + ".device-info") <= 160
# Physical rebind only authorizes transport recovery. Visible recovery is
# still fenced on the later non-empty post-published PCL.
assert runtime.snapshot()["phase"] == "reconnecting"
assert runtime.snapshot()["source_ready"] is False
assert control.start_projects == start_projects_before
assert control.stop_calls == stop_calls_before
@pytest.mark.parametrize(
("observed_state", "expected_reason", "reconcile_expected"),
[
("ready", "device-reported-standby", True),
("scan_over", "device-reported-scan-over", True),
],
)
def test_active_stream_recovery_device_standby_never_restarts_scanner(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
observed_state: str,
expected_reason: str,
reconcile_expected: bool,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control, physical = _install_composite_active_recovery_fixture(
service,
runtime,
monkeypatch,
)
service.state()
lineage = service._active_stream_recovery_lineage # noqa: SLF001
assert lineage is not None
physical["reconciliation_ready"] = True
physical["observed_session_state"] = observed_state
control.state = "connection-ready"
start_projects_before = list(control.start_projects)
stop_calls_before = control.stop_calls
reconcile_ids: list[str] = []
def reconcile_resolved_active(*, reconciliation_id: str) -> dict[str, object]:
reconcile_ids.append(reconciliation_id)
record = physical["record"]
assert isinstance(record, dict)
record["revision"] = int(record["revision"]) + 1
physical["resolved_active_recovery_required"] = False
physical["resolved_scan_over_recovery_required"] = observed_state == "scan_over"
physical["requires_reconciliation"] = observed_state == "scan_over"
return record
monkeypatch.setattr(
service._physical_command_coordinator, # noqa: SLF001
"reconcile_resolved_active",
reconcile_resolved_active,
)
monkeypatch.setattr(
control,
"request_start",
lambda **_kwargs: pytest.fail("standby recovery must not repeat START"),
)
monkeypatch.setattr(
control,
"request_stop",
lambda **_kwargs: pytest.fail("standby recovery must not send STOP"),
)
decision = asyncio.run(
service._reconcile_active_stream_physical_state_owned( # noqa: SLF001
lineage,
attempt=4,
)
)
assert decision == "standby"
assert bool(reconcile_ids) is reconcile_expected
assert control.start_projects == start_projects_before
assert control.stop_calls == stop_calls_before
assert service._active_stream_recovery_state == "standby" # noqa: SLF001
assert service._active_stream_recovery_reason_code == expected_reason # noqa: SLF001
assert physical["resolved_active_recovery_required"] is False
assert physical["requires_reconciliation"] is (observed_state == "scan_over")
def test_active_stream_recovery_wrong_identity_blocks_without_retry_or_camera_reopen(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control, _physical = _install_composite_active_recovery_fixture(
service,
runtime,
monkeypatch,
)
service.state()
lineage = service._active_stream_recovery_lineage # noqa: SLF001
assert lineage is not None
start_projects_before = list(control.start_projects)
stop_calls_before = control.stop_calls
async def monitor_quiescent() -> bool:
return True
monkeypatch.setattr(
service,
"_await_connection_monitor_quiescence",
monitor_quiescent,
)
monkeypatch.setattr(
service,
"_acquire_k1_lifecycle_process_lease",
lambda _holder: None,
)
monkeypatch.setattr(
service,
"_release_k1_lifecycle_process_lease",
lambda _holder: None,
)
monkeypatch.setattr(
service,
"_probe_control_endpoint",
lambda _target, **_kwargs: facade_module._CorrelatedEndpointObservation( # noqa: SLF001
path=_direct_host_path(lineage.target_ipv4),
reachable=True,
reason_code=None,
),
)
async def reject_wrong_identity(**_kwargs: object) -> None:
raise facade_module.ConnectionVerificationError(
"same IP belongs to another K1",
reason_code="control-bootstrap-device-identity-unverified",
)
camera_reopens: list[str] = []
monkeypatch.setattr(
service,
"_bootstrap_prestart_control_ready_owned",
reject_wrong_identity,
)
monkeypatch.setattr(
service.camera_preview,
"select",
lambda *_args: camera_reopens.append("camera") or {},
)
decision = asyncio.run(
service._recover_active_stream_connection_owned(lineage, 1) # noqa: SLF001
)
assert decision == "blocked"
assert service._active_stream_recovery_state == "blocked" # noqa: SLF001
assert service._active_stream_recovery_reason_code == ( # noqa: SLF001
"control-bootstrap-device-identity-unverified"
)
assert camera_reopens == []
assert control.start_projects == start_projects_before
assert control.stop_calls == stop_calls_before
def test_active_stream_recovery_owned_path_is_read_only_and_resumes_exact_lineage(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control, _physical = _install_composite_active_recovery_fixture(
service,
runtime,
monkeypatch,
)
service.state()
lineage = service._active_stream_recovery_lineage # noqa: SLF001
assert lineage is not None
control.state = "idle"
start_projects_before = list(control.start_projects)
stop_calls_before = control.stop_calls
events: list[tuple[str, object]] = []
async def monitor_quiescent() -> bool:
events.append(("monitor", True))
return True
def probe_exact_target( # noqa: SLF001
target_ipv4: str,
*,
association_timeout_seconds: float,
) -> facade_module._CorrelatedEndpointObservation:
events.append(
("probe", (target_ipv4, association_timeout_seconds))
)
return facade_module._CorrelatedEndpointObservation( # noqa: SLF001
path=_direct_host_path(target_ipv4),
reachable=True,
reason_code=None,
)
async def inspection_only_bootstrap(**kwargs: object) -> None:
assert kwargs["connection_mode"] == lineage.connection_mode
assert kwargs["inspection_only"] is True
events.append(("device-info-status", kwargs["parent_operation_id"]))
async def reconcile_same_lineage(
candidate: facade_module._ActiveStreamRecoveryLineage, # noqa: SLF001
*,
attempt: int,
) -> facade_module.RecoveryDecision:
assert candidate is lineage
events.append(("physical-read-only", attempt))
return "resume"
def recover_local_camera(
candidate: facade_module._ActiveStreamRecoveryLineage, # noqa: SLF001
) -> facade_module.RecoveryDecision:
assert candidate is lineage
events.append(("camera-local", candidate.evidence_session_id))
return "resume"
def forbidden_device_command(**_kwargs: object) -> object:
pytest.fail("active stream recovery must not publish START or STOP")
async def forbidden_ble_or_network_mutation(*_args: object, **_kwargs: object) -> object:
pytest.fail("active stream recovery must not scan, write BLE, or provision Wi-Fi")
monkeypatch.setattr(service, "_await_connection_monitor_quiescence", monitor_quiescent)
monkeypatch.setattr(
service,
"_acquire_k1_lifecycle_process_lease",
lambda holder: events.append(("lease-acquire", holder)),
)
monkeypatch.setattr(
service,
"_release_k1_lifecycle_process_lease",
lambda holder: events.append(("lease-release", holder)),
)
monkeypatch.setattr(service, "_probe_control_endpoint", probe_exact_target)
monkeypatch.setattr(
service,
"_bootstrap_prestart_control_ready_owned",
inspection_only_bootstrap,
)
monkeypatch.setattr(
service,
"_reconcile_active_stream_physical_state_owned",
reconcile_same_lineage,
)
monkeypatch.setattr(service, "_recover_active_stream_camera_owned", recover_local_camera)
monkeypatch.setattr(control, "request_start", forbidden_device_command)
monkeypatch.setattr(control, "request_stop", forbidden_device_command)
monkeypatch.setattr(service, "scan_ble", forbidden_ble_or_network_mutation)
monkeypatch.setattr(service, "connect", forbidden_ble_or_network_mutation)
decision = asyncio.run(
service._recover_active_stream_connection_owned(lineage, 5) # noqa: SLF001
)
assert decision == "resume"
assert events == [
("monitor", True),
("lease-acquire", "network"),
(
"probe",
(
lineage.target_ipv4,
facade_module.ACTIVE_STREAM_RECOVERY_ASSOCIATION_TIMEOUT_SECONDS,
),
),
(
"device-info-status",
(
f"active-stream-recovery:{lineage.acquisition_id}:"
f"{lineage.recovery_generation}"
),
),
("physical-read-only", 5),
("lease-release", "network"),
]
# Camera recovery is now intentionally downstream of the post-Rerun
# checkpoint rebind. Control recovery alone cannot open/promote media.
assert ("camera-local", lineage.evidence_session_id) not in events
assert control.start_projects == start_projects_before
assert control.stop_calls == stop_calls_before
assert service._active_stream_recovery_lineage_is_current(lineage) is True # noqa: SLF001
assert service._active_stream_recovery_reason_code == "mqtt-resubscribe-pending" # noqa: SLF001
def test_incident_recovery_retires_epoch_one_control_and_retries_fresh_inspection_binding(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""Regress the 2026-08-12 acq-209faf83 route-loss failure.
The incident START/control owner was bound to host-path epoch 1. Wi-Fi
loss rotated that epoch, and the first fresh inspection raced one more
association edge. That expected local binding loss must keep retrying;
the next inspection must bind the current epoch without replaying any
physical or network command.
"""
service, runtime = service_with_fake_runtime(tmp_path)
class IncidentControl(FakeInteractiveControlSession):
def __init__(self) -> None:
super().__init__()
self.opened_bindings: list[ApplicationConnectionBinding] = []
self.close_calls = 0
self.retire_calls = 0
self.binding_validation_calls = 0
def validate_connection_binding(self) -> None:
self.binding_validation_calls += 1
raise AssertionError("recovery must not validate/reuse the epoch-1 owner")
def close(self) -> None:
self.close_calls += 1
super().close()
def retire_for_network_change(self, **kwargs: object) -> dict[str, object]:
self.retire_calls += 1
return super().retire_for_network_change(**kwargs)
def open(
self,
*,
connection_binding: ApplicationConnectionBinding,
inspection_only: bool = False,
**kwargs: object,
) -> dict[str, object]:
self.opened_bindings.append(connection_binding)
if len(self.opened_bindings) == 1:
# Match the live failure: the newly opened worker observed one
# more route/association epoch before its first MQTT publish.
service._connection_supervisor.observe_host_path( # noqa: SLF001
recovered_path_b
)
self.state = "failed"
self.failure = {
"reason_code": "application-connection-binding-lost",
"safe_to_retry": True,
"modeling_command_attempted": False,
}
return self.snapshot()
self.session_generation += 1
super().open(
connection_binding=connection_binding,
inspection_only=inspection_only,
**kwargs,
)
assert self.verified_control is not None
self.verified_control = {
**self.verified_control,
"control_session_id": (
f"fake-recovery-control-{self.session_generation}"
),
"producer_generation": self.session_generation,
}
return self.snapshot()
control = IncidentControl()
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
_control, _physical = _install_composite_active_recovery_fixture(
service,
runtime,
monkeypatch,
runtime_phase="reconnecting",
camera_phase="streaming",
)
# The fixture installs its own fake session; replace it before freezing the
# recovery lineage while retaining the exact already-resolved START proof.
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
control.state = "scanning"
original_epoch = service._connection_supervisor.snapshot().host_path.epoch # noqa: SLF001
assert original_epoch == 1
service.state()
lineage = service._active_stream_recovery_lineage # noqa: SLF001
assert lineage is not None
lost_path = HostPathProbeResult(
available=False,
fingerprint=None,
interface=None,
source_ipv4=None,
route_class="unavailable",
reason_code="host-route-unavailable",
)
recovered_path_a = HostPathProbeResult(
available=True,
fingerprint="incident-route-after-wifi-return-a",
interface="test0",
source_ipv4="192.168.68.100",
route_class="direct",
)
recovered_path_b = HostPathProbeResult(
available=True,
fingerprint="incident-route-after-wifi-return-b",
interface="test0",
source_ipv4="192.168.68.100",
route_class="direct",
)
service._connection_supervisor.observe_host_path(lost_path) # noqa: SLF001
assert service._connection_supervisor.snapshot().host_path.epoch == 2 # noqa: SLF001
probe_paths = iter((recovered_path_a, recovered_path_b))
def probe_current_epoch(
target_ipv4: str,
**_kwargs: object,
) -> facade_module._CorrelatedEndpointObservation: # noqa: SLF001
path = next(probe_paths)
service._observe_connection_transport( # noqa: SLF001
target_ipv4,
path=path,
reachable=True,
)
return facade_module._CorrelatedEndpointObservation( # noqa: SLF001
path=path,
reachable=True,
reason_code=None,
)
async def monitor_quiescent() -> bool:
return True
async def reconcile_same_lineage(
candidate: facade_module._ActiveStreamRecoveryLineage, # noqa: SLF001
*,
attempt: int,
) -> facade_module.RecoveryDecision:
assert candidate is lineage
assert attempt == 6
return "resume"
service._bootstrap_prestart_control_ready_owned = MethodType( # type: ignore[method-assign] # noqa: SLF001
XgridsK1CompatibilityService._bootstrap_prestart_control_ready_owned, # noqa: SLF001
service,
)
monkeypatch.setattr(service, "_await_connection_monitor_quiescence", monitor_quiescent)
monkeypatch.setattr(service, "_probe_control_endpoint", probe_current_epoch)
monkeypatch.setattr(service, "_acquire_k1_lifecycle_process_lease", lambda _holder: None)
monkeypatch.setattr(service, "_release_k1_lifecycle_process_lease", lambda _holder: None)
monkeypatch.setattr(service, "_acquire_application_control_process_lease", lambda: None)
monkeypatch.setattr(service, "_reconcile_application_control_process_lease", lambda _s: None)
monkeypatch.setattr(
service,
"_reconcile_active_stream_physical_state_owned",
reconcile_same_lineage,
)
monkeypatch.setattr(
service,
"_recover_active_stream_camera_owned",
lambda candidate: "resume" if candidate is lineage else "blocked",
)
monkeypatch.setattr(
control,
"request_start",
lambda **_kwargs: pytest.fail("recovery must not replay START"),
)
monkeypatch.setattr(
control,
"request_stop",
lambda **_kwargs: pytest.fail("recovery must not publish STOP"),
)
monkeypatch.setattr(
service,
"scan_ble",
lambda *_args, **_kwargs: pytest.fail("recovery must not touch BLE"),
)
monkeypatch.setattr(
service,
"connect",
lambda *_args, **_kwargs: pytest.fail("recovery must not mutate network state"),
)
first = asyncio.run(
service._recover_active_stream_connection_owned(lineage, 5) # noqa: SLF001
)
assert first == "retry"
assert service._active_stream_recovery_state == "reconnecting" # noqa: SLF001
assert service._active_stream_recovery_reason_code == ( # noqa: SLF001
"application-connection-binding-lost"
)
assert control.opened_bindings[0].host_path_epoch == 3
assert control.close_calls == 1
assert control.retire_calls == 2
assert control.binding_validation_calls == 0
second = asyncio.run(
service._recover_active_stream_connection_owned(lineage, 6) # noqa: SLF001
)
assert second == "resume"
assert [binding.host_path_epoch for binding in control.opened_bindings] == [3, 4]
assert control.opened_bindings[-1].host_path_epoch == (
service._connection_supervisor.snapshot().host_path.epoch # noqa: SLF001
)
assert control.inspection_only is True
assert control.state == "connection-ready"
assert service._active_stream_recovery_lineage_is_current(lineage) is True # noqa: SLF001
assert service._active_stream_recovery_reason_code == "mqtt-resubscribe-pending" # noqa: SLF001
def test_active_stream_recovery_waits_for_terminal_control_worker_retirement(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control, _physical = _install_composite_active_recovery_fixture(
service,
runtime,
monkeypatch,
)
service.state()
lineage = service._active_stream_recovery_lineage # noqa: SLF001
assert lineage is not None
control.state = "failed"
control.failure = {
"reason_code": "mqtt_network_loop_failed",
"modeling_command_attempted": True,
"safe_to_retry": False,
}
retire_attempts = 0
def retire_terminal_control(**_kwargs: object) -> dict[str, object]:
nonlocal retire_attempts
retire_attempts += 1
if retire_attempts == 1:
raise ApplicationAcceptanceError("control session worker is still retiring")
control.state = "idle"
control.verified_control = None
return control.snapshot()
async def monitor_quiescent() -> bool:
return True
async def inspection_only_bootstrap(**_kwargs: object) -> None:
return None
async def reconcile_same_lineage(
candidate: facade_module._ActiveStreamRecoveryLineage, # noqa: SLF001
*,
attempt: int,
) -> facade_module.RecoveryDecision:
assert candidate is lineage
assert attempt == 2
return "resume"
monkeypatch.setattr(control, "retire_for_network_change", retire_terminal_control)
monkeypatch.setattr(service, "_await_connection_monitor_quiescence", monitor_quiescent)
monkeypatch.setattr(
service,
"_acquire_k1_lifecycle_process_lease",
lambda _holder: None,
)
monkeypatch.setattr(
service,
"_release_k1_lifecycle_process_lease",
lambda _holder: None,
)
monkeypatch.setattr(
service,
"_probe_control_endpoint",
lambda _target, **_kwargs: facade_module._CorrelatedEndpointObservation( # noqa: SLF001
path=_direct_host_path(lineage.target_ipv4),
reachable=True,
reason_code=None,
),
)
monkeypatch.setattr(
service,
"_bootstrap_prestart_control_ready_owned",
inspection_only_bootstrap,
)
monkeypatch.setattr(
service,
"_reconcile_active_stream_physical_state_owned",
reconcile_same_lineage,
)
monkeypatch.setattr(
service,
"_recover_active_stream_camera_owned",
lambda candidate: "resume" if candidate is lineage else "blocked",
)
decision = asyncio.run(
service._recover_active_stream_connection_owned(lineage, 2) # noqa: SLF001
)
assert decision == "resume"
assert retire_attempts == 2
assert service._active_stream_recovery_state == "reconnecting" # noqa: SLF001
assert service._active_stream_recovery_reason_code == "mqtt-resubscribe-pending" # noqa: SLF001
def test_active_stream_recovery_exact_device_system_fault_is_terminal_without_commands(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control, _physical = _install_composite_active_recovery_fixture(
service,
runtime,
monkeypatch,
)
service.state()
lineage = service._active_stream_recovery_lineage # noqa: SLF001
assert lineage is not None
control.state = "idle"
start_projects_before = list(control.start_projects)
stop_calls_before = control.stop_calls
async def monitor_quiescent() -> bool:
return True
async def bootstrap_system_fault(**kwargs: object) -> None:
assert kwargs["inspection_only"] is True
control.state = "failed"
control.failure = {
"reason_code": "application-device-system-error",
"modeling_command_attempted": False,
"safe_to_retry": False,
}
monkeypatch.setattr(service, "_await_connection_monitor_quiescence", monitor_quiescent)
monkeypatch.setattr(
service,
"_acquire_k1_lifecycle_process_lease",
lambda _holder: None,
)
monkeypatch.setattr(
service,
"_release_k1_lifecycle_process_lease",
lambda _holder: None,
)
monkeypatch.setattr(
service,
"_probe_control_endpoint",
lambda _target, **_kwargs: facade_module._CorrelatedEndpointObservation( # noqa: SLF001
path=_direct_host_path(lineage.target_ipv4),
reachable=True,
reason_code=None,
),
)
monkeypatch.setattr(
service,
"_bootstrap_prestart_control_ready_owned",
bootstrap_system_fault,
)
monkeypatch.setattr(
service,
"_recover_active_stream_camera_owned",
lambda _candidate: pytest.fail("system fault must not reopen camera"),
)
monkeypatch.setattr(
control,
"request_start",
lambda **_kwargs: pytest.fail("system fault recovery must not repeat START"),
)
monkeypatch.setattr(
control,
"request_stop",
lambda **_kwargs: pytest.fail("system fault recovery must not send STOP"),
)
decision = asyncio.run(
service._recover_active_stream_connection_owned(lineage, 6) # noqa: SLF001
)
assert decision == "fault"
assert service._active_stream_recovery_state == "fault" # noqa: SLF001
assert service._active_stream_recovery_reason_code == ( # noqa: SLF001
"active-stream-recovery-system-error"
)
assert service._active_stream_recovery_terminal_outcome == "fault" # noqa: SLF001
assert control.start_projects == start_projects_before
assert control.stop_calls == stop_calls_before
def test_active_stream_recovery_bootstrap_system_error_is_normalized_terminal_fault(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control, _physical = _install_composite_active_recovery_fixture(
service,
runtime,
monkeypatch,
)
service.state()
lineage = service._active_stream_recovery_lineage # noqa: SLF001
assert lineage is not None
control.state = "idle"
start_projects_before = list(control.start_projects)
stop_calls_before = control.stop_calls
monkeypatch.setattr(service, "_seal_acquisition_capture_clock", lambda: None)
async def monitor_quiescent() -> bool:
return True
async def bootstrap_system_error(**kwargs: object) -> None:
assert kwargs["inspection_only"] is True
raise facade_module.ConnectionVerificationError(
"DeviceInfo reported a system fault",
reason_code="application-device-system-error",
)
monkeypatch.setattr(service, "_await_connection_monitor_quiescence", monitor_quiescent)
monkeypatch.setattr(
service,
"_acquire_k1_lifecycle_process_lease",
lambda _holder: None,
)
monkeypatch.setattr(
service,
"_release_k1_lifecycle_process_lease",
lambda _holder: None,
)
monkeypatch.setattr(
service,
"_probe_control_endpoint",
lambda _target, **_kwargs: facade_module._CorrelatedEndpointObservation( # noqa: SLF001
path=_direct_host_path(lineage.target_ipv4),
reachable=True,
reason_code=None,
),
)
monkeypatch.setattr(
service,
"_bootstrap_prestart_control_ready_owned",
bootstrap_system_error,
)
monkeypatch.setattr(
service,
"_reconcile_active_stream_physical_state_owned",
lambda *_args, **_kwargs: pytest.fail(
"bootstrap system fault must stop before physical reconciliation"
),
)
monkeypatch.setattr(
service,
"_recover_active_stream_camera_owned",
lambda _candidate: pytest.fail("bootstrap system fault must not reopen camera"),
)
monkeypatch.setattr(
control,
"request_start",
lambda **_kwargs: pytest.fail("system fault recovery must not repeat START"),
)
monkeypatch.setattr(
control,
"request_stop",
lambda **_kwargs: pytest.fail("system fault recovery must not send STOP"),
)
decision = asyncio.run(
service._recover_active_stream_connection_owned(lineage, 7) # noqa: SLF001
)
assert decision == "fault"
assert service._active_stream_recovery_state == "fault" # noqa: SLF001
assert service._active_stream_recovery_reason_code == ( # noqa: SLF001
"active-stream-recovery-system-error"
)
assert service._active_stream_recovery_terminal_outcome == "fault" # noqa: SLF001
assert control.start_projects == start_projects_before
assert control.stop_calls == stop_calls_before
terminal = service.state()
assert terminal["acquisition"]["state"] == "failed"
assert terminal["acquisition"]["result"]["device_state"] == "fault"
assert terminal["source_mode"] == "idle"
assert runtime.stop_calls == 1
assert control.start_projects == start_projects_before
assert control.stop_calls == stop_calls_before
def test_active_stream_recovery_never_restarts_nontransport_camera_error(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
_control, _physical = _install_composite_active_recovery_fixture(
service,
runtime,
monkeypatch,
)
service.state()
lineage = service._active_stream_recovery_lineage # noqa: SLF001
assert lineage is not None
camera = service.camera_preview.snapshot()
camera["phase"] = "error"
camera["error"] = {
"code": "camera-artifact-write-failed",
"message": "synthetic local artifact failure",
}
restart_calls: list[str] = []
monkeypatch.setattr(
service.camera_preview,
"restart_recording_producer",
lambda *_args, **_kwargs: restart_calls.append("restart") or {},
)
decision = service._recover_active_stream_camera_owned(lineage) # noqa: SLF001
assert decision == "blocked"
assert restart_calls == []
@pytest.mark.parametrize(
("camera_phase", "camera_error", "producer_alive", "active_epoch"),
[
("connecting", None, False, 7),
(
"error",
{
"code": "invalid-fmp4",
"message": "synthetic pre-first-media camera failure",
},
False,
7,
),
(
"error",
{
"code": "invalid-fmp4",
"message": "synthetic detached pre-finalize camera failure",
},
False,
None,
),
],
)
def test_active_stream_recovery_keeps_pre_first_media_camera_downstream_of_mqtt(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
camera_phase: str,
camera_error: dict[str, str] | None,
producer_alive: bool,
active_epoch: int | None,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control, _physical = _install_composite_active_recovery_fixture(
service,
runtime,
monkeypatch,
camera_phase="streaming",
)
service.state()
lineage = service._active_stream_recovery_lineage # noqa: SLF001
assert lineage is not None
start_projects_before = list(control.start_projects)
stop_calls_before = control.stop_calls
camera = service.camera_preview.snapshot()
camera.update(
{
"phase": camera_phase,
"generation": 7,
"active_source_id": facade_module.DEFAULT_ACQUISITION_CAMERA_SOURCE,
"recording": {
"active": True,
"session": lineage.evidence_session_id,
"active_epoch": active_epoch,
"producer_alive": producer_alive,
"producer_age_ms": (
facade_module.ACTIVE_STREAM_CAMERA_STALL_MILLISECONDS + 1
),
"last_segment_age_ms": None,
"committed_media_segment_count": 0,
"completed_epochs": 0,
"last_summary": None,
},
"error": camera_error,
}
)
activation_lineage = (
lineage.acquisition_id,
lineage.evidence_session_id,
lineage.runtime_producer_generation,
)
with service._lock: # noqa: SLF001
service._camera_activation_lineage = activation_lineage # noqa: SLF001
restart_calls: list[str] = []
monkeypatch.setattr(
service.camera_preview,
"restart_recording_producer",
lambda *_args, **_kwargs: restart_calls.append("restart") or {},
)
decision = service._recover_active_stream_camera_owned(lineage) # noqa: SLF001
assert decision == "resume"
assert restart_calls == []
with service._lock: # noqa: SLF001
if camera_phase == "error" or producer_alive is False:
assert service._camera_activation_lineage is None # noqa: SLF001
assert service._camera_activation_retry_lineage == activation_lineage # noqa: SLF001
else:
assert service._camera_activation_lineage == activation_lineage # noqa: SLF001
state = service.state()
assert state["phase"] == "reconnecting"
assert state["acquisition"]["state"] == "acquiring"
assert state["camera_preview"]["activation_admission"]["state"] == "activating"
assert runtime.stop_calls == 0
assert control.start_projects == start_projects_before
assert control.stop_calls == stop_calls_before
def test_active_stream_recovery_never_retries_invalid_fmp4_after_media_commit(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control, _physical = _install_composite_active_recovery_fixture(
service,
runtime,
monkeypatch,
camera_phase="streaming",
)
service.state()
lineage = service._active_stream_recovery_lineage # noqa: SLF001
assert lineage is not None
camera = service.camera_preview.snapshot()
camera.update(
{
"phase": "error",
"generation": 7,
"active_source_id": facade_module.DEFAULT_ACQUISITION_CAMERA_SOURCE,
"recording": {
"active": True,
"session": lineage.evidence_session_id,
"active_epoch": 7,
"committed_media_segment_count": 1,
"producer_alive": False,
"producer_age_ms": 1_000,
"last_segment_age_ms": 0,
"completed_epochs": 0,
"last_summary": None,
},
"error": {
"code": "invalid-fmp4",
"message": "synthetic corruption after the first media commit",
},
}
)
activation_lineage = (
lineage.acquisition_id,
lineage.evidence_session_id,
lineage.runtime_producer_generation,
)
with service._lock: # noqa: SLF001
service._camera_activation_lineage = activation_lineage # noqa: SLF001
restart_calls: list[str] = []
monkeypatch.setattr(
service.camera_preview,
"restart_recording_producer",
lambda *_args, **_kwargs: restart_calls.append("restart") or {},
)
monkeypatch.setattr(service, "_seal_acquisition_capture_clock", lambda: None)
assert service._recover_active_stream_camera_owned(lineage) == "blocked" # noqa: SLF001
assert restart_calls == []
with service._lock: # noqa: SLF001
assert service._camera_activation_lineage == activation_lineage # noqa: SLF001
assert service._camera_activation_retry_lineage is None # noqa: SLF001
terminal = service.state()
assert terminal["acquisition"]["state"] == "failed"
assert terminal["acquisition"]["result"]["camera_failure_code"] == "invalid-fmp4"
assert runtime.stop_calls == 1
assert control.stop_calls == 0
def test_bound_scan_over_without_stop_dominates_late_empty_camera_epoch_failure(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control, physical = _install_composite_active_recovery_fixture(
service,
runtime,
monkeypatch,
runtime_phase="live",
camera_phase="streaming",
)
camera = service.camera_preview.snapshot()
recording = camera["recording"]
assert isinstance(recording, dict)
recording.update(
{
"active": True,
"active_epoch": 2,
"committed_media_segment_count": 4_833,
"producer_alive": False,
"completed_epochs": 2,
"last_summary": {
"codec_epoch": 2,
"status": "failed",
"media_segment_count": 0,
"failure_code": "invalid-fmp4",
},
}
)
camera.update(
{
"phase": "error",
"error": {
"code": "invalid-fmp4",
"message": "synthetic empty post-power-loss epoch",
},
}
)
physical.update(
{
"runtime_bound": True,
"reconciliation_ready": True,
"observed_session_state": "scan_over",
}
)
control.state = "failed"
control.state_revision += 1
control.failure = {
"reason_code": "application_acceptance_failed",
"failed_phase": "scanning",
"modeling_command_attempted": True,
"stop_command_attempted": False,
"diagnostic_snapshot_unavailable": [],
"diagnostic_evidence_unavailable": [],
"safe_to_retry": False,
}
def scan_over_control_snapshot() -> dict[str, object]:
snapshot = FakeInteractiveControlSession.snapshot(control)
snapshot["transport"] = {
"state": "failed",
"publish_attempts": 7,
"device_status_reports": 9,
"latest_device_session_state": "scan_over",
"latest_device_project_bound": True,
"latest_device_init_ready": False,
"latest_system_error_code": None,
"automatic_retry": False,
"automatic_reconnect": False,
}
return snapshot
monkeypatch.setattr(control, "snapshot", scan_over_control_snapshot)
monkeypatch.setattr(service, "_seal_acquisition_capture_clock", lambda: None)
camera_stop_calls: list[str] = []
monkeypatch.setattr(
service.camera_preview,
"stop_current",
lambda: camera_stop_calls.append("stop") or {},
)
start_projects_before = list(control.start_projects)
stop_calls_before = control.stop_calls
terminal = service.state()
assert terminal["acquisition"]["state"] == "interrupted"
assert terminal["acquisition"]["message_code"] == (
"acquisition.recovery.device_standby_observed"
)
assert terminal["acquisition"]["result"] == {
"receiver_stopped": True,
"device_state": "scan_over",
"device_stop": "not-sent",
"automatic_command_retry": False,
"read_only_recovery": True,
"physical_reconciliation_required": True,
}
assert terminal["acquisition"]["cleanup_pending"] is False
assert camera_stop_calls == ["stop"]
assert runtime.stop_calls == 1
assert control.start_projects == start_projects_before
assert control.stop_calls == stop_calls_before == 0
def test_active_stream_recovery_reopens_exact_camera_epoch_once_and_fences_stale_lineage(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
_control, _physical = _install_composite_active_recovery_fixture(
service,
runtime,
monkeypatch,
)
state = service.state()
lineage = service._active_stream_recovery_lineage # noqa: SLF001
assert lineage is not None
camera = dict(state["camera_preview"])
camera["phase"] = "streaming"
camera["generation"] = 7
camera["active_source_id"] = facade_module.DEFAULT_ACQUISITION_CAMERA_SOURCE
camera["recording"] = {
"active": True,
"session": lineage.evidence_session_id,
"active_epoch": 7,
"producer_alive": True,
"producer_age_ms": facade_module.ACTIVE_STREAM_CAMERA_STALL_MILLISECONDS + 1,
"last_segment_age_ms": (facade_module.ACTIVE_STREAM_CAMERA_STALL_MILLISECONDS + 1),
"committed_media_segment_count": 4,
}
camera_calls: list[tuple[str, str, int, str, int | None, int]] = []
perception_binds: list[tuple[str, int]] = []
def snapshot_camera() -> dict[str, object]:
return dict(camera)
def reopen_camera(
source_id: str,
target: str,
*,
expected_generation: int,
expected_recording_session: str,
expected_active_epoch: int | None,
expected_recording_media_segment_count: int,
pre_detach_fence: Callable[[Callable[[], bool]], bool],
commit_fence: Callable[[Callable[[], bool]], bool] | None = None,
committed_before_start: Callable[[dict[str, object]], None] | None = None,
) -> dict[str, object]:
camera_calls.append(
(
source_id,
target,
expected_generation,
expected_recording_session,
expected_active_epoch,
expected_recording_media_segment_count,
)
)
assert pre_detach_fence(lambda: True) is True
camera.update(
{
"phase": "connecting",
"generation": expected_generation + 1,
"active_source_id": source_id,
"recording": {
"active": True,
"session": lineage.evidence_session_id,
"active_epoch": 8,
"producer_alive": True,
"producer_age_ms": 0,
"last_segment_age_ms": 0,
"last_media_segment_age_ms": None,
"committed_media_segment_count": 4,
"media_ready": False,
"current_epoch": {
"generation": 8,
"init_committed": False,
"init_committed_age_ms": None,
"first_media_committed": False,
"first_media_committed_age_ms": None,
"committed_media_segment_count": 0,
"last_media_segment_age_ms": None,
},
},
}
)
assert commit_fence is not None
assert committed_before_start is not None
assert commit_fence(
lambda: committed_before_start(dict(camera)) is None
) is True
return dict(camera)
def bind_perception(session: str, reopened: dict[str, object]) -> None:
recording = reopened["recording"]
assert isinstance(recording, dict)
active_epoch = recording["active_epoch"]
assert isinstance(active_epoch, int)
perception_binds.append((session, active_epoch))
monkeypatch.setattr(service.camera_preview, "snapshot", snapshot_camera)
monkeypatch.setattr(
service.camera_preview,
"restart_recording_producer",
reopen_camera,
)
monkeypatch.setattr(
service,
"_bind_live_perception_camera",
bind_perception,
)
runtime.phase = "live"
runtime.source_ready = True
runtime.recovery_state = "recovered"
with service._lock: # noqa: SLF001
service._active_stream_recovery_state = "recovered" # noqa: SLF001
assert ( # noqa: SLF001
service._recover_active_stream_camera_owned(
lineage,
require_runtime_reconnecting=False,
)
== "resume"
)
assert ( # noqa: SLF001
service._recover_active_stream_camera_owned(
lineage,
require_runtime_reconnecting=False,
)
== "resume"
)
assert camera_calls == [
(
facade_module.DEFAULT_ACQUISITION_CAMERA_SOURCE,
lineage.target_ipv4,
7,
lineage.evidence_session_id,
7,
4,
)
]
assert perception_binds == [(lineage.evidence_session_id, 8)]
assert camera["recording"]["media_ready"] is False
recovery = service._active_stream_recovery_projection( # noqa: SLF001
runtime.snapshot(),
camera=camera,
)
assert recovery["camera_recovery"] == "owned"
assert recovery["camera_media_state"] == "pending-init"
assert recovery["camera_media_ready"] is False
assert recovery["camera_epoch"] == {
"generation": 8,
"init_committed": False,
"init_committed_age_ms": None,
"first_media_committed": False,
"first_media_committed_age_ms": None,
"committed_media_segment_count": 0,
"last_media_segment_age_ms": None,
}
runtime.producer_generation += 1
assert ( # noqa: SLF001
service._recover_active_stream_camera_owned(
lineage,
require_runtime_reconnecting=False,
)
== "blocked"
)
assert len(camera_calls) == 1
def test_device_standby_retires_sources_after_terminal_local_stop_failure(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control = FakeInteractiveControlSession()
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
binding = _seed_supervised_connection(service)
service._compatibility_attestation = ATTESTATION.model_dump(mode="json") # noqa: SLF001
prepared = service.prepare_acquisition(
_prepare_request(
project_name="TEST001",
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
service.start_acquisition(
_start_request(
acquisition_id=acquisition_id,
physical_acceptance=PHYSICAL_ACCEPTANCE,
)
)
start_operation_id = service._acquisition_start_operation_id # noqa: SLF001
assert isinstance(start_operation_id, str)
physical_proof = _exact_start_physical_proof(
operation_id=start_operation_id,
acquisition_id=acquisition_id,
binding=binding,
resolved=True,
)
monkeypatch.setattr(
service._physical_command_coordinator, # noqa: SLF001
"snapshot",
lambda: physical_proof,
)
runtime.mark_ready()
runtime.pcl_frames = 1
service.state()
stopping = service.stop_acquisition(
_stop_request(
acquisition_id=acquisition_id,
mode="graceful",
physical_acceptance=PHYSICAL_ACCEPTANCE,
)
)
stop_operation = stopping["last_operation"]
with service._lock: # noqa: SLF001
assert service._acquisition is not None # noqa: SLF001
service._acquisition.transition( # noqa: SLF001
"failed",
message_code="acquisition.camera_failed",
result={"camera_failure_code": "camera-source-ended"},
)
service._operations.transition( # noqa: SLF001
stop_operation["operation_id"],
"failed",
stage_code="runtime-failed",
message_code="acquisition.stop.runtime_failed",
error={
"category": "stream",
"code": "runtime-failed",
"retryable": False,
"safe_to_retry": False,
"side_effect_status": "unknown",
},
)
control.state = "completed"
recovered = service.state()
assert control.stop_calls == 1
assert control.state == "completed"
assert recovered["acquisition"]["state"] == "failed"
assert recovered["application_control_session"]["state"] == "completed"
assert runtime.stop_calls == 1
def test_second_start_conflict_does_not_tear_down_start_owner(tmp_path: Path) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
service.start_acquisition(_start_request(acquisition_id=acquisition_id))
with pytest.raises(RuntimeError, match="состояния starting"):
service.start_acquisition(_start_request(acquisition_id=acquisition_id))
state = service.state()
start_operations = [
item for item in state["operations"] if item["action"] == "acquisition.start"
]
assert state["acquisition"]["state"] == "starting"
assert runtime.stop_calls == 0
assert [item["status"] for item in start_operations] == ["running", "failed"]
assert start_operations[-1]["error"]["category"] == "conflict"
def test_state_waits_for_atomic_start_handoff(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
entered_start = threading.Event()
release_start = threading.Event()
state_started = threading.Event()
state_finished = threading.Event()
worker_errors: list[BaseException] = []
snapshots: list[dict[str, Any]] = []
original_start_live = runtime.start_live
def blocked_start_live(*args: object, **kwargs: object) -> None:
entered_start.set()
if not release_start.wait(timeout=2):
raise TimeoutError("test did not release start handoff")
original_start_live(*args, **kwargs) # type: ignore[arg-type]
def start_worker() -> None:
try:
service.start_acquisition(_start_request(acquisition_id=acquisition_id))
except BaseException as exc: # pragma: no cover - asserted below
worker_errors.append(exc)
def state_worker() -> None:
state_started.set()
try:
snapshots.append(service.state())
except BaseException as exc: # pragma: no cover - asserted below
worker_errors.append(exc)
finally:
state_finished.set()
monkeypatch.setattr(runtime, "start_live", blocked_start_live)
start_thread = threading.Thread(target=start_worker)
state_thread = threading.Thread(target=state_worker)
start_thread.start()
assert entered_start.wait(timeout=2)
state_thread.start()
assert state_started.wait(timeout=2)
assert not state_finished.wait(timeout=0.05)
release_start.set()
start_thread.join(timeout=2)
state_thread.join(timeout=2)
assert not start_thread.is_alive()
assert not state_thread.is_alive()
assert worker_errors == []
assert snapshots[0]["acquisition"]["state"] == "starting"
assert runtime.source_mode == "live"
assert service._acquisition_session_lease is not None # noqa: SLF001
def test_abort_waits_for_start_handoff_then_stops_owned_producers(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
entered_start = threading.Event()
release_start = threading.Event()
abort_finished = threading.Event()
worker_errors: list[BaseException] = []
original_start_live = runtime.start_live
def blocked_start_live(*args: object, **kwargs: object) -> None:
entered_start.set()
if not release_start.wait(timeout=2):
raise TimeoutError("test did not release start handoff")
original_start_live(*args, **kwargs) # type: ignore[arg-type]
def start_worker() -> None:
try:
service.start_acquisition(_start_request(acquisition_id=acquisition_id))
except BaseException as exc: # pragma: no cover - asserted below
worker_errors.append(exc)
def abort_worker() -> None:
try:
service.abort_acquisition(_abort_request(acquisition_id=acquisition_id))
except BaseException as exc: # pragma: no cover - asserted below
worker_errors.append(exc)
finally:
abort_finished.set()
monkeypatch.setattr(runtime, "start_live", blocked_start_live)
start_thread = threading.Thread(target=start_worker)
abort_thread = threading.Thread(target=abort_worker)
start_thread.start()
assert entered_start.wait(timeout=2)
abort_thread.start()
assert not abort_finished.wait(timeout=0.05)
release_start.set()
start_thread.join(timeout=2)
abort_thread.join(timeout=2)
assert worker_errors == []
state = service.state()
assert state["acquisition"]["state"] == "aborted"
assert runtime.source_mode == "idle"
assert service._acquisition_session_lease is None # noqa: SLF001
def test_camera_selection_finishes_before_serialized_acquisition_stop(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
device_session_id = prepared["device_session"]["device_session_id"]
service.start_acquisition(_start_request(acquisition_id=acquisition_id))
control = FakeInteractiveControlSession()
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
_seed_supervised_connection(service)
service._device_session_id = device_session_id # noqa: SLF001
out_dir = service._acquisition_out_dir # noqa: SLF001
assert out_dir is not None
entered_camera_arm = threading.Event()
release_camera_arm = threading.Event()
stop_finished = threading.Event()
worker_errors: list[BaseException] = []
events: list[str] = []
def blocked_camera_arm(_out_dir: Path, *, require_session: bool = False) -> None:
assert require_session is True
events.append("arm")
entered_camera_arm.set()
if not release_camera_arm.wait(timeout=2):
raise TimeoutError("test did not release camera arm")
def select_worker() -> None:
try:
service.select_camera_preview(
CameraPreviewSelectRequest(
source_id="sensor.camera.left",
device_session_id=device_session_id,
)
)
except BaseException as exc: # pragma: no cover - asserted below
worker_errors.append(exc)
def stop_worker() -> None:
try:
service.stop_acquisition(
_stop_request(
acquisition_id=acquisition_id,
mode="capture-only",
)
)
except BaseException as exc: # pragma: no cover - asserted below
worker_errors.append(exc)
finally:
stop_finished.set()
camera_snapshot = service.camera_preview.snapshot()
camera_snapshot.update(
{
"phase": "streaming",
"generation": 1,
"active_source_id": facade_module.DEFAULT_ACQUISITION_CAMERA_SOURCE,
"recording": {
"active": True,
"session": out_dir.name,
"active_epoch": 1,
"media_ready": True,
"current_epoch": {
"generation": 1,
"init_committed": True,
"first_media_committed": True,
},
},
}
)
monkeypatch.setattr(service, "_arm_camera_recording", blocked_camera_arm)
monkeypatch.setattr(
service.camera_preview,
"snapshot",
lambda: camera_snapshot,
)
monkeypatch.setattr(
service.camera_preview,
"select",
lambda source_id, _target: (
events.append("select")
or {
"active_source_id": source_id,
"recording": {"active": False},
}
),
)
monkeypatch.setattr(
service.camera_preview,
"stop_recording",
lambda **_kwargs: events.append("camera-stop"),
)
monkeypatch.setattr(runtime, "stop", lambda: events.append("runtime-stop"))
select_thread = threading.Thread(target=select_worker)
stop_thread = threading.Thread(target=stop_worker)
select_thread.start()
assert entered_camera_arm.wait(timeout=2)
stop_thread.start()
assert not stop_finished.wait(timeout=0.05)
release_camera_arm.set()
select_thread.join(timeout=2)
stop_thread.join(timeout=2)
assert worker_errors == []
assert events == ["arm", "select", "camera-stop", "runtime-stop"]
assert service.state()["acquisition"]["state"] == "completed"
assert service._acquisition_session_lease is None # noqa: SLF001
def test_receiver_start_failure_seals_stopped_session_before_releasing_lease(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
events: list[str] = []
def start_live(
_host: str,
out_dir: Path,
*,
duration_seconds: float | None,
project_name: str,
recover_connection: object | None = None,
) -> None:
assert duration_seconds is None
assert project_name == PROJECT_NAME
assert recover_connection is None
events.append("start")
out_dir.mkdir(parents=True)
runtime.phase = "starting_live"
runtime.source_mode = "live"
raise RuntimeError("synthetic receiver start failure")
def stop_runtime() -> None:
events.append("runtime")
runtime.phase = "idle"
runtime.source_mode = "idle"
monkeypatch.setattr(runtime, "start_live", start_live)
monkeypatch.setattr(runtime, "stop", stop_runtime)
camera_arm_calls: list[Path] = []
monkeypatch.setattr(
service,
"_arm_camera_recording",
lambda out_dir, **_kwargs: camera_arm_calls.append(out_dir),
)
monkeypatch.setattr(
service.camera_preview,
"stop_recording",
lambda **_kwargs: events.append("camera"),
)
monkeypatch.setattr(
facade_module,
"seal_capture_clock",
lambda _capture_root: events.append("seal"),
)
with pytest.raises(RuntimeError, match="synthetic receiver start failure"):
service.start_acquisition(_start_request(acquisition_id=acquisition_id))
state = service.state()
assert state["acquisition"]["state"] == "failed"
assert state["last_operation"]["status"] == "failed"
assert events == ["start", "camera", "runtime", "seal"]
assert camera_arm_calls == []
assert service._acquisition_session_lease is None # noqa: SLF001
def test_start_cleanup_failure_retains_lease_and_marks_side_effect_unknown(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
def fail_receiver_start(
_host: str,
out_dir: Path,
*,
duration_seconds: float | None,
project_name: str,
recover_connection: Callable[[int], str] | None = None,
) -> None:
assert duration_seconds is None
assert project_name == PROJECT_NAME
assert recover_connection is None
out_dir.mkdir()
raise RuntimeError("synthetic receiver start failure")
monkeypatch.setattr(runtime, "start_live", fail_receiver_start)
camera_arm_calls: list[Path] = []
monkeypatch.setattr(
service,
"_arm_camera_recording",
lambda out_dir, **_kwargs: camera_arm_calls.append(out_dir),
)
monkeypatch.setattr(facade_module, "seal_capture_clock", lambda _capture_root: None)
runtime.stop_error = RuntimeError("synthetic cleanup timeout")
with pytest.raises(RuntimeError, match="synthetic receiver start failure"):
service.start_acquisition(_start_request(acquisition_id=acquisition_id))
state = service.state()
operation = next(item for item in state["operations"] if item["action"] == "acquisition.start")
assert state["acquisition"]["state"] == "failed"
assert operation["status"] == "failed"
assert operation["error"]["side_effect_status"] == "unknown"
assert service._acquisition_session_lease is not None # noqa: SLF001
assert camera_arm_calls == []
runtime.stop_error = None
service.stop()
assert service._acquisition_session_lease is None # noqa: SLF001
def test_receiver_completion_without_point_data_fails_start_operation(tmp_path: Path) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
duration_seconds=60,
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
service.start_acquisition(_start_request(acquisition_id=acquisition_id))
runtime.phase = "idle"
runtime.source_mode = "idle"
failed = service.state()
assert failed["acquisition"]["state"] == "failed"
assert failed["last_operation"]["status"] == "failed"
assert failed["acquisition"]["result"]["device_state"] == "unknown"
def test_capture_only_stop_never_claims_that_physical_k1_stopped(tmp_path: Path) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
duration_seconds=60,
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
service.start_acquisition(_start_request(acquisition_id=acquisition_id))
stopped = service.stop_acquisition(
_stop_request(acquisition_id=acquisition_id, mode="capture-only")
)
assert runtime.stop_calls == 1
assert stopped["acquisition"]["state"] == "completed"
assert stopped["acquisition"]["result"] == {
"receiver_stopped": True,
"device_stop": "unknown",
}
operations = {item["action"]: item for item in stopped["operations"]}
assert operations["acquisition.start"]["status"] == "cancelled"
assert operations["acquisition.stop"]["status"] == "succeeded"
def test_stop_seals_session_clock_after_camera_and_runtime_before_lease_release(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
out_dir = tmp_path / "evidence-session"
out_dir.mkdir()
service._acquisition_out_dir = out_dir # noqa: SLF001
events: list[object] = []
monkeypatch.setattr(
service.camera_preview,
"stop_recording",
lambda **_kwargs: events.append("camera"),
)
monkeypatch.setattr(runtime, "stop", lambda: events.append("runtime"))
monkeypatch.setattr(
facade_module,
"seal_capture_clock",
lambda capture_root: events.append(("seal", capture_root)),
)
class Lease:
def release(self) -> None:
events.append("lease")
service._acquisition_session_lease = Lease() # type: ignore[assignment] # noqa: SLF001
service._stop_acquisition_sources( # noqa: SLF001
camera_status="complete",
camera_failure_code=None,
)
assert events == [
"camera",
"runtime",
("seal", out_dir / "captures" / "mqtt_live"),
"lease",
]
def test_stop_timeout_retains_lease_and_blocks_replacement_acquisition(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
service.start_acquisition(_start_request(acquisition_id=acquisition_id))
out_dir = service._acquisition_out_dir # noqa: SLF001
assert out_dir is not None
out_dir.mkdir()
seal_calls: list[Path] = []
monkeypatch.setattr(
facade_module,
"seal_capture_clock",
lambda capture_root: seal_calls.append(capture_root),
)
runtime.stop_error = RuntimeError("synthetic stop timeout")
with pytest.raises(RuntimeError, match="synthetic stop timeout"):
service.stop_acquisition(_stop_request(acquisition_id=acquisition_id, mode="capture-only"))
assert seal_calls == []
assert service._acquisition_session_lease is not None # noqa: SLF001
assert service.state()["acquisition"]["cleanup_pending"] is True
with pytest.raises(RuntimeError, match="evidence-сессия"):
service.prepare_acquisition(
_prepare_request(
project_name="replacement",
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
runtime.stop_error = None
retried = service.stop()
assert retried["acquisition"]["state"] == "failed"
assert len(seal_calls) == 1
assert service._acquisition_session_lease is None # noqa: SLF001
assert retried["acquisition"]["cleanup_pending"] is False
replacement = service.prepare_acquisition(
_prepare_request(
project_name="replacement",
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
assert replacement["acquisition"]["state"] == "prepared"
def test_replay_rejects_retained_failed_acquisition_lease(
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
service.start_acquisition(_start_request(acquisition_id=acquisition_id))
runtime.stop_error = RuntimeError("synthetic stop timeout")
with pytest.raises(RuntimeError, match="synthetic stop timeout"):
service.stop_acquisition(_stop_request(acquisition_id=acquisition_id, mode="capture-only"))
with pytest.raises(RuntimeError, match="не запечатана"):
service.start_replay("sessions/fixture.k1mqtt", speed=1.0, loop=False)
runtime.stop_error = None
service.stop()
def test_new_explicit_stop_retries_retained_terminal_cleanup(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
service.start_acquisition(_start_request(acquisition_id=acquisition_id))
out_dir = service._acquisition_out_dir # noqa: SLF001
assert out_dir is not None
out_dir.mkdir()
seal_calls: list[Path] = []
monkeypatch.setattr(
facade_module,
"seal_capture_clock",
lambda capture_root: seal_calls.append(capture_root),
)
runtime.stop_error = RuntimeError("synthetic stop timeout")
with pytest.raises(RuntimeError, match="synthetic stop timeout"):
service.stop_acquisition(_stop_request(acquisition_id=acquisition_id, mode="capture-only"))
runtime.stop_error = None
recovered = service.stop_acquisition(
_stop_request(
acquisition_id=acquisition_id,
mode="capture-only",
idempotency_key="retry-retained-cleanup",
)
)
retry_operation = recovered["last_operation"]
assert retry_operation["status"] == "succeeded"
assert retry_operation["stage_code"] == "retained-cleanup-completed"
assert retry_operation["result"]["device_stop"] == "unknown"
assert len(seal_calls) == 1
assert service._acquisition_session_lease is None # noqa: SLF001
def test_natural_receiver_completion_fails_acquisition_when_session_clock_cannot_seal(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
service.start_acquisition(_start_request(acquisition_id=acquisition_id))
runtime.pcl_frames = 1
service.state()
out_dir = service._acquisition_out_dir # noqa: SLF001
assert out_dir is not None
out_dir.mkdir()
monkeypatch.setattr(
facade_module,
"seal_capture_clock",
lambda _capture_root: (_ for _ in ()).throw(RuntimeError("synthetic seal failure")),
)
runtime.phase = "idle"
runtime.source_mode = "idle"
with pytest.raises(RuntimeError, match="synthetic seal failure"):
service.state()
assert service._acquisition is not None # noqa: SLF001
assert service._acquisition.state == "failed" # noqa: SLF001
def test_natural_receiver_completion_reserves_finalization_before_reentrant_callback(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
service.start_acquisition(_start_request(acquisition_id=acquisition_id))
runtime.pcl_frames = 1
service.state()
out_dir = service._acquisition_out_dir # noqa: SLF001
assert out_dir is not None
out_dir.mkdir()
events: list[str] = []
def reentrant_camera_stop(**_kwargs: object) -> None:
events.append("camera")
nested = service.state()
assert nested["acquisition"]["state"] == "finalizing"
monkeypatch.setattr(service.camera_preview, "stop_recording", reentrant_camera_stop)
monkeypatch.setattr(
facade_module,
"seal_capture_clock",
lambda _capture_root: events.append("seal"),
)
runtime.phase = "idle"
runtime.source_mode = "idle"
completed = service.state()
assert completed["acquisition"]["state"] == "completed"
assert events == ["camera", "seal"]
def test_graceful_stop_waits_for_explicit_operator_confirmation(tmp_path: Path) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
duration_seconds=60,
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
service.start_acquisition(_start_request(acquisition_id=acquisition_id))
runtime.mark_ready()
service.state()
runtime.pcl_frames = 1
acquiring = service.state()
assert acquiring["acquisition"]["state"] == "acquiring"
awaiting = service.stop_acquisition(
_stop_request(acquisition_id=acquisition_id, mode="graceful")
)
operation_id = awaiting["last_operation"]["operation_id"]
assert runtime.stop_calls == 0
assert awaiting["acquisition"]["state"] == "awaiting_external_stop"
assert awaiting["last_operation"]["status"] == "operator_action_required"
retried = service.stop_acquisition(
_stop_request(
acquisition_id=acquisition_id,
operation_id=operation_id,
mode="graceful",
)
)
assert retried["acquisition"]["state"] == "awaiting_external_stop"
assert retried["last_operation"]["operation_id"] == operation_id
assert retried["last_operation"]["status"] == "operator_action_required"
with pytest.raises(ValueError, match="исходную stop-operation"):
service.stop_acquisition(
_stop_request(
acquisition_id=acquisition_id,
mode="graceful",
operator_confirmed=True,
)
)
completed = service.stop_acquisition(
_stop_request(
acquisition_id=acquisition_id,
operation_id=operation_id,
mode="graceful",
operator_confirmed=True,
)
)
assert runtime.stop_calls == 1
assert completed["acquisition"]["result"]["device_stop"] == "operator-confirmed"
stop_operations = [
item for item in completed["operations"] if item["action"] == "acquisition.stop"
]
assert len(stop_operations) == 1
assert stop_operations[0]["operation_id"] == operation_id
assert stop_operations[0]["status"] == "succeeded"
def test_graceful_stop_retry_by_idempotency_key_reuses_original_operation(
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
service.start_acquisition(_start_request(acquisition_id=acquisition_id))
runtime.mark_ready()
service.state()
runtime.pcl_frames = 1
service.state()
first = service.stop_acquisition(
_stop_request(
acquisition_id=acquisition_id,
idempotency_key="graceful-stop-once",
mode="graceful",
)
)
first_operation_id = first["last_operation"]["operation_id"]
retried = service.stop_acquisition(
_stop_request(
acquisition_id=acquisition_id,
idempotency_key="graceful-stop-once",
mode="graceful",
)
)
assert retried["last_operation"]["operation_id"] == first_operation_id
assert retried["last_operation"]["status"] == "operator_action_required"
assert (
len([item for item in retried["operations"] if item["action"] == "acquisition.stop"]) == 1
)
def test_unrelated_graceful_stop_is_rejected_while_confirmation_is_pending(
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
service.start_acquisition(_start_request(acquisition_id=acquisition_id))
runtime.mark_ready()
service.state()
runtime.pcl_frames = 1
service.state()
first = service.stop_acquisition(_stop_request(acquisition_id=acquisition_id, mode="graceful"))
expected_operation_id = first["last_operation"]["operation_id"]
with pytest.raises(ValueError, match="уже ожидает"):
service.stop_acquisition(
_stop_request(
acquisition_id=acquisition_id,
idempotency_key="unrelated-stop-request",
mode="graceful",
)
)
original = next(
item
for item in service.state()["operations"]
if item["operation_id"] == expected_operation_id
)
assert original["status"] == "operator_action_required"
def test_graceful_stop_is_rejected_until_point_data_confirms_acquisition(
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
service.start_acquisition(_start_request(acquisition_id=acquisition_id))
with pytest.raises(ValueError, match="подтверждённого потока point cloud"):
service.stop_acquisition(_stop_request(acquisition_id=acquisition_id, mode="graceful"))
state = service.state()
assert runtime.stop_calls == 0
assert state["acquisition"]["state"] == "starting"
assert state["last_operation"]["action"] == "acquisition.start"
assert state["last_operation"]["status"] == "running"
@pytest.mark.parametrize("evidence_policy", ["best-effort", "disabled"])
def test_prepare_rejects_unsupported_evidence_policies(
tmp_path: Path,
evidence_policy: str,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
with pytest.raises(ValueError, match="evidence_policy=required"):
service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
evidence_policy=evidence_policy, # type: ignore[arg-type]
compatibility_attestation=ATTESTATION,
)
)
assert service.state()["compatibility"]["profile_id"] is None
@pytest.mark.parametrize(
"requested_streams",
[
DEFAULT_LIVE_STREAMS[:-1],
(*DEFAULT_LIVE_STREAMS, DEFAULT_LIVE_STREAMS[0]),
],
)
def test_prepare_rejects_stream_subsets_and_duplicates(
tmp_path: Path,
requested_streams: tuple[str, ...],
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
with pytest.raises(ValueError, match="полный проверенный набор"):
service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
requested_streams=requested_streams, # type: ignore[arg-type]
compatibility_attestation=ATTESTATION,
)
)
def test_exact_profile_is_inactive_until_selected_for_live_device_info_verification(
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
initial = service.state()
assert initial["compatibility"] == {
"profile_id": None,
"decision": "unknown",
"permitted_mode": "evidence-only",
"firmware_claim": "exact-3.0.2-profile-not-selected",
"attestation": None,
"vendor_writes_enabled": False,
"camera_preview": "unverified",
}
assert initial["device_calibration"]["compatibility_profile_id"] is None
attested = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
assert attested["compatibility"]["profile_id"] == XGRIDS_K1_COMPATIBILITY_PROFILE_ID
assert attested["compatibility"]["decision"] == "limited"
assert attested["compatibility"]["attestation"]["basis"] == (
"selected-profile-live-device-info-required"
)
assert attested["device_session"]["compatibility_profile_id"] == (
XGRIDS_K1_COMPATIBILITY_PROFILE_ID
)
def test_prepare_rejects_device_ap_without_completed_quick_connect(tmp_path: Path) -> None:
service, _ = service_with_fake_runtime(tmp_path)
with pytest.raises(ValueError, match="connection flow"):
service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.56.1",
compatibility_attestation=QUICK_CONNECT_ATTESTATION,
)
)
state = service.state()
assert state["device_ref"] is None
assert state["compatibility"]["profile_id"] is None
def test_runtime_error_terminalizes_pending_graceful_stop(tmp_path: Path) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
service.start_acquisition(_start_request(acquisition_id=acquisition_id))
runtime.mark_ready()
service.state()
runtime.pcl_frames = 1
service.state()
awaiting = service.stop_acquisition(
_stop_request(acquisition_id=acquisition_id, mode="graceful")
)
stop_operation_id = awaiting["last_operation"]["operation_id"]
runtime.phase = "error"
failed = service.state()
stop_operation = next(
item for item in failed["operations"] if item["operation_id"] == stop_operation_id
)
assert failed["acquisition"]["state"] == "failed"
assert stop_operation["status"] == "failed"
assert stop_operation["error"]["side_effect_status"] == "unknown"
assert failed["source_mode"] == "idle"
assert failed["phase"] != "error"
assert runtime.stop_calls == 1
def test_receiver_completion_terminalizes_unconfirmed_graceful_stop(
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
service.start_acquisition(_start_request(acquisition_id=acquisition_id))
runtime.mark_ready()
service.state()
runtime.pcl_frames = 1
service.state()
awaiting = service.stop_acquisition(
_stop_request(acquisition_id=acquisition_id, mode="graceful")
)
stop_operation_id = awaiting["last_operation"]["operation_id"]
runtime.phase = "idle"
runtime.source_mode = "idle"
runtime.source_ready = False
failed = service.state()
stop_operation = next(
item for item in failed["operations"] if item["operation_id"] == stop_operation_id
)
assert failed["acquisition"]["state"] == "failed"
assert failed["acquisition"]["result"] == {
"receiver_stopped": True,
"device_state": "unknown",
}
assert stop_operation["status"] == "failed"
assert stop_operation["error"]["code"] == ("receiver-completed-before-device-stop-confirmation")
def test_unconfirmed_stop_operation_terminalizes_before_clock_seal_error(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
service.start_acquisition(_start_request(acquisition_id=acquisition_id))
runtime.pcl_frames = 1
service.state()
awaiting = service.stop_acquisition(
_stop_request(acquisition_id=acquisition_id, mode="graceful")
)
stop_operation_id = awaiting["last_operation"]["operation_id"]
out_dir = service._acquisition_out_dir # noqa: SLF001
assert out_dir is not None
out_dir.mkdir()
monkeypatch.setattr(
facade_module,
"seal_capture_clock",
lambda _capture_root: (_ for _ in ()).throw(RuntimeError("synthetic seal failure")),
)
runtime.phase = "idle"
runtime.source_mode = "idle"
with pytest.raises(RuntimeError, match="synthetic seal failure"):
service.state()
state = service.state()
stop_operation = next(
item for item in state["operations"] if item["operation_id"] == stop_operation_id
)
assert state["acquisition"]["state"] == "failed"
assert stop_operation["status"] == "failed"
assert service._acquisition_session_lease is not None # noqa: SLF001
monkeypatch.setattr(facade_module, "seal_capture_clock", lambda _capture_root: None)
service.stop()
def test_abort_failure_terminalizes_acquisition_and_pending_start(tmp_path: Path) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
service.start_acquisition(_start_request(acquisition_id=acquisition_id))
runtime.stop_error = RuntimeError("synthetic receiver stop failure")
with pytest.raises(RuntimeError, match="synthetic receiver stop failure"):
service.abort_acquisition(_abort_request(acquisition_id=acquisition_id))
state = service.state()
operations = {item["action"]: item for item in state["operations"]}
assert state["acquisition"]["state"] == "failed"
assert state["acquisition"]["result"] == {
"receiver_stopped": False,
"device_state": "unknown",
}
assert operations["acquisition.start"]["status"] == "cancelled"
assert operations["acquisition.abort"]["status"] == "failed"
assert state["source_mode"] == "live"
def test_abort_reserves_stopping_before_reentrant_runtime_callback(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
service.start_acquisition(_start_request(acquisition_id=acquisition_id))
runtime.pcl_frames = 1
service.state()
out_dir = service._acquisition_out_dir # noqa: SLF001
assert out_dir is not None
out_dir.mkdir()
events: list[str] = []
monkeypatch.setattr(
service.camera_preview,
"stop_recording",
lambda **_kwargs: events.append("camera"),
)
def reentrant_runtime_stop() -> None:
events.append("runtime")
runtime.phase = "idle"
runtime.source_mode = "idle"
nested = service.state()
assert nested["acquisition"]["state"] == "stopping"
monkeypatch.setattr(runtime, "stop", reentrant_runtime_stop)
monkeypatch.setattr(
facade_module,
"seal_capture_clock",
lambda _capture_root: events.append("seal"),
)
aborted = service.abort_acquisition(_abort_request(acquisition_id=acquisition_id))
assert aborted["acquisition"]["state"] == "aborted"
assert events == ["camera", "runtime", "seal"]
assert service._acquisition_session_lease is None # noqa: SLF001
def test_clean_close_seals_and_cancels_pending_start_operation(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
service.start_acquisition(_start_request(acquisition_id=acquisition_id))
out_dir = service._acquisition_out_dir # noqa: SLF001
assert out_dir is not None
out_dir.mkdir()
events: list[str] = []
monkeypatch.setattr(
service.camera_preview,
"close",
lambda: events.append("camera"),
)
def close_runtime() -> None:
events.append("runtime")
runtime.phase = "idle"
runtime.source_mode = "idle"
monkeypatch.setattr(runtime, "close", close_runtime)
monkeypatch.setattr(
facade_module,
"seal_capture_clock",
lambda _capture_root: events.append("seal"),
)
service.close()
state = service.state()
start_operation = next(
item for item in state["operations"] if item["action"] == "acquisition.start"
)
assert state["acquisition"]["state"] == "interrupted"
assert start_operation["status"] == "cancelled"
assert events == ["camera", "runtime", "seal"]
assert service._acquisition_session_lease is None # noqa: SLF001
def test_clean_close_cancels_pending_external_stop_operation(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
service.start_acquisition(_start_request(acquisition_id=acquisition_id))
runtime.pcl_frames = 1
service.state()
awaiting = service.stop_acquisition(
_stop_request(acquisition_id=acquisition_id, mode="graceful")
)
stop_operation_id = awaiting["last_operation"]["operation_id"]
monkeypatch.setattr(service.camera_preview, "close", lambda: None)
monkeypatch.setattr(runtime, "close", lambda: runtime.stop())
service.close()
state = service.state()
stop_operation = next(
item for item in state["operations"] if item["operation_id"] == stop_operation_id
)
assert state["acquisition"]["state"] == "interrupted"
assert stop_operation["status"] == "cancelled"
assert all(
item["status"] not in {"accepted", "running", "operator_action_required"}
for item in state["operations"]
if item["action"].startswith("acquisition.")
)
@pytest.mark.parametrize("cleanup_failure", [False, True], ids=["clean", "cleanup-failed"])
def test_close_settles_exact_prepared_stop_as_not_dispatched_after_worker_retirement(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
cleanup_failure: bool,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(service, runtime)
service.stop_acquisition(fixture.request)
monkeypatch.setattr(service.camera_preview, "close", lambda: None)
if cleanup_failure:
monkeypatch.setattr(
runtime,
"close",
lambda: (_ for _ in ()).throw(RuntimeError("synthetic shutdown cleanup failure")),
)
else:
monkeypatch.setattr(runtime, "close", runtime.stop)
if cleanup_failure:
with pytest.raises(RuntimeError, match="synthetic shutdown cleanup failure"):
service.close()
else:
service.close()
operation = service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert operation.status == "failed"
assert operation.stage_code == "physical-stop-classified-not-dispatched"
assert operation.error is not None
assert operation.error["side_effect_status"] == "none"
assert operation.error["physical_command_sent"] is False
assert operation.error["automatic_replay_allowed"] is False
record = fixture.ledger.snapshot().record
assert record is not None and record.stage == "prepared"
def test_close_never_classifies_stop_none_after_dispatch_boundary(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(service, runtime)
service.stop_acquisition(fixture.request)
dispatch = ApplicationMqttPublishEvidence(
operation_key="modeling:stop",
topic=fixture.envelope.topic,
payload_sha256=fixture.envelope.payload_sha256,
qos=2,
retain=False,
packet_id=None,
)
assert service._k1_command_dispatch_gate.acquire(blocking=False) # noqa: SLF001
try:
fixture.coordinator.publish_dispatching(dispatch)
finally:
service._k1_command_dispatch_gate.release() # noqa: SLF001
monkeypatch.setattr(service.camera_preview, "close", lambda: None)
monkeypatch.setattr(runtime, "close", runtime.stop)
service.close()
record = fixture.ledger.snapshot().record
assert record is not None and record.stage == "dispatching"
operation = service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert operation.status == "failed"
assert operation.stage_code == "physical-stop-outcome-unknown-local-retirement"
assert operation.error is not None
assert operation.error["side_effect_status"] == "unknown"
assert operation.error["automatic_replay_allowed"] is False
def test_close_with_live_prepared_worker_and_busy_dispatch_gate_stays_conservative(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_real_prepared_stop_dispatch_fixture(service, runtime)
service.stop_acquisition(fixture.request)
monkeypatch.setattr(service.camera_preview, "close", lambda: None)
monkeypatch.setattr(runtime, "close", runtime.stop)
assert service._k1_command_dispatch_gate.acquire(blocking=False) # noqa: SLF001
try:
with pytest.raises(
facade_module.LocalAcquisitionLifecycleError,
match="publish-переходом STOP",
) as raised:
service.close()
finally:
service._k1_command_dispatch_gate.release() # noqa: SLF001
assert raised.value.reason_code == "acquisition-stop-dispatch-retirement-pending"
record = fixture.ledger.snapshot().record
assert record is not None and record.stage == "prepared"
operation = service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert operation.status == "running"
assert operation.stage_code == "awaiting-external-stop"
assert operation.error is None
assert service._acquisition_stop_operation_id == fixture.stop_operation_id # noqa: SLF001
assert service._acquisition is not None # noqa: SLF001
assert service._acquisition.state == "awaiting_external_stop" # noqa: SLF001
assert runtime.stop_calls == 0
def test_close_defers_real_worker_queued_before_dispatch_without_tearing_owner(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
fixture = _install_actual_worker_recovered_stop_fixture(
service,
runtime,
monkeypatch,
)
service.stop_acquisition(fixture.request)
assert fixture.transport.before_transport_guard.wait(3.0)
cleanup_calls: list[str] = []
monkeypatch.setattr(
service.camera_preview,
"close",
lambda: cleanup_calls.append("camera"),
)
monkeypatch.setattr(runtime, "close", lambda: cleanup_calls.append("runtime"))
with pytest.raises(
facade_module.LocalAcquisitionLifecycleError,
match="не завершил PREPARED STOP",
) as raised:
service.close()
assert raised.value.reason_code == "acquisition-stop-worker-retirement-pending"
assert cleanup_calls == []
assert fixture.transport.fake_client_publish_calls == []
assert fixture.transport.publish_attempts == 0
operation = service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert operation.status == "running"
assert operation.error is None
record = fixture.ledger.snapshot().record
assert record is not None and record.stage == "prepared"
assert service._acquisition_stop_operation_id == fixture.stop_operation_id # noqa: SLF001
assert service._acquisition is not None # noqa: SLF001
assert service._acquisition.state == "failed" # noqa: SLF001
assert service._acquisition.result is not None # noqa: SLF001
assert service._acquisition.result["recovery_only"] is True # noqa: SLF001
assert runtime.stop_calls == 0
# The shutdown attempt explicitly failed, so the still-owned operation may
# resume. Its eventual publish is retained as ambiguous evidence, never
# retroactively labelled cancelled or not-dispatched.
fixture.transport.release_fake_publish.set()
fixture.transport.release_transport_guard.set()
closed = _wait_control_state(fixture.control, {"closed"})
assert closed["state"] == "closed"
assert len(fixture.transport.fake_client_publish_calls) == 1
record = fixture.ledger.snapshot().record
assert record is not None and record.stage in {"dispatching", "observing"}
operation = service._operations.get(fixture.stop_operation_id) # noqa: SLF001
assert operation.status == "running"
assert operation.stage_code != "physical-stop-classified-not-dispatched"
def test_close_failure_fails_pending_operation_and_retains_lease(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
service.start_acquisition(_start_request(acquisition_id=acquisition_id))
monkeypatch.setattr(service.camera_preview, "close", lambda: None)
monkeypatch.setattr(
runtime,
"close",
lambda: (_ for _ in ()).throw(RuntimeError("synthetic close timeout")),
)
with pytest.raises(RuntimeError, match="synthetic close timeout"):
service.close()
state = service.state()
start_operation = next(
item for item in state["operations"] if item["action"] == "acquisition.start"
)
assert state["acquisition"]["state"] == "failed"
assert start_operation["status"] == "failed"
assert start_operation["error"]["side_effect_status"] == "unknown"
assert service._acquisition_session_lease is not None # noqa: SLF001
runtime.stop_error = None
service.stop()
assert service._acquisition_session_lease is None # noqa: SLF001
def test_replay_is_rejected_during_nonterminal_acquisition(tmp_path: Path) -> None:
service, _ = service_with_fake_runtime(tmp_path)
service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
with pytest.raises(RuntimeError, match="активной acquisition-сессии"):
service.start_replay("sessions/fixture.k1mqtt", speed=1.0, loop=False)
assert service.state()["acquisition"]["state"] == "prepared"
def test_prepare_rejects_active_replay_without_stopping_or_replacing_it(
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
runtime.phase = "replay"
runtime.source_mode = "replay"
runtime.source_ready = True
with pytest.raises(RuntimeError, match="активного live/replay"):
service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
state = service.state()
assert state["acquisition"] is None
assert state["source_mode"] == "replay"
assert runtime.stop_calls == 0
assert service._acquisition_session_lease is None # noqa: SLF001
def test_network_provisioning_is_single_flight_and_secret_is_unwrapped_only_at_boundary(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
monkeypatch.setattr(
facade_module,
"_await_control_endpoint_reachable",
_reachable_control_endpoint,
)
_set_scanned_devices(
service,
[{"device_id": "k1-a"}, {"device_id": "k1-b"}],
)
boundary_calls: list[tuple[str, str, str, str]] = []
async def scenario() -> dict[str, Any]:
entered = asyncio.Event()
release = asyncio.Event()
async def fake_provision(
device_id: str,
ssid: str,
password: str,
*,
write_mode: str,
on_write_dispatch: Callable[[dict[str, Any], str], None] | None = None,
**_: object,
) -> dict[str, Any]:
boundary_calls.append((device_id, ssid, password, write_mode))
_dispatch_test_network_write(on_write_dispatch)
entered.set()
await release.wait()
return {
"started_at_utc": "2026-07-16T12:00:00Z",
"completed_at_utc": "2026-07-16T12:00:01Z",
"profile_id": "xgrids-k1-fw3-wifi-v1",
"outcome": "lan_address_observed",
"observations": [{"status": _wifi_status_read("192.168.1.20")["status"]}],
}
monkeypatch.setattr(facade_module, "provision_wifi_once", fake_provision)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(
facade_module,
"_host_route_class",
lambda _target: "direct-or-routed",
)
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
monkeypatch.setattr(
facade_module,
"_control_endpoint_reachable",
lambda _target: True,
)
first = asyncio.create_task(
service.connect(
_connect_request(
device_id="k1-a",
ssid="lab-network",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
)
)
)
await asyncio.wait_for(entered.wait(), timeout=1.0)
with pytest.raises(facade_module.ProvisioningAlreadyRunning):
await service.connect(
_connect_request(
device_id="k1-b",
ssid="other-network",
password=SecretStr(SECONDARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
)
)
release.set()
return await asyncio.wait_for(first, timeout=1.0)
connected = asyncio.run(scenario())
assert boundary_calls == [("k1-a", "lab-network", PRIMARY_TEST_CREDENTIAL, "with_response")]
assert connected["k1_ip"] == "192.168.1.20"
assert connected["connection_mode"] == "bridge"
assert PRIMARY_TEST_CREDENTIAL not in str(connected)
provision_operations = [
item for item in connected["operations"] if item["action"] == "network.provision"
]
assert len(provision_operations) == 1
assert provision_operations[0]["status"] == "succeeded"
attempt = connected["connection_attempt"]
assert attempt["attempt_id"] == provision_operations[0]["operation_id"]
assert attempt["connection_mode"] == "bridge"
assert attempt["side_effect_status"] == "applied"
assert attempt["safe_next_action"] == "start-acquisition"
assert [event["stage_code"] for event in attempt["timeline"]] == [
"accepted",
"scan-selection-admitted",
"ble-provisioning-write",
"ble-write-dispatched",
"status-observing",
"device-topology-applied",
"host-wifi-switch-not-authorized",
"network-configured",
"accepted",
"host-route-and-control-endpoint",
"device-info-confirmed",
]
diagnostic_bundle = attempt["diagnostic_bundle"]
assert diagnostic_bundle["redacted"] is True
assert diagnostic_bundle["automatic_retry"] is False
assert PRIMARY_TEST_CREDENTIAL not in json.dumps(diagnostic_bundle)
assert "lab-network" not in json.dumps(diagnostic_bundle)
switched = service.select_connection_mode(
DesiredConnectionModeRequest(
connection_mode="quick-connect",
expected_revision=connected["desired_connection_mode_revision"],
)
)
assert switched["connection_lifecycle"]["ready_to_start"] is False
assert switched["connection_attempt"]["status"] == "succeeded"
assert switched["connection_attempt"]["safe_next_action"] == "scan-select-connect"
assert (
switched["connection_attempt"]["diagnostic_bundle"]["attempt"]["safe_next_action"]
== "scan-select-connect"
)
cancelled = service.select_connection_mode(
DesiredConnectionModeRequest(
connection_mode="bridge",
expected_revision=switched["desired_connection_mode_revision"],
)
)
assert cancelled["connection_lifecycle"]["ready_to_start"] is True
assert cancelled["connection_attempt"]["safe_next_action"] == "start-acquisition"
assert (
cancelled["connection_attempt"]["diagnostic_bundle"]["attempt"]["safe_next_action"]
== "start-acquisition"
)
invalidations: list[bool] = []
monkeypatch.setattr(
facade_module,
"invalidate_connected_device_session",
lambda *_args, **_kwargs: invalidations.append(True) or True,
)
lost_path = HostPathProbeResult(
available=False,
fingerprint=None,
interface=None,
source_ipv4=None,
route_class="unavailable",
reason_code="router-link-lost",
)
disconnected = cancelled
for _ in range(3):
service._connection_supervisor.observe_host_path(lost_path) # noqa: SLF001
disconnected = service.state()
assert invalidations == [True]
assert disconnected["connection_lifecycle"]["active_mode"] is None
assert disconnected["connection_lifecycle"]["ready_to_start"] is False
assert disconnected["connection_attempt"]["status"] == "succeeded"
assert disconnected["connection_attempt"]["safe_next_action"] == ("scan-select-connect")
assert (
disconnected["connection_attempt"]["diagnostic_bundle"]["attempt"]["safe_next_action"]
== "scan-select-connect"
)
def test_replay_cannot_start_while_network_transition_owns_lifecycle_gate(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service, device_id="k1-a")
async def scenario() -> None:
entered = asyncio.Event()
release = asyncio.Event()
async def held_network_write(
*_args: object,
on_write_dispatch: Callable[[dict[str, Any], str], None] | None = None,
**_kwargs: object,
) -> dict[str, Any]:
_dispatch_test_network_write(on_write_dispatch)
entered.set()
await release.wait()
return {
"started_at_utc": "2026-08-08T12:00:00Z",
"completed_at_utc": "2026-08-08T12:00:01Z",
"profile_id": "xgrids-k1-fw3-wifi-v1",
"outcome": "lan_address_observed",
"write_mode": "with_response",
"observations": [
{"status": _wifi_status_read("192.168.68.50", device_id="k1-a")["status"]}
],
}
monkeypatch.setattr(facade_module, "provision_wifi_once", held_network_write)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(facade_module, "_host_route_class", lambda _target: "direct-or-routed")
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
monkeypatch.setattr(facade_module, "_control_endpoint_reachable", lambda _target: True)
monkeypatch.setattr(
facade_module,
"_await_control_endpoint_reachable",
_reachable_control_endpoint,
)
network_task = asyncio.create_task(
service.connect(
_connect_request(
device_id="k1-a",
ssid="lab-network",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
)
)
)
await asyncio.wait_for(entered.wait(), timeout=1.0)
with pytest.raises(facade_module.ApplicationControlProcessLeaseUnavailable):
await asyncio.to_thread(
service.start_replay,
"sessions/fixture.k1mqtt",
1.0,
False,
)
assert runtime.phase == "idle"
assert runtime.source_mode == "idle"
release.set()
await asyncio.wait_for(network_task, timeout=1.0)
asyncio.run(scenario())
def test_network_transition_cannot_enter_while_replay_start_owns_lifecycle_gate(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service, device_id="k1-a")
replay_path = service.repository_root / "sessions" / "fixture.k1mqtt"
replay_path.parent.mkdir(parents=True, exist_ok=True)
replay_path.write_bytes(b"fixture")
entered = threading.Event()
release = threading.Event()
def held_replay_start(_path: Path, *, speed: float, loop: bool) -> None:
assert speed == 1.0
assert loop is False
runtime.phase = "replay"
runtime.source_mode = "replay"
entered.set()
assert release.wait(timeout=1.0)
monkeypatch.setattr(runtime, "start_replay", held_replay_start, raising=False)
replay_errors: list[BaseException] = []
def replay_worker() -> None:
try:
service.start_replay(str(replay_path), speed=1.0, loop=False)
except BaseException as exc: # pragma: no cover - assertion captures it below
replay_errors.append(exc)
thread = threading.Thread(target=replay_worker, daemon=True)
thread.start()
assert entered.wait(timeout=1.0)
try:
with pytest.raises(facade_module.NetworkProvisioningConflict) as raised:
asyncio.run(
service.connect(
_connect_request(
device_id="k1-a",
ssid="lab-network",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
)
)
)
assert raised.value.reason_code == "network-provision-lifecycle-busy"
finally:
release.set()
thread.join(timeout=1.0)
assert not thread.is_alive()
assert replay_errors == []
assert runtime.phase == "replay"
assert runtime.source_mode == "replay"
def test_exact_network_idempotency_replay_precedes_expired_candidate_checks(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_devices(service, [{"device_id": "k1-a"}])
monkeypatch.setattr(
facade_module,
"_await_control_endpoint_reachable",
_reachable_control_endpoint,
)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(
facade_module,
"_host_route_class",
lambda _target: "direct-or-routed",
)
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
monkeypatch.setattr(
facade_module,
"_control_endpoint_reachable",
lambda _target: True,
)
writes = 0
async def fake_provision(
*_: object,
on_write_dispatch: Callable[[dict[str, Any], str], None] | None = None,
**__: object,
) -> dict[str, Any]:
nonlocal writes
writes += 1
_dispatch_test_network_write(on_write_dispatch)
return {
"started_at_utc": "2026-08-06T08:00:00Z",
"completed_at_utc": "2026-08-06T08:00:01Z",
"profile_id": "xgrids-k1-fw3-wifi-v1",
"outcome": "lan_address_observed",
"write_mode": "with_response",
"observations": [{"status": _wifi_status_read("192.168.1.20")["status"]}],
}
monkeypatch.setattr(facade_module, "provision_wifi_once", fake_provision)
request = _connect_request(
device_id="k1-a",
ssid="lab-network",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
idempotency_key="one-browser-intent",
)
asyncio.run(service.connect(request))
journal_path = service._require_network_provisioning_idempotency_journal().path # noqa: SLF001
journal_document = journal_path.read_text(encoding="utf-8")
assert "one-browser-intent" not in journal_document
assert "lab-network" not in journal_document
assert PRIMARY_TEST_CREDENTIAL not in journal_document
service._devices = [] # noqa: SLF001
service._ble_device_last_seen_monotonic = {} # noqa: SLF001
service._ble_device_last_seen_suspend_aware = {} # noqa: SLF001
replayed = asyncio.run(service.connect(request))
restarted_service, _ = service_with_fake_runtime(tmp_path)
restarted = asyncio.run(restarted_service.connect(request))
with pytest.raises(NetworkProvisioningIdempotencyConflict):
asyncio.run(
restarted_service.connect(request.model_copy(update={"ssid": "different-network"}))
)
with pytest.raises(NetworkProvisioningIdempotencyConflict):
asyncio.run(
restarted_service.connect(request.model_copy(update={"allow_host_wifi_switch": True}))
)
assert writes == 1
operations = [item for item in replayed["operations"] if item["action"] == "network.provision"]
assert len(operations) == 1
assert operations[0]["status"] == "succeeded"
restarted_operation = next(
item for item in restarted["operations"] if item["action"] == "network.provision"
)
assert restarted_operation["operation_id"] == operations[0]["operation_id"]
assert restarted_operation["status"] == "succeeded"
assert restarted_operation["stage_code"] == "durable-terminal-replay"
assert restarted_operation["result"]["phase"] == "network_applied"
assert restarted_operation["result"]["control_state"] == "unknown"
assert restarted_operation["result"]["replay_binding_available"] is True
assert restarted_operation["result"]["snapshot_runtime_id"] == restarted["snapshot_runtime_id"]
assert restarted_operation["result"]["parent_intent_id"] == restarted_operation["operation_id"]
assert restarted_operation["result"]["transport_ref"] == "k1-a"
assert restarted_operation["result"]["connection_mode"] == "bridge"
assert restarted_operation["result"]["target_ipv4"] == "192.168.1.20"
assert restarted["connection_attempt"]["phase"] == "network_applied"
assert restarted["connection_attempt"]["control_state"] == "unknown"
monkeypatch.setattr(
facade_module,
"_probe_control_endpoint_socket",
lambda _target: facade_module.TcpReachabilityProbeResult(reachable=True),
)
verified = asyncio.run(restarted_service.verify_connection(ConnectionVerifyRequest()))
assert writes == 1
assert verified["last_operation"]["action"] == "connection.verify"
assert verified["last_operation"]["status"] == "succeeded"
assert verified["connection_attempt"]["attempt_id"] == restarted_operation["operation_id"]
assert verified["connection_attempt"]["phase"] == "network_applied"
assert verified["connection_attempt"]["control_state"] == "ready"
assert verified["connection_attempt"]["safe_next_action"] == "start-acquisition"
def test_successful_session_requires_new_scan_generation_before_next_connect(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service, device_id="k1-a")
targets = iter(["192.168.68.50", "192.168.68.51"])
writes = 0
async def successful_write(
*_args: object,
on_write_dispatch: Callable[[dict[str, Any], str], None] | None = None,
**_kwargs: object,
) -> dict[str, Any]:
nonlocal writes
writes += 1
target = next(targets)
_dispatch_test_network_write(on_write_dispatch)
return {
"started_at_utc": "2026-08-08T13:00:00Z",
"completed_at_utc": "2026-08-08T13:00:01Z",
"profile_id": "xgrids-k1-fw3-wifi-v1",
"outcome": "lan_address_observed",
"write_mode": "with_response",
"observations": [{"status": _wifi_status_read(target, device_id="k1-a")["status"]}],
}
monkeypatch.setattr(facade_module, "provision_wifi_once", successful_write)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(facade_module, "_host_route_class", lambda _target: "direct-or-routed")
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
monkeypatch.setattr(facade_module, "_control_endpoint_reachable", lambda _target: True)
monkeypatch.setattr(
facade_module,
"_await_control_endpoint_reachable",
_reachable_control_endpoint,
)
first = asyncio.run(
service.connect(
_connect_request(
device_id="k1-a",
ssid="lab-network",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
)
)
)
first_session = first["device_session"]["device_session_id"]
with pytest.raises(facade_module.NetworkProvisioningConflict) as raised:
asyncio.run(
service.connect(
_connect_request(
device_id="k1-a",
ssid="lab-network",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
)
)
)
assert raised.value.reason_code == "network-provision-candidate-not-fresh"
assert service._device_session_id == first_session # noqa: SLF001
assert service._selected_device_id == "k1-a" # noqa: SLF001
assert writes == 1
service._ble_discovery_generation += 1 # noqa: SLF001
_set_scanned_k1(service, device_id="k1-a")
with pytest.raises(RuntimeError, match="не сообщило адрес"):
asyncio.run(
service.connect(
_connect_request(
device_id="k1-a",
ssid="lab-network",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
expected_discovery_generation=1,
)
)
)
assert service._device_session_id is None # noqa: SLF001
assert service._selected_device_id is None # noqa: SLF001
assert writes == 2
def test_operation_admission_failure_terminalizes_prepared_network_intent(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
def fail_operation_admission(*_args: object, **_kwargs: object) -> object:
raise RuntimeError("synthetic operation journal failure")
monkeypatch.setattr(service._operations, "begin", fail_operation_admission) # noqa: SLF001
request = _connect_request(
device_id="k1-a",
ssid="lab-network",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
idempotency_key="operation-admission-failure",
)
with pytest.raises(RuntimeError, match="operation journal failure"):
asyncio.run(service.connect(request))
snapshot = service._require_network_provisioning_idempotency_journal().snapshot() # noqa: SLF001
assert snapshot.active_record is None
assert len(snapshot.records) == 1
record = snapshot.records[0]
assert record.stage == "terminal"
assert record.terminal is not None
assert record.terminal.outcome == "failed"
assert record.terminal.outcome_code == "network.provision.admission_failed"
assert record.terminal.error_code == "operation-journal-admission-failed"
assert record.terminal.side_effect_status == "none"
assert record.terminal.safe_to_retry is True
def test_live_process_lease_prevents_false_restart_recovery_of_prepared_request(
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
request = _connect_request(
device_id="k1-a",
ssid="lab-network",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
idempotency_key="live-owner-prepared-request",
)
canonical_request = json.dumps(
{
"schema_version": "missioncore.xgrids-k1-network-provision-request/v1",
"device_id": request.device_id,
"ssid": request.ssid,
"password": PRIMARY_TEST_CREDENTIAL,
"connection_mode": request.connection_mode,
"expected_mode_revision": request.expected_mode_revision,
"expected_discovery_generation": request.expected_discovery_generation,
"expected_reconfiguration_revision": (request.expected_reconfiguration_revision),
"expected_reconfiguration_intent_id": (request.expected_reconfiguration_intent_id),
"compatibility_attestation": request.compatibility_attestation.model_dump(mode="json"),
},
ensure_ascii=False,
sort_keys=True,
separators=(",", ":"),
).encode("utf-8")
owner_lease = ApplicationControlProcessLease.acquire(tmp_path)
try:
journal = service._require_network_provisioning_idempotency_journal() # noqa: SLF001
operation_id = "op-11111111-2222-4333-8444-555555555555"
admitted = journal.begin(
idempotency_key=request.idempotency_key,
action=facade_module.ACTION_NETWORK_PROVISION,
operation_id=operation_id,
request_binding_sha256=derive_request_binding_sha256(
request.idempotency_key,
action=facade_module.ACTION_NETWORK_PROVISION,
canonical_request=canonical_request,
),
)
assert admitted.record.stage == "prepared"
competing_service, _ = service_with_fake_runtime(tmp_path)
still_live = journal.snapshot().active_record
assert still_live is not None
assert still_live.operation_id == operation_id
assert still_live.stage == "prepared"
finally:
owner_lease.release()
# The already-running competing facade may take over only after the OS
# lease proves that the original process is gone. It replays a durable,
# no-side-effect terminal result without touching BLE.
replayed = asyncio.run(competing_service.connect(request))
terminal = journal.snapshot().records[-1]
operation = next(
item for item in replayed["operations"] if item["action"] == "network.provision"
)
assert terminal.stage == "terminal"
assert terminal.terminal is not None
assert terminal.terminal.side_effect_status == "none"
assert terminal.terminal.safe_to_retry is True
assert operation["operation_id"] == operation_id
assert operation["status"] == "failed"
assert operation["stage_code"] == "durable-terminal-replay"
@pytest.mark.parametrize("legacy_stage", ["dispatching", "observing"])
def test_restart_terminalizes_dispatched_legacy_ledger_as_interrupted_audit(
tmp_path: Path,
legacy_stage: str,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
operation_id = f"legacy-{legacy_stage}-operation"
_seed_legacy_network_mutation_without_idempotency(
service,
operation_id=operation_id,
stage=legacy_stage,
)
journal_path = service._require_network_provisioning_idempotency_journal().path # noqa: SLF001
assert not journal_path.exists()
restarted, _ = service_with_fake_runtime(tmp_path)
idempotency = restarted._require_network_provisioning_idempotency_journal().snapshot() # noqa: SLF001
assert idempotency.status == "ready"
assert idempotency.active_record is None
terminal = idempotency.records[-1]
assert terminal.operation_id == operation_id
assert terminal.action == facade_module.ACTION_NETWORK_PROVISION
assert terminal.stage == "terminal"
assert terminal.terminal is not None
assert terminal.terminal.outcome_code == "network.provision.interrupted"
assert terminal.terminal.side_effect_status == "reconciled"
assert terminal.terminal.safe_to_retry is False
persisted = journal_path.read_text(encoding="utf-8")
assert "test-ble-transport" not in persisted
assert "WIFI_CLIENT" not in persisted
assert '"stage":"terminal"' in persisted
state = restarted.state()
assert state["network_mutation_ledger"]["stage"] == "resolved"
assert state["network_mutation_ledger"]["resolution"] == "interrupted"
assert state["network_write_reconciliation"] is None
def test_restart_resolves_legacy_prepared_as_not_dispatched_without_adoption(
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_seed_legacy_network_mutation_without_idempotency(
service,
operation_id="legacy-prepared-operation",
stage="prepared",
)
journal_path = service._require_network_provisioning_idempotency_journal().path # noqa: SLF001
assert not journal_path.exists()
restarted, _ = service_with_fake_runtime(tmp_path)
state = restarted.state()
assert state["network_mutation_ledger"]["status"] == "resolved"
assert state["network_mutation_ledger"]["resolution"] == "not-dispatched"
assert state["network_write_reconciliation"] is None
assert state["network_provisioning_idempotency"]["status"] == "empty"
assert state["network_provisioning_idempotency"]["active_operation_id"] is None
assert not journal_path.exists()
def test_restart_supersedes_cross_journal_mismatch_without_blocking_new_intent(
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_seed_unresolved_network_mutation(
service,
operation_id="legacy-ledger-operation",
idempotency_operation_id="other-idempotency-operation",
)
restarted, _ = service_with_fake_runtime(tmp_path)
state = restarted.state()
assert state["network_mutation_ledger"]["status"] == "resolved"
assert state["network_mutation_ledger"]["operation_id"] == "legacy-ledger-operation"
assert state["network_mutation_ledger"]["resolution"] == "interrupted"
assert state["network_provisioning_idempotency"]["status"] == "ready"
assert state["network_provisioning_idempotency"]["reason_code"] is None
assert state["network_provisioning_idempotency"]["mutation_allowed"] is True
def test_new_explicit_intent_is_admitted_after_interrupted_dispatched_session(
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_seed_unresolved_network_mutation(
service,
operation_id="interrupted-operation",
idempotency_operation_id="interrupted-operation",
)
journal = service._require_network_provisioning_idempotency_journal() # noqa: SLF001
recovered = facade_module._recover_network_provisioning_under_exclusive_process_lease( # noqa: SLF001
network_ledger=service._network_mutation_ledger, # noqa: SLF001
idempotency_journal=journal,
)
admitted = journal.begin(
idempotency_key="new-explicit-operator-intent",
action=facade_module.ACTION_NETWORK_PROVISION,
operation_id="new-explicit-operation",
request_binding_sha256="a" * 64,
)
assert recovered.status == "resolved"
assert recovered.record is not None
assert recovered.record.resolution == "interrupted"
assert admitted.disposition == "admitted"
assert admitted.record.stage == "prepared"
def test_restart_legacy_adoption_preserves_corrupt_journal_and_fails_closed(
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_seed_legacy_network_mutation_without_idempotency(service)
journal_path = service._require_network_provisioning_idempotency_journal().path # noqa: SLF001
corrupt = b'{"schema_version":"corrupt","records":[]}\n'
journal_path.write_bytes(corrupt)
journal_path.chmod(0o600)
restarted, _ = service_with_fake_runtime(tmp_path)
state = restarted.state()
assert journal_path.read_bytes() == corrupt
assert state["network_mutation_ledger"]["status"] == "unresolved"
assert state["network_provisioning_idempotency"]["status"] == "corrupt"
assert state["network_provisioning_idempotency"]["reason_code"] == (
"network-provisioning-idempotency-corrupt"
)
assert state["network_provisioning_idempotency"]["mutation_allowed"] is False
@pytest.mark.parametrize(
"corruption",
[
"wrong-mode",
"oversize",
"symlink",
"ledger-wrong-mode",
"both-corrupt",
"journal-disappeared",
],
)
def test_explicit_connect_quarantines_corrupt_network_audit_without_replay(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
corruption: str,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
journal = service._require_network_provisioning_idempotency_journal() # noqa: SLF001
path = journal.path
ledger_path = service._network_mutation_ledger.path # noqa: SLF001
path.parent.mkdir(parents=True, exist_ok=True)
foreign_target = tmp_path / "foreign-audit-target"
if corruption in {"wrong-mode", "both-corrupt", "journal-disappeared"}:
path.write_text('{"schema_version":"wrong"}\n', encoding="utf-8")
path.chmod(0o644)
elif corruption == "oversize":
path.write_bytes(b"x" * (300 * 1024))
path.chmod(0o600)
else:
if corruption == "symlink":
foreign_target.write_text("foreign", encoding="utf-8")
path.unlink(missing_ok=True)
path.symlink_to(foreign_target)
if corruption in {"ledger-wrong-mode", "both-corrupt"}:
ledger_path.write_text('{"schema_version":"wrong"}\n', encoding="utf-8")
ledger_path.chmod(0o644)
if corruption == "journal-disappeared":
service._network_provisioning_idempotency_journal = None # noqa: SLF001
service._network_provisioning_idempotency_reason = ( # noqa: SLF001
"network-provisioning-idempotency-corrupt"
)
path.unlink()
_set_scanned_k1(service, device_id="k1-a")
async def successful_write(
*_args: object,
on_write_dispatch: Callable[[dict[str, Any], str], None] | None = None,
**_kwargs: object,
) -> dict[str, Any]:
_dispatch_test_network_write(on_write_dispatch)
return {
"started_at_utc": "2026-08-08T10:00:00Z",
"completed_at_utc": "2026-08-08T10:00:01Z",
"profile_id": "xgrids-k1-fw3-wifi-v1",
"outcome": "lan_address_observed",
"write_mode": "with_response",
"baseline_status": _wifi_status_read(None, device_id="k1-a")["status"],
"observations": [
{"status": _wifi_status_read("192.168.68.50", device_id="k1-a")["status"]}
],
}
monkeypatch.setattr(facade_module, "provision_wifi_once", successful_write)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(facade_module, "_host_route_class", lambda _target: "direct-or-routed")
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
monkeypatch.setattr(facade_module, "_control_endpoint_reachable", lambda _target: True)
monkeypatch.setattr(
facade_module,
"_await_control_endpoint_reachable",
_reachable_control_endpoint,
)
state = asyncio.run(
service.connect(
_connect_request(
device_id="k1-a",
ssid="lab-network",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
)
)
)
assert state["connection_mode"] == "bridge"
assert state["network_provisioning_idempotency"]["status"] == "ready"
journal_quarantines = list(path.parent.glob(f"{path.name}.corrupt-*"))
ledger_quarantines = list(ledger_path.parent.glob(f"{ledger_path.name}.corrupt-*"))
assert len(journal_quarantines) == (
1
if corruption
in {
"wrong-mode",
"oversize",
"symlink",
"both-corrupt",
}
else 0
)
assert len(ledger_quarantines) == (
1
if corruption
in {
"ledger-wrong-mode",
"both-corrupt",
}
else 0
)
if corruption == "symlink":
assert foreign_target.read_text(encoding="utf-8") == "foreign"
def test_cancelled_bridge_write_is_audited_and_new_explicit_intent_writes_once(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_devices(service, [{"device_id": "k1-a"}])
calls = 0
async def scenario() -> None:
entered = asyncio.Event()
async def cancelled_write(
*_: object,
on_write_dispatch: Callable[[dict[str, Any], str], None] | None = None,
**__: object,
) -> dict[str, Any]:
nonlocal calls
calls += 1
assert on_write_dispatch is not None
on_write_dispatch(
_wifi_status_read(None, device_id="k1-a")["status"],
"with_response",
)
entered.set()
try:
await asyncio.Event().wait()
except asyncio.CancelledError as exc:
exc.operation_stage = "gatt-write" # type: ignore[attr-defined]
exc.device_write_attempted = True # type: ignore[attr-defined]
exc.device_write_confirmed = True # type: ignore[attr-defined]
raise
async def successful_second_write(
*_: object,
on_write_dispatch: Callable[[dict[str, Any], str], None] | None = None,
**__: object,
) -> dict[str, Any]:
nonlocal calls
calls += 1
_dispatch_test_network_write(on_write_dispatch)
return {
"started_at_utc": "2026-08-08T10:00:00Z",
"completed_at_utc": "2026-08-08T10:00:01Z",
"profile_id": "xgrids-k1-fw3-wifi-v1",
"outcome": "lan_address_observed",
"write_mode": "with_response",
"baseline_status": _wifi_status_read(None, device_id="k1-a")["status"],
"observations": [
{"status": _wifi_status_read("192.168.68.50", device_id="k1-a")["status"]}
],
}
monkeypatch.setattr(facade_module, "provision_wifi_once", cancelled_write)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(facade_module, "_host_route_class", lambda _target: "direct-or-routed")
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
monkeypatch.setattr(facade_module, "_control_endpoint_reachable", lambda _target: True)
monkeypatch.setattr(
facade_module,
"_await_control_endpoint_reachable",
_reachable_control_endpoint,
)
first = asyncio.create_task(
service.connect(
_connect_request(
device_id="k1-a",
ssid="lab-network",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
idempotency_key="cancelled-write-1",
)
)
)
await entered.wait()
first.cancel()
with pytest.raises(asyncio.CancelledError):
await first
monkeypatch.setattr(facade_module, "provision_wifi_once", successful_second_write)
second = await service.connect(
_connect_request(
device_id="k1-a",
ssid="lab-network",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
idempotency_key="cancelled-write-2",
)
)
assert second["connection_mode"] == "bridge"
assert second["k1_ip"] == "192.168.68.50"
asyncio.run(scenario())
state = service.state()
operation = next(
item for item in state["operations"] if item["idempotency_key"] == "cancelled-write-1"
)
assert operation["status"] == "failed"
assert operation["error"]["code"] == "CancelledError"
assert operation["error"]["side_effect_status"] == "unknown"
assert operation["error"]["safe_to_retry"] is False
assert state["network_mutation_ledger"]["status"] == "resolved"
assert state["network_write_reconciliation"] is None
assert calls == 2
def test_cancelled_host_mutation_finishes_before_ownership_is_released() -> None:
started = threading.Event()
release = threading.Event()
completed = threading.Event()
def bounded_host_mutation() -> str:
started.set()
assert release.wait(timeout=2.0)
completed.set()
return "completed"
async def scenario() -> None:
task = asyncio.create_task(
facade_module._run_blocking_operation_without_abandonment( # noqa: SLF001
bounded_host_mutation
)
)
for _ in range(100):
if started.is_set():
break
await asyncio.sleep(0.01)
assert started.is_set()
task.cancel()
await asyncio.sleep(0.01)
assert not task.done()
task.cancel()
await asyncio.sleep(0.01)
assert not task.done()
release.set()
with pytest.raises(asyncio.CancelledError):
await task
assert completed.is_set()
asyncio.run(scenario())
def test_bridge_network_change_retires_terminal_acquisition_and_receiver_error(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
monkeypatch.setattr(
facade_module,
"_await_control_endpoint_reachable",
_reachable_control_endpoint,
)
_set_scanned_devices(service, [{"device_id": "k1-a", "name": "XGR-TEST-A"}])
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
service.abort_acquisition(
_abort_request(
acquisition_id=prepared["acquisition"]["acquisition_id"],
)
)
runtime.phase = "error"
runtime.source_mode = "live"
stop_calls_before_connect = runtime.stop_calls
async def fake_provision(
*_: object,
on_write_dispatch: Callable[[dict[str, Any], str], None] | None = None,
**__: object,
) -> dict[str, Any]:
_dispatch_test_network_write(on_write_dispatch)
return {
"started_at_utc": "2026-07-28T18:11:37Z",
"completed_at_utc": "2026-07-28T18:11:44Z",
"profile_id": "xgrids-k1-fw3-wifi-v1",
"outcome": "lan_address_observed",
"observations": [{"status": _wifi_status_read("192.168.1.20")["status"]}],
}
monkeypatch.setattr(facade_module, "provision_wifi_once", fake_provision)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(
facade_module,
"_host_route_class",
lambda _target: "direct-or-routed",
)
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
monkeypatch.setattr(
facade_module,
"_control_endpoint_reachable",
lambda _target: True,
)
connected = asyncio.run(
service.connect(
_connect_request(
device_id="k1-a",
ssid="lab-network",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
connection_mode="bridge",
compatibility_attestation=ATTESTATION,
)
)
)
assert connected["connection_mode"] == "bridge"
assert connected["k1_ip"] == "192.168.1.20"
assert connected["acquisition"] is None
assert connected["source_mode"] == "idle"
assert connected["phase"] == "connected"
assert connected["device_session"]["connectivity"] == "connected"
assert connected["connection_verification"]["lease_state"] == "reachable"
assert connected["connection_lifecycle"]["connection_ready"] is True
assert runtime.stop_calls == stop_calls_before_connect + 1
def test_bridge_provisioning_reports_host_route_mismatch_without_hiding_device_success(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_devices(service, [{"device_id": "k1-a", "name": "XGR-TEST-A"}])
host_associations: list[tuple[str, str]] = []
async def fake_provision(
*_: object,
on_write_dispatch: Callable[[dict[str, Any], str], None] | None = None,
**__: object,
) -> dict[str, Any]:
_dispatch_test_network_write(on_write_dispatch)
return {
"started_at_utc": "2026-07-28T19:43:03Z",
"completed_at_utc": "2026-07-28T19:43:16Z",
"profile_id": "xgrids-k1-fw3-wifi-v1",
"outcome": "lan_address_observed",
"observations": [{"status": _wifi_status_read("192.168.68.50")["status"]}],
}
monkeypatch.setattr(facade_module, "provision_wifi_once", fake_provision)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(facade_module, "_host_route_class", lambda _target: "tunnel")
monkeypatch.setattr(facade_module, "_inspect_host_path", _tunnel_host_path)
monkeypatch.setattr(
facade_module,
"_await_control_endpoint_reachable",
_unreachable_control_endpoint,
)
monkeypatch.setattr(facade_module, "_control_endpoint_reachable", lambda _target: False)
monkeypatch.setattr(
facade_module,
"associate_with_ephemeral_wifi_credentials_once",
lambda _helper, ssid, password, **_kwargs: (
host_associations.append((ssid, password))
or {
"adapter": "CoreWLAN",
"outcome": "associated",
"already_associated": False,
"scan_attempt_count": 1,
"scan_elapsed_ms": 20,
}
),
)
async def connect_and_join_read_only_continuation() -> dict[str, Any]:
await service.connect(
_connect_request(
device_id="k1-a",
ssid="lab-router",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
connection_mode="bridge",
compatibility_attestation=ATTESTATION,
allow_host_wifi_switch=True,
)
)
with service._lock: # noqa: SLF001
task = service._control_bootstrap_continuation_task # noqa: SLF001
if task is not None:
with pytest.raises(facade_module.ConnectionVerificationError):
await task
return service.state()
connected = asyncio.run(connect_and_join_read_only_continuation())
assert host_associations == [("lab-router", PRIMARY_TEST_CREDENTIAL)]
assert connected["k1_ip"] == "192.168.68.50"
assert connected["phase"] == "device_selected"
assert connected["device_session"]["connectivity"] == "offline"
assert connected["connection_verification"] == {
"status": "endpoint-unreachable",
"lease_state": "configured-unverified",
"lease_generation": connected["connection_supervisor"]["lease"]["generation"],
"endpoint_validation": "host-route",
"network_reachability": "unreachable",
"reason_code": "tcp-endpoint-unreachable",
"host_route_class": "tunnel",
"write_performed": True,
"observed_at": connected["connection_verification"]["observed_at"],
"supervisor_revision": connected["connection_verification"]["supervisor_revision"],
}
operation = next(
item for item in connected["operations"] if item["action"] == "network.provision"
)
assert operation["status"] == "succeeded"
assert operation["result"]["phase"] == "network_applied"
assert operation["result"]["host_wifi_switch_authorized"] is True
assert operation["result"]["host_route_ready"] is None
assert operation["result"]["host_route_class"] is None
assert connected["connection_attempt"]["phase"] == "network_applied"
assert connected["connection_attempt"]["control_state"] == "control_not_ready"
def test_bridge_provisioning_separates_address_from_reachable_control_endpoint(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_devices(service, [{"device_id": "k1-a", "name": "XGR-TEST-A"}])
async def fake_provision(
*_: object,
on_write_dispatch: Callable[[dict[str, Any], str], None] | None = None,
**__: object,
) -> dict[str, Any]:
_dispatch_test_network_write(on_write_dispatch)
return {
"started_at_utc": "2026-08-06T10:00:00Z",
"completed_at_utc": "2026-08-06T10:00:01Z",
"profile_id": "xgrids-k1-fw3-wifi-v1",
"outcome": "lan_address_observed",
"write_mode": "with_response",
"observations": [{"status": _wifi_status_read("192.168.68.50")["status"]}],
}
monkeypatch.setattr(facade_module, "provision_wifi_once", fake_provision)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(facade_module, "_host_route_class", lambda _target: "direct-or-routed")
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
monkeypatch.setattr(
facade_module,
"_await_control_endpoint_reachable",
_unreachable_control_endpoint,
)
monkeypatch.setattr(
facade_module,
"_control_endpoint_reachable",
lambda _target: False,
)
async def connect_and_join_read_only_continuation() -> dict[str, Any]:
await service.connect(
_connect_request(
device_id="k1-a",
ssid="lab-router",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
connection_mode="bridge",
compatibility_attestation=ATTESTATION,
)
)
with service._lock: # noqa: SLF001
task = service._control_bootstrap_continuation_task # noqa: SLF001
if task is not None:
with pytest.raises(facade_module.ConnectionVerificationError):
await task
return service.state()
state = asyncio.run(connect_and_join_read_only_continuation())
assert state["k1_ip"] == "192.168.68.50"
assert state["phase"] == "device_selected"
assert state["device_session"]["connectivity"] == "offline"
assert state["connection_verification"] == {
"status": "endpoint-unreachable",
"lease_state": "configured-unverified",
"lease_generation": state["connection_supervisor"]["lease"]["generation"],
"endpoint_validation": "provisioning-status+mqtt-tcp-connect",
"network_reachability": "unreachable",
"reason_code": "tcp-endpoint-unreachable",
"host_route_class": "direct-or-routed",
"write_performed": True,
"observed_at": state["connection_verification"]["observed_at"],
"supervisor_revision": state["connection_verification"]["supervisor_revision"],
}
operation = next(item for item in state["operations"] if item["action"] == "network.provision")
assert operation["status"] == "succeeded"
assert operation["stage_code"] == "network-configured"
assert operation["result"]["phase"] == "network_applied"
assert operation["result"]["control_state"] == "unknown"
assert operation["result"]["control_endpoint_reachable"] is None
assert state["connection_attempt"]["phase"] == "network_applied"
assert state["connection_attempt"]["control_state"] == "control_not_ready"
def test_quick_connect_activates_the_device_ap_then_associates_the_host(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
mode_revision = _select_connection_mode(service, "quick-connect")
monkeypatch.setattr(
facade_module,
"_await_control_endpoint_reachable",
_reachable_control_endpoint,
)
monkeypatch.setattr(
facade_module,
"_control_endpoint_reachable",
lambda _target: True,
)
_set_scanned_devices(service, [{"device_id": "k1-a", "name": "XGR-TEST-A"}])
activation_calls: list[tuple[str, str]] = []
association_calls: list[tuple[Path, str, str]] = []
ble_session_open = False
monkeypatch.setattr(
facade_module,
"ensure_wifi_profile_from_credential_source",
lambda *_args, **_kwargs: {
"schema_version": 1,
"adapter": "macOS Keychain",
"available": True,
"profile_enrolled": True,
"credential_source": "exact-firmware-profile",
},
)
@asynccontextmanager
async def fake_activation_session(
device_id: str,
*,
write_mode: str,
on_write_dispatch: Callable[[dict[str, Any], str], None] | None = None,
**_: object,
) -> AsyncIterator[dict[str, Any]]:
nonlocal ble_session_open
activation_calls.append((device_id, write_mode))
_dispatch_test_network_write(on_write_dispatch)
ble_session_open = True
try:
yield {
"profile_id": "xgrids-k1-fw3-quick-connect-ap-v1",
"started_at_utc": "2026-07-19T15:00:00Z",
"completed_at_utc": "2026-07-19T15:00:01Z",
"outcome": "ap_ready_observed",
"ready_observed": True,
"write_performed": True,
"write_mode": "with_response",
"observations": [{"status": _ap_ready_wifi_status()}],
}
finally:
ble_session_open = False
def fake_associate(
helper_path: Path,
profile_id: str,
expected_ssid: str,
**_: object,
) -> dict[str, Any]:
assert ble_session_open
association_calls.append((helper_path, profile_id, expected_ssid))
return {
"schema_version": 1,
"adapter": "CoreWLAN",
"outcome": "associated",
"already_associated": False,
"profile_enrolled": True,
"scan_attempt_count": 2,
"scan_elapsed_ms": 900,
"credential_source": "exact-firmware-profile",
}
async def forbidden_provisioning_write(*_: object, **__: object) -> dict[str, Any]:
raise AssertionError("Quick Connect must not send router credentials to the K1")
monkeypatch.setattr(
facade_module,
"device_ap_activation_session",
fake_activation_session,
)
monkeypatch.setattr(facade_module, "associate_with_wifi_profile_once", fake_associate)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_provisioning_write)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
state = asyncio.run(
service.connect(
_connect_request(
device_id="k1-a",
connection_mode="quick-connect",
compatibility_attestation=QUICK_CONNECT_ATTESTATION,
expected_mode_revision=mode_revision,
)
)
)
assert activation_calls == [("k1-a", "with_response")]
assert not ble_session_open
assert len(association_calls) == 1
assert association_calls[0][0].name == "associate_wifi.swift"
assert association_calls[0][1] == facade_module.quick_connect_host_profile_id("XGR-TEST-A")
assert association_calls[0][2] == "XGR-TEST-A"
assert state["connection_mode"] == "quick-connect"
assert state["k1_ip"] == "192.168.56.1"
assert state["compatibility"]["attestation"]["topology"] == "device-ap"
quick_sessions = sorted(service.evidence_root.glob("*viewer_k1_ap_association*"))
assert len(quick_sessions) == 1
assert not (quick_sessions[0] / "provisioning.sensitive.json").exists()
redacted_manifest = (quick_sessions[0] / "manifest.redacted.json").read_text(encoding="utf-8")
assert PRIMARY_TEST_CREDENTIAL not in redacted_manifest
assert "host_wifi_profile_id" in redacted_manifest
assert '"host_wifi_profile_ready_before_device_write": true' in redacted_manifest
assert '"credentials_resolved_by_plugin": true' in redacted_manifest
assert "credential_provider_id" in redacted_manifest
assert "device_ap_activation_profile_id" in redacted_manifest
assert (quick_sessions[0] / "ap-activation.redacted.json").exists()
assert (
service._camera_target_for_session( # noqa: SLF001
state["device_session"]["device_session_id"]
)
== "192.168.56.1"
)
assert state["connection_lifecycle"]["connection_ready"] is True
control = state["application_control_session"]
workspace = service.enter_application_workspace(
EnterApplicationWorkspaceRequest(
operator_confirmed=True,
expected_session_generation=control["session_generation"],
expected_state_revision=control["state_revision"],
)
)
workspace_control = workspace["application_control_session"]
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
compatibility_attestation=QUICK_CONNECT_ATTESTATION,
expected_control_session_generation=workspace_control["session_generation"],
expected_control_state_revision=workspace_control["state_revision"],
)
)
assert prepared["acquisition"]["target_host"] == "192.168.56.1"
def test_quick_connect_read_only_verify_requires_fresh_ble_status_without_write(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_select_connection_mode(service, "quick-connect")
_seed_supervised_connection(
service,
target_ipv4="192.168.56.1",
connection_mode="quick-connect",
transport_ref="k1-a",
logical_device_id="device-k1-a",
with_control=False,
)
service._device_session_id = "session-k1-a" # noqa: SLF001
_set_scanned_k1(service, device_id="k1-a")
supervisor_generation = service._connection_supervisor.snapshot().lease.generation # noqa: SLF001
service._connection_lease_generation = supervisor_generation # noqa: SLF001
service._connection_verification = { # noqa: SLF001
"status": "endpoint-unreachable",
"lease_state": "disconnected",
"lease_generation": supervisor_generation,
"endpoint_validation": "provisioning-status+mqtt-tcp-connect",
"network_reachability": "unreachable",
"reason_code": "connection_lease_endpoint_unreachable_after_provision",
"write_performed": True,
"observed_at": "2026-08-06T10:00:00Z",
}
monkeypatch.setattr(
facade_module,
"_control_endpoint_reachable",
lambda _target: True,
)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(facade_module, "_host_route_class", lambda _target: "device-ap")
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
status_reads: list[tuple[str, float, bool]] = []
async def exact_ble_status(
device_id: str,
*,
timeout_seconds: float,
rediscover: bool,
**_: object,
) -> dict[str, Any]:
status_reads.append((device_id, timeout_seconds, rediscover))
status = _wifi_status_read("192.168.56.1", device_id=device_id)
status["status"] = _ap_ready_wifi_status()
return status
monkeypatch.setattr(facade_module, "read_wifi_status_once", exact_ble_status)
state = asyncio.run(
service.verify_connection(
ConnectionVerifyRequest(
device_id="k1-a",
compatibility_attestation=QUICK_CONNECT_ATTESTATION,
expected_discovery_generation=0,
)
)
)
assert status_reads == [("k1-a", 20.0, False)]
assert state["connection_verification"]["lease_state"] == "reachable"
assert state["connection_verification"]["network_reachability"] == "reachable"
assert state["device_session"]["connectivity"] == "connected"
assert state["connection_verification"]["write_performed"] is False
assert state["connection_verification"]["endpoint_validation"] == (
"ble-wifi-status-read+mqtt-tcp-connect"
)
assert state["last_operation"]["action"] == "connection.verify"
assert state["last_operation"]["status"] == "succeeded"
def test_direct_connect_reuses_the_reviewed_ble_provisioning_frame(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
mode_revision = _select_connection_mode(service, "direct-connect")
monkeypatch.setattr(
facade_module,
"_await_control_endpoint_reachable",
_reachable_control_endpoint,
)
_set_scanned_devices(service, [{"device_id": "k1-a", "name": "XGR-TEST-A"}])
provisioning_calls: list[tuple[str, str, str]] = []
async def fake_provision(
device_id: str,
ssid: str,
password: str,
*,
on_write_dispatch: Callable[[dict[str, Any], str], None] | None = None,
**_: object,
) -> dict[str, Any]:
provisioning_calls.append((device_id, ssid, password))
_dispatch_test_network_write(on_write_dispatch)
return {
"started_at_utc": "2026-07-19T01:00:00Z",
"completed_at_utc": "2026-07-19T01:00:01Z",
"profile_id": "xgrids-k1-fw3-wifi-v1",
"outcome": "lan_address_observed",
"observations": [{"status": _wifi_status_read("172.20.10.2")["status"]}],
}
def forbidden_host_association(*_: object, **__: object) -> dict[str, Any]:
raise AssertionError("Direct Connect must not switch the host Wi-Fi network")
monkeypatch.setattr(facade_module, "provision_wifi_once", fake_provision)
monkeypatch.setattr(
facade_module,
"associate_with_wifi_profile_once",
forbidden_host_association,
)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(
facade_module,
"_host_route_class",
lambda _target: "direct-or-routed",
)
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
monkeypatch.setattr(
facade_module,
"_control_endpoint_reachable",
lambda _target: True,
)
state = asyncio.run(
service.connect(
_connect_request(
device_id="k1-a",
ssid="controller-hotspot",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
connection_mode="direct-connect",
compatibility_attestation=DIRECT_CONNECT_ATTESTATION,
expected_mode_revision=mode_revision,
)
)
)
assert provisioning_calls == [("k1-a", "controller-hotspot", PRIMARY_TEST_CREDENTIAL)]
assert state["connection_mode"] == "direct-connect"
assert state["k1_ip"] == "172.20.10.2"
assert state["compatibility"]["attestation"]["topology"] == ("controller-hotspot")
def test_quick_connect_missing_credential_provider_stops_before_ap_write(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
mode_revision = _select_connection_mode(service, "quick-connect")
_set_scanned_devices(service, [{"device_id": "k1-a", "name": "XGR-TEST-A"}])
service._selected_device_id = "previous-k1" # noqa: SLF001
service._k1_ip = "192.168.1.20" # noqa: SLF001
service._connection_mode = "bridge" # noqa: SLF001
monkeypatch.setattr(
facade_module,
"ensure_wifi_profile_from_credential_source",
lambda *_args, **_kwargs: {
"schema_version": 1,
"adapter": "macOS Keychain",
"available": False,
"profile_enrolled": False,
"credential_source": None,
},
)
@asynccontextmanager
async def forbidden_activation(
*_args: object, **_kwargs: object
) -> AsyncIterator[dict[str, Any]]:
raise AssertionError("missing host credential must stop before the K1 AP write")
yield {}
monkeypatch.setattr(
facade_module,
"device_ap_activation_session",
forbidden_activation,
)
with pytest.raises(RuntimeError, match="credential-source-unavailable"):
asyncio.run(
service.connect(
_connect_request(
device_id="k1-a",
connection_mode="quick-connect",
compatibility_attestation=QUICK_CONNECT_ATTESTATION,
expected_mode_revision=mode_revision,
)
)
)
state = service.state()
assert state["selected_device_id"] is None
assert state["device_session"] is None
assert state["k1_ip"] is None
assert state["connection_mode"] is None
failed_sessions = list(service.evidence_root.glob("*viewer_k1_ap_association*"))
assert len(failed_sessions) == 1
assert (failed_sessions[0] / "operation-reservation.redacted.json").exists()
assert not (failed_sessions[0] / "ap-activation.redacted.json").exists()
operation = next(item for item in state["operations"] if item["action"] == "network.provision")
assert operation["status"] == "failed"
assert operation["error"]["side_effect_status"] == "none"
assert operation["error"]["safe_to_retry"] is True
def test_quick_connect_does_not_start_host_wifi_without_ap_ready_flag(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
mode_revision = _select_connection_mode(service, "quick-connect")
_set_scanned_devices(service, [{"device_id": "k1-a", "name": "XGR-TEST-A"}])
monkeypatch.setattr(
facade_module,
"ensure_wifi_profile_from_credential_source",
lambda *_args, **_kwargs: {
"schema_version": 1,
"adapter": "macOS Keychain",
"available": True,
"profile_enrolled": False,
"credential_source": "exact-firmware-profile",
},
)
@asynccontextmanager
async def not_ready_session(
*_: object,
on_write_dispatch: Callable[[dict[str, Any], str], None] | None = None,
**__: object,
) -> AsyncIterator[dict[str, Any]]:
assert on_write_dispatch is not None
on_write_dispatch(
_wifi_status_read(None, device_id="k1-a")["status"],
"with_response",
)
yield {
"profile_id": "xgrids-k1-fw3-quick-connect-ap-v1",
"started_at_utc": "2026-07-19T15:00:00Z",
"completed_at_utc": "2026-07-19T15:00:15Z",
"outcome": "no_status_change_before_timeout",
"ready_observed": False,
"write_performed": True,
"write_mode": "with_response",
"observations": [],
}
def forbidden_association(*_: object, **__: object) -> dict[str, Any]:
raise AssertionError("host Wi-Fi must wait for the canonical AP-ready flag")
monkeypatch.setattr(
facade_module,
"device_ap_activation_session",
not_ready_session,
)
monkeypatch.setattr(
facade_module,
"associate_with_wifi_profile_once",
forbidden_association,
)
with pytest.raises(RuntimeError, match="не подтвердил готовность"):
asyncio.run(
service.connect(
_connect_request(
device_id="k1-a",
connection_mode="quick-connect",
compatibility_attestation=QUICK_CONNECT_ATTESTATION,
expected_mode_revision=mode_revision,
)
)
)
quick_sessions = sorted(service.evidence_root.glob("*viewer_k1_ap_association*"))
assert len(quick_sessions) == 1
assert (quick_sessions[0] / "ap-activation.redacted.json").exists()
assert not (quick_sessions[0] / "manifest.redacted.json").exists()
reconciliation = service.state()["network_write_reconciliation"]
assert reconciliation["transport_ref"] == "k1-a"
assert reconciliation["status"] == "previous-session-result-unknown"
assert reconciliation["reason_code"] == "network-mutation-audit-open"
assert reconciliation["blocks_new_explicit_intent"] is False
assert reconciliation["operation_stage"] == "observing"
assert reconciliation["scope"] == "durable-ledger"
assert reconciliation["ledger_revision"] == 3
def test_quick_connect_unchanged_ready_baseline_does_not_associate_host_wifi(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
mode_revision = _select_connection_mode(service, "quick-connect")
_set_scanned_devices(service, [{"device_id": "k1-a", "name": "XGR-TEST-A"}])
monkeypatch.setattr(
facade_module,
"ensure_wifi_profile_from_credential_source",
lambda *_args, **_kwargs: {
"schema_version": 1,
"adapter": "macOS Keychain",
"available": True,
"profile_enrolled": True,
"credential_source": "exact-firmware-profile",
},
)
ready_status = _ap_ready_wifi_status()
@asynccontextmanager
async def unchanged_ready_session(
*_: object,
on_write_dispatch: Callable[[dict[str, Any], str], None] | None = None,
**__: object,
) -> AsyncIterator[dict[str, Any]]:
assert on_write_dispatch is not None
on_write_dispatch(ready_status, "with_response")
yield {
"profile_id": "xgrids-k1-fw3-quick-connect-ap-v1",
"started_at_utc": "2026-08-06T10:00:00Z",
"completed_at_utc": "2026-08-06T10:00:01Z",
"outcome": "ap_ready_observed",
"baseline_status": ready_status,
"ready_observed": True,
"write_performed": True,
"write_mode": "with_response",
"observations": [{"status": ready_status}],
}
def forbidden_association(*_: object, **__: object) -> dict[str, Any]:
raise AssertionError("baseline/previous AP-ready is not authority to mutate host Wi-Fi")
monkeypatch.setattr(
facade_module,
"device_ap_activation_session",
unchanged_ready_session,
)
monkeypatch.setattr(
facade_module,
"associate_with_wifi_profile_once",
forbidden_association,
)
with pytest.raises(facade_module.NetworkProvisioningConflict) as raised:
asyncio.run(
service.connect(
_connect_request(
device_id="k1-a",
connection_mode="quick-connect",
compatibility_attestation=QUICK_CONNECT_ATTESTATION,
expected_mode_revision=mode_revision,
)
)
)
assert raised.value.reason_code == (
"network-provision-target-not-distinguishable-from-baseline"
)
state = service.state()
assert state["network_mutation_ledger"]["status"] == "unresolved"
assert state["network_mutation_ledger"]["stage"] == "observing"
assert state["semantic_topology_store"]["status"] == "empty"
assert state["selected_device_id"] is None
operation = next(item for item in state["operations"] if item["action"] == "network.provision")
assert operation["error"]["code"] == (
"network-provision-target-not-distinguishable-from-baseline"
)
assert operation["error"]["side_effect_status"] == "unknown"
assert operation["error"]["safe_to_retry"] is False
def test_failed_connection_change_revokes_the_previous_route(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
mode_revision = _select_connection_mode(service, "quick-connect")
_set_scanned_devices(service, [{"device_id": "k1-a", "name": "XGR-TEST-A"}])
service._selected_device_id = "previous-k1" # noqa: SLF001
service._k1_ip = "192.168.1.20" # noqa: SLF001
service._connection_mode = "bridge" # noqa: SLF001
monkeypatch.setattr(
facade_module,
"ensure_wifi_profile_from_credential_source",
lambda *_args, **_kwargs: {
"schema_version": 1,
"adapter": "macOS Keychain",
"available": True,
"profile_enrolled": False,
"credential_source": "exact-firmware-profile",
},
)
@asynccontextmanager
async def fake_activation_session(
*_: object,
on_write_dispatch: Callable[[dict[str, Any], str], None] | None = None,
**__: object,
) -> AsyncIterator[dict[str, Any]]:
assert on_write_dispatch is not None
on_write_dispatch(
_wifi_status_read(None, device_id="k1-a")["status"],
"with_response",
)
yield {
"profile_id": "xgrids-k1-fw3-quick-connect-ap-v1",
"started_at_utc": "2026-07-19T15:00:00Z",
"completed_at_utc": "2026-07-19T15:00:01Z",
"outcome": "ap_ready_observed",
"ready_observed": True,
"write_performed": True,
"write_mode": "with_response",
"observations": [{"status": _ap_ready_wifi_status()}],
}
def failed_association(*_: object, **__: object) -> dict[str, Any]:
raise facade_module.HostWifiProfileError(
"network-not-found",
scan_attempt_count=4,
scan_elapsed_ms=15014,
)
monkeypatch.setattr(
facade_module,
"device_ap_activation_session",
fake_activation_session,
)
monkeypatch.setattr(facade_module, "associate_with_wifi_profile_once", failed_association)
with pytest.raises(RuntimeError, match="network-not-found"):
asyncio.run(
service.connect(
_connect_request(
device_id="k1-a",
connection_mode="quick-connect",
compatibility_attestation=QUICK_CONNECT_ATTESTATION,
expected_mode_revision=mode_revision,
)
)
)
state = service.state()
# AP-ready is a semantic device-side commit. Host association may fail,
# but the old Bridge route must not be resurrected and the new Quick
# topology remains explicit, configured and offline.
assert state["selected_device_id"] == "k1-a"
assert state["k1_ip"] == facade_module.AP_FALLBACK_IPV4
assert state["connection_mode"] == "quick-connect"
assert state["compatibility"]["attestation"]["topology"] == "device-ap"
assert state["device_session"]["connectivity"] == "offline"
assert state["connection_verification"]["lease_state"] == ("configured-unverified")
operation = next(item for item in state["operations"] if item["action"] == "network.provision")
assert operation["error"]["scan_attempt_count"] == 4
assert operation["error"]["scan_elapsed_ms"] == 15014
quick_sessions = sorted(service.evidence_root.glob("*viewer_k1_ap_association*"))
failure_evidence = json.loads(
(quick_sessions[0] / "host-wifi-association.redacted.json").read_text(encoding="utf-8")
)
assert failure_evidence["reason_code"] == "network-not-found"
assert failure_evidence["scan_attempt_count"] == 4
assert failure_evidence["scan_elapsed_ms"] == 15014
def test_quick_connect_keychain_failure_after_ap_write_preserves_side_effect_facts(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
mode_revision = _select_connection_mode(service, "quick-connect")
_set_scanned_devices(service, [{"device_id": "k1-a", "name": "XGR-TEST-A"}])
monkeypatch.setattr(
facade_module,
"ensure_wifi_profile_from_credential_source",
lambda *_args, **_kwargs: {
"schema_version": 1,
"adapter": "macOS Keychain",
"available": True,
"profile_enrolled": False,
"credential_source": "exact-firmware-profile",
},
)
@asynccontextmanager
async def ready_activation(
*_: object,
on_write_dispatch: Callable[[dict[str, Any], str], None] | None = None,
**__: object,
) -> AsyncIterator[dict[str, Any]]:
assert on_write_dispatch is not None
on_write_dispatch(
_wifi_status_read(None, device_id="k1-a")["status"],
"with_response",
)
yield {
"profile_id": "xgrids-k1-fw3-quick-connect-ap-v1",
"started_at_utc": "2026-08-06T10:00:00Z",
"completed_at_utc": "2026-08-06T10:00:01Z",
"outcome": "ap_ready_observed",
"ready_observed": True,
"write_performed": True,
"write_mode": "with_response",
"observations": [{"status": _ap_ready_wifi_status()}],
}
def failed_post_write_profile_read(*_: object, **__: object) -> dict[str, Any]:
raise facade_module.HostWifiProfileError(
"keychain-authorization-required",
)
monkeypatch.setattr(facade_module, "device_ap_activation_session", ready_activation)
monkeypatch.setattr(
facade_module,
"associate_with_wifi_profile_once",
failed_post_write_profile_read,
)
with pytest.raises(
facade_module.HostWifiProfileError,
match="keychain-authorization-required",
):
asyncio.run(
service.connect(
_connect_request(
device_id="k1-a",
connection_mode="quick-connect",
compatibility_attestation=QUICK_CONNECT_ATTESTATION,
expected_mode_revision=mode_revision,
)
)
)
state = service.state()
operation = next(item for item in state["operations"] if item["action"] == "network.provision")
assert operation["stage_code"] == "host-wifi-association-failed"
assert operation["error"]["code"] == "keychain-authorization-required"
assert operation["error"]["host_diagnostic"]["code"] == ("host.keychain.interaction-required")
assert operation["error"]["side_effect_status"] == "confirmed"
assert operation["error"]["safe_to_retry"] is False
assert "helper_stage" not in operation["error"]
assert state["network_write_reconciliation"] is None
def test_network_provisioning_rejects_an_ipv4_owned_by_the_local_host(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
caplog: pytest.LogCaptureFixture,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_devices(service, [{"device_id": "k1-a"}])
async def fake_provision(
*_: object,
on_write_dispatch: Callable[[dict[str, Any], str], None] | None = None,
**__: object,
) -> dict[str, Any]:
baseline_status = _ap_ready_wifi_status()
assert on_write_dispatch is not None
on_write_dispatch(baseline_status, "with_response")
return {
"started_at_utc": "2026-07-18T15:19:25Z",
"completed_at_utc": "2026-07-18T15:19:26Z",
"profile_id": "xgrids-k1-fw3-wifi-v1",
"outcome": "lan_address_observed",
"write_mode": "with_response",
"baseline_status": baseline_status,
"observations": [
{
"status": {
"mode": "WIFI_CLIENT",
"ipv4": "10.255.254.51",
"status_code": 1,
"reserved": 0,
}
}
],
}
monkeypatch.setattr(facade_module, "provision_wifi_once", fake_provision)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: True)
with (
caplog.at_level(logging.ERROR, logger=facade_module.__name__),
pytest.raises(RuntimeError, match="уже принадлежит этому компьютеру"),
):
asyncio.run(
service.connect(
_connect_request(
device_id="k1-a",
ssid="lab-network",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
)
)
)
state = service.state()
# The K1 already confirmed its new device-side topology before the local
# address conflict was discovered. Preserve that truth while withholding
# all host/control authority.
assert state["selected_device_id"] == "k1-a"
assert state["k1_ip"] == "10.255.254.51"
assert state["connection_mode"] == "bridge"
assert state["device_session"]["connectivity"] == "offline"
operation = next(item for item in state["operations"] if item["action"] == "network.provision")
assert operation["status"] == "failed"
assert operation["error"]["safe_to_retry"] is False
assert operation["error"]["side_effect_status"] == "confirmed"
assert state["network_write_reconciliation"] is None
failure_log = next(
record
for record in caplog.records
if getattr(record, "event_code", None) == "k1_network_provision_failed"
)
assert failure_log.operation_stage == "ble-provisioning-write"
assert failure_log.connection_mode == "bridge"
assert failure_log.error_code == "RuntimeError"
assert failure_log.safe_to_retry is False
assert failure_log.side_effect_status == "confirmed"
assert failure_log.network_change_attempted is True
assert failure_log.device_write_attempted is True
assert failure_log.device_write_confirmed is True
assert PRIMARY_TEST_CREDENTIAL not in caplog.text
assert "lab-network" not in caplog.text
def test_ambiguous_ble_write_is_audit_only_for_next_explicit_intent(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
caplog: pytest.LogCaptureFixture,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_devices(service, [{"device_id": "k1-a"}])
calls = 0
async def ambiguous_write(
*_: object,
on_write_dispatch: Callable[[dict[str, Any], str], None] | None = None,
**__: object,
) -> dict[str, Any]:
nonlocal calls
calls += 1
assert on_write_dispatch is not None
on_write_dispatch(
_wifi_status_read(None, device_id="k1-a")["status"],
"with_response",
)
exc = RuntimeError("synthetic transport failure")
exc.operation_stage = "gatt-write" # type: ignore[attr-defined]
exc.device_write_attempted = True # type: ignore[attr-defined]
exc.device_write_confirmed = False # type: ignore[attr-defined]
exc.att_error_code = 4 # type: ignore[attr-defined]
exc.att_error_name = "INVALID_PDU" # type: ignore[attr-defined]
exc.resolved_write_mode = "with_response" # type: ignore[attr-defined]
exc.write_characteristic_properties = ( # type: ignore[attr-defined]
"notify",
"write",
)
exc.max_write_without_response_size = 253 # type: ignore[attr-defined]
exc.frame_length = 99 # type: ignore[attr-defined]
raise exc
monkeypatch.setattr(facade_module, "provision_wifi_once", ambiguous_write)
with (
caplog.at_level(logging.ERROR, logger=facade_module.__name__),
pytest.raises(RuntimeError, match="synthetic transport failure"),
):
asyncio.run(
service.connect(
_connect_request(
device_id="k1-a",
ssid="lab-network",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
idempotency_key="ambiguous-write-1",
)
)
)
state = service.state()
operation = next(item for item in state["operations"] if item["action"] == "network.provision")
assert operation["error"] == {
"category": "device",
"code": "RuntimeError",
"retryable": False,
"safe_to_retry": False,
"side_effect_status": "unknown",
"operation_stage": "gatt-write",
"device_write_attempted": True,
"device_write_confirmed": False,
"ble_att_error_code": 4,
"ble_att_error_name": "INVALID_PDU",
"resolved_write_mode": "with_response",
"max_write_without_response_size": 253,
"frame_length": 99,
"write_characteristic_properties": ["notify", "write"],
}
audit = state["network_write_reconciliation"]
assert audit["status"] == "previous-session-result-unknown"
assert audit["operation_id"] == operation["operation_id"]
assert audit["reason_code"] == "network-mutation-audit-open"
assert audit["required_action"] == "none"
assert audit["blocks_new_explicit_intent"] is False
failure_log = next(
record
for record in caplog.records
if getattr(record, "event_code", None) == "k1_network_provision_failed"
)
assert failure_log.resolved_write_mode == "with_response"
assert failure_log.write_characteristic_properties == ["notify", "write"]
assert failure_log.max_write_without_response_size == 253
assert failure_log.frame_length == 99
restarted_service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_devices(restarted_service, [{"device_id": "k1-a"}])
restarted_state = restarted_service.state()
assert restarted_state["network_write_reconciliation"] is None
assert restarted_state["network_mutation_ledger"]["mutation_allowed"] is True
assert restarted_state["network_mutation_ledger"]["resolution"] == "interrupted"
assert (
restarted_state["connection_policy"]["actions"]["provision-fresh-device"]["allowed"] is True
)
assert calls == 1
def test_unchanged_status_does_not_confirm_without_response_write(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
caplog: pytest.LogCaptureFixture,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_devices(service, [{"device_id": "k1-a"}])
unchanged_status = _wifi_status_read(None, device_id="k1-a")["status"]
async def unchanged_write(
*_: object,
on_write_dispatch: Callable[[dict[str, Any], str], None] | None = None,
**__: object,
) -> dict[str, Any]:
assert on_write_dispatch is not None
on_write_dispatch(unchanged_status, "without_response")
return {
"started_at_utc": "2026-08-06T10:00:00Z",
"completed_at_utc": "2026-08-06T10:00:01Z",
"profile_id": "xgrids-k1-fw3-wifi-v1",
"outcome": "no_status_change_before_timeout",
"write_mode": "without_response",
"baseline_status": unchanged_status,
"observations": [{"status": unchanged_status}],
}
monkeypatch.setattr(facade_module, "provision_wifi_once", unchanged_write)
with (
caplog.at_level(logging.ERROR, logger=facade_module.__name__),
pytest.raises(RuntimeError, match="не сообщило адрес"),
):
asyncio.run(
service.connect(
_connect_request(
device_id="k1-a",
ssid="lab-network",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
)
)
)
record = next(
item
for item in caplog.records
if getattr(item, "event_code", None) == "k1_network_provision_failed"
)
assert record.device_write_attempted is True
assert record.device_write_confirmed is False
assert record.side_effect_status == "unknown"
fence = service.state()["network_write_reconciliation"]
assert fence is not None
assert fence["transport_ref"] == "k1-a"
assert fence["connection_mode"] == "bridge"
assert fence["operation_stage"] == "observing"
assert fence["reason_code"] == "network-mutation-audit-open"
assert fence["required_action"] == "none"
assert fence["blocks_new_explicit_intent"] is False
assert fence["scope"] == "durable-ledger"
assert fence["ledger_revision"] == 3
ledger = service.state()["network_mutation_ledger"]
assert ledger["status"] == "unresolved"
assert ledger["mutation_allowed"] is True
assert ledger["stage"] == "observing"
assert ledger["revision"] == 3
def test_same_bridge_baseline_does_not_confirm_with_response_write(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_devices(service, [{"device_id": "k1-a"}])
unchanged_status = _wifi_status_read("192.168.68.50", device_id="k1-a")["status"]
async def unchanged_write(
*_: object,
on_write_dispatch: Callable[[dict[str, Any], str], None] | None = None,
**__: object,
) -> dict[str, Any]:
assert on_write_dispatch is not None
on_write_dispatch(unchanged_status, "with_response")
return {
"started_at_utc": "2026-08-06T10:00:00Z",
"completed_at_utc": "2026-08-06T10:00:01Z",
"profile_id": "xgrids-k1-fw3-wifi-v1",
"outcome": "no_status_change_before_timeout",
"write_mode": "with_response",
"baseline_status": unchanged_status,
"observations": [{"status": unchanged_status}],
}
monkeypatch.setattr(facade_module, "provision_wifi_once", unchanged_write)
with pytest.raises(RuntimeError, match="не сообщило адрес"):
asyncio.run(
service.connect(
_connect_request(
device_id="k1-a",
ssid="replacement-network",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
)
)
)
state = service.state()
assert state["network_mutation_ledger"]["status"] == "unresolved"
assert state["network_mutation_ledger"]["stage"] == "observing"
assert state["network_mutation_ledger"]["resolution"] is None
assert state["network_write_reconciliation"] is not None
assert state["semantic_topology_store"]["status"] == "empty"
assert state["selected_device_id"] is None
@pytest.mark.parametrize(
("connection_mode", "attestation", "observed_ipv4"),
[
("bridge", ATTESTATION, "192.168.68.99"),
("direct-connect", DIRECT_CONNECT_ATTESTATION, "172.20.10.2"),
],
)
def test_live_client_baseline_with_different_ipv4_keeps_write_ambiguous(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
connection_mode: NetworkConnectionMode,
attestation: CompatibilityAttestationRequest,
observed_ipv4: str,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
mode_revision = _select_connection_mode(service, connection_mode)
_set_scanned_devices(service, [{"device_id": "k1-a"}])
baseline = _wifi_status_read("192.168.68.40", device_id="k1-a")["status"]
async def changed_client_address(
*_: object,
on_write_dispatch: Callable[[dict[str, Any], str], None] | None = None,
**__: object,
) -> dict[str, Any]:
assert on_write_dispatch is not None
on_write_dispatch(baseline, "with_response")
return {
"started_at_utc": "2026-08-06T10:00:00Z",
"completed_at_utc": "2026-08-06T10:00:01Z",
"profile_id": "xgrids-k1-fw3-wifi-v1",
"outcome": "lan_address_observed",
"write_mode": "with_response",
"baseline_status": baseline,
"observations": [
{
"status": _wifi_status_read(
observed_ipv4,
device_id="k1-a",
)["status"]
}
],
}
monkeypatch.setattr(facade_module, "provision_wifi_once", changed_client_address)
with pytest.raises(RuntimeError, match="не сообщило адрес"):
asyncio.run(
service.connect(
_connect_request(
device_id="k1-a",
ssid="replacement-network",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
connection_mode=connection_mode,
compatibility_attestation=attestation,
expected_mode_revision=mode_revision,
)
)
)
state = service.state()
assert state["network_mutation_ledger"]["status"] == "unresolved"
assert state["network_mutation_ledger"]["stage"] == "observing"
assert state["network_mutation_ledger"]["resolution"] is None
assert state["network_write_reconciliation"] is not None
assert state["semantic_topology_store"]["status"] == "empty"
assert state["selected_device_id"] is None
def test_read_only_reconciliation_terminalizes_the_matching_idempotency_edge(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service)
_seed_unresolved_network_mutation(
service,
operation_id="lost-response-operation",
)
reads = 0
async def read_current_status(*_: object, **__: object) -> dict[str, Any]:
nonlocal reads
reads += 1
return _wifi_status_read("192.168.68.50")
monkeypatch.setattr(facade_module, "read_wifi_status_once", read_current_status)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(facade_module, "_host_route_class", lambda _target: "direct-or-routed")
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
monkeypatch.setattr(facade_module, "_control_endpoint_reachable", lambda _target: True)
state = asyncio.run(
service.verify_connection(
ConnectionVerifyRequest(
device_id="test-ble-transport",
compatibility_attestation=ATTESTATION,
expected_discovery_generation=0,
)
)
)
assert reads == 1
assert state["connection_mode"] == "bridge"
assert state["k1_ip"] == "192.168.68.50"
assert state["network_write_reconciliation"] is None
assert state["network_mutation_ledger"]["status"] == "resolved"
assert state["network_mutation_ledger"]["resolution"] == "target-observed"
assert state["network_provisioning_idempotency"] == {
"status": "ready",
"revision": state["network_provisioning_idempotency"]["revision"],
"reason_code": None,
"active_operation_id": None,
"active_action": None,
"active_stage": None,
"terminal_record_count": 1,
"mutation_allowed": True,
}
idempotency_record = (
service._require_network_provisioning_idempotency_journal() # noqa: SLF001
.snapshot()
.records[0]
)
assert idempotency_record.operation_id == "lost-response-operation"
assert idempotency_record.stage == "terminal"
assert idempotency_record.terminal is not None
assert idempotency_record.terminal.outcome == "succeeded"
assert idempotency_record.terminal.outcome_code == "network.provision.reconciled"
assert idempotency_record.terminal.side_effect_status == "reconciled"
def test_restart_interrupts_legacy_edge_before_optional_read_only_verify(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
operation_id = "legacy-read-only-reconciliation"
_seed_legacy_network_mutation_without_idempotency(
service,
operation_id=operation_id,
stage="observing",
)
restarted, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(restarted)
reads = 0
async def read_current_status(*_: object, **__: object) -> dict[str, Any]:
nonlocal reads
reads += 1
return _wifi_status_read("192.168.68.50")
monkeypatch.setattr(facade_module, "read_wifi_status_once", read_current_status)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(facade_module, "_host_route_class", lambda _target: "direct-or-routed")
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
monkeypatch.setattr(facade_module, "_control_endpoint_reachable", lambda _target: True)
state = asyncio.run(
restarted.verify_connection(
ConnectionVerifyRequest(
device_id="test-ble-transport",
compatibility_attestation=ATTESTATION,
expected_discovery_generation=0,
)
)
)
assert reads == 1
assert state["network_write_reconciliation"] is None
assert state["network_mutation_ledger"]["status"] == "resolved"
assert state["network_mutation_ledger"]["resolution"] == "interrupted"
idempotency = restarted._require_network_provisioning_idempotency_journal().snapshot() # noqa: SLF001
assert idempotency.status == "ready"
assert idempotency.active_record is None
terminal = idempotency.records[-1]
assert terminal.operation_id == operation_id
assert terminal.stage == "terminal"
assert terminal.terminal is not None
assert terminal.terminal.outcome_code == "network.provision.interrupted"
assert terminal.terminal.side_effect_status == "reconciled"
def test_read_only_reconciliation_rejects_cross_journal_mismatch_before_gatt(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service)
fence = _seed_unresolved_network_mutation(
service,
operation_id="network-ledger-operation",
idempotency_operation_id="idempotency-journal-operation",
)
async def forbidden_status_read(*_: object, **__: object) -> dict[str, Any]:
raise AssertionError("cross-journal mismatch must fail before GATT")
monkeypatch.setattr(facade_module, "read_wifi_status_once", forbidden_status_read)
with pytest.raises(facade_module.ConnectionVerificationError) as raised:
asyncio.run(
service.verify_connection(
ConnectionVerifyRequest(
device_id="test-ble-transport",
compatibility_attestation=ATTESTATION,
expected_discovery_generation=0,
)
)
)
assert raised.value.reason_code == "connection-verify-idempotency-operation-mismatch"
state = service.state()
assert state["network_write_reconciliation"] == fence
assert state["network_mutation_ledger"]["status"] == "unresolved"
assert state["network_provisioning_idempotency"]["status"] == "blocked"
assert state["network_provisioning_idempotency"]["active_operation_id"] == (
"idempotency-journal-operation"
)
def test_read_only_addressless_status_keeps_network_write_reconciliation_fence(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service)
_seed_unresolved_network_mutation(service)
async def read_current_status(*_: object, **__: object) -> dict[str, Any]:
return _wifi_status_read(None)
monkeypatch.setattr(facade_module, "read_wifi_status_once", read_current_status)
with pytest.raises(
facade_module.ConnectionVerificationError,
match="не сообщил адрес общей локальной сети",
) as raised:
asyncio.run(
service.verify_connection(
ConnectionVerifyRequest(
device_id="test-ble-transport",
compatibility_attestation=ATTESTATION,
expected_discovery_generation=0,
)
)
)
assert raised.value.reason_code == "connection-verify-address-unavailable"
fence = service.state()["network_write_reconciliation"]
assert fence is not None
assert fence["operation_id"] == "ambiguous-operation"
assert fence["operation_stage"] == "dispatching"
assert fence["scope"] == "durable-ledger"
assert fence["ledger_revision"] == 2
def test_read_only_ble_status_for_another_transport_keeps_reconciliation_fence(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service, device_id="k1-b")
fence = _seed_unresolved_network_mutation(service, transport_ref="k1-a")
async def read_other_status(*_: object, **__: object) -> dict[str, Any]:
raise AssertionError("target mismatch must fail before a GATT read")
monkeypatch.setattr(facade_module, "read_wifi_status_once", read_other_status)
with pytest.raises(
facade_module.ConnectionVerificationError,
match="относится к другому K1",
) as raised:
asyncio.run(
service.verify_connection(
ConnectionVerifyRequest(
device_id="k1-b",
compatibility_attestation=ATTESTATION,
expected_discovery_generation=0,
)
)
)
assert raised.value.reason_code == "connection-verify-reconciliation-target-mismatch"
assert service.state()["network_write_reconciliation"] == fence
@pytest.mark.parametrize(
("intended_mode", "attestation", "requested_mode"),
[
("bridge", DIRECT_CONNECT_ATTESTATION, "direct-connect"),
("direct-connect", ATTESTATION, "bridge"),
],
)
def test_read_only_reconciliation_requires_exact_requested_mode_despite_shared_status(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
intended_mode: NetworkConnectionMode,
attestation: CompatibilityAttestationRequest,
requested_mode: str,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service)
original_fence = _seed_unresolved_network_mutation(
service,
intended_mode=intended_mode,
)
async def read_current_status(*_: object, **__: object) -> dict[str, Any]:
raise AssertionError("mode mismatch must fail before a GATT read")
monkeypatch.setattr(facade_module, "read_wifi_status_once", read_current_status)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(facade_module, "_host_route_class", lambda _target: "direct-or-routed")
monkeypatch.setattr(facade_module, "_control_endpoint_reachable", lambda _target: True)
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
with pytest.raises(facade_module.ConnectionVerificationError) as raised:
asyncio.run(
service.verify_connection(
ConnectionVerifyRequest(
device_id="test-ble-transport",
compatibility_attestation=attestation,
expected_discovery_generation=0,
)
)
)
assert raised.value.reason_code == "connection-verify-reconciliation-target-mismatch"
state = service.state()
assert state["connection_mode"] is None
assert state["k1_ip"] is None
assert state["network_write_reconciliation"] == original_fence
ledger = state["network_mutation_ledger"]
assert ledger["status"] == "unresolved"
assert ledger["mutation_allowed"] is True
assert ledger["intended_mode"] == intended_mode
assert ledger["revision"] == 2
assert ledger["resolution"] is None
verify_operation = next(
item for item in state["operations"] if item["action"] == "connection.verify"
)
assert verify_operation["status"] == "failed"
def test_durable_restart_interrupts_old_attempt_without_implicit_gatt_recovery(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
first, _ = service_with_fake_runtime(tmp_path)
_seed_unresolved_network_mutation(
first,
operation_id="durable-restart-reconciliation",
transport_ref=DURABLE_K1_UUID,
)
restarted, _ = service_with_fake_runtime(tmp_path)
captured = _durable_status_capture()
status_reads: list[tuple[str, bool, str | None]] = []
pin_calls: list[tuple[object, str]] = []
write_calls: list[str] = []
async def read_server_target(
device_id: str,
*,
captured_device: object | None = None,
recovery_device_session_id: str | None = None,
allow_known_device_retrieval: bool = False,
on_gatt_validated: Callable[[object], None] | None = None,
**_: object,
) -> dict[str, Any]:
status_reads.append((device_id, allow_known_device_retrieval, recovery_device_session_id))
assert captured_device is None
assert on_gatt_validated is not None
on_gatt_validated(captured)
return _wifi_status_read("192.168.68.50", device_id=device_id)
async def forbidden_write(*_: object, **__: object) -> dict[str, Any]:
write_calls.append("write")
raise AssertionError("durable reconciliation must not write to K1")
monkeypatch.setattr(facade_module, "read_wifi_status_once", read_server_target)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_write)
monkeypatch.setattr(
facade_module,
"pin_connected_device_handle",
lambda handle, *, device_session_id: pin_calls.append((handle, device_session_id)),
)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(facade_module, "_host_route_class", lambda _target: "direct-or-routed")
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
monkeypatch.setattr(facade_module, "_control_endpoint_reachable", lambda _target: True)
before = restarted.state()
assert before["devices"] == []
assert before["selected_device_id"] is None
assert before["network_mutation_ledger"]["status"] == "resolved"
assert before["network_mutation_ledger"]["resolution"] == "interrupted"
with pytest.raises(facade_module.ConnectionVerificationError) as raised:
asyncio.run(
restarted.verify_connection(
ConnectionVerifyRequest(
device_id=DURABLE_K1_UUID,
source="durable-configured-state",
compatibility_attestation=ATTESTATION,
)
)
)
assert raised.value.reason_code == "connection-verify-candidate-not-fresh"
state = restarted.state()
assert status_reads == []
assert write_calls == []
assert pin_calls == []
assert state["selected_device_id"] is None
assert state["device_session"] is None
assert state["network_write_reconciliation"] is None
assert state["network_mutation_ledger"]["status"] == "resolved"
assert state["network_mutation_ledger"]["resolution"] == "interrupted"
assert state["network_provisioning_idempotency"]["status"] == "ready"
assert state["network_provisioning_idempotency"]["active_operation_id"] is None
assert state["network_provisioning_idempotency"]["terminal_record_count"] == 1
terminal = (
restarted._require_network_provisioning_idempotency_journal() # noqa: SLF001
.snapshot()
.records[-1]
)
assert terminal.operation_id == "durable-restart-reconciliation"
assert terminal.stage == "terminal"
assert terminal.terminal is not None
assert terminal.terminal.outcome_code == "network.provision.interrupted"
assert terminal.terminal.side_effect_status == "reconciled"
assert state["connection_supervisor"]["authority"]["control_allowed"] is False
# Without an independently durable current/configured topology, startup's
# interrupted audit must not turn an arbitrary new advertisement into an
# implicit recovery continuation.
_set_scanned_k1(restarted, device_id="replacement-k1")
fresh_policy = restarted.state()["connection_policy"]
assert fresh_policy["actions"]["observe-fresh-device-network"]["allowed"] is True
assert fresh_policy["recommended_action"] == "select-connection-intent"
@pytest.mark.parametrize(
("device_id", "attestation", "source", "reason_code"),
[
(
"AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE",
ATTESTATION,
"durable-configured-state",
"connection-verify-reconciliation-target-mismatch",
),
(
DURABLE_K1_UUID,
QUICK_CONNECT_ATTESTATION,
"durable-configured-state",
"connection-verify-reconciliation-target-mismatch",
),
(
DURABLE_K1_UUID,
ATTESTATION,
"fresh-scan",
"connection-verify-source-mismatch",
),
],
)
def test_durable_restart_rejects_request_target_mismatch_before_gatt(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
device_id: str,
attestation: CompatibilityAttestationRequest,
source: str,
reason_code: str,
) -> None:
first, _ = service_with_fake_runtime(tmp_path)
_seed_unresolved_network_mutation(
first,
operation_id="durable-request-mismatch",
transport_ref=DURABLE_K1_UUID,
)
restarted, _ = service_with_fake_runtime(tmp_path)
reads: list[str] = []
async def forbidden_read(*_: object, **__: object) -> dict[str, Any]:
reads.append("read")
raise AssertionError("request mismatch must fail before GATT")
monkeypatch.setattr(facade_module, "read_wifi_status_once", forbidden_read)
monkeypatch.setattr(
facade_module,
"provision_wifi_once",
lambda *_args, **_kwargs: (_ for _ in ()).throw(
AssertionError("request mismatch must not write")
),
)
with pytest.raises(facade_module.ConnectionVerificationError) as raised:
asyncio.run(
restarted.verify_connection(
ConnectionVerifyRequest(
device_id=device_id,
source=source, # type: ignore[arg-type]
compatibility_attestation=attestation,
**({"expected_discovery_generation": 0} if source == "fresh-scan" else {}),
)
)
)
assert raised.value.reason_code == "connection-verify-candidate-not-fresh"
assert reads == []
state = restarted.state()
assert state["network_write_reconciliation"] is None
assert state["network_mutation_ledger"]["status"] == "resolved"
assert state["network_mutation_ledger"]["resolution"] == "interrupted"
assert state["selected_device_id"] is None
assert state["device_session"] is None
def test_durable_restart_same_bridge_baseline_cannot_resolve_ambiguous_write(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
baseline = NetworkStatusEvidence(
mode="WIFI_CLIENT",
ipv4="192.168.68.50",
status_code=1,
reserved=0,
)
first, _ = service_with_fake_runtime(tmp_path)
_seed_unresolved_network_mutation(
first,
operation_id="durable-unchanged-bridge-baseline",
transport_ref=DURABLE_K1_UUID,
baseline_status=baseline,
)
restarted, _ = service_with_fake_runtime(tmp_path)
captured = _durable_status_capture()
reads = 0
pin_calls: list[tuple[object, str]] = []
async def read_unchanged_bridge_status(
device_id: str,
*,
allow_known_device_retrieval: bool = False,
on_gatt_validated: Callable[[object], None] | None = None,
**_: object,
) -> dict[str, Any]:
nonlocal reads
reads += 1
assert device_id == DURABLE_K1_UUID
assert allow_known_device_retrieval is True
assert on_gatt_validated is not None
on_gatt_validated(captured)
return _wifi_status_read("192.168.68.50", device_id=device_id)
monkeypatch.setattr(
facade_module,
"read_wifi_status_once",
read_unchanged_bridge_status,
)
monkeypatch.setattr(
facade_module,
"pin_connected_device_handle",
lambda handle, *, device_session_id: pin_calls.append((handle, device_session_id)),
)
with pytest.raises(facade_module.ConnectionVerificationError) as raised:
asyncio.run(
restarted.verify_connection(
ConnectionVerifyRequest(
device_id=DURABLE_K1_UUID,
source="durable-configured-state",
compatibility_attestation=ATTESTATION,
)
)
)
assert raised.value.reason_code == "connection-verify-candidate-not-fresh"
assert reads == 0
assert pin_calls == []
state = restarted.state()
assert state["network_write_reconciliation"] is None
assert state["network_mutation_ledger"]["status"] == "resolved"
assert state["network_mutation_ledger"]["resolution"] == "interrupted"
assert state["network_provisioning_idempotency"]["status"] == "ready"
assert state["semantic_topology_store"]["status"] == "empty"
assert state["selected_device_id"] is None
assert state["device_session"] is None
@pytest.mark.parametrize(
("intended_mode", "attestation", "baseline", "previous", "observed_status"),
[
(
"quick-connect",
QUICK_CONNECT_ATTESTATION,
NetworkStatusEvidence("WIFI_CLIENT", "192.168.68.50", 1, 0),
PreviousConnectionEvidence(
DURABLE_K1_UUID,
"quick-connect",
"192.168.56.1",
"previous-quick-session",
),
_ap_ready_wifi_status(),
),
(
"bridge",
ATTESTATION,
NetworkStatusEvidence("WIFI_AP", "192.168.56.1", 1, 1),
PreviousConnectionEvidence(
DURABLE_K1_UUID,
"bridge",
"192.168.68.40",
"previous-bridge-session",
),
_wifi_status_read("192.168.68.99")["status"],
),
(
"direct-connect",
DIRECT_CONNECT_ATTESTATION,
NetworkStatusEvidence("WIFI_AP", "192.168.56.1", 1, 1),
PreviousConnectionEvidence(
DURABLE_K1_UUID,
"direct-connect",
"172.20.10.3",
"previous-direct-session",
),
_wifi_status_read("172.20.10.2")["status"],
),
],
)
def test_durable_restart_previous_topology_cannot_resolve_ambiguous_write(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
intended_mode: NetworkConnectionMode,
attestation: CompatibilityAttestationRequest,
baseline: NetworkStatusEvidence,
previous: PreviousConnectionEvidence,
observed_status: dict[str, Any],
) -> None:
first, _ = service_with_fake_runtime(tmp_path)
_seed_unresolved_network_mutation(
first,
operation_id=f"durable-previous-{intended_mode}",
transport_ref=DURABLE_K1_UUID,
intended_mode=intended_mode,
baseline_status=baseline,
previous_connection=previous,
)
restarted, _ = service_with_fake_runtime(tmp_path)
captured = _durable_status_capture()
reads = 0
pin_calls: list[tuple[object, str]] = []
write_calls: list[str] = []
async def read_previous_topology(
device_id: str,
*,
allow_known_device_retrieval: bool = False,
on_gatt_validated: Callable[[object], None] | None = None,
**_: object,
) -> dict[str, Any]:
nonlocal reads
reads += 1
assert device_id == DURABLE_K1_UUID
assert allow_known_device_retrieval is True
assert on_gatt_validated is not None
on_gatt_validated(captured)
status_read = _wifi_status_read(None, device_id=device_id)
status_read["status"] = observed_status
return status_read
async def forbidden_write(*_: object, **__: object) -> dict[str, Any]:
write_calls.append("write")
raise AssertionError("read-only restart reconciliation must not write")
monkeypatch.setattr(facade_module, "read_wifi_status_once", read_previous_topology)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_write)
monkeypatch.setattr(
facade_module,
"pin_connected_device_handle",
lambda handle, *, device_session_id: pin_calls.append((handle, device_session_id)),
)
with pytest.raises(facade_module.ConnectionVerificationError) as raised:
asyncio.run(
restarted.verify_connection(
ConnectionVerifyRequest(
device_id=DURABLE_K1_UUID,
source="durable-configured-state",
compatibility_attestation=attestation,
)
)
)
assert raised.value.reason_code == "connection-verify-candidate-not-fresh"
assert reads == 0
assert write_calls == []
assert pin_calls == []
state = restarted.state()
assert state["network_write_reconciliation"] is None
assert state["network_mutation_ledger"]["status"] == "resolved"
assert state["network_mutation_ledger"]["resolution"] == "interrupted"
assert state["network_provisioning_idempotency"]["status"] == "ready"
assert state["semantic_topology_store"]["status"] == "empty"
assert state["selected_device_id"] is None
assert state["device_session"] is None
@pytest.mark.parametrize("outcome", ["baseline", "wrong-mode", "read-failure"])
def test_durable_restart_failed_status_keeps_ambiguity_and_does_not_pin(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
outcome: str,
) -> None:
first, _ = service_with_fake_runtime(tmp_path)
_seed_unresolved_network_mutation(
first,
operation_id=f"durable-{outcome}",
transport_ref=DURABLE_K1_UUID,
)
restarted, _ = service_with_fake_runtime(tmp_path)
captured = _durable_status_capture()
reads = 0
pin_calls: list[tuple[object, str]] = []
write_calls: list[str] = []
async def read_nonmatching_status(
device_id: str,
*,
allow_known_device_retrieval: bool = False,
on_gatt_validated: Callable[[object], None] | None = None,
**_: object,
) -> dict[str, Any]:
nonlocal reads
reads += 1
assert device_id == DURABLE_K1_UUID
assert allow_known_device_retrieval is True
if outcome == "read-failure":
raise RuntimeError("synthetic durable GATT read failure")
assert on_gatt_validated is not None
on_gatt_validated(captured)
result = _wifi_status_read(None, device_id=device_id)
if outcome == "wrong-mode":
result["status"] = _ap_ready_wifi_status()
return result
async def forbidden_write(*_: object, **__: object) -> dict[str, Any]:
write_calls.append("write")
raise AssertionError("failed status observation must not write")
monkeypatch.setattr(facade_module, "read_wifi_status_once", read_nonmatching_status)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_write)
monkeypatch.setattr(
facade_module,
"pin_connected_device_handle",
lambda handle, *, device_session_id: pin_calls.append((handle, device_session_id)),
)
with pytest.raises(facade_module.ConnectionVerificationError):
asyncio.run(
restarted.verify_connection(
ConnectionVerifyRequest(
device_id=DURABLE_K1_UUID,
source="durable-configured-state",
compatibility_attestation=ATTESTATION,
)
)
)
assert reads == 0
assert write_calls == []
assert pin_calls == []
state = restarted.state()
assert state["network_mutation_ledger"]["status"] == "resolved"
assert state["network_mutation_ledger"]["resolution"] == "interrupted"
assert state["network_provisioning_idempotency"]["status"] == "ready"
assert state["semantic_topology_store"]["status"] == "empty"
assert state["selected_device_id"] is None
assert state["device_session"] is None
def test_semantic_only_durable_restart_uses_lan_and_mqtt_identity_not_ble(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
first, _ = service_with_fake_runtime(tmp_path)
topology_store = first._semantic_topology_store # noqa: SLF001
assert topology_store is not None
topology_store.commit(
transport_ref=DURABLE_K1_UUID,
connection_mode="bridge",
ipv4="192.168.68.50",
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
firmware_version="3.0.2",
source="ble-read-only-status",
observed_at_utc="2026-08-06T12:00:00Z",
)
_seed_unresolved_network_mutation(
first,
operation_id="semantic-restart-post-dispatch-unknown",
transport_ref=DURABLE_K1_UUID,
intended_mode="bridge",
)
restarted, _ = service_with_fake_runtime(tmp_path)
association_probe = FakeHostWifiAssociationProbe("a" * 64)
restarted._host_wifi_association_probe = association_probe # type: ignore[assignment] # noqa: SLF001
reads = 0
pin_calls: list[tuple[object, str]] = []
binding_validation_epochs: list[tuple[int, int]] = []
async def forbidden_status_read(*_: object, **__: object) -> dict[str, Any]:
nonlocal reads
reads += 1
raise AssertionError("resolved durable restart must not require BLE")
monkeypatch.setattr(facade_module, "read_wifi_status_once", forbidden_status_read)
network_writes: list[str] = []
async def forbidden_network_write(*_: object, **__: object) -> dict[str, Any]:
network_writes.append("network-write")
raise AssertionError("semantic observation must not write")
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_network_write)
monkeypatch.setattr(
facade_module,
"pin_connected_device_handle",
lambda handle, *, device_session_id: pin_calls.append((handle, device_session_id)),
)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
monkeypatch.setattr(
facade_module,
"_probe_control_endpoint_socket",
lambda _target: facade_module.TcpReachabilityProbeResult(reachable=True),
)
async def bootstrap_after_exact_path_validation(
bound_service: XgridsK1CompatibilityService,
*,
parent_operation_id: str | None,
connection_mode: facade_module.ConnectionMode,
inspection_only: bool = False,
) -> None:
supervisor = bound_service._connection_supervisor.snapshot() # noqa: SLF001
assert supervisor.intent is not None
assert supervisor.device_network.target is not None
assert supervisor.device_network.transport_ref is not None
binding = ApplicationConnectionBinding(
intent_id=supervisor.intent.intent_id,
transport_ref=supervisor.device_network.transport_ref,
host_path_epoch=supervisor.host_path.epoch,
target_ipv4=supervisor.device_network.target.ipv4,
target_port=supervisor.device_network.target.port,
connection_mode=connection_mode,
)
epoch_before = supervisor.host_path.epoch
bound_service._validate_application_connection_path(binding) # noqa: SLF001
epoch_after = bound_service._connection_supervisor.snapshot().host_path.epoch # noqa: SLF001
binding_validation_epochs.append((epoch_before, epoch_after))
await _synthetic_prestart_control_bootstrap(
bound_service,
parent_operation_id=parent_operation_id,
connection_mode=connection_mode,
inspection_only=inspection_only,
)
restarted._bootstrap_prestart_control_ready_owned = MethodType( # type: ignore[method-assign] # noqa: SLF001
bootstrap_after_exact_path_validation,
restarted,
)
before = restarted.state()
assert before["devices"] == []
assert before["selected_device_id"] is None
assert before["connection_attempt"] is None
assert before["network_mutation_ledger"]["status"] == "resolved"
assert before["network_mutation_ledger"]["resolution"] == "interrupted"
assert before["semantic_topology_store"]["record"]["revision"] == 1
assert (
before["connection_policy"]["actions"]["observe-configured-device-network"][
"requires_live_gatt_validation"
]
is False
)
assert (
before["connection_policy"]["actions"]["observe-configured-device-network"]["allowed"]
is True
)
assert before["connection_policy"]["recommended_action"] == (
"observe-configured-device-network"
)
assert before["connection_policy"]["actions"]["scan-ble"]["allowed"] is True
state = asyncio.run(
restarted.verify_connection(
ConnectionVerifyRequest(
device_id=DURABLE_K1_UUID,
source="durable-configured-state",
compatibility_attestation=ATTESTATION,
)
)
)
assert reads == 0
assert network_writes == []
assert pin_calls == []
assert state["semantic_topology_store"]["record"]["revision"] == 1
assert state["connection_verification"]["endpoint_validation"] == (
"durable-semantic-topology+mqtt-tcp-connect"
)
assert state["connection_verification"]["lease_state"] == "reachable"
assert state["connection_supervisor"]["observed"]["device_network"]["source"] == (
"durable-semantic-topology"
)
assert state["connection_supervisor"]["observed"]["device_identity"]["state"] == "verified"
assert state["connection_supervisor"]["authority"]["control_allowed"] is True
assert state["connection_supervisor"]["authority"]["acquisition_start_allowed"] is True
assert binding_validation_epochs == [(1, 1)]
assert association_probe.interfaces == ["test0", "test0", "test0"]
assert state["connection_supervisor"]["observed"]["host_path"]["fingerprint"] != (
"test-route:192.168.68.50"
)
def test_semantic_durable_verify_refreshes_stale_dhcp_over_exact_read_only_ble(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
first, _ = service_with_fake_runtime(tmp_path)
topology_store = first._semantic_topology_store # noqa: SLF001
assert topology_store is not None
topology_store.commit(
transport_ref=DURABLE_K1_UUID,
connection_mode="bridge",
ipv4="192.168.68.50",
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
firmware_version="3.0.2",
source="ble-read-only-status",
observed_at_utc="2026-08-06T12:00:00Z",
)
restarted, _ = service_with_fake_runtime(tmp_path)
association_probe = FakeHostWifiAssociationProbe("a" * 64)
restarted._host_wifi_association_probe = association_probe # type: ignore[assignment] # noqa: SLF001
capture = _durable_status_capture()
status_reads: list[tuple[str, bool, str | None]] = []
pin_calls: list[tuple[object, str]] = []
network_writes: list[str] = []
async def read_current_dhcp_status(
device_id: str,
*,
captured_device: object | None = None,
recovery_device_session_id: str | None = None,
allow_known_device_retrieval: bool = False,
on_gatt_validated: Callable[[object], None] | None = None,
**_: object,
) -> dict[str, Any]:
status_reads.append(
(device_id, allow_known_device_retrieval, recovery_device_session_id)
)
assert captured_device is None
assert allow_known_device_retrieval is True
assert on_gatt_validated is not None
on_gatt_validated(capture)
return _wifi_status_read("192.168.68.51", device_id=device_id)
async def forbidden_network_write(*_: object, **__: object) -> dict[str, Any]:
network_writes.append("network-write")
raise AssertionError("stale DHCP recovery must not write to K1")
monkeypatch.setattr(facade_module, "read_wifi_status_once", read_current_dhcp_status)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_network_write)
monkeypatch.setattr(
facade_module,
"pin_connected_device_handle",
lambda handle, *, device_session_id: pin_calls.append((handle, device_session_id)),
)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
monkeypatch.setattr(facade_module, "_host_route_class", lambda _target: "direct-or-routed")
monkeypatch.setattr(facade_module, "_control_endpoint_reachable", lambda _target: True)
monkeypatch.setattr(
facade_module,
"_probe_configured_endpoint_host_only",
lambda target, **_kwargs: facade_module._ConfiguredEndpointHostObservation( # noqa: SLF001
path=_direct_host_path(target),
reachable=False,
reason_code="tcp-connection-timeout",
),
)
async def bootstrap_after_refresh(
bound_service: XgridsK1CompatibilityService,
*,
parent_operation_id: str | None,
connection_mode: facade_module.ConnectionMode,
inspection_only: bool = False,
) -> None:
await _synthetic_prestart_control_bootstrap(
bound_service,
parent_operation_id=parent_operation_id,
connection_mode=connection_mode,
inspection_only=inspection_only,
)
restarted._bootstrap_prestart_control_ready_owned = MethodType( # type: ignore[method-assign] # noqa: SLF001
bootstrap_after_refresh,
restarted,
)
state = asyncio.run(
restarted.verify_connection(
ConnectionVerifyRequest(
device_id=DURABLE_K1_UUID,
source="durable-configured-state",
compatibility_attestation=ATTESTATION,
)
)
)
assert status_reads == [(DURABLE_K1_UUID, True, None)]
assert network_writes == []
assert len(pin_calls) == 1
assert pin_calls[0][0] is capture
assert state["k1_ip"] == "192.168.68.51"
assert state["semantic_topology_store"]["record"]["revision"] == 2
assert state["semantic_topology_store"]["record"]["ipv4"] == "192.168.68.51"
assert state["connection_verification"]["endpoint_validation"] == (
"ble-wifi-status-read+mqtt-tcp-connect"
)
assert state["connection_verification"]["address_source"] == "ble-wifi-status-read"
assert state["connection_verification"]["address_changed"] is True
assert state["connection_verification"]["write_performed"] is False
assert state["connection_supervisor"]["observed"]["device_identity"]["state"] == (
"verified"
)
assert state["connection_supervisor"]["authority"]["control_allowed"] is True
def test_semantic_durable_verify_rejects_association_change_during_tcp_probe(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
first, _ = service_with_fake_runtime(tmp_path)
topology_store = first._semantic_topology_store # noqa: SLF001
assert topology_store is not None
topology_store.commit(
transport_ref=DURABLE_K1_UUID,
connection_mode="bridge",
ipv4="192.168.68.50",
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
firmware_version="3.0.2",
source="ble-read-only-status",
observed_at_utc="2026-08-06T12:00:00Z",
)
restarted, _ = service_with_fake_runtime(tmp_path)
association_probe = FakeHostWifiAssociationProbe("a" * 64, "b" * 64)
restarted._host_wifi_association_probe = association_probe # type: ignore[assignment] # noqa: SLF001
device_edges: list[str] = []
async def forbidden_device_edge(*_: object, **__: object) -> dict[str, Any]:
device_edges.append("device")
raise AssertionError("association race must fail before BLE or device write")
async def forbidden_bootstrap(*_: object, **__: object) -> None:
device_edges.append("mqtt-bootstrap")
raise AssertionError("association race must fail before DeviceInfo bootstrap")
monkeypatch.setattr(facade_module, "read_wifi_status_once", forbidden_device_edge)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_device_edge)
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
monkeypatch.setattr(
facade_module,
"_probe_control_endpoint_socket",
lambda _target: facade_module.TcpReachabilityProbeResult(reachable=True),
)
restarted._bootstrap_prestart_control_ready_owned = forbidden_bootstrap # type: ignore[method-assign] # noqa: SLF001
with pytest.raises(facade_module.ConnectionVerificationError) as raised:
asyncio.run(
restarted.verify_connection(
ConnectionVerifyRequest(
device_id=DURABLE_K1_UUID,
source="durable-configured-state",
compatibility_attestation=ATTESTATION,
)
)
)
assert raised.value.reason_code == "connection-verify-mqtt-unreachable"
assert device_edges == []
assert association_probe.interfaces == ["test0", "test0"]
state = restarted.state()
assert state["selected_device_id"] is None
assert state["active_connection_mode"] is None
assert state["connection_supervisor"]["intent"] is None
assert state["connection_supervisor"]["observed"]["endpoint"]["target"] is None
assert state["semantic_topology_store"]["record"]["revision"] == 1
@pytest.mark.parametrize("observed_session_state", ["ready", "scanning"])
def test_public_physical_recovery_refreshes_stale_dhcp_then_classifies_without_writes(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
observed_session_state: str,
) -> None:
original, _ = service_with_fake_runtime(tmp_path)
stop_operation_id, compatibility_revision = (
_persist_resolved_unclassified_stop_for_restart(original)
)
topology_store = original._semantic_topology_store # noqa: SLF001
assert topology_store is not None
topology_store.commit(
transport_ref="test-ble-transport",
connection_mode="bridge",
ipv4="192.168.68.52",
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
firmware_version="3.0.2",
source="ble-read-only-status",
observed_at_utc="2026-08-12T13:28:19.000Z",
)
restarted, runtime = service_with_fake_runtime(tmp_path)
retirement_permissions: list[bool] = []
class TerminalDeviceFaultControl(FakeInteractiveControlSession):
def retire_for_network_change(
self,
*,
allow_terminal_failure: bool = False,
**kwargs: object,
) -> dict[str, object]:
retirement_permissions.append(allow_terminal_failure)
if not allow_terminal_failure:
raise ApplicationAcceptanceError(
"terminal device fault requires explicit local retirement"
)
return super().retire_for_network_change(**kwargs)
association_probe = FakeHostWifiAssociationProbe("a" * 64)
restarted._host_wifi_association_probe = association_probe # type: ignore[assignment] # noqa: SLF001
capture = _durable_status_capture(device_id="test-ble-transport")
host_probes: list[str] = []
status_reads: list[tuple[str, bool, bool, float | None]] = []
command_edges: list[str] = []
def stale_host_probe(
target: str,
**_: object,
) -> facade_module._ConfiguredEndpointHostObservation: # noqa: SLF001
host_probes.append(target)
return facade_module._ConfiguredEndpointHostObservation( # noqa: SLF001
path=_direct_host_path(target),
reachable=False,
reason_code="tcp-connection-timeout",
)
async def read_current_dhcp_status(
device_id: str,
*,
allow_known_device_retrieval: bool = False,
rediscover: bool = False,
exact_scan_timeout_seconds: float | None = None,
on_gatt_validated: Callable[[object], None] | None = None,
**_: object,
) -> dict[str, Any]:
status_reads.append(
(
device_id,
allow_known_device_retrieval,
rediscover,
exact_scan_timeout_seconds,
)
)
assert on_gatt_validated is not None
on_gatt_validated(capture)
return _wifi_status_read("192.168.68.51", device_id=device_id)
async def forbidden_network_write(*_: object, **__: object) -> dict[str, Any]:
command_edges.append("network-write")
raise AssertionError("physical recovery must not write K1 network state")
monkeypatch.setattr(
facade_module,
"_probe_configured_endpoint_host_only",
stale_host_probe,
)
monkeypatch.setattr(facade_module, "read_wifi_status_once", read_current_dhcp_status)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_network_write)
monkeypatch.setattr(facade_module, "pin_connected_device_handle", lambda *_a, **_k: None)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
monkeypatch.setattr(facade_module, "_host_route_class", lambda _target: "direct-or-routed")
monkeypatch.setattr(facade_module, "_control_endpoint_reachable", lambda _target: True)
_install_real_coordinator_bootstrap(
restarted,
observed_session_state=observed_session_state,
)
before = restarted.state()
configured_recovery = before["connection_policy"]["actions"][
"observe-configured-device-network"
]
assert configured_recovery["allowed"] is True
assert configured_recovery["required_transport_ref"] == "test-ble-transport"
assert configured_recovery["required_connection_mode"] == "bridge"
assert configured_recovery["requires_live_gatt_validation"] is True
restarted._application_control_session = TerminalDeviceFaultControl( # type: ignore[assignment] # noqa: SLF001
initial_state="failed"
)
verified = asyncio.run(restarted.verify_connection(ConnectionVerifyRequest()))
after = restarted._physical_command_ledger.snapshot().record # noqa: SLF001
assert after is not None
assert after.operation_id == stop_operation_id
assert after.revision == compatibility_revision + 1
assert after.resolved_unclassified_stop_recovery_required is False
assert after.reconciliations[-1].resolution == (
"physical-active-observed"
if observed_session_state == "scanning"
else "physical-standby-observed"
)
assert host_probes == []
assert status_reads == [
(
"test-ble-transport",
True,
True,
facade_module.CONNECTION_VERIFY_EXACT_UUID_SCAN_TIMEOUT_SECONDS,
)
]
assert association_probe.timeout_seconds == [
facade_module.COMMAND_BOUND_ASSOCIATION_TIMEOUT_SECONDS,
facade_module.COMMAND_BOUND_ASSOCIATION_TIMEOUT_SECONDS,
]
assert command_edges == []
assert retirement_permissions == [True]
assert runtime.start_calls == []
assert runtime.stop_calls == 0
assert verified["k1_ip"] == "192.168.68.51"
assert verified["semantic_topology_store"]["record"]["ipv4"] == "192.168.68.51"
assert verified["last_operation"]["result"]["write_performed"] is False
assert verified["last_operation"]["result"]["physical_reconciliation"][
"performed"
] is True
def test_durable_restart_rejects_network_revision_race_before_commit_or_pin(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
operation_id = "durable-revision-race"
first, _ = service_with_fake_runtime(tmp_path)
_seed_unresolved_network_mutation(
first,
operation_id=operation_id,
transport_ref=DURABLE_K1_UUID,
)
restarted, _ = service_with_fake_runtime(tmp_path)
captured = _durable_status_capture()
pin_calls: list[tuple[object, str]] = []
async def read_while_revision_changes(
device_id: str,
*,
on_gatt_validated: Callable[[object], None] | None = None,
**_: object,
) -> dict[str, Any]:
assert on_gatt_validated is not None
on_gatt_validated(captured)
current_ledger = restarted._network_mutation_ledger.snapshot() # noqa: SLF001
assert current_ledger.record is not None
restarted._network_mutation_ledger.mark_observing( # noqa: SLF001
operation_id,
expected_revision=current_ledger.record.revision,
write_confirmed=False,
observation=NetworkStatusEvidence(
mode="WIFI_CLIENT",
ipv4="192.168.68.50",
status_code=1,
reserved=0,
),
)
return _wifi_status_read("192.168.68.50", device_id=device_id)
monkeypatch.setattr(facade_module, "read_wifi_status_once", read_while_revision_changes)
monkeypatch.setattr(
facade_module,
"provision_wifi_once",
lambda *_args, **_kwargs: (_ for _ in ()).throw(
AssertionError("revision race must not write")
),
)
monkeypatch.setattr(
facade_module,
"pin_connected_device_handle",
lambda handle, *, device_session_id: pin_calls.append((handle, device_session_id)),
)
with pytest.raises(facade_module.ConnectionVerificationError) as raised:
asyncio.run(
restarted.verify_connection(
ConnectionVerifyRequest(
device_id=DURABLE_K1_UUID,
source="durable-configured-state",
compatibility_attestation=ATTESTATION,
)
)
)
assert raised.value.reason_code == "connection-verify-candidate-not-fresh"
assert pin_calls == []
state = restarted.state()
assert state["network_mutation_ledger"]["status"] == "resolved"
assert state["network_mutation_ledger"]["resolution"] == "interrupted"
assert state["semantic_topology_store"]["status"] == "empty"
assert state["selected_device_id"] is None
assert state["device_session"] is None
def test_provisioning_cannot_switch_device_during_active_acquisition(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_devices(service, [{"device_id": "k1-a"}])
service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
called = False
async def should_not_run(*_: object, **__: object) -> dict[str, Any]:
nonlocal called
called = True
raise AssertionError("provisioning boundary must not be reached")
monkeypatch.setattr(facade_module, "provision_wifi_once", should_not_run)
with pytest.raises(RuntimeError, match="активной acquisition-сессии"):
asyncio.run(
service.connect(
_connect_request(
device_id="k1-a",
ssid="lab-network",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
)
)
)
assert called is False
def test_sensor_catalog_exposes_two_browser_adapter_cameras_after_profile_attestation(
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
initial = service.state()
initial_cameras = [
stream
for stream in initial["sensor_catalog"]["streams"]
if stream.get("semantic_channel_id") == "camera.preview.live"
]
assert {stream["source_id"] for stream in initial_cameras} == {
"sensor.camera.left",
"sensor.camera.right",
}
assert all(stream["availability"] == "unverified" for stream in initial_cameras)
state = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
cameras = [
stream
for stream in state["sensor_catalog"]["streams"]
if stream.get("semantic_channel_id") == "camera.preview.live"
]
assert len(cameras) == 2
assert all(camera["availability"] == "available" for camera in cameras)
assert all(camera["modality"] == "encoded-video" for camera in cameras)
assert all(camera["decode_status"] == "rtsp-h264-observed-browser-remux" for camera in cameras)
assert all(camera["activation"]["max_active"] == 1 for camera in cameras)
assert all(camera["delivery"] is None for camera in cameras)
assert state["connection_verification"]["network_reachability"] == "unknown"
assert state["device_calibration"]["status"] == "unavailable"
assert state["device_calibration"]["vehicle_extrinsics"] == ("host-domain-not-owned-by-plugin")
def test_quick_to_bridge_requires_new_explicit_scan_instead_of_retained_session(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_seed_supervised_connection(
service,
target_ipv4=facade_module.AP_FALLBACK_IPV4,
connection_mode="quick-connect",
transport_ref="k1-a",
logical_device_id="device-a",
)
service._device_session_id = "quick-session-a" # noqa: SLF001
service._device_session_opened_at = "2026-08-06T12:00:00Z" # noqa: SLF001
supervisor_generation = service._connection_supervisor.snapshot().lease.generation # noqa: SLF001
service._connection_verification = { # noqa: SLF001
"status": "control-transport-lost",
"lease_state": "disconnected",
"lease_generation": supervisor_generation,
"endpoint_validation": "terminal-mqtt-network-loop",
"network_reachability": "unreachable",
"reason_code": "connection_lease_control_transport_lost",
"observed_at": "2026-08-06T12:01:00Z",
}
captured = facade_module.CapturedDiscoveredDevice(
device=SimpleNamespace(address="k1-a"), # type: ignore[arg-type]
macos_uuid="k1-a",
owner_epoch=7,
)
provision_calls: list[tuple[object | None, str | None]] = []
pin_calls: list[tuple[object, str]] = []
def recover(device_id: str, *, device_session_id: str) -> object | None:
assert (device_id, device_session_id) == ("k1-a", "quick-session-a")
return captured
async def provision(
*_args: object,
captured_device: object | None = None,
recovery_device_session_id: str | None = None,
on_write_dispatch: Callable[[dict[str, Any], str], None] | None = None,
**_kwargs: object,
) -> dict[str, Any]:
provision_calls.append((captured_device, recovery_device_session_id))
_dispatch_test_network_write(on_write_dispatch)
return {
"started_at_utc": "2026-08-06T12:02:00Z",
"completed_at_utc": "2026-08-06T12:02:01Z",
"profile_id": "xgrids-k1-fw3-wifi-v1",
"outcome": "lan_address_observed",
"write_mode": "with_response",
"baseline_status": {"mode": "WIFI_AP", "ipv4": "192.168.56.1"},
"observations": [{"status": _wifi_status_read("192.168.68.50")["status"]}],
}
monkeypatch.setattr(facade_module, "connected_device_capture", recover)
monkeypatch.setattr(
facade_module,
"connected_device_recovery_snapshot",
lambda *_args, **_kwargs: {
"status": "retained",
"scope": "owner-epoch-device-session",
"advertised_now": False,
"gatt_validated_recently": False,
},
)
monkeypatch.setattr(facade_module, "provision_wifi_once", provision)
monkeypatch.setattr(
facade_module,
"pin_connected_device_handle",
lambda handle, *, device_session_id: pin_calls.append((handle, device_session_id)),
)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(facade_module, "_host_route_class", lambda _target: "direct-or-routed")
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
monkeypatch.setattr(
facade_module,
"_control_endpoint_reachable",
lambda _target: True,
)
monkeypatch.setattr(
facade_module,
"_await_control_endpoint_reachable",
_reachable_control_endpoint,
)
with pytest.raises(facade_module.NetworkProvisioningConflict) as raised:
asyncio.run(
service.connect(
_connect_request(
device_id="k1-a",
ssid="lab-router",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
connection_mode="bridge",
compatibility_attestation=ATTESTATION,
)
)
)
assert raised.value.reason_code == "network-provision-candidate-not-fresh"
assert provision_calls == []
assert pin_calls == []
def test_quick_to_bridge_does_not_retrieve_old_handle_without_new_scan(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_seed_supervised_connection(
service,
target_ipv4=facade_module.AP_FALLBACK_IPV4,
connection_mode="quick-connect",
transport_ref="k1-a",
logical_device_id="device-a",
)
service._device_session_id = "quick-session-a" # noqa: SLF001
service._device_session_opened_at = "2026-08-06T12:00:00Z" # noqa: SLF001
captured = facade_module.CapturedDiscoveredDevice(
device=SimpleNamespace(address="k1-a"), # type: ignore[arg-type]
macos_uuid="k1-a",
owner_epoch=7,
source="retrieved-session",
)
retained_lookups: list[tuple[str, str]] = []
provision_calls: list[tuple[object | None, str | None]] = []
def retained_lookup(device_id: str, *, device_session_id: str) -> object | None:
retained_lookups.append((device_id, device_session_id))
# Facade obtains the exact validated object only after the low-level
# operation resolved/retrieved it inside its BLE arbiter lease.
return captured
async def provision(
*_args: object,
captured_device: object | None = None,
recovery_device_session_id: str | None = None,
on_write_dispatch: Callable[[dict[str, Any], str], None] | None = None,
**_kwargs: object,
) -> dict[str, Any]:
provision_calls.append((captured_device, recovery_device_session_id))
_dispatch_test_network_write(on_write_dispatch)
return {
"started_at_utc": "2026-08-06T12:02:00Z",
"completed_at_utc": "2026-08-06T12:02:01Z",
"profile_id": "xgrids-k1-fw3-wifi-v1",
"outcome": "lan_address_observed",
"write_mode": "with_response",
"baseline_status": {"mode": "WIFI_AP", "ipv4": "192.168.56.1"},
"observations": [{"status": _wifi_status_read("192.168.68.50")["status"]}],
}
monkeypatch.setattr(facade_module, "connected_device_capture", retained_lookup)
monkeypatch.setattr(
facade_module,
"connected_device_recovery_snapshot",
lambda *_args, **_kwargs: {
"status": "retained",
"scope": "owner-epoch-device-session",
"advertised_now": False,
"gatt_validated_recently": False,
},
)
monkeypatch.setattr(facade_module, "provision_wifi_once", provision)
monkeypatch.setattr(facade_module, "pin_connected_device_handle", lambda *_args, **_kw: None)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(facade_module, "_host_route_class", lambda _target: "direct-or-routed")
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
monkeypatch.setattr(facade_module, "_control_endpoint_reachable", lambda _target: True)
monkeypatch.setattr(
facade_module,
"_await_control_endpoint_reachable",
_reachable_control_endpoint,
)
with pytest.raises(facade_module.NetworkProvisioningConflict) as raised:
asyncio.run(
service.connect(
_connect_request(
device_id="k1-a",
ssid="lab-router",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
connection_mode="bridge",
compatibility_attestation=ATTESTATION,
)
)
)
assert raised.value.reason_code == "network-provision-candidate-not-fresh"
assert retained_lookups == []
assert provision_calls == []
def test_connection_policy_exposes_retained_recovery_without_inventing_presence(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
service._selected_device_id = "k1-a" # noqa: SLF001
service._connection_mode = "quick-connect" # noqa: SLF001
service._device_id = "device-a" # noqa: SLF001
service._device_session_id = "quick-session-a" # noqa: SLF001
service._device_session_opened_at = "2026-08-06T12:00:00Z" # noqa: SLF001
service._k1_ip = facade_module.AP_FALLBACK_IPV4 # noqa: SLF001
monkeypatch.setattr(
facade_module,
"connected_device_recovery_snapshot",
lambda *_args, **_kwargs: {
"status": "retained",
"scope": "owner-epoch-device-session",
"gatt_validated_recently": True,
},
)
state = service.state()
assert state["devices"] == []
assert state["current_device_recovery"]["handle_retained"] is True
assert state["current_device_recovery"]["advertised_now"] is False
policy = state["connection_policy"]
assert policy["facts"]["retained_context_is_presence"] is False
assert policy["actions"]["provision-fresh-device"]["allowed"] is False
assert policy["actions"]["recover-current-device-network"] == {
"allowed": True,
"reason_codes": [],
"target_source": "retained-current-process",
"required_transport_ref": "k1-a",
"requires_live_gatt_validation": True,
"automatic_retry": False,
}
assert policy["recommended_action"] == "recover-current-device-network"
def test_connection_policy_treats_open_durable_audit_as_nonblocking_context(
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service, device_id="k1-a")
_seed_unresolved_network_mutation(service, transport_ref="k1-a")
policy = service.state()["connection_policy"]
assert policy["facts"]["physical_network_state"] == "unknown"
assert policy["actions"]["provision-fresh-device"]["allowed"] is True
assert policy["actions"]["recover-current-device-network"]["allowed"] is False
assert policy["actions"]["observe-fresh-device-network"]["allowed"] is True
assert policy["actions"]["observe-fresh-device-network"]["required_transport_ref"] == "k1-a"
assert policy["recommended_action"] == "observe-fresh-device-network"
def _project_connection_policy_for_test(
service: XgridsK1CompatibilityService,
*,
idempotency: dict[str, object] | None = None,
idempotency_available: bool = True,
identity_pins: dict[str, object] | None = None,
physical_command: dict[str, object] | None = None,
ble_runtime: dict[str, object] | None = None,
lifecycle_holders: tuple[str, ...] = (),
current_device_recovery: dict[str, object] | None = None,
acquisition_active: bool = False,
acquisition_state: str | None = None,
acquisition_cleanup_pending: bool = False,
runtime_active: bool = False,
application_control_session: dict[str, object] | None = None,
) -> dict[str, Any]:
with service._lock: # noqa: SLF001
fresh_devices = service._fresh_ble_devices_locked() # noqa: SLF001
desired_connection_mode = service._desired_connection_mode # noqa: SLF001
configured_connection_mode = service._connection_mode # noqa: SLF001
supervisor = service._connection_supervisor.snapshot() # noqa: SLF001
active_connection_mode = (
configured_connection_mode if supervisor.authority.control_allowed else None
)
return facade_module._connection_policy_projection( # noqa: SLF001
supervisor=supervisor,
ledger=service._network_mutation_ledger.snapshot(), # noqa: SLF001
network_provisioning_idempotency=(
idempotency
if idempotency is not None
else service._network_provisioning_idempotency_public_snapshot() # noqa: SLF001
),
network_provisioning_idempotency_available=idempotency_available,
semantic_topology_store=service._semantic_topology_public_snapshot(), # noqa: SLF001
device_identity_pin_store=(
identity_pins
if identity_pins is not None
else service._device_identity_pin_public_snapshot() # noqa: SLF001
),
physical_command=(
physical_command
if physical_command is not None
else service._physical_command_coordinator.snapshot() # noqa: SLF001
),
ble_runtime=(
ble_runtime
if ble_runtime is not None
else {
"owner_epoch": 1,
"owner_loop_bound": True,
"active_operation_kind": None,
"cleanup_pending": False,
"poisoned": False,
}
),
lifecycle_process_lease_holders=lifecycle_holders,
fresh_devices=fresh_devices,
current_device_recovery=current_device_recovery,
provisioning_active=False,
acquisition_active=acquisition_active,
acquisition_state=acquisition_state,
acquisition_cleanup_pending=acquisition_cleanup_pending,
runtime_active=runtime_active,
application_control_session=(
application_control_session
if application_control_session is not None
else {"state": "idle", "failure": None}
),
desired_connection_mode=desired_connection_mode,
active_connection_mode=active_connection_mode,
)
@pytest.mark.parametrize(
("available", "status", "expected_reason"),
[
(False, "corrupt", "network-provisioning-idempotency-unavailable"),
(True, "corrupt", "network-provisioning-idempotency-corrupt"),
],
)
def test_connection_policy_blocks_network_actions_when_idempotency_authority_is_untrusted(
tmp_path: Path,
available: bool,
status: str,
expected_reason: str,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service)
policy = _project_connection_policy_for_test(
service,
idempotency={
"status": status,
"revision": None,
"reason_code": expected_reason,
"active_operation_id": None,
"active_action": None,
"active_stage": None,
"terminal_record_count": 0,
"mutation_allowed": False,
},
idempotency_available=available,
)
assert policy["actions"]["provision-fresh-device"]["allowed"] is False
assert expected_reason in policy["actions"]["provision-fresh-device"]["reason_codes"]
assert policy["actions"]["observe-fresh-device-network"]["allowed"] is False
assert expected_reason in policy["actions"]["observe-fresh-device-network"]["reason_codes"]
assert policy["actions"]["scan-ble"]["allowed"] is True
def test_connection_policy_blocks_cross_journal_mismatch_before_observation(
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service, device_id="k1-a")
_seed_unresolved_network_mutation(
service,
transport_ref="k1-a",
operation_id="network-ledger-operation",
)
policy = _project_connection_policy_for_test(
service,
idempotency={
"status": "blocked",
"revision": 3,
"reason_code": "network-provisioning-idempotency-reconciliation-required",
"active_operation_id": "different-idempotency-operation",
"active_action": facade_module.ACTION_NETWORK_PROVISION,
"active_stage": "unresolved",
"terminal_record_count": 0,
"mutation_allowed": False,
},
)
decision = policy["actions"]["observe-fresh-device-network"]
assert decision["allowed"] is False
assert "network-provisioning-idempotency-operation-mismatch" in decision["reason_codes"]
assert policy["facts"]["network_provisioning_active_operation_matches_ledger"] is False
def test_connection_policy_blocks_identity_dependent_network_control_and_start(
tmp_path: Path,
) -> None:
verify_service, _ = service_with_fake_runtime(tmp_path / "verify")
_set_scanned_k1(verify_service)
_seed_supervised_connection(verify_service, with_control=False)
corrupt_pins = {
"schema_version": "missioncore.xgrids-k1-device-identity-pins/v1",
"status": "corrupt",
"revision": None,
"pin_count": 0,
"reason_code": "device-identity-pin-store-corrupt",
}
verify_policy = _project_connection_policy_for_test(
verify_service,
identity_pins=corrupt_pins,
)
for action in (
"provision-fresh-device",
"observe-fresh-device-network",
"verify-control-device-info",
):
assert verify_policy["actions"][action]["allowed"] is False
assert (
"device-identity-pin-store-corrupt" in verify_policy["actions"][action]["reason_codes"]
)
start_service, _ = service_with_fake_runtime(tmp_path / "start")
_seed_supervised_connection(start_service)
start_policy = _project_connection_policy_for_test(
start_service,
identity_pins=corrupt_pins,
)
assert start_policy["actions"]["start-acquisition"]["allowed"] is False
assert (
"device-identity-pin-store-corrupt"
in start_policy["actions"]["start-acquisition"]["reason_codes"]
)
def test_connection_policy_blocks_network_observation_when_topology_store_is_corrupt(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service)
monkeypatch.setattr(
service,
"_semantic_topology_public_snapshot",
lambda: {
"schema_version": "missioncore.xgrids-k1-semantic-topology/v1",
"status": "corrupt",
"configured_offline_evidence": False,
"live_connection_authority": False,
"reason_code": "semantic-topology-store-corrupt",
"record": None,
},
)
policy = _project_connection_policy_for_test(service)
assert policy["actions"]["observe-fresh-device-network"]["allowed"] is False
assert (
"semantic-topology-store-corrupt"
in policy["actions"]["observe-fresh-device-network"]["reason_codes"]
)
@pytest.mark.parametrize(
("status", "expected_reason"),
[
("unresolved", "physical-command-reconciliation-required"),
("corrupt", "physical-command-ledger-corrupt"),
],
)
def test_connection_policy_blocks_physical_start_and_stop_on_untrusted_ledger(
tmp_path: Path,
status: str,
expected_reason: str,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
binding = _seed_supervised_connection(service)
supervisor = service._connection_supervisor # noqa: SLF001
assert supervisor.observe_data_plane(
intent_id=binding.intent_id,
host_path_epoch=binding.host_path_epoch,
state="healthy",
session_id="data-session-a",
)
physical_command = {
"status": status,
"reason_code": expected_reason,
"requires_reconciliation": True,
"automatic_replay_allowed": False,
"normal_session_recovery_supported": False,
"recovery_requirement": "explicit-read-only-reconciliation",
"runtime_bound": False,
"active_operation_id": None,
"record": None,
}
policy = _project_connection_policy_for_test(
service,
physical_command=physical_command,
)
for action in ("start-acquisition", "stop-acquisition"):
assert policy["actions"][action]["allowed"] is False
assert expected_reason in policy["actions"][action]["reason_codes"]
def test_pending_reopened_physical_state_allows_only_read_only_recovery_or_retirement(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service, device_id="k1-a")
physical = _pending_reopened_physical_snapshot()
policy = _project_connection_policy_for_test(
service,
physical_command=physical,
)
for action in (
"provision-fresh-device",
"recover-current-device-network",
"start-acquisition",
"stop-acquisition",
):
assert policy["actions"][action]["allowed"] is False
assert (
"physical-command-reconciliation-required"
in policy["actions"][action]["reason_codes"]
)
read_only = policy["actions"]["observe-fresh-device-network"]
assert read_only["allowed"] is True
assert read_only["required_transport_ref"] == "k1-a"
assert read_only["required_connection_mode"] == "bridge"
# A scanning-shaped local snapshot is not STOP authority by itself. The
# reopened durable row must remain fenced unless the exact adopted worker
# explicitly exposes its STOP checkpoint.
no_stop_checkpoint = _project_connection_policy_for_test(
service,
physical_command=physical,
application_control_session={
"state": "scanning",
"can_stop": False,
"failure": None,
},
)
assert no_stop_checkpoint["actions"]["stop-acquisition"]["allowed"] is False
assert (
"physical-command-reconciliation-required"
in no_stop_checkpoint["actions"]["stop-acquisition"]["reason_codes"]
)
monkeypatch.setattr(
service._physical_command_coordinator, # noqa: SLF001
"snapshot",
lambda: physical,
)
retirement = service._physical_operator_retirement_projection() # noqa: SLF001
assert retirement["allowed"] is True
assert retirement["reason_codes"] == []
@pytest.mark.parametrize(
("ble_snapshot", "expected_reason"),
[
(
{
"owner_epoch": 4,
"owner_loop_bound": False,
"active_operation_kind": "scan",
"cleanup_pending": True,
"poisoned": False,
},
"ble-runtime-cleanup-pending",
),
(
{
"owner_epoch": 5,
"owner_loop_bound": False,
"active_operation_kind": "status-read",
"cleanup_pending": True,
"poisoned": True,
},
"ble-runtime-restart-required",
),
],
)
def test_connection_policy_blocks_control_and_physical_edges_on_ble_quarantine(
tmp_path: Path,
ble_snapshot: dict[str, object],
expected_reason: str,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_seed_supervised_connection(service)
policy = _project_connection_policy_for_test(
service,
ble_runtime=ble_snapshot,
)
assert policy["actions"]["start-acquisition"]["allowed"] is False
assert expected_reason in policy["actions"]["start-acquisition"]["reason_codes"]
def test_state_projects_ble_runtime_quarantine_into_composite_policy(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
poisoned = {
"owner_epoch": 8,
"owner_loop_bound": False,
"active_operation_kind": "status-read",
"cleanup_pending": True,
"poisoned": True,
}
monkeypatch.setattr(facade_module, "ble_runtime_snapshot", lambda: poisoned)
state = service.state()
assert state["ble_runtime"] == poisoned
assert state["connection_policy"]["facts"]["ble_runtime"] == {
"active_operation_kind": "status-read",
"cleanup_pending": True,
"poisoned": True,
}
assert (
"ble-runtime-restart-required"
in state["connection_policy"]["actions"]["scan-ble"]["reason_codes"]
)
def test_connection_policy_blocks_physical_edges_while_network_owns_process_lease(
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
binding = _seed_supervised_connection(service)
assert service._connection_supervisor.observe_data_plane( # noqa: SLF001
intent_id=binding.intent_id,
host_path_epoch=binding.host_path_epoch,
state="healthy",
session_id="data-session-a",
)
policy = _project_connection_policy_for_test(
service,
lifecycle_holders=("network",),
)
for action in ("start-acquisition", "stop-acquisition"):
assert policy["actions"][action]["allowed"] is False
assert (
"k1-lifecycle-process-lease-network-owned" in policy["actions"][action]["reason_codes"]
)
def test_connection_policy_keeps_host_tcp_probe_independent_of_other_failures(
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_seed_supervised_connection(
service,
with_control=False,
endpoint_reachable=False,
)
policy = _project_connection_policy_for_test(
service,
idempotency={
"status": "corrupt",
"active_operation_id": None,
},
idempotency_available=False,
identity_pins={"status": "corrupt"},
physical_command={
"status": "corrupt",
"requires_reconciliation": True,
},
ble_runtime={
"owner_epoch": 9,
"owner_loop_bound": False,
"active_operation_kind": "scan",
"cleanup_pending": True,
"poisoned": True,
},
lifecycle_holders=("network",),
)
assert policy["actions"]["probe-endpoint"]["allowed"] is True
assert policy["actions"]["verify-control-device-info"]["allowed"] is False
assert policy["actions"]["start-acquisition"]["allowed"] is False
def test_connection_policy_data_loss_preserves_exact_stop_and_falls_back_to_local_only(
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
binding = _seed_supervised_connection(service)
supervisor = service._connection_supervisor # noqa: SLF001
assert supervisor.observe_data_plane(
intent_id=binding.intent_id,
host_path_epoch=binding.host_path_epoch,
state="healthy",
session_id="data-session-a",
)
assert supervisor.observe_data_plane(
intent_id=binding.intent_id,
host_path_epoch=binding.host_path_epoch,
state="lost",
session_id="data-session-a",
reason_code="test-data-loss",
)
healthy_control = _project_connection_policy_for_test(
service,
acquisition_active=True,
runtime_active=True,
)
assert healthy_control["actions"]["acknowledge-data-loss"]["allowed"] is False
assert healthy_control["actions"]["stop-acquisition"]["allowed"] is True
assert healthy_control["actions"]["stop-local-receiver"]["allowed"] is True
assert healthy_control["actions"]["stop-local-receiver"]["physical_command_allowed"] is False
assert healthy_control["actions"]["stop-local-receiver"]["physical_outcome"] == ("unknown")
assert healthy_control["recommended_action"] == "stop-acquisition"
assert supervisor.observe_control_loss(
intent_id=binding.intent_id,
host_path_epoch=binding.host_path_epoch,
control_session_id="test-control-test-ble-transport",
reason_code="test-control-loss",
)
control_lost = _project_connection_policy_for_test(
service,
acquisition_active=True,
runtime_active=True,
)
assert control_lost["actions"]["stop-acquisition"]["allowed"] is False
assert (
"physical-control-authority-unavailable"
in control_lost["actions"]["stop-acquisition"]["reason_codes"]
)
assert control_lost["actions"]["stop-local-receiver"]["allowed"] is True
assert control_lost["actions"]["stop-local-receiver"]["execution_mode"] == ("capture-only")
assert control_lost["actions"]["stop-local-receiver"]["physical_command_allowed"] is False
assert control_lost["recommended_action"] == "stop-local-receiver"
@pytest.mark.parametrize(
("acquisition_active", "cleanup_pending", "runtime_active", "expected_allowed"),
[
(True, False, False, True),
(False, True, False, True),
(False, False, True, True),
(False, False, False, False),
],
)
def test_connection_policy_local_receiver_cleanup_uses_independent_local_liveness(
tmp_path: Path,
acquisition_active: bool,
cleanup_pending: bool,
runtime_active: bool,
expected_allowed: bool,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_seed_supervised_connection(service)
policy = _project_connection_policy_for_test(
service,
acquisition_active=acquisition_active,
acquisition_cleanup_pending=cleanup_pending,
runtime_active=runtime_active,
)
local_cleanup = policy["actions"]["stop-local-receiver"]
assert local_cleanup["allowed"] is expected_allowed
assert local_cleanup["execution_mode"] == "capture-only"
assert local_cleanup["physical_command_allowed"] is False
assert local_cleanup["physical_outcome"] == "unknown"
if expected_allowed:
assert local_cleanup["reason_codes"] == []
else:
assert local_cleanup["reason_codes"] == ["local-acquisition-receiver-not-active"]
# Local cleanup eligibility never broadens the separately gated physical STOP.
assert policy["actions"]["stop-acquisition"]["allowed"] is False
def test_connection_policy_current_target_allows_host_probe_not_ble_refresh(
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
binding = _seed_supervised_connection(service)
assert service._connection_supervisor.observe_control_loss( # noqa: SLF001
intent_id=binding.intent_id,
host_path_epoch=binding.host_path_epoch,
control_session_id="test-control-test-ble-transport",
reason_code="test-control-loss",
)
policy = _project_connection_policy_for_test(
service,
current_device_recovery=None,
)
assert service._connection_supervisor.snapshot().last_known is not None # noqa: SLF001
assert policy["actions"]["inspect-configured-endpoint"]["allowed"] is True
assert (
policy["actions"]["inspect-configured-endpoint"]["requires_live_gatt_validation"] is False
)
assert policy["actions"]["inspect-configured-endpoint"]["target_source"] == (
"configured-topology"
)
assert policy["actions"]["inspect-configured-endpoint"]["required_transport_ref"] is None
assert policy["actions"]["observe-fresh-device-network"]["allowed"] is False
assert (
"fresh-ble-candidate-required"
in policy["actions"]["observe-fresh-device-network"]["reason_codes"]
)
def test_configured_endpoint_probe_uses_durable_topology_after_restart_without_ble(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
first, _ = service_with_fake_runtime(tmp_path)
topology_store = first._semantic_topology_store # noqa: SLF001
assert topology_store is not None
topology_store.commit(
transport_ref="durable-k1-transport",
connection_mode="bridge",
ipv4="192.168.1.20",
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
firmware_version="3.0.2",
source="ble-read-only-status",
observed_at_utc="2026-08-06T12:00:00Z",
)
restarted, _ = service_with_fake_runtime(tmp_path)
ble_calls: list[str] = []
async def forbidden_ble(*_: object, **__: object) -> dict[str, Any]:
ble_calls.append("ble")
raise AssertionError("configured endpoint probe must not enter BLE")
def forbidden_ble_lease(*_: object, **__: object) -> object:
ble_calls.append("ble-lease")
raise AssertionError("configured endpoint probe must not borrow the BLE lease")
def forbidden_authoritative_probe(*_: object, **__: object) -> object:
raise AssertionError("configured endpoint probe must not update the supervisor")
monkeypatch.setattr(facade_module, "read_wifi_status_once", forbidden_ble)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_ble)
monkeypatch.setattr(
facade_module,
"borrow_ble_runtime_process_lease",
forbidden_ble_lease,
)
monkeypatch.setattr(restarted, "_probe_control_endpoint", forbidden_authoritative_probe)
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
monkeypatch.setattr(
facade_module,
"_probe_control_endpoint_socket",
lambda target: facade_module.TcpReachabilityProbeResult(
reachable=target == "192.168.1.20",
reason_code=(None if target == "192.168.1.20" else "tcp-endpoint-unreachable"),
),
)
before = restarted.state()
assert before["selected_device_id"] is None
assert before["connection_policy"]["actions"]["inspect-configured-endpoint"]["allowed"] is True
assert (
before["connection_policy"]["actions"]["inspect-configured-endpoint"]["target_source"]
== "configured-topology"
)
assert (
before["connection_policy"]["actions"]["inspect-configured-endpoint"][
"required_transport_ref"
]
is None
)
assert (
before["connection_policy"]["actions"]["observe-fresh-device-network"]["allowed"] is False
)
state = asyncio.run(
restarted.probe_configured_endpoint(
ConfiguredEndpointProbeRequest(
operation_id="op-00000000-0000-4000-8000-000000000651",
)
)
)
assert ble_calls == []
assert state["selected_device_id"] is None
assert state["connection_verification"]["status"] == "not-probed"
assert state["configured_endpoint_probe"] == {
"schema_version": "missioncore.xgrids-k1-configured-endpoint-probe/v1",
"status": "reachable",
"target_source": "durable-semantic-topology",
"connection_mode": "bridge",
"endpoint": "192.168.1.20",
"transport_ref": "durable-k1-transport",
"intent_id": None,
"semantic_revision": 1,
"host_route_available": True,
"host_route_class": "direct",
"tcp_reachable": True,
"identity_validation": "not-performed",
"control_authority_granted": False,
"ble_operation_performed": False,
"network_mutation_performed": False,
"automatic_retry": False,
"observed_at": state["configured_endpoint_probe"]["observed_at"],
"reason_code": None,
}
assert state["connection_supervisor"]["authority"]["control_allowed"] is False
assert state["last_operation"]["action"] == "connection.endpoint-probe"
assert state["last_operation"]["status"] == "succeeded"
assert state["last_operation"]["result"]["identity_validation"] == "not-performed"
assert state["last_operation"]["result"]["network_mutation_performed"] is False
def test_configured_endpoint_probe_reports_unreachable_without_promoting_authority(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
topology_store = service._semantic_topology_store # noqa: SLF001
assert topology_store is not None
topology_store.commit(
transport_ref="durable-k1-transport",
connection_mode="quick-connect",
ipv4="192.168.56.1",
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
firmware_version="3.0.2",
source="ble-read-only-status",
observed_at_utc="2026-08-06T12:00:00Z",
)
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
monkeypatch.setattr(
facade_module,
"_probe_control_endpoint_socket",
lambda _target: facade_module.TcpReachabilityProbeResult(
reachable=False,
reason_code="tcp-endpoint-unreachable",
),
)
state = asyncio.run(service.probe_configured_endpoint())
probe = state["configured_endpoint_probe"]
assert probe["status"] == "endpoint-unreachable"
assert probe["host_route_available"] is True
assert probe["tcp_reachable"] is False
assert probe["reason_code"] == "tcp-endpoint-unreachable"
assert probe["control_authority_granted"] is False
assert state["connection_supervisor"]["authority"]["control_allowed"] is False
def test_configured_endpoint_probe_prefers_current_supervisor_target(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
topology_store = service._semantic_topology_store # noqa: SLF001
assert topology_store is not None
topology_store.commit(
transport_ref="older-durable-transport",
connection_mode="bridge",
ipv4="192.168.1.99",
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
firmware_version="3.0.2",
source="ble-read-only-status",
observed_at_utc="2026-08-06T12:00:00Z",
)
_seed_supervised_connection(
service,
target_ipv4="192.168.1.20",
with_control=False,
)
probed_targets: list[str] = []
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
monkeypatch.setattr(
facade_module,
"_probe_control_endpoint_socket",
lambda target: (
probed_targets.append(target)
or facade_module.TcpReachabilityProbeResult(reachable=True)
),
)
state = asyncio.run(service.probe_configured_endpoint())
assert probed_targets == ["192.168.1.20"]
assert state["configured_endpoint_probe"]["target_source"] == "current-supervisor"
assert state["configured_endpoint_probe"]["endpoint"] == "192.168.1.20"
assert state["configured_endpoint_probe"]["transport_ref"] == "test-ble-transport"
assert state["configured_endpoint_probe"]["intent_id"] is not None
assert state["configured_endpoint_probe"]["semantic_revision"] is None
assert state["configured_endpoint_probe"]["identity_validation"] == "not-performed"
def test_configured_endpoint_probe_requires_current_or_durable_target(
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
with pytest.raises(
facade_module.ConfiguredEndpointProbeError,
match="Нет сохранённого endpoint",
) as raised:
asyncio.run(service.probe_configured_endpoint())
assert raised.value.reason_code == "configured-endpoint-unavailable"
operation = service.state()["last_operation"]
assert operation["action"] == "connection.endpoint-probe"
assert operation["status"] == "failed"
assert operation["error"]["side_effect_status"] == "none"
assert operation["error"]["safe_to_retry"] is True
def test_configured_endpoint_probe_maps_untrusted_store_to_action_scoped_error(
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
service._semantic_topology_store = None # noqa: SLF001
with pytest.raises(facade_module.ConfiguredEndpointProbeError) as raised:
asyncio.run(service.probe_configured_endpoint())
assert raised.value.reason_code == "configured-endpoint-topology-corrupt"
operation = service.state()["last_operation"]
assert operation["action"] == "connection.endpoint-probe"
assert operation["status"] == "failed"
assert operation["error"]["side_effect_status"] == "none"
@pytest.mark.parametrize(
(
"previous_mode",
"previous_session_id",
"previous_ipv4",
"requested_mode",
"requested_ssid",
"requested_password",
"requested_attestation",
),
[
pytest.param(
"quick-connect",
"quick-session-a",
facade_module.AP_FALLBACK_IPV4,
"bridge",
"lab-router",
SecretStr(PRIMARY_TEST_CREDENTIAL),
ATTESTATION,
id="quick-to-bridge",
),
pytest.param(
"bridge",
"bridge-session-a",
"192.168.68.50",
"quick-connect",
None,
None,
QUICK_CONNECT_ATTESTATION,
id="bridge-to-quick-connect",
),
],
)
def test_fresh_cross_mode_prewrite_failure_leaves_clean_unselected_state(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
previous_mode: str,
previous_session_id: str,
previous_ipv4: str,
requested_mode: str,
requested_ssid: str | None,
requested_password: SecretStr | None,
requested_attestation: CompatibilityAttestationRequest,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
service._selected_device_id = "k1-a" # noqa: SLF001
service._connection_mode = previous_mode # type: ignore[assignment] # noqa: SLF001
service._device_id = "device-a" # noqa: SLF001
service._device_session_id = previous_session_id # noqa: SLF001
service._device_session_opened_at = "2026-08-06T12:00:00Z" # noqa: SLF001
service._device_session_discovery_generation = 0 # noqa: SLF001
service._k1_ip = previous_ipv4 # noqa: SLF001
mode_revision = _select_connection_mode(service, requested_mode)
service._ble_discovery_generation += 1 # noqa: SLF001
_set_scanned_k1(service, device_id="k1-a")
captured = facade_module.CapturedDiscoveredDevice(
device=SimpleNamespace(address="k1-a"), # type: ignore[arg-type]
macos_uuid="k1-a",
owner_epoch=7,
scan_generation=service._ble_discovery_generation, # noqa: SLF001
)
prewrite_attempts: list[tuple[str, object | None]] = []
def prewrite_failure(captured_device: object | None) -> RuntimeError:
prewrite_attempts.append((requested_mode, captured_device))
error = RuntimeError("powered off after fresh advertisement")
error.operation_stage = "connect" # type: ignore[attr-defined]
error.device_write_attempted = False # type: ignore[attr-defined]
error.device_write_confirmed = False # type: ignore[attr-defined]
return error
async def bridge_powered_off_before_write(
*_args: object,
captured_device: object | None = None,
**_kwargs: object,
) -> dict[str, Any]:
raise prewrite_failure(captured_device)
@asynccontextmanager
async def quick_powered_off_before_write(
*_args: object,
captured_device: object | None = None,
**_kwargs: object,
) -> AsyncIterator[dict[str, Any]]:
raise prewrite_failure(captured_device)
yield {}
monkeypatch.setattr(
facade_module,
"_capture_network_intent_device",
lambda _device_id: captured,
)
monkeypatch.setattr(
facade_module,
"connected_device_capture",
lambda *_args, **_kwargs: None,
)
if requested_mode == "quick-connect":
monkeypatch.setattr(
facade_module,
"ensure_wifi_profile_from_credential_source",
lambda *_args, **_kwargs: {
"schema_version": 1,
"adapter": "macOS Keychain",
"available": True,
"profile_enrolled": True,
"credential_source": "exact-firmware-profile",
},
)
monkeypatch.setattr(
facade_module,
"device_ap_activation_session",
quick_powered_off_before_write,
)
monkeypatch.setattr(
facade_module,
"provision_wifi_once",
lambda *_args, **_kwargs: (_ for _ in ()).throw(
AssertionError("Quick Connect must not use the Bridge provisioning write")
),
)
else:
monkeypatch.setattr(
facade_module,
"provision_wifi_once",
bridge_powered_off_before_write,
)
monkeypatch.setattr(
facade_module,
"device_ap_activation_session",
lambda *_args, **_kwargs: (_ for _ in ()).throw(
AssertionError("Bridge must not use the Quick Connect AP write")
),
)
monkeypatch.setattr(
facade_module,
"pin_connected_device_handle",
lambda *_args, **_kwargs: (_ for _ in ()).throw(
AssertionError("a failed pre-write recovery must not promote a new session")
),
)
with pytest.raises(RuntimeError, match="powered off after fresh advertisement"):
asyncio.run(
service.connect(
_connect_request(
device_id="k1-a",
ssid=requested_ssid,
password=requested_password,
connection_mode=requested_mode,
compatibility_attestation=requested_attestation,
expected_mode_revision=mode_revision,
expected_discovery_generation=(
service._ble_discovery_generation # noqa: SLF001
),
)
)
)
assert prewrite_attempts == [(requested_mode, captured)]
assert service._selected_device_id is None # noqa: SLF001
assert service._connection_mode is None # noqa: SLF001
assert service._device_id == "device-a" # noqa: SLF001
assert service._device_session_id is None # noqa: SLF001
assert service._k1_ip is None # noqa: SLF001
state = service.state()
assert state["current_device_recovery"] is None
operation = next(item for item in state["operations"] if item["action"] == "network.provision")
assert operation["error"]["safe_to_retry"] is True
assert operation["error"]["side_effect_status"] == "none"
assert operation["error"]["operation_stage"] == "connect"
assert state["network_mutation_ledger"]["status"] == "empty"
assert state["connection_policy"]["actions"]["provision-fresh-device"]["allowed"] is True
def test_same_uuid_rediscovery_is_candidate_only_and_never_resurrects_session(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
service._selected_device_id = "k1-a" # noqa: SLF001
service._connection_mode = "bridge" # noqa: SLF001
service._device_id = "device-a" # noqa: SLF001
service._device_session_id = "ended-session-a" # noqa: SLF001
service._device_session_opened_at = "2026-08-06T12:00:00Z" # noqa: SLF001
service._device_session_discovery_generation = 0 # noqa: SLF001
service._k1_ip = "192.168.68.50" # noqa: SLF001
invalidations: list[tuple[str, str]] = []
monkeypatch.setattr(
facade_module,
"invalidate_connected_device_session",
lambda device_id, *, device_session_id: (
invalidations.append((device_id, device_session_id)) or True
),
)
service._retire_ephemeral_device_binding_for_new_intent() # noqa: SLF001
assert invalidations == [("k1-a", "ended-session-a")]
discovery_calls: list[float] = []
gatt_or_session_edges: list[str] = []
async def rediscover_same_uuid(
duration_seconds: float,
*,
on_admitted: Callable[[], None] | None = None,
) -> dict[str, Any]:
discovery_calls.append(duration_seconds)
assert on_admitted is not None
on_admitted()
return _ble_scan_result("k1-a")
def forbidden_edge(*_args: object, **_kwargs: object) -> None:
gatt_or_session_edges.append("unexpected")
raise AssertionError("rediscovery must remain candidate-only until explicit Connect")
monkeypatch.setattr(facade_module, "scan", rediscover_same_uuid)
monkeypatch.setattr(facade_module, "_capture_network_intent_device", forbidden_edge)
monkeypatch.setattr(facade_module, "connected_device_capture", forbidden_edge)
monkeypatch.setattr(facade_module, "pin_connected_device_handle", forbidden_edge)
monkeypatch.setattr(facade_module, "read_wifi_status_once", forbidden_edge)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_edge)
monkeypatch.setattr(facade_module, "device_ap_activation_session", forbidden_edge)
rediscovered = asyncio.run(service.scan_ble(BleScanRequest(duration_seconds=1.0)))
assert discovery_calls == [1.0]
assert gatt_or_session_edges == []
assert rediscovered["devices"] == [
{
"device_id": "k1-a",
"name": "XGR-K1",
"rssi": -44,
"address": None,
"connectable": None,
"likely_k1": True,
}
]
assert rediscovered["selected_device_id"] is None
assert rediscovered["ble_discovery_generation"] == 1
assert rediscovered["device_session"] is None
assert rediscovered["current_device_recovery"] is None
assert rediscovered["connection_mode"] is None
assert rediscovered["k1_ip"] is None
assert rediscovered["connection_policy"]["actions"]["provision-fresh-device"]["allowed"] is True
def test_quick_to_bridge_recovery_rejects_nonterminal_control_before_retirement(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
service._selected_device_id = "k1-a" # noqa: SLF001
service._connection_mode = "quick-connect" # noqa: SLF001
service._device_session_id = "quick-session-a" # noqa: SLF001
service._k1_ip = facade_module.AP_FALLBACK_IPV4 # noqa: SLF001
_set_scanned_k1(service, device_id="k1-a")
captured = facade_module.CapturedDiscoveredDevice(
device=SimpleNamespace(address="k1-a"), # type: ignore[arg-type]
macos_uuid="k1-a",
owner_epoch=7,
)
class BusyControlSession:
def snapshot(self) -> dict[str, object]:
return {"state": "scanning", "failure": None}
def retire_for_network_change(self, **_: object) -> dict[str, object]:
raise AssertionError("recovery admission must fail before retirement")
service._application_control_session = BusyControlSession() # type: ignore[assignment] # noqa: SLF001
monkeypatch.setattr(
facade_module,
"_capture_network_intent_device",
lambda *_args, **_kwargs: captured,
)
monkeypatch.setattr(
facade_module,
"connected_device_capture",
lambda *_args, **_kwargs: captured,
)
monkeypatch.setattr(
facade_module,
"connected_device_recovery_snapshot",
lambda *_args, **_kwargs: {
"status": "retained",
"scope": "owner-epoch-device-session",
"advertised_now": False,
"gatt_validated_recently": False,
},
)
monkeypatch.setattr(
facade_module,
"provision_wifi_once",
lambda *_args, **_kwargs: (_ for _ in ()).throw(
AssertionError("rejected recovery must not reach BLE")
),
)
with pytest.raises(facade_module.NetworkProvisioningConflict) as raised:
asyncio.run(
service.connect(
_connect_request(
device_id="k1-a",
ssid="lab-router",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
connection_mode="bridge",
compatibility_attestation=ATTESTATION,
)
)
)
assert raised.value.reason_code == "network-provision-recovery-control-not-admissible"
assert service._connection_mode == "quick-connect" # noqa: SLF001
assert service._device_session_id == "quick-session-a" # noqa: SLF001
@pytest.mark.parametrize(
"failure_reason",
["mqtt_network_loop_failed", "application-connection-binding-lost"],
)
def test_terminal_control_loss_retires_ephemeral_device_session_without_retry(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
failure_reason: str,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_seed_supervised_connection(
service,
target_ipv4=facade_module.AP_FALLBACK_IPV4,
connection_mode="quick-connect",
transport_ref="k1-a",
logical_device_id="device-a",
)
service._device_session_id = "quick-session-a" # noqa: SLF001
service._device_session_opened_at = "2026-08-06T12:00:00Z" # noqa: SLF001
supervisor_generation = service._connection_supervisor.snapshot().lease.generation # noqa: SLF001
service._connection_verification = { # noqa: SLF001
"status": "reachable",
"lease_state": "reachable",
"lease_generation": supervisor_generation,
"endpoint_validation": "provisioning-status+mqtt-tcp-connect",
"network_reachability": "reachable",
"write_performed": True,
"observed_at": "2026-08-06T12:00:00Z",
}
class FailedControlSession:
retire_calls = 0
retired = False
def snapshot(self) -> dict[str, object]:
if self.retired:
return {"state": "idle", "can_open": True, "failure": None}
return {
"state": "failed",
"failure": {
"reason_code": failure_reason,
"failed_phase": "maintain-open",
},
}
def retire_for_network_change(self, **_: object) -> dict[str, object]:
self.retire_calls += 1
if self.retire_calls == 1:
raise RuntimeError("control worker is still retiring")
self.retired = True
return {"state": "idle", "can_open": True}
service._application_control_session = FailedControlSession() # type: ignore[assignment] # noqa: SLF001
invalidations: list[bool] = []
monkeypatch.setattr(
facade_module,
"invalidate_connected_device_session",
lambda *_args, **_kwargs: invalidations.append(True) or True,
)
state = service.state()
assert invalidations == [True]
assert state["k1_ip"] is None
assert state["connection_mode"] is None
assert state["device_session"] is None
assert state["current_device_recovery"] is None
assert service._selected_device_id is None # noqa: SLF001
assert state["connection_supervisor"]["authority"]["control_allowed"] is False
assert state["connection_supervisor"]["authority"]["acquisition_start_allowed"] is False
_set_scanned_k1(service, device_id="k1-a")
fresh = service.state()
assert service._application_control_session.retire_calls == 2 # type: ignore[attr-defined] # noqa: SLF001
assert fresh["connection_policy"]["actions"]["provision-fresh-device"]["allowed"] is True
def test_configured_unverified_endpoint_loss_retires_ephemeral_session(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_seed_supervised_connection(
service,
target_ipv4="192.168.68.50",
connection_mode="bridge",
transport_ref="k1-a",
logical_device_id="device-a",
with_control=False,
)
assert service._connection_supervisor.snapshot().last_known is None # noqa: SLF001
invalidations: list[bool] = []
monkeypatch.setattr(
facade_module,
"invalidate_connected_device_session",
lambda *_args, **_kwargs: invalidations.append(True) or True,
)
supervisor = service._connection_supervisor # noqa: SLF001
snapshot = supervisor.snapshot()
assert snapshot.intent is not None
assert snapshot.endpoint.target is not None
for attempt in range(3):
accepted = supervisor.observe_endpoint(
target=snapshot.endpoint.target,
intent_id=snapshot.intent.intent_id,
host_path_epoch=snapshot.host_path.epoch,
reachable=False,
reason_code="k1-control-port-unreachable",
)
assert accepted is True
state = service.state()
if attempt < 2:
assert state["device_session"] is not None
assert invalidations == [True]
assert state["device_session"] is None
assert state["connection_mode"] is None
assert state["k1_ip"] is None
_set_scanned_k1(service, device_id="k1-a")
fresh = service.state()
assert fresh["connection_policy"]["actions"]["provision-fresh-device"]["allowed"] is True
def test_endpoint_loss_preserves_same_generation_fresh_candidate_for_reprovision(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_seed_supervised_connection(
service,
target_ipv4="192.168.68.50",
connection_mode="bridge",
transport_ref="k1-a",
logical_device_id="device-a",
with_control=False,
)
_set_scanned_k1(service, device_id="k1-a")
discovery_generation = service._ble_discovery_generation # noqa: SLF001
invalidations: list[tuple[str, str]] = []
monkeypatch.setattr(
facade_module,
"invalidate_connected_device_session",
lambda device_id, *, device_session_id: (
invalidations.append((device_id, device_session_id)) or True
),
)
supervisor = service._connection_supervisor # noqa: SLF001
snapshot = supervisor.snapshot()
assert snapshot.intent is not None
assert snapshot.endpoint.target is not None
for _ in range(3):
accepted = supervisor.observe_endpoint(
target=snapshot.endpoint.target,
intent_id=snapshot.intent.intent_id,
host_path_epoch=snapshot.host_path.epoch,
reachable=False,
reason_code="k1-control-port-unreachable",
)
assert accepted is True
state = service.state()
assert invalidations == [("k1-a", "test-session-k1-a")]
assert state["device_session"] is None
assert state["selected_device_id"] is None
assert state["k1_ip"] is None
assert service._ble_discovery_generation == discovery_generation # noqa: SLF001
assert [item["device_id"] for item in state["devices"]] == ["k1-a"]
assert state["connection_policy"]["actions"]["provision-fresh-device"]["allowed"] is True
assert "свежий Bluetooth-кандидат можно настроить заново" in state["message"]
def test_three_proven_host_path_losses_retire_session_and_require_new_scan(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_seed_supervised_connection(
service,
target_ipv4="192.168.68.50",
connection_mode="bridge",
transport_ref="k1-a",
logical_device_id="device-a",
)
invalidations: list[bool] = []
monkeypatch.setattr(
facade_module,
"invalidate_connected_device_session",
lambda *_args, **_kwargs: invalidations.append(True) or True,
)
lost_path = HostPathProbeResult(
available=False,
fingerprint=None,
interface=None,
source_ipv4=None,
route_class="unavailable",
reason_code="router-link-lost",
)
service._connection_supervisor.observe_host_path(lost_path) # noqa: SLF001
first = service.state()
assert first["device_session"] is not None
assert first["connection_mode"] == "bridge"
assert invalidations == []
# Unrelated supervisor revisions must not count as additional host-path
# failures while the same negative observation remains current.
supervisor = service._connection_supervisor # noqa: SLF001
current_intent = supervisor.snapshot().intent
assert current_intent is not None
for _ in range(2):
supervisor.set_intent(
intent_id=current_intent.intent_id,
requested_mode=current_intent.requested_mode,
expected_device_id=current_intent.expected_device_id,
)
unchanged = service.state()
assert unchanged["device_session"] is not None
assert invalidations == []
service._connection_supervisor.observe_host_path(lost_path) # noqa: SLF001
second = service.state()
assert second["device_session"] is not None
assert invalidations == []
service._connection_supervisor.observe_host_path(lost_path) # noqa: SLF001
third = service.state()
assert invalidations == [True]
assert third["device_session"] is None
assert third["connection_mode"] is None
assert third["k1_ip"] is None
assert service._selected_device_id is None # noqa: SLF001
assert service._connection_monitor_target() is None # noqa: SLF001
assert third["connection_policy"]["actions"]["provision-fresh-device"]["allowed"] is False
_set_scanned_k1(service, device_id="k1-a")
fresh = service.state()
assert fresh["connection_policy"]["actions"]["provision-fresh-device"]["allowed"] is True
@pytest.mark.parametrize("plane", ["host", "endpoint"])
def test_positive_transport_edge_resets_loss_streak_between_state_polls(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
plane: str,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_seed_supervised_connection(
service,
target_ipv4="192.168.68.50",
connection_mode="bridge",
transport_ref="k1-a",
logical_device_id="device-a",
with_control=False,
)
invalidations: list[bool] = []
monkeypatch.setattr(
facade_module,
"invalidate_connected_device_session",
lambda *_args, **_kwargs: invalidations.append(True) or True,
)
supervisor = service._connection_supervisor # noqa: SLF001
def observe(reachable: bool) -> None:
snapshot = supervisor.snapshot()
assert snapshot.intent is not None
assert snapshot.device_network.target is not None
if plane == "host":
supervisor.observe_host_path(
_direct_host_path("192.168.68.50")
if reachable
else HostPathProbeResult(
available=False,
fingerprint=None,
interface=None,
source_ipv4=None,
route_class="unavailable",
reason_code="router-link-lost",
)
)
else:
accepted = supervisor.observe_endpoint(
target=snapshot.device_network.target,
intent_id=snapshot.intent.intent_id,
host_path_epoch=snapshot.host_path.epoch,
reachable=reachable,
reason_code=None if reachable else "k1-control-port-unreachable",
)
assert accepted is True
observe(False)
assert service.state()["device_session"] is not None
observe(True) # The UI does not poll state() on this recovery edge.
observe(False)
assert service.state()["device_session"] is not None
observe(False)
assert service.state()["device_session"] is not None
assert invalidations == []
observe(False)
assert service.state()["device_session"] is None
assert invalidations == [True]
@pytest.mark.parametrize("plane", ["host", "endpoint"])
def test_positive_edge_between_loss_confirmation_and_teardown_cancels_retirement(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
plane: str,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_seed_supervised_connection(
service,
target_ipv4="192.168.68.50",
connection_mode="bridge",
transport_ref="k1-a",
logical_device_id="device-a",
with_control=False,
)
supervisor = service._connection_supervisor # noqa: SLF001
def observe(reachable: bool) -> None:
snapshot = supervisor.snapshot()
assert snapshot.intent is not None
assert snapshot.device_network.target is not None
if plane == "host":
supervisor.observe_host_path(
_direct_host_path("192.168.68.50")
if reachable
else HostPathProbeResult(
available=False,
fingerprint=None,
interface=None,
source_ipv4=None,
route_class="unavailable",
reason_code="router-link-lost",
)
)
else:
accepted = supervisor.observe_endpoint(
target=snapshot.device_network.target,
intent_id=snapshot.intent.intent_id,
host_path_epoch=snapshot.host_path.epoch,
reachable=reachable,
reason_code=None if reachable else "k1-control-port-unreachable",
)
assert accepted is True
for _ in range(3):
observe(False)
original_snapshot = supervisor.snapshot
snapshot_calls = 0
def snapshot_with_recovery_edge() -> Any:
nonlocal snapshot_calls
snapshot_calls += 1
if snapshot_calls == 2:
before_recovery = original_snapshot()
assert before_recovery.intent is not None
assert before_recovery.device_network.target is not None
if plane == "host":
supervisor.observe_host_path(_direct_host_path("192.168.68.50"))
else:
accepted = supervisor.observe_endpoint(
target=before_recovery.device_network.target,
intent_id=before_recovery.intent.intent_id,
host_path_epoch=before_recovery.host_path.epoch,
reachable=True,
)
assert accepted is True
return original_snapshot()
monkeypatch.setattr(supervisor, "snapshot", snapshot_with_recovery_edge)
invalidations: list[bool] = []
monkeypatch.setattr(
facade_module,
"invalidate_connected_device_session",
lambda *_args, **_kwargs: invalidations.append(True) or True,
)
service._retire_ephemeral_connection_binding_on_proven_loss( # noqa: SLF001
service._application_control_session.snapshot() # noqa: SLF001
)
assert snapshot_calls == 2
assert service._device_session_id is not None # noqa: SLF001
assert service._selected_device_id == "k1-a" # noqa: SLF001
assert invalidations == []
def test_old_loss_teardown_preserves_candidate_from_new_scan_generation(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_seed_supervised_connection(
service,
target_ipv4="192.168.68.50",
connection_mode="bridge",
transport_ref="k1-a",
logical_device_id="device-a",
)
service._device_session_discovery_generation = 4 # noqa: SLF001
service._ble_discovery_generation = 4 # noqa: SLF001
invalidations: list[tuple[str, str]] = []
monkeypatch.setattr(
facade_module,
"invalidate_connected_device_session",
lambda device_id, *, device_session_id: (
invalidations.append((device_id, device_session_id)) or True
),
)
lost_path = HostPathProbeResult(
available=False,
fingerprint=None,
interface=None,
source_ipv4=None,
route_class="unavailable",
reason_code="router-link-lost",
)
service._connection_supervisor.observe_host_path(lost_path) # noqa: SLF001
service.state()
# A new explicit scan generation completes while old-loss confirmation is
# still pending. Its selected candidate belongs to the next operator
# intent and must not be erased by teardown of the old device-session.
service._ble_discovery_generation = 5 # noqa: SLF001
_set_scanned_k1(service, device_id="k1-a")
service._connection_supervisor.observe_host_path(lost_path) # noqa: SLF001
service.state()
service._connection_supervisor.observe_host_path(lost_path) # noqa: SLF001
state = service.state()
assert invalidations == [("k1-a", "test-session-k1-a")]
assert state["device_session"] is None
assert [item["device_id"] for item in state["devices"]] == ["k1-a"]
assert state["connection_policy"]["actions"]["provision-fresh-device"]["allowed"] is True
def test_connection_mode_and_discovery_cas_reject_stale_connect_before_io(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service, device_id="k1-a")
initial = service.state()
assert initial["desired_connection_mode"] == "bridge"
assert initial["desired_connection_mode_revision"] == 0
selected = service.select_connection_mode(
DesiredConnectionModeRequest(
connection_mode="quick-connect",
expected_revision=0,
)
)
assert selected["desired_connection_mode"] == "quick-connect"
assert selected["desired_connection_mode_revision"] == 1
assert selected["configured_connection_mode"] is None
assert selected["active_connection_mode"] is None
assert selected["ble_discovery_generation"] == 0
with pytest.raises(facade_module.NetworkProvisioningConflict) as stale_select:
service.select_connection_mode(
DesiredConnectionModeRequest(
connection_mode="direct-connect",
expected_revision=0,
)
)
assert stale_select.value.reason_code == "connection-mode-draft-revision-conflict"
io_calls: list[str] = []
def forbidden_preflight(*_: object, **__: object) -> dict[str, Any]:
io_calls.append("host-preflight")
raise AssertionError("stale mode/generation must fail before host or device I/O")
async def forbidden_provision(*_: object, **__: object) -> dict[str, Any]:
io_calls.append("ble-write")
raise AssertionError("stale mode/generation must fail before BLE")
monkeypatch.setattr(
facade_module,
"ensure_wifi_profile_from_credential_source",
forbidden_preflight,
)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_provision)
with pytest.raises(facade_module.NetworkProvisioningConflict) as stale_mode:
asyncio.run(
service.connect(
_connect_request(
device_id="k1-a",
connection_mode="quick-connect",
compatibility_attestation=QUICK_CONNECT_ATTESTATION,
expected_mode_revision=0,
)
)
)
assert stale_mode.value.reason_code == "connection-mode-draft-revision-conflict"
with pytest.raises(facade_module.NetworkProvisioningConflict) as stale_scan:
asyncio.run(
service.connect(
_connect_request(
device_id="k1-a",
connection_mode="quick-connect",
compatibility_attestation=QUICK_CONNECT_ATTESTATION,
expected_mode_revision=1,
expected_discovery_generation=1,
)
)
)
assert stale_scan.value.reason_code == "network-provision-discovery-generation-conflict"
assert io_calls == []
assert service.state()["operations"] == []
def test_pending_mode_scan_retires_prestart_control_without_physical_edge(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_select_connection_mode(service, "quick-connect")
binding = _seed_supervised_connection(
service,
target_ipv4=facade_module.AP_FALLBACK_IPV4,
connection_mode="quick-connect",
transport_ref="k1-a",
logical_device_id="device-a",
)
control = FakeInteractiveControlSession(initial_state="idle")
control.open(connection_binding=binding)
control.verified_control = _verified_control_for_binding(
binding,
logical_device_id="device-a",
)
close_calls: list[tuple[int | None, int | None]] = []
original_close_prestart = control.close_prestart
def counted_close_prestart(
_self: FakeInteractiveControlSession,
*,
expected_session_generation: int | None = None,
expected_state_revision: int | None = None,
) -> dict[str, object]:
close_calls.append((expected_session_generation, expected_state_revision))
return original_close_prestart(
expected_session_generation=expected_session_generation,
expected_state_revision=expected_state_revision,
)
control.close_prestart = MethodType(counted_close_prestart, control) # type: ignore[method-assign]
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
service._acquire_application_control_process_lease() # noqa: SLF001
ready = service.state()
assert ready["active_connection_mode"] == "quick-connect"
assert ready["connection_lifecycle"]["connection_ready"] is True
expected_close_checkpoint = (
ready["application_control_session"]["session_generation"],
ready["application_control_session"]["state_revision"],
)
switched = service.select_connection_mode(
DesiredConnectionModeRequest(
connection_mode="bridge",
expected_revision=ready["desired_connection_mode_revision"],
)
)
assert switched["connection_lifecycle"]["mode_change"] == {
"state": "switch-selected",
"from": "quick-connect",
"to": "bridge",
}
assert switched["connection_policy"]["actions"]["scan-ble"]["allowed"] is True
assert switched["connection_policy"]["actions"]["start-acquisition"]["allowed"] is False
assert (
"connection-mode-switch-pending"
in switched["connection_policy"]["actions"]["start-acquisition"]["reason_codes"]
)
device_edges: list[str] = []
async def fake_scan(
_duration_seconds: float,
*,
on_admitted: Callable[[], None] | None = None,
) -> dict[str, Any]:
assert control.snapshot()["state"] == "idle"
assert service._connection_supervisor.snapshot().authority.control_allowed is False # noqa: SLF001
assert service._selected_device_id is None # noqa: SLF001
assert on_admitted is not None
on_admitted()
return _ble_scan_result("bridge-candidate")
async def forbidden_device_write(*_: object, **__: object) -> dict[str, Any]:
device_edges.append("network-write")
raise AssertionError("mode selection/scan must not write device network state")
monkeypatch.setattr(facade_module, "scan", fake_scan)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_device_write)
monkeypatch.setattr(
service._physical_command_coordinator, # noqa: SLF001
"prepare",
lambda *_args, **_kwargs: device_edges.append("physical-command"),
)
scanned = asyncio.run(service.scan_ble(1.0))
assert close_calls == [expected_close_checkpoint]
assert device_edges == []
assert scanned["desired_connection_mode"] == "bridge"
assert scanned["configured_connection_mode"] is None
assert scanned["active_connection_mode"] is None
assert scanned["connection_lifecycle"]["connection_ready"] is False
assert [item["device_id"] for item in scanned["devices"]] == ["bridge-candidate"]
repeated = service.state()
assert repeated["active_connection_mode"] is None
assert repeated["selected_device_id"] is None
def test_pending_reopened_physical_state_blocks_connect_and_mode_scan_before_device_io(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
device_edges: list[str] = []
async def forbidden_device_write(*_: object, **__: object) -> dict[str, Any]:
device_edges.append("network-write")
raise AssertionError("pending physical reopen must fail before GATT/Wi-Fi")
async def forbidden_scan(*_: object, **__: object) -> dict[str, Any]:
device_edges.append("ble-scan")
raise AssertionError("unsafe mode transition must fail before BLE scan")
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_device_write)
monkeypatch.setattr(facade_module, "scan", forbidden_scan)
connect_service, _ = service_with_fake_runtime(tmp_path / "connect")
_set_scanned_k1(connect_service, device_id="k1-a")
pending_bridge = _pending_reopened_physical_snapshot()
monkeypatch.setattr(
connect_service._physical_command_coordinator, # noqa: SLF001
"snapshot",
lambda: pending_bridge,
)
connect_topology_before = (
connect_service._selected_device_id, # noqa: SLF001
connect_service._k1_ip, # noqa: SLF001
connect_service._connection_mode, # noqa: SLF001
connect_service._connection_supervisor.snapshot(), # noqa: SLF001
)
with pytest.raises(facade_module.NetworkProvisioningConflict) as blocked_connect:
asyncio.run(
connect_service.connect(
_connect_request(
device_id="k1-a",
ssid="synthetic-network",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
)
)
)
assert blocked_connect.value.reason_code == "physical-command-reconciliation-required"
assert (
connect_service._selected_device_id, # noqa: SLF001
connect_service._k1_ip, # noqa: SLF001
connect_service._connection_mode, # noqa: SLF001
connect_service._connection_supervisor.snapshot(), # noqa: SLF001
) == connect_topology_before
mode_service, _ = service_with_fake_runtime(tmp_path / "mode")
_seed_supervised_connection(
mode_service,
transport_ref="k1-a",
connection_mode="bridge",
)
pending_mode = _pending_reopened_physical_snapshot()
monkeypatch.setattr(
mode_service._physical_command_coordinator, # noqa: SLF001
"snapshot",
lambda: pending_mode,
)
with mode_service._lock: # noqa: SLF001
mode_service._desired_connection_mode = "quick-connect" # noqa: SLF001
mode_service._desired_connection_mode_revision += 1 # noqa: SLF001
mode_topology_before = (
mode_service._selected_device_id, # noqa: SLF001
mode_service._k1_ip, # noqa: SLF001
mode_service._connection_mode, # noqa: SLF001
mode_service._connection_supervisor.snapshot(), # noqa: SLF001
)
with pytest.raises(facade_module.BleDiscoveryUnavailable) as blocked_scan:
asyncio.run(mode_service.scan_ble(1.0))
assert blocked_scan.value.reason_code == "connection-mode-switch-physical-state-unsafe"
assert (
mode_service._selected_device_id, # noqa: SLF001
mode_service._k1_ip, # noqa: SLF001
mode_service._connection_mode, # noqa: SLF001
mode_service._connection_supervisor.snapshot(), # noqa: SLF001
) == mode_topology_before
assert device_edges == []
def test_state_polling_auto_retires_terminal_prestart_control_once(
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
class FailedPrestartControl:
def __init__(self) -> None:
self.retire_calls = 0
self.retired = False
def snapshot(self) -> dict[str, object]:
if self.retired:
return {"state": "idle", "can_open": True, "failure": None}
return {
"state": "failed",
"can_open": True,
"failure": {
"reason_code": "mqtt-device-info-timeout",
"modeling_command_attempted": False,
"safe_to_retry": True,
},
}
def retire_for_network_change(self, **_: object) -> dict[str, object]:
self.retire_calls += 1
self.retired = True
return self.snapshot()
control = FailedPrestartControl()
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
service._acquire_application_control_process_lease() # noqa: SLF001
first = service.state()
second = service.state()
assert control.retire_calls == 1
assert first["application_control_session"]["state"] == "idle"
assert second["application_control_session"]["state"] == "idle"
assert first["connection_policy"]["actions"]["scan-ble"]["allowed"] is True
assert service._application_control_process_lease_holders == set() # noqa: SLF001
def _install_authoritative_ready_bridge_control(
service: XgridsK1CompatibilityService,
*,
transport_ref: str = "k1-a",
) -> tuple[FakeInteractiveControlSession, ApplicationConnectionBinding, dict[str, Any]]:
binding = _seed_supervised_connection(
service,
connection_mode="bridge",
transport_ref=transport_ref,
logical_device_id="device-a",
)
control = FakeInteractiveControlSession(initial_state="idle")
control.open(connection_binding=binding)
control.verified_control = _verified_control_for_binding(
binding,
logical_device_id="device-a",
control_session_id=f"test-control-{transport_ref}",
control_proof_revision=2,
)
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
service._reconcile_connection_supervisor( # noqa: SLF001
control.snapshot(),
service.runtime.snapshot(),
)
service._acquire_application_control_process_lease() # noqa: SLF001
state = service.state()
assert state["active_connection_mode"] == "bridge"
assert state["connection_lifecycle"]["active_binding_key"] is not None
return control, binding, state
def _reconfiguration_request(
state: dict[str, Any],
intent: str,
) -> PrepareConnectionReconfigurationRequest:
reconfiguration = state["connection_reconfiguration"]
lifecycle = state["connection_lifecycle"]
return PrepareConnectionReconfigurationRequest(
intent=intent, # type: ignore[arg-type]
expected_reconfiguration_revision=reconfiguration["revision"],
expected_reconfiguration_intent_id=reconfiguration["intent_id"],
expected_desired_mode_revision=state["desired_connection_mode_revision"],
expected_active_binding_key=lifecycle["active_binding_key"],
)
def _seed_durable_bridge_topology(
service: XgridsK1CompatibilityService,
*,
transport_ref: str,
ipv4: str,
) -> None:
store = service._semantic_topology_store # noqa: SLF001
assert store is not None
snapshot = store.snapshot()
store.commit(
transport_ref=transport_ref,
connection_mode="bridge",
ipv4=ipv4,
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
firmware_version="3.0.2",
source="ble-read-only-status",
observed_at_utc="2026-08-10T12:00:00Z",
predecessor_revision=(snapshot.record.revision if snapshot.record is not None else 0),
)
def _install_successful_bridge_verify_transport(
monkeypatch: pytest.MonkeyPatch,
*,
device_id: str,
ipv4: str,
writes: list[str],
) -> None:
async def existing_network_status(*_: object, **__: object) -> dict[str, Any]:
return {
**_wifi_status_read(ipv4),
"device_macos_uuid": device_id,
}
async def forbidden_network_write(*_: object, **__: object) -> dict[str, Any]:
writes.append("network-write")
raise AssertionError("read-only Verify must not provision Wi-Fi")
monkeypatch.setattr(facade_module, "read_wifi_status_once", existing_network_status)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_network_write)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(
facade_module,
"_host_route_class",
lambda _target: "direct-or-routed",
)
monkeypatch.setattr(facade_module, "_control_endpoint_reachable", lambda _target: True)
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
def test_read_only_monitor_holder_does_not_flap_reconfiguration_policy(
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_control, _binding, ready = _install_authoritative_ready_bridge_control(service)
ready_binding_key = ready["connection_lifecycle"]["active_binding_key"]
ready_host_epoch = ready["connection_supervisor"]["observed"]["host_path"]["epoch"]
assert ready["connection_policy"]["actions"]["prepare-select-device"]["allowed"] is True
assert ready["connection_policy"]["actions"]["prepare-change-network"]["allowed"] is True
service._acquire_k1_lifecycle_process_lease("monitor") # noqa: SLF001
try:
during_probe = service.state()
finally:
service._release_k1_lifecycle_process_lease("monitor") # noqa: SLF001
assert "monitor" in during_probe["k1_lifecycle_process_lease"]["holders"]
assert during_probe["connection_lifecycle"]["active_binding_key"] == ready_binding_key
assert (
during_probe["connection_supervisor"]["observed"]["host_path"]["epoch"] == ready_host_epoch
)
for action in ("prepare-select-device", "prepare-change-network"):
decision = during_probe["connection_policy"]["actions"][action]
assert decision["allowed"] is True
assert "k1-lifecycle-process-lease-network-owned" not in decision["reason_codes"]
def test_monitor_transient_wifi_observer_failures_retain_verified_control_and_refresh_tcp(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_control, binding, _ready = _install_authoritative_ready_bridge_control(service)
initial = service._connection_supervisor.snapshot() # noqa: SLF001
assert initial.authority.control_allowed is True
tcp_calls: list[str] = []
def association_observation(
reason_code: str,
token: str,
) -> HostWifiAssociationIdentityResult:
return {
"schema_version": 1,
"adapter": "unavailable",
"wifi_interface": None,
"association_state": "unavailable",
"evidence_quality": "unavailable",
"continuity_proven": False,
"continuity_token": token,
"reason_code": reason_code,
}
association_calls = 0
def alternating_unproven_association(
_interface_name: str | None,
*,
timeout_seconds: float = 30.0,
) -> HostWifiAssociationIdentityResult:
nonlocal association_calls
assert timeout_seconds == (facade_module.CONNECTION_MONITOR_ASSOCIATION_TIMEOUT_SECONDS)
association_calls += 1
return (
association_observation("host-wifi-operation-timeout", "a" * 64)
if association_calls % 2
else association_observation("association-identity-unavailable", "b" * 64)
)
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
monkeypatch.setattr(
service._host_wifi_association_probe, # noqa: SLF001
"observe",
alternating_unproven_association,
)
monkeypatch.setattr(
facade_module,
"_probe_control_endpoint_socket",
lambda target: (
tcp_calls.append(target) or facade_module.TcpReachabilityProbeResult(reachable=True)
),
)
async def three_mixed_cycles() -> tuple[
facade_module.ConnectionSupervisorSnapshot,
facade_module.ConnectionSupervisorSnapshot,
facade_module.ConnectionSupervisorSnapshot,
]:
first = await service._connection_monitor.poll_once() # noqa: SLF001
second = await service._connection_monitor.poll_once() # noqa: SLF001
third = await service._connection_monitor.poll_once() # noqa: SLF001
return first, second, third
retained_cycles = asyncio.run(three_mixed_cycles())
assert association_calls == 6
assert tcp_calls == [binding.target_ipv4] * 3
for retained in retained_cycles:
assert retained.revision > initial.revision
assert retained.host_path.available is True
assert retained.host_path.epoch == initial.host_path.epoch
assert retained.host_path.fingerprint == initial.host_path.fingerprint
assert retained.endpoint.tcp_state == "reachable"
assert retained.endpoint.host_path_epoch == initial.host_path.epoch
assert retained.device_identity.state == "verified"
assert retained.control_plane.state == "healthy"
assert retained.authority.control_allowed is True
assert retained.lease.state == "reachable"
assert retained.lease.generation == initial.lease.generation
assert service._connection_monitor_contact_gate.locked() is False # noqa: SLF001
assert service._application_control_process_lease_holders == {"control"} # noqa: SLF001
def privacy_limited_association(
_interface_name: str | None,
*,
timeout_seconds: float = 30.0,
) -> HostWifiAssociationIdentityResult:
assert timeout_seconds == (facade_module.CONNECTION_MONITOR_ASSOCIATION_TIMEOUT_SECONDS)
return association_observation("association-identity-unavailable", "b" * 64)
monkeypatch.setattr(
service._host_wifi_association_probe, # noqa: SLF001
"observe",
privacy_limited_association,
)
privacy_path = service._sample_host_path( # noqa: SLF001
binding.target_ipv4,
association_timeout_seconds=(facade_module.CONNECTION_MONITOR_ASSOCIATION_TIMEOUT_SECONDS),
fail_closed_unproven_association=True,
)
assert privacy_path.available is True
assert privacy_path.reason_code is None
assert privacy_path.observation_failure_class == "association-observer"
assert privacy_path.fingerprint == initial.host_path.fingerprint
@pytest.mark.parametrize(
("reason_code", "expected_failure_class"),
[
("host-wifi-operation-timeout", "association-observer"),
("wifi-interface-inactive", "route"),
],
)
def test_monitor_debounces_only_technical_association_timeout(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
reason_code: str,
expected_failure_class: str,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
def unavailable_association(
_interface_name: str | None,
*,
timeout_seconds: float = 30.0,
) -> HostWifiAssociationIdentityResult:
assert timeout_seconds == 3.0
return {
"schema_version": 1,
"adapter": "CoreWLAN",
"wifi_interface": True,
"association_state": "unavailable",
"evidence_quality": "unavailable",
"continuity_proven": False,
"continuity_token": "a" * 64,
"reason_code": reason_code,
}
monkeypatch.setattr(
service._host_wifi_association_probe, # noqa: SLF001
"observe",
unavailable_association,
)
path = service._sample_host_path( # noqa: SLF001
"192.168.68.51",
association_timeout_seconds=3.0,
fail_closed_unproven_association=True,
)
assert path.available is False
assert path.reason_code == reason_code
assert path.observation_failure_class == expected_failure_class
assert path.kernel_route_fingerprint == "test-route:192.168.68.51"
def test_monitor_association_sample_over_two_seconds_survives_four_full_cycles(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_control, binding, _ready = _install_authoritative_ready_bridge_control(service)
host_samples: list[str] = []
tcp_samples: list[str] = []
def slow_first_host_sample(
target: str,
*,
association_timeout_seconds: float = 30.0,
fail_closed_unproven_association: bool = False,
) -> HostPathProbeResult:
assert association_timeout_seconds == 3.0
assert association_timeout_seconds == (
facade_module.CONNECTION_MONITOR_ASSOCIATION_TIMEOUT_SECONDS
)
assert fail_closed_unproven_association is True
host_samples.append(target)
if len(host_samples) % 2 == 1:
# Reproduce the field boundary that exceeded the former 2 s
# xcrun/CoreWLAN deadline without making the test depend on macOS.
time.sleep(2.05)
return _direct_host_path(target)
monkeypatch.setattr(service, "_sample_host_path", slow_first_host_sample)
monkeypatch.setattr(
facade_module,
"_probe_control_endpoint_socket",
lambda target: (
tcp_samples.append(target) or facade_module.TcpReachabilityProbeResult(reachable=True)
),
)
async def four_cycles() -> tuple[list[Any], list[float], list[dict[str, Any]]]:
snapshots: list[Any] = []
elapsed_cycles: list[float] = []
public_states: list[dict[str, Any]] = []
for _ in range(4):
started = time.monotonic()
snapshots.append(
await service._connection_monitor.poll_once() # noqa: SLF001
)
elapsed_cycles.append(time.monotonic() - started)
public_states.append(service.state())
return snapshots, elapsed_cycles, public_states
refreshed_cycles, elapsed_cycles, public_states = asyncio.run(four_cycles())
assert all(
2.0 < elapsed < DEFAULT_TRANSPORT_OBSERVATION_TTL_SECONDS for elapsed in elapsed_cycles
)
assert facade_module.CONNECTION_MONITOR_HOST_CONTACT_BOUND_SECONDS == 5.0
assert (
facade_module.CONNECTION_MONITOR_HOST_CONTACT_BOUND_SECONDS
< facade_module.CONNECTION_MONITOR_QUIESCE_TIMEOUT_SECONDS
)
assert facade_module.CONNECTION_MONITOR_FULL_PASS_BOUND_SECONDS == 11.5
assert (
2 * (facade_module.CONNECTION_MONITOR_FULL_PASS_BOUND_SECONDS + 1.0)
< DEFAULT_TRANSPORT_OBSERVATION_TTL_SECONDS
)
assert host_samples == [binding.target_ipv4, binding.target_ipv4] * 4
assert tcp_samples == [binding.target_ipv4] * 4
initial_epoch = refreshed_cycles[0].host_path.epoch
initial_lease_generation = refreshed_cycles[0].lease.generation
initial_selected = public_states[0]["selected_device_id"]
initial_session = public_states[0]["device_session"]["device_session_id"]
for refreshed, public in zip(refreshed_cycles, public_states, strict=True):
assert refreshed.host_path.available is True
assert refreshed.host_path.epoch == initial_epoch
assert refreshed.endpoint.tcp_state == "reachable"
assert refreshed.lease.state == "reachable"
assert refreshed.lease.generation == initial_lease_generation
assert refreshed.authority.control_allowed is True
assert public["selected_device_id"] == initial_selected
assert public["device_session"]["device_session_id"] == initial_session
assert public["application_control_session"]["state"] == "connection-ready"
def test_monitor_refreshes_verified_binding_across_timeout_positive_timeout_cycles(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
control, binding, ready = _install_authoritative_ready_bridge_control(service)
baseline_supervisor = service._connection_supervisor.snapshot() # noqa: SLF001
baseline_path = baseline_supervisor.host_path
assert baseline_path.kernel_route_fingerprint is not None
selected_device_id = ready["selected_device_id"]
device_session_id = ready["device_session"]["device_session_id"]
active_binding_key = ready["connection_lifecycle"]["active_binding_key"]
tcp_samples: list[str] = []
probe_mode = {"technical_failure": True}
def sample_host(target: str, **_: object) -> HostPathProbeResult:
if not probe_mode["technical_failure"]:
return _direct_host_path(target)
return HostPathProbeResult(
available=False,
fingerprint=None,
interface=baseline_path.interface,
source_ipv4=baseline_path.source_ipv4,
route_class="unavailable",
reason_code="host-wifi-operation-timeout",
observation_failure_class="association-observer",
kernel_route_fingerprint=baseline_path.kernel_route_fingerprint,
)
monkeypatch.setattr(service, "_sample_host_path", sample_host)
monkeypatch.setattr(
facade_module,
"_probe_control_endpoint_socket",
lambda target: (
tcp_samples.append(target) or facade_module.TcpReachabilityProbeResult(reachable=True)
),
)
async def scenario() -> tuple[list[Any], list[dict[str, Any]]]:
snapshots: list[Any] = []
states: list[dict[str, Any]] = []
for _ in range(2):
snapshots.append(
await service._connection_monitor.poll_once() # noqa: SLF001
)
states.append(service.state())
probe_mode["technical_failure"] = False
snapshots.append(await service._connection_monitor.poll_once()) # noqa: SLF001
states.append(service.state())
probe_mode["technical_failure"] = True
for _ in range(5):
snapshots.append(
await service._connection_monitor.poll_once() # noqa: SLF001
)
states.append(service.state())
return snapshots, states
monitor_states, public_states = asyncio.run(scenario())
assert len(monitor_states) == 8
assert tcp_samples == [binding.target_ipv4] * 8
previous_revision = baseline_supervisor.revision
for retained, public in zip(monitor_states, public_states, strict=True):
assert retained.revision > previous_revision
previous_revision = retained.revision
assert retained.host_path.available is True
assert retained.host_path.epoch == baseline_path.epoch
assert retained.host_path.fingerprint == baseline_path.fingerprint
assert retained.host_path.reason_code is None
assert retained.host_path_negative_streak == 0
assert retained.endpoint.tcp_state == "reachable"
assert retained.endpoint.host_path_epoch == baseline_path.epoch
assert retained.device_identity.state == "verified"
assert retained.control_plane.state == "healthy"
assert retained.lease.state == "reachable"
assert retained.lease.generation == baseline_supervisor.lease.generation
assert retained.authority.control_allowed is True
assert public["selected_device_id"] == selected_device_id
assert public["device_session"]["device_session_id"] == device_session_id
assert public["connection_lifecycle"]["active_binding_key"] == active_binding_key
assert public["application_control_session"]["state"] == "connection-ready"
assert public["k1_lifecycle_process_lease"]["holders"] == ["control"]
assert monitor_states[-1].host_path.observed_at != baseline_path.observed_at
assert control.state == "connection-ready"
def test_command_preflight_retains_exact_route_when_only_association_observer_times_out(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_control, binding, _ready = _install_authoritative_ready_bridge_control(service)
baseline = service._connection_supervisor.snapshot() # noqa: SLF001
association_calls = 0
def timed_out_association(
_interface_name: str | None,
*,
timeout_seconds: float = 30.0,
) -> HostWifiAssociationIdentityResult:
nonlocal association_calls
assert timeout_seconds == facade_module.COMMAND_BOUND_ASSOCIATION_TIMEOUT_SECONDS
association_calls += 1
return {
"schema_version": 1,
"adapter": "CoreWLAN",
"wifi_interface": True,
"association_state": "unavailable",
"evidence_quality": "unavailable",
"continuity_proven": False,
"continuity_token": f"{association_calls:064x}",
"reason_code": "host-wifi-operation-timeout",
}
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
monkeypatch.setattr(
service._host_wifi_association_probe, # noqa: SLF001
"observe",
timed_out_association,
)
for _ in range(5):
service._validate_application_connection_path(binding) # noqa: SLF001
retained = service._connection_supervisor.snapshot() # noqa: SLF001
assert retained.host_path.available is True
assert retained.host_path.epoch == baseline.host_path.epoch
assert retained.host_path.fingerprint == baseline.host_path.fingerprint
assert retained.endpoint.tcp_state == "reachable"
assert retained.device_identity.state == "verified"
assert retained.control_plane.state == "healthy"
assert retained.lease.state == "reachable"
assert retained.authority.control_allowed is True
assert association_calls == 5
def test_command_prepare_allows_contended_probe_plus_own_helper_within_eight_seconds(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
harness = DeterministicContendedAssociationProbe(
lock_wait_seconds=3.0,
helper_required_seconds=3.2,
)
probe = harness.build(monkeypatch, tmp_path)
service, _ = service_with_fake_runtime(tmp_path)
service._host_wifi_association_probe = probe # type: ignore[assignment] # noqa: SLF001
supervisor = service._connection_supervisor # noqa: SLF001
supervisor._monotonic_clock = lambda: harness.monotonic # noqa: SLF001
supervisor._suspend_aware_clock = lambda: harness.wall # noqa: SLF001
# The helper crosses this deliberately narrow regression TTL. A fresh
# exact same route/association result is itself the replacement sample and
# must refresh the original epoch before any snapshot reduction runs.
supervisor._observation_ttl_seconds = 5.0 # noqa: SLF001
control, binding, _ready = _install_binding_validating_ready_control(
service,
host_path=_association_bound_direct_host_path("192.168.1.20"),
)
target = EndpointTarget(binding.target_ipv4, binding.target_port)
harness.on_first_lock_acquired = lambda: supervisor.observe_endpoint(
target=target,
intent_id=binding.intent_id,
host_path_epoch=binding.host_path_epoch,
reachable=True,
)
control.state = "workspace-ready"
control.state_revision += 1
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host=binding.target_ipv4,
compatibility_attestation=ATTESTATION,
expected_control_session_generation=control.session_generation,
expected_control_state_revision=control.state_revision,
)
)
assert facade_module.CONNECTION_MONITOR_ASSOCIATION_TIMEOUT_SECONDS == 3.0
assert facade_module.COMMAND_BOUND_ASSOCIATION_TIMEOUT_SECONDS == 8.0
assert facade_module.CONNECTION_VERIFY_HARD_TIMEOUT_SECONDS == 125.0
assert prepared["acquisition"]["state"] == "prepared"
assert prepared["application_control_session"]["state"] == "project-ready"
assert supervisor.snapshot().host_path.epoch == binding.host_path_epoch
assert supervisor.snapshot().authority.control_allowed is True
assert control.validation_calls == 2
assert harness.lock_timeouts == [8.0, 8.0]
assert harness.helper_timeouts == [pytest.approx(5.0)]
assert harness.monotonic == pytest.approx(106.2)
def test_privacy_limited_monitor_keeps_prestart_authority_through_three_minutes(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
monotonic_now = [100.0]
suspend_aware_now = [1_000.0]
supervisor = service._connection_supervisor # noqa: SLF001
supervisor._monotonic_clock = lambda: monotonic_now[0] # noqa: SLF001
supervisor._suspend_aware_clock = lambda: suspend_aware_now[0] # noqa: SLF001
control, binding, _ready = _install_binding_validating_ready_control(
service,
host_path=_association_bound_direct_host_path("192.168.1.20"),
)
timeouts: list[float] = []
tcp_calls: list[str] = []
def privacy_limited_association(
_interface_name: str | None,
*,
timeout_seconds: float,
) -> HostWifiAssociationIdentityResult:
timeouts.append(timeout_seconds)
return {
"schema_version": 1,
"adapter": "CoreWLAN",
"wifi_interface": True,
"association_state": "unavailable",
"evidence_quality": "unavailable",
"continuity_proven": False,
"continuity_token": "d" * 64,
"reason_code": "association-identity-unavailable",
}
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
monkeypatch.setattr(
service._host_wifi_association_probe, # noqa: SLF001
"observe",
privacy_limited_association,
)
monkeypatch.setattr(
facade_module,
"_probe_control_endpoint_socket",
lambda target: (
tcp_calls.append(target) or facade_module.TcpReachabilityProbeResult(reachable=True)
),
)
async def monitor_for_three_minutes() -> None:
for proof_revision in range(3, 33):
observed = await service._connection_monitor.poll_once() # noqa: SLF001
assert observed.host_path.epoch == binding.host_path_epoch
assert observed.authority.control_allowed is True
assert control.verified_control is not None
control.verified_control = {
**control.verified_control,
"control_proof_revision": proof_revision,
}
service._reconcile_connection_supervisor( # noqa: SLF001
control.snapshot(),
service.runtime.snapshot(),
)
monotonic_now[0] += 6.1
suspend_aware_now[0] += 6.1
asyncio.run(monitor_for_three_minutes())
assert monotonic_now[0] > 280.0
control.state = "workspace-ready"
control.state_revision += 1
prepared = service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host=binding.target_ipv4,
compatibility_attestation=ATTESTATION,
expected_control_session_generation=control.session_generation,
expected_control_state_revision=control.state_revision,
)
)
final = supervisor.snapshot()
assert prepared["acquisition"]["state"] == "prepared"
assert final.host_path.epoch == binding.host_path_epoch
assert final.host_path.fingerprint == (
_association_bound_direct_host_path(binding.target_ipv4).fingerprint
)
assert final.endpoint.tcp_state == "reachable"
assert final.device_identity.state == "verified"
assert final.control_plane.state == "healthy"
assert final.authority.control_allowed is True
assert tcp_calls == [binding.target_ipv4] * 30
assert timeouts.count(facade_module.CONNECTION_MONITOR_ASSOCIATION_TIMEOUT_SECONDS) == 60
assert timeouts.count(facade_module.COMMAND_BOUND_ASSOCIATION_TIMEOUT_SECONDS) == 2
def test_command_timeout_after_stale_epoch_fails_before_local_or_physical_mutation(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
supervisor = service._connection_supervisor # noqa: SLF001
def expire_current_epoch() -> None:
stale = supervisor.snapshot()
assert stale.host_path.reason_code == "host-path-observation-stale"
harness = DeterministicContendedAssociationProbe(
lock_wait_seconds=3.0,
helper_required_seconds=6.0,
on_first_lock_acquired=expire_current_epoch,
)
probe = harness.build(monkeypatch, tmp_path)
service._host_wifi_association_probe = probe # type: ignore[assignment] # noqa: SLF001
supervisor._monotonic_clock = lambda: harness.monotonic # noqa: SLF001
supervisor._suspend_aware_clock = lambda: harness.wall # noqa: SLF001
supervisor._observation_ttl_seconds = 2.0 # noqa: SLF001
control, binding, _ready = _install_binding_validating_ready_control(
service,
host_path=_association_bound_direct_host_path("192.168.1.20"),
)
control.state = "workspace-ready"
control.state_revision += 1
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
operations_before = service._operations.snapshot() # noqa: SLF001
physical_before = service._physical_command_ledger.snapshot() # noqa: SLF001
with pytest.raises(ApplicationConnectionBindingLost):
service.prepare_acquisition(
_prepare_request(
project_name=PROJECT_NAME,
host=binding.target_ipv4,
compatibility_attestation=ATTESTATION,
expected_control_session_generation=control.session_generation,
expected_control_state_revision=control.state_revision,
)
)
stale = supervisor.snapshot()
assert harness.lock_timeouts == [8.0]
assert harness.helper_timeouts == [pytest.approx(5.0)]
assert harness.monotonic == pytest.approx(108.0)
assert stale.host_path.epoch == binding.host_path_epoch + 1
assert stale.host_path.reason_code == "host-path-observation-stale"
assert service._acquisition is None # noqa: SLF001
assert service._operations.snapshot() == operations_before # noqa: SLF001
assert service._physical_command_ledger.snapshot() == physical_before # noqa: SLF001
def test_command_privacy_bridge_never_retains_a_proven_association_change(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_control, binding, _ready = _install_binding_validating_ready_control(
service,
host_path=_association_bound_direct_host_path("192.168.1.20"),
)
baseline = service._connection_supervisor.snapshot() # noqa: SLF001
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
monkeypatch.setattr(
service._host_wifi_association_probe, # noqa: SLF001
"observe",
lambda *_args, **_kwargs: {
**DeterministicContendedAssociationProbe.proven_observation(),
"continuity_token": "b" * 64,
},
)
with pytest.raises(ApplicationConnectionBindingLost):
service._validate_application_connection_path(binding) # noqa: SLF001
changed = service._connection_supervisor.snapshot() # noqa: SLF001
assert changed.host_path.epoch == baseline.host_path.epoch + 1
assert changed.host_path.kernel_route_fingerprint == (
baseline.host_path.kernel_route_fingerprint
)
assert changed.host_path.fingerprint != baseline.host_path.fingerprint
assert changed.authority.control_allowed is False
@pytest.mark.parametrize(
"broken_fact",
[
"configured-unverified",
"identity-stale",
"identity-intent",
"identity-mode",
"identity-epoch",
"control-lost",
"control-session",
"control-epoch",
"lease-lost",
"lease-intent",
"lease-mode",
"lease-target",
"lease-epoch",
"authority-denied",
],
)
def test_command_privacy_bridge_requires_exact_verified_control_chain(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
broken_fact: str,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_control, binding, _ready = _install_binding_validating_ready_control(
service,
host_path=_association_bound_direct_host_path("192.168.1.20"),
)
supervisor = service._connection_supervisor # noqa: SLF001
baseline = supervisor.snapshot()
candidate = baseline
if broken_fact == "configured-unverified":
candidate = replace(
baseline,
device_identity=replace(baseline.device_identity, state="unverified"),
control_plane=replace(baseline.control_plane, state="idle", session_id=None),
lease=replace(baseline.lease, state="configured-unverified"),
authority=replace(
baseline.authority,
control_allowed=False,
acquisition_start_allowed=False,
),
)
elif broken_fact.startswith("identity-"):
identity_changes: dict[str, object] = {
"identity-stale": {"state": "stale"},
"identity-intent": {"intent_id": "other-intent"},
"identity-mode": {"connection_mode": "quick-connect"},
"identity-epoch": {"host_path_epoch": binding.host_path_epoch + 1},
}[broken_fact]
candidate = replace(
baseline,
device_identity=replace(baseline.device_identity, **identity_changes),
)
elif broken_fact.startswith("control-"):
control_changes: dict[str, object] = {
"control-lost": {"state": "lost"},
"control-session": {"session_id": " "},
"control-epoch": {"host_path_epoch": binding.host_path_epoch + 1},
}[broken_fact]
candidate = replace(
baseline,
control_plane=replace(baseline.control_plane, **control_changes),
)
elif broken_fact.startswith("lease-"):
lease_changes: dict[str, object] = {
"lease-lost": {"state": "lost"},
"lease-intent": {"intent_id": "other-intent"},
"lease-mode": {"connection_mode": "quick-connect"},
"lease-target": {
"target": EndpointTarget("192.168.1.21", binding.target_port)
},
"lease-epoch": {"host_path_epoch": binding.host_path_epoch + 1},
}[broken_fact]
candidate = replace(
baseline,
lease=replace(baseline.lease, **lease_changes),
)
else:
assert broken_fact == "authority-denied"
candidate = replace(
baseline,
authority=replace(
baseline.authority,
control_allowed=False,
acquisition_start_allowed=False,
),
)
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
monkeypatch.setattr(
service._host_wifi_association_probe, # noqa: SLF001
"observe",
lambda *_args, **_kwargs: {
"schema_version": 1,
"adapter": "CoreWLAN",
"wifi_interface": True,
"association_state": "unavailable",
"evidence_quality": "unavailable",
"continuity_proven": False,
"continuity_token": "d" * 64,
"reason_code": "association-identity-unavailable",
},
)
monkeypatch.setattr(
supervisor,
"association_timeout_retention_candidate",
lambda *, expected_target: (
candidate
if expected_target == EndpointTarget(binding.target_ipv4, binding.target_port)
else None
),
)
sampled = service._sample_host_path(binding.target_ipv4) # noqa: SLF001
assert sampled.available is True
assert sampled.reason_code == "association-identity-unavailable"
assert sampled.fingerprint != baseline.host_path.fingerprint
@pytest.mark.parametrize("changed_raw_fact", ["kernel-route", "interface", "source-ipv4"])
def test_command_privacy_bridge_never_retains_a_raw_route_change(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
changed_raw_fact: str,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_control, binding, _ready = _install_binding_validating_ready_control(
service,
host_path=_association_bound_direct_host_path("192.168.1.20"),
)
supervisor = service._connection_supervisor # noqa: SLF001
baseline = supervisor.snapshot()
assert baseline.host_path.kernel_route_fingerprint is not None
changed_path = HostPathProbeResult(
available=True,
fingerprint=(
"changed-kernel-route"
if changed_raw_fact == "kernel-route"
else baseline.host_path.kernel_route_fingerprint
),
interface=(
"changed0" if changed_raw_fact == "interface" else baseline.host_path.interface
),
source_ipv4=(
"192.168.99.2"
if changed_raw_fact == "source-ipv4"
else baseline.host_path.source_ipv4
),
route_class="direct",
kernel_route_fingerprint=(
"changed-kernel-route"
if changed_raw_fact == "kernel-route"
else baseline.host_path.kernel_route_fingerprint
),
)
monkeypatch.setattr(facade_module, "_inspect_host_path", lambda _target: changed_path)
monkeypatch.setattr(
service._host_wifi_association_probe, # noqa: SLF001
"observe",
lambda *_args, **_kwargs: {
"schema_version": 1,
"adapter": "CoreWLAN",
"wifi_interface": True,
"association_state": "unavailable",
"evidence_quality": "unavailable",
"continuity_proven": False,
"continuity_token": "d" * 64,
"reason_code": "association-identity-unavailable",
},
)
with pytest.raises(ApplicationConnectionBindingLost):
service._validate_application_connection_path(binding) # noqa: SLF001
changed = supervisor.snapshot()
assert changed.host_path.epoch == binding.host_path_epoch + 1
assert changed.authority.control_allowed is False
def test_command_timeout_crossing_host_ttl_refreshes_same_route_without_epoch_loss(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
monotonic_now = [100.0]
suspend_aware_now = [1_000.0]
supervisor = service._connection_supervisor # noqa: SLF001
supervisor._monotonic_clock = lambda: monotonic_now[0] # noqa: SLF001
supervisor._suspend_aware_clock = lambda: suspend_aware_now[0] # noqa: SLF001
supervisor._observation_ttl_seconds = 5.0 # noqa: SLF001
_control, binding, _ready = _install_authoritative_ready_bridge_control(service)
baseline = supervisor.snapshot()
target = EndpointTarget(binding.target_ipv4, binding.target_port)
monotonic_now[0] += 4.0
suspend_aware_now[0] += 4.0
assert supervisor.observe_endpoint(
target=target,
intent_id=binding.intent_id,
host_path_epoch=binding.host_path_epoch,
reachable=True,
)
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
def timeout_after_crossing_host_ttl(
_interface_name: str | None,
*,
timeout_seconds: float,
) -> HostWifiAssociationIdentityResult:
assert timeout_seconds == facade_module.COMMAND_BOUND_ASSOCIATION_TIMEOUT_SECONDS
monotonic_now[0] += 2.0
suspend_aware_now[0] += 2.0
return {
"schema_version": 1,
"adapter": "CoreWLAN",
"wifi_interface": True,
"association_state": "unavailable",
"evidence_quality": "unavailable",
"continuity_proven": False,
"continuity_token": "f" * 64,
"reason_code": "host-wifi-operation-timeout",
}
monkeypatch.setattr(
service._host_wifi_association_probe, # noqa: SLF001
"observe",
timeout_after_crossing_host_ttl,
)
service._validate_application_connection_path(binding) # noqa: SLF001
retained = supervisor.snapshot()
assert retained.host_path.epoch == baseline.host_path.epoch
assert retained.host_path.fingerprint == baseline.host_path.fingerprint
assert retained.host_path.available is True
assert retained.endpoint.tcp_state == "reachable"
assert retained.device_identity.state == "verified"
assert retained.control_plane.state == "healthy"
assert retained.lease.state == "reachable"
assert retained.authority.control_allowed is True
def test_configured_unverified_monitor_keeps_same_route_without_promoting_authority(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
binding = _seed_supervised_connection(service, with_control=False)
baseline = service._connection_supervisor.snapshot() # noqa: SLF001
association_calls = 0
tcp_calls: list[str] = []
def timed_out_association(
_interface_name: str | None,
*,
timeout_seconds: float = 30.0,
) -> HostWifiAssociationIdentityResult:
nonlocal association_calls
assert timeout_seconds == facade_module.CONNECTION_MONITOR_ASSOCIATION_TIMEOUT_SECONDS
association_calls += 1
return {
"schema_version": 1,
"adapter": "CoreWLAN",
"wifi_interface": True,
"association_state": "unavailable",
"evidence_quality": "unavailable",
"continuity_proven": False,
"continuity_token": f"{association_calls:064x}",
"reason_code": "host-wifi-operation-timeout",
}
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
monkeypatch.setattr(
service._host_wifi_association_probe, # noqa: SLF001
"observe",
timed_out_association,
)
monkeypatch.setattr(
facade_module,
"_probe_control_endpoint_socket",
lambda target: (
tcp_calls.append(target) or facade_module.TcpReachabilityProbeResult(reachable=True)
),
)
async def poll_five_times() -> list[facade_module.ConnectionSupervisorSnapshot]:
return [
await service._connection_monitor.poll_once() # noqa: SLF001
for _ in range(5)
]
snapshots = asyncio.run(poll_five_times())
assert association_calls == 10
assert tcp_calls == [binding.target_ipv4] * 5
for retained in snapshots:
assert retained.host_path.available is True
assert retained.host_path.epoch == baseline.host_path.epoch
assert retained.host_path.fingerprint == baseline.host_path.fingerprint
assert retained.endpoint.tcp_state == "reachable"
assert retained.device_identity.state == "unverified"
assert retained.control_plane.state != "healthy"
assert retained.lease.state == "configured-unverified"
assert retained.authority.control_allowed is False
assert retained.authority.acquisition_start_allowed is False
assert "verify-control-device-info" in retained.allowed_actions
def test_monitor_layer_retains_exact_configured_route_across_association_lock_timeout(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
binding = _seed_supervised_connection(service, with_control=False)
baseline = service._connection_supervisor.snapshot() # noqa: SLF001
assert baseline.host_path.kernel_route_fingerprint is not None
tcp_calls: list[str] = []
monkeypatch.setattr(
service,
"_sample_host_path",
lambda target, **_kwargs: HostPathProbeResult(
available=False,
fingerprint=None,
interface=baseline.host_path.interface,
source_ipv4=baseline.host_path.source_ipv4,
route_class="unavailable",
reason_code="host-wifi-operation-timeout",
observation_failure_class="association-observer",
kernel_route_fingerprint=baseline.host_path.kernel_route_fingerprint,
),
)
monkeypatch.setattr(
facade_module,
"_probe_control_endpoint_socket",
lambda target: (
tcp_calls.append(target)
or facade_module.TcpReachabilityProbeResult(reachable=True)
),
)
async def poll_three_times() -> list[facade_module.ConnectionSupervisorSnapshot]:
return [
await service._connection_monitor.poll_once() # noqa: SLF001
for _ in range(3)
]
snapshots = asyncio.run(poll_three_times())
assert tcp_calls == [binding.target_ipv4] * 3
for retained in snapshots:
assert retained.host_path.available is True
assert retained.host_path.epoch == baseline.host_path.epoch
assert retained.host_path.fingerprint == baseline.host_path.fingerprint
assert retained.endpoint.tcp_state == "reachable"
assert retained.device_identity.state == "unverified"
assert retained.authority.control_allowed is False
assert retained.authority.acquisition_start_allowed is False
assert "verify-control-device-info" in retained.allowed_actions
def test_association_timeout_cannot_hide_a_real_kernel_route_change(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_control, binding, _ready = _install_authoritative_ready_bridge_control(service)
baseline = service._connection_supervisor.snapshot() # noqa: SLF001
changed_path = HostPathProbeResult(
available=True,
fingerprint="changed-kernel-route",
interface=baseline.host_path.interface,
source_ipv4=baseline.host_path.source_ipv4,
route_class="direct",
kernel_route_fingerprint="changed-kernel-route",
)
monkeypatch.setattr(facade_module, "_inspect_host_path", lambda _target: changed_path)
monkeypatch.setattr(
service._host_wifi_association_probe, # noqa: SLF001
"observe",
lambda *_args, **_kwargs: {
"schema_version": 1,
"adapter": "CoreWLAN",
"wifi_interface": True,
"association_state": "unavailable",
"evidence_quality": "unavailable",
"continuity_proven": False,
"continuity_token": "f" * 64,
"reason_code": "host-wifi-operation-timeout",
},
)
with pytest.raises(ApplicationConnectionBindingLost):
service._validate_application_connection_path(binding) # noqa: SLF001
changed = service._connection_supervisor.snapshot() # noqa: SLF001
assert changed.host_path.epoch == baseline.host_path.epoch + 1
assert changed.host_path.kernel_route_fingerprint == "changed-kernel-route"
assert changed.authority.control_allowed is False
assert changed.lease.state != "reachable"
def test_command_preflight_drops_stale_sample_after_concurrent_route_change(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_control, binding, _ready = _install_authoritative_ready_bridge_control(service)
baseline = service._connection_supervisor.snapshot() # noqa: SLF001
changed_path = HostPathProbeResult(
available=True,
fingerprint="changed-combined-route",
interface="changed0",
source_ipv4="192.168.99.2",
route_class="direct",
kernel_route_fingerprint="changed-kernel-route",
)
stale_path = HostPathProbeResult(
available=True,
fingerprint=baseline.host_path.fingerprint,
interface=baseline.host_path.interface,
source_ipv4=baseline.host_path.source_ipv4,
route_class="direct",
kernel_route_fingerprint=baseline.host_path.kernel_route_fingerprint,
)
def sample_after_newer_route_wins(
_target: str,
*,
association_timeout_seconds: float,
) -> HostPathProbeResult:
assert (
association_timeout_seconds
== facade_module.COMMAND_BOUND_ASSOCIATION_TIMEOUT_SECONDS
)
observed_epoch = service._connection_supervisor.observe_host_path( # noqa: SLF001
changed_path
)
assert observed_epoch == baseline.host_path.epoch + 1
return stale_path
monkeypatch.setattr(service, "_sample_host_path", sample_after_newer_route_wins)
with pytest.raises(ApplicationConnectionBindingLost):
service._validate_application_connection_path(binding) # noqa: SLF001
current = service._connection_supervisor.snapshot() # noqa: SLF001
assert current.host_path.epoch == baseline.host_path.epoch + 1
assert current.host_path.fingerprint == "changed-combined-route"
assert current.host_path.kernel_route_fingerprint == "changed-kernel-route"
assert current.host_path.interface == "changed0"
assert current.host_path.source_ipv4 == "192.168.99.2"
assert current.authority.control_allowed is False
@pytest.mark.parametrize(
"changed_route_fact",
["fingerprint", "interface", "source-ipv4"],
)
def test_monitor_does_not_debounce_real_route_change_hidden_by_observer_failure(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
changed_route_fact: str,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_control, _binding, _ready = _install_authoritative_ready_bridge_control(service)
baseline = service._connection_supervisor.snapshot() # noqa: SLF001
baseline_path = baseline.host_path
assert baseline_path.kernel_route_fingerprint is not None
changed = HostPathProbeResult(
available=False,
fingerprint=None,
interface=("changed0" if changed_route_fact == "interface" else baseline_path.interface),
source_ipv4=(
"192.168.99.2" if changed_route_fact == "source-ipv4" else baseline_path.source_ipv4
),
route_class="unavailable",
reason_code="host-wifi-operation-timeout",
observation_failure_class="association-observer",
kernel_route_fingerprint=(
"changed-kernel-route"
if changed_route_fact == "fingerprint"
else baseline_path.kernel_route_fingerprint
),
)
monkeypatch.setattr(service, "_sample_host_path", lambda *_args, **_kwargs: changed)
tcp_samples: list[str] = []
monkeypatch.setattr(
facade_module,
"_probe_control_endpoint_socket",
lambda target: (
tcp_samples.append(target) or facade_module.TcpReachabilityProbeResult(reachable=True)
),
)
observed = asyncio.run(service._connection_monitor.poll_once()) # noqa: SLF001
assert observed.revision > baseline.revision
assert observed.host_path.available is False
assert observed.host_path.reason_code == "host-wifi-operation-timeout"
assert observed.authority.control_allowed is False
assert observed.lease.state != "reachable"
assert tcp_samples == []
def test_read_only_monitor_runs_alongside_steady_control_holder(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_control, binding, _ready = _install_authoritative_ready_bridge_control(service)
initial = service._connection_supervisor.snapshot() # noqa: SLF001
host_samples: list[str] = []
tcp_samples: list[str] = []
def sample_host(
target: str,
*,
association_timeout_seconds: float = 30.0,
fail_closed_unproven_association: bool = False,
) -> HostPathProbeResult:
assert association_timeout_seconds == (
facade_module.CONNECTION_MONITOR_ASSOCIATION_TIMEOUT_SECONDS
)
assert fail_closed_unproven_association is True
host_samples.append(target)
return _direct_host_path(target)
def sample_tcp(target: str) -> facade_module.TcpReachabilityProbeResult:
tcp_samples.append(target)
return facade_module.TcpReachabilityProbeResult(reachable=True)
monkeypatch.setattr(service, "_sample_host_path", sample_host)
monkeypatch.setattr(facade_module, "_probe_control_endpoint_socket", sample_tcp)
refreshed = asyncio.run(service._connection_monitor.poll_once()) # noqa: SLF001
assert host_samples == [binding.target_ipv4, binding.target_ipv4]
assert tcp_samples == [binding.target_ipv4]
assert refreshed.revision > initial.revision
assert refreshed.host_path.epoch == initial.host_path.epoch
assert refreshed.endpoint.tcp_state == "reachable"
assert service._application_control_process_lease_holders == {"control"} # noqa: SLF001
def test_read_only_monitor_keeps_ready_from_exact_durable_target_after_ephemeral_cleanup(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_control, binding, _ready = _install_authoritative_ready_bridge_control(
service,
transport_ref="F89438FA-55ED-85AD-EED7-734AC84746D8",
)
_seed_durable_bridge_topology(
service,
# CoreBluetooth UUID spelling is not durable identity. The monitor
# compares its physical key case-insensitively while retaining the
# exact supervisor spelling for current-process evidence.
transport_ref=binding.transport_ref.lower(),
ipv4=binding.target_ipv4,
)
service._retire_ephemeral_device_binding_for_new_intent() # noqa: SLF001
host_samples: list[str] = []
tcp_samples: list[str] = []
def sample_host(
target: str,
**_: object,
) -> HostPathProbeResult:
host_samples.append(target)
return _direct_host_path(target)
def sample_tcp(target: str) -> facade_module.TcpReachabilityProbeResult:
tcp_samples.append(target)
return facade_module.TcpReachabilityProbeResult(reachable=True)
monkeypatch.setattr(service, "_sample_host_path", sample_host)
monkeypatch.setattr(facade_module, "_probe_control_endpoint_socket", sample_tcp)
refreshed = asyncio.run(service._connection_monitor.poll_once()) # noqa: SLF001
assert service._selected_device_id is None # noqa: SLF001
assert service._device_session_id is None # noqa: SLF001
assert host_samples == [binding.target_ipv4, binding.target_ipv4]
assert tcp_samples == [binding.target_ipv4]
assert refreshed.host_path.available is True
assert refreshed.endpoint.tcp_state == "reachable"
assert refreshed.device_identity.state == "verified"
assert refreshed.control_plane.state == "healthy"
assert refreshed.lease.state == "reachable"
assert refreshed.authority.control_allowed is True
assert refreshed.authority.acquisition_start_allowed is True
def test_read_only_monitor_durable_target_still_downgrades_on_real_route_loss(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_control, binding, _ready = _install_authoritative_ready_bridge_control(service)
_seed_durable_bridge_topology(
service,
transport_ref=binding.transport_ref,
ipv4=binding.target_ipv4,
)
service._retire_ephemeral_device_binding_for_new_intent() # noqa: SLF001
tcp_samples: list[str] = []
monkeypatch.setattr(
service,
"_sample_host_path",
lambda _target, **_kwargs: HostPathProbeResult(
available=False,
fingerprint=None,
interface=None,
source_ipv4=None,
route_class="unavailable",
reason_code="router-link-lost",
),
)
monkeypatch.setattr(
facade_module,
"_probe_control_endpoint_socket",
lambda target: (
tcp_samples.append(target) or facade_module.TcpReachabilityProbeResult(reachable=True)
),
)
lost = asyncio.run(service._connection_monitor.poll_once()) # noqa: SLF001
assert tcp_samples == []
assert lost.host_path.available is False
assert lost.host_path.reason_code == "router-link-lost"
assert lost.endpoint.tcp_state == "unknown"
assert lost.lease.state == "configured-unverified"
assert lost.authority.control_allowed is False
assert lost.authority.acquisition_start_allowed is False
@pytest.mark.parametrize(
"invalid_context",
[
"selected-without-session",
"session-without-selected",
"semantic-empty",
"semantic-store-missing",
"semantic-store-corrupt",
"semantic-ref-mismatch",
"semantic-mode-mismatch",
"semantic-ip-mismatch",
"semantic-profile-mismatch",
"physically-retired",
],
)
def test_read_only_monitor_durable_fallback_rejects_inexact_or_unsafe_context(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
invalid_context: str,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_control, binding, _ready = _install_authoritative_ready_bridge_control(service)
store = service._semantic_topology_store # noqa: SLF001
assert store is not None
contexts_with_exact_semantic = {
"selected-without-session",
"session-without-selected",
"semantic-store-missing",
"semantic-store-corrupt",
"physically-retired",
}
if invalid_context in contexts_with_exact_semantic:
_seed_durable_bridge_topology(
service,
transport_ref=binding.transport_ref,
ipv4=binding.target_ipv4,
)
elif invalid_context.startswith("semantic-") and invalid_context != "semantic-empty":
snapshot = store.snapshot()
store.commit(
transport_ref=(
"different-k1"
if invalid_context == "semantic-ref-mismatch"
else binding.transport_ref
),
connection_mode=(
"direct-connect" if invalid_context == "semantic-mode-mismatch" else "bridge"
),
ipv4=(
"192.168.68.77"
if invalid_context == "semantic-ip-mismatch"
else binding.target_ipv4
),
compatibility_profile_id=(
"different.compatibility.profile"
if invalid_context == "semantic-profile-mismatch"
else XGRIDS_K1_COMPATIBILITY_PROFILE_ID
),
firmware_version="3.0.2",
source="ble-read-only-status",
observed_at_utc="2026-08-11T08:00:00Z",
predecessor_revision=(snapshot.record.revision if snapshot.record is not None else 0),
)
service._retire_ephemeral_device_binding_for_new_intent() # noqa: SLF001
if invalid_context == "selected-without-session":
with service._lock: # noqa: SLF001
service._selected_device_id = binding.transport_ref # noqa: SLF001
elif invalid_context == "session-without-selected":
with service._lock: # noqa: SLF001
service._device_session_id = "orphaned-session" # noqa: SLF001
elif invalid_context == "semantic-store-missing":
service._semantic_topology_store = None # noqa: SLF001
elif invalid_context == "semantic-store-corrupt":
def corrupt_snapshot() -> object:
raise facade_module.SemanticTopologyStoreCorrupt("synthetic corrupt store")
monkeypatch.setattr(store, "snapshot", corrupt_snapshot)
elif invalid_context == "physically-retired":
monkeypatch.setattr(
service,
"_retired_physical_transport_refs",
lambda: {binding.transport_ref.casefold()},
)
host_samples: list[str] = []
tcp_samples: list[str] = []
monkeypatch.setattr(
service,
"_sample_host_path",
lambda target, **_kwargs: host_samples.append(target) or _direct_host_path(target),
)
monkeypatch.setattr(
facade_module,
"_probe_control_endpoint_socket",
lambda target: (
tcp_samples.append(target) or facade_module.TcpReachabilityProbeResult(reachable=True)
),
)
assert service._connection_monitor_target() is None # noqa: SLF001
rejected = asyncio.run(service._connection_monitor.poll_once()) # noqa: SLF001
assert host_samples == []
assert tcp_samples == []
assert rejected.host_path.available is False
assert rejected.host_path.reason_code == "endpoint-target-unconfigured"
assert rejected.endpoint.tcp_state == "unknown"
assert rejected.lease.state == "configured-unverified"
assert rejected.authority.control_allowed is False
assert rejected.authority.acquisition_start_allowed is False
@pytest.mark.parametrize(
"durable_store_change",
["missing", "corrupt", "replaced"],
)
def test_monitor_revalidates_durable_sourced_supervisor_even_with_ephemeral_binding(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
durable_store_change: str,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_control, binding, _ready = _install_authoritative_ready_bridge_control(service)
_seed_durable_bridge_topology(
service,
transport_ref=binding.transport_ref,
ipv4=binding.target_ipv4,
)
supervisor = service._connection_supervisor # noqa: SLF001
current = supervisor.snapshot()
assert current.intent is not None
assert current.device_network.target is not None
assert supervisor.observe_device_network_applied(
intent_id=current.intent.intent_id,
transport_ref=binding.transport_ref,
connection_mode="bridge",
target=current.device_network.target,
source="durable-semantic-topology",
)
assert service._connection_monitor_target() == current.device_network.target # noqa: SLF001
store = service._semantic_topology_store # noqa: SLF001
assert store is not None
if durable_store_change == "missing":
service._semantic_topology_store = None # noqa: SLF001
elif durable_store_change == "corrupt":
def corrupt_snapshot() -> object:
raise facade_module.SemanticTopologyStoreCorrupt("synthetic corrupt store")
monkeypatch.setattr(store, "snapshot", corrupt_snapshot)
else:
semantic = store.snapshot()
assert semantic.record is not None
store.commit(
transport_ref=binding.transport_ref,
connection_mode="bridge",
ipv4="192.168.68.77",
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
firmware_version="3.0.2",
source="ble-read-only-status",
observed_at_utc="2026-08-11T08:30:00Z",
predecessor_revision=semantic.record.revision,
)
host_samples: list[str] = []
monkeypatch.setattr(
service,
"_sample_host_path",
lambda target, **_kwargs: host_samples.append(target) or _direct_host_path(target),
)
assert service._connection_monitor_target() is None # noqa: SLF001
rejected = asyncio.run(service._connection_monitor.poll_once()) # noqa: SLF001
assert host_samples == []
assert rejected.host_path.available is False
assert rejected.host_path.reason_code == "endpoint-target-unconfigured"
assert rejected.authority.control_allowed is False
def test_monitor_network_admission_race_is_dropped_without_negative_evidence(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_control, _binding, _ready = _install_authoritative_ready_bridge_control(service)
initial = service._connection_supervisor.snapshot() # noqa: SLF001
original_acquire = service._acquire_k1_lifecycle_process_lease # noqa: SLF001
network_injected = False
host_io: list[str] = []
def raced_acquire(holder: Any) -> None:
nonlocal network_injected
if holder == "monitor" and not network_injected:
original_acquire("network")
network_injected = True
original_acquire(holder)
monkeypatch.setattr(service, "_acquire_k1_lifecycle_process_lease", raced_acquire)
monkeypatch.setattr(
service,
"_sample_host_path",
lambda *_args, **_kwargs: host_io.append("host") or _direct_host_path("10.0.0.1"),
)
try:
after_race = asyncio.run(service._connection_monitor.poll_once()) # noqa: SLF001
finally:
if network_injected:
service._release_k1_lifecycle_process_lease("network") # noqa: SLF001
assert network_injected is True
assert host_io == []
assert after_race.revision == initial.revision
assert after_race.host_path == initial.host_path
assert after_race.endpoint == initial.endpoint
assert service._application_control_process_lease_holders == {"control"} # noqa: SLF001
def test_explicit_reconfiguration_waits_for_monitor_and_drops_stale_probe(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control, binding, ready = _install_authoritative_ready_bridge_control(service)
request = _reconfiguration_request(ready, "select-device")
initial_supervisor = service._connection_supervisor.snapshot() # noqa: SLF001
probe_entered = threading.Event()
release_probe = threading.Event()
device_edges: list[str] = []
def blocked_host_path(
target: str,
*,
association_timeout_seconds: float = 30.0,
fail_closed_unproven_association: bool = False,
) -> HostPathProbeResult:
assert association_timeout_seconds == (
facade_module.CONNECTION_MONITOR_ASSOCIATION_TIMEOUT_SECONDS
)
assert fail_closed_unproven_association is True
probe_entered.set()
assert release_probe.wait(timeout=5.0)
assert target == binding.target_ipv4
# If this superseded result were admitted after the operator won the
# transition, it would rotate the host epoch and revoke the old proof.
return _direct_host_path("192.168.56.20")
async def forbidden_device_io(*_args: object, **_kwargs: object) -> object:
device_edges.append("ble-or-network")
raise AssertionError("local reconfiguration must not perform device I/O")
monkeypatch.setattr(service, "_sample_host_path", blocked_host_path)
monkeypatch.setattr(facade_module, "read_wifi_status_once", forbidden_device_io)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_device_io)
monkeypatch.setattr(
service._physical_command_coordinator, # noqa: SLF001
"prepare",
lambda *_args, **_kwargs: device_edges.append("physical-command"),
)
async def scenario() -> tuple[dict[str, Any], dict[str, Any]]:
monitor_task = asyncio.create_task(
service._connection_monitor.poll_once() # noqa: SLF001
)
assert await asyncio.to_thread(probe_entered.wait, 5.0)
during_probe = await asyncio.to_thread(service.state)
assert "monitor" in during_probe["k1_lifecycle_process_lease"]["holders"]
for action in ("prepare-select-device", "prepare-change-network"):
assert during_probe["connection_policy"]["actions"][action]["allowed"] is True
prepare_task = asyncio.create_task(service.prepare_connection_reconfiguration(request))
for _ in range(100):
if service._k1_lifecycle_transition_gate.locked(): # noqa: SLF001
break
await asyncio.sleep(0.001)
assert service._k1_lifecycle_transition_gate.locked() # noqa: SLF001
await asyncio.sleep(0.01)
assert prepare_task.done() is False
release_probe.set()
monitor_state = await monitor_task
prepared = await prepare_task
return monitor_state, prepared
monitor_state, prepared = asyncio.run(scenario())
assert monitor_state.host_path.epoch == initial_supervisor.host_path.epoch
assert prepared["connection_reconfiguration"]["intent"] == "select-device"
assert prepared["connection_reconfiguration"]["status"] == "awaiting-fresh-scan"
assert prepared["connection_supervisor"]["observed"]["host_path"]["epoch"] == (
initial_supervisor.host_path.epoch
)
assert "monitor" not in service._application_control_process_lease_holders # noqa: SLF001
assert control.stop_calls == 0
assert control.start_projects == []
assert runtime.start_calls == []
assert runtime.stop_calls == 0
assert device_edges == []
assert binding.target_ipv4 == "192.168.1.20"
def test_cancelled_monitor_keeps_contact_owned_until_operator_can_commit(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control, binding, ready = _install_authoritative_ready_bridge_control(service)
request = _reconfiguration_request(ready, "select-device")
initial = service._connection_supervisor.snapshot() # noqa: SLF001
probe_entered = threading.Event()
release_probe = threading.Event()
device_edges: list[str] = []
def blocked_host_path(
target: str,
*,
association_timeout_seconds: float = 30.0,
fail_closed_unproven_association: bool = False,
) -> HostPathProbeResult:
assert association_timeout_seconds == (
facade_module.CONNECTION_MONITOR_ASSOCIATION_TIMEOUT_SECONDS
)
assert fail_closed_unproven_association is True
probe_entered.set()
assert release_probe.wait(timeout=5.0)
assert target == binding.target_ipv4
return _direct_host_path("192.168.56.20")
async def forbidden_device_io(*_args: object, **_kwargs: object) -> object:
device_edges.append("ble-or-network")
raise AssertionError("cancelled monitor handoff must not perform device I/O")
monkeypatch.setattr(service, "_sample_host_path", blocked_host_path)
monkeypatch.setattr(facade_module, "read_wifi_status_once", forbidden_device_io)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_device_io)
async def scenario() -> tuple[dict[str, Any], bool]:
monitor_task = asyncio.create_task(
service._connection_monitor.poll_once() # noqa: SLF001
)
assert await asyncio.to_thread(probe_entered.wait, 5.0)
monitor_task.cancel()
prepare_task = asyncio.create_task(service.prepare_connection_reconfiguration(request))
for _ in range(100):
if service._k1_lifecycle_transition_gate.locked(): # noqa: SLF001
break
await asyncio.sleep(0.001)
assert service._k1_lifecycle_transition_gate.locked() # noqa: SLF001
await asyncio.sleep(0.01)
assert prepare_task.done() is False
assert "network" not in service._application_control_process_lease_holders # noqa: SLF001
release_probe.set()
with pytest.raises(asyncio.CancelledError):
await monitor_task
prepared = await prepare_task
return prepared, service._connection_monitor_contact_gate.locked() # noqa: SLF001
prepared, contact_locked = asyncio.run(scenario())
assert contact_locked is False
assert service._k1_lifecycle_transition_gate.locked() is False # noqa: SLF001
assert service._connection_reconfiguration_gate.locked() is False # noqa: SLF001
assert prepared["connection_reconfiguration"]["status"] == "awaiting-fresh-scan"
assert prepared["connection_supervisor"]["observed"]["host_path"]["epoch"] == (
initial.host_path.epoch
)
assert "monitor" not in service._application_control_process_lease_holders # noqa: SLF001
assert control.stop_calls == 0
assert control.start_projects == []
assert runtime.start_calls == []
assert device_edges == []
def test_monitor_quiescence_timeout_releases_operator_gates_and_drops_late_result(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control, binding, ready = _install_authoritative_ready_bridge_control(service)
request = _reconfiguration_request(ready, "select-device")
initial = service._connection_supervisor.snapshot() # noqa: SLF001
probe_entered = threading.Event()
release_probe = threading.Event()
device_edges: list[str] = []
def blocked_host_path(
target: str,
*,
association_timeout_seconds: float = 30.0,
fail_closed_unproven_association: bool = False,
) -> HostPathProbeResult:
assert association_timeout_seconds == (
facade_module.CONNECTION_MONITOR_ASSOCIATION_TIMEOUT_SECONDS
)
assert fail_closed_unproven_association is True
probe_entered.set()
assert release_probe.wait(timeout=5.0)
assert target == binding.target_ipv4
return _direct_host_path("192.168.56.20")
async def forbidden_device_io(*_args: object, **_kwargs: object) -> object:
device_edges.append("ble-or-network")
raise AssertionError("quiescence timeout must not perform device I/O")
monkeypatch.setattr(
facade_module,
"CONNECTION_MONITOR_QUIESCE_TIMEOUT_SECONDS",
0.01,
)
monkeypatch.setattr(service, "_sample_host_path", blocked_host_path)
monkeypatch.setattr(facade_module, "read_wifi_status_once", forbidden_device_io)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_device_io)
async def scenario() -> None:
monitor_task = asyncio.create_task(
service._connection_monitor.poll_once() # noqa: SLF001
)
assert await asyncio.to_thread(probe_entered.wait, 5.0)
with pytest.raises(facade_module.NetworkProvisioningConflict) as conflict:
await service.prepare_connection_reconfiguration(request)
assert conflict.value.reason_code == "connection-reconfiguration-lifecycle-busy"
assert service._k1_lifecycle_transition_gate.locked() is False # noqa: SLF001
assert service._connection_reconfiguration_gate.locked() is False # noqa: SLF001
assert "network" not in service._application_control_process_lease_holders # noqa: SLF001
monitor_task.cancel()
release_probe.set()
with pytest.raises(asyncio.CancelledError):
await monitor_task
asyncio.run(scenario())
after = service._connection_supervisor.snapshot() # noqa: SLF001
assert after.revision == initial.revision
assert after.host_path == initial.host_path
assert service._connection_monitor_contact_gate.locked() is False # noqa: SLF001
assert service._connection_reconfiguration_intent is None # noqa: SLF001
assert service._application_control_process_lease_holders == {"control"} # noqa: SLF001
assert control.stop_calls == 0
assert control.start_projects == []
assert runtime.start_calls == []
assert device_edges == []
def test_same_mode_scan_waits_for_monitor_instead_of_returning_busy(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _runtime = service_with_fake_runtime(tmp_path)
_control, binding, ready = _install_authoritative_ready_bridge_control(service)
initial_epoch = ready["connection_supervisor"]["observed"]["host_path"]["epoch"]
probe_entered = threading.Event()
release_probe = threading.Event()
scan_calls: list[float] = []
tcp_calls: list[str] = []
def blocked_host_path(
target: str,
*,
association_timeout_seconds: float = 30.0,
fail_closed_unproven_association: bool = False,
) -> HostPathProbeResult:
assert association_timeout_seconds == (
facade_module.CONNECTION_MONITOR_ASSOCIATION_TIMEOUT_SECONDS
)
assert fail_closed_unproven_association is True
probe_entered.set()
assert release_probe.wait(timeout=5.0)
assert target == binding.target_ipv4
return _direct_host_path("192.168.56.20")
async def fake_scan(
duration_seconds: float,
*,
on_admitted: Callable[[], None] | None = None,
) -> dict[str, Any]:
scan_calls.append(duration_seconds)
assert on_admitted is not None
on_admitted()
return _ble_scan_result("fresh-k1")
def forbidden_tcp(target: str) -> facade_module.TcpReachabilityProbeResult:
tcp_calls.append(target)
raise AssertionError("operator lifecycle gate must supersede the next monitor contact")
monkeypatch.setattr(service, "_sample_host_path", blocked_host_path)
monkeypatch.setattr(facade_module, "_probe_control_endpoint_socket", forbidden_tcp)
monkeypatch.setattr(facade_module, "scan", fake_scan)
async def scenario() -> tuple[dict[str, Any], int]:
monitor_task = asyncio.create_task(
service._connection_monitor.poll_once() # noqa: SLF001
)
assert await asyncio.to_thread(probe_entered.wait, 5.0)
scan_task = asyncio.create_task(service.scan_ble(0.1))
for _ in range(100):
if service._k1_lifecycle_transition_gate.locked(): # noqa: SLF001
break
await asyncio.sleep(0.001)
assert service._k1_lifecycle_transition_gate.locked() # noqa: SLF001
await asyncio.sleep(0.01)
assert scan_task.done() is False
assert scan_calls == []
assert "network" not in service._application_control_process_lease_holders # noqa: SLF001
release_probe.set()
monitor_state = await monitor_task
scanned = await scan_task
return scanned, monitor_state.host_path.epoch
scanned, monitor_epoch = asyncio.run(scenario())
assert scan_calls == [0.1]
assert [item["device_id"] for item in scanned["devices"]] == ["fresh-k1"]
assert monitor_epoch == initial_epoch
assert scanned["connection_supervisor"]["observed"]["host_path"]["epoch"] == (initial_epoch)
assert service._connection_monitor_contact_gate.locked() is False # noqa: SLF001
assert "monitor" not in service._application_control_process_lease_holders # noqa: SLF001
assert tcp_calls == []
def test_select_device_handoff_is_local_cancel_invalidates_candidates_and_stale_tabs(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control, _binding, ready = _install_authoritative_ready_bridge_control(service)
initial_request = _reconfiguration_request(ready, "select-device")
semantic_before = ready["semantic_topology_store"]
identity_before = ready["device_identity_pin_store"]
device_edges: list[str] = []
async def forbidden_network_write(*_: object, **__: object) -> dict[str, Any]:
device_edges.append("network-write")
raise AssertionError("local reconfiguration handoff must not write K1")
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_network_write)
monkeypatch.setattr(
service._physical_command_coordinator, # noqa: SLF001
"prepare",
lambda *_args, **_kwargs: device_edges.append("physical-command"),
)
prepared = asyncio.run(service.prepare_connection_reconfiguration(initial_request))
assert prepared["connection_reconfiguration"]["intent"] == "select-device"
assert prepared["connection_reconfiguration"]["status"] == "awaiting-fresh-scan"
assert prepared["connection_reconfiguration"]["required_connection_mode"] == "bridge"
assert prepared["connection_lifecycle"]["active_binding"] is None
assert prepared["selected_device_id"] is None
assert (
prepared["connection_policy"]["actions"]["prepare-select-device"][
"required_connection_mode"
]
== "bridge"
)
assert prepared["semantic_topology_store"] == semantic_before
assert prepared["device_identity_pin_store"] == identity_before
assert control.state == "idle"
assert control.start_projects == []
assert control.stop_calls == 0
assert runtime.start_calls == []
assert runtime.stop_calls == 0
assert service._application_control_process_lease_holders == set() # noqa: SLF001
assert device_edges == []
# The losing tab cannot repeat the original handoff after the stable
# operator-only revision/intent id advanced.
with pytest.raises(facade_module.NetworkProvisioningConflict) as stale_prepare:
asyncio.run(service.prepare_connection_reconfiguration(initial_request))
assert stale_prepare.value.reason_code == "connection-reconfiguration-revision-conflict"
minimum_generation = prepared["connection_reconfiguration"]["minimum_discovery_generation"]
service._ble_discovery_generation = minimum_generation # noqa: SLF001
_set_scanned_k1(service, device_id="k1-b")
fresh = service.state()
assert fresh["connection_reconfiguration"]["status"] == "fresh-scan-completed"
assert [item["device_id"] for item in fresh["devices"]] == ["k1-b"]
stale_connect_request = _connect_request(
device_id="k1-b",
ssid="lab-router",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
connection_mode="bridge",
compatibility_attestation=ATTESTATION,
expected_mode_revision=fresh["desired_connection_mode_revision"],
expected_discovery_generation=fresh["ble_discovery_generation"],
expected_reconfiguration_revision=fresh["connection_reconfiguration"]["revision"],
expected_reconfiguration_intent_id=fresh["connection_reconfiguration"]["intent_id"],
)
stale_verify_request = ConnectionVerifyRequest(
device_id="k1-b",
source="fresh-scan",
compatibility_attestation=ATTESTATION,
expected_discovery_generation=fresh["ble_discovery_generation"],
expected_reconfiguration_revision=fresh["connection_reconfiguration"]["revision"],
expected_reconfiguration_intent_id=fresh["connection_reconfiguration"]["intent_id"],
)
quick_verify_request = ConnectionVerifyRequest(
device_id="k1-b",
source="fresh-scan",
compatibility_attestation=QUICK_CONNECT_ATTESTATION,
expected_discovery_generation=fresh["ble_discovery_generation"],
expected_reconfiguration_revision=fresh["connection_reconfiguration"]["revision"],
expected_reconfiguration_intent_id=fresh["connection_reconfiguration"]["intent_id"],
)
with pytest.raises(facade_module.NetworkProvisioningConflict) as quick_isolated:
asyncio.run(service.verify_connection(quick_verify_request))
assert quick_isolated.value.reason_code == "connection-reconfiguration-target-mismatch"
cancel_request = _reconfiguration_request(fresh, "cancel")
cancelled = asyncio.run(service.prepare_connection_reconfiguration(cancel_request))
assert cancelled["connection_reconfiguration"]["status"] == "idle"
assert cancelled["connection_reconfiguration"]["intent_id"] is None
assert cancelled["devices"] == []
assert cancelled["ble_discovery_generation"] > minimum_generation
assert cancelled["semantic_topology_store"] == semantic_before
assert cancelled["device_identity_pin_store"] == identity_before
assert device_edges == []
password_reads: list[str] = []
process_lease_calls: list[str] = []
def forbidden_password_read(_secret: SecretStr) -> str:
password_reads.append("unwrapped")
raise AssertionError("stale Connect must fail before password unwrap")
def forbidden_process_lease(holder: str) -> None:
process_lease_calls.append(holder)
raise AssertionError("stale mutation must fail before process lease")
monkeypatch.setattr(SecretStr, "get_secret_value", forbidden_password_read)
monkeypatch.setattr(
service,
"_acquire_k1_lifecycle_process_lease",
forbidden_process_lease,
)
with pytest.raises(facade_module.NetworkProvisioningConflict) as stale_connect:
asyncio.run(service.connect(stale_connect_request))
assert stale_connect.value.reason_code == "connection-reconfiguration-revision-conflict"
with pytest.raises(facade_module.NetworkProvisioningConflict) as stale_verify:
asyncio.run(service.verify_connection(stale_verify_request))
assert stale_verify.value.reason_code == "connection-reconfiguration-revision-conflict"
assert password_reads == []
assert process_lease_calls == []
assert service._operations.snapshot() == [] # noqa: SLF001
with pytest.raises(facade_module.NetworkProvisioningConflict) as stale_cancel:
asyncio.run(service.prepare_connection_reconfiguration(cancel_request))
assert stale_cancel.value.reason_code == "connection-reconfiguration-revision-conflict"
def test_change_network_requires_authoritative_binding_before_any_local_teardown(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
control, _binding, ready = _install_authoritative_ready_bridge_control(service)
supervisor = service._connection_supervisor # noqa: SLF001
supervisor_state = supervisor.snapshot()
assert supervisor_state.intent is not None
assert supervisor_state.device_network.target is not None
assert supervisor.observe_endpoint(
target=supervisor_state.device_network.target,
intent_id=supervisor_state.intent.intent_id,
host_path_epoch=supervisor_state.host_path.epoch,
reachable=False,
reason_code="tcp-endpoint-unreachable",
)
degraded = service.state()
assert degraded["selected_device_id"] == "k1-a"
assert degraded["connection_lifecycle"]["active_binding"] is None
assert control.state == "connection-ready"
decision = degraded["connection_policy"]["actions"]["prepare-change-network"]
assert decision["allowed"] is False
assert "connection-reconfiguration-current-device-unavailable" in decision["reason_codes"]
process_lease_calls: list[str] = []
original_acquire = service._acquire_k1_lifecycle_process_lease # noqa: SLF001
def counted_acquire(holder: str) -> None:
process_lease_calls.append(holder)
original_acquire(holder)
monkeypatch.setattr(service, "_acquire_k1_lifecycle_process_lease", counted_acquire)
before_control_revision = control.state_revision
with pytest.raises(facade_module.NetworkProvisioningConflict) as unavailable:
asyncio.run(
service.prepare_connection_reconfiguration(
_reconfiguration_request(degraded, "change-network")
)
)
assert unavailable.value.reason_code == (
"connection-reconfiguration-current-device-unavailable"
)
assert process_lease_calls == []
assert control.state == "connection-ready"
assert control.state_revision == before_control_revision
assert service._selected_device_id == "k1-a" # noqa: SLF001
assert service._connection_reconfiguration_intent is None # noqa: SLF001
assert service._application_control_process_lease_holders == {"control"} # noqa: SLF001
def test_bridge_reconfiguration_policy_rejects_quick_and_unresolved_physical_state(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
quick_service, _ = service_with_fake_runtime(tmp_path / "quick")
_select_connection_mode(quick_service, "quick-connect")
quick_binding = _seed_supervised_connection(
quick_service,
target_ipv4=facade_module.AP_FALLBACK_IPV4,
connection_mode="quick-connect",
transport_ref="k1-quick",
logical_device_id="device-quick",
)
quick_control = FakeInteractiveControlSession(initial_state="idle")
quick_control.open(connection_binding=quick_binding)
quick_control.verified_control = _verified_control_for_binding(
quick_binding,
logical_device_id="device-quick",
control_session_id="test-control-k1-quick",
control_proof_revision=2,
)
quick_service._application_control_session = quick_control # type: ignore[assignment] # noqa: SLF001
quick_service._reconcile_connection_supervisor( # noqa: SLF001
quick_control.snapshot(),
quick_service.runtime.snapshot(),
)
quick_service._acquire_application_control_process_lease() # noqa: SLF001
quick_state = quick_service.state()
quick_decision = quick_state["connection_policy"]["actions"]["prepare-select-device"]
assert quick_decision["allowed"] is False
assert "connection-reconfiguration-bridge-only" in quick_decision["reason_codes"]
with pytest.raises(facade_module.NetworkProvisioningConflict) as quick_rejected:
asyncio.run(
quick_service.prepare_connection_reconfiguration(
_reconfiguration_request(quick_state, "select-device")
)
)
assert quick_rejected.value.reason_code == "connection-reconfiguration-bridge-only"
assert quick_control.state == "connection-ready"
bridge_service, _ = service_with_fake_runtime(tmp_path / "physical")
bridge_control, _binding, _ready = _install_authoritative_ready_bridge_control(bridge_service)
monkeypatch.setattr(
bridge_service._physical_command_coordinator, # noqa: SLF001
"snapshot",
lambda: {
"status": "unresolved",
"requires_reconciliation": True,
"record": None,
},
)
unsafe = bridge_service.state()
unsafe_decision = unsafe["connection_policy"]["actions"]["prepare-select-device"]
assert unsafe_decision["allowed"] is False
assert "physical-command-reconciliation-required" in unsafe_decision["reason_codes"]
with pytest.raises(facade_module.NetworkProvisioningConflict) as physical_rejected:
asyncio.run(
bridge_service.prepare_connection_reconfiguration(
_reconfiguration_request(unsafe, "select-device")
)
)
assert physical_rejected.value.reason_code == ("physical-command-reconciliation-required")
assert bridge_control.state == "connection-ready"
assert bridge_service._connection_reconfiguration_intent is None # noqa: SLF001
def test_change_network_handoff_pins_exact_active_bridge_transport_without_write(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control, _binding, ready = _install_authoritative_ready_bridge_control(service)
decision = ready["connection_policy"]["actions"]["prepare-change-network"]
assert decision["allowed"] is True
assert decision["required_transport_ref"] == "k1-a"
assert decision["required_connection_mode"] == "bridge"
device_edges: list[str] = []
async def forbidden_write(*_: object, **__: object) -> dict[str, Any]:
device_edges.append("network-write")
raise AssertionError("Prepare must remain local-only")
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_write)
monkeypatch.setattr(
service._physical_command_coordinator, # noqa: SLF001
"prepare",
lambda *_args, **_kwargs: device_edges.append("physical-command"),
)
prepared = asyncio.run(
service.prepare_connection_reconfiguration(
_reconfiguration_request(ready, "change-network")
)
)
reconfiguration = prepared["connection_reconfiguration"]
assert reconfiguration["intent"] == "change-network"
assert reconfiguration["required_transport_ref"] == "k1-a"
assert reconfiguration["required_connection_mode"] == "bridge"
minimum_generation = reconfiguration["minimum_discovery_generation"]
service._ble_discovery_generation = minimum_generation # noqa: SLF001
_set_scanned_k1(service, device_id="k1-a")
observed = service.state()
assert observed["connection_reconfiguration"]["required_transport_observed"] is True
provision = observed["connection_policy"]["actions"]["provision-fresh-device"]
assert provision["required_transport_ref"] == "k1-a"
assert provision["required_connection_mode"] == "bridge"
wrong_target_request = _connect_request(
device_id="k1-b",
ssid="lab-router",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
connection_mode="bridge",
compatibility_attestation=ATTESTATION,
expected_mode_revision=observed["desired_connection_mode_revision"],
expected_discovery_generation=observed["ble_discovery_generation"],
expected_reconfiguration_revision=observed["connection_reconfiguration"]["revision"],
expected_reconfiguration_intent_id=observed["connection_reconfiguration"]["intent_id"],
)
password_reads: list[str] = []
def forbidden_password_read(_secret: SecretStr) -> str:
password_reads.append("unwrapped")
raise AssertionError("wrong pinned target must fail before password unwrap")
monkeypatch.setattr(SecretStr, "get_secret_value", forbidden_password_read)
with pytest.raises(facade_module.NetworkProvisioningConflict) as wrong_target:
asyncio.run(service.connect(wrong_target_request))
assert wrong_target.value.reason_code == "connection-reconfiguration-target-mismatch"
assert password_reads == []
assert service._operations.snapshot() == [] # noqa: SLF001
assert control.stop_calls == 0
assert runtime.start_calls == []
assert runtime.stop_calls == 0
assert device_edges == []
def test_select_device_fresh_verify_consumes_exact_reconfiguration_without_write(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_seed_durable_bridge_topology(
service,
transport_ref="k1-a",
ipv4="10.255.254.20",
)
service._pin_or_match_device_identity( # noqa: SLF001
transport_ref="k1-a",
logical_device_id="device-a",
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
)
service._pin_or_match_device_identity( # noqa: SLF001
transport_ref="k1-new",
logical_device_id="device-b",
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
)
semantic_before = service._semantic_topology_store.snapshot() # type: ignore[union-attr] # noqa: SLF001
assert semantic_before.record is not None
assert semantic_before.record.transport_ref == "k1-a"
initial = service.state()
assert initial["connection_policy"]["actions"]["prepare-select-device"]["allowed"] is True
prepared = asyncio.run(
service.prepare_connection_reconfiguration(
_reconfiguration_request(initial, "select-device")
)
)
minimum_generation = prepared["connection_reconfiguration"]["minimum_discovery_generation"]
service._ble_discovery_generation = minimum_generation # noqa: SLF001
_set_scanned_k1(service, device_id="k1-new")
fresh = service.state()
writes: list[str] = []
_install_successful_bridge_verify_transport(
monkeypatch,
device_id="k1-new",
ipv4="10.255.254.77",
writes=writes,
)
original_bootstrap = service._bootstrap_prestart_control_ready_owned # noqa: SLF001
semantic_during_bootstrap: list[str] = []
async def assert_semantic_commit_is_deferred(**kwargs: object) -> None:
before_device_info = service._semantic_topology_store.snapshot() # type: ignore[union-attr] # noqa: SLF001
assert before_device_info.record is not None
semantic_during_bootstrap.append(before_device_info.record.transport_ref)
await original_bootstrap(**kwargs) # type: ignore[arg-type]
after_device_info = service._semantic_topology_store.snapshot() # type: ignore[union-attr] # noqa: SLF001
assert after_device_info.record is not None
semantic_during_bootstrap.append(after_device_info.record.transport_ref)
monkeypatch.setattr(
service,
"_bootstrap_prestart_control_ready_owned",
assert_semantic_commit_is_deferred,
)
verified = asyncio.run(
service.verify_connection(
ConnectionVerifyRequest(
device_id="k1-new",
source="fresh-scan",
compatibility_attestation=ATTESTATION,
expected_discovery_generation=fresh["ble_discovery_generation"],
expected_reconfiguration_revision=fresh["connection_reconfiguration"]["revision"],
expected_reconfiguration_intent_id=fresh["connection_reconfiguration"]["intent_id"],
)
)
)
assert writes == []
assert verified["selected_device_id"] == "k1-new"
assert verified["active_connection_mode"] == "bridge"
assert verified["connection_reconfiguration"]["status"] == "idle"
assert verified["connection_reconfiguration"]["intent_id"] is None
assert semantic_during_bootstrap == ["k1-a", "k1-a"]
semantic_after = service._semantic_topology_store.snapshot() # type: ignore[union-attr] # noqa: SLF001
assert semantic_after.record is not None
assert semantic_after.record.transport_ref == "k1-new"
assert semantic_after.record.revision == semantic_before.record.revision + 1
def test_select_device_identity_mismatch_preserves_a_and_cancel_restart_recovers_a(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_seed_durable_bridge_topology(
service,
transport_ref="k1-a",
ipv4="10.255.254.20",
)
service._pin_or_match_device_identity( # noqa: SLF001
transport_ref="k1-a",
logical_device_id="device-a",
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
)
service._pin_or_match_device_identity( # noqa: SLF001
transport_ref="k1-b",
logical_device_id="device-b",
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
)
topology_store = service._semantic_topology_store # noqa: SLF001
pin_store = service._device_identity_pin_store # noqa: SLF001
assert topology_store is not None
assert pin_store is not None
semantic_before = topology_store.snapshot()
pins_before = pin_store.snapshot()
prepared = asyncio.run(
service.prepare_connection_reconfiguration(
_reconfiguration_request(service.state(), "select-device")
)
)
service._ble_discovery_generation = prepared["connection_reconfiguration"][ # noqa: SLF001
"minimum_discovery_generation"
]
_set_scanned_k1(service, device_id="k1-b")
fresh = service.state()
writes: list[str] = []
_install_successful_bridge_verify_transport(
monkeypatch,
device_id="k1-b",
ipv4="10.255.254.77",
writes=writes,
)
# Force the synthetic DeviceInfo proof to present a different logical ID
# than B's immutable transport pin. The production reducer then rejects it.
monkeypatch.setattr(service, "_expected_vendor_device_id", lambda _ref: None)
with pytest.raises(facade_module.ConnectionVerificationError) as mismatch:
asyncio.run(
service.verify_connection(
ConnectionVerifyRequest(
device_id="k1-b",
source="fresh-scan",
compatibility_attestation=ATTESTATION,
expected_discovery_generation=fresh["ble_discovery_generation"],
expected_reconfiguration_revision=fresh["connection_reconfiguration"][
"revision"
],
expected_reconfiguration_intent_id=fresh["connection_reconfiguration"][
"intent_id"
],
)
)
)
assert mismatch.value.reason_code == "control-bootstrap-device-identity-unverified"
assert writes == []
assert topology_store.snapshot() == semantic_before
assert pin_store.snapshot() == pins_before
failed = service.state()
assert failed["connection_reconfiguration"]["intent"] == "select-device"
assert failed["selected_device_id"] is None
assert failed["device_session"] is None
assert failed["connection_lifecycle"]["active_binding"] is None
assert failed["application_control_session"]["state"] == "idle"
assert [item["device_id"] for item in failed["devices"]] == ["k1-b"]
supervisor = service._connection_supervisor.snapshot() # noqa: SLF001
assert supervisor.authority.control_allowed is False
assert not (
supervisor.intent is not None
and supervisor.device_network.intent_id == supervisor.intent.intent_id
and supervisor.device_network.transport_ref == "k1-b"
)
cancelled = asyncio.run(
service.prepare_connection_reconfiguration(_reconfiguration_request(failed, "cancel"))
)
assert cancelled["connection_reconfiguration"]["status"] == "idle"
assert topology_store.snapshot() == semantic_before
assert pin_store.snapshot() == pins_before
restarted, _ = service_with_fake_runtime(tmp_path)
restarted_state = restarted.state()
restarted_record = restarted._semantic_topology_store.snapshot().record # type: ignore[union-attr] # noqa: SLF001
assert restarted_record is not None
assert restarted_record.transport_ref == "k1-a"
assert restarted_state["selected_device_id"] is None
assert restarted._configured_endpoint_target().transport_ref == "k1-a" # noqa: SLF001
def test_cold_fresh_bridge_identity_mismatch_keeps_semantic_empty_after_restart(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
service._pin_or_match_device_identity( # noqa: SLF001
transport_ref="k1-b",
logical_device_id="device-b",
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
)
topology_store = service._semantic_topology_store # noqa: SLF001
pin_store = service._device_identity_pin_store # noqa: SLF001
assert topology_store is not None
assert pin_store is not None
assert topology_store.snapshot().status == "empty"
pins_before = pin_store.snapshot()
_set_scanned_k1(service, device_id="k1-b")
fresh = service.state()
writes: list[str] = []
_install_successful_bridge_verify_transport(
monkeypatch,
device_id="k1-b",
ipv4="10.255.254.77",
writes=writes,
)
monkeypatch.setattr(service, "_expected_vendor_device_id", lambda _ref: None)
with pytest.raises(facade_module.ConnectionVerificationError) as mismatch:
asyncio.run(
service.verify_connection(
ConnectionVerifyRequest(
device_id="k1-b",
source="fresh-scan",
compatibility_attestation=ATTESTATION,
expected_discovery_generation=fresh["ble_discovery_generation"],
)
)
)
assert mismatch.value.reason_code == "control-bootstrap-device-identity-unverified"
assert writes == []
assert topology_store.snapshot().status == "empty"
assert pin_store.snapshot() == pins_before
failed = service.state()
assert failed["connection_reconfiguration"]["status"] == "idle"
assert failed["selected_device_id"] is None
assert failed["device_session"] is None
assert failed["connection_lifecycle"]["active_binding"] is None
assert failed["application_control_session"]["state"] == "idle"
assert [item["device_id"] for item in failed["devices"]] == ["k1-b"]
restarted, _ = service_with_fake_runtime(tmp_path)
restarted_state = restarted.state()
assert restarted_state["semantic_topology_store"]["status"] == "empty"
assert restarted_state["selected_device_id"] is None
def test_cold_fresh_bridge_commits_semantic_only_after_device_info_pin(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
topology_store = service._semantic_topology_store # noqa: SLF001
assert topology_store is not None
assert topology_store.snapshot().status == "empty"
_set_scanned_k1(service, device_id="k1-cold")
fresh = service.state()
writes: list[str] = []
_install_successful_bridge_verify_transport(
monkeypatch,
device_id="k1-cold",
ipv4="10.255.254.88",
writes=writes,
)
original_bootstrap = service._bootstrap_prestart_control_ready_owned # noqa: SLF001
semantic_status_during_bootstrap: list[str] = []
async def assert_cold_commit_is_deferred(**kwargs: object) -> None:
semantic_status_during_bootstrap.append(topology_store.snapshot().status)
await original_bootstrap(**kwargs) # type: ignore[arg-type]
semantic_status_during_bootstrap.append(topology_store.snapshot().status)
monkeypatch.setattr(
service,
"_bootstrap_prestart_control_ready_owned",
assert_cold_commit_is_deferred,
)
verified = asyncio.run(
service.verify_connection(
ConnectionVerifyRequest(
device_id="k1-cold",
source="fresh-scan",
compatibility_attestation=ATTESTATION,
expected_discovery_generation=fresh["ble_discovery_generation"],
)
)
)
assert writes == []
assert semantic_status_during_bootstrap == ["empty", "empty"]
record = topology_store.snapshot().record
assert record is not None
assert record.transport_ref == "k1-cold"
assert record.ipv4 == "10.255.254.88"
assert record.revision == 1
assert verified["selected_device_id"] == "k1-cold"
assert verified["connection_reconfiguration"]["status"] == "idle"
assert verified["device_identity_pin_store"]["pin_count"] == 1
def test_select_device_cancel_during_device_info_discards_only_provisional_b(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_seed_durable_bridge_topology(
service,
transport_ref="k1-a",
ipv4="10.255.254.20",
)
topology_store = service._semantic_topology_store # noqa: SLF001
assert topology_store is not None
semantic_before = topology_store.snapshot()
prepared = asyncio.run(
service.prepare_connection_reconfiguration(
_reconfiguration_request(service.state(), "select-device")
)
)
service._ble_discovery_generation = prepared["connection_reconfiguration"][ # noqa: SLF001
"minimum_discovery_generation"
]
_set_scanned_k1(service, device_id="k1-b")
fresh = service.state()
writes: list[str] = []
_install_successful_bridge_verify_transport(
monkeypatch,
device_id="k1-b",
ipv4="10.255.254.77",
writes=writes,
)
async def scenario() -> None:
bootstrap_entered = asyncio.Event()
async def paused_device_info(**_: object) -> None:
bootstrap_entered.set()
await asyncio.Event().wait()
monkeypatch.setattr(
service,
"_bootstrap_prestart_control_ready_owned",
paused_device_info,
)
verify_task = asyncio.create_task(
service.verify_connection(
ConnectionVerifyRequest(
device_id="k1-b",
source="fresh-scan",
compatibility_attestation=ATTESTATION,
expected_discovery_generation=fresh["ble_discovery_generation"],
expected_reconfiguration_revision=fresh["connection_reconfiguration"][
"revision"
],
expected_reconfiguration_intent_id=fresh["connection_reconfiguration"][
"intent_id"
],
)
)
)
await asyncio.wait_for(bootstrap_entered.wait(), timeout=1.0)
projected = service.state()
assert projected["selected_device_id"] == "k1-b"
assert topology_store.snapshot() == semantic_before
verify_task.cancel()
with pytest.raises(asyncio.CancelledError):
await verify_task
asyncio.run(scenario())
assert writes == []
assert topology_store.snapshot() == semantic_before
cancelled = service.state()
assert cancelled["connection_reconfiguration"]["intent"] == "select-device"
assert cancelled["selected_device_id"] is None
assert cancelled["device_session"] is None
assert cancelled["connection_lifecycle"]["active_binding"] is None
assert [item["device_id"] for item in cancelled["devices"]] == ["k1-b"]
assert cancelled["last_operation"]["status"] == "cancelled"
def test_reconfiguration_aborts_only_purely_local_prepare_without_start_or_stop(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
control, _binding, _ready = _install_authoritative_ready_bridge_control(service)
control.state = "workspace-ready"
control.state_revision = 1
service._reconcile_connection_supervisor( # noqa: SLF001
control.snapshot(),
service.runtime.snapshot(),
)
prepared_acquisition = service.prepare_acquisition(
_prepare_request(
project_name="TEST001",
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
assert prepared_acquisition["acquisition"]["state"] == "prepared"
assert control.state == "project-ready"
device_edges: list[str] = []
monkeypatch.setattr(
service._physical_command_coordinator, # noqa: SLF001
"prepare",
lambda *_args, **_kwargs: device_edges.append("physical-command"),
)
handed_off = asyncio.run(
service.prepare_connection_reconfiguration(
_reconfiguration_request(prepared_acquisition, "select-device")
)
)
assert handed_off["acquisition"]["state"] == "aborted"
assert handed_off["acquisition"]["result"] == {
"receiver_started": False,
"device_command_attempted": False,
"reason_code": "superseded-by-connection-reconfiguration",
}
assert control.start_projects == []
assert control.stop_calls == 0
assert runtime.start_calls == []
assert runtime.stop_calls == 0
assert device_edges == []
def test_orphaned_prestart_control_retires_on_host_epoch_loss_but_not_transient_tcp(
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
control, _binding, _ready = _install_authoritative_ready_bridge_control(service)
supervisor = service._connection_supervisor # noqa: SLF001
before = supervisor.snapshot()
changed_path = HostPathProbeResult(
available=True,
fingerprint="test-route:changed-after-sleep",
interface="test0",
source_ipv4="192.168.1.2",
route_class="direct",
)
new_epoch = supervisor.observe_host_path(changed_path)
assert new_epoch != before.host_path.epoch
assert supervisor.snapshot().control_plane.reason_code == "host-path-epoch-changed"
retired = service.state()
assert control.state == "idle"
assert service._application_control_process_lease_holders == set() # noqa: SLF001
assert retired["connection_policy"]["actions"]["scan-ble"]["allowed"] is True
transient_service, _ = service_with_fake_runtime(tmp_path / "transient")
transient_control, _binding, _ready = _install_authoritative_ready_bridge_control(
transient_service
)
transient_supervisor = transient_service._connection_supervisor # noqa: SLF001
transient = transient_supervisor.snapshot()
assert transient.intent is not None
assert transient.device_network.target is not None
assert transient_supervisor.observe_endpoint(
target=transient.device_network.target,
intent_id=transient.intent.intent_id,
host_path_epoch=transient.host_path.epoch,
reachable=False,
reason_code="tcp-endpoint-unreachable",
)
one_negative = transient_service.state()
assert transient_control.state == "connection-ready"
assert transient_service._application_control_process_lease_holders == { # noqa: SLF001
"control"
}
assert one_negative["connection_policy"]["actions"]["scan-ble"]["allowed"] is False
def test_default_transport_observation_ttl_outlives_one_slow_healthy_monitor_cycle(
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
monotonic_now = [100.0]
suspend_aware_now = [1_000.0]
supervisor = service._connection_supervisor # noqa: SLF001
supervisor._monotonic_clock = lambda: monotonic_now[0] # noqa: SLF001
supervisor._suspend_aware_clock = lambda: suspend_aware_now[0] # noqa: SLF001
control, _binding, _ready = _install_authoritative_ready_bridge_control(service)
# One production pass can consume 11.5 seconds plus its one-second
# interval. Observer silence through the former 15-second boundary must
# not tear down a verified pre-START owner or fabricate an epoch change.
monotonic_now[0] += 10.0
suspend_aware_now[0] += 10.0
delayed = service.state()
assert control.state == "connection-ready"
assert delayed["active_connection_mode"] == "bridge"
assert delayed["connection_lifecycle"]["active_binding_key"] is not None
assert supervisor.snapshot().authority.control_allowed is True
# The fallback now tolerates two complete bounded monitor passes.
monotonic_now[0] += 5.01
suspend_aware_now[0] += 5.01
former_boundary = service.state()
assert control.state == "connection-ready"
assert former_boundary["active_connection_mode"] == "bridge"
assert supervisor.snapshot().authority.control_allowed is True
# Complete silence beyond 30 seconds still fails closed. Existing explicit
# negative and fingerprint-change tests cover the faster loss paths.
monotonic_now[0] += 15.0
suspend_aware_now[0] += 15.0
expired = service.state()
assert control.state == "idle"
assert expired["active_connection_mode"] is None
assert supervisor.snapshot().authority.control_allowed is False
def test_orphan_retirement_waits_for_inflight_lifecycle_transition(tmp_path: Path) -> None:
service, _ = service_with_fake_runtime(tmp_path)
control, _binding, _ready = _install_authoritative_ready_bridge_control(service)
supervisor = service._connection_supervisor # noqa: SLF001
supervisor.observe_host_path(
HostPathProbeResult(
available=True,
fingerprint="test-route:bootstrap-race",
interface="test0",
source_ipv4="192.168.1.2",
route_class="direct",
)
)
assert service._k1_lifecycle_transition_gate.acquire(blocking=False) # noqa: SLF001
try:
service.state()
assert control.state == "connection-ready"
finally:
service._k1_lifecycle_transition_gate.release() # noqa: SLF001
service.state()
assert control.state == "idle"
def test_mode_select_winner_fences_connect_before_password_or_durable_admission(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service, device_id="k1-a")
selection_entered = threading.Event()
release_selection = threading.Event()
selection_failures: list[BaseException] = []
selection_results: list[dict[str, Any]] = []
original_runtime_snapshot = runtime.snapshot
paused = False
def paused_snapshot() -> dict[str, object]:
nonlocal paused
if threading.current_thread().name == "reconfigure-mode-winner" and not paused:
paused = True
selection_entered.set()
assert release_selection.wait(2.0)
return original_runtime_snapshot()
monkeypatch.setattr(runtime, "snapshot", paused_snapshot)
def run_selection() -> None:
try:
selection_results.append(
service.select_connection_mode(
DesiredConnectionModeRequest(
connection_mode="quick-connect",
expected_revision=0,
)
)
)
except BaseException as exc: # pragma: no cover - assertion aid
selection_failures.append(exc)
selection_thread = threading.Thread(
target=run_selection,
name="reconfigure-mode-winner",
daemon=True,
)
selection_thread.start()
assert selection_entered.wait(2.0)
password_reads: list[str] = []
losing_request = _connect_request(
device_id="k1-a",
ssid="lab-router",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
connection_mode="bridge",
expected_mode_revision=0,
expected_discovery_generation=0,
compatibility_attestation=ATTESTATION,
)
def forbidden_password_read(_secret: SecretStr) -> str:
password_reads.append("unwrapped")
raise AssertionError("losing Connect must fail before password unwrap")
monkeypatch.setattr(SecretStr, "get_secret_value", forbidden_password_read)
try:
with pytest.raises(facade_module.NetworkProvisioningConflict) as losing_connect:
asyncio.run(service.connect(losing_request))
finally:
release_selection.set()
selection_thread.join(timeout=3.0)
assert losing_connect.value.reason_code == "connection-reconfiguration-lifecycle-busy"
assert password_reads == []
assert selection_thread.is_alive() is False
assert selection_failures == []
assert selection_results[0]["desired_connection_mode"] == "quick-connect"
assert service._operations.snapshot() == [] # noqa: SLF001
assert service._network_provisioning_idempotency_journal.snapshot().records == () # noqa: SLF001
def test_bridge_host_association_is_one_shot_and_connection_finishes_ready(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service, device_id="k1-a")
writes = 0
associations: list[tuple[str, str]] = []
route_classes = iter(["default-route", "direct-or-routed"])
async def successful_write(
*_: object,
on_write_dispatch: Callable[[dict[str, Any], str], None] | None = None,
**__: object,
) -> dict[str, Any]:
nonlocal writes
writes += 1
_dispatch_test_network_write(on_write_dispatch)
return {
"started_at_utc": "2026-08-09T10:00:00Z",
"completed_at_utc": "2026-08-09T10:00:01Z",
"profile_id": "xgrids-k1-fw3-wifi-v1",
"outcome": "lan_address_observed",
"write_mode": "with_response",
"observations": [
{"status": _wifi_status_read("192.168.68.50", device_id="k1-a")["status"]}
],
}
monkeypatch.setattr(facade_module, "provision_wifi_once", successful_write)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(facade_module, "_host_route_class", lambda _target: next(route_classes))
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
monkeypatch.setattr(
facade_module,
"associate_with_ephemeral_wifi_credentials_once",
lambda _helper, ssid, password, **_kwargs: (
associations.append((ssid, password))
or {
"adapter": "CoreWLAN",
"outcome": "associated",
"already_associated": False,
"scan_attempt_count": 1,
"scan_elapsed_ms": 25,
}
),
)
monkeypatch.setattr(
facade_module,
"_await_control_endpoint_reachable",
_reachable_control_endpoint,
)
monkeypatch.setattr(facade_module, "_control_endpoint_reachable", lambda _target: True)
state = asyncio.run(
service.connect(
_connect_request(
device_id="k1-a",
ssid="lab-router",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
allow_host_wifi_switch=True,
)
)
)
assert writes == 1
assert associations == [("lab-router", PRIMARY_TEST_CREDENTIAL)]
assert state["connection_lifecycle"]["connection_ready"] is True
assert state["connection_lifecycle"]["active_mode"] == "bridge"
operation = next(item for item in state["operations"] if item["action"] == "network.provision")
assert operation["result"]["host_route_class"] is None
assert operation["result"]["control_endpoint_reachable"] is None
assert operation["result"]["host_wifi_switch_authorized"] is True
assert operation["result"]["host_wifi_association_performed"] is True
assert PRIMARY_TEST_CREDENTIAL not in str(state)
def test_bridge_host_wifi_switch_defaults_to_denied_and_does_not_replay_network_write(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service, device_id="k1-a")
writes = 0
association_calls: list[str] = []
async def successful_write(
*_: object,
on_write_dispatch: Callable[[dict[str, Any], str], None] | None = None,
**__: object,
) -> dict[str, Any]:
nonlocal writes
writes += 1
_dispatch_test_network_write(on_write_dispatch)
return {
"started_at_utc": "2026-08-09T10:30:00Z",
"completed_at_utc": "2026-08-09T10:30:01Z",
"profile_id": "xgrids-k1-fw3-wifi-v1",
"outcome": "lan_address_observed",
"write_mode": "with_response",
"observations": [
{"status": _wifi_status_read("192.168.68.50", device_id="k1-a")["status"]}
],
}
def forbidden_host_association(*_: object, **__: object) -> dict[str, Any]:
association_calls.append("attempted")
raise AssertionError("Bridge must not switch host Wi-Fi without explicit opt-in")
monkeypatch.setattr(facade_module, "provision_wifi_once", successful_write)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(facade_module, "_host_route_class", lambda _target: "tunnel")
monkeypatch.setattr(facade_module, "_inspect_host_path", _tunnel_host_path)
monkeypatch.setattr(
facade_module,
"associate_with_ephemeral_wifi_credentials_once",
forbidden_host_association,
)
request = _connect_request(
device_id="k1-a",
ssid="lab-router",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
idempotency_key="bridge-host-switch-default-deny",
)
assert request.allow_host_wifi_switch is False
first = asyncio.run(service.connect(request))
replay = asyncio.run(service.connect(request))
assert writes == 1
assert association_calls == []
operation = next(item for item in first["operations"] if item["action"] == "network.provision")
assert operation["status"] == "succeeded"
assert operation["result"]["phase"] == "network_applied"
assert operation["result"]["host_wifi_switch_authorized"] is False
assert operation["result"]["host_wifi_association_performed"] is False
assert operation["result"]["host_wifi_association_outcome"] == "not-authorized"
assert first["connection_attempt"]["phase"] == "network_applied"
assert first["connection_attempt"]["control_state"] == "unknown"
assert first["connection_attempt"]["safe_next_action"] == "wait-for-current-attempt"
assert replay["connection_attempt"]["phase"] == "network_applied"
assert replay["connection_attempt"]["control_state"] == "unknown"
assert replay["connection_attempt"]["safe_next_action"] == "verify-control-read-only"
assert PRIMARY_TEST_CREDENTIAL not in str(first)
def test_applied_network_bootstrap_failure_recovers_by_verify_without_rewrite(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service, device_id="k1-a")
writes = 0
bootstrap_attempts = 0
async def successful_write(
*_: object,
on_write_dispatch: Callable[[dict[str, Any], str], None] | None = None,
**__: object,
) -> dict[str, Any]:
nonlocal writes
writes += 1
_dispatch_test_network_write(on_write_dispatch)
return {
"started_at_utc": "2026-08-09T11:00:00Z",
"completed_at_utc": "2026-08-09T11:00:01Z",
"profile_id": "xgrids-k1-fw3-wifi-v1",
"outcome": "lan_address_observed",
"write_mode": "with_response",
"observations": [
{"status": _wifi_status_read("192.168.68.50", device_id="k1-a")["status"]}
],
}
async def failed_bootstrap(
bound_service: XgridsK1CompatibilityService,
*,
parent_operation_id: str | None,
connection_mode: facade_module.ConnectionMode,
inspection_only: bool = False,
) -> None:
nonlocal bootstrap_attempts
assert inspection_only is True
bootstrap_attempts += 1
operation, _ = bound_service._operations.begin( # noqa: SLF001
facade_module.ACTION_CONNECTION_CONTROL_BOOTSTRAP,
context={
"connection_mode": connection_mode,
"parent_operation_id": parent_operation_id,
"automatic_retry": False,
},
)
bound_service._operations.transition( # noqa: SLF001
operation.operation_id,
"running",
stage_code="mqtt-device-info",
message_code="connection.control_bootstrap.running",
)
failure = facade_module.ConnectionVerificationError(
"synthetic DeviceInfo timeout",
reason_code="control-bootstrap-timeout",
)
bound_service._operations.transition( # noqa: SLF001
operation.operation_id,
"failed",
stage_code="device-info-failed",
message_code="connection.control_bootstrap.failed",
error={
"category": "connection",
"code": failure.reason_code,
"retryable": True,
"safe_to_retry": True,
"side_effect_status": "none",
},
)
raise failure
monkeypatch.setattr(facade_module, "provision_wifi_once", successful_write)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(facade_module, "_host_route_class", lambda _target: "direct-or-routed")
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
monkeypatch.setattr(
facade_module,
"_await_control_endpoint_reachable",
_reachable_control_endpoint,
)
monkeypatch.setattr(facade_module, "_control_endpoint_reachable", lambda _target: True)
service._bootstrap_prestart_control_ready_owned = MethodType( # type: ignore[method-assign] # noqa: SLF001
failed_bootstrap,
service,
)
request = _connect_request(
device_id="k1-a",
ssid="lab-router",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
idempotency_key="applied-network-device-info-recovery",
)
failed = asyncio.run(service.connect(request))
assert writes == 1
assert bootstrap_attempts == 1
assert failed["configured_connection_mode"] == "bridge"
assert failed["active_connection_mode"] is None
assert failed["connection_lifecycle"]["connection_ready"] is False
assert failed["connection_attempt"]["status"] == "failed"
assert failed["connection_attempt"]["phase"] == "network_applied"
assert failed["connection_attempt"]["control_state"] == "control_not_ready"
assert failed["connection_attempt"]["safe_next_action"] == "verify-control-read-only"
assert failed["network_mutation_ledger"]["resolution"] == "target-observed"
assert failed["network_provisioning_idempotency"]["active_operation_id"] is None
replayed = asyncio.run(service.connect(request))
assert writes == 1
assert bootstrap_attempts == 1
assert replayed["connection_lifecycle"]["connection_ready"] is False
assert replayed["connection_attempt"]["phase"] == "network_applied"
assert replayed["connection_attempt"]["control_state"] == "control_not_ready"
service._bootstrap_prestart_control_ready_owned = MethodType( # type: ignore[method-assign] # noqa: SLF001
_synthetic_prestart_control_bootstrap,
service,
)
monkeypatch.setattr(
facade_module,
"_probe_control_endpoint_socket",
lambda _target: facade_module.TcpReachabilityProbeResult(reachable=True),
)
monkeypatch.setattr(
facade_module,
"read_wifi_status_once",
lambda *_args, **_kwargs: asyncio.sleep(
0,
result=_wifi_status_read("192.168.68.50", device_id="k1-a"),
),
)
recovered = asyncio.run(service.verify_connection(ConnectionVerifyRequest()))
assert writes == 1
assert recovered["connection_lifecycle"]["connection_ready"] is True
assert recovered["connection_lifecycle"]["active_mode"] == "bridge"
assert recovered["last_operation"]["action"] == "connection.verify"
assert recovered["last_operation"]["status"] == "succeeded"
assert recovered["connection_attempt"]["status"] == "succeeded"
assert recovered["connection_attempt"]["phase"] == "network_applied"
assert recovered["connection_attempt"]["control_state"] == "ready"
assert recovered["connection_attempt"]["safe_next_action"] == "start-acquisition"
assert (
recovered["connection_attempt"]["recovery_operation_id"]
== recovered["last_operation"]["operation_id"]
)
semantic_after_verify = service._semantic_topology_store.snapshot() # type: ignore[union-attr] # noqa: SLF001
assert semantic_after_verify.record is not None
assert semantic_after_verify.record.source == "ble-read-only-status"
restarted_service, _ = service_with_fake_runtime(tmp_path)
restarted_replay = asyncio.run(restarted_service.connect(request))
restarted_network = next(
item
for item in restarted_replay["operations"]
if item["action"] == facade_module.ACTION_NETWORK_PROVISION
)
assert writes == 1
assert restarted_network["stage_code"] == "durable-terminal-replay"
assert restarted_network["result"]["replay_binding_available"] is True
assert restarted_network["result"]["target_ipv4"] == "192.168.68.50"
assert restarted_replay["connection_attempt"]["control_state"] == "unknown"
# A same-UUID advertisement is incidental presence, not a reason to hide
# the exact resolved-Apply LAN recovery target or force another GATT read.
_set_scanned_k1(restarted_service, device_id="k1-a")
advertised_recovery = restarted_service.state()
configured_observation = advertised_recovery["connection_policy"]["actions"][
"observe-configured-device-network"
]
assert advertised_recovery["current_device_recovery"] is None
assert configured_observation["allowed"] is True
assert configured_observation["required_transport_ref"] == "k1-a"
assert configured_observation["required_connection_mode"] == "bridge"
assert configured_observation["requires_live_gatt_validation"] is False
assert (
"fresh-candidate-supersedes-durable-recovery" not in configured_observation["reason_codes"]
)
durable_ble_reads = 0
async def forbidden_durable_ble_read(*_: object, **__: object) -> dict[str, Any]:
nonlocal durable_ble_reads
durable_ble_reads += 1
raise AssertionError("resolved Apply recovery must stay LAN/MQTT-only")
monkeypatch.setattr(
facade_module,
"read_wifi_status_once",
forbidden_durable_ble_read,
)
restarted_verified = asyncio.run(
restarted_service.verify_connection(
ConnectionVerifyRequest(
device_id="k1-a",
source="durable-configured-state",
compatibility_attestation=ATTESTATION,
)
)
)
assert writes == 1
assert durable_ble_reads == 0
assert restarted_verified["last_operation"]["action"] == "connection.verify"
assert restarted_verified["last_operation"]["status"] == "succeeded"
assert (
restarted_verified["connection_attempt"]["attempt_id"] == restarted_network["operation_id"]
)
assert restarted_verified["connection_attempt"]["control_state"] == "ready"
assert restarted_verified["connection_attempt"]["safe_next_action"] == ("start-acquisition")
@pytest.mark.parametrize(
("mismatched_field", "mismatched_value"),
[
("transport_ref", "foreign-k1"),
("connection_mode", "quick-connect"),
("ipv4", "192.168.68.99"),
("source", "foreign-evidence-source"),
("compatibility_profile_id", "foreign.compatibility.profile"),
],
)
def test_resolved_apply_durable_mismatch_blocks_policy_and_verify_without_io(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
mismatched_field: str,
mismatched_value: str,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
ledger = service._network_mutation_ledger # noqa: SLF001
observation = NetworkStatusEvidence(
mode="WIFI_CLIENT",
ipv4="192.168.68.50",
status_code=1,
reserved=0,
)
prepared = ledger.prepare(
operation_id="resolved-apply-mismatch",
transport_ref="k1-a",
intended_mode="bridge",
write_mode="with_response",
baseline_status=NetworkStatusEvidence(
mode="WIFI_AP",
ipv4="192.168.56.1",
status_code=1,
reserved=1,
),
)
dispatching = ledger.mark_dispatching(
prepared.operation_id,
expected_revision=prepared.revision,
)
observing = ledger.mark_observing(
dispatching.operation_id,
expected_revision=dispatching.revision,
write_confirmed=True,
observation=observation,
)
ledger.resolve(
observing.operation_id,
expected_revision=observing.revision,
resolution="target-observed",
)
topology_store = service._semantic_topology_store # noqa: SLF001
assert topology_store is not None
exact_record = topology_store.commit(
transport_ref="k1-a",
connection_mode="bridge",
ipv4="192.168.68.50",
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
firmware_version=ATTESTATION.firmware_version,
source="ble-post-write-status",
observed_at_utc="2026-08-11T12:00:00Z",
)
mismatched_record = exact_record.as_dict()
mismatched_record[mismatched_field] = mismatched_value
mismatched_snapshot_dict = {
"schema_version": "missioncore.xgrids-k1-semantic-topology/v1",
"status": "available",
"configured_offline_evidence": True,
"live_connection_authority": False,
"reason_code": None,
"record": mismatched_record,
}
mismatched_snapshot = SimpleNamespace(
status="available",
record=SimpleNamespace(**mismatched_record),
reason_code=None,
configured_offline_evidence=True,
live_connection_authority=False,
as_dict=lambda: mismatched_snapshot_dict,
)
monkeypatch.setattr(topology_store, "snapshot", lambda: mismatched_snapshot)
calls = {"host_probe": 0, "ble_read": 0, "network_write": 0, "control_open": 0}
def forbidden_host_probe(*_: object, **__: object) -> None:
calls["host_probe"] += 1
raise AssertionError("mismatched durable target must not probe the host")
async def forbidden_ble_read(*_: object, **__: object) -> dict[str, Any]:
calls["ble_read"] += 1
raise AssertionError("mismatched durable target must not read BLE")
async def forbidden_network_write(*_: object, **__: object) -> dict[str, Any]:
calls["network_write"] += 1
raise AssertionError("mismatched durable target must not write the network")
def forbidden_control_open(*_: object, **__: object) -> dict[str, object]:
calls["control_open"] += 1
raise AssertionError("mismatched durable target must not open control")
monkeypatch.setattr(
facade_module,
"_probe_configured_endpoint_host_only",
forbidden_host_probe,
)
monkeypatch.setattr(facade_module, "read_wifi_status_once", forbidden_ble_read)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_network_write)
monkeypatch.setattr(
service._application_control_session, # noqa: SLF001
"open",
forbidden_control_open,
)
before = service.state()
decision = before["connection_policy"]["actions"]["observe-configured-device-network"]
assert decision["allowed"] is False
assert "resolved-apply-durable-target-mismatch" in decision["reason_codes"]
assert decision["required_transport_ref"] is None
assert decision.get("required_connection_mode") is None
with pytest.raises(facade_module.ConnectionVerificationError) as raised:
asyncio.run(
service.verify_connection(
ConnectionVerifyRequest(
device_id="k1-a",
source="durable-configured-state",
compatibility_attestation=ATTESTATION,
)
)
)
assert raised.value.reason_code == ("connection-verify-resolved-apply-target-mismatch")
assert calls == {
"host_probe": 0,
"ble_read": 0,
"network_write": 0,
"control_open": 0,
}
after = ledger.snapshot()
assert after.record is not None
assert after.record.operation_id == "resolved-apply-mismatch"
assert after.record.write_confirmed is True
assert after.record.resolution == "target-observed"
def test_applied_network_bootstrap_cancellation_does_not_cancel_fast_ack_or_rewrite(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service, device_id="k1-a")
writes = 0
async def successful_write(
*_: object,
on_write_dispatch: Callable[[dict[str, Any], str], None] | None = None,
**__: object,
) -> dict[str, Any]:
nonlocal writes
writes += 1
_dispatch_test_network_write(on_write_dispatch)
return {
"started_at_utc": "2026-08-09T11:30:00Z",
"completed_at_utc": "2026-08-09T11:30:01Z",
"profile_id": "xgrids-k1-fw3-wifi-v1",
"outcome": "lan_address_observed",
"write_mode": "with_response",
"observations": [
{"status": _wifi_status_read("192.168.68.50", device_id="k1-a")["status"]}
],
}
def cancelled_control_open(**_: object) -> None:
raise asyncio.CancelledError
monkeypatch.setattr(facade_module, "provision_wifi_once", successful_write)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(facade_module, "_host_route_class", lambda _target: "direct-or-routed")
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
monkeypatch.setattr(
facade_module,
"_await_control_endpoint_reachable",
_reachable_control_endpoint,
)
monkeypatch.setattr(facade_module, "_control_endpoint_reachable", lambda _target: True)
service._bootstrap_prestart_control_ready_owned = MethodType( # type: ignore[method-assign] # noqa: SLF001
XgridsK1CompatibilityService._bootstrap_prestart_control_ready_owned, # noqa: SLF001
service,
)
monkeypatch.setattr(
service._application_control_session, # noqa: SLF001
"open",
cancelled_control_open,
)
request = _connect_request(
device_id="k1-a",
ssid="lab-router",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
idempotency_key="applied-network-device-info-cancelled",
)
fast_ack = asyncio.run(service.connect(request))
assert fast_ack["connection_attempt"]["phase"] == "network_applied"
cancelled = service.state()
assert writes == 1
network_operation = next(
item for item in cancelled["operations"] if item["action"] == "network.provision"
)
assert network_operation["status"] == "succeeded"
assert network_operation["result"]["phase"] == "network_applied"
bootstrap_operation = next(
item
for item in service._operations.snapshot() # noqa: SLF001
if item["action"] == facade_module.ACTION_CONNECTION_CONTROL_BOOTSTRAP
)
assert bootstrap_operation["status"] == "cancelled"
assert cancelled["connection_attempt"]["phase"] == "network_applied"
assert cancelled["connection_attempt"]["control_state"] == "unknown"
assert cancelled["connection_attempt"]["safe_next_action"] == ("verify-control-read-only")
replayed = asyncio.run(service.connect(request))
assert writes == 1
assert replayed["connection_attempt"]["phase"] == "network_applied"
assert replayed["connection_attempt"]["control_state"] == "unknown"
def _install_successful_fast_ack_bridge_write(
monkeypatch: pytest.MonkeyPatch,
) -> list[str]:
writes: list[str] = []
async def successful_write(
*_: object,
on_write_dispatch: Callable[[dict[str, Any], str], None] | None = None,
**__: object,
) -> dict[str, Any]:
writes.append("network-write")
_dispatch_test_network_write(on_write_dispatch)
return {
"started_at_utc": "2026-08-11T10:00:00Z",
"completed_at_utc": "2026-08-11T10:00:01Z",
"profile_id": "xgrids-k1-fw3-wifi-v1",
"outcome": "lan_address_observed",
"write_mode": "with_response",
"observations": [
{"status": _wifi_status_read("192.168.68.50", device_id="k1-a")["status"]}
],
}
monkeypatch.setattr(facade_module, "provision_wifi_once", successful_write)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
monkeypatch.setattr(facade_module, "_control_endpoint_reachable", lambda _target: True)
return writes
def test_connect_fast_ack_does_not_wait_for_blocked_endpoint_and_write_is_once(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service, device_id="k1-a")
writes = _install_successful_fast_ack_bridge_write(monkeypatch)
request = _connect_request(
device_id="k1-a",
ssid="lab-router",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
idempotency_key="fast-ack-blocked-endpoint-once",
)
async def scenario() -> None:
endpoint_started = asyncio.Event()
release_endpoint = asyncio.Event()
async def blocked_endpoint(*_: object, **__: object) -> object:
endpoint_started.set()
await release_endpoint.wait()
path = _direct_host_path("192.168.68.50")
service._observe_connection_transport( # noqa: SLF001
"192.168.68.50",
path=path,
reachable=True,
)
return facade_module._CorrelatedEndpointObservation( # noqa: SLF001
path=path,
reachable=True,
reason_code=None,
)
monkeypatch.setattr(
facade_module,
"_await_control_endpoint_reachable",
blocked_endpoint,
)
fast_ack = await asyncio.wait_for(service.connect(request), timeout=1.0)
assert endpoint_started.is_set()
assert writes == ["network-write"]
network_operation = next(
item
for item in fast_ack["operations"]
if item["action"] == facade_module.ACTION_NETWORK_PROVISION
)
assert network_operation["status"] == "succeeded"
assert network_operation["stage_code"] == "network-configured"
assert network_operation["result"]["phase"] == "network_applied"
assert network_operation["result"]["control_state"] == "unknown"
assert network_operation["result"]["host_route_ready"] is None
assert network_operation["result"]["control_endpoint_reachable"] is None
assert fast_ack["connection_attempt"]["control_state"] == "unknown"
assert fast_ack["connection_attempt"]["safe_next_action"] == ("wait-for-current-attempt")
with service._lock: # noqa: SLF001
continuation_task = service._control_bootstrap_continuation_task # noqa: SLF001
assert continuation_task is not None
assert not continuation_task.done()
release_endpoint.set()
await asyncio.wait_for(asyncio.shield(continuation_task), timeout=1.0)
ready = service.state()
assert ready["connection_attempt"]["control_state"] == "ready"
assert ready["connection_attempt"]["safe_next_action"] == "start-acquisition"
replay = await service.connect(request)
assert writes == ["network-write"]
assert replay["connection_attempt"]["phase"] == "network_applied"
asyncio.run(scenario())
def test_connect_fast_ack_does_not_wait_for_blocked_device_info(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service, device_id="k1-a")
writes = _install_successful_fast_ack_bridge_write(monkeypatch)
monkeypatch.setattr(
facade_module,
"_await_control_endpoint_reachable",
_reachable_control_endpoint,
)
synthetic_bootstrap = service._bootstrap_prestart_control_ready_owned # noqa: SLF001
request = _connect_request(
device_id="k1-a",
ssid="lab-router",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
idempotency_key="fast-ack-blocked-device-info",
)
async def scenario() -> None:
device_info_started = asyncio.Event()
release_device_info = asyncio.Event()
async def blocked_bootstrap(
_service: XgridsK1CompatibilityService,
*,
parent_operation_id: str | None,
connection_mode: facade_module.ConnectionMode,
inspection_only: bool = False,
) -> None:
device_info_started.set()
await release_device_info.wait()
await synthetic_bootstrap(
parent_operation_id=parent_operation_id,
connection_mode=connection_mode,
inspection_only=inspection_only,
)
service._bootstrap_prestart_control_ready_owned = MethodType( # type: ignore[method-assign] # noqa: SLF001
blocked_bootstrap,
service,
)
fast_ack = await asyncio.wait_for(service.connect(request), timeout=1.0)
assert device_info_started.is_set()
assert writes == ["network-write"]
assert fast_ack["connection_attempt"]["status"] == "running"
assert fast_ack["connection_attempt"]["control_state"] == "unknown"
assert fast_ack["connection_attempt"]["safe_next_action"] == ("wait-for-current-attempt")
with service._lock: # noqa: SLF001
continuation_task = service._control_bootstrap_continuation_task # noqa: SLF001
assert continuation_task is not None
release_device_info.set()
await asyncio.wait_for(asyncio.shield(continuation_task), timeout=1.0)
assert service.state()["connection_attempt"]["control_state"] == "ready"
asyncio.run(scenario())
@pytest.mark.parametrize("observed_state", ["ready", "scanning"])
def test_reset_retired_apply_continuation_settles_without_receiver_rehydrate(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
observed_state: str,
) -> None:
"""A reset-owned Apply settles physical truth without reviving capture."""
service, runtime = service_with_fake_runtime(tmp_path)
old_binding = _seed_supervised_connection(
service,
transport_ref="k1-a",
logical_device_id="k1-a",
)
_seed_unresolved_physical_stop_for_retirement(service, old_binding)
reset = service.select_connection_mode(
DesiredConnectionModeRequest(
connection_mode="bridge",
expected_revision=service.state()["desired_connection_mode_revision"],
reset_scenario=True,
reset_id="reset-retired-apply-scanning-stop-only-0001",
)
)
async def fresh_scan(
_duration_seconds: float,
*,
on_admitted: Callable[[], None] | None = None,
) -> dict[str, Any]:
assert on_admitted is not None
on_admitted()
return _ble_scan_result("k1-a")
monkeypatch.setattr(facade_module, "scan", fresh_scan)
scanned = asyncio.run(service.scan_ble(BleScanRequest(duration_seconds=1.0)))
_set_scanned_k1(service, device_id="k1-a")
writes = _install_successful_fast_ack_bridge_write(monkeypatch)
monkeypatch.setattr(
facade_module,
"_await_control_endpoint_reachable",
_reachable_control_endpoint,
)
synthetic_bootstrap = service._bootstrap_prestart_control_ready_owned # noqa: SLF001
coordinator = service._physical_command_coordinator # noqa: SLF001
inspection_modes: list[bool] = []
async def physical_bootstrap(
bound_service: XgridsK1CompatibilityService,
*,
parent_operation_id: str | None,
connection_mode: facade_module.ConnectionMode,
inspection_only: bool = False,
) -> None:
inspection_modes.append(inspection_only)
assert inspection_only is True
coordinator.prepare_read_only_bootstrap()
coordinator.application_response(
ApplicationMqttResponseEvidence(
operation_key=f"bootstrap:{parent_operation_id}:DeviceInfoRequest",
response_topic="lixel/application/response/device_info",
payload_sha256="7" * 64,
modeling_action=None,
result_code=None,
success=None,
observed_at_utc="2026-08-14T08:30:00.000Z",
)
)
await synthetic_bootstrap(
parent_operation_id=parent_operation_id,
connection_mode=connection_mode,
inspection_only=inspection_only,
)
verified = bound_service._application_control_session.snapshot().get( # noqa: SLF001
"verified_control"
)
assert isinstance(verified, dict)
reopened = bound_service._physical_command_ledger.snapshot().record # noqa: SLF001
assert reopened is not None
assert reopened.stage == "observing"
coordinator.bind_control_session(
PhysicalCommandRuntimeBinding(
vendor_device_id_sha256=(
reopened.identity.vendor_device_id_sha256
),
device_serial_sha256=reopened.identity.device_serial_sha256,
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
intent_id=str(verified["intent_id"]),
transport_ref=str(verified["transport_ref"]),
connection_mode=verified["connection_mode"], # type: ignore[arg-type]
target_ipv4=str(verified["target_ipv4"]),
target_port=int(verified["target_port"]),
host_path_epoch=int(verified["host_path_epoch"]),
control_session_id=str(verified["control_session_id"]),
producer_generation=int(verified["producer_generation"]),
)
)
coordinator.device_status(
ApplicationMqttDeviceStatusEvidence(
vendor_device_id_sha256=(
reopened.identity.vendor_device_id_sha256
),
device_serial_sha256=reopened.identity.device_serial_sha256,
session_state=observed_state, # type: ignore[arg-type]
session_state_code=(
MODELING_STATE_BASE + (302 if observed_state == "scanning" else 300)
),
project_bound=observed_state == "scanning",
project_id_sha256=(
"8" * 64 if observed_state == "scanning" else None
),
init_ready=observed_state == "scanning",
status_message_sha256="9" * 64,
mqtt_retained=False,
observed_at_utc="2026-08-14T08:30:01.000Z",
)
)
bound_service._acquire_application_control_process_lease() # noqa: SLF001
async def forbidden_receiver_rehydrate(**_kwargs: object) -> None:
pytest.fail("reset-owned SCANNING settlement must not recreate a receiver")
service._bootstrap_prestart_control_ready_owned = MethodType( # type: ignore[method-assign] # noqa: SLF001
physical_bootstrap,
service,
)
monkeypatch.setattr(
service,
"_rehydrate_active_acquisition_after_restart",
forbidden_receiver_rehydrate,
)
request = _connect_request(
device_id="k1-a",
ssid="lab-router",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
idempotency_key="reset-retired-apply-scanning-stop-only",
operation_id="op-00000000-0000-4000-8000-000000001401",
expected_mode_revision=reset["desired_connection_mode_revision"],
expected_discovery_generation=scanned["ble_discovery_generation"],
)
async def scenario() -> tuple[
dict[str, Any],
dict[str, Any],
dict[str, Any] | None,
]:
applied = await service.connect(request)
with service._lock: # noqa: SLF001
continuation_task = service._control_bootstrap_continuation_task # noqa: SLF001
if continuation_task is not None:
await asyncio.wait_for(asyncio.shield(continuation_task), timeout=1.0)
settled = service.state()
await service.connect(request.model_copy(update={"operation_id": None}))
successor: dict[str, Any] | None = None
if observed_state == "ready":
with pytest.raises(facade_module.NetworkProvisioningConflict) as stale:
await service.connect(
request.model_copy(
update={
"operation_id": None,
"ssid": "changed-without-reconfiguration",
}
)
)
assert stale.value.reason_code == "physical-command-target-retired"
prepared = await service.prepare_connection_reconfiguration(
_reconfiguration_request(settled, "change-network")
)
fresh = await service.scan_ble(BleScanRequest(duration_seconds=1.0))
_set_scanned_k1(service, device_id="k1-a")
monkeypatch.setattr(
service,
"_schedule_control_bootstrap_continuation",
lambda **_kwargs: None,
)
successor = await service.connect(
_connect_request(
device_id="k1-a",
ssid="new-lab-router",
password=SecretStr(SECONDARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
idempotency_key="reset-ready-explicit-change-network-successor",
operation_id="op-00000000-0000-4000-8000-000000001402",
expected_mode_revision=prepared[
"desired_connection_mode_revision"
],
expected_discovery_generation=fresh[
"ble_discovery_generation"
],
expected_reconfiguration_revision=fresh[
"connection_reconfiguration"
]["revision"],
expected_reconfiguration_intent_id=fresh[
"connection_reconfiguration"
]["intent_id"],
)
)
return applied, settled, successor
applied, settled, successor = asyncio.run(scenario())
physical = settled["physical_command"]
control = settled["application_control_session"]
acquisition = settled["acquisition"]
assert applied["connection_attempt"]["phase"] == "network_applied"
assert inspection_modes == [True]
assert writes == (
["network-write", "network-write"]
if observed_state == "ready"
else ["network-write"]
)
expected_resolution = (
"physical-active-observed"
if observed_state == "scanning"
else "physical-standby-observed"
)
assert physical["record"]["resolution"] == expected_resolution
assert physical["requires_reconciliation"] is False
assert physical["resolved_active_recovery_required"] is (
observed_state == "scanning"
)
if observed_state == "scanning":
assert control["state"] == "scanning"
assert control["inspection_only"] is True
assert control["can_stop"] is True
assert control["can_start"] is False
assert acquisition["state"] == "failed"
assert acquisition["requested_streams"] == []
assert acquisition["result"]["recovery_only"] is True
assert settled["connection_attempt"]["safe_next_action"] == "stop-acquisition"
assert settled["connection_policy"]["actions"]["stop-acquisition"]["allowed"] is True
assert settled["connection_policy"]["actions"]["start-acquisition"]["allowed"] is False
authority = service._connection_scenario_reset_retired_transport_authority # noqa: SLF001
assert authority is not None
synthetic_standby = {
**physical,
"status": "resolved",
"requires_reconciliation": False,
"resolved_active_recovery_required": False,
"reconciled_physical_state": "standby",
"physical_active": False,
"observed_session_state": "ready",
"record": {
**physical["record"],
"resolution": "stop-standby-observed",
},
}
with service._lock: # noqa: SLF001
assert (
service._consumed_reset_authority_has_safe_reconfiguration_successor_locked( # noqa: SLF001
authority=authority,
physical=physical,
request=request,
)
is False
)
# Even after a later STOP proves standby, the old request itself
# still lacks a separately committed Change Network generation.
assert (
service._consumed_reset_authority_has_safe_reconfiguration_successor_locked( # noqa: SLF001
authority=authority,
physical=synthetic_standby,
request=request,
)
is False
)
service._connection_reconfiguration_revision += 1 # noqa: SLF001
service._connection_reconfiguration_intent_id = ( # noqa: SLF001
"change-network-after-explicit-stop"
)
service._connection_reconfiguration_intent = "change-network" # noqa: SLF001
service._connection_reconfiguration_required_transport_ref = "k1-a" # noqa: SLF001
service._connection_reconfiguration_required_connection_mode = "bridge" # noqa: SLF001
service._ble_discovery_generation += 1 # noqa: SLF001
service._connection_reconfiguration_minimum_discovery_generation = ( # noqa: SLF001
service._ble_discovery_generation # noqa: SLF001
)
successor_request = request.model_copy(
update={
"operation_id": None,
"ssid": "new-network-after-explicit-stop",
"idempotency_key": "new-key-after-explicit-stop",
"expected_discovery_generation": (
service._ble_discovery_generation # noqa: SLF001
),
"expected_reconfiguration_revision": (
service._connection_reconfiguration_revision # noqa: SLF001
),
"expected_reconfiguration_intent_id": (
service._connection_reconfiguration_intent_id # noqa: SLF001
),
}
)
assert service._consumed_reset_authority_has_safe_reconfiguration_successor_locked( # noqa: SLF001
authority=authority,
physical=synthetic_standby,
request=successor_request,
)
else:
assert control["state"] == "connection-ready"
assert control["inspection_only"] is True
assert control["inspection_promotion_allowed"] is False
assert settled["connection_attempt"]["safe_next_action"] == (
"start-acquisition"
)
assert successor is not None
assert successor["last_operation"]["status"] == "succeeded"
assert service._connection_scenario_reset_retired_transport_authority is None # noqa: SLF001
assert runtime.phase == "idle"
assert runtime.source_mode == "idle"
assert runtime.start_calls == []
assert service._acquisition_session_lease is None # noqa: SLF001
assert service.camera_preview.snapshot()["phase"] == "idle"
assert service._live_perception_camera_binding is None # noqa: SLF001
@pytest.mark.parametrize("supersession", ["intent", "runtime"])
def test_control_bootstrap_continuation_cannot_publish_stale_parent_proof(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
supersession: str,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service, device_id="k1-a")
writes = _install_successful_fast_ack_bridge_write(monkeypatch)
request = _connect_request(
device_id="k1-a",
ssid="lab-router",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
idempotency_key=f"fast-ack-stale-{supersession}",
)
async def scenario() -> None:
endpoint_started = asyncio.Event()
release_endpoint = asyncio.Event()
async def blocked_endpoint(*_: object, **__: object) -> object:
endpoint_started.set()
await release_endpoint.wait()
return facade_module._CorrelatedEndpointObservation( # noqa: SLF001
path=_direct_host_path("192.168.68.50"),
reachable=True,
reason_code=None,
)
monkeypatch.setattr(
facade_module,
"_await_control_endpoint_reachable",
blocked_endpoint,
)
fast_ack = await service.connect(request)
assert endpoint_started.is_set()
with service._lock: # noqa: SLF001
continuation_task = service._control_bootstrap_continuation_task # noqa: SLF001
if supersession == "runtime":
service._snapshot_runtime_id = "snapshot-runtime-superseded" # noqa: SLF001
assert continuation_task is not None
if supersession == "intent":
service._connection_supervisor.set_intent( # noqa: SLF001
intent_id="explicit-new-intent",
requested_mode="bridge",
)
release_endpoint.set()
with pytest.raises(facade_module.ConnectionVerificationError):
await asyncio.wait_for(asyncio.shield(continuation_task), timeout=1.0)
state = service.state()
assert writes == ["network-write"]
assert fast_ack["connection_attempt"]["phase"] == "network_applied"
assert state["connection_attempt"]["phase"] == "network_applied"
assert state["connection_attempt"]["control_state"] == "control_not_ready"
assert state["connection_attempt"]["safe_next_action"] == ("verify-control-read-only")
assert state["network_mutation_ledger"]["resolution"] == "target-observed"
asyncio.run(scenario())
def test_service_close_cancels_owned_control_bootstrap_without_rewriting_network(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service, device_id="k1-a")
writes = _install_successful_fast_ack_bridge_write(monkeypatch)
request = _connect_request(
device_id="k1-a",
ssid="lab-router",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
idempotency_key="fast-ack-service-close-owns-child",
)
async def scenario() -> None:
endpoint_started = asyncio.Event()
async def blocked_endpoint(*_: object, **__: object) -> object:
endpoint_started.set()
await asyncio.Event().wait()
monkeypatch.setattr(
facade_module,
"_await_control_endpoint_reachable",
blocked_endpoint,
)
fast_ack = await service.connect(request)
assert endpoint_started.is_set()
with service._lock: # noqa: SLF001
continuation_task = service._control_bootstrap_continuation_task # noqa: SLF001
continuation = service._control_bootstrap_continuation # noqa: SLF001
assert continuation_task is not None
assert continuation is not None
service.close()
with pytest.raises(asyncio.CancelledError):
await continuation_task
child = service._operations.get(continuation.operation_id).as_dict() # noqa: SLF001
network = service._operations.get(continuation.parent_operation_id).as_dict() # noqa: SLF001
assert child["status"] == "cancelled"
assert network["status"] == "succeeded"
assert network["result"]["phase"] == "network_applied"
assert fast_ack["connection_attempt"]["phase"] == "network_applied"
assert writes == ["network-write"]
asyncio.run(scenario())
def test_control_bootstrap_final_fence_rejects_supersession_during_device_info(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service, device_id="k1-a")
writes = _install_successful_fast_ack_bridge_write(monkeypatch)
monkeypatch.setattr(
facade_module,
"_await_control_endpoint_reachable",
_reachable_control_endpoint,
)
control = FakeInteractiveControlSession(initial_state="idle")
original_open = control.open
def open_with_exact_identity(
*,
connection_binding: ApplicationConnectionBinding,
**kwargs: object,
) -> dict[str, object]:
snapshot = original_open(connection_binding=connection_binding, **kwargs)
intent = service._connection_supervisor.snapshot().intent # noqa: SLF001
assert intent is not None
control.verified_control = _verified_control_for_binding(
connection_binding,
logical_device_id=str(intent.expected_device_id or service._device_id), # noqa: SLF001
)
return snapshot
monkeypatch.setattr(control, "open", open_with_exact_identity)
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
production_bootstrap = MethodType(
XgridsK1CompatibilityService._bootstrap_prestart_control_ready_owned, # noqa: SLF001
service,
)
request = _connect_request(
device_id="k1-a",
ssid="lab-router",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
idempotency_key="fast-ack-device-info-final-fence",
)
async def scenario() -> None:
device_info_ready = asyncio.Event()
release_device_info = asyncio.Event()
async def ready_then_block(
_service: XgridsK1CompatibilityService,
*,
parent_operation_id: str | None,
connection_mode: facade_module.ConnectionMode,
inspection_only: bool = False,
) -> None:
await production_bootstrap(
parent_operation_id=parent_operation_id,
connection_mode=connection_mode,
inspection_only=inspection_only,
)
device_info_ready.set()
await release_device_info.wait()
service._bootstrap_prestart_control_ready_owned = MethodType( # type: ignore[method-assign] # noqa: SLF001
ready_then_block,
service,
)
fast_ack = await service.connect(request)
await asyncio.wait_for(device_info_ready.wait(), timeout=1.0)
with service._lock: # noqa: SLF001
continuation_task = service._control_bootstrap_continuation_task # noqa: SLF001
continuation = service._control_bootstrap_continuation # noqa: SLF001
assert continuation_task is not None
assert continuation is not None
child_before_release = service._operations.get( # noqa: SLF001
continuation.operation_id
).as_dict()
assert child_before_release["status"] == "running"
service._connection_supervisor.record_monitor_failure( # noqa: SLF001
"test-route-lost-during-device-info"
)
release_device_info.set()
with pytest.raises(facade_module.ConnectionVerificationError):
await asyncio.wait_for(asyncio.shield(continuation_task), timeout=1.0)
child = service._operations.get(continuation.operation_id).as_dict() # noqa: SLF001
network = service._operations.get(continuation.parent_operation_id).as_dict() # noqa: SLF001
state = service.state()
assert child["status"] == "failed"
assert network["status"] == "succeeded"
assert network["result"]["phase"] == "network_applied"
assert fast_ack["connection_attempt"]["phase"] == "network_applied"
assert state["connection_attempt"]["control_state"] == "control_not_ready"
assert state["connection_attempt"]["safe_next_action"] != "start-acquisition"
assert control.state in {"closed", "idle"}
assert writes == ["network-write"]
asyncio.run(scenario())
def test_historical_bootstrap_success_loses_ready_projection_with_live_route(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service, device_id="k1-a")
writes = _install_successful_fast_ack_bridge_write(monkeypatch)
monkeypatch.setattr(
facade_module,
"_await_control_endpoint_reachable",
_reachable_control_endpoint,
)
request = _connect_request(
device_id="k1-a",
ssid="lab-router",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
idempotency_key="fast-ack-live-authority-loss",
)
async def scenario() -> None:
await service.connect(request)
with service._lock: # noqa: SLF001
continuation_task = service._control_bootstrap_continuation_task # noqa: SLF001
if continuation_task is not None:
await asyncio.wait_for(asyncio.shield(continuation_task), timeout=1.0)
ready = service.state()
assert ready["connection_attempt"]["control_state"] == "ready"
assert ready["connection_attempt"]["safe_next_action"] == "start-acquisition"
service._connection_supervisor.record_monitor_failure( # noqa: SLF001
"test-route-loss-after-bootstrap-success"
)
lost = service.state()
child = next(
item
for item in service._operations.snapshot() # noqa: SLF001
if item["action"] == facade_module.ACTION_CONNECTION_CONTROL_BOOTSTRAP
and item.get("context", {}).get("ownership") == "service-owned-apply-continuation"
)
assert child["status"] == "succeeded"
assert lost["connection_attempt"]["control_state"] == "control_not_ready"
assert lost["connection_attempt"]["safe_next_action"] != "start-acquisition"
assert lost["connection_lifecycle"]["ready_to_start"] is False
assert writes == ["network-write"]
asyncio.run(scenario())
def test_control_bootstrap_cancelled_before_first_step_is_never_left_accepted(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service, device_id="k1-a")
writes = _install_successful_fast_ack_bridge_write(monkeypatch)
monkeypatch.setattr(
facade_module,
"_await_control_endpoint_reachable",
_reachable_control_endpoint,
)
request = _connect_request(
device_id="k1-a",
ssid="lab-router",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
idempotency_key="fast-ack-cancel-before-first-step",
)
async def scenario() -> None:
connected = await service.connect(request)
with service._lock: # noqa: SLF001
first_task = service._control_bootstrap_continuation_task # noqa: SLF001
if first_task is not None:
await asyncio.wait_for(asyncio.shield(first_task), timeout=1.0)
await asyncio.sleep(0)
network = next(
item
for item in connected["operations"]
if item["action"] == facade_module.ACTION_NETWORK_PROVISION
)
result = network["result"]
service._schedule_control_bootstrap_continuation( # noqa: SLF001
parent_operation_id=network["operation_id"],
connection_mode=result["connection_mode"],
transport_ref=result["transport_ref"],
target=facade_module.EndpointTarget(
result["target_ipv4"],
result["target_port"],
),
device_session_id=result["device_session_id"],
)
with service._lock: # noqa: SLF001
cancelled_task = service._control_bootstrap_continuation_task # noqa: SLF001
cancelled_continuation = service._control_bootstrap_continuation # noqa: SLF001
assert cancelled_task is not None
assert cancelled_continuation is not None
# No await has occurred since create_task: the coroutine has not entered.
service._request_control_bootstrap_continuation_close() # noqa: SLF001
with pytest.raises(asyncio.CancelledError):
await cancelled_task
await asyncio.sleep(0)
child = service._operations.get( # noqa: SLF001
cancelled_continuation.operation_id
).as_dict()
assert child["status"] == "cancelled"
assert child["stage_code"] == "control-bootstrap-cancelled"
with service._lock: # noqa: SLF001
assert service._control_bootstrap_continuation is None # noqa: SLF001
assert service._control_bootstrap_continuation_task is None # noqa: SLF001
assert service._control_bootstrap_continuation_loop is None # noqa: SLF001
assert writes == ["network-write"]
asyncio.run(scenario())
def _seed_terminal_network_attempt(
service: XgridsK1CompatibilityService,
) -> None:
operation, created = service._operations.begin( # noqa: SLF001
facade_module.ACTION_NETWORK_PROVISION,
operation_id="op-00000000-0000-4000-8000-000000009901",
context={
"snapshot_runtime_id": service.state()["snapshot_runtime_id"],
"transport_ref": "terminal-attempt-k1",
"connection_mode": "bridge",
},
)
assert created is True
service._operations.transition( # noqa: SLF001
operation.operation_id,
"running",
stage_code="ble-provisioning-write",
message_code="connection.network.running",
)
service._operations.transition( # noqa: SLF001
operation.operation_id,
"succeeded",
stage_code="network-configured",
message_code="connection.network.succeeded",
result={
"phase": "network_applied",
"side_effect_status": "applied",
"automatic_retry": False,
},
)
def test_terminal_connection_attempt_projects_current_local_cleanup_not_wait(
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
_seed_terminal_network_attempt(service)
runtime.source_mode = "live"
runtime.phase = "error"
state = service.state()
assert state["connection_attempt"]["status"] == "succeeded"
assert state["connection_policy"]["actions"]["stop-local-receiver"]["allowed"] is True
assert state["connection_attempt"]["safe_next_action"] == ("stop-local-receiver")
assert (
state["connection_attempt"]["diagnostic_bundle"]["attempt"]["safe_next_action"]
== "stop-local-receiver"
)
def test_terminal_connection_attempt_without_allowed_action_never_claims_wait_or_scan(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
_seed_terminal_network_attempt(service)
monkeypatch.setattr(
facade_module,
"ble_runtime_snapshot",
lambda: {
"owner_epoch": 9,
"owner_loop_bound": False,
"active_operation_kind": "status-read",
"cleanup_pending": True,
"poisoned": True,
},
)
state = service.state()
assert state["connection_attempt"]["status"] == "succeeded"
assert state["connection_policy"]["actions"]["scan-ble"]["allowed"] is False
assert state["connection_policy"]["actions"]["stop-local-receiver"]["allowed"] is False
assert state["connection_attempt"]["safe_next_action"] == ("manual-recovery-required")
def test_connection_attempt_projection_never_starts_without_ready_control() -> None:
runtime_id = "snapshot-runtime-test"
network_operation_id = "op-00000000-0000-4000-8000-000000000001"
network_operation = {
"operation_id": network_operation_id,
"action": facade_module.ACTION_NETWORK_PROVISION,
"status": "succeeded",
"stage_code": "network-configured",
"context": {
"snapshot_runtime_id": runtime_id,
"transport_ref": "k1-a",
"connection_mode": "bridge",
},
"result": {
"phase": "network_applied",
"control_state": "unknown",
"snapshot_runtime_id": runtime_id,
"parent_intent_id": network_operation_id,
"transport_ref": "k1-a",
"connection_mode": "bridge",
"target_ipv4": "192.168.68.50",
"target_port": facade_module.CONTROL_MQTT_PORT,
},
"events": [],
}
without_child = facade_module._connection_attempt_projection([network_operation]) # noqa: SLF001
assert without_child is not None
assert without_child["control_state"] == "unknown"
assert without_child["safe_next_action"] == "verify-control-read-only"
foreign_child = {
"operation_id": "op-00000000-0000-4000-8000-000000000002",
"action": facade_module.ACTION_CONNECTION_CONTROL_BOOTSTRAP,
"status": "running",
"stage_code": "mqtt-device-info",
"context": {
"parent_operation_id": network_operation["operation_id"],
"connection_mode": "bridge",
},
"events": [],
}
foreign = facade_module._connection_attempt_projection( # noqa: SLF001
[network_operation, foreign_child]
)
assert foreign is not None
assert foreign["safe_next_action"] == "verify-control-read-only"
owned_child = {
**foreign_child,
"context": {
"ownership": "service-owned-apply-continuation",
"snapshot_runtime_id": runtime_id,
"parent_operation_id": network_operation["operation_id"],
"parent_intent_id": network_operation["operation_id"],
"connection_mode": "bridge",
"transport_ref": "k1-a",
"target_ipv4": "192.168.68.50",
"target_port": facade_module.CONTROL_MQTT_PORT,
"device_session_id": "device-session-test",
"network_mutation_performed": False,
"ble_operation_performed": False,
"automatic_retry": False,
},
}
owned = facade_module._connection_attempt_projection( # noqa: SLF001
[network_operation, owned_child]
)
assert owned is not None
assert owned["control_state"] == "unknown"
assert owned["safe_next_action"] == "wait-for-current-attempt"
ready_child = {
**owned_child,
"status": "succeeded",
"result": {
"connection_mode": "bridge",
"control_verified": True,
"network_mutation_performed": False,
"ble_operation_performed": False,
"automatic_retry": False,
},
}
ready = facade_module._connection_attempt_projection( # noqa: SLF001
[network_operation, ready_child]
)
assert ready is not None
assert ready["control_state"] == "ready"
assert ready["safe_next_action"] == "start-acquisition"
scanning_child = {
**ready_child,
"result": {
**ready_child["result"],
"physical_reconciliation": {
"performed": True,
"resolution": "physical-active-observed",
"observed_session_state": "scanning",
"device_write_performed": False,
"automatic_retry": False,
},
},
}
scanning = facade_module._connection_attempt_projection( # noqa: SLF001
[network_operation, scanning_child]
)
assert scanning is not None
assert scanning["control_state"] == "unknown"
assert scanning["safe_next_action"] == "stop-acquisition"
assert scanning["safe_next_action"] != "start-acquisition"
assert scanning["physical_reconciliation"] == (
scanning_child["result"]["physical_reconciliation"]
)
foreign_verify = {
"operation_id": "op-00000000-0000-4000-8000-000000000003",
"action": facade_module.ACTION_CONNECTION_VERIFY,
"status": "succeeded",
"stage_code": "device-info-confirmed",
"context": {
"snapshot_runtime_id": runtime_id,
"requested_transport_ref": "other-k1",
"requested_connection_mode": "quick-connect",
},
"result": {
"write_performed": False,
"control_verified": True,
"verified_binding": {
"snapshot_runtime_id": runtime_id,
"intent_id": "foreign-intent",
"transport_ref": "other-k1",
"connection_mode": "quick-connect",
"target_ipv4": "192.168.43.1",
"target_port": facade_module.CONTROL_MQTT_PORT,
"host_path_epoch": 2,
},
},
"events": [],
}
foreign_verify_projection = facade_module._connection_attempt_projection( # noqa: SLF001
[network_operation, foreign_verify]
)
assert foreign_verify_projection is not None
assert foreign_verify_projection["control_state"] == "unknown"
assert foreign_verify_projection["safe_next_action"] == "verify-control-read-only"
exact_verify_context = {
"snapshot_runtime_id": runtime_id,
"recovery_parent_operation_id": network_operation_id,
"recovery_parent_intent_id": network_operation_id,
"recovery_transport_ref": "k1-a",
"recovery_connection_mode": "bridge",
"recovery_target_ipv4": "192.168.68.50",
"recovery_target_port": facade_module.CONTROL_MQTT_PORT,
}
exact_verify = {
**foreign_verify,
"status": "running",
"context": exact_verify_context,
"result": None,
}
exact_pending = facade_module._connection_attempt_projection( # noqa: SLF001
[network_operation, exact_verify]
)
assert exact_pending is not None
assert exact_pending["control_state"] == "unknown"
assert exact_pending["safe_next_action"] == "wait-for-current-attempt"
wrong_verify_binding = {
**exact_verify,
"status": "succeeded",
"result": foreign_verify["result"],
}
wrong_verify = facade_module._connection_attempt_projection( # noqa: SLF001
[network_operation, wrong_verify_binding]
)
assert wrong_verify is not None
assert wrong_verify["control_state"] == "unknown"
assert wrong_verify["safe_next_action"] == "verify-control-read-only"
exact_verify_success = {
**exact_verify,
"status": "succeeded",
"result": {
"write_performed": False,
"control_verified": True,
"verified_binding": {
"snapshot_runtime_id": runtime_id,
"intent_id": "durable-read-only-verify-intent",
"transport_ref": "k1-a",
"connection_mode": "bridge",
"target_ipv4": "192.168.68.50",
"target_port": facade_module.CONTROL_MQTT_PORT,
"host_path_epoch": 2,
},
},
}
exact_ready = facade_module._connection_attempt_projection( # noqa: SLF001
[network_operation, exact_verify_success]
)
assert exact_ready is not None
assert exact_ready["control_state"] == "ready"
assert exact_ready["safe_next_action"] == "start-acquisition"
def test_connect_reconfiguration_admission_fences_mode_selection_before_transition_gate(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
"""Connect's pre-secret semantic admission is one deterministic winner."""
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service, device_id="k1-a")
borrow_entered = threading.Event()
release_borrow = threading.Event()
connect_failures: list[BaseException] = []
device_writes: list[str] = []
@contextmanager
def paused_network_ble_borrow() -> Iterator[object]:
# Connect has passed its semantic admission and retains the
# reconfiguration gate across durable journal creation. Mode Select
# cannot publish a stale draft in this pre-transition interval.
borrow_entered.set()
assert release_borrow.wait(2.0)
raise RuntimeError("synthetic admitted Connect ended before BLE")
yield object() # pragma: no cover - contextmanager generator marker
async def forbidden_device_write(*_: object, **__: object) -> dict[str, Any]:
device_writes.append("gatt-write")
raise AssertionError("stale mode Connect crossed the GATT boundary")
monkeypatch.setattr(
service,
"_borrow_network_ble_process_lease",
paused_network_ble_borrow,
)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_device_write)
request = _connect_request(
device_id="k1-a",
ssid="lab-router",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
idempotency_key="connect-admission-wins-before-mode-selection",
)
def run_connect() -> None:
try:
asyncio.run(service.connect(request))
except BaseException as exc: # pragma: no branch - expected contract edge
connect_failures.append(exc)
connect_thread = threading.Thread(target=run_connect, daemon=True)
connect_thread.start()
assert borrow_entered.wait(2.0)
try:
with pytest.raises(facade_module.NetworkProvisioningConflict) as blocked:
service.select_connection_mode(
DesiredConnectionModeRequest(
connection_mode="quick-connect",
expected_revision=0,
)
)
assert blocked.value.reason_code == "connection-mode-selection-lifecycle-busy"
finally:
release_borrow.set()
connect_thread.join(timeout=3.0)
assert connect_thread.is_alive() is False
assert len(connect_failures) == 1
assert isinstance(connect_failures[0], RuntimeError)
assert str(connect_failures[0]) == "synthetic admitted Connect ended before BLE"
assert device_writes == []
state = service.state()
assert state["desired_connection_mode"] == "bridge"
assert state["desired_connection_mode_revision"] == 0
assert state["configured_connection_mode"] is None
assert state["active_connection_mode"] is None
operation = next(item for item in state["operations"] if item["action"] == "network.provision")
assert operation["status"] == "failed"
assert operation["error"]["side_effect_status"] == "none"
terminal_record = next(
record
for record in (
service._require_network_provisioning_idempotency_journal() # noqa: SLF001
.snapshot()
.records
)
if record.operation_id == operation["operation_id"]
)
terminal = terminal_record.terminal
assert terminal is not None
assert terminal.side_effect_status == "none"
assert terminal.safe_to_retry is True
def test_mode_selection_is_rejected_while_connect_owns_transition_gate(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
"""Once Connect owns lifecycle admission its exact mode cannot change."""
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service, device_id="k1-a")
capture_entered = threading.Event()
release_capture = threading.Event()
connect_failures: list[BaseException] = []
device_writes: list[str] = []
def paused_capture(_device_id: str) -> None:
# Capture is the first candidate-bound step after Connect acquired the
# lifecycle gate and repeated its exact mode/discovery CAS check.
capture_entered.set()
assert release_capture.wait(2.0)
return None
async def forbidden_device_write(*_: object, **__: object) -> dict[str, Any]:
device_writes.append("gatt-write")
raise AssertionError("test precondition must fail before GATT")
monkeypatch.setattr(facade_module, "_capture_network_intent_device", paused_capture)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_device_write)
request = _connect_request(
device_id="k1-a",
ssid="lab-router",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
idempotency_key="mode-cas-connect-owns-transition-gate",
)
def run_connect() -> None:
try:
asyncio.run(service.connect(request))
except BaseException as exc: # pragma: no branch - expected contract edge
connect_failures.append(exc)
connect_thread = threading.Thread(target=run_connect, daemon=True)
connect_thread.start()
assert capture_entered.wait(2.0)
try:
with pytest.raises(facade_module.NetworkProvisioningConflict) as busy_select:
service.select_connection_mode(
DesiredConnectionModeRequest(
connection_mode="quick-connect",
expected_revision=0,
)
)
assert busy_select.value.reason_code == "connection-mode-selection-lifecycle-busy"
during_connect = service.state()
assert during_connect["desired_connection_mode"] == "bridge"
assert during_connect["desired_connection_mode_revision"] == 0
finally:
release_capture.set()
connect_thread.join(timeout=3.0)
assert connect_thread.is_alive() is False
assert len(connect_failures) == 1
assert isinstance(connect_failures[0], facade_module.NetworkProvisioningConflict)
assert connect_failures[0].reason_code == "network-provision-candidate-not-fresh"
assert device_writes == []
state = service.state()
assert state["desired_connection_mode"] == "bridge"
assert state["desired_connection_mode_revision"] == 0
operation = next(item for item in state["operations"] if item["action"] == "network.provision")
assert operation["status"] == "failed"
assert operation["error"]["side_effect_status"] == "none"
def test_mode_selection_winning_before_start_final_admission_publishes_no_start(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
"""A newer prepared-mode draft wins before START owns its final fence."""
service, runtime = service_with_fake_runtime(tmp_path)
_select_connection_mode(service, "quick-connect")
control = FakeInteractiveControlSession()
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
binding = _seed_supervised_connection(
service,
target_ipv4=facade_module.AP_FALLBACK_IPV4,
connection_mode="quick-connect",
transport_ref="k1-a",
)
control.verified_control = _verified_control_for_binding(binding)
prepared = service.prepare_acquisition(
_prepare_request(
project_name="TEST001",
host=facade_module.AP_FALLBACK_IPV4,
compatibility_attestation=QUICK_CONNECT_ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
fingerprint_entered = threading.Event()
release_fingerprint = threading.Event()
start_failures: list[BaseException] = []
selection_results: list[dict[str, Any]] = []
selection_failures: list[BaseException] = []
original_fingerprint = service._request_fingerprint # noqa: SLF001
def paused_fingerprint(action: str, payload: dict[str, Any]) -> str:
if action == facade_module.ACTION_ACQUISITION_START:
fingerprint_entered.set()
assert release_fingerprint.wait(2.0)
return original_fingerprint(action, payload)
monkeypatch.setattr(service, "_request_fingerprint", paused_fingerprint)
def run_start() -> None:
try:
service.start_acquisition(
_start_request(
acquisition_id=acquisition_id,
physical_acceptance=PHYSICAL_ACCEPTANCE,
)
)
except BaseException as exc: # pragma: no branch - expected race loser
start_failures.append(exc)
start_thread = threading.Thread(target=run_start, daemon=True)
start_thread.start()
assert fingerprint_entered.wait(2.0)
def run_selection() -> None:
try:
selection_results.append(
service.select_connection_mode(
DesiredConnectionModeRequest(
connection_mode="bridge",
expected_revision=1,
)
)
)
except BaseException as exc: # pragma: no cover - assertion aid
selection_failures.append(exc)
selection_thread = threading.Thread(target=run_selection, daemon=True)
selection_thread.start()
try:
deadline = time.monotonic() + 2.0
while time.monotonic() < deadline:
with service._lock: # noqa: SLF001
if service._desired_connection_mode_revision == 2: # noqa: SLF001
break
time.sleep(0.01)
with service._lock: # noqa: SLF001
assert service._desired_connection_mode == "bridge" # noqa: SLF001
assert service._desired_connection_mode_revision == 2 # noqa: SLF001
finally:
release_fingerprint.set()
start_thread.join(timeout=3.0)
selection_thread.join(timeout=3.0)
assert start_thread.is_alive() is False
assert selection_thread.is_alive() is False
assert selection_failures == []
assert selection_results[0]["desired_connection_mode"] == "bridge"
assert selection_results[0]["desired_connection_mode_revision"] == 2
assert len(start_failures) == 1
assert isinstance(start_failures[0], facade_module.NetworkProvisioningConflict)
assert start_failures[0].reason_code == "connection-mode-switch-pending"
assert control.start_projects == []
assert runtime.start_calls == []
state = service.state()
assert state["acquisition"]["state"] == "prepared"
start_operation = next(
item for item in state["operations"] if item["action"] == "acquisition.start"
)
assert start_operation["status"] == "failed"
assert start_operation["error"]["side_effect_status"] == "none"
def test_start_owned_and_queued_states_reject_mode_selection_until_dispatch_resolves(
tmp_path: Path,
) -> None:
"""Queued START remains a mode-selection fence after the HTTP call returns."""
service, runtime = service_with_fake_runtime(tmp_path)
_select_connection_mode(service, "quick-connect")
request_start_entered = threading.Event()
release_request_start = threading.Event()
class QueuedStartControl(FakeInteractiveControlSession):
def request_start(
self,
*,
project_name: str,
confirmation: object,
command_context: object,
preparation_checkpoint_observer: object | None = None,
expected_session_generation: int | None = None,
expected_state_revision: int | None = None,
) -> dict[str, object]:
del preparation_checkpoint_observer
assert confirmation is not None
assert command_context is not None
assert self.state == "project-ready"
self._accept_checkpoint(
expected_session_generation=expected_session_generation,
expected_state_revision=expected_state_revision,
)
self.start_projects.append(project_name)
self.start_contexts.append(command_context)
self.state = "start-requested"
request_start_entered.set()
assert release_request_start.wait(2.0)
# The real worker has only been released here; modeling:start has
# deliberately not been published in this deterministic fixture.
return self.snapshot()
control = QueuedStartControl()
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
binding = _seed_supervised_connection(
service,
target_ipv4=facade_module.AP_FALLBACK_IPV4,
connection_mode="quick-connect",
transport_ref="k1-a",
)
control.verified_control = _verified_control_for_binding(binding)
prepared = service.prepare_acquisition(
_prepare_request(
project_name="TEST001",
host=facade_module.AP_FALLBACK_IPV4,
compatibility_attestation=QUICK_CONNECT_ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
start_failures: list[BaseException] = []
def run_start() -> None:
try:
service.start_acquisition(
_start_request(
acquisition_id=acquisition_id,
physical_acceptance=PHYSICAL_ACCEPTANCE,
)
)
except BaseException as exc: # pragma: no cover - assertion aid
start_failures.append(exc)
start_thread = threading.Thread(target=run_start, daemon=True)
start_thread.start()
assert request_start_entered.wait(2.0)
try:
with pytest.raises(facade_module.NetworkProvisioningConflict) as owned:
service.select_connection_mode(
DesiredConnectionModeRequest(
connection_mode="bridge",
expected_revision=1,
)
)
assert owned.value.reason_code == "connection-mode-selection-lifecycle-busy"
finally:
release_request_start.set()
start_thread.join(timeout=3.0)
assert start_thread.is_alive() is False
assert start_failures == []
queued = service.state()
assert queued["acquisition"]["state"] == "starting"
assert queued["desired_connection_mode"] == "quick-connect"
assert queued["desired_connection_mode_revision"] == 1
assert queued["connection_lifecycle"]["mode_selection"] == {
"allowed": False,
"reason_codes": [
"connection-mode-selection-physical-state-unsafe",
"connection-mode-selection-control-state-unsafe",
],
"automatic_retry": False,
}
assert "select-connection-mode" not in queued["connection_lifecycle"]["allowed_actions"]
assert runtime.start_calls
with pytest.raises(facade_module.NetworkProvisioningConflict) as queued_select:
service.select_connection_mode(
DesiredConnectionModeRequest(
connection_mode="bridge",
expected_revision=1,
)
)
assert queued_select.value.reason_code == "connection-mode-selection-physical-state-unsafe"
assert service.state()["desired_connection_mode_revision"] == 1
@pytest.mark.parametrize(
("source_mode", "target_mode", "target_ipv4", "source_attestation"),
[
(
"quick-connect",
"bridge",
facade_module.AP_FALLBACK_IPV4,
QUICK_CONNECT_ATTESTATION,
),
(
"bridge",
"quick-connect",
"192.168.1.20",
ATTESTATION,
),
],
ids=["quick-to-bridge", "bridge-to-quick"],
)
def test_pending_mode_scan_aborts_purely_local_prepared_acquisition_without_stop(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
source_mode: facade_module.ConnectionMode,
target_mode: facade_module.ConnectionMode,
target_ipv4: str,
source_attestation: CompatibilityAttestationRequest,
) -> None:
"""PREPARE without START is locally reversible at the explicit Scan commit."""
service, runtime = service_with_fake_runtime(tmp_path)
if source_mode != "bridge":
_select_connection_mode(service, source_mode)
source_revision = service.state()["desired_connection_mode_revision"]
control = FakeInteractiveControlSession()
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
binding = _seed_supervised_connection(
service,
target_ipv4=target_ipv4,
connection_mode=source_mode,
transport_ref="k1-a",
)
control.verified_control = _verified_control_for_binding(binding)
prepared = service.prepare_acquisition(
_prepare_request(
project_name="TEST001",
host=target_ipv4,
compatibility_attestation=source_attestation,
)
)
assert prepared["acquisition"]["state"] == "prepared"
assert control.state == "project-ready"
switched = service.select_connection_mode(
DesiredConnectionModeRequest(
connection_mode=target_mode,
expected_revision=source_revision,
)
)
assert switched["connection_policy"]["actions"]["scan-ble"]["allowed"] is True
assert switched["connection_lifecycle"]["mode_selection"]["allowed"] is True
assert "select-connection-mode" in switched["connection_lifecycle"]["allowed_actions"]
physical_or_network_edges: list[str] = []
async def fake_scan(
_duration_seconds: float,
*,
on_admitted: Callable[[], None] | None = None,
) -> dict[str, Any]:
assert service._acquisition is not None # noqa: SLF001
assert service._acquisition.state == "aborted" # noqa: SLF001
assert control.state == "idle"
assert on_admitted is not None
on_admitted()
return _ble_scan_result(f"{target_mode}-candidate")
async def forbidden_device_write(*_: object, **__: object) -> dict[str, Any]:
physical_or_network_edges.append("network-write")
raise AssertionError("prepared mode switch must not write K1 network state")
monkeypatch.setattr(facade_module, "scan", fake_scan)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_device_write)
monkeypatch.setattr(
service._physical_command_coordinator, # noqa: SLF001
"prepare",
lambda *_args, **_kwargs: physical_or_network_edges.append("physical-command"),
)
scanned = asyncio.run(service.scan_ble(1.0))
assert physical_or_network_edges == []
assert control.start_projects == []
assert control.stop_calls == 0
assert runtime.start_calls == []
assert runtime.stop_calls == 0
assert scanned["acquisition"]["state"] == "aborted"
assert scanned["acquisition"]["result"] == {
"receiver_started": False,
"device_command_attempted": False,
"reason_code": "superseded-by-connection-mode-switch",
}
assert scanned["configured_connection_mode"] is None
assert scanned["active_connection_mode"] is None
assert [item["device_id"] for item in scanned["devices"]] == [f"{target_mode}-candidate"]
def test_mode_draft_can_be_cancelled_before_scan_without_touching_active_binding(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
"""Quick -> Bridge draft -> Quick is two local CAS writes and no I/O."""
service, runtime = service_with_fake_runtime(tmp_path)
_select_connection_mode(service, "quick-connect")
control = FakeInteractiveControlSession(initial_state="project-ready")
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
binding = _seed_supervised_connection(
service,
target_ipv4=facade_module.AP_FALLBACK_IPV4,
connection_mode="quick-connect",
transport_ref="k1-a",
)
control.verified_control = _verified_control_for_binding(binding)
before = service.state()
before_supervisor_revision = service._connection_supervisor.snapshot().revision # noqa: SLF001
device_edges: list[str] = []
async def forbidden_scan(*_: object, **__: object) -> dict[str, Any]:
device_edges.append("ble-scan")
raise AssertionError("draft cancellation must not scan")
async def forbidden_network_write(*_: object, **__: object) -> dict[str, Any]:
device_edges.append("network-write")
raise AssertionError("draft cancellation must not write network state")
monkeypatch.setattr(facade_module, "scan", forbidden_scan)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_network_write)
monkeypatch.setattr(
service._physical_command_coordinator, # noqa: SLF001
"prepare",
lambda *_args, **_kwargs: device_edges.append("physical-command"),
)
switched = service.select_connection_mode(
DesiredConnectionModeRequest(
connection_mode="bridge",
expected_revision=before["desired_connection_mode_revision"],
)
)
cancelled = service.select_connection_mode(
DesiredConnectionModeRequest(
connection_mode="quick-connect",
expected_revision=switched["desired_connection_mode_revision"],
)
)
assert device_edges == []
assert runtime.start_calls == []
assert runtime.stop_calls == 0
assert control.state == "project-ready"
assert control.start_projects == []
assert control.stop_calls == 0
assert cancelled["desired_connection_mode_revision"] == (
before["desired_connection_mode_revision"] + 2
)
assert cancelled["desired_connection_mode"] == "quick-connect"
assert cancelled["configured_connection_mode"] == "quick-connect"
assert cancelled["active_connection_mode"] == "quick-connect"
assert (
cancelled["connection_lifecycle"]["active_binding_key"]
== before["connection_lifecycle"]["active_binding_key"]
)
assert (
cancelled["connection_lifecycle"]["active_binding"]
== before["connection_lifecycle"]["active_binding"]
)
assert cancelled["connection_lifecycle"]["mode_change"]["state"] == "ready"
assert cancelled["connection_lifecycle"]["connection_ready"] is True
assert cancelled["connection_lifecycle"]["ready_to_start"] is True
assert cancelled["connection_lifecycle"]["mode_selection"]["allowed"] is True
assert service._connection_supervisor.snapshot().revision == before_supervisor_revision # noqa: SLF001
def test_lifecycle_mode_selection_is_disallowed_while_acquiring(
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
_select_connection_mode(service, "quick-connect")
control = FakeInteractiveControlSession()
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
binding = _seed_supervised_connection(
service,
target_ipv4=facade_module.AP_FALLBACK_IPV4,
connection_mode="quick-connect",
transport_ref="k1-a",
)
control.verified_control = _verified_control_for_binding(binding)
service.prepare_acquisition(
_prepare_request(
project_name="TEST001",
host=facade_module.AP_FALLBACK_IPV4,
compatibility_attestation=QUICK_CONNECT_ATTESTATION,
)
)
with service._lock: # noqa: SLF001
assert service._acquisition is not None # noqa: SLF001
service._acquisition.transition( # noqa: SLF001
"starting",
message_code="acquisition.start.waiting_receiver_ready",
)
service._acquisition.transition( # noqa: SLF001
"acquiring",
message_code="acquisition.acquiring",
)
service._acquisition_start_operation_id = "test-start-operation" # noqa: SLF001
runtime.source_mode = "live"
runtime.phase = "live"
control.state = "scanning"
state = service.state()
assert state["connection_lifecycle"]["mode_selection"]["allowed"] is False
assert (
"connection-mode-selection-physical-state-unsafe"
in state["connection_lifecycle"]["mode_selection"]["reason_codes"]
)
assert (
"connection-mode-selection-control-state-unsafe"
in state["connection_lifecycle"]["mode_selection"]["reason_codes"]
)
assert "select-connection-mode" not in state["connection_lifecycle"]["allowed_actions"]
def test_lifecycle_mode_selection_is_disallowed_by_unsafe_physical_ledger(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
control = FakeInteractiveControlSession(initial_state="connection-ready")
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
binding = _seed_supervised_connection(service, connection_mode="bridge")
control.verified_control = _verified_control_for_binding(binding)
monkeypatch.setattr(
service._physical_command_coordinator, # noqa: SLF001
"snapshot",
lambda: {
"status": "unresolved",
"requires_reconciliation": True,
"record": None,
},
)
state = service.state()
assert state["connection_lifecycle"]["mode_selection"] == {
"allowed": False,
"reason_codes": ["connection-mode-selection-physical-state-unsafe"],
"automatic_retry": False,
}
assert "select-connection-mode" not in state["connection_lifecycle"]["allowed_actions"]
def test_disconnected_mode_draft_ignores_old_physical_history_without_io(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
"""A cold selector is local; the old ledger still fences later actions."""
service, runtime = service_with_fake_runtime(tmp_path)
control = FakeInteractiveControlSession(initial_state="idle")
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
physical_snapshot = {
"status": "unresolved",
"requires_reconciliation": True,
"resolved_active_recovery_required": False,
"record": {
"operation_id": "old-stop",
"action": "stop",
"stage": "observing",
"resolution": None,
},
}
monkeypatch.setattr(
service._physical_command_coordinator, # noqa: SLF001
"snapshot",
lambda: physical_snapshot,
)
device_edges: list[str] = []
monkeypatch.setattr(
facade_module,
"scan",
lambda *_args, **_kwargs: device_edges.append("scan"),
)
monkeypatch.setattr(
facade_module,
"provision_wifi_once",
lambda *_args, **_kwargs: device_edges.append("network-write"),
)
before = service.state()
assert before["connection_lifecycle"]["mode_selection"]["allowed"] is True
selected = service.select_connection_mode(
DesiredConnectionModeRequest(
connection_mode="quick-connect",
expected_revision=before["desired_connection_mode_revision"],
)
)
assert selected["desired_connection_mode"] == "quick-connect"
assert selected["desired_connection_mode_revision"] == 1
assert selected["physical_command"]["requires_reconciliation"] is True
assert selected["connection_policy"]["actions"]["provision-fresh-device"]["allowed"] is False
assert runtime.start_calls == []
assert runtime.stop_calls == 0
assert control.state == "idle"
assert device_edges == []
def test_carried_old_reopen_audit_does_not_freeze_a_successor_mode_draft() -> None:
physical_snapshot: dict[str, object] = {
"status": "unresolved",
"requires_reconciliation": True,
"record": {
"operation_id": "successor-stop",
"revision": 41,
"stage": "observing",
"resolution": None,
"operator_retirements": [
{
"retirement_id": "old-retirement",
"original_attempt": {"operation_id": "old-stop"},
}
],
"operator_reconciliation_reopens": [
{
"retirement_id": "old-retirement",
"retired_record_revision": 12,
}
],
},
}
assert (
facade_module._physical_command_pending_reopened_reconciliation_mode( # noqa: SLF001
physical_snapshot
)
is None
)
assert (
facade_module._connection_mode_selection_reason_codes( # noqa: SLF001
acquisition_state=None,
acquisition_lease_retained=False,
acquisition_start_operation_id=None,
runtime={"source_mode": "idle"},
physical_command=physical_snapshot,
control_state="idle",
desired_connection_mode="bridge",
)
== []
)
_RECOVERY_VENDOR_HASH = "a" * 64
_RECOVERY_SERIAL_HASH = "b" * 64
_RECOVERY_PROJECT_HASH = "c" * 64
_RECOVERY_ACQUISITION_ID = "acquisition-persisted-active-k1"
_RECOVERY_START_OPERATION_ID = "physical-start-persisted-active-k1"
def _persist_resolved_active_start_for_restart(
service: XgridsK1CompatibilityService,
) -> None:
"""Persist one successful START without retaining process-local acquisition."""
identity = PhysicalCommandIdentity(
vendor_device_id_sha256=_RECOVERY_VENDOR_HASH,
device_serial_sha256=_RECOVERY_SERIAL_HASH,
)
connection = PhysicalCommandConnectionBinding(
intent_id="old-start-intent",
transport_ref="test-ble-transport",
connection_mode="bridge",
target_ipv4="192.168.68.52",
target_port=facade_module.CONTROL_MQTT_PORT,
host_path_epoch=1,
control_session_id="old-start-control",
producer_generation=1,
)
def status(
session_state: str,
*,
observed_at_utc: str,
) -> PhysicalCommandStatusEvidence:
project_bound = session_state == "scanning"
return PhysicalCommandStatusEvidence(
source="live-control-session",
vendor_device_id_sha256=_RECOVERY_VENDOR_HASH,
device_serial_sha256=_RECOVERY_SERIAL_HASH,
control_session_id=connection.control_session_id,
host_path_epoch=connection.host_path_epoch,
producer_generation=connection.producer_generation,
session_state=session_state, # type: ignore[arg-type]
session_state_code=302 if session_state == "scanning" else 300,
project_bound=project_bound,
project_id_sha256=_RECOVERY_PROJECT_HASH if project_bound else None,
init_ready=project_bound,
status_message_sha256=hashlib.sha256(
f"{session_state}:{observed_at_utc}".encode()
).hexdigest(),
mqtt_retained=False,
observed_at_utc=observed_at_utc,
)
ledger = service._physical_command_ledger # noqa: SLF001
ledger.prepare(
operation_id=_RECOVERY_START_OPERATION_ID,
parent_operation_id=None,
acquisition_id=_RECOVERY_ACQUISITION_ID,
action="start",
identity=identity,
connection=connection,
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
payload_sha256="d" * 64,
baseline_status=status(
"ready",
observed_at_utc="2026-08-09T12:00:00.000Z",
),
)
ledger.mark_dispatching(_RECOVERY_START_OPERATION_ID)
ledger.mark_observing(
_RECOVERY_START_OPERATION_ID,
publish_call_returned=True,
packet_id=41,
)
ledger.mark_qos2_completed(_RECOVERY_START_OPERATION_ID, packet_id=41)
ledger.record_application_response(
_RECOVERY_START_OPERATION_ID,
PhysicalCommandApplicationResponse(
operation_id=_RECOVERY_START_OPERATION_ID,
action="start",
control_session_id=connection.control_session_id,
host_path_epoch=connection.host_path_epoch,
producer_generation=connection.producer_generation,
result_code=PHYSICAL_COMMAND_APPLICATION_SUCCESS_CODE,
success=True,
payload_sha256="e" * 64,
observed_at_utc="2026-08-09T12:00:01.000Z",
),
)
ledger.record_status_observation(
_RECOVERY_START_OPERATION_ID,
status("scanning", observed_at_utc="2026-08-09T12:00:02.000Z"),
)
ledger.resolve(
_RECOVERY_START_OPERATION_ID,
resolution="start-active-observed",
)
def _persist_resolved_unclassified_stop_for_restart(
service: XgridsK1CompatibilityService,
) -> tuple[str, int]:
"""Persist the exact legacy startup shape without process-local owners."""
_persist_resolved_active_start_for_restart(service)
ledger = service._physical_command_ledger # noqa: SLF001
start = ledger.snapshot().record
assert start is not None
assert start.last_status is not None
stop_operation_id = "physical-stop-resolved-unclassified-k1"
ledger.prepare(
operation_id=stop_operation_id,
parent_operation_id=start.operation_id,
acquisition_id=start.acquisition_id,
action="stop",
identity=start.identity,
connection=start.connection,
compatibility_profile_id=start.compatibility_profile_id,
payload_sha256="6" * 64,
baseline_status=start.last_status,
)
resolved = ledger.resolve(
stop_operation_id,
resolution="not-dispatched",
)
assert resolved.resolved_unclassified_stop_recovery_required is True
return stop_operation_id, resolved.revision
def _persist_classified_ready_stop_for_restart(
service: XgridsK1CompatibilityService,
) -> tuple[str, PhysicalCommandConnectionBinding]:
"""Persist S0 plus one read-only READY proof on an obsolete C1 binding."""
stop_operation_id, _ = _persist_resolved_unclassified_stop_for_restart(service)
coordinator = service._physical_command_coordinator # noqa: SLF001
observed_at_utc = datetime.now(UTC).isoformat(timespec="milliseconds").replace(
"+00:00",
"Z",
)
c1 = PhysicalCommandRuntimeBinding(
vendor_device_id_sha256=_RECOVERY_VENDOR_HASH,
device_serial_sha256=_RECOVERY_SERIAL_HASH,
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
intent_id="classified-ready-c1-intent",
transport_ref="test-ble-transport",
connection_mode="bridge",
target_ipv4="192.168.68.52",
target_port=facade_module.CONTROL_MQTT_PORT,
host_path_epoch=7,
control_session_id="classified-ready-c1-control",
producer_generation=7,
)
coordinator.application_response(
ApplicationMqttResponseEvidence(
operation_key="bootstrap:classified-ready-c1:DeviceInfoRequest",
response_topic="lixel/application/response/device_info",
payload_sha256="4" * 64,
modeling_action=None,
result_code=None,
success=None,
observed_at_utc=observed_at_utc,
)
)
coordinator.bind_control_session(c1)
coordinator.device_status(
ApplicationMqttDeviceStatusEvidence(
vendor_device_id_sha256=_RECOVERY_VENDOR_HASH,
device_serial_sha256=_RECOVERY_SERIAL_HASH,
session_state="ready",
session_state_code=MODELING_STATE_BASE + 300,
project_bound=False,
project_id_sha256=None,
init_ready=False,
status_message_sha256="5" * 64,
mqtt_retained=False,
observed_at_utc=observed_at_utc,
)
)
classified = coordinator.reconcile_unresolved(
reconciliation_id="classified-ready-c1",
)
assert classified["operation_id"] == stop_operation_id
assert classified["resolution"] == "not-dispatched"
return stop_operation_id, PhysicalCommandConnectionBinding(
intent_id=c1.intent_id,
transport_ref=c1.transport_ref,
connection_mode=c1.connection_mode,
target_ipv4=c1.target_ipv4,
target_port=c1.target_port,
host_path_epoch=c1.host_path_epoch,
control_session_id=c1.control_session_id,
producer_generation=c1.producer_generation,
)
def test_resolved_active_power_loss_exposes_local_retirement_and_revokes_target(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
_persist_resolved_active_start_for_restart(service)
_seed_terminal_network_attempt(service)
before = service.state()
checkpoint = before["physical_command"]["operator_retirement"]
action = before["connection_policy"]["actions"]["retire-unavailable-physical-target"]
io_calls: list[str] = []
async def forbidden_io(*_args: object, **_kwargs: object) -> object:
io_calls.append("device-or-network-io")
raise AssertionError("resolved-active retirement must stay local-only")
monkeypatch.setattr(facade_module, "read_wifi_status_once", forbidden_io)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_io)
monkeypatch.setattr(
service,
"_probe_control_endpoint",
lambda *_args, **_kwargs: io_calls.append("tcp-probe"),
)
assert before["physical_command"]["resolved_active_recovery_required"] is True
assert checkpoint["allowed"] is True
assert action["allowed"] is True
assert action["target_source"] == "durable-physical-command"
assert action["required_transport_ref"] == "test-ble-transport"
assert before["connection_policy"]["recommended_action"] == (
"retire-unavailable-physical-target"
)
assert before["connection_attempt"]["safe_next_action"] == (
"retire-unavailable-physical-target"
)
retired = service.retire_unavailable_physical_command(
RetireUnavailablePhysicalCommandRequest(
retirement_id="retirement-resolved-active-power-loss",
expected_operation_id=checkpoint["expected_operation_id"],
expected_revision=checkpoint["expected_revision"],
expected_transport_ref=checkpoint["expected_transport_ref"],
operator_confirmed=True,
reason="device-permanently-unavailable-or-replaced",
)
)
assert retired["physical_command"]["record"]["resolution"] == (
"operator-retired-outcome-unknown"
)
assert retired["physical_command"]["operator_retirement"]["allowed"] is False
assert retired["selected_device_id"] is None
assert retired["k1_ip"] is None
assert retired["connection_policy"]["facts"]["retired_transport_refs"] == ["test-ble-transport"]
assert runtime.start_calls == []
assert runtime.stop_calls == 0
assert io_calls == []
class _VerifyPhysicalRecoveryCoordinator:
"""Small exact-proof coordinator double for facade Verify recovery tests."""
def __init__(
self,
*,
observed_session_state: str | None,
reconciliation_ready: bool,
prepared_stop_operation_id: str | None = None,
) -> None:
self.observed_session_state = observed_session_state
self.reconciliation_ready = reconciliation_ready
self.resolution: str | None = None
self.reconciliation_ids: list[str] = []
self.verified_control: dict[str, object] | None = None
self.prepared_stop_operation_id = prepared_stop_operation_id
def _resolved_record(self, reconciliation_id: str) -> dict[str, object]:
assert self.verified_control is not None
connection = {
field: self.verified_control[field]
for field in (
"intent_id",
"transport_ref",
"connection_mode",
"target_ipv4",
"target_port",
"host_path_epoch",
"control_session_id",
"producer_generation",
)
}
return {
"operation_id": self.prepared_stop_operation_id or "persisted-start-observing",
"acquisition_id": "acq-persisted-start",
"action": "stop" if self.prepared_stop_operation_id is not None else "start",
"stage": "resolved",
"resolution": (
"not-dispatched"
if self.prepared_stop_operation_id is not None
else self.resolution
),
"compatibility_profile_id": XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
"connection": {
"transport_ref": "test-ble-transport",
"connection_mode": "bridge",
},
"reconciliations": [
{
"reconciliation_id": reconciliation_id,
"kind": (
"prepared-stop-classification"
if self.prepared_stop_operation_id is not None
else "ambiguous-outcome"
),
"resolution": "physical-active-observed",
"original_attempt": {
"operation_id": (
self.prepared_stop_operation_id or "persisted-start-observing"
),
"action": (
"stop" if self.prepared_stop_operation_id is not None else "start"
),
},
"verified_binding": {"connection": connection},
"observation": {
"source": "explicit-read-only-reconciliation",
"control_session_id": self.verified_control["control_session_id"],
"host_path_epoch": self.verified_control["host_path_epoch"],
"producer_generation": self.verified_control["producer_generation"],
"session_state": "scanning",
"project_bound": True,
"project_id_sha256": "8" * 64,
"init_ready": True,
"mqtt_retained": False,
},
}
],
}
def snapshot(self) -> dict[str, object]:
resolved_active_recovery_required = self.resolution == "physical-active-observed"
reconciliations = [{"resolution": self.resolution}] if self.resolution is not None else []
return {
"status": "resolved" if self.resolution is not None else "unresolved",
"reason_code": (
None if self.resolution is not None else "physical-command-reconciliation-required"
),
"requires_reconciliation": self.resolution is None,
"resolved_active_recovery_required": resolved_active_recovery_required,
"automatic_replay_allowed": False,
"normal_session_recovery_supported": False,
"recovery_requirement": (
"explicit-read-only-deviceinfo-and-non-retained-devicestatus"
if self.resolution is None or resolved_active_recovery_required
else None
),
"runtime_bound": True,
"reconciliation_ready": (
(self.resolution is None or resolved_active_recovery_required)
and self.reconciliation_ready
),
"observed_session_state": self.observed_session_state,
"active_operation_id": None,
"record": {
"operation_id": self.prepared_stop_operation_id or "persisted-start-observing",
"action": "stop" if self.prepared_stop_operation_id is not None else "start",
"stage": "resolved" if self.resolution is not None else "observing",
"resolution": self.resolution,
"connection": {
"transport_ref": "test-ble-transport",
"connection_mode": "bridge",
},
"reconciliations": reconciliations,
},
}
def reconcile_unresolved(self, *, reconciliation_id: str) -> dict[str, object]:
assert self.reconciliation_ready is True
assert self.observed_session_state in {"ready", "scanning"}
self.reconciliation_ids.append(reconciliation_id)
self.resolution = (
"physical-standby-observed"
if self.observed_session_state == "ready"
else "physical-active-observed"
)
return self._resolved_record(reconciliation_id)
def reconcile_resolved_active(
self,
*,
reconciliation_id: str,
) -> dict[str, object]:
assert self.resolution == "physical-active-observed"
assert self.reconciliation_ready is True
assert self.observed_session_state in {"ready", "scanning"}
self.reconciliation_ids.append(reconciliation_id)
if self.observed_session_state == "ready":
self.resolution = "physical-standby-observed"
return self._resolved_record(reconciliation_id)
def _install_synthetic_verify_recovery(
service: XgridsK1CompatibilityService,
coordinator: _VerifyPhysicalRecoveryCoordinator,
) -> None:
"""Install a no-I/O topology+DeviceInfo path while keeping real gates."""
_seed_supervised_connection(service, connection_mode="bridge", with_control=False)
with service._lock: # noqa: SLF001
service._connection_verification = { # noqa: SLF001
"lease_generation": service._connection_lease_generation, # noqa: SLF001
"lease_state": "reachable",
}
service._physical_command_coordinator = coordinator # type: ignore[assignment] # noqa: SLF001
async def verify_topology_without_io(
bound_service: XgridsK1CompatibilityService,
request: ConnectionVerifyRequest,
) -> tuple[str, bool, None]:
operation, created = bound_service._operations.begin( # noqa: SLF001
facade_module.ACTION_CONNECTION_VERIFY,
operation_id=request.operation_id,
deadline_seconds=10.0,
)
if created:
bound_service._operations.transition( # noqa: SLF001
operation.operation_id,
"running",
stage_code="topology-confirmed-device-info-pending",
message_code="connection.verify.device_info_pending",
)
return operation.operation_id, created, None
async def bootstrap_with_process_holder(
bound_service: XgridsK1CompatibilityService,
*,
parent_operation_id: str | None,
connection_mode: facade_module.ConnectionMode,
inspection_only: bool = False,
) -> None:
await _synthetic_prestart_control_bootstrap(
bound_service,
parent_operation_id=parent_operation_id,
connection_mode=connection_mode,
inspection_only=inspection_only,
)
verified = bound_service._application_control_session.snapshot().get( # noqa: SLF001
"verified_control"
)
assert isinstance(verified, dict)
coordinator.verified_control = dict(verified)
bound_service._acquire_application_control_process_lease() # noqa: SLF001
service._verify_connection_owned = MethodType( # type: ignore[method-assign] # noqa: SLF001
verify_topology_without_io,
service,
)
service._bootstrap_prestart_control_ready_owned = MethodType( # type: ignore[method-assign] # noqa: SLF001
bootstrap_with_process_holder,
service,
)
def _install_real_coordinator_bootstrap(
service: XgridsK1CompatibilityService,
*,
observed_session_state: str,
) -> None:
"""Install exact DeviceInfo/status evidence on the facade's real topology path."""
assert observed_session_state in {"ready", "scanning"}
coordinator = service._physical_command_coordinator # noqa: SLF001
async def bootstrap_with_real_coordinator(
bound_service: XgridsK1CompatibilityService,
*,
parent_operation_id: str | None,
connection_mode: facade_module.ConnectionMode,
inspection_only: bool = False,
) -> None:
coordinator.prepare_read_only_bootstrap()
coordinator.application_response(
ApplicationMqttResponseEvidence(
operation_key=(
f"bootstrap:{parent_operation_id}:DeviceInfoRequest"
),
response_topic="lixel/application/response/device_info",
payload_sha256="7" * 64,
modeling_action=None,
result_code=None,
success=None,
observed_at_utc="2026-08-13T08:00:00.000Z",
)
)
await _synthetic_prestart_control_bootstrap(
bound_service,
parent_operation_id=parent_operation_id,
connection_mode=connection_mode,
inspection_only=inspection_only,
)
verified = bound_service._application_control_session.snapshot().get( # noqa: SLF001
"verified_control"
)
assert isinstance(verified, dict)
coordinator.bind_control_session(
PhysicalCommandRuntimeBinding(
vendor_device_id_sha256=_RECOVERY_VENDOR_HASH,
device_serial_sha256=_RECOVERY_SERIAL_HASH,
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
intent_id=str(verified["intent_id"]),
transport_ref=str(verified["transport_ref"]),
connection_mode=verified["connection_mode"], # type: ignore[arg-type]
target_ipv4=str(verified["target_ipv4"]),
target_port=int(verified["target_port"]),
host_path_epoch=int(verified["host_path_epoch"]),
control_session_id=str(verified["control_session_id"]),
producer_generation=int(verified["producer_generation"]),
)
)
scanning = observed_session_state == "scanning"
coordinator.device_status(
ApplicationMqttDeviceStatusEvidence(
vendor_device_id_sha256=_RECOVERY_VENDOR_HASH,
device_serial_sha256=_RECOVERY_SERIAL_HASH,
session_state=observed_session_state, # type: ignore[arg-type]
session_state_code=MODELING_STATE_BASE + (302 if scanning else 300),
project_bound=scanning,
project_id_sha256=_RECOVERY_PROJECT_HASH if scanning else None,
init_ready=scanning,
status_message_sha256="8" * 64,
mqtt_retained=False,
observed_at_utc="2026-08-13T08:00:01.000Z",
)
)
bound_service._acquire_application_control_process_lease() # noqa: SLF001
service._bootstrap_prestart_control_ready_owned = MethodType( # type: ignore[method-assign] # noqa: SLF001
bootstrap_with_real_coordinator,
service,
)
def _install_real_coordinator_verify_recovery(
service: XgridsK1CompatibilityService,
*,
observed_session_state: str,
) -> None:
"""Drive public Verify with real durable reconciliation and no topology I/O."""
assert observed_session_state in {"ready", "scanning"}
_seed_supervised_connection(service, connection_mode="bridge", with_control=False)
with service._lock: # noqa: SLF001
service._connection_verification = { # noqa: SLF001
"lease_generation": service._connection_lease_generation, # noqa: SLF001
"lease_state": "reachable",
}
async def verify_topology_without_io(
bound_service: XgridsK1CompatibilityService,
request: ConnectionVerifyRequest,
) -> tuple[str, bool, None]:
operation, created = bound_service._operations.begin( # noqa: SLF001
facade_module.ACTION_CONNECTION_VERIFY,
operation_id=request.operation_id,
deadline_seconds=10.0,
)
if created:
bound_service._operations.transition( # noqa: SLF001
operation.operation_id,
"running",
stage_code="topology-confirmed-device-info-pending",
message_code="connection.verify.device_info_pending",
)
return operation.operation_id, created, None
service._verify_connection_owned = MethodType( # type: ignore[method-assign] # noqa: SLF001
verify_topology_without_io,
service,
)
_install_real_coordinator_bootstrap(
service,
observed_session_state=observed_session_state,
)
def _retained_physical_recovery_verify_request(
*,
operation_id: str,
) -> ConnectionVerifyRequest:
"""Address the exact process-retained K1 seeded by recovery fixtures."""
return ConnectionVerifyRequest(
device_id="test-ble-transport",
source="retained-current-process",
compatibility_attestation=ATTESTATION,
operation_id=operation_id,
)
def _install_terminal_camera_error_residual(
service: XgridsK1CompatibilityService,
monkeypatch: pytest.MonkeyPatch,
*,
cleanup_failure: Exception | None = None,
producer_alive: bool = False,
) -> list[str]:
"""Reproduce the inert camera/process residue left by archive failure."""
source_id = facade_module.DEFAULT_ACQUISITION_CAMERA_SOURCE
camera_state = dict(service.camera_preview.snapshot())
camera_state.update(
{
"phase": "error",
"generation": 17,
"active_source_id": source_id,
"delivery": None,
"error": {
"code": "segment-too-large",
"message": "synthetic terminal camera archive failure",
},
}
)
camera_state["recording"] = {
"active": False,
"source_end_expected": False,
"session": None,
"active_epoch": None,
"committed_media_segment_count": None,
"producer_alive": producer_alive,
"producer_age_ms": None,
"last_segment_age_ms": None,
"preview_consumer_count": 0,
"completed_epochs": 1,
"last_summary": None,
}
camera_gate = threading.RLock()
cleanup_calls: list[str] = []
def snapshot() -> dict[str, Any]:
with camera_gate:
copied = dict(camera_state)
copied["recording"] = dict(camera_state["recording"])
error = camera_state.get("error")
copied["error"] = dict(error) if isinstance(error, dict) else None
return copied
def stop_current() -> dict[str, Any]:
cleanup_calls.append("stop-current")
if cleanup_failure is not None:
raise cleanup_failure
with camera_gate:
camera_state.update(
{
"phase": "idle",
"generation": None,
"active_source_id": None,
"delivery": None,
"error": None,
}
)
return snapshot()
monkeypatch.setattr(service.camera_preview, "snapshot", snapshot)
monkeypatch.setattr(service.camera_preview, "stop_current", stop_current)
assert service._ensure_camera_preview_process_lease() is True # noqa: SLF001
with service._lock: # noqa: SLF001
service._live_perception_camera_binding = ( # noqa: SLF001
"camera-failed-session",
source_id,
17,
)
service._camera_activation_lineage = ( # noqa: SLF001
"acq-camera-failed",
"camera-failed-session",
0,
)
service._camera_activation_retry_lineage = ( # noqa: SLF001
"acq-camera-failed",
"camera-failed-session",
0,
)
service._camera_activation_retry_not_before_monotonic = 42.0 # noqa: SLF001
return cleanup_calls
def test_explicit_verify_reconciles_persisted_start_to_ready_without_device_io(
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
coordinator = _VerifyPhysicalRecoveryCoordinator(
observed_session_state="ready",
reconciliation_ready=True,
)
_install_synthetic_verify_recovery(service, coordinator)
operation_id = "op-00000000-0000-4000-8000-000000001201"
verify_state = asyncio.run(
service.verify_connection(
_retained_physical_recovery_verify_request(operation_id=operation_id)
)
)
state = service.state()
assert coordinator.reconciliation_ids == [f"{operation_id}.physical"]
assert state["physical_command"]["requires_reconciliation"] is False
assert state["physical_command"]["record"]["resolution"] == ("physical-standby-observed")
assert state["connection_lifecycle"]["mode_selection"]["allowed"] is True, state[
"connection_lifecycle"
]["mode_selection"]
assert verify_state["last_operation"]["status"] == "succeeded"
assert verify_state["last_operation"]["stage_code"] == ("physical-reconciliation-confirmed")
assert verify_state["last_operation"]["result"]["physical_reconciliation"] == {
"performed": True,
"resolution": "physical-standby-observed",
"observed_session_state": "ready",
"device_write_performed": False,
"automatic_retry": False,
}
assert service._application_control_process_lease_holders == {"control"} # noqa: SLF001
def test_long_first_verify_refreshes_aged_transport_before_exposing_prestart_control(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
"""A long checkpoint reconciliation cannot orphan its new ready socket."""
service, _ = service_with_fake_runtime(tmp_path)
coordinator = _VerifyPhysicalRecoveryCoordinator(
observed_session_state="ready",
reconciliation_ready=True,
)
_install_synthetic_verify_recovery(service, coordinator)
supervisor = service._connection_supervisor # noqa: SLF001
monotonic_now = [100.0]
suspend_aware_now = [1_000.0]
supervisor._monotonic_clock = lambda: monotonic_now[0] # noqa: SLF001
supervisor._suspend_aware_clock = lambda: suspend_aware_now[0] # noqa: SLF001
before = supervisor.snapshot()
assert before.intent is not None
assert before.device_network.target is not None
host_epoch = supervisor.observe_host_path(
_association_bound_direct_host_path(before.device_network.target.ipv4)
)
assert supervisor.observe_endpoint(
target=before.device_network.target,
intent_id=before.intent.intent_id,
host_path_epoch=host_epoch,
reachable=True,
)
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
tcp_probes: list[str] = []
def reachable(target: str) -> bool:
tcp_probes.append(target)
return True
monkeypatch.setattr(facade_module, "_control_endpoint_reachable", reachable)
reconcile = service._reconcile_physical_command_after_verify_owned # noqa: SLF001
async def reconcile_after_transport_ages(
bound_service: XgridsK1CompatibilityService,
*,
verify_operation_id: str,
allow_receiver_rehydrate: bool = True,
) -> dict[str, Any]:
result = await reconcile(
verify_operation_id=verify_operation_id,
allow_receiver_rehydrate=allow_receiver_rehydrate,
)
monotonic_now[0] += 20.0
suspend_aware_now[0] += 20.0
return result
service._reconcile_physical_command_after_verify_owned = MethodType( # type: ignore[method-assign] # noqa: SLF001
reconcile_after_transport_ages,
service,
)
operation_id = "op-00000000-0000-4000-8000-000000001202"
verified = asyncio.run(
service.verify_connection(
_retained_physical_recovery_verify_request(operation_id=operation_id)
)
)
assert tcp_probes == ["192.168.1.20"]
assert verified["last_operation"]["status"] == "succeeded"
assert verified["active_connection_mode"] == "bridge"
assert verified["connection_policy"]["actions"]["start-acquisition"]["allowed"] is True
assert service._application_control_session.snapshot()["state"] == "connection-ready" # noqa: SLF001
assert service._application_control_process_lease_holders == {"control"} # noqa: SLF001
fresh = supervisor.snapshot()
assert fresh.intent is not None
assert fresh.device_network.target is not None
assert supervisor.endpoint_observation_has_remaining_lease(
target=fresh.device_network.target,
intent_id=fresh.intent.intent_id,
host_path_epoch=fresh.host_path.epoch,
minimum_remaining_seconds=(
facade_module.VERIFY_POST_TRANSITION_ENDPOINT_MIN_REMAINING_SECONDS
),
)
def test_explicit_verify_reconciliation_does_not_require_normal_command_authority(
tmp_path: Path,
) -> None:
"""Fresh DeviceInfo/READY resolves the old edge before command authority exists."""
service, _ = service_with_fake_runtime(tmp_path)
coordinator = _VerifyPhysicalRecoveryCoordinator(
observed_session_state="ready",
reconciliation_ready=True,
)
_install_synthetic_verify_recovery(service, coordinator)
bootstrap = service._bootstrap_prestart_control_ready_owned # noqa: SLF001
reconciliation_validations: list[str] = []
async def bootstrap_with_command_authority_blocked(
bound_service: XgridsK1CompatibilityService,
*,
parent_operation_id: str | None,
connection_mode: facade_module.ConnectionMode,
inspection_only: bool = False,
) -> None:
await bootstrap(
parent_operation_id=parent_operation_id,
connection_mode=connection_mode,
inspection_only=inspection_only,
)
control = bound_service._application_control_session # noqa: SLF001
def reject_normal_command_authority() -> None:
raise RuntimeError("normal command authority remains blocked")
def accept_exact_read_only_reconciliation() -> None:
reconciliation_validations.append("read-only")
control.validate_connection_binding = reject_normal_command_authority # type: ignore[method-assign]
control.validate_physical_reconciliation_binding = ( # type: ignore[method-assign]
accept_exact_read_only_reconciliation
)
service._bootstrap_prestart_control_ready_owned = MethodType( # type: ignore[method-assign] # noqa: SLF001
bootstrap_with_command_authority_blocked,
service,
)
operation_id = "op-00000000-0000-4000-8000-000000001212"
result = asyncio.run(
service.verify_connection(
_retained_physical_recovery_verify_request(operation_id=operation_id)
)
)
assert reconciliation_validations == ["read-only", "read-only"]
assert result["last_operation"]["status"] == "succeeded"
assert result["physical_command"]["record"]["resolution"] == ("physical-standby-observed")
def test_explicit_verify_reconciliation_rechecks_binding_before_durable_commit(
tmp_path: Path,
) -> None:
"""A route/control change between proof and CAS leaves the ledger unresolved."""
service, _ = service_with_fake_runtime(tmp_path)
coordinator = _VerifyPhysicalRecoveryCoordinator(
observed_session_state="ready",
reconciliation_ready=True,
)
_install_synthetic_verify_recovery(service, coordinator)
bootstrap = service._bootstrap_prestart_control_ready_owned # noqa: SLF001
validation_count = 0
async def bootstrap_with_binding_change(
bound_service: XgridsK1CompatibilityService,
*,
parent_operation_id: str | None,
connection_mode: facade_module.ConnectionMode,
inspection_only: bool = False,
) -> None:
await bootstrap(
parent_operation_id=parent_operation_id,
connection_mode=connection_mode,
inspection_only=inspection_only,
)
control = bound_service._application_control_session # noqa: SLF001
def validate_until_commit() -> None:
nonlocal validation_count
validation_count += 1
if validation_count == 2:
raise RuntimeError("control generation changed before commit")
control.validate_physical_reconciliation_binding = ( # type: ignore[method-assign]
validate_until_commit
)
service._bootstrap_prestart_control_ready_owned = MethodType( # type: ignore[method-assign] # noqa: SLF001
bootstrap_with_binding_change,
service,
)
operation_id = "op-00000000-0000-4000-8000-000000001213"
with pytest.raises(facade_module.ConnectionVerificationError) as failure:
asyncio.run(
service.verify_connection(
_retained_physical_recovery_verify_request(operation_id=operation_id)
)
)
assert failure.value.reason_code == "physical-command-reconciliation-failed"
assert validation_count == 2
assert coordinator.reconciliation_ids == []
physical = coordinator.snapshot()
assert physical["requires_reconciliation"] is True
assert physical["record"]["resolution"] is None
operation = service.state()["last_operation"]
assert operation["operation_id"] == operation_id
assert operation["status"] == "failed"
def test_explicit_verify_reconciles_scanning_as_active_without_unblocking_mode_change(
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
coordinator = _VerifyPhysicalRecoveryCoordinator(
observed_session_state="scanning",
reconciliation_ready=True,
)
_install_synthetic_verify_recovery(service, coordinator)
state = asyncio.run(
service.verify_connection(
_retained_physical_recovery_verify_request(
operation_id="op-00000000-0000-4000-8000-000000001202"
)
)
)
assert state["physical_command"]["requires_reconciliation"] is False
assert state["physical_command"]["record"]["resolution"] == ("physical-active-observed")
assert state["connection_lifecycle"]["mode_selection"]["allowed"] is False
assert (
"connection-mode-selection-physical-state-unsafe"
in state["connection_lifecycle"]["mode_selection"]["reason_codes"]
)
assert (
"physical-device-already-active"
not in state["connection_policy"]["actions"]["scan-ble"]["reason_codes"]
)
assert (
"physical-device-already-active"
in state["connection_policy"]["actions"]["provision-fresh-device"]["reason_codes"]
)
assert state["acquisition"]["acquisition_id"] == "acq-persisted-start"
assert state["acquisition"]["state"] == "failed"
assert state["acquisition"]["cleanup_pending"] is False
assert state["acquisition"]["requested_streams"] == []
assert state["acquisition"]["result"]["recovery_only"] is True
assert state["acquisition"]["result"]["automatic_replay_allowed"] is False
assert state["application_control_session"]["can_stop"] is True
assert state["last_operation"]["result"]["physical_reconciliation"] == {
"performed": True,
"resolution": "physical-active-observed",
"observed_session_state": "scanning",
"device_write_performed": False,
"automatic_retry": False,
}
def test_explicit_verify_scanning_cleans_terminal_camera_residual_for_stop_only_shell(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
coordinator = _VerifyPhysicalRecoveryCoordinator(
observed_session_state="scanning",
reconciliation_ready=True,
)
_install_synthetic_verify_recovery(service, coordinator)
cleanup_calls = _install_terminal_camera_error_residual(service, monkeypatch)
operation_id = "op-00000000-0000-4000-8000-000000001214"
state = asyncio.run(
service.verify_connection(
_retained_physical_recovery_verify_request(operation_id=operation_id)
)
)
control = service._application_control_session # noqa: SLF001
assert isinstance(control, FakeInteractiveControlSession)
assert cleanup_calls == ["stop-current"]
assert coordinator.reconciliation_ids == [f"{operation_id}.physical"]
assert state["physical_command"]["record"]["resolution"] == (
"physical-active-observed"
)
assert state["acquisition"]["acquisition_id"] == "acq-persisted-start"
assert state["acquisition"]["state"] == "failed"
assert state["acquisition"]["result"]["recovery_only"] is True
assert state["application_control_session"]["can_stop"] is True
assert service.camera_preview.snapshot()["phase"] == "idle"
assert service._live_perception_camera_binding is None # noqa: SLF001
assert service._camera_activation_lineage is None # noqa: SLF001
assert service._camera_activation_retry_lineage is None # noqa: SLF001
assert service._camera_activation_retry_not_before_monotonic == 0.0 # noqa: SLF001
assert service._application_control_process_lease_holders == { # noqa: SLF001
"control"
}
assert control.start_projects == []
assert control.stop_calls == 0
assert runtime.start_calls == []
assert runtime.stop_calls == 0
def test_explicit_verify_scanning_camera_cleanup_failure_retains_fence(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
coordinator = _VerifyPhysicalRecoveryCoordinator(
observed_session_state="scanning",
reconciliation_ready=True,
)
_install_synthetic_verify_recovery(service, coordinator)
cleanup_calls = _install_terminal_camera_error_residual(
service,
monkeypatch,
cleanup_failure=RuntimeError("synthetic terminal camera cleanup failed"),
)
operation_id = "op-00000000-0000-4000-8000-000000001215"
with pytest.raises(facade_module.ConnectionVerificationError) as failure:
asyncio.run(
service.verify_connection(
_retained_physical_recovery_verify_request(operation_id=operation_id)
)
)
state = service.state()
control = service._application_control_session # noqa: SLF001
assert isinstance(control, FakeInteractiveControlSession)
assert failure.value.reason_code == "physical-command-reconciliation-failed"
assert cleanup_calls == ["stop-current"]
assert coordinator.reconciliation_ids == [f"{operation_id}.physical"]
assert state["physical_command"]["record"]["resolution"] == (
"physical-active-observed"
)
assert state["acquisition"] is None
assert state["last_operation"]["operation_id"] == operation_id
assert state["last_operation"]["status"] == "failed"
assert service.camera_preview.snapshot()["phase"] == "error"
assert service._live_perception_camera_binding is not None # noqa: SLF001
assert service._camera_activation_lineage is not None # noqa: SLF001
assert service._camera_activation_retry_lineage is not None # noqa: SLF001
assert service._application_control_process_lease_holders == { # noqa: SLF001
"camera"
}
assert control.start_projects == []
assert control.stop_calls == 0
assert runtime.start_calls == []
assert runtime.stop_calls == 0
def test_explicit_verify_scanning_refuses_to_cleanup_live_camera_producer(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
coordinator = _VerifyPhysicalRecoveryCoordinator(
observed_session_state="scanning",
reconciliation_ready=True,
)
_install_synthetic_verify_recovery(service, coordinator)
cleanup_calls = _install_terminal_camera_error_residual(
service,
monkeypatch,
producer_alive=True,
)
operation_id = "op-00000000-0000-4000-8000-000000001216"
with pytest.raises(facade_module.ConnectionVerificationError) as failure:
asyncio.run(
service.verify_connection(
_retained_physical_recovery_verify_request(operation_id=operation_id)
)
)
control = service._application_control_session # noqa: SLF001
assert isinstance(control, FakeInteractiveControlSession)
assert failure.value.reason_code == "physical-command-reconciliation-failed"
assert cleanup_calls == []
assert service._acquisition is None # noqa: SLF001
assert service.camera_preview.snapshot()["recording"]["producer_alive"] is True
assert service._application_control_process_lease_holders == { # noqa: SLF001
"camera"
}
assert control.start_projects == []
assert control.stop_calls == 0
assert runtime.start_calls == []
assert runtime.stop_calls == 0
def test_fresh_service_real_verify_rotation_rehydrates_one_stop_only_target(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
original, _ = service_with_fake_runtime(tmp_path)
_persist_resolved_active_start_for_restart(original)
assert original._acquisition is None # noqa: SLF001
# A genuinely fresh facade starts with no process-local acquisition. Its
# only physical authority is the persisted resolved-active START record.
restarted, _ = service_with_fake_runtime(tmp_path)
assert restarted._acquisition is None # noqa: SLF001
assert restarted.state()["physical_command"]["resolved_active_recovery_required"] is True
_set_scanned_k1(restarted, device_id="test-ble-transport")
async def read_status(
device_id: str,
*,
timeout_seconds: float,
rediscover: bool,
**_: object,
) -> dict[str, Any]:
assert (device_id, timeout_seconds, rediscover) == (
"test-ble-transport",
20.0,
False,
)
return _wifi_status_read("10.255.254.77", device_id=device_id)
monkeypatch.setattr(facade_module, "read_wifi_status_once", read_status)
monkeypatch.setattr(facade_module, "_target_is_local_ipv4", lambda _target: False)
monkeypatch.setattr(facade_module, "_host_route_class", lambda _target: "direct-or-routed")
monkeypatch.setattr(facade_module, "_control_endpoint_reachable", lambda _target: True)
monkeypatch.setattr(facade_module, "_inspect_host_path", _direct_host_path)
coordinator = restarted._physical_command_coordinator # noqa: SLF001
published_physical_edges: list[str] = []
async def bootstrap_recovery_control(
bound_service: XgridsK1CompatibilityService,
*,
parent_operation_id: str | None,
connection_mode: facade_module.ConnectionMode,
inspection_only: bool = False,
) -> None:
await _synthetic_prestart_control_bootstrap(
bound_service,
parent_operation_id=parent_operation_id,
connection_mode=connection_mode,
inspection_only=inspection_only,
)
control = bound_service._application_control_session # noqa: SLF001
verified = control.snapshot().get("verified_control")
assert isinstance(verified, dict)
coordinator.application_response(
ApplicationMqttResponseEvidence(
operation_key="bootstrap:1:DeviceInfoRequest",
response_topic="lixel/application/response/device_info",
payload_sha256="f" * 64,
modeling_action=None,
result_code=None,
success=None,
observed_at_utc="2026-08-09T12:10:00.000Z",
)
)
coordinator.bind_control_session(
PhysicalCommandRuntimeBinding(
vendor_device_id_sha256=_RECOVERY_VENDOR_HASH,
device_serial_sha256=_RECOVERY_SERIAL_HASH,
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
intent_id=str(verified["intent_id"]),
transport_ref=str(verified["transport_ref"]),
connection_mode=verified["connection_mode"], # type: ignore[arg-type]
target_ipv4=str(verified["target_ipv4"]),
target_port=int(verified["target_port"]),
host_path_epoch=int(verified["host_path_epoch"]),
control_session_id=str(verified["control_session_id"]),
producer_generation=int(verified["producer_generation"]),
)
)
coordinator.device_status(
ApplicationMqttDeviceStatusEvidence(
vendor_device_id_sha256=_RECOVERY_VENDOR_HASH,
device_serial_sha256=_RECOVERY_SERIAL_HASH,
session_state="scanning",
session_state_code=MODELING_STATE_BASE + 302,
project_bound=True,
project_id_sha256=_RECOVERY_PROJECT_HASH,
init_ready=True,
status_message_sha256="1" * 64,
mqtt_retained=False,
observed_at_utc="2026-08-09T12:10:01.000Z",
)
)
original_request_stop = control.request_stop
def request_stop_with_durable_edge(
*,
confirmation: object,
command_context: object,
dispatch_admission_deadline_reached: Callable[[], bool] | None = None,
expected_session_generation: int | None = None,
expected_state_revision: int | None = None,
) -> dict[str, object]:
assert dispatch_admission_deadline_reached is not None
payload = b"recovered-stop"
coordinator.prepare(
command_context, # type: ignore[arg-type]
action="stop",
envelope=OneShotPublishEnvelope(
operation_key="modeling:stop",
topic="lixel/application/request/modeling",
payload=payload,
payload_sha256=hashlib.sha256(payload).hexdigest(),
payload_bytes=len(payload),
qos=2,
retain=False,
),
)
published_physical_edges.append("stop")
return original_request_stop(
confirmation=confirmation,
command_context=command_context,
dispatch_admission_deadline_reached=(
dispatch_admission_deadline_reached
),
expected_session_generation=expected_session_generation,
expected_state_revision=expected_state_revision,
)
control.request_stop = request_stop_with_durable_edge # type: ignore[method-assign]
bound_service._acquire_application_control_process_lease() # noqa: SLF001
restarted._bootstrap_prestart_control_ready_owned = MethodType( # type: ignore[method-assign] # noqa: SLF001
bootstrap_recovery_control,
restarted,
)
verify_operation_id = "op-00000000-0000-4000-8000-000000001230"
verified = asyncio.run(
restarted.verify_connection(
ConnectionVerifyRequest(
device_id="test-ble-transport",
compatibility_attestation=ATTESTATION,
operation_id=verify_operation_id,
expected_discovery_generation=0,
)
)
)
acquisition = verified["acquisition"]
assert acquisition["acquisition_id"] == _RECOVERY_ACQUISITION_ID
assert acquisition["device_session_id"] == verified["device_session"]["device_session_id"]
assert acquisition["state"] == "failed"
assert acquisition["cleanup_pending"] is False
assert acquisition["requested_streams"] == []
assert acquisition["project_name"] is None
assert acquisition["result"] == {
"receiver_stopped": True,
"device_state": "scanning",
"recovery_only": True,
"physical_command_operation_id": _RECOVERY_START_OPERATION_ID,
"physical_reconciliation_id": f"{verify_operation_id}.physical",
"project_id_sha256": _RECOVERY_PROJECT_HASH,
"automatic_replay_allowed": False,
}
assert verified["application_control_session"]["state"] == "scanning"
assert verified["application_control_session"]["can_stop"] is True
assert published_physical_edges == []
control = restarted._application_control_session # noqa: SLF001
control_snapshot = control.snapshot()
with pytest.raises(RuntimeError, match="ожидать сохранения проекта"):
restarted.prepare_acquisition(
_prepare_request(
project_name="must-not-prepare",
compatibility_attestation=ATTESTATION,
expected_control_session_generation=control_snapshot["session_generation"],
expected_control_state_revision=control_snapshot["state_revision"],
)
)
with pytest.raises(RuntimeError, match="ещё не готов принять START"):
restarted.start_acquisition(
_start_request(
acquisition_id=_RECOVERY_ACQUISITION_ID,
expected_state_revision=acquisition["state_revision"],
physical_acceptance=PHYSICAL_ACCEPTANCE,
expected_control_session_generation=control_snapshot["session_generation"],
expected_control_state_revision=control_snapshot["state_revision"],
)
)
assert published_physical_edges == []
stop_operation_id = "op-00000000-0000-4000-8000-000000001231"
stop_request = _stop_request(
acquisition_id=_RECOVERY_ACQUISITION_ID,
operation_id=stop_operation_id,
idempotency_key="recovered-stop-once",
mode="graceful",
expected_control_session_generation=control_snapshot["session_generation"],
expected_control_state_revision=control_snapshot["state_revision"],
physical_acceptance=PHYSICAL_ACCEPTANCE,
)
stopped = restarted.stop_acquisition(stop_request)
assert stopped["acquisition"]["result"]["recovery_only"] is True
assert published_physical_edges == ["stop"]
repeated = restarted.stop_acquisition(stop_request)
assert repeated["last_operation"]["operation_id"] == stop_operation_id
assert published_physical_edges == ["stop"]
payload_hash = hashlib.sha256(b"recovered-stop").hexdigest()
dispatch = ApplicationMqttPublishEvidence(
operation_key="modeling:stop",
topic="lixel/application/request/modeling",
payload_sha256=payload_hash,
qos=2,
retain=False,
packet_id=None,
)
coordinator.publish_dispatching(dispatch)
returned = ApplicationMqttPublishEvidence(
operation_key="modeling:stop",
topic="lixel/application/request/modeling",
payload_sha256=payload_hash,
qos=2,
retain=False,
packet_id=42,
)
coordinator.publish_result(returned, publish_call_returned=True)
coordinator.qos2_completed(returned)
coordinator.application_response(
ApplicationMqttResponseEvidence(
operation_key="modeling:stop",
response_topic="lixel/application/response/modeling",
payload_sha256="2" * 64,
modeling_action="stop",
result_code=PHYSICAL_COMMAND_APPLICATION_SUCCESS_CODE,
success=True,
observed_at_utc="2026-08-09T12:10:02.000Z",
)
)
coordinator.device_status(
ApplicationMqttDeviceStatusEvidence(
vendor_device_id_sha256=_RECOVERY_VENDOR_HASH,
device_serial_sha256=_RECOVERY_SERIAL_HASH,
session_state="ready",
session_state_code=MODELING_STATE_BASE + 300,
project_bound=False,
project_id_sha256=None,
init_ready=False,
status_message_sha256="3" * 64,
mqtt_retained=False,
observed_at_utc="2026-08-09T12:10:03.000Z",
)
)
coordinator.resolve("stop")
control.state = "completed"
ready = restarted.state()
assert ready["physical_command"]["record"]["resolution"] == "stop-standby-observed"
assert ready["physical_command"]["resolved_active_recovery_required"] is False
assert ready["connection_lifecycle"]["mode_selection"]["allowed"] is True
terminal_stop = next(
operation
for operation in ready["operations"]
if operation["operation_id"] == stop_operation_id
)
assert terminal_stop["status"] == "succeeded"
assert published_physical_edges == ["stop"]
def test_active_reconciliation_survives_post_commit_adoption_failure_and_next_ready_verify(
tmp_path: Path,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
coordinator = _VerifyPhysicalRecoveryCoordinator(
observed_session_state="scanning",
reconciliation_ready=True,
)
_install_synthetic_verify_recovery(service, coordinator)
bootstrap_attempts = 0
async def bootstrap_with_first_adoption_failure(
bound_service: XgridsK1CompatibilityService,
*,
parent_operation_id: str | None,
connection_mode: facade_module.ConnectionMode,
inspection_only: bool = False,
) -> None:
nonlocal bootstrap_attempts
bootstrap_attempts += 1
await _synthetic_prestart_control_bootstrap(
bound_service,
parent_operation_id=parent_operation_id,
connection_mode=connection_mode,
inspection_only=inspection_only,
)
bound_service._acquire_application_control_process_lease() # noqa: SLF001
if bootstrap_attempts == 1:
control = bound_service._application_control_session # noqa: SLF001
def fail_after_durable_commit(*_args: object, **_kwargs: object) -> None:
raise RuntimeError("synthetic adoption loss after ledger commit")
control.adopt_reconciled_scanning = fail_after_durable_commit # type: ignore[method-assign]
service._bootstrap_prestart_control_ready_owned = MethodType( # type: ignore[method-assign] # noqa: SLF001
bootstrap_with_first_adoption_failure,
service,
)
first_operation = "op-00000000-0000-4000-8000-000000001210"
with pytest.raises(facade_module.ConnectionVerificationError):
asyncio.run(
service.verify_connection(
_retained_physical_recovery_verify_request(operation_id=first_operation)
)
)
after_failure = service.state()
assert coordinator.resolution == "physical-active-observed"
assert after_failure["physical_command"]["resolved_active_recovery_required"] is True
assert after_failure["application_control_session"]["state"] == "idle"
mutation_reasons = after_failure["connection_policy"]["actions"][
"provision-fresh-device"
]["reason_codes"]
assert "physical-command-reconciliation-required" in mutation_reasons
assert "physical-device-already-active" in mutation_reasons
assert after_failure["connection_policy"]["actions"]["verify-control-device-info"][
"allowed"
] is True
coordinator.observed_session_state = "ready"
second_operation = "op-00000000-0000-4000-8000-000000001211"
verify_result = asyncio.run(
service.verify_connection(
_retained_physical_recovery_verify_request(operation_id=second_operation)
)
)
recovered = service.state()
assert coordinator.reconciliation_ids == [
f"{first_operation}.physical",
f"{second_operation}.physical",
]
assert coordinator.resolution == "physical-standby-observed"
assert verify_result["last_operation"]["status"] == "succeeded"
assert recovered["physical_command"]["resolved_active_recovery_required"] is False
assert recovered["physical_command"]["requires_reconciliation"] is False
assert recovered["connection_lifecycle"]["mode_selection"]["allowed"] is True, recovered[
"connection_lifecycle"
]["mode_selection"]
@pytest.mark.parametrize(
("proof_kind", "observed_session_state"),
[
("missing-status", None),
("retained-status", "ready"),
("stale-device-info", None),
],
)
def test_explicit_verify_fails_closed_without_fresh_physical_recovery_proof(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
proof_kind: str,
observed_session_state: str | None,
) -> None:
del proof_kind
service, _ = service_with_fake_runtime(tmp_path)
coordinator = _VerifyPhysicalRecoveryCoordinator(
observed_session_state=observed_session_state,
reconciliation_ready=False,
)
_install_synthetic_verify_recovery(service, coordinator)
monkeypatch.setattr(
facade_module,
"PHYSICAL_RECONCILIATION_PROOF_TIMEOUT_SECONDS",
0.0,
)
operation_id = "op-00000000-0000-4000-8000-000000001203"
with pytest.raises(facade_module.ConnectionVerificationError) as raised:
asyncio.run(
service.verify_connection(
_retained_physical_recovery_verify_request(operation_id=operation_id)
)
)
assert raised.value.reason_code == "physical-command-reconciliation-proof-timeout"
assert coordinator.reconciliation_ids == []
state = service.state()
operation = next(item for item in state["operations"] if item["operation_id"] == operation_id)
assert operation["status"] == "failed"
assert operation["stage_code"] == "physical-reconciliation-failed"
assert operation["error"]["code"] == ("physical-command-reconciliation-proof-timeout")
assert operation["error"]["safe_to_retry"] is True
assert operation["error"]["side_effect_status"] == "none"
assert state["application_control_session"]["state"] == "idle"
assert service._application_control_process_lease_holders == set() # noqa: SLF001
assert state["connection_policy"]["actions"]["verify-control-device-info"]["allowed"] is True
def test_bootstrap_identity_rejection_retires_only_session_opened_by_attempt(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
"""Rejected DeviceInfo cannot leak a ready socket or process lease."""
service, _ = service_with_fake_runtime(tmp_path)
control = FakeInteractiveControlSession(initial_state="idle")
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
_seed_supervised_connection(
service,
connection_mode="bridge",
transport_ref="k1-a",
with_control=False,
)
physical_edges: list[str] = []
def reject_identity(**_: object) -> None:
raise DeviceIdentityPinStoreCorrupt("synthetic DeviceInfo pin rejection")
monkeypatch.setattr(service, "_pin_or_match_device_identity", reject_identity)
monkeypatch.setattr(
service._physical_command_coordinator, # noqa: SLF001
"prepare",
lambda *_args, **_kwargs: physical_edges.append("physical-command"),
)
with pytest.raises(facade_module.ConnectionVerificationError) as rejected:
asyncio.run(
XgridsK1CompatibilityService._bootstrap_prestart_control_ready_owned( # noqa: SLF001
service,
parent_operation_id=None,
connection_mode="bridge",
)
)
assert rejected.value.reason_code == "control-bootstrap-device-identity-unverified"
assert physical_edges == []
state = service.state()
assert state["application_control_session"]["state"] == "idle"
assert service._application_control_process_lease_holders == set() # noqa: SLF001
assert state["active_connection_mode"] is None
assert state["connection_policy"]["actions"]["scan-ble"]["allowed"] is True
assert state["connection_policy"]["actions"]["verify-control-device-info"]["allowed"] is True
@pytest.mark.parametrize("inspection_only", [True, False], ids=["verify", "ordinary"])
def test_read_only_bootstrap_detaches_physical_observer_before_fresh_control_open(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
inspection_only: bool,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
control = FakeInteractiveControlSession(initial_state="idle")
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
_seed_supervised_connection(
service,
connection_mode="bridge",
transport_ref="k1-a",
with_control=False,
)
ordering: list[str] = []
def detach_before_read_only_open() -> None:
ordering.append("physical-observer-detached")
monkeypatch.setattr(
service._physical_command_coordinator, # noqa: SLF001
"prepare_read_only_bootstrap",
detach_before_read_only_open,
)
original_open = control.open
def open_after_detach(
*,
connection_binding: ApplicationConnectionBinding,
**kwargs: object,
) -> dict[str, object]:
if inspection_only:
assert ordering == ["physical-observer-detached"]
else:
assert ordering == []
ordering.append("fresh-control-observer-opened")
return original_open(connection_binding=connection_binding, **kwargs)
monkeypatch.setattr(control, "open", open_after_detach)
asyncio.run(
XgridsK1CompatibilityService._bootstrap_prestart_control_ready_owned( # noqa: SLF001
service,
parent_operation_id=None,
connection_mode="bridge",
inspection_only=inspection_only,
)
)
assert ordering == (
["physical-observer-detached", "fresh-control-observer-opened"]
if inspection_only
else ["fresh-control-observer-opened"]
)
assert control.state == "connection-ready"
def test_polling_self_cleans_prepared_acquisition_after_proven_prestart_failure(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
"""A battery/control loss before START recovers without refresh or ABORT."""
service, runtime = service_with_fake_runtime(tmp_path)
_select_connection_mode(service, "quick-connect")
class TerminalPrestartControl(FakeInteractiveControlSession):
failure: dict[str, object] | None = None
def snapshot(self) -> dict[str, object]:
snapshot = super().snapshot()
snapshot["failure"] = self.failure
return snapshot
control = TerminalPrestartControl()
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
binding = _seed_supervised_connection(
service,
target_ipv4=facade_module.AP_FALLBACK_IPV4,
connection_mode="quick-connect",
transport_ref="k1-a",
)
control.verified_control = _verified_control_for_binding(binding)
prepared = service.prepare_acquisition(
_prepare_request(
project_name="TEST001",
host=facade_module.AP_FALLBACK_IPV4,
compatibility_attestation=QUICK_CONNECT_ATTESTATION,
)
)
assert prepared["acquisition"]["state"] == "prepared"
service._acquire_application_control_process_lease() # noqa: SLF001
physical_or_network_edges: list[str] = []
monkeypatch.setattr(
service._physical_command_coordinator, # noqa: SLF001
"prepare",
lambda *_args, **_kwargs: physical_or_network_edges.append("physical-command"),
)
async def forbidden_device_write(*_: object, **__: object) -> dict[str, Any]:
physical_or_network_edges.append("network-write")
raise AssertionError("polling recovery must remain read/local-only")
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_device_write)
control.state = "failed"
control.failure = {
"reason_code": "mqtt_network_loop_failed",
"modeling_command_attempted": False,
"safe_to_retry": True,
"network_change_admissible": True,
}
recovered = service.state()
assert physical_or_network_edges == []
assert runtime.start_calls == []
assert runtime.stop_calls == 0
assert recovered["acquisition"]["state"] == "aborted"
assert recovered["acquisition"]["result"] == {
"receiver_started": False,
"device_command_attempted": False,
"reason_code": "prestart-control-terminal-failure",
}
assert recovered["application_control_session"]["state"] == "idle"
assert service._application_control_process_lease_holders == set() # noqa: SLF001
assert recovered["connection_policy"]["actions"]["scan-ble"]["allowed"] is True
@pytest.mark.parametrize("observed_session_state", ["ready", "scanning"])
def test_verify_classification_settles_original_prepared_stop_as_not_dispatched(
tmp_path: Path,
observed_session_state: str,
) -> None:
service, _ = service_with_fake_runtime(tmp_path)
original_stop_operation_id = "op-00000000-0000-4000-8000-000000001409"
operation, created = service._operations.begin( # noqa: SLF001
facade_module.ACTION_ACQUISITION_STOP,
operation_id=original_stop_operation_id,
device_id="known-k1",
device_session_id="old-stop-session",
deadline_seconds=60.0,
idempotency_key="old-prepared-stop",
)
assert created is True
service._operations.transition( # noqa: SLF001
operation.operation_id,
"running",
stage_code="awaiting-external-stop",
message_code="acquisition.stop.device_stopping",
)
coordinator = _VerifyPhysicalRecoveryCoordinator(
observed_session_state=observed_session_state,
reconciliation_ready=True,
prepared_stop_operation_id=original_stop_operation_id,
)
_install_synthetic_verify_recovery(service, coordinator)
verify_operation_id = "op-00000000-0000-4000-8000-000000001410"
verified = asyncio.run(
service.verify_connection(
_retained_physical_recovery_verify_request(operation_id=verify_operation_id)
)
)
original = service._operations.get(original_stop_operation_id) # noqa: SLF001
assert original.status == "failed"
assert original.stage_code == "physical-stop-classified-not-dispatched"
assert original.error == {
"category": "device",
"code": "physical-stop-not-dispatched",
"retryable": False,
"safe_to_retry": False,
"side_effect_status": "none",
"physical_command_sent": False,
"automatic_replay_allowed": False,
}
assert coordinator._resolved_record(f"{verify_operation_id}.physical")["resolution"] == ( # noqa: SLF001
"not-dispatched"
)
if observed_session_state == "scanning":
assert verified["acquisition"]["result"]["physical_command_operation_id"] == (
original_stop_operation_id
)
assert verified["application_control_session"]["can_stop"] is True
else:
assert verified["application_control_session"]["can_stop"] is False
acquisition = verified.get("acquisition")
assert not (
isinstance(acquisition, dict)
and isinstance(acquisition.get("result"), dict)
and acquisition["result"].get("recovery_only") is True
)
@pytest.mark.parametrize("observed_session_state", ["ready", "scanning"])
def test_public_verify_reconciles_fresh_service_resolved_unclassified_stop_without_writes(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
observed_session_state: str,
) -> None:
original, _ = service_with_fake_runtime(tmp_path)
stop_operation_id, compatibility_revision = (
_persist_resolved_unclassified_stop_for_restart(original)
)
restarted, runtime = service_with_fake_runtime(tmp_path)
before = restarted._physical_command_ledger.snapshot().record # noqa: SLF001
assert before is not None
assert before.operation_id == stop_operation_id
assert before.revision == compatibility_revision
assert before.stage == "resolved"
assert before.resolution == "not-dispatched"
assert before.resolved_unclassified_stop_recovery_required is True
assert restarted._acquisition is None # noqa: SLF001
forbidden_io: list[str] = []
async def forbid_device_io(*_args: object, **_kwargs: object) -> object:
forbidden_io.append("device-io")
raise AssertionError("resolved STOP Verify must stay read-only")
monkeypatch.setattr(facade_module, "read_wifi_status_once", forbid_device_io)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbid_device_io)
_install_real_coordinator_verify_recovery(
restarted,
observed_session_state=observed_session_state,
)
verify_operation_id = "op-00000000-0000-4000-8000-000000001411"
verified = asyncio.run(
restarted.verify_connection(
_retained_physical_recovery_verify_request(
operation_id=verify_operation_id,
)
)
)
after = restarted._physical_command_ledger.snapshot().record # noqa: SLF001
assert after is not None
assert after.operation_id == stop_operation_id
assert after.revision == compatibility_revision + 1
assert after.stage == "resolved"
assert after.resolution == "not-dispatched"
assert after.resolved_unclassified_stop_recovery_required is False
classification = after.reconciliations[-1]
assert classification.kind == "prepared-stop-classification"
assert classification.original_attempt.stage == "resolved"
assert classification.original_attempt.resolution == "not-dispatched"
assert classification.resolution == (
"physical-active-observed"
if observed_session_state == "scanning"
else "physical-standby-observed"
)
assert verified["last_operation"]["operation_id"] == verify_operation_id
assert verified["last_operation"]["status"] == "succeeded"
assert verified["last_operation"]["result"]["write_performed"] is False
assert verified["last_operation"]["result"]["physical_reconciliation"] == {
"performed": True,
"resolution": classification.resolution,
"observed_session_state": observed_session_state,
"device_write_performed": False,
"automatic_retry": False,
}
control = restarted._application_control_session # noqa: SLF001
assert isinstance(control, FakeInteractiveControlSession)
assert control.start_projects == []
assert control.stop_calls == 0
assert runtime.start_calls == []
assert runtime.stop_calls == 0
assert forbidden_io == []
if observed_session_state == "ready":
assert verified.get("acquisition") is None
assert verified["application_control_session"]["state"] == "connection-ready"
assert verified["application_control_session"]["can_stop"] is False
assert verified["connection_policy"]["actions"]["start-acquisition"][
"allowed"
] is True
assert "physical-command-reconciliation-required" not in verified[
"connection_policy"
]["actions"]["start-acquisition"]["reason_codes"]
assert verified["connection_lifecycle"]["mode_selection"]["allowed"] is False
with pytest.raises(facade_module.NetworkProvisioningConflict) as mutation:
restarted._require_physical_command_network_mutation_allowed() # noqa: SLF001
assert mutation.value.reason_code == "physical-command-reconciliation-required"
else:
assert verified["application_control_session"]["state"] == "scanning"
assert verified["application_control_session"]["can_stop"] is True
assert verified["acquisition"]["result"]["recovery_only"] is True
assert verified["acquisition"]["result"]["physical_command_operation_id"] == (
stop_operation_id
)
assert verified["connection_policy"]["actions"]["start-acquisition"][
"allowed"
] is False
assert verified["connection_policy"]["actions"]["stop-acquisition"][
"allowed"
] is True
def test_restart_classified_ready_uses_fresh_live_binding_for_one_start(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
"""C1 proves historical standby; fresh DeviceInfo + live READY on C2 owns START."""
original, _ = service_with_fake_runtime(tmp_path)
stop_operation_id, c1 = _persist_classified_ready_stop_for_restart(original)
classified = original._physical_command_ledger.snapshot().record # noqa: SLF001
assert classified is not None
assert classified.operation_id == stop_operation_id
assert classified.reconciliations[-1].verified_binding.connection == c1
restarted, runtime = service_with_fake_runtime(tmp_path)
binding = _seed_supervised_connection(
restarted,
target_ipv4="192.168.68.52",
connection_mode="bridge",
transport_ref="test-ble-transport",
logical_device_id="known-k1",
)
stable_path = _direct_host_path(binding.target_ipv4)
monkeypatch.setattr(
restarted,
"_sample_host_path",
lambda *_args, **_kwargs: stable_path,
)
control = _BindingValidatingControlSession(restarted, binding)
control.open(connection_binding=binding)
control.verified_control = _verified_control_for_binding(
binding,
logical_device_id="known-k1",
control_session_id="fresh-live-c2-control",
control_proof_revision=2,
)
restarted._application_control_session = control # type: ignore[assignment] # noqa: SLF001
restarted._reconcile_connection_supervisor( # noqa: SLF001
control.snapshot(),
runtime.snapshot(),
)
restarted._acquire_application_control_process_lease() # noqa: SLF001
coordinator = restarted._physical_command_coordinator # noqa: SLF001
observed_at_utc = datetime.now(UTC).isoformat(timespec="milliseconds").replace(
"+00:00",
"Z",
)
coordinator.application_response(
ApplicationMqttResponseEvidence(
operation_key="bootstrap:fresh-live-c2:DeviceInfoRequest",
response_topic="lixel/application/response/device_info",
payload_sha256="6" * 64,
modeling_action=None,
result_code=None,
success=None,
observed_at_utc=observed_at_utc,
)
)
verified = control.verified_control
assert verified is not None
c2 = PhysicalCommandRuntimeBinding(
vendor_device_id_sha256=_RECOVERY_VENDOR_HASH,
device_serial_sha256=_RECOVERY_SERIAL_HASH,
compatibility_profile_id=XGRIDS_K1_COMPATIBILITY_PROFILE_ID,
intent_id=str(verified["intent_id"]),
transport_ref=str(verified["transport_ref"]),
connection_mode=verified["connection_mode"], # type: ignore[arg-type]
target_ipv4=str(verified["target_ipv4"]),
target_port=int(verified["target_port"]),
host_path_epoch=int(verified["host_path_epoch"]),
control_session_id=str(verified["control_session_id"]),
producer_generation=int(verified["producer_generation"]),
)
assert c2.control_session_id != c1.control_session_id
coordinator.bind_control_session(c2)
coordinator.device_status(
ApplicationMqttDeviceStatusEvidence(
vendor_device_id_sha256=_RECOVERY_VENDOR_HASH,
device_serial_sha256=_RECOVERY_SERIAL_HASH,
session_state="ready",
session_state_code=MODELING_STATE_BASE + 300,
project_bound=False,
project_id_sha256=None,
init_ready=False,
status_message_sha256="7" * 64,
mqtt_retained=False,
observed_at_utc=observed_at_utc,
)
)
inherited_reconciliations = classified.reconciliations
ready = restarted.state()
workspace = restarted.enter_application_workspace(
EnterApplicationWorkspaceRequest(
operator_confirmed=True,
expected_session_generation=ready["application_control_session"][
"session_generation"
],
expected_state_revision=ready["application_control_session"]["state_revision"],
)
)
prepared = restarted.prepare_acquisition(
_prepare_request(
project_name="RESTART_READY_C2",
host=binding.target_ipv4,
compatibility_attestation=ATTESTATION,
expected_control_session_generation=workspace["application_control_session"][
"session_generation"
],
expected_control_state_revision=workspace["application_control_session"][
"state_revision"
],
)
)
before_start = restarted._physical_command_ledger.snapshot().record # noqa: SLF001
assert before_start == classified
assert before_start.reconciliations == inherited_reconciliations
prepared_edges: list[str] = []
original_request_start = control.request_start
def request_start_with_durable_edge(
*,
project_name: str,
confirmation: object,
command_context: object,
preparation_checkpoint_observer: object | None = None,
expected_session_generation: int | None = None,
expected_state_revision: int | None = None,
) -> dict[str, object]:
payload = b"fresh-start-on-c2"
coordinator.prepare(
command_context, # type: ignore[arg-type]
action="start",
envelope=OneShotPublishEnvelope(
operation_key="modeling:start",
topic="lixel/application/request/modeling",
payload=payload,
payload_sha256=hashlib.sha256(payload).hexdigest(),
payload_bytes=len(payload),
qos=2,
retain=False,
),
)
prepared_edges.append("start")
return original_request_start(
project_name=project_name,
confirmation=confirmation,
command_context=command_context,
preparation_checkpoint_observer=preparation_checkpoint_observer,
expected_session_generation=expected_session_generation,
expected_state_revision=expected_state_revision,
)
control.request_start = request_start_with_durable_edge # type: ignore[method-assign]
start_operation_id = "op-00000000-0000-4000-8000-000000001412"
started = restarted.start_acquisition(
_start_request(
acquisition_id=prepared["acquisition"]["acquisition_id"],
operation_id=start_operation_id,
physical_acceptance=PHYSICAL_ACCEPTANCE,
expected_control_session_generation=prepared["application_control_session"][
"session_generation"
],
expected_control_state_revision=prepared["application_control_session"][
"state_revision"
],
)
)
successor = restarted._physical_command_ledger.snapshot().record # noqa: SLF001
assert successor is not None
assert successor.operation_id == start_operation_id
assert successor.parent_operation_id == stop_operation_id
assert successor.action == "start"
assert successor.stage == "prepared"
assert successor.connection.control_session_id == c2.control_session_id
assert successor.connection.host_path_epoch == c2.host_path_epoch
assert successor.connection.producer_generation == c2.producer_generation
assert successor.baseline_status.control_session_id == c2.control_session_id
assert successor.reconciliations == inherited_reconciliations
assert prepared_edges == ["start"]
assert control.start_projects == ["RESTART_READY_C2"]
assert len(runtime.start_calls) == 1
assert started["acquisition"]["state"] == "starting"
def test_recovered_terminal_stop_losing_wifi_stays_acknowledged_unconfirmed_and_never_replays(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
service, runtime = service_with_fake_runtime(tmp_path)
class TerminalStopControl(FakeInteractiveControlSession):
failure: dict[str, object] | None = None
def snapshot(self) -> dict[str, object]:
snapshot = super().snapshot()
snapshot["failure"] = self.failure
return snapshot
control = TerminalStopControl(initial_state="workspace-ready")
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
binding = _seed_supervised_connection(
service,
connection_mode="bridge",
transport_ref="k1-a",
)
control.verified_control = _verified_control_for_binding(binding)
prepared = service.prepare_acquisition(
_prepare_request(
project_name="RECOVERED_STOP",
host="192.168.1.20",
compatibility_attestation=ATTESTATION,
)
)
acquisition_id = prepared["acquisition"]["acquisition_id"]
service.start_acquisition(
_start_request(
acquisition_id=acquisition_id,
physical_acceptance=PHYSICAL_ACCEPTANCE,
)
)
start_operation_id = service._acquisition_start_operation_id # noqa: SLF001
assert isinstance(start_operation_id, str)
monkeypatch.setattr(
service._physical_command_coordinator, # noqa: SLF001
"snapshot",
lambda: _exact_start_physical_proof(
operation_id=start_operation_id,
acquisition_id=acquisition_id,
binding=binding,
resolved=True,
),
)
runtime.mark_ready()
runtime.pcl_frames = 1
acquiring = service.state()
assert acquiring["acquisition"]["state"] == "acquiring"
# Model the already-sealed local half after power loss. A later read-only
# Verify has adopted SCANNING, so the terminal acquisition exposes one
# explicit canonical STOP without restarting the receiver or capture.
service._stop_acquisition_sources( # noqa: SLF001
camera_status="failed",
camera_failure_code="power-loss-before-recovery-stop",
)
with service._lock: # noqa: SLF001
assert service._acquisition is not None # noqa: SLF001
service._acquisition.transition( # noqa: SLF001
"failed",
message_code="acquisition.connection_lost",
result={"receiver_stopped": True, "device_state": "active-unconfirmed"},
)
control.state = "scanning"
stop_operation_id = "op-00000000-0000-4000-8000-000000001220"
stop_request = _stop_request(
acquisition_id=acquisition_id,
operation_id=stop_operation_id,
mode="graceful",
physical_acceptance=PHYSICAL_ACCEPTANCE,
)
issued = service.stop_acquisition(stop_request)
assert issued["acquisition"]["state"] == "failed"
assert control.stop_calls == 1
stop_operation = next(
operation
for operation in issued["operations"]
if operation["operation_id"] == stop_operation_id
)
assert stop_operation["status"] == "running"
control.state = "failed"
control.failure = {
"reason_code": "mqtt_network_loop_failed",
"safe_to_retry": False,
"modeling_command_attempted": True,
"network_change_admissible": True,
"network_change_reconciliation": {
"device_session_state": "scan_stopping",
"device_project_bound": True,
"system_error_code": None,
"stop_complete": True,
"standby_confirmed": False,
"automatic_retry": False,
},
}
physical_proof = {
"status": "unresolved",
"reason_code": "physical-command-reconciliation-required",
"requires_reconciliation": True,
"resolved_active_recovery_required": False,
"record": {
"operation_id": stop_operation_id,
"action": "stop",
"stage": "observing",
"resolution": None,
"application_response": {"action": "stop", "success": True},
"last_status": {
"session_state": "scan_stopping",
"mqtt_retained": False,
"project_bound": True,
"system_error_code": None,
},
"connection": {
"transport_ref": "k1-a",
"connection_mode": "bridge",
},
"reconciliations": [],
},
}
monkeypatch.setattr(
service._physical_command_coordinator, # noqa: SLF001
"snapshot",
lambda: physical_proof,
)
recovered = service.state()
terminal_stop = next(
operation
for operation in recovered["operations"]
if operation["operation_id"] == stop_operation_id
)
assert terminal_stop["status"] == "failed"
assert terminal_stop["stage_code"] == "stop-acknowledged-standby-unconfirmed"
assert terminal_stop["error"] == {
"category": "device",
"code": "stop-acknowledged-standby-unconfirmed",
"retryable": False,
"safe_to_retry": False,
"side_effect_status": "unknown",
"automatic_replay_allowed": False,
}
assert recovered["application_control_session"]["state"] == "idle"
assert recovered["source_mode"] == "idle"
assert recovered["acquisition"]["cleanup_pending"] is False
assert control.stop_calls == 1
repeated = service.stop_acquisition(stop_request)
repeated_stop = next(
operation
for operation in repeated["operations"]
if operation["operation_id"] == stop_operation_id
)
assert repeated_stop["stage_code"] == "stop-acknowledged-standby-unconfirmed"
assert control.stop_calls == 1
def test_mode_select_winner_fences_concurrent_prepare_before_stale_record(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
"""PREPARE and Mode Select share one winner before local publication."""
service, runtime = service_with_fake_runtime(tmp_path)
_select_connection_mode(service, "quick-connect")
control = FakeInteractiveControlSession(initial_state="connection-ready")
service._application_control_session = control # type: ignore[assignment] # noqa: SLF001
binding = _seed_supervised_connection(
service,
target_ipv4=facade_module.AP_FALLBACK_IPV4,
connection_mode="quick-connect",
transport_ref="k1-a",
)
control.verified_control = _verified_control_for_binding(binding)
selection_entered = threading.Event()
release_selection = threading.Event()
selection_results: list[dict[str, Any]] = []
selection_failures: list[BaseException] = []
original_runtime_snapshot = runtime.snapshot
snapshot_pause_used = False
snapshot_pause_lock = threading.Lock()
def paused_selection_runtime_snapshot() -> dict[str, object]:
nonlocal snapshot_pause_used
should_pause = False
if threading.current_thread().name == "mode-select-winner":
with snapshot_pause_lock:
if not snapshot_pause_used:
snapshot_pause_used = True
should_pause = True
if should_pause:
selection_entered.set()
assert release_selection.wait(2.0)
return original_runtime_snapshot()
monkeypatch.setattr(runtime, "snapshot", paused_selection_runtime_snapshot)
def run_selection() -> None:
try:
selection_results.append(
service.select_connection_mode(
DesiredConnectionModeRequest(
connection_mode="bridge",
expected_revision=1,
)
)
)
except BaseException as exc: # pragma: no cover - assertion aid
selection_failures.append(exc)
selection_thread = threading.Thread(
target=run_selection,
name="mode-select-winner",
daemon=True,
)
selection_thread.start()
assert selection_entered.wait(2.0)
try:
with pytest.raises(facade_module.ApplicationControlProcessLeaseUnavailable):
service.prepare_acquisition(
_prepare_request(
project_name="STALE01",
host=facade_module.AP_FALLBACK_IPV4,
compatibility_attestation=QUICK_CONNECT_ATTESTATION,
)
)
finally:
release_selection.set()
selection_thread.join(timeout=3.0)
assert selection_thread.is_alive() is False
assert selection_failures == []
assert selection_results[0]["desired_connection_mode"] == "bridge"
assert selection_results[0]["desired_connection_mode_revision"] == 2
assert service._acquisition is None # noqa: SLF001
assert control.state == "connection-ready"
device_edges: list[str] = []
async def fake_scan(
_duration_seconds: float,
*,
on_admitted: Callable[[], None] | None = None,
) -> dict[str, Any]:
assert service._acquisition is None # noqa: SLF001
assert control.state == "idle"
assert on_admitted is not None
on_admitted()
return _ble_scan_result("bridge-candidate")
async def forbidden_network_write(*_: object, **__: object) -> dict[str, Any]:
device_edges.append("network-write")
raise AssertionError("losing PREPARE must not create a device edge")
monkeypatch.setattr(facade_module, "scan", fake_scan)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_network_write)
monkeypatch.setattr(
service._physical_command_coordinator, # noqa: SLF001
"prepare",
lambda *_args, **_kwargs: device_edges.append("physical-command"),
)
scanned = asyncio.run(service.scan_ble(1.0))
assert device_edges == []
assert scanned["acquisition"] is None
assert scanned["desired_connection_mode"] == "bridge"
assert [item["device_id"] for item in scanned["devices"]] == ["bridge-candidate"]
@pytest.mark.parametrize(
("network_stage", "expected_resolution", "expected_terminal_records"),
[
("prepared", "not-dispatched", 0),
("dispatching", "interrupted", 1),
("observing", "interrupted", 1),
],
ids=["prepared", "dispatching", "observing"],
)
def test_restart_after_any_open_network_stage_starts_with_a_clean_explicit_flow(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
network_stage: str,
expected_resolution: str,
expected_terminal_records: int,
) -> None:
"""CONN-08/11: restart terminalizes audit without restoring live authority."""
first, _ = service_with_fake_runtime(tmp_path)
_seed_supervised_connection(
first,
target_ipv4="192.168.68.50",
connection_mode="bridge",
transport_ref="k1-a",
logical_device_id="device-a",
)
_set_scanned_k1(first, device_id="k1-a")
_seed_legacy_network_mutation_without_idempotency(
first,
operation_id=f"restart-{network_stage}-operation",
stage=network_stage,
)
assert first.state()["selected_device_id"] == "k1-a"
# A process restart loses every CoreBluetooth object even when the same
# macOS UUID is later advertised again. Construction/recovery is durable
# bookkeeping only and may not discover, read or write the device.
_SYNTHETIC_SCAN_CAPTURES.clear()
implicit_device_edges: list[str] = []
async def forbidden_scan(*_: object, **__: object) -> dict[str, Any]:
implicit_device_edges.append("scan")
raise AssertionError("restart recovery must not scan automatically")
async def forbidden_read(*_: object, **__: object) -> dict[str, Any]:
implicit_device_edges.append("read")
raise AssertionError("restart recovery must not open GATT automatically")
async def forbidden_write(*_: object, **__: object) -> dict[str, Any]:
implicit_device_edges.append("write")
raise AssertionError("restart recovery must not replay a network write")
monkeypatch.setattr(facade_module, "scan", forbidden_scan)
monkeypatch.setattr(facade_module, "read_wifi_status_once", forbidden_read)
monkeypatch.setattr(facade_module, "provision_wifi_once", forbidden_write)
restarted, _ = service_with_fake_runtime(tmp_path)
state = restarted.state()
assert implicit_device_edges == []
assert state["devices"] == []
assert state["selected_device_id"] is None
assert state["device_session"] is None
assert state["current_device_recovery"] is None
assert state["configured_connection_mode"] is None
assert state["active_connection_mode"] is None
assert state["connection_lifecycle"]["active_binding"] is None
assert state["connection_lifecycle"]["connection_ready"] is False
assert state["network_write_reconciliation"] is None
assert state["network_mutation_ledger"]["status"] == "resolved"
assert state["network_mutation_ledger"]["resolution"] == expected_resolution
assert state["network_provisioning_idempotency"]["active_operation_id"] is None
assert state["network_provisioning_idempotency"]["terminal_record_count"] == (
expected_terminal_records
)
assert state["connection_policy"]["actions"]["scan-ble"]["allowed"] is True
assert state["connection_lifecycle"]["automatic_retry"] is False
# A later advertisement is only a fresh candidate. It does not resurrect
# the old binding, but it does make a new explicit Connect admissible.
_set_scanned_k1(restarted, device_id="k1-a")
fresh = restarted.state()
assert fresh["selected_device_id"] is None
assert fresh["active_connection_mode"] is None
assert fresh["connection_policy"]["actions"]["provision-fresh-device"]["allowed"] is True
assert implicit_device_edges == []
def test_power_loss_before_network_prepare_clears_selection_without_write_or_retry(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
"""CONN-10: a pre-PREPARED disconnect is a clean, retryable no-write end."""
service, _ = service_with_fake_runtime(tmp_path)
_seed_supervised_connection(
service,
target_ipv4=facade_module.AP_FALLBACK_IPV4,
connection_mode="quick-connect",
transport_ref="k1-a",
logical_device_id="device-a",
)
_set_scanned_k1(service, device_id="k1-a")
provisioning_calls = 0
async def powered_off_before_prepare(
*_: object,
on_write_dispatch: Callable[[dict[str, Any], str], None] | None = None,
**__: object,
) -> dict[str, Any]:
nonlocal provisioning_calls
provisioning_calls += 1
assert on_write_dispatch is not None
error = RuntimeError("K1 powered off before durable prepare")
error.operation_stage = "gatt-connect" # type: ignore[attr-defined]
error.device_write_attempted = False # type: ignore[attr-defined]
error.device_write_confirmed = False # type: ignore[attr-defined]
raise error
monkeypatch.setattr(facade_module, "provision_wifi_once", powered_off_before_prepare)
with pytest.raises(RuntimeError, match="powered off before durable prepare"):
asyncio.run(
service.connect(
_connect_request(
device_id="k1-a",
ssid="lab-router",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
connection_mode="bridge",
compatibility_attestation=ATTESTATION,
)
)
)
state = service.state()
operation = next(item for item in state["operations"] if item["action"] == "network.provision")
assert provisioning_calls == 1
assert state["selected_device_id"] is None
assert state["device_session"] is None
assert state["configured_connection_mode"] is None
assert state["active_connection_mode"] is None
assert state["network_mutation_ledger"]["status"] == "empty"
assert state["network_provisioning_idempotency"]["active_operation_id"] is None
assert operation["status"] == "failed"
assert operation["error"]["side_effect_status"] == "none"
assert operation["error"]["safe_to_retry"] is True
assert operation["context"]["automatic_retry"] is False
assert state["connection_attempt"]["phase"] == "network_not_applied"
assert state["connection_attempt"]["side_effect_status"] == "none"
assert state["connection_attempt"]["automatic_retry"] is False
assert state["connection_policy"]["actions"]["scan-ble"]["allowed"] is True
_set_scanned_k1(service, device_id="k1-a")
assert (
service.state()["connection_policy"]["actions"]["provision-fresh-device"]["allowed"] is True
)
assert provisioning_calls == 1
def test_power_loss_after_dispatch_becomes_terminal_unknown_without_replay(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
"""CONN-12: a dispatched write is unknown audit, never an automatic retry."""
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service, device_id="k1-a")
write_calls = 0
async def powered_off_after_dispatch(
*_: object,
on_write_dispatch: Callable[[dict[str, Any], str], None] | None = None,
**__: object,
) -> dict[str, Any]:
nonlocal write_calls
write_calls += 1
_dispatch_test_network_write(on_write_dispatch)
error = RuntimeError("K1 powered off after dispatch")
error.operation_stage = "gatt-write" # type: ignore[attr-defined]
error.device_write_attempted = True # type: ignore[attr-defined]
error.device_write_confirmed = False # type: ignore[attr-defined]
raise error
monkeypatch.setattr(facade_module, "provision_wifi_once", powered_off_after_dispatch)
with pytest.raises(RuntimeError, match="powered off after dispatch"):
asyncio.run(
service.connect(
_connect_request(
device_id="k1-a",
ssid="lab-router",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
)
)
)
# The old advertisement may already be gone after the failed write. The
# durable unresolved ledger still pins an exact read-only target and must
# outrank a generic new scan in current operator guidance.
_set_scanned_devices(service, [])
failed = service.state()
failed_operation = next(
item for item in failed["operations"] if item["action"] == "network.provision"
)
assert write_calls == 1
assert failed["selected_device_id"] is None
assert failed["device_session"] is None
assert failed["network_mutation_ledger"]["status"] == "unresolved"
assert failed["network_mutation_ledger"]["stage"] == "dispatching"
assert failed_operation["error"]["side_effect_status"] == "unknown"
assert failed_operation["error"]["safe_to_retry"] is False
assert failed_operation["context"]["automatic_retry"] is False
assert failed["connection_attempt"]["phase"] == "network_outcome_unknown"
assert failed["connection_attempt"]["side_effect_status"] == "unknown"
assert failed["connection_attempt"]["safe_next_action"] == "verify-control-read-only"
assert failed["connection_attempt"]["automatic_retry"] is False
assert (
failed["connection_policy"]["actions"]["observe-configured-device-network"]["allowed"]
is True
)
assert failed["connection_policy"]["recommended_action"] == (
"observe-configured-device-network"
)
assert failed["connection_policy"]["actions"]["scan-ble"]["allowed"] is True
_set_scanned_k1(service, device_id="k1-a")
assert (
service.state()["connection_policy"]["actions"]["provision-fresh-device"]["allowed"] is True
)
assert write_calls == 1
_SYNTHETIC_SCAN_CAPTURES.clear()
restarted, _ = service_with_fake_runtime(tmp_path)
terminal = restarted.state()
assert write_calls == 1
assert terminal["selected_device_id"] is None
assert terminal["device_session"] is None
assert terminal["network_write_reconciliation"] is None
assert terminal["network_mutation_ledger"]["status"] == "resolved"
assert terminal["network_mutation_ledger"]["resolution"] == "interrupted"
assert terminal["network_provisioning_idempotency"]["active_operation_id"] is None
durable_terminal = (
restarted._require_network_provisioning_idempotency_journal() # noqa: SLF001
.snapshot()
.records[-1]
)
assert durable_terminal.terminal is not None
assert durable_terminal.terminal.outcome_code == "network.provision.interrupted"
assert durable_terminal.terminal.side_effect_status == "reconciled"
assert durable_terminal.terminal.safe_to_retry is False
_set_scanned_k1(restarted, device_id="k1-a")
assert (
restarted.state()["connection_policy"]["actions"]["provision-fresh-device"]["allowed"]
is True
)
assert write_calls == 1
def test_power_loss_during_observation_preserves_audit_and_releases_ownership(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
"""CONN-13: bounded observation survives; selection and ownership do not."""
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_k1(service, device_id="k1-a")
baseline = _wifi_status_read(None, device_id="k1-a")["status"]
bounded_baseline = {key: baseline[key] for key in ("mode", "ipv4", "status_code", "reserved")}
write_calls = 0
async def power_lost_while_observing(
*_: object,
on_write_dispatch: Callable[[dict[str, Any], str], None] | None = None,
**__: object,
) -> dict[str, Any]:
nonlocal write_calls
write_calls += 1
assert on_write_dispatch is not None
on_write_dispatch(baseline, "with_response")
return {
"started_at_utc": "2026-08-08T10:00:00Z",
"completed_at_utc": "2026-08-08T10:00:01Z",
"profile_id": "xgrids-k1-fw3-wifi-v1",
"outcome": "connection-lost-during-status-observation",
"write_mode": "with_response",
"baseline_status": baseline,
"observations": [{"status": baseline}],
}
monkeypatch.setattr(facade_module, "provision_wifi_once", power_lost_while_observing)
with pytest.raises(RuntimeError, match="не сообщило адрес"):
asyncio.run(
service.connect(
_connect_request(
device_id="k1-a",
ssid="lab-router",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
)
)
)
failed = service.state()
failed_record = service._network_mutation_ledger.snapshot().record # noqa: SLF001
failed_operation = next(
item for item in failed["operations"] if item["action"] == "network.provision"
)
assert write_calls == 1
assert failed["selected_device_id"] is None
assert failed["device_session"] is None
assert failed["network_mutation_ledger"]["status"] == "unresolved"
assert failed["network_mutation_ledger"]["stage"] == "observing"
assert failed_record is not None
assert failed_record.write_confirmed is True
assert failed_record.last_observation is not None
assert failed_record.last_observation.as_dict() == bounded_baseline
assert failed_operation["error"]["side_effect_status"] == "unknown"
assert failed_operation["error"]["safe_to_retry"] is False
assert failed_operation["context"]["automatic_retry"] is False
assert failed["connection_policy"]["actions"]["scan-ble"]["allowed"] is True
_set_scanned_k1(service, device_id="k1-a")
assert (
service.state()["connection_policy"]["actions"]["provision-fresh-device"]["allowed"] is True
)
assert write_calls == 1
_SYNTHETIC_SCAN_CAPTURES.clear()
restarted, _ = service_with_fake_runtime(tmp_path)
terminal = restarted.state()
terminal_record = restarted._network_mutation_ledger.snapshot().record # noqa: SLF001
assert write_calls == 1
assert terminal["selected_device_id"] is None
assert terminal["device_session"] is None
assert terminal["network_write_reconciliation"] is None
assert terminal["network_mutation_ledger"]["status"] == "resolved"
assert terminal["network_mutation_ledger"]["resolution"] == "interrupted"
assert terminal_record is not None
assert terminal_record.last_observation is not None
assert terminal_record.last_observation.as_dict() == bounded_baseline
assert terminal["network_provisioning_idempotency"]["active_operation_id"] is None
_set_scanned_k1(restarted, device_id="k1-a")
assert (
restarted.state()["connection_policy"]["actions"]["provision-fresh-device"]["allowed"]
is True
)
assert write_calls == 1