Coverage for node / src / stigmem_node / models / auth.py: 100%
37 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-05-25 01:49 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-05-25 01:49 +0000
1"""Authentication route wire-format models."""
3from __future__ import annotations
5from pydantic import BaseModel, Field
7STATIC_KEY_MIN_RAW_LENGTH = 32 # matches bootstrap's `openssl rand -hex 32`
10class ExchangeRequest(BaseModel):
11 id_token: str
12 permissions: list[str] = Field(default=["read", "write"])
15class ExchangeResponse(BaseModel):
16 api_key: str
17 entity_uri: str
18 permissions: list[str]
19 expires_at: str
22class KeyInfo(BaseModel):
23 id: str
24 entity_uri: str
25 permissions: list[str]
26 description: str | None
27 created_at: str
28 expires_at: str | None
29 oidc_sub: str | None
32class ExpiringKeyInfo(KeyInfo):
33 tenant_id: str
34 days_remaining: float
37class RegisterKeyRequest(BaseModel):
38 raw_key: str = Field(
39 ...,
40 min_length=STATIC_KEY_MIN_RAW_LENGTH,
41 description=(
42 "Caller-generated raw key material (e.g. `openssl rand -hex 32`). "
43 "The node hashes it and never stores or echoes the raw value."
44 ),
45 )
46 entity_uri: str = Field(..., min_length=1)
47 permissions: list[str] = Field(default_factory=lambda: ["read", "write"])
48 description: str | None = None
49 expires_at: str | None = Field(
50 default=None,
51 description="ISO-8601 timestamp; omit for no expiry.",
52 )
53 tenant_id: str | None = Field(
54 default=None,
55 description="Target tenant; defaults to the caller's tenant.",
56 )
59class RegisterKeyResponse(BaseModel):
60 id: str
61 entity_uri: str
62 permissions: list[str]
63 description: str | None
64 created_at: str
65 expires_at: str | None
66 tenant_id: str