Commit Graph
1225 Commits
Author SHA1 Message Date
Rightup c9fddbfd4b fix: update file handling to use UTF-8 encoding for YAML operations 2026-09-06 20:32:43 +01:00
Lloyd f634c684ce Merge pull request #442 from openhop-dev/feat-plugin-manager
Feat plugin manager
2026-09-05 23:44:58 +01:00
Rightup 6a2315d5ce feat: add plugin update checking and display in Plugins view 2026-09-05 23:37:22 +01:00
Lloyd d2c42a8c6c Merge pull request #441 from yellowcooln/fix/docker-compat
fix(docker): preserve upgrade defaults and use catalogue plugins
2026-09-05 23:32:02 +01:00
yellowcooln f1fff383b4 fix(docker): preserve upgrade defaults and use catalogue plugins 2026-09-05 18:20:58 -04:00
Rightup 8182242f9f update home page plugin buttons 2026-09-05 22:07:12 +01:00
Rightup 3836cb8cf3 feat(catalogue): add homepage field to CataloguePlugin and validate URL format - tighten the fixes to be portable across macOS/Linux 2026-09-05 21:56:19 +01:00
Lloyd 632ec89ee7 Merge pull request #440 from yellowcooln/fix/plugin-security-hardening
fix(security): address authorization, file access and privileged execution vulnerabilities
2026-09-05 21:05:42 +01:00
yellowcooln 766c2c2605 docs(web): direct frontend edits to matching RepeaterUI branch 2026-09-05 15:39:17 -04:00
yellowcooln 4aa67a354f fix(plugins): recover interrupted Python environment rebuilds 2026-09-05 13:15:26 -04:00
yellowcooln 1cafdd0383 fix(auth): serialize setup and configuration import transactions 2026-09-05 13:15:26 -04:00
yellowcooln c294de2b12 fix(web): confine frontend assets by resolved path components 2026-09-05 13:11:11 -04:00
yellowcooln 06c41bccba fix(plugins): harden provisioning, runtime, IPC and native upgrades 2026-09-05 13:04:34 -04:00
Rightup c32fb83626 update ui for larger imgs 2026-09-05 00:13:04 +01:00
Rightup 6a393c5c61 feat(plugins): add runtime endpoint and functionality to retrieve plugin runtime data 2026-09-04 22:16:52 +01:00
Rightup 6f9ef1c394 fix(stats): handle missing plugin argument in StatsApp routing 2026-09-04 21:38:10 +01:00
Rightup 9ce23a77d5 feat(plugins): add plugin manager service installation and restart logic 2026-09-04 21:30:29 +01:00
Yellowcooln 65836c2e2f Merge pull request #438 from yellowcooln/fix/plugin-manager-docker-runtime
Harden plugin manager Docker and catalogue support
2026-09-04 13:37:18 -04:00
yellowcooln c6098f88e3 Download approved plugins from GitHub Releases 2026-09-04 13:08:09 -04:00
yellowcooln eb8f934124 Install approved plugin wheels directly from R2 2026-09-04 12:13:08 -04:00
yellowcooln 3e008cac26 fix(plugins): use hosted catalogue endpoint 2026-09-04 11:00:03 -04:00
yellowcooln 9150264f49 ci: satisfy plugin branch quality gates 2026-09-04 10:42:33 -04:00
yellowcooln c0aeb89399 fix(docker): supervise plugin manager lifecycle 2026-09-04 10:39:42 -04:00
Rightup 8054333e3f feat:add ui switcher for plugins 2026-09-04 11:12:15 +01:00
Rightup ae8569bbec feat: add web frontends API endpoint and corresponding tests 2026-09-04 11:09:48 +01:00
Rightup 472025da16 feat:add images to catalogue 2026-09-04 08:58:18 +01:00
Rightup 03efbf1a21 feat:plugin-ui 2026-09-03 22:21:07 +01:00
Rightup 26560fd50a Add comprehensive tests for plugin management and IPC functionality
- Introduced tests for the plugin catalogue installation and update flows in `test_plugin_catalogue_install.py`.
- Added unit tests for the GitHub Releases plugin client in `test_plugin_github_releases.py`.
- Implemented IPC tests for the plugin manager Unix socket protocol in `test_plugin_ipc.py`.
- Created lifecycle and installation tests for the plugin manager in `test_plugin_manager_lifecycle.py`.
- Added tests for plugin manifest parsing in `test_plugin_manifest.py`.
- Developed tests for plugin filesystem layout and state management in `test_plugin_storage.py`.
2026-09-03 22:16:38 +01:00
Perry MosbacherandClaude Opus 5 bd0c340856 fix(sqlite): stop creating the upstream index before its columns exist
`SQLiteHandler.__init__` runs `_init_database()` and then `_run_migrations()`.
`_init_database` created `idx_packets_upstream_time`, which spans
`upstream_hash` and `upstream_hash_size` -- columns that, on a database
predating migration 13, only appear once `add_upstream_hash_to_packets` has
added them in the *later* migration step.

Fresh installs were fine, because the `CREATE TABLE` carries both columns. Any
existing database raised `no such column: upstream_hash` part-way through
`_init_database`, which caught and logged it. Every statement after the failing
index was therefore skipped -- including the `room_messages` and
`room_client_sync` tables -- and the daemon started with a partially-created
schema while reporting itself healthy: service active, radio initialised,
companions serving, HTTP up, and no packets recorded.

The `add_upstream_hash_to_packets` migration already creates this index, right
after adding the columns it depends on, so the copy in `_init_database` was
redundant as well as too early. Remove it and leave the index to the migration
that owns those columns. All three paths still end up with it: a fresh database
gets the columns from `CREATE TABLE` and the index when the migration runs, an
un-migrated database gets both from the migration, and an already-migrated one
kept the index from its earlier run.

Observed on a Raspberry Pi 4 upgrading a ~13 MB production database from 1.1.1;
the repeater was off-air for four minutes before the cause was found. It
self-heals on a second start, because the migration still runs after the failed
init, which makes it easy to misread as harmless.

`tests/test_sqlite_upgrade_existing_db.py` builds a database with the
pre-migration-13 schema and asserts `_init_database` runs to completion, keyed
on tables created after the old failure point. Asserting only on the upstream
columns is not sufficient -- the migration adds those either way.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 09:05:50 +01:00
Rightup bddb21a14a fix: correct project description in pyproject.toml 2026-09-03 08:51:14 +01:00
Rightup 77e938a167 Merge pull request #427 from yellowcooln/ci/fix-precommit-format 2026-09-03 08:50:08 +01:00
Rightup e476b6fb51 fix(api): improve send_advert function handling and response messages 2026-09-03 08:49:25 +01:00
Rightup af21189115 Merge pull request #431 from pfmos/fix/test-suite-self-kill 2026-09-03 08:44:53 +01:00
Perry MosbacherandClaude Opus 5 19ab3df5fc test: stop the suite killing itself part-way through
`RepeaterDaemon._shutdown` arms an exit watchdog -- a `threading.Timer` that
calls `os._exit(0)` after `SHUTDOWN_EXIT_GRACE_S` (5 s). That is right in
production: it guarantees SIGTERM is honoured.

`test_run_starts_http_and_handles_dispatcher_cancelled_gracefully` awaits
`daemon.run()`, whose `finally` reaches `_shutdown()`, so it armed a real
watchdog and returned. Five seconds later the timer fired and took the whole
pytest process down.

The failure mode is what makes this expensive: `os._exit(0)` exits with **status
zero**. pytest produces no summary line and a truncated progress bar, so the run
looks like it simply ended -- CI reads exit 0 as green on a run that never
finished, and any failure after that point is invisible. Locally the suite
appeared to hang at ~77% with no failures reported; it was actually being killed
there.

It also misattributes itself. The test blamed is whichever happened to be
running five seconds later, so it moves between runs
(`test_route_login_server_companion_only_skips_login_helper` and
`test_route_login_server_hash_collision_offers_to_both` on two runs here) and
never points at the cause. Finding it needed wrapping `_arm_exit_watchdog` to
log the arming test.

Two changes:

- Patch `_arm_exit_watchdog` for that test, matching the guard the shutdown
  tests in `test_main_py_coverage.py` already use.
- Add `tests/conftest.py` with an autouse fixture that fails any test leaving a
  live `shutdown-watchdog` timer, and cancels it. This blames the responsible
  test at the moment it leaks, rather than an unrelated one later. Verified it
  catches the original bug: reverting the one-line fix turns the silent
  process-kill into a teardown error naming the right test.

`test_exit_watchdog_is_a_daemon_timer_that_forces_exit` is unaffected -- it sets
a 0.05 s grace and asserts on a patched `os._exit` before returning, so it
leaves nothing behind.

With this the suite runs to completion: 3 failed, 1580 passed. Those 3 are
pre-existing on `dev` and unrelated.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 23:14:35 -04:00
yellowcooln 1d5b8f8537 ci: expand pull request validation 2026-09-02 16:22:05 -04:00
yellowcooln f665237825 ci: format room server for pre-commit 2026-09-02 15:57:30 -04:00
Lloyd efc5616ec4 Merge pull request #421 from Wild-Nisse/fix/companion-battery-mv
fix(companion): report real battery voltage in core stats
2026-09-02 20:53:46 +01:00
yellowcooln 991cf8c47e fix(companion): resolve storage paths consistently 2026-09-02 12:05:57 -04:00
yellowcooln e2ea8b01ad fix(companion): reject non-finite battery values 2026-09-02 10:12:26 -04:00
Rightup ca3d4ecb8f fix(docs): update references from pyMC to openHop in README 2026-09-01 21:34:34 +01:00
Rightup 5c4615dd58 Merge branch 'pr-422' into dev 2026-09-01 21:00:17 +01:00
yellowcooln 50921e1400 refactor(sensors): remove legacy Station G3 fallback 2026-09-01 10:48:36 -04:00
yellowcooln 0d28072063 merge: sync modem power telemetry PR with dev 2026-08-30 20:56:48 -04:00
yellowcooln 40a4e4f245 fix(sensors): normalize modem power telemetry 2026-08-30 20:55:48 -04:00
Yellowcooln a0d75b6739 Merge pull request #419 from yellowcooln/feat/proxmox-debian13-installer
feat: modernize Proxmox LXC installer for Debian 13
2026-08-30 20:51:49 -04:00
skjegg a3f8ec18e7 fix(companion): report battery and storage to companion clients
The previous commit fixed battery_mv in the STATS_TYPE_CORE frame, but that is
not the path companion apps use to display battery. CMD_GET_BATT_AND_STORAGE
goes through `CompanionFrameServer._get_batt_and_storage()`, an openhop_core
extension hook documented as "Default: all zeros" that the repeater never
overrode — so apps showed 0% regardless of what any sensor reported.

Override it in the repeater's frame server: battery from the same sensor lookup
added for core stats, storage from the filesystem holding the configured
storage_dir. Both are wired in from main.py alongside stats_getter.

Found by deploying the previous fix and observing that Home Assistant showed the
modem battery correctly while the phone app still showed 0% — two different
paths, only one of which had been fixed.
2026-08-30 12:18:52 -04:00
CB 035ba2f672 bus current power sensor payload 2026-08-30 11:42:56 -04:00
skjegg 0a2eeea8ee fix(companion): report real battery voltage in core stats
`_get_companion_stats` hardcoded `battery_mv: 0`, so every MeshCore companion
client connected to a Python repeater showed no battery, even when a sensor
plug-in was reporting one. The protocol side is already complete: the frame
server packs `battery_mv` into the STATS_TYPE_CORE frame and clients request it
via CMD_GET_BATT_AND_STORAGE.

Surface the first sensor reading that publishes a usable battery voltage,
accepting either `battery_voltage_mv` or `battery_voltage_v`. This covers an
attached UPS HAT as well as the battery of an openHop modem the repeater is
driving, which is the case that prompted this: a solar-powered modem whose
battery was invisible to the companion app right up until it went flat.

Returns 0 when no sensor reports a battery, which is what clients already
expect from a mains-powered node, and the lookup never raises — stats must
not be able to take down the companion connection.
2026-08-30 08:54:36 -04:00
yellowcooln 9e79acc887 docs: update Proxmox LXC requirements 2026-08-29 23:46:49 -04:00
yellowcooln a6ab8bc906 feat: shallow clone Console distribution 2026-08-29 23:19:09 -04:00