# `Accrue.Auth`
[🔗](https://github.com/szTheory/accrue/blob/accrue-v0.3.0/lib/accrue/auth.ex#L1)

Behaviour + facade for host-app auth integration (AUTH-01, AUTH-02).

Accrue does NOT own authentication. The host application (using Sigra,
`phx.gen.auth`, Ueberauth, or any custom solution) implements this
behaviour and wires it via `config :accrue, :auth_adapter, MyApp.Auth`.
`Accrue.Admin` (Phase 7) and any callers that need `current_user` reach
through this facade.

## Default adapter (`Accrue.Auth.Default`)

Phase 1 ships a dev-permissive default (`Accrue.Auth.Default`) that
returns a stubbed `%{id: "dev"}` in `:dev` / `:test` and **refuses to
boot** in `:prod` (D-40). Plan 06 will call
`Accrue.Auth.Default.boot_check!/0` from `Accrue.Application.start/2`
so production deploys can never run with no auth in place.

## Contract

- `current_user/1` — lookup the user from a `%Plug.Conn{}` or any
  arbitrary map. Returns the user struct/map or `nil`.
- `require_admin_plug/0` — returns a plug function that raises on
  non-admins. Admin UI mounts this at the router level.
- `user_schema/0` — returns the host's user Ecto schema module (or
  `nil` if not applicable). Used by the admin UI for joins / previews.
- `log_audit/2` — emit an audit record for a user action. Default is
  a no-op; hosts may persist or forward to a SIEM.
- `actor_id/1` — extract the canonical actor id string from a user
  struct/map. Used by `Accrue.Events.record/1` when auto-stamping
  actor context.
- `step_up_challenge/2` — optional destructive-action challenge hook
  for admin step-up flows.
- `verify_step_up/3` — optional destructive-action verification hook
  paired with `step_up_challenge/2`.

# `conn`

```elixir
@type conn() :: Plug.Conn.t() | map()
```

# `user`

```elixir
@type user() :: map() | struct()
```

# `actor_id`

```elixir
@callback actor_id(user()) :: String.t() | nil
```

# `current_user`

```elixir
@callback current_user(conn()) :: user() | nil
```

# `log_audit`

```elixir
@callback log_audit(user(), map()) :: :ok
```

# `require_admin_plug`

```elixir
@callback require_admin_plug() :: (conn(), keyword() -&gt; conn())
```

# `step_up_challenge`
*optional* 

```elixir
@callback step_up_challenge(user(), map()) :: map()
```

# `user_schema`

```elixir
@callback user_schema() :: module() | nil
```

# `verify_step_up`
*optional* 

```elixir
@callback verify_step_up(user(), map(), map()) :: :ok | {:error, term()}
```

# `actor_id`

```elixir
@spec actor_id(user()) :: String.t() | nil
```

Delegates to the configured adapter's `actor_id/1`.

# `admin?`

```elixir
@spec admin?(user() | nil) :: boolean()
```

Returns whether `user` should be treated as an admin.

Adapters may expose a dedicated `admin?/1` helper; otherwise Accrue
falls back to conservative host-shape heuristics (`role`, `is_admin`,
`admin`).

# `current_user`

```elixir
@spec current_user(conn()) :: user() | nil
```

Delegates to the configured adapter's `current_user/1`.

# `log_audit`

```elixir
@spec log_audit(user(), map()) :: :ok
```

Delegates to the configured adapter's `log_audit/2`.

# `require_admin_plug`

```elixir
@spec require_admin_plug() :: (conn(), keyword() -&gt; conn())
```

Delegates to the configured adapter's `require_admin_plug/0`.

# `step_up_challenge`

```elixir
@spec step_up_challenge(user(), map()) :: map()
```

Delegates to the configured adapter's optional `step_up_challenge/2`.

# `user_schema`

```elixir
@spec user_schema() :: module() | nil
```

Delegates to the configured adapter's `user_schema/0`.

# `verify_step_up`

```elixir
@spec verify_step_up(user(), map(), map()) :: :ok | {:error, term()}
```

Delegates to the configured adapter's optional `verify_step_up/3`.

---

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