# `Ash.Info.Manifest`
[🔗](https://github.com/ash-project/ash/blob/v3.25.1/lib/ash/info/manifest.ex#L5)

Generates a language-agnostic API specification from Ash resources and actions.

Given a list of `{resource, action_name}` tuples or an OTP app, traverses the
type graph to find all reachable resources and types, producing structured IR
(Elixir structs) that can also be serialized to JSON.

## Operator canonical name vs. alias

`%Operator{}.name` is the user-facing symbol that appears in
`Ash.Query.filter` expressions (e.g. `:==`, `:<`, `:in`). The
`%Operator{}.aliases` list carries internal/legacy module-derived names
(e.g. `:eq`, `:less_than`) for backward-compatible rendering. New code
should prefer `name`; alias-substitution is for tools that historically
rendered the module-derived spelling.

# `action_lookup`

```elixir
@type action_lookup() :: %{required({atom(), atom()}) =&gt; Ash.Info.Manifest.Action.t()}
```

# `resource_lookup`

```elixir
@type resource_lookup() :: %{required(atom()) =&gt; Ash.Info.Manifest.Resource.t()}
```

# `t`

```elixir
@type t() :: %Ash.Info.Manifest{
  custom: map(),
  entrypoints: [Ash.Info.Manifest.Entrypoint.t()],
  filter_capabilities: Ash.Info.Manifest.FilterCapabilities.t() | nil,
  resources: [Ash.Info.Manifest.Resource.t()],
  sort_capabilities: Ash.Info.Manifest.SortCapabilities.t() | nil,
  types: [Ash.Info.Manifest.Type.t()]
}
```

# `type_lookup`

```elixir
@type type_lookup() :: %{required(atom()) =&gt; Ash.Info.Manifest.Type.t()}
```

# `action_lookup`

```elixir
@spec action_lookup(t()) :: action_lookup()
```

Builds an action lookup map from the spec, keyed by `{resource_module, action_name}`.

# `applicable_filter_custom_expressions`

```elixir
@spec applicable_filter_custom_expressions(
  t(),
  {atom(), atom()}
) :: [Ash.Info.Manifest.ApplicableCustomExpression.t()]
```

Returns the resolved `%ApplicableCustomExpression{}` list for `{resource_module, field_name}`.
See `applicable_filter_operators/2` for behavior.

# `applicable_filter_functions`

```elixir
@spec applicable_filter_functions(
  t(),
  {atom(), atom()}
) :: [Ash.Info.Manifest.ApplicableFunction.t()]
```

Returns the resolved `%ApplicableFunction{}` list for `{resource_module, field_name}`.
See `applicable_filter_operators/2` for behavior.

# `applicable_filter_operators`

```elixir
@spec applicable_filter_operators(
  t(),
  {atom(), atom()}
) :: [Ash.Info.Manifest.ApplicableOperator.t()]
```

Returns the resolved `%ApplicableOperator{}` list for `{resource_module, field_name}`.

Returns `[]` when the field exists but is not filterable. Raises if the
resource or field is unknown.

# `custom_expression_lookup`

```elixir
@spec custom_expression_lookup(t()) :: %{
  required(atom()) =&gt; Ash.Info.Manifest.CustomExpression.t()
}
```

Builds a custom-expression lookup map from the spec, keyed by expression name atom.

# `function_lookup`

```elixir
@spec function_lookup(t()) :: %{required(atom()) =&gt; Ash.Info.Manifest.Function.t()}
```

Builds a function lookup map from the spec, keyed by function name atom.

# `generate`

```elixir
@spec generate(keyword()) :: {:ok, t()} | {:error, term()}
```

Generate an API specification for the given OTP app.

## Options

  * `:otp_app` - The OTP app to scan for Ash domains and resources (required)
  * `:action_entrypoints` - Optional list of `{resource_module, action_name}` tuples
    used as entrypoints for deriving the spec. When omitted, all public actions
    across all domains are included.

# `generate_resource_lookup`

```elixir
@spec generate_resource_lookup(keyword()) ::
  {:ok, resource_lookup()} | {:error, term()}
```

Generates a spec and returns the resource lookup map directly.

# `get_action`

```elixir
@spec get_action(action_lookup(), atom(), atom()) ::
  Ash.Info.Manifest.Action.t() | nil
```

Gets an action by resource module and action name from an action lookup.

# `get_field`

```elixir
@spec get_field(resource_lookup(), atom(), atom()) ::
  Ash.Info.Manifest.Field.t() | nil
```

Gets a field by resource module and field name.

# `get_field_or_relationship`

```elixir
@spec get_field_or_relationship(resource_lookup(), atom(), atom()) ::
  Ash.Info.Manifest.Field.t() | Ash.Info.Manifest.Relationship.t() | nil
```

Gets a field or relationship by name, checking fields first.

Returns `%Ash.Info.Manifest.Field{}`, `%Ash.Info.Manifest.Relationship{}`, or nil.

# `get_identity`

```elixir
@spec get_identity(resource_lookup(), atom(), atom()) :: %{keys: [atom()]} | nil
```

Gets an identity by resource module and identity name.

# `get_relationship`

```elixir
@spec get_relationship(resource_lookup(), atom(), atom()) ::
  Ash.Info.Manifest.Relationship.t() | nil
```

Gets a relationship by resource module and relationship name.

# `get_resource`

```elixir
@spec get_resource(resource_lookup(), atom()) :: Ash.Info.Manifest.Resource.t() | nil
```

Looks up a resource by module. Returns nil if not found.

# `get_resource!`

```elixir
@spec get_resource!(resource_lookup(), atom()) :: Ash.Info.Manifest.Resource.t()
```

Looks up a resource by module. Raises if not found.

# `get_type`

```elixir
@spec get_type(type_lookup(), atom()) :: Ash.Info.Manifest.Type.t() | nil
```

Looks up a named type's full definition by module. Returns nil if not found.

# `get_type!`

```elixir
@spec get_type!(type_lookup(), atom()) :: Ash.Info.Manifest.Type.t()
```

Looks up a named type's full definition by module. Raises if not found.

A miss indicates a reachability bug: the type was referenced via `:type_ref`
somewhere in the type graph but was never registered during spec generation.
Reachability analysis (`Ash.Info.Manifest.Generator.Reachability`) should have
collected it as a standalone type.

# `has_resource?`

```elixir
@spec has_resource?(resource_lookup(), atom()) :: boolean()
```

Checks if a resource exists in the lookup.

# `operator_lookup`

```elixir
@spec operator_lookup(t()) :: %{required(atom()) =&gt; Ash.Info.Manifest.Operator.t()}
```

Builds an operator lookup map from the spec, keyed by operator name atom.

Returns an empty map when `filter_capabilities` is `nil`.

# `primary_key`

```elixir
@spec primary_key(resource_lookup(), atom()) :: [atom()]
```

Gets the primary key field names by resource module.

# `resource_lookup`

```elixir
@spec resource_lookup(t()) :: resource_lookup()
```

Builds a resource lookup map from the spec, keyed by resource module.

# `schema_version`

```elixir
@spec schema_version() :: String.t()
```

The schema version of the manifest's JSON serialization format.

Bumped when the JSON output schema in `Ash.Info.Manifest.JsonSerializer`
changes in a way downstream tools need to detect.

# `type_lookup`

```elixir
@spec type_lookup(t()) :: type_lookup()
```

Builds a type lookup map from the spec, keyed by named type module.

Each entry is the fully-resolved `%Ash.Info.Manifest.Type{}` for a named type
(Ash.Type.Enum implementations and Ash.Type.NewType subtypes) referenced
somewhere in the reachable type graph.

---

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