Commit Graph

150 Commits

Author SHA1 Message Date
UNITRONIX 4d2a4e0488 fix(api,ui): fix tags/groups, status type, operator permissions (#138)
UI: group chip buttons changed to icon-only (matching folder chips), Create Group tile styling unified with Create Folder, old .group-chip-action CSS replaced with unified .chip-action class.

Go server: peerResponse and singlePeerResponse now return status as int (1=active, 0=disabled) instead of string, added status_text for admin panel backward compat. Fixes RustDesk client crash 'type String is not a subtype of type int?'.

Go server: new handleUsersWithClientFallback — detects RustDesk client requests to /api/users and returns current user without requiring user.view permission. Fixes disappearing folders/groups caused by _getUsers() 403 short-circuiting _pull().

Node.js: normalisePeer updated to use status_text fallback for status_tier.

Branding: RustDesk Server Management -> BetterDesk Server Management across themes, i18n, settings. Console version bumped to 3.0.0.

This commit was made possible thanks to Insolve.
2026-05-28 01:46:19 +02:00
UNITRONIX 40cde4ebee fix(security): remove non-standard browsing-topics from Permissions-Policy
Removes browsing-topics=() directive which caused console warnings in browsers
that don't support this non-standard feature.

This commit was made possible thanks to Insolve.
2026-05-27 01:02:00 +02:00
UNITRONIX ae7498fdaa fix(api): fix RustDesk client AB, groups & peer list format
- Remove string 'id' from group payload (caused Dart 'String is not subtype of int?' crash)
- Add team.peers array with device IDs, access_perm, sort to group response
- Change device filter from online-only to all non-banned/non-disabled peers
- Fix peer format: nested info object, int status, bool online (matching Go server)
- Enable includeDevices for admin/operator AB sync (60 peers now visible)
- Collect peer_ids from device_group_members and device_folder_assignments

This commit was made possible thanks to Insolve.
2026-05-27 01:01:20 +02:00
UNITRONIX ab2dc5d3ab feat(scripts): add HTTP/HTTPS protocol toggle to installer scripts
- Add menu option T (Toggle HTTP/HTTPS) to betterdesk.sh and betterdesk.ps1
- Add --protocol http|https CLI flag (bash) and -Protocol param (PS1)
- Toggle updates .env, systemd/NSSM services, and Go server TLS flags
- Auto-generate self-signed cert when switching to HTTPS if none exists
- Go API (:21114) always stays HTTP (internal Node.js<->Go communication)
- Fix betterdeskApi.js: conditional httpsAgent/httpAgent based on URL scheme
- Fix deviceStatusPush.js: TLS options only applied for wss:// connections

This commit was made possible thanks to Insolve.
2026-05-27 00:10:51 +02:00
Knienartowicz 5670bdc8b1 fix(api): resolve RustDesk client tag/group/peer type mismatches (#138)
5 root causes identified and fixed:

- H1: /api/peers returned status as string 'ONLINE' — RustDesk PeerPayload expects int (1=active, 0=disabled). New handleClientPeersList() detects client requests (?accessible/?pageSize) and returns {total,data} envelope with PeerPayload format (nested info map, int status).

- H2: mergeAdminTagsIntoAB() used typed struct → silently dropped tag_colors field. Rewritten with map[string]any to preserve all AB fields.

- H3: /api/device-group/accessible missing (404) — RustDesk GroupModel._getDeviceGroups() calls this endpoint. Added route pointing to handleClientGroupList.

- H4: /api/users returned plain array with wrong field names — RustDesk expects {total,data} with UserPayload (name, display_name, status:int, is_admin:bool). New handleClientUsersList() returns correct format.

- L1: .group-chip.chip-add CSS didn't fully override base 3-column grid. Added explicit grid/centering/dashed-border overrides.

Also updated handleClientGroupPeers (/api/peers/list) to use PeerPayload format with nested info map for consistency.

This commit was made possible thanks to Insolve.
2026-05-26 15:47:27 +02:00
Knienartowicz de53408803 security: apply audit fixes (H-02/H-03/H-04/H-05) — branding, TOTP recovery codes, NodeSource SHA verification
Node.js (web-nodejs):

- H-02 (services/brandingService.js): tighten SVG sanitization (strip <style>/<use>/<image>, DOCTYPE/PI, CSS expression()/@import); export validateBrandingUrl() rejecting protocol-relative // and unknown schemes

- H-03 (routes/settings.routes.js): logo upload — whitelist /^logo-[0-9a-f]{16}.(png|jpg|jpeg|gif|webp|svg)$/i + path.resolve prefix check + fs.lstatSync symlink guard before deleting old logo

Go server (betterdesk-server):

- H-04 (auth/recovery.go NEW): TOTP recovery codes — GenerateRecoveryCodes (10 codes XXXX-XXXX-XX, unambiguous alphabet), HashRecoveryCodes (JSON array of bcrypt hashes, cost 10), ConsumeRecoveryCode (single-use, returns updated store)

- H-04 (db/database.go,sqlite.go,postgres.go): User.TOTPRecoveryCodes field with read/write via COALESCE-tolerant SELECTs (additive, backward-compat: column already existed from Phase 12 migration)

- H-04 (api/auth_handlers.go): handleConfirmTOTP returns plaintext recovery codes ONCE on enable; handleLogin2FA falls back to ConsumeRecoveryCode on invalid TOTP and audits with 2fa=recovery_code; handleDisableTOTP clears stored codes

Scripts:

- H-05 (betterdesk.sh): replace curl|bash piping with download-to-tempfile + validation — HTTPS-only (--proto=https --tlsv1.2), size sanity (1-500KB), shebang sanity check, SHA-256 logged, optional pinning via NODESOURCE_SHA256 env

Verification: go build ./... ✓, go vet ./... ✓ (exit 0), go test ./auth/... ./db/... ✓, jest 102/102 passed

This commit was made possible thanks to Insolve.
2026-05-26 14:57:01 +02:00
Knienartowicz 3888e68811 ui(sidebar): translate user role label via users.role_* i18n keys
Sidebar footer previously rendered the raw DB role string (e.g. 'global_admin'). Now resolves user.role to users.role_<role> translation key with snake_case->Title Case fallback when key is missing.
2026-05-26 14:01:27 +02:00
Knienartowicz f8fbb88e47 security: apply 12 audit fixes (H-03/H-04/M-03/M-04/M-05/M-06/M-07/L-01/L-02/L-04/I-02/I-04)
Node.js (no recompile required):

- H-04: RUSTDESK_API_DISABLE_TOTP now requires explicit _ACKNOWLEDGED flag

- M-03: drop Referer-based skip from apiLimiter; add dedicated widgetLimiter

- M-06: gate /api/system/info, /logs/recent, /database/stats, /docker/containers, /speed-test behind requirePermission('metrics.view')

- L-01: startup banner now warns when TRUST_PROXY is off in production / errors when TOTP bypass is set without acknowledgement

Scripts / Docker:

- M-04: betterdesk.sh migration tool invocation switched from eval(cmd-string) to bash array exec

- M-05: all admin / PostgreSQL password generators switched from openssl rand -base64+tr+head to openssl rand -hex 16 (full entropy)

- L-02: docker-compose.yml / single.yml / quick.yml services gain security_opt: no-new-privileges and cap_drop: ALL

Documentation:

- I-04: add SECURITY.md (supported versions, reporting channels, SLA, scope, hardening defaults)

Go server (requires rebuild on host: cd betterdesk-server && go build ./...):

- H-03: /metrics now gated by METRICS_IP_ALLOWLIST / METRICS_PUBLIC; per-username login + 2FA rate-limit added on top of per-IP

- M-07: enrollment (/api/devices/register*) and branding (GET /api/branding) endpoints rate-limited per IP

- I-02: bd-mgmt WebSocket gets SetReadLimit(16 MiB) to bound memory

- L-04: auth middleware skips noisy public probes and redacts /peers/{id} segments

This commit was made possible thanks to Insolve.
2026-05-26 13:58:16 +02:00
Knienartowicz 8da6f8c9fd security: fix 3 critical + 3 high findings from production audit
Critical:

- C-01: WebSocket Origin validation (CSWSH protection) via new middleware/wsOrigin.js, applied to wsRelay, chatRelay, remoteRelay, bdRelay, cdapTerminalProxy, cdapMediaProxy

- C-02: Remove Tauri Origin-based CSRF bypass in server.js; only /api/bd/* skipped

- C-03: Update vulnerable deps (express 4.21.2, multer 2.0.0, protobufjs 7.4.0, helmet 7.2.0, axios 1.9.0, cookie-parser 1.4.7, express-session 1.18.1)

High:

- H-01: Disable auto-create-local-user on login by default; opt-in via BETTERDESK_AUTH_AUTOCREATE=true (does not affect ensureDefaultAdmin fresh-install bootstrap)

- H-02: Bearer-only auth for /api/bd/*; session cookie fallback removed; tokens redacted in logs

- H-05: Replace custom PBKDF2 with golang.org/x/crypto/pbkdf2; 600k iterations; new format pbkdf2-sha256\\\ with backward-compat for legacy salt:hash

Backward compatibility: legacy password hashes still verify; CSRF tokens still obtainable via csrfTokenProvider; fresh-install admin bootstrap (.admin_credentials flow) unchanged.

Audit report: docs/security/AUDIT_PRODUCTION_2026-04-10.md

This commit was made possible thanks to Insolve.
2026-05-26 13:35:12 +02:00
Knienartowicz 84252f5c40 feat: add warning and outline button styles to main.css; update action button styles in users.css 2026-05-26 13:16:31 +02:00
Knienartowicz 888cbcf38e feat: conditionally initialize backup and update sections based on server.config permission 2026-05-26 13:07:59 +02:00
Knienartowicz c934f07783 feat: add RustDesk PRO group endpoints and adjust request body limits 2026-05-26 13:03:59 +02:00
Knienartowicz 84987c7c9d feat: update Polish translations for BetterDesk dashboard 2026-05-26 12:49:41 +02:00
UNITRONIX 415b6cf967 feat: add terminal updater and keep Go API HTTP 2026-05-23 00:49:49 +02:00
UNITRONIX 274a52d1cd feat: Enhance update process for BetterDesk console and Go server
- Updated Polish and Chinese language files to reflect changes in update descriptions and confirmations.
- Modified settings.js to automatically include server updates in the update process.
- Simplified the update installation API to automatically handle server updates without user intervention.
- Improved updateService.js to ensure all supported components are updated together, enhancing reliability.
- Added logic to check and install the Go toolchain as needed during updates, ensuring compatibility.
- Enhanced error handling and logging during the update process for better visibility of issues.
2026-05-23 00:29:19 +02:00
UNITRONIX 9041fb7227 fix: clarify group management workflows (#140)
Make device group edit/delete actions visible, add direct user-group management entry points from the device group ACL modal, and allow device group editors to load user groups for ACL assignment.

Refs #140.
2026-05-23 00:16:22 +02:00
UNITRONIX 321e49b7f7 fix: polish folder tiles and Available Devices payload (#138) 2026-05-22 02:29:16 +02:00
UNITRONIX 6134b4235e Show pending enrollments in registrations UI (Refs #149) 2026-05-22 01:56:11 +02:00
UNITRONIX 99add5d434 fix: improve device folder tiles and RustDesk group sync (#138) 2026-05-19 18:56:09 +02:00
UNITRONIX bc7dc42f89 Fix browser update restart confirmation 2026-05-19 02:35:32 +02:00
UNITRONIX 41616fa121 Fix RustDesk tag and folder filters 2026-05-19 00:06:54 +02:00
UNITRONIX bdbf09edc6 feat: add user groups management functionality
- Implemented user groups creation, editing, and deletion features.
- Added API endpoints for managing user groups: create, update, and delete.
- Enhanced user interface with a dedicated user groups manager section.
- Updated translations for user groups related strings in multiple languages.
- Improved CSS styles for user groups display and actions.
- Added tests for user groups API functionality.
2026-05-18 23:58:56 +02:00
UNITRONIX c30d1a86aa Fix RustDesk folder tag sync 2026-05-18 02:34:38 +02:00
UNITRONIX 87e9251d31 feat: Implement user group management and access control
- Added user group membership functionality, allowing users to be assigned to groups.
- Introduced validation for group GUIDs and enhanced error handling in user routes.
- Updated device group routes to support allowed user groups, enabling better access control for devices.
- Enhanced database schema to include user group memberships and device group user group access.
- Updated services and database adapters to handle user group data and relationships.
- Modified front-end views to display and manage user groups effectively.
- Added tests to ensure proper functionality of user group assignments and device access control.
2026-05-18 02:23:57 +02:00
UNITRONIX 1460b55951 fix: separate RustDesk folder groups from tags (#138) 2026-05-15 01:19:21 +02:00
UNITRONIX 1f3b310a11 fix: keep RustDesk address books user-owned (#137)
Prevent the RustDesk Client API address-book response from auto-creating peers from console inventory. Existing address-book peers still receive console-side tag synchronization, while /api/peers remains the inventory endpoint.

Refs: #137

Reported-by: @boruto79

Also-reported-by: @karabelnikov
2026-05-15 01:05:32 +02:00
UNITRONIX 241d367ea7 fix: add tag-based dynamic device groups (#140) 2026-05-15 00:57:59 +02:00
UNITRONIX 96858c187b fix: scope RustDesk API peers to address books (#143)
Limit RustDesk client peer inventory for non-edit roles to peers already present in the authenticated user's legacy or personal address book. Keep editable operator/admin inventory sync unchanged and add route regression coverage for viewer accounts.

Reported-by: Henry-739
Refs: #143
Co-authored-by: GitHub Copilot <copilot@github.com>
2026-05-15 00:30:15 +02:00
UNITRONIX b9d4c77076 fix: update address book sync logic to exclude folder tags and enhance tag handling 2026-05-14 02:00:10 +02:00
UNITRONIX 8612ffd53b fix: allow HTTP client API for self-signed TLS
Adds explicit RUSTDESK_API_TLS mode so self-signed deployments can keep the web panel HTTPS while serving the RustDesk Client API on HTTP for stock client compatibility.

Refs #138
2026-05-11 23:02:42 +02:00
UNITRONIX 783f2a8a43 fix: sync device tags with RustDesk client API
Refs #138

Reported-by: Skansmer (#138)
2026-05-11 22:56:19 +02:00
UNITRONIX 73ff76885f fix(users): standardize roles and surface org membership inline
Address the follow-up feedback on #136 about the user-management UX
feeling disjointed and using non-standard role labels:

- Rename the base organization role from "Viewer"/"User" to
  "Member" across all 26 locales. This removes the vocabulary
  collision with the server-wide "Viewer" role and makes the
  two-axis role model (server role vs per-org role) clearer.
- Add an Organizations column to the System > Users table so
  admins can see each user's org memberships at a glance without
  opening a modal. Badges are clickable and reopen the existing
  Organizations modal for that user.
- Clarify the Add/Edit User form: the role dropdown is now
  labelled "Server Role" with a hint that per-organization roles
  are configured separately under each user's Organizations.
- The Organizations modal now has an explicit section heading and
  a short hint, and uses i18n labels for the role dropdown with
  an aria-label so the org role is visually distinct from the
  server role.

Backend role values are unchanged ("user"/"operator"/"admin"/
"owner" for orgs, existing 7 server roles), so this is a pure
UX/i18n change with no schema or API impact.

Refs: #136

Suggested-by: Sterlyn Kong <68391309+SterlynKong@users.noreply.github.com>
2026-05-11 02:19:08 +02:00
UNITRONIX 5dd4933b41 i18n/docs: integrate community PR improvements
Complete Czech console translation from PR #133, update Docker quick-start admin credential lookup from PR #134, and fix live device-status updates found while reviewing PR #35.

Refs: #133, #134, #35

Co-authored-by: Karel Lowprize K <lowprize@gmail.com>

Suggested-by: Rafael Monteiro <96262868+rafaelgm@users.noreply.github.com>
2026-05-11 00:05:51 +02:00
UNITRONIX f101953f28 Fix multi-org assignment from system users
Reported-by: @SterlynKong

Refs: #136
2026-05-10 03:45:03 +02:00
UNITRONIX 74300c916c Fix user recovery after update
Reported-by: @SterlynKong

Refs: #136
2026-05-09 01:02:00 +02:00
UNITRONIX a33bc4f95b fix: handle org assignment IDs consistently
Fixes #135

Reported-by: lowprize
2026-05-09 00:52:44 +02:00
UNITRONIX a8d3259d43 feat(server-management): add server management service and terminal proxy
- Implemented server management service providing resource snapshots, file browser, service control, and audit logging.
- Added terminal proxy for WebSocket-backed PTY, allowing browser-based shell access with user authentication and role-based access control.
- Created server management view with tabs for overview, terminal, file management, and services, including UI elements for displaying system metrics and managing files/services.

Co-authored-by: Copilot <copilot@github.com>
2026-05-07 03:09:03 +02:00
UNITRONIX c249f63317 fix(web): polish dashboard and accessibility layout 2026-05-03 03:11:49 +02:00
UNITRONIX 723c95121f feat(web): add accessibility preferences panel 2026-05-03 02:49:22 +02:00
UNITRONIX 454585893d fix(web): embed beta 3.1 modules reliably 2026-05-03 02:24:35 +02:00
UNITRONIX 99216040eb fix(web): stabilize beta 3.1 dashboard lifecycle 2026-05-03 02:12:20 +02:00
UNITRONIX c5970657e7 feat(i18n): expose all panel languages in selector
Render language choices dynamically from loaded locale files instead of hardcoding EN/PL. Add selectors on the navbar, login screen, and desktop login screen so users can choose a language before or after authentication.

Persist the selected language in the browser via cookie/localStorage and on authenticated accounts via users.preferred_language. Merge client translations with the default locale fallback so incomplete language files do not surface raw keys in the UI.
2026-05-03 02:02:15 +02:00
UNITRONIX 452c76069c fix(users): mirror Node panel users to Go server for org linking (#125)
Panel accounts were created only in the Node auth.db while the
Organization 'Add User -> Add Existing' dropdown queries the Go
server's users table via db.ListUsersNotInOrg(). This produced a
mismatch where only the seeded admin appeared as linkable.

Add a userSync service that mirrors create / update / delete /
password-reset operations from the Node panel to the Go server's
/api/users endpoints, plus a one-shot backfill at startup that
creates Go-side records for any pre-existing panel users (random
throwaway password; Node bcrypt remains authoritative for panel
login).

Reported-by: SterlynKong <SterlynKong@users.noreply.github.com>
2026-05-03 01:48:08 +02:00
UNITRONIX b66ddbe98f i18n(web): fill missing Node.js locale keys
Backfill missing web console translation keys across all available locale files using the English and Polish catalogs as the completeness baseline.

Also normalize the locale JSON files so they parse consistently during tooling and validation.
2026-05-01 22:31:14 +02:00
UNITRONIX a23b860d41 fix(scaling): make Relay Nodes Add/Edit actually save (#119)
Three independent bugs combined to make 'Add Relay' silently do nothing:

1. saveRelay() in public/js/scaling.js used raw fetch() without the panel's
   CSRF token, so every POST/PUT/DELETE was rejected by the CSRF middleware.
2. The catch block swallowed every error and the modal closed regardless of
   the response code, so the user never saw the rejection.
3. The relay/rules routes proxied to /scaling/relays on the Go server, but
   the Go server doesn't (yet) implement those endpoints — every request
   ended up as a 404 and the panel's relay table stayed empty forever.

Changes:

- routes/scaling.routes.js: drop the dead Go proxy, persist relay-node
  metadata and assignment rules in the existing 'settings' table
  (auth.db / DATABASE_URL). Strict input validation (host:port,
  Unicode-safe name, ranges for sessions/bandwidth/priority), 409 on
  duplicate addresses, capped at 100 relays / 200 rules. Health and
  metrics endpoints now return explicit 'live telemetry not yet
  available' placeholders instead of 500s.
- public/js/scaling.js: every mutating fetch() now sends x-csrf-token,
  validates inputs with a toast, parses JSON error bodies, only closes
  the modal and reloads on success. Falls back to alert() if the toast
  service is missing so users are never left guessing.
- views/scaling.ejs: info banner above the Relay Nodes table making
  clear that the list is operator-side metadata and that actual relay
  routing is configured via RELAY_SERVERS on the BetterDesk server.
- public/css/scaling.css: styles for the new info banner.
- lang/en.json, lang/pl.json: i18n keys for the banner, validation
  messages and success/failure toasts.

Note: the reporter also tried RELAY=... — only RELAY_SERVERS is read
by the Go server (see config/config.go:160). Worth surfacing in docs
in a follow-up.

Reported-by: @Elektrik1
2026-05-01 22:24:57 +02:00
UNITRONIX 294f006cd0 fix(ui,i18n): standardize role labels between server and org user modals (#120)
The 'Add User' modal in an organization showed Owner / Admin / Operator / User
while the server-level 'Add User' modal showed Viewer / Operator / Administrator
/ Global Admin / Server Admin / Super Admin / Pro. Same conceptual roles had
inconsistent labels (Admin vs Administrator) and the lowest tier used different
words (User vs Viewer), making the two modals look unrelated.

Server-only roles (Super Admin, Server Admin, Global Admin, Pro) intentionally
remain absent from the org modal — they are not org-scoped.

Changes:
- web-nodejs/public/js/organizationDetail.js: reorder roleOptions() to
  lowest-first ['user','operator','admin','owner'] to match the server modal's
  Viewer→Pro ordering pattern.
- web-nodejs/lang/*.json (26 locales): in the 'organizations' section, rename
  role_user label to the localized equivalent of 'Viewer' (matching the
  server section's role_viewer) and role_admin to 'Administrator' (matching
  server section's role_admin). Backend enum values ('user', 'admin') are
  unchanged — this is a pure label change, no schema migration required.

Reported-by: @SterlynKong
2026-05-01 22:15:23 +02:00
UNITRONIX b65a16c7b5 fix(signal,updater,ratelimit): address #121, #122, #123
Three independent bug fixes bundled together; none of the issues are
auto-closed by this commit so the reporters can confirm on a tagged build.

#121 — NAT hairpin: same-public-IP detection forces relay path

The signal handler now distinguishes 'same /24 private subnet' (genuine
LAN, keep direct path) from 'same public IP' (NAT hairpin scenario).
When both peers register from the same public IP, both the UDP and
TCP/WS punch-hole handlers skip the LAN-address exchange and steer the
client straight to the relay — matching upstream RustDesk behavior.
Most consumer routers and cellular gateways drop hairpinned UDP, which
was causing same-Wi-Fi connections to silently time out.

  - new helper isSamePublicIP() in signal/handler.go
  - new config flag SameNATRelay (default: enabled)
  - env: SAME_NAT_RELAY=N to opt out
  - cli: --same-nat-relay=false to opt out

Reported-by: @eternalliving (#121)

#122 — Rate limit configurable, 0 disables

The 20 registrations/min/IP cap was unworkable for any deployment with
real NAT/CGNAT in front of it. Made it tunable without recompiling and
hardened the limiter to short-circuit when disabled.

  - new config field SignalRateLimitPerIP (default: 20, unchanged)
  - env: SIGNAL_RATE_LIMIT_PER_IP=<n> (0 = unlimited)
  - cli: --signal-rate-limit-per-ip=<n>
  - ratelimit.IPLimiter.Allow() now returns true early when limit<=0

Reported-by: @Henry-739 (#122)

#123 — Updater corrupting live SQLite WAL files

A previous gitleaks-fix commit accidentally tracked live SQLite sidecar
files (auth.db-shm/wal, betterdesk.db-shm/wal, .session_secret,
.update_sha). The in-app updater's diff-against-GitHub logic then
'restored' those tracked-by-mistake files on user installs, which is
exactly how SQLite database corruption gets manufactured.

Layered defense:
  - .gitignore now covers *.db-shm, *.db-wal, *.sqlite3-{shm,wal,journal},
    web-nodejs/data/, .session_secret, .update_sha, .api_key,
    .admin_credentials, .force_password_update, .env*
  - removed the offending files from the index (data/.gitkeep retained)
  - updateService.js EXCLUDE_PATTERNS extended to match the new gitignore
  - new write-time guard isProtectedRuntimePath() wired into all four
    write sites in updateService.js so even a stale GitHub diff cannot
    overwrite a runtime state file on disk

Reported-by: @SterlynKong (#123)
2026-05-01 16:22:50 +02:00
UNITRONIX 7ffd109243 Gitleaks fix 2026-04-29 01:54:04 +02:00
UNITRONIX 57c4806514 feat(api): RustDesk Flutter compatibility shims and 404 diagnostics
Adds three small but valuable compatibility patches inspired by progloto's
PR #81 analysis, reworked to fit our codebase and security baseline:

* Stub /api/group, /api/group/get, /api/peers/list with the {total,data,msg}
  envelope so RustDesk PRO Flutter clients can finish their device-list
  flow and gracefully fall back to address-book mode.
* Log every unmatched route in the Go API catch-all (method, path, client
  IP, User-Agent) so missing client compatibility endpoints surface in ops
  logs immediately.
* Mirror the same 404 logging in the Node.js RustDesk-compatible API app
  and the main panel app (limited to /api/* and /ws/* paths to avoid
  static-asset noise).

The original PR #81 also bundled a docker-compose.qnap.yml with hardcoded
production secrets, a private NAS deploy script, and a VERSION bump that
collided with our release cycle, so we are not merging it as-is.  The
ideas behind these three patches were sound and are credited here and
in CHANGELOG.md.

Co-authored-by: progloto <progloto@users.noreply.github.com>
2026-04-26 16:02:25 +02:00
UNITRONIX ab6adff56f fix(security): harden login and audit endpoints 2026-04-26 02:09:44 +02:00