From e5756d7ab065475a18acdcafc008a767fcff87e0 Mon Sep 17 00:00:00 2001 From: Ivan Date: Wed, 22 Jul 2026 10:32:36 -0500 Subject: [PATCH] feat: various updates to filesync, ui, deps, add active sessions in about page and stuff related to new rns 1.4.0 --- CHANGELOG.md | 28 +- cogs/__init__.py | 0 cogs/basic.py | 18 + config/cogs/__init__.py | 0 docs/agents/README.md | 2 + docs/agents/conventions/backend.md | 1 + docs/agents/conventions/path-jail.md | 37 + docs/agents/conventions/tests.md | 1 + docs/agents/overview.md | 2 + docs/agents/skills/lxmf-messaging/SKILL.md | 32 +- .../agents/skills/path-jail-local-fs/SKILL.md | 118 + docs/en/messaging.md | 1 + electron/loading.html | 4 +- meshchatx.rsm | Bin 160505 -> 161752 bytes meshchatx/meshchat.py | 261 +- meshchatx/src/backend/active_sessions.py | 85 + meshchatx/src/backend/config_manager.py | 5 + .../src/backend/data/THIRD_PARTY_NOTICES.txt | 714 ++- .../src/backend/data/licenses_backend.json | 20 +- .../src/backend/data/licenses_frontend.json | 1046 ++--- meshchatx/src/backend/meshchat_utils.py | 89 + meshchatx/src/backend/rns_filesync_handler.py | 386 +- meshchatx/src/frontend/components/App.vue | 70 + .../frontend/components/about/AboutPage.vue | 268 +- .../filesync/FilesyncFileManager.vue | 294 ++ .../components/filesync/RnsFilesyncPage.vue | 68 +- .../components/settings/SettingsPage.vue | 20 + meshchatx/src/frontend/js/activeSessions.js | 28 + .../registries/coreSettingsSectionKeywords.js | 2 + meshchatx/src/frontend/locales/de.json | 32 +- meshchatx/src/frontend/locales/en.json | 28 +- meshchatx/src/frontend/locales/es.json | 32 +- meshchatx/src/frontend/locales/fi.json | 32 +- meshchatx/src/frontend/locales/fr.json | 32 +- meshchatx/src/frontend/locales/it.json | 32 +- meshchatx/src/frontend/locales/nl.json | 32 +- meshchatx/src/frontend/locales/ru.json | 32 +- meshchatx/src/frontend/locales/zh.json | 32 +- .../public/meshchatx-docs/en/messaging.md | 1 + package.json | 44 +- pnpm-lock.yaml | 4042 ++++++++--------- pnpm-workspace.yaml | 2 +- .../eect/packs/test_auth_surface_pack.py | 16 + tests/backend/fixtures/http_api_routes.json | 24 + tests/backend/http_api_response_registry.py | 9 + tests/backend/http_api_response_schemas.py | 13 + tests/backend/test_active_sessions.py | 304 ++ tests/backend/test_lxmf_cancel_api.py | 38 + tests/backend/test_lxmf_inbound_cancel.py | 66 + tests/backend/test_path_jail_oracles.py | 31 + tests/backend/test_rns_filesync_handler.py | 80 + tests/backend/test_rns_filesync_security.py | 160 +- tests/e2e/acceptance-settings-privacy.spec.js | 3 + tests/e2e/api.spec.js | 21 + tests/e2e/smoke.spec.js | 19 + tests/frontend/AboutPage.test.js | 184 +- tests/frontend/AppMultiSessionWarning.test.js | 76 + tests/frontend/RnsFilesyncPage.test.js | 93 + tests/frontend/activeSessions.test.js | 39 + vendor/README.txt | 4 +- vendor/lxmfy/CHANGELOG.md | 39 + vendor/lxmfy/CONTRIBUTING.md | 42 - vendor/lxmfy/README.md | 33 +- vendor/lxmfy/TODO.md | 4 - vendor/lxmfy/docs/source/api-reference.rst | 99 +- vendor/lxmfy/docs/source/creating-bots.rst | 90 + vendor/lxmfy/docs/source/quick-start.rst | 10 +- vendor/lxmfy/lxmfy/__init__.py | 22 + vendor/lxmfy/lxmfy/__version__.py | 4 +- vendor/lxmfy/lxmfy/cli.py | 31 +- vendor/lxmfy/lxmfy/config.py | 16 +- vendor/lxmfy/lxmfy/core.py | 339 +- vendor/lxmfy/lxmfy/reticulum_config.py | 141 + vendor/lxmfy/lxmfy/rrc/__init__.py | 70 + vendor/lxmfy/lxmfy/rrc/client.py | 1110 +++++ vendor/lxmfy/lxmfy/rrc/constants.py | 92 + vendor/lxmfy/lxmfy/rrc/envelope.py | 149 + vendor/lxmfy/lxmfy/rrc/manager.py | 275 ++ vendor/lxmfy/lxmfy/templates/__init__.py | 3 +- vendor/lxmfy/lxmfy/templates/rrc_bot.py | 79 + vendor/lxmfy/poetry.lock | 67 +- vendor/lxmfy/pyproject.toml | 9 +- vendor/lxmfy/tests/pytest.ini | 6 +- vendor/lxmfy/tests/test_cli.py | 2 +- vendor/lxmfy/tests/test_integration.py | 4 +- vendor/lxmfy/tests/test_live_lxmf.py | 416 ++ vendor/lxmfy/tests/test_memory_guards.py | 129 + .../lxmfy/tests/test_message_persistence.py | 143 + vendor/lxmfy/tests/test_reticulum_config.py | 250 + vendor/lxmfy/tests/test_rrc.py | 587 +++ vendor/lxmfy/tests/test_rrc_live.py | 238 + vendor/lxmfy/uv.lock | 265 ++ 92 files changed, 10075 insertions(+), 3842 deletions(-) create mode 100644 cogs/__init__.py create mode 100644 cogs/basic.py create mode 100644 config/cogs/__init__.py create mode 100644 docs/agents/conventions/path-jail.md create mode 100644 docs/agents/skills/path-jail-local-fs/SKILL.md create mode 100644 meshchatx/src/backend/active_sessions.py create mode 100644 meshchatx/src/frontend/components/filesync/FilesyncFileManager.vue create mode 100644 meshchatx/src/frontend/js/activeSessions.js create mode 100644 tests/backend/test_active_sessions.py create mode 100644 tests/backend/test_lxmf_inbound_cancel.py create mode 100644 tests/frontend/AppMultiSessionWarning.test.js create mode 100644 tests/frontend/activeSessions.test.js delete mode 100644 vendor/lxmfy/CONTRIBUTING.md delete mode 100644 vendor/lxmfy/TODO.md create mode 100644 vendor/lxmfy/lxmfy/reticulum_config.py create mode 100644 vendor/lxmfy/lxmfy/rrc/__init__.py create mode 100644 vendor/lxmfy/lxmfy/rrc/client.py create mode 100644 vendor/lxmfy/lxmfy/rrc/constants.py create mode 100644 vendor/lxmfy/lxmfy/rrc/envelope.py create mode 100644 vendor/lxmfy/lxmfy/rrc/manager.py create mode 100644 vendor/lxmfy/lxmfy/templates/rrc_bot.py create mode 100644 vendor/lxmfy/tests/test_live_lxmf.py create mode 100644 vendor/lxmfy/tests/test_memory_guards.py create mode 100644 vendor/lxmfy/tests/test_message_persistence.py create mode 100644 vendor/lxmfy/tests/test_reticulum_config.py create mode 100644 vendor/lxmfy/tests/test_rrc.py create mode 100644 vendor/lxmfy/tests/test_rrc_live.py create mode 100644 vendor/lxmfy/uv.lock diff --git a/CHANGELOG.md b/CHANGELOG.md index 24ff5abb..e6fb188e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,17 +10,27 @@ All notable changes to this project will be documented in this file. - Bundled Bug Reports plugin and plugin i18n / UI slots / contribution registries - Map overlays from NomadNet and RNGit (KMZ/KML/GeoJSON) with cache and refresh - RNS Link WebSocket API for external apps (and plugin capabilities) +- RNS File Sync for shared folders on the mesh, with an in-app file manager to browse, upload, download, and delete files in the sync folder - Settings: Reticulum instance/share controls, tabbed Settings nav, desktop close/tray behavior - Nomad favourites: per-identity section layout in the database - Optional pip-rns / rngit install path for RNS packages and docs - Message export and import with contacts and read state +- Message maintenance in Settings: purge old local messages and clear duplicates - Host battery status on About and in the header (Electron, Android, Chromium) -- RSM signing and verification for meshchatx.rsm (CI and pre-commit resign) +- System resource monitoring for CPU and memory in the UI +- RSM signing and verification for meshchatx.rsm - Notification sound settings -- LXMFy 1.6.5 vendor refresh, wasmtime, mutation test tasks +- LXMFy 2.0.1 vendor refresh with RRC hub client support for bots, plus wasmtime - Network visualiser WebGL + WASM renderer (vis-network fallback) and Settings renderer preference - Interfaces: internal mode, recursive path requests, announces-from-internal, discovery location command, and Backbone fast-flapping options (RNS 1.3.7 to 1.3.9) -- Dependencies: **RNS** 1.4.0 and **LXMF** 1.1.0, with local propagation node controls for sequential stamp validation, static-peer bypass, max inbound syncs, transfer size reporting, and inbound delivery cancel +- Reticulum interface module management from the UI +- Reticulum 1.4.0 and LXMF 1.1.0, with propagation node options and cancel for incoming large message downloads from the header +- Relay Chat room keys so hosts can require a key to join a room +- Desktop privacy: Windows screen security to omit MeshChatX from screenshots, recording, and Recall +- Android privacy options to block screenshots and clear the clipboard when backgrounded +- Remote management allow-list for identities that may query this instance with rnstatus/rnpath +- Post-install prompts for existing users after upgrades +- Coolify-oriented Docker Compose with resource limits for deployments ### Changed @@ -30,20 +40,19 @@ All notable changes to this project will be documented in this file. - Conversation list API omits contact image blobs and caps unbounded callers (Map, Network Visualiser) - Messages page conversation poll is slower and skips while the tab is hidden - Schema v51 message-flag backfill skips empty databases so fresh init stays fast +- Outbound message status icons and titles reflect delivery method and state more clearly - Relay Chat: denser hub UI, announce interval, collapsed system lines, reconnect notices - Relay Chat: clickable Nomad and LXMF links plus basic markdown for code, bold, italic, and strikethrough - Low-memory cleanup and SQLite pragmas under memory pressure -- CI benches use median-of-medians and quieter regression gates -- Backend benchmarks cover slim conversation list, mark-as-read, call history, and missed-call notification paths -- Benchmark gate fails when a full-suite run drops required benches or loses coverage vs baseline -- Backend tests can run sharded in CI +- Auto-resend keeps attachments and cleans duplicate outbound rows more reliably +- Calls and audio work in Docker and headless setups via hostless LXST backends and the web audio bridge +- Hardened identity path handling, stamp enforcement, plugin integrity, Nomad downloads, and local file path jails - Plugin strings live in plugin bundles, not main locale files - Docker frontend build installs Go, builds visualiser WASM, and fails if WASM artifacts are missing ### Fixed -- SLSA provenance jobs compile the generic generator from source so attest no longer fails with a missing slsa-generator-generic-linux-amd64 binary -- Android: lxmfy packaging, flock soft-lock, splash/logo clipping, emulator smoke, Landlock skipped on Android +- Android: lxmfy packaging, flock soft-lock, splash/logo clipping, Landlock skipped on Android - Android RNode BLE/USB via Chaquopy - Startup check and disable unsupported interfaces - Nomad favourites: no more Unknown Node / lost custom sections @@ -51,7 +60,6 @@ All notable changes to this project will be documented in this file. - Bots and RNSh work in frozen macOS/Windows builds - Sensitive config no longer mutable over WebSocket. Reticulum config repair on startup - Paper message URI encoding for non-ASCII title and content -- Nightly releases and broader self-test / CI coverage - LXMA contact import works with current RNS public-key loading and remembers the peer key before announce - Android calls: overlay accept opens the phone tab so native audio attaches. Web-audio no longer permanently disabled after a bridge error - Android Codec2: reliable libcodec2 preload, Gradle fails without Codec2 wheels or jniLibs, and unavailable Codec2 profiles are hidden diff --git a/cogs/__init__.py b/cogs/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/cogs/basic.py b/cogs/basic.py new file mode 100644 index 00000000..3895f4ae --- /dev/null +++ b/cogs/basic.py @@ -0,0 +1,18 @@ +from lxmfy import Command + + +class BasicCommands: + def __init__(self, bot): + self.bot = bot + + @Command(name="hello", description="Says hello") + async def hello(self, ctx): + ctx.reply(f"Hello {ctx.sender}!") + + @Command(name="about", description="About this bot") + async def about(self, ctx): + ctx.reply("I'm a bot created with LXMFy!") + + +def setup(bot): + bot.add_cog(BasicCommands(bot)) diff --git a/config/cogs/__init__.py b/config/cogs/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/docs/agents/README.md b/docs/agents/README.md index cd13fe4f..d034ba61 100644 --- a/docs/agents/README.md +++ b/docs/agents/README.md @@ -26,6 +26,7 @@ Optional editor rules (if present under `.cursor/rules/` or similar): | [conventions/core.md](conventions/core.md) | Always-on standards | | [conventions/frontend.md](conventions/frontend.md) | Vue UI | | [conventions/backend.md](conventions/backend.md) | Python / HTTP / SQLite | +| [conventions/path-jail.md](conventions/path-jail.md) | Local FS APIs: jail, symlinks, tests | | [conventions/android.md](conventions/android.md) | Android WebView bridge | | [conventions/tests.md](conventions/tests.md) | Test placement, oracles, verification | @@ -62,6 +63,7 @@ Optional editor rules (if present under `.cursor/rules/` or similar): | Skill | Use when | | ------------------------------------------------------------------ | ------------------------------------------- | | [auth-csrf-ws-security](skills/auth-csrf-ws-security/SKILL.md) | CSRF, auth, WS mutator denylist | +| [path-jail-local-fs](skills/path-jail-local-fs/SKILL.md) | Local file browse/upload/delete path jails | | [plugin-install-security](skills/plugin-install-security/SKILL.md) | Plugin install, RSG, permissions, integrity | ### Platforms and boot diff --git a/docs/agents/conventions/backend.md b/docs/agents/conventions/backend.md index e728ecd1..15e0ef89 100644 --- a/docs/agents/conventions/backend.md +++ b/docs/agents/conventions/backend.md @@ -11,3 +11,4 @@ Applies when editing `meshchatx/**/*.py`. - Identity restore validates size and empty payloads. Preserve existing identity metadata on re-import. - No backticks in code comments. Prefer plain words or quoted identifiers. - RRC / LXMF / LXST changes: open the matching skill under `docs/agents/skills/` and run oracle-style tests when behaviour changes. +- Local filesystem browse/upload/download/delete: follow `docs/agents/conventions/path-jail.md` and `docs/agents/skills/path-jail-local-fs/SKILL.md`. diff --git a/docs/agents/conventions/path-jail.md b/docs/agents/conventions/path-jail.md new file mode 100644 index 00000000..95d09cdf --- /dev/null +++ b/docs/agents/conventions/path-jail.md @@ -0,0 +1,37 @@ +# Path jail for local filesystem APIs + +Applies when adding or changing HTTP or handler code that lists, reads, writes, uploads, downloads, or deletes files under identity storage or a feature root. + +## Default threat model + +Treat MeshChatX local API access (UI session, shared host, scripted client) as already compromised for the purpose of path checks. The attacker must still fail to: + +- Escape the feature root with `../`, absolute paths, null bytes, or Windows separators +- Reach sibling identity storage or host paths outside the active identity +- Touch reserved tops (`identity`, `lxmf`, `database.db`, bots, plugins, backups, keys) +- Follow symlinks that point outside the jail +- Exfil via download or content endpoints that skip the same resolve helper +- Upload filenames that smuggle path segments or reserved sidecars + +## Hard rules + +1. One dedicated resolve helper per feature root (example: sync-root only for FileSync manager). Do not reuse a looser picker jail for CRUD. +2. Normalize then `realpath`. Success paths must equal the root or start with `root + sep`. +3. Fail closed: generic error, HTTP 400 for bad input, never 500 for jail rejects. +4. Upload: sanitize to basename only. Join under a resolved parent. Cap size. +5. Delete: refuse the root itself. Default to file or empty directory only unless recursive delete is explicit and tested. +6. Skip and refuse mutation of dotfiles and protocol sidecars (for FileSync: `.rns-filesync*`, `.rns-xfer*`). +7. Mutating routes stay CSRF-protected HTTP via `window.api`. No WS mutators for file CRUD. +8. Keep identity-scoped state. Never browse or mutate another identity storage path. + +## Tests required + +- Adversarial traversal and absolute-path cases with bait files that must survive +- Cross-identity bait directory in the same test +- Symlink-out cases (POSIX) for list, read, write, delete +- Oracle or Hypothesis: accept only when resolved path stays under the root +- Frontend mutators go through `window.api` (apiFetchGuard stays green) + +Full workflow: `docs/agents/skills/path-jail-local-fs/SKILL.md`. +Reference implementation: `meshchatx/src/backend/rns_filesync_handler.py` (`_resolve_manager_path` and manager APIs). +Oracle examples: `tests/backend/test_rns_filesync_security.py`, `tests/backend/test_path_jail_oracles.py`. diff --git a/docs/agents/conventions/tests.md b/docs/agents/conventions/tests.md index 170ec1c5..098de001 100644 --- a/docs/agents/conventions/tests.md +++ b/docs/agents/conventions/tests.md @@ -28,6 +28,7 @@ Prefer: - Round-trip or shape invariants when the API is pure parsing Full skill: `docs/agents/skills/test-oracles/SKILL.md`. +Path jail filesystem features: `docs/agents/skills/path-jail-local-fs/SKILL.md` and `docs/agents/conventions/path-jail.md`. Exploratory bug hunting: `docs/agents/skills/exploratory-testing/SKILL.md`. ## Extended Edge Case Tester (EECT) and Live Validation (LV) diff --git a/docs/agents/overview.md b/docs/agents/overview.md index 484ba98c..78414366 100644 --- a/docs/agents/overview.md +++ b/docs/agents/overview.md @@ -205,6 +205,8 @@ Prefer bind `127.0.0.1`, HTTPS, and auth if other local users share the host. Sensitive config changes (for example auth enable / password hash) must use CSRF-protected HTTP endpoints, not unrestricted WebSocket mutators. +Local filesystem browse/upload/download/delete APIs must path-jail to a feature or identity root. See `docs/agents/conventions/path-jail.md` and `docs/agents/skills/path-jail-local-fs/SKILL.md`. + Password reset: `--reset-password` or `MESHCHAT_RESET_PASSWORD=true` clears the stored hash so a new password can be set in the UI. ### Plugins diff --git a/docs/agents/skills/lxmf-messaging/SKILL.md b/docs/agents/skills/lxmf-messaging/SKILL.md index ecc9b1a6..0cbf7133 100644 --- a/docs/agents/skills/lxmf-messaging/SKILL.md +++ b/docs/agents/skills/lxmf-messaging/SKILL.md @@ -15,13 +15,31 @@ LXMF is store-and-forward mail on Reticulum. Do not require clearnet, DNS, or a ## Key paths -| Area | Path | -| ------------------------ | --------------------------------------------------------- | -| Identity / router wiring | `meshchatx/src/backend/identity_context.py` | -| Message handler | `meshchatx/src/backend/message_handler.py` (and related) | -| HTTP/WS surface | `meshchatx/meshchat.py` | -| Frontend conversations | `meshchatx/src/frontend/components/` conversation viewers | -| Config | config managers / settings UI for LXMF options | +| Area | Path | +| ------------------------ | -------------------------------------------------------------------------------------------------- | +| Identity / router wiring | `meshchatx/src/backend/identity_context.py` | +| Message handler | `meshchatx/src/backend/message_handler.py` (and related) | +| HTTP/WS surface | `meshchatx/meshchat.py` | +| Inbound cancel helpers | `meshchatx/src/backend/meshchat_utils.py` (`list_inbound_deliveries`, `cancel_inbound_deliveries`) | +| Frontend conversations | `meshchatx/src/frontend/components/` conversation viewers | +| Config | config managers / settings UI for LXMF options | + +## LXMF 1.1 / RNS 1.4 inbound cancel + +Large inbound LXMF deliveries use RNS Resources. LXMF exposes: + +- `LXMRouter.inbound_resources()` / `inbound_count()` +- `cancel_inbound(resource_hash)` and `cancel_all_inbound()` + +MeshChatX surfaces them as: + +- Status: `inbound_delivery_count` and `inbound_deliveries` on `/api/v1/lxmf/propagation-node/status` +- Cancel: `POST /api/v1/lxmf/propagation-node/cancel-inbound` with optional `{ "resource_hash": "..." }` +- Header UI in `App.vue` when active inbound transfers exist + +Outbound cancel remains `POST /api/v1/lxmf-messages/{hash}/cancel` via `cancel_outbound`. + +Keep minimum versions: `rns>=1.4.0`, `lxmf>=1.1.0`. ## Gates diff --git a/docs/agents/skills/path-jail-local-fs/SKILL.md b/docs/agents/skills/path-jail-local-fs/SKILL.md new file mode 100644 index 00000000..1ac5765a --- /dev/null +++ b/docs/agents/skills/path-jail-local-fs/SKILL.md @@ -0,0 +1,118 @@ +# Skill: path-jail-local-fs + +Add or change local filesystem features (browse, upload, download, mkdir, delete) with a hard path jail, CSRF-safe mutators, and oracle-style tests. Do not ship file CRUD that can escape identity or feature roots. + +## When to use + +- New in-app file managers, uploads, downloads, or directory browsers +- Extending FileSync, RNCP, page-nodes files, docs packs, repo wheels, or similar storage APIs +- Any handler that takes a client path or multipart filename and touches disk +- Security review of existing list/read/write/delete file endpoints + +Also read: + +- `docs/agents/conventions/path-jail.md` +- `docs/agents/skills/auth-csrf-ws-security/SKILL.md` +- `docs/agents/skills/test-oracles/SKILL.md` +- `docs/agents/skills/page-toast-tests/SKILL.md` when adding UI + +## Threat model (assume without asking) + +Caller already has MeshChatX HTTP API access. They must not list, read, write, or delete outside the configured feature root. That includes host home dirs, `/etc`, other identities, and reserved identity-storage tops. + +You do not need the user to restate path jail, symlink policy, CSRF, or bait-file tests. Apply them by default. + +## Workflow + +### 1) Choose the jail root + +Pick the tightest correct root for the feature: + +| Feature shape | Jail root | +| -------------------------------------- | --------------------------------------------- | +| FileSync in-app manager | Configured `sync_directory` only | +| Folder picker for choosing a sync root | Identity storage with reserved tops blocked | +| RNCP received / shared | That feature directory under identity storage | +| Page-node files | That node file directory | + +Never use a looser picker jail for tree/upload/delete/content of a tighter feature. + +### 2) One resolve helper + +Add something like `_resolve__path(...)` that: + +1. Takes relative client paths only (reject absolute / drive / UNC / null bytes) +2. Uses vendor or shared normalize helpers when available (`normalize_relpath`, `resolve_under_root`) +3. Rejects forbidden names (dotfiles, protocol sidecars) +4. `realpath` membership: equal root or `root + sep` prefix +5. Symlinks: after realpath still inside root. Prefer rejecting symlink entries for write/delete/content +6. Returns fail-closed errors with generic messages (no out-of-jail path reflection) + +Reference: `RnsFilesyncHandler._resolve_manager_path` in `meshchatx/src/backend/rns_filesync_handler.py`. + +### 3) Wire APIs + +Typical surface: + +| Method | Role | +| ------------- | --------------------------------------------------------------------------------- | +| GET tree/list | Browse under jail (works even if a mesh service is stopped when state is on disk) | +| POST mkdir | Relative path under jail | +| POST upload | Multipart. Optional subdir. Basename only. Size cap | +| DELETE entry | File or empty dir by default | +| GET content | Stream only after jail pass | + +HTTP: 400 on jail failure / bad input. Register routes in `tests/backend/fixtures/http_api_routes.json`. Add JSON GET contracts or exclude binary download routes in `http_api_response_registry.py`. Add mutating samples to EECT auth surface when relevant. + +### 4) Frontend + +- Relative paths only in the UI. Never send host absolute paths for CRUD. +- Mutators via `window.api` / FormData so CSRF attaches. +- Confirm before delete. Toasts via `ToastUtils`. User strings via i18n. +- Keep OS "open folder" as optional convenience, not the only management path. + +### 5) Mandatory tests + +Extend or add: + +- Happy-path CRUD under the root (including stopped-service disk CRUD when applicable) +- `_TRAVERSAL_PAYLOADS`-style rejects for tree, content, delete, mkdir, upload subdir +- Absolute path to bait file outside storage (must survive) +- Reserved tops under identity storage +- Second identity storage bait in the same test +- Symlink inside root pointing outside (list/read/write/delete fail closed) +- Upload basename sanitization (path segments stripped or rejected, never escape) +- Hypothesis or explicit oracle: accept only when resolved path stays under root +- Frontend: mock `window.api`, assert upload/delete calls and toasts + +Soft fuzz that only checks "did not crash" is not enough. See `test-oracles`. + +## Stupid crap to refuse + +- Reusing identity-storage browse APIs as the file-manager base for a tighter root +- Trusting `Content-Disposition` or multipart filenames as full save paths +- Recursive delete of arbitrary trees without an explicit, tested flag +- New WebSocket mutators for file upload/delete +- Logging full absolute paths of failed escapes into user-visible errors +- Cross-identity caches or shared temp dirs for uploads + +## Verification + +```bash +task test:filesync:security +uv run pytest tests/backend/test_path_jail_oracles.py -q --tb=short +pnpm exec vitest run tests/frontend/apiFetchGuard.test.js +``` + +Adjust pytest and vitest paths to the feature you touched. Prefer `task` targets when they exist. + +## Finish gate + +Do not ship until all are true: + +1. Every list/read/write/delete/upload goes through the feature resolve helper +2. Escape payloads never read or delete bait files outside the root +3. Symlink-out and cross-identity cases fail closed with tests +4. Oracle or Hypothesis coverage exists for the resolve helper +5. Mutators are CSRF HTTP via `window.api` +6. Route fixture / JSON contract registry updated when routes change diff --git a/docs/en/messaging.md b/docs/en/messaging.md index 64bd5054..9a8df6c0 100644 --- a/docs/en/messaging.md +++ b/docs/en/messaging.md @@ -105,6 +105,7 @@ WebSocket lxmf_message event on recipient UI - Enable **auto-announce** so your `lxmf.delivery` aspect stays visible on the mesh. - Check **Interfaces** if messages stall. No path to the peer means LXMF cannot deliver. - Review stamp settings before joining busy public meshes. +- While a large message is downloading, the header shows **Cancel incoming**. That stops active LXMF delivery resource transfers (`cancel_all_inbound` / per-resource cancel). Outbound send cancel stays on each message menu. ## See also diff --git a/electron/loading.html b/electron/loading.html index 3aae7aa8..ff9ba902 100644 --- a/electron/loading.html +++ b/electron/loading.html @@ -33,9 +33,7 @@ class="overflow-hidden rounded-2xl border border-slate-200/80 bg-white/90 shadow-lg shadow-slate-200/50 backdrop-blur-sm dark:border-zinc-700/80 dark:bg-zinc-900/90 dark:shadow-black/40" >
-
+

MeshChatX

diff --git a/meshchatx.rsm b/meshchatx.rsm index a84ea4e34a9466968a52ac619bc5618198b13598..910da8dd69886c4efced5bd2f9930ada5e48e893 100644 GIT binary patch delta 4540 zcmbuDeXQPPdB^iRfNenws6c5&Pt8!7w!Pn9>g0KXOMO8wjSid{9PZb8v^}joEwK_{ zNVY_YG0n5^#E=-l7+s8HMn#IZkSjPIHn4Ss$-Rippgj^%H^ z;>ZUtd*jEyar&PgzH#S||NoksZe82;Z~t)X!{(;9{^`oWKYQ!xcdako{+&m@d*4OV z5Sy)96ctR$(PU+vPfd%QWVF$w;7rjy>gb)1-B;6HNxnuYyA`gdjYpq-$u;wz-#c7) zOF4RIec#H;>e}jwm6g56PF<+2(aoo%o%gOOp32!pFQT=rn3#m>xtm^;bV&;#Y78w% zQB_s0mr$3N&mNi6`f8c~^xomX73Jt!Up=(%_usVfFZN@@)LCOit4*d-Y-&+h8KiO| z^P?{LRgun^EJQF`8R3Q2N!R9;6-CGHW)J&2r(O6Yz3eL36s;;=blrQ7u6ko)tS#%R zl(zIkSQl*fE-9Upt+~1&mQK8F&)d`L;n|zx(MhP?NgH*usypsPFJm{_m7a8pP8VMo zOGsTfFGZBv#jK6eK0A|>nSCYfnq9Sj+eBq;Rdk67@>*Yv6v^q{Qgx1L6=S_0Z>yu^ zN3~Zkg7Pv-FNzd)qwW9O^QWE*d+n^Jv)Nl6v=Tw6Vk7gFInYGe3|KNg;n1Ao!Q^cUKBSpx%R(p&k zg%Xu)Ue+3YuTIp|z>t^D_MpP@^89D79B$sY>OkE(ZK?5Y%eb_Rs(Ih7<6<#H({ive z+b&fLO`8hrOjNM|`>X}%^G2JEFWmSSTc)y!&fqK^_t_)|>6{I8DYz7qbRBjiKFbhu zRKbgJ>cG|rS6vBdhm>;*}}% zpadCa2j6n#_HttN_O`O#*4I~$uB~r8aPud&OhqwS@{J-xlL9bw!&yOQP=-iUN|#FO zPWK!w)W+#1K$S|lbYCDhz%s@aj-J}?ykzjbKEOnmPU7lJ3HJlIc(zF8MXtr8}*WRV?6W@JZ8 zY>fTfL64EdQJ^~))uPr5e#OTL|0Zf#I6?EQ)JNS!z|r# z<;I=wKX3cBp^8vwPZmYgRuoF8tIRyDs;x-|A-(cWW{JYN0zqSmBG7a#YnknS;w2mZ z`@na$PI*w&>@=$EVl^iCZos%yL7G-MVnk*QS(+Y?O z{7MzM^-*sWMa$s>fi&^^no%17?4BHofxqaBZW2)s?WNFucKDCSQA^S>AwEQAec{G&`A)kr*cnQsaS4D5wX$ML(OR zlewV0De>aj!3Q@Fd~I9bJP?=&k1EwjpRun-6hOcbIHxtn9vgs9y<>erI?1@QpqId+ zQEJlTJ$KJv^|E2>)Q-*+J8fcy-Uz%fIgf1#kk<`@)qxy$&A~L=B#8mt@8d_5qHiAc zntptnUIhg*(&HyLFN%T{SC9hSp3vfnR7$8Q zu)5$xX_@#Hz#*j}4;n7FhCh3hkp{W>?mg!&x_JE`53jzIc=HFD{p_ia@0@?&<-?Zw zZTpAkE}nViFyB74-d5{dN_ngyc%4ZQMq}#GR_B1UXasG>5PZ{O+l|AM zd#8kRtfg~JXGS5xCJ>zl`Oi~omUm8S3^5)mxGhDfN=I-J8r72qg z38&-1p5Fq3EHY+8pn><*5ch-2J|T8uWSnqx{*m_#mrbR@h6OmS zBe};!fd7pIC1GaHE|G8!;dDUJiY_1wca5F^kwUHd>`{wL?;Q@EHvy+aI!4ZP(pU({ zP(4(XOAxg^u)yUV;%XI?!q9ym?=PbclrjI>Y`Fa5O%eZ1?pmDq>tX-Ci6yx=bi_H- z1>_UDJqrvXz)6Tll?v7oP&2B`){%(bs441%id8#5c>i$u{QHj%7c91ZYIy0=gj9gX zu*INBik!qo0+3Q-(UPhcp%^$WsWl6a30+}=)ZQG_mh%WM#}Ck%RyP7Kq`99v}wGEUBGT%l50o{GLy4p7fl> z)!!O^@Pesg0k*ko;%`Wx2*TFl&u)WRCstd-i>$+Dh^@uKI!r2IaDnVaIGW#dW)M>X zc+K=6zdt~eViQ5LrFr7D#A&dWl-a<77A%MaE#k_UiAr1i^O@nxOHh)_zWix!e$NF<&wt(xCl8-kJr`$gPRG|)*A6X?K5OaJ-f3l1 zAowzC_Kj3KI}0L4!mAiFYa{DY?3#U^j|dODSRHkR#^dHhw#Ccr(nH%`MJu}Tpc@M| z;7XcYJo|Lve*lQ{9yKCOXyTrr@Wi}}smznK>+1aAfu-kP{=1oL?}@g40{>e4>$OY5 F{0cqSN>~5@ delta 3646 zcmbuC>95>n702_tfbDH7TLZQ%S_qJU(mwlwgqeV*CK!cxic5G_qm)wHx}ai<3W<`4 z&5#ZT1tTgDqR5`u4tHoR~l2JkcY>R(`T)7zQ*%=ta%obNV& zI=1}U%gf_Oe)x}l_x}6If4+3LJa=~Ff;)CR`pl-s&fB;D&?%oieCM6}*Ic>$ktZH` z^0uY#o`3C|5B=tvU#&l4@BjV5!+#&0ebyVVymr!w2gaMWoPGH-w_bkXPhP$BTU%ec z={t|#f9#689y{sjXTEvW7e4;fb9deL?19hkS=znf&|hy`KX%rX9Ayzssib_g*%cLK zttClqLzOa`;8d?p>85-SB_@@G$*s#!yr2Di!^s!U9&q2qXXJ>(|L3$E=rqqc1bOYy>D;Zvv<$d>+8Chr8JIHm5F6leDbF2rlpd)o0xSe z!8;`lo%U{pbh*i*4fkv+``Huke&F~K4TKoFYAOi9@gQBz-6k6phXY-9*GdSjcjroz z)tKV5>8jQ&gq$53e`%QAefckr9|vihOf6MqiipzqqOCB=S!=AW$wlSpU;2=3HPt0< zQe+OkMP5Z4XW!m_WbN3C9%}6=Yn`pL+)7!Wq)p9xqpTFN+2p+p(M3_%3`=KnqS|H| zNSz(L>Z5DMrdAQP>_Vmrn6&ZP%HC=#wlf4{RTf1VRaCVuyQ);k!E#dp1e)kG^`Xm$ z*$W@OZ_UVcK;yfwMtdp6q7QDx%8G9-tL6mfV=ca?)U!`5YDV95_uAE3C+B=|^W^!o zdt|Fu^xC6yfkCL67>3PO8QGa-7oNRak#qA6tP9_qbV8+KlT1!eZr;6lva6pk`EkB| z)acY$xKLwL+6NP~ZQeNNy$*C!OHl!Y@&X8CClyeuqM7PVb9pk{xms&OU4DN~<+`@B zZvE7r8+NWsifh!ItBJ}(8UPQNe9K@wixj~GsLyQDyPRNAj;5r-E@JS?{_m2r4fUln z#|yB)Dcw2MbODsQD;Y+ouCF8LUckiah)Z>wTKO-!ynxOsNu_Tx?*gJ!tym9SQM zcBZ9sIW9;otx%x@m@cC2!HJx-SE>f9h16U;16MJ5`q$^p&b#}SwIj#dUCN$x6iru9 z#ki~xqT3)tWeeS9Enr)AzPl<)Ih0jc7__`phM@5L87P zdd$`)$QUBEBKOQjSON8F(v2siZj$QIH|U9+ojY9Y)yJ5+n8?4KJ>7EJuzo%}WjJTk z$n)?nT0ygc2;5TANx^JTWNQo@2(d*Vo58Y)O?p^UO!m^ENP6<(u`{M`UNo%TUfU{m zA#>;pNGV^M*FDRH@Z%l5D+~K|?^#PqOQhFC55-avEhVUujGCm!R|+mq@40ALGpZ?I zGfH$(d8&*Qx7bGLK}GMq5a?iA*pN{nqCl3l%8JezDYWpDa~@o&cJgHjy0hMf1}D`* z?!dPP7?CiyivQ4+FD_`kP$*|mHP7k2?yr8 z4hiuAi=ahGh3R1&&1luxThdk+u(De4y`S8>S}%_ z2cprW+LAyTOrLIf*KqFk-Je-4);yz%45^f?qXnCl)jEe$Dm)ne=Y^0puoAM=I-;3n zMFlIqohAqFU2S%L)5XITr;Pqj$6G1)z45Sla_{yJPVd+}yluL8H9s^OHl0Wil8`H5 zS{==-Q1%TcN0*S%M-eaa`Q{C9-iAeHaLO|*_VvQ@&Q+Q ztZY4D8T@VGpf-58RZ6eIHWnlBXtbK{Z7~PGJe)Rt>Spxh#{I*!OXGmjHXOHiY@%5# zQACDi65+!|-$;{4p;2fJ!{{D`Mtc;h&VZEa(@%em*{iP(S1yeg?=%d}kguApL3Bet z!~tA3@F7)`Xn7&e#5Ht@aXXeEARDi9onCdzuzC8&TZYrdt_!rC&S{?`wFYz~7fmzX z*OWml4#x9rssedcfR5>tf`KPGwNh&So?C}c95>(ijlpdj2bSeSsghzI36P8A5f=Iq zJ$EKl5N>3l^-`f|hzU#O@}1O`2rAQ8A05t||KQQ#f~C1TJlwi*tTXcmIq=67WTS^J z@I|~6;fxu>Ah7y`b}i^Y;&!?h($d2BOfYtO=;`6~`KeD0S7Ozw%2+|pB8?IhP&U+` zd~NWeiZ3z5K)vV*BVNN|F9?LNtzmY4dT2JBK7Gg0;jPnOzA&sGIdB$~j4LV{y(MvI z1=ORV!&Y>0uvT@TCi$sAkx-^Z<6qDhR?5vO_r_Ucc7x7BE2O<;VcANQ89`~d1o}VCXAY<>X*%Ao) zx%6a=#)`0+w#e}F-@ZQlZfVS;5j9b;e7+MH#5QG~LUf}A^bC1Vizt@~1%^3h%~t^C zO89XIaQ^9^mtH<$T!bZ@3DC>^RCOJ0sKl)csR1V;#iMbAUY(ed(1;kB0iuw46Jhjc zYnJvMH$S#+Y1h`v&{7nH87a5ey2qW7ah!|c;AsrbbyEByPhdjib&6-=4 0: transfer_size_bytes = int(transfer_size) inbound_delivery_count = 0 - if router is not None and hasattr(router, "inbound_count"): - with contextlib.suppress(Exception): - inbound_delivery_count = int(router.inbound_count() or 0) + inbound_deliveries = [] + if router is not None: + inbound_deliveries = list_inbound_deliveries(router) + inbound_delivery_count = len(inbound_deliveries) return web.json_response( { "propagation_node_status": { @@ -12675,6 +12696,7 @@ class ReticulumMeshChat: "progress": progress_pct, "transfer_size_bytes": transfer_size_bytes, "inbound_delivery_count": inbound_delivery_count, + "inbound_deliveries": inbound_deliveries, "messages_received": last_result, "messages_stored": sync_metrics["messages_stored"], "delivery_confirmations": sync_metrics[ @@ -12728,26 +12750,41 @@ class ReticulumMeshChat: @routes.post("/api/v1/lxmf/propagation-node/cancel-inbound") async def propagation_node_cancel_inbound(request): router = self.message_router - if router is None or not hasattr(router, "cancel_all_inbound"): + data = {} + with contextlib.suppress(Exception): + data = await request.json() + if not isinstance(data, dict): + data = {} + resource_hash = data.get("resource_hash") + result = cancel_inbound_deliveries(router, resource_hash=resource_hash) + if not result.get("ok"): + status = 503 if "unavailable" in str(result.get("error") or "") else 400 return web.json_response( { - "message": "Inbound delivery cancellation is unavailable.", + "message": result.get( + "error", + "Failed to cancel inbound deliveries", + ), + "cancelled": result.get("cancelled", 0), }, - status=503, + status=status, ) - try: - cancelled = int(router.cancel_all_inbound() or 0) - except Exception as exc: - return web.json_response( - { - "message": f"Failed to cancel inbound deliveries: {exc}", - }, - status=500, + cancelled = int(result.get("cancelled") or 0) + if resource_hash: + message = ( + "Cancelled inbound delivery" + if cancelled + else "Inbound delivery was not active" ) + else: + message = f"Cancelled {cancelled} inbound deliveries" return web.json_response( { - "message": f"Cancelled {cancelled} inbound deliveries", + "message": message, "cancelled": cancelled, + "resource_hash": result.get("resource_hash"), + "inbound_delivery_count": len(list_inbound_deliveries(router)), + "inbound_deliveries": list_inbound_deliveries(router), }, ) @@ -13884,6 +13921,149 @@ class ReticulumMeshChat: return not_ready return web.json_response({"files": self.rns_filesync_handler.list_files()}) + @routes.get("/api/v1/filesync/tree") + async def filesync_tree(request): + not_ready = _filesync_require_handler() + if not_ready is not None: + return not_ready + path = request.rel_url.query.get("path") + try: + result = await asyncio.to_thread( + self.rns_filesync_handler.list_tree, + path, + ) + except Exception as e: + return web.json_response({"message": str(e)}, status=500) + if not result.get("ok"): + return web.json_response( + {"message": result.get("error", "list tree failed")}, + status=400, + ) + return web.json_response(result) + + @routes.post("/api/v1/filesync/mkdir") + async def filesync_mkdir(request): + not_ready = _filesync_require_handler() + if not_ready is not None: + return not_ready + data = await request.json() + if not isinstance(data, dict): + return web.json_response({"message": "Invalid JSON body"}, status=400) + try: + result = await asyncio.to_thread( + self.rns_filesync_handler.manager_mkdir, + data.get("path", ""), + ) + except Exception as e: + return web.json_response({"message": str(e)}, status=500) + if not result.get("ok"): + return web.json_response( + {"message": result.get("error", "mkdir failed")}, + status=400, + ) + return web.json_response(result) + + @routes.post("/api/v1/filesync/upload") + async def filesync_upload(request): + not_ready = _filesync_require_handler() + if not_ready is not None: + return not_ready + subdir = None + filename = None + file_data = None + try: + reader = await request.multipart() + while True: + field = await reader.next() + if field is None: + break + name = field.name or "" + if name == "path": + subdir = (await field.text()).strip() or None + elif name == "file": + filename = field.filename or "upload" + file_data = await field.read() + else: + with contextlib.suppress(Exception): + await field.read() + except Exception as e: + return web.json_response( + {"message": f"Invalid upload request: {e}"}, + status=400, + ) + if file_data is None: + return web.json_response({"message": "No file uploaded"}, status=400) + try: + result = await asyncio.to_thread( + self.rns_filesync_handler.manager_upload, + filename=filename, + data=file_data, + subdir=subdir, + ) + except Exception as e: + return web.json_response({"message": str(e)}, status=500) + if not result.get("ok"): + return web.json_response( + {"message": result.get("error", "upload failed")}, + status=400, + ) + return web.json_response(result) + + @routes.delete("/api/v1/filesync/entry") + async def filesync_entry_delete(request): + not_ready = _filesync_require_handler() + if not_ready is not None: + return not_ready + data = {} + with contextlib.suppress(Exception): + data = await request.json() + if not isinstance(data, dict): + data = {} + path = data.get("path", "") + try: + result = await asyncio.to_thread( + self.rns_filesync_handler.manager_delete, + path, + ) + except Exception as e: + return web.json_response({"message": str(e)}, status=500) + if not result.get("ok"): + return web.json_response( + {"message": result.get("error", "delete failed")}, + status=400, + ) + return web.json_response(result) + + @routes.get("/api/v1/filesync/content") + async def filesync_content(request): + not_ready = _filesync_require_handler() + if not_ready is not None: + return not_ready + path = request.rel_url.query.get("path", "") + try: + result = await asyncio.to_thread( + self.rns_filesync_handler.manager_content, + path, + ) + except Exception as e: + return web.json_response({"message": str(e)}, status=500) + if not result.get("ok"): + return web.json_response( + {"message": result.get("error", "content failed")}, + status=400, + ) + abspath = result.get("abspath") + filename = result.get("filename") or "download" + if not abspath or not os.path.isfile(abspath): + return web.json_response({"message": "file not found"}, status=404) + safe_name = os.path.basename(str(filename)).replace('"', "") + return web.FileResponse( + abspath, + headers={ + "Content-Disposition": f'attachment; filename="{safe_name}"', + }, + ) + @routes.get("/api/v1/filesync/directories") async def filesync_directories(request): not_ready = _filesync_require_handler() @@ -19006,6 +19186,11 @@ class ReticulumMeshChat: self._parse_bool(data["privacy_mode_enabled"]), ) + if "multi_session_warning_enabled" in data: + self.config.multi_session_warning_enabled.set( + self._parse_bool(data["multi_session_warning_enabled"]), + ) + # update map settings if "map_offline_enabled" in data: self.config.map_offline_enabled.set( @@ -19557,6 +19742,8 @@ class ReticulumMeshChat: # send config to websocket clients await self.send_config_to_websocket_clients() + if "multi_session_warning_enabled" in data: + await self.send_active_sessions_to_websocket_clients() # converts nomadnetwork page variables from a string to a map # converts: "field1=123|field2=456" @@ -21040,6 +21227,7 @@ class ReticulumMeshChat: async def websocket_broadcast(self, data): # Serialize: concurrent callers must not interleave. The second snapshot must run # only after the first broadcast has finished mutating the live client list. + sessions_changed = False async with self._websocket_broadcast_lock: dead = [] # Iterate a copy: awaits allow other tasks to mutate self.websocket_clients. @@ -21054,10 +21242,46 @@ class ReticulumMeshChat: self.websocket_clients.remove(client) except ValueError: pass + if self._detach_active_session(client): + sessions_changed = True try: await client.close(code=WSCloseCode.GOING_AWAY) except Exception: pass + if sessions_changed: + await self.send_active_sessions_to_websocket_clients() + + def _detach_active_session(self, websocket_response) -> bool: + session_id = getattr(websocket_response, "_meshchatx_session_id", None) + if not session_id: + return False + try: + delattr(websocket_response, "_meshchatx_session_id") + except Exception: + pass + return self.active_sessions.remove(session_id) + + def get_active_sessions_payload(self) -> dict: + snap = self.active_sessions.snapshot() + warning_enabled = True + try: + cfg = getattr(self, "config", None) + if cfg is not None and hasattr(cfg, "multi_session_warning_enabled"): + warning_enabled = bool(cfg.multi_session_warning_enabled.get()) + except Exception: + warning_enabled = True + count = int(snap.get("count") or 0) + return { + "count": count, + "sessions": list(snap.get("sessions") or []), + "warning": should_warn_multi_session(count, warning_enabled), + "warning_enabled": warning_enabled, + } + + async def send_active_sessions_to_websocket_clients(self): + payload = self.get_active_sessions_payload() + payload["type"] = "app.sessions.updated" + await self.websocket_broadcast(json.dumps(payload)) # broadcasts config to all websocket clients async def send_config_to_websocket_clients(self, context=None): @@ -21166,6 +21390,7 @@ class ReticulumMeshChat: "crawler_max_concurrent": ctx.config.crawler_max_concurrent.get(), "auth_enabled": self.auth_enabled, "privacy_mode_enabled": ctx.config.privacy_mode_enabled.get(), + "multi_session_warning_enabled": ctx.config.multi_session_warning_enabled.get(), "voicemail_enabled": ctx.config.voicemail_enabled.get(), "voicemail_greeting": ctx.config.voicemail_greeting.get(), "voicemail_auto_answer_delay_seconds": ctx.config.voicemail_auto_answer_delay_seconds.get(), diff --git a/meshchatx/src/backend/active_sessions.py b/meshchatx/src/backend/active_sessions.py new file mode 100644 index 00000000..0514f26f --- /dev/null +++ b/meshchatx/src/backend/active_sessions.py @@ -0,0 +1,85 @@ +# SPDX-License-Identifier: 0BSD + +"""Track active UI WebSocket sessions (IP and user-agent) for local multi-client warnings.""" + +from __future__ import annotations + +import threading +import time +import uuid +from typing import Any + + +_MAX_UA_LEN = 512 +_MAX_IP_LEN = 128 + + +def _clean_ip(value: str | None) -> str: + cleaned = str(value or "").strip() + if not cleaned: + return "unknown" + return cleaned[:_MAX_IP_LEN] + + +def _clean_user_agent(value: str | None) -> str: + cleaned = str(value or "").strip() + if not cleaned: + return "unknown" + # Strip control characters that break logs or JSON displays. + cleaned = "".join(ch for ch in cleaned if ch.isprintable()) + if not cleaned: + return "unknown" + return cleaned[:_MAX_UA_LEN] + + +def should_warn_multi_session(count: int, warning_enabled: bool) -> bool: + """Oracle: warn when two or more sessions are active and the setting is on.""" + try: + active = int(count) + except (TypeError, ValueError): + return False + return bool(warning_enabled) and active >= 2 + + +class ActiveSessionTracker: + """In-memory registry of connected MeshChatX UI WebSocket clients.""" + + def __init__(self) -> None: + self._lock = threading.RLock() + self._sessions: dict[str, dict[str, Any]] = {} + + def add(self, *, ip: str | None, user_agent: str | None) -> dict[str, Any]: + session_id = uuid.uuid4().hex + entry = { + "id": session_id, + "ip": _clean_ip(ip), + "user_agent": _clean_user_agent(user_agent), + "connected_at": time.time(), + } + with self._lock: + self._sessions[session_id] = entry + return dict(entry) + + def remove(self, session_id: str | None) -> bool: + cleaned = str(session_id or "").strip() + if not cleaned: + return False + with self._lock: + return self._sessions.pop(cleaned, None) is not None + + def count(self) -> int: + with self._lock: + return len(self._sessions) + + def list_sessions(self) -> list[dict[str, Any]]: + with self._lock: + rows = [dict(row) for row in self._sessions.values()] + rows.sort(key=lambda row: float(row.get("connected_at") or 0.0)) + return rows + + def snapshot(self) -> dict[str, Any]: + sessions = self.list_sessions() + return { + "count": len(sessions), + "sessions": sessions, + } diff --git a/meshchatx/src/backend/config_manager.py b/meshchatx/src/backend/config_manager.py index 19e8119b..ac4810e8 100644 --- a/meshchatx/src/backend/config_manager.py +++ b/meshchatx/src/backend/config_manager.py @@ -174,6 +174,11 @@ class ConfigManager: self.auth_password_hash = self.StringConfig(self, "auth_password_hash", None) self.auth_session_secret = self.StringConfig(self, "auth_session_secret", None) self.privacy_mode_enabled = self.BoolConfig(self, "privacy_mode_enabled", False) + self.multi_session_warning_enabled = self.BoolConfig( + self, + "multi_session_warning_enabled", + True, + ) self.gitea_base_url = self.StringConfig( self, "gitea_base_url", diff --git a/meshchatx/src/backend/data/THIRD_PARTY_NOTICES.txt b/meshchatx/src/backend/data/THIRD_PARTY_NOTICES.txt index 2b465b96..1d8193ac 100644 --- a/meshchatx/src/backend/data/THIRD_PARTY_NOTICES.txt +++ b/meshchatx/src/backend/data/THIRD_PARTY_NOTICES.txt @@ -1,5 +1,5 @@ Reticulum MeshChatX - Third-party notices -Generated at: 2026-07-19T06:42:05.960356Z +Generated at: 2026-07-22T15:24:54.544053Z Frontend source: pnpm Python dependencies @@ -49,12 +49,9 @@ idna 3.18 lxmf 1.1.0 License: Reticulum License Author: Mark Qvist -lxmfy 1.6.5 +lxmfy 2.0.1 License: BSD-0-Clause Author: Quad4 -rns-filesync 1.0.0 - License: BSD-2-Clause - Author: Sudo-Ivan / Quad4.io lxst 0.5.0 License: Other/Proprietary License Author: Mark Qvist @@ -91,6 +88,9 @@ reticulum-meshchatx 4.8.0 rns 1.4.0 License: Reticulum License Author: Mark Qvist +rns-filesync 1.0.0 + License: BSD-2-Clause + Author: — wasmtime 46.0.1 License: Apache-2.0 WITH LLVM-exception Author: The Wasmtime Project Developers @@ -103,9 +103,6 @@ yarl 1.23.0 Node dependencies ----------------- -@aashutoshrathi/word-wrap 1.2.6 - License: MIT - Author: Jon Schlinkert @asamuzakjp/css-color 5.1.11 License: MIT Author: asamuzaK @@ -148,7 +145,7 @@ Node dependencies @csstools/css-parser-algorithms 4.0.0 License: MIT Author: — -@csstools/css-syntax-patches-for-csstree 1.1.6 +@csstools/css-syntax-patches-for-csstree 1.1.3 License: MIT-0 Author: — @csstools/css-tokenizer 4.0.0 @@ -157,7 +154,7 @@ Node dependencies @egjs/hammerjs 2.0.17 License: MIT Author: — -@electron-internal/extract-zip 1.0.4 +@electron-internal/extract-zip 1.0.1 License: BSD-2-Clause Author: — @electron/asar 3.4.1 @@ -175,7 +172,7 @@ Node dependencies @electron/osx-sign 1.3.3 License: BSD-2-Clause Author: electron -@electron/rebuild 4.0.6 +@electron/rebuild 4.0.4 License: MIT Author: — @electron/universal 2.0.3 @@ -187,10 +184,10 @@ Node dependencies @epic-web/invariant 1.0.0 License: MIT Author: Kent C. Dodds -@eslint-community/eslint-utils 4.4.0 +@eslint-community/eslint-utils 4.8.0 License: MIT Author: Toru Nagashima -@eslint-community/regexpp 4.12.1 +@eslint-community/regexpp 4.12.2 License: MIT Author: Toru Nagashima @eslint/config-array 0.21.2 @@ -202,10 +199,10 @@ Node dependencies @eslint/core 0.17.0 License: Apache-2.0 Author: Nicholas C. Zakas -@eslint/eslintrc 3.3.5 +@eslint/eslintrc 3.3.6 License: MIT Author: Nicholas C. Zakas -@eslint/js 9.39.4 +@eslint/js 9.39.5 License: MIT Author: — @eslint/object-schema 2.1.7 @@ -217,39 +214,42 @@ Node dependencies @exodus/bytes 1.15.0 License: MIT Author: Exodus Movement, Inc. -@fontsource/noto-sans 5.2.10 +@fontsource/noto-sans 5.3.0 License: OFL-1.1 Author: Google Inc. -@humanfs/core 0.19.1 +@gar/promise-retry 1.0.3 + License: MIT + Author: — +@humanfs/core 0.19.2 License: Apache-2.0 Author: Nicholas C. Zakas -@humanfs/node 0.16.6 +@humanfs/node 0.16.8 + License: Apache-2.0 + Author: Nicholas C. Zakas +@humanfs/types 0.15.0 License: Apache-2.0 Author: Nicholas C. Zakas @humanwhocodes/module-importer 1.0.1 License: Apache-2.0 Author: Nicholas C. Zaks -@humanwhocodes/retry 0.3.0 +@humanwhocodes/retry 0.4.3 License: Apache-2.0 Author: Nicholas C. Zaks -@intlify/core-base 11.4.6 +@intlify/core-base 11.4.7 License: MIT Author: kazuya kawaguchi -@intlify/devtools-types 11.4.6 +@intlify/devtools-types 11.4.7 License: MIT Author: kazuya kawaguchi -@intlify/message-compiler 11.4.6 +@intlify/message-compiler 11.4.7 License: MIT Author: kazuya kawaguchi -@intlify/shared 11.4.6 +@intlify/shared 11.4.7 License: MIT Author: kazuya kawaguchi @isaacs/cliui 8.0.2 License: ISC Author: Ben Coe -@isaacs/cliui 9.0.0 - License: BlueOak-1.0.0 - Author: — @isaacs/fs-minipass 4.0.0 License: ISC Author: Isaac Z. Schlueter @@ -274,22 +274,19 @@ Node dependencies @jridgewell/trace-mapping 0.3.9 License: MIT Author: Justin Ridgewell -@keyv/serialize 1.1.1 - License: MIT - Author: Jared Wray @malept/cross-spawn-promise 2.0.0 License: Apache-2.0 Author: Mark Lee @malept/flatpak-bundler 0.4.0 License: MIT Author: Matt Watson -@mapbox/jsonlint-lines-primitives 2.0.3 - License: MIT +@mapbox/jsonlint-lines-primitives 2.0.2 + License: Unknown Author: Zach Carter -@mapbox/unitbezier 1.0.0 +@mapbox/unitbezier 0.0.1 License: BSD-2-Clause Author: — -@maplibre/maplibre-gl-style-spec 24.10.0 +@maplibre/maplibre-gl-style-spec 24.4.1 License: ISC Author: MapLibre @mdi/font 7.4.47 @@ -301,19 +298,28 @@ Node dependencies @noble/hashes 1.4.0 License: MIT Author: Paul Miller +@npmcli/agent 4.0.2 + License: ISC + Author: GitHub Inc. +@npmcli/fs 5.0.0 + License: ISC + Author: GitHub Inc. +@npmcli/redact 4.0.0 + License: ISC + Author: GitHub Inc. @one-ini/wasm 0.1.1 License: MIT Author: — -@oxc-parser/binding-linux-x64-gnu 0.137.0 +@oxc-parser/binding-linux-x64-gnu 0.140.0 License: MIT Author: Boshen and oxc contributors -@oxc-project/types 0.133.0 +@oxc-project/types 0.139.0 License: MIT Author: Boshen and oxc contributors -@oxc-resolver/binding-linux-x64-gnu 11.21.3 +@oxc-resolver/binding-linux-x64-gnu 11.24.2 License: MIT Author: — -@peculiar/asn1-schema 2.8.0 +@peculiar/asn1-schema 2.7.0 License: MIT Author: PeculiarVentures, LLC @peculiar/json-schema 1.1.12 @@ -340,49 +346,52 @@ Node dependencies @polka/url 1.0.0-next.24 License: MIT Author: Luke Edwards -@rolldown/binding-linux-x64-gnu 1.0.3 +@rolldown/binding-linux-x64-gnu 1.1.5 License: MIT Author: — @rolldown/pluginutils 1.0.0 License: MIT Author: — -@sec-ant/readable-stream 0.4.1 - License: MIT - Author: Ze-Zheng Wu -@sindresorhus/is 8.1.0 +@sindresorhus/is 4.0.0 License: MIT Author: Sindre Sorhus @standard-schema/spec 1.1.0 License: MIT Author: Colin McDonnell +@szmarczak/http-timer 4.0.5 + License: MIT + Author: Szymon Marczak @tailwindcss/forms 0.5.11 License: MIT Author: — -@tailwindcss/node 4.2.4 +@tailwindcss/node 4.3.3 License: MIT Author: — -@tailwindcss/oxide 4.2.4 +@tailwindcss/oxide 4.3.3 License: MIT Author: — -@tailwindcss/oxide-linux-x64-gnu 4.2.4 +@tailwindcss/oxide-linux-x64-gnu 4.3.3 License: MIT Author: — -@tailwindcss/vite 4.2.4 +@tailwindcss/vite 4.3.3 License: MIT Author: — -@tanstack/virtual-core 3.17.2 +@tanstack/virtual-core 3.17.6 License: MIT Author: Tanner Linsley -@tanstack/vue-virtual 3.13.30 +@tanstack/vue-virtual 3.13.34 License: MIT Author: Tanner Linsley -@types/chai 5.2.2 +@types/cacheable-request 6.0.1 License: MIT Author: — -@types/debug 4.1.13 +@types/chai 5.2.3 License: MIT Author: — -@types/deep-eql 4.0.0 +@types/debug 4.1.6 + License: MIT + Author: — +@types/deep-eql 4.0.2 License: MIT Author: — @types/estree 1.0.0 @@ -391,16 +400,16 @@ Node dependencies @types/fs-extra 9.0.13 License: MIT Author: — -@types/hammerjs 2.0.36 +@types/hammerjs 2.0.46 License: MIT Author: — -@types/http-cache-semantics 4.2.0 +@types/http-cache-semantics 4.0.0 License: MIT Author: — @types/json-schema 7.0.15 License: MIT Author: — -@types/ms 2.1.0 +@types/keyv 3.0.0 License: MIT Author: — @types/node 0.0.0 @@ -409,37 +418,40 @@ Node dependencies @types/rbush 4.0.0 License: MIT Author: — +@types/responselike 1.0.0 + License: MIT + Author: — @types/trusted-types 2.0.7 License: MIT Author: — -@vitejs/plugin-vue 6.0.7 +@vitejs/plugin-vue 6.0.8 License: MIT Author: Evan You -@vitest/coverage-v8 4.1.5 +@vitest/coverage-v8 4.1.10 License: MIT Author: Anthony Fu -@vitest/expect 4.1.5 +@vitest/expect 4.1.10 License: MIT Author: — -@vitest/mocker 4.1.5 +@vitest/mocker 4.1.10 License: MIT Author: — -@vitest/pretty-format 4.1.5 +@vitest/pretty-format 4.1.10 License: MIT Author: — -@vitest/runner 4.1.5 +@vitest/runner 4.1.10 License: MIT Author: — -@vitest/snapshot 4.1.5 +@vitest/snapshot 4.1.10 License: MIT Author: — -@vitest/spy 4.1.5 +@vitest/spy 4.1.10 License: MIT Author: — -@vitest/ui 4.1.9 +@vitest/ui 4.1.10 License: MIT Author: — -@vitest/utils 4.1.5 +@vitest/utils 4.1.10 License: MIT Author: — @volar/language-core 2.4.28 @@ -451,37 +463,37 @@ Node dependencies @volar/typescript 2.4.28 License: MIT Author: — -@vue/compiler-core 3.5.39 +@vue/compiler-core 3.5.40 License: MIT Author: Evan You -@vue/compiler-dom 3.5.39 +@vue/compiler-dom 3.5.40 License: MIT Author: Evan You -@vue/compiler-sfc 3.5.39 +@vue/compiler-sfc 3.5.40 License: MIT Author: Evan You -@vue/compiler-ssr 3.5.39 +@vue/compiler-ssr 3.5.40 License: MIT Author: Evan You -@vue/devtools-api 6.6.4 +@vue/devtools-api 6.5.0 License: MIT Author: Guillaume Chau -@vue/language-core 3.3.6 +@vue/language-core 3.3.7 License: MIT Author: — -@vue/reactivity 3.5.39 +@vue/reactivity 3.5.40 License: MIT Author: Evan You -@vue/runtime-core 3.5.39 +@vue/runtime-core 3.5.40 License: MIT Author: Evan You -@vue/runtime-dom 3.5.39 +@vue/runtime-dom 3.5.40 License: MIT Author: Evan You -@vue/server-renderer 3.5.39 +@vue/server-renderer 3.5.40 License: MIT Author: Evan You -@vue/shared 3.5.39 +@vue/shared 3.5.40 License: MIT Author: Evan You @vue/test-utils 2.4.11 @@ -493,9 +505,12 @@ Node dependencies @zarrita/storage 0.2.0 License: MIT Author: — -abbrev 2.0.0 +abbrev 4.0.0 License: ISC Author: GitHub Inc. +abbrev 1.0.3 + License: Unknown + Author: Isaac Z. Schlueter acorn 0.11.0 License: MIT Author: — @@ -511,6 +526,9 @@ ajv 6.14.0 alien-signals 3.2.1 License: MIT Author: — +amdefine 1.0.1 + License: BSD-3-Clause OR MIT + Author: James Burke ansi-regex 5.0.1 License: MIT Author: Sindre Sorhus @@ -523,39 +541,30 @@ app-builder-lib 26.15.3 argparse 2.0.1 License: Python-2.0 Author: — -array-buffer-byte-length 1.0.2 - License: MIT - Author: Jordan Harband -arraybuffer.prototype.slice 1.0.4 - License: MIT - Author: Jordan Harband asn1js 3.0.10 License: BSD-3-Clause Author: Yury Strozhevsky -ast-types 0.8.15 +assertion-error 2.0.1 + License: MIT + Author: Jake Luer +ast-types 0.6.12 License: MIT Author: Ben Newman ast-v8-to-istanbul 1.0.0 License: MIT Author: Ari Perkkiö -async 3.2.6 +async 3.2.3 License: MIT Author: Caolan McMahon async-exit-hook 2.0.1 License: MIT Author: Tapani Moilanen -async-function 1.0.0 - License: MIT - Author: Jordan Harbamd asynckit 0.4.0 License: MIT Author: Alex Indigo at-least-node 1.0.0 License: ISC Author: Ryan Zimmerman -available-typed-arrays 1.0.7 - License: MIT - Author: Jordan Harband aws4 1.13.2 License: MIT Author: Michael Hart @@ -577,7 +586,7 @@ blueimp-canvas-to-blob 3.29.0 boolbase 1.0.0 License: ISC Author: Felix Boehm -boolean 3.2.0 +boolean 3.0.1 License: MIT Author: — brace-expansion 1.1.12 @@ -592,28 +601,22 @@ builder-util 26.15.3 builder-util-runtime 9.7.0 License: MIT Author: Vladimir Krivosheev -byte-counter 0.1.0 - License: MIT - Author: Sindre Sorhus bytestreamjs 2.0.1 License: BSD-3-Clause Author: Yury Strozhevsky -cacheable-lookup 7.0.0 +cacache 20.0.4 + License: ISC + Author: GitHub Inc. +cacheable-lookup 5.0.3 License: MIT Author: Szymon Marczak -cacheable-request 13.0.19 +cacheable-request 7.0.2 License: MIT - Author: Jared Wray -call-bind 1.0.9 + Author: Luke Childs +call-bind-apply-helpers 1.0.1 License: MIT Author: Jordan Harband -call-bind-apply-helpers 1.0.0 - License: MIT - Author: Jordan Harband -call-bound 1.0.4 - License: MIT - Author: Jordan Harband -callsites 3.0.0 +callsites 3.1.0 License: MIT Author: Sindre Sorhus camelcase 5.0.0 @@ -622,7 +625,7 @@ camelcase 5.0.0 chai 6.2.2 License: MIT Author: Jake Luer -chalk 4.0.0 +chalk 4.1.1 License: MIT Author: — chownr 3.0.0 @@ -631,10 +634,7 @@ chownr 3.0.0 chromium-pickle-js 0.2.0 License: MIT Author: — -chunk-data 0.1.0 - License: MIT - Author: Sindre Sorhus -ci-info 4.3.1 +ci-info 4.2.0 License: MIT Author: Thomas Watson Steen cli-table3 0.5.0 @@ -643,6 +643,9 @@ cli-table3 0.5.0 cliui 4.0.0 License: ISC Author: Ben Coe +clone-response 1.0.2 + License: MIT + Author: Luke Childs code-point-at 1.0.0 License: MIT Author: Sindre Sorhus @@ -703,37 +706,28 @@ csstype 3.2.3 data-urls 7.0.0 License: MIT Author: Domenic Denicola -data-view-buffer 1.0.2 - License: MIT - Author: Jordan Harband -data-view-byte-length 1.0.2 - License: MIT - Author: Jordan Harband -data-view-byte-offset 1.0.1 - License: MIT - Author: Jordan Harband dayjs 1.11.21 License: MIT Author: iamkun debug 4.3.1 License: MIT - Author: TJ Holowaychuk + Author: Josh Junon decamelize 1.2.0 License: MIT Author: Sindre Sorhus decimal.js 10.6.0 License: MIT Author: Michael Mclaughlin -decompress-response 10.0.0 +decompress-response 6.0.0 License: MIT Author: Sindre Sorhus -deep-is 0.1.3 +deep-is 0.1.4 License: MIT Author: Thorsten Lorenz -define-data-property 1.1.4 +defer-to-connect 2.0.0 License: MIT - Author: Jordan Harband -define-properties 1.2.1 + Author: Szymon Marczak +define-properties 1.1.2 License: MIT Author: Jordan Harband delayed-stream 1.0.0 @@ -742,8 +736,8 @@ delayed-stream 1.0.0 detect-libc 2.0.3 License: Apache-2.0 Author: Lovell Fuller -detect-node 2.1.0 - License: MIT +detect-node 2.0.4 + License: ISC Author: Ilya Kantor dijkstrajs 1.0.1 License: MIT @@ -754,13 +748,13 @@ dir-compare 4.2.0 dmg-builder 26.15.3 License: MIT Author: Vladimir Krivosheev -dompurify 3.4.11 +dompurify 3.4.12 License: (MPL-2.0 OR Apache-2.0) Author: Dr.-Ing. Mario Heiderich, Cure53 dotenv 16.6.1 License: BSD-2-Clause Author: — -dotenv-expand 11.0.7 +dotenv-expand 11.0.6 License: BSD-2-Clause Author: motdotla dunder-proto 1.0.0 @@ -769,13 +763,13 @@ dunder-proto 1.0.0 duplexer2 0.1.4 License: BSD-3-Clause Author: Conrad Pankoff -earcut 3.1.0 +earcut 3.0.0 License: ISC - Author: Volodymyr Agafonkin + Author: Vladimir Agafonkin eastasianwidth 0.2.0 License: MIT Author: Masaki Komagata -editorconfig 1.0.7 +editorconfig 1.0.3 License: MIT Author: EditorConfig Team ejs 3.1.10 @@ -808,7 +802,10 @@ emoji-picker-element-data 1.8.0 emoji-regex 8.0.0 License: MIT Author: Mathias Bynens -enhanced-resolve 5.19.0 +end-of-stream 1.1.0 + License: MIT + Author: Mathias Buus +enhanced-resolve 5.24.1 License: MIT Author: Tobias Koppers @sokra entities 7.0.1 @@ -817,13 +814,10 @@ entities 7.0.1 env-paths 2.2.0 License: MIT Author: Sindre Sorhus -err-code 2.0.3 +err-code 2.0.2 License: MIT Author: IndigoUnited -es-abstract 1.24.2 - License: MIT - Author: Jordan Harband -es-abstract-get 1.0.0 +es-abstract 1.5.0 License: MIT Author: Jordan Harband es-define-property 1.0.1 @@ -832,7 +826,7 @@ es-define-property 1.0.1 es-errors 1.3.0 License: MIT Author: Jordan Harband -es-module-lexer 2.2.0 +es-module-lexer 2.0.0 License: MIT Author: Guy Bedford es-object-atoms 1.0.0 @@ -841,7 +835,7 @@ es-object-atoms 1.0.0 es-set-tostringtag 2.1.0 License: MIT Author: Jordan Harband -es-to-primitive 1.3.4 +es-to-primitive 1.1.0 License: MIT Author: Jordan Harband es6-error 4.1.1 @@ -853,7 +847,7 @@ escalade 3.1.1 escape-string-regexp 4.0.0 License: MIT Author: Sindre Sorhus -eslint 9.39.4 +eslint 9.39.5 License: MIT Author: Nicholas C. Zakas eslint-config-prettier 10.1.8 @@ -865,13 +859,13 @@ eslint-plugin-prettier 5.5.6 eslint-plugin-security 3.0.1 License: Apache-2.0 Author: Node Security Project -eslint-plugin-vue 10.9.2 +eslint-plugin-vue 10.10.0 License: MIT Author: Toru Nagashima eslint-scope 8.2.0 License: BSD-2-Clause Author: — -eslint-visitor-keys 3.3.0 +eslint-visitor-keys 3.4.3 License: Apache-2.0 Author: Toru Nagashima esmangle-evaluator 1.0.0 @@ -880,10 +874,10 @@ esmangle-evaluator 1.0.0 espree 10.3.0 License: BSD-2-Clause Author: Nicholas C. Zakas -esprima-fb 15001.1001.0-dev-harmony-fb +esprima-fb 12001.1.0-dev-harmony-fb License: BSD Author: Ariya Hidayat -esquery 1.5.0 +esquery 1.6.0 License: BSD-3-Clause Author: Joel Feenstra esrecurse 4.3.0 @@ -895,8 +889,8 @@ estraverse 5.1.0 estree-walker 2.0.2 License: MIT Author: Rich Harris -esutils 2.0.2 - License: BSD +esutils 2.0.3 + License: BSD-2-Clause Author: — execa 0.10.0 License: MIT @@ -916,16 +910,16 @@ falafel 1.0.1 fast-deep-equal 3.1.3 License: MIT Author: Evgeny Poberezkin -fast-diff 1.3.0 +fast-diff 1.1.2 License: Apache-2.0 Author: Jason Chen -fast-json-stable-stringify 2.0.0 +fast-json-stable-stringify 2.1.0 License: MIT Author: James Halliday fast-levenshtein 2.0.6 License: MIT Author: Ramesh Nair -fast-uri 3.1.2 +fast-uri 4.1.1 License: BSD-3-Clause Author: Vincent Le Goff fd-package-json 2.0.0 @@ -946,15 +940,18 @@ filelist 1.0.1 find-up 3.0.0 License: MIT Author: Sindre Sorhus -flat-cache 4.0.0 +flat-cache 4.0.1 License: MIT Author: Jared Wray flatted 3.4.2 License: ISC Author: Andrea Giammarchi -for-each 0.3.5 +for-each 0.3.3 License: MIT Author: Raynos +foreach 2.0.6 + License: MIT + Author: Manuel Stofer foreground-child 3.1.0 License: ISC Author: Isaac Z. Schlueter @@ -967,39 +964,27 @@ formatly 0.3.0 fs-extra 7.0.1 License: MIT Author: JP Richardson +fs-minipass 3.0.3 + License: ISC + Author: GitHub Inc. fs.realpath 1.0.0 License: ISC Author: Isaac Z. Schlueter -function-bind 1.1.1 +function-bind 1.0.2 License: MIT Author: Raynos -function.prototype.name 1.2.0 - License: MIT - Author: Jordan Harband -functions-have-names 1.2.3 - License: MIT - Author: Jordan Harband -generator-function 2.0.0 - License: MIT - Author: Jordan Harbamd geotiff 3.0.5 License: MIT Author: Fabian Schindler get-caller-file 1.0.1 License: ISC Author: Stefan Penner -get-intrinsic 1.1.3 - License: MIT - Author: Jordan Harband -get-proto 1.0.1 +get-intrinsic 1.2.6 License: MIT Author: Jordan Harband get-stream 3.0.0 License: MIT Author: Sindre Sorhus -get-symbol-description 1.1.0 - License: MIT - Author: Jordan Harband get-tsconfig 4.14.0 License: MIT Author: Hiroki Osame @@ -1015,45 +1000,33 @@ global-agent 3.0.0 globals 14.0.0 License: MIT Author: Sindre Sorhus -globalthis 1.0.4 +globalthis 1.0.1 License: MIT Author: Jordan Harband -gopd 1.0.1 +gopd 1.2.0 License: MIT Author: Jordan Harband -got 15.0.7 +got 11.8.6 License: MIT Author: — graceful-fs 4.1.2 License: ISC Author: — -has 1.0.3 - License: MIT - Author: Thiago de Arruda -has-bigints 1.1.0 - License: MIT - Author: Jordan Harband has-flag 4.0.0 License: MIT Author: Sindre Sorhus -has-property-descriptors 1.0.2 - License: MIT - Author: Jordan Harband -has-proto 1.2.0 - License: MIT - Author: Jordan Harband has-symbols 1.0.3 License: MIT Author: Jordan Harband has-tostringtag 1.0.2 License: MIT Author: Jordan Harband -hasown 2.0.2 +hasown 2.0.4 License: MIT Author: Jordan Harband -hosted-git-info 10.1.1 +hosted-git-info 2.8.9 License: ISC - Author: GitHub Inc. + Author: Rebecca Turner html-encoding-sniffer 6.0.0 License: MIT Author: Domenic Denicola @@ -1066,19 +1039,22 @@ http-cache-semantics 4.1.1 http-proxy-agent 7.0.0 License: MIT Author: Nathan Rajlich -http2-wrapper 2.2.1 +http2-wrapper 1.0.0-beta.5.2 License: MIT Author: Szymon Marczak https-proxy-agent 7.0.0 License: MIT Author: Nathan Rajlich -ignore 5.2.0 +iconv-lite 0.7.2 + License: MIT + Author: Alexander Shtuchkin +ignore 5.3.2 License: MIT Author: kael immediate 3.0.5 License: MIT Author: — -import-fresh 3.2.1 +import-fresh 3.3.1 License: MIT Author: Sindre Sorhus imurmurhash 0.1.4 @@ -1099,94 +1075,40 @@ ini 1.3.6 inline-process-browser 1.0.0 License: MIT Author: Calvin W. Metcalf -internal-slot 1.1.0 - License: MIT - Author: Jordan Harband invert-kv 2.0.0 License: MIT Author: Sindre Sorhus -is-array-buffer 3.0.5 +ip-address 9.0.5 License: MIT - Author: Jordan Harband -is-async-function 2.1.1 - License: MIT - Author: Jordan Harband -is-bigint 1.1.0 - License: MIT - Author: Jordan Harband + Author: Beau Gunderson is-blob 2.1.0 License: MIT Author: Sindre Sorhus -is-boolean-object 1.2.0 +is-callable 1.1.1 License: MIT Author: Jordan Harband -is-callable 1.2.7 - License: MIT - Author: Jordan Harband -is-data-view 1.0.2 - License: MIT - Author: Jordan Harband -is-date-object 1.1.0 - License: MIT - Author: Jordan Harband -is-document.all 1.0.0 +is-date-object 1.0.1 License: MIT Author: Jordan Harband is-extglob 2.1.1 License: MIT Author: Jon Schlinkert -is-finalizationregistry 1.1.1 - License: MIT - Author: Jordan Harband is-fullwidth-code-point 1.0.0 License: MIT Author: Sindre Sorhus -is-generator-function 1.1.2 - License: MIT - Author: Jordan Harband -is-glob 4.0.0 +is-glob 4.0.3 License: MIT Author: Jon Schlinkert -is-map 2.0.3 - License: MIT - Author: Jordan Harband -is-negative-zero 2.0.3 - License: MIT - Author: Jordan Harband -is-number-object 1.1.0 - License: MIT - Author: Jordan Harband is-potential-custom-element-name 1.0.1 License: MIT Author: Mathias Bynens -is-regex 1.2.1 - License: MIT - Author: Jordan Harband -is-set 2.0.3 - License: MIT - Author: Jordan Harband -is-shared-array-buffer 1.0.4 +is-regex 1.0.3 License: MIT Author: Jordan Harband is-stream 1.1.0 License: MIT Author: Sindre Sorhus -is-string 1.1.1 - License: MIT - Author: Jordan Harband -is-symbol 1.1.0 - License: MIT - Author: Jordan Harband -is-typed-array 1.1.15 - License: MIT - Author: Jordan Harband -is-weakmap 2.0.2 - License: MIT - Author: Jordan Harband -is-weakref 1.1.1 - License: MIT - Author: Jordan Harband -is-weakset 2.0.4 +is-symbol 1.0.1 License: MIT Author: Jordan Harband isarray 0.0.1 @@ -1198,6 +1120,9 @@ isbinaryfile 4.0.8 isexe 2.0.0 License: ISC Author: Isaac Z. Schlueter +isexe 3.1.5 + License: BlueOak-1.0.0 + Author: Isaac Z. Schlueter istanbul-lib-coverage 3.2.2 License: BSD-3-Clause Author: Krishnan Anantheswaran @@ -1216,18 +1141,18 @@ jake 10.8.5 jiti 2.4.2 License: MIT Author: — -js-beautify 1.15.4 +js-beautify 1.14.9 License: MIT Author: Einar Lielmanis -js-cookie 3.0.8 - License: MIT - Author: Klaus Hartl js-tokens 10.0.0 License: MIT Author: Simon Lydell js-yaml 4.2.0 License: MIT Author: Vladimir Zapparov +jsbn 1.1.0 + License: MIT + Author: Tom Wu jsdom 29.1.1 License: MIT Author: — @@ -1261,10 +1186,10 @@ jszip 3.10.1 keycharm 0.4.0 License: (Apache-2.0 OR MIT) Author: Alex de Mulder -keyv 4.5.4 +keyv 4.0.0 License: MIT Author: Jared Wray -knip 6.24.0 +knip 6.29.0 License: ISC Author: Lars Kappert lazy-val 1.0.5 @@ -1297,7 +1222,7 @@ lodash 4.18.0 lodash.merge 4.6.2 License: MIT Author: John-David Dalton -lowercase-keys 3.0.0 +lowercase-keys 2.0.0 License: MIT Author: Sindre Sorhus lru-cache 6.0.0 @@ -1315,10 +1240,13 @@ magicast 0.5.2 make-dir 4.0.0 License: MIT Author: Sindre Sorhus +make-fetch-happen 15.0.6 + License: ISC + Author: GitHub Inc. mapbox-to-css-font 3.2.0 License: BSD-2-Clause Author: Andreas Hocevar -marked 18.0.5 +marked 18.0.7 License: MIT Author: Christopher Jeffrey matcher 3.0.0 @@ -1336,7 +1264,7 @@ mem 3.0.1 micron-parser 0.0.0 License: Unknown Author: — -mime 2.6.0 +mime 2.5.2 License: MIT Author: Robert Kieffer mime-db 1.52.0 @@ -1345,10 +1273,10 @@ mime-db 1.52.0 mime-types 2.1.35 License: MIT Author: — -mimic-fn 1.2.0 +mimic-fn 1.0.0 License: MIT Author: Sindre Sorhus -mimic-response 4.0.0 +mimic-response 1.0.0 License: MIT Author: Sindre Sorhus mini-svg-data-uri 1.2.3 @@ -1363,15 +1291,27 @@ minimatch 10.2.3 minimist 1.2.8 License: MIT Author: James Halliday -minipass 7.1.2 +minipass 3.0.0 License: ISC Author: Isaac Z. Schlueter -minizlib 3.1.0 +minipass-collect 2.0.1 + License: ISC + Author: Isaac Z. Schlueter +minipass-fetch 5.0.2 + License: MIT + Author: GitHub Inc. +minipass-flush 1.0.7 + License: BlueOak-1.0.0 + Author: Isaac Z. Schlueter +minipass-pipeline 1.2.4 + License: ISC + Author: Isaac Z. Schlueter +minipass-sized 2.0.0 + License: ISC + Author: Isaac Z. Schlueter +minizlib 3.0.1 License: MIT Author: Isaac Z. Schlueter -mkdirp 0.5.1 - License: MIT - Author: James Halliday mrmime 2.0.0 License: MIT Author: Luke Edwards @@ -1387,25 +1327,28 @@ nanoid 3.3.12 natural-compare 1.4.0 License: MIT Author: Lauri Rooden -node-abi 4.31.0 +negotiator 1.0.0 + License: MIT + Author: — +node-abi 4.2.0 License: MIT Author: Lukas Geiger node-api-version 0.2.1 License: MIT Author: Tim Fish -node-gyp 12.4.0 +node-gyp 12.2.0 License: MIT Author: Nathan Rajlich node-int64 0.4.0 License: MIT Author: Robert Kieffer -nopt 7.2.1 +nopt 6.0.0 License: ISC Author: GitHub Inc. -normalize-url 8.1.1 +normalize-url 6.0.1 License: MIT Author: Sindre Sorhus -npm-run-path 2.0.2 +npm-run-path 2.0.0 License: MIT Author: Sindre Sorhus nth-check 2.1.1 @@ -1420,13 +1363,7 @@ numcodecs 0.3.2 object-assign 4.1.0 License: MIT Author: Sindre Sorhus -object-inspect 1.13.4 - License: MIT - Author: James Halliday -object-keys 1.1.1 - License: MIT - Author: Jordan Harband -object.assign 4.1.7 +object-keys 1.0.8 License: MIT Author: Jordan Harband obug 2.1.1 @@ -1438,24 +1375,24 @@ ol 10.9.0 ol-mapbox-style 13.4.1 License: BSD-2-Clause Author: — -once 1.4.0 - License: ISC +once 1.3.0 + License: BSD Author: Isaac Z. Schlueter -optionator 0.9.3 +optionator 0.9.4 License: MIT Author: George Zahariev os-locale 3.0.0 License: MIT Author: Sindre Sorhus -own-keys 1.0.1 - License: MIT - Author: Jordan Harband -oxc-parser 0.137.0 +oxc-parser 0.140.0 License: MIT Author: Boshen and oxc contributors -oxc-resolver 11.21.3 +oxc-resolver 11.24.2 License: MIT Author: — +p-cancelable 2.0.0 + License: MIT + Author: Sindre Sorhus p-finally 1.0.0 License: MIT Author: Sindre Sorhus @@ -1468,6 +1405,9 @@ p-limit 2.0.0 p-locate 3.0.0 License: MIT Author: Sindre Sorhus +p-map 7.0.6 + License: MIT + Author: Sindre Sorhus p-try 2.0.0 License: MIT Author: Sindre Sorhus @@ -1480,7 +1420,7 @@ pako 1.0.2 pako 2.0.4 License: (MIT AND Zlib) Author: — -parent-module 1.0.0 +parent-module 1.0.1 License: MIT Author: Sindre Sorhus parse-headers 2.0.2 @@ -1510,7 +1450,7 @@ pathe 2.0.3 pbf 4.0.1 License: BSD-3-Clause Author: Konstantin Kaefer -pe-library 0.4.1 +pe-library 0.4.0 License: MIT Author: jet picocolors 1.1.1 @@ -1534,13 +1474,10 @@ plist 3.0.5 pngjs 5.0.0 License: MIT Author: — -possible-typed-array-names 1.1.0 - License: MIT - Author: Jordan Harband -postcss 8.5.15 +postcss 8.5.19 License: MIT Author: Andrey Sitnik -postcss-selector-parser 7.1.0 +postcss-selector-parser 7.1.4 License: MIT Author: — postject 1.0.0-alpha.6 @@ -1549,7 +1486,7 @@ postject 1.0.0-alpha.6 prelude-ls 1.2.1 License: MIT Author: George Zahariev -prettier 3.9.3 +prettier 3.9.6 License: MIT Author: James Long prettier-linter-helpers 1.0.1 @@ -1558,7 +1495,7 @@ prettier-linter-helpers 1.0.1 private 0.1.5 License: MIT Author: Ben Newman -proc-log 6.1.0 +proc-log 6.0.0 License: ISC Author: GitHub Inc. process-nextick-args 1.0.0 @@ -1573,19 +1510,22 @@ promise-retry 2.0.1 proper-lockfile 4.1.2 License: MIT Author: André Cruz -proto-list 1.2.4 - License: ISC +proto-list 1.2.1 + License: MIT Author: Isaac Z. Schlueter protocol-buffers-schema 3.6.1 License: MIT Author: Mathias Buus -punycode 2.1.0 +pump 3.0.0 + License: MIT + Author: Mathias Buus Madsen +punycode 2.3.1 License: MIT Author: Mathias Bynens pvtsutils 1.3.6 License: MIT Author: PeculiarVentures -pvutils 1.1.5 +pvutils 1.1.3 License: MIT Author: Yury Strozhevsky qrcode 1.5.4 @@ -1606,21 +1546,15 @@ read-binary-file-arch 1.0.6 readable-stream 1.0.31 License: MIT Author: — -recast 0.10.43 +recast 0.10.1 License: MIT Author: Ben Newman reference-spec-reader 0.2.0 License: MIT Author: manzt -reflect.getprototypeof 1.0.10 - License: MIT - Author: Jordan Harband regexp-tree 0.1.1 License: MIT Author: Dmitry Soshnikov -regexp.prototype.flags 1.5.4 - License: MIT - Author: Jordan Harband require-directory 2.1.1 License: MIT Author: Troy Goode @@ -1630,10 +1564,10 @@ require-from-string 2.0.2 require-main-filename 1.0.1 License: ISC Author: Ben Coe -resedit 1.7.2 +resedit 1.7.0 License: MIT Author: jet -resolve-alpn 1.2.1 +resolve-alpn 1.0.0 License: MIT Author: Szymon Marczak resolve-from 4.0.0 @@ -1645,37 +1579,34 @@ resolve-pkg-maps 1.0.0 resolve-protobuf-schema 2.1.0 License: MIT Author: Mathias Buus -responselike 4.0.2 +responselike 2.0.0 License: MIT - Author: — + Author: lukechilds retry 0.12.0 License: MIT Author: Tim Koschützki rimraf 2.6.2 License: ISC Author: Isaac Z. Schlueter -roarr 2.15.4 +roarr 2.15.3 License: BSD-3-Clause Author: Gajus Kuizinas -rolldown 1.0.3 +rolldown 1.1.5 License: MIT Author: — -safe-array-concat 1.1.4 - License: MIT - Author: Jordan Harband +rw 1.3.3 + License: BSD-3-Clause + Author: Mike Bostock safe-buffer 5.1.1 License: MIT Author: Feross Aboukhadijeh -safe-push-apply 1.0.0 - License: MIT - Author: Jordan Harband safe-regex 2.1.1 License: MIT Author: James C. -safe-regex-test 1.1.0 +safer-buffer 2.1.2 License: MIT - Author: Jordan Harband -sanitize-filename 1.6.4 + Author: Nikita Skovoroda +sanitize-filename 1.6.3 License: WTFPL OR ISC Author: Parsha Pourkhomami sax 1.2.4 @@ -1696,15 +1627,6 @@ serialize-error 7.0.1 set-blocking 2.0.0 License: ISC Author: Ben Coe -set-function-length 1.2.2 - License: MIT - Author: Jordan Harband -set-function-name 2.0.2 - License: MIT - Author: Jordan Harband -set-proto 1.0.0 - License: MIT - Author: Jordan Harband setimmediate 1.0.5 License: MIT Author: YuzuJS @@ -1714,18 +1636,6 @@ shebang-command 2.0.0 shebang-regex 3.0.0 License: MIT Author: Sindre Sorhus -side-channel 1.1.1 - License: MIT - Author: Jordan Harband -side-channel-list 1.0.1 - License: MIT - Author: Jordan Harband -side-channel-map 1.0.1 - License: MIT - Author: Jordan Harband -side-channel-weakmap 1.0.2 - License: MIT - Author: Jordan Harband siginfo 2.0.0 License: ISC Author: Emil Bay @@ -1738,21 +1648,36 @@ simple-update-notifier 2.0.0 sirv 3.0.2 License: MIT Author: Luke Edwards +smart-buffer 4.2.0 + License: MIT + Author: Josh Glazebrook smol-toml 1.7.0 License: BSD-3-Clause Author: Cynthia Rey -source-map 0.5.0 +socks 2.8.0 + License: MIT + Author: Josh Glazebrook +socks-proxy-agent 8.0.3 + License: MIT + Author: Nathan Rajlich +source-map 0.6.0 License: BSD-3-Clause Author: Nick Fitzgerald +source-map 0.3.0 + License: BSD + Author: Nick Fitzgerald source-map-js 1.0.2 License: BSD-3-Clause Author: Valentin 7rulnik Semirulnik source-map-support 0.5.19 License: MIT Author: — -sprintf-js 1.1.3 +sprintf-js 1.1.2 License: BSD-3-Clause Author: Alexandru Mărășteanu +ssri 13.0.1 + License: ISC + Author: GitHub Inc. stackback 0.0.2 License: MIT Author: Roman Shtylman @@ -1762,19 +1687,10 @@ stat-mode 1.0.0 std-env 4.0.0-rc.1 License: MIT Author: — -stop-iteration-iterator 1.1.0 - License: MIT - Author: Jordan Harband string-width 1.0.1 License: MIT Author: Sindre Sorhus -string.prototype.trim 1.2.11 - License: MIT - Author: Jordan Harband -string.prototype.trimend 1.0.10 - License: MIT - Author: Jordan Harband -string.prototype.trimstart 1.0.8 +string.prototype.trim 1.1.2 License: MIT Author: Jordan Harband string_decoder 0.10.24 @@ -1801,25 +1717,22 @@ symbol-tree 3.2.4 synckit 0.11.13 License: MIT Author: JounQin -tagged-tag 1.0.0 - License: MIT - Author: Sindre Sorhus -tailwindcss 4.2.4 +tailwindcss 4.3.3 License: MIT Author: — -tapable 2.3.0 +tapable 2.3.3 License: MIT Author: Tobias Koppers @sokra -tar 7.5.19 +tar 7.5.21 License: BlueOak-1.0.0 Author: Isaac Z. Schlueter -temp 0.9.4 +temp 0.9.0 License: MIT Author: Bruce Williams temp-file 3.4.0 License: MIT Author: Vladimir Krivosheev -terser 5.48.0 +terser 5.49.0 License: BSD-2-Clause Author: Mihai Bazon through2 0.6.2 @@ -1843,16 +1756,16 @@ tinyqueue 3.0.0 tinyrainbow 3.1.0 License: MIT Author: — -tldts 7.4.5 +tldts 7.0.5 License: MIT Author: Rémi Berson -tldts-core 7.4.5 +tldts-core 7.0.5 License: MIT Author: Rémi Berson tmp 0.2.7 License: MIT Author: KARASZI István -tmp-promise 3.0.3 +tmp-promise 3.0.2 License: MIT Author: Benjamin Gruenbaum and Collaborators. totalist 3.0.0 @@ -1864,10 +1777,10 @@ tough-cookie 6.0.1 tr46 6.0.0 License: MIT Author: Sebastian Mayr -truncate-utf8-bytes 1.0.2 +truncate-utf8-bytes 1.0.0 License: WTFPL Author: Carl Xiong -tslib 2.4.0 +tslib 2.8.1 License: 0BSD Author: Microsoft Corp. type-check 0.4.0 @@ -1876,30 +1789,12 @@ type-check 0.4.0 type-fest 0.13.1 License: (MIT OR CC0-1.0) Author: Sindre Sorhus -typed-array-buffer 1.0.3 - License: MIT - Author: Jordan Harband -typed-array-byte-length 1.0.3 - License: MIT - Author: Jordan Harband -typed-array-byte-offset 1.0.4 - License: MIT - Author: Jordan Harband -typed-array-length 1.0.8 - License: MIT - Author: Jordan Harband typescript 6.0.3 License: Apache-2.0 Author: Microsoft Corp. -uint8array-extras 1.5.0 - License: MIT - Author: Sindre Sorhus -unbash 4.0.2 +unbash 4.0.3 License: ISC Author: Lars Kappert -unbox-primitive 1.1.0 - License: MIT - Author: Jordan Harband undici 7.28.0 License: MIT Author: — @@ -1915,17 +1810,17 @@ unreachable-branch-transform 0.3.0 unzipit 2.0.0 License: MIT Author: — -unzipper 0.12.5 +unzipper 0.12.3 License: MIT - Author: Ziggy Jonsson + Author: Evan Oxfeld upath 2.0.1 License: MIT Author: Angelos Pikoulas -uri-js 4.2.2 +uri-js 4.4.1 License: BSD-2-Clause Author: Gary Court -utf8-byte-length 1.0.5 - License: (WTFPL OR MIT) +utf8-byte-length 1.0.1 + License: WTFPL Author: Carl Xiong util-deprecate 1.0.1 License: MIT @@ -1942,37 +1837,37 @@ vis-network 9.1.13 vis-util 5.0.7 License: (Apache-2.0 OR MIT) Author: Alex de Mulder -vite 8.0.16 +vite 8.1.5 License: MIT Author: Evan You vite-plugin-vuetify 2.1.3 License: MIT Author: Kael Watts-Deuchar -vitest 4.1.5 +vitest 4.1.10 License: MIT Author: Anthony Fu -vscode-uri 3.1.0 +vscode-uri 3.0.8 License: MIT Author: Microsoft -vue 3.5.39 +vue 3.5.40 License: MIT Author: Evan You -vue-component-type-helpers 3.3.5 +vue-component-type-helpers 3.0.0 License: MIT Author: — vue-eslint-parser 10.4.1 License: MIT Author: Toru Nagashima -vue-i18n 11.4.6 +vue-i18n 11.4.7 License: MIT Author: kazuya kawaguchi vue-router 4.6.4 License: MIT Author: Eduardo San Martin Morote -vue-tsc 3.3.6 +vue-tsc 3.3.7 License: MIT Author: — -vuetify 3.12.8 +vuetify 3.12.10 License: MIT Author: John Leider w3c-xmlserializer 5.0.0 @@ -1999,31 +1894,22 @@ whatwg-url 16.0.1 which 2.0.1 License: ISC Author: GitHub Inc. -which-boxed-primitive 1.1.0 - License: MIT - Author: Jordan Harband -which-builtin-type 1.2.1 - License: MIT - Author: Jordan Harband -which-collection 1.0.2 - License: MIT - Author: Jordan Harband which-module 2.0.0 License: ISC Author: nexdrew -which-typed-array 1.1.22 - License: MIT - Author: Jordan Harband why-is-node-running 2.3.0 License: MIT Author: Mathias Buus +word-wrap 1.2.5 + License: MIT + Author: Jon Schlinkert wrap-ansi 2.0.0 License: MIT Author: Sindre Sorhus -wrappy 1.0.2 +wrappy 1.0.0 License: ISC Author: Isaac Z. Schlueter -xml-name-validator 4.0.0 +xml-name-validator 5.0.0 License: Apache-2.0 Author: Domenic Denicola xml-utils 1.10.2 diff --git a/meshchatx/src/backend/data/licenses_backend.json b/meshchatx/src/backend/data/licenses_backend.json index ef16fc96..f372a171 100644 --- a/meshchatx/src/backend/data/licenses_backend.json +++ b/meshchatx/src/backend/data/licenses_backend.json @@ -8,7 +8,7 @@ { "name": "aiohttp", "version": "3.14.1", - "author": "\u2014", + "author": "—", "license": "Apache-2.0 AND MIT" }, { @@ -32,7 +32,7 @@ { "name": "audioop-lts", "version": "0.2.2", - "author": "\u2014", + "author": "—", "license": "PSF-2.0" }, { @@ -50,7 +50,7 @@ { "name": "cbor2", "version": "6.1.1", - "author": "Alex Gr\u00f6nholm ", + "author": "Alex Grönholm ", "license": "MIT" }, { @@ -91,16 +91,10 @@ }, { "name": "lxmfy", - "version": "1.6.5", + "version": "2.0.1", "author": "Quad4 ", "license": "BSD-0-Clause" }, - { - "name": "rns-filesync", - "version": "1.0.0", - "author": "Sudo-Ivan / Quad4.io", - "license": "BSD-2-Clause" - }, { "name": "lxst", "version": "0.5.0", @@ -173,6 +167,12 @@ "author": "Mark Qvist", "license": "Reticulum License" }, + { + "name": "rns-filesync", + "version": "1.0.0", + "author": "—", + "license": "BSD-2-Clause" + }, { "name": "wasmtime", "version": "46.0.1", diff --git a/meshchatx/src/backend/data/licenses_frontend.json b/meshchatx/src/backend/data/licenses_frontend.json index 98c0be7f..e646aea6 100644 --- a/meshchatx/src/backend/data/licenses_frontend.json +++ b/meshchatx/src/backend/data/licenses_frontend.json @@ -1,10 +1,4 @@ [ - { - "name": "@aashutoshrathi/word-wrap", - "version": "1.2.6", - "author": "Jon Schlinkert", - "license": "MIT" - }, { "name": "@asamuzakjp/css-color", "version": "5.1.11", @@ -91,7 +85,7 @@ }, { "name": "@csstools/css-syntax-patches-for-csstree", - "version": "1.1.6", + "version": "1.1.3", "author": "—", "license": "MIT-0" }, @@ -109,7 +103,7 @@ }, { "name": "@electron-internal/extract-zip", - "version": "1.0.4", + "version": "1.0.1", "author": "—", "license": "BSD-2-Clause" }, @@ -145,7 +139,7 @@ }, { "name": "@electron/rebuild", - "version": "4.0.6", + "version": "4.0.4", "author": "—", "license": "MIT" }, @@ -169,13 +163,13 @@ }, { "name": "@eslint-community/eslint-utils", - "version": "4.4.0", + "version": "4.8.0", "author": "Toru Nagashima", "license": "MIT" }, { "name": "@eslint-community/regexpp", - "version": "4.12.1", + "version": "4.12.2", "author": "Toru Nagashima", "license": "MIT" }, @@ -199,13 +193,13 @@ }, { "name": "@eslint/eslintrc", - "version": "3.3.5", + "version": "3.3.6", "author": "Nicholas C. Zakas", "license": "MIT" }, { "name": "@eslint/js", - "version": "9.39.4", + "version": "9.39.5", "author": "—", "license": "MIT" }, @@ -229,19 +223,31 @@ }, { "name": "@fontsource/noto-sans", - "version": "5.2.10", + "version": "5.3.0", "author": "Google Inc.", "license": "OFL-1.1" }, + { + "name": "@gar/promise-retry", + "version": "1.0.3", + "author": "—", + "license": "MIT" + }, { "name": "@humanfs/core", - "version": "0.19.1", + "version": "0.19.2", "author": "Nicholas C. Zakas", "license": "Apache-2.0" }, { "name": "@humanfs/node", - "version": "0.16.6", + "version": "0.16.8", + "author": "Nicholas C. Zakas", + "license": "Apache-2.0" + }, + { + "name": "@humanfs/types", + "version": "0.15.0", "author": "Nicholas C. Zakas", "license": "Apache-2.0" }, @@ -253,31 +259,31 @@ }, { "name": "@humanwhocodes/retry", - "version": "0.3.0", + "version": "0.4.3", "author": "Nicholas C. Zaks", "license": "Apache-2.0" }, { "name": "@intlify/core-base", - "version": "11.4.6", + "version": "11.4.7", "author": "kazuya kawaguchi", "license": "MIT" }, { "name": "@intlify/devtools-types", - "version": "11.4.6", + "version": "11.4.7", "author": "kazuya kawaguchi", "license": "MIT" }, { "name": "@intlify/message-compiler", - "version": "11.4.6", + "version": "11.4.7", "author": "kazuya kawaguchi", "license": "MIT" }, { "name": "@intlify/shared", - "version": "11.4.6", + "version": "11.4.7", "author": "kazuya kawaguchi", "license": "MIT" }, @@ -287,12 +293,6 @@ "author": "Ben Coe", "license": "ISC" }, - { - "name": "@isaacs/cliui", - "version": "9.0.0", - "author": "—", - "license": "BlueOak-1.0.0" - }, { "name": "@isaacs/fs-minipass", "version": "4.0.0", @@ -341,12 +341,6 @@ "author": "Justin Ridgewell", "license": "MIT" }, - { - "name": "@keyv/serialize", - "version": "1.1.1", - "author": "Jared Wray", - "license": "MIT" - }, { "name": "@malept/cross-spawn-promise", "version": "2.0.0", @@ -361,19 +355,19 @@ }, { "name": "@mapbox/jsonlint-lines-primitives", - "version": "2.0.3", + "version": "2.0.2", "author": "Zach Carter", - "license": "MIT" + "license": "Unknown" }, { "name": "@mapbox/unitbezier", - "version": "1.0.0", + "version": "0.0.1", "author": "—", "license": "BSD-2-Clause" }, { "name": "@maplibre/maplibre-gl-style-spec", - "version": "24.10.0", + "version": "24.4.1", "author": "MapLibre", "license": "ISC" }, @@ -395,6 +389,24 @@ "author": "Paul Miller", "license": "MIT" }, + { + "name": "@npmcli/agent", + "version": "4.0.2", + "author": "GitHub Inc.", + "license": "ISC" + }, + { + "name": "@npmcli/fs", + "version": "5.0.0", + "author": "GitHub Inc.", + "license": "ISC" + }, + { + "name": "@npmcli/redact", + "version": "4.0.0", + "author": "GitHub Inc.", + "license": "ISC" + }, { "name": "@one-ini/wasm", "version": "0.1.1", @@ -403,25 +415,25 @@ }, { "name": "@oxc-parser/binding-linux-x64-gnu", - "version": "0.137.0", + "version": "0.140.0", "author": "Boshen and oxc contributors", "license": "MIT" }, { "name": "@oxc-project/types", - "version": "0.133.0", + "version": "0.139.0", "author": "Boshen and oxc contributors", "license": "MIT" }, { "name": "@oxc-resolver/binding-linux-x64-gnu", - "version": "11.21.3", + "version": "11.24.2", "author": "—", "license": "MIT" }, { "name": "@peculiar/asn1-schema", - "version": "2.8.0", + "version": "2.7.0", "author": "PeculiarVentures, LLC", "license": "MIT" }, @@ -475,7 +487,7 @@ }, { "name": "@rolldown/binding-linux-x64-gnu", - "version": "1.0.3", + "version": "1.1.5", "author": "—", "license": "MIT" }, @@ -485,15 +497,9 @@ "author": "—", "license": "MIT" }, - { - "name": "@sec-ant/readable-stream", - "version": "0.4.1", - "author": "Ze-Zheng Wu", - "license": "MIT" - }, { "name": "@sindresorhus/is", - "version": "8.1.0", + "version": "4.0.0", "author": "Sindre Sorhus", "license": "MIT" }, @@ -503,6 +509,12 @@ "author": "Colin McDonnell", "license": "MIT" }, + { + "name": "@szmarczak/http-timer", + "version": "4.0.5", + "author": "Szymon Marczak", + "license": "MIT" + }, { "name": "@tailwindcss/forms", "version": "0.5.11", @@ -511,55 +523,61 @@ }, { "name": "@tailwindcss/node", - "version": "4.2.4", + "version": "4.3.3", "author": "—", "license": "MIT" }, { "name": "@tailwindcss/oxide", - "version": "4.2.4", + "version": "4.3.3", "author": "—", "license": "MIT" }, { "name": "@tailwindcss/oxide-linux-x64-gnu", - "version": "4.2.4", + "version": "4.3.3", "author": "—", "license": "MIT" }, { "name": "@tailwindcss/vite", - "version": "4.2.4", + "version": "4.3.3", "author": "—", "license": "MIT" }, { "name": "@tanstack/virtual-core", - "version": "3.17.2", + "version": "3.17.6", "author": "Tanner Linsley", "license": "MIT" }, { "name": "@tanstack/vue-virtual", - "version": "3.13.30", + "version": "3.13.34", "author": "Tanner Linsley", "license": "MIT" }, + { + "name": "@types/cacheable-request", + "version": "6.0.1", + "author": "—", + "license": "MIT" + }, { "name": "@types/chai", - "version": "5.2.2", + "version": "5.2.3", "author": "—", "license": "MIT" }, { "name": "@types/debug", - "version": "4.1.13", + "version": "4.1.6", "author": "—", "license": "MIT" }, { "name": "@types/deep-eql", - "version": "4.0.0", + "version": "4.0.2", "author": "—", "license": "MIT" }, @@ -577,13 +595,13 @@ }, { "name": "@types/hammerjs", - "version": "2.0.36", + "version": "2.0.46", "author": "—", "license": "MIT" }, { "name": "@types/http-cache-semantics", - "version": "4.2.0", + "version": "4.0.0", "author": "—", "license": "MIT" }, @@ -594,8 +612,8 @@ "license": "MIT" }, { - "name": "@types/ms", - "version": "2.1.0", + "name": "@types/keyv", + "version": "3.0.0", "author": "—", "license": "MIT" }, @@ -611,6 +629,12 @@ "author": "—", "license": "MIT" }, + { + "name": "@types/responselike", + "version": "1.0.0", + "author": "—", + "license": "MIT" + }, { "name": "@types/trusted-types", "version": "2.0.7", @@ -619,61 +643,61 @@ }, { "name": "@vitejs/plugin-vue", - "version": "6.0.7", + "version": "6.0.8", "author": "Evan You", "license": "MIT" }, { "name": "@vitest/coverage-v8", - "version": "4.1.5", + "version": "4.1.10", "author": "Anthony Fu", "license": "MIT" }, { "name": "@vitest/expect", - "version": "4.1.5", + "version": "4.1.10", "author": "—", "license": "MIT" }, { "name": "@vitest/mocker", - "version": "4.1.5", + "version": "4.1.10", "author": "—", "license": "MIT" }, { "name": "@vitest/pretty-format", - "version": "4.1.5", + "version": "4.1.10", "author": "—", "license": "MIT" }, { "name": "@vitest/runner", - "version": "4.1.5", + "version": "4.1.10", "author": "—", "license": "MIT" }, { "name": "@vitest/snapshot", - "version": "4.1.5", + "version": "4.1.10", "author": "—", "license": "MIT" }, { "name": "@vitest/spy", - "version": "4.1.5", + "version": "4.1.10", "author": "—", "license": "MIT" }, { "name": "@vitest/ui", - "version": "4.1.9", + "version": "4.1.10", "author": "—", "license": "MIT" }, { "name": "@vitest/utils", - "version": "4.1.5", + "version": "4.1.10", "author": "—", "license": "MIT" }, @@ -697,67 +721,67 @@ }, { "name": "@vue/compiler-core", - "version": "3.5.39", + "version": "3.5.40", "author": "Evan You", "license": "MIT" }, { "name": "@vue/compiler-dom", - "version": "3.5.39", + "version": "3.5.40", "author": "Evan You", "license": "MIT" }, { "name": "@vue/compiler-sfc", - "version": "3.5.39", + "version": "3.5.40", "author": "Evan You", "license": "MIT" }, { "name": "@vue/compiler-ssr", - "version": "3.5.39", + "version": "3.5.40", "author": "Evan You", "license": "MIT" }, { "name": "@vue/devtools-api", - "version": "6.6.4", + "version": "6.5.0", "author": "Guillaume Chau", "license": "MIT" }, { "name": "@vue/language-core", - "version": "3.3.6", + "version": "3.3.7", "author": "—", "license": "MIT" }, { "name": "@vue/reactivity", - "version": "3.5.39", + "version": "3.5.40", "author": "Evan You", "license": "MIT" }, { "name": "@vue/runtime-core", - "version": "3.5.39", + "version": "3.5.40", "author": "Evan You", "license": "MIT" }, { "name": "@vue/runtime-dom", - "version": "3.5.39", + "version": "3.5.40", "author": "Evan You", "license": "MIT" }, { "name": "@vue/server-renderer", - "version": "3.5.39", + "version": "3.5.40", "author": "Evan You", "license": "MIT" }, { "name": "@vue/shared", - "version": "3.5.39", + "version": "3.5.40", "author": "Evan You", "license": "MIT" }, @@ -781,10 +805,16 @@ }, { "name": "abbrev", - "version": "2.0.0", + "version": "4.0.0", "author": "GitHub Inc.", "license": "ISC" }, + { + "name": "abbrev", + "version": "1.0.3", + "author": "Isaac Z. Schlueter", + "license": "Unknown" + }, { "name": "acorn", "version": "0.11.0", @@ -815,6 +845,12 @@ "author": "—", "license": "MIT" }, + { + "name": "amdefine", + "version": "1.0.1", + "author": "James Burke", + "license": "BSD-3-Clause OR MIT" + }, { "name": "ansi-regex", "version": "5.0.1", @@ -839,27 +875,21 @@ "author": "—", "license": "Python-2.0" }, - { - "name": "array-buffer-byte-length", - "version": "1.0.2", - "author": "Jordan Harband", - "license": "MIT" - }, - { - "name": "arraybuffer.prototype.slice", - "version": "1.0.4", - "author": "Jordan Harband", - "license": "MIT" - }, { "name": "asn1js", "version": "3.0.10", "author": "Yury Strozhevsky", "license": "BSD-3-Clause" }, + { + "name": "assertion-error", + "version": "2.0.1", + "author": "Jake Luer", + "license": "MIT" + }, { "name": "ast-types", - "version": "0.8.15", + "version": "0.6.12", "author": "Ben Newman", "license": "MIT" }, @@ -871,7 +901,7 @@ }, { "name": "async", - "version": "3.2.6", + "version": "3.2.3", "author": "Caolan McMahon", "license": "MIT" }, @@ -881,12 +911,6 @@ "author": "Tapani Moilanen", "license": "MIT" }, - { - "name": "async-function", - "version": "1.0.0", - "author": "Jordan Harbamd", - "license": "MIT" - }, { "name": "asynckit", "version": "0.4.0", @@ -899,12 +923,6 @@ "author": "Ryan Zimmerman", "license": "ISC" }, - { - "name": "available-typed-arrays", - "version": "1.0.7", - "author": "Jordan Harband", - "license": "MIT" - }, { "name": "aws4", "version": "1.13.2", @@ -949,7 +967,7 @@ }, { "name": "boolean", - "version": "3.2.0", + "version": "3.0.1", "author": "—", "license": "MIT" }, @@ -977,51 +995,39 @@ "author": "Vladimir Krivosheev", "license": "MIT" }, - { - "name": "byte-counter", - "version": "0.1.0", - "author": "Sindre Sorhus", - "license": "MIT" - }, { "name": "bytestreamjs", "version": "2.0.1", "author": "Yury Strozhevsky", "license": "BSD-3-Clause" }, + { + "name": "cacache", + "version": "20.0.4", + "author": "GitHub Inc.", + "license": "ISC" + }, { "name": "cacheable-lookup", - "version": "7.0.0", + "version": "5.0.3", "author": "Szymon Marczak", "license": "MIT" }, { "name": "cacheable-request", - "version": "13.0.19", - "author": "Jared Wray", - "license": "MIT" - }, - { - "name": "call-bind", - "version": "1.0.9", - "author": "Jordan Harband", + "version": "7.0.2", + "author": "Luke Childs", "license": "MIT" }, { "name": "call-bind-apply-helpers", - "version": "1.0.0", - "author": "Jordan Harband", - "license": "MIT" - }, - { - "name": "call-bound", - "version": "1.0.4", + "version": "1.0.1", "author": "Jordan Harband", "license": "MIT" }, { "name": "callsites", - "version": "3.0.0", + "version": "3.1.0", "author": "Sindre Sorhus", "license": "MIT" }, @@ -1039,7 +1045,7 @@ }, { "name": "chalk", - "version": "4.0.0", + "version": "4.1.1", "author": "—", "license": "MIT" }, @@ -1055,15 +1061,9 @@ "author": "—", "license": "MIT" }, - { - "name": "chunk-data", - "version": "0.1.0", - "author": "Sindre Sorhus", - "license": "MIT" - }, { "name": "ci-info", - "version": "4.3.1", + "version": "4.2.0", "author": "Thomas Watson Steen", "license": "MIT" }, @@ -1079,6 +1079,12 @@ "author": "Ben Coe", "license": "ISC" }, + { + "name": "clone-response", + "version": "1.0.2", + "author": "Luke Childs", + "license": "MIT" + }, { "name": "code-point-at", "version": "1.0.0", @@ -1199,24 +1205,6 @@ "author": "Domenic Denicola", "license": "MIT" }, - { - "name": "data-view-buffer", - "version": "1.0.2", - "author": "Jordan Harband", - "license": "MIT" - }, - { - "name": "data-view-byte-length", - "version": "1.0.2", - "author": "Jordan Harband", - "license": "MIT" - }, - { - "name": "data-view-byte-offset", - "version": "1.0.1", - "author": "Jordan Harband", - "license": "MIT" - }, { "name": "dayjs", "version": "1.11.21", @@ -1226,7 +1214,7 @@ { "name": "debug", "version": "4.3.1", - "author": "TJ Holowaychuk", + "author": "Josh Junon", "license": "MIT" }, { @@ -1243,25 +1231,25 @@ }, { "name": "decompress-response", - "version": "10.0.0", + "version": "6.0.0", "author": "Sindre Sorhus", "license": "MIT" }, { "name": "deep-is", - "version": "0.1.3", + "version": "0.1.4", "author": "Thorsten Lorenz", "license": "MIT" }, { - "name": "define-data-property", - "version": "1.1.4", - "author": "Jordan Harband", + "name": "defer-to-connect", + "version": "2.0.0", + "author": "Szymon Marczak", "license": "MIT" }, { "name": "define-properties", - "version": "1.2.1", + "version": "1.1.2", "author": "Jordan Harband", "license": "MIT" }, @@ -1279,9 +1267,9 @@ }, { "name": "detect-node", - "version": "2.1.0", + "version": "2.0.4", "author": "Ilya Kantor", - "license": "MIT" + "license": "ISC" }, { "name": "dijkstrajs", @@ -1303,7 +1291,7 @@ }, { "name": "dompurify", - "version": "3.4.11", + "version": "3.4.12", "author": "Dr.-Ing. Mario Heiderich, Cure53", "license": "(MPL-2.0 OR Apache-2.0)" }, @@ -1315,7 +1303,7 @@ }, { "name": "dotenv-expand", - "version": "11.0.7", + "version": "11.0.6", "author": "motdotla", "license": "BSD-2-Clause" }, @@ -1333,8 +1321,8 @@ }, { "name": "earcut", - "version": "3.1.0", - "author": "Volodymyr Agafonkin", + "version": "3.0.0", + "author": "Vladimir Agafonkin", "license": "ISC" }, { @@ -1345,7 +1333,7 @@ }, { "name": "editorconfig", - "version": "1.0.7", + "version": "1.0.3", "author": "EditorConfig Team", "license": "MIT" }, @@ -1409,9 +1397,15 @@ "author": "Mathias Bynens", "license": "MIT" }, + { + "name": "end-of-stream", + "version": "1.1.0", + "author": "Mathias Buus", + "license": "MIT" + }, { "name": "enhanced-resolve", - "version": "5.19.0", + "version": "5.24.1", "author": "Tobias Koppers @sokra", "license": "MIT" }, @@ -1429,19 +1423,13 @@ }, { "name": "err-code", - "version": "2.0.3", + "version": "2.0.2", "author": "IndigoUnited", "license": "MIT" }, { "name": "es-abstract", - "version": "1.24.2", - "author": "Jordan Harband", - "license": "MIT" - }, - { - "name": "es-abstract-get", - "version": "1.0.0", + "version": "1.5.0", "author": "Jordan Harband", "license": "MIT" }, @@ -1459,7 +1447,7 @@ }, { "name": "es-module-lexer", - "version": "2.2.0", + "version": "2.0.0", "author": "Guy Bedford", "license": "MIT" }, @@ -1477,7 +1465,7 @@ }, { "name": "es-to-primitive", - "version": "1.3.4", + "version": "1.1.0", "author": "Jordan Harband", "license": "MIT" }, @@ -1501,7 +1489,7 @@ }, { "name": "eslint", - "version": "9.39.4", + "version": "9.39.5", "author": "Nicholas C. Zakas", "license": "MIT" }, @@ -1525,7 +1513,7 @@ }, { "name": "eslint-plugin-vue", - "version": "10.9.2", + "version": "10.10.0", "author": "Toru Nagashima", "license": "MIT" }, @@ -1537,7 +1525,7 @@ }, { "name": "eslint-visitor-keys", - "version": "3.3.0", + "version": "3.4.3", "author": "Toru Nagashima", "license": "Apache-2.0" }, @@ -1555,13 +1543,13 @@ }, { "name": "esprima-fb", - "version": "15001.1001.0-dev-harmony-fb", + "version": "12001.1.0-dev-harmony-fb", "author": "Ariya Hidayat", "license": "BSD" }, { "name": "esquery", - "version": "1.5.0", + "version": "1.6.0", "author": "Joel Feenstra", "license": "BSD-3-Clause" }, @@ -1585,9 +1573,9 @@ }, { "name": "esutils", - "version": "2.0.2", + "version": "2.0.3", "author": "—", - "license": "BSD" + "license": "BSD-2-Clause" }, { "name": "execa", @@ -1627,13 +1615,13 @@ }, { "name": "fast-diff", - "version": "1.3.0", + "version": "1.1.2", "author": "Jason Chen", "license": "Apache-2.0" }, { "name": "fast-json-stable-stringify", - "version": "2.0.0", + "version": "2.1.0", "author": "James Halliday", "license": "MIT" }, @@ -1645,7 +1633,7 @@ }, { "name": "fast-uri", - "version": "3.1.2", + "version": "4.1.1", "author": "Vincent Le Goff", "license": "BSD-3-Clause" }, @@ -1687,7 +1675,7 @@ }, { "name": "flat-cache", - "version": "4.0.0", + "version": "4.0.1", "author": "Jared Wray", "license": "MIT" }, @@ -1699,10 +1687,16 @@ }, { "name": "for-each", - "version": "0.3.5", + "version": "0.3.3", "author": "Raynos", "license": "MIT" }, + { + "name": "foreach", + "version": "2.0.6", + "author": "Manuel Stofer", + "license": "MIT" + }, { "name": "foreground-child", "version": "3.1.0", @@ -1727,6 +1721,12 @@ "author": "JP Richardson", "license": "MIT" }, + { + "name": "fs-minipass", + "version": "3.0.3", + "author": "GitHub Inc.", + "license": "ISC" + }, { "name": "fs.realpath", "version": "1.0.0", @@ -1735,28 +1735,10 @@ }, { "name": "function-bind", - "version": "1.1.1", + "version": "1.0.2", "author": "Raynos", "license": "MIT" }, - { - "name": "function.prototype.name", - "version": "1.2.0", - "author": "Jordan Harband", - "license": "MIT" - }, - { - "name": "functions-have-names", - "version": "1.2.3", - "author": "Jordan Harband", - "license": "MIT" - }, - { - "name": "generator-function", - "version": "2.0.0", - "author": "Jordan Harbamd", - "license": "MIT" - }, { "name": "geotiff", "version": "3.0.5", @@ -1771,13 +1753,7 @@ }, { "name": "get-intrinsic", - "version": "1.1.3", - "author": "Jordan Harband", - "license": "MIT" - }, - { - "name": "get-proto", - "version": "1.0.1", + "version": "1.2.6", "author": "Jordan Harband", "license": "MIT" }, @@ -1787,12 +1763,6 @@ "author": "Sindre Sorhus", "license": "MIT" }, - { - "name": "get-symbol-description", - "version": "1.1.0", - "author": "Jordan Harband", - "license": "MIT" - }, { "name": "get-tsconfig", "version": "4.14.0", @@ -1825,19 +1795,19 @@ }, { "name": "globalthis", - "version": "1.0.4", - "author": "Jordan Harband", - "license": "MIT" - }, - { - "name": "gopd", "version": "1.0.1", "author": "Jordan Harband", "license": "MIT" }, + { + "name": "gopd", + "version": "1.2.0", + "author": "Jordan Harband", + "license": "MIT" + }, { "name": "got", - "version": "15.0.7", + "version": "11.8.6", "author": "—", "license": "MIT" }, @@ -1847,36 +1817,12 @@ "author": "—", "license": "ISC" }, - { - "name": "has", - "version": "1.0.3", - "author": "Thiago de Arruda", - "license": "MIT" - }, - { - "name": "has-bigints", - "version": "1.1.0", - "author": "Jordan Harband", - "license": "MIT" - }, { "name": "has-flag", "version": "4.0.0", "author": "Sindre Sorhus", "license": "MIT" }, - { - "name": "has-property-descriptors", - "version": "1.0.2", - "author": "Jordan Harband", - "license": "MIT" - }, - { - "name": "has-proto", - "version": "1.2.0", - "author": "Jordan Harband", - "license": "MIT" - }, { "name": "has-symbols", "version": "1.0.3", @@ -1891,14 +1837,14 @@ }, { "name": "hasown", - "version": "2.0.2", + "version": "2.0.4", "author": "Jordan Harband", "license": "MIT" }, { "name": "hosted-git-info", - "version": "10.1.1", - "author": "GitHub Inc.", + "version": "2.8.9", + "author": "Rebecca Turner", "license": "ISC" }, { @@ -1927,7 +1873,7 @@ }, { "name": "http2-wrapper", - "version": "2.2.1", + "version": "1.0.0-beta.5.2", "author": "Szymon Marczak", "license": "MIT" }, @@ -1937,9 +1883,15 @@ "author": "Nathan Rajlich", "license": "MIT" }, + { + "name": "iconv-lite", + "version": "0.7.2", + "author": "Alexander Shtuchkin", + "license": "MIT" + }, { "name": "ignore", - "version": "5.2.0", + "version": "5.3.2", "author": "kael", "license": "MIT" }, @@ -1951,7 +1903,7 @@ }, { "name": "import-fresh", - "version": "3.2.1", + "version": "3.3.1", "author": "Sindre Sorhus", "license": "MIT" }, @@ -1991,12 +1943,6 @@ "author": "Calvin W. Metcalf", "license": "MIT" }, - { - "name": "internal-slot", - "version": "1.1.0", - "author": "Jordan Harband", - "license": "MIT" - }, { "name": "invert-kv", "version": "2.0.0", @@ -2004,21 +1950,9 @@ "license": "MIT" }, { - "name": "is-array-buffer", - "version": "3.0.5", - "author": "Jordan Harband", - "license": "MIT" - }, - { - "name": "is-async-function", - "version": "2.1.1", - "author": "Jordan Harband", - "license": "MIT" - }, - { - "name": "is-bigint", - "version": "1.1.0", - "author": "Jordan Harband", + "name": "ip-address", + "version": "9.0.5", + "author": "Beau Gunderson", "license": "MIT" }, { @@ -2027,33 +1961,15 @@ "author": "Sindre Sorhus", "license": "MIT" }, - { - "name": "is-boolean-object", - "version": "1.2.0", - "author": "Jordan Harband", - "license": "MIT" - }, { "name": "is-callable", - "version": "1.2.7", - "author": "Jordan Harband", - "license": "MIT" - }, - { - "name": "is-data-view", - "version": "1.0.2", + "version": "1.1.1", "author": "Jordan Harband", "license": "MIT" }, { "name": "is-date-object", - "version": "1.1.0", - "author": "Jordan Harband", - "license": "MIT" - }, - { - "name": "is-document.all", - "version": "1.0.0", + "version": "1.0.1", "author": "Jordan Harband", "license": "MIT" }, @@ -2063,48 +1979,18 @@ "author": "Jon Schlinkert", "license": "MIT" }, - { - "name": "is-finalizationregistry", - "version": "1.1.1", - "author": "Jordan Harband", - "license": "MIT" - }, { "name": "is-fullwidth-code-point", "version": "1.0.0", "author": "Sindre Sorhus", "license": "MIT" }, - { - "name": "is-generator-function", - "version": "1.1.2", - "author": "Jordan Harband", - "license": "MIT" - }, { "name": "is-glob", - "version": "4.0.0", + "version": "4.0.3", "author": "Jon Schlinkert", "license": "MIT" }, - { - "name": "is-map", - "version": "2.0.3", - "author": "Jordan Harband", - "license": "MIT" - }, - { - "name": "is-negative-zero", - "version": "2.0.3", - "author": "Jordan Harband", - "license": "MIT" - }, - { - "name": "is-number-object", - "version": "1.1.0", - "author": "Jordan Harband", - "license": "MIT" - }, { "name": "is-potential-custom-element-name", "version": "1.0.1", @@ -2113,19 +1999,7 @@ }, { "name": "is-regex", - "version": "1.2.1", - "author": "Jordan Harband", - "license": "MIT" - }, - { - "name": "is-set", - "version": "2.0.3", - "author": "Jordan Harband", - "license": "MIT" - }, - { - "name": "is-shared-array-buffer", - "version": "1.0.4", + "version": "1.0.3", "author": "Jordan Harband", "license": "MIT" }, @@ -2135,39 +2009,9 @@ "author": "Sindre Sorhus", "license": "MIT" }, - { - "name": "is-string", - "version": "1.1.1", - "author": "Jordan Harband", - "license": "MIT" - }, { "name": "is-symbol", - "version": "1.1.0", - "author": "Jordan Harband", - "license": "MIT" - }, - { - "name": "is-typed-array", - "version": "1.1.15", - "author": "Jordan Harband", - "license": "MIT" - }, - { - "name": "is-weakmap", - "version": "2.0.2", - "author": "Jordan Harband", - "license": "MIT" - }, - { - "name": "is-weakref", - "version": "1.1.1", - "author": "Jordan Harband", - "license": "MIT" - }, - { - "name": "is-weakset", - "version": "2.0.4", + "version": "1.0.1", "author": "Jordan Harband", "license": "MIT" }, @@ -2189,6 +2033,12 @@ "author": "Isaac Z. Schlueter", "license": "ISC" }, + { + "name": "isexe", + "version": "3.1.5", + "author": "Isaac Z. Schlueter", + "license": "BlueOak-1.0.0" + }, { "name": "istanbul-lib-coverage", "version": "3.2.2", @@ -2227,16 +2077,10 @@ }, { "name": "js-beautify", - "version": "1.15.4", + "version": "1.14.9", "author": "Einar Lielmanis", "license": "MIT" }, - { - "name": "js-cookie", - "version": "3.0.8", - "author": "Klaus Hartl", - "license": "MIT" - }, { "name": "js-tokens", "version": "10.0.0", @@ -2249,6 +2093,12 @@ "author": "Vladimir Zapparov", "license": "MIT" }, + { + "name": "jsbn", + "version": "1.1.0", + "author": "Tom Wu", + "license": "MIT" + }, { "name": "jsdom", "version": "29.1.1", @@ -2317,13 +2167,13 @@ }, { "name": "keyv", - "version": "4.5.4", + "version": "4.0.0", "author": "Jared Wray", "license": "MIT" }, { "name": "knip", - "version": "6.24.0", + "version": "6.29.0", "author": "Lars Kappert", "license": "ISC" }, @@ -2389,7 +2239,7 @@ }, { "name": "lowercase-keys", - "version": "3.0.0", + "version": "2.0.0", "author": "Sindre Sorhus", "license": "MIT" }, @@ -2423,6 +2273,12 @@ "author": "Sindre Sorhus", "license": "MIT" }, + { + "name": "make-fetch-happen", + "version": "15.0.6", + "author": "GitHub Inc.", + "license": "ISC" + }, { "name": "mapbox-to-css-font", "version": "3.2.0", @@ -2431,7 +2287,7 @@ }, { "name": "marked", - "version": "18.0.5", + "version": "18.0.7", "author": "Christopher Jeffrey", "license": "MIT" }, @@ -2467,7 +2323,7 @@ }, { "name": "mime", - "version": "2.6.0", + "version": "2.5.2", "author": "Robert Kieffer", "license": "MIT" }, @@ -2485,13 +2341,13 @@ }, { "name": "mimic-fn", - "version": "1.2.0", + "version": "1.0.0", "author": "Sindre Sorhus", "license": "MIT" }, { "name": "mimic-response", - "version": "4.0.0", + "version": "1.0.0", "author": "Sindre Sorhus", "license": "MIT" }, @@ -2521,22 +2377,46 @@ }, { "name": "minipass", - "version": "7.1.2", + "version": "3.0.0", + "author": "Isaac Z. Schlueter", + "license": "ISC" + }, + { + "name": "minipass-collect", + "version": "2.0.1", + "author": "Isaac Z. Schlueter", + "license": "ISC" + }, + { + "name": "minipass-fetch", + "version": "5.0.2", + "author": "GitHub Inc.", + "license": "MIT" + }, + { + "name": "minipass-flush", + "version": "1.0.7", + "author": "Isaac Z. Schlueter", + "license": "BlueOak-1.0.0" + }, + { + "name": "minipass-pipeline", + "version": "1.2.4", + "author": "Isaac Z. Schlueter", + "license": "ISC" + }, + { + "name": "minipass-sized", + "version": "2.0.0", "author": "Isaac Z. Schlueter", "license": "ISC" }, { "name": "minizlib", - "version": "3.1.0", + "version": "3.0.1", "author": "Isaac Z. Schlueter", "license": "MIT" }, - { - "name": "mkdirp", - "version": "0.5.1", - "author": "James Halliday", - "license": "MIT" - }, { "name": "mrmime", "version": "2.0.0", @@ -2567,9 +2447,15 @@ "author": "Lauri Rooden", "license": "MIT" }, + { + "name": "negotiator", + "version": "1.0.0", + "author": "—", + "license": "MIT" + }, { "name": "node-abi", - "version": "4.31.0", + "version": "4.2.0", "author": "Lukas Geiger", "license": "MIT" }, @@ -2581,7 +2467,7 @@ }, { "name": "node-gyp", - "version": "12.4.0", + "version": "12.2.0", "author": "Nathan Rajlich", "license": "MIT" }, @@ -2593,19 +2479,19 @@ }, { "name": "nopt", - "version": "7.2.1", + "version": "6.0.0", "author": "GitHub Inc.", "license": "ISC" }, { "name": "normalize-url", - "version": "8.1.1", + "version": "6.0.1", "author": "Sindre Sorhus", "license": "MIT" }, { "name": "npm-run-path", - "version": "2.0.2", + "version": "2.0.0", "author": "Sindre Sorhus", "license": "MIT" }, @@ -2633,21 +2519,9 @@ "author": "Sindre Sorhus", "license": "MIT" }, - { - "name": "object-inspect", - "version": "1.13.4", - "author": "James Halliday", - "license": "MIT" - }, { "name": "object-keys", - "version": "1.1.1", - "author": "Jordan Harband", - "license": "MIT" - }, - { - "name": "object.assign", - "version": "4.1.7", + "version": "1.0.8", "author": "Jordan Harband", "license": "MIT" }, @@ -2671,13 +2545,13 @@ }, { "name": "once", - "version": "1.4.0", + "version": "1.3.0", "author": "Isaac Z. Schlueter", - "license": "ISC" + "license": "BSD" }, { "name": "optionator", - "version": "0.9.3", + "version": "0.9.4", "author": "George Zahariev", "license": "MIT" }, @@ -2687,24 +2561,24 @@ "author": "Sindre Sorhus", "license": "MIT" }, - { - "name": "own-keys", - "version": "1.0.1", - "author": "Jordan Harband", - "license": "MIT" - }, { "name": "oxc-parser", - "version": "0.137.0", + "version": "0.140.0", "author": "Boshen and oxc contributors", "license": "MIT" }, { "name": "oxc-resolver", - "version": "11.21.3", + "version": "11.24.2", "author": "—", "license": "MIT" }, + { + "name": "p-cancelable", + "version": "2.0.0", + "author": "Sindre Sorhus", + "license": "MIT" + }, { "name": "p-finally", "version": "1.0.0", @@ -2729,6 +2603,12 @@ "author": "Sindre Sorhus", "license": "MIT" }, + { + "name": "p-map", + "version": "7.0.6", + "author": "Sindre Sorhus", + "license": "MIT" + }, { "name": "p-try", "version": "2.0.0", @@ -2755,7 +2635,7 @@ }, { "name": "parent-module", - "version": "1.0.0", + "version": "1.0.1", "author": "Sindre Sorhus", "license": "MIT" }, @@ -2815,7 +2695,7 @@ }, { "name": "pe-library", - "version": "0.4.1", + "version": "0.4.0", "author": "jet", "license": "MIT" }, @@ -2861,21 +2741,15 @@ "author": "—", "license": "MIT" }, - { - "name": "possible-typed-array-names", - "version": "1.1.0", - "author": "Jordan Harband", - "license": "MIT" - }, { "name": "postcss", - "version": "8.5.15", + "version": "8.5.19", "author": "Andrey Sitnik", "license": "MIT" }, { "name": "postcss-selector-parser", - "version": "7.1.0", + "version": "7.1.4", "author": "—", "license": "MIT" }, @@ -2893,7 +2767,7 @@ }, { "name": "prettier", - "version": "3.9.3", + "version": "3.9.6", "author": "James Long", "license": "MIT" }, @@ -2911,7 +2785,7 @@ }, { "name": "proc-log", - "version": "6.1.0", + "version": "6.0.0", "author": "GitHub Inc.", "license": "ISC" }, @@ -2941,9 +2815,9 @@ }, { "name": "proto-list", - "version": "1.2.4", + "version": "1.2.1", "author": "Isaac Z. Schlueter", - "license": "ISC" + "license": "MIT" }, { "name": "protocol-buffers-schema", @@ -2951,9 +2825,15 @@ "author": "Mathias Buus", "license": "MIT" }, + { + "name": "pump", + "version": "3.0.0", + "author": "Mathias Buus Madsen", + "license": "MIT" + }, { "name": "punycode", - "version": "2.1.0", + "version": "2.3.1", "author": "Mathias Bynens", "license": "MIT" }, @@ -2965,7 +2845,7 @@ }, { "name": "pvutils", - "version": "1.1.5", + "version": "1.1.3", "author": "Yury Strozhevsky", "license": "MIT" }, @@ -3007,7 +2887,7 @@ }, { "name": "recast", - "version": "0.10.43", + "version": "0.10.1", "author": "Ben Newman", "license": "MIT" }, @@ -3017,24 +2897,12 @@ "author": "manzt", "license": "MIT" }, - { - "name": "reflect.getprototypeof", - "version": "1.0.10", - "author": "Jordan Harband", - "license": "MIT" - }, { "name": "regexp-tree", "version": "0.1.1", "author": "Dmitry Soshnikov", "license": "MIT" }, - { - "name": "regexp.prototype.flags", - "version": "1.5.4", - "author": "Jordan Harband", - "license": "MIT" - }, { "name": "require-directory", "version": "2.1.1", @@ -3055,13 +2923,13 @@ }, { "name": "resedit", - "version": "1.7.2", + "version": "1.7.0", "author": "jet", "license": "MIT" }, { "name": "resolve-alpn", - "version": "1.2.1", + "version": "1.0.0", "author": "Szymon Marczak", "license": "MIT" }, @@ -3085,8 +2953,8 @@ }, { "name": "responselike", - "version": "4.0.2", - "author": "—", + "version": "2.0.0", + "author": "lukechilds", "license": "MIT" }, { @@ -3103,21 +2971,21 @@ }, { "name": "roarr", - "version": "2.15.4", + "version": "2.15.3", "author": "Gajus Kuizinas", "license": "BSD-3-Clause" }, { "name": "rolldown", - "version": "1.0.3", + "version": "1.1.5", "author": "—", "license": "MIT" }, { - "name": "safe-array-concat", - "version": "1.1.4", - "author": "Jordan Harband", - "license": "MIT" + "name": "rw", + "version": "1.3.3", + "author": "Mike Bostock", + "license": "BSD-3-Clause" }, { "name": "safe-buffer", @@ -3125,12 +2993,6 @@ "author": "Feross Aboukhadijeh", "license": "MIT" }, - { - "name": "safe-push-apply", - "version": "1.0.0", - "author": "Jordan Harband", - "license": "MIT" - }, { "name": "safe-regex", "version": "2.1.1", @@ -3138,14 +3000,14 @@ "license": "MIT" }, { - "name": "safe-regex-test", - "version": "1.1.0", - "author": "Jordan Harband", + "name": "safer-buffer", + "version": "2.1.2", + "author": "Nikita Skovoroda", "license": "MIT" }, { "name": "sanitize-filename", - "version": "1.6.4", + "version": "1.6.3", "author": "Parsha Pourkhomami", "license": "WTFPL OR ISC" }, @@ -3185,24 +3047,6 @@ "author": "Ben Coe", "license": "ISC" }, - { - "name": "set-function-length", - "version": "1.2.2", - "author": "Jordan Harband", - "license": "MIT" - }, - { - "name": "set-function-name", - "version": "2.0.2", - "author": "Jordan Harband", - "license": "MIT" - }, - { - "name": "set-proto", - "version": "1.0.0", - "author": "Jordan Harband", - "license": "MIT" - }, { "name": "setimmediate", "version": "1.0.5", @@ -3221,30 +3065,6 @@ "author": "Sindre Sorhus", "license": "MIT" }, - { - "name": "side-channel", - "version": "1.1.1", - "author": "Jordan Harband", - "license": "MIT" - }, - { - "name": "side-channel-list", - "version": "1.0.1", - "author": "Jordan Harband", - "license": "MIT" - }, - { - "name": "side-channel-map", - "version": "1.0.1", - "author": "Jordan Harband", - "license": "MIT" - }, - { - "name": "side-channel-weakmap", - "version": "1.0.2", - "author": "Jordan Harband", - "license": "MIT" - }, { "name": "siginfo", "version": "2.0.0", @@ -3269,18 +3089,42 @@ "author": "Luke Edwards", "license": "MIT" }, + { + "name": "smart-buffer", + "version": "4.2.0", + "author": "Josh Glazebrook", + "license": "MIT" + }, { "name": "smol-toml", "version": "1.7.0", "author": "Cynthia Rey", "license": "BSD-3-Clause" }, + { + "name": "socks", + "version": "2.8.0", + "author": "Josh Glazebrook", + "license": "MIT" + }, + { + "name": "socks-proxy-agent", + "version": "8.0.3", + "author": "Nathan Rajlich", + "license": "MIT" + }, { "name": "source-map", - "version": "0.5.0", + "version": "0.6.0", "author": "Nick Fitzgerald", "license": "BSD-3-Clause" }, + { + "name": "source-map", + "version": "0.3.0", + "author": "Nick Fitzgerald", + "license": "BSD" + }, { "name": "source-map-js", "version": "1.0.2", @@ -3295,10 +3139,16 @@ }, { "name": "sprintf-js", - "version": "1.1.3", + "version": "1.1.2", "author": "Alexandru Mărășteanu", "license": "BSD-3-Clause" }, + { + "name": "ssri", + "version": "13.0.1", + "author": "GitHub Inc.", + "license": "ISC" + }, { "name": "stackback", "version": "0.0.2", @@ -3317,12 +3167,6 @@ "author": "—", "license": "MIT" }, - { - "name": "stop-iteration-iterator", - "version": "1.1.0", - "author": "Jordan Harband", - "license": "MIT" - }, { "name": "string-width", "version": "1.0.1", @@ -3331,19 +3175,7 @@ }, { "name": "string.prototype.trim", - "version": "1.2.11", - "author": "Jordan Harband", - "license": "MIT" - }, - { - "name": "string.prototype.trimend", - "version": "1.0.10", - "author": "Jordan Harband", - "license": "MIT" - }, - { - "name": "string.prototype.trimstart", - "version": "1.0.8", + "version": "1.1.2", "author": "Jordan Harband", "license": "MIT" }, @@ -3395,33 +3227,27 @@ "author": "JounQin", "license": "MIT" }, - { - "name": "tagged-tag", - "version": "1.0.0", - "author": "Sindre Sorhus", - "license": "MIT" - }, { "name": "tailwindcss", - "version": "4.2.4", + "version": "4.3.3", "author": "—", "license": "MIT" }, { "name": "tapable", - "version": "2.3.0", + "version": "2.3.3", "author": "Tobias Koppers @sokra", "license": "MIT" }, { "name": "tar", - "version": "7.5.19", + "version": "7.5.21", "author": "Isaac Z. Schlueter", "license": "BlueOak-1.0.0" }, { "name": "temp", - "version": "0.9.4", + "version": "0.9.0", "author": "Bruce Williams", "license": "MIT" }, @@ -3433,7 +3259,7 @@ }, { "name": "terser", - "version": "5.48.0", + "version": "5.49.0", "author": "Mihai Bazon", "license": "BSD-2-Clause" }, @@ -3481,13 +3307,13 @@ }, { "name": "tldts", - "version": "7.4.5", + "version": "7.0.5", "author": "Rémi Berson", "license": "MIT" }, { "name": "tldts-core", - "version": "7.4.5", + "version": "7.0.5", "author": "Rémi Berson", "license": "MIT" }, @@ -3499,7 +3325,7 @@ }, { "name": "tmp-promise", - "version": "3.0.3", + "version": "3.0.2", "author": "Benjamin Gruenbaum and Collaborators.", "license": "MIT" }, @@ -3523,13 +3349,13 @@ }, { "name": "truncate-utf8-bytes", - "version": "1.0.2", + "version": "1.0.0", "author": "Carl Xiong", "license": "WTFPL" }, { "name": "tslib", - "version": "2.4.0", + "version": "2.8.1", "author": "Microsoft Corp.", "license": "0BSD" }, @@ -3545,54 +3371,18 @@ "author": "Sindre Sorhus", "license": "(MIT OR CC0-1.0)" }, - { - "name": "typed-array-buffer", - "version": "1.0.3", - "author": "Jordan Harband", - "license": "MIT" - }, - { - "name": "typed-array-byte-length", - "version": "1.0.3", - "author": "Jordan Harband", - "license": "MIT" - }, - { - "name": "typed-array-byte-offset", - "version": "1.0.4", - "author": "Jordan Harband", - "license": "MIT" - }, - { - "name": "typed-array-length", - "version": "1.0.8", - "author": "Jordan Harband", - "license": "MIT" - }, { "name": "typescript", "version": "6.0.3", "author": "Microsoft Corp.", "license": "Apache-2.0" }, - { - "name": "uint8array-extras", - "version": "1.5.0", - "author": "Sindre Sorhus", - "license": "MIT" - }, { "name": "unbash", - "version": "4.0.2", + "version": "4.0.3", "author": "Lars Kappert", "license": "ISC" }, - { - "name": "unbox-primitive", - "version": "1.1.0", - "author": "Jordan Harband", - "license": "MIT" - }, { "name": "undici", "version": "7.28.0", @@ -3625,8 +3415,8 @@ }, { "name": "unzipper", - "version": "0.12.5", - "author": "Ziggy Jonsson", + "version": "0.12.3", + "author": "Evan Oxfeld", "license": "MIT" }, { @@ -3637,15 +3427,15 @@ }, { "name": "uri-js", - "version": "4.2.2", + "version": "4.4.1", "author": "Gary Court", "license": "BSD-2-Clause" }, { "name": "utf8-byte-length", - "version": "1.0.5", + "version": "1.0.1", "author": "Carl Xiong", - "license": "(WTFPL OR MIT)" + "license": "WTFPL" }, { "name": "util-deprecate", @@ -3679,7 +3469,7 @@ }, { "name": "vite", - "version": "8.0.16", + "version": "8.1.5", "author": "Evan You", "license": "MIT" }, @@ -3691,25 +3481,25 @@ }, { "name": "vitest", - "version": "4.1.5", + "version": "4.1.10", "author": "Anthony Fu", "license": "MIT" }, { "name": "vscode-uri", - "version": "3.1.0", + "version": "3.0.8", "author": "Microsoft", "license": "MIT" }, { "name": "vue", - "version": "3.5.39", + "version": "3.5.40", "author": "Evan You", "license": "MIT" }, { "name": "vue-component-type-helpers", - "version": "3.3.5", + "version": "3.0.0", "author": "—", "license": "MIT" }, @@ -3721,7 +3511,7 @@ }, { "name": "vue-i18n", - "version": "11.4.6", + "version": "11.4.7", "author": "kazuya kawaguchi", "license": "MIT" }, @@ -3733,13 +3523,13 @@ }, { "name": "vue-tsc", - "version": "3.3.6", + "version": "3.3.7", "author": "—", "license": "MIT" }, { "name": "vuetify", - "version": "3.12.8", + "version": "3.12.10", "author": "John Leider", "license": "MIT" }, @@ -3791,42 +3581,24 @@ "author": "GitHub Inc.", "license": "ISC" }, - { - "name": "which-boxed-primitive", - "version": "1.1.0", - "author": "Jordan Harband", - "license": "MIT" - }, - { - "name": "which-builtin-type", - "version": "1.2.1", - "author": "Jordan Harband", - "license": "MIT" - }, - { - "name": "which-collection", - "version": "1.0.2", - "author": "Jordan Harband", - "license": "MIT" - }, { "name": "which-module", "version": "2.0.0", "author": "nexdrew", "license": "ISC" }, - { - "name": "which-typed-array", - "version": "1.1.22", - "author": "Jordan Harband", - "license": "MIT" - }, { "name": "why-is-node-running", "version": "2.3.0", "author": "Mathias Buus", "license": "MIT" }, + { + "name": "word-wrap", + "version": "1.2.5", + "author": "Jon Schlinkert", + "license": "MIT" + }, { "name": "wrap-ansi", "version": "2.0.0", @@ -3835,13 +3607,13 @@ }, { "name": "wrappy", - "version": "1.0.2", + "version": "1.0.0", "author": "Isaac Z. Schlueter", "license": "ISC" }, { "name": "xml-name-validator", - "version": "4.0.0", + "version": "5.0.0", "author": "Domenic Denicola", "license": "Apache-2.0" }, diff --git a/meshchatx/src/backend/meshchat_utils.py b/meshchatx/src/backend/meshchat_utils.py index df37fdb2..7233542a 100644 --- a/meshchatx/src/backend/meshchat_utils.py +++ b/meshchatx/src/backend/meshchat_utils.py @@ -50,6 +50,95 @@ def create_lxmf_router( return LXMF.LXMRouter(**kwargs) +def list_inbound_deliveries(router) -> list[dict]: + """Serialize active inbound LXMF delivery resources (LXMF 1.1+ / RNS 1.4+).""" + if router is None or not hasattr(router, "inbound_resources"): + return [] + items: list[dict] = [] + try: + resources = router.inbound_resources() or [] + except Exception: + return [] + for resource in resources: + try: + resource_hash = getattr(resource, "hash", None) + if resource_hash is None and hasattr(resource, "get_hash"): + resource_hash = resource.get_hash() + if resource_hash is None: + continue + if isinstance(resource_hash, (bytes, bytearray)): + hash_hex = bytes(resource_hash).hex() + else: + hash_hex = str(resource_hash) + size = None + transfer_size = None + progress = None + with contextlib.suppress(Exception): + size = int(resource.get_data_size() or 0) + with contextlib.suppress(Exception): + transfer_size = int(resource.get_transfer_size() or 0) + with contextlib.suppress(Exception): + progress_raw = float(resource.get_progress() or 0.0) + progress = max(0.0, min(100.0, progress_raw * 100.0)) + items.append( + { + "hash": hash_hex, + "size_bytes": size, + "transfer_size_bytes": transfer_size, + "progress": progress, + } + ) + except Exception: + continue + return items + + +def cancel_inbound_deliveries(router, resource_hash: str | None = None) -> dict: + """Cancel one or all active inbound LXMF delivery resources. + + Returns a result dict with ok, cancelled count, and optional error. + """ + if router is None: + return {"ok": False, "error": "router unavailable", "cancelled": 0} + + cleaned = str(resource_hash or "").strip().lower().replace(":", "") + if cleaned: + if not hasattr(router, "cancel_inbound"): + return { + "ok": False, + "error": "inbound delivery cancellation is unavailable", + "cancelled": 0, + } + try: + hash_bytes = bytes.fromhex(cleaned) + except ValueError: + return {"ok": False, "error": "invalid resource_hash", "cancelled": 0} + if not hash_bytes: + return {"ok": False, "error": "invalid resource_hash", "cancelled": 0} + try: + ok = bool(router.cancel_inbound(hash_bytes)) + except Exception as exc: + return {"ok": False, "error": str(exc), "cancelled": 0} + return { + "ok": ok, + "cancelled": 1 if ok else 0, + "resource_hash": cleaned, + "error": None if ok else "resource not active", + } + + if not hasattr(router, "cancel_all_inbound"): + return { + "ok": False, + "error": "inbound delivery cancellation is unavailable", + "cancelled": 0, + } + try: + cancelled = int(router.cancel_all_inbound() or 0) + except Exception as exc: + return {"ok": False, "error": str(exc), "cancelled": 0} + return {"ok": True, "cancelled": cancelled} + + def parse_bool_query_param(value: str | None) -> bool: if value is None: return False diff --git a/meshchatx/src/backend/rns_filesync_handler.py b/meshchatx/src/backend/rns_filesync_handler.py index 401d7604..270ad85e 100644 --- a/meshchatx/src/backend/rns_filesync_handler.py +++ b/meshchatx/src/backend/rns_filesync_handler.py @@ -7,17 +7,21 @@ from __future__ import annotations import contextlib import json import os +import tempfile import threading from collections.abc import Callable from typing import Any from rns_filesync.constants import ANNOUNCE_INTERVAL_DEFAULT -from rns_filesync.paths import PathJailError, normalize_relpath +from rns_filesync.paths import PathJailError, normalize_relpath, relative_to_root from rns_filesync.permissions import PermissionStore from rns_filesync.service import FileSyncService _ALL_ALIASES = frozenset({"all", "a", "everyone", "*"}) +# Cap for in-app sync-tree uploads (local control plane only). +MANAGER_UPLOAD_MAX_BYTES = 64 * 1024 * 1024 + def _normalize_peer_hash(value: str | None) -> str | None: cleaned = str(value or "").strip().lower().replace(":", "") @@ -34,6 +38,33 @@ def _normalize_peer_hash(value: str | None) -> str | None: return cleaned +def _is_forbidden_entry_name(name: str) -> bool: + """Reject hidden and protocol sidecar names in the file manager.""" + cleaned = str(name or "") + if not cleaned or cleaned in (".", ".."): + return True + if cleaned.startswith("."): + return True + if cleaned == ".rns-filesync.db" or cleaned.startswith(".rns-filesync"): + return True + if cleaned.startswith(".rns-xfer"): + return True + return False + + +def _sanitize_upload_basename(filename: str | None) -> str | None: + """Keep only a safe basename for uploads. Fail closed on escape tricks.""" + raw = str(filename or "").strip() + if not raw or "\x00" in raw: + return None + base = os.path.basename(raw.replace("\\", "/")) + if not base or base in (".", "..") or _is_forbidden_entry_name(base): + return None + if "/" in base or "\\" in base: + return None + return base + + _RESERVED_SYNC_TOP = frozenset( { "identity", @@ -111,6 +142,359 @@ class RnsFilesyncHandler: return None return resolved + def _sync_root(self) -> str: + """Real path of the configured sync directory (file manager jail base).""" + os.makedirs(self._sync_directory, exist_ok=True) + return os.path.realpath(self._sync_directory) + + def _is_under_sync_root(self, candidate: str) -> bool: + root = self._sync_root() + real = os.path.realpath(candidate) + return real == root or real.startswith(root + os.sep) + + def _resolve_manager_path( + self, + path: str | None, + *, + allow_root: bool = False, + must_exist: bool = False, + ) -> tuple[str | None, str | None]: + """Resolve a path for the sync-root file manager. + + Returns (abspath, error). Fail closed with a generic error string. + Empty path with allow_root returns the sync root itself. + """ + root = self._sync_root() + cleaned = str(path or "").strip() + if not cleaned: + if allow_root: + return root, None + return None, "path is required" + + # Absolute client paths are never accepted for the manager. + if "\x00" in cleaned: + return None, "path not allowed" + if os.path.isabs(cleaned) or cleaned.startswith(("/", "\\")): + return None, "path not allowed" + if len(cleaned) >= 2 and cleaned[1] == ":": + return None, "path not allowed" + + try: + safe_rel = normalize_relpath(cleaned) + except PathJailError: + return None, "path not allowed" + + parts = safe_rel.replace("\\", "/").split("/") + if any(_is_forbidden_entry_name(part) for part in parts): + return None, "path not allowed" + + joined = os.path.join(root, safe_rel) + # Reject symlink parents that escape before realpath of missing leaves. + parent = os.path.dirname(joined) + if parent != root and not self._is_under_sync_root(parent): + return None, "path not allowed" + if os.path.lexists(joined) and os.path.islink(joined): + real = os.path.realpath(joined) + if real != root and not real.startswith(root + os.sep): + return None, "path not allowed" + if must_exist and not os.path.exists(real): + return None, "path not found" + return real, None + + if must_exist and not os.path.lexists(joined): + return None, "path not found" + + try: + real = os.path.realpath(joined) + except OSError: + return None, "path not allowed" + + if real != root and not real.startswith(root + os.sep): + return None, "path not allowed" + if not allow_root and real == root: + return None, "path not allowed" + return real, None + + def _relpath_under_sync(self, abspath: str) -> str | None: + try: + return relative_to_root(self._sync_root(), abspath) + except PathJailError: + return None + + def _nudge_inventory(self, relpath: str | None = None) -> None: + if self.service is None: + return + inventory = getattr(self.service, "inventory", None) + if inventory is None: + return + with contextlib.suppress(Exception): + if relpath: + inventory.update_from_path(relpath) + else: + inventory.scan() + + def list_tree(self, path: str | None = None) -> dict[str, Any]: + """List files and directories under a relative path inside the sync root.""" + with self._lock: + target, err = self._resolve_manager_path(path, allow_root=True) + if err or target is None: + return {"ok": False, "error": err or "path not allowed"} + if not os.path.isdir(target): + return {"ok": False, "error": "not a directory"} + + root = self._sync_root() + entries: list[dict[str, Any]] = [] + try: + names = sorted(os.listdir(target), key=str.lower) + except OSError as exc: + return {"ok": False, "error": str(exc)} + + for name in names: + if _is_forbidden_entry_name(name): + continue + full = os.path.join(target, name) + if os.path.islink(full): + real = os.path.realpath(full) + if real != root and not real.startswith(root + os.sep): + continue + else: + real = os.path.realpath(full) + if real != root and not real.startswith(root + os.sep): + continue + + is_dir = os.path.isdir(real) and not os.path.islink(full) + # Treat in-jail symlinks to dirs as dirs for navigation only when target stays inside. + if os.path.islink(full) and os.path.isdir(real): + is_dir = True + rel = self._relpath_under_sync(real) + if rel is None and real == root: + continue + if rel is None: + continue + item: dict[str, Any] = { + "name": name, + "path": rel, + "type": "dir" if is_dir else "file", + } + if not is_dir: + try: + item["size"] = os.path.getsize(real) + except OSError: + item["size"] = 0 + entries.append(item) + + current_rel = "" + if target != root: + current_rel = self._relpath_under_sync(target) or "" + parent_rel = None + if target != root: + parent_abs = os.path.dirname(target) + if parent_abs == root: + parent_rel = "" + else: + parent_rel = self._relpath_under_sync(parent_abs) + + return { + "ok": True, + "root": root, + "current": current_rel, + "parent": parent_rel, + "entries": entries, + } + + def manager_mkdir(self, path: str) -> dict[str, Any]: + """Create a directory under the sync root (relative path).""" + with self._lock: + cleaned = str(path or "").strip() + if not cleaned: + return {"ok": False, "error": "path is required"} + # Resolve parent and create leaf so we do not require the leaf to exist. + try: + safe_rel = normalize_relpath(cleaned) + except PathJailError: + return {"ok": False, "error": "path not allowed"} + parts = safe_rel.replace("\\", "/").split("/") + if any(_is_forbidden_entry_name(part) for part in parts): + return {"ok": False, "error": "path not allowed"} + leaf = parts[-1] + parent_rel = "/".join(parts[:-1]) if len(parts) > 1 else "" + parent_abs, err = self._resolve_manager_path( + parent_rel if parent_rel else None, + allow_root=True, + must_exist=True, + ) + if err or parent_abs is None: + return {"ok": False, "error": err or "path not allowed"} + if not os.path.isdir(parent_abs): + return {"ok": False, "error": "parent is not a directory"} + if os.path.islink(parent_abs): + return {"ok": False, "error": "path not allowed"} + + new_path = os.path.join(parent_abs, leaf) + if not self._is_under_sync_root(os.path.dirname(new_path)): + return {"ok": False, "error": "path not allowed"} + if os.path.lexists(new_path): + return {"ok": False, "error": "already exists"} + try: + os.mkdir(new_path) + except OSError as exc: + return {"ok": False, "error": str(exc)} + real = os.path.realpath(new_path) + if not self._is_under_sync_root(real): + with contextlib.suppress(OSError): + os.rmdir(new_path) + return {"ok": False, "error": "path not allowed"} + rel = self._relpath_under_sync(real) or safe_rel + return {"ok": True, "path": rel} + + def manager_upload( + self, + *, + filename: str | None, + data: bytes, + subdir: str | None = None, + ) -> dict[str, Any]: + """Write an uploaded file under the sync root.""" + with self._lock: + if not isinstance(data, (bytes, bytearray)): + return {"ok": False, "error": "invalid upload data"} + if len(data) > MANAGER_UPLOAD_MAX_BYTES: + return {"ok": False, "error": "upload too large"} + base = _sanitize_upload_basename(filename) + if base is None: + return {"ok": False, "error": "invalid filename"} + + parent_abs, err = self._resolve_manager_path( + subdir, + allow_root=True, + must_exist=True, + ) + if err or parent_abs is None: + return {"ok": False, "error": err or "path not allowed"} + if not os.path.isdir(parent_abs) or os.path.islink(parent_abs): + return {"ok": False, "error": "path not allowed"} + + dest = os.path.join(parent_abs, base) + if os.path.islink(dest): + return {"ok": False, "error": "path not allowed"} + if os.path.lexists(dest): + real_existing = os.path.realpath(dest) + if not self._is_under_sync_root(real_existing): + return {"ok": False, "error": "path not allowed"} + + tmp_path = None + try: + fd, tmp_path = tempfile.mkstemp( + prefix=".upload-", + suffix=".tmp", + dir=parent_abs, + ) + try: + with os.fdopen(fd, "wb") as handle: + handle.write(data) + except Exception: + with contextlib.suppress(OSError): + os.close(fd) + raise + if not self._is_under_sync_root(tmp_path): + with contextlib.suppress(OSError): + os.unlink(tmp_path) + return {"ok": False, "error": "path not allowed"} + os.replace(tmp_path, dest) + tmp_path = None + except OSError as exc: + if tmp_path: + with contextlib.suppress(OSError): + os.unlink(tmp_path) + return {"ok": False, "error": str(exc)} + + real = os.path.realpath(dest) + if not self._is_under_sync_root(real) or not os.path.isfile(real): + with contextlib.suppress(OSError): + os.unlink(dest) + return {"ok": False, "error": "path not allowed"} + rel = self._relpath_under_sync(real) + if rel is None: + with contextlib.suppress(OSError): + os.unlink(dest) + return {"ok": False, "error": "path not allowed"} + self._nudge_inventory(rel) + return {"ok": True, "path": rel, "size": len(data)} + + def manager_delete(self, path: str) -> dict[str, Any]: + """Delete a file or empty directory under the sync root.""" + with self._lock: + root = self._sync_root() + try: + safe_rel = normalize_relpath(str(path or "").strip()) + except PathJailError: + return {"ok": False, "error": "path not allowed"} + lex_path = os.path.join(root, safe_rel) + if os.path.islink(lex_path): + return {"ok": False, "error": "path not allowed"} + + target, err = self._resolve_manager_path( + path, + allow_root=False, + must_exist=True, + ) + if err or target is None: + return {"ok": False, "error": err or "path not allowed"} + if target == root: + return {"ok": False, "error": "path not allowed"} + + rel = self._relpath_under_sync(target) + if rel is None: + return {"ok": False, "error": "path not allowed"} + + try: + if os.path.isdir(target): + try: + os.rmdir(target) + except OSError: + return {"ok": False, "error": "directory is not empty"} + elif os.path.isfile(target): + os.unlink(target) + else: + return {"ok": False, "error": "path not found"} + except OSError as exc: + return {"ok": False, "error": str(exc)} + + self._nudge_inventory(rel) + return {"ok": True, "path": rel} + + def manager_content(self, path: str) -> dict[str, Any]: + """Resolve a file under the sync root for download streaming.""" + with self._lock: + root = self._sync_root() + try: + safe_rel = normalize_relpath(str(path or "").strip()) + except PathJailError: + return {"ok": False, "error": "path not allowed"} + lex_path = os.path.join(root, safe_rel) + if os.path.islink(lex_path): + return {"ok": False, "error": "path not allowed"} + + target, err = self._resolve_manager_path( + path, + allow_root=False, + must_exist=True, + ) + if err or target is None: + return {"ok": False, "error": err or "path not allowed"} + if not os.path.isfile(target): + return {"ok": False, "error": "not a file"} + rel = self._relpath_under_sync(target) + if rel is None: + return {"ok": False, "error": "path not allowed"} + return { + "ok": True, + "abspath": target, + "path": rel, + "filename": os.path.basename(target), + "size": os.path.getsize(target), + } + def _load_settings(self) -> None: os.makedirs(self._root, exist_ok=True) if not os.path.isfile(self._settings_path): diff --git a/meshchatx/src/frontend/components/App.vue b/meshchatx/src/frontend/components/App.vue index 2b9ed26b..1d3073e0 100644 --- a/meshchatx/src/frontend/components/App.vue +++ b/meshchatx/src/frontend/components/App.vue @@ -148,6 +148,15 @@ :class="{ 'animate-spin': isSyncingPropagationNode }" /> + +
+ +
+
+
+ + {{ $t("about.active_sessions") }} +
+ + {{ $t("about.active_sessions_count", { count: activeSessionCount }) }} + +
+

+ {{ $t("about.active_sessions_description") }} +

+
+ {{ $t("about.active_sessions_empty") }} +
+
    +
  • +
    +
    +
    + {{ $t("about.active_session_ip") }} +
    +
    + {{ session.ip || "unknown" }} +
    +
    +
    +
    + {{ $t("about.active_session_connected") }} +
    +
    + {{ formatSessionConnectedAt(session.connected_at) }} +
    +
    +
    +
    + {{ $t("about.active_session_user_agent") }} +
    +
    + {{ session.user_agent || "unknown" }} +
    +
    +
    +
  • +
+
+
{{ $t("about.environment_information") }}
-
+
{{ $t("about.reticulum_config") }} @@ -405,111 +468,6 @@ {{ $t("about.reveal_database_file") }}
-
-
-
- {{ - $t("about.identity_hash") - }} - {{ - config.identity_hash - }} -
-
- {{ - $t("about.lxmf_address") - }} - {{ - config.lxmf_address_hash - }} -
-
-
- {{ - $t("about.env_python") - }} - v{{ appInfo.python_version || $t("about.path_unknown") }} -
-
- {{ - $t("about.env_lxmf") - }} - v{{ appInfo.lxmf_version || $t("about.path_unknown") }} -
-
- {{ - $t("about.env_rns") - }} - v{{ appInfo.rns_version || $t("about.path_unknown") }} -
-
- {{ - $t("about.env_platform") - }} - {{ environmentInfo.platform }} -
-
-
- {{ - $t("app.landlock_status") - }} - - {{ - appInfo.landlock_active - ? $t("app.landlock_active") - : $t("app.landlock_inactive") - }} - -
-

- {{ landlockInactiveReason }} -

-
-
- {{ - $t("about.env_language") - }} - {{ environmentInfo.language }} -
-
- {{ - $t("about.env_backend_url") - }} - {{ environmentInfo.backendUrl }} -
-
- {{ - $t("about.env_user_agent") - }} - {{ - environmentInfo.userAgent - }} -
-
@@ -1241,6 +1199,7 @@ import DialogUtils from "../../js/DialogUtils"; import ToastUtils from "../../js/ToastUtils"; import DownloadUtils from "../../js/DownloadUtils"; import GlobalEmitter from "../../js/GlobalEmitter"; +import { onWsEvent, offWsEvent } from "../../js/registries/wsEventRegistry.js"; import { appBatteryUsageToneClass, batteryStatusIconName, @@ -1266,7 +1225,6 @@ export default { appInfo: { version: "unknown", }, - config: null, updateInterval: null, healthInterval: null, databaseHealth: null, @@ -1307,6 +1265,9 @@ export default { developerLxmfAlternate: "43d3309adf27fc446556121b553b56a6", moneroDonateAddress: "83SUg6mmkkVGwCycckLEgRfdmXNm7H9XtVjbGXp5kko71N6pTefYURJeS7WdEGHrz2aagmt4nF3dWg6mHcYs6yu4EokwhTh", + activeSessions: [], + activeSessionCount: 0, + sessionsWsHandler: null, }; }, computed: { @@ -1332,21 +1293,6 @@ export default { return ""; } }, - isLinuxHost() { - return this.appInfo && this.appInfo.host_platform === "linux"; - }, - landlockInactiveReason() { - if (!this.appInfo || this.appInfo.landlock_active) { - return null; - } - if (this.appInfo.landlock_kernel_supported === false) { - return this.$t("app.landlock_kernel_unsupported"); - } - if (this.appInfo.landlock_disabled_by_env) { - return this.$t("app.landlock_disabled_by_env"); - } - return this.$t("app.landlock_inactive"); - }, batteryStatusIcon() { return batteryStatusIconName(this.batteryStatus); }, @@ -1440,43 +1386,10 @@ export default { } return ""; }, - environmentInfo() { - const ua = typeof navigator !== "undefined" ? navigator.userAgent || "" : ""; - let platform = typeof navigator !== "undefined" && navigator.platform ? navigator.platform : ""; - if ( - !platform && - typeof navigator !== "undefined" && - navigator.userAgentData && - navigator.userAgentData.platform - ) { - platform = navigator.userAgentData.platform; - } - if (!platform && /Android/i.test(ua)) { - platform = "Android"; - } - if (!platform && this.appInfo && this.appInfo.host_platform) { - platform = this.appInfo.host_platform; - } - if (!platform) { - platform = "unknown"; - } - const language = - typeof navigator !== "undefined" && navigator.language - ? navigator.language - : typeof navigator !== "undefined" && navigator.languages && navigator.languages[0] - ? navigator.languages[0] - : "unknown"; - return { - platform, - language, - userAgent: ua || "unknown", - backendUrl: typeof window !== "undefined" && window.location ? window.location.origin : "unknown", - }; - }, }, mounted() { this.getAppInfo(); - this.getConfig(); + this.getActiveSessions(); this.getDatabaseHealth(); this.listSnapshots(); this.listAutoBackups(); @@ -1485,6 +1398,10 @@ export default { this.restartAboutPollIntervals(); }; GlobalEmitter.on(BATTERY_SAVER_CHANGED_EVENT, this._batterySaverPrefsHandler); + this.sessionsWsHandler = (payload) => { + this.applyActiveSessionsPayload(payload); + }; + onWsEvent("app.sessions.updated", this.sessionsWsHandler); this.restartAboutPollIntervals(); }, beforeUnmount() { @@ -1497,6 +1414,10 @@ export default { if (this._batterySaverPrefsHandler) { GlobalEmitter.off(BATTERY_SAVER_CHANGED_EVENT, this._batterySaverPrefsHandler); } + if (this.sessionsWsHandler) { + offWsEvent("app.sessions.updated", this.sessionsWsHandler); + this.sessionsWsHandler = null; + } }, methods: { restartAboutPollIntervals() { @@ -1510,6 +1431,7 @@ export default { this.updateInterval = setInterval( () => { this.getAppInfo(); + this.getActiveSessions(); }, applyBackgroundPollInterval(5000, prefs) ); @@ -1668,6 +1590,31 @@ export default { console.log(e); } }, + applyActiveSessionsPayload(payload) { + const sessions = Array.isArray(payload?.sessions) ? payload.sessions : []; + this.activeSessions = sessions; + const count = Number(payload?.count); + this.activeSessionCount = Number.isFinite(count) ? count : sessions.length; + }, + async getActiveSessions() { + try { + const response = await window.api.get("/api/v1/app/sessions"); + this.applyActiveSessionsPayload(response?.data || {}); + } catch (e) { + console.log(e); + } + }, + formatSessionConnectedAt(value) { + const ts = Number(value); + if (!Number.isFinite(ts) || ts <= 0) { + return "unknown"; + } + try { + return new Date(ts * 1000).toLocaleString(); + } catch { + return "unknown"; + } + }, async refreshBatteryStatus() { try { this.batteryStatus = await getDeviceBatteryStatus(); @@ -1818,15 +1765,6 @@ export default { this.databaseActionInProgress = false; } }, - async getConfig() { - try { - const response = await window.api.get("/api/v1/config"); - this.config = response.data.config; - } catch (e) { - // do nothing if failed to load config - console.log(e); - } - }, async copyValue(value, labelKey) { if (!value) { return; diff --git a/meshchatx/src/frontend/components/filesync/FilesyncFileManager.vue b/meshchatx/src/frontend/components/filesync/FilesyncFileManager.vue new file mode 100644 index 00000000..dcd6449f --- /dev/null +++ b/meshchatx/src/frontend/components/filesync/FilesyncFileManager.vue @@ -0,0 +1,294 @@ + + + + + diff --git a/meshchatx/src/frontend/components/filesync/RnsFilesyncPage.vue b/meshchatx/src/frontend/components/filesync/RnsFilesyncPage.vue index 3d5a4677..9801ea46 100644 --- a/meshchatx/src/frontend/components/filesync/RnsFilesyncPage.vue +++ b/meshchatx/src/frontend/components/filesync/RnsFilesyncPage.vue @@ -260,37 +260,11 @@
-
- - -
-
- {{ $t("rns_filesync.no_files") }} -
-
    -
  • -
    {{ file.path }}
    -
    - {{ formatFileSize(file.size) }} - · {{ shortHash(file.hash) }} -
    -
  • -
+
@@ -407,6 +381,7 @@ import MaterialDesignIcon from "../MaterialDesignIcon.vue"; import ToastUtils from "../../js/ToastUtils"; import ToolsPageHeader from "../tools/ToolsPageHeader.vue"; import FilesyncDirectoryBrowserModal from "./FilesyncDirectoryBrowserModal.vue"; +import FilesyncFileManager from "./FilesyncFileManager.vue"; import ElectronUtils from "../../js/ElectronUtils"; import Utils from "../../js/Utils"; import { onWsEvent, offWsEvent } from "../../js/registries/wsEventRegistry.js"; @@ -417,6 +392,7 @@ export default { MaterialDesignIcon, ToolsPageHeader, FilesyncDirectoryBrowserModal, + FilesyncFileManager, }, data() { return { @@ -442,7 +418,6 @@ export default { monitor: true, connectHash: "", peers: [], - files: [], browsePeerId: "", remoteFiles: [], aclEnforce: false, @@ -546,11 +521,11 @@ export default { await this.refreshStatus(); }); bind("filesync.file.updated", async () => { - await this.refreshFiles(); + await this.refreshFileManager(); ToastUtils.info(this.$t("rns_filesync.file_updated")); }); bind("filesync.file.deleted", async () => { - await this.refreshFiles(); + await this.refreshFileManager(); ToastUtils.info(this.$t("rns_filesync.file_deleted")); }); bind("filesync.error", (payload) => { @@ -561,13 +536,6 @@ export default { formatFileSize(bytes) { return Utils.formatBytes(bytes || 0); }, - shortHash(hash) { - const value = String(hash || ""); - if (value.length <= 12) { - return value; - } - return `${value.slice(0, 8)}...`; - }, peerStatusLabel(peer) { const raw = peer?.status; if (raw === 1 || raw === "connected" || raw === true) { @@ -606,7 +574,14 @@ export default { } }, async refreshAll() { - await Promise.all([this.refreshStatus(), this.refreshPeers(), this.refreshFiles(), this.refreshAcl()]); + await Promise.all([this.refreshStatus(), this.refreshPeers(), this.refreshAcl()]); + await this.refreshFileManager(); + }, + async refreshFileManager() { + const manager = this.$refs.fileManager; + if (manager && typeof manager.refresh === "function") { + await manager.refresh(); + } }, async refreshStatus() { try { @@ -635,15 +610,6 @@ export default { ToastUtils.error(err?.message || this.$t("rns_filesync.error")); } }, - async refreshFiles() { - try { - const response = await window.api.get("/api/v1/filesync/files"); - const data = response?.data || {}; - this.files = Array.isArray(data.files) ? data.files : []; - } catch (err) { - ToastUtils.error(err?.message || this.$t("rns_filesync.error")); - } - }, async refreshAcl() { try { const response = await window.api.get("/api/v1/filesync/acl"); diff --git a/meshchatx/src/frontend/components/settings/SettingsPage.vue b/meshchatx/src/frontend/components/settings/SettingsPage.vue index 2729b45f..b68263b7 100644 --- a/meshchatx/src/frontend/components/settings/SettingsPage.vue +++ b/meshchatx/src/frontend/components/settings/SettingsPage.vue @@ -2987,6 +2987,22 @@ + +