Coverage for src / lexigram / contracts / ai / relay / auth.py: 0%

15 statements  

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

1"""Inbound relay authentication contracts. 

2 

3The gateway itself never validates keys: a host binds a 

4``RelayAuthVerifierProtocol`` implementation (e.g. the lexigram-auth 

5adapter) through the container, and the gateway only calls it. When no 

6verifier is bound the gateway stays open by default (``require_auth`` 

7is opt-in at the config level). 

8""" 

9 

10from __future__ import annotations 

11 

12from dataclasses import dataclass 

13from typing import Protocol, runtime_checkable 

14 

15from lexigram.contracts.core.result import Result 

16 

17 

18@dataclass(frozen=True, slots=True) 

19class RelayAuthIdentity: 

20 """Identity of an authenticated relay caller.""" 

21 

22 user_id: str 

23 token_id: str 

24 key_prefix: str = "sk_" 

25 

26 

27@dataclass(frozen=True, slots=True) 

28class RelayAuthError: 

29 """Rejection reason for an inbound relay request.""" 

30 

31 code: str 

32 message: str 

33 

34 

35@runtime_checkable 

36class RelayAuthVerifierProtocol(Protocol): 

37 """Verify the caller of an inbound relay request. 

38 

39 The implementation is responsible for parsing credentials from any 

40 supported location (``Authorization``, ``x-api-key``, 

41 ``x-goog-api-key``, ``?key=``) and returning either an identity or 

42 a rejection reason. It must never raise for a bad credential. 

43 """ 

44 

45 async def authenticate( 

46 self, request: object 

47 ) -> Result[RelayAuthIdentity, RelayAuthError]: ...