# `PhoenixKit.Notifications.Routing`
[🔗](https://github.com/BeamLabEU/phoenix_kit/blob/v2.13.8/lib/phoenix_kit/notifications/routing.ex#L1)

Decides which external delivery channels a user's notification should go out
on (the in-app inbox is handled separately, by the creation choke point).

**External routing is FAIL-CLOSED.** Unlike the fail-open in-app inbox, an
action that doesn't resolve to a known notification type, or a type the user
hasn't explicitly opted a channel into, is NOT delivered externally. A channel
is a target only when, for that specific type, the user has it `enabled`, has
opted the type in (`types[type_key] == true`), and the channel reports
`configured?/2`.

# `target`

```elixir
@type target() :: {module(), map()}
```

A resolved delivery target: the channel module + the user's config for it.

# `any_target?`

```elixir
@spec any_target?(map(), String.t() | nil) :: boolean()
```

Whether ANY external channel wants this action — the cheap check the creation
choke point uses to decide whether to enqueue delivery even when the in-app
inbox is muted for the type (Model B: independent destinations).

# `targets_for_action`

```elixir
@spec targets_for_action(map(), String.t() | nil) :: [target()]
```

Delivery targets for an activity `action` string. Resolves the action to its
notification type, then delegates to `targets_for_type/2`. Unknown/unmapped
action ⇒ `[]` (fail-closed — standalone/untyped notifications never route out).

# `targets_for_type`

```elixir
@spec targets_for_type(map(), String.t() | nil) :: [target()]
```

Delivery targets for an explicit type key. `nil`/non-binary ⇒ `[]`.

---

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