The Extensions Protocol is a negotiation mechanism used to establish non-firmware communication channels (e.g., health metrics, logs, shell) between the NervesHub platform and a device. Extensions are negotiated rather than assumed to ensure that traffic never interferes with firmware updates and that both sides agree on the capabilities being used.
The handshake follows a strict four-frame sequence:
- Platform Advertisement (
extensions:get): The platform sends a list of all available extensions and their versions (newest first) to the device. This is only sent to devices with device_api_version >= 2.2.0. - Device Join (
phx_join "extensions"): The device responds by joining the extensions topic, declaring exactly one version per extension it is capable of serving. - Platform Attach List (
phx_reply): The platform replies with a list of keys (extension names) that it has authorized for this specific device. An extension might be implemented by the platform but disabled for a specific product or device. - Device Confirmation (
<key>:attached): The device sends an attachment confirmation for each authorized key. Only after this step does the platform begin requesting data via <key>:<event> scoped messages.
Important Constraints:
- A client must not join the
extensions topic before receiving frame 1. - If an extension is omitted from the platform's attach list (frame 3), the device should treat this as a local failure/unsupported feature.
1. server -> device extensions:get {"extensions": {"logging": ["0.1.0", "0.0.1"], ..}}
2. device -> server phx_join "extensions" {"logging": "0.1.0", "health": "0.0.1"}
3. server -> device phx_reply ["logging", "health"]
4. device -> server logging:attached {}