Skip to content

🌟3.3.0

Choose a tag to compare

@EstrellaXD EstrellaXD released this 07 Jul 12:36
dc3a032

3.3.0 — async architecture, first-class aria2, movies/specials, security hardening

Merging this PR triggers the 3.3.0 release build (the release job fires on merged PRs from *dev* branches; version is already bumped to 3.3.0).

Architecture (behavior- and API-compatible)

  • Fully async database layer (sqlite+aiosqlite, WAL + busy_timeout); repositories and Database are async, composition over inheritance
  • Program god-object replaced by a lifespan AppContext composition root with a generic Scheduler/PeriodicTask; startup is awaited and aborts on migration failure
  • Table-driven migrations with already_applied guards (v9–v12)
  • Downloader Protocol with capability flags; qBittorrent session reused across operations (#1039, #900)
  • Config reloads unified through AppContext.reload_settings()

Features

  • aria2 is now a first-class backend: real querying, gid-based dedup reconciled against aria2's live state, collision-safe filesystem renames
  • Movies / OVA / Specials: 剧场版/Movie/OVA/SP token parsing (episode_type), TMDB search/movie fallback, Title (Year) movie layout and Season 0 for specials — validated against Mikan's live feed (98/100 titles parsed, movie releases correctly classified)
  • Per-bangumi release preference: preferred group/resolution with best-release-per-episode dedup (no more double downloads when two groups match)
  • Notifications: typed events (RSS feed failure, download-add failure, offset needs-review) and {{title}}-style templates for every provider
  • Offset suggestions computed from real parsed episodes + one-click apply endpoints (single/bulk)
  • Per-provider parser choice for custom search providers; OpenAI parser now rescues titles the regex parser misses instead of replacing it
  • Configurable TMDB / bgm.tv base URLs (#1040, #1042)
  • Security: login IP allowlist, MCP CIDR allowlist + Bearer token, WebAuthn/passkey hardening, env-gated dev auth bypass (AB_DEV_NO_AUTH)
  • Unauthenticated GET /health + Docker HEALTHCHECK
  • New SSE endpoint (/api/v1/events/stream) replacing the WebUI's three polling loops

Security & correctness fixes (post-review, all 10 verified findings fixed)

  • PyJWT + bcrypt replace EOL python-jose (CVE-2024-33663/33664) and passlib; 72-byte truncation preserved so existing long passwords keep working
  • Failed torrent adds actually retry; duplicates no longer emit failure notifications (AddResult tri-state)
  • Filter-rejected torrents no longer pollute offset scanning
  • Multi-file movie torrents get distinct filenames; aria2 renames can never overwrite existing files
  • Season floor restored: only specials may land in Season 0
  • SSE stream can't be frozen by an unreachable downloader (3s bound + explicit degraded payload)
  • Destructive API endpoints converted GET→POST (CSRF hardening)

WebUI

  • Component system unified on naive-ui (fixed a theme-token crash that blanked the Config page and restored all settings controls; naive-ui 2.39→2.44 for Vue 3.5 compatibility)
  • Oversized editors split into a shared useBangumiRuleForm composable; calendar split into components
  • RSS refresh buttons (per-feed + all), decluttered RSS table, calendar cards show titles without posters, log page copy fixes, mobile nav labels fixed, WCAG AA contrast pass
  • API contract tests (path + verb) for every api/*.ts module

Tooling & CI

  • mypy in CI at 0 errors (176+ source files); ruff + frontend lint/vitest gates on dev-branch PRs
  • E2E suite green again (67/67) after updating stale expectations
  • scripts/dev.sh: one-command seeded dev environment (qB + mock RSS + backend + webui)
  • Version-aware release changelog step; docker-compose example PUID/PGID fix

Test status

Backend: 984 passed (from 792), mypy 0 errors, ruff/black clean. Frontend: 131 passed, vue-tsc clean. E2E (Docker qB + mock RSS): 67/67.

🤖 Generated with Claude Code

https://claude.ai/code/session_01GTnuEgR78cBk32bLNKar3z