feat: add live K1 Foxglove console

This commit is contained in:
DCCONSTRUCTIONS
2026-07-15 21:53:43 +03:00
parent 6b22e5a1d2
commit 6be96f0b85
34 changed files with 6037 additions and 15 deletions
+51 -2
View File
@@ -95,11 +95,13 @@ def test_validate_private_ipv4_rejects_other_targets(address: str) -> None:
def test_capture_writes_verifiable_frames_metadata_and_summary(tmp_path: Path) -> None:
fake = FakeClient()
observed = []
summary = capture_mqtt(
"192.168.1.50",
tmp_path / "capture",
duration_seconds=30,
on_message_recorded=observed.append,
_client_factory=lambda: cast(mqtt.Client, fake),
)
@@ -110,6 +112,10 @@ def test_capture_writes_verifiable_frames_metadata_and_summary(tmp_path: Path) -
assert summary["message_count"] == 1
assert summary["payload_bytes"] == len(fake.payload)
assert summary["subscriptions"] == list(REPORT_TOPICS)
assert len(observed) == 1
assert observed[0].topic == fake.topic
assert observed[0].payload == fake.payload
assert observed[0].received_at_epoch_ns > 0
capture_dir = tmp_path / "capture"
raw = (capture_dir / "mqtt.raw.k1mqtt").read_bytes()
@@ -122,14 +128,14 @@ def test_capture_writes_verifiable_frames_metadata_and_summary(tmp_path: Path) -
assert raw[payload_start:] == fake.payload
records: list[dict[str, object]] = [
json.loads(line)
for line in (capture_dir / "mqtt.metadata.jsonl").read_text().splitlines()
json.loads(line) for line in (capture_dir / "mqtt.metadata.jsonl").read_text().splitlines()
]
assert len(records) == 1
record = records[0]
assert record["record_type"] == "message"
assert record["topic"] == fake.topic
assert record["payload_bytes"] == len(fake.payload)
assert isinstance(record["received_at_epoch_ns"], int)
assert record["payload_sha256"] == hashlib.sha256(fake.payload).hexdigest()
assert record["raw_frame_offset"] == len(RAW_MAGIC)
assert record["raw_payload_offset"] == payload_start
@@ -187,6 +193,49 @@ def test_capture_refuses_to_overwrite_existing_artifacts(tmp_path: Path) -> None
assert raw.read_bytes() == b"existing evidence"
def test_capture_can_be_stopped_by_owner_without_losing_artifacts(tmp_path: Path) -> None:
fake = FakeClient()
stop_checks = 0
def should_stop() -> bool:
nonlocal stop_checks
stop_checks += 1
return stop_checks >= 4
summary = capture_mqtt(
"192.168.1.50",
tmp_path / "capture",
duration_seconds=30,
should_stop=should_stop,
_client_factory=lambda: cast(mqtt.Client, fake),
)
assert summary["stop_reason"] == "external_stop"
assert summary["message_count"] == 1
assert list(iter_capture_frames(tmp_path / "capture" / "mqtt.raw.k1mqtt"))[0].payload
def test_preview_failure_happens_after_raw_message_is_preserved(tmp_path: Path) -> None:
fake = FakeClient()
capture_dir = tmp_path / "capture"
def fail_preview(_message: object) -> None:
raise ValueError("synthetic preview failure")
with pytest.raises(CaptureError, match="preview callback failed") as error:
capture_mqtt(
"192.168.1.50",
capture_dir,
on_message_recorded=fail_preview,
_client_factory=lambda: cast(mqtt.Client, fake),
)
assert error.value.summary is not None
assert error.value.summary["message_count"] == 1
frames = list(iter_capture_frames(capture_dir / "mqtt.raw.k1mqtt"))
assert frames[0].payload == fake.payload
@pytest.mark.parametrize(
("raw", "message"),
[