Skip to content

Optional SQL policy providers

Dosi can run independently or bind a request-local SQL policy provider. Public Dosi does not depend on an implementation package. A configured provider is required for that invocation: failure to load or validate it refuses compilation and execution instead of returning unprotected SQL.

Native CLI

Install a trusted native library implementing dosi_policy_plugin_v1 for the same OS/CPU as Dosi. Check dosi info --format json for native ABI and SQL AST schema versions. A Python extension is not a CLI policy library.

# connections.yaml
datasources:
  warehouse:
    type: duckdb
    uri: data.duckdb
    default: true
sql_policy:
  library: plugins/libpolicy.so
  config: policy.yaml
  context: request.json

sql_policy.library, config and optional context are paths relative to the connections file. macOS libraries use .dylib, Windows .dll. Configuration and context are YAML/JSON objects interpreted by the provider; Dosi does not manage roles or authenticate the context's user.

dosi --model model.yaml --connections connections.yaml \
  query --metrics revenue --execute

Explicit deployment overrides are --policy-library, --policy-config and --policy-context-file, or DOSI_POLICY_LIBRARY, DOSI_POLICY_CONFIG and DOSI_POLICY_CONTEXT. Policy compilation opens the selected execution connection for metadata, even without --execute.

The CLI uses protected query/detail/attribution APIs and verifies the bound receipt before execution. Providers receive the completed lowered SQL AST so independently generated subqueries can be protected. No policy is reapplied to returned rows by the generic host.

Python hosts

The policy and policy_required arguments are request-local. Providers may implement bind_execution_host(host) to bind to Dosi's actual native execution connection. The host exposes context_json (connection hints), target, metadata_query(sql) (JSON object rows) and verify_context(); the provider owns actual namespace capture and table/column resolution.

Named execution connections are rebound before compile/execute/detail and attribution. A compilation-only provider may implement for_compilation(); it must reject compilation if it cannot bind safe metadata without a connection. No provider is loaded and no policy metadata is queried when policy is absent. POLICY_EXECUTION_HOST_VERSION advertises this optional binding capability.

Implementing a provider

dosi-policy-api defines the generic Rust traits, native ffi module and optional dynamic loader. The public host contains no private dependency, even as an optional Cargo dependency. Providers may be distributed separately.

Native ABI v1 uses C-compatible structs and versioned JSON. Inputs and host callbacks are borrowed for one synchronous call; they must never be retained. Each response is freed exactly once by its producer's function. Native libraries are trusted code. The host holds the library until all request scopes are gone. ABI or AST schema mismatches are rejected before binding.

Metadata callbacks execute internal metadata SQL on the final executor without re-entering policy rewriting. Providers must verify namespace changes and resolve native columns through that connection. SQLite sources expose read-only native SQLite metadata so declared types are preserved while business SQL uses the DuckDB SQLite bridge.