feat: add IFAC network_name and passphrase support for RNode interfaces#718
feat: add IFAC network_name and passphrase support for RNode interfaces#718torlando-tech merged 4 commits intomainfrom
Conversation
Closes #714 Add optional network_name and passphrase fields to RNode interface configuration, enabling Reticulum's Interface Access Code (IFAC) cryptographic authentication for LoRa radio interfaces. Changes across the full stack: - Add networkName/passphrase to InterfaceConfig.RNode data class - Update JSON serialization/deserialization in InterfaceConfigExt and InterfaceRepository - Pass IFAC params through Kotlin→Python bridge in ServiceReticulumProtocol - Generate IFAC config lines for TCP RNode in reticulum_wrapper.py - Store IFAC params in pending config dict for BT/USB RNode - Read IFAC from config in ColumbaRNodeInterface.__init__ - Map IFAC fields in ViewModel configToState/stateToConfig - Extract shared IfacFields composable from TCPClientFields, reuse for new RNodeFields in InterfaceConfigDialog advanced options - Add tests covering all three data flow paths (TCP config file, BT/USB pending dict, ColumbaRNodeInterface init) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Greptile SummaryThis PR delivers a clean full-stack implementation of IFAC ( Confidence Score: 5/5Safe to merge; the implementation is correct and the only open item is a defensive best-practice in the Python config writer. All four code paths are covered by tests, the full-stack data flow is consistent, previous review concerns about passphrase trim asymmetry are resolved, and the one remaining P2 (newline strip) is a minor hardening suggestion rather than a functional bug given the UI already enforces single-line input. python/reticulum_wrapper.py — unquoted string values written to INI config without newline sanitization. Important Files Changed
Sequence DiagramsequenceDiagram
participant UI as InterfaceConfigDialog / ReviewConfigStep
participant VM as ViewModel (IMVM / RNodeWizardVM)
participant Repo as InterfaceRepository
participant Proto as ServiceReticulumProtocol
participant Py as reticulum_wrapper.py
participant IF as ColumbaRNodeInterface
UI->>VM: onConfigUpdate(networkName, passphrase)
VM->>Repo: save InterfaceConfig.RNode(networkName, passphrase)
Repo-->>VM: persisted
VM->>Proto: send RNode JSON (network_name, passphrase)
Proto->>Py: JSON over Kotlin→Python bridge
alt TCP connection mode
Py->>Py: _create_config_file()<br/>write network_name / passphrase to INI
Note over Py: RNS reads config → starts TCP RNode
else BT / USB connection mode
Py->>Py: store in _pending_rnode_configs dict
Py->>IF: ColumbaRNodeInterface(config)
IF->>IF: ifac_netname = config["network_name"]<br/>ifac_netkey = config["passphrase"]
Note over IF: RNS.Transport derives IFAC key
end
Prompt To Fix All With AIThis is a comment left during a code review.
Path: python/reticulum_wrapper.py
Line: 1582-1588
Comment:
**Strip newlines from IFAC strings before writing to config**
`network_name` and `passphrase` are the first user-supplied arbitrary strings written directly into the Reticulum INI config file (all other values, such as `frequency`, `bandwidth`, `interface_mode`, etc., are numeric or known-safe enum strings). An embedded newline — e.g. from a crafted JSON payload sent to the service — would split the value across lines, either silently truncating it or injecting spurious INI content below it.
The Android UI prevents this via `singleLine = true`, but a defensive strip on the Python side would close the gap at the write boundary:
```suggestion
# IFAC parameters
network_name = iface.get("network_name")
if network_name:
config_lines.append(f" network_name = {network_name.replace(chr(10), '').replace(chr(13), '')}")
passphrase = iface.get("passphrase")
if passphrase:
config_lines.append(f" passphrase = {passphrase.replace(chr(10), '').replace(chr(13), '')}")
```
How can I resolve this? If you propose a fix, please make it concise.Reviews (4): Last reviewed commit: "fix: skip to Review step when editing ex..." | Re-trigger Greptile |
app/src/main/java/com/lxmf/messenger/viewmodel/InterfaceManagementViewModel.kt
Outdated
Show resolved
Hide resolved
Apply .trim() to passphrase in both TCP and RNode stateToConfig paths to prevent silent IFAC mismatch from accidental whitespace. Clarify that ifac_netkey holds the raw passphrase (RNS.Transport derives the actual key). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The InterfaceConfigDialog is not used for RNode interfaces — editing goes through the RNode wizard. Add network_name and passphrase fields to the wizard's Review & Configure step (under Advanced Settings), wire through RNodeWizardState, and persist on save/load. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
In edit mode, jump directly to REVIEW_CONFIGURE with advanced settings expanded so the user sees their existing config immediately instead of starting at Device Discovery with default values. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
network_nameandpassphrasefields to RNode interface configuration, enabling Reticulum's IFAC (Interface Access Code) cryptographic authentication for LoRa radio interfacesIfacFieldscomposable fromTCPClientFieldsand reuse for RNode in the interface config dialog advanced optionsCloses #714
How it works
IFAC allows interfaces with matching
network_nameandpassphraseto communicate securely by signing and verifying packets using keys derived from these shared credentials. This is especially valuable for LoRa/RNode where anyone with the same frequency settings can receive traffic.Users can set these optional fields in the Advanced Options when editing an RNode interface.
Files changed (12)
ReticulumConfig.ktnetworkName/passphrasetoInterfaceConfig.RNodeInterfaceConfigExt.ktInterfaceRepository.ktServiceReticulumProtocol.ktreticulum_wrapper.pyreticulum_wrapper.pyrnode_interface.pyColumbaRNodeInterface.__init__reads IFAC from configInterfaceManagementViewModel.ktconfigToState/stateToConfigmap IFAC for RNodeInterfaceConfigDialog.ktIfacFieldscomposable,RNodeFieldsin advanced optionsTest plan
InterfaceConfigExtTest— RNode serialization includes/omits IFAC fieldsTestTcpRNodeConfigGeneration— TCP RNode config file contains/omits IFAC linesTestCreateConfigFile— BT/USB pending config dict stores/omits IFAC paramsTestIfacInit—ColumbaRNodeInterface.__init__reads IFAC from config dict🤖 Generated with Claude Code