Foresight.Tenancy (Foresight v0.1.1)

Copy Markdown View Source

Public tenant-schema provisioning and execution boundaries.

Consumers embedding Foresight should use provision_mode_c_schema/4 to create or upgrade a role-neutral Mode C schema. Role and tenant-key lifecycle remains an opt-in concern of Foresight's HTTP deployment surface.

Summary

Functions

Installs Foresight's control plane and provisions a Mode C tenant schema.

Reset all tenant scoping on a freshly checked-out connection.

Runs fun inside the database scope described by ctx.

Runs fun inside the database scope described by ctx.

Functions

provision_mode_c_schema(repo, tenant_id, prefix, opts \\ [])

@spec provision_mode_c_schema(module(), String.t(), String.t(), keyword()) ::
  {:ok,
   %{tenant_id: String.t(), prefix: String.t(), migrated_versions: [integer()]}}
  | {:error, term()}

Installs Foresight's control plane and provisions a Mode C tenant schema.

:rls_enabled is required and must be a boolean. The operation deliberately does not create a PostgreSQL role or a tenant API-key record. It delegates the schema work to the internal schema provisioner with runtime startup disabled and returns that provisioner's result:

{:ok, %{tenant_id: tenant_id, prefix: prefix, migrated_versions: versions}}

Additional options are passed to the schema provisioner. :repo, :tenant_id, :rls_enabled, and :start_runtime cannot be overridden by those options.

reset_connection(conn)

@spec reset_connection(pid()) :: :ok

Reset all tenant scoping on a freshly checked-out connection.

Used as a Postgrex after_connect hook: clears both the role and the session-level foresight.tenant_prefix GUC. Both are set non-LOCAL, so if a scope's after cleanup is ever skipped (process killed mid-flight), a stale role or prefix could otherwise ride a pooled connection into the next tenant's request.

Also applies hnsw.ef_search = 200 for HNSW recall-quality parity with Hindsight (memory_engine.py:1900-1905) — pgvector's default of 40 under-searches the per-fact_type semantic ANN queries. Set per connection (persists for its lifetime), and best-effort: a build without the pgvector HNSW GUC must not kill the connection.

with_tenant_role(ctx, fun)

@spec with_tenant_role(Foresight.Context.t(), (-> result)) :: result when result: var

Runs fun inside the database scope described by ctx.

with_tenant_role(ctx, fun, opts)

@spec with_tenant_role(Foresight.Context.t(), (-> result), keyword()) :: result
when result: var

Runs fun inside the database scope described by ctx.

Options include :repo and :rls_enabled. An explicitly supplied boolean :rls_enabled always overrides application configuration.