Ctrl K
ComunidadGuías…

CHANGELOG.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [v1.6.6] - 2026-10-31

### Added

- Show opt-in same-source R18 evidence in scrape review (#474).
- Add opt-in read-only catalog name output to scrapes (#427).
- Add confirmed offline actress name sync with preview, batch jobs, API worker and catalog UI (#452, #453, #454, #457, #472).
- Preserve target scalars with an explicit merge policy and opt in to transactional imported name updates (#396, #397).
- Add verified catalog filters while preserving UI state (#389).
- Add guarded per-performer name overrides and guarded source-name corrections with provenance UI (#401, #441).
- Add an isolated metadata provider resolver boundary (#456).
- Add unwired bounded target-safe metadata acquisition (#473).
- Add bounded cache groundwork for image input validation, evidence snapshots, an offline r18.dev dump adapter and POSIX artifact publication (#444, #446, #447, #448).

### Fixed

- Add explicit video collision decisions and guide credit-blocked files to current collision details (#378, #379).
- Keep recursive metadata and artwork beside each movie (#387).
- Retain native cast names in JapaneseName and decode cast labels once before routing (#386, #440).
- Decode Jav321 actress entities before splitting names (#477).
- Keep JavLibrary metadata fields within their own sections and preserve fallback when the HTML parser rejects a document (#418, #537).
- Recognize EBML unknown-size VINT values (#405).
- Create migration metadata only after acquiring the startup lock, bound malformed stored migration hash diagnostics, and retain preview rollback ownership after cancellation (#433, #434, #436).
- Preserve bulk outcomes and sanitize boundary failures (#420).
- Join the startup sweep during shutdown (#439).
- Fence scrape admission on server cancellation and stop preview collision planning after cancellation (#471, #484).
- Tolerate refused chmod on ACL-managed staging files and use exclusive rename on Darwin (#390, #424).
- Harden artifact staging seal key loading (#392).
- Preserve explicit numeric scraper overrides (#398).
- Restore the last browse location after scrape navigation, restore the Jobs review source after automatic completion, and restore document titles across navigation (#426, #463, #553).
- Redact paid Google request construction errors (#432).
- Pin validated endpoints within dial budgets (#445).
- Honor opt-in Undo backup retention (#464).
- Update golang.org/x/net for HTML security fixes (#493).
- Close DMM direct probe response bodies and reject empty DMM results after streaming redirects (#500, #546).
- Release owned FlareSolverr sessions on graceful teardown (#545).
- Resolve dot autocomplete in the current directory (#532).
- Preserve source credit identity before enrichment (#556).

### Changed

- Reduce positive-DMM import scans, index canonical import matching transactionally, and skip unchanged candidate quarantine refreshes (#388, #399, #402).
- Remove unreachable version handler fallbacks, unreachable scraper fallback branches, redundant actress template handlers and impossible name and encoding branches (#523, #526, #531, #550).
- Consolidate scraper charset fallback handling and simplify concrete update status callers (#528, #534).
- Share event filter query predicates, apply progress callback wiring, FileBrowser stale-selection pruning, folder-name budgeting and translation model picker presentation (#375, #376, #377, #381, #382).
- Limit NFO pointer metadata to emptiness checks (#541).
- Extend offline and boundary coverage contracts across CLI, API, scraper, database, storage, worker, publication and native filesystem paths (#394, #400, #403, #466, #524, #535).
- Raise the Windows test job timeout to 40 minutes, isolate database-heavy Windows unit suites and allow frontend browser setup within the overall job budget (#393, #438, #513).
- Clarify imported alias metadata boundaries and the durable name correction workflow (#395, #451).
- Accept either fail-closed path error when the working directory is removed, keeping the API suite green on macOS.

## [v1.6.5] - 2026-10-21

### Added

- Add optional center and fit poster fallbacks (#373).

### Fixed

- Isolate batch test working directories to prevent accumulated fixture timeouts.
- Preserve indexed lookups for legacy R18 dump sidecars (#374).
- Preserve upstream service variants and Unicode DVD IDs (#372).
- Clarify strict-upload row rejection diagnostics (#371).
- Avoid redundant chmod on exact-mode staging files (#370).
- Preserve mixed-case source content IDs (#369).

### Changed

- Share poster success reconciliation (#365).
- Extract production review selection model (#364).
- Share selected operation revert runner (#363).
- Centralize output rendering options (#362).
- Share authoritative progress count selection (#361).
- Remove unused genre replacement editor (#360).
- Unify structural validation (#359).

## [v1.6.4] - 2026-10-20

### Added

- Add manual dump uploads (#273).
- Activate ASCII remaster identity with guarded sources (#346).

### Fixed

- Honor umask for published directories (#358).
- Omit empty FlareSolverr session IDs (#355).
- Exercise concurrent sweeps on native filesystem (#356).
- Discharge legacy credit errors after successful retry (#352).
- Keep new collision-only attempts retryable (#351).
- Preserve selection when movie groups change (#350).
- Report retained staging proofs and preserve recovery state (#348).
- Recognize persisted legacy credit gate failures (#349).
- Preserve channel prefix on selected raw CID (#347).
- Bind dump lookup and remaster source identities atomically (#344).
- Resolve remaster queries with end-to-end identity guards (#345).
- Guard raw CID and parsed page identity (#341).
- Validate remaster selection and final detail identity (#342).
- Add guarded marker-aware dump candidates (#340).
- Expand exponent settings input before integer parsing (#338).
- Compose history filters and bound replacement pagination (#337).
- Cancel and join dump workers during runtime shutdown (#336).
- Preserve word drafts and show current settings errors (#335).
- Honor translated metadata priorities and source attribution (#334).

### Changed

- Isolate Windows workflow offline test budget (#353).
- Remove superseded timing-based rollback assertion (#343).
- Share LLM HTTP execution (#339).

## [v1.6.3] - 2026-10-18

### Fixed

- Retain selected raw actor evidence across alias conversion (#333).
- Preserve legacy actor thumbnail edits and omit blank separators (#332).
- Keep actor selection, save receipts and credited fallback consistent (#331).
- Preserve actor-credit choices during forced rescrape (#329).
- Reject destructive empty actor renames in movie edits (#330).
- Refresh inferred legacy single-part actor names safely (#328).
- Handle pinned preview connection cleanup errors.
- Retain NFO cast projection across rescrape ID correction.
- Preserve actor credit choices across NFO merges (#325).
- Reconcile actor identity lifecycle during import (#323).
- Stage timeout outcomes until the database fence commits.
- Preserve credit review recovery and mutation ordering.
- Derive display titles from authoritative credits.
- Retain credit-fenced Apply timeout outcomes.
- Align the organize credit gate with live credits (#320).
- Truncate multiline Discord release notes correctly (#319).

### Changed

- Avoid intercepting Vite imports in retry browser mocks.
- Make watchdog and idle-reclaim timing deterministic (#326).
- Use native paths for rescraped actor images.
- Synchronize expired writeback with completed SQLite rollback.

## [v1.6.2] - 2026-10-16

### Fixed

- Keep completed dump imports from stalling on optional EOF probes while retaining resumed-payload stall detection (#316).
- Isolate review refresh state between jobs and prevent Apply or retry after failed saves or non-authoritative refreshes (#317).
- Fix native BSD lint validation while preserving primary Undo timestamp precision.
- Avoid redundant staging copies for organize and in-place video moves; allocate staging on the planned destination filesystem, including writable destinations with read-only parents (#276, #282, #285).
- Preserve configured subtitle policy and source ownership across copy, link, multipart and case-insensitive publication; keep internal busy markers out of published artifacts and allow safe cleanup retries (#281, #284, #290).
- Preserve existing resident videos, aliases and unowned artwork during Apply and Undo; recover owned directory moves and retain unresolved recovery state (#291, #292, #295, #296).
- Preserve restored replacement files during cleanup; retain native Windows volumes when restoring primary files and NFO snapshots (#294, #303, #304).
- Add journaled, copy-first cross-volume primary Undo on supported POSIX platforms, with identity checks, retry retention and cancellation checks before further mutations (#303, #306).
- Show failed or skipped Undo outcomes accurately and keep eligible retries available (#300).
- Keep failed-Apply recovery safe after cancellation; prevent late Apply updates from racing Undo, and commit recovery records together with their paths and status (#315).
- Stabilize title previews across metadata refreshes and catalog-identity choices; preserve movie-specific actress-name drafts through refreshes and asynchronous saves (#276, #282, #283, #286).
- Resume interrupted r18.dev dump downloads using validated HTTP Range requests; exclude local importer work from the network-stall budget and finish cancelled SQLite rollback before temporary-file cleanup (#272, #301, #309).
- Honor cancellation during DMM direct URL probes (#299).
- Omit unsupported temperature parameters for explicitly recognized OpenAI reasoning models while preserving other provider/model behavior (#288).
- Preserve committed configuration during failed publication and concurrent initialization (#289).
- Preflight no-clobber capability before verified payload streaming on unsupported destination volumes (#308).
- Stop and join the API-owned token cleanup worker during shutdown and explicitly validate nil dependency receivers (#310, #311).

### Changed

- Replace live-network short-test dependencies with synthetic/offline fixtures and add guarded Linux/Windows CI; isolate the synthetic UNC fixture from host filesystem access (#298, #307, #312).
- Expand native Windows, isolated SMB, FUSE, browser and recovery regression coverage; stabilize native identity and timing fixtures (#274, #287, #293, #297, #302, #305, #308).
- Update the pinned linter for Go 1.27 export data (#271).

### Known limitations

- Existing distinct video files are still protected against overwrite. Issue #277 remains open; related resident-file fixes do not establish resolution of the original report.
- Volumes lacking both supported atomic no-replace publication primitives remain unsupported. FUSE fixtures do not establish compatibility with a particular Unraid/shfs deployment; actual Unraid validation is deferred (#252).
- Windows cross-volume primary Undo remains unsupported and fails closed. Ambiguous historical recovery records are not migrated; interrupted cleanup claims may require manual recovery. Legacy unowned staging directories are retained.
- Unresolved failed-Apply reconciliation can leave Undo blocked and require manual recovery; missing recovery proofs are not reconstructed automatically. Do not clear recovery markers or use older binaries to Undo affected operations (#315).
- AI-remastered title sorting (#254 / #257) is not included.
- The historical Windows Go GC crash and subsequent test hang remain unexplained. The lifecycle/nil-validation fixes and successful bounded tests do not prove their cause or resolution. Diagnostic-only PR #313 is not included.

## [v1.6.1] - 2026-09-27

### Fixed

- Stop title preview flap from volatile actress metadata (#269)
- Resolve pre-commit golangci-lint robustly (#267)
- Replace 30m r18dev dump download deadline with stall watchdog (#266)
- Render unquarantined scrape candidates (#265)

## [v1.6.0] - 2026-09-24

### Added

- Separate actress identity from per-movie credits: the actress database is the source of truth, scrape results record reported attribution per movie without mutating identities, ambiguous names surface as review candidates, and per-movie credit overrides persist independently of the identity
- Gate actress image URLs in NFO actors

### Fixed

- Review thumbnails, name matching, and per-movie overrides: identity-snapshot credits refresh on every rename path (catalog edit, review rename, collision adoption), scraper-reported and user-touched credits are never rewritten as snapshots, explicit thumbnail clears are honored with stale-payload drift protection, and persisted credit overrides update the authoritative review state immediately (#264)
- Exclude male co-stars from javdb casts and keep actress thumbnails
- Test unsaved proxy profiles during initial setup (#259)
- Probe no-clobber capability before staging streams (#255)
- Restore background job indicator after page reload (#253)

## [v1.5.2] - 2026-09-08

### Added

- Detect cd/disc/disk multipart suffixes (closes #224 phase matcher) (#242)
- Per-destination lock registry unification for organizer (#239)
- Dry-run duplicate preflight + subtitle modes (#241)
- Audit crumb for force-overwrite of occupied destinations (#249)
- Persist batch skip warnings to history (#248)
- Require proven source identity for manual poster crops (#251)
- Expose typed warning codes to API and UI (#236)
- Wildcard match mode for word replacements (#228)
- Recover review loads and apply state (#222)

### Fixed

- Codex review iteration on crop-identity enforcement: bounded poster verify body (64 MiB), poster-verified marker clear semantics, wrapped recrop refusal recognition (#251 rounds 1–11)
- Carry multipart part-suffix into sort planning (#243)
- Refuse silent overwrite of same-named multipart destinations (#225)
- Atomic no-clobber terminal ops via fsutil composites (#234)
- Kind-typed organize conflicts; authorization applies to files only (#235)
- Joinable background-check shutdown (Windows TempDir race) (#250)
- Skip revert journaling in dry-run and dedupe duplicate-path message (#247)
- Match censored-token word replacements in CJK text (#231)
- Honor rename_file=false for rename-in-place operation (#230)
- Reflect rename_file setting in rename-in-place description (#233)
- Image crop/reader zero-dimension guard coverage
- Windows CI tolerance for transient bridge path walk entries

### Changed

- Resolved stepDownload's PosterVerified flag from aggregate Downloaded to per-media-type verification (#251 round 9)

## [v1.5.1] - 2026-08-12

### Added

- Resolve null-dvd_id titles via dump content-id candidates (#205)

### Fixed

- Use canonical movie ID for poster crop source URL (#206)
- Eliminate import heartbeat data race in r18devdump (#207)

## [v1.5.0] - 2026-08-09

### Added

- Add server-side image cache for review preview images (#197)
- Write <set> in tiered Kodi 19+ collection format (#196)
- Surface <RELEASEDATE> tag in folder/file naming UI (#194)
- Add overwrite-media option with SSR-stable browse plan UI (#177)

### Fixed

- Render statically served SPA on hard navigation (#204)
- Expand template tags in tagline and custom NFO tags (#202)
- Page-derived identity for JavLibrary + JavStash, URL redaction hardening (#198)
- Detect letter+quality-tag multipart suffixes (#193)
- Persist manual poster crop through organize (#187)
- Harden release version flow and add artifact assertions (#185)
- Native export save + in-app import confirms (webview gaps) (#183)
- Local project coverage matches Codecov + fail-loud test run (#181)

### Changed

- Skip live-network tryDirectURLs tests in short mode (#203)

## [v1.4.0] - 2026-07-29

### Added

- Wire history record creation during scrape/organize (#171)
- Redesign review page with sidebar layout and UX improvements (#170)

### Fixed

- Correct actress panel spacing, dynamic grids, and single-column layout (#175)
- Honor unknown_actress_mode=skip in GroupActress @Unknown substitution (#174)
- Clear error when path overhead exceeds max_path_length + CJK rune truncation (#173)
- Match plain numeric IDs in itemIDRegex (#172)

## [v1.3.3] - 2026-07-24

### Added

- Add bidirectional favorite-genre shuttle in movie editor (#169)
- Add favorite genre quick-apply palette (#168)
- Show existing NFO values alongside scraped data (#160)

### Fixed

- Sync scraper ProxyEnabled with resolved proxy mode (#167)
- Use CREATE_NO_WINDOW for silent Windows upgrade helper (#166)

## [v1.3.2] - 2026-07-21

### Added

- Group actress min threshold config option (#163)
- Language selector on pre-auth (setup/login) screens (#165)

### Fixed

- Infinite page-refresh loop for Simplified/Traditional Chinese browser locales (#164, #165)

## [v1.3.1] - 2026-07-19

### Added

- Minimal config persistence with user-only scraper overrides and sparse saves (#161)
- Surface localized, typed scrape-error messages (#157)

### Fixed

- Separate title and display_title fields to prevent code doubling (#159)
- Raise request_timeout_seconds default to 180s and keep environment overrides out of config.yaml

## [v1.3.0] - 2026-07-17

### Added

- Add --output json mode to scrape for machine-readable per-scraper results (#155)
- Full internationalization support across Web UI, TUI, and API (#144)

### Fixed

- Enforce configurable timeouts and guard against hard-coded literals (#154)
- Join background check goroutine to fix flaky TempDir cleanup
- Prune phantom file selections on directory refresh (#147)
- Preserve matcher MovieID when scraped ID differs, preventing wrong grouping (#146)
- Check for duplicate DMM ID before actress update
- Reuse configured port across desktop restarts instead of random

### Changed

- Guard web-build deps and add build-app-local Makefile target
- Replace ProgressFunc with context-scoped ProgressReporter (#151)
- Extract job persistence codec into jobpersist package (#150)
- Extract fs utilities into fscase and fanout packages (#149)
- Extract result tracker into resultstore package (#148)
- Remove openspec from tracked .gitignore
- Remove tracked unused.yaml fixture, use temp dirs in tests
- Ignore node_modules at repo root, not just web/frontend

## [v1.2.3] - 2026-07-15

### Fixed

- Preserve matcher MovieID when scraped ID differs, preventing wrong grouping (#146)
- Check for duplicate DMM ID before actress update
- Reuse configured port across desktop restarts instead of random

### Changed

- Remove tracked unused.yaml fixture, use temp dirs in tests
- Ignore node_modules at repo root, not just web/frontend

## [v1.2.2] - 2026-07-13

### Added

- Expose r18.dev dump management via API + WebUI (#136)
- Validate disabled-scraper priority overrides (#138)

### Fixed

- Manual inputs override multi-part grouping key so files with different manual IDs split into separate movies (#143, closes #142)
- Seamless progress bar with monotonic phase transitions + clear file selection after batch scrape completion (#141)
- Retry lock release on Windows to handle AV/sharing violations (#137, #140)
- Resolve ABF-030 misresolution via content-id variations (#135)
- Use high-res cover as poster in r18dev dump path (#134)
- Use javinizer icon for favicon instead of generic J logo (#130)
- Lower MinPoster threshold to accept real DMM posters (#132)

### Changed

- Codex label sync tracks latest review, not unresolved threads (#139)
- Block npx/npm drive-by suggestions from sleeper accounts
- Disable auto-triggering @codex review from label sync
- Grant pull-requests: write for codex label sync
- Use PowerShell syntax for APPDATA in migration snippets (#133)
- Cover missing readFileWithRetry not-exist path

## [v1.2.1] - 2026-07-11

### Added

- Display actress names in first-name order when config enabled (#127)

### Fixed

- Respect actress_language_ja preference in name display (#129)
- Run organize step for in-place rename modes (#125)
- Upgrade DMM covers/posters to high-res awsimgsrc CDN (#124)

### Changed

- Add Codex review label sync workflow (#126)

## [v1.2.0] - 2026-07-10

### Added

- Single-line progress bar to r18dev dump download
- First-run setup as a 3-step wizard
- Ignore-list and favorites UI to genre management

### Fixed

- Recover orphaned running/pending jobs on startup
- Deny root-resolving allowed_directories entries
- Pin actions/github-script to v7 tag
- Make TestAcquireConfigFileLock_Contention deterministic
- CORS preflight, default port, `<img>` auth in dev environment
- Browse box focus ring + allowed_directories persistence
- Windows CI flake: SQLite file handle race in batch test teardown
- Boundary-aware word replacement for censored tokens
- Ship metadata.priority.* as inherited by default

### Changed

- Add CLI-to-Desktop migration guide with Windows paths
- Harden path picker: autocomplete stays alive + browse respects allowed_directories
- Bump Go to 1.26.5 to clear govulncheck GO-2026-5856
- Clarify desktop/CLI relationship, document r18.dev dump
- Add anti-spam filter for unauthorized patch/attachment drops on issue comments

## [v1.1.1] - 2026-07-07

### Added

- Desktop app one-liner installers

### Fixed

- Poster preview rendering across desktop, r18dev, and web subcommand
- Group Update & restart with Check for Updates action
- Docker `make docker-run` now works end-to-end (CMD api→web, writable media, trusted CIDRs, quoted paths)
- WebSocket hub goroutine shut down before DB close in CreateTestDeps (Windows/Linux temp-dir cleanup flake)
- Docker entrypoint chown non-fatal on read-only mounts
- Update popover redesign: version flow, copy-to-clipboard command block, docker instructions hidden
- Discord release notification embed enriched (thumbnail, author, fields, truncated release notes)
- Docker Quick Start admin setup unblocked, migrated to docker compose v2

### Changed

- Docker host port default 8080 → 8765 (less collision-prone)
- Bump quic-go v0.57.0 → v0.59.1 (GO-2026-5676)
- Lead README Quick Start with desktop one-liner, demote CLI to alternative
- Fix cli-release.yml YAML syntax error in Discord notify job

## [v1.1.0] - 2026-07-07

### Added

- Package as clickable desktop app for macOS, Windows, and Linux (#84)
- Add desktop bundle self-upgrade (#89)
- Add environment-aware upgrade UX (docker/desktop/cli)
- Add UI and API for managing allowed_directories (#93)
- Add allowed_directories to first-run setup (#94)
- Embed Windows app icon via genicon .syso resource
- Extract UpgradeAction and force same-origin API in desktop webview
- Add per-field source override with source-merge modal (#80)
- Add local dump lookup with zero-HTTP fast path for r18dev (#76)

### Fixed

- Fix desktop Windows launch, WebSocket progress, and browse security model (#99)
- Redesign allowed directories editor and fix PathInput Enter behavior (#98)
- Reverse-proxy through Wails asset server instead of redirecting (#96)
- Add desktop app icon and fix web favicon (#95)
- Resolve NTFS volume mount points in canonicalizePath (#92)
- Make hot_reload atomic across registry/config/factories (#82)
- Fail-closed on nil auth manager (#81)
- Give "Remember me" sessions a longer TTL than ephemeral ones
- Detect podman/nerdctl containers and document cgroup v2 limit
- Persist window geometry across launches
- Point JAVINIZER_DATA_DIR at the portable data dir
- Use OS-correct separator in organize preview folder names
- Use 'web' subcommand in CLI flag e2e test
- Skip window-state perm test on Windows

### Changed

- Rename 'api' subcommand to 'web'
- Introduce DTOs for MovieView nested collections (#83)
- Add make config-sync to mirror the embedded config master
- Move Discord notify into cli-release workflow
- Add brew trust step for Homebrew 6.0+ tap-trust requirement
- Document environment-aware upgrade behavior
- Post-v1.0.0 housekeeping
- Split e2e suites into frontend/fullstack/live and add upgrade-CTA coverage
- Expand fullstack e2e coverage to scrape pipeline and APIs
- Cover PersistentSessionTTL getter, NoOpAuth mock, and clamp guard
- Cover container-detected branch in fetchWithBrowser
- Rename pendingCount to revertEligibleCount to match semantics

## [v1.0.0] - 2026-07-03

### Added

- Add per-scraper output invariants and update-checker live e2e tests
- Add PR template with issue auto-close reminder
- Add stale issues workflow
- Add real-live scraper e2e suite (local only, not CI)
- Add live CLI end-to-end suite driving the real javinizer binary

### Fixed

- Respect download_extrafanart config when --extrafanart is omitted (#79)

### Changed

- Notify Discord webhook on release publish
- Rewrite README future-tense framing to present tense for v1.0.0 stable
- Ignore build-tagged e2e and generated/vendored paths in codecov
- Pin all CLI flags and flag-supersedes-config behavior in e2e
- Drop issue #72 refs, SignPath-pending note, and broken code-signing link in README

## [v1.0.0-rc4] - 2026-07-02

### Added

- Add self-upgrade (`javinizer upgrade`), Homebrew/Scoop taps, and one-shot installers for v1.0.0 (#78)
- Add alias-aware actress dedup and per-movie NFO name choice (#74)

### Fixed

- Harden actress rename path and guard review save-flow (rc3 regressions) (#73)
- Address CodeRabbit review: collapse redundant Homebrew darwin branches and restore BackgroundCheck error logging

### Changed

- Close codecov patch gaps and enforce the 80% patch gate over informational hide
- Cover defensive branches in the update/version commands via DI seams rather than filesystem tricks

## [v1.0.0-rc3] - 2026-06-30

### Fixed

- Persist actress name edits from review page to DB and NFO (#71)
- Restore movie.OriginalFileName so `<FILENAME>` NFO tag resolves

### Changed

- Drop version from release asset names + link to releases page
- Add doc comments to exported identifiers + enable exported lint (#47)
- Remove 146 stale ADR citations referencing deleted ADRs (#46)

## [v1.0.0-rc2] - 2026-06-30

### Added

- Manual scrape: per-file ID/URL override + /manual review route (#68)

### Fixed

- WebUI Output/NFO settings broken by nested JSON (#70) — OutputConfig and NFOConfig serialized as nested objects while the frontend read a flat shape, leaving download checkboxes unchecked and dropping saves; also fixed the delimiter ↔ actress_delimiter mismatch and guarded array .join() against undefined. Closes #69.
- Rescrape: refresh images and reset baseline on content-id change (#67)
- Poster: preserve original cover URL across resets

### Changed

- Docs: fix accuracy across all docs per audit (18 files)
- CI(docker): bump login-action to v4.2.0 (Node 24 runtime)
- Test: reach 100% coverage on Output/NFO UnmarshalJSON probe branch

## [v1.0.0-rc1] - 2026-06-28

### Changed

- **Workflow seam**: replaced ad-hoc task types (ScrapeTask/DownloadTask/OrganizeTask/NFOTask) with a unified `Workflow` abstraction. Jobs execute via phase-based `BatchJobInterface` (scrape / apply / rescrape), consolidating the worker pool onto a single seam.
- **API projection layer**: movie/actress/genre views lifted into `internal/api/contracts`, decoupling the wire format from persistence models (content_id → code rename, PosterState fields lifted to top-level).
- **Scraper registry**: replaced the `init()`-based plugin system with a centralized registry (`internal/scraper/registry.go` + `scraperutil` registration catalog).
- **Job reconstruction**: `SetReconstructionDeps` re-hydrates infrastructure dependencies on jobs loaded from the database at startup, so post-restart apply/rescrape and movie-edit persistence work.

### Removed

- **Dead code**: ~138 intentional deletions consolidated during the refactor — `version.txt` → `version.go` (VCS-embedded via `debug.ReadBuildInfo`), `internal/api/*/aliases.go` re-exports folded in, worker pool refactored onto the Workflow seam. 5 empty/comment-only files removed (zero declarations, zero references).

### Added

- **Word replacement toggle + opt-in default**: added `metadata.word_replacement` (opt-in, `enabled: false`) to the example configs and `defaultMetadataConfig()`, and moved the genre/word replacement enable toggles into the dedicated `/settings` sections with null-safe handlers.
- **Update-available UI**: surface update availability in the web UI and harden the checker against GitHub rate limits.
- **JavDB actress avatars**: construct actress thumbnail URLs from the actor ID in the movie-page link (`https://c0.jdbstatic.com/avatars/<pp>/<ID>.jpg`), populating `ActressInfo.ThumbURL` without extra HTTP fetches.
- **CI release hardening**: explicit `make_latest` on the GitHub release step so stable releases deterministically become "Latest" and prereleases never steal it.
- **Docker CI**: build arm64 natively via a per-arch matrix (free `ubuntu-24.04-arm` runner) + `merge-manifest` job instead of QEMU emulation, cutting the docker job from ~15min to ~5min.
- **Web frontend (SvelteKit SPA)**: review flow with jobId-scoped state and monotonic WebSocket-driven progress bars; fullstack E2E suite + vitest unit tests.
- **Mockery freshness gate**: pinned mockery v3.7.1; added a `make check-mocks` target + `test.yml` step that fails CI if mocks drift from their interfaces (caught a real portability bug — `sed -i` macOS-only — on its first run).
- **`.gitignore` hardening**: `tmp/`, `web/frontend/playwright-report/`, `blob-report/`, `playwright/.cache/`, `*.db-shm`, `*.db-wal`, `*.log`.

### Fixed

- **Per-field metadata.priority exclusivity (consistency + `--scrapers`)**: `AggregateWithPriority` (the selected-scrapers / `--scrapers` path) now honors a per-field override exclusively, matching `resolvePriorities` (the default path). Previously it applied `cmd.SelectedScrapers` as a flat priority for every field, ignoring per-field overrides — so `series: [tokyohot]` (skip Series via exclusivity) still populated Series from DMM when scraping with `--scrapers dmm` (BMD-284). Both paths now use pure v1 exclusivity consistently: a per-field list means "only these scrapers, no global fallback." No skip sentinel — a field is left empty by pointing it at a scraper that didn't run or lacks it (e.g. `series: [tokyohot]`). **Backward-incompatible (config semantics):** an empty list `metadata.priority.<field>: []` previously meant "inherit global"; it now means "consult no scrapers — the field is left empty" (key *absent* is the inherit-global state). If you hand-wrote `<field>: []` in `config.yaml` expecting the field to inherit the global priority, **delete the key** so it inherits; otherwise the field will now be left empty after upgrading. "Remove all" + Save in the priority editor intentionally produces this empty-list state.
- **Rescrape merge strategies**: the API previously accepted + validated `preset` / `scalar_strategy` / `array_strategy` then silently dropped them; `RescrapeCmd` now carries `MergeOptions` and `CompleteRescrape` applies the merge (reusing the apply-path logic).
- **Theme toggle**: rendered as a component, fixing an unknown-element regression in the web UI.
- **Test coverage** raised to meet the 75% CI threshold; race-clean.
- **DMM director + rating extraction** restored after the upstream DMM markup migration.
- **Image previews** refetch on URL change via a reactive error state, eliminating stale thumbnails.
- **Per-field metadata.priority (consolidated)**: `[]` now inherits global; the `["__skip__"]` skip sentinel is honored, with YAML persistence fixed across the priority editor.
- **Aggregator per-field priority exclusivity**: per-field `metadata.priority` is now exclusive (not merged with global) consistently across both the default and `--scrapers` paths.
- **Update checker**: background update checker + startup check wired up.
- **History pagination**: filtered history API endpoints now paginate correctly.
- **Poster crop**: preserve `ShouldCropPoster` through `GeneratePoster` so the apply-phase crop runs after rescrape.
- **Web rescrape modal**: removed stray `}` in the title; pass `movie_id` (not `result_id`) to `openRescrapeModal`; show feedback when "Reload Config" is pressed.
- **Filename template**: strip the extension from the `<FILENAME>` token and add `<FILENAME_EXT>`.
- **Vulnerability scan**: bump `x/image` + Go toolchain to clear 10 govulncheck findings; gate the Vulnerability Scan job on token presence. Codecov upload now supplies a token and fails loud on upload error.

### Tooling

- **`.coderabbit.yaml`** rewritten as a durable repo-level review policy (dropped the transient review-history header and invalid `review_status` sub-keys; added `auto_review`, `high_level_summary`, `poem`, `review_status: true`).

## [v0.3.15-alpha] - 2026-06-23

### Fixed

- Persist edited poster URL before manual crop so the crop endpoint operates on the edited image, not the stale server-side poster (issue #37)
- Persist Move Files setting across restarts via a real Output.MoveFiles config field; --move flag remains a session-only override (issue #36)
- Prevent config leakage and harden move-files persistence: saveConfig reloads from disk so session-only CLI/env overrides are not written to config.yaml
- Use atomic config.Update (read-modify-write under the file lock) for move-files persistence, eliminating a TOCTOU race and lost updates
- Strip stdout/stderr from the TUI logger so logs don't leak into the terminal (the default dual-output "stdout,file" config was leaking)
- Harden the TUI log-leak fix: InitLogger errors on zero valid outputs instead of silently falling back to stdout; fix the pre-alt-screen startup leak via isTUICommand; extract a pure configureTUILogging helper
- Resolve JAVINIZER_CONFIG in the TUI so LoadOrCreate and SetConfigPath use the same path (config persistence broke when the env var was set)
- Guard the runtime move-files toggle against the move+link combo rejected at startup (ValidateMoveLinkMode)
- Honor JAVINIZER_LOG_DIR in the TUI fallback log path and report the actual relocated log path
- Nil-guard config.Update against a nil mutate callback

### Changed

- Add end-to-end stdout-leak tests (os.Pipe capture) plus a non-vacuous contrast test
- Add tests for resolveConfigPath, canEnableMoveMode/runtime guard, JAVINIZER_LOG_DIR fallback, and config.Update nil-guard
- Prove config.Update atomicity with a 100-writer concurrency test (no lost updates)
- Cover persist-before-crop in the poster crop controller
- Use the real TUI command in the isTUICommand detection test; use io.ReadAll for stdout pipe capture consistency

## [v0.3.14-alpha] - 2026-06-22

### Fixed

- Resolve poster/cover reactivity and edit persistence bugs
- Add id DESC tiebreaker to job-list ordering

## [v0.3.13-alpha] - 2026-06-21

### Added

- Configurable max_poster_height with frontend override

## [v0.3.12-alpha] - 2026-06-20

### Added

- Implement User-Agent priority chain for scrapers
- Support actress Japanese name in folder/file templates
- Add @Unknown substitution for grouped unknown actresses
- Support tag-level first-name-order modifier on actress tags
- Rename output.delimiter -> actress_delimiter; DELIM= modifier; hard break

### Fixed

- Disable proxy by default since r18.dev doesn't need it
- Capture PPV underscore prefixes in content_id lookup
- Apply word replacement to genres
- Stop upgrading poster URL ps.jpg -> pl.jpg
- Set shouldCrop=true when falling back to cover poster
- Address sub-agent code review findings

### Changed

- Regenerate swagger docs
- Update template system docs for new actress tag features

## [v0.3.11-alpha] - 2026-06-07

### Fixed

- Generate 3-digit padded content_id variations for lookup prefixes (fixes ABF-346 and similar titles)

### Changed

- Fix stale doc comment on generateContentIDVariations

## [v0.3.10-alpha] - 2026-06-07

### Added

- Content-ID variation fallback for digital-only r18.dev titles that return 404 on the dvd_id endpoint
- Awsimgsrc poster resolution using prefix lookup table for digital/video content
- Screenshot discovery fallback that probes pics.dmm.co.jp when the API returns no screenshots or placeholder filter removes all
- DepadContentID to handle zero-padded content_ids (e.g. 118gets00081 → 118gets081)
- Configurable RespectRetryAfter setting for r18dev scraper with tri-state *bool (nil = default true)
- 274KB content_id_prefixes lookup table generated from r18.dev database dump

### Changed

- Retry logic uses max(Retry-After, exponential backoff) when RespectRetryAfter is enabled
- Export GetImageDimensions from imageutil for reuse
- Move DiscoverScreenshots fallback after placeholder filter so it triggers when all screenshots are filtered

## [v0.3.9-alpha] - 2026-06-06

### Added

- Replace mutable movieId with stable ResultID for batch job API lookups

## [v0.3.8] - 2026-06-05

### Added

- PathInput component with whitelist autocomplete for source and destination path inputs

### Changed

- Improve multipart detection with TrailingPrefix and prefix-based validation

## [v0.3.7-alpha] - 2026-06-02

### Added

- Trailer preview, review tabs, and View Failed button on jobs page

### Fixed

- Redirect View Failed to Failed tab and sync tab URL bidirectionally
- Extract javlibrary rating from `var $rating` JS var and add aggregator-side range check that surfaces corrupt scores as warnings

## [v0.3.6-alpha] - 2026-05-31

### Added

- Expand LibreDMM scope to support FC2/MGStage/SOD sources
- Surface unidentified files and allow manual rescrape from review page
- Add first_name_order config for actress name formatting

### Fixed

- Fix caribbeancom English URL construction and reject soft-404 responses
- Detect caribbeancom English blank-entry soft-404 (var Movie = null)
- Fix docker frontend-builder stage ordering and limit Rollup parallel file ops
- Remove content ID zero-stripping canonicalization that broke r18.dev image URLs
- Refresh aggregator replacement caches after CRUD operations
- Detect Windows cross-device move error, add customizable GroupActressName

### Changed

- Embed swagger.json in binary via go:embed
- Clarify --scrapers flag only selects from enabled scrapers
- Add .omo/ to .gitignore

## [v0.3.5-alpha] - 2026-05-25

### Fixed

- Extract DMM screenshot URL normalization into shared imageutil package, fixing R18Dev screenshots missing `jp` suffix which caused smaller thumbnails to be pulled (issue #23)
- Fix DMM new-site extractScreenshotsNewSite missing NormalizeDMMScreenshotURL
- Fix JavLibrary incorrect jp- screenshot filter that was filtering out higher-resolution images
- Remove LibreDMM dead ThumbnailImageURL-derived poster code that was always overwritten

### Changed

- Consolidate duplicated DMM screenshot URL normalization logic from 6 scrapers into shared `internal/imageutil/` package (NormalizeDMMScreenshotURL, UpgradeCoverResolution, GetOptimalPosterURL)
- All 6 scrapers (DMM, R18Dev, JavBus, LibreDMM, JavLibrary, DMM actress) now use shared normalization pipeline for consistent CDN rewrite, host lowercase, and cover resolution upgrade
- Actress thumbnail normalization in DMM actress.go delegates to shared imageutil.NormalizeDMMScreenshotURL instead of inline CDN rewrite

## [v0.3.4-alpha] - 2026-05-02

### Fixed

- Replace contentIDMatchesExpected with core series+number validation (contentIDCoreMatch) to reach 97.7% r18.dev match rate, ignoring suffix mismatches that caused 84% of old failures
- Remove generateAlternateContentIDs fallback which matched 0% of misses due to only trying 4 hardcoded maker codes out of 7,704
- Prevent ONED-025 false positive resolving to ONED-205 by validating core number match

## [v0.3.3-alpha] - 2026-05-02

### Added

- Completeness scoring system with configurable essential/important/nice-to-have tiers and weighted percentage calculation
- CompletenessDial SVG component with tier-appropriate colors (red/yellow/green) and hover breakdown tooltip
- Completeness filter buttons on review page to filter movies by Incomplete/Partial/Complete
- Grid card selection mode with shift-click range selection, select all/deselect all, and bulk exclude/rescrape actions
- Review page grid view with poster and cover display modes (3-column layout for cover art)
- WebUI config section with `default_review_view` setting (detail, grid-poster, grid-cover) and settings UI
- Runes-based global background-job store (`$state`) replacing local component state for cross-page persistence
- BackgroundJobIndicator and ProgressModal moved to authenticated layout so they persist across page navigation
- BackgroundJobIndicator redesigned as theme-aware card (`bg-card`) with status-tinted rings and lucide icons
- All Go backend job statuses handled in indicator and modal (completed, failed, cancelled, organized, reverted, pending, running)
- Status-specific success messages in ProgressModal (scraping completed, organization complete, revert complete)
- Real-time job progress synchronization on /jobs page via WebSocket-derived `computeJobProgress` utility
- Auto-polling (5s interval) for running jobs on /jobs page, stopping when no jobs are running
- `liveProgress` in ProgressModal derived from WebSocket data instead of REST API polling
- Shared `$lib/utils/job-progress.ts` utility with `TERMINAL_STATUSES`, `isTerminalStatus()`, and `computeJobProgress()`
- `clearJobMessages()` method on websocket store for evicting stale per-job data
- WebSocket store deep-copy for `messagesByFile` per-job records (store immutability)
- Capped WebSocket `messages` array at 200 entries to prevent unbounded growth
- Playwright E2E test suite (98 tests) for review page: completeness dial, selection mode, bulk actions, view toggle, keyboard navigation, filter persistence, and edge cases
- Review state unit tests for completeness computation and view mode handling
- Completeness utility tests for tier scoring, edge cases, and custom weight validation
- Batch rescrape endpoint with scraper selection, NFO merge strategy presets, and progress indicator
- Batch exclude endpoint with per-movie and bulk exclusion support
- Movie edit PATCH endpoint for inline field editing on review page
- `Update` field persisted on `BatchJob` and `BatchJobSlim` for update mode tracking
- Database migration `000008_jobs_update_column.sql` for jobs update column
- Comprehensive backend test coverage: batch rescrape (unit + integration), batch exclude integration, API handlers (actress, auth, genre, history, events, version, system, jobs), config validation/redact, NFO merger DMMID preservation, database helpers/race branches, WebSocket hub nil guards, fsutil move, httpclient builder, DMM scraper helpers, worker single_scrape branches

### Changed

- Rename `metadata-only` operation mode to `metadata-artwork` across codebase (Go types, organizer strategy, config, tests)
- Derive version from git tags/commit hash instead of embedded `version.txt` file (removed `version.txt`)
- Review page view mode is now 3-state: `detail | grid-poster | grid-cover` (legacy `grid` maps to `grid-poster`)
- ProgressModal uses two separate `$effect` blocks with `untrack()` to avoid `cancelRedirect` circular dependency
- ProgressModal auto-redirect countdown now guarded by `hasNavigated` flag preventing duplicate navigation
- ProgressModal `latestMessage` derived from `messagesByFile` instead of capped `messages` array
- `TERMINAL_STATUSES` aligned with Go backend: `completed`, `failed`, `cancelled`, `organized`, `reverted` (removed non-existent `done` and `skipped`)
- `createBatchJobPollingQuery` uses `isTerminalStatus()` to stop polling for all terminal statuses
- Homepage `activeJobCount` uses shared `isTerminalStatus` utility instead of inline Set
- E2E test selectors updated from `/^grid$/i` to `/^poster$/i` for view mode toggle buttons

### Fixed

- Scraped movies now always persisted to database regardless of custom scraper selection
- NFO actress merge preserves DMMIDs from scraped data when matching by JapaneseName or romanized name
- Omit `Translations` in `Upsert` to prevent transaction rollback on orphaned rows
- Frontend review page reads destination from job data instead of query param
- Actress search switched to server-side to prevent client-side performance issues
- svelte-check added to pre-commit hook to catch TypeScript errors early
- BackgroundJobIndicator auto-dismiss timer re-arms when user closes modal after terminal status (tracks `showModal` as dependency)
- Auto-dismiss timer callback guards against null `jobId` and verifies prop matches store's current jobId
- ProgressModal dismisses job store state after successful `goto()` navigation (handles rejection too)
- `reopenModal()` guards against null `jobId` to prevent inconsistent store state
- `Math.max(0, ...)` for remaining files count when `completed + failed > total_files` (retry scenarios)
- Windows path separators handled in browse page file display (`split(/[\\/]/)`)
- Unnecessary `Record<string, any>` type assertion removed from browse page config access

## [v0.3.2-alpha] - 2026-05-01

### Added

- API token authentication with bearer tokens (jv_ prefix, SHA-256 hash storage, one-time display)
- Token CRUD REST endpoints: POST/GET/DELETE /api/v1/tokens, POST /api/v1/tokens/:id/regenerate
- `requireTokenOrSession` middleware coexisting with existing session/cookie auth
- `javinizer token create/revoke/list` CLI subcommands with `--json` output
- API Tokens section in web UI settings with create, revoke, and regenerate flows
- TokenDisplayModal with security warning, copy-to-clipboard, and one-time display pattern
- Rate limiting on token write endpoints (create, revoke, regenerate)

### Fixed

- MediaInfo OOM issues — use mp4.DecModeLazyMdat to skip mdat data in MP4/MOV parsing, add 16MB element size cap in EBML reader, fix EBML readVintSize mask bug for lengths 3-6
- Replace ebml-go with manual EBML parser and add mp4_fallback.go for manual ISOBMFF parsing when mp4ff fails
- Remove FLV support (flv.go, flv_test.go)
- TokenService.Validate() now uses synchronous UpdateLastUsed matching middleware behavior
- Token CRUD endpoints moved to writeProtected group with IP rate limiting

## [v0.3.1-alpha] - 2026-04-30

### Added

- Word replacement (uncensor) system with database-backed replacements and API endpoints
- Import/export API endpoints for genres, actresses, and word replacements
- Frontend types and API client methods for import/export
- Import/export UI to genres, words, and actresses pages
- CLI word command with list/add/remove/export/import subcommands
- Import/export subcommands to genre and actress CLI commands
- Playwright e2e test infrastructure
- E2e tests for import/export with fixtures
- E2e auth mode with rate limit bypass
- E2e tests for import/export across all three features
- Support both id and original query params for genre/word deletion endpoints
- Swagger annotations added to all API handlers
- golangci-lint config expanded with custom rules
- govulncheck added to CI pipeline
- Frontend tests included in CI pipeline

### Fixed

- R18.dev scraper reliability — rental ID handling, direct URL fallback, alternate content IDs, nil guards, regex dedup
- DMM scraper hardening — priority scaling, cover extraction, proxy auth, JSON parsing, nil guards
- Replace remaining native confirm() with confirmDialog
- Hide Review & Organize button when no files completed successfully
- Address code review findings on import/export and Upsert paths
- TypeScript type errors in e2e tests
- SQLite lock detection — add string-based fallback for database is locked errors in retryOnLocked
- E2e runner port check to only match LISTEN state
- Export endpoints to use GET instead of POST
- defer fileCancel() in for-loop context leak
- initBatchDependencies error handling
- Debug log artifact removed from production logging
- TypeScript type for original_should_crop_poster uses `boolean | null` matching Go `*bool`
- context.Background() replaced with caller context in scraper GetURL wrappers
- Scraper GetURL method naming normalized
- Decomposed batch functions use consistent error wrapping
- saveScrapedResult returns Upsert errors to callers
- Frontend store errors surface to users via toast/notification
- Retry loops use context-aware sleep
- applyDisplayTitle exists in single shared location
- NFO discovery logic extracted into shared helper
- Duplicate normalize* functions consolidated into shared scraperutil helpers
- Duplicate FlareSolverrConfig unified into single definition
- Unused `_ = db` parameter removed from 11 scraper module.go Config() methods

### Changed

- Switch genre/word replacement deletion from original-key to ID-based (both id and original params supported)
- Gitignore Playwright test artifacts (test-results/, auth-state.json)
- All `any` types replaced with proper typed interfaces
- settings/+page.svelte split into focused sub-components
- review/[jobId]/+page.svelte split into focused sub-components
- actresses/+page.svelte split into focused sub-components
- Debug console.log statements removed from production code
- Large files (dmm.go, translation/service.go, aggregator.go) split into focused files
- RunBatchScrapeOnce, processUpdateMode, processOrganizeJob, processBatchJob decomposed into focused sub-functions

## [v0.3.0-alpha] - 2026-04-29

### Added

- StandardModule base struct and BaseScraperConfig eliminating ~2,150 lines of module.go boilerplate across 14 scrapers
- ValidateCommonSettings shared validation function replacing 14 identical validation blocks
- NewScraperHTTPClient and InitScraperClient helpers replacing 14 per-scraper httpclient.go files
- BaseRepository[T, ID] generic struct with CRUD methods for 12 database repositories
- ResolveNFOPath/FindNFOFile shared helpers replacing triplicated NFO path discovery logic
- FormatActressName package-level function consolidating duplicated implementations
- core.ParsePagination helper replacing 4 duplicated limit/offset parsing implementations
- toHistoryRecord and paginateAndConvert helpers eliminating 4x copy-pasted conversion blocks
- Svelte-query QueryClientProvider with SSR-safe lazy client module
- Poster-from-url, exclude-movie, and save-edits mutations using createMutation
- Shared query helpers for config and scrapers with cache deduplication
- createBatchJobPollingQuery helper with refetchInterval for polling components
- Reactive actress list query with CRUD mutations and merge flow
- Dark mode with class-based toggle and styling across all pages
- Grid view for review page with ReviewGridCard and viewMode toggle
- Use-as-poster button for screenshots in review page
- Favicon for web frontend
- unknown_actress_mode config (skip by default, fallback for placeholder)
- Use-as-poster backend with poster generation, reset, and cache-busting
- Shift-click range selection for files and persistent recursive checkbox
- Translation warnings propagated to frontend UI
- BaseFileName in OrganizePlan, MaxPathLength enabled in preview
- Auto-switch operation mode to 'Rename file only' when destination matches source path with empty folder/subfolder format

### Fixed

- Recursive chown on /javinizer for Unraid compatibility — fixes pre-existing root-owned files from prior versions
- Convert javstash runtime from seconds to minutes
- JavLibrary search result parsing: handle current HTML format with videothumblist divs, multiline HTML, attribute-order independence
- JavLibrary double language segment in URL construction when legacy pattern returns /en/?v=...
- JavLibrary over-broad cover-screenshot filter that removed all screenshots
- FlareSolverr proxy bypass in direct mode — removed fallback that overrode empty proxyProfile
- URL encoding for query parameters in GetURL/ScrapeURL
- Missing template tags and YEAR/Translations data loss
- Template structure preservation during MaxPathLength truncation
- Truncated path names use ~ instead of ... with improved in-place preview path display
- Umask respected in file/directory permissions for Docker group-write support
- MGStage prefixed IDs (GANA-2850 → 200GANA-2850) and hyphenated ID format for search queries
- Actresses matching unknown_actress_text filtered from scraper results
- Stale actress/genre associations cleared when upserting with empty lists
- Global scraper priority merged as fallback when per-field overrides exclude sources
- Actress name keys normalized in aggregator and batch jobs cancelled when all movies excluded
- DMM-resolved ContentID propagated as fallback with diagnostic logging
- Operation_mode forwarded in organize request
- Organizer regression: copyOnly path, subtitle handling, truncation guards
- OOM issue #13: reduced memory in crop/placeholder/dimension reads, persist poster crop state
- Output preview refreshed when movie fields are edited on review page
- Genre replacement DELETE uses query param to handle special characters
- Local state used instead of direct onUpdate for Use as Poster
- Live R18.dev test skips on 403 instead of failing
- Direct proxy mode does not leak global proxy to FlareSolverr
- Inherit proxy mode passes global proxy to FlareSolverr

### Changed

- All 14 scrapers migrated to shared infrastructure (StandardModule, BaseScraperConfig, shared HTTP client)
- All frontend pages migrated from manual fetch + $state patterns to TanStack svelte-query
- MoveToFolder/RenameFolderInPlace removed from OutputConfig, API contracts, and frontend
- Deprecated merge_strategy removed from NFOComparisonRequest API contracts and Swagger
- Deprecated MergeMovieMetadata() and ParseMergeStrategy() functions removed
- No-op validateNoLegacyProxyDirectFields() stub removed, rejectUnknownProxyFields() wired
- Stale artifacts deleted: coverage files, root binaries, orphaned testdata, stale docs
- Preview generation refactored to use OperationStrategy.Plan()
- 86 files changed, +3,795/-1,598 lines

## [v0.2.11-alpha] - 2026-04-28

### Added

- Persist file browser sort preference across navigation within session
- Use '...' truncation marker with '~' fallback for trailing dots

### Fixed

- Prevent blank file on Windows when src==dst and harden preview/organizer edge cases
- Windows mixed slashes in preview and empty folder format creating unwanted subfolders

## [v0.2.10-alpha] - 2026-04-27

### Added

- Client-side pagination to FileBrowser
- Pagination controls above file list in FileBrowser
- Allow Docker bridge access to /auth/setup via configurable trusted CIDRs
- GitHub issue templates for bug reports, feature requests, and scraper issues

### Fixed

- Allow same-origin WebSocket and CORS when AllowedOrigins is configured
- Remove user directive from docker-compose to enable entrypoint privilege bootstrap
- Add Docker defaults for setup CIDRs and fix bind mount ownership
- Resolve AP-288 404 from r18.dev by accepting blank dvd_id with validated content_id fallback
- Add TokyoHot short-prefix ID matching and search query resolution

## [v0.2.9-alpha] - 2026-04-22

### Fixed

- Apply environment variable overrides (DEEPL_API_KEY, OPENAI_API_KEY, etc.) before config validation in `LoadOrCreate()`, preventing "api_key is required" errors when keys are set via env vars but empty in config file- Persist per-field scraper priorities to config file and add scrollbar to priority modal- Clean `web/dist` before `git checkout` to remove stale build artifacts- Update `with_embedded_web.sh` restore_placeholder to use `git checkout`- Add `ACTRESS` singular tag and fix `ACTORNAME` to resolve from actress data instead of movie title- Add `subfolder_path` to organize preview response and improve cross-platform compatibility- Add cross-device move fallback to file organizer

### Changed

- Switch nightly releases to commit-hash tagging scheme- Remove duplicated `web/placeholder` dir, use `git checkout` in Makefile restore target

## [v0.2.8-alpha] - 2026-04-19

### Added

- Windows CI test runner for path-specific bug detection- `fsPath()` helper in `internal/history/reverter.go` that normalizes paths for afero MemMapFs (forward-slash + drive letter stripping)- `filepath.ToSlash()` normalization on `WillMove` path comparisons in organizer strategies to prevent false positives on Windows- `filepath.ToSlash()` normalization on `isDescendant()` path comparisons for cross-platform directory hierarchy checks- Windows volume root detection in `cleanupEmptyDir` termination conditions- `runtime.GOOS == "windows"` skip guards for Unix-only tests (file permissions, shell scripts, `/dev/null`, concurrent file locking)- `FormatActressName` shared helper in `internal/models/movie.go` deduplicating `Actress.FullName()` and `ActressInfo.FullName()` implementations- `ScraperOption` and `ScraperChoice` types moved from `internal/api/contracts` to `internal/models/` with backward-compatible aliases, eliminating reverse dependency where all 14 scrapers imported the API layer- `JobRepositoryInterface.Upsert()` method replacing read-then-write `FindByID` → `Create`/`Update` pattern with single atomic operation- `UpdateRequest` struct for `POST /api/v1/batch/{id}/update` with `force_overwrite`, `preserve_nfo`, `preset`, `scalar_strategy`, `array_strategy`, `skip_nfo`, `skip_download` fields- `skip_nfo` and `skip_download` fields on `OrganizeRequest` for `POST /api/v1/batch/{id}/organize`- Update options UI in review page header (force overwrite, preserve NFO, skip NFO, skip download toggles) with collapsible options panel- Organize options UI in destination settings card (skip NFO, skip download toggles)- Older-than-days cleanup picker on Jobs page with "Clean History" and "Clean Events" buttons and client-side validation- Version check section in ServerSettingsSection: current/latest version display, "Update available" badge, "Check for Updates" button, error state handling- `getVersionStatus()` and `checkVersion()` API client methods- `VersionStatusResponse` TypeScript interface with error field- Server-side validation rejecting `force_overwrite` + `preserve_nfo` as mutually exclusive (returns 400)- `preset` binding validation (`oneof=conservative gap-fill aggressive`)- 1MB request body size cap on update endpoint via `io.LimitReader`

### Fixed

- Windows path separator mismatches in organizer plan tests and batch preview tests (hardcoded `/` vs `\` from `filepath.Join`)- Windows file handle locks preventing `t.TempDir()` cleanup — added `defer CloseLogger()` and `defer db.Close()` in test helpers- Windows `filepath.IsAbs` returning false for `\dest\...` paths (no drive letter) in multipart test- Windows tilde expansion failure in `validateNFOPath` — `filepath.Join("~", ...)` produces `~\...` which doesn't match the `~/` prefix check- Windows double-slash in database error messages — normalized with `strings.ReplaceAll("//", "/")` after `filepath.ToSlash`- Windows `WillMove` incorrectly `true` when source/target paths differ only in separator style (production bug in `organizer.go`, `strategy_organize.go`, `strategy_inplace.go`, `strategy_inplace_norenamefolder.go`)- Windows `isDescendant()` failing to detect descendant paths due to separator mismatch- Windows `cleanupEmptyDir` walking past drive root — added `filepath.VolumeName` root detection- Windows concurrent config writer test timing out due to different file locking semantics- Windows `fsPath()` drive-letter check order — check before `filepath.ToSlash()` to avoid dead code- Windows afero MemMapFs path lookup failures in `ReadNFOSnapshot` — use `fsPath()` to strip drive letter and normalize separators- Windows LogDir output using backslash separators — apply `filepath.ToSlash` in `overrides.go`

### Changed

- Javstash scraper `module.go` proxy declaration changed from value type `config.ProxyConfig` to pointer type `*config.ProxyConfig`, matching the pattern used by all other 13 scrapers- `AggregatorOptions` and `Aggregator` struct fields changed from concrete `*database.GenreReplacementRepository`/`*database.ActressAliasRepository` to interface types `database.GenreReplacementRepositoryInterface`/`database.ActressAliasRepositoryInterface`- `processUpdateJob` and `processUpdateMode` now accept `*UpdateOptions` parameter for configurable update behavior- `processOrganizeJob` now accepts `skipNFO` and `skipDownload` parameters- `updateBatchJob` handler now parses optional `UpdateRequest` body (backward compatible with empty body), validates job existence/status before body parsing, and returns 400 for malformed JSON- `persistToDatabase` uses `Upsert` instead of `FindByID` + `Create`/`Update`, eliminating persistence race condition- All 14 scraper module.go files updated to import `models.ScraperOption`/`models.ScraperChoice` instead of `contracts.ScraperOption`/`contracts.ScraperChoice`- Downloader HTTP client creation deferred until actually needed — `skip_download=true` no longer triggers downloader setup, preventing proxy/registry errors on NFO-only updates- `preserve_nfo` now uses `PreserveExisting` merge strategy (not `PreferNFO`) to prevent blanking fields when existing NFO is incomplete- `preserve_nfo` takes final precedence after preset resolution, preventing silent override- DisplayTitle templating runs for ALL update paths (including `force_overwrite`), not just the NFO merge block- Preview `$effect` reactive to skip toggles via `void` references; retry path persists last update options and skip flags- Force Overwrite and Preserve NFO made mutually exclusive in UI via reactive `$effects`- Test databases switched from in-memory shared-cache SQLite to temp file-based SQLite with WAL mode, eliminating `database table is locked` flaky test failures under concurrency- Cross-platform path utility (`path.ts`) with `splitPath`, `buildPathUp`, `buildBreadcrumbPath`, `isRootPath` functions for Windows/Unix path handling- FileBrowser breadcrumb navigation, "go up" button, and path construction now use cross-platform path utility instead of Unix-only logic- OperationRow truncated paths now show 40/60 head-tail split with click-to-expand/collapse- 54 files changed, ~1,192 lines added, ~468 lines removed

## [v0.2.7-alpha] - 2026-04-16

### Added

- Per-IP rate limiting middleware (`internal/api/middleware/ratelimit.go`) for write endpoints using `golang.org/x/time/rate` token bucket- Sort-by whitelist validation returning 400 Bad Request on invalid column names per endpoint- Secure cookie flag support for reverse proxy via `X-Forwarded-Proto` header and `force_secure_cookies` config option- Bootstrap secret env var (`JAVINIZER_SETUP_SECRET`) for `/auth/setup` endpoint protection with local-only fallback- `DrainAndClose` HTTP utility (`internal/httpclient/drain.go`) replacing bare `resp.Body.Close()` on all error paths- JobQueue cleanup goroutine lifecycle with `stopCleanup` channel for graceful shutdown- BatchJob thread-safe accessors (`GetID`, `GetJobStatus`) for concurrent read access- `ErrNotFound` sentinel error (`internal/database/errors.go`) for cache miss distinction from actual database failures- Partial success response for NFO merge operations indicating which fields succeeded or failed- Per-file timeout for `processUpdateJob` with configurable duration bounds (30s–600s)- Job queue `PersistError` field for persistence failure visibility in job status- Database save error wrapping with operation context for debugging- `GetStatusSlim` for lightweight status polling without full movie data payloads- `MovieRepository.Upsert` returning populated `(*Movie, error)` with associations, eliminating extra database query- Template engine injection as shared dependency (`template.Engine`) across organizer, downloader, and job queue- `strings.Fields` replacing character-by-character `splitActressName` concatenation- O(1) scanner extension map lookup replacing linear scan- `DefaultFlattenConfig` and `DefaultFlattenConfigWithRaw` helpers (`internal/scraperutil/flatten.go`) with `FlattenOverrides` struct for all 14 scrapers- Rescrape handler decomposition into focused files: `rescrape_scrape.go`, `rescrape_update.go`, `rescrape_validate.go`, `rescrape_poster.go`- `BatchProcessOptions` and `BatchScrapeOptions` structs replacing positional parameters- `AggregateWithPriority` method on `AggregatorInterface` for priority-based aggregation- `MovieRepositoryInterface.Upsert` updated to return `(*Movie, error)`- Genre replacement CRUD API at `/api/v1/genres/replacements/` with list, create (idempotent), and delete endpoints- `GenreReplacementsSection` Svelte component in settings page with two-column add/remove table

### Changed

- All 14 scrapers migrated to shared `DefaultFlattenConfig` or `DefaultFlattenConfigWithRaw` helpers, eliminating per-scraper `FlattenFunc` boilerplate- Rescrape handler decomposed from 666-line monolith to 110-line main handler + 8 focused helper functions- Batch job processing uses options structs instead of positional parameters- Mocks regenerated with updated `AggregatorInterface` and `MovieRepositoryInterface` signatures- 146 files changed, ~4,057 lines added, ~2,382 lines removed

### Fixed

- Unauthenticated users cannot create admin accounts via `/auth/setup` without bootstrap secret or local access- Authenticated API endpoints reject excessive requests from a single IP with 429 response- Invalid `sort_by` query parameters rejected with 400 instead of being passed to the database- Session cookies have Secure flag set when request arrives via HTTPS reverse proxy- HTTP response bodies fully drained before close on all error paths — no leaked connections- Job cleanup goroutine stops cleanly when application shuts down- Concurrent access to BatchJob fields passes race detector with no warnings- Download errors for covers, posters, and trailers visible in logs and API responses- Cache miss errors distinguishable from actual database failures in code- Job queue persistence failures visible in job status- Review page explicitly requests full batch data (`include_data=true`) to prevent blank editor- Slim polling by default for `BackgroundJobIndicator` and `ProgressModal` — avoids unnecessary payload overhead- Genre replacement POST/DELETE routes under rate-limited `writeProtected` group- `GetStatusSlim` deep-copies `FieldSources` and `ActressSources` maps to prevent shared mutable state- Preview effect gated during organize polling to avoid redundant `/preview` API calls

### Removed

- `normalizeJSONLDImageURL` dead code from `internal/scraper/dmm/jsonld.go`- Ineffective first loop from `extractDescriptionNewSite` in `internal/scraper/dmm/video_dmm.go`

### Security

- Rate limiting protects write endpoints (scrape, batch, proxy, auth, genre mutations) from per-IP abuse- Sort-by whitelist prevents SQL injection via query parameters- Bootstrap secret prevents first-arriver takeover of `/auth/setup`- Secure cookie flag prevents session cookie leakage over HTTP behind reverse proxy

## [v0.2.6-alpha] - 2026-04-16

### Added

- SSRF protection package (`internal/ssrf`) with `NewSSRFSafeClient()`, `WrapTransportWithSSRFCheck()`, and `CheckRedirect()` validation blocking private/loopback/link-local IPs- Typed scraper error model (`models.ScraperError`) with categorized error kinds (network, parsing, not-found, rate-limit, auth, timeout, context-cancelled)- Config redaction utility (`internal/config/redact.go`) for safe logging of sensitive fields (API keys, passwords, tokens)- Panic recovery middleware for batch processing with structured error reporting- Job queue improvements: context-aware cancellation, improved state transitions, structured error aggregation- Batch query support for movie repository (`FindMoviesByIDs`, `FindMoviesByContentIDs`) reducing N+1 database queries- Translation service typed errors with retry classification- Panic recovery tests for batch execute pipeline

### Changed

- Context propagation threaded through all 14 scrapers: `.SetContext(ctx)` on every resty request in ctx-aware methods- Context threaded through full DMM actress thumbnail chain: `parseHTML` → `extractActresses` → `extractActressFromLink` → `tryActressThumbURLs` → `extractRomajiVariantsFromActressPageCtx`- Context threaded through JavDB `Search` retry and `ScrapeURL` paths via `fetchPageDirectCtx`- Context threaded through DMM `FetchWithBrowser` as chromedp parent context- Context threaded through `DownloadMediaFiles` → `DownloadAll` chain- Aggregator simplified with typed scraper errors replacing ad-hoc error classification- Worker pool and scraper task pipeline refactored for structured error handling- Downloader retry logic improved with per-error-kind backoff strategies- Temp API handlers now use `ssrf.NewSSRFSafeClient()` instead of raw `http.Client`- Proxy test client uses `resty.NoRedirectPolicy()` to prevent open-redirect SSRF- Removed unused context-free wrapper functions (`fetchPageDirect`, `extractRomajiVariantsFromActressPage`, etc.)- 135 files changed, ~2,659 lines added, ~1,265 lines removed

### Fixed

- SSRF redirect bypass: proxy test and temp API handlers now validate redirect destinations against internal IPs- Scraper context cancellation gaps: all scraper HTTP requests now respect caller context for proper timeout/cancel propagation- DMM actress thumbnail fallback now cancellable (previously used `context.Background()` for romaji lookup and HEAD probes)- JavDB ScrapeURL retry path now respects caller context instead of spawning untracked requests- Batch organize goroutine immediately cancelled due to deriving context from `c.Request.Context()` instead of `context.Background()`

### Security

- SSRF hardening: `NewSSRFSafeClient()` blocks connections to loopback, private, and link-local IP ranges (prevents cloud metadata credential exfiltration via `169.254.169.254` and internal service access)- SSRF redirect validation: `CheckRedirect()` blocks HTTP redirects to internal IP addresses- Config redaction prevents API keys and tokens from leaking into logs

## [v0.2.5-alpha] - 2026-04-14

### Added

- Database repository layer extracted into focused repos: `movie_repo`, `actress_repo`, `actress_alias_repo`, `genre_repo`, `genre_replacement_repo`, `movie_tag_repo`, `movie_translation_repo`, `event_repo`, `batch_file_operation_repo`, `history_repo`- Database helpers package with `InTransaction()` wrapper and common query builders- Scraper config validation tests for all 12 configurable scrapers- Shared scraper utility helpers (`internal/scraperutil/helpers.go`) for common extraction patterns- Aggregator priority tests for field resolution ordering- Organizer strategy tests for all operation modes- NFO generator and merger unit tests- MediaInfo extended tests: AVI/RIFF parser, MKV, MP4 with edge cases- Worker pool error classification tests and poster cache tests- Batch revert check tests and lifecycle extra tests

### Changed

- Monolithic `database.go` (~1,436 lines) decomposed into 10 focused repository files- All 14 scraper `Search`/`ScrapeURL` methods refactored for consistent error handling and config-driven behavior- Jav321 scraper restructured with improved HTML parsing reliability- Worker pool improved with structured error wrapping- Test coverage increased (67 files changed, ~4,829 lines added, ~2,153 lines removed)

### Fixed

- Aventertainment, DLGetchu, Jav321, JavBus, JavDB, LibreDMM, MGStage, R18Dev, TokyoHot scraper config and edge-case bugs- DMM JSON-LD parsing and video.dmm.co.jp extraction robustness- FC2 and Caribbeancom scraper config handling- Worker pool error reporting for concurrent scrape failures

## [v0.2.4-alpha] - 2026-04-12

### Added

- 5-mode OperationMode enum (organize, in-place, in-place-norenamefolder, metadata-only, preview) with strategy pattern- Auto-migration from legacy `MoveToFolder`/`RenameFolderInPlace` boolean flags to OperationMode in config- OperationMode wired through full API stack with 4-mode frontend selector- `LooksLikeTemplatedTitle()` with UTF-8 safe rune-based detection for double-templating prevention- NFOTitle field to ParseResult for future NFO preservation logic- Regression tests for double-templating and display title edge cases- `internal/types/operation_mode.go` package with validation and parsing- Config pipeline system for structured migration paths- Operation mode tests across organizer, config, API, and worker packages

### Changed

- Renamed `display_name` to `display_title` across Go backend and TypeScript frontend- DisplayTitle is now the canonical editable field with aggregator always setting it- DisplayTitle handling simplified: always regenerate from template with fallback to Title- Preview mode removed from frontend UI (kept in backend API)- Strategy pattern replaces monolithic Organizer with separate strategies per operation mode- Database migration 000003 for column rename (display_name → display_title)- 123 files changed, ~6,665 lines added, ~988 lines removed

### Fixed

- NFO and media generation for in-place and metadata-only modes (ShouldGenerateMetadata)- History logging for metadata-only and in-place modes- Preview missing screenshots for metadata-only mode- Date clearing now emits undefined instead of empty string for `*time.Time` fields- Date formatting guards against invalid dates- DisplayTitle not regenerated when user edits Title — now always recomputed from template

## [v0.2.3-alpha] - 2026-04-10

### Added

- DMM placeholder detection with hash-based filtering for "now_printing.jpg" screenshots- Shared placeholder detection package (`internal/scraper/image/placeholder`) for multi-scraper reuse- Config-driven placeholder filtering opt-in via `ScraperSettings.Extra`- Default placeholder hashes for DMM CDN images- Collapsible info banner in Web UI explaining screenshot filtering behavior- Runtime config drift detection script (`scripts/validate-config-sync.sh`) with multiline struct support

### Changed

- r18dev and libredmm scrapers now use shared placeholder detection package- Test coverage increased to 76.02% (from 75.97%)

### Fixed

- DMM scraper config drift: hardcoded Timeout=30, RetryCount=3, RateLimit=0 now correctly use settings values- DMM scraper fallback HTTP client now preserves Proxy and DownloadProxy settings- Placeholder detection early return bug that skipped ALL filtering when hashes empty- Size-based placeholder detection now works independently of hash matching- Aggregator fallback to r18dev/libredmm with unfiltered placeholders resolved

### Security

- Path validation TOCTOU vulnerability resolved- Rate limiter cancellation under contention fixed

## [v0.2.2-alpha] - 2026-04-09

### Added

- Unified scraper scaffolding across all 14 scrapers with 86% reduction in registration boilerplate- HTTP Client Builder pattern eliminating ~560 lines of duplicated code- Declarative scraper registration system (reduced from 98 to 14 registration calls)

### Changed

- Consolidated scraper platform architecture for easier maintenance and extension- Test coverage increased to 75.97% (from 67.4%)

## [v0.2.1-alpha] - 2026-04-09

### Added

- JavStash scraper for Stash-Box GraphQL API integration- Clear All Jobs button with confirmation dialog on jobs page- Status filter and visual grouping on jobs page- Log rotation and improved logging configuration- DirectURLScraper interface for all scrapers supporting direct URL scraping

### Changed

- Refactored rate limiting to shared thread-safe package for consistent throttling- Reorganized Browser Settings UI section with subsections for clarity

### Fixed

- Security vulnerabilities from code review (rate limiter rollback bug, path validation TOCTOU, scanner TOCTOU, job queue deadlock)- Job state machine for organization retry workflow- Temp poster cleanup moved from organization to job dismissal- Chrome crashpad handler error in Docker container- Log file creation and permissions issues in Docker- Job poster persistence after rescrape- Frontend manual search rescrape using correct movie ID- Domain boundary checks in multiple scrapers (javbus, r18dev, javdb, caribbeancom)- Race conditions and edge cases in rescrape functionality

## [v0.2.0-alpha] - 2026-04-05

### Added

- Multi-language template tags support (e.g., `<TITLE:EN>`, `<TITLE:JA|EN>`)- Language-specific fields for R18.dev API (EN/JA)- Job persistence to database for batch operations- Auto-archive cleanup goroutine in JobQueue- Persistent destination path in jobs- Jobs page redesign with job cards and temp poster persistence- OpenAI Compatible and Anthropic translation providers- Extended model discovery for new translation providers- Hash-based cache invalidation for translations (settings_hash)- Remember-me sessions for authentication- OpenAI-compatible thinking toggle for translations- Configurable temp directory for poster files- Scraper plugin system with unified config architecture- Configuration migration system- Browser automation settings UI- Letter-pattern multipart file discovery

### Changed

- Database migrations squashed to single baseline with hash tracking- Renamed SystemConfig fields for clarity- Translation configuration provider value standardized to `openai-compatible`- Frontend scraper options disabled when global switches are off

### Fixed

- R18.dev API translations populated for both EN and JA languages- Invalid language specs handled with base field fallback- Destination field included in GetStatus snapshot- Svelte 5 runes mode compatibility for dynamic components- Navigation to /jobs when all movies excluded in review- Job card layout and poster thumbnail centering- Preserve multipart metadata for letter-pattern files- Multipart move conflict for letter-pattern files- Preserve multipart metadata in rescrape endpoint- Translation JSON array parsing with conversational text handling- WebSocket origin validation hardened (removed wildcard support)- Poster path generation only when DownloadPoster enabled- Organize preview respects NFO/media download settings

## [v0.1.5-alpha] - 2026-03-30

### Fixed

- Config round-trip: YAML/JSON save/load now preserves all scraper-specific fields- FlareSolverr block preserved across config cycles- DeepCopy() prevents mutation leaks between DefaultConfig() and global registry- JavLibrary FlareSolverr client only initializes when enabled; nil proxy handled safely- Translation ordering: buildTranslations() called after field aggregation- Registry validation: fail-fast on malformed scraper config blocks, unknown fields disallowed- API key validation in translation config

## [v0.1.4-alpha] - 2026-03-30

### Changed

- Code reorganization: config.go split into 7 focused files (~1968 lines reorganized)- DMM helpers extracted to dedicated utilities (-482 lines)- Database utilities extracted (-402 lines)- Aggregator utilities extracted (-153 lines)- FlareSolverr config restructured from proxy to scrapers level for cleaner architecture

## [v0.1.2-alpha] - 2026-03-17

### Added

- Web UI embedded in binary for single-binary distribution- `web` command alias for unified API/web server entrypoint

### Changed

- CI Node.js version bumped to 22 for builds

### Fixed

- Web assets bundled in CI binaries- API and web usage clarified in documentation

## [v0.1.1-alpha] - 2026-03-17

### Added

- R18.dev language option support (en/ja)- GHCR Docker images with version-first tags

### Changed

- Config profile inheritance for cleaner configuration- Legacy proxy fields removed in favor of profile-based approach

## [v0.1.0-alpha] - 2026-03-16

### Added

- **Multi-source scraping**: R18.dev, DMM/Fanza, JavLibrary, JavDB, JavBus, Jav321, LibreDMM, MGStage, TokyoHot, AVEntertainment, DLGetchu, Caribbeancom, FC2 scrapers- **Smart file organization**: Rename and organize files/folders using configurable templates- **Dry-run preview**: Full preview before making any changes- **NFO generation**: Kodi/Plex-compatible metadata files- **Media downloads**: Cover, poster, fanart, trailer, and actress image downloads- **Multiple interfaces**: CLI, interactive TUI (Bubble Tea), REST API, and web UI (SvelteKit)- **Interactive TUI**: Browse and scrape files with real-time progress display- **Tag system**: Per-movie custom tags stored in database- **Genre management**: Genre replacement rules with CLI commands- **History tracking**: File organization operation history with rollback support- **HTTP/SOCKS5 proxy support**: For all network requests including chromedp- **MediaInfo integration**: Video format probing with AVI/RIFF and FLV parsers, CLI fallback- **Actress alias system**: Alternative names mapping- **Template system**: Folder/file naming with conditional logic and multi-part support- **Docker deployment**: Container with user/group mapping, environment variable support- **Authentication**: Single-user auth with setup flow and secured sessions- **API documentation**: Scalar UI and Swagger UI at /docs and /swagger- **WebSocket progress**: Real-time progress streaming for batch operations- **Configurable umask**: File permission control- **Environment variables**: JAVINIZER_* overrides for config, database, logging, temp directory- **Amateur video scraping**: DMM support for amateur content- **Actress thumbnail extraction**: From DMM streaming pages- **Poster quality detection**: Intelligent cropping for DMM and R18Dev- **Chromium support**: In Docker for headless browser scraping

### Security

- Path traversal protection for API endpoints- CORS origin validation- Directory traversal prevention- SQL injection prevention- Header injection and path traversal sanitization in frontend

[v1.6.3]: https://github.com/javinizer/javinizer-go/compare/v1.6.2...v1.6.3
[v1.6.2]: https://github.com/javinizer/javinizer-go/compare/v1.6.1...v1.6.2