Coverage for src / lexigram / contracts / exceptions / security.py: 0%

32 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-08-15 18:57 +0800

1"""Security exception classes for the Lexigram Framework. 

2 

3Defines the exception hierarchy for the security subsystem, 

4covering guard denials, input sanitization failures, and CORS violations. 

5""" 

6 

7from __future__ import annotations 

8 

9from typing import Any 

10 

11from lexigram.contracts.exceptions.base import LexigramError 

12 

13 

14class SecurityError(LexigramError): 

15 """Base security error for the Lexigram security subsystem.""" 

16 

17 _code = "LEX_ERR_SEC_001" 

18 

19 def __init__(self, message: str = "Security error", **kwargs: Any) -> None: 

20 super().__init__(message, **kwargs) 

21 

22 

23class GuardDeniedError(SecurityError): 

24 """Raised when a GuardChain denies the request. 

25 

26 Attributes: 

27 guard: The name or type of the guard that triggered the denial. 

28 reason: Human-readable reason for the denial, if provided. 

29 """ 

30 

31 _code = "LEX_ERR_SEC_002" 

32 

33 def __init__( 

34 self, 

35 message: str = "Access denied by guard", 

36 guard: str | None = None, 

37 reason: str | None = None, 

38 **kwargs: Any, 

39 ) -> None: 

40 super().__init__(message, **kwargs) 

41 self.guard = guard 

42 self.reason = reason 

43 

44 

45class InputSanitizationError(SecurityError): 

46 """Raised when sanitization fails due to unrecoverable input structure.""" 

47 

48 _code = "LEX_ERR_SEC_003" 

49 

50 def __init__( 

51 self, message: str = "Input sanitization failed", **kwargs: Any 

52 ) -> None: 

53 super().__init__(message, **kwargs) 

54 

55 

56class CORSViolationError(SecurityError): 

57 """Raised when a request violates the configured CORS policy. 

58 

59 Attributes: 

60 origin: The request origin that was rejected. 

61 """ 

62 

63 _code = "LEX_ERR_SEC_004" 

64 

65 def __init__( 

66 self, 

67 message: str = "CORS policy violation", 

68 origin: str | None = None, 

69 **kwargs: Any, 

70 ) -> None: 

71 super().__init__(message, **kwargs) 

72 self.origin = origin 

73 

74 

75class SecretAccessError(SecurityError): 

76 """Raised when the caller lacks permission to access or modify a secret. 

77 

78 Attributes: 

79 secret_name: Name of the secret that was denied access. 

80 operation: The operation that was denied (read, write, delete, etc.). 

81 """ 

82 

83 _code = "LEX_ERR_SEC_005" 

84 

85 def __init__( 

86 self, 

87 secret_name: str, 

88 operation: str = "read", 

89 **kwargs: Any, 

90 ) -> None: 

91 details = kwargs.get("details", {}) 

92 details["secret_name"] = secret_name 

93 details["operation"] = operation 

94 super().__init__( 

95 message=f"Access denied: cannot {operation} secret '{secret_name}'", 

96 details=details, 

97 **kwargs, 

98 ) 

99 self.secret_name = secret_name 

100 self.operation = operation 

101 

102 

103__all__ = [ 

104 "CORSViolationError", 

105 "GuardDeniedError", 

106 "InputSanitizationError", 

107 "SecretAccessError", 

108 "SecurityError", 

109]