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
« prev ^ index » next coverage.py v7.13.5, created at 2026-08-15 18:57 +0800
1"""Inbound relay authentication contracts.
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"""
10from __future__ import annotations
12from dataclasses import dataclass
13from typing import Protocol, runtime_checkable
15from lexigram.contracts.core.result import Result
18@dataclass(frozen=True, slots=True)
19class RelayAuthIdentity:
20 """Identity of an authenticated relay caller."""
22 user_id: str
23 token_id: str
24 key_prefix: str = "sk_"
27@dataclass(frozen=True, slots=True)
28class RelayAuthError:
29 """Rejection reason for an inbound relay request."""
31 code: str
32 message: str
35@runtime_checkable
36class RelayAuthVerifierProtocol(Protocol):
37 """Verify the caller of an inbound relay request.
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 """
45 async def authenticate(
46 self, request: object
47 ) -> Result[RelayAuthIdentity, RelayAuthError]: ...