# `Mediate.Repo`
[🔗](https://github.com/mrmeku/mediate/blob/v0.1.0/lib/mediate/repo.ex#L1)

The seam. Its purpose is log completeness: no read or write of a
protected schema goes unrecorded, because a call that carries no decision
and no exemption raises before any SQL. It is not a reference monitor. It
sees repo calls and nothing else, and no control asks it for more.

`use Mediate.Repo` after `use Ecto.Repo` overrides every function of the
Ecto surface the repo defines, and puts each in one of four buckets:

- query: `all`, `one`, `get`, `get_by`, `reload`, `aggregate`, `exists?`,
  `stream`, `preload`, and `all_by`, with their bang forms. A read of a
  protected schema under a decision publishes one access event after it
  returns. `update_all` and `delete_all` sit here too, and refuse on an
  audited schema.
- write: `insert`, `update`, `delete`, `insert_or_update`, and
  `insert_all`, with their bang forms. A single-row write to an audited
  schema publishes one change event inside its transaction.
- raw: `query` and `query_many`, with their bang forms. A raw call passes
  under an exemption and refuses a decision.
- plumbing: everything else passes.

    defmodule MyApp.Repo do
      use Ecto.Repo, otp_app: :my_app, adapter: Ecto.Adapters.Postgres
      use Mediate.Repo
    end

## The `mediate:` option

Every query, write, and raw call takes it, in one of three forms:

- a `%Mediate.Decision{}` from `Mediate.authorize/4` or `Mediate.scope/4`
- `{:exempt, reason}` with a non-empty reason, a declared exemption the
  seam records with the caller
- `{:exempt, :library}`, which the seam accepts from a `Mediate.*` caller
  alone

The root source of a query decides it. A protected root passes when the
decision names its object type, when the parent's decision carries it
through `carries/1`, or when the call is exempt. A joined or subquery
source passes the same way, and a source with no schema or no object type
passes without a check. A preload is a query of its own with the
association's schema as root.

A nested association write that Ecto makes on the caller's behalf reuses
the parent's mediation, because Ecto forwards only `timeout`, `log`,
`telemetry_event`, `prefix`, and `allow_stale` to it. `prepare_query/3`
is the extension point: the seam judges every query there, and an
adapter wraps every mediated call through `around_query/3`.

## What refuses

- `%Mediate.Error{reason: :unmediated}` for a call on a protected schema
  with no decision and no exemption.
- `%Mediate.Error{reason: :invalid}` with `:bulk_write` in the detail for
  `update_all`, `delete_all`, and `insert_all` on an audited schema, with
  `:upsert` for a write with `on_conflict:` on a fact schema, and with
  `:mediate` for a raw call given a decision.
- `%Mediate.Error{}` with the denial's own reason, one of
  `Mediate.Answer.reasons/0`, for a deny decision handed to a call.

## Options

- `role:` `:app`, the application's repo, or `:owner`, the library's own
  channel. Defaults to `:app`.

An owner-role repo runs migrations and the library's own writes. Every
call on it carries the library exemption, and it records nothing.

# `entry`

```elixir
@type entry() :: {atom(), non_neg_integer(), :query | :write | :raw | :plumbing}
```

One function of the surface the repo compiled against: its name, its arity, and its bucket.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
