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

1"""Governance module for dependency injection.""" 

2 

3from __future__ import annotations 

4 

5from typing import TYPE_CHECKING 

6 

7from lexigram.contracts.ai.governance import ( 

8 AIGovernanceProtocol, 

9 CostTrackingProtocol, 

10) 

11from lexigram.di.module import DynamicModule, Module, module 

12 

13if TYPE_CHECKING: 

14 from lexigram.ai.governance.config import GovernanceConfig 

15 

16 

17@module() 

18class GovernanceModule(Module): 

19 """AI Governance policy enforcement and cost-tracking integration. 

20 

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. 

25 

26 Usage:: 

27 

28 from lexigram.ai.governance.config import GovernanceConfig 

29 

30 @module( 

31 imports=[ 

32 GovernanceModule.configure( 

33 GovernanceConfig(monthly_budget=100.0) 

34 ) 

35 ] 

36 ) 

37 class AppModule(Module): 

38 pass 

39 

40 Error Handling:: 

41 

42 Governance violations surface as typed exceptions that can be caught 

43 directly or handled via the Result pattern:: 

44 

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 ) 

51 

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 """ 

60 

61 @classmethod 

62 def configure(cls, config: GovernanceConfig | None = None) -> DynamicModule: 

63 """Create a GovernanceModule with the given configuration. 

64 

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. 

69 

70 Returns: 

71 A :class:`~lexigram.di.module.DynamicModule` descriptor. 

72 

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 ) 

92 

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 ) 

111 

112 @classmethod 

113 def stub(cls, config: GovernanceConfig | None = None) -> DynamicModule: 

114 """Create a GovernanceModule suitable for unit and integration testing. 

115 

116 Uses in-memory or no-op implementations with minimal side effects. 

117 

118 Args: 

119 config: Optional config override. Uses safe test defaults when None. 

120 

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 ) 

139 

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 ) 

158 

159 

160__all__ = ["GovernanceModule"]