# `Sekisho.Explanation`
[🔗](https://github.com/hattoriai/sekisho/blob/v0.1.0-dev/lib/sekisho/explanation.ex#L1)

Why a permission is allowed or not: what `explain/3` returns.

`reasons` lists everything that allows it, each one of:

  * `{:allow}`: a rule of the policy (`allow/2`);
  * `{:grant, role, grant}`: a role granted on the record (`Sekisho.Grant`),
    a role of the policy (an atom) or one the record defines (its name);
  * `{:source, role}`: a role from your sources;
  * `{:related, role, relation, record, reasons}`: a role derived from one
    held on a related record, and why that one is held;
  * `{:derived, permission, relation, record, reasons}`: the permission,
    from a role or a permission on a related record, and why.

`denied` is true when `deny/2` refuses it, whatever the reasons.

    iex> MyApp.Permissions.explain(scope, :update, document)
    #Sekisho.Explanation<allowed :update on MyApp.Docs.Document 7
      holds :editor through :folder: MyApp.Docs.Folder 3
        holds :viewer through :parent: MyApp.Docs.Folder 1
          holds :owner: granted to users 5>

# `reason`

```elixir
@type reason() ::
  {:allow}
  | {:grant, atom() | String.t(), Sekisho.Grant.t()}
  | {:source, atom()}
  | {:related, atom(), atom(), struct(), [reason()]}
  | {:derived, atom(), atom(), struct(), [reason()]}
```

# `t`

```elixir
@type t() :: %Sekisho.Explanation{
  allowed?: boolean(),
  denied: boolean(),
  permission: atom(),
  reasons: [reason()],
  resource: struct()
}
```

# `lines`

```elixir
@spec lines(t()) :: [String.t()]
```

The explanation as lines of text, for a log or a test's failure.

---

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