Coverage for src / lexigram / contracts / ai / governance / resource_unit.py: 0%
42 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-08-15 18:57 +0800
« prev ^ index » next coverage.py v7.13.5, created at 2026-08-15 18:57 +0800
1"""Resource unit contracts for per-tenant resource quotas (LXF-001)."""
3from __future__ import annotations
5from dataclasses import dataclass
6from datetime import datetime, timedelta
7from enum import Enum
9from lexigram.contracts.ai.governance.errors import GovernanceError
12class ResourceWindowKind(str, Enum):
13 """Time window strategy for resource tracking."""
15 SLIDING = "sliding"
16 CALENDAR = "calendar"
17 INSTANTANEOUS = "instantaneous"
20@dataclass(frozen=True, slots=True)
21class ResourceUnit:
22 """A measurable resource the governance system tracks per tenant."""
24 name: str
25 unit_kind: str
26 window: timedelta | None = None
27 window_kind: ResourceWindowKind = ResourceWindowKind.SLIDING
30@dataclass(frozen=True, slots=True)
31class ResourceQuota:
32 """Per-tenant quota for a specific resource unit."""
34 tenant_id: str
35 unit: ResourceUnit
36 limit: float
37 soft_threshold_pct: float | None = None
40@dataclass(frozen=True, slots=True)
41class ResourceUsageSnapshot:
42 """A point-in-time snapshot of resource usage."""
44 tenant_id: str
45 unit_name: str
46 current: float
47 limit: float
48 window_resets_at: datetime | None = None
51class ResourceUsageResult(str, Enum):
52 """Result of a resource usage check."""
54 APPROVED = "approved"
55 SOFT_THRESHOLD_BREACH = "soft_threshold_breach"
56 EXHAUSTED = "exhausted"
59class ResourceExhaustedError(GovernanceError):
60 """Raised when a resource quota is exhausted."""
62 _code: str = "LEX_ERR_GOV_010"
64 def __init__(
65 self,
66 tenant_id: str,
67 unit_name: str,
68 limit: float,
69 current: float,
70 actor_id: str | None = None,
71 ) -> None:
72 self.tenant_id = tenant_id
73 self.unit_name = unit_name
74 self.limit = limit
75 self.current = current
76 self.actor_id = actor_id
77 super().__init__(
78 f"Resource quota exhausted: tenant={tenant_id}, unit={unit_name}, "
79 f"{current}/{limit}"
80 )
83__all__ = [
84 "ResourceExhaustedError",
85 "ResourceQuota",
86 "ResourceUnit",
87 "ResourceUsageResult",
88 "ResourceUsageSnapshot",
89 "ResourceWindowKind",
90]