# `AshPhoenixGenApi.Resource.MfaConfig`
[🔗](https://github.com/ohhi-vn/ash_phoenix_gen_api/blob/v1.0.3/lib/ash_phoenix_gen_api/resource/mfa_config.ex#L1)

Configuration struct for a standalone PhoenixGenApi MFA endpoint.

This struct is the target of the `mfa` entity in the `gen_api` DSL section.
Unlike `ActionConfig` (which maps an Ash resource action to a FunConfig),
`MfaConfig` defines a PhoenixGenApi endpoint that calls an arbitrary MFA
function directly — with no Ash action involved.

This is useful for exposing custom functions that don't map to standard
Ash CRUD actions, such as utility endpoints, batch operations, or
service-to-service calls.

## Fields

- `name` - A unique identifier for this MFA endpoint (required)
- `request_type` - The PhoenixGenApi request type string (required)
- `mfa` - The MFA tuple to call, e.g., `{Module, :function, []}` (required)
- `arg_types` - Argument types map (required, no auto-derivation)
- `arg_orders` - Argument order list, or `:map` to derive from arg_types keys (default: `:map`)
- `timeout` - Timeout in milliseconds
- `response_type` - Response mode (:sync, :async, :stream, :none)
- `request_info` - Whether to pass request info as last argument
- `check_permission` - Permission check mode
- `permission_callback` - Custom callback MFA for permission checking
- `choose_node_mode` - Node selection strategy
- `nodes` - Target nodes (list, MFA tuple, or :local)
- `retry` - Retry configuration
- `version` - API version string
- `disabled` - Whether this endpoint is disabled

## Resolution Order

When generating a `FunConfig`, values are resolved in this order:

1. MFA-level explicit configuration (e.g., `mfa :foo do timeout 10_000 end`)
2. Section-level defaults (e.g., `gen_api do timeout 5_000 end`)
3. Built-in defaults (e.g., timeout defaults to 5000)

Unlike `ActionConfig`, there is no auto-derivation of `request_type`,
`arg_types`, or `arg_orders` from an Ash action — all must be explicitly
provided (except `arg_orders` which defaults to `:map`).

# `choose_node_mode`

```elixir
@type choose_node_mode() :: AshPhoenixGenApi.Resource.SharedTypes.choose_node_mode()
```

# `gen_api_type`

```elixir
@type gen_api_type() :: AshPhoenixGenApi.Resource.SharedTypes.gen_api_type()
```

# `node_config`

```elixir
@type node_config() :: AshPhoenixGenApi.Resource.SharedTypes.node_config()
```

# `permission_callback`

```elixir
@type permission_callback() ::
  AshPhoenixGenApi.Resource.SharedTypes.permission_callback()
```

# `permission_mode`

```elixir
@type permission_mode() :: AshPhoenixGenApi.Resource.SharedTypes.permission_mode()
```

# `retry_config`

```elixir
@type retry_config() :: AshPhoenixGenApi.Resource.SharedTypes.retry_config()
```

# `t`

```elixir
@type t() :: %AshPhoenixGenApi.Resource.MfaConfig{
  __spark_metadata__: any(),
  arg_orders: [String.t()] | :map,
  arg_types: %{required(String.t()) =&gt; gen_api_type()},
  check_permission: permission_mode() | nil,
  choose_node_mode: choose_node_mode() | nil,
  disabled: boolean(),
  mfa: {module(), atom(), [any()]},
  name: atom(),
  nodes: node_config() | nil,
  permission_callback: permission_callback(),
  request_info: boolean() | nil,
  request_type: String.t(),
  response_type: :sync | :async | :stream | :none | nil,
  retry: retry_config() | nil,
  timeout: pos_integer() | :infinity | nil,
  version: String.t() | nil
}
```

# `permission_callback`

```elixir
@callback permission_callback(request_type :: String.t(), args :: map()) :: boolean()
```

Callback function signature for permission checking.

The callback receives two arguments:
- `request_type` - The PhoenixGenApi request type string (e.g., `"delete_user"`)
- `args` - A map of request arguments (e.g., `%{"user_id" => "123", "role" => "admin"}`)

Returns `true` to allow the request, or `false` to deny permission.

# `effective_check_permission`

```elixir
@spec effective_check_permission(t(), permission_mode()) :: permission_mode()
```

Resolves the effective check_permission, falling back to the provided default.

# `effective_choose_node_mode`

```elixir
@spec effective_choose_node_mode(t(), choose_node_mode()) :: choose_node_mode()
```

Resolves the effective choose_node_mode, falling back to the provided default.

# `effective_nodes`

```elixir
@spec effective_nodes(t(), node_config()) :: node_config()
```

Resolves the effective nodes, falling back to the provided default.

# `effective_permission_callback`

```elixir
@spec effective_permission_callback(t(), permission_callback()) ::
  permission_callback()
```

Resolves the effective permission_callback, falling back to the provided default.

When the entity-level `permission_callback` is set, returns that value.
Otherwise, returns the section-level default.

The callback MFA function receives `(request_type, args)` as arguments and
returns `true` (continue) or `false` (permission denied).

## Examples

    iex> config = %Elixir.AshPhoenixGenApi.Resource.MfaConfig{permission_callback: {MyModule, :check, []}}
    iex> Elixir.AshPhoenixGenApi.Resource.MfaConfig.effective_permission_callback(config, nil)
    {MyModule, :check, []}

    iex> config = %Elixir.AshPhoenixGenApi.Resource.MfaConfig{permission_callback: nil}
    iex> Elixir.AshPhoenixGenApi.Resource.MfaConfig.effective_permission_callback(config, {MyModule, :check, []})
    {MyModule, :check, []}

    iex> config = %Elixir.AshPhoenixGenApi.Resource.MfaConfig{permission_callback: nil}
    iex> Elixir.AshPhoenixGenApi.Resource.MfaConfig.effective_permission_callback(config, nil)
    nil

# `effective_request_info`

```elixir
@spec effective_request_info(t(), boolean()) :: boolean()
```

Resolves the effective request_info, falling back to the provided default.

# `effective_response_type`

```elixir
@spec effective_response_type(t(), :sync | :async | :stream | :none) ::
  :sync | :async | :stream | :none
```

Resolves the effective response type, falling back to the provided default.

# `effective_retry`

```elixir
@spec effective_retry(t(), retry_config()) :: retry_config()
```

Resolves the effective retry, falling back to the provided default.

# `effective_timeout`

```elixir
@spec effective_timeout(t(), pos_integer() | :infinity) :: pos_integer() | :infinity
```

Resolves the effective timeout, falling back to the provided default.

## Examples

    iex> config = %Elixir.AshPhoenixGenApi.Resource.MfaConfig{timeout: 10_000}
    iex> Elixir.AshPhoenixGenApi.Resource.MfaConfig.effective_timeout(config, 5_000)
    10_000

    iex> config = %Elixir.AshPhoenixGenApi.Resource.MfaConfig{timeout: nil}
    iex> Elixir.AshPhoenixGenApi.Resource.MfaConfig.effective_timeout(config, 5_000)
    5000

# `effective_version`

```elixir
@spec effective_version(t(), String.t()) :: String.t()
```

Resolves the effective version, falling back to the provided default.

# `enabled?`

```elixir
@spec enabled?(t()) :: boolean()
```

Checks if this config is enabled (not disabled).

# `has_explicit_arg_orders?`

```elixir
@spec has_explicit_arg_orders?(t()) :: boolean()
```

Checks if this config has explicit arg_orders defined (not `:map`).

# `has_explicit_arg_types?`

```elixir
@spec has_explicit_arg_types?(t()) :: boolean()
```

Checks if this config has explicit arg_types defined.

---

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