# `Parrhesia.API.ACL`

Public ACL API and rule matching for protected sync traffic.

ACL checks are only applied when the requested subject overlaps with
`config :parrhesia, :acl, protected_filters: [...]`.

The intended flow is:

1. mark a subset of sync traffic as protected with `protected_filters`
2. persist pubkey-based grants with `grant/2`
3. call `check/3` during sync reads and writes

Unprotected subjects always return `:ok`.

# `check`

```elixir
@spec check(atom(), map(), keyword()) :: :ok | {:error, term()}
```

Authorizes a protected sync read or write subject for the given request context.

Supported capabilities are `:sync_read` and `:sync_write`.

`opts[:context]` defaults to an empty `Parrhesia.API.RequestContext`, which means protected
subjects will fail with `{:error, :auth_required}` until authenticated pubkeys are present.

Local callers bypass ACL enforcement entirely. ACL is intended to protect external sync traffic,
not trusted in-process calls.

# `grant`

```elixir
@spec grant(
  map(),
  keyword()
) :: :ok | {:error, term()}
```

Persists an ACL rule.

A typical rule looks like:

```elixir
%{
  principal_type: :pubkey,
  principal: "...64 hex chars...",
  capability: :sync_read,
  match: %{"kinds" => [5000], "#r" => ["tribes.accounts.user"]}
}
```

# `list`

```elixir
@spec list(keyword()) :: {:ok, [map()]} | {:error, term()}
```

Lists persisted ACL rules.

Supported filters are:

- `:principal_type`
- `:principal`
- `:capability`

# `protected_read?`

```elixir
@spec protected_read?(map()) :: boolean()
```

Returns `true` when a filter overlaps the configured protected read surface.

# `protected_read_filters`

```elixir
@spec protected_read_filters() :: {:ok, [map()]} | {:error, term()}
```

Returns the configured protected read filters.

# `protected_write?`

```elixir
@spec protected_write?(map()) :: boolean()
```

Returns `true` when an event matches the configured protected write surface.

# `revoke`

```elixir
@spec revoke(
  map(),
  keyword()
) :: :ok | {:error, term()}
```

Deletes ACL rules matching the given selector.

The selector is passed through to the configured storage adapter, which typically accepts an
id-based selector such as `%{id: rule_id}`.

---

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