# `Mobus.Stepwise.Capabilities`
[🔗](https://github.com/fosferon/mobus_stepwise/blob/main/lib/mobus/stepwise/capabilities.ex#L1)

Configurable capability runner adapter for the stepwise engine.

When adapter is nil (default), capability execution returns
`{:ok, %{context: %{}}}` (no-op). This allows the package to work for
form-only wizards (e.g. Atrapos tenant creation) without requiring a
capability runner.

Configure via `:mobus_stepwise` application config:

    config :mobus_stepwise, :capability_runner_adapter, MyApp.CapabilityRunner

### `:strict` mode

Some consumers (e.g. workflow_stem with its own adapter plumbing) prefer
strict semantics where a nil adapter signals a misconfiguration rather
than silently succeeding. Enable via:

    config :mobus_stepwise, :capability_runner_strict, true

When strict is `true`, calling `execute/3` with no adapter configured
returns `{:error, :capability_runner_disabled}` instead of the default
no-op success. Default: `false` (backwards compatible).

# `adapter`

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

Returns the configured capability runner adapter module, or `nil` if none is set.

Reads from application config key `:mobus_stepwise, :capability_runner_adapter`.

## Examples

    Capabilities.adapter()
    #=> MyApp.CapabilityRunner

    # When unconfigured:
    Capabilities.adapter()
    #=> nil

# `enabled?`

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

Returns `true` if a capability runner adapter is configured and exports `execute/3`.

Checks that the adapter is a non-nil atom module with an `execute/3` function exported.

## Examples

    Capabilities.enabled?()
    #=> true

# `execute`

```elixir
@spec execute(String.t(), String.t() | atom(), map()) ::
  {:ok, term()} | {:error, term()}
```

Executes a capability via the configured adapter, or returns a no-op result.

When no adapter is configured, returns `{:ok, %{context: %{}}}` (no-op).
Otherwise delegates to `adapter.execute(tenant_id, capability_handle, input)`.

## Parameters

  * `tenant_id` — tenant identifier string
  * `capability_handle` — capability name (string or atom), e.g. `"myapp.validate"`
  * `input` — execution input map with event context, payload, and state

## Returns

  * `{:ok, result}` — successful execution with context updates and/or artifacts
  * `{:error, reason}` — capability execution failed

## Examples

    Capabilities.execute("tenant-1", "myapp.validate", %{payload: %{email: "a@b.com"}})
    #=> {:ok, %{context: %{valid: true}}}

# `strict?`

```elixir
@spec strict?() :: boolean()
```

Returns `true` when `:capability_runner_strict` mode is active.

When true, `execute/3` returns `{:error, :capability_runner_disabled}` if
no adapter is configured instead of silently succeeding. Consumers that
always configure an adapter (e.g. workflow_stem) should set this to `true`
so accidental nil-adapter calls are caught as errors.

## Examples

    Capabilities.strict?()
    #=> false

    # After config:
    #   config :mobus_stepwise, :capability_runner_strict, true
    Capabilities.strict?()
    #=> true

---

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