Commit Graph

206 Commits

Author SHA1 Message Date
niccellular
8cab967c14 feat(lockdown): gate toggle on Capabilities.supportsLockdown; soften enable warning
- Add Capabilities.supportsLockdown (atLeast V2_8_0) and gate the security-screen
  lockdown toggle visibility on it, consistent with the other firmware-version
  capability flags. SecurityConfigScreen computes Capabilities from the connected
  node's firmware_version; LockdownModeSetting takes a `supported` flag.
- Reword the enable-lockdown warning: it's reversible (disable with passphrase, or
  a full erase), so drop the inaccurate "permanent/irreversible" framing and the
  red error styling; rename strings lockdown_irreversible_* -> lockdown_enable_*.
- Update CapabilitiesTest for the V2_8_0 floor.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 18:36:20 -04:00
niccellular
d0857ef278 feat(lockdown): runtime enable/disable toggle and DISABLED state
Make lockdown a runtime, user-toggleable setting rather than a one-way lock:

- Thread a `disable` flag through the lockdown send path (CommandSender,
  LockdownCoordinator, MeshActionHandler, RadioController, AIDL, UIViewModel)
  so the app can send LockdownAuth{passphrase, disable=true} to decrypt
  storage and leave lockdown.
- Add LockdownState.Disabled and map LockdownStatus.State.DISABLED; clear the
  stored passphrase and session authorization when a device reports DISABLED
  (or when the user disables it), so we never auto-unlock a disabled device.
- Add a "Lockdown mode" switch to the security settings screen
  (LockdownModeSetting): enable from DISABLED via a set-passphrase dialog with
  a one-time irreversible-SWD warning + explicit confirm; disable from UNLOCKED
  via a passphrase prompt; "Lock now" and session info while unlocked. The
  setting is hidden when the device never reports lockdown_status (non-capable).
- Tests for the disable round-trip and DISABLED mapping; refresh fakes/strings.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 16:30:37 -04:00
niccellular
2f6c8288c4 Merge remote-tracking branch 'origin/main' into features/lockdown-v2
# Conflicts:
#	.specify/feature.json
#	AGENTS.md
#	core/proto/src/main/proto
#	feature/settings/src/commonMain/kotlin/org/meshtastic/feature/settings/radio/component/SecurityConfigScreen.kt
2026-05-28 15:13:33 -04:00
Copilot
a5d176d4d5 docs: add settings validation reference (#5218)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2026-05-28 12:32:21 -05:00
James Rich
a67927818b Extract node list display settings to dedicated screen (#5580)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-23 00:01:50 +00:00
James Rich
5ec6d80f61 docs: comprehensive documentation audit and refresh (#5572)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-21 20:50:01 -05:00
James Rich
5d9e71da39 feat: node list density switching with compact layout and field toggles (#5444)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-21 17:44:48 -05:00
James Rich
a871dad7c1 chore(build): centralize feature CMP dependency wiring (#5567)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-21 19:02:07 +00:00
niccellular
3b02df3e67 Merge remote-tracking branch 'origin/main' into features/lockdown-v2
# Conflicts:
#	.specify/feature.json
#	AGENTS.md
#	core/proto/src/main/proto
2026-05-21 14:01:47 -04:00
James Rich
41e368641b fix(settings): remote admin always showed local node config (#5560)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-20 22:29:56 -05:00
James Rich
676be26460 Remove admin_channel_enabled toggle from Security Config screen (#5547)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-20 21:14:45 +00:00
James Rich
fc0df1a79a feat(docs): In-app documentation browser with Jekyll site and Docusaurus sync (#5445)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-19 04:00:22 +00:00
James Rich
f5128798a8 feat: adopt Material 3 Expressive design system (M3-native APIs only) (#5479)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-19 01:10:47 +00:00
niccellular
6ce565f16c feat(lockdown): thread max_session_seconds through coordinator and UI
End-to-end plumbing for LockdownAuth.max_session_seconds (per-boot
uptime cap on the unlocked session; 0 = unlimited).

Wire:
- CommandSenderImpl populates LockdownAuth.max_session_seconds in the
  outbound admin packet (clamped non-negative).

Coordinator + persistence:
- LockdownCoordinator.submitPassphrase gains optional maxSessionSeconds
  (default 0); persisted alongside boots/hours and replayed by
  auto-unlock so cached sessions keep the operator's cap on reconnect.
- StoredPassphrase gains a new field with a default of 0 so existing
  call sites stay source-compatible.
- LockdownPassphraseStore (Android EncryptedSharedPreferences impl):
  reads/writes the new field with a `_maxSessionSeconds` key suffix;
  legacy entries decode to 0.
- LockdownPassphraseStore (JVM file-backed impl): bumps the per-entry
  on-disk serialization from 3-line to 4-line; legacy 3-line entries
  still decode (treated as maxSessionSeconds=0).

IPC + radio plumbing:
- IMeshService.sendLockdownUnlock AIDL gains a 4th int parameter.
- MeshService stub, MeshActionHandler, RadioController interface, and
  both impls (AndroidRadioControllerImpl, DirectRadioControllerImpl)
  thread the field through.
- FakeIMeshService, FakeRadioController, FakeLockdownCoordinator
  updated to match.

UI:
- LockdownDialog adds a single optional "Session cap (minutes)" field
  below the boots/hours row. Operators enter minutes for ergonomics;
  the dialog multiplies by 60 before passing to the coordinator. Blank
  or 0 = unlimited (firmware default).
- UIViewModel.sendLockdownUnlock gains the new param with default 0.
- New string resources: lockdown_session_minutes,
  lockdown_session_minutes_help. Strings re-sorted via
  scripts/sort-strings.py.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 16:57:49 -04:00
James Rich
df4f10c4d6 fix(nav): remote admin nodenum + Nav3 consolidation and improvements (#5478)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-18 17:29:27 +00:00
James Rich
1dd47bc090 fix(settings): add input validation for BLE PIN, LoRa modem, and ambient lighting (#5477)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-18 12:52:17 +00:00
James Rich
f4b6b02ace refactor(build): rename entry modules and remove DESKTOP_ONLY mode (#5476)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-18 12:44:12 +00:00
Ben Meadors
a04a261b80 feat: TAK v2 protocol integration with zstd compression and full CoT type support (#5434)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: jamesarich <2199651+jamesarich@users.noreply.github.com>
Co-authored-by: James Rich <james.a.rich@gmail.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-14 12:50:01 +00:00
James Rich
d3324b1b12 fix: use positional format specifiers and show TTL fields in unlock mode
Compose Multiplatform stringResource requires positional specifiers
(%1$s, %1$d) — plain %s/%d renders literal format tokens.

Boot TTL and Hour TTL fields are now shown for both provision and
unlock, matching the original implementation. Confirm passphrase
field remains provisioning-only.
2026-05-13 12:44:22 -05:00
James Rich
2a1734d932 fix: finish lockdown review follow-ups
Address remaining review items, add integration and JVM store tests,
and sync the lockdown spec docs with the implemented API and UI.
2026-05-13 11:59:56 -05:00
James Rich
7beb639761 feat: implement lockdown mode authentication
- Add LockdownCoordinator state machine with auto-replay, lock-now,
  and error-resilient passphrase store calls
- Add EncryptedSharedPreferences-backed Android passphrase store
  with nullable fallback on crypto init failure
- Add LockdownDialog (provision/unlock/backoff) with byte-length
  passphrase validation and string resources
- Add LockdownSessionStatus composable for token info display
- Gate region-unset banner on sessionAuthorized in ConnectionsScreen
- Wire Lock Now button in SecurityConfigScreen
- Add LockdownCoordinatorImplTest covering all state transitions,
  auto-replay, lock-now, error paths, and uint32 overflow
- Add FakeLockdownCoordinator and update test fakes
- Delete unused LockdownUnlockDialog.kt
2026-05-13 10:49:50 -05:00
James Rich
585666bb81 feat(lockdown): Lock Now auto-disconnect, session status, provision confirm
- T027/T028: Auto-disconnect on LockNowAcknowledged state in app shell
- T020/T021: Confirm passphrase field in provision mode with mismatch validation
- T035/T036: LockdownSessionStatus composable showing boots remaining and expiry
- Wire session status and Lock Now button enabled state based on sessionAuthorized
- Expose lockdownTokenInfo and sessionAuthorized from RadioConfigViewModel
2026-05-13 09:19:29 -05:00
James Rich
ed7c8aa22f feat(lockdown): add non-dismissable LockdownDialog and app shell integration
Phase 3 (User Story 1 - Unlock a Locked Node):
- T014: Create LockdownDialog composable in feature/settings/lockdown/
  - Non-dismissable AlertDialog (onDismissRequest = {})
  - Passphrase field with visibility toggle
  - Provision mode with boots/hours TTL fields
  - Error display for UnlockFailed and UnlockBackoff states
  - Disconnect button instead of Cancel
- T017: Integrate dialog in Main.kt app shell
  - Observe lockdownState from UIViewModel
  - Submit triggers sendLockdownUnlock
  - Disconnect triggers setDeviceAddress("n") to drop connection
2026-05-13 09:15:52 -05:00
James Rich
d25136f83e fix: resolve compile errors from PR merge
- Replace java.text.DateFormat/java.util.Date usage in SecurityConfigScreen
  (constitution violation: no java.* in commonMain) with simplified Lock Now button
- Replace material.icons imports with MeshtasticIcons in LockdownUnlockDialog
- Proper token info display to be re-implemented in Phase 5 (T025-T026)
2026-05-13 09:03:11 -05:00
James Rich
c9c416ee1c Merge branch 'features/lockdown-v2' of https://github.com/meshtastic/Meshtastic-Android into feat/lockdown-mode
# Conflicts:
#	app/src/main/kotlin/org/meshtastic/app/ui/Main.kt
#	core/data/src/commonMain/kotlin/org/meshtastic/core/data/manager/CommandSenderImpl.kt
#	core/data/src/commonMain/kotlin/org/meshtastic/core/data/manager/FromRadioPacketHandlerImpl.kt
#	core/data/src/commonMain/kotlin/org/meshtastic/core/data/manager/MeshActionHandlerImpl.kt
#	core/data/src/commonMain/kotlin/org/meshtastic/core/data/manager/MeshConnectionManagerImpl.kt
#	core/repository/src/commonMain/kotlin/org/meshtastic/core/repository/MeshConnectionManager.kt
#	feature/connections/src/commonMain/kotlin/org/meshtastic/feature/connections/ui/ConnectionsScreen.kt
#	feature/settings/src/commonMain/kotlin/org/meshtastic/feature/settings/radio/RadioConfigViewModel.kt
2026-05-13 08:54:22 -05:00
niccellular
dae4369149 feat(lockdown): add unlock dialog, Lock Now button, region gating
- LockdownUnlockDialog: passphrase entry with boots / hours TTL inputs.
  Shows lock_reason on LOCKED, a backoff countdown on UNLOCK_FAILED with
  backoff_seconds > 0 (Submit disabled while in backoff), and switches
  the title to "Set Passphrase" on NEEDS_PROVISION.
- Main: collect lockdownState/lockdownTokenInfo, show the dialog,
  auto-clear on LockNowAcknowledged so the connection drops without
  a dialog flash.
- ConnectionsScreen: gate the "must set region" banner on
  isLockdownAuthorized so an unauthorized client isn't told to fix a
  region it can't see.
- SecurityConfigItemList: "Lock Now" button under Administration,
  labelled with the active session token's boots remaining and (if set)
  the wall-clock expiry.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 09:01:12 -04:00
niccellular
0c8e5302e4 feat(lockdown): wire AIDL, RadioController, and ViewModels
- IMeshService: sendLockdownUnlock(passphrase, bootTtl, hourTtl) and
  sendLockNow() AIDL methods.
- MeshService: AIDL stubs forwarding to MeshActionHandler.
- AndroidRadioControllerImpl: forward to meshService over AIDL.
- DirectRadioControllerImpl: forward directly to actionHandler (in-process
  non-Android targets).
- FakeIMeshService: test stubs.
- UIViewModel: lockdownState/lockdownTokenInfo flows, sendLockdownUnlock,
  sendLockNow, clearLockdownState. Routed through radioController so the
  commonMain code does not depend on the AIDL service directly.
- ConnectionsViewModel: expose lockdownState.
- RadioConfigViewModel: lockdownTokenInfo + sendLockNow for the Lock Now
  button in security settings.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 09:01:03 -04:00
James Rich
1976808a36 refactor: use immutable destNum in RadioConfigViewModel (#5436) 2026-05-13 02:06:52 +00:00
James Rich
dcb147163c fix: clarify position precision as ± radius (#5428) 2026-05-12 10:24:29 -05:00
James Rich
85c840de32 feat: add Compose Preview Screenshot Testing infrastructure (#5410)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-12 02:18:23 +00:00
James Rich
95c3bc0bce Brownfield gap remediation: 28 tasks + intro commonMain migration (#5401)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-11 20:10:23 +00:00
James Rich
3c75510f01 fix(mqtt): harden TLS enforcement, add user CA trust, and improve error diagnostics (#5365)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-06 12:09:49 -05:00
James Rich
2de57a9e81 feat: align theme with Design Standards v1.3, remove contrast setting (#5355)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-04 16:10:06 -05:00
James Rich
c0b0b9edd4 fix(network): resolve empty MQTT address and enforce TLS on default server (#5333)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-02 14:59:44 +00:00
James Rich
e198f52de5 refactor(coroutines): migrate to kotlinx-coroutines 1.11.0-rc02 (#5312)
Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-01 03:11:22 +00:00
James Rich
2822290908 refactor(build): build-logic cleanup, CC safety, and detekt 2.0 upgrade (#5311) 2026-05-01 02:48:37 +00:00
James Rich
e8f8e14984 fix: persist language switching and correctly map locales (#5287) 2026-04-29 14:59:10 +00:00
James Rich
815882d880 feat(messaging): add entry points for filter settings (#5229) 2026-04-23 10:25:43 +00:00
Nick
019c65ad8b fix(ui): make footer buttons expand downwards (#5226) 2026-04-23 09:47:34 +00:00
James Rich
f14ae2643c feat(node): smoother remote-admin UX with per-node session tracking (#5217)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-22 14:21:04 -05:00
James Rich
ba559549ba refactor: eliminate Accompanist permissions library (#5211)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-22 11:04:57 -05:00
James Rich
6e1a500ca7 fix(settings): restore Import/Export button functionality in #4913 (#5204) 2026-04-21 14:48:39 +00:00
James Rich
4fd52ffb46 fix(canned-messages): enable multiline text editing for long message lists (#5203)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-21 14:44:44 +00:00
James Rich
14e86b90f1 feat(mqtt): adopt mqttastic-client-kmp 0.2.0 — disconnect reasons + Test Connection (#5181)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-17 21:33:55 -05:00
James Rich
b979663e24 refactor: consolidate metric formatting through MetricFormatter (#5169)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-17 17:13:01 +00:00
James Rich
90f6e21a9c fix(ui): stable LazyColumn keys, semantic roles, and content descriptions (#5168)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-17 16:24:18 +00:00
James Rich
adfe3bfed1 refactor: use injected ioDispatcher and ApplicationCoroutineScope (#5167)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-17 16:18:45 +00:00
James Rich
a97f704300 feat(mqtt): migrate to MQTTastic-Client-KMP (#5165)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-17 15:19:08 +00:00
James Rich
17e69c6d4c chore: review-cleanup fleet (audit + fix + hardening) (#5158) 2026-04-17 00:02:59 +00:00
James Rich
72b981f73b chore: KMP audit — commonize code, centralize utilities, eliminate dead abstractions (#5133)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-15 02:17:50 +00:00