You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A device reports which event firmware it runs, and clients turn that into branding, event information, and lifecycle nudges drawn from a shared over-the-air metadata source.
Identity comes from the proto enum MyNodeInfo.firmware_edition. Display data for each edition, meaning name, welcome message, dates, venue, links, accent color and icon, lives off-device at GET https://api.meshtastic.org/resource/eventFirmware, with a bundled JSON snapshot as the always-available offline fallback. A new event therefore ships without an app release.
Given the edition, every client surfaces event branding on the surface that describes the connected device, auto-suppresses new-node notifications while on event firmware and restores them on return to vanilla, and nudges the user back to standard firmware once the event's end date has passed.
The proto enum name is the stable join key. The API and bundled metadata are the shared presentation layer keyed on it, with a localized enum-name map remaining an optional fallback for the edition name only.
Context
The MVP is shipped on both mobile clients. Android delivered the metadata pipeline, branding, theme fonts, notifications and post-event nudge in #6162 and #6163, then relocated branding in #6676. Apple shipped the metadata pipeline in #2082, branding and the info sheet in #2222, contrast and layout fixes in #2283, onboarding ordering in #2323, and the post-event nudge in commit 6d26b41f.
What remains is in-app event OTA, which is blocked, plus the parity items listed under open items.
The two data surfaces
Identity is the proto enum MyNodeInfo.firmware_edition, a FirmwareEdition reported at config handshake. Firmware owns the value set, and the first sixteen values are reserved for non-event special firmwares.
Value
Name
Kind
0
VANILLA
standard, not an event
1
SMART_CITIZEN
special, reserved below 16
16
OPEN_SAUCE
event
17
DEFCON
event
18
BURNING_MAN
event
19
HAMVENTION
event
127
DIY_EDITION
special
An edition other than VANILLA is an event. Clients must handle unknown or future values gracefully, treating them as the reported name with no branding, still non-vanilla for notification purposes.
Presentation comes from the metadata resource, which returns a version 2 envelope keyed by the enum name, sharing the {version, generatedAt, source, editions[]} shape used by deviceLinks. The edition string is the join key and must match the enum name exactly.
The minimum viable field set every client should consume is edition, displayName, welcomeMessage, eventStart, eventEnd, timeZone, location, accentColor, iconUrl and links. The richer tag, domain, theme and firmware objects are progressive; clients may ignore what they do not use but must tolerate unknown keys.
Field coverage is uneven and every sub-field is independently optional. Clients must not assume any of them is populated.
The firmware object carries the event's own build, meaning version, zip URL and release notes, so a client could offer the event firmware directly and compare it against the connected device's reported version. That capability is blocked; see open items.
There is no separate JSON schema. The live API is the source of truth and each client's typed models are its contract. If a formal schema is ever wanted it should live once with the API publisher, not per client.
Required Client Behavior
Seed from the bundled snapshot on first run so the feature works instantly with no network, refresh from the metadata resource in the background, and cache the result across launches.
Do not impose a short network deadline. The API is regularly measured at twenty to sixty seconds, and a tight timeout cancels every refresh and pins users to the bundled seed. Rely on the client's normal HTTP timeout and retry.
Leave the cache intact on an empty or failed response. Never wipe it to blank.
On connect, when the edition is not vanilla, look up the metadata record by enum name. When no record is found, still treat the device as running an event, showing the name without branding, and do not block.
On the first connect to any non-vanilla edition, auto-disable new-node and other high-churn notifications and set a one-shot latch. On the next connect to vanilla, if the latch is set, re-enable and clear it. The user may re-enable manually at any time and the latch must not fight them.
When the connected device runs an event edition whose end date has passed, evaluated in the edition's timeZone and falling back to the device zone, surface a persistent reminder to flash back to standard firmware, linking to the client's own firmware-update flow. It clears once the device is back on vanilla. A missing or unparseable end date is never treated as ended.
Show event branding on the surface that describes the connected device, not on the app chrome. Show the event icon, display name and a brand-color strip, and open the event info surface when tapped.
Do not replace the app-bar logo or tint the primary app bar. Android reverted exactly that in post-DEF CON review, on the grounds that the app's identity should not change based on the firmware running on the connected device.
Contrast-check every publisher-supplied color before use. Accent colors come from an editable feed, so no client can assume any of them is legible against its own surfaces. Derive foreground color from the accent's luminance and clamp tints to at least 3:1 against the surface rather than rendering raw brand hex. Design Standards v1.4 sections 2 and 7 apply.
Do not derive a full color scheme from the brand colors. There is no standard, contrast-correct way to build one from an arbitrary seed, and dropping raw brand hex into primary and secondary roles breaks tuned on-color contrast across every screen. Keep color to the accent strip and header treatment.
Optionally render the app-wide typeface from the theme fonts. These are Google Font family names rather than URLs, so each client loads them through its own downloadable-font mechanism and degrades to the default typeface where unavailable.
Make the ambient theme opt-out-able with a single toggle. The branding icon and info surface stay available when opted out, so the user can still see the event and re-enable.
Provide an event info surface showing the welcome message, venue, date range and links. It is purely informational.
Open items
In-app event OTA is blocked on the signed release contract. A client must not write executable bytes on the strength of an editable public metadata feed, so the firmware capability is gated behind design PR #133, which defines an Ed25519 schema-v1 contract with exact device targeting, immutable artifact URLs, SHA-256 and byte counts, source-version floors, explicit return-to-standard artifacts, ESP32 partition and nRF bootloader gates, and a mandatory web-flasher fallback whenever trust or compatibility cannot be proven. Its dependencies are meshtastic/api#110 and Meshtastic-Apple#2223, both draft. The contract must not be activated until a project-owned signing key is provisioned, its public key ships in clients, and every listed artifact clears the hardware validation matrix. A physical event-firmware OTA round trip has not been run.
The endpoint stays api.meshtastic.org. That host is moving to Cloudflare, which brings the cache and revalidation headers the current host lacks at the same hostname. The apiv2.meshtastic.org constants in Meshtastic-Apple#2393 are for testing that migration and are not the release path, so no client should hardcode apiv2. The ETag-aware fetch in that PR, which skips the decode and re-upsert when the payload is unchanged, is the durable half and is worth mirroring on Android.
The July event-sessions addendum is superseded. firmware#11109 was closed the same day it was filed with the clarification that the event workflow should reuse existing QR add and replace semantics rather than add a general channel-profile protocol. What shipped instead is firmware#11110, which preserves normal channel and LoRa files across an event OTA so standard firmware resumes them afterwards. Three client trackers still describe the abandoned design and need re-scoping or closing: Meshtastic-Apple#2133, meshtastic/web#1324, and Meshtastic-Android#3911.
Richer fields are adopted unevenly. Android consumes the theme fonts; Apple consumes the theme palette and tagline. Neither consumes the other's, which makes these the cheapest parity wins. The domain and tag fields are unused everywhere.
Icon handling differs. Apple loads the hosted icon through an HTTPS-only policy that rejects a plain-http URL rather than downgrading it, which is worth adopting as the cross-platform rule. Android still falls back to bundled per-edition drawables.
Notification scope should be confirmed as consistent. Apple gates new-node notifications and Android gates its node-events channel; whether the event latch suppresses the same categories on both has not been checked.
Publishing ownership is unconfirmed. The API still reports its source as bundled, and it remains unsettled who authors and edits editions and whether each app's bundled snapshot is regenerated from the same payload. Standardizing one bundled filename would let the same authored payload seed every app.
Localization has a known tradeoff. The display name and welcome message come from data rather than per-client string catalogs, so they are not translated. Clients that want a localized edition name may keep a localized enum-name map and layer the API metadata on top for everything else.
Acceptance Criteria
A device on event firmware shows event branding on its connected-device surface, and no client changes its app-bar identity.
Every publisher-supplied color is contrast-checked before rendering, and no accent produces text below the contrast minimum in either theme.
New-node notifications are suppressed on first connect to an event edition and restored on return to vanilla, without overriding a later manual change.
A device on an edition whose end date has passed shows the return-to-standard reminder, and one with a missing or unparseable end date never does.
An unknown or future edition value renders by name without branding and does not block.
A failed or empty metadata refresh leaves the previously cached data intact.
[PARENT] [ALIGNMENT]: Event firmware metadata
Decision
A device reports which event firmware it runs, and clients turn that into branding, event information, and lifecycle nudges drawn from a shared over-the-air metadata source.
Identity comes from the proto enum
MyNodeInfo.firmware_edition. Display data for each edition, meaning name, welcome message, dates, venue, links, accent color and icon, lives off-device atGET https://api.meshtastic.org/resource/eventFirmware, with a bundled JSON snapshot as the always-available offline fallback. A new event therefore ships without an app release.Given the edition, every client surfaces event branding on the surface that describes the connected device, auto-suppresses new-node notifications while on event firmware and restores them on return to vanilla, and nudges the user back to standard firmware once the event's end date has passed.
The proto enum name is the stable join key. The API and bundled metadata are the shared presentation layer keyed on it, with a localized enum-name map remaining an optional fallback for the edition name only.
Context
The MVP is shipped on both mobile clients. Android delivered the metadata pipeline, branding, theme fonts, notifications and post-event nudge in #6162 and #6163, then relocated branding in #6676. Apple shipped the metadata pipeline in #2082, branding and the info sheet in #2222, contrast and layout fixes in #2283, onboarding ordering in #2323, and the post-event nudge in commit
6d26b41f.What remains is in-app event OTA, which is blocked, plus the parity items listed under open items.
The two data surfaces
Identity is the proto enum
MyNodeInfo.firmware_edition, aFirmwareEditionreported at config handshake. Firmware owns the value set, and the first sixteen values are reserved for non-event special firmwares.VANILLASMART_CITIZENOPEN_SAUCEDEFCONBURNING_MANHAMVENTIONDIY_EDITIONAn edition other than
VANILLAis an event. Clients must handle unknown or future values gracefully, treating them as the reported name with no branding, still non-vanilla for notification purposes.Presentation comes from the metadata resource, which returns a
version 2envelope keyed by the enum name, sharing the{version, generatedAt, source, editions[]}shape used bydeviceLinks. Theeditionstring is the join key and must match the enum name exactly.The minimum viable field set every client should consume is
edition,displayName,welcomeMessage,eventStart,eventEnd,timeZone,location,accentColor,iconUrlandlinks. The richertag,domain,themeandfirmwareobjects are progressive; clients may ignore what they do not use but must tolerate unknown keys.Field coverage is uneven and every sub-field is independently optional. Clients must not assume any of them is populated.
The
firmwareobject carries the event's own build, meaning version, zip URL and release notes, so a client could offer the event firmware directly and compare it against the connected device's reported version. That capability is blocked; see open items.There is no separate JSON schema. The live API is the source of truth and each client's typed models are its contract. If a formal schema is ever wanted it should live once with the API publisher, not per client.
Required Client Behavior
timeZoneand falling back to the device zone, surface a persistent reminder to flash back to standard firmware, linking to the client's own firmware-update flow. It clears once the device is back on vanilla. A missing or unparseable end date is never treated as ended.Open items
In-app event OTA is blocked on the signed release contract. A client must not write executable bytes on the strength of an editable public metadata feed, so the
firmwarecapability is gated behind design PR #133, which defines an Ed25519 schema-v1 contract with exact device targeting, immutable artifact URLs, SHA-256 and byte counts, source-version floors, explicit return-to-standard artifacts, ESP32 partition and nRF bootloader gates, and a mandatory web-flasher fallback whenever trust or compatibility cannot be proven. Its dependencies are meshtastic/api#110 and Meshtastic-Apple#2223, both draft. The contract must not be activated until a project-owned signing key is provisioned, its public key ships in clients, and every listed artifact clears the hardware validation matrix. A physical event-firmware OTA round trip has not been run.The endpoint stays
api.meshtastic.org. That host is moving to Cloudflare, which brings the cache and revalidation headers the current host lacks at the same hostname. Theapiv2.meshtastic.orgconstants in Meshtastic-Apple#2393 are for testing that migration and are not the release path, so no client should hardcodeapiv2. The ETag-aware fetch in that PR, which skips the decode and re-upsert when the payload is unchanged, is the durable half and is worth mirroring on Android.The July event-sessions addendum is superseded. firmware#11109 was closed the same day it was filed with the clarification that the event workflow should reuse existing QR add and replace semantics rather than add a general channel-profile protocol. What shipped instead is firmware#11110, which preserves normal channel and LoRa files across an event OTA so standard firmware resumes them afterwards. Three client trackers still describe the abandoned design and need re-scoping or closing: Meshtastic-Apple#2133, meshtastic/web#1324, and Meshtastic-Android#3911.
Richer fields are adopted unevenly. Android consumes the theme fonts; Apple consumes the theme palette and tagline. Neither consumes the other's, which makes these the cheapest parity wins. The
domainandtagfields are unused everywhere.Icon handling differs. Apple loads the hosted icon through an HTTPS-only policy that rejects a plain-http URL rather than downgrading it, which is worth adopting as the cross-platform rule. Android still falls back to bundled per-edition drawables.
Notification scope should be confirmed as consistent. Apple gates new-node notifications and Android gates its node-events channel; whether the event latch suppresses the same categories on both has not been checked.
Publishing ownership is unconfirmed. The API still reports its source as bundled, and it remains unsettled who authors and edits editions and whether each app's bundled snapshot is regenerated from the same payload. Standardizing one bundled filename would let the same authored payload seed every app.
Localization has a known tradeoff. The display name and welcome message come from data rather than per-client string catalogs, so they are not translated. Clients that want a localized edition name may keep a localized enum-name map and layer the API metadata on top for everything else.
Acceptance Criteria
Platform Tracking
6d26b41fFirmwareEditionvalues and the publishing of the metadata resource