Commit Graph

109 Commits

Author SHA1 Message Date
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
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
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
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 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 431f0d77bf fix: resolve CI lint failures (spotless + detekt)
- spotlessApply across core:repository, core:service, core:ui
- Android LockdownPassphraseStoreImpl: inline requirePrefs() body
  (FunctionSignature)
- JVM LockdownPassphraseStoreImpl: suppress ReturnCount on deserialize()
2026-05-13 16:50:03 -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 e1e678e374 feat(lockdown): implement encrypted JVM passphrase store
Replace no-op stub with PKCS12 KeyStore + AES-256-GCM file-backed
store at ~/.meshtastic/lockdown/. Passphrases now persist across
Desktop sessions with same error resilience as Android impl.
2026-05-13 11:02:28 -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 d3ae49781b refactor(lockdown): extract interfaces and move coordinator to commonMain
Phase 2 foundational refactor:
- T006: Extract LockdownPassphraseStore interface to core/repository
- T007: Make concrete Android impl implement the interface (renamed to Impl)
- T008: Add JVM/Desktop no-op passphrase store stub
- T010: Move coordinator state machine from core/service/androidMain to
  core/data/commonMain as LockdownCoordinatorImpl (pure KMP, no Android deps)
- Remove old LockdownHandlerImpl (superseded)
- Convert KoinComponent lazy inject to constructor injection
2026-05-13 09:09:15 -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 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
niccellular f6e97d7ff7 feat(lockdown): implement coordinator and typed status dispatch
- CommandSenderImpl: build AdminMessage.lockdown_auth = LockdownAuth(...)
  for provision/unlock and lock_now=true for the lock command.
- FromRadioPacketHandlerImpl: route the new FromRadio.lockdown_status
  variant to the coordinator; also notify the coordinator on
  config_complete_id.
- MeshActionHandlerImpl: forward handleSendLockdownUnlock/handleSendLockNow
  to the coordinator.
- MeshConnectionManagerImpl: call coordinator.onConnect/onDisconnect; add
  clearRadioConfig to purge cached config after a lock-now ACK.
- ServiceRepositoryImpl: back the lockdownState/lockdownTokenInfo/
  sessionAuthorized flows.
- LockdownHandlerImpl: orchestration. Switches on LockdownStatus.State
  (NEEDS_PROVISION / LOCKED / UNLOCKED / UNLOCK_FAILED), auto-replays
  stored passphrase on LOCKED, clears stored passphrase on a fresh
  UNLOCK_FAILED, surfaces backoff_seconds on rate-limit. Tracks a
  wasLockNow flag locally so the next LOCKED status after a lock-now
  command is translated to LockdownState.LockNowAcknowledged for an
  immediate UI disconnect (the new schema has no explicit ACK type).
- LockdownPassphraseStore: per-device EncryptedSharedPreferences store
  for auto-unlock. Not biometric-gated by design.
- Add androidx.security:security-crypto dependency.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 09:00:53 -04:00
James Rich 82135df865 Update notification intents and deep link URI format (#5408)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-11 19:34:24 -05: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 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 9e0ad369dd fix: update notification icon (#5293) 2026-04-29 16:02:41 +00:00
James Rich e0c1934d96 fix: Resolve top Crashlytics issues for 29320633 beta release (#5278) 2026-04-29 11:13:52 +00:00
James Rich 247f342210 chore: project-wide cruft cleanup and dead code removal (#5249)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-04-27 16:09:37 +00:00
James Rich 58eeef1152 feat(service): send polite ToRadio(disconnect=true) before transport close (#5210)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-22 11:04:29 -05:00
James Rich 17e69c6d4c chore: review-cleanup fleet (audit + fix + hardening) (#5158) 2026-04-17 00:02:59 +00:00
James Rich 401f59489a chore: remove deprecated mesh_service_example module (#5055) 2026-04-15 03:10:23 +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
James Rich 099aea2d81 feat(desktop): add entitlements and wire MeshConnectionManager into orchestrator (#5127) 2026-04-14 15:16:10 +00:00
James Rich 9acdf5309f refactor: modern APIs — Koin 4.2, CMP 1.11, Ktor resilience, Room @Upsert, injected dispatchers (#5119) 2026-04-14 11:41:01 +00:00
James Rich b13f9bf989 fix(resources): add resourcePrefix to KMP + widget modules, rename prefixed resources (#5111) 2026-04-13 18:25:23 +00:00
James Rich e85300531e refactor(transport): complete transport architecture overhaul — extract callback, wire BleReconnectPolicy, fix safety issues (#5080) 2026-04-12 04:22:18 +00:00
James Rich 9468bc6ebe refactor(service): unify dual connectionState flows into single source of truth (#5077) 2026-04-12 00:50:52 +00:00
James Rich 62264b10c6 refactor(model): remove ConnectionState helper methods and fix updateStatusNotification return type (#5074) 2026-04-11 23:41:34 +00:00
James Rich 174315b21f refactor(data): replace lateinit var scope + start() with constructor injection (#5075) 2026-04-11 23:39:29 +00:00
James Rich 929e273978 fix(build): resolve all actionable compile-time warnings (#5058) 2026-04-10 22:42:30 +00:00
James Rich 02f6fd67b8 fix: clean up flaky, duplicated, and misplaced tests; remove redundant deps (#5048) 2026-04-10 19:46:45 +00:00
James Rich ebf3b8272c fix(service): resolve MeshService crash from eager notification channel init (#5034) 2026-04-10 03:24:03 +00:00
James Rich 14b381c1eb fix: harden reliability, clean up KMP compliance, and improve code quality (#5023) 2026-04-09 18:21:46 +00:00
James Rich 60cc2f4237 fix: resolve bugs across connection, PKI, admin, packet flow, and stability subsystems (#5011) 2026-04-09 13:20:06 +00:00
Copilot 15419aba6c fix: resolve correct node public key in sendSharedContact and favoriteNode (#5005)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2026-04-08 12:54:47 +00:00
James Rich 6af3ad6f0c refactor(service): harden KMP service layer — database init, connection reliability, handler decomposition (#4992) 2026-04-04 18:07:44 +00:00
James Rich 51251ab16a feat(ci): shard test suite and enable JUnit 5 parallel execution (#4977) 2026-04-03 13:08:49 +00:00
James Rich 7e041c00e1 feat(wifi): introduce BLE-based WiFi provisioning for nymea-compatible devices (#4968) 2026-04-02 17:31:17 +00:00
James Rich e249461e3c feat(tak): introduce built-in Local TAK Server and mesh integration (#4951)
Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
2026-04-01 20:21:25 +00:00
James Rich c75c9b34d6 feat: implement XModem file transfers and enhance BLE connection robustness (#4959) 2026-03-31 03:49:31 +00:00
James Rich 518096ddc8 build: update Compose Multiplatform and migrate lifecycle dependencies (#4932)
Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
2026-03-26 15:18:45 +00:00
James Rich 8ce17defb7 refactor: remove demoscenario and enhance BLE connection stability (#4914)
Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
2026-03-25 14:24:42 +00:00
James Rich 6516287c62 refactor: BLE transport and UI for Kotlin Multiplatform unification (#4911)
Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
2026-03-25 02:15:51 +00:00
James Rich 96060a0a4d refactor: coroutine dispatchers and modernize testing infrastructure (#4901)
Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
2026-03-24 01:31:48 +00:00
James Rich 664ebf218e refactor: null safety, update date/time libraries, and migrate tests (#4900)
Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
2026-03-23 23:17:50 +00:00
James Rich d5d4aa4577 refactor(service): update string formatting for local stats notif (#4885)
Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
2026-03-22 15:55:30 +00:00