Source code for kstlib.secrets.models
"""Data models used by the secrets resolver."""
from __future__ import annotations
import typing
from dataclasses import dataclass, field
from enum import Enum
from typing import TYPE_CHECKING, Any
if TYPE_CHECKING:
from collections.abc import Mapping, MutableMapping
else: # pragma: no cover - runtime aliases for typing constructs
Mapping = typing.Mapping
MutableMapping = typing.MutableMapping
[docs]
class SecretSource(str, Enum):
"""Enumerates the possible origins for a resolved secret."""
KWARGS = "kwargs"
ENVIRONMENT = "environment"
KEYRING = "keyring"
SOPS = "sops"
KMS = "kms"
DEFAULT = "default"
[docs]
@dataclass(slots=True)
class SecretRequest:
"""Describes a secret lookup request.
Attributes:
name: Identifier of the secret (e.g. "smtp.password").
scope: Optional scope that providers can exploit for namespacing.
required: Whether the resolver must raise if the secret is missing.
default: Optional fallback value when the secret is not required.
metadata: Arbitrary provider hints (e.g. keyring namespace).
"""
name: str
scope: str | None = None
required: bool = True
# Default fallback value : aligned with SecretRecord.value, hidden from
# the dataclass repr so a future "log.debug('Request: %s', request)"
# never accidentally leaks a fallback secret.
default: Any | None = field(default=None, repr=False)
metadata: MutableMapping[str, Any] = field(default_factory=dict)
[docs]
@dataclass(slots=True)
class SecretRecord:
"""Represents the value returned by the resolver.
Attributes:
value: The secret itself.
source: The origin of the secret.
metadata: Provider specific metadata (e.g. timestamp, path, ttl).
"""
value: Any = field(repr=False)
source: SecretSource
metadata: Mapping[str, Any] = field(default_factory=dict)
__all__ = ["SecretRecord", "SecretRequest", "SecretSource"]