feat(plugins): isolate device integrations

This commit is contained in:
DCCONSTRUCTIONS
2026-07-17 19:29:32 +03:00
parent f9ffb7bd1c
commit 24a47318f2
122 changed files with 3304 additions and 1892 deletions
+47 -13
View File
@@ -160,20 +160,44 @@ class WorkspaceLayout:
}
@dataclass(frozen=True, slots=True)
class ReplayArtifact:
"""One confined input artifact selected for plugin-owned preparation."""
artifact_id: str
path: Path
media_type: str
file_byte_length: int
replay_byte_length: int
expected_sha256: str | None
@dataclass(frozen=True, slots=True)
class ReplayCommand:
"""Internal-only replay command. ``source_path`` never enters an API DTO."""
"""Internal replay request containing no vendor format or channel names."""
session_id: str
source_path: Path
plugin_id: str
allowed_root: Path
session_root: Path
replay_byte_length: int
metadata_byte_length: int
expected_source_sha256: str | None
primary_artifact_id: str
artifacts: tuple[ReplayArtifact, ...]
timeline_origin_epoch_ns: int
timeline_origin_monotonic_ns: int
speed: float
loop: bool
@property
def primary_artifact(self) -> ReplayArtifact:
matches = tuple(
artifact
for artifact in self.artifacts
if artifact.artifact_id == self.primary_artifact_id
)
if len(matches) != 1:
raise SessionIntegrityError("replay command has no unique primary artifact")
return matches[0]
@dataclass(frozen=True, slots=True)
class RecordedMediaArtifact:
@@ -191,7 +215,19 @@ class RecordedMediaArtifact:
@dataclass(frozen=True, slots=True)
class LegacySessionCandidate:
class ObservationArtifactCandidate:
artifact_id: str
kind: str
media_type: str
locator: Path
byte_length: int
replay_byte_length: int
sha256: str | None
integrity_status: str
@dataclass(frozen=True, slots=True)
class ObservationSessionCandidate:
session_id: str
display_name: str
status: SessionStatus
@@ -203,13 +239,11 @@ class LegacySessionCandidate:
total_bytes: int
allowed_root: Path
session_root: Path
raw_path: Path
raw_byte_length: int
replay_raw_byte_length: int
replay_metadata_byte_length: int
raw_sha256: str | None
raw_integrity_status: str
media_sources: tuple[LegacyMediaSourceCandidate, ...]
primary_replay_artifact_id: str | None
timeline_origin_epoch_ns: int | None
timeline_origin_monotonic_ns: int | None
sources: tuple[SessionSource, ...]
artifacts: tuple[ObservationArtifactCandidate, ...]
@dataclass(frozen=True, slots=True)