Coverage for src / lexigram / admin / rbac / types.py: 88%

26 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-08-13 22:14 +0800

1"""Core types for the RBAC system.""" 

2 

3from __future__ import annotations 

4 

5from dataclasses import dataclass, field 

6from typing import Any, Protocol, runtime_checkable 

7 

8 

9@dataclass(frozen=True) 

10class Permission: 

11 """A single permission string with optional scope.""" 

12 

13 resource: str # e.g., "users" 

14 action: str # e.g., "read", "write", "delete" 

15 scope: str | None = None # e.g., "self", "team", "all" 

16 

17 def __str__(self) -> str: 

18 if self.scope: 

19 return f"{self.resource}.{self.action}:{self.scope}" 

20 return f"{self.resource}.{self.action}" 

21 

22 

23@dataclass 

24class Role: 

25 """A named collection of permissions.""" 

26 

27 name: str 

28 description: str = "" 

29 permissions: list[Permission] = field(default_factory=list) 

30 inherits: list[str] = field(default_factory=list) # Parent role names 

31 

32 

33@dataclass(frozen=True) 

34class PolicyContext: 

35 """Context passed to policy evaluators.""" 

36 

37 user: Any 

38 resource_name: str 

39 action: str 

40 record: Any | None = None # For record-level/RLS policies 

41 

42 

43@runtime_checkable 

44class Policy(Protocol): 

45 """Protocol for policy evaluators.""" 

46 

47 def __call__(self, context: PolicyContext) -> bool: ...