# `Tack.BoundaryDeclarations`
[🔗](https://github.com/giggleton/pica/blob/v0.1.0/dev/tack/boundary_declarations.ex#L1)

Reads the `use Boundary` declarations out of Elixir source, so a test can assert on the shape of
the architecture's enforcement.

The boundary declarations fail in one direction only. A declaration that is too **narrow** fails
loudly — a forbidden reference, and the gate's compile step goes red. One that is too **wide**
compiles in silence, and nothing in the toolchain will ever report that more permission was
granted than the code uses. So the options that make the compiler check *less* are pinned by the
generated boundary declarations test against a list of sanctioned exceptions, and widening a
`deps:`/`exports:` grant is gated at authoring time by `.claude/hooks/waiver-gate.sh`.

One widening arrives the other way round — by deletion rather than addition — so it is read by
its own function rather than by the escape-hatch list: see `strict?/1`.

## Only the declaration is read, never prose about one

A declaration runs from a line whose first token is `use Boundary` until its brackets balance on
a line that does not run on — one ending in neither `,` nor `:`, since `mix format` may leave a
bare `use Boundary,` or a bare key such as `exports:` on a line of its own. The body of every
`"""` heredoc is skipped first. That matters more than it sounds: a moduledoc explaining why a
module may never say `exports: :all`, a test module quoting every option it forbids, or an
installer whose template strings hold whole declarations must all score nothing. A scanner that
matched anywhere in the file would score each as a maximal grant.

# `declaration`

```elixir
@type declaration() :: String.t()
```

A `use Boundary …` declaration, flattened to one line.

# `hatch`

```elixir
@type hatch() :: {Regex.t(), String.t(), String.t()}
```

A check-disabling option: the token to search for, and what it does.

# `compiler_configured?`

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

Whether `mix_exs_source` actually runs the boundary compiler.

Comment lines are dropped first, because a `mix.exs` may also *describe* `compilers: [:boundary]`
in a note above the dependency — a bare substring search passes on that prose after the setting
itself is deleted, which is the single largest bypass in the scheme.

# `compiler_configured_in?`

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

`compiler_configured?/1` for a file on disk.

# `declarations`

```elixir
@spec declarations(String.t()) :: [declaration()]
```

The `use Boundary` declarations in `source`, each flattened to a single line.

A declaration starts at a line whose first non-space token is `use Boundary` and ends when the
brackets opened since then balance on a line ending in neither `,` nor `:`, so a multi-line
declaration is returned whole — including `mix format`'s shape of a key alone on its line with
the value below — and a comment or moduledoc mentioning one is ignored.

# `declarations_in`

```elixir
@spec declarations_in(String.t()) :: [declaration()]
```

`declarations/1` for a file on disk.

# `disabled_checks`

```elixir
@spec disabled_checks(String.t()) :: [{String.t(), String.t()}]
```

The check-disabling options used in `source`, as `{token, effect}` pairs.

Each is a place where the compiler was told to enforce less than it could.

# `disabled_checks_in`

```elixir
@spec disabled_checks_in(String.t()) :: [{String.t(), String.t()}]
```

`disabled_checks/1` for a file on disk.

# `escape_hatches`

```elixir
@spec escape_hatches() :: [hatch()]
```

Every check-disabling option this module knows about, as `{pattern, token, effect}`.

# `exports_all?`

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

Whether any declaration in `source` exports everything with a bare `exports: :all`.

Legal for the umbrella, and a trap for a sub-boundary: it makes every module public the moment
it compiles, where an explicit list fails safe — a new module is private until a person admits
it. `exports: {:all, except: […]}` is a narrowing of the same thing and does not count.

# `exports_all_in?`

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

`exports_all?/1` for a file on disk.

# `source_files`

```elixir
@spec source_files(String.t()) :: [String.t()]
```

Every file under `root` that carries at least one `use Boundary` declaration.

# `strict?`

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

Whether any declaration in `source` sets `type: :strict`.

The mirror of `disabled_checks/1`, and the reason it needs its own function: every option that
function scans for is a token whose *presence* weakens the check, so its arrival shows up in a
diff. `type: :strict` weakens by *going away*. Boundary's default is `:relaxed`, which checks
calls into an external application only when the boundary already names some other module from
it — so deleting one word from a pure core's declaration drops the "nothing outside the standard
library" half of its guarantee, and the deletion compiles clean, passes the gate, and scores
nothing in `.claude/hooks/waiver-gate.sh`, which ranks `deps:`/`exports:` entries and does not
read `type:`.

# `strict_in?`

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

`strict?/1` for a file on disk.

---

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