Commit Graph

970 Commits

Author SHA1 Message Date
agessaman d8bc448f82 fix: update dependencies for platform-specific installation of openhop_core 2026-07-08 10:13:28 +01:00
Björkan 4a124782ae Replace favicon with openhop favicon 2026-07-08 10:12:47 +01:00
Will Dillon d1a9230ab5 feat: allow API key authentication in WebSocket handler
The PacketWebSocket.opened() method only accepts JWT tokens for
authentication. API keys (used via X-API-Key header for REST endpoints)
are silently rejected, forcing WS clients to obtain a JWT through a
separate login flow.

Add fallback to token_manager.verify_token() when JWT verification
fails or when an X-API-Key header is present. This lets API token
holders connect directly to the WebSocket without needing a JWT.

Auth priority:
1. JWT in ?token= query parameter (existing behavior)
2. API key in X-API-Key header
3. API key in ?token= query parameter (falls through from JWT reject)
2026-07-08 10:12:47 +01:00
Vashiru 667169c7ff feat: Bump to 168 hours to match docs.meshcore.io 2026-07-08 10:12:47 +01:00
Vashiru 17f8bcca2f feat: Allow setting max. flood interval to 50 2026-07-08 10:12:46 +01:00
Rightup 05d1e391d6 Merge branch 'dev' of https://github.com/rightup/pyMC_Repeater into dev 2026-07-08 07:25:56 +01:00
Rightup 630f2cfa4e Merge branch 'pr-343' into dev 2026-07-08 07:25:07 +01:00
Yellowcooln 143c7633bf Merge pull request #344 from yellowcooln/fix/docker-console-cache-bust
fix: refresh bundled Console in Docker builds
2026-07-07 21:44:37 -04:00
yellowcooln c14d8b2226 fix: refresh bundled console in docker builds
Invalidate the Docker cache layer that downloads the bundled Console release when the latest release changes, and allow manual builds to pin a Console tag.

Co-Authored-By: Warp <agent@warp.dev>
2026-07-07 21:35:13 -04:00
agessaman 4a055be8df fix(router): try both companion and server on colliding dest hash
On-air dest hashes are one byte, so a companion and a room-server (or
repeater) identity can share one. The login and text dispatch used
`if dest_hash in companion_bridges: ... elif login_helper/text_helper`,
so a companion silently shadowed a same-hash room server: its login
never reached the room-server handler and failed with Invalid HMAC
(e.g. Lake Stevens pubkey f55d.. / hash 0xf5 colliding with a companion).

Offer the packet to both handlers when both are registered at the hash;
decryption disambiguates — the key owner replies, the other fails HMAC
and no-ops. Non-colliding paths are unchanged. Applied to both the
LoginServerHandler and TextMessageHandler branches.

Adds regression tests covering collision (both invoked), companion-only
(server helper skipped), and server-without-companion for each path.
2026-07-07 14:51:59 -07:00
Rightup 9177d1aacc feat: add repeat on/off to status for mqtt 2026-07-07 22:41:32 +01:00
Rightup 1a0823b6d7 fix: rename radio settings entry for rak6421-13300x-slot2 to rak6421-13300x-slot2-hw-mod 2026-07-07 22:40:15 +01:00
Rightup 90d63d61de Merge branch 'pr-340' into dev 2026-07-07 22:34:41 +01:00
Rastislav Vysoky f15884565e Merge branch 'dev' into patch-1 2026-07-07 23:02:33 +02:00
Lloyd 7d30dd4247 Merge pull request #342 from agessaman/companion/post-refactor-cleanup
Companion/post refactor cleanup
2026-07-07 21:03:59 +01:00
agessaman 954150b2d8 merge: reconcile companion cleanup with fix-general-tidy
Merge the maintainer's fix-general-tidy branch (neighbor discovery,
keygen, API endpoints, web-asset rebuild, HTTP server config/control
commands, and an independent #286 room-server push/ACK/guest fix) into
the companion cleanup branch.

Both branches fixed #286 in parallel with byte-identical push-ACK CRC
logic. In the six overlapping files the maintainer's implementation is
kept (ACL replay-detection/session helpers, encoded path-len with legacy
fallback, expected_crc/ack_timeout_s injector API, dispatcher ACK
helpers); this branch's unique companion work is preserved on top
(sender_prefix persistence + migration, boot-state hardening /
CompanionStateLoadError, MessageQueue.max_size, older-core fallbacks).

Conflict resolution took the maintainer's side across the overlap, then
fixed two integration seams the merge introduced and updated this
branch's tests to the maintainer's API:
- room_server: timeout used undefined `hops`; aligned to `path_len`.
- packet_router: PATH helper was invoked twice (maintainer's
  unconditional call plus this branch's conditional local-identity
  call); dropped the now-redundant conditional block.

Pin openhop_core to @dev (was @feature/publish-workflow-message-handling)
so this can merge to the repeater's dev; core dev carries the required
sender_prefix and PathUtils.is_valid_path_len APIs.

Full suite green (1040 passed) against openhop_core dev and
refactor/companion-housekeeping; ruff clean.
2026-07-07 12:56:43 -07:00
Rightup 43a112ce7c feat: add HTTP server configuration and control commands 2026-07-07 20:38:22 +01:00
agessaman b2e45c2038 fix: resolve room-server push ACKs through the dispatcher
Room server pushes waited on dispatcher.wait_for_ack, but nothing in the
repeater could ever resolve it, so every push timed out and re-pushed on
the backoff schedule (issue #286's duplicate floods — worst for virtual
companions on the same instance, whose ACKs never even cross the air):

- no core AckHandler is registered (all RX lands in the router fallback),
  so received ACK CRCs were never fed to dispatcher ACK matching
- inject_packet waited on packet.get_crc(), a packet-hash CRC that no ACK
  sender produces; the crypto CRC only the room server knows was ignored
- PATH returns (how a flood-received DM is ACKed) were decrypted by
  PathHelper, but it read the encoded path_len wire byte as a raw count —
  an empty 3-byte-hash path (0x80) parsed as a 128-byte truncated
  payload — and the router's PATH branch never ran PathHelper for
  room/repeater destinations when any companion bridge existed

Fixes:
- router ACK branch feeds discrete ACK CRCs (RF and locally injected) to
  dispatcher._register_ack_received
- PATH packets addressed to a local server identity are processed by
  PathHelper regardless of companion bridges; PathHelper decodes the
  encoded path_len via PathUtils, keeps the encoded byte in out_path_len,
  and registers the embedded ACK via ack_received_fn
- inject_packet accepts expected_ack_crc/ack_timeout; the room server
  passes its crypto CRC and a hop-count-based timeout (the encoded byte
  would have produced a ~4-minute direct-push wait)

Verified live on a real mesh: push to a same-instance virtual companion
resolves via the PATH-embedded ACK (encoded path_len 0x80) and push to a
firmware client resolves via the discrete RF ACK, no re-push loops.

Fixes #286
Fixes #341
2026-07-07 11:17:54 -07:00
agessaman 9c6ea0151e fix: compute signed-post push ACK over the full signed span
push_post_to_client sent posts as TXT_TYPE_SIGNED_PLAIN (plaintext =
timestamp + flags + author_prefix + text) but computed its expected ACK
over the plain-DM span (timestamp + attempt byte + text). Signed-plain
receivers (firmware BaseChatMesh::onPeerDataRecv, and openhop_core's
text handler since it gained signed-message ACKs) reply with
sha256(decrypted[0 : 9 + strlen(text)] || client_pubkey)[:4], so the
server never recognized any push ACK: every push timed out and the same
posts were re-pushed forever (issue #286's repeating 'Push timed out'
log and duplicate unread floods).

Hash the exact plaintext span that is encrypted and sent, plus the
client pubkey. Verified against openhop_core's TextMessageHandler: the
ACK it emits for a pushed post now matches the stored pending_ack_crc.

Fixes #286
2026-07-07 10:35:28 -07:00
agessaman 0404b3ab44 fix: add blank-password read-only guests to the room ACL
A blank-password login replied success (read-only guest) without ever
creating an ACL entry or storing the ECDH shared secret. The client app
believed it was logged in, but the room server's text handler and sync
loop only see ACL members: the client's posts were dropped without a
delivery ACK (send shows failed) and posts were never pushed to it.
Rooms with only an admin password configured were fully affected since
every guest login is blank-password.

Add the guest to the ACL with guest permissions, the shared secret, and
sync_since (mirroring the password path), reject when the ACL is full,
and refresh activity timestamps on repeat blank logins.

Refs #286
2026-07-07 10:35:01 -07:00
agessaman 3a29061e24 fix: tolerate openhop_core without QueuedMessage.sender_prefix
Installed openhop_core releases predating the sender_prefix change
(paired with fd43d86) reject the kwarg, so restoring queued messages
raised TypeError and aborted companion init. Detect support via the
QueuedMessage signature and drop persisted prefixes with a warning on
older cores instead of failing the boot.
2026-07-07 07:53:49 -07:00
agessaman e6d4b68d01 fix: fail companion init loudly when persisted state cannot be loaded
A transient SQLite error during boot made companion_load_channels/
contacts/messages swallow the exception and return [], which is
indistinguishable from "no data". The Public-channel backfill then ran
over the empty store, so clients saw their channels wiped and later
saves could overwrite the persisted state.

- companion_load_{contacts,channels,messages} now return None on error
  vs [] for genuinely empty, and log the companion hash
- add companion_count_{channels,messages} helpers
- extract shared _restore_companion_state used by both the boot and
  hot-reload companion paths; each load is cross-checked against the
  table's row count for the hash, retried once after a short delay,
  and raises CompanionStateLoadError if it still cannot load, aborting
  companion init (and the Public backfill) instead of starting empty
- log restored row counts per companion; log when the channel store
  rejects a persisted channel (unchecked channels.set return)
- trim_companion_contacts_to_fit refuses to trim on a failed load
2026-07-07 07:43:27 -07:00
agessaman fd43d86ea8 fix: persist sender_prefix for signed room posts
TXT_TYPE_SIGNED_PLAIN room posts carry a 4-byte author pubkey prefix
(QueuedMessage.sender_prefix, added in openhop_core). The SQLite
persistence path dropped it, so posts replayed from persistence showed
a zero-padded author prefix in the app frame while posts synced from
the live in-memory queue were correct.

- add sender_prefix column (hex text, default '') to companion_messages
  with an ALTER TABLE migration for existing databases
- store/return the prefix in companion_push/pop/load_messages
- pass sender_prefix when rebuilding QueuedMessage from persistence in
  the frame server and the startup preload paths
- add round-trip, default, migration, and rebuild tests
2026-07-06 22:46:49 -07:00
agessaman 700a38b8c1 refactor: use public max_size property for offline-queue retention
Prefer MessageQueue.max_size (new public property in openhop_core) over
the private _max_size attribute, keeping a getattr fallback for older
cores that predate the property.
2026-07-06 16:38:45 -07:00
Rastislav Vysoky 141126a9a6 Clean up radio-settings.json by removing unused fields
Removed invalid settings from rak6421 and station g3
2026-07-06 21:50:15 +02:00
Lloyd e52637535d Merge pull request #337 from Littleaton/radio-fix-comma
Radio fix comma
2026-07-06 16:12:40 +01:00
Littleaton 0e26ed3cb3 fied extra comma 2026-07-06 09:06:55 -06:00
Rightup 1a2bf9e4fd feat:update ui with repeater discovery 2026-07-04 23:48:32 +01:00
Rightup 8b3894d2d5 fix: remove duplicate import statements in test files 2026-07-04 23:41:51 +01:00
Rightup daec7f0ebc feat: implement neighbor discovery session management and API endpoints 2026-07-04 23:41:33 +01:00
Lloyd a5c85dd9d9 Merge pull request #326 from Littleaton/dev
updated working zebra duo config radio 0 / 1 / Rak6421 pi hat
2026-07-04 22:27:33 +01:00
Lloyd ff43d85b85 Merge pull request #333 from mdspann/issue305
Add timezone to MQTT packet data
2026-07-04 22:19:49 +01:00
Rightup 229d71459f fix: improve upsert_client_sync to prevent over write. 2026-07-04 18:41:55 +01:00
mike 047ad19fd3 Add timezone to MQTT packet data 2026-07-03 15:07:26 -07:00
Rightup 05449987c1 feat: update packet detail screen to lookup repeater names 2026-07-03 21:21:20 +01:00
Rightup ae6ac1bd05 update packet table desktop/mobile with dupe groups 2026-07-02 21:47:51 +01:00
Rightup ae68112377 - Refactored ACL authentication flow with shared helpers for replay detection and session updates.
- Changed blank-password login behavior to create/manage guest sessions (when read-only is enabled), including replay protection and session timestamp tracking.
- Preserved and centralized `sync_since` handling during successful auth/session updates.
- Updated login handling to return explicit `(success, permissions)` and reset room-server sync guard state in SQLite on successful room-server login.
- Updated identity/banner output in mesh CLI from `pyMC_*` to `openHop_*` and adjusted default version fallback.
- Extended path handling to support encoded path-length semantics via `PathUtils`, with legacy fallback support for older/malformed packets.
- Added bundled ACK extraction from PATH payload extras and callback-based ACK propagation.
- Hardened room-server push logic: max-failure early skip, corrected expected ACK CRC calculation, path encoding compatibility, persisted sync/last-activity fields, and passed expected CRC + timeout into packet injection.
- Enhanced packet router ACK flow with dispatcher ACK registration helper, support for multipart ACK wrapper handling, configurable ACK wait timeout/CRC in injection, and ensured PATH helper processing always runs.
- Updated daemon wiring to pass ACK callback into `PathHelper`,
- make dispatcher dedupe configurable (prevent dbl deduping), and only register duplicate logging hook when dedupe is enabled.
- Expanded tests to cover guest blank-password replay tracking, updated room-server injector ACK expectations, and new duplicate-logging-hook gating behavior.
2026-07-02 16:32:32 +01:00
Rightup 34747d2610 feat: add packet retrieval by ID endpoint and corresponding database methods 2026-07-02 16:18:54 +01:00
yellowcooln 0561803eeb merge: sync dev with main 2026-07-02 09:23:56 -04:00
Yellowcooln a88ac21e61 Merge pull request #330 from yellowcooln/dev
Bundle Console UI into Docker image
2026-07-02 09:19:23 -04:00
yellowcooln f3d3129d4a fix: route fork Docker image publishes 2026-07-01 23:34:04 -04:00
yellowcooln 4a7720e7ae fix: route fork Docker image publishes 2026-07-01 23:15:19 -04:00
yellowcooln add7011c21 feat: bundle PyMC Console in Docker image 2026-07-01 23:05:28 -04:00
Littleaton b84479de0c fixed rak6421 config. 2026-06-30 14:11:55 -06:00
Littleaton baa89e836c updated working zebra duo config radio 0 / 1 2026-06-30 13:37:38 -06:00
Lloyd 823308aa3f fix: update drop reason handling in PacketRouter and RepeaterHandler 2026-06-29 15:48:19 +01:00
Lloyd a964062bf6 Merge branch 'pr-323' into dev 2026-06-29 15:22:16 +01:00
Lloyd 9be74efeb0 Merge remote-tracking branch 'origin/feat-std-key-formats' into dev 2026-06-29 15:21:05 +01:00
Lloyd 38efb05eeb fix: expose effective drop reason to PacketRouter 2026-06-29 15:18:39 +01:00
Rightup a53df3d76f feat: implement MeshCore-compatible key generation for all identity keys with guards for 0x00 and 0xff prefixs 2026-06-28 22:57:14 +01:00