Standalone Ash Framework extension for Zanzibar / ReBAC authorization
backed by Licet (embedded Postgres/Ecto), SpiceDB / Authzed (HTTP via Req),
or AshAuthzed.Adapters.Memory (in-memory Licet engine).
Usage
defmodule MyApp.Accounts.User do
use Ash.Resource,
domain: MyApp.Accounts,
data_layer: AshPostgres.DataLayer,
authorizers: [Ash.Policy.Authorizer],
extensions: [AshAuthzed]
authzed do
object_type "user_profile"
adapter :licet
adapter_opts [instance: MyApp.Licet]
relation :owner, subject_type: "user", subject_id: :id
relation :platform, static_subject: "platform:main"
external_role :role, target: "platform:main", subject_type: "user", subject_id: :id
conditional_wildcard :is_protected_admin,
subject_type: "user",
attribute: :role,
in: [:admin, :super_admin]
end
policies do
policy action(:read) do
authorize_if rebac_can(:view)
end
policy action(:update_profile) do
authorize_if rebac_can(:edit)
end
end
end
Summary
Functions
Builds the adapter options keyword list for a given Ash resource, merging any call-site overrides.
Applies the given .zed or YAML schema (file path or raw string) to the configured ReBAC adapter.
Streams an Ash Resource or Ash.Query in keyset-paginated batches and writes
its relationship tuples via AshAuthzed.Adapter.write_tuples/2.
Backfills all AshAuthzed-enabled resources in the given OTP app or domain list.
Returns all ReBAC entities declared in the resource's authzed and rebac DSL sections.
Fetches a configuration option from the resource's authzed or rebac DSL section.
Discovers all Ash resources in the given OTP app (or list of Ash domains)
that use the AshAuthzed extension.
Functions
@spec adapter_config(Ash.Resource.t(), keyword()) :: keyword()
Builds the adapter options keyword list for a given Ash resource, merging any call-site overrides.
Applies the given .zed or YAML schema (file path or raw string) to the configured ReBAC adapter.
@spec backfill(Ash.Resource.t() | Ash.Query.t(), keyword()) :: {:ok, %{ records: non_neg_integer(), operations: non_neg_integer(), batches: non_neg_integer() }} | {:error, term()}
Streams an Ash Resource or Ash.Query in keyset-paginated batches and writes
its relationship tuples via AshAuthzed.Adapter.write_tuples/2.
Options
:batch_size- Number of records per chunk (default:500):reconcile?- Whether to also emit:deleteops for non-matching enum roles (default:true):dry_run?- Iftrue, computes operations and returns counts without writing to the adapter (default:false):tenant- Optional tenant passed toAsh.stream!/2:stream_opts- Additional options forwarded toAsh.stream!/2:adapter_opts- Additional options forwarded toAshAuthzed.Adapter.write_tuples/2:on_batch- Optional callback invoked with running stats after each batch
@spec backfill_all(atom() | [Ash.Domain.t()], keyword()) :: {:ok, %{optional(Ash.Resource.t()) => map()}} | {:error, {Ash.Resource.t(), term()}}
Backfills all AshAuthzed-enabled resources in the given OTP app or domain list.
@spec get_entities(Ash.Resource.t()) :: [ AshAuthzed.Relation.t() | AshAuthzed.ExternalRole.t() | AshAuthzed.ConditionalWildcard.t() ]
Returns all ReBAC entities declared in the resource's authzed and rebac DSL sections.
@spec get_opt(Ash.Resource.t(), atom(), term()) :: term()
Fetches a configuration option from the resource's authzed or rebac DSL section.
@spec registered_resources(atom() | [Ash.Domain.t()]) :: [Ash.Resource.t()]
Discovers all Ash resources in the given OTP app (or list of Ash domains)
that use the AshAuthzed extension.