Host-side build-time gate: runs Verify.verify_plugin/2 + the
TrustStore check across every activated plugin and refuses the
build on any failure.
This is the Phase 2 cryptographic counterpart to the capability
drift check in Validator. Both run at the same hook point inside
Validator.raise_on_capability_drift!/1 so the iOS-sim, iOS-device,
and Android paths all enforce them as a one-liner.
Three distinct failure modes are surfaced (per MOB_PLUGIN_SECURITY.md,
Phase 2):
- Missing signature — author hasn't run
mix mob.plugin.sign. Suppressible per-plugin viaconfig :mob, :acknowledge_unsafe_pluginswith a persistent banner. - Invalid signature — sig is present but doesn't verify; the manifest or sources have been tampered with after signing. Not suppressible.
- Untrusted fingerprint — signature verifies but the public key
isn't in
config :mob, :trusted_plugins(or is a different key from the trusted one, the key-rotation case). Not suppressible; user must runmix mob.plugin.trust <name>.
Summary
Types
Errors check_plugin/2 can return.
Functions
Runs the signature + trust check across plugins (the
MobDev.Plugin.activated/0 shape — [{plugin_dir, manifest}]).
Pure variant of check_activated/1 for tests.
Prints a stderr banner when any activated plugin is allowed only via
:acknowledge_unsafe_plugins. Idempotent within a single Mix invocation
in spirit — the banner fires every time it's called, so callers should
invoke it once per build.
Runs check_activated/1 and raises a Mix.raise/1 with a clear,
actionable message when any plugin fails. No-op on success.
Types
@type gate_error() :: {:missing_signature, atom()} | {:missing_pubkey, atom()} | {:invalid_signature, atom()} | {:untrusted, atom(), MobDev.Plugin.Crypto.fingerprint(), MobDev.Plugin.Crypto.fingerprint() | nil}
Errors check_plugin/2 can return.
Functions
@spec check_activated([{Path.t(), map() | nil}]) :: :ok | {:error, [gate_error()]}
Runs the signature + trust check across plugins (the
MobDev.Plugin.activated/0 shape — [{plugin_dir, manifest}]).
Returns :ok when every plugin verifies AND is trusted (or, for
missing signatures, is listed in config :mob, :acknowledge_unsafe_plugins).
Returns {:error, errors} otherwise — a list of gate_error/0 tagged
by plugin name.
Reads the trust map from mob.exs (via TrustStore.load_trusted_plugins/0)
and the acknowledgement list from :mob's Application env or mob.exs.
Pass the trust_map + acknowledged list explicitly via
check_activated/3 from tests that need isolation.
@spec check_activated( [{Path.t(), map() | nil}], MobDev.Plugin.TrustStore.trust_map(), [atom()] ) :: :ok | {:error, [gate_error()]}
Pure variant of check_activated/1 for tests.
Prints a stderr banner when any activated plugin is allowed only via
:acknowledge_unsafe_plugins. Idempotent within a single Mix invocation
in spirit — the banner fires every time it's called, so callers should
invoke it once per build.
Runs check_activated/1 and raises a Mix.raise/1 with a clear,
actionable message when any plugin fails. No-op on success.