chore(node): preserve pre-canonicalization experiment snapshot

Historical working copy retained for audit before consolidation into main. The canonicalized plugin architecture and later fixes already live in main; this snapshot is not a release or a request to restore obsolete source layout.
This commit is contained in:
DCCONSTRUCTIONS
2026-09-21 08:45:34 +03:00
parent 020a878915
commit 1c7dd29d8a
89 changed files with 5026 additions and 487 deletions
+111
View File
@@ -0,0 +1,111 @@
import copy
import json
import secrets
import threading
from datetime import UTC, datetime, timedelta
import pytest
from k1link.fleet.device_enrollment import DeviceEnrollment, validate
from k1link.fleet.trust import PairingError
class Fleet:
def __init__(self):
self.lock = threading.RLock()
self.row = {
"id": "vehicle",
"node_id": "node-1",
"binding": {"binding_id": "binding-1"},
"device_enrollment": {"available": True, "runtime_id": "runtime-1"},
}
def find(self, _identifier):
return self.row
def public(self, row):
return {"connectivity": "online"}
def command():
# Synthetic value constructed at runtime; never a real WLAN credential.
return {
"operation_id": "op_" + "a" * 32,
"node_id": "node-1",
"runtime_id": "runtime-1",
"action": "connect",
"deadline_at": (datetime.now(UTC) + timedelta(seconds=60)).isoformat(),
"parameters": {
"device_id": "AA:BB:CC:DD:EE:FF",
"discovery_generation": 1,
"mode_revision": 0,
"ssid": "test-net",
"password": secrets.token_urlsafe(20),
},
}
def test_password_only_lives_in_pending_delivery_and_never_in_fleet_or_result():
fleet, bus, request = Fleet(), DeviceEnrollment(), command()
secret = request["parameters"]["password"]
public = bus.submit(fleet, "vehicle", request)
assert secret not in json.dumps(public)
assert secret not in json.dumps(fleet.row)
envelope = bus.heartbeat(fleet.row, {})
assert envelope["enrollment_commands"][0]["parameters"]["password"] == secret
bus.heartbeat(
fleet.row,
{"enrollment_results": [{"operation_id": request["operation_id"], "state": "running"}]},
)
assert secret not in json.dumps(list(bus.pending.values()))
assert not bus.heartbeat(fleet.row, {})["enrollment_commands"]
def test_unknown_after_core_restart_does_not_recreate_command():
fleet, bus, request = Fleet(), DeviceEnrollment(), command()
bus.submit(fleet, "vehicle", request)
restarted = DeviceEnrollment()
assert restarted.operation(fleet, "vehicle", request["operation_id"])["state"] == "unknown"
assert not restarted.heartbeat(fleet.row, {})["enrollment_commands"]
def test_fences_board_runtime_and_deadline_and_forbids_host_actions():
for change in (
{"node_id": "node-2"},
{"runtime_id": "runtime-2"},
{"action": "quick-connect"},
{"deadline_at": datetime.now(UTC).isoformat()},
):
fleet, bus, request = Fleet(), DeviceEnrollment(), command()
request.update(change)
with pytest.raises(PairingError):
bus.submit(fleet, "vehicle", request)
request = command()
request["parameters"]["allow_host_wifi_switch"] = True
with pytest.raises(PairingError):
validate(request)
def test_rebinding_drops_delivery_and_old_results():
fleet, bus, request = Fleet(), DeviceEnrollment(), command()
bus.submit(fleet, "vehicle", request)
fleet.row["binding"]["binding_id"] = "binding-2"
assert not bus.heartbeat(fleet.row, {})["enrollment_commands"]
assert bus.operation(fleet, "vehicle", request["operation_id"])["state"] == "unknown"
def test_expiry_drops_secret_without_automatic_retry():
fleet, bus, request = Fleet(), DeviceEnrollment(), command()
bus.submit(fleet, "vehicle", request)
bus.pending[("vehicle", request["operation_id"])]["deadline"] = 0
assert bus.operation(fleet, "vehicle", request["operation_id"])["state"] == "unknown"
assert bus.pending[("vehicle", request["operation_id"])]["payload"] is None
def test_duplicate_id_cannot_replace_original_secret():
fleet, bus, request = Fleet(), DeviceEnrollment(), command()
bus.submit(fleet, "vehicle", request)
duplicate = copy.deepcopy(request)
duplicate["parameters"]["password"] += "changed"
bus.submit(fleet, "vehicle", duplicate)
assert bus.pending[("vehicle", request["operation_id"])]["payload"] == request
+119 -8
View File
@@ -1,5 +1,5 @@
import asyncio
from collections.abc import Iterator
from collections.abc import Callable, Iterator
from pathlib import Path
from typing import Literal
@@ -36,6 +36,117 @@ from k1link.device_plugins.xgrids_k1.ble.scanner import (
RecoveryOperationKind = Literal["status-read", "wifi-provision", "ap-enable"]
def install_advertisement_source(
monkeypatch: MonkeyPatch,
observations: list[tuple[float, BLEDevice, str | None]],
) -> dict[str, int]:
"""A single native scanner that delivers advertisements while it is open."""
lifecycle = {"started": 0, "stopped": 0}
class FakeScanner:
def __init__(
self, detection_callback: Callable[[BLEDevice, AdvertisementData], None]
) -> None:
self.callback = detection_callback
self.scheduled: list[asyncio.TimerHandle] = []
async def __aenter__(self) -> "FakeScanner":
lifecycle["started"] += 1
for delay, device, name in observations:
advertisement = AdvertisementData(
local_name=name, manufacturer_data={}, service_data={},
service_uuids=[], tx_power=None, rssi=-45, platform_data=(),
)
self.scheduled.append(asyncio.get_running_loop().call_later(
delay, self.callback, device, advertisement
))
return self
async def __aexit__(self, *_args: object) -> None:
lifecycle["stopped"] += 1
for timer in self.scheduled:
timer.cancel()
monkeypatch.setattr(scanner_module, "BleakScanner", FakeScanner)
monkeypatch.setattr(scanner_module, "BLE_SCAN_INITIAL_WINDOW_SECONDS", 0.02)
return lifecycle
def test_discovery_keeps_one_scanner_open_for_a_late_k1_name(monkeypatch: MonkeyPatch) -> None:
device = BLEDevice("LATE-K1", None, details=object())
lifecycle = install_advertisement_source(monkeypatch, [
(0, device, None), (0.05, device, "XGR-LATE"),
])
async def scenario() -> None:
result = await scan(0.4)
timing = result["discovery_timing"]
assert timing["scan_extended"] is True
assert timing["first_candidate_ms"] >= timing["initial_window_ms"]
assert timing["scan_elapsed_ms"] < 400
assert len(result["devices"]) == 1
assert result["devices"][0]["k1_name_candidate"] is True
assert discovered_device(device.address) is device
asyncio.run(scenario())
assert lifecycle == {"started": 1, "stopped": 1}
def test_discovery_finishes_after_initial_window_when_k1_is_visible(
monkeypatch: MonkeyPatch,
) -> None:
device = BLEDevice("EARLY-K1", "XGR-EARLY", details=object())
lifecycle = install_advertisement_source(monkeypatch, [(0, device, "XGR-EARLY")])
result = asyncio.run(scan(0.4))
timing = result["discovery_timing"]
assert timing["scan_extended"] is False
assert timing["first_candidate_ms"] < timing["initial_window_ms"]
assert 20 <= timing["scan_elapsed_ms"] < 400
assert lifecycle == {"started": 1, "stopped": 1}
def test_discovery_without_k1_stops_at_deadline_and_does_not_reuse_old_results(
monkeypatch: MonkeyPatch,
) -> None:
device = BLEDevice("OTHER-DEVICE", "Headphones", details=object())
lifecycle = install_advertisement_source(monkeypatch, [(0, device, "Headphones")])
async def scenario() -> None:
result = await scan(0.06)
timing = result["discovery_timing"]
assert timing["scan_extended"] is True
assert "first_candidate_ms" not in timing
assert timing["scan_elapsed_ms"] >= 60
assert result["devices"][0]["k1_name_candidate"] is False
install_advertisement_source(monkeypatch, [])
empty = await scan(0.01)
assert empty["devices"] == []
assert empty["discovery_timing"]["scan_extended"] is False
assert discovered_device(device.address) is None
asyncio.run(scenario())
assert lifecycle == {"started": 1, "stopped": 1}
def test_cancelled_discovery_closes_scanner_without_publishing_partial_handles(
monkeypatch: MonkeyPatch,
) -> None:
device = BLEDevice("PARTIAL", "Headphones", details=object())
lifecycle = install_advertisement_source(monkeypatch, [(0, device, "Headphones")])
async def scenario() -> None:
task = asyncio.create_task(scan(1))
await asyncio.sleep(0.04)
assert lifecycle["started"] == 1
task.cancel()
with pytest.raises(asyncio.CancelledError):
await task
assert discovered_device(device.address) is None
asyncio.run(scenario())
assert lifecycle == {"started": 1, "stopped": 1}
async def _retrieve_connected_inside_ble_lease(
macos_uuid: str,
*,
@@ -175,7 +286,7 @@ def test_scan_retains_the_live_corebluetooth_handle(
return {"LIVE-UUID": (device, advertisement)}
monkeypatch.setattr(
"k1link.device_plugins.xgrids_k1.ble.scanner.BleakScanner.discover",
"k1link.device_plugins.xgrids_k1.ble.scanner._discover_k1_advertisements",
fake_discover,
)
@@ -209,7 +320,7 @@ def test_scan_start_invalidates_previous_lease_and_failure_leaves_it_empty(
) -> dict[str, tuple[BLEDevice, AdvertisementData]]:
return {old_device.address: (old_device, old_advertisement)}
monkeypatch.setattr(scanner_module.BleakScanner, "discover", initial_discover)
monkeypatch.setattr(scanner_module, "_discover_k1_advertisements", initial_discover)
await scan(1.0)
assert discovered_device(old_device.address) is old_device
@@ -221,7 +332,7 @@ def test_scan_start_invalidates_previous_lease_and_failure_leaves_it_empty(
await release_failing_scan.wait()
raise RuntimeError("synthetic BLE scan failure")
monkeypatch.setattr(scanner_module.BleakScanner, "discover", failing_discover)
monkeypatch.setattr(scanner_module, "_discover_k1_advertisements", failing_discover)
scan_task = asyncio.create_task(scan(1.0))
await failing_scan_started.wait()
@@ -263,7 +374,7 @@ def test_process_arbiter_rejects_overlapping_scan(monkeypatch: MonkeyPatch) -> N
await release_older_scan.wait()
return {older_device.address: (older_device, older_advertisement)}
monkeypatch.setattr(scanner_module.BleakScanner, "discover", blocked_discover)
monkeypatch.setattr(scanner_module, "_discover_k1_advertisements", blocked_discover)
older_task = asyncio.create_task(scan(1.0))
await older_scan_started.wait()
@@ -377,7 +488,7 @@ def test_connected_handle_is_session_scoped_and_survives_wall_clock_age(
async def fake_discover(**_kwargs: object) -> dict[str, tuple[BLEDevice, AdvertisementData]]:
return discoveries.pop(0)
monkeypatch.setattr(scanner_module.BleakScanner, "discover", fake_discover)
monkeypatch.setattr(scanner_module, "_discover_k1_advertisements", fake_discover)
monkeypatch.setattr(scanner_module, "monotonic", lambda: monotonic_clock[0])
monkeypatch.setattr(
scanner_module,
@@ -487,7 +598,7 @@ def test_scan_and_retained_handle_survive_macos_sleep_until_explicit_invalidatio
) -> dict[str, tuple[BLEDevice, AdvertisementData]]:
return {device.address: (device, advertisement)}
monkeypatch.setattr(scanner_module.BleakScanner, "discover", fake_discover)
monkeypatch.setattr(scanner_module, "_discover_k1_advertisements", fake_discover)
monkeypatch.setattr(scanner_module, "monotonic", lambda: monotonic_clock[0])
monkeypatch.setattr(
scanner_module,
@@ -1340,7 +1451,7 @@ def test_later_fresh_scan_does_not_replace_retained_corebluetooth_object(
async def fake_discover(**_kwargs: object) -> dict[str, tuple[BLEDevice, AdvertisementData]]:
return discoveries.pop(0)
monkeypatch.setattr(scanner_module.BleakScanner, "discover", fake_discover)
monkeypatch.setattr(scanner_module, "_discover_k1_advertisements", fake_discover)
async def scenario() -> None:
await scan(1.0)
+72
View File
@@ -0,0 +1,72 @@
from copy import deepcopy
import pytest
from k1link.device_plugins.xgrids_k1.wifi_failure import reviewed_station_failure_code
def station_error(code: int = 4) -> dict[str, object]:
return {
"code": "BleakGATTProtocolError",
"operation_stage": "gatt-write",
"device_write_attempted": True,
"device_write_confirmed": False,
"resolved_write_mode": "with_response",
"frame_length": 99,
"ble_att_error_code": code,
"ble_att_error_name": "INVALID_PDU",
"safe_to_retry": False,
"side_effect_status": "unknown",
}
@pytest.mark.parametrize("mode", ["bridge", "direct-connect"])
@pytest.mark.parametrize(
"code,reason", [(4, "k1-wifi-network-not-found"), (6, "k1-wifi-credentials-required")]
)
def test_reviewed_station_reply_retains_raw_facts_and_retry_fence(
mode: str, code: int, reason: str
) -> None:
error = station_error(code)
before = deepcopy(error)
assert (
reviewed_station_failure_code(error, firmware_version="3.0.2", connection_mode=mode)
== reason
)
assert error == before
@pytest.mark.parametrize(
"field,value",
[
("code", "RuntimeError"),
("operation_stage", "baseline-read"),
("device_write_attempted", False),
("device_write_confirmed", True),
("resolved_write_mode", "without_response"),
("frame_length", 100),
("ble_att_error_code", 14),
("ble_att_error_code", "4"),
("ble_att_error_code", {}),
],
)
def test_unrelated_transport_failures_are_not_wifi_diagnoses(field: str, value: object) -> None:
error = {**station_error(), field: value}
assert (
reviewed_station_failure_code(error, firmware_version="3.0.2", connection_mode="bridge")
is None
)
@pytest.mark.parametrize(
"firmware,mode", [("3.0.1", "bridge"), ("unknown", "bridge"), ("3.0.2", "quick-connect")]
)
def test_other_firmware_and_quick_connect_do_not_inherit_station_codes(
firmware: str, mode: str
) -> None:
assert (
reviewed_station_failure_code(
station_error(), firmware_version=firmware, connection_mode=mode
)
is None
)
+204
View File
@@ -0,0 +1,204 @@
import asyncio
import copy
import json
import secrets
from datetime import UTC, datetime, timedelta
from pathlib import Path
import pytest
from missioncore_plugin_sdk.v0alpha2.session import DeviceSessionSnapshot
from k1link.device_plugins.xgrids_k1.linux_host import nm_fields, route_fields
from k1link.device_plugins.xgrids_k1.node_bridge import NodeBridge
from k1link.device_plugins.xgrids_k1.node_sensor import NodeK1Sensor, project_sensor
from k1link.viewer.node_rerun import NodeRerunHub
def state():
return {
"snapshot_runtime_id": "runtime-one",
"snapshot_revision": 1,
"devices": [
{"device_id": "AA:BB:CC:DD:EE:FF", "name": "K1-test", "likely_k1": True},
{"device_id": "unrelated", "name": "Other", "likely_k1": False},
],
"ble_discovery_generation": 1,
"desired_connection_mode_revision": 0,
"active_connection_mode": "bridge",
"connection_lifecycle": {"connection_ready": True, "ready_to_start": True},
"selected_device_id": "AA:BB:CC:DD:EE:FF",
"source_mode": "idle",
"device_session": {
"device_id": "synthetic-k1",
"device_session_id": "session-test",
"opened_at": datetime.now(UTC).isoformat(),
},
"application_control_session": {
"session_generation": 1,
"state_revision": 1,
"state": "connection-ready",
},
}
class Facade:
def __init__(self):
self.current = state()
self.actions = []
async def invoke(self, request):
self.actions.append((request.action_id, copy.deepcopy(request.parameters)))
if request.action_id == "application-control.workspace.enter":
self.current["application_control_session"]["state"] = "workspace-ready"
elif request.action_id == "acquisition.prepare":
self.current["acquisition"] = {
"acquisition_id": "acquisition-test",
"state": "prepared",
"state_revision": 1,
}
self.current["application_control_session"]["state"] = "project-ready"
elif request.action_id == "acquisition.start":
self.current["application_control_session"]["state"] = "initializing"
self.current["acquisition"]["state"] = "running"
self.current["source_mode"] = "live"
return copy.deepcopy(self.current)
def bridge():
result = NodeBridge(Path.cwd(), service=object())
result.facade = Facade()
return result
def test_node_bridge_forces_reviewed_bridge_and_clears_input_secret():
async def run():
device = bridge()
command = {
"operation_id": "op_" + "a" * 32,
"runtime_id": "runtime-one",
"deadline_at": (datetime.now(UTC) + timedelta(seconds=60)).isoformat(),
"action": "connect",
"parameters": {
"device_id": "AA:BB:CC:DD:EE:FF",
"discovery_generation": 1,
"mode_revision": 0,
"ssid": "test-network",
"password": secrets.token_urlsafe(24),
"allow_host_wifi_switch": True,
},
}
secret = command["parameters"]["password"]
output = await device.execute(command)
payload = next(v for a, v in device.facade.actions if a == "network.provision")
assert payload["connection_mode"] == "bridge"
assert payload["allow_host_wifi_switch"] is False
assert payload["password"] == secret
assert "password" not in command["parameters"]
assert secret not in json.dumps(output)
assert [v["id"] for v in output["candidates"]] == ["AA:BB:CC:DD:EE:FF"]
asyncio.run(run())
def test_stale_discovery_prevents_provisioning():
async def run():
device = bridge()
with pytest.raises(ValueError):
await device.execute(
{
"operation_id": "op_" + "a" * 32,
"runtime_id": "runtime-one",
"deadline_at": (datetime.now(UTC) + timedelta(seconds=60)).isoformat(),
"action": "connect",
"parameters": {
"device_id": "AA:BB:CC:DD:EE:FF",
"discovery_generation": 0,
"mode_revision": 0,
},
}
)
assert all(action != "network.provision" for action, _ in device.facade.actions)
asyncio.run(run())
def test_sensor_projection_binds_native_sdk_to_board():
value = project_sensor(state(), "node-test")
snapshot = DeviceSessionSnapshot.model_validate(value["snapshot"])
assert snapshot.context.execution.node_id == "node-test"
assert snapshot.context.device.device_id == value["id"]
assert value["kind"] == "k1"
def test_one_start_intent_preserves_canonical_enter_prepare_start_sequence():
async def run():
device = bridge()
sensor = NodeK1Sensor(device, None)
item = project_sensor(state(), "node-test")
command = {
"operation_id": "op_" + "a" * 32,
"action_id": "start",
"session": {"device_id": item["id"], "session_id": "session-test"},
"deadline_at": (datetime.now(UTC) + timedelta(seconds=60)).isoformat(),
"parameters": {
"operator_confirmed": True,
"control_generation": 1,
"acquisition_id": None,
},
}
result = await sensor.execute(command, "node-test")
actions = [a for a, _ in device.facade.actions if a != "state.read"]
assert actions == [
"application-control.workspace.enter",
"acquisition.prepare",
"acquisition.start",
]
assert result["snapshot"]["acquisition"] == "streaming"
command["parameters"]["control_generation"] = 2
with pytest.raises(ValueError):
await sensor.execute(command, "node-test")
assert len([a for a, _ in device.facade.actions if a == "acquisition.start"]) == 1
asyncio.run(run())
def test_networkmanager_ssids_are_not_split_at_escaped_colons():
assert nm_fields(r"field\:network\\name:88:WPA2") == ["field:network\\name", "88", "WPA2"]
def test_linux_kernel_route_is_matched_route_not_resolved_host(monkeypatch):
from k1link.device_plugins.xgrids_k1 import linux_host
from k1link.device_plugins.xgrids_k1.facade import _classify_host_route
calls = []
def run(args):
calls.append(args)
return '[{"dst":"default","dev":"wlp2s0","gateway":"192.168.1.1"}]'
monkeypatch.setattr(linux_host, "_run", run)
result = route_fields("192.168.2.7")
assert calls[0] == ["ip", "-j", "route", "get", "192.168.2.7", "fibmatch"]
assert _classify_host_route(result["interface"], result["destination"])[0] == "default"
assert _classify_host_route("wlp2s0", "192.168.1.0/24")[0] == "direct"
assert _classify_host_route("tailscale0", "192.168.1.7")[0] == "tunnel"
def test_native_node_rrd_opens_no_grpc_listener(monkeypatch):
from k1link.viewer import rerun_bridge
def forbidden(*_args, **_kwargs):
raise AssertionError("Node must not expose a gRPC listener")
monkeypatch.setattr(rerun_bridge, "_select_available_grpc_port", forbidden)
hub = NodeRerunHub()
publisher = hub.create()
publisher.begin_session()
subscriber = hub.subscribe()
try:
data = subscriber.read()
assert data[:4] == b"RRF2"
finally:
subscriber.close()
subscriber.thread.join(6)
publisher.close()
+102
View File
@@ -0,0 +1,102 @@
import asyncio
import queue
import pytest
from aiortc import RTCConfiguration, RTCPeerConnection, RTCSessionDescription
from k1link.viewer.node_media import NodeMediaPeers, admit_sdp
SDP_HEADER = "v=0\r\nm=application 9 UDP/DTLS/SCTP webrtc-datachannel\r\n"
@pytest.mark.parametrize(
"address,kind", [("8.8.8.8", "host"), ("192.168.1.2", "relay"), ("::1", "host")]
)
def test_media_rejects_non_private_or_relay_candidates(address, kind):
with pytest.raises(ValueError):
admit_sdp(SDP_HEADER + f"a=candidate:1 1 udp 1 {address} 12345 typ {kind}\r\n")
def test_media_accepts_paired_lan_and_tailnet_candidates():
for address in ("192.168.1.2", "100.80.6.113", "peer.local"):
admit_sdp(SDP_HEADER + f"a=candidate:1 1 udp 1 {address} 12345 typ host\r\n")
def test_failed_media_offer_retires_peer_without_camera_channel(monkeypatch):
async def reject(*_):
raise ValueError("Invalid remote description")
monkeypatch.setattr(RTCPeerConnection, "setRemoteDescription", reject)
async def run():
class Camera:
def snapshot(self):
return {}
peers = NodeMediaPeers(None, Camera())
try:
with pytest.raises(ValueError):
await peers.offer({"sdp": SDP_HEADER})
assert peers.items == {}
finally:
await peers.close_all()
asyncio.run(run())
def test_native_webrtc_roundtrip_and_missing_camera_preserve_rrd(monkeypatch):
"""One bounded loopback peer, no STUN/TURN, device or external network."""
import aioice.ice
class Subscription:
def __init__(self):
self.output = queue.Queue()
self.output.put(b"RRF2-transport-fixture")
def read(self):
try:
return self.output.get(timeout=0.1)
except queue.Empty:
return b""
def close(self):
pass
class Hub:
def subscribe(self):
return Subscription()
class Camera:
def snapshot(self):
return {"generation": None}
async def run():
peers = NodeMediaPeers(Hub(), Camera())
monkeypatch.setattr(aioice.ice, "get_host_addresses", lambda **_: ["127.0.0.1"])
client = RTCPeerConnection(RTCConfiguration(iceServers=[]))
channel = client.createDataChannel("rrd", ordered=True)
client.createDataChannel("camera", ordered=True)
received = asyncio.Event()
payloads = []
@channel.on("message")
def message(data):
payloads.append(data)
received.set()
try:
await client.setLocalDescription(await client.createOffer())
answer = await peers.offer({"sdp": client.localDescription.sdp})
await client.setRemoteDescription(
RTCSessionDescription(sdp=answer["sdp"], type="answer")
)
await asyncio.wait_for(received.wait(), timeout=8)
assert payloads == [b"RRF2-transport-fixture"]
assert answer["peer_id"] in peers.items
assert channel.readyState == "open"
finally:
await client.close()
await peers.close_all()
assert not peers.items
asyncio.run(run())
+49
View File
@@ -42,6 +42,29 @@ def _request(*, ui_build_id: str | None = None) -> Request:
return Request({"type": "http", "method": "GET", "path": "/", "headers": headers})
def test_scanner_exception_keeps_location_without_private_message_or_locals(
tmp_path: Path,
) -> None:
target = configure_scanner_diagnostics(tmp_path / "logs")
logger = logging.getLogger(f"{SCANNER_LOGGER_NAME}.test")
private_detail = "synthetic-private-runtime-detail"
try:
raise ValueError(private_detail)
except ValueError:
logger.exception("Camera activation failed")
for handler in logging.getLogger(SCANNER_LOGGER_NAME).handlers:
handler.flush()
serialized = target.read_text(encoding="utf-8").splitlines()[-1]
document = json.loads(serialized)
assert document["exception_type"] == "ValueError"
assert document["exception_site"].startswith("test_viewer_diagnostics_api.py:")
assert document["exception_site"].endswith(
":test_scanner_exception_keeps_location_without_private_message_or_locals"
)
assert private_detail not in serialized
assert str(Path(__file__).parent) not in serialized
def test_private_scanner_diagnostics_are_durable_structured_and_bounded(
tmp_path: Path,
) -> None:
@@ -67,6 +90,19 @@ def test_private_scanner_diagnostics_are_durable_structured_and_bounded(
"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,
"mtu_size": 256,
"frame_length": 99,
"write_characteristic_properties": ["read", "write"],
"scan_elapsed_ms": 7300,
"scanner_start_ms": 31,
"initial_window_ms": 6000,
"first_candidate_ms": 7240,
"scan_extended": True,
"candidate_count": 4,
"likely_k1_candidate_count": 1,
"discovery_generation": 2,
"helper_stage": "compile",
"helper_elapsed_ms": 34720,
"camera_source_id": "sensor.camera.right",
@@ -126,6 +162,19 @@ def test_private_scanner_diagnostics_are_durable_structured_and_bounded(
assert document["device_write_confirmed"] is False
assert document["ble_att_error_code"] == 4
assert document["ble_att_error_name"] == "INVALID_PDU"
assert document["resolved_write_mode"] == "with_response"
assert document["max_write_without_response_size"] == 253
assert document["mtu_size"] == 256
assert document["frame_length"] == 99
assert document["write_characteristic_properties"] == ["read", "write"]
assert document["scan_elapsed_ms"] == 7300
assert document["scanner_start_ms"] == 31
assert document["initial_window_ms"] == 6000
assert document["first_candidate_ms"] == 7240
assert document["scan_extended"] is True
assert document["candidate_count"] == 4
assert document["likely_k1_candidate_count"] == 1
assert document["discovery_generation"] == 2
assert document["helper_stage"] == "compile"
assert document["helper_elapsed_ms"] == 34720
assert document["camera_source_id"] == "sensor.camera.right"
+63 -3
View File
@@ -5256,11 +5256,14 @@ def test_ble_scan_operation_id_is_exactly_once_and_request_bound(
if on_admitted is not None:
on_admitted()
transport_calls += 1
return _ble_scan_result("exactly-once-device")
return {
**_ble_scan_result("exactly-once-device"),
"discovery_timing": {"scan_elapsed_ms": 7100, "scan_extended": True},
}
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)
request = BleScanRequest(operation_id=operation_id)
first = asyncio.run(service.scan_ble(request))
repeated = asyncio.run(service.scan_ble(request))
@@ -5271,8 +5274,10 @@ def test_ble_scan_operation_id_is_exactly_once_and_request_bound(
assert first["last_operation"]["result"] == {
"candidate_count": 1,
"likely_k1_candidate_count": 1,
"duration_seconds": 6.0,
"duration_seconds": 20.0,
"discovery_generation": 1,
"scan_elapsed_ms": 7100,
"scan_extended": True,
}
assert repeated["last_operation"]["operation_id"] == operation_id
with pytest.raises(ValueError, match="different request"):
@@ -21315,6 +21320,61 @@ def test_network_provisioning_rejects_an_ipv4_owned_by_the_local_host(
assert "lab-network" not in caplog.text
@pytest.mark.parametrize(
("att_code", "public_code"),
[(4, "k1-wifi-network-not-found"), (6, "k1-wifi-credentials-required")],
)
def test_station_reply_preserves_ambiguity_and_explains_wifi_failure(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
att_code: int,
public_code: str,
) -> None:
from bleak.exc import BleakGATTProtocolError
service, _ = service_with_fake_runtime(tmp_path)
_set_scanned_devices(service, [{"device_id": "k1-a"}])
calls = 0
async def rejected_write(
*_: object, on_write_dispatch: Any = None, **__: object,
) -> dict[str, Any]:
nonlocal calls
calls += 1
on_write_dispatch(_wifi_status_read(None, device_id="k1-a")["status"], "with_response")
exc = BleakGATTProtocolError(att_code)
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 = att_code # type: ignore[attr-defined]
exc.att_error_name = exc.code.name # type: ignore[attr-defined]
exc.resolved_write_mode = "with_response" # type: ignore[attr-defined]
exc.frame_length = 99 # type: ignore[attr-defined]
raise exc
monkeypatch.setattr(facade_module, "provision_wifi_once", rejected_write)
with pytest.raises(BleakGATTProtocolError):
asyncio.run(service.connect(_connect_request(
device_id="k1-a", ssid="lab-network",
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
compatibility_attestation=ATTESTATION,
idempotency_key="explicit-station-rejection",
)))
state = service.state()
operation = next(item for item in state["operations"] if item["action"] == "network.provision")
error = operation["error"]
assert calls == 1
assert operation["status"] == "failed"
assert error["code"] == public_code
assert error["transport_error_code"] == "BleakGATTProtocolError"
assert error["ble_att_error_code"] == att_code
assert error["safe_to_retry"] is False
assert error["device_write_confirmed"] is False
assert error["side_effect_status"] == "unknown"
assert state["connection_attempt"]["public_error_code"] == public_code
assert state["network_mutation_ledger"]["status"] == "unresolved"
def test_ambiguous_ble_write_is_audit_only_for_next_explicit_intent(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
+1 -1
View File
@@ -181,7 +181,7 @@ def test_scan_lease_rejects_wifi_entrypoints_process_wide(
resolution_attempted = True
raise AssertionError("busy contender must not touch CoreBluetooth")
monkeypatch.setattr(scanner_module.BleakScanner, "discover", blocked_discover)
monkeypatch.setattr(scanner_module, "_discover_k1_advertisements", blocked_discover)
monkeypatch.setattr(
wifi_module.BleakScanner,
"find_device_by_address",
+93
View File
@@ -299,6 +299,99 @@ def test_camera_selection_is_exclusive_and_hides_device_transport(
gateway.close()
@pytest.mark.parametrize("entrypoint", ["acquisition", "selected-preview"])
def test_camera_records_in_configured_evidence_outside_source_checkout(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, entrypoint: str,
) -> None:
checkout = tmp_path / "checkout"
checkout.mkdir()
evidence = tmp_path / "durable" / "sessions"
session = evidence / "synthetic-camera-session"
session.mkdir(parents=True)
monkeypatch.setenv("MISSIONCORE_FFMPEG_BINARY", str(_fake_ffmpeg(tmp_path)))
gateway = XgridsK1CameraGateway(checkout, XGRIDS_K1_PLUGIN_ID, evidence_root=evidence)
try:
if entrypoint == "acquisition":
gateway.activate_recording_producer(
"sensor.camera.right", "192.168.1.20", session,
pre_prepare_fence=lambda reserve: reserve(),
commit_fence=lambda commit: commit(),
)
else:
gateway.select("sensor.camera.right", "192.168.1.20")
gateway.start_recording(session)
_wait_until(lambda: gateway.snapshot()["recording"]["media_ready"] is True)
assert gateway.snapshot()["recording"]["session"] == session.name
assert not list(checkout.rglob("*.m4s"))
finally:
gateway.close()
assert any(session.rglob("*.m4s"))
@pytest.mark.parametrize("entrypoint", ["acquisition", "selected-preview"])
@pytest.mark.parametrize("escape", ["sibling", "symlink"])
def test_camera_rejects_paths_outside_configured_evidence_before_admission(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, entrypoint: str, escape: str,
) -> None:
checkout = tmp_path / "checkout"
checkout.mkdir()
evidence = tmp_path / "evidence"
evidence.mkdir()
outside = checkout / "not-evidence"
outside.mkdir()
session = outside
if escape == "symlink":
session = evidence / "escaped-session"
session.symlink_to(outside, target_is_directory=True)
gateway = XgridsK1CameraGateway(checkout, XGRIDS_K1_PLUGIN_ID, evidence_root=evidence)
def forbidden(*_args: object, **_kwargs: object) -> bool:
raise AssertionError("An escaped path must not reach authority or FFmpeg")
monkeypatch.setattr(camera_module.subprocess, "Popen", forbidden)
try:
with pytest.raises(ValueError, match="configured evidence root"):
if entrypoint == "acquisition":
gateway.activate_recording_producer(
"sensor.camera.right", "192.168.1.20", session,
pre_prepare_fence=forbidden, commit_fence=forbidden,
)
else:
gateway.start_recording(session)
assert gateway.snapshot()["recording"]["active"] is False
finally:
gateway.close()
def test_service_camera_uses_the_same_external_evidence_root_as_acquisition(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch,
) -> None:
checkout = tmp_path / "checkout"
checkout.mkdir()
evidence = tmp_path / "configured-evidence"
session = evidence / "synthetic-session"
session.mkdir(parents=True)
monkeypatch.setenv("MISSIONCORE_EVIDENCE_DIR", str(evidence))
service = XgridsK1CompatibilityService(checkout)
authority_entered = False
def deny_authority(_reserve: Callable[[], bool]) -> bool:
nonlocal authority_entered
authority_entered = True
return False
try:
with pytest.raises(ValueError, match="authority"):
service.camera_preview.activate_recording_producer(
"sensor.camera.right", "192.168.1.20", session,
pre_prepare_fence=deny_authority, commit_fence=lambda _commit: False,
)
assert authority_entered is True
assert service.camera_preview.snapshot()["active_source_id"] is None
finally:
service.close()
def test_camera_derived_observer_runs_only_after_durable_archive_commit(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,