Coverage for src / lexigram / contracts / security / secrets.py: 0%
9 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"""Secret store protocol for Lexigram Framework.
3Provides a protocol for retrieving, storing, and deleting named secrets.
4Implementations may delegate to environment variables, HashiCorp Vault,
5AWS Secrets Manager, GCP Secret Manager, Azure Key Vault, or a local
6encrypted store, depending on the deployment environment.
8Example::
10 from lexigram.contracts.secrets import SecretStoreProtocol
12 async def bootstrap(store: SecretStoreProtocol) -> None:
13 api_key = await store.get_secret("stripe/api-key")
14 db_url = await store.get_secret("database/url")
16Container registration::
18 container.singleton(SecretStoreProtocol, EnvSecretStore)
19"""
21from __future__ import annotations
23from typing import Protocol, runtime_checkable
26@runtime_checkable
27class SecretStoreProtocol(Protocol):
28 """Protocol for retrieving, writing, and deleting named secrets.
30 Secret names may use any naming convention; a hierarchical path
31 (e.g. ``"database/password"``) is recommended for readability and
32 to align with most provider APIs.
34 All mutating operations (``set_secret``, ``delete_secret``) are
35 **synchronous** at the protocol level — implementations may perform
36 async I/O internally but the public contract accepts simple calls from
37 both sync and async contexts.
39 Example::
41 store = EnvSecretStore()
42 val = store.get_secret("MY_API_KEY")
44 Async-first usage via a wrapping coroutine::
46 val = await asyncio.to_thread(store.get_secret, "MY_API_KEY")
47 """
49 def get_secret(self, name: str) -> str:
50 """Return the value of a secret by name.
52 Args:
53 name: Unique secret identifier (e.g. ``"stripe/api-key"``).
55 Returns:
56 The plaintext secret value.
58 Raises:
59 SecretNotFoundError: If no secret with that name exists.
60 SecretAccessError: If the caller lacks permission.
61 """
62 ...
64 def set_secret(self, name: str, value: str) -> None:
65 """Write or overwrite a secret.
67 Args:
68 name: Unique secret identifier.
69 value: Plaintext secret value to store.
71 Raises:
72 SecretAccessError: If the caller lacks permission to write.
73 """
74 ...
76 def delete_secret(self, name: str) -> None:
77 """Delete a secret by name.
79 Non-existent secrets are silently ignored (idempotent delete).
81 Args:
82 name: Unique secret identifier.
84 Raises:
85 SecretAccessError: If the caller lacks permission to delete.
86 """
87 ...
89 def has_secret(self, name: str) -> bool:
90 """Return ``True`` if a secret with *name* exists, ``False`` otherwise.
92 Args:
93 name: Unique secret identifier.
94 """
95 ...
98__all__ = [
99 "SecretStoreProtocol",
100]