diff --git a/docs/mcp/modules/mail_intake.credentials.json b/docs/mcp/modules/mail_intake.credentials.json index 3d5a3b7..f18c4df 100644 --- a/docs/mcp/modules/mail_intake.credentials.json +++ b/docs/mcp/modules/mail_intake.credentials.json @@ -247,6 +247,13 @@ "signature": "", "docstring": null }, + "Any": { + "name": "Any", + "kind": "alias", + "path": "mail_intake.credentials.redis.Any", + "signature": "", + "docstring": null + }, "TypeVar": { "name": "TypeVar", "kind": "alias", @@ -295,7 +302,7 @@ "name": "RedisCredentialStore", "kind": "class", "path": "mail_intake.credentials.redis.RedisCredentialStore", - "signature": "", + "signature": "", "docstring": "Redis-backed implementation of `CredentialStore`.\n\nThis store persists credentials in Redis and is suitable for\ndistributed and horizontally scaled deployments where credentials\nmust be shared across multiple processes or nodes.\n\nNotes:\n **Responsibilities:**\n\n - This class is responsible only for persistence and retrieval.\n - It does not interpret, validate, refresh, or otherwise manage the\n lifecycle of the credentials being stored.\n\n **Guarantees:**\n\n - The store is intentionally generic and delegates all serialization\n concerns to caller-provided functions.\n - This avoids unsafe mechanisms such as `pickle` and allows\n credential formats to be explicitly controlled and audited.", "members": { "redis": { @@ -337,31 +344,24 @@ "name": "load", "kind": "function", "path": "mail_intake.credentials.redis.RedisCredentialStore.load", - "signature": "", + "signature": "", "docstring": "Load credentials from Redis.\n\nReturns:\n T | None:\n An instance of type `T` if credentials are present and\n successfully deserialized; otherwise `None`.\n\nNotes:\n **Guarantees:**\n\n - If no value exists for the configured key, or if the stored\n payload cannot be successfully deserialized, this method\n returns `None`.\n - The store does not attempt to validate the returned\n credentials or determine whether they are expired or\n otherwise usable." }, "save": { "name": "save", "kind": "function", "path": "mail_intake.credentials.redis.RedisCredentialStore.save", - "signature": "", + "signature": "", "docstring": "Persist credentials to Redis.\n\nArgs:\n credentials (T):\n The credential object to persist.\n\nNotes:\n **Responsibilities:**\n\n - Any previously stored credentials under the same key are overwritten\n - If a TTL is configured, the credentials will expire automatically after the specified duration" }, "clear": { "name": "clear", "kind": "function", "path": "mail_intake.credentials.redis.RedisCredentialStore.clear", - "signature": "", + "signature": "", "docstring": "Remove stored credentials from Redis.\n\nNotes:\n **Lifecycle:**\n\n - This operation deletes the configured Redis key if it exists\n - Implementations should treat this method as idempotent" } } - }, - "Any": { - "name": "Any", - "kind": "alias", - "path": "mail_intake.credentials.redis.Any", - "signature": "", - "docstring": null } } }, diff --git a/docs/mcp/modules/mail_intake.credentials.redis.json b/docs/mcp/modules/mail_intake.credentials.redis.json index 8c39459..4325f23 100644 --- a/docs/mcp/modules/mail_intake.credentials.redis.json +++ b/docs/mcp/modules/mail_intake.credentials.redis.json @@ -11,6 +11,13 @@ "signature": "", "docstring": null }, + "Any": { + "name": "Any", + "kind": "alias", + "path": "mail_intake.credentials.redis.Any", + "signature": "", + "docstring": null + }, "TypeVar": { "name": "TypeVar", "kind": "alias", @@ -59,7 +66,7 @@ "name": "RedisCredentialStore", "kind": "class", "path": "mail_intake.credentials.redis.RedisCredentialStore", - "signature": "", + "signature": "", "docstring": "Redis-backed implementation of `CredentialStore`.\n\nThis store persists credentials in Redis and is suitable for\ndistributed and horizontally scaled deployments where credentials\nmust be shared across multiple processes or nodes.\n\nNotes:\n **Responsibilities:**\n\n - This class is responsible only for persistence and retrieval.\n - It does not interpret, validate, refresh, or otherwise manage the\n lifecycle of the credentials being stored.\n\n **Guarantees:**\n\n - The store is intentionally generic and delegates all serialization\n concerns to caller-provided functions.\n - This avoids unsafe mechanisms such as `pickle` and allows\n credential formats to be explicitly controlled and audited.", "members": { "redis": { @@ -101,31 +108,24 @@ "name": "load", "kind": "function", "path": "mail_intake.credentials.redis.RedisCredentialStore.load", - "signature": "", + "signature": "", "docstring": "Load credentials from Redis.\n\nReturns:\n T | None:\n An instance of type `T` if credentials are present and\n successfully deserialized; otherwise `None`.\n\nNotes:\n **Guarantees:**\n\n - If no value exists for the configured key, or if the stored\n payload cannot be successfully deserialized, this method\n returns `None`.\n - The store does not attempt to validate the returned\n credentials or determine whether they are expired or\n otherwise usable." }, "save": { "name": "save", "kind": "function", "path": "mail_intake.credentials.redis.RedisCredentialStore.save", - "signature": "", + "signature": "", "docstring": "Persist credentials to Redis.\n\nArgs:\n credentials (T):\n The credential object to persist.\n\nNotes:\n **Responsibilities:**\n\n - Any previously stored credentials under the same key are overwritten\n - If a TTL is configured, the credentials will expire automatically after the specified duration" }, "clear": { "name": "clear", "kind": "function", "path": "mail_intake.credentials.redis.RedisCredentialStore.clear", - "signature": "", + "signature": "", "docstring": "Remove stored credentials from Redis.\n\nNotes:\n **Lifecycle:**\n\n - This operation deletes the configured Redis key if it exists\n - Implementations should treat this method as idempotent" } } - }, - "Any": { - "name": "Any", - "kind": "alias", - "path": "mail_intake.credentials.redis.Any", - "signature": "", - "docstring": null } } } diff --git a/docs/mcp/modules/mail_intake.json b/docs/mcp/modules/mail_intake.json index ba08875..041d5b5 100644 --- a/docs/mcp/modules/mail_intake.json +++ b/docs/mcp/modules/mail_intake.json @@ -891,6 +891,13 @@ "signature": "", "docstring": null }, + "Any": { + "name": "Any", + "kind": "alias", + "path": "mail_intake.credentials.redis.Any", + "signature": "", + "docstring": null + }, "TypeVar": { "name": "TypeVar", "kind": "alias", @@ -939,7 +946,7 @@ "name": "RedisCredentialStore", "kind": "class", "path": "mail_intake.credentials.redis.RedisCredentialStore", - "signature": "", + "signature": "", "docstring": "Redis-backed implementation of `CredentialStore`.\n\nThis store persists credentials in Redis and is suitable for\ndistributed and horizontally scaled deployments where credentials\nmust be shared across multiple processes or nodes.\n\nNotes:\n **Responsibilities:**\n\n - This class is responsible only for persistence and retrieval.\n - It does not interpret, validate, refresh, or otherwise manage the\n lifecycle of the credentials being stored.\n\n **Guarantees:**\n\n - The store is intentionally generic and delegates all serialization\n concerns to caller-provided functions.\n - This avoids unsafe mechanisms such as `pickle` and allows\n credential formats to be explicitly controlled and audited.", "members": { "redis": { @@ -981,31 +988,24 @@ "name": "load", "kind": "function", "path": "mail_intake.credentials.redis.RedisCredentialStore.load", - "signature": "", + "signature": "", "docstring": "Load credentials from Redis.\n\nReturns:\n T | None:\n An instance of type `T` if credentials are present and\n successfully deserialized; otherwise `None`.\n\nNotes:\n **Guarantees:**\n\n - If no value exists for the configured key, or if the stored\n payload cannot be successfully deserialized, this method\n returns `None`.\n - The store does not attempt to validate the returned\n credentials or determine whether they are expired or\n otherwise usable." }, "save": { "name": "save", "kind": "function", "path": "mail_intake.credentials.redis.RedisCredentialStore.save", - "signature": "", + "signature": "", "docstring": "Persist credentials to Redis.\n\nArgs:\n credentials (T):\n The credential object to persist.\n\nNotes:\n **Responsibilities:**\n\n - Any previously stored credentials under the same key are overwritten\n - If a TTL is configured, the credentials will expire automatically after the specified duration" }, "clear": { "name": "clear", "kind": "function", "path": "mail_intake.credentials.redis.RedisCredentialStore.clear", - "signature": "", + "signature": "", "docstring": "Remove stored credentials from Redis.\n\nNotes:\n **Lifecycle:**\n\n - This operation deletes the configured Redis key if it exists\n - Implementations should treat this method as idempotent" } } - }, - "Any": { - "name": "Any", - "kind": "alias", - "path": "mail_intake.credentials.redis.Any", - "signature": "", - "docstring": null } } }, diff --git a/mail_intake/credentials/redis.py b/mail_intake/credentials/redis.py index dcba383..9d64fe2 100644 --- a/mail_intake/credentials/redis.py +++ b/mail_intake/credentials/redis.py @@ -25,7 +25,7 @@ responsibility of authentication provider implementations. """ from collections.abc import Callable -from typing import TypeVar +from typing import Any, TypeVar from mail_intake.credentials.store import CredentialStore @@ -57,7 +57,7 @@ class RedisCredentialStore(CredentialStore[T]): def __init__( self, - redis_client, + redis_client: Any, key: str, serialize: Callable[[T], bytes], deserialize: Callable[[bytes], T], @@ -66,10 +66,18 @@ class RedisCredentialStore(CredentialStore[T]): """ Initialize a Redis-backed credential store. - Callers supply all runtime dependencies: ``redis_client`` is an - initialized Redis client instance, ``key`` names the storage key, - ``serialize``/``deserialize`` are the encoding and decoding callables, - and ``ttl_seconds`` optionally limits credential lifetime. + Args: + redis_client (Any): + Initialized Redis client instance used for persistence. + key (str): + Storage key under which credentials are persisted. + serialize (Callable[[T], bytes]): + Callable that encodes credentials to bytes for storage. + deserialize (Callable[[bytes], T]): + Callable that decodes stored bytes back into credentials. + ttl_seconds (int | None): + Optional time-to-live in seconds after which stored + credentials expire automatically. ``None`` disables expiry. """ self.redis = redis_client self.key = key