Skip to content

v5.0.0 Major Refactor: Move from Vue 3 + JSDoc to Svelte 5 + Typescript - #84

Open
Sudo-Ivan wants to merge 93 commits into
masterfrom
next
Open

v5.0.0 Major Refactor: Move from Vue 3 + JSDoc to Svelte 5 + Typescript#84
Sudo-Ivan wants to merge 93 commits into
masterfrom
next

Conversation

@Sudo-Ivan

Copy link
Copy Markdown
Contributor

Why? Better maintainability and opportunity to break down all those "god" files into components and more maintainable frontend. I am more experienced with Svelte and Typescript.

This will also feature large backend refactors to break down meshchat.py.

Using various open-weight models.

Ivan added 30 commits September 5, 2026 06:52
…to codebase brought to you by slopcoder5000 the worlds best model for massive refactors.
…nhance conversation viewer with contact filtering and telemetry item selection
…ing archive listing, viewer, and export functionality
…ive session, audio settings, contacts tab, history panel, overlay, phonebook, and phone tab
…agement, including dialer, active session, voicemail, and tab navigation
…t related references in ESLint and TypeScript configurations
…ainability, and improve archive routes with database checks
…mentation, and standardize TypeScript file extensions
…eadability and consistency across app shell and map features
…nd remote management across multiple languages
…om vue/js to svelte/ts and updating docs and other improvements/fixes
Ivan added 18 commits September 5, 2026 22:50
Align reconnect, confirm, and list-row behavior on the remaining migrated tool pages.
Cover Toggle and PluginInstallDialog in browser mode, and add a backend-free Electron shell smoke via Playwright.
Update CHANGELOG, CONTRIBUTING, and development guides for the new DX gates and Task targets. Sync Electron shell dark-mode CSS.
Recover and land RNCP, FileSync, Settings, Tools, PageNodes, and svelte shell migration contract tests that were dropped during an earlier pre-commit stash conflict.
Comment thread meshchatx/src/frontend/js/mapExchange/descriptionFlatten.ts Fixed
Comment thread meshchatx/src/frontend/js/mapExchange/descriptionFlatten.ts Fixed
Comment thread meshchatx/src/frontend/js/mapExchange/descriptionFlatten.ts Fixed
Comment thread meshchatx/src/frontend/js/MicronParser.ts Fixed
@deepsource-io

deepsource-io Bot commented Sep 6, 2026

Copy link
Copy Markdown

DeepSource Code Review

We reviewed changes in fe9acaf...8ba9e8f on this pull request. Below is the summary for the review, and you can see the individual issues we found as inline review comments.

See full review on DeepSource ↗

Code Review Summary

Analyzer Status Updated (UTC) Details
Docker Sep 6, 2026 9:52p.m. Review ↗
Go Sep 6, 2026 9:52p.m. Review ↗
Java Sep 6, 2026 9:52p.m. Review ↗
JavaScript Sep 6, 2026 9:52p.m. Review ↗
Python Sep 6, 2026 9:52p.m. Review ↗
Shell Sep 6, 2026 9:52p.m. Review ↗
Secrets Sep 6, 2026 9:52p.m. Review ↗

Important

AI Review is run only on demand for your team. We're only showing results of static analysis review right now. To trigger AI Review, comment @deepsourcebot review on this thread.

@deepsource-io

deepsource-io Bot commented Sep 6, 2026

Copy link
Copy Markdown

DeepSource Code Review

We reviewed changes in fe9acaf...78a3554 on this pull request. Below is the summary for the review, and you can see the individual issues we found as inline review comments.

See full review on DeepSource ↗

Important

Some issues found as part of this review are outside of the diff in this pull request and aren't shown in the inline review comments due to GitHub's API limitations. You can see those issues on the DeepSource dashboard.

PR Report Card

Overall Grade  

Focus Area: Reliability
Security  

Reliability  

Complexity  

Hygiene  

Feedback

Type safety and “escape hatches” across the new TS/Svelte stack

  • The combination of any everywhere, ! non-null assertions, var, and bodies that contain no code points to a pattern of leaning on escape hatches while doing the big refactor.
  • It’s worth deciding where you want strict types and invariants first; tightening that contract in a few core modules will knock out a lot of these reliability issues in one pass.

Legacy imports and globals bleeding into the new structure

  • Massive unused import sets, undefined LXMF in many files, re-importing annotations, and wildcard or alias imports that don’t rename all point to the same thing: old global-style modules being pulled into the new layout without being fully “owned” by each file.
  • Clarifying which modules are true dependencies vs. legacy glue will cut a surprising number of hygiene and reliability warnings at once.

Code Review Summary

Analyzer Status Updated (UTC) Details
Docker Sep 8, 2026 11:31p.m. Review ↗
Go Sep 8, 2026 11:31p.m. Review ↗
Java Sep 8, 2026 11:31p.m. Review ↗
JavaScript Sep 8, 2026 11:31p.m. Review ↗
Python Sep 8, 2026 11:31p.m. Review ↗
Shell Sep 8, 2026 11:31p.m. Review ↗
Secrets Sep 8, 2026 11:31p.m. Review ↗

Important

AI Review is run only on demand for your team. We're only showing results of static analysis review right now. To trigger AI Review, comment @deepsourcebot review on this thread.

Comment thread meshchatx/src/backend/lifecycle/config_dict.py Fixed
Comment thread meshchatx/src/backend/lifecycle/config_update.py Fixed
Comment thread meshchatx/src/backend/lifecycle/lxmf_delivery.py Fixed
Comment thread meshchatx/src/backend/lifecycle/lxmf_send.py Fixed
Comment thread meshchatx/src/backend/lifecycle/reticulum_reload.py Fixed
Comment thread meshchatx/src/frontend/features/archives/lib/archiveRender.ts Fixed
@Sudo-Ivan Sudo-Ivan changed the title v5.0.0 Major Refactor: Move from Vue 3 and JSDoc to Svelte 5 and Typescript v5.0.0 Major Refactor: Move from Vue 3 + JSDoc to Svelte 5 + Typescript Sep 6, 2026

# track incoming message timestamps for flood protection
app._lxmf_incoming_timestamps.append(time.time())
app._lxmf_incoming_timestamps = prune_lxmf_incoming_timestamps(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CRITICAL]: prune_lxmf_incoming_timestamps is not bound - every inbound LXMF message is dropped

The module's global-binding whitelist (lines 15-61) does not include prune_lxmf_incoming_timestamps, and the module imports nothing else, so this call raises NameError on the first inbound message. The outer except at line 438 swallows it and only prints lxmf_delivery error, so every inbound delivery dies before app.db_upsert_lxmf_message - no message is stored or broadcast. meshchat.py imported this name before this PR (merge-base line 199) and ran the same logic in-process; the split lost it.

The same whitelist is also missing extract_sideband_command_entries, SidebandCommands, lxmf_signature_validated, lxmf_is_reaction_only_delivery, has_attachments, normalize_lxmf_destination_hash, _valid_number, parse_lxmf_icon_appearance and parse_lxmf_display_name, all used below. Import the required helpers directly (as lxmf_forwarding.py does) or add them to the whitelist.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

lxmf_message.fields[LXMF.FIELD_COMMANDS] = commands

if reply_to_hash is not None:
lxmf_message.fields[FIELD_REPLY_TO] = bytes.fromhex(reply_to_hash)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CRITICAL]: FIELD_REPLY_TO / FIELD_REACTION are unbound - replies, reactions and app-extension sends raise NameError

None of FIELD_REPLY_TO (301), FIELD_REPLY_QUOTE (303), FIELD_REACTION (308) or LXMF_APP_EXTENSIONS_FIELD (313) is imported by this module or present in the whitelist above, and meshchat.py no longer imports them (it did before this PR - merge-base meshchat.py lines 166-170). Sending any reply, reaction or app-extension message therefore fails with NameError after the LXMF object was already built. build_lxmf_reaction_field is whitelisted but was also removed from meshchat.py's imports, so the if _k in g skip makes it unbound too. Import these names directly from meshchatx.src.backend.lxmf_utils like other lifecycle modules do.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

list,
):
file_attachments = [
LxmfFileAttachment(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[WARNING]: LxmfFileAttachment is unbound - auto-resend of messages with file attachments raises NameError

This module binds globals by star-copying meshchatx.meshchat.__dict__, but meshchat.py no longer imports LxmfFileAttachment (it only imports LxmfAudioField, LxmfFileAttachmentsField, LxmfImageField; the merge-base also imported LxmfFileAttachment at line 156). Auto-resending a failed message that has file attachments therefore raises NameError here; image/audio resends still work. Import LxmfFileAttachment directly from lxmf_message_fields.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

ctx.database.misc.update_crawl_task(
task_id,
status="pending",
next_retry_at=datetime.now(UTC) + timedelta(hours=6),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[WARNING]: timedelta is unbound - crawl defer/retry scheduling raises NameError

This module star-copies meshchatx.meshchat globals, but meshchat.py changed from datetime import UTC, datetime, timedelta to from datetime import UTC, datetime in this PR (merge-base line 37 still had timedelta). Every deferral path (timedelta(hours=6) here, timedelta(minutes=15) at line 53, and the failure backoff at ~225) raises NameError instead of rescheduling the crawl task. Import timedelta directly.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

if announce["aspect"] == "lxmf.delivery":
display_name = parse_lxmf_display_name(announce["app_data"])
elif announce["aspect"] == "nomadnetwork.node":
display_name = parse_nomadnetwork_node_display_name(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[WARNING]: parse_nomadnetwork_node_display_name is unbound - NomadNet announce conversion fails

The star-copy of meshchat.py globals can no longer supply this name: meshchat.py dropped its import in this PR (merge-base line 222 still had it) and this module does not import it locally either. Both convert_db_announce_to_dict (here) and batch_convert_announces_to_api_dicts (line 77) raise NameError whenever a nomadnetwork.node announce is converted, breaking the announce listing and the WS broadcast for NomadNet nodes. Import it directly from its source module.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

activeRecording = session;
isRecordingAudioAttachment = true;
audioAttachmentRecordingDuration = "0:00";
audioRecordingTimer = setInterval(() => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CRITICAL]: Active microphone recording is never torn down when the component unmounts

startAudioRecording opens a real MicrophoneRecorder/Codec2MicrophoneRecorder session and starts this 1-second interval, but the only teardown path is the user clicking stop (stopAudioRecording, line 168). There is no $effect cleanup or onDestroy in this component, and the parent never stops the recording on unmount - so closing the pane or navigating away mid-recording leaves the interval ticking forever against detached state and the microphone stream open (OS mic indicator stays on). Each abandoned recording leaks another interval. Add a cleanup effect such as $effect(() => () => { if (isRecordingAudioAttachment) void stopAudioRecording(); }).


Reply with @kilocode-bot fix it to have Kilo Code address this issue.


let scrollTop = $state(0);
let viewportHeight = $state(0);
let measuredHeights = $state<Record<number, number>>({});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[WARNING]: measuredHeights is keyed by row index and never reset - stale heights corrupt the virtual layout

The record persists for the component's lifetime, the component is not keyed per conversation, and nothing clears it when groups changes. Switching conversations makes the new conversation's first rows inherit the previous conversation's pixel heights (line 28), so scrollToBottom() (which uses layout.totalSize) lands in the wrong place and rows jump as the ResizeObserver re-corrects. "Load previous" inserts groups at the top, shifting every index so all measurements briefly apply to the wrong groups. The record also grows unboundedly over a session. Reset or re-key the measurements whenever the conversation identity changes.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

const composeSuggestions = $derived(
buildComposeAddressSuggestions(contacts, conversations, composeAddress, isComposeInputFocused)
);
const isSelectedPeerBlocked = $derived(isPeerBlockedInState(GlobalState.blockedDestinations, selectedHash));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[WARNING]: GlobalState.blockedDestinations is not Svelte-reactive - the blocked-peer state can go permanently stale

GlobalState is a plain Proxy with its own listener list (js/GlobalState.ts:26-44), so reading it inside $derived registers no dependency: isSelectedPeerBlocked is computed once and only recomputed when another tracked dep (e.g. selectedHash, chatItems) changes. After banish/unbanish the composer's blocked notice stays wrong - the send box remains enabled while the peer is banished, or stays hidden after unblock - until an unrelated state change. Mirror the flag into a $state via a subscription (the pattern appShellState already uses) instead of reading the proxy directly.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

const currentIdentity = $derived(identities.find((i) => i.is_current) || null);
const otherIdentities = $derived(identities.filter((i) => !i.is_current));
const identityIconStyle = $derived.by(() => {
const cfg = GlobalState.config as { message_icon_size?: number } | null | undefined;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[SUGGESTION]: Same non-reactive-GlobalState pattern as ConversationViewer - icon size renders stale

GlobalState.config.message_icon_size read inside $derived.by creates no Svelte dependency, so identity icon sizes only update when identities/isLoading change, not when the config value is patched (e.g. from a second pane sharing GlobalState). Consider subscribing to the config change and copying the value into a $state, consistent with the fix suggested for ConversationViewer.svelte:271.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

java.net.URI uri = java.net.URI.create(baseUrl);
return RemoteBackendUrl.isLoopbackHost(uri.getHost());
} catch (Exception e) {
return true;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[SUGGESTION]: isLocalBackend fails open - parse failure routes traffic to the trust-all client

catch (Exception e) { return true; } sends URI-parse failures to the loopback trust-all client instead of the system-trust client. base is normally a normalized origin, so this is near-unreachable, but a security-sensitive routing decision should fail closed.

Suggested change
return true;
return false;

Reply with @kilocode-bot fix it to have Kilo Code address this issue.

@kilo-code-bot

kilo-code-bot Bot commented Sep 6, 2026

Copy link
Copy Markdown

Code Review Summary

Status: 3 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 2
Issue Details (click to expand)

WARNING

File Line Issue
meshchatx/src/frontend/features/relay-chat/components/RelayChatPage.svelte 176 fetchDiscoveredHubs fetches /api/v1/announces without an aspect filter, so every announce type (chat peers, NomadNet nodes, telephony, propagation nodes) renders as a "discovered hub" and can be persisted as an RRC hub via Connect; pass aspect: "rrc.hub". Also notes the dead res.data?.hubs fallback (endpoint returns {announces, total_count}).

SUGGESTION

File Line Issue
meshchatx/src/frontend/features/nomadnetwork/components/NomadNetworkBrowser.svelte 71 routeHashWatchReady derived plus the no-op $effect that only reads it are dead code — nothing consumes the value and the effect has no side effect.
tests/backend/conftest.py 365 owner_identity=app.current_context.identity passes an RNS.Identity object; RRCServerManager only accepts bytes/bytearray and silently stores None, diverging from production which passes self.identity.hash.
Files Reviewed (31 files)
  • meshchatx/src/backend/http/routes/bots/bots.py - 0 issues
  • meshchatx/src/backend/http/routes/maintenance/ops.py - 0 issues
  • meshchatx/src/backend/http/routes/path_probe/__init__.py - 0 issues
  • meshchatx/src/backend/http/routes/path_probe/destination.py - 0 issues
  • meshchatx/src/backend/http/routes/websocket_upgrade/upgrade.py - 0 issues
  • meshchatx/src/backend/lifecycle/lxmf_send.py - 0 issues
  • meshchatx/src/backend/lifecycle/reticulum_reload.py - 0 issues
  • meshchatx/src/backend/lifecycle/user_guidance.py - 0 issues
  • meshchatx/src/backend/map_overlay_manager/__init__.py - 0 issues
  • meshchatx/src/backend/map_overlay_manager/core.py - 0 issues
  • meshchatx/src/frontend/features/app-shell/components/SidebarLink.svelte - 0 issues
  • meshchatx/src/frontend/features/messages/lib/conversationViewerActions.ts - 0 issues
  • meshchatx/src/frontend/features/messages/lib/viewerActions.ts - 0 issues
  • meshchatx/src/frontend/features/nomadnetwork/components/NomadNetworkBrowser.svelte - 1 issue
  • meshchatx/src/frontend/features/relay-chat/components/RelayChatPage.svelte - 1 issue
  • package.json - 0 issues
  • pnpm-lock.yaml - 0 issues
  • pnpm-workspace.yaml - 0 issues
  • tests/backend/conftest.py - 1 issue
  • tests/backend/test_bot_handler_extended.py - 0 issues
  • tests/backend/test_bot_lxmf_config_http.py - 0 issues
  • tests/backend/test_interface_enabled_flag_oracle.py - 0 issues
  • tests/backend/test_licenses_api.py - 0 issues
  • tests/backend/test_map_data_manager.py - 0 issues
  • tests/backend/test_map_overlay_manager.py - 0 issues
  • tests/backend/test_path_probe_lxmf_delivery_resolve.py - 0 issues
  • tests/backend/test_shell_service_worker_headers.py - 0 issues
  • tests/frontend/SidebarLink.test.js - 0 issues
  • tests/frontend/WebSocketConnection.test.js - 0 issues
  • tests/frontend/featureModuleLocCaps.test.js - 0 issues
  • vitest.config.mjs - 0 issues

Fix these issues in Kilo Cloud

Previous Review Summaries (2 snapshots, latest commit a2ceccf)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit a2ceccf)

Status: No Issues Found | Recommendation: Merge

All 11 findings from the previous review pass were re-verified against HEAD (a2ceccf8) and are resolved in this increment. No new issues found in the changed code.

Files Reviewed (85 files)
  • android/app/src/main/java/com/meshchatx/LocalApiClient.java
  • android/app/src/main/java/com/meshchatx/LocalhostTrustOkHttpClient.java
  • android/app/src/main/java/org/able/BLE.java
  • docker/Dockerfile
  • docker/Dockerfile.hardened
  • meshchatx/meshchat.py
  • meshchatx/repository_http_standalone.py
  • meshchatx/src/backend/bake_frozen_pycodec2.py
  • meshchatx/src/backend/data/interfaces/HTTPInterface.py
  • meshchatx/src/backend/database/announces.py
  • meshchatx/src/backend/database/contacts.py
  • meshchatx/src/backend/database/map_overlays.py
  • meshchatx/src/backend/database/messages/dao.py
  • meshchatx/src/backend/docs_manager/core.py
  • meshchatx/src/backend/http/routes/interfaces/add.py
  • meshchatx/src/backend/interface_port_check.py
  • meshchatx/src/backend/lifecycle/announce_convert.py
  • meshchatx/src/backend/lifecycle/config_dict.py
  • meshchatx/src/backend/lifecycle/config_update.py
  • meshchatx/src/backend/lifecycle/crawler_task.py
  • meshchatx/src/backend/lifecycle/lxmf_delivery.py
  • meshchatx/src/backend/lifecycle/lxmf_resend.py
  • meshchatx/src/backend/lifecycle/lxmf_send.py
  • meshchatx/src/backend/lifecycle/reticulum_reload.py
  • meshchatx/src/backend/map_geo_sanitizer.py
  • meshchatx/src/backend/map_geo_validator.py
  • meshchatx/src/backend/map_overlay_export.py
  • meshchatx/src/backend/page_node/core.py
  • meshchatx/src/backend/plugin_manager/manager.py
  • meshchatx/src/backend/plugin_permissions.py
  • meshchatx/src/backend/plugin_signature.py
  • meshchatx/src/backend/plugin_wasm_bundle.py
  • meshchatx/src/backend/repository_server_manager.py
  • meshchatx/src/frontend/features/archives/lib/archiveRender.ts
  • meshchatx/src/frontend/features/interfaces/AddInterfacePage.svelte
  • meshchatx/src/frontend/features/interfaces/components/AddInterfaceHttpDetails.svelte
  • meshchatx/src/frontend/features/interfaces/lib/addInterfacePayload.ts
  • meshchatx/src/frontend/features/interfaces/lib/interfacesFormat.ts
  • meshchatx/src/frontend/features/map/MapPage.svelte
  • meshchatx/src/frontend/features/map/lib/mapPageHelpers.ts
  • meshchatx/src/frontend/features/messages/components/ConversationMessageListVirtual.svelte
  • meshchatx/src/frontend/features/messages/components/ConversationViewer.svelte
  • meshchatx/src/frontend/features/messages/components/ConversationViewerComposerHost.svelte
  • meshchatx/src/frontend/features/settings/components/IdentitiesPage.svelte
  • meshchatx/src/frontend/js/MicronParser.ts
  • meshchatx/src/frontend/js/mapExchange/descriptionFlatten.ts
  • meshchatx/src/frontend/public/vendor/micron-parser-go/integrity.json
  • meshchatx/src/ssl_self_signed.py
  • scripts/build_community_interfaces_json.py
  • scripts/ci/github-upload-bunny-flatpak-ostree.py
  • scripts/ci/github-upload-bunny-storage-release-assets.py
  • scripts/ci/tree_manifest_generate.py
  • scripts/deps-allowlist.json
  • scripts/docker_entrypoint_chainguard.py
  • scripts/micron-parser-go-version.mjs
  • tests/backend/compare_benchmarks.py
  • tests/backend/test_android_cryptography_pyo3_patch.py
  • tests/backend/test_audio_codec.py
  • tests/backend/test_bake_frozen_pycodec2.py
  • tests/backend/test_benchmark_gate.py
  • tests/backend/test_docker_runtime_smoke.py
  • tests/backend/test_docs_manager.py
  • tests/backend/test_frozen_runtime_arch.py
  • tests/backend/test_github_release_changelog.py
  • tests/backend/test_https_file_response_sendfile.py
  • tests/backend/test_https_wss_side_sniffing.py
  • tests/backend/test_interface_port_check.py
  • tests/backend/test_lxmf_live_tcp_path.py
  • tests/backend/test_lxmf_send_delivery_oracle.py
  • tests/backend/test_pip_rns_integration.py
  • tests/backend/test_plugin_manager.py
  • tests/backend/test_plugin_security.py
  • tests/backend/test_repository_server_manager.py
  • tests/backend/test_reticulum_config_editor.py
  • tests/backend/test_reticulum_config_guard.py
  • tests/backend/test_rnsh_live.py
  • tests/backend/test_translator_argos_integration.py
  • tests/backend/test_tree_manifest_generate.py
  • tests/backend/test_websocket_runtime.py
  • tests/frontend/viteDx.test.js
  • tests/test_android_emulator_smoke_script.py
  • tests/test_stage_android_release_apks.py
  • tsconfig.json
  • vite.config.mjs (renamed from vite.config.js)
  • vitest.config.mjs (renamed from vitest.config.js)

Previous review (commit 8ba9e8f)

Status: 11 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 3
WARNING 6
SUGGESTION 2

The dominant defect class is the new backend/lifecycle/ split: several modules resolve meshchat.py globals through hand-maintained whitelists or star-copies, but this PR simultaneously removed the matching imports from meshchat.py, so the whitelists can never bind them and calls raise NameError at runtime — inbound LXMF delivery, reply/reaction sending, attachment auto-resend, crawl deferral, NomadNet announce conversion, and hot-reload port probes are all affected.

Issue Details (click to expand)

CRITICAL

File Line Issue
meshchatx/src/backend/lifecycle/lxmf_delivery.py 91 Whitelist omits prune_lxmf_incoming_timestamps (and 9 other used names); every inbound LXMF delivery raises NameError and is silently dropped before the DB upsert
meshchatx/src/backend/lifecycle/lxmf_send.py 301 FIELD_REPLY_TO/FIELD_REPLY_QUOTE/FIELD_REACTION/LXMF_APP_EXTENSIONS_FIELD unbound; replies, reactions and app-extension sends raise NameError
meshchatx/src/frontend/features/messages/components/ConversationViewerComposerHost.svelte 161 Active microphone recording and its 1s interval are never torn down on unmount; mic stays live and intervals leak per abandoned recording

WARNING

File Line Issue
meshchatx/src/backend/lifecycle/lxmf_resend.py 129 LxmfFileAttachment unbound via star-copy; auto-resend of messages with file attachments raises NameError
meshchatx/src/backend/lifecycle/crawler_task.py 41 timedelta unbound (meshchat.py dropped it from the datetime import); crawl defer/retry paths raise NameError
meshchatx/src/backend/lifecycle/announce_convert.py 153 parse_nomadnetwork_node_display_name unbound; nomadnetwork.node announce conversion fails in listing and WS broadcast
meshchatx/src/backend/lifecycle/reticulum_reload.py 45 Whitelist omits socket/psutil; hot-reload port probes raise NameError swallowed by broad excepts and silently no-op
meshchatx/src/frontend/features/messages/components/ConversationMessageListVirtual.svelte 23 measuredHeights keyed by row index and never reset; stale/misapplied heights corrupt virtual scrolling across conversations and prepends
meshchatx/src/frontend/features/messages/components/ConversationViewer.svelte 271 GlobalState.blockedDestinations read in $derived is not Svelte-reactive; blocked-peer notice can go permanently stale

SUGGESTION

File Line Issue
meshchatx/src/frontend/features/settings/components/IdentitiesPage.svelte 41 Same non-reactive GlobalState read in $derived; identity icon size renders stale
android/app/src/main/java/com/meshchatx/LocalApiClient.java 168 isLocalBackend fails open (return true in catch); parse failure routes traffic to the trust-all client — prefer return false

Notes: all findings were verified against the PR merge-base (29e835c) diff and current HEAD (8ba9e8f). Findings that are already fixed on master after this branch diverged (localhost trust-manager validation, repository server bind default, reticulum config overwrite) were excluded as outside this PR's diff.

Files Reviewed (11 files)
  • meshchatx/src/backend/lifecycle/lxmf_delivery.py - 1 issue
  • meshchatx/src/backend/lifecycle/lxmf_send.py - 1 issue
  • meshchatx/src/backend/lifecycle/lxmf_resend.py - 1 issue
  • meshchatx/src/backend/lifecycle/crawler_task.py - 1 issue
  • meshchatx/src/backend/lifecycle/announce_convert.py - 1 issue
  • meshchatx/src/backend/lifecycle/reticulum_reload.py - 1 issue
  • meshchatx/src/frontend/features/messages/components/ConversationViewerComposerHost.svelte - 1 issue
  • meshchatx/src/frontend/features/messages/components/ConversationMessageListVirtual.svelte - 1 issue
  • meshchatx/src/frontend/features/messages/components/ConversationViewer.svelte - 1 issue
  • meshchatx/src/frontend/features/settings/components/IdentitiesPage.svelte - 1 issue
  • android/app/src/main/java/com/meshchatx/LocalApiClient.java - 1 issue

Fix these issues in Kilo Cloud


Reviewed by glm-5.3-flash · Input: 86K · Output: 20.4K · Cached: 1.3M

- Preserve user Reticulum config on startup instead of overwriting it.
- Default HTTP/repository listen hosts to 127.0.0.1 and add BAN-B104 nosecs.
- Resolve DeepSource Batch A and C findings: chmod modes, Android trust,
  shutil.which resolution, and nosec annotations.
- Validate Android LocalhostTrustOkHttpClient self-signed certs and make
  BLE.appContext private.
- Rename vite.config.js and vitest.config.js to .mjs and use
  import.meta.dirname.
- Bump micron-parser-go WASM to v1.1.5 and update integrity.
- Add UTM and OLC to map context-menu coordinate rows and wire per-format
  copy.
- Align HTTP interface frontend listen host default with backend.
- Fix backend lifecycle dynamic imports and Svelte GlobalState reactivity.
- Add focused regression tests and update test source paths.
Comment thread tests/backend/test_interface_port_check.py Dismissed
const api = (window as any).api;
if (!api) return;
try {
const res = await api.get("/api/v1/announces");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Discovery fetches all announces, not just relay-chat hubs

GET /api/v1/announces without an aspect query param returns every announce type (LXMF chat peers, nomadnetwork.node nodes, lxst.telephony, lxmf.propagation, ...), not just RRC hubs. All of them land in discoveredHubs and render as "discovered hubs" in the discovery view, and clicking Connect then persists any arbitrary peer as a relay-chat hub via POST /api/v1/rrc/hubs. The endpoint already supports filtering — pass the hub aspect (rrc.hub, the aspect hubs announce under; relayLinkUtils.ts already defaults to it):

Suggested change
const res = await api.get("/api/v1/announces");
const res = await api.get("/api/v1/announces", { params: { aspect: "rrc.hub" } });

Also on the next line: this endpoint returns {"announces": [...], "total_count": N} — there is no hubs key (that belongs to /api/v1/rrc/hubs), so res.data?.hubs is a dead fallback.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.


const routePath = $derived(path || routeQuery.path || DEFAULT_PAGE_PATH);
const routeArchiveId = $derived(routeQuery.archive_id || null);
const routeHashWatchReady = $derived(Boolean(destinationHash || routePath));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUGGESTION: Dead code — routeHashWatchReady and the no-op $effect do nothing

routeHashWatchReady is never consumed anywhere else in the file, and the $effect only reads it into an unused local — it creates a reactive subscription with no side effect, so both statements are runtime no-ops. If the intent was to re-run tab restoration when the route hash changes after mount, that logic is missing (the onMount restore still runs only once); otherwise these five lines can be removed.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

Comment thread tests/backend/conftest.py
if app.rrc_server_manager is None:
app.rrc_server_manager = RRCServerManager(
storage_dir=app.current_context.storage_path,
owner_identity=app.current_context.identity,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUGGESTION: owner_identity receives the identity object, not its hash

RRCServerManager.__init__ only accepts bytes/bytearray for owner_identity and silently stores None otherwise, so this fixture ends up with no owner trust, diverging from production, which passes self.identity.hash (identity_context/core.py). Pass the hash so fixture-created hubs match production owner auto-trust behaviour.

Suggested change
owner_identity=app.current_context.identity,
owner_identity=app.current_context.identity.hash,

Reply with @kilocode-bot fix it to have Kilo Code address this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants