File location
manifest.yaml lives at the root of the .adosplug archive. The host
opens the archive, reads the manifest first, and refuses to unpack
anything else if the manifest fails validation.
Top-level shape
Identity and configuration live as flat top-level keys. There is noplugin: wrapper.
agent or gcs must be present. The host accepts
plugins that ship only one half; the first-party Battery Health Panel,
for example, is GCS-only.
The manifest also accepts optional install-dialog content fields the GCS
renders for a richer pre-install summary (
description_long, features,
hardware_requirements, resource_impact, required_fc_parameters,
telemetry_fields, documentation_url, screenshots). The agent does
not interpret any of them.
compatibility
Node profiles are declared on the agent half (
agent.target_profiles),
not here.
agent
entrypoint is a relative path inside the archive (no absolute paths,
no ..). For a file-path entrypoint like agent/plugin.py the runner
loads a class named Plugin. A module:Class entrypoint is also
accepted and is how built-in plugins declare themselves.
isolation: subprocess is the default and the only mode third-party
plugins may declare. inprocess is reserved for first-party plugins
that import into the supervisor. runtime: rust runs the entrypoint as
its own binary (rust always runs subprocess).
Agent field reference
agent.resources
agent.mavlink_components
Each entry registers a MAVLink component so the router claims its id and
answers component-info on the plugin’s behalf.
Permission shape
A permission entry is either a bare string (which means required) or an object withid, required, and an optional degraded_behavior:
Schema-2 agent fields
contains_vendor_binary, vendor_attribution, subprocess_spawn, and
per_drone_config are schema-2 fields. A v1 manifest gets the defaults.
per_drone_config: trueruns one process per connected drone, each with its ownctx.agent_idand config at/var/lib/ados/plugins/<plugin_id>/config/<agent_id>.yaml.subprocess_spawnis an allowlist of binary basenames the plugin may exec. The plugin host rejects any spawn whose basename is not on the list, and the manifest validator requires theprocess.spawnpermission whenever the list is non-empty.contains_vendor_binaryplusvendor_attributiontravel together: the flag must be set when (and only when) at least one attribution record is present. Eachvendor_attributionentry takeslicense(required) plus optionalname,source_url,source_offer_url,upstream_repo,upstream_version,commit_sha, andnotice. See Vendor binaries.
gcs
contributes carries skills, tabs, parameters, settings,
panels, overlays, notifications, missionTemplates, mapOverlays,
and models. The slot value in contributes.panels[].slot comes from
the slot taxonomy (fc.tab, hardware.tab, settings.section, and the
rest; see the contribution points
reference). Mounting in a slot also requires the matching ui.slot.*
permission listed under gcs.permissions. Locales are listed under
gcs.locales, a sibling of contributes.
skills declares flight Skills that surface in the cockpit Skill Bar
(toggle, hotkey or gamepad binding, activation through per-drone config,
read-back over an event topic). Each skill entry needs the
ui.slot.flight-skill permission. The agent does not interpret skill
entries; the GCS skill registry reads them.
The full contribution reference, with the manifest shape of each kind and
where it renders, is on the
contribution points page.
Signing and the archive
The.adosplug archive is a zip. There is no per-asset hash list in the
manifest and no signing: block. Instead the archive carries a separate
top-level SIGNATURE file with two lines: the signer key id, then the
base64 Ed25519 signature over a canonical payload hash (the SHA-256 of
the sorted <path>\n<sha256-hex>\n lines for every entry except
SIGNATURE). Because the hash covers every entry, any tampering after
signing fails verification.
Archives are size-bounded (50 MB per archive, 25 MB per entry) and
reject path-traversal entries (.., absolute paths, symlinks). A
manifest that fails validation raises a manifest error; a signature from
an unknown or revoked signer is rejected (see
Signing keys).