Commit Graph
100 Commits
Author SHA1 Message Date
JingleManSweep 9724e24279 Merge pull request #389 from ipnet-mesh/renovate/daisyui-5.x-lockfile
chore(deps): update dependency daisyui to v5.7.47
2026-10-12 19:21:02 +01:00
JingleManSweep f97020b540 Merge branch 'main' into renovate/daisyui-5.x-lockfile 2026-10-12 19:08:04 +01:00
JingleManSweep e5b915c2de Merge pull request #391 from ipnet-mesh/renovate/node-24.x-lockfile
chore(deps): update dependency @types/node to v24.19.2
2026-10-12 19:07:49 +01:00
JingleManSweep a471e1a166 Merge pull request #392 from ipnet-mesh/renovate/react-monorepo
chore(deps): update react monorepo to v19.3.0
2026-10-12 18:57:42 +01:00
JingleManSweep 16037e19e6 Merge branch 'main' into renovate/react-monorepo 2026-10-12 18:39:07 +01:00
JingleManSweep adea0bbe1e Merge pull request #393 from ipnet-mesh/renovate/vite-8.x-lockfile
chore(deps): update dependency vite to v8.3.4
2026-10-12 18:38:50 +01:00
JingleManSweep f29160f829 Merge branch 'main' into renovate/vite-8.x-lockfile 2026-10-12 18:06:42 +01:00
JingleManSweep b0886f1c2e Merge pull request #394 from ipnet-mesh/renovate/anomalyco-opencode-2.x
chore(deps): update anomalyco/opencode action to v2
2026-10-12 18:06:25 +01:00
JingleManSweep 4467c0dbb3 Merge branch 'main' into renovate/anomalyco-opencode-2.x 2026-10-12 17:21:35 +01:00
JingleManSweep 0ae075ab6c Merge pull request #395 from ipnet-mesh/renovate/react-i18next-17.x-lockfile
chore(deps): update dependency react-i18next to v17.0.16
2026-10-12 17:21:15 +01:00
JingleManSweep 5074e6ab58 Merge branch 'main' into renovate/react-i18next-17.x-lockfile 2026-10-12 15:50:22 +01:00
JingleManSweep 5e9454d890 Merge pull request #402 from ipnet-mesh/renovate/tanstack-query-monorepo
chore(deps): update dependency @tanstack/react-query to v5.104.2
2026-10-12 15:50:03 +01:00
JingleManSweep 9f7e330d08 Merge branch 'main' into renovate/tanstack-query-monorepo 2026-10-12 15:22:40 +01:00
JingleManSweep 4057ea867e Merge pull request #405 from ipnet-mesh/renovate/vitest-monorepo
chore(deps): update dependency vitest to v5.0.4
2026-10-12 15:22:18 +01:00
JingleManSweep 636c64644f Merge branch 'main' into renovate/tanstack-query-monorepo 2026-10-12 09:50:04 +01:00
JingleManSweep a10229e6d8 Merge pull request #404 from ipnet-mesh/renovate/i18next-26.x-lockfile
chore(deps): update dependency i18next to v26.4.4
2026-10-12 09:49:48 +01:00
JingleManSweep 47bf267f3b Merge branch 'main' into renovate/react-i18next-17.x-lockfile 2026-10-12 08:53:17 +01:00
JingleManSweep 679770ffa8 Merge pull request #403 from ipnet-mesh/renovate/jsdom-30.x-lockfile
chore(deps): update dependency jsdom to v30.1.2
2026-10-12 08:53:00 +01:00
JingleManSweep a17606c81b Merge pull request #401 from ipnet-mesh/renovate/i18next-26.x-lockfile
chore(deps): update dependency i18next to v26.4.3
2026-10-12 00:18:32 +01:00
JingleManSweep d646bbb64a Merge pull request #396 from ipnet-mesh/renovate/testing-library-monorepo
chore(deps): update dependency @testing-library/dom to v10.4.2
2026-10-11 23:33:17 +01:00
JingleManSweep 6c6da618e7 Merge branch 'main' into renovate/testing-library-monorepo 2026-10-11 23:24:58 +01:00
JingleManSweep 2e643f2b4d Merge pull request #397 from ipnet-mesh/renovate/vitest-monorepo
chore(deps): update dependency vitest to v5.0.3
2026-10-11 23:24:44 +01:00
JingleManSweep 72910af686 Merge pull request #399 from ipnet-mesh/renovate/vitejs-plugin-react-6.x-lockfile
chore(deps): update dependency @vitejs/plugin-react to v6.1.2
2026-10-11 23:07:35 +01:00
JingleManSweep a46c6271ad Merge pull request #400 from ipnet-mesh/fix/sqlalchemy-2.1-ci
fix(deps): restore CI under SQLAlchemy 2.1
2026-10-11 23:01:19 +01:00
Louis KingandClaude Opus 5.5 45bcf25fe8 fix(deps): restore CI under SQLAlchemy 2.1
SQLAlchemy 2.1 no longer installs greenlet by default, so the async
engine fails to import (Test, E2E api container), and its sources use
the `untyped-decorator` mypy code that the pinned mypy 1.9 hook rejects
(Lint).

- depend on sqlalchemy[asyncio] so greenlet is installed again
- bump the mirrors-mypy pre-commit hook to v2.4.0
- guard nullable tag values / channel_idx flagged by the newer mypy

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UFsp2i9E98EzovBaurmtEb
2026-10-11 22:53:10 +01:00
JingleManSweep 403a3c7a1c Merge pull request #398 from ipnet-mesh/renovate/react-router-monorepo
chore(deps): update dependency react-router to v8.4.0
2026-10-11 17:28:39 +01:00
JingleManSweep 5e886cfb23 Merge pull request #383 from ipnet-mesh/renovate/daisyui-5.x-lockfile
chore(deps): update dependency daisyui to v5.7.28
2026-09-05 13:43:36 +01:00
JingleManSweep 8e94ad93f8 Merge branch 'main' into renovate/daisyui-5.x-lockfile 2026-09-05 13:41:06 +01:00
JingleManSweep 87b33f824b Merge pull request #384 from ipnet-mesh/renovate/i18next-26.x-lockfile
chore(deps): update dependency i18next to v26.4.2
2026-09-05 13:40:50 +01:00
JingleManSweep f188194f25 Merge pull request #385 from ipnet-mesh/renovate/react-i18next-17.x-lockfile
chore(deps): update dependency react-i18next to v17.0.13
2026-09-05 13:28:46 +01:00
JingleManSweep 3eb83d6544 Merge branch 'main' into renovate/react-i18next-17.x-lockfile 2026-09-05 13:26:18 +01:00
JingleManSweep 45a599b43d Merge pull request #386 from ipnet-mesh/renovate/anomalyco-opencode-1.x
chore(deps): update anomalyco/opencode action to v1.18.29
2026-09-05 13:26:03 +01:00
JingleManSweep da13b9362c Merge pull request #387 from ipnet-mesh/renovate/react-monorepo
chore(deps): update dependency @types/react-dom to v19.2.7
2026-09-05 11:56:46 +01:00
JingleManSweep 3e44c4c77b Merge pull request #388 from ipnet-mesh/renovate/major-vitest-monorepo
chore(deps): update dependency vitest to v5
2026-09-05 11:53:44 +01:00
JingleManSweep b4c5d384a6 Merge pull request #382 from ipnet-mesh/feat/rss-feed-icon-toolbar-links
feat(web): add RSS feed icon links to list toolbars
2026-08-31 10:27:57 +01:00
Louis King 8fb4b4705b feat(web): add RSS feed icon links to list toolbars
- Add IconRss component and feedHref prop to ListToolbar
- Wire feed links on Nodes, Advertisements, and Messages pages
- Messages feed link respects channel filter, defaults to idx 17
- Simplify advert/node feed item bodies, link adverts to packet hashes
- Add unit tests, page tests, and e2e specs for feed link behavior
2026-08-31 10:22:52 +01:00
JingleManSweep f5ae082adb Merge pull request #381 from ipnet-mesh/feat/rss-atom-public-feeds
feat(api): add RSS/Atom feeds for public mesh data
2026-08-30 23:48:43 +01:00
Louis King 1513561df9 feat(api): add RSS/Atom feeds for public mesh data
Four feeds (public messages, node adverts deduped per node, new nodes,
per-community-channel messages), each in RSS 2.0 and Atom, built with
stdlib ElementTree. Feeds are hard-pinned to the logged-out view
(anonymous visibility, spam always filtered, identity headers ignored)
and served at clean public web URLs (/feeds/*) via a shared proxy helper
that forwards If-None-Match + X-Forwarded-* and gates on maintenance
mode. Responses are Redis-cached (ETag/304, public max-age) and
invalidated with messages/adverts/channels mutations. Item/self links
always target the public web endpoint; WEB_PUBLIC_URL pins the canonical
origin. Includes a FEATURE_FEEDS kill switch, SPA autodiscovery <link>
tags, and env/docs updates (v0.21.0 upgrading notes).
2026-08-30 23:44:02 +01:00
JingleManSweep f6a0d9c331 Merge pull request #380 from ipnet-mesh/chore/remove-postgres-transition-shims
chore(db): remove v0.19 Postgres-transition shims (v0.20)
2026-08-30 22:24:32 +01:00
Louis King c643c50378 chore(db): remove v0.19 Postgres-transition shims
Remove the upgrade-compatibility items scheduled for v0.20 in the v0.19
release notes:

- the `meshcore-hub db migrate-to-postgres` command and its
  `common/db_migrate.py` module (with its dedicated tests)
- the `database_backend` settings field and its legacy-backend validator
  (a leftover DATABASE_BACKEND is now silently ignored)
- the `[postgres]` pip extra alias (Dockerfile installs `.` now)

`tests/test_main.py` is rewritten as a minimal CLI smoke test to keep
entry-point coverage. Docs updated: v0.20.0 upgrade section notes the
removals (SQLite deployments must upgrade through v0.19 first), README
and database.md pointers reworded, stale .env.example comment dropped.
2026-08-30 22:20:16 +01:00
JingleManSweep 1948a3d367 Merge pull request #379 from ipnet-mesh/feat/mandatory-redis
feat(api): make Redis a required cache dependency
2026-08-30 21:57:24 +01:00
Louis King 3593d14878 feat(api): make Redis a required cache dependency
Redis becomes mandatory infrastructure (PostgreSQL-parity): the
REDIS_ENABLED flag, NullCache backend, and every conditional caching
code path are removed. /health/ready reports not_ready (503) when
Redis is unreachable and cached endpoints return 503 instead of
silently degrading; invalidation helpers never raise after a
committed write.

The bundled redis container joins the core profile only via
docker-compose.dev.yml (production points REDIS_* at an external
instance, same no-shadowing pattern as postgres), the backend suite
runs against real Redis (test-redis on 127.0.0.1:55433, CI redis:8
service container, per-xdist-worker key prefixes), and operator docs
describe the required-dependency setup (upgrading.md gains the
v0.20.0 section).
2026-08-30 21:51:51 +01:00
JingleManSweep e1f421f7bd Merge pull request #377 from ipnet-mesh/feat/map-node-clustering
feat(web): cluster map markers for large node counts
2026-08-30 13:20:23 +01:00
Louis King d1dd96fb7c test(e2e): make map spec clustering-aware
Marker clustering changed the map DOM contract the spec relied on:
clustered and off-viewport markers are absent, so raw .map-marker counts
undercount and first-marker clicks can hit-test against the sticky
navbar/banners. Count nodes as individual markers plus cluster badge
totals (new data-testid on the badge), zoom into a cluster before the
label and popup interactions so targets sit mid-map, and assert cluster
clicks spread children into individual markers.
2026-08-30 13:11:43 +01:00
Louis King c1024bed04 feat(web): cluster map markers for large node counts
Wrap MapPage node markers in react-leaflet-cluster (leaflet.markercluster)
with spiderfy-at-max-zoom, zoom-to-bounds on click, clustering disabled at
zoom >= 15, and viewport culling so off-screen markers stay out of the DOM.
Cluster bubbles render a plain themed count badge. Marker label HTML is now
only built when the show-labels toggle is on, halving per-marker DOM weight;
hover-to-reveal no longer applies while labels are toggled off.
2026-08-30 13:01:07 +01:00
JingleManSweep bda6370cb0 Merge pull request #376 from ipnet-mesh/test/e2e-ui-regression-coverage
test(e2e): expand Playwright coverage for UI regression protection
2026-08-30 12:39:53 +01:00
JingleManSweep 4a4eb134d0 Merge branch 'main' into test/e2e-ui-regression-coverage 2026-08-30 12:37:54 +01:00
Louis King 47fa9c6749 test(e2e): fix selector and assertion bugs in the new specs
- channels: post-delete card count is 6 (6 seeded + 1 created - 1), not 5
- empty-states/pagination: the empty text renders twice (mobile
  EmptyState + desktop EmptyRow); scope assertions to the table cell
- mobile: list-row is desktop-only; assert the mobile sort select and
  card text instead
- not-found: '/$' is a glob, not a regex; assert the exact URL '/'
- packets-detail: the newest seeded packet is the ce01 message, not an
  advert; assert the event type returned by the API
2026-08-30 12:32:53 +01:00
Louis King ec199e4e2b test(e2e): expand Playwright coverage for UI regression protection
Grow the suite from 41 to 77 specs covering previously untested UI
surfaces: channels admin CRUD with QR codes and keyboard nav, node
detail adoption/tag editing with the role permission matrix, SPA 404
page, sortable tables with URL-synced sort state, pagination with
filter-preserving links, mobile viewport (hamburger nav, mobile cards,
sort select), anonymous/member auth gating, raw packet detail, and
empty states. Route cards now assert history chart, recent-match links
and owner profile links.

Supporting changes: purposeful data-testids on channels/node-detail/
pagination/sort headers (plus aria-sort) and mobile nav; seed_data adds
30 trace_data filler groups for pagination, channels at every
visibility tier incl. one disabled, and a pw-operator profile.
2026-08-30 12:27:48 +01:00
JingleManSweep 18e3eb88de Merge pull request #375 from ipnet-mesh/renovate/major-github-artifact-actions
chore(deps): update actions/download-artifact action to v8
2026-08-30 11:58:17 +01:00
JingleManSweep e67e0ec3ae Merge pull request #374 from ipnet-mesh/chore/ci-summary
ci: add consolidated job summary with test results and artifacts
2026-08-30 11:50:53 +01:00
Louis King 9f9cd67440 ci: add consolidated job summary with test results and artifacts
Add a summary job that runs after all CI jobs (even on failure),
parses the pytest/vitest/Playwright JUnit reports plus coverage.xml,
and renders a consolidated Markdown summary to $GITHUB_STEP_SUMMARY:
job results, test counts, durations, backend coverage, failure
details, and the artifact inventory. Enable a Playwright JUnit
reporter and include it in the playwright-report artifact.
2026-08-30 11:46:12 +01:00
JingleManSweep 8aa451d4b7 Merge pull request #373 from ipnet-mesh/fix/postgres-profile-dev-only
fix(compose): keep bundled postgres out of the core profile in production
2026-08-30 11:24:46 +01:00
Louis King 5a8794f5c9 fix(compose): keep bundled postgres out of the core profile in production
Starting core with docker-compose.prod.yml also started the bundled
postgres container, whose 'postgres' network alias shadowed a shared
instance of the same name on the same Docker network — the live site
silently talked to an empty local database instead of DATABASE_HOST.

- Base file: postgres profiles are now [all, postgres] (core dropped);
  the dev override unions 'core' back in, so the documented dev
  workflow (make up, --profile core) is unchanged
- migrate's postgres dependency is required: false — still health-gated
  when the bundled container is active, skipped when profile-inactive
- prod override documents the behavior; opt in explicitly with
  --profile postgres (or --profile all) for a bundled production DB
- Docs: database.md/deployment.md/configuration.md/README/.env.example
  updated; upgrading.md gains a one-time cleanup runbook (full down to
  remove the previously started hub-postgres container)
2026-08-30 11:22:08 +01:00
JingleManSweep c085e124eb Merge pull request #372 from ipnet-mesh/chore/ci-e2e-and-report-artifacts
Add Playwright e2e job to CI and upload test report artifacts
2026-08-30 11:05:35 +01:00
JingleManSweep 5f621d8036 Merge branch 'main' into chore/ci-e2e-and-report-artifacts 2026-08-30 11:02:56 +01:00
Louis King 3ca379c923 Add Playwright e2e job to CI and upload test report artifacts 2026-08-30 11:02:12 +01:00
JingleManSweep 562e54a2ff Merge pull request #371 from ipnet-mesh/docs/remove-sqlite-support-plan
Remove SQLite support; PostgreSQL is now the only database backend
2026-08-30 10:49:13 +01:00
Louis King 81dcd3dead Remove SQLite support; PostgreSQL is now the only database backend 2026-08-30 10:19:12 +01:00
Louis King 2c805f2ae1 Updates 2026-08-29 23:31:15 +01:00
JingleManSweep e87a002238 Merge pull request #370 from ipnet-mesh/fix/operational-hardening
fix: readiness 503s, maintenance gating, cache invalidation, and webhook/engine hardening
2026-08-29 22:43:25 +01:00
Louis King 3f9669f7e5 fix: readiness 503s, maintenance gating, cache invalidation, and webhook/engine hardening
- /health/ready returns 503 (not 200) when not ready; body no longer leaks
  raw backend error text (api + web tiers)
- SYSTEM_MAINTENANCE now gates the web /api/* proxy (503 MAINTENANCE)
  instead of only hiding the SPA UI
- channel mutations invalidate messages/packets/packet_groups/dashboard
  caches so visibility/key changes apply immediately (was stale up to 1h)
- async DB engine: pool_size/max_overflow/pre_ping matching the sync
  engine (survives Postgres restarts); adispose() awaited from the API
  lifespan (async connections were leaked by the sync dispose)
- webhooks: permanent 4xx (except 408/429) fail fast instead of retrying;
  dispatch queue bounded at 1000 with drop-oldest + warning; shutdown
  logs dropped events; matches_event evaluated once
- SPA: apiGet/apiPostForm redirect to OIDC login on 401; chart date
  labels and route timestamps rendered in UTC/configured timezone
- e2e compose collector healthcheck uses 'meshcore-hub health collector'
  (image has no pgrep)
- docs/upgrading.md: fold unreleased notes into v0.18.0 and document the
  above
2026-08-29 22:40:19 +01:00
JingleManSweep d4cbfb63a4 Merge pull request #369 from ipnet-mesh/fix/correctness-bugs
fix: silent config drops, metrics event-loop stall, and route/decoder bugs
2026-08-29 22:13:04 +01:00
Louis King b23e7bcf15 fix: silent config drops, metrics event-loop stall, and route/decoder bugs
- api CLI single-process path now passes spam_detection_enabled /
  spam_score_threshold to create_app() so the messages hide-filter
  actually runs in the default (Docker) deployment
- OIDC role names (oidc_role_admin/operator/member/test) moved from
  WebSettings to CommonSettings and wired onto API app.state; the API
  tier previously matched hardcoded role names, ignoring customized
  OIDC_ROLE_* config in authz, channel visibility, and tag/adoption
  checks (oidc_roles_claim stays web-only)
- /metrics handler is now sync def so collection runs in the
  threadpool instead of blocking the event loop; hoisted fragile
  in-loop imports
- evaluate_route_history gates max_path_length on the packet's true
  hop count (RawPacket.path_len) instead of the prefix-filtered hop
  list, so history day buckets agree with snapshot evaluation
- reload_keys clears the decode cache: negatively-cached packets for
  a newly added channel key were permanently dropped by the normalizer

Also documents 'sudo npx playwright install-deps chromium' in the
AGENTS.md e2e setup.
2026-08-29 22:08:25 +01:00
JingleManSweep ee6e0c4894 Merge pull request #368 from ipnet-mesh/fix/security-hardening
fix(security): close fail-open defaults, header spoofing, and add CSP
2026-08-29 21:39:28 +01:00
Louis King dca3dcb309 fix(security): close fail-open defaults, header spoofing, and add CSP
- /map/data: resolve viewer OIDC session and apply the endpoint access
  mapping before fetching profiles; serve Cache-Control: private when
  OIDC is enabled (payload varies by viewer)
- /user/profile/me + /user/profile/{id}: trust X-User-Id only with a
  valid API key (new optional_user_identity dependency); closes the
  OIDC subject-identifier leak via forged headers
- OIDC_SESSION_SECRET is now mandatory when OIDC is enabled (hard fail,
  no insecure-dev-secret fallback)
- /metrics denies unauthenticated access when no API read key is set;
  new METRICS_PUBLIC opt-in (Settings, CLI, compose, env factory)
- CORS: unset CORS_ORIGINS keeps wildcard compat but drops
  allow_credentials (invalid combination in browsers) + warns
- Web tier: SecurityHeadersMiddleware (nosniff, X-Frame-Options DENY,
  Referrer-Policy, Permissions-Policy) + nonce-based CSP; nonce applied
  to spa.html inline scripts; WEB_SECURITY_HEADERS kill switch and
  WEB_CSP_EXTRA for custom tile hosts; API emits nosniff

Breaking changes documented in docs/upgrading.md.
2026-08-29 21:32:41 +01:00
JingleManSweep b751cf68b8 Merge pull request #367 from ipnet-mesh/fix/map-data-pagination
fix(web): paginate /map/data node and profile fetches
2026-08-29 13:33:20 +01:00
Louis King 9b6a16d862 fix(web): paginate /map/data node and profile fetches
The map endpoint fetched a single limit=500 page (the API's hard max,
sorted last_seen desc), so networks with more than 500 nodes silently
hid stale/offline nodes from the unfiltered map — including adopted
infrastructure, which still appeared under the adopted_by filter
because that filter narrows the query before the limit applies.

Follow offset/total pagination via a new _fetch_all_pages helper (40
pages / 20k nodes safety cap, partial results on later-page failure)
for both /api/v1/nodes and /api/v1/user/profiles, and report the
API-reported total in debug.total_nodes.
2026-08-29 13:01:16 +01:00
JingleManSweep c9d5e86953 Merge pull request #365 from ipnet-mesh/renovate/anomalyco-opencode-1.x
chore(deps): update anomalyco/opencode action to v1.18.25
2026-08-29 11:39:51 +01:00
JingleManSweep 95e99a2278 Merge pull request #363 from ipnet-mesh/renovate/tanstack-query-monorepo
chore(deps): update dependency @tanstack/react-query to v5.102.8
2026-08-29 11:36:09 +01:00
JingleManSweep 972898cff5 Merge branch 'main' into renovate/tanstack-query-monorepo 2026-08-29 11:33:38 +01:00
JingleManSweep 191ccd07d1 Merge pull request #357 from ipnet-mesh/renovate/leaflet-1.x-lockfile
chore(deps): update dependency @types/leaflet to v1.9.22
2026-08-29 11:33:23 +01:00
JingleManSweep b30f1231ec Merge pull request #355 from ipnet-mesh/renovate/vite-8.x-lockfile
chore(deps): update dependency vite to v8.2.2
2026-08-29 11:30:06 +01:00
JingleManSweep 2dd99f7f92 Merge pull request #364 from hardtofindg/hardtofindg-patch-1
docs: align README Python version
2026-08-29 11:26:30 +01:00
JingleManSweep 18cebeb5ea Merge branch 'main' into hardtofindg-patch-1 2026-08-29 11:19:42 +01:00
JingleManSweep 933ad756f2 Merge pull request #354 from ipnet-mesh/renovate/vitejs-plugin-react-6.x-lockfile
chore(deps): update dependency @vitejs/plugin-react to v6.1.1
2026-08-29 11:17:44 +01:00
JingleManSweep 806b378261 Merge pull request #358 from ipnet-mesh/renovate/testing-library-monorepo
chore(deps): update testing-library monorepo
2026-08-29 11:13:35 +01:00
JingleManSweep 1e871d5c51 Merge pull request #366 from ipnet-mesh/renovate/react-router-monorepo
chore(deps): update dependency react-router to v8.3.1
2026-08-29 11:10:01 +01:00
JingleManSweep b74855ee01 Merge branch 'main' into hardtofindg-patch-1 2026-08-29 11:07:18 +01:00
JingleManSweep 8400fc524f Merge pull request #353 from ipnet-mesh/renovate/jsdom-30.x
chore(deps): update dependency jsdom to v30
2026-08-29 11:06:27 +01:00
JingleManSweep ceb4f2be52 Merge branch 'main' into renovate/jsdom-30.x 2026-08-29 11:03:57 +01:00
JingleManSweep e3bb6752a3 Merge branch 'main' into hardtofindg-patch-1 2026-08-29 11:03:29 +01:00
JingleManSweep 604ff06cb9 Merge pull request #356 from ipnet-mesh/renovate/react-monorepo
chore(deps): update react monorepo to v19.2.18
2026-08-29 11:02:48 +01:00
JingleManSweep 2afffedaf0 Merge branch 'main' into hardtofindg-patch-1 2026-08-29 11:02:00 +01:00
JingleManSweep 1a082edbb8 Merge branch 'main' into renovate/jsdom-30.x 2026-08-29 10:57:18 +01:00
JingleManSweep 08f74f1522 Merge pull request #351 from ipnet-mesh/renovate/daisyui-5.x-lockfile
chore(deps): update dependency daisyui to v5.7.22
2026-08-29 10:57:02 +01:00
JingleManSweep 872cbedd6b Merge pull request #359 from ipnet-mesh/renovate/vitest-monorepo
chore(deps): update dependency vitest to v4.1.11
2026-08-26 00:04:01 +01:00
JingleManSweep e0e9c6e781 Merge branch 'main' into renovate/vitest-monorepo 2026-08-26 00:01:45 +01:00
JingleManSweep fcbd780105 Merge pull request #362 from ipnet-mesh/renovate/react-i18next-17.x-lockfile
chore(deps): update dependency react-i18next to v17.0.12
2026-08-25 23:59:12 +01:00
JingleManSweep df0a34a5c6 Merge branch 'main' into renovate/vitest-monorepo 2026-08-25 23:55:32 +01:00
JingleManSweep 8bbb38e554 Merge pull request #352 from ipnet-mesh/renovate/anomalyco-opencode-1.x
chore(deps): update anomalyco/opencode action to v1.18.23
2026-08-25 23:55:17 +01:00
JingleManSweep de62572dd2 Merge branch 'main' into renovate/vitest-monorepo 2026-08-25 23:52:41 +01:00
JingleManSweep 553b4060e9 Merge pull request #360 from ipnet-mesh/renovate/i18next-26.x-lockfile
chore(deps): update dependency i18next to v26.4.0
2026-08-25 23:51:25 +01:00
JingleManSweep b6e53c6cee Merge pull request #361 from ipnet-mesh/fix/mqtt-zombie-connection-hardening
fix(collector): survive broker dropping MQTT connections without FIN
2026-08-25 23:46:33 +01:00
Louis King 9913ffdecb fix(collector): survive broker dropping MQTT connections without FIN
The meshcore-mqtt-broker destroys subscriber connections (keep-alive
timeout) without sending FIN/RST, leaving a half-open socket that paho
never sees as disconnected: the collector stays "healthy" but silently
stops ingesting forever.

- Enable TCP keepalive (idle 60s / intvl 30s / count 3) on every
  connect, unwrapping paho's _WebsocketWrapper to reach the raw socket;
  kernel now fails zombie sockets so paho reconnects and resubscribes
- Verify SUBACKs via on_subscribe; log broker refusals (0x80) as ERROR
- Resubscribe with the registered QoS instead of paho's QoS 0 default
- Drop the optimistic _mqtt_connected flag; health now reports
  mqtt.is_connected, driven by real CONNACK/disconnect callbacks
2026-08-25 23:39:59 +01:00
JingleManSweep 9c1d3e5210 Merge pull request #349 from ipnet-mesh/renovate/daisyui-5.x-lockfile
chore(deps): update dependency daisyui to v5.7.3
2026-07-25 14:59:06 +01:00
JingleManSweep 10a38502eb Merge pull request #350 from ipnet-mesh/fix/dashboard-packet-retention-window
fix(dashboard): make packet displays retention-aware
2026-07-25 14:54:42 +01:00
Louis King 993ba7b5b6 docs: sync retention/evaluator defaults to #348 values
PR #348 changed several defaults but left a handful of docs, the
docker-compose fallback, example seed files, and code docstrings stale:

- docker-compose.yml: RAW_PACKET_RETENTION_DAYS fallback 7->2 (the
  :-7 override was the most consequential — operators without the env
  var set got 7 days, contradicting the code default and .env.example)
- docs/configuration.md: route-history backfill now references the
  300 s evaluator cadence (was 60 s)
- docs/seeding.md + example/seed/routes.yaml: window_hours 48/24 -> 6
  (matches the new default; both exceeded the 12 h max)
- routes.py docstring: evaluator tick 60 s -> 300 s
- subscriber.py: raw_packet_retention_days signature defaults 7 -> 2
  (overridden at runtime by effective_raw_packet_retention_days, but
  kept consistent with the authoritative config default)
2026-07-25 14:52:06 +01:00
Louis King 7802a00db3 fix(dashboard): make packet displays retention-aware
PR #348 lowered the RAW_PACKET_RETENTION_DAYS default 7->2, but the
dashboard packet count, activity chart, and breakdown chart still
advertised "Last 7 days" — a label that lied once only 2 days of data
remained. Make every raw-packet-derived window track the effective
retention so labels stay honest:

- get_dashboard_stats: packets_7d window = min(7, retention); expose
  packets_window_days on DashboardStats so the UI renders the real window
- packet-activity / packet-breakdown: clamp days = min(days, 90, retention)
  so responses never advertise days whose data has been purged
- Home StatCard + Dashboard chart subtitles: dynamic "Last N days" /
  "Per day (last N days)" via new time.last_n_days / time.per_day_last_n_days
  i18n keys ({{n}} interpolation, matching routes_over_last_n_days)
- ActivitySeries.days made optional (type shared across activity charts);
  PacketBreakdown.days added (backend always serializes it)

Messages/ads 7-day displays are unchanged — those draw on event data
which retains the full 30-day DATA_RETENTION_DAYS window.

Tests: autouse retention fixture (->90) on the three packet test classes
so existing days-handling tests stay valid; added retention-clamp tests
proving the window tracks retention=2 and relaxes to 7 at retention>=7.
2026-07-25 14:39:33 +01:00
JingleManSweep 153ba14ea0 Merge pull request #348 from ipnet-mesh/perf/route-evaluator-remediation
perf(routes): cut evaluator scan cost via window/retention/index/sweep
2026-07-25 13:21:30 +01:00