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