134 lines
4.1 KiB
Python
134 lines
4.1 KiB
Python
#!/usr/bin/env python3
|
|
"""Trusted latest-assistant-message observer boundary for receipt promotion.
|
|
|
|
Production adapters deliver finalized assistant content over the daemon-owned
|
|
observer socket after the daemon authenticates their peer against the broker's
|
|
kernel-anchored session identity. The broker request protocol never accepts
|
|
assistant-message content. Claude supplies its latest assistant entry; Pi
|
|
supplies finalized assistant content at ``message_end``.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import os
|
|
import stat
|
|
from pathlib import Path
|
|
from typing import Protocol
|
|
|
|
|
|
class ReceiptObserver(Protocol):
|
|
def observe_latest_assistant_message(
|
|
self,
|
|
session_id: str,
|
|
runtime: str,
|
|
runtime_generation: int,
|
|
binding: dict[str, object],
|
|
) -> str | None: ...
|
|
|
|
|
|
class UnavailableReceiptObserver:
|
|
"""Fail-closed only for direct unit construction without daemon transport."""
|
|
|
|
def observe_latest_assistant_message(
|
|
self,
|
|
_session_id: str,
|
|
_runtime: str,
|
|
_runtime_generation: int,
|
|
_binding: dict[str, object],
|
|
) -> str | None:
|
|
return None
|
|
|
|
|
|
class RuntimeReceiptObserver:
|
|
"""Daemon-owned production observer populated only by authenticated adapters."""
|
|
|
|
def __init__(self) -> None:
|
|
self._messages: dict[tuple[str, str, int], str] = {}
|
|
|
|
def record_latest_assistant_message(
|
|
self,
|
|
session_id: str,
|
|
runtime: str,
|
|
runtime_generation: int,
|
|
message: str,
|
|
) -> None:
|
|
self._messages[(session_id, runtime, runtime_generation)] = message
|
|
|
|
def observe_latest_assistant_message(
|
|
self,
|
|
session_id: str,
|
|
runtime: str,
|
|
runtime_generation: int,
|
|
_binding: dict[str, object],
|
|
) -> str | None:
|
|
return self._messages.get((session_id, runtime, runtime_generation))
|
|
|
|
|
|
class TestReceiptObserver:
|
|
"""Deterministic controlled observer used only by byte-build tests."""
|
|
|
|
def __init__(self) -> None:
|
|
self._messages: dict[tuple[str, int], str] = {}
|
|
|
|
def record_latest_assistant_message(
|
|
self, session_id: str, runtime_generation: int, message: str
|
|
) -> None:
|
|
self._messages[(session_id, runtime_generation)] = message
|
|
|
|
def observe_latest_assistant_message(
|
|
self,
|
|
session_id: str,
|
|
_runtime: str,
|
|
runtime_generation: int,
|
|
_binding: dict[str, object],
|
|
) -> str | None:
|
|
return self._messages.get((session_id, runtime_generation))
|
|
|
|
|
|
class FileTestReceiptObserver:
|
|
"""Private fixture-file observer for isolated out-of-process test drivers only."""
|
|
|
|
def __init__(self, path: Path) -> None:
|
|
self.path = path
|
|
|
|
def observe_latest_assistant_message(
|
|
self,
|
|
session_id: str,
|
|
_runtime: str,
|
|
runtime_generation: int,
|
|
_binding: dict[str, object],
|
|
) -> str | None:
|
|
flags = os.O_RDONLY | getattr(os, "O_CLOEXEC", 0) | getattr(os, "O_NOFOLLOW", 0)
|
|
try:
|
|
descriptor = os.open(self.path, flags)
|
|
except OSError:
|
|
return None
|
|
try:
|
|
metadata = os.fstat(descriptor)
|
|
if (
|
|
not stat.S_ISREG(metadata.st_mode)
|
|
or stat.S_IMODE(metadata.st_mode) != 0o600
|
|
or metadata.st_uid != os.geteuid()
|
|
or metadata.st_size > 64 * 1024
|
|
):
|
|
return None
|
|
raw = os.read(descriptor, 64 * 1024 + 1)
|
|
finally:
|
|
os.close(descriptor)
|
|
if len(raw) > 64 * 1024:
|
|
return None
|
|
try:
|
|
value = json.loads(raw)
|
|
except (json.JSONDecodeError, UnicodeDecodeError):
|
|
return None
|
|
if (
|
|
not isinstance(value, dict)
|
|
or set(value) != {"session_id", "runtime_generation", "latest_assistant_message"}
|
|
or value["session_id"] != session_id
|
|
or value["runtime_generation"] != runtime_generation
|
|
or not isinstance(value["latest_assistant_message"], str)
|
|
):
|
|
return None
|
|
return value["latest_assistant_message"]
|