Row-level security as the adapter: the rules are Postgres policies on the tables themselves.
Migrations write the policies. The database enforces them on every
statement, with the statements this library never sees among them. The
configuration entry is the bare module, because the adapter takes no
options (Mediate.Config). The adapter finds the repo and the schemas
through the binding that Mediate.Postgres.Binding.bind/1 makes at boot.
Three mechanisms.
Session settings. around_query/3 runs set_config(name, value, true)
for the length of the call. It sets mediate.subject_id,
mediate.subject_kind, mediate.operation, mediate.now, and one name
per fact the caller supplied. A call outside a transaction opens one, so
the settings leave with the call. Two subjects in one transaction each
set their own. A policy reads a setting with current_setting(name, true).
Answers. decide runs one statement under those settings. A row the
operation's SELECT policy does not admit is a denial. Where the
operation has an UPDATE gate, the same statement reads the gate's
USING expression. So an answer given before a write agrees with what
WITH CHECK does to the write.
scope runs no statement and answers the rule true, because the policy
narrows the query when the repo runs it. Its reason names the policy and
the SHA-256 of the settings the database reads, which together are what
it enforced. The scope cap is :none.
Policy versions. The version is the migration number.
Mediate.Postgres.Migration.publish!/2 reads the policies back from
pg_policy and emits the version in the same transaction as the DDL.
the events document under
"Policy version" has the event.
The database does not report which policy admitted a row, so an answer names the policy of the operation and nothing further. The adapter reports the replica-lag component of revocation latency as "not measured", because every statement goes to the primary.
The application's role must carry NOBYPASSRLS, because a role with
BYPASSRLS is not subject to the policies. The package carries no
driver: ecto_sql and postgrex serve its tests alone, and Boundary
holds lib to that.
Summary
Functions
Read the policies and the version once, so no call on the request path pays for the read. An application calls this at boot, after the binding.
Read the policies and the version again, for an application that ran a migration after boot. Every call after this one reads what the database now holds.
The component of revocation latency this adapter cannot measure.
Functions
@spec load!() :: Mediate.Postgres.Catalog.t()
Read the policies and the version once, so no call on the request path pays for the read. An application calls this at boot, after the binding.
@spec reload!() :: Mediate.Postgres.Catalog.t()
Read the policies and the version again, for an application that ran a migration after boot. Every call after this one reads what the database now holds.
@spec replica_lag() :: String.t()
The component of revocation latency this adapter cannot measure.