feat(k1): recover exact application bootstrap

This commit is contained in:
DCCONSTRUCTIONS
2026-07-18 13:54:25 +03:00
parent af9319a33b
commit d7749208a7
15 changed files with 906 additions and 215 deletions
+39 -20
View File
@@ -2,6 +2,10 @@ from __future__ import annotations
import pytest
from k1link.device_plugins.xgrids_k1.protocol.application_bootstrap import (
ApplicationControlAuthority,
LiveDeviceControlBinding,
)
from k1link.device_plugins.xgrids_k1.protocol.modeling_control import (
MODELING_STATE_BASE,
ModelingAction,
@@ -9,7 +13,6 @@ from k1link.device_plugins.xgrids_k1.protocol.modeling_control import (
)
from k1link.device_plugins.xgrids_k1.protocol.modeling_safety import (
DEVICE_STATUS_TOPIC,
DeviceBoundControlEnrollment,
LiveModelingControlSafety,
ModelingControlSafetyError,
)
@@ -61,14 +64,22 @@ def _status_message(
)
def _enrollment(**changes: str) -> DeviceBoundControlEnrollment:
def _authority() -> ApplicationControlAuthority:
return ApplicationControlAuthority(openapi_key="application-private-key")
def _binding(**changes: object) -> LiveDeviceControlBinding:
values = {
"vendor_device_id": "vendor-device-001",
"device_serial": "serial-001",
"openapi_key": "device-bound-private-key",
"software_version": "V3.0.2-build.1",
"system_version": "V3.0.2",
"device_model": "LixelKity K1",
"device_type": "K1",
"is_activated": True,
}
values.update(changes)
return DeviceBoundControlEnrollment(**values)
return LiveDeviceControlBinding(**values) # type: ignore[arg-type]
def test_live_status_identity_is_observed_without_accepting_replay() -> None:
@@ -95,7 +106,7 @@ def test_start_shadow_plan_is_exact_bounded_and_never_executable() -> None:
safety = LiveModelingControlSafety()
safety.observe(_status_message(SessionState.READY), BridgeMetrics())
plan = safety.plan_start(_enrollment(), project_name="SAFE_PROJECT")
plan = safety.plan_start(_authority(), _binding(), project_name="SAFE_PROJECT")
fields = {field.number: field for field in iter_fields(plan.command.payload, max_fields=16)}
assert plan.action is ModelingAction.START
@@ -109,8 +120,8 @@ def test_start_shadow_plan_is_exact_bounded_and_never_executable() -> None:
assert plan.executable is False
assert plan.blockers == ("vendor-writes-disabled", "publisher-not-installed")
assert plan.retry_policy == "never-automatic"
assert "device-bound-private-key" not in repr(plan)
assert "device-bound-private-key" not in str(plan.as_dict())
assert "application-private-key" not in repr(plan)
assert "application-private-key" not in str(plan.as_dict())
def test_stop_shadow_plan_requires_same_live_device_and_active_project() -> None:
@@ -120,13 +131,13 @@ def test_stop_shadow_plan_requires_same_live_device_and_active_project() -> None
BridgeMetrics(),
)
plan = safety.plan_stop(_enrollment())
plan = safety.plan_stop(_authority(), _binding())
fields = list(iter_fields(plan.command.payload, max_fields=8))
assert plan.action is ModelingAction.STOP
assert [field.number for field in fields] == [1, 2]
with pytest.raises(ModelingControlSafetyError, match="does not match"):
safety.plan_stop(_enrollment(device_serial="another-serial"))
safety.plan_stop(_authority(), _binding(device_serial="another-serial"))
def test_identity_drift_and_decode_failure_fail_closed() -> None:
@@ -139,7 +150,7 @@ def test_identity_drift_and_decode_failure_fail_closed() -> None:
)
assert safety.snapshot().identity_conflict
with pytest.raises(ModelingControlSafetyError, match="conflicted"):
safety.plan_start(_enrollment(), project_name="SAFE_PROJECT")
safety.plan_start(_authority(), _binding(), project_name="SAFE_PROJECT")
safety.reset()
malformed = StreamMessage(
@@ -153,23 +164,31 @@ def test_identity_drift_and_decode_failure_fail_closed() -> None:
assert safety.observe(malformed, metrics)
assert safety.snapshot().decode_errors == 1
with pytest.raises(ModelingControlSafetyError, match="conflicted"):
safety.plan_start(_enrollment(), project_name="SAFE_PROJECT")
safety.plan_start(_authority(), _binding(), project_name="SAFE_PROJECT")
def test_shadow_plan_requires_exact_safe_lifecycle_state() -> None:
safety = LiveModelingControlSafety()
safety.observe(_status_message(SessionState.SCAN_STARTING), BridgeMetrics())
with pytest.raises(ModelingControlSafetyError, match="must be ready"):
safety.plan_start(_enrollment(), project_name="SAFE_PROJECT")
safety.plan_start(_authority(), _binding(), project_name="SAFE_PROJECT")
with pytest.raises(ModelingControlSafetyError, match="must be scanning"):
safety.plan_stop(_enrollment())
safety.plan_stop(_authority(), _binding())
def test_enrollment_rejects_runtime_profile_substitution() -> None:
with pytest.raises(ModelingControlSafetyError, match="exact reviewed K1 profile"):
DeviceBoundControlEnrollment(
vendor_device_id="vendor-device-001",
device_serial="serial-001",
openapi_key="device-bound-private-key",
firmware_version="3.0.3", # type: ignore[arg-type]
def test_device_info_binding_rejects_unreviewed_or_inactive_profile() -> None:
safety = LiveModelingControlSafety()
safety.observe(_status_message(SessionState.READY), BridgeMetrics())
with pytest.raises(ModelingControlSafetyError, match="does not attest"):
safety.plan_start(
_authority(),
_binding(software_version="V3.0.3"),
project_name="SAFE_PROJECT",
)
with pytest.raises(ModelingControlSafetyError, match="does not attest"):
safety.plan_start(
_authority(),
_binding(is_activated=False),
project_name="SAFE_PROJECT",
)