feat(k1): add local connection matrix
This commit is contained in:
@@ -12,8 +12,10 @@ from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
PROFILE_SCHEMA_VERSION = 1
|
||||
DEFAULT_PROFILE_ID = "xgrids.lixelkity-k1.fw-3.0.2.direct-lan.v1"
|
||||
DEFAULT_PROFILE_PATH = Path(__file__).parent / "profiles" / "fw-3.0.2" / "direct-lan.v1.json"
|
||||
DEFAULT_PROFILE_ID = "xgrids.lixelkity-k1.fw-3.0.2.local-network.v2"
|
||||
DEFAULT_PROFILE_PATH = (
|
||||
Path(__file__).parent / "profiles" / "fw-3.0.2" / "local-network.v2.json"
|
||||
)
|
||||
EVIDENCE_FLAGS = (
|
||||
"observed",
|
||||
"decoded",
|
||||
@@ -129,6 +131,49 @@ def _validate_sources(profile: dict[str, Any]) -> set[str]:
|
||||
return set(sources)
|
||||
|
||||
|
||||
def _validate_connection_modes(scope: dict[str, Any]) -> None:
|
||||
modes = _unique_index(
|
||||
_array(scope.get("connection_modes"), "$.scope.connection_modes"),
|
||||
"$.scope.connection_modes",
|
||||
)
|
||||
expected = {
|
||||
"bridge": {
|
||||
"topology": "direct-lan",
|
||||
"direction": "k1-joins-existing-network",
|
||||
"device_network_action": "single-reviewed-ble-provisioning-write",
|
||||
"host_network_action": "none",
|
||||
"target_address_policy": "ble-status-non-ap-private-ipv4",
|
||||
"acceptance": "mission-core-physical-accepted",
|
||||
},
|
||||
"direct-connect": {
|
||||
"topology": "controller-hotspot",
|
||||
"direction": "k1-joins-controller-network",
|
||||
"device_network_action": "single-reviewed-ble-provisioning-write",
|
||||
"host_network_action": "operator-prepared-hotspot",
|
||||
"target_address_policy": "ble-status-non-ap-private-ipv4",
|
||||
"acceptance": "implementation-ready-physical-acceptance-pending",
|
||||
},
|
||||
"quick-connect": {
|
||||
"topology": "device-ap",
|
||||
"direction": "controller-joins-k1-network",
|
||||
"device_network_action": "none",
|
||||
"host_network_action": "single-corewlan-association",
|
||||
"target_address_policy": "reviewed-fixed-k1-ap-private-ipv4",
|
||||
"acceptance": (
|
||||
"lixelgo-data-plane-observed-mission-core-physical-acceptance-pending"
|
||||
),
|
||||
},
|
||||
}
|
||||
if set(modes) != set(expected):
|
||||
raise CompatibilityProfileError("connection mode set differs from reviewed evidence")
|
||||
for mode_id, expected_fields in expected.items():
|
||||
actual = {key: value for key, value in modes[mode_id].items() if key != "id"}
|
||||
if actual != expected_fields:
|
||||
raise CompatibilityProfileError(
|
||||
f"connection mode {mode_id!r} differs from reviewed evidence"
|
||||
)
|
||||
|
||||
|
||||
def _validate_source_references(value: Any, source_ids: set[str], path: str = "$") -> None:
|
||||
if isinstance(value, dict):
|
||||
if "source_ids" in value:
|
||||
@@ -155,7 +200,7 @@ def _validate_transports(profile: dict[str, Any]) -> None:
|
||||
)
|
||||
if set(transports) != {
|
||||
"ble.wifi-bootstrap.fw3.v1",
|
||||
"mqtt.direct-lan.fw3.v1",
|
||||
"mqtt.local-ipv4.fw3.v1",
|
||||
"rtsp.camera-preview.fw3.v1",
|
||||
}:
|
||||
raise CompatibilityProfileError("$.transports must contain only the reviewed v1 transports")
|
||||
@@ -180,14 +225,14 @@ def _validate_transports(profile: dict[str, Any]) -> None:
|
||||
physical_verified=True,
|
||||
)
|
||||
|
||||
mqtt = transports["mqtt.direct-lan.fw3.v1"]
|
||||
mqtt = transports["mqtt.local-ipv4.fw3.v1"]
|
||||
if mqtt.get("protocol") != "MQTT 3.1.1":
|
||||
raise CompatibilityProfileError("direct-LAN application protocol must remain MQTT 3.1.1")
|
||||
raise CompatibilityProfileError("local application protocol must remain MQTT 3.1.1")
|
||||
network = _object(mqtt.get("network"), "$.transports[mqtt].network")
|
||||
if network.get("transport") != "TCP" or network.get("port") != 1883:
|
||||
raise CompatibilityProfileError("direct-LAN MQTT endpoint must remain TCP 1883")
|
||||
raise CompatibilityProfileError("local MQTT endpoint must remain TCP 1883")
|
||||
if network.get("tls") is not False or network.get("authentication") != "none-observed":
|
||||
raise CompatibilityProfileError("direct-LAN MQTT security claim differs from observation")
|
||||
raise CompatibilityProfileError("local MQTT security claim differs from observation")
|
||||
allowlist = _array(
|
||||
mqtt.get("subscription_allowlist"),
|
||||
"$.transports[mqtt].subscription_allowlist",
|
||||
@@ -202,7 +247,7 @@ def _validate_transports(profile: dict[str, Any]) -> None:
|
||||
)
|
||||
_expect_evidence(
|
||||
mqtt,
|
||||
"$.transports[mqtt.direct-lan.fw3.v1]",
|
||||
"$.transports[mqtt.local-ipv4.fw3.v1]",
|
||||
observed=True,
|
||||
decoded=False,
|
||||
replay_verified=False,
|
||||
@@ -504,7 +549,7 @@ def _validate_acquisition_control(profile: dict[str, Any]) -> None:
|
||||
|
||||
|
||||
def validate_compatibility_profile(profile: Any) -> dict[str, Any]:
|
||||
"""Validate and return one read-only firmware-3/direct-LAN profile object."""
|
||||
"""Validate the read-only firmware-3 local connection matrix."""
|
||||
root = _object(profile, "$")
|
||||
if root.get("schema_version") != PROFILE_SCHEMA_VERSION:
|
||||
raise CompatibilityProfileError("unsupported compatibility profile schema_version")
|
||||
@@ -519,8 +564,9 @@ def validate_compatibility_profile(profile: Any) -> dict[str, Any]:
|
||||
firmware = _object(scope.get("firmware"), "$.scope.firmware")
|
||||
if firmware != {"match": "exact", "version": "3.0.2"}:
|
||||
raise CompatibilityProfileError("profile must match firmware 3.0.2 exactly")
|
||||
if scope.get("topology") != "direct-lan":
|
||||
raise CompatibilityProfileError("profile topology must remain direct-lan")
|
||||
if scope.get("topology") != "local-network-matrix":
|
||||
raise CompatibilityProfileError("profile topology must remain local-network-matrix")
|
||||
_validate_connection_modes(scope)
|
||||
|
||||
vocabulary = _object(root.get("evidence_vocabulary"), "$.evidence_vocabulary")
|
||||
if set(vocabulary) != set(EVIDENCE_FLAGS):
|
||||
@@ -580,7 +626,10 @@ def matches_target(
|
||||
validated = validate_compatibility_profile(profile)
|
||||
scope = validated["scope"]
|
||||
firmware_scope = _object(scope.get("firmware"), "$.scope.firmware")
|
||||
return firmware_scope.get("version") == firmware and scope.get("topology") == topology
|
||||
modes = _array(scope.get("connection_modes"), "$.scope.connection_modes")
|
||||
return firmware_scope.get("version") == firmware and any(
|
||||
isinstance(mode, dict) and mode.get("topology") == topology for mode in modes
|
||||
)
|
||||
|
||||
|
||||
def _main() -> int:
|
||||
|
||||
Reference in New Issue
Block a user