cadrumo.adapters.persistence.storage.secret_store.store module¶
Encrypted, file-locked store for secret and session-bearing records.
Layered on top of adapters.persistence.storage.blob_store.blob_store.EncryptedBlobStore
and core.locks.exclusive_file_lock(), the store persists
short-lived bearer state and long-lived authentication material under a
stable string key. SECRET_STORE_CLASSES below is the one statement of
which SensitivityClass members those are; every refusal and
docstring here reads it rather than restating it. Each record is wrapped in an
adapters.persistence.storage.envelope.contract.Envelope of
SecretRecord, encrypted via the blob store’s per-record DEK wrapped
by the active bucket session’s data key using AES-256-GCM, and indexed by
an HMAC-SHA256 digest of the natural-key string so consumers can query
SecretStore.get() without leaking the plaintext key.
A JSON catalogue file at store_dir / "index.json" maps the hex
digest of each key to the underlying
adapters.persistence.storage.blob_store.blob_store.BlobReference.
Every mutation acquires exclusive_file_lock(store_dir / "secrets.lock")
so parallel writers serialise rather than race.
The retention contract is enforced at write time: SECRET- and SESSION-class
records MUST carry an expires_at field; the store raises
RetentionPolicyError
when it is absent.
- SECRET_STORE_CLASSES: Final[frozenset[SensitivityClass]]¶
The only classes a record in this store may carry. The record model and the index row that describes it both enforce this one set, so an index cannot name a class no record here can have.
- class SecretRecord(**data)[source]¶
Bases:
BaseModelFrozen record persisted in the
SecretStore.- Variables:
key – Operator-facing natural key (e.g.
aeat:google:oauth-token).value – Secret payload as raw bytes. Plaintext on the API surface only; the blob store encrypts before write.
classification – Sensitivity class. Must be a member of
SECRET_STORE_CLASSES, which is the one statement of that closed set; other classes are rejected by the field validator at construction time.metadata – Operator-supplied non-secret tags (e.g. operator email, issued_by, scope). Stringified key/value entries only.
created_at – Timezone-aware datetime captured at write time.
expires_at – Optional explicit expiry. Required for the
SECRETandSESSIONclasses per the default retention policy.
- Parameters:
data (Any)
- key: str¶
- value: bytes¶
- classification: SensitivityClass¶
- metadata: dict[str, str]¶
- created_at: datetime¶
- expires_at: datetime | None¶
- class SecretStore(*, store_dir, blob_store)[source]¶
Bases:
objectRepository for the substrate’s secret and session-bearing state.
Wraps an
adapters.persistence.storage.blob_store.blob_store.EncryptedBlobStorebehind a digest-keyed index so callers can query records by their natural string key without that key ever appearing in plaintext on disk. Mutating operations are serialised viacore.locks.exclusive_file_lock().- Parameters:
store_dir (Path)
blob_store (EncryptedBlobStore)
- value_witness(*, key, value)[source]¶
Return a master-keyed, non-reversible witness for one key/value request.
- put(record, *, overwrite=False)[source]¶
Persist
recordand return the underlying blob reference.Acquires the store-wide
core.locks.exclusive_file_lock()for the duration of the write.- Parameters:
record (
SecretRecord) – TheSecretRecordto persist.overwrite (
bool) – IfTrue, replace any existing record at the same key. IfFalse(default), raiseSecretAlreadyExistsErroron collision.
- Return type:
- Returns:
The
adapters.persistence.storage.blob_store.blob_store.BlobReferencefor the freshly written blob.
- get(key)[source]¶
Return the
SecretRecordpersisted underkey.- Parameters:
- Return type:
- Returns:
The decrypted
SecretRecord.- Raises:
SecretNotFoundError – When no record exists for
key.StorageValidationError – When the index, the stored envelope, and the record itself do not all name the same class.
- delete(key)[source]¶
Remove the record persisted under
key.- Parameters:
- Raises:
SecretNotFoundError – When no record exists for
key.- Return type:
- list_digests()[source]¶
Yield every persisted lookup digest.
Plaintext keys are NOT recoverable from digests by design; this method exists for inventory diagnostics (e.g. counting records, rotating store-wide).
- rotate(key, new_value, *, expires_at=None)[source]¶
Replace the value of an existing secret and return the new blob reference.
Holds the store-wide
core.locks.exclusive_file_lock()across the read and write so a concurrentrotate(),put(), ordelete()cannot interleave between the lookup and the overwrite.- Parameters:
- Return type:
- Returns:
The
adapters.persistence.storage.blob_store.blob_store.BlobReferenceof the rotated blob.