v0.2.0
A reliability release: no download can appear stuck as "downloading" forever
anymore, and imports now survive crashes, power loss, and restarts.
Fixed
- Every permanently-stuck "downloading" state is gone. The three ways a grab
could wedge forever are each fixed or surfaced honestly:- A torrent removed from the download client out-of-band is now reconciled:
after a 5-minute grace period the grab fails and the episode reverts to
wanted (this closes the known limitation from 0.1.0). - A deferred batch/season-pack grab now shows a distinct deferred status
instead of "downloading" forever. It stays honest — the bytes are on disk
and seeding — and manually grabbing a single-episode release replaces the
deferred grab cleanly. - An import that keeps failing (a qBittorrent path-mapping gap, library
permissions, disk full) now surfaces as stuck, with the actual error
shown on the grab, instead of retrying silently with the reason visible
only in the logs.
- A torrent removed from the download client out-of-band is now reconciled:
- Folder-wrapped downloads now import. A single-episode torrent that
delivers a directory payload is resolved to its one episode file at
completion time;import_deferredis reserved for payloads that genuinely
can't be disambiguated (real batches). - Imports are crash-safe. Durability and shutdown ordering across the whole
import path:- Copy-mode imports fsync the file before renaming it into the library —
previously a power loss could land the rename before the data, leaving a
truncated episode that was treated as already-imported forever. - Hardlink-mode imports fsync the linked inode (and directory entry) before
the grab settles, closing the same window. - Truncated files left in the library by past crashes are detected and
reclaimed for re-import instead of being invisible. - Graceful shutdown now waits for the importer: the store can no longer close
mid-import, in-flight multi-GB copies abort promptly within the shutdown
budget, and a completedPlacealways gets its have/status writes.
- Copy-mode imports fsync the file before renaming it into the library —
- API failures in the web UI render as error states with retry, not as
misleading empty states ("No titles found" after a rate-limited AniList
search). Abandoned searches are now aborted instead of left running, and an
untrimmed search cache key no longer causes duplicate AniList queries. - Expired sessions are swept on a daily ticker, not only at startup, so
long-lived instances no longer accumulate expired session rows.
Security
- Rate-limited the change-password endpoint (
POST /api/v1/auth/password).
It verifies the current password but was not throttled, so repeated wrong
guesses were unmetered. This matters most underTRANSPONDARR_AUTH_REQUIRED=local,
where any loopback/private-network client is admitted without a credential: the
endpoint was an unauthenticated password-guessing oracle for anyone on the LAN.
In the defaultenabledmode a valid session was already required, so there it
is re-authentication hygiene. Unmetered argon2id verification was also a cheap
CPU/memory exhaustion lever. Login and change-password now share a single
per-client bucket (5 attempts per 15 minutes) rather than getting one each,
since both verify the same admin password.