Skip to content

RFC: Bounded local client app metadata storage#12

Open
gotnull wants to merge 1 commit into
meshtastic:mainfrom
gotnull:feature/client-app-data
Open

RFC: Bounded local client app metadata storage#12
gotnull wants to merge 1 commit into
meshtastic:mainfrom
gotnull:feature/client-app-data

Conversation

@gotnull
Copy link
Copy Markdown

@gotnull gotnull commented May 5, 2026

Summary

Propose a small, bounded, local-node-only metadata store for Meshtastic companion applications, exposed through AdminMessage. Each record is keyed by a short ASCII app_id, carries an opaque payload up to 512 bytes plus a small schema/version integer and a firmware-set timestamp, survives reboot, and never leaves the locally-connected node.

The feature is intentionally namespaced, not owned: the firmware enforces shape and capacity, but it does NOT authenticate which companion app is writing. Any admin-capable client may overwrite or delete any app_id. Clients must therefore treat stored payloads as untrusted, optional, and recoverable.

Full RFC text in rfcs/2026-05-05-client-app-data.md.

Why an RFC

This change touches a frequently-edited proto (admin.proto), introduces a small new on-disk file in the firmware's /prefs tree, and lands a wire-additive surface that companion apps will rely on. The trust-model framing (namespaced, not owned) is also a design choice worth socializing before code lands. Surfacing it here so the maintainers can push back on:

  • the field-number allocation (proposing 104..107)
  • the empty-app_id get-miss sentinel (instead of a new status envelope)
  • the local-only-set/remote-read split
  • the 4-record / 512-byte limits
  • whether app_id naming should be convention-only or registry-based
  • whether per-app ownership should ever be added (no firmware primitive exists today)

before implementation lands upstream.

Affected components

  • meshtastic/protobufs: additive (1 new top-level message, 1 new wrapper, 4 new oneof fields, nanopb sizing). buf format / lint / breaking against master all pass.
  • meshtastic/firmware: 1 new module (ClientAppDataStore), 1 new /prefs/clientappdata.proto file, 4 new dispatch cases in AdminModule, 1 new init line in main.cpp, 1 new file path constant in NodeDB.h. 27 new native tests. Two virtual keywords on NodeDB::loadProto/saveProto for testability (mirrors the existing MockNodeDB::getMeshNode override precedent in test_traffic_management).
  • All companion clients: opt-in. Apps that don't use the feature are unaffected. Apps that do must treat it as optional and gracefully fall back when the firmware does not support it.

Linked PRs

Request for input

The full Unresolved Questions section of the RFC enumerates 11 open points. The most important ones for early maintainer feedback:

  1. Are field numbers 104..107 acceptable, or should they be allocated from a different range?
  2. Should remote authenticated admin be allowed to read client_app_data, or should all operations be local-only?
  3. Is 4 records x 512 bytes = 2.3 KB peak storage acceptable on constrained targets (STM32WL, low-flash nRF52 variants)? Should there be a MESHTASTIC_EXCLUDE_CLIENT_APP_DATA compile-out flag?
  4. Is the empty-app_id get-miss sentinel acceptable, or do you want to wait for a future broader admin-wide status-envelope model?
  5. Should there ever be per-client / per-app ownership or write protection? The firmware has no per-app identity primitive today (session_passkey is a node-minted nonce; admin_key[3] identifies operators, not apps). Adding one is out of scope for v1, but would change the trust model substantially.

Happy to revise the RFC and the implementation PRs based on the discussion here.

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented May 5, 2026

CLA assistant check
All committers have signed the CLA.

Add an RFC for a bounded, local-node-only AdminMessage metadata store
for companion apps. The store is intended for small, non-secret
convenience metadata and avoids encouraging clients to overload
user-visible fields or unrelated configuration surfaces.

Each record is keyed by app_id (^[a-z0-9._-]{1,32}$), carries an opaque
payload up to 512 bytes plus a small schema/version integer and a
firmware-set timestamp, survives reboot, and never leaves the locally-
connected node. Capped at 4 records per node (worst-case ~2.3 KB).

Important caveat: namespaced, not owned. Firmware enforces shape and
capacity but does not authenticate which client is writing. Any
admin-capable client may overwrite or delete any app_id. Documented
explicitly throughout the RFC, with a do-not-store list for secrets,
identity keys, paid-entitlement state, and any data used for security/
routing/authentication/purchase decisions.

Wire-additive only: no breaking changes. buf format/lint/breaking
against master all pass. Native firmware tests pass clean against the
implementation drafted on local feature branches.

RFC PR placeholder Meshtastic/rfcs#0000 should be replaced with the
real PR number after the RFC PR is opened.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants