diff --git a/.grype.yaml b/.grype.yaml index 22b61b88..0ef4aabf 100644 --- a/.grype.yaml +++ b/.grype.yaml @@ -13,6 +13,32 @@ # stable Python 3.14 or Debian 13 packages become available upstream. ignore: + # Renewed by Adam Hernandez on 2026-09-14 only for this DHI libc6 revision. + # Accepted risk, NOT a fix: Debian 13 still lists this TSIG-printing issue + # as vulnerable/no-DSA. Direct Pullbox callers were not found, but dependency + # reachability and DHI backport status remain unproven. Re-review by + # 2026-09-30 or the next base refresh, whichever comes first; remove when + # a fixed stable package ships. All other High findings remain blocking. + # https://security-tracker.debian.org/tracker/CVE-2026-5435 + - vulnerability: CVE-2026-5435 + package: + name: libc6 + version: 2.41-12+deb13u4+dhi0 + type: deb + + # Approved by Adam Hernandez on 2026-09-15 for this exact runtime revision. + # Accepted risk, NOT a fix: strfmon/strfmon_l right-padding buffer overflow. + # Debian 13 lists this as vulnerable/no-DSA with no fixed stable package. + # No direct Pullbox callers were found; dependency reachability remains unproven. + # Re-review by 2026-09-30 or the next base refresh, whichever comes first; + # remove when a fixed stable package ships. All other High findings block. + # https://security-tracker.debian.org/tracker/CVE-2026-19499 + - vulnerability: CVE-2026-19499 + package: + name: libc6 + version: 2.41-12+deb13u4+dhi0 + type: deb + # Renewed by Adam Hernandez on 2026-09-13 for eight exact findings in the # refreshed DHI runtime. These are accepted-risk exceptions, NOT fixes. # Keep all other High findings blocking, including other package versions. diff --git a/CHANGELOG.md b/CHANGELOG.md index b8948cfa..4390a1b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.3.0] - 2026-09-15 + +Minor release adding Story Arc management, an optional local Comic Vine catalog, +multi-root and in-place library imports, and substantial large-library import +performance and recovery improvements. + ### Added - Added an optional local Comic Vine catalog for series searches and import @@ -25,6 +31,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 user-owned arc references. - Added category-scoped bulk import safety review with bounded previews and audit evidence. +- Added a dedicated import Follow-up workspace for remaining matching, recovery, + and cleanup decisions without restarting a completed import. +- Added previewed clean-library builds with background progress, configurable + naming and conversion, and explicit safeguards for source files and destinations. +- Added safe removal of disabled library roots with dependency checks before + deleting their configuration. - Added Comic Vine Story Arc discovery, reviewed member ordering, canonical series/issue reuse, provider-change review, and arc-scoped missing-issue search. - Added Mylar in-place adoption and original-filename arc copies with optional @@ -33,8 +45,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added a guarded, manually published signed development-image channel for isolated testing without a general-availability release. +### Changed + +- Grouped Mylar library-access problems by their underlying root and offered + explicit resolution, skip, or detailed repair actions instead of presenting + every affected series as a separate configuration problem. +- Unified Comic Vine series and Story Arc discovery, added a selectable header + Add action, and simplified Story Arc reading-order review and reordering. +- Centralized library naming and Story Arc file policies, including independent + permissions for referenced existing files and managed library destinations. + ### Fixed +- Improved completed-import recovery for trusted legacy identities, misplaced + files, and deferred outcomes. Bounded retries preserve successful imports, + revalidate changed sources and approved roots, and resume interrupted work + without losing matching evidence or repeating completed actions. +- Reconciled stale Mylar issue identifiers, renamed files, and unqualified volume + identities when independent evidence proves the target. Mixed folders no longer + require treating every file as belonging to the folder's series. +- Restored actionable recovery controls on completed jobs and kept safety-approved + items, archived history, background activity, and import counters consistent. +- Preserved file ownership and dependent records during in-place adoption and + clean-library execution, and corrected folder imports' reference-root setup. +- Sent torrent metadata through Pullbox to download clients rather than requiring + remote clients to fetch private Prowlarr or indexer download URLs themselves. +- Corrected reader progress display for large compendiums. - Improved Mylar and folder scan throughput with resource-capped archive inspection, batched review inserts, and fewer unnecessary duplicate checks. Corrected current-item scan progress and unknown time estimates, and bounded @@ -105,6 +141,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Performance +- Prioritized visible catalog hydration after import while keeping ComicInfo + writes in separate background work. Improved restart recovery and progress + reporting, and prevented duplicate manual refreshes during initial metadata sync. +- Reduced large-library scan and review overhead with bounded worker budgets, + compact projections, and batched database work. Import, rollback, and hydration + progress now use clearer phase-aware completion and time estimates. - Streamed complete import-review safety summaries using one narrow-field query instead of repeatedly scanning and sorting blocked files for every batch. Category counts, examples, and bulk-approval eligibility remain unchanged. diff --git a/src/pullbox/__init__.py b/src/pullbox/__init__.py index 4e83f1f3..dd412321 100644 --- a/src/pullbox/__init__.py +++ b/src/pullbox/__init__.py @@ -2,7 +2,7 @@ from datetime import UTC, datetime -__version__ = "1.3.0-dev" +__version__ = "1.3.1-dev" # Set once at process start; used by System > About for uptime calculation. STARTED_AT: datetime = datetime.now(UTC) diff --git a/tests/unit/test_local_security_scan_contracts.py b/tests/unit/test_local_security_scan_contracts.py index f7030ed1..5fe4a292 100644 --- a/tests/unit/test_local_security_scan_contracts.py +++ b/tests/unit/test_local_security_scan_contracts.py @@ -152,7 +152,7 @@ def test_approved_glibc_exceptions_are_exact_version_and_package_scoped() -> Non config = yaml.safe_load((ROOT / ".grype.yaml").read_text()) approved_cves = {"CVE-2026-5435", "CVE-2026-5450", "CVE-2026-5928"} entries = [entry for entry in config["ignore"] if entry["vulnerability"] in approved_cves] - assert len(entries) == 19 + assert len(entries) == 20 assert { (entry["vulnerability"], entry["package"]["name"], entry["package"]["version"]) for entry in entries @@ -161,10 +161,51 @@ def test_approved_glibc_exceptions_are_exact_version_and_package_scoped() -> Non for cve in approved_cves for package in ("libc6", "libc6-dev", "libc-dev-bin") for version in ("2.41-12+deb13u3+dhi1", "2.41-12+deb13u3+dhi2") - } | {("CVE-2026-5435", "libc6", "2.41-12+deb13u4")} + } | { + ("CVE-2026-5435", "libc6", "2.41-12+deb13u4"), + ("CVE-2026-5435", "libc6", "2.41-12+deb13u4+dhi0"), + } assert all(entry["package"]["type"] == "deb" for entry in entries) +def test_september_glibc_renewals_cover_only_the_approved_runtime_revision() -> None: + config_text = (ROOT / ".grype.yaml").read_text() + config = yaml.safe_load(config_text) + entries = [ + entry for entry in config["ignore"] if entry["package"]["version"] == "2.41-12+deb13u4+dhi0" + ] + + assert entries == [ + { + "vulnerability": "CVE-2026-5435", + "package": {"name": "libc6", "version": "2.41-12+deb13u4+dhi0", "type": "deb"}, + }, + { + "vulnerability": "CVE-2026-19499", + "package": {"name": "libc6", "version": "2.41-12+deb13u4+dhi0", "type": "deb"}, + }, + ] + assert "Renewed by Adam Hernandez on 2026-09-14" in config_text + assert "2026-09-30" in config_text + assert "NOT a fix" in config_text + + +def test_strfmon_exception_is_limited_to_the_approved_package_and_review_deadline() -> None: + config_text = (ROOT / ".grype.yaml").read_text() + config = yaml.safe_load(config_text) + entries = [entry for entry in config["ignore"] if entry["vulnerability"] == "CVE-2026-19499"] + assert entries == [ + { + "vulnerability": "CVE-2026-19499", + "package": {"name": "libc6", "version": "2.41-12+deb13u4+dhi0", "type": "deb"}, + } + ] + assert "Approved by Adam Hernandez on 2026-09-15" in config_text + assert "strfmon/strfmon_l" in config_text + assert "reachability remains unproven" in config_text + assert "2026-09-30 or the next base refresh, whichever comes first" in config_text + + def test_september_13_dhi_renewal_covers_only_eight_approved_matches() -> None: config_text = (ROOT / ".grype.yaml").read_text() config = yaml.safe_load(config_text)