Coverage for src / lexigram / contracts / admin / principal.py: 100%

14 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-08-19 05:41 +0800

1"""Admin principal bridge — the app <-> panel identity seam (spec D3).""" 

2 

3from __future__ import annotations 

4 

5from dataclasses import dataclass, field 

6from typing import Protocol, runtime_checkable 

7 

8 

9@dataclass(frozen=True) 

10class AdminPrincipal: 

11 """A panel-view of an application principal (Strapi-style dual identity). 

12 

13 ``hashed_password`` is an optional write-through used by the panel's 

14 app-mode store adapter: non-empty values are forwarded on 

15 ``update_principal`` so implementers can persist panel-side password 

16 mutations (the app's hashing policy still owns verification). 

17 """ 

18 

19 user_id: str 

20 name: str 

21 email: str 

22 roles: list[str] = field(default_factory=list) 

23 permissions: list[str] = field(default_factory=list) 

24 is_active: bool = True 

25 hashed_password: str = "" 

26 

27 

28@runtime_checkable 

29class AdminPrincipalProviderProtocol(Protocol): 

30 """Bridge implemented ONCE by the application; consumed by lexigram-admin. 

31 

32 Distinct from ``RoleResolverProtocol`` (lexigram-web PEP for app-user API 

33 routes): this is the PANEL identity seam. 

34 """ 

35 

36 async def principal_for(self, user_id: str) -> AdminPrincipal | None: ... 

37 

38 async def list_principals(self) -> list[AdminPrincipal]: ... 

39 

40 async def create_principal( 

41 self, name: str, email: str, password: str, roles: list[str] | None = None 

42 ) -> AdminPrincipal: ... 

43 

44 async def update_principal(self, principal: AdminPrincipal) -> None: ... 

45 

46 async def delete_principal(self, user_id: str) -> None: ... 

47 

48 async def authenticate( 

49 self, email: str, password: str 

50 ) -> AdminPrincipal | None: ... 

51 

52 async def sync_roles(self, user_id: str, roles: list[str]) -> None: ... 

53 

54 async def ensure_schema(self) -> None: ...