Skip to content

fix(resources): publish downloaded resources atomically - #4230

Merged
gantoine merged 4 commits into
rommapp:masterfrom
sdornan:claude/atomic-file-fix-extract-f7nail
Aug 19, 2026
Merged

fix(resources): publish downloaded resources atomically#4230
gantoine merged 4 commits into
rommapp:masterfrom
sdornan:claude/atomic-file-fix-extract-f7nail

Conversation

@sdornan

@sdornan sdornan commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Description

Splits the atomic-write half out of #4160 so it can be reviewed and land on its own. None of that PR's locked_fields provenance work is included here: no migration, no model, endpoint, or scan-handler changes. #4160 stays open for that half.

write_file_streamed opened the destination file directly, so an interrupted transfer truncated the target in place. A truncated file is worse than a missing one: it still satisfies the *_exists checks, so every later scan skips it and never refetches. The existing error paths cleaned it up, but only when the process survived to run them, which a SIGKILL or host reboot does not.

write_file_streamed is now an async context manager that writes to a temp file in the destination directory and renames it over the target once the caller's block completes, reusing the _atomic_write helper that uploads already use. The handle closes before the rename, so the target never sees a partial flush.

The _discard_partial_file calls that followed a streamed write are gone. There is no longer a partial file to remove, and the target now holds either nothing or the previous good copy, which those calls would delete. Refreshing a cover no longer costs the existing one when the transfer dies. _discard_partial_file itself stays, since the non-streamed paths (resize, small cover) still use it.

The second commit fixes cleanup on cancel: _atomic_write cleaned up in except Exception, which does not catch CancelledError, so stopping a scan mid-download stranded a .romm_tmp_* file per cancelled transfer. It now catches BaseException, which also covers uploads.

On tests: the two disk-full tests patched write_file_streamed itself, so they were asserting against the non-atomicity this removes. They now fail the write from the response stream and exercise the real path. Added coverage for an interrupted transfer leaving the previous cover intact, and for a cancelled transfer leaving no temp file behind.

AI assistance disclosure: written with Claude Code. The first commit is cherry-picked unchanged from #4160; the second commit and its test were lifted by hand from that PR's follow-up. I reviewed the result and ran the checks listed below.

Checklist
Please check all that apply.

  • I've tested the changes locally
  • I've updated relevant comments
  • I've assigned reviewers for this PR
  • I've added unit tests that cover the changes

Verification: full backend suite against MariaDB, 2821 passed. The one failure in my run is pre-existing and unrelated (test_extract_chd_hash_permission_error fails on master too, because my local run is as root and chmod does not deny root). Merges cleanly into master at 7f57646, with the filesystem suite green on the merged tree (333 passed). black, isort, and ruff clean on the changed files.

sdornan and others added 2 commits August 18, 2026 14:57
Streamed downloads opened the destination directly, so an interrupted
transfer truncated the file in place. A truncated file is worse than a
missing one: it still satisfies the *_exists checks, so later scans skip
it and never refetch. The error paths cleaned it up, but only when the
process survived to run them, which a SIGKILL or host reboot does not.

write_file_streamed now writes to a temp file in the destination
directory and renames it over the target once the caller's block
completes, reusing the _atomic_write helper uploads already use. The
handle closes before the rename, so the target never sees a partial
flush.

The _discard_partial_file calls that followed a streamed write are gone.
There is no longer a partial file to remove, and the target now holds
either nothing or the previous good copy, which those calls would
delete. Refreshing a cover no longer costs the existing one when the
transfer dies.

The two disk-full tests patched write_file_streamed itself, so they were
asserting against the non-atomicity this removes. They now fail the
write from the response stream and exercise the real path.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
(cherry picked from commit 9b81fef)
_atomic_write cleaned up in `except Exception`, which does not catch
CancelledError. Stopping a scan mid-download therefore stranded a
`.romm_tmp_*` file per cancelled transfer. Catch BaseException instead.
This also covers uploads, which have always gone through this path.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YKbk4cDmdKKMcBxGmsRVT5
Copilot AI lite review requested due to automatic review settings August 18, 2026 16:22
@greptile-apps

greptile-apps Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR makes streamed resource downloads atomic by writing into same-directory temporary files and publishing them only after successful completion. It also cleans temporary files when writes are cancelled and updates resource-download tests for interrupted, disk-full, and cancellation scenarios.

  • Converts write_file_streamed into an async context manager backed by _atomic_write.
  • Preserves existing resources when replacement downloads fail.
  • Extends temporary-file cleanup to cancellation and other BaseException paths.
  • Updates all resource callers and adds atomicity and cleanup coverage.

Confidence Score: 5/5

The PR appears safe to merge, with atomic publication and cancellation cleanup consistently applied to all repository callers.

Streamed writes close their temporary handle before same-directory replacement, failures preserve any existing target, cancellation removes the temporary file and propagates, and all known callers use the new context-manager contract.

Important Files Changed

Filename Overview
backend/handler/filesystem/base_handler.py Implements atomic streamed writes and broadens rollback cleanup to include cancellation while re-raising the original control-flow exception.
backend/handler/filesystem/resources_handler.py Adopts the async-context-manager API at all streamed resource-download sites and removes cleanup that would incorrectly delete an existing good target.
backend/tests/handler/filesystem/test_base_handler.py Updates the streamed-write test to use the new context-manager contract.
backend/tests/handler/filesystem/test_resources_handler.py Exercises disk-full, interrupted-refresh, and cancellation behavior through the real atomic streaming path.

Reviews (1): Last reviewed commit: "fix(resources): clean up the temp file w..." | Re-trigger Greptile

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This pull request updates backend filesystem resource downloads to publish streamed writes atomically, preventing interrupted transfers from truncating existing resources in place. It also improves temp-file cleanup on cancellation, and updates the filesystem handler tests to cover the new behavior.

Changes:

  • Convert write_file_streamed to an async context manager that writes via _atomic_write (temp file then os.replace).
  • Update resource download call sites to use the new context manager API and remove post-failure partial-file deletion that is no longer correct.
  • Expand _atomic_write cleanup to cover cancellations, and adjust tests to exercise real streamed failure paths (disk full, dropped connection, cancellation).

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
backend/handler/filesystem/base_handler.py Makes streamed writes atomic and ensures temp files are cleaned up on cancellation.
backend/handler/filesystem/resources_handler.py Switches resource downloads to the new streamed atomic writer and removes partial-file cleanup that would delete good existing files.
backend/tests/handler/filesystem/test_base_handler.py Updates tests to use the new write_file_streamed async context manager API.
backend/tests/handler/filesystem/test_resources_handler.py Adjusts failure-mode tests to exercise atomic streamed writes and adds coverage for cancellation and refresh safety.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread backend/handler/filesystem/base_handler.py
Comment thread backend/handler/filesystem/resources_handler.py Outdated
sdornan and others added 2 commits August 18, 2026 11:51
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Comment thread backend/handler/filesystem/base_handler.py
@gantoine
gantoine merged commit 42fcf27 into rommapp:master Aug 19, 2026
6 checks passed
bigSmooth7867 pushed a commit to bigSmooth7867/swarm that referenced this pull request Aug 21, 2026
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [rommapp/romm](https://github.com/rommapp/romm) | minor | `5.1.0` → `5.2.0` |

---

### Release Notes

<details>
<summary>rommapp/romm (rommapp/romm)</summary>

### [`v5.2.0`](https://github.com/rommapp/romm/releases/tag/5.2.0)

[Compare Source](rommapp/romm@5.1.0...5.2.0)

#### Minor changes

- feat(screenscraper): pace and report scans against the account's reported limits by [@&#8203;Spinnich](https://github.com/Spinnich) in [#&#8203;3989](rommapp/romm#3989)
- feat: reorderable region and language priority lists in scan settings by [@&#8203;gantoine](https://github.com/gantoine) in [#&#8203;4015](rommapp/romm#4015)
- feat(frontend): autofocus the search field on the Search view by [@&#8203;gantoine](https://github.com/gantoine) in [#&#8203;4022](rommapp/romm#4022)
- feat(home): make the random pick widget clickable and denser by [@&#8203;gantoine](https://github.com/gantoine) in [#&#8203;4056](rommapp/romm#4056)
- feat(rating): show provider ratings by [@&#8203;wadiebs](https://github.com/wadiebs) in [#&#8203;4096](rommapp/romm#4096)
- feat(soundtrack player): improve artwork by [@&#8203;wadiebs](https://github.com/wadiebs) in [#&#8203;4168](rommapp/romm#4168)
- feat(v2): previous / next game buttons on the details page by [@&#8203;gantoine](https://github.com/gantoine) in [#&#8203;4012](rommapp/romm#4012)
- feat(v2): search platforms by slug, folder, category and family by [@&#8203;Spinnich](https://github.com/Spinnich) in [#&#8203;4136](rommapp/romm#4136)
- feat(hasheous): map famicom to the NES platform by [@&#8203;sdornan](https://github.com/sdornan) in [#&#8203;4162](rommapp/romm#4162)
- feat(v2): show IGDB ports on the game overview by [@&#8203;sdornan](https://github.com/sdornan) in [#&#8203;4184](rommapp/romm#4184)

#### Fixes

- fix(steamgriddb): skip DMCA-locked grids when scraping SteamGridDB by [@&#8203;gantoine](https://github.com/gantoine) in [#&#8203;4004](rommapp/romm#4004)
- fix(security): close three permission gaps found auditing 5.1.0 by [@&#8203;gantoine](https://github.com/gantoine) in [#&#8203;3993](rommapp/romm#3993)
- fix(backend): re-run the Hasheous hash lookup on a hashes scan by [@&#8203;gantoine](https://github.com/gantoine) in [#&#8203;4013](rommapp/romm#4013)
- fix(v2): keep RSelect menus inside the viewport and tidy the selection text by [@&#8203;gantoine](https://github.com/gantoine) in [#&#8203;4014](rommapp/romm#4014)
- fix(roms): give each FPKGi package a unique name within its rom by [@&#8203;gantoine](https://github.com/gantoine) in [#&#8203;4021](rommapp/romm#4021)
- fix(backend): scope ScreenScraper French fallback to taxonomy fields by [@&#8203;gantoine](https://github.com/gantoine) in [#&#8203;4026](rommapp/romm#4026)
- fix(v2): pivot to a filtered search from the overview info grid by [@&#8203;gantoine](https://github.com/gantoine) in [#&#8203;4023](rommapp/romm#4023)
- fix(backend): tolerate calendar-invalid gamelist dates on PostgreSQL by [@&#8203;gantoine](https://github.com/gantoine) in [#&#8203;4024](rommapp/romm#4024)
- fix(player): skip the save load a state immediately discards by [@&#8203;gantoine](https://github.com/gantoine) in [#&#8203;4025](rommapp/romm#4025)
- fix(roms): search the gallery by CRC32, MD5, SHA-1 and RA hash by [@&#8203;Spinnich](https://github.com/Spinnich) in [#&#8203;4032](rommapp/romm#4032)
- fix(docker): always start the RQ scheduler by [@&#8203;XenuIsWatching](https://github.com/XenuIsWatching) in [#&#8203;4033](rommapp/romm#4033)
- fix(backend): scope the kiosk read-only cap to the anonymous visitor by [@&#8203;Spinnich](https://github.com/Spinnich) in [#&#8203;4047](rommapp/romm#4047)
- fix: batch of open bug fixes ([#&#8203;4027](rommapp/romm#4027), [#&#8203;4034](rommapp/romm#4034), [#&#8203;4035](rommapp/romm#4035), [#&#8203;4038](rommapp/romm#4038), [#&#8203;4040](rommapp/romm#4040), [#&#8203;4043](rommapp/romm#4043), [#&#8203;4045](rommapp/romm#4045)) by [@&#8203;gantoine](https://github.com/gantoine) in [#&#8203;4051](rommapp/romm#4051)
- fix(scan): report only newly discovered firmware by [@&#8203;gantoine](https://github.com/gantoine) in [#&#8203;4055](rommapp/romm#4055)
- fix(rom-details): render the manual viewer on mobile by [@&#8203;gantoine](https://github.com/gantoine) in [#&#8203;4058](rommapp/romm#4058)
- fix(hasheous): read the CHD and DOS signature sources by [@&#8203;gantoine](https://github.com/gantoine) in [#&#8203;4060](rommapp/romm#4060)
- fix(stats): pluralize the platform game count and lift meta legibility by [@&#8203;gantoine](https://github.com/gantoine) in [#&#8203;4065](rommapp/romm#4065)
- fix(config): map tic80 to the tic-80 platform slug by [@&#8203;XenuIsWatching](https://github.com/XenuIsWatching) in [#&#8203;4090](rommapp/romm#4090)
- fix(docker): keep the Redis password out of the RQ worker command line by [@&#8203;gantoine](https://github.com/gantoine) in [#&#8203;4093](rommapp/romm#4093)
- fix(v2): make hashes recoverable without HTTPS and show all firmware hashes by [@&#8203;Spinnich](https://github.com/Spinnich) in [#&#8203;4083](rommapp/romm#4083)
- fix(home): stop scanning the library filesystem on every home page load by [@&#8203;Spinnich](https://github.com/Spinnich) in [#&#8203;4069](rommapp/romm#4069)
- fix(auth): accept a stale user-bound CSRF token on anonymous requests by [@&#8203;bikeborb](https://github.com/bikeborb) in [#&#8203;4086](rommapp/romm#4086)
- fix(v2): drop a random pick after leaving the platform by [@&#8203;Spinnich](https://github.com/Spinnich) in [#&#8203;4113](rommapp/romm#4113)
- fix(states): repoint the row when a re-upload changes emulator by [@&#8203;TowyTowy](https://github.com/TowyTowy) in [#&#8203;4112](rommapp/romm#4112)
- fix(v2): keep Playmatch selectable when providers are set to All by [@&#8203;sdornan](https://github.com/sdornan) in [#&#8203;4120](rommapp/romm#4120)
- fix(hashing): extract CHD SHA-1 for folder-based ROMs by [@&#8203;sdornan](https://github.com/sdornan) in [#&#8203;4129](rommapp/romm#4129)
- fix(v2): compute game-card cover width instead of deriving it by [@&#8203;sdornan](https://github.com/sdornan) in [#&#8203;4135](rommapp/romm#4135)
- fix(media): stop recording paths for media that never landed by [@&#8203;sdornan](https://github.com/sdornan) in [#&#8203;4131](rommapp/romm#4131)
- fix(screenscraper): report rejected credentials instead of a bare 403 by [@&#8203;Spinnich](https://github.com/Spinnich) in [#&#8203;4130](rommapp/romm#4130)
- fix(launchbox): match ROMs during a scan the way Match ROM does by [@&#8203;sdornan](https://github.com/sdornan) in [#&#8203;4121](rommapp/romm#4121)
- fix(hltb): renew rejected HLTB sessions instead of failing the scan by [@&#8203;sdornan](https://github.com/sdornan) in [#&#8203;4125](rommapp/romm#4125)
- fix(v2): drop a random pick that lands after leaving the gallery by [@&#8203;Spinnich](https://github.com/Spinnich) in [#&#8203;4138](rommapp/romm#4138)
- fix(ss): store the ScreenScraper box-2D front locally by [@&#8203;sdornan](https://github.com/sdornan) in [#&#8203;4139](rommapp/romm#4139)
- fix(v2): show a running scan on pages loaded mid-scan by [@&#8203;sdornan](https://github.com/sdornan) in [#&#8203;4142](rommapp/romm#4142)
- fix(resources): fetch each cover once instead of once per size by [@&#8203;Spinnich](https://github.com/Spinnich) in [#&#8203;4143](rommapp/romm#4143)
- fix(metadata): identify archives and folder ROMs by the right file by [@&#8203;Spinnich](https://github.com/Spinnich) in [#&#8203;4146](rommapp/romm#4146)
- fix(match-rom): show the saving overlay above the grid match panel by [@&#8203;sdornan](https://github.com/sdornan) in [#&#8203;4147](rommapp/romm#4147)
- refactor(i18n): name gallery filters by property instead of "Show X" by [@&#8203;sdornan](https://github.com/sdornan) in [#&#8203;4149](rommapp/romm#4149)
- fix(v2): bulk favorite no-ops on a fresh instance and reports the wrong direction by [@&#8203;Spinnich](https://github.com/Spinnich) in [#&#8203;4151](rommapp/romm#4151)
- fix: refresh the v2 gallery when a ROM is edited or matched by [@&#8203;sdornan](https://github.com/sdornan) in [#&#8203;4153](rommapp/romm#4153)
- fix(v2): pin mobile bottom nav with sticky instead of fixed by [@&#8203;nickybmon](https://github.com/nickybmon) in [#&#8203;4155](rommapp/romm#4155)
- fix(export): stop miximage\_v2 colliding with miximage, persist gamelist back covers by [@&#8203;sdornan](https://github.com/sdornan) in [#&#8203;4156](rommapp/romm#4156)
- fix(hashing): surface unreadable zip and tar archives by [@&#8203;sdornan](https://github.com/sdornan) in [#&#8203;4163](rommapp/romm#4163)
- fix: remove double URL-encoding of MobyGames search terms by [@&#8203;justinjd00](https://github.com/justinjd00) in [#&#8203;4181](rommapp/romm#4181)
- fix(i18n): correct Breton pt\_BR player-count and align ja\_JP/tr\_TR by [@&#8203;sdornan](https://github.com/sdornan) in [#&#8203;4183](rommapp/romm#4183)
- fix(i18n): translate pt\_BR strings left in English by [@&#8203;sdornan](https://github.com/sdornan) in [#&#8203;4185](rommapp/romm#4185)
- fix(v2): close open overlays when the route changes by [@&#8203;sdornan](https://github.com/sdornan) in [#&#8203;4193](rommapp/romm#4193)
- Changed default compose, will explain more in pull by [@&#8203;danblu3](https://github.com/danblu3) in [#&#8203;4202](rommapp/romm#4202)
- fix(v2): drop the roms from the gallery when they leave the collection on screen by [@&#8203;sdornan](https://github.com/sdornan) in [#&#8203;4204](rommapp/romm#4204)
- fix(scan): normalize region and language tags to one canonical spelling by [@&#8203;sdornan](https://github.com/sdornan) in [#&#8203;4206](rommapp/romm#4206)
- fix: demote uvicorn HTTP access logs to WARNING/DEBUG only by [@&#8203;gantoine](https://github.com/gantoine) with [@&#8203;Copilot](https://github.com/Copilot) in [#&#8203;4214](rommapp/romm#4214)
- fix: Add `.xdelta` support to server-side ROM patcher and v2 patcher UI by [@&#8203;gantoine](https://github.com/gantoine) with [@&#8203;Copilot](https://github.com/Copilot) in [#&#8203;4215](rommapp/romm#4215)
- fix(states): enforce ROM visibility when uploading a state by [@&#8203;gantoine](https://github.com/gantoine) in [#&#8203;4216](rommapp/romm#4216)
- fix(auth): build invite links from ROMM\_BASE\_URL by [@&#8203;sdornan](https://github.com/sdornan) in [#&#8203;4217](rommapp/romm#4217)
- fix(scan): re-read filename tags on a complete rescan by [@&#8203;sdornan](https://github.com/sdornan) in [#&#8203;4218](rommapp/romm#4218)
- fix(libretro): cache missing thumbnail listings by [@&#8203;sdornan](https://github.com/sdornan) in [#&#8203;4219](rommapp/romm#4219)
- fix(launchbox): match titles differing only by punctuation by [@&#8203;sdornan](https://github.com/sdornan) in [#&#8203;4224](rommapp/romm#4224)
- fix(hltb): match titles whose series prefix the catalogue omits by [@&#8203;sdornan](https://github.com/sdornan) in [#&#8203;4225](rommapp/romm#4225)
- fix(ss): don't use the Switch icon URL as the manual URL by [@&#8203;TowyTowy](https://github.com/TowyTowy) in [#&#8203;4228](rommapp/romm#4228)
- fix(resources): publish downloaded resources atomically by [@&#8203;sdornan](https://github.com/sdornan) in [#&#8203;4230](rommapp/romm#4230)
- fix(i18n): translate route titles once locale messages are loaded by [@&#8203;sdornan](https://github.com/sdornan) in [#&#8203;4231](rommapp/romm#4231)
- fix(i18n): add the missing playlists permission entity label by [@&#8203;sdornan](https://github.com/sdornan) in [#&#8203;4234](rommapp/romm#4234)
- fix(hltb): fetch metadata when a HowLongToBeat ID is set by hand by [@&#8203;sdornan](https://github.com/sdornan) in [#&#8203;4235](rommapp/romm#4235)
- fix(launchbox): match LaunchBox dumps that separate words with underscores by [@&#8203;sdornan](https://github.com/sdornan) in [#&#8203;4239](rommapp/romm#4239)
- fix(backend): make filters match against all grouped versions instead of only the main version of each game entry by [@&#8203;darkpaul91](https://github.com/darkpaul91) in [#&#8203;4240](rommapp/romm#4240)
- feat(metadata): warn when ScreenScraper dev credentials are missing by [@&#8203;gantoine](https://github.com/gantoine) in [#&#8203;4243](rommapp/romm#4243)
- fix(scan): ignore Windows Zone.Identifier files by [@&#8203;Florian-Cullmann](https://github.com/Florian-Cullmann) in [#&#8203;4245](rommapp/romm#4245)

#### Other changes

- perf(roms): stop the Missing tab scanning the whole library by [@&#8203;Spinnich](https://github.com/Spinnich) in [#&#8203;4005](rommapp/romm#4005)
- perf(scan): stop hashing single-file ROMs twice by [@&#8203;XenuIsWatching](https://github.com/XenuIsWatching) in [#&#8203;4017](rommapp/romm#4017)
- perf(collections): serve smart and standard collections from a composed query by [@&#8203;Spinnich](https://github.com/Spinnich) in [#&#8203;4039](rommapp/romm#4039)
- perf(roms): extend the sibling covering index to cover the ROM grouping query by [@&#8203;Spinnich](https://github.com/Spinnich) in [#&#8203;4054](rommapp/romm#4054)
- perf(roms): let a gallery window fetch skip the library count by [@&#8203;Spinnich](https://github.com/Spinnich) in [#&#8203;4062](rommapp/romm#4062)
- perf(roms): pick a random rom without paging to a random offset by [@&#8203;Spinnich](https://github.com/Spinnich) in [#&#8203;4071](rommapp/romm#4071)
- perf(roms): sort metadata fields on the indexed roms column by [@&#8203;Spinnich](https://github.com/Spinnich) in [#&#8203;4078](rommapp/romm#4078)
- perf(gallery): resolve the random rom button in one request by [@&#8203;Spinnich](https://github.com/Spinnich) in [#&#8203;4097](rommapp/romm#4097)
- perf(home): stop counting the whole library for the two home rows by [@&#8203;Spinnich](https://github.com/Spinnich) in [#&#8203;4110](rommapp/romm#4110)
- perf(scan): scope a rom-id scan to the selected roms by [@&#8203;sdornan](https://github.com/sdornan) in [#&#8203;4188](rommapp/romm#4188)
- perf(scan): cut scan memory and drop a quadratic file listing check by [@&#8203;XenuIsWatching](https://github.com/XenuIsWatching) in [#&#8203;4198](rommapp/romm#4198)
- perf(scan): stop re-hashing unchanged firmware on every scan by [@&#8203;sdornan](https://github.com/sdornan) in [#&#8203;4211](rommapp/romm#4211)
- test: fix flaky LaunchBox release date property test (DST fold) by [@&#8203;sdornan](https://github.com/sdornan) in [#&#8203;4242](rommapp/romm#4242)
- chore(deps): bump aiohttp from 3.14.1 to 3.14.3 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;4115](rommapp/romm#4115)
- chore(deps-dev): bump fast-uri from 3.1.4 to 3.1.5 in /frontend by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;4118](rommapp/romm#4118)
- chore(deps): bump socket.io-parser from 4.2.6 to 4.2.7 in /frontend by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;4119](rommapp/romm#4119)
- chore(deps-dev): bump js-yaml from 4.2.0 to 4.3.1 in /frontend by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;4189](rommapp/romm#4189)

> \[!NOTE]
>
> ### API changes
>
> | Change                                   | Description                                                                                                                                                                                                     |
> | ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
> | `GET /roms/random`                       | Retrieve one rom picked at random, or `null` when the scope holds none. Accepts `platform_ids`, `collection_id`, `virtual_collection_id` and `smart_collection_id`.                                             |
> | `GET /roms`                              | Now accepts a `with_total` parameter (default `true`). Set it to `false` when the caller already knows the total; `total` then comes back `null` unless the rom id index is being built and already carries it. |
> | `GET /setup/library`                     | `existing_platforms` now comes back empty once the database holds roms, instead of walking every platform directory.                                                                                            |
> | `POST /states`                           | Now rejects an upload against a rom the caller cannot see.                                                                                                                                                      |
> | `DELETE /roms/{rom_id}/files/{file_id}`  | Now requires the `ROMS`/`DELETE` grant instead of `ROMS`/`WRITE`.                                                                                                                                               |
> | `GET /feeds/fpkgi`                       | Package names are deduplicated within a rom, so two packages that share a title id no longer overwrite each other on the console.                                                                               |
> | `GET /collections/smart/{id}`            | The cached `rom_ids`, `rom_count` and covers are now resolved as the collection owner, not the requesting viewer. The live rom listing is still per-requester.                                                  |
> | `CustomLimitOffsetPage[SimpleRomSchema]` | `total` is now nullable.                                                                                                                                                                                        |
> | `InviteLinkSchema`                       | Adds `url`, the full registration link built from `ROMM_BASE_URL`, or `null` when that points at loopback.                                                                                                      |
> | `MetadataSourcesDict`                    | Adds `SS_DEV_CREDENTIALS_SET`.                                                                                                                                                                                  |
> | `RomSSMetadata`                          | Adds `box2d_path`.                                                                                                                                                                                              |
> | `RomGamelistMetadata`                    | Adds `box2d_back_path`, `fanart_path` and `title_screen_path`.                                                                                                                                                  |
> | `RomHasheousMetadata`                    | Adds `mame_redump_match`.                                                                                                                                                                                       |
>
> #### Streaming endpoints
>
> These moved from `ROMS_READ` to `ROMS_USER_WRITE`, which is always-on for authenticated users but absent from the read-only set a kiosk visitor gets.

#### New Contributors

- [@&#8203;wadiebs](https://github.com/wadiebs) made their first contribution in [#&#8203;4096](rommapp/romm#4096)
- [@&#8203;sdornan](https://github.com/sdornan) made their first contribution in [#&#8203;4120](rommapp/romm#4120)
- [@&#8203;nickybmon](https://github.com/nickybmon) made their first contribution in [#&#8203;4155](rommapp/romm#4155)
- [@&#8203;justinjd00](https://github.com/justinjd00) made their first contribution in [#&#8203;4181](rommapp/romm#4181)
- [@&#8203;danblu3](https://github.com/danblu3) made their first contribution in [#&#8203;4202](rommapp/romm#4202)
- [@&#8203;darkpaul91](https://github.com/darkpaul91) made their first contribution in [#&#8203;4240](rommapp/romm#4240)
- [@&#8203;Florian-Cullmann](https://github.com/Florian-Cullmann) made their first contribution in [#&#8203;4245](rommapp/romm#4245)

**Full Changelog**: <rommapp/romm@5.1.0...5.2.0>

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate CLI](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4zMC40IiwidXBkYXRlZEluVmVyIjoiNDQuMzAuNCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsibWlub3IiLCJyZW5vdmF0ZSJdfQ==-->

Reviewed-on: https://gitea.vcasaserver.com/omar/swarm/pulls/740
Co-authored-by: Renovate Bot <renovate-bot@vcasaserver.com>
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.

3 participants