1"""Exception hierarchy for AI Governance."""
2
3from __future__ import annotations
4
5from lexigram.contracts.ai.governance import (
6 BudgetExceededError,
7 GovernanceError,
8 ResourceExhaustedError,
9)
10
11
12class RateLimitExceededError(GovernanceError):
13 """Raised when RPM or TPM limits are exceeded.
14
15 Attributes:
16 limit: Configured limit value.
17 current: Current counter value.
18 limit_type: Type of limit exceeded (``"rpm"`` or ``"tpm"``).
19 """
20
21 _code: str = "LEX_ERR_GOV_006"
22
23 def __init__(
24 self,
25 limit: int,
26 current: int,
27 limit_type: str = "rpm",
28 user_id: str | None = None,
29 ) -> None:
30 self.limit = limit
31 self.current = current
32 self.limit_type = limit_type
33 self.user_id = user_id
34 super().__init__(
35 f"{limit_type.upper()} exceeded: {current}/{limit} (user={user_id})"
36 )
37
38
39class ModelAccessDeniedError(GovernanceError):
40 """Raised when a user is denied access to a model by policy.
41
42 Attributes:
43 model: Model identifier that was denied.
44 reason: Why access was denied (``"restricted"``, ``"not_in_allowlist"``,
45 ``"in_denylist"``).
46 """
47
48 _code: str = "LEX_ERR_GOV_007"
49
50 def __init__(
51 self,
52 model: str,
53 reason: str,
54 user_id: str | None = None,
55 ) -> None:
56 self.model = model
57 self.reason = reason
58 self.user_id = user_id
59 super().__init__(
60 f"Model access denied: model={model}, reason={reason} (user={user_id})"
61 )
62
63
64class GovernancePersistenceError(GovernanceError):
65 """Raised when a governance persistence backend is unavailable.
66
67 Raised by
68 :class:`~lexigram.ai.governance.persistence.RedisGovernancePersistence`
69 when the cache backend reports failure (an ``Err`` result). The
70 :class:`~lexigram.ai.governance.manager.AIGovernanceManager` catches this at
71 the policy boundary and applies the configured fail-open / fail-closed
72 decision instead of letting a fabricated value inform the allow/deny
73 verdict.
74 """
75
76 _code: str = "LEX_ERR_GOV_008"
77
78
79__all__ = [
80 "BudgetExceededError",
81 "GovernanceError",
82 "GovernancePersistenceError",
83 "ModelAccessDeniedError",
84 "RateLimitExceededError",
85 "ResourceExhaustedError",
86]