# `Ash.Policy.Check`
[🔗](https://github.com/ash-project/ash/blob/v3.23.1/lib/ash/policy/check.ex#L5)

A behaviour for declaring checks, which can be used to easily construct
authorization rules.

If a check can be expressed simply, i.e as a function of the actor, or the context of the request,
see `Ash.Policy.SimpleCheck` for an easy way to write that check.
If a check can be expressed with a filter statement, see `Ash.Policy.FilterCheck`
for an easy way to write that check.

# `actor`

```elixir
@type actor() :: any()
```

# `authorizer`

```elixir
@type authorizer() :: Ash.Policy.Authorizer.t()
```

# `check_type`

```elixir
@type check_type() :: :simple | :filter | :manual
```

# `context`

```elixir
@type context() :: %{resource: Ash.Resource.t()}
```

# `options`

```elixir
@type options() :: Keyword.t()
```

# `ref`

```elixir
@type ref() :: {module(), Keyword.t()} | module()
```

# `t`

```elixir
@type t() :: %Ash.Policy.Check{
  __spark_metadata__: Spark.Dsl.Entity.spark_meta(),
  check: ref(),
  check_module: module(),
  check_opts: options(),
  type: check_type()
}
```

# `auto_filter`
*optional* 

```elixir
@callback auto_filter(actor(), authorizer(), options()) :: Keyword.t() | Ash.Expr.t()
```

An optional callback, that allows the check to work with policies set to `access_type :filter`

Return a keyword list filter that will be applied to the query being made, and will scope the results to match the rule

# `check`
*optional* 

```elixir
@callback check(actor(), [Ash.Resource.record()], map(), options()) :: [
  Ash.Resource.record()
]
```

An optional callback, that allows the check to work with policies set to `access_type :runtime`

Takes a list of records, and returns the subset of authorized records.

# `conflicts?`
*optional* 

```elixir
@callback conflicts?(ref(), ref(), context()) :: boolean()
```

Determine if two check references are mutually exclusive (conflicting).

This is used by the SAT solver to optimize policy evaluation by understanding
when two checks cannot both be true at the same time.

# `describe`

```elixir
@callback describe(options()) :: String.t()
```

Describe the check in human readable format, given the options

# `eager_evaluate?`

```elixir
@callback eager_evaluate?() :: boolean()
```

# `expand_description`
*optional* 

```elixir
@callback expand_description(
  actor(),
  authorizer(),
  options()
) :: {:ok, String.t()} | :none
```

Expands the description of the check, given the actor and subject

# `implies?`
*optional* 

```elixir
@callback implies?(ref(), ref(), context()) :: boolean()
```

Determine if the first check reference implies the second check reference.

This is used by the SAT solver to optimize policy evaluation by understanding
when one check being true guarantees another check is also true.

# `init`

```elixir
@callback init(opts :: Keyword.t()) :: {:ok, Keyword.t()} | {:error, String.t()}
```

Initialize and validate the opts for the check module.

This callback is called at compile time when the check is defined in a policy.
It allows checks to verify and normalize their options before they are used.

# `prefer_expanded_description?`

```elixir
@callback prefer_expanded_description?() :: boolean()
```

Whether or not the expanded description should replace the basic description in breakdowns

# `requires_original_data?`

```elixir
@callback requires_original_data?(authorizer(), options()) :: boolean()
```

Whether or not your check requires the original data of a changeset (if applicable)

# `simplify`
*optional* 

```elixir
@callback simplify(ref(), context()) :: Crux.Expression.t(ref())
```

Simplify a check reference into a SAT expression of simpler check references.

This is used by the SAT solver to break down complex checks into simpler components
for more efficient policy evaluation. For example, a check that matches multiple
action types could be simplified into an OR expression of separate checks for each
action type. Or ActorAbsent could simplify into `not(ActorPresent)`.

# `strict_check`

```elixir
@callback strict_check(actor(), authorizer(), options()) ::
  {:ok, boolean() | :unknown} | {:error, term()}
```

Strict checks should be cheap, and should never result in external calls (like database or domain)

It should return `{:ok, true}` if it can tell that the request is authorized, and `{:ok, false}` if
it can tell that it is not. If unsure, it should return `{:ok, :unknown}`

# `type`

```elixir
@callback type() :: check_type()
```

The type of the check

`:manual` checks must be written by hand as standard check modules
`:filter` checks can use `Ash.Policy.FilterCheck` for simplicity
`:simple` checks can use `Ash.Policy.SimpleCheck` for simplicity

# `defines_auto_filter?`

# `defines_check?`

---

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