# `MobDev.Plugin`
[🔗](https://github.com/genericjam/mob_dev/blob/master/lib/mob_dev/plugin.ex#L1)

Compile-time host-config surface for code-generated plugins.

Spec-v2 plugins that generate their contributions from the host app's
configuration — e.g. a `mob_ash` plugin reading the host's registered
Ash domains, or a `mob_ecto` plugin reading its schemas — read that
config through this function rather than calling `Application.get_env/3`
directly. Routing every host-config read through one named surface is
what later lets the plugin audit (see `MOB_PLUGINS.md` and
`MOB_PLUGIN_SECURITY.md`) verify exactly which keys a generator touches.

When a generator runs under `with_host_config_audit/3` (which the
build-time generator runner uses), every read is checked against the
plugin's declared `:host_config_keys` and recorded; an undeclared read
fails the build loudly. Outside an audit scope (e.g. in tests) it is a
plain `Application.get_env/3`.

# `activated`

```elixir
@spec activated() :: [{Path.t(), map() | nil}]
```

The activated plugins as `{plugin_dir, manifest}` pairs, ready for
`MobDev.Plugin.Merge`.

Resolves each activated name to its dependency directory and loads its
manifest (nil for a tier-0 plugin). Activated names that don't resolve to a
dep are skipped — `mix mob.plugins` is where that mismatch surfaces to users.

# `activated_names`

```elixir
@spec activated_names() :: [atom()]
```

The activated plugin names — `config :mob, :plugins` from `mob.exs`.

Activation is the second opt-in step (see `MOB_PLUGINS.md`): a plugin in
`deps` contributes nothing until it appears here. Falls back to the loaded
Application env, then `[]`.

# `host_config`

```elixir
@spec host_config(atom(), atom(), term()) :: term()
```

Reads `key` from the host application's environment, returning `default`
when the key is unset.

`otp_app` is the host app's OTP application name — the atom under which it
registers `config :my_app, ...`. Code-generated plugins call this during
the compile step:

    domains = MobDev.Plugin.host_config(:my_app, :ash_domains, [])

Under an audit scope, reading a key the plugin didn't declare in its
manifest `:host_config_keys` raises — the generator must declare what it
touches so `mix mob.audit_plugins` can verify it.

# `with_host_config_audit`

```elixir
@spec with_host_config_audit(atom(), [atom()], (-&gt; result)) ::
  {result, [{atom(), atom()}]}
when result: term()
```

Runs `fun` with host-config auditing scoped to `plugin` (allowing only the
keys in `allowed`, the plugin's manifest `:host_config_keys`). Returns
`{result, reads}` where `reads` is the ordered list of `{otp_app, key}` the
generator actually touched. Nested scopes restore the prior one on exit.

---

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