# `AshScim.Filter`
[🔗](https://github.com/ash-project/ash_scim/blob/main/lib/ash_scim/filter.ex#L5)

Parses a SCIM 2.0 filter expression (RFC 7644 §3.4.2.2) directly into the
map-shaped filter input accepted by `Ash.Query.filter/2` and
`Ash.Filter.parse_input/2`.

Performs the security-critical resolution in the same pass: every attribute
path mentioned in the filter must be declared in the resource's `scim`
mappings, otherwise the parse fails. Unmapped fields can never reach Ash.

## Output shape

  * Simple comparison: `%{email: %{eq: "alice"}}`
  * Presence: `%{email: %{is_nil: false}}`
  * Complex sub-attribute: flattens to the underlying scalar attribute,
    e.g. `name.givenName` → `%{first_name: %{eq: "Alice"}}`.
  * Single-attribute multivalued: same flattening.
  * **Relationship-backed multivalued**: emits Ash's native nested filter
    form, e.g. `members.value eq "u1"` →
    `%{memberships: %{user_id: %{eq: "u1"}}}`.
  * Boolean composition: `%{and: [filter, …]}` / `%{or: [filter, …]}` /
    `%{not: filter}`. Chained `and`/`or` flatten to a single list.

## Operator support

| SCIM | Ash |
| ---- | --- |
| `eq` | `eq` |
| `ne` | `not_eq` |
| `co` | `contains` |
| `sw` | `string_starts_with?` |
| `ew` | `string_ends_with?` |
| `pr` | `is_nil: false` |
| `gt` | `greater_than` |
| `ge` | `greater_than_or_equal` |
| `lt` | `less_than` |
| `le` | `less_than_or_equal` |

# `opts`

```elixir
@type opts() :: [{:prefix, [String.t()]}]
```

# `parse`

```elixir
@spec parse(String.t(), module(), opts()) :: {:ok, map()} | {:error, term()}
```

Parse a SCIM filter string against `resource`'s SCIM mappings.

## Options

  * `:prefix` — a list of SCIM attribute names to virtually prepend to every
    attribute path inside the filter. Used by the PATCH bracket-filter
    parser: a filter `value eq "x"` written inside `members[…]` is parsed
    with `prefix: ["members"]` so it resolves as if it were
    `members.value eq "x"`.

Returns `{:ok, filter}` where `filter` is a map suitable for
`Ash.Query.filter_input/2`, or `{:error, reason}`.

---

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