loom.core.sql.config

Typed configuration for the backend-agnostic sql: section.

Parsed via ctx.section(ConfigKey.SQL, SqlConfig). Validation is fail-fast: invalid values abort the parse and surface as ConfigError through the config loader.

Functions

_redact_url(url)

_validate_endpoint(endpoint, allowed_roles, ...)

_validate_limits(default_limit, max_limit)

_validate_role_format(role)

_validate_roles(allowed_roles, default_role)

roles_need_identity_binding(allowed_roles, ...)

Report whether an allowlist would be left for the caller to pick from.

Classes

SqlConfig(*, connections)

Root of the sql: config section.

SqlConnectionConfig(*, backend, url[, ...])

Named SQL connection with role policy, limits and driver tuning.

SqlEndpointConfig(*[, enabled, auth, path, ...])

Opt-in REST endpoint settings for a SQL connection.

loom.core.sql.config.roles_need_identity_binding(allowed_roles, *, mechanism_binds_roles)[source]

Report whether an allowlist would be left for the caller to pick from.

A connection allowing several roles only makes sense when something binds a caller to a subset of them. Without that binding the allowlist stops being a ceiling and becomes a menu, so every layer that can mount such an endpoint refuses to. The predicate lives here, next to the config it judges; each layer phrases its own error.

Parameters:
  • allowed_roles (Sequence[str]) – Connection allowlist.

  • mechanism_binds_roles (bool) – Whether the configured authentication mechanism binds roles to the verified caller identity.

Returns:

True when the configuration is unsafe as it stands.

Return type:

bool

class loom.core.sql.config.SqlEndpointConfig(*, enabled=False, auth=None, path=None, include_in_schema=False)[source]

Bases: LoomFrozenStruct

Opt-in REST endpoint settings for a SQL connection.

Parameters:
  • enabled (bool)

  • auth (Literal['identity', 'jwt', 'external'] | None)

  • path (str | None)

  • include_in_schema (bool)

enabled

Whether to mount the generic POST /sql/{name} endpoint. Defaults to False (double opt-in).

Type:

bool

auth

Mandatory when enabled: "identity" (the framework authenticates the caller with the configured mechanism and binds roles to their verified identity) or "external" (explicit acknowledgement that the operator provides authentication, with no identity the framework can read). "jwt" is a deprecated alias of "identity".

Type:

Literal[‘identity’, ‘jwt’, ‘external’] | None

path

Mount path override. Defaults to /sql/{name} when None.

Type:

str | None

include_in_schema

Whether the endpoint appears in the OpenAPI schema.

Type:

bool

property binds_identity: bool

Whether this endpoint requires an identity the framework can read.

Returns:

True for "identity" and its deprecated "jwt" alias.

class loom.core.sql.config.SqlConnectionConfig(*, backend, url, username=None, password=None, allowed_roles=(), default_role=None, readonly=True, default_limit=1000, max_limit=10000, max_execution_time=30, max_sql_bytes=262144, connect_timeout=10, send_receive_timeout=60, executor_threads=None, pool_size=None, settings=<factory>, sql_endpoint=<factory>)[source]

Bases: LoomFrozenStruct

Named SQL connection with role policy, limits and driver tuning.

backend

Backend identifier. Only "clickhouse" is supported; any other value fails the parse.

Type:

Literal[‘clickhouse’]

url

Backend DSN. Canonically injected via environment or secret resolver, never inline.

Type:

str

username

Driver username, handed to the driver as an explicit argument. Takes precedence over any credential embedded in url.

Type:

str | None

password

Driver password, handed to the driver as an explicit argument. Unlike a DSN credential it is never URL-parsed, so any character is safe (a # inside a DSN password truncates it as a fragment delimiter and the driver does not unescape quoted ones), and it never appears in repr or in dumps of url.

Type:

str | None

allowed_roles

Ceiling of roles this connection may ever apply — the last barrier, not a per-caller permission. Empty means every caller-provided role is rejected (fail-closed). A mounted endpoint with a non-empty allowlist requires the sql_endpoint.auth mode that binds roles to a verified identity.

Type:

tuple[str, …]

default_role

Role applied when the request carries none. Without it, a request without role is refused. Never a fallback for a request whose roles are bound to verified claims.

Type:

str | None

readonly

Whether queries run in read-only mode. Defaults to True.

Type:

bool

default_limit

Row limit applied when the request brings none.

Type:

int

max_limit

Hard cap for any requested limit.

Type:

int

max_execution_time

Per-query execution timeout in seconds.

Type:

int

max_sql_bytes

Maximum accepted SQL statement size in bytes.

Type:

int

connect_timeout

Driver connect timeout in seconds.

Type:

int

send_receive_timeout

Driver send/receive timeout in seconds.

Type:

int

executor_threads

Async client thread pool size (driver default if None).

Type:

int | None

pool_size

HTTP connection pool size (driver default if None).

Type:

int | None

settings

Extra backend settings handed to the executor at construction. They can never override the policy.

Type:

dict[str, Any]

sql_endpoint

Optional REST endpoint settings for this connection.

Type:

loom.core.sql.config.SqlEndpointConfig

Raises:

ValueError – On invalid role format, default_limit above max_limit, or an enabled endpoint without role/auth, including a non-empty allowlist under an auth mode that carries no verified identity. Surfaced as ConfigError when parsed through the config loader.

Parameters:
class loom.core.sql.config.SqlConfig(*, connections)[source]

Bases: LoomFrozenStruct

Root of the sql: config section.

Parameters:

connections (dict[str, SqlConnectionConfig])

connections

Named SQL connections available to the query service.

Type:

dict[str, loom.core.sql.config.SqlConnectionConfig]