# `Attesto.ResourceIndicator`
[🔗](https://github.com/XukuLLC/attesto/blob/v0.13.0/lib/attesto/resource_indicator.ex#L1)

RFC 8707 Resource Indicators for OAuth 2.0 — the conn-free primitive.

A `resource` request parameter scopes an issued access token to one or more
protected resources by setting the token's `aud` claim to the requested
resource identifier(s) (§2.2). Audience is the cryptographic, RFC-blessed
confinement: a token minted for resource A is structurally invalid at a
sibling resource B, even when both share a scope vocabulary.

This module is the single place that turns the raw `resource` parameter into
a validated, authorized set of audience identifiers. It does two things and
no more (it never touches a `Plug.Conn`, a store, or a clock):

  * **`validate/1`** — RFC 8707 §2.1 syntax. The parameter is multi-valued
    (scalar or array); each value MUST be an absolute URI with no fragment.
    Returns the de-duplicated indicator list, `{:ok, []}` when none was
    requested, or `{:error, :invalid_target}` for any malformed value.

  * **`authorize/2`** — RFC 8707 §2.2 authorization. Every requested resource
    MUST be one this authorization server is willing to mint for (the caller
    composes the allowlist — typically the server's own audience plus any
    configured / per-client allow-listed resources). An unserved resource is
    rejected `:invalid_target`: the AS never issues a token for a resource it
    does not serve.

`:invalid_target` is the RFC 8707 §2 / RFC 6749 §5.2 error code the framing
layer renders; this module returns the bare atom so it stays transport-free.

# `authorize`

```elixir
@spec authorize([String.t()], [String.t()]) ::
  {:ok, [String.t()]} | {:error, :invalid_target}
```

Authorize already-validated resource indicators against an allowlist.

Every member of `resources` MUST appear in `allowed`. Returns the resources
unchanged on success, or `{:error, :invalid_target}` if any is not served by
this authorization server. An empty `resources` list (no indicator requested)
is trivially authorized.

# `valid_indicator?`

```elixir
@spec valid_indicator?(term()) :: boolean()
```

Whether a single value is a syntactically valid RFC 8707 resource indicator:
an absolute URI (a non-empty scheme plus a host or path) with no fragment
(§2.1) and no malformed percent-encoding (RFC 3986 §2.1).

# `validate`

```elixir
@spec validate(term()) :: {:ok, [String.t()]} | {:error, :invalid_target}
```

Parse and syntactically validate the requested resource indicator(s).

`nil` (the parameter absent) yields `{:ok, []}`. A scalar binary or an array
of binaries yields the de-duplicated list (order preserved) when every value
is a valid absolute-URI indicator, else `{:error, :invalid_target}`. A
present-but-empty value (`resource=`, an empty array, a blank/non-binary
entry) fails closed rather than being treated as absent.

---

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