Releases: nitrobass24/seedsync
Releases · nitrobass24/seedsync
v1.0.0
What's Changed
SeedSync 1.0.0 — first stable release. This milestone bundles the optional FTPS transfer protocol, a large backend reliability and persistence hardening pass, frontend performance work, the Angular 22 upgrade, and a security-focused test and runtime baseline. Existing SFTP installs are unaffected.
Added
- Optional FTPS transfer protocol — A new
protocolsetting (sftpby default, orftps) runs transfers over FTPS (FTP over TLS) instead of SFTP for substantially higher throughput on high-latency links. Hybrid design: file discovery always stays on SSH (newremote_ftp_port, default21, used only for FTPS transfers). FTPS uses the same persisted Connections settings as SFTP. The data channel is always TLS-encrypted; certificate verification (ftp_ssl_verify_certificate) defaults off with a per-connectionWARNINGlog to accommodate self-signed seedbox certificates. FTPS options live in a dedicated Transfer Protocol settings section. (#485) - Notify on download start — New
notify_on_download_startoption (off by default) emits adownload_startevent when a file entersDOWNLOADING, via webhook/Discord/Telegram. (#486) - Automatic extract/validate worker recovery — A crashed extract or validate worker is detected and recreated via a shared
WorkerSupervisor, so processing resumes after a transient fault without a container restart. (#535) - Failed-move surfacing + in-session retry — A failed staging→final move now shows as a distinct
MOVE_FAILEDstate (with a "Move failed" badge) instead of silently appearing done, and is retried within the session. (#536)
Changed
- Angular 21 → 22 upgrade — Lockstep major bump of all
@angular/*packages,@angular/cli,@angular/build,@angular/cdk, andangular-eslintto 22.0.0; TypeScript to 6.0; migrated toprovideAppInitializer()and explicitprovideZonelessChangeDetection(). (#556) - Performance — backend model build — Replaced the O(n²) per-cycle build with O(1) BFS frontiers and a skipped child-list copy. (#520)
- Performance — frontend file list — Coalesced SSE-driven rebuilds, memoized the filter, single-pass bulk-remove. (#521)
- Performance — logs page — Capped live-log buffer (ring buffer + stable trackBy), CDK virtual scroll, batched change detection. (#522, #539)
- Refactor — lftp parser — Decomposed the 412-line, complexity-48
__parse_jobsinto focused, strictly-typed helpers. (#523) - Refactor — ViewFileService — Split into capabilities module, selection service, and command service with a single source of truth for the status→capability state machine. (#524, #541)
- Refactor — backend coupling & service conventions — Decoupled
Controller/CommandPipeline/persist-sync, typo-safe config option types, tap-based mutating-service contract forConfigService.set/AutoQueueService. (#525, #542) - Repo & CI hygiene —
.gitignorecleanup, SHA-pinned third-party GitHub Actions, per-job timeouts, dead-script removal, re-enabled mock-based lftp/ssh/scanner unit tests in CI. (#527, #529) - Dependency updates — Angular, React 19.2.x, typescript-eslint, eslint, vitest, hono, qs, postcss, webpack-dev-server, webob, shell-quote, and
astral-sh/setup-uv, among others. (#488–#506, #545–#554, #560, #565)
Fixed
- Remote scan timed out at 30s under password auth — The SSH password-prompt wait now uses the full command timeout instead of pexpect's silent 30s default. (#562)
- Config handler persistence atomicity —
/server/config/setcaptures the pre-mutation value, attempts the write, and rolls back in-memory state + returns a structured HTTP 500 on failure; the LFTP hot-reload callback only fires after a successful write. (#469) - Config values containing
%crashed persistence —Config.from_str/to_strnow useConfigParser(interpolation=None); the handler rolls back on any persist failure. (#530, #507) - Integration delete persistence ordering — DELETE writes
path_pairs.jsonbeforeintegrations.json, downgrading a crash to a harmless orphaned instance. (#496) - Handlers wrap persistence in try/except — auto-queue, path-pairs, and integrations endpoints return a controlled HTTP 500 instead of leaking a stack trace; auto-queue rolls back on failure. (#497, #518, #530)
Controller.exit()leaked worker subprocesses and queue FDs — teardown is now best-effort with bounded joins. (#508)- Auto-queue thread-safety — cross-thread set/list races are lock-guarded. (#509)
- Move pipeline silent data loss — failed staging→final moves now propagate via a result queue. (#510)
- Cross-device move raced lftp's temp-file rename — the copy fallback now defers while
*.lftptemp files remain, instead of crashingMoveProcesswithENOENT. (#567) - Worker crash isolation & ERROR surfacing — a Validate/Extract subprocess crash is isolated from the controller loop; a permanently-dead worker and failed periodic
persist()are surfaced at ERROR. (#511, #512) - lftp job-status parser robustness — three edge-case parsing bugs, plus a pget header with no data line that consumed the next job's header. (#517, #555)
- Directory validation broke on tilde/relative remote paths — fixed tilde expansion in the remote find/hash commands. (#519)
- Web command handlers could block the request thread indefinitely — now bounded with a 504 timeout. (#526)
- Frontend resilience — single-file action errors surface and stuck rows recover (#513); SSE 401 init deadlock fixed by bootstrapping config off the stream (#514); two-click confirm for bulk Delete Local/Remote (#515); guarded
JSON.parsein SSE/logs/auto-queue handlers (#516); version-check banner bounded with a 10s timeout (#527).
Security
- Documented hardened Docker runtime baseline —
docker-compose.dev.ymland the install docs recommendno-new-privilegesandcap_drop: ALL(adding back onlyCHOWN,SETUID,SETGID,DAC_OVERRIDE,FOWNER). (#528) - Web API key no longer persisted client-side — kept out of browser storage. (#514)
- Security-critical path test coverage — extraction zip-slip, SSH command quoting, persist races, config special characters, scanner symlinks, webhook URL-scheme validation. (#530)
Docker Pull
docker pull ghcr.io/nitrobass24/seedsync:1.0.0Full Changelog: v0.18.1...v1.0.0
v0.18.1
What's Changed
- chore(deps): bump ip-address and express-rate-limit in /src/angular by @dependabot[bot] in #473
- chore(deps): bump hono from 4.12.14 to 4.12.18 in /src/angular by @dependabot[bot] in #474
- chore(deps): bump fast-uri from 3.1.0 to 3.1.2 in /website by @dependabot[bot] in #475
- chore(deps): bump fast-uri from 3.1.0 to 3.1.2 in /src/angular by @dependabot[bot] in #476
- chore(deps): bump @babel/plugin-transform-modules-systemjs from 7.29.0 to 7.29.4 in /website by @dependabot[bot] in #477
- chore(deps): bump react from 19.2.5 to 19.2.6 in /website by @dependabot[bot] in #478
- chore(deps): bump the angular group in /src/angular with 10 updates by @dependabot[bot] in #480
- chore(deps-dev): bump typescript-eslint from 8.59.1 to 8.59.2 in /src/angular by @dependabot[bot] in #481
- chore(deps): bump react-dom from 19.2.5 to 19.2.6 in /website by @dependabot[bot] in #479
- Fix Discord webhook 403 by setting explicit User-Agent by @nitrobass24 in #484
Full Changelog: v0.18.0...v0.18.1
v0.18.0
What's Changed
Changed
- Image size reduced from 50 MB to 39 MB —
RUN --mount=from=ghcr.io/astral-sh/uvkeepsuvout of the runtime image; build artifacts no longer persist (#437) - Dockerfile collapsed to 2 stages on Python 3.13-alpine — Removes an intermediate stage and the legacy Buster build path (#436)
- Test image rewritten as Alpine with Python 3.13 (#435)
- Removed stale Docker test infrastructure — Old Compose files and fixture data carried over from the Protractor era (#434)
- Playwright E2E migrated to the official
mcr.microsoft.com/playwrightcontainer — Eliminates host-side browser install andapt installof system deps; image tag auto-pinned to the@playwright/testversion frompackage-lock.json(#456) - Build and Test (amd64) runs on develop pushes — Populates the GHA cache so PRs against develop hit a warm cache instead of paying the install cost on every run (#456)
- Playwright browser cache + npm cache wired through
actions/cache(#452, #453) - Python 3.12 → 3.13 in CI and Dockerfile (#451)
- README refreshed to cover features through v0.17.0 — Notifications, Sonarr/Radarr, integrity verification, staging, API key (#454)
- Test count badges added to the README (#451)
- Dependency updates — Angular group (10 packages), typescript-eslint, jsdom, eslint, Docusaurus 3.10.0 → 3.10.1 across 5 packages (#458, #459, #460, #461, #463, #464, #465, #466)
Added
- LFTP hot-reload — Connection-related settings (parallel connections, max total connections, socket buffer size, bandwidth limit) apply without a container restart. Settings UI distinguishes between options that take effect immediately and those that require restart (#433)
- Atomic config writes —
Config.to_file()now flushes to disk via temp file +os.renameso a process kill mid-write can't truncate the config (#433) - Expanded unit and E2E test coverage:
- 47 security middleware unit tests (#439)
- 36 controller core unit tests (#444)
- 28 FileOptions / Integrations / Option component tests (#448)
- 25 AutoQueueService and PathPairsService tests (#445)
- 20 HeaderComponent and VersionCheckService tests (#443)
- 18 ViewFileFilterService tests (#440)
- E2E for integrations CRUD (#441)
- E2E for File Actions & Error States (#438)
- E2E Settings coverage expansion (#442)
- Web App Job & Context Python tests (#446)
- Handler integration test expansion (#447)
- Python integration tests added to CI (#449)
Fixed
- Hash Algorithm select test flake — Test waited on the wrong config field; the algorithm select's disable gate is
validate.enabled, notvalidate.xfer_verify. Test now sets the correct field and waits for the SSE-delivered model value before asserting (#455) - StreamHandler leaks in test setUp methods — Tests added a handler to the shared root logger but never removed it. Loggers are singletons, so by test N the logger had N handlers and each log line printed N times. Fixed via `self.addCleanup(logger.removeHandler, handler)` across 8 test files / 10 setUp methods (#450, #457)
- Multiprocessing resource leak in
test_active_scanner.py—scanner.close()now registered withaddCleanupso resources release even if assertions raise
Security
- `apk` and its package database are stripped from the runtime image —
/sbin/apk,/etc/apk,/var/cache/apk,/lib/apk, and thelibapkshared libraries are removed in the runtime stage to keep the image under 64 MB (#437). This means in-image vulnerability scanners (Trivy, Grype) can't enumerate Alpine packages directly from a running container; consumers should scan the published `ghcr.io/nitrobass24/seedsync` image via SBOM or image-history tooling. Affected runtime packages: `lftp`, `openssh-client`, `ca-certificates`, `setpriv`, `libstdc++`. Derived images that need `apk add` should base on Alpine and reinstall what they need rather than extending this image.
Docker Pull
```bash
docker pull ghcr.io/nitrobass24/seedsync:0.18.0
```
Full Changelog: v0.17.0...v0.18.0
v0.17.0
What's Changed
Added
- Multi-instance Sonarr/Radarr integration — Replace single Sonarr/Radarr config with named instances stored in
integrations.json; each path pair can be mapped to specific *arr instances viaarr_target_ids; full CRUD REST API and chip-picker UI (#425, #426) - Discord notification preset — Configure a Discord webhook URL in Settings to receive rich embed notifications with color-coded event types; includes Test button (#329, #428)
- Telegram notification preset — Configure a Telegram bot token and chat ID in Settings to receive Markdown-formatted notifications; includes Test button (#329, #428)
- Cross-validation for arr_target_ids — Path pair create/update rejects unknown integration instance IDs (#426)
Changed
- Notification architecture — Refactored
WebhookNotifierwith extracted_resolve_event_typeand generic_fire_rawdispatch; Discord and Telegram formatters are pure functions (#428) - Controller decomposition — Decomposed
step(),_update_pair_model_state(), andupdate()into focused methods for C901 compliance (#419, #420) - Settings UI consistency — Matching headers, dark mode fixes, semantic
<h3>headings (#429, #430, #431) - Dependency updates — Angular group (10 updates), vitest, typescript-eslint, postcss (#421-#424)
Fixed
- Corrupt integrations.json recovery — Returns empty config instead of re-migrating with new UUIDs (#426)
- Refresh preserves instances on error — No longer replaces list with empty on HTTP error (#426)
- Toggle enabled error handling — Shows error and refreshes on failure (#426)
- Arr-picker dark mode — Fixed white dropdown background (#430)
- Telegram Markdown safety — Backticks in filenames escaped (#428)
- Thread leak on start failure — Cleans up
_active_threadsifthread.start()raises (#428)
Security
- Credential redaction — Discord webhook URLs, Telegram bot tokens, and webhook URLs redacted in API responses (#428)
- URL scheme validation — Notification test endpoints reject non-http(s) URLs (#428)
Docker Pull
docker pull ghcr.io/nitrobass24/seedsync:0.17.0Full Changelog: v0.16.0...v0.17.0
v0.16.0
What's Changed
Added
- Sonarr/Radarr integration — Test connection buttons in Settings to verify Sonarr and Radarr API connectivity (#328, #362)
- Angular ESLint enforced in CI — All 17 lint rules at
errorwith--max-warnings 0; covers OnPush, a11y, type safety, and code style (#376-#382, #389-#392)
Fixed
- Mobile file list scrolling — Fixed items skipping during scroll on Android/iOS by correcting virtual scroll
itemSize(50→82) and switching to dynamic viewport height measurement via ResizeObserver (#370, #371, #396) - Log streaming memory — Stream log files line-by-line instead of
readlines()to avoid loading entire log into memory (#385) - Controller deadlock on exception — Use
withstatement on model lock to prevent deadlock when exception occurs during model update (#373, #384) - Integrations error leaking details — Strip internal exception details from Sonarr/Radarr error responses (#386)
Changed
- Accessibility — 55 template a11y violations fixed:
<div>/<a>click targets converted to<button>, keyboard navigation added, decorative images marked withalt="" aria-hidden="true"(#391) - OnPush change detection — All components now use
ChangeDetectionStrategy.OnPushwith Angular signals (#392) - Type safety — Replaced 50
no-explicit-anyviolations with proper types; addedModelFileJson,ConfigValue,OptionValueinterfaces (#390) - Dependency updates — Angular group (8 packages), follow-redirects, hono, vitest, ruff, pytest, pexpect, tblib, Docusaurus (#347-#368, #388)
Security
- npm audit fixes — Resolved high-severity vulnerabilities in Angular dependencies (#388)
Docker Pull
docker pull ghcr.io/nitrobass24/seedsync:0.16.0Full Changelog: v0.15.0...v0.16.0
v0.15.0
What's Changed
Added
- Virtual scrolling for large file lists — Improves performance when browsing directories with many files (#335)
- Size sorting in file list — New sort option to order files by size (#334)
- Log level dropdown — Replaced debug toggle with a full log level selector (DEBUG/INFO/WARNING/ERROR/CRITICAL) (#332)
Fixed
- Bulk delete crash — Fixed unbounded process spawning that caused crashes during bulk delete; scoped concurrency cap to delete operations and added move retry on failure (#338, #341)
- Infinite busy-loop in command process throttling — Fixed CPU spin in the controller process throttle logic
- Mobile viewport height — File list viewport no longer wastes 40px on small screens where the header row is hidden
- Bulk action error resilience — A single failed action no longer aborts the entire bulk operation pipeline
Changed
- Dependency updates — Angular group bump (9 packages), hono 4.12.7→4.12.12, @hono/node-server bump, jsdom 29.0.1→29.0.2, vitest 4.1.2→4.1.3, lodash 4.17.23→4.18.1, all deps to latest compatible versions (#326, #333, #336, #337, #343, #344, #345)
- Documentation — Moved recommended hard-link workflow from FAQ to a dedicated Usage section; fixed UI label consistency for "Delete from remote after download" (#340)
Docker Pull
docker pull ghcr.io/nitrobass24/seedsync:0.15.0Full Changelog: v0.14.4...v0.15.0
v0.14.4
What's Changed
Changed
- Pyright strict mode — Upgraded Pyright type checking from basic to strict mode across the entire Python codebase; added type stubs for bottle, pexpect, and tblib (#291, #316)
Fixed
- Extraction-move validation race — Extraction completion no longer spawns a staging move while validation is still running; the move is deferred to the validation completion path (#316)
- Directory size preservation in exclude filter —
_filter_childrennow preserves scanner-reported directory sizes instead of recomputing from filtered children, preventingremote_sizedivergence (#316)
Security
- Website dependency bumps — Fixed 4 vulnerabilities in website transitive dependencies: brace-expansion, path-to-regexp, picomatch, minimatch (#324)
- Pygments 2.20.0 — Bumped pygments to fix ReDoS vulnerability GHSA-5239-wwwm-4pmq (#325)
Docker Pull
docker pull ghcr.io/nitrobass24/seedsync:0.14.4Full Changelog: v0.14.3...v0.14.4
v0.14.3
What's Changed
Added
- Configurable remote Python path — New "Remote Python Path" setting lets users specify a custom Python binary on the remote server (e.g.
~/python3/bin/python3), solving issues on seedboxes wherepython3is not on the default PATH (#314, #315) - Startup config validation — SeedSync now validates required LFTP config fields on startup and shows clear error messages when
remote_address,remote_username,remote_path, orlocal_pathare missing (#310, #313)
Fixed
- scan_fs.py Python 3.5 compatibility — Remote scanner script now works on servers with Python 3.5+ by using
typing.List/Optionalinstead of modern type syntax (#314, #315) - Sshcp.copy() user@host format — Fixed
scpcommand construction to use the shared_remote_address()helper (#312) - Pre-existing code quality bugs — Fixed extraction retry counter, NotImplementedError base class, and process cleanup issues (#289, #312)
Changed
- uv for Python dependencies — Replaced pip + requirements.txt with uv and PEP 621 dependency groups; pinned uv versions in CI and Docker (#286, #311)
Docker Pull
docker pull ghcr.io/nitrobass24/seedsync:0.14.3Full Changelog: v0.14.2...v0.14.3
v0.14.2
What's Changed
Added
- Playwright E2E test suite — Replaced legacy Protractor tests with Playwright; 55 tests covering all pages, navigation, themes, and settings (#250)
- Pyright type checking enforced in CI — Completed Pyright phases 3 & 4, fixing 166 type errors to reach 0 errors in basic mode; Pyright check is now required in CI (#249)
Fixed
- ModelFile nullable size fields —
local_sizeandremote_sizeare now correctly typed asnumber | nullto match the Python backend JSON contract
Security
- Reject control characters in filenames — Decoded filenames containing control characters are now rejected to prevent corrupted file entries and queue command injection (#300)
- Redact sensitive credentials from API — SSH password and key passphrase are no longer exposed in API responses; set handler rejects the redacted sentinel value (#257)
Changed
- Angular dependency updates — Bumped Angular group to latest, jsdom to 29.0.1 (#307, #308)
- CI: actions/setup-python v6 — Bumped setup-python action from v5 to v6 (#306)
Removed
- Legacy Docker E2E infrastructure — Cleaned up Protractor Docker Compose files, test images, and fixture data
Docker Pull
docker pull ghcr.io/nitrobass24/seedsync:0.14.2Full Changelog: v0.14.1...v0.14.2
v0.14.1
What's Changed
Fixed
- Parser crash on long filenames — Chunk progress lines that wrap across PTY boundaries no longer crash the controller; unrecognized lines inside a job context are skipped with a warning (#290, #293)
- False download completion on parser error — Parser failures no longer trigger false "download completed" signals that left files stuck in staging at partial progress (#296)
- Progress tracking with .lftp temp naming — ActiveScanner now recognizes
.lftp-suffixed temp files in staging, fixing 0% progress display for single-file downloads when temp naming is enabled (#298) - Remote scanner compatibility — Fixed Python 3.8+ compatibility for
scan_fs.pywhich runs on remote seedbox servers
Changed
- PEP 621 pyproject.toml — Consolidated Python dependencies from Poetry format to PEP 621 with proper dependency groups (runtime, test, dev); removed dead dependencies (#287)
- Ruff linting and formatting — Added Ruff as Python linter/formatter with CI enforcement; applied auto-fixes across 99 files (#288)
- Pyright type checking — Added Pyright in basic mode with CI reporting; fixed 91 type errors across 26 modules (#292, #295)
- Python unit tests in CI — Python tests now run in CI alongside Angular tests (#287)
- Angular dependency updates — Bumped Angular group to 21.2.4, vitest to 4.1.0, jsdom to 29.0.0 (#282, #283, #284)
Docker Pull
docker pull ghcr.io/nitrobass24/seedsync:0.14.1Full Changelog: v0.14.0...v0.14.1