Reads, validates, and classifies a plugin's priv/mob_plugin.exs manifest.
The manifest is data, not code (see MOB_PLUGINS.md): a plain Elixir map
describing what a plugin contributes. This module is the single place that
turns that map into a validated, classified description — tier, hot-push
status, activation — that mix mob.plugins reports and the compile-time
merge will later consume.
A tier-0 plugin has no manifest at all; load/1 returns {:ok, nil} for
that case, and tier(nil) is 0.
Summary
Functions
Whether the plugin's contributions can be hot-pushed without a native rebuild.
Loads the manifest for a plugin checked out at plugin_dir.
Returns true when plugin_dir has a priv/mob_plugin.exs, false
otherwise. Distinguishes tier-0 plugins (no manifest, no signature
needed) from tier-1+ plugins (manifest present, signature required)
without evaluating the manifest itself. See Verify.load_verified/1.
Whether the native build compiles this nifs: entry for platform
(:android, :ios, or :all) — the one platform rule every NIF consumer
shares: the build args, the driver_tab, and the MOB-281 native-build record.
The language of a nifs: entry. Defaults to :c so existing (haptic)
plugins are unaffected; lang: :zig etc. opt into other compile paths.
Classifies the plugin tier (0–4) from which capability sections are present.
Whether an ios.plist_keys key is a privacy usage description
(NSBluetoothAlwaysUsageDescription, NFCReaderUsageDescription, …): the
string iOS shows in a permission prompt to explain why the app asks. Several
plugins may each need the same permission for their own reason, so these keys
combine across plugins instead of colliding (MobDev.Plugin.Merge.plist_keys/1,
MobDev.Plugin.Validator.cross_validate/2).
Validates a manifest map against the spec's required top-level fields.
Functions
@spec hot_pushable(map() | nil) :: true | false | :partial
Whether the plugin's contributions can be hot-pushed without a native rebuild.
Computed from populated sections, not from tier: true for pure-Elixir
plugins, false for native-only ones (NIFs / components), and :partial
when a plugin mixes native code with hot-pushable Elixir (screens, lifecycle).
Loads the manifest for a plugin checked out at plugin_dir.
Returns {:ok, nil} when there is no priv/mob_plugin.exs (a tier-0
plugin), {:ok, map} when one is present and evaluates to a map, or
{:error, reason} when the file is unreadable or doesn't yield a map.
Does not validate field contents — call validate/1 for that.
Returns true when plugin_dir has a priv/mob_plugin.exs, false
otherwise. Distinguishes tier-0 plugins (no manifest, no signature
needed) from tier-1+ plugins (manifest present, signature required)
without evaluating the manifest itself. See Verify.load_verified/1.
Whether the native build compiles this nifs: entry for platform
(:android, :ios, or :all) — the one platform rule every NIF consumer
shares: the build args, the driver_tab, and the MOB-281 native-build record.
An entry with no :platform is compiled on every platform; one tagged
:ios/:android only on that platform. lang: :objc is implicitly
Apple-only: Objective-C has no Android runtime, so an objc NIF authored
without an explicit platform: :ios must still be excluded from the Android
build args + driver_tab (otherwise zig tries to compile a .m source Android
cannot build).
The language of a nifs: entry. Defaults to :c so existing (haptic)
plugins are unaffected; lang: :zig etc. opt into other compile paths.
@spec tier(map() | nil) :: 0..4
Classifies the plugin tier (0–4) from which capability sections are present.
Highest matching section wins. nil (no manifest) is tier 0. A manifest
with required fields but no capability sections is the tier-1 floor (the
"minimum viable manifest").
Whether an ios.plist_keys key is a privacy usage description
(NSBluetoothAlwaysUsageDescription, NFCReaderUsageDescription, …): the
string iOS shows in a permission prompt to explain why the app asks. Several
plugins may each need the same permission for their own reason, so these keys
combine across plugins instead of colliding (MobDev.Plugin.Merge.plist_keys/1,
MobDev.Plugin.Validator.cross_validate/2).
Validates a manifest map against the spec's required top-level fields.
Returns {:ok, manifest} or {:error, reasons} with a list of every
problem found (validation never stops at the first error). nil (no
manifest) is valid — a tier-0 plugin has nothing to validate.