563 Commits
Author SHA1 Message Date
John Smith 8b57d4bcac feat(ui): render declarative settingsSchema in admin and extension settings (#92)
Both the Server Admin Plugins page and the Desktop Extension Settings section
now render every settingsSchema field type (string/password/number/boolean/
select), load current values from the settings API, and save partial updates.
Password inputs leave the stored secret untouched unless a new value is typed.
2026-09-17 23:43:49 -04:00
John Smith d50272e9a6 feat(desktop): add plugin_open_external host command
Backs ctx.ui.openExternal for client plugins. Only http(s) URLs are opened,
through the configured opener plugin, so a plugin cannot launch arbitrary
local protocol handlers.
2026-09-17 22:44:03 -04:00
John Smith 3170984891 feat(process): merge plugin launch overrides into the launch command
launch_process accepts optional LaunchOverrides and applies them after the
manifest/handler launch command is resolved: executable replacement, wrapper
bin/args prepended around the game command, appended arguments, merged
environment, and a working-directory override. All fields are additive, so a
plugin that sends none is byte-for-byte unaffected. launch_game forwards the
overrides through the new Option parameter. Unit tests cover each merge rule.
2026-09-17 22:43:59 -04:00
John Smith 65fe0af615 feat(desktop): add runner provider SPI and launch-override pipeline
Client plugin contexts gain registerRunnerProvider (game:runner), launchGame,
library queries, host ui helpers, and a local event bus. executeLaunchPipeline
now resolves LaunchOverrides from pre-launch hooks and applicable runner
providers (skipping unavailable/non-matching ones) and forwards them to the
launch closure, which the library view passes to the native launch_game
command. Adds the plugin_open_external host command for ctx.ui.openExternal.
2026-09-17 22:43:51 -04:00
John Smith b23ff35238 test(process): cover game-provided uninstaller execution (#56)
Extract the resolved-uninstaller execution into run_uninstaller_command and
add hermetic tests: the uninstaller runs with the managed install directory
as its working directory, and a non-zero exit is reported as a status
(non-fatal) instead of a ProcessError so directory removal proceeds.
2026-09-17 22:10:09 -04:00
John Smith e237e39876 feat(desktop): add pre-launch:network-post launch stage to the plugin host
Runs after pre-launch:network and right before the game process spawns so
plugins can act on state finalized by the network stage (e.g. drop-gse
refreshing custom_broadcasts.txt with freshly assigned ZeroTier mesh
addresses). The stage participates in reverse-order rollback like the other
pre-launch stages.
2026-09-17 21:54:55 -04:00
John Smith 1aedb5ce0e fix(security): resolve devalue advisory, scan alerts, sidecar auth gate
- Bump devalue override to >=5.9.2 (closes #89)
- Eliminate Semgrep alerts and align SARIF upload filter (closes #68, closes #88)
- Guard binary plugin sidecar assets with ACL check and private cache (closes #91)
- Fix Windows installer Rust candidates immutable borrow error (closes #90)
- Document session token digest invariant
2026-09-17 21:11:13 -04:00
John Smith 33eac31fe0 feat(plugins): bundle sidecar provisioning for client plugins
Server:
- Verify client.sidecars during bundle verification (fail-closed on
  missing files, sha256 mismatch, unallowlisted names, path escape)
- Manifest spread ships sidecars through plugin discovery

Desktop:
- plugin_sidecar_stage Tauri command: fetch the platform target from the
  client asset route, verify sha256, stage into the per-plugin app-data
  bin dir with 0755, atomic rename, symlink refusal, allowlist gating
- plugin_sidecar_clear removes staged binaries at unregister
- plugin_system_run resolution falls back to the staged bin dir after
  PATH and well-known dirs, still gated by client.commands
- detectSidecarPlatform picks os/arch targets for the host; staging
  failures are non-fatal (PATH/TypeScript fallback intact)

Ref Heretek-Games/drop#87
2026-09-17 18:02:26 -04:00
John Smith 4738a60d6a style(rust): apply rustfmt to cloud saves and plugin runner 2026-09-17 16:43:21 -04:00
John Smith 148424984f feat(desktop): post-install launch target resolution in the setup modal
- scan the installed directory and resolve the launch target via the
  server after an installer-based setup completes, with a scored picker
  fallback when confidence is low
- include the install dir and a preempt-scan hint on pipeline completion
- optionally identify the adopted binary with the GameBox plugin
2026-09-17 16:43:16 -04:00
John Smith 6533b3e235 feat(desktop): plugin command well-known-dir fallback and topbar:status slot
- When an allowlisted bare command fails to spawn (not on PATH), retry from
  platform well-known installation directories (Linux /usr|/usr/local sbin,
  /opt/ZeroTier/One; macOS ZeroTier & Homebrew dirs; Windows ZeroTier
  Program Files/ProgramData dirs). Only plain, non-symlink, executable files
  match the exact allowlisted name, preserving the bare-name security model
- Mount the topbar:status plugin slot in the header so global plugin status
  indicators (e.g. mesh connection state) are rendered
2026-09-17 16:23:46 -04:00
John Smith 85d0d39c49 test(plugins): add launch pipeline rollback, security host, and .dropplugin tests 2026-09-17 15:57:03 -04:00
John Smith 19423b081d fix(desktop): tolerate unconfigured server and NVIDIA+Wayland at startup
- Auto-disable WebKitGTK DMA-BUF renderer on NVIDIA + Wayland sessions
  (Error 71 protocol error at startup) unless the user overrides it
- Replace unguarded base-url panic during webview startup IPC with
  graceful errors (try_base_url, check_online map to error responses)
- Document frontend dev-server requirement and tray/deprecation notes
2026-09-16 19:07:14 -04:00
John Smith e405d0f6b6 fix(desktop): clear SonarCloud develop triage issues in desktop/main
Resolve the 6 open SonarCloud issues scoped to desktop/main code on
develop:
- workshop planner sorts mod paths and missing entries with
  localeCompare comparators instead of default sort (S2871, bug class).
- WebRTC ICE config fetch moves to module scope; the composable only
  needed it for createPeer and closed over nothing (S7721).
- remote plugin loader keeps the root-capabilities fallback in its own
  statement instead of a nested ternary (S3358).
- browser-mode invoke fallback prefers the nullish coalescing
  operator (S6606).
- Store Scanner SPI store union keeps its known-store literals
  suggestible by widening with (string & {}) instead of plain string,
  which swallowed them (S6571).
- big-picture keyboard navigation moves to a window keydown listener
  so the tiles container does not pose as an interactive element
  (Web:S6842); arrow tiles are natively focusable and the listener
  makes arrow navigation reach files without a prior container click.
2026-09-15 16:44:36 -04:00
John Smith 4a32227eba fix(cloud-saves): make crate compile for windows and macOS targets
- declare known-folders dep and serde/derive used by the crate
  instead of relying on feature unification with the app crate
- un-gate the Platform import so it is in scope on every target
- drop unused rustix::path::Arg import (rustix path module is
  feature-gated and unavailable natively on windows)
- replace Component::as_str (does not exist on std) with an
  as_os_str().to_str() match, falling back to the raw OsStr
- regen Cargo.lock
2026-09-15 15:15:43 -04:00
John Smith 6b735f348a fix(xss): mark micromark-rendered v-html as safe for semgrep 2026-09-15 09:35:55 -04:00
John Smith 4b15962c6a fix(desktop): use static log format strings and shell-free spawning 2026-09-15 09:35:51 -04:00
John Smith f8535cd449 Merge remote-tracking branch 'upstream/develop' into develop
# Conflicts:
#	server/.gitignore
#	server/deploy-template/quadlet/base/drop-postgres.container
#	server/deploy-template/quadlet/base/drop.container
#	server/deploy-template/quadlet/env/drop.env.example
#	server/deploy-template/quadlet/install.sh
#	server/deploy-template/quadlet/uninstall.sh
#	server/server/internal/objects/fsBackend.ts
#	server/server/internal/saves/index.ts
2026-09-14 22:21:37 -04:00
BillyOutlast bac28098f9 Merge pull request #76 from Heretek-Games/fix/rust-hygiene
[audit] Rust hygiene: desktop/native_model fmt, clippy, and doctests
2026-09-14 22:04:21 -04:00
John Smith 006cec7d2b docs(native-model): compile maintainable doctests; document feature-gated examples
- README upgrade example no longer calls the nonexistent encode_downgrade; it
  converts back to the old model and encodes that using the real API
- add log dev-dependency so attribute-macro-generated doctests compile
- Encode/Decode trait examples use the default bincode_1_3 codec and now run
  in the default doctest suite (5 pass, was 1 pass/9 ignored)
- feature-gated codec examples stay ignored with the reason documented in
  codec/mod.rs; verified they compile with all three codecs enabled
2026-09-14 21:10:52 -04:00
Nate PelzelandDecDuck 06eb5e59ac Fix Install in the missing-dependency modal (#489)
* Fix Install in the missing-dependency modal

The "Missing required dependency" modal calls download_game without
enableUpdates, but the command requires it, so clicking Install fails with:

  invalid args `enableUpdates` for command `download_game`: command
  download_game missing required key enableUpdates

Pass it the same way the library page does: true when installing the
latest version.

* Update DependencyRequiredModal.vue

---------

Co-authored-by: DecDuck <[email protected]>
2026-09-15 10:16:45 +10:00
John Smith f364a7533e fix(rust): make desktop clippy clean under -D warnings
Resolve the desktop workspace lints surfaced by clippy --all-targets
--all-features -- -D warnings: redundant references in formatting macros,
collapsible ifs, irregular format braces, a legacy std::usize import,
deprecated constants, unused nightly features, and a MutexGuard held across
the await inside send!. Allow too_many_arguments on the two pipeline runners
with a rationale.

Refs #67
2026-09-14 18:29:09 -04:00
John Smith 96c294ef4e style(rust): apply cargo fmt and fix broken native_model doctests
- Run cargo +nightly fmt across desktop/src-tauri (37 files) and
  libraries/native_model (fmt drift).
- Mark the feature-gated/outdated native_model doc examples as ignore so
  cargo test --doc passes (they reference optional codec features and a
  removed encode_downgrade helper); the default bincode_1_3 example still runs.

Refs #67
2026-09-14 18:25:11 -04:00
John Smith ab3355969e fix(deps): update rustls to 0.23.45 and chacha20 to 0.10.2
RUSTSEC-2026-0285 affects rustls 0.23.43 (TLS 1.3 handshake accepted across
encryption levels); 0.23.45 is the fixed release. chacha20 0.10.1 is yanked.
Update all three lockfiles and silence the shared deny.toml's expected
unmatched diagnostics (advisory ignore only matches native_model; the license
allow list is a cross-crate superset, so drop the unused bzip2-1.0.6 entry).

Closes #64
2026-09-14 18:23:36 -04:00
John Smith 65313e61c4 feat(power): add handheld battery policy and command
Phase 2 / #18 handheld power management:

- New power crate: PowerPolicy/PowerState/PowerDecision with a pure
  decide() and a Linux sysfs battery reader (parse_linux_power_state +
  read_linux_power_state).
- download_power_decision Tauri command maps the current battery state to
  allow/throttle/pause for the download manager (unrestricted when
  unknown).
- 5 tests (mains/charging, thresholds, clamping, validation, sysfs
  parsing); clippy clean and cargo check -p drop-app passes.
2026-09-14 13:58:34 -04:00
John Smith 501b040ca7 feat(input): add shareable controller profiles
Phase 2 / #18 per-game input configurations:

- input::profile: ControllerProfile (name, deadzone, gyro sensitivity,
  button remaps) with serde JSON round-trip, validate_profile, remap and
  apply_profile (deadzone + gyro scale + remaps).
- 4 tests (JSON round-trip, validation errors, apply, remap dedupe);
  clippy clean and cargo check -p drop-app passes.
2026-09-14 13:56:20 -04:00
John Smith 8950364fd9 feat(desktop): add a workshop mod manager page
Completes the desktop mod-manager loop for #20:

- fetch_workshop_subscriptions / fetch_workshop_mod Tauri commands.
- useWorkshopMods fetches subscriptions, reads each mod manifest, and
  plans the load order.
- pages/workshop.vue shows the ordered mods, missing dependencies and
  file conflicts.
- Desktop typecheck/lint/tests clean and cargo check -p drop-app passes.
2026-09-14 13:55:11 -04:00
John Smith dd54cada81 feat(desktop): add the workshop mod load planner
Phase 4 / #20 mod manager core:

- internal/workshop/planner.ts computes a dependency-first load order,
  reports missing dependencies, and detects file conflicts between mods.
- 5 tests (ordering, missing deps, cycles, conflicts, disjoint files);
  desktop suite now 16 tests, typecheck clean.
2026-09-14 13:52:10 -04:00
John Smith 4c9e59dbf5 feat(desktop): add the client WebRTC peer module
Phase 3 / #19 NAT traversal (client half):

- internal/webrtc/peer.ts wraps the webview RTCPeerConnection: offer/
  answer/ICE flow over a data channel, plus pure signaling/ICE helpers.
- useWebRtc composable fetches ICE config and builds a peer; the
  fetch_ice_config Tauri command performs the authenticated GET.
- Desktop tests cover the pure helpers (11 total); typecheck/lint clean
  and cargo check -p drop-app passes.
2026-09-14 13:51:04 -04:00
John Smith d7d8439e59 feat(desktop): report local presence on launch and exit
Completes the rich-presence loop for #20:

- Tauri commands report_presence / clear_presence call the authenticated
  client presence API and no-op quietly when unauthenticated.
- The library page reports in-game with the game id after a successful
  launch and back online when the game is stopped.
2026-09-14 13:31:03 -04:00
John Smith de1b808014 feat(community): add a public screenshot gallery
Phase 4 / #20 community hubs (screenshot galleries):

- ObjectHandler.setPermissions replaces an object's permission list.
- ScreenshotManager gains getPublicAllByGame and setVisibility, which
  synchronize object permissions (owner read; anonymous:read when public)
  with the screenshot's visibility.
- Public GET /api/v1/community/:gameid/screenshots and owner-only
  POST /api/v1/client/screenshots/:id/visibility.
- Desktop community page renders the gallery via the existing object
  asset protocol; new fetch_game_screenshots Tauri command.
- 2 tests for the permission mapping.
2026-09-14 13:10:52 -04:00
John Smith 327996fc53 feat(input): add a Linux uinput virtual-gamepad backend
Phase 2 / #18 Drop Input:

- New input::uinput module: state_to_events maps sticks/triggers/dpad to
  ABS events and emits every button's pressed/released state each frame.
- UinputBackend opens /dev/uinput, configures EV_KEY/EV_ABS bits and axis
  ranges, creates the device, pushes input_event frames with SYN_REPORT,
  and destroys the device. create() surfaces the OS error when /dev/uinput
  is unavailable rather than faking a device.
- supported_backends() now reports Uinput on Linux alongside the Null
  fallback; BackendKind docs updated.
- 4 new tests (axis scaling/clamping, button+release/dpad, pre-create
  push error); 10 total.
2026-09-14 13:04:02 -04:00
John Smith 3db58710cb feat(desktop): show per-game forum threads on the community page
Completes the forums UI for #20:

- Tauri commands fetch_forum_threads / fetch_forum_thread read the public
  community API and deserialize into camelCase views.
- community.vue loads reviews and threads together and renders a
  discussion section with an inline thread view.
- Registered the new commands alongside fetch_game_reviews.
2026-09-14 12:54:44 -04:00
John Smith c6b92063fe feat(desktop): stage shader caches before launch and document the pack format
Phase 1 / #17 remaining shader pre-caching work:

- shader_cache::stage_shader_caches restores packaged *.dxvk-cache files
  into the install directory before launch, preserving a locally warmed
  cache unless overwrite is requested.
- docs/implementation/shader-cache-format.md defines the manifest/pack
  format shared with the drop-gamebox community index, including SHA-256
  verification and trust notes.
- 1 new test (cache-only filtering, preserve, overwrite).
2026-09-14 12:41:28 -04:00
John Smith 8dde0ae641 refactor(desktop): expose a generic findFiles host primitive
plugin_game_check_anticheat hardcoded EAC/BattlEye/Vanguard/Denuvo names in
the generic client host. Replace it with plugin_game_find_files, which
returns installed paths matching caller-supplied patterns, and drop the
AntiCheatReport/checkAntiCheat SPI so that domain knowledge lives in the
plugin (e.g. drop-gse) rather than core.
2026-09-14 11:17:23 -04:00
John Smith d0e2953065 fix(desktop): consume plugin events through the Tauri event bridge
plugin_subscribe emits a Tauri event named plugin:event, but subscribe()
listened with window.addEventListener and expected a DOM CustomEvent, so
plugin WebSocket messages never reached their listeners. Register a real
Tauri listener for plugin:event (payload {channel,data}) in the Tauri host
and keep the DOM CustomEvent path as the browser/dev fallback.
2026-09-14 10:53:47 -04:00
BillyOutlast e4b5106ba5 Merge branch 'develop' into fix/core-hardening 2026-09-14 09:15:09 -04:00
John Smith 3b99bc5a50 fix(input): report only implemented virtual-gamepad backends 2026-09-14 09:10:55 -04:00
John Smith b72dc0fb1a fix(cloud_saves): skip unreadable save paths instead of panicking 2026-09-14 09:10:52 -04:00
John Smith e7c1786e1f chore(security): run cargo-deny over every Rust crate 2026-09-14 09:10:31 -04:00
John Smith 59cccd1187 fix(process): sweep symlink escapes after archive extraction 2026-09-14 09:10:26 -04:00
John Smith 53930c39fb fix(desktop): resolve typecheck errors in client plugin manager
Expose the shared serverWs bridge as a manager-level readonly member so
useAchievementToasts can subscribe via the typed ClientPluginWebSocket
instead of reaching for the per-plugin context field. Narrow the remaining
noUncheckedIndexedAccess findings in the manager and its tests.
2026-09-14 08:55:59 -04:00
John Smith 0ef75a6251 feat(store-import): add desktop page driving the StoreScanner SPI 2026-09-14 02:00:51 -04:00
John Smith a7b079f0cd feat(achievements): mount unlock toasts in the desktop app shell 2026-09-14 02:00:01 -04:00
John Smith d81df27640 feat(input): report platform backend availability and fail explicitly when absent (#18)
- Add BackendKind/supported_backends() and a NullBackend that returns a clear
  BackendUnavailable error when /dev/uinput or ViGEm is missing, so the missing
  native driver is surfaced instead of silently no-op'ing.
2026-09-14 01:56:48 -04:00
John Smith 58706fba0d feat(achievements): add unlock_achievements Tauri command for plugin bridges (#8) 2026-09-14 01:55:37 -04:00
John Smith e4f1eff07d feat(achievements): add desktop unlock toasts for drop:achievement:unlock (#8)
- Pure toast queue (enqueue/dedupe/dismiss/expire) with tests.
- useAchievementToasts() subscribes to the core unlock channel; a toast
  component renders the overlay notifications.
2026-09-14 01:54:41 -04:00
John Smith 49f2f61296 feat(commerce): dispatch payment webhooks and wire store-scanner imports (#21)
- Add a payment webhook dispatcher + public /api/v1/commerce/webhook/:gateway
  route that resolves the plugin-registered PaymentGateway and verifies its
  signature inside handleWebhook.
- Add collectStoreGames() aggregating every StoreScanner SPI result with
  per-store failure isolation, plus a useStoreImport() composable.
2026-09-14 01:53:01 -04:00
John Smith bbdc7a2b2d feat(delivery): add shader-cache discovery hook and desktop export commands (#17)
- Add the shader_cache crate: DXVK/VKD3D *.dxvk-cache discovery across the
  install dir and Proton/UMU prefix, plus collision-safe collection, tested
  with tempfiles.
- Expose list_shader_caches/export_shader_caches Tauri commands; the community
  index lives in the drop-gamebox plugin.
2026-09-14 01:49:50 -04:00
John Smith f8d57cef1a feat(cloud-saves): provision managed Ludusavi into <data>/tools/ludusavi
- Add cloud_saves::provision with platform asset resolution, GitHub release
  tag parsing, tar.gz/raw extraction, and executable install, unit-tested.
- Add a provision_ludusavi Tauri command and run a best-effort provisioning
  task on startup, mirroring the managed 7z/innoextract tools.
2026-09-14 01:46:52 -04:00