# `Minga.Project.Root`
[🔗](https://github.com/jsmestad/minga/blob/main/lib/minga/project/root.ex#L1)

Identifies the kind and authorization of a project root.

Recursive project features accept only explicit directory roots. Broad roots such as the user's home directory, the filesystem root, and mounted-volume roots additionally require confirmation from the user flow that created the value. Directory paths are canonicalized so symlink aliases cannot bypass that boundary.

# `canonical_error`

```elixir
@type canonical_error() :: File.posix() | :too_many_symlinks
```

Why a filesystem path could not be canonicalized.

# `error`

```elixir
@type error() ::
  :not_a_directory
  | :broad_root_confirmation_required
  | :invalid_broad_root_confirmation
  | :not_a_directory_root
  | :root_changed
```

Why a root cannot authorize recursive project behavior.

# `file_error`

```elixir
@type file_error() ::
  error()
  | canonical_error()
  | :absolute_path
  | :parent_traversal
  | :outside_workspace
```

Why a workspace-relative file path could not be authorized.

# `kind`

```elixir
@type kind() :: :file | :directory
```

The filesystem object represented by a root.

# `t`

```elixir
@type t() :: %Minga.Project.Root{
  broad_root_confirmed?: boolean(),
  kind: kind(),
  path: String.t()
}
```

A project root with explicit kind and broad-root authorization.

# `broad_path?`

```elixir
@spec broad_path?(String.t()) :: boolean()
```

Returns true when a path names a root whose recursive traversal needs explicit confirmation.

# `canonical_path`

```elixir
@spec canonical_path(String.t()) :: {:ok, String.t()} | {:error, canonical_error()}
```

Returns the canonical target of an existing filesystem path.

# `directory`

```elixir
@spec directory(
  String.t(),
  keyword()
) :: {:ok, t()} | {:error, error()}
```

Builds an explicit directory workspace root.

# `file`

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

Builds a file-scoped root that cannot authorize recursive inventory.

# `inventory_path`

```elixir
@spec inventory_path(t()) :: {:ok, String.t()} | {:error, error()}
```

Returns the authorized canonical path for recursive inventory.

# `resolve_file`

```elixir
@spec resolve_file(t(), String.t()) :: {:ok, String.t()} | {:error, file_error()}
```

Resolves an existing workspace-relative path inside an authorized directory root.

---

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