Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .grype.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
42 changes: 42 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion src/pullbox/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
45 changes: 43 additions & 2 deletions tests/unit/test_local_security_scan_contracts.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down
Loading