feat(observatory): attest recording equipment and capture profiles

This commit is contained in:
DCCONSTRUCTIONS
2026-09-02 00:57:27 +03:00
parent 7025e173a3
commit d655d6998d
17 changed files with 1089 additions and 42 deletions
@@ -0,0 +1,209 @@
from __future__ import annotations
from pathlib import Path
from k1link.observatory.portable_run_definitions import PortableRunDefinitionRegistry
from k1link.observatory.portable_setup_projection import PortableSetupProjector
from k1link.sessions.equipment import (
EquipmentCaptureRegistry,
RecordedCaptureAttestation,
)
from k1link.sessions.models import (
ObservationArtifactCandidate,
ObservationSessionCandidate,
SessionSource,
SessionSummary,
)
from k1link.sessions.plugin_contract import ObservationArchiveSource
from k1link.sessions.store import SessionStore
REPOSITORY_ROOT = Path(__file__).resolve().parents[1]
def _equipment_registry() -> EquipmentCaptureRegistry:
registry = EquipmentCaptureRegistry.from_repository(REPOSITORY_ROOT)
assert registry is not None
return registry
def _definition_registry() -> PortableRunDefinitionRegistry:
return PortableRunDefinitionRegistry.from_file(
REPOSITORY_ROOT / "config" / "observatory-portable-run-definitions.json"
)
def test_k1_equipment_and_capture_profiles_have_exact_content_identities() -> None:
registry = _equipment_registry()
assert len(registry.equipment_models) == 1
assert len(registry.capture_profiles) == 1
equipment = registry.equipment_models[0]
capture = registry.capture_profiles[0]
assert equipment.equipment_model_id == "xgrids.lixelkity-k1"
assert equipment.equipment_model_sha256 == (
"c95d7183ffd2e425892fd9ddfc4cd8dcbccc0231289127ddc14db6b52bbb92aa"
)
assert capture.equipment == equipment
for definition in _definition_registry().definitions:
assert (
registry.compatible_profile_for_requirements(
definition.source_requirements.as_dict()
)
== capture
)
def test_session_store_persists_immutable_k1_capture_attestation(tmp_path: Path) -> None:
archive_root = tmp_path / "evidence"
session_root = archive_root / "recording-001"
session_root.mkdir(parents=True)
raw = session_root / "capture.bin"
video = session_root / "camera.mp4"
raw.write_bytes(b"sealed spatial capture")
video.write_bytes(b"sealed camera capture")
candidate = _k1_candidate(archive_root, session_root, raw, video)
source = ObservationArchiveSource(
plugin_id="nodedc.device.xgrids-lixelkity-k1",
archive_id="xgrids-k1.viewer-live.evidence",
root=archive_root,
discover=lambda _root: (candidate,),
)
data_dir = tmp_path / "data"
store = SessionStore(REPOSITORY_ROOT, data_dir=data_dir)
assert store.reconcile_archive(source) == ("recording-001",)
attestation = store.get_session("recording-001").summary.capture_attestation
assert attestation is not None
assert attestation.equipment_model_id == "xgrids.lixelkity-k1"
assert attestation.capture_profile_id == "xgrids-k1.viewer-live.fw-3.0.2.v1"
assert attestation.state == "attested-with-legacy-evidence"
reopened = SessionStore(REPOSITORY_ROOT, data_dir=data_dir)
assert reopened.get_session("recording-001").summary.capture_attestation == attestation
def test_other_equipment_is_blocked_before_any_profile_probe() -> None:
registry = _equipment_registry()
calls: list[str] = []
class Probe:
def probe(self, **kwargs: str) -> object:
calls.append(kwargs["source_session_id"])
raise AssertionError("incompatible equipment must not reach source probing")
projector = PortableSetupProjector(
registry=_definition_registry(),
capability_probe=Probe(),
dispatch_available=True,
equipment_capture_registry=registry,
)
source = _summary(
RecordedCaptureAttestation(
equipment_model_id="example.other-scanner",
equipment_model_sha256="1" * 64,
equipment_display_name="Other scanner",
capture_profile_id="example.other.capture.v1",
capture_profile_sha256="2" * 64,
capture_attestation_sha256="3" * 64,
state="attested",
)
)
catalog = projector.catalog(source)
assert calls == []
assert len(catalog["setups"]) == 2
for setup in catalog["setups"]:
assert setup["source_compatibility"]["compatible"] is False
assert setup["source_compatibility"]["reason_code"] == (
"equipment-model-mismatch"
)
assert setup["preflight"]["submission_allowed"] is False
def _summary(attestation: RecordedCaptureAttestation) -> SessionSummary:
return SessionSummary(
session_id="other-equipment-recording-001",
display_name="Other equipment",
status="ready",
started_at_utc="2026-09-01T10:00:00Z",
completed_at_utc="2026-09-01T10:01:00Z",
duration_seconds=60.0,
modalities=("point-cloud", "trajectory", "video"),
source_count=3,
total_bytes=1,
replayable=True,
origin="example.other.archive",
capture_attestation=attestation,
)
def _k1_candidate(
archive_root: Path,
session_root: Path,
raw: Path,
video: Path,
) -> ObservationSessionCandidate:
return ObservationSessionCandidate(
session_id="recording-001",
display_name="K1 recording",
status="ready",
started_at_utc="2026-09-01T10:00:00Z",
completed_at_utc="2026-09-01T10:01:00Z",
duration_seconds=60.0,
modalities=("point-cloud", "trajectory", "video"),
replayable=True,
total_bytes=raw.stat().st_size + video.stat().st_size,
allowed_root=archive_root,
session_root=session_root,
primary_replay_artifact_id="raw-transport-primary",
timeline_origin_epoch_ns=1,
timeline_origin_monotonic_ns=1,
sources=(
SessionSource(
source_id="sensor.lidar.primary",
semantic_channel_id="spatial.point-cloud.recorded",
modality="point-cloud",
status="recorded",
seekable=True,
artifact_id="raw-transport-primary",
),
SessionSource(
source_id="spatial.trajectory",
semantic_channel_id="spatial.pose.recorded",
modality="trajectory",
status="recorded",
seekable=True,
artifact_id="raw-transport-primary",
),
SessionSource(
source_id="sensor.camera.right",
semantic_channel_id="camera.video.recorded",
modality="video",
status="recorded",
seekable=True,
artifact_id="camera-right",
),
),
artifacts=(
ObservationArtifactCandidate(
artifact_id="raw-transport-primary",
kind="native-recording",
media_type="application/x-k1-recording",
locator=raw,
byte_length=raw.stat().st_size,
replay_byte_length=raw.stat().st_size,
sha256=None,
integrity_status="validated-structure",
),
ObservationArtifactCandidate(
artifact_id="camera-right",
kind="recorded-video",
media_type="video/mp4",
locator=video,
byte_length=video.stat().st_size,
replay_byte_length=0,
sha256=None,
integrity_status="validated-structure",
),
),
)
@@ -174,22 +174,23 @@ def test_calculation_profile_policies_cover_both_exact_portable_definitions() ->
assert resolved["m49-tgs-portable-v2"].display_name == PORTABLE_M49_DISPLAY_NAME
def test_new_compatible_source_passes_capability_but_uninstalled_executor_blocks() -> None:
def test_new_compatible_source_passes_capability_but_disabled_dispatch_blocks() -> None:
source = _source(NEW_SESSION_ID)
setup = _projector(lambda session_id: _capability(session_id)).project(source)
assert setup["source_compatibility"] == {
"outcome": "pass",
"compatible": True,
"reason_code": "source-compatible",
"reason": "Запись соответствует требованиям EoMT + DDRNet.",
}
assert setup["executor"]["state"] == "not-installed"
assert setup["executor"]["ready"] is False
assert setup["executor"]["state"] == "ready"
assert setup["executor"]["ready"] is True
assert setup["existing_results"] == []
assert setup["preflight"] == {
"outcome": "blocked",
"action": "blocked",
"reason": "Вычислительный контур LAB V1 пока недоступен.",
"reason": "Server-side проверка и постановка portable-сетапа в очередь недоступны.",
"submission_allowed": False,
"existing_result_ids": [],
}
@@ -207,7 +208,7 @@ def test_legacy_vegetation_result_is_never_existing_for_portable_v2() -> None:
assert setup["preflight"] == {
"outcome": "blocked",
"action": "blocked",
"reason": "Вычислительный контур LAB V1 пока недоступен.",
"reason": "Server-side проверка и постановка portable-сетапа в очередь недоступны.",
"submission_allowed": False,
"existing_result_ids": [],
}
@@ -225,6 +226,7 @@ def test_real_capability_probe_rejection_wins_over_summary() -> None:
assert setup["source_compatibility"] == {
"outcome": "blocked",
"compatible": False,
"reason_code": "source-contract-mismatch",
"reason": "Запись не соответствует требованиям EoMT + DDRNet.",
}
assert setup["existing_results"] == []
+1
View File
@@ -292,6 +292,7 @@ def test_session_router_lists_details_and_dispatches_opaque_replay(tmp_path: Pat
"modalities": ["point-cloud", "trajectory"],
"duration_seconds": 1440.1,
"replayable": True,
"capture_attestation": None,
}
assert detail["timeline"]["seekable"] is True
assert detail["modalities"] == ["point-cloud", "trajectory"]