"""Versioned Shard lifecycle and structured status contract. This module defines the semantic contract consumed by a future generated gRPC binding. It deliberately contains no Meshnet routing, authentication policy, billing, or llama.cpp types. """ from __future__ import annotations from dataclasses import dataclass, field from enum import Enum import json import threading from typing import Any, Callable, ClassVar SCHEMA_NAME = "meshnet.shard-runtime" SCHEMA_VERSION = 1 SUPPORTED_VERSIONS = frozenset({SCHEMA_VERSION}) DEFAULT_MAX_INFLIGHT_FRAMES = 32 DEFAULT_MAX_INFLIGHT_BYTES = 8 * 1024 * 1024 class RpcName(str, Enum): CAPABILITY = "GetCapability" HEALTH = "CheckHealth" SESSION = "OpenSession" CANCEL = "CancelSession" RELEASE = "ReleaseSession" METRICS = "GetMetrics" class StatusCode(str, Enum): OK = "OK" INVALID_ARGUMENT = "INVALID_ARGUMENT" UNSUPPORTED_VERSION = "UNSUPPORTED_VERSION" FAILED_PRECONDITION = "FAILED_PRECONDITION" MALFORMED_LIFECYCLE = "MALFORMED_LIFECYCLE" NOT_FOUND = "NOT_FOUND" ALREADY_EXISTS = "ALREADY_EXISTS" CANCELLED = "CANCELLED" DEADLINE_EXCEEDED = "DEADLINE_EXCEEDED" RESOURCE_EXHAUSTED = "RESOURCE_EXHAUSTED" UNAUTHENTICATED = "UNAUTHENTICATED" PERMISSION_DENIED = "PERMISSION_DENIED" DATA_LOSS = "DATA_LOSS" UNAVAILABLE = "UNAVAILABLE" INTERNAL = "INTERNAL" class LifecycleState(str, Enum): OPEN = "OPEN" PREFILLING = "PREFILLING" DECODING = "DECODING" CANCELLING = "CANCELLING" CANCELLED = "CANCELLED" RELEASING = "RELEASING" RELEASED = "RELEASED" FAILED = "FAILED" class CacheExpectation(str, Enum): NONE = "NONE" OPTIONAL = "OPTIONAL" REQUIRED = "REQUIRED" class CacheResult(str, Enum): NOT_REQUESTED = "NOT_REQUESTED" HIT = "HIT" MISS = "MISS" INVALIDATED = "INVALIDATED" STORED = "STORED" class SessionPhase(str, Enum): PREFILL = "PREFILL" DECODE = "DECODE" class LifecycleContractError(ValueError): """A protocol violation represented by a structured status.""" def __init__(self, status: "StructuredStatus") -> None: self.status = status super().__init__(status.message) @dataclass(frozen=True) class StructuredStatus: code: StatusCode message: str retryable: bool = False details: dict[str, str] = field(default_factory=dict) def to_dict(self) -> dict[str, Any]: return { "code": self.code.value, "message": self.message, "retryable": self.retryable, "details": dict(sorted(self.details.items())), } @classmethod def from_dict(cls, value: dict[str, Any]) -> "StructuredStatus": return cls( code=StatusCode(str(value["code"])), message=str(value["message"]), retryable=bool(value.get("retryable", False)), details={str(k): str(v) for k, v in value.get("details", {}).items()}, ) @dataclass(frozen=True) class DeadlinePolicy: capability_seconds: float = 5.0 health_seconds: float = 2.0 session_open_seconds: float = 10.0 session_idle_seconds: float = 30.0 cancel_seconds: float = 2.0 release_seconds: float = 5.0 metrics_seconds: float = 5.0 def __post_init__(self) -> None: if any(value <= 0 for value in self.__dict__.values()): raise ValueError("all RPC deadlines must be positive") @dataclass(frozen=True) class TlsAuthHooks: """Transport hooks only; Meshnet remains the identity and billing authority.""" tls_required: bool = True server_name: str = "shard.meshnet" client_certificate_hook: str | None = None peer_identity_hook: str | None = None auth_metadata_hook: str | None = None def validate(self) -> None: if self.tls_required and not self.server_name: raise ValueError("TLS server_name is required when TLS is enabled") @dataclass(frozen=True) class FlowControlLimits: max_inflight_frames: int = DEFAULT_MAX_INFLIGHT_FRAMES max_inflight_bytes: int = DEFAULT_MAX_INFLIGHT_BYTES max_frame_bytes: int = 1024 * 1024 def __post_init__(self) -> None: if min(self.max_inflight_frames, self.max_inflight_bytes, self.max_frame_bytes) <= 0: raise ValueError("flow-control limits must be positive") class FlowControl: """Bounded sender window; callers block or fail instead of growing unbounded.""" def __init__(self, limits: FlowControlLimits = FlowControlLimits()) -> None: self.limits = limits self._condition = threading.Condition() self._frames = 0 self._bytes = 0 @property def outstanding(self) -> tuple[int, int]: with self._condition: return self._frames, self._bytes def acquire(self, size: int, *, wait: bool = False, cancelled: Callable[[], bool] | None = None) -> None: if size < 0 or size > self.limits.max_frame_bytes: raise LifecycleContractError(StructuredStatus( StatusCode.RESOURCE_EXHAUSTED, "frame exceeds bounded flow-control window", details={"max_frame_bytes": str(self.limits.max_frame_bytes)}, )) with self._condition: while ( self._frames >= self.limits.max_inflight_frames or self._bytes + size > self.limits.max_inflight_bytes ): if cancelled and cancelled(): raise LifecycleContractError(StructuredStatus(StatusCode.CANCELLED, "flow-control wait cancelled")) if not wait: raise LifecycleContractError(StructuredStatus( StatusCode.RESOURCE_EXHAUSTED, "flow-control window is full", retryable=True, )) self._condition.wait(timeout=0.05) self._frames += 1 self._bytes += size def release(self, size: int) -> None: with self._condition: self._frames = max(0, self._frames - 1) self._bytes = max(0, self._bytes - max(0, size)) self._condition.notify_all() class CancellationToken: def __init__(self) -> None: self._event = threading.Event() @property def cancelled(self) -> bool: return self._event.is_set() def cancel(self) -> None: self._event.set() @dataclass(frozen=True) class CapabilityRequest: schema_version: int = SCHEMA_VERSION @dataclass(frozen=True) class CapabilityResponse: status: StructuredStatus schema_version: int supported_versions: tuple[int, ...] artifact_fingerprint: str = "" runtime_fingerprint: str = "" shard_start: int = 0 shard_end: int = 0 effective_start: int = 0 max_sessions: int = 0 max_frame_bytes: int = DEFAULT_MAX_INFLIGHT_BYTES def validate(self) -> None: if self.status.code is StatusCode.OK and self.schema_version not in SUPPORTED_VERSIONS: raise LifecycleContractError(StructuredStatus( StatusCode.UNSUPPORTED_VERSION, "worker selected an unsupported schema version", )) if self.shard_end < self.shard_start or self.effective_start < self.shard_start: raise LifecycleContractError(StructuredStatus( StatusCode.INVALID_ARGUMENT, "invalid authoritative shard range", )) @dataclass(frozen=True) class HealthRequest: schema_version: int = SCHEMA_VERSION include_metrics: bool = False @dataclass(frozen=True) class HealthResponse: status: StructuredStatus serving: bool state: str active_sessions: int = 0 @dataclass(frozen=True) class SessionRequest: schema_version: int request_id: str work_id: str route_session: str route_epoch: int artifact_fingerprint: str runtime_fingerprint: str shard_start: int shard_end: int effective_start: int cache_expectation: CacheExpectation = CacheExpectation.NONE deadline_seconds: float = 30.0 def validate(self) -> None: if self.schema_version not in SUPPORTED_VERSIONS: raise LifecycleContractError(StructuredStatus( StatusCode.UNSUPPORTED_VERSION, "unsupported session schema version", details={"requested": str(self.schema_version), "supported": "1"}, )) if not self.request_id or not self.work_id or not self.route_session: raise LifecycleContractError(StructuredStatus( StatusCode.INVALID_ARGUMENT, "request, work, and route-session IDs are required", )) if self.route_epoch < 0 or self.shard_start < 0 or self.shard_end <= self.shard_start: raise LifecycleContractError(StructuredStatus( StatusCode.INVALID_ARGUMENT, "invalid route epoch or shard range", )) if not self.shard_start <= self.effective_start <= self.shard_end: raise LifecycleContractError(StructuredStatus( StatusCode.INVALID_ARGUMENT, "effective start must be inside the shard range", )) if self.deadline_seconds <= 0: raise LifecycleContractError(StructuredStatus( StatusCode.INVALID_ARGUMENT, "session deadline must be positive", )) @dataclass(frozen=True) class SessionFrame: phase: SessionPhase position: int idempotency_step: int payload: Any cache_expectation: CacheExpectation = CacheExpectation.NONE size_bytes: int = 0 def validate(self, limits: FlowControlLimits) -> None: if self.position < 0 or self.idempotency_step < 0: raise LifecycleContractError(StructuredStatus( StatusCode.INVALID_ARGUMENT, "position and idempotency step must be non-negative", )) if self.size_bytes < 0 or self.size_bytes > limits.max_frame_bytes: raise LifecycleContractError(StructuredStatus( StatusCode.RESOURCE_EXHAUSTED, "session frame exceeds max_frame_bytes", )) @dataclass(frozen=True) class SessionResult: status: StructuredStatus cache_result: CacheResult = CacheResult.NOT_REQUESTED position: int = 0 idempotency_step: int = 0 payload: Any = None @dataclass(frozen=True) class CancelRequest: schema_version: int request_id: str work_id: str route_session: str route_epoch: int reason: str = "" @dataclass(frozen=True) class ReleaseRequest: schema_version: int request_id: str work_id: str route_session: str route_epoch: int @dataclass(frozen=True) class MetricsRequest: schema_version: int = SCHEMA_VERSION @dataclass(frozen=True) class MetricsResponse: status: StructuredStatus active_sessions: int queued_frames: int inflight_bytes: int kv_entries: int generated_tokens: int cancelled_sessions: int @dataclass class SessionLifecycle: """Fail-closed state machine for one Route Session Activation Seam.""" request: SessionRequest state: LifecycleState = LifecycleState.OPEN cancellation: CancellationToken = field(default_factory=CancellationToken) last_idempotency_step: int = -1 _seen_steps: set[int] = field(default_factory=set, init=False, repr=False) _ALLOWED: ClassVar[dict[LifecycleState, frozenset[LifecycleState]]] = { LifecycleState.OPEN: frozenset({LifecycleState.PREFILLING, LifecycleState.CANCELLING, LifecycleState.RELEASING, LifecycleState.FAILED}), LifecycleState.PREFILLING: frozenset({LifecycleState.PREFILLING, LifecycleState.DECODING, LifecycleState.CANCELLING, LifecycleState.RELEASING, LifecycleState.FAILED}), LifecycleState.DECODING: frozenset({LifecycleState.DECODING, LifecycleState.CANCELLING, LifecycleState.RELEASING, LifecycleState.FAILED}), LifecycleState.CANCELLING: frozenset({LifecycleState.CANCELLED, LifecycleState.RELEASING, LifecycleState.FAILED}), LifecycleState.CANCELLED: frozenset({LifecycleState.RELEASING, LifecycleState.RELEASED}), LifecycleState.RELEASING: frozenset({LifecycleState.RELEASED, LifecycleState.FAILED}), LifecycleState.RELEASED: frozenset(), LifecycleState.FAILED: frozenset({LifecycleState.RELEASING, LifecycleState.RELEASED}), } def _transition(self, target: LifecycleState) -> None: if target not in self._ALLOWED[self.state]: raise LifecycleContractError(StructuredStatus( StatusCode.MALFORMED_LIFECYCLE, f"cannot transition from {self.state.value} to {target.value}", details={"state": self.state.value, "target": target.value}, )) self.state = target def apply(self, frame: SessionFrame) -> None: frame.validate(FlowControlLimits()) if self.cancellation.cancelled and frame.phase is not SessionPhase.PREFILL: raise LifecycleContractError(StructuredStatus(StatusCode.CANCELLED, "session cancellation propagated")) if frame.idempotency_step in self._seen_steps: raise LifecycleContractError(StructuredStatus( StatusCode.ALREADY_EXISTS, "duplicate idempotency step", details={"step": str(frame.idempotency_step)}, )) if frame.idempotency_step <= self.last_idempotency_step: raise LifecycleContractError(StructuredStatus( StatusCode.MALFORMED_LIFECYCLE, "idempotency steps must increase monotonically", )) target = LifecycleState.PREFILLING if frame.phase is SessionPhase.PREFILL else LifecycleState.DECODING self._transition(target) self._seen_steps.add(frame.idempotency_step) self.last_idempotency_step = frame.idempotency_step def cancel(self, reason: str = "") -> StructuredStatus: if self.state in {LifecycleState.RELEASED, LifecycleState.RELEASING}: return StructuredStatus(StatusCode.FAILED_PRECONDITION, "session is already releasing or released") if self.state is LifecycleState.CANCELLED: return StructuredStatus(StatusCode.OK, "session already cancelled") self._transition(LifecycleState.CANCELLING) self.cancellation.cancel() self._transition(LifecycleState.CANCELLED) return StructuredStatus(StatusCode.CANCELLED, reason or "session cancelled") def release(self) -> StructuredStatus: if self.state is LifecycleState.RELEASED: return StructuredStatus(StatusCode.OK, "session already released") self._transition(LifecycleState.RELEASING) self.cancellation.cancel() self._transition(LifecycleState.RELEASED) return StructuredStatus(StatusCode.OK, "session released") @dataclass(frozen=True) class ShardRpcContract: """Service/method and operational rules for generated gRPC bindings.""" schema: str = SCHEMA_NAME version: int = SCHEMA_VERSION methods: tuple[RpcName, ...] = tuple(RpcName) deadlines: DeadlinePolicy = DeadlinePolicy() flow_control: FlowControlLimits = FlowControlLimits() tls_auth: TlsAuthHooks = TlsAuthHooks() def validate(self) -> None: if self.schema != SCHEMA_NAME or self.version not in SUPPORTED_VERSIONS: raise LifecycleContractError(StructuredStatus( StatusCode.UNSUPPORTED_VERSION, "unsupported Shard RPC contract version", )) if self.methods != tuple(RpcName): raise LifecycleContractError(StructuredStatus( StatusCode.FAILED_PRECONDITION, "contract must expose the complete lifecycle RPC set", )) self.tls_auth.validate() def to_bytes(self) -> bytes: self.validate() data = { "schema": self.schema, "version": self.version, "methods": [method.value for method in self.methods], "deadlines": self.deadlines.__dict__, "flow_control": self.flow_control.__dict__, "tls_auth": self.tls_auth.__dict__, } return json.dumps(data, sort_keys=True, separators=(",", ":")).encode("utf-8") @classmethod def from_bytes(cls, raw: bytes) -> "ShardRpcContract": data = json.loads(raw) if int(data.get("version", -1)) not in SUPPORTED_VERSIONS: raise LifecycleContractError(StructuredStatus( StatusCode.UNSUPPORTED_VERSION, "unsupported Shard RPC contract version", )) methods = tuple(RpcName(item) for item in data.get("methods", ())) contract = cls( schema=str(data.get("schema", "")), version=int(data["version"]), methods=methods, deadlines=DeadlinePolicy(**data.get("deadlines", {})), flow_control=FlowControlLimits(**data.get("flow_control", {})), tls_auth=TlsAuthHooks(**data.get("tls_auth", {})), ) contract.validate() return contract