Jump to content

Connect SuperML | Leeroopedia MCP: Equip your AI agents with best practices, code verification, and debugging knowledge. Powered by Leeroo — building Organizational Superintelligence. Contact us at founders@leeroo.com.

Implementation:OpenHands OpenHands SaasSettingsStore

From Leeroopedia
Knowledge Sources
Domains Storage, Settings, SaaS_Infrastructure
Last Updated 2026-02-11 21:00 GMT

Overview

Multi-table settings composition store with LiteLLM key management and field-level encryption, provided by the OpenHands enterprise storage layer.

Description

SaasSettingsStore manages user and organization settings by composing data from multiple database tables into a unified settings object and distributing writes back across those tables.

The load() method reads from three sources -- the Org table, the User table, and the OrgMember table -- and merges them into a single settings dictionary. This composition allows settings to have different scopes (organization-wide vs. user-specific vs. membership-specific) while presenting a unified interface to callers.

The store() method performs the reverse operation: it takes a unified settings dictionary and distributes the values to the appropriate tables based on which fields belong where.

A key feature is _ensure_api_key(), which manages LiteLLM API keys. When settings include LLM configuration, this method ensures a valid LiteLLM API key exists for the user, creating one if necessary. This integrates the settings store with the LiteLLM proxy for model routing.

The store encrypts sensitive fields before persisting them. The ENCRYPT_VALUES list defines which fields require encryption:

ENCRYPT_VALUES = ['llm_api_key', 'llm_api_key_for_byor', 'search_api_key']

These fields are encrypted at rest and decrypted when loaded, ensuring API keys and credentials are never stored in plaintext.

Usage

Use SaasSettingsStore in the settings API endpoints to load and persist user/org settings. Call load() to retrieve the composed settings for display in the UI. Call store() after the user saves changes to distribute updates to the appropriate tables and ensure LiteLLM keys are provisioned.

Code Reference

Source Location

Signature

class SaasSettingsStore:
    ENCRYPT_VALUES = ['llm_api_key', 'llm_api_key_for_byor', 'search_api_key']

    def __init__(self, session: Session, org_id: str, config: AppConfig):
        ...

    def load(self, user_id: str) -> dict:
        """Composes settings from Org + User + OrgMember tables into a unified dict."""
        ...

    def store(self, user_id: str, settings: dict) -> None:
        """Distributes settings to appropriate tables and ensures LiteLLM key exists."""
        ...

    def _ensure_api_key(self, user_id: str, settings: dict) -> str:
        """Creates or retrieves a LiteLLM API key for the user."""
        ...

Import

from enterprise.storage.saas_settings_store import SaasSettingsStore

I/O Contract

Inputs

Constructor

Name Type Required Description
session Session Yes SQLAlchemy database session for executing queries
org_id str Yes Organization ID that scopes the settings
config AppConfig Yes Application configuration containing encryption keys and LiteLLM settings

load()

Name Type Required Description
user_id str Yes The user whose composed settings to load

store()

Name Type Required Description
user_id str Yes The user whose settings to persist
settings dict Yes Unified settings dictionary; values are distributed to appropriate tables

_ensure_api_key()

Name Type Required Description
user_id str Yes The user to provision a LiteLLM key for
settings dict Yes The current settings (used to determine if LLM config is present)

Outputs

Method Return Type Description
load() dict Unified settings dictionary composed from Org, User, and OrgMember tables (encrypted fields are decrypted)
store() None Distributes settings to tables, encrypts sensitive fields, and provisions LiteLLM key if needed
_ensure_api_key() str The LiteLLM API key (existing or newly created)

Encrypted Fields

Field Name Description
llm_api_key Primary LLM provider API key
llm_api_key_for_byor Bring-your-own-runtime LLM API key
search_api_key Search provider API key (e.g., for web search integration)

Usage Examples

Loading Composed Settings

from enterprise.storage.saas_settings_store import SaasSettingsStore

settings_store = SaasSettingsStore(
    session=db_session,
    org_id="org-123",
    config=app_config
)

# Load unified settings from multiple tables
settings = settings_store.load(user_id="user-456")
# Returns composed dict:
# {
#     "llm_model": "claude-sonnet-4-20250514",   (from Org table)
#     "llm_api_key": "sk-decrypted-key",  (from OrgMember, decrypted)
#     "theme": "dark",                     (from User table)
#     ...
# }

Storing Settings with LiteLLM Key Provisioning

# Store updated settings -- values are distributed to the right tables
settings_store.store(
    user_id="user-456",
    settings={
        "llm_model": "claude-sonnet-4-20250514",
        "llm_api_key": "sk-new-api-key",       # Will be encrypted at rest
        "search_api_key": "search-key-abc",  # Will be encrypted at rest
        "theme": "dark",
        "language": "en"
    }
)
# _ensure_api_key() is called internally to provision/verify the LiteLLM key

Related Pages

Related Implementations

Environment

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment