Skip to content

feat(protocol): probe private-key import/export capability at connect #357

Description

@kNoAPP

Part of #353. Prerequisite for every user-facing flow in the epic.

Problem or Motivation

The seed-identity feature depends entirely on CMD_EXPORT_PRIVATE_KEY and CMD_IMPORT_PRIVATE_KEY, both of which can be compiled out of the firmware. When they are, the radio answers RESP.DISABLED and the client raises PrivateKeyError('disabled') (client.ts:1661).

Research for #353 found the flags are enabled by defaultENABLE_PRIVATE_KEY_IMPORT=1 and ENABLE_PRIVATE_KEY_EXPORT=1 live in [arduino_base] in the firmware's platformio.ini, inherited by every platform base and every board variant, and no variant overrides them. But the flag sits under the comment "NOTE: comment these out for more secure firmware", which actively invites security-conscious builders to disable it, and prebuilt vendor images are outside our visibility.

Without a probe, a user on such a build walks through a multi-step wizard — generating a phrase, writing it down, confirming the words — and only discovers at the final write that their radio will not accept it. The two capabilities are also independent: a build can permit import but not export, or the reverse.

Proposed Solution

Detect both capabilities once per session and expose them on the store, so the UI can hide or disable the feature up front rather than failing at the end.

  • Probe during the connect flow in useMeshCore.ts, alongside the existing best-effort hydrate round-trips that already tolerate older firmware (readAutoAddBits is the precedent).
  • Export is safely probeable: call exportPrivateKey and catch PrivateKeyError('disabled') / ('unsupported'). Zero the returned key immediately — this probe must not leave the identity resident, and the existing method's TSDoc already makes that the caller's responsibility.
  • Import cannot be probed without performing it. Infer it: treat it as available when export is, and surface the real failure if a later import is refused. Document the inference rather than implying it was tested.
  • Add the result to MeshState as a capability field. It describes the connected radio, so it resets on disconnect and is not a preference — it must not enter RadioPreferences or the per-radio blob.
  • Gate the phase 1 and 2 entry points on it, with a localized explanation naming the build flag when unavailable, so a user can act on it.

Notes

Firmware predating the commands answers ERR rather than RESP.DISABLED; MeshCoreClient.privateKeyError already maps both onto distinguishable PrivateKeyError reasons, so the probe can tell "compiled out" from "too old" and say which.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions