Skip to main content

Secure API key management for FastHTML applications with encrypted storage, session/database persistence, and built-in UI components.

Project description

cjm-fasthtml-byok

Install

pip install cjm_fasthtml_byok

Project Structure

nbs/
├── components/ (2)
│   ├── alerts.ipynb  # FastHTML alert and notification components for user feedback
│   └── forms.ipynb   # FastHTML form components for API key input and management
├── core/ (3)
│   ├── security.ipynb  # Encryption and security utilities for API key management
│   ├── storage.ipynb   # Storage backends for API keys (session and database)
│   └── types.ipynb     # Type definitions and protocols for the BYOK system
├── middleware/ (1)
│   └── beforeware.ipynb  # FastHTML beforeware for API key management
└── utils/ (1)
    └── helpers.ipynb  # Helper functions for BYOK system

Total: 7 notebooks across 4 directories

Module Dependencies

graph LR
    components_alerts[components.alerts<br/>Alerts]
    components_forms[components.forms<br/>Forms]
    core_security[core.security<br/>Security]
    core_storage[core.storage<br/>Storage]
    core_types[core.types<br/>Types]
    middleware_beforeware[middleware.beforeware<br/>Beforeware]
    utils_helpers[utils.helpers<br/>Helpers]

    components_forms --> core_security
    components_forms --> utils_helpers
    core_security --> core_types
    core_storage --> core_types
    core_storage --> core_security
    middleware_beforeware --> core_security
    middleware_beforeware --> core_types
    middleware_beforeware --> core_storage
    utils_helpers --> core_security

9 cross-module dependencies detected

CLI Reference

No CLI commands found in this project.

Module Overview

Detailed documentation for each module in the project:

Alerts (alerts.ipynb)

FastHTML alert and notification components for user feedback

Import

from cjm_fasthtml_byok.components.alerts import (
    InfoIcon,
    SuccessIcon,
    WarningIcon,
    ErrorIcon,
    Alert,
    SecurityAlert,
    KeyStatusNotification,
    ToastContainer,
    Toast,
    ValidationMessage,
    AlertStack
)

Functions

def InfoIcon(
    size: str = "6"  # Size of the icon (matches Tailwind h-{size} and w-{size} classes)
) -> FT:  # SVG element for the info icon
    "Create an info icon SVG."
def SuccessIcon(
    size: str = "6"  # Size of the icon (matches Tailwind h-{size} and w-{size} classes)
) -> FT:  # SVG element for the success icon
    "Create a success/check icon SVG."
def WarningIcon(
    size: str = "6"  # Size of the icon (matches Tailwind h-{size} and w-{size} classes)
) -> FT:  # SVG element for the warning icon
    "Create a warning/exclamation icon SVG."
def ErrorIcon(
    size: str = "6"  # Size of the icon (matches Tailwind h-{size} and w-{size} classes)
) -> FT:  # SVG element for the error icon
    "Create an error/X icon SVG."
def Alert(
    message: str,  # The alert message
    kind: Literal["info", "success", "warning", "error"] = "info",
    title: Optional[str] = None,  # Optional title for the alert
    dismissible: bool = False,  # Whether the alert can be dismissed
    show_icon: bool = True,  # Whether to show an icon
    style: Optional[str] = None,  # Alert style ("soft", "outline", or None for default)
    id: Optional[str] = None  # HTML ID for the alert element
) -> FT:  # Alert component
    "Create an alert component for displaying messages."
def SecurityAlert(
    message: str,  # Security alert message
    severity: Literal["low", "medium", "high", "critical"] = "medium",
    action_url: Optional[str] = None,  # Optional URL for remediation action
    action_text: str = "Fix Now"  # Text for the action button
) -> FT:  # Security alert component
    "Create a security-focused alert with severity levels."
def KeyStatusNotification(
    provider: str,  # Provider name
    status: Literal["added", "updated", "deleted", "expired", "invalid"],
    masked_key: Optional[str] = None,  # Masked version of the key
    auto_dismiss: bool = True,  # Whether to auto-dismiss
    dismiss_after: int = 5000  # Milliseconds before auto-dismiss
) -> FT:  # Key status notification component
    "Create a notification for API key status changes."
def ToastContainer(
    position: Literal["top", "middle", "bottom"] = "top",
    align: Literal["start", "center", "end"] = "end",
    id: str = "toast-container"  # HTML ID for the container
) -> FT:  # Toast container component
    "Create a container for toast notifications."
def Toast(
    message: str,  # Toast message
    kind: Literal["info", "success", "warning", "error"] = "info",
    duration: int = 3000  # Duration in milliseconds
) -> FT:  # Toast notification component
    "Create a toast notification."
def ValidationMessage(
    message: str,  # Validation message
    is_valid: bool = False,  # Whether the validation passed
    show_icon: bool = True  # Whether to show an icon
) -> FT:  # Validation message component
    "Create an inline validation message for form fields."
def AlertStack(
    alerts: list,  # List of alert components
    max_visible: int = 3,  # Maximum number of visible alerts
    spacing: str = "4"  # Gap between alerts
) -> FT:  # Alert stack component
    "Create a stack of alerts with optional limit."

Beforeware (beforeware.ipynb)

FastHTML beforeware for API key management

Import

from cjm_fasthtml_byok.middleware.beforeware import (
    create_byok_beforeware,
    require_api_key,
    require_any_api_key,
    SecurityCheckBeforeware,
    CleanupBeforeware,
    setup_byok
)

Functions

def create_byok_beforeware(
    byok_manager: BYOKManager  # The BYOK manager instance
)
    "Create a FastHTML beforeware handler for BYOK functionality."
def require_api_key(
    provider: str,  # The provider name to check for
    user_id_func: Optional[Callable] = None  # Optional function to get user_id from request Usage: @rt @require_api_key("openai") def chat(request): byok = request.scope['byok'] api_key = byok.get_key(request, "openai") # Use the API key...
)
    "Decorator that requires an API key to be present for a route."
def require_any_api_key(
    providers: List[str],  # List of provider names to check
    user_id_func: Optional[Callable] = None  # Optional function to get user_id from request Usage: @rt @require_any_api_key(["openai", "anthropic", "google"]) def chat(request): # Use whichever API key is available pass
)
    "Decorator that requires at least one of the specified API keys."
def setup_byok(
    secret_key: str,  # Application secret key
    db: Optional[Any] = None,  # Optional database for persistent storage
    user_id_func: Optional[Callable] = None,  # Optional function to get user_id from request
    enable_security_checks: bool = True,  # Enable HTTPS checking
    enable_cleanup: bool = True  # Enable automatic cleanup of expired keys
)
    "Complete setup helper for BYOK with FastHTML. Returns beforeware functions and the BYOK manager."

Classes

class SecurityCheckBeforeware:
    def __init__(
        self,
        require_https: bool = True,  # Whether to require HTTPS in production
        is_production: Optional[bool] = None  # Whether running in production (auto-detected if None)
    )
    "Beforeware that performs security checks."
    
    def __init__(
            self,
            require_https: bool = True,  # Whether to require HTTPS in production
            is_production: Optional[bool] = None  # Whether running in production (auto-detected if None)
        )
        "Initialize security check beforeware with HTTPS requirements"
class CleanupBeforeware:
    def __init__(
        self,
        byok_manager: BYOKManager,  # The BYOK manager instance
        user_id_func: Optional[Callable] = None  # Optional function to get user_id from request
    )
    "Beforeware that cleans up expired keys."
    
    def __init__(
            self,
            byok_manager: BYOKManager,  # The BYOK manager instance
            user_id_func: Optional[Callable] = None  # Optional function to get user_id from request
        )
        "Initialize cleanup beforeware with BYOK manager"

Forms (forms.ipynb)

FastHTML form components for API key input and management

Import

from cjm_fasthtml_byok.components.forms import (
    KeyInputForm,
    MultiProviderKeyForm,
    KeyManagementCard,
    KeyManagerDashboard,
    InlineKeyInput
)

Functions

def KeyInputForm(
    provider: str,  # The API provider identifier
    action: Optional[str] = None,  # Form action URL (defaults to /api/keys/{provider})
    method: str = "post",  # HTTP method (default: "post")
    show_help: bool = True,  # Whether to show help text
    custom_placeholder: Optional[str] = None,  # Custom placeholder text
    extra_fields: Optional[List[tuple]] = None,  # Additional form fields as [(name, type, placeholder, required), ...]
    provider_config: Optional[Dict[str, Any]] = None  # Optional provider configuration
) -> FT:  # FastHTML Form component
    "Create a form for inputting an API key with improved design."
def MultiProviderKeyForm(
    providers: List[str],  # List of provider identifiers
    action: str = "/api/keys",  # Form action URL
    method: str = "post",  # HTTP method
    default_provider: Optional[str] = None,  # Initially selected provider
    provider_config: Optional[Dict[str, Any]] = None  # Optional provider configuration
) -> FT:  # FastHTML Form component with provider selection
    "Create a form that allows selecting from multiple providers with enhanced UX."
def KeyManagementCard(
    provider: str,  # Provider identifier
    has_key: bool,  # Whether a key is stored
    masked_key: Optional[str] = None,  # Masked version of the key for display
    created_at: Optional[str] = None,  # When the key was stored
    expires_at: Optional[str] = None,  # When the key expires
    delete_action: Optional[str] = None,  # URL for delete action
    update_action: Optional[str] = None,  # URL for update action
    provider_config: Optional[Dict[str, Any]] = None  # Optional provider configuration
) -> FT:  # Card component for key management
    "Create a card component for managing a stored API key with enhanced design."
def KeyManagerDashboard(
    request,  # FastHTML request object
    providers: List[str],  # List of provider identifiers to manage
    byok_manager = None,
    user_id: Optional[str] = None,  # Optional user ID for database storage
    base_url: str = "/api/keys",  # Base URL for API endpoints
    provider_config: Optional[Dict[str, Any]] = None  # Optional provider configuration
) -> FT:  # Dashboard component with all provider cards
    "Create a complete dashboard for managing multiple API keys with improved layout."
def InlineKeyInput(
    provider: str,  # Provider identifier
    input_id: Optional[str] = None,  # HTML ID for the input element
    on_save: Optional[str] = None,  # JavaScript to execute on save (or hx-post URL for HTMX)
    compact: bool = True,  # Whether to use compact styling
    provider_config: Optional[Dict[str, Any]] = None  # Optional provider configuration
) -> FT:  # Inline input component
    "Create a compact inline key input component with polished design."

Helpers (helpers.ipynb)

Helper functions for BYOK system

Import

from cjm_fasthtml_byok.utils.helpers import (
    get_provider_info,
    format_provider_name,
    format_key_age,
    format_expiration,
    get_key_summary,
    get_env_key,
    import_from_env
)

Functions

def get_provider_info(
    provider: str,  # Provider identifier
    provider_config: Optional[Dict[str, Any]] = None  # Optional provider configuration
) -> Dict[str, Any]:  # Provider info dict with defaults
    "Get provider information from config or generate defaults."
def format_provider_name(
    provider: str,  # Provider identifier
    provider_config: Optional[Dict[str, Any]] = None  # Optional provider configuration
) -> str:  # Formatted provider name
    "Format provider name for display."
def format_key_age(
    created_at: datetime  # When the key was created
) -> str:  # Human-readable age string
    "Format the age of a key for display."
def format_expiration(
    expires_at: Optional[datetime]  # Expiration datetime
) -> str:  # Human-readable expiration string
    "Format expiration time for display."
def get_key_summary(
    byok_manager,  # BYOK manager instance
    request,  # FastHTML request
    user_id: Optional[str] = None,  # Optional user ID
    provider_config: Optional[Dict[str, Any]] = None  # Optional provider configuration
) -> Dict[str, Any]:  # Summary dictionary with provider info
    "Get a summary of all stored keys."
def get_env_key(
    provider: str,  # Provider name
    env_prefix: str = "API_KEY_"  # Environment variable prefix
) -> Optional[str]:  # API key from environment or None
    "Get an API key from environment variables."
def import_from_env(
    byok_manager,  # BYOK manager instance
    request,  # FastHTML request
    providers: List[str],  # List of providers to check
    user_id: Optional[str] = None,  # Optional user ID
    env_prefix: str = "API_KEY_"  # Environment variable prefix
) -> Dict[str, bool]:  # Dict of provider: success status
    "Import API keys from environment variables."

Security (security.ipynb)

Encryption and security utilities for API key management

Import

from cjm_fasthtml_byok.core.security import (
    generate_encryption_key,
    get_or_create_app_key,
    KeyEncryptor,
    check_https,
    validate_environment,
    mask_key,
    get_key_fingerprint
)

Functions

def generate_encryption_key(
    password: Optional[str] = None,  # Optional password to derive key from
    salt: Optional[bytes] = None  # Optional salt for key derivation (required if password provided)
) -> bytes:  # 32-byte encryption key suitable for Fernet
    "Generate or derive an encryption key."
def get_or_create_app_key(
    "Get or create an app-specific encryption key derived from the app's secret key."
def check_https(
    request  # FastHTML/Starlette request object
) -> bool:  # True if using HTTPS, False otherwise
    "Check if the request is using HTTPS."
def validate_environment(
    request,  # FastHTML/Starlette request object
    require_https: bool = True,  # Whether to require HTTPS
    is_production: bool = None  # Whether running in production (auto-detected if None)
) -> None
    "Validate the security environment."
def mask_key(
    key: str,  # The API key to mask
    visible_chars: int = 4  # Number of characters to show at start and end
) -> str:  # Masked key like 'sk-a...xyz'
    "Mask an API key for display purposes."
def get_key_fingerprint(
    key: str  # The API key
) -> str:  # SHA256 fingerprint of the key (first 16 chars)
    "Generate a fingerprint for an API key (for logging/tracking without exposing the key)."

Classes

class KeyEncryptor:
    def __init__(
        self,
        encryption_key: Optional[bytes] = None  # Encryption key to use. If None, generates a new one
    )
    "Handles encryption and decryption of API keys."
    
    def __init__(
            self,
            encryption_key: Optional[bytes] = None  # Encryption key to use. If None, generates a new one
        )
        "Initialize the encryptor.

Args:
    encryption_key: Encryption key to use. If None, generates a new one."
    
    def encrypt(
            self,
            value: str  # Plain text API key to encrypt
        ) -> bytes:  # Encrypted bytes
        "Encrypt an API key value.

Args:
    value: Plain text API key

Returns:
    Encrypted bytes

Raises:
    EncryptionError: If encryption fails"
    
    def decrypt(
            self,
            encrypted_value: bytes  # Encrypted bytes to decrypt
        ) -> str:  # Decrypted plain text API key
        "Decrypt an API key value.

Args:
    encrypted_value: Encrypted bytes

Returns:
    Decrypted API key

Raises:
    EncryptionError: If decryption fails"
    
    def rotate_key(
            self,
            new_key: bytes,  # New encryption key to use
            encrypted_value: bytes  # Value encrypted with current key
        ) -> bytes:  # Value re-encrypted with new key
        "Re-encrypt a value with a new key.

Args:
    new_key: New encryption key
    encrypted_value: Value encrypted with current key

Returns:
    Value encrypted with new key"

Storage (storage.ipynb)

Storage backends for API keys (session and database)

Import

from cjm_fasthtml_byok.core.storage import (
    SessionStorage,
    DatabaseStorage,
    HybridStorage,
    BYOKManager
)

Classes

class SessionStorage:
    def __init__(
        self,
        config: BYOKConfig  # BYOK configuration object
    )
    """
    Session-based storage for API keys.
    Keys are stored in the user's session and expire with the session.
    """
    
    def __init__(
            self,
            config: BYOKConfig  # BYOK configuration object
        )
        "Initialize session storage with configuration"
    
    def store(
            self,
            request: Any,  # FastHTML/Starlette request object with session
            key: APIKey  # API key object to store
        ) -> None
        "Store an API key in the session"
    
    def retrieve(
            self,
            request: Any,  # FastHTML/Starlette request object with session
            provider: str,  # Provider name to retrieve key for
            user_id: Optional[str] = None  # User ID (unused in session storage)
        ) -> Optional[APIKey]:  # API key object if found and valid, None otherwise
        "Retrieve an API key from the session"
    
    def delete(
            self,
            request: Any,  # FastHTML/Starlette request object with session
            provider: str,  # Provider name to delete key for
            user_id: Optional[str] = None  # User ID (unused in session storage)
        ) -> None
        "Delete an API key from the session"
    
    def list_providers(
            self,
            request: Any,  # FastHTML/Starlette request object with session
            user_id: Optional[str] = None  # User ID (unused in session storage)
        ) -> List[str]:  # List of provider names with stored keys
        "List all providers with stored keys"
    
    def clear_all(
            self,
            request: Any,  # FastHTML/Starlette request object with session
            user_id: Optional[str] = None  # User ID (unused in session storage)
        ) -> None
        "Clear all API keys from the session"
class DatabaseStorage:
    def __init__(
        self,
        config: BYOKConfig,  # BYOK configuration object
        db_url: str = "sqlite:///byok_keys.db"  # Database URL (defaults to SQLite)
    )
    """
    Database-backed storage for API keys using SQLAlchemy 2.0+.
    Keys persist across sessions and devices.
    """
    
    def __init__(
            self,
            config: BYOKConfig,  # BYOK configuration object
            db_url: str = "sqlite:///byok_keys.db"  # Database URL (defaults to SQLite)
        )
        "Initialize database storage with SQLAlchemy."
    
    def store(
            self,
            request: Any,  # FastHTML/Starlette request object (unused but kept for interface consistency)
            key: APIKey  # API key object to store in database
        ) -> None
        "Store an API key in the database"
    
    def retrieve(
            self,
            request: Any,  # FastHTML/Starlette request object (unused but kept for interface consistency)
            provider: str,  # Provider name to retrieve key for
            user_id: Optional[str] = None  # User ID to retrieve key for (required for database)
        ) -> Optional[APIKey]:  # API key object if found and valid, None otherwise
        "Retrieve an API key from the database"
    
    def delete(
            self,
            request: Any,  # FastHTML/Starlette request object (unused but kept for interface consistency)
            provider: str,  # Provider name to delete key for
            user_id: Optional[str] = None  # User ID to delete key for (required for database)
        ) -> None
        "Delete an API key from the database"
    
    def list_providers(
            self,
            request: Any,  # FastHTML/Starlette request object (unused but kept for interface consistency)
            user_id: Optional[str] = None  # User ID to list providers for (required for database)
        ) -> List[str]:  # List of provider names with stored keys
        "List all providers with stored keys for a user"
    
    def clear_all(
            self,
            request: Any,  # FastHTML/Starlette request object (unused but kept for interface consistency)
            user_id: Optional[str] = None  # User ID to clear keys for (required for database)
        ) -> None
        "Clear all API keys for a user"
class HybridStorage:
    def __init__(
        self,
        config: BYOKConfig,  # BYOK configuration object
        db_url: Optional[str] = None  # Optional database URL for persistent storage
    )
    """
    Hybrid storage using both session and database.
    Session acts as a cache, database provides persistence.
    """
    
    def __init__(
            self,
            config: BYOKConfig,  # BYOK configuration object
            db_url: Optional[str] = None  # Optional database URL for persistent storage
        )
        "Initialize hybrid storage with session and optional database backends"
    
    def store(
            self,
            request: Any,  # FastHTML/Starlette request object with session
            key: APIKey  # API key object to store
        ) -> None
        "Store in both session and database"
    
    def retrieve(
            self,
            request: Any,  # FastHTML/Starlette request object with session
            provider: str,  # Provider name to retrieve key for
            user_id: Optional[str] = None  # User ID for database lookup
        ) -> Optional[APIKey]:  # API key object if found, None otherwise
        "Retrieve from session first, then database"
    
    def delete(
            self,
            request: Any,  # FastHTML/Starlette request object with session
            provider: str,  # Provider name to delete key for
            user_id: Optional[str] = None  # User ID for database deletion
        ) -> None
        "Delete from both storages"
    
    def list_providers(
            self,
            request: Any,  # FastHTML/Starlette request object with session
            user_id: Optional[str] = None  # User ID for database lookup
        ) -> List[str]:  # Combined list of providers from both storages
        "List providers from both storages"
    
    def clear_all(
            self,
            request: Any,  # FastHTML/Starlette request object with session
            user_id: Optional[str] = None  # User ID for database clearing
        ) -> None
        "Clear from both storages"
class BYOKManager:
    def __init__(
        self,
        secret_key: str,  # Application secret key for encryption
        db_url: Optional[str] = None,  # Optional database URL for persistent storage (e.g., "sqlite:///keys.db")
        config: Optional[BYOKConfig] = None  # Optional configuration (uses defaults if not provided)
    )
    """
    Main manager for the BYOK system.
    Handles encryption and storage coordination.
    """
    
    def __init__(
            self,
            secret_key: str,  # Application secret key for encryption
            db_url: Optional[str] = None,  # Optional database URL for persistent storage (e.g., "sqlite:///keys.db")
            config: Optional[BYOKConfig] = None  # Optional configuration (uses defaults if not provided)
        )
        "Initialize the BYOK manager."
    
    def set_key(
            self,
            request: Any,  # FastHTML/Starlette request object
            provider: str,  # Provider name (e.g., 'openai', 'anthropic')
            api_key: str,  # The API key to store
            user_id: Optional[str] = None,  # Optional user ID for database storage
            ttl: Optional[timedelta] = None  # Optional time-to-live for the key
        ) -> None
        "Store an API key."
    
    def get_key(
            self,
            request: Any,  # FastHTML/Starlette request object
            provider: str,  # Provider name
            user_id: Optional[str] = None  # Optional user ID for database lookup
        ) -> Optional[str]:  # Decrypted API key or None if not found
        "Retrieve and decrypt an API key."
    
    def delete_key(
            self,
            request: Any,  # FastHTML/Starlette request object
            provider: str,  # Provider name
            user_id: Optional[str] = None  # Optional user ID
        ) -> None
        "Delete an API key."
    
    def list_providers(
            self,
            request: Any,  # FastHTML/Starlette request object
            user_id: Optional[str] = None  # Optional user ID
        ) -> List[str]:  # List of provider names
        "List all providers with stored keys."
    
    def clear_keys(
            self,
            request: Any,  # FastHTML/Starlette request object
            user_id: Optional[str] = None  # Optional user ID
        ) -> None
        "Clear all stored API keys."
    
    def has_key(
            self,
            request: Any,  # FastHTML/Starlette request object
            provider: str,  # Provider name
            user_id: Optional[str] = None  # Optional user ID
        ) -> bool:  # True if key exists, False otherwise
        "Check if a key exists for a provider."

Types (types.ipynb)

Type definitions and protocols for the BYOK system

Import

from cjm_fasthtml_byok.core.types import (
    StorageBackend,
    APIKey,
    KeyStorage,
    BYOKConfig,
    UserAPIKey,
    BYOKException,
    EncryptionError,
    StorageError,
    KeyNotFoundError,
    SecurityWarning
)

Classes

class StorageBackend(Enum):
    "Available storage backends for API keys"
@dataclass
class APIKey:
    "Represents an encrypted API key with metadata"
    
    provider: str  # e.g., 'openai', 'anthropic', 'google'
    encrypted_value: bytes  # Encrypted key value
    created_at: datetime = field(...)
    expires_at: Optional[datetime]
    user_id: Optional[str]  # For database storage
    
    def is_expired(
            self
        ) -> bool:  # True if key has expired, False otherwise
        "Check if the key has expired"
    
    def to_dict(
            self
        ) -> Dict[str, Any]:  # Dictionary representation for serialization
        "Convert to dictionary for storage"
    
    def from_dict(
            cls,  # The APIKey class
            data: Dict[str, Any]  # Dictionary containing serialized key data
        ) -> 'APIKey':  # Reconstructed APIKey instance
        "Create from dictionary"
@runtime_checkable
class KeyStorage(Protocol):
    "Protocol for key storage implementations"
    
    def store(
            self,
            request: Any,  # FastHTML/Starlette request object
            key: APIKey  # API key object to store
        ) -> None
        "Store an API key"
    
    def retrieve(
            self,
            request: Any,  # FastHTML/Starlette request object
            provider: str,  # Provider name to retrieve key for
            user_id: Optional[str] = None  # Optional user ID for database lookup
        ) -> Optional[APIKey]:  # API key object if found, None otherwise
        "Retrieve an API key for a provider"
    
    def delete(
            self,
            request: Any,  # FastHTML/Starlette request object
            provider: str,  # Provider name to delete key for
            user_id: Optional[str] = None  # Optional user ID for database deletion
        ) -> None
        "Delete an API key"
    
    def list_providers(
            self,
            request: Any,  # FastHTML/Starlette request object
            user_id: Optional[str] = None  # Optional user ID for database lookup
        ) -> list[str]:  # List of provider names with stored keys
        "List all stored providers"
    
    def clear_all(
            self,
            request: Any,  # FastHTML/Starlette request object
            user_id: Optional[str] = None  # Optional user ID for database clearing
        ) -> None
        "Clear all stored keys"
@dataclass
class BYOKConfig:
    "Configuration for the BYOK system"
    
    storage_backend: StorageBackend = StorageBackend.SESSION
    encryption_key: Optional[bytes]  # If None, will be generated
    default_ttl: Optional[timedelta] = timedelta(hours=24)  # Default key expiration
    session_key_prefix: str = 'byok_'  # Prefix for session storage keys
    db_table_name: str = 'user_api_keys'  # Database table name
    auto_cleanup: bool = True  # Auto-cleanup expired keys
    require_https: bool = True  # Warn if not using HTTPS in production
class UserAPIKey:
    "Database schema for persistent API key storage (for use with fastsql)"
class BYOKException(Exception):
    "Base exception for BYOK errors"
class EncryptionError(BYOKException):
    "Error during encryption/decryption"
class StorageError(BYOKException):
    "Error during storage operations"
class KeyNotFoundError(BYOKException):
    "Requested key not found"
class SecurityWarning(BYOKException):
    "Security-related warning"

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cjm_fasthtml_byok-0.0.3.tar.gz (38.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cjm_fasthtml_byok-0.0.3-py3-none-any.whl (36.0 kB view details)

Uploaded Python 3

File details

Details for the file cjm_fasthtml_byok-0.0.3.tar.gz.

File metadata

  • Download URL: cjm_fasthtml_byok-0.0.3.tar.gz
  • Upload date:
  • Size: 38.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.13

File hashes

Hashes for cjm_fasthtml_byok-0.0.3.tar.gz
Algorithm Hash digest
SHA256 55f03ccdb2cac8e65e04b011e5e72a7a399d992e1f113b3bd7998895b1c77781
MD5 9e1dba4c7b92a67d00174432d5fd0820
BLAKE2b-256 fd3ba66d6cd9073533ff1d285febd2e9bdf750cc2237372b690f8c39b7813585

See more details on using hashes here.

File details

Details for the file cjm_fasthtml_byok-0.0.3-py3-none-any.whl.

File metadata

File hashes

Hashes for cjm_fasthtml_byok-0.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 6a1d9477e645a9ce1e31d60d9c735edc8863fe31ffb683a86274dc8059899e17
MD5 ed52f745160bb85330f151b639f76e77
BLAKE2b-256 f82cc08dab4bed11c1ecead1dfab706de0c21510b26a29b7f107627b7f02ece7

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page