# `A2UICore.Validation.Topology`
[🔗](https://github.com/a2ui-elixir/a2ui/blob/v0.1.1/umbrella/apps/a2ui_core/lib/a2ui_core/validation/topology.ex#L1)

Component-graph validation: root presence, dangling references,
self-references, cycles, depth, unreachable components, and catalog
composition constraints.

All checks work on an `A2UICore.State.Components` set and an
`info_fun` — a function from a component to what its catalog knows
about the type (`t:A2UICore.State.Component.info/0`: the child
`RefSpec`, `allowed_parents`, `allowed_children`; `nil` for an unknown
type). They are pure and return `:ok` / `{:ok, reachable}` or
`{:error, %A2UICore.Error{}}`.

Error categories follow the reference: a missing root, a dangling
reference or an unreachable component is `:integrity`; a
self-reference, a cycle or exceeding the depth limit is `:recursion`;
a composition-constraint violation is `:validation`
(`UNALLOWED_PARENT` / `UNALLOWED_CHILD`). Messages carry both the
Python and TypeScript SDK phrasings, because conformance matches on
message substrings.

Components are visited in sorted id order, so where a graph has
several violations the one reported is deterministic (the reference
follows insertion order).

# `info_fun`
*since 0.1.0* 

```elixir
@type info_fun() :: (A2UICore.State.Component.t() -&gt;
                 A2UICore.State.Component.info() | nil)
```

# `analyze`
*since 0.1.0* 

```elixir
@spec analyze(
  A2UICore.State.Components.t(),
  info_fun(),
  A2UICore.Validation.Config.t()
) ::
  {:ok, MapSet.t(String.t())} | {:error, A2UICore.Error.t()}
```

Checks self-references, cycles and the depth limit, and (unless
`allow_orphan_components`) that every component is reachable from the
root. Returns the set of reachable ids.

# `validate`
*since 0.1.0* 

```elixir
@spec validate(
  A2UICore.State.Components.t(),
  info_fun(),
  A2UICore.Validation.Config.t()
) ::
  :ok | {:error, A2UICore.Error.t()}
```

Full topology validation: integrity, then reachability/cycles/depth.
Empty component sets are valid.

# `validate_composition`
*since 0.1.0* 

```elixir
@spec validate_composition(A2UICore.State.Components.t(), info_fun()) ::
  :ok | {:error, A2UICore.Error.t()}
```

Checks catalog `allowedParents` / `allowedChildren` constraints. A
component constrained by `allowed_parents` that no component
references is treated as a child of the surface itself.

# `validate_integrity`
*since 0.1.0* 

```elixir
@spec validate_integrity(
  A2UICore.State.Components.t(),
  info_fun(),
  A2UICore.Validation.Config.t()
) ::
  :ok | {:error, A2UICore.Error.t()}
```

Checks that the root exists (unless `allow_missing_root`) and that
every referenced component exists (unless `allow_dangling_references`).

---

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