Coverage for /home/admin/Documents/AI/applications/lexigram-dev/lexigram/experimental/ai/lexigram-ai-governance/src/lexigram/ai/governance/module.py: 79%
19 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-25 07:19 +0800
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-25 07:19 +0800
1"""Governance module for dependency injection."""
3from __future__ import annotations
5from typing import TYPE_CHECKING
7from lexigram.contracts.ai.governance import (
8 AIGovernanceProtocol,
9 CostTrackingProtocol,
10)
11from lexigram.di.module import DynamicModule, Module, module
13if TYPE_CHECKING:
14 from lexigram.ai.governance.config import GovernanceConfig
17@module()
18class GovernanceModule(Module):
19 """AI Governance policy enforcement and cost-tracking integration.
21 Call :meth:`configure` to register
22 :class:`~lexigram.contracts.ai.governance.AIGovernanceProtocol` and
23 :class:`~lexigram.contracts.ai.governance.CostTrackingProtocol`
24 implementations for injection.
26 Usage::
28 from lexigram.ai.governance.config import GovernanceConfig
30 @module(
31 imports=[
32 GovernanceModule.configure(
33 GovernanceConfig(monthly_budget=100.0)
34 )
35 ]
36 )
37 class AppModule(Module):
38 pass
40 Error Handling::
42 Governance violations surface as typed exceptions that can be caught
43 directly or handled via the Result pattern::
45 from lexigram.ai.governance.exceptions import (
46 GovernanceError, # base — catch-all
47 BudgetExceededError, # monthly spend cap breached
48 RateLimitExceededError,# RPM / TPM limit exceeded
49 ModelAccessDeniedError,# policy denied model access
50 )
52 Exports:
53 :class:`~lexigram.contracts.ai.governance.AIGovernanceProtocol`,
54 :class:`~lexigram.contracts.ai.governance.CostTrackingProtocol`,
55 :class:`~lexigram.ai.governance.exceptions.GovernanceError`,
56 :class:`~lexigram.ai.governance.exceptions.BudgetExceededError`,
57 :class:`~lexigram.ai.governance.exceptions.RateLimitExceededError`,
58 :class:`~lexigram.ai.governance.exceptions.ModelAccessDeniedError`
59 """
61 @classmethod
62 def configure(cls, config: GovernanceConfig | None = None) -> DynamicModule:
63 """Create a GovernanceModule with the given configuration.
65 Args:
66 config: :class:`~lexigram.ai.governance.config.GovernanceConfig`,
67 a plain ``dict`` of the same keys, or ``None`` to read from
68 environment variables.
70 Returns:
71 A :class:`~lexigram.di.module.DynamicModule` descriptor.
73 Raises:
74 TypeError: If *config* is not a ``GovernanceConfig``, ``dict``,
75 or ``None``.
76 """
77 from lexigram.ai.governance.di.provider import GovernanceProvider
78 from lexigram.ai.governance.exceptions import (
79 BudgetExceededError,
80 GovernanceError,
81 ModelAccessDeniedError,
82 RateLimitExceededError,
83 )
84 from lexigram.contracts.ai.governance.resource_unit import (
85 ResourceExhaustedError,
86 ResourceQuota,
87 ResourceUnit,
88 ResourceUsageResult,
89 ResourceUsageSnapshot,
90 ResourceWindowKind,
91 )
93 return DynamicModule(
94 module=cls,
95 providers=[GovernanceProvider(config=config)],
96 exports=[
97 AIGovernanceProtocol,
98 CostTrackingProtocol,
99 GovernanceError,
100 BudgetExceededError,
101 RateLimitExceededError,
102 ModelAccessDeniedError,
103 ResourceExhaustedError,
104 ResourceQuota,
105 ResourceUnit,
106 ResourceUsageResult,
107 ResourceUsageSnapshot,
108 ResourceWindowKind,
109 ],
110 )
112 @classmethod
113 def stub(cls, config: GovernanceConfig | None = None) -> DynamicModule:
114 """Create a GovernanceModule suitable for unit and integration testing.
116 Uses in-memory or no-op implementations with minimal side effects.
118 Args:
119 config: Optional config override. Uses safe test defaults when None.
121 Returns:
122 A :class:`~lexigram.di.module.DynamicModule` descriptor.
123 """
124 from lexigram.ai.governance.di.provider import GovernanceProvider
125 from lexigram.ai.governance.exceptions import (
126 BudgetExceededError,
127 GovernanceError,
128 ModelAccessDeniedError,
129 RateLimitExceededError,
130 )
131 from lexigram.contracts.ai.governance.resource_unit import (
132 ResourceExhaustedError,
133 ResourceQuota,
134 ResourceUnit,
135 ResourceUsageResult,
136 ResourceUsageSnapshot,
137 ResourceWindowKind,
138 )
140 return DynamicModule(
141 module=cls,
142 providers=[GovernanceProvider(config=config)],
143 exports=[
144 AIGovernanceProtocol,
145 CostTrackingProtocol,
146 GovernanceError,
147 BudgetExceededError,
148 RateLimitExceededError,
149 ModelAccessDeniedError,
150 ResourceExhaustedError,
151 ResourceQuota,
152 ResourceUnit,
153 ResourceUsageResult,
154 ResourceUsageSnapshot,
155 ResourceWindowKind,
156 ],
157 )
160__all__ = ["GovernanceModule"]