Skip to content

Releases: I4cTime/protonshift

v0.9.7 — packaged-build CSS fix + docs refresh

14 May 21:57

Choose a tag to compare

Quality + docs release. One real bug fix, plus a long-overdue docs pass.

Bug fix

  • Packaged builds rendered unstyled. The static-export HTTP server inside the Electron main process rejected any request whose pathname contained `..` as a traversal attempt. That blanket check also matched Turbopack's content-hashed CSS chunk filenames (e.g. `16-.0wq_hn57..css`), so the renderer 403'd its own stylesheet and loaded as raw HTML.
    • Fix replaces the substring check with a per-segment check that only rejects literal traversal segments (`..` / `.`), so dots inside filenames pass through.
    • File: `electron/main.ts`.
    • User-visible: AppImage / deb / rpm / flatpak builds now look the same as `pnpm dev` again.

Docs

  • New ARCHITECTURE.md (326 lines): system diagram, renderer & backend layout, HTTP API contract, project layout, build-from-source, VM-testing harness, pre-commit checks, contributing guide, and the release process used here.
  • README rewrite: social-card hero image, CI / release / downloads / license badges, "Why ProtonShift?" intro, consolidated install section with copy-pasteable per-format commands (AppImage, deb, dnf, zypper, flatpak), roadmap, and a link to ARCHITECTURE.md in the nav strip.

Housekeeping

  • Version bumped to 0.9.7 in all six sources (electron, renderer, python `version`, AppStream metainfo with new `<release date="2026-05-14">` entry, bug-report issue template placeholder, nav-bar fallback string).
  • Zero open Dependabot alerts — all 18 from the previous window were closed by v0.9.6 and no new advisories appeared.

Verification

  • `tsc` on Electron main: clean.
  • `next build` (static export, Next 16.2.6): clean, 8/8 routes prerendered.

v0.9.6 — security hardening

13 May 11:08

Choose a tag to compare

Security maintenance release. Closes 18 open Dependabot alerts; no functional changes.

Direct bump

  • Next.js 16.2.3 → 16.2.6 — closes 13 CVEs:
    • High: segment-prefetch proxy bypass (incl. 16.2.6 incomplete-fix follow-up GHSA-26hh-7cqf-hhc6), Pages-Router i18n proxy bypass, dynamic-route-param proxy bypass, SSRF on WebSocket upgrades, Server Component DoS, Cache-Components connection-exhaustion DoS.
    • Medium: CSP-nonce XSS in App Router, beforeInteractive script XSS, RSC response cache poisoning, Image Optimization API DoS, transitive postcss.
    • Low: Middleware/Proxy redirect cache poisoning, RSC cache-key collisions.

Transitive overrides added (electron/package.json)

  • postcss <8.5.10 → ^8.5.10 (now 8.5.14 across next and @tailwindcss/postcss) — GHSA-qx2v-qp2m-jg93 (XSS via unescaped `</style>` in CSS stringify).
  • ip-address <=10.1.0 → ^10.1.1 (now 10.2.0 via electron-builder → node-gyp → socks) — GHSA-v2v4-37r5-5v8g (XSS in Address6 HTML methods). Build-time only.
  • @xmldom/xmldom <0.8.13 → ^0.8.13 (via electron-builder → plist) — closes 3 high CVEs (GHSA-f6ww-3ggp-fr8h, GHSA-j759-j44w-7fr8, GHSA-x6wf-f3px-wcqx: XML/PI/comment injection). Build-time only.

Overrides are version-pinned narrowly so they auto-disengage once upstreams legitimately ship the patched floor.

Context

  • The renderer ships as a Next.js static export packaged inside Electron, so Next's server-runtime attack surface (Middleware, Image Optimization API, RSC server cache, WebSocket upgrades) is not reachable at runtime — but bundled dep versions are still patched.
  • Electron is already on 39.8.5, which closes the 35 previously-listed Electron CVEs from the 38.x and 39.x advisories. No Electron change this round.

Verification

  • pnpm install (workspace, both packages) clean.
  • tsc on Electron main: clean.
  • next build (static export, Next 16.2.6): clean — 8/8 routes prerendered.

v0.9.5

13 May 04:37

Choose a tag to compare

ProtonShift v0.9.5 — ScopeBuddy, gamepad tester, Ctrl+K command palette, new VM test harness.

Install

Grab the asset for your distro below once the build job finishes.

# AppImage (any distro)
chmod +x ProtonShift-*.AppImage && ./ProtonShift-*.AppImage

# .deb (Ubuntu / Pop!_OS / Mint / elementary OS)
sudo dpkg -i protonshift_*_amd64.deb

# .rpm (Fedora / openSUSE / RHEL)
sudo dnf install ProtonShift-*.rpm

# Flatpak
flatpak install ProtonShift-*.flatpak && flatpak run io.github.protonshift

What's new

App + UI

  • Navbar version now reads app.getVersion() via a new IPC bridge — no more stale v0.1 brand string drifting behind releases.
  • Version sources synced to 0.9.5 in lockstep: electron/package.json, electron/renderer/package.json, src/game_setup_hub/__init__.py, AppStream metainfo, bug report template.

Renderer features

  • ScopeBuddy: dedicated /scopebuddy page with KV override editor, per-game overrides, and detection toasts in the Gamescope builder.
  • Command palette (Ctrl+K) with cross-page navigation.
  • Gamepad tester component on the Controllers page.
  • Game detail rebuilt as KPI strip + tabs + profiles menu.
  • Renderer-wide HeroUI v3 polish (semantic tokens replace ad-hoc opacity classes).

Python backend

  • New scopebuddy module + /scopebuddy API routes (detect, read, write KV overrides).
  • Hardening across gamescope, protontricks, presets, steam, tool_check, _vendor_compat.
  • API state/model split for testability; new tests/test_scopebuddy.py.

Repo & dev experience

  • New vm-test/ harness for exercising packaged builds against real distros via Quickemu (Ubuntu 24.04, Fedora 41, Debian 12, CachyOS, openSUSE Tumbleweed, Bazzite). run-vm.sh stages docs into the SMB share so guests can less /mnt/protonshift-build/_docs/<distro>.md while testing.
  • docs/python-review.md moved under docs/internal/.
  • scripts/linux-matrix.sh moved under scripts/ci/.
  • Fixed accidentally-gitignored vm-test/ and tests/ paths that had been hiding the harness and new tests from git.

Pre-release checks (local)

  • ruff check src/ — clean
  • pytest -q — 103 passed
  • tsc (electron-main) — clean
  • tsc --noEmit (renderer) — clean

Linux packages (AppImage, .deb, .rpm, .flatpak) are built automatically by build-release.yml and attached to this release once the job finishes.

ProtonShift v0.9.0

18 Apr 16:52
3fb8591

Choose a tag to compare

Highlights

AppImage compatibility (closes #13 follow-up)

The vendored-native-extension fix shipped in v0.8.11 was a no-op on read-only squashfs. v0.9.0 ships the real fix:

  • _vendor_compat.py mutates sys.path in memory instead of trying to shutil.rmtree the bundled pydantic_core. AppImage users on a different Python minor version now silently fall back to the system copy.
  • electron/main.ts no longer sets PYTHONNOUSERSITE="" (CPython treats that as truthy and disables user site-packages — the opposite of what we wanted).
  • Bundled native deps trimmed from 5 to 1: switched uvicorn[standard] -> bare uvicorn (drops uvloop / httptools / watchfiles, all unnecessary for a localhost workload).

Backend security hardening

  • 2 critical command-injection fixes: protontricks.py (whitelist Steam app id + winetricks verb) and display.py:set_resolution (whitelist monitor name against get_monitors(), bound width/height/refresh).
  • Removed --print-token CLI flag (avoids credentials ending up in journald / Electron logs).
  • Defense-in-depth validate_user_path() calls inside prefix.py and saves.py so each FS function refuses paths outside the user-writable roots even when called directly.
  • Per-launch bearer-token auth on every API endpoint (except /health//docs).
  • CORS narrowed to 127.0.0.1 / localhost.

Reliability

  • Atomic writes everywhere. All config / VDF / env / profile / MangoHud / Heroic writes go through fsutil.atomic_write_text (tempfile + fsync + os.replace). VDF endpoints also refuse to write while Steam is running, so we can't clobber localconfig.vdf mid-session.
  • Centralized path sanitizer (paths.py) at every API boundary: rejects .., absolute overrides, null bytes, anything outside ~//run/media//media//mnt//tmp.
  • Hardened backup/restore against zip-slip and added size + file-count tripwires.

Refactor

  • The 1183-LOC api.py is now an api/ package: _state.py, _models.py, _helpers.py, _app.py, and 8 domain-specific routers under routes/ (games, system, saves, mangohud, heroic, profiles, utility, health).
  • Consolidated FS helpers into fsutil.py (dir_size, human_size, atomic writes).
  • Promoted _resolve_heroic_root -> resolve_heroic_root.
  • Centralized logging setup (logging_setup.py).
  • TTL cache on steam.discover_games (200 ms).
  • Real SDL controller GUIDs (16-byte little-endian bus/vendor/product/version).
  • gamescope returns both an argv list and a shell-safe quoted string.

Cleanup

  • Deleted dead GTK4 UI (app.py, __main__.py, theme.css) and the obsolete protonshift console script.
  • Single source of truth for the version (game_setup_hub.__version__ -> exposed via FastAPI app.version).

Tests + tooling

  • New tests/ suite: 96 cases (was 0), covering VDF round-trip, env-var management, gamescope arg building, controllers, paths, fsutil, vendor-compat, protontricks/display whitelists, and a FastAPI smoke suite.
  • ruff + pyright (standard mode) both clean.

Compatibility

  • Bundled vs system Python: when the AppImage runs against a Python whose minor version doesn't match the build, the API now falls back to a system copy of pydantic_core. If neither matches, you'll get a loud actionable warning instead of a silent ModuleNotFoundError.
  • Token auth: any external integration calling the API directly must now send Authorization: Bearer <token> (the token is in PROTONSHIFT_API_TOKEN, set by Electron at launch).

Full changelog

  • #15 refactor(python): execute full backend review plan (P0+P1+P2+P3)
  • #16 release: v0.9.0 — Python backend hardening + AppImage compat fix
  • See docs/python-review.md for the complete review and rationale.

ProtonShift v0.8.11

18 Apr 15:26
1d6e23a

Choose a tag to compare

Fix: AppImage crash on Python 3.13 systems (#13)

The AppImage failed to start on distros with Python 3.13 (e.g. CachyOS, latest Arch) with:

ModuleNotFoundError: No module named 'pydantic_core._pydantic_core'

Cause: The vendored pydantic_core native extension was compiled for Python 3.12 and wouldn't load on 3.13 due to ABI mismatch.

Fix: Added a startup compatibility layer (_vendor_compat.py) that detects when vendored native extensions don't match the running Python version and removes them so the system-installed packages are used instead. Also added python3-pydantic as a package dependency for .deb and .rpm builds.

Other changes

  • CI now pins Python 3.12 via actions/setup-python
  • Vendor script cleans up __pycache__ and dist-info bloat

Install

Format File
AppImage ProtonShift-0.8.11.AppImage
Debian/Ubuntu protonshift_0.8.11_amd64.deb
Fedora/RHEL protonshift-0.8.11.x86_64.rpm
Flatpak ProtonShift-0.8.11-x86_64.flatpak

Full Changelog: v0.8.10...v0.8.11

ProtonShift v0.8.10

16 Apr 08:08
049af40

Choose a tag to compare

Fixes

  • Controllers page crash — Fixed "This page couldn't load" error on the Controllers page. The HeroUI Alert component was missing a required Alert.Content wrapper, causing a React render crash when the error state was shown (e.g. backend unreachable).

Install

Format File
AppImage ProtonShift-0.8.10.AppImage
Debian/Ubuntu protonshift_0.8.10_amd64.deb
Fedora/RHEL protonshift-0.8.10.x86_64.rpm
Flatpak ProtonShift-0.8.10-x86_64.flatpak

Full Changelog: v0.8.9...v0.8.10

ProtonShift v0.8.9

15 Apr 17:38
9c3976d

Choose a tag to compare

Fix: Tool detection on Bazzite & immutable distros

Gamescope, MangoHud, GameMode, and Protontricks were reported as "Not Installed" on Bazzite and other immutable Fedora Atomic distros (Kinoite, Silverblue, SteamOS) even when present on the system. (#10)

What changed

  • New tool_check.py module — all tool detection now uses a three-tier strategy: normal PATH lookup → extra immutable-distro bin directories (/var/usrlocal/bin, /usr/lib/extensions/, NixOS paths) → tool-specific known paths
  • Electron PATH augmentation — the Python backend now inherits additional bin paths that AppImage/Flatpak wrappers may strip
  • Bazzite/SteamOS install hints — the "Not Installed" screens for Gamescope and MangoHud now list Bazzite/SteamOS as the first entry (pre-installed)
  • All detection in gamescope.py, mangohud.py, presets.py, protontricks.py, and display.py migrated to the shared helper

Install

Download the package for your distro below. Requires Python 3.12+.

Format File
AppImage ProtonShift-0.8.9.AppImage
Debian/Ubuntu protonshift_0.8.9_amd64.deb
Fedora/RHEL protonshift-0.8.9.x86_64.rpm
Flatpak ProtonShift-0.8.9-x86_64.flatpak

Full Changelog: v0.8.8...v0.8.9

ProtonShift v0.8.8

15 Apr 15:23
a4e12f8

Choose a tag to compare

What's Changed

  • Release v0.8.8: power profiles, System UI, Linux CI artifacts by @I4cTime in #9

Full Changelog: v0.8.7...v0.8.8

ProtonShift v0.8.7

15 Apr 14:43
a29fc63

Choose a tag to compare

Fix: packaged UI looked broken (unstyled / blank)

The Electron build loaded the Next static export with file://. Root-relative URLs such as /_next/static/... and /splash.png do not resolve correctly in that context, so scripts and CSS never loaded.

0.8.7 serves renderer/out/ from http://127.0.0.1:&lt;ephemeral-port> when packaged (same idea as dev on http://localhost:3000), then opens that URL in the window.

Install

  • .deb: sudo apt install ./protonshift_0.8.7_amd64.deb
  • AppImage: chmod +x ProtonShift-0.8.7.AppImage && ./ProtonShift-0.8.7.AppImage

ProtonShift v0.8.6

15 Apr 14:26
19f7901

Choose a tag to compare

Fix: packaged app would not start

0.8.5 shipped the Python source tree but not FastAPI / Uvicorn / VDF, so the backend exited immediately and the window never appeared. 0.8.6 vendors those dependencies into the AppImage and .deb.

Install

  • .deb: sudo apt install ./protonshift_0.8.6_amd64.deb (or sudo dpkg -i … then sudo apt-get install -f if needed)
  • AppImage: chmod +x ProtonShift-0.8.6.AppImage && ./ProtonShift-0.8.6.AppImage

You still need Python 3.12+ as python3 on your PATH; everything else for the API is bundled.

Debug from a terminal

If anything still fails, run /opt/ProtonShift/protonshift from a terminal and check [python] lines on stderr.