Coverage for src/lexigram/auth/policies/types.py: 100%

39 statements  

« prev     ^ index     » next       coverage.py v7.15.4, created at 2026-08-25 12:26 +0800

1"""Core types for Lexigram ABAC Policy Engine.""" 

2 

3from __future__ import annotations 

4 

5from dataclasses import dataclass, field 

6from enum import StrEnum 

7from typing import Any 

8 

9 

10class PolicyEffect(StrEnum): 

11 ALLOW = "allow" 

12 DENY = "deny" 

13 

14 

15class DecisionOutcome(StrEnum): 

16 ALLOW = "allow" 

17 DENY = "deny" 

18 INDETERMINATE = "indeterminate" 

19 

20 

21@dataclass(frozen=True) 

22class Condition: 

23 """A condition that must be met for a policy to apply.""" 

24 

25 attribute: str 

26 operator: str 

27 value: Any 

28 

29 

30@dataclass(frozen=True) 

31class Policy: 

32 """A granular authorization policy.""" 

33 

34 policy_id: str 

35 name: str 

36 effect: PolicyEffect 

37 principals: list[str] = field(default_factory=list) 

38 actions: list[str] = field(default_factory=list) 

39 resources: list[str] = field(default_factory=list) 

40 conditions: list[Condition] = field(default_factory=list) 

41 priority: int = 0 

42 description: str | None = None 

43 

44 

45@dataclass(frozen=True) 

46class AuthorizationRequest: 

47 """A request for authorization evaluation.""" 

48 

49 principal: str # e.g., "user:123" 

50 action: str # e.g., "read" 

51 resource: str # e.g., "document:456" 

52 context: dict[str, Any] = field(default_factory=dict) 

53 

54 

55@dataclass(frozen=True) 

56class AuthorizationDecision: 

57 """The result of an authorization evaluation.""" 

58 

59 decision: DecisionOutcome 

60 reason: str | None = None 

61 applied_policies: list[str] = field(default_factory=list) 

62 

63 

64__all__ = [ 

65 "AuthorizationDecision", 

66 "AuthorizationRequest", 

67 "Condition", 

68 "DecisionOutcome", 

69 "Policy", 

70 "PolicyEffect", 

71]