Skip to content

Adapt to comicbox 5.3.x: doctor tab, probe() credentials, ask match mode - #968

Merged
ajslater merged 7 commits into
developfrom
comicbox-5.3.0
Oct 7, 2026
Merged

ajslater merged 7 commits into
developfrom
comicbox-5.3.0

Conversation

@ajslater

@ajslater ajslater commented Oct 7, 2026

Copy link
Copy Markdown
Owner

Summary

Adapts codex to comicbox 5.3.0 and 5.3.1 and takes up what they added.

Doctor tab

  • codex/doctor wraps comicbox 5.3's run_checks() (archive tools, PDF, Pillow codecs, comicbox config, package pins) and adds a Codex section: SQLite version, FTS5 and journal mode; config dir free space; one row per library root (missing, unmounted Docker sentinel, unreadable, not writable unless read only, empty); the event watcher's folder count against the Linux inotify limit; and whether the stored tagging credentials still decrypt with the key file.
  • GET /api/v4/admin/doctor returns comicbox's rows and codex's apart; a new admin Doctor tab renders them under their own headings with the verdict as the page heading and a Re-check button. Problems are also logged once at startup, after loguru is configured.
  • comicbox's Online section is left out: codex keeps credentials in its own database and checks them on the Tagging tab.
  • The Docker final stage runs comicbox doctor -q as its smoke test (not exercised in an image build here; CI builds that stage only on deploy).

Scanner keeps every suffix

The scan used to drop .cbr and .pdf when comicbox said the tool was missing. The poller's database snapshot lists every row, so an excluded suffix made every existing CBR or PDF row look deleted the day unrar broke, and 5.3.0's probe test-extracts a member, which fails on more hosts than the path check it replaced. Suffixes now derive from FileTypeEnum, shared with the janitor; an unreadable archive fails its import with comicbox's reason.

Credentials

  • The credential validator uses OnlineSource.probe() instead of hand-rolled mokkari and simyan calls; Metron's goes through comicbox's rate gate and Comic Vine's counts against the real shared bucket.
  • Adopting it exposed that _build_credentials passed an unset Metron key as "". mokkari sends a blank Bearer header for any token that is not None, replacing the username and password, so legacy logins failed on every real run while the old validator passed them. Unset fields are now None.

comicbox 5.3.1: Ask match mode

  • Requires comicbox[pdf]~=5.3.1, whose session accepts MatchMode.ASK with a prompt handler (Accept MatchMode.ASK in OnlineSession when prompts can be resolved comicbox#237).
  • Match modes derive from comicbox's enum on the model (migration 0056 adds ask) and in the UI choices, so Ask, which prompts for every match, is offered in the admin default, the launcher and the start endpoint. The start endpoint now validates the mode.

Smaller

  • Chosen-match replay passes codex's online config so it reads the cache the search filled.
  • The reader imports pdffile lazily behind is_pdf_supported(), so a broken pymupdf disables PDFs instead of failing server start, as comicbox does.
  • make ty was clean of 25 pre-existing diagnostics: ty ignore twins beside existing pyright ignores, one filter(bool, ...) → comprehension, one documented waiver on the stats view's permission override.

Review notes

  • NEWS v2.5.3 carries the user-facing items; the "about 165 MB smaller" line is from the earlier in-image measurement of the numpy/scipy/pywt stack, not a rebuild.
  • Browser-verified against a scratch config dir: the Doctor tab at desktop and phone width, Re-check, and the startup log line.

Verification

  • make lint, make ty: clean
  • Python: 1662 passed, 1 xfailed
  • Frontend: 973 passed

🤖 Generated with Claude Code

ajslater and others added 7 commits October 6, 2026 19:11
…edentials

comicbox 5.3.0 ships a doctor (run_checks) that reports whether the host can
read each archive format, has the image codecs cover matching needs, and
whether its config and package pins are in order, with a fix per problem.
Codex now runs it: problems are logged once at startup after loguru is up,
GET /api/v4/admin/doctor serves the rows, and the admin Jobs tab ends with a
Doctor section with a Re-check button. The Online section is left out
because codex keeps credentials in its own database and checks them on the
Tagging tab. The Docker final stage runs `comicbox doctor -q` as its smoke
test, which proves unrar extracts, pymupdf loads and every pin is satisfied.

The scanner no longer drops .cbr or .pdf when comicbox says the tool is
missing. The poller's database snapshot lists every row, so an excluded
suffix made every existing CBR or PDF row look deleted the day unrar broke,
and 5.3.0's probe test-extracts a member, which fails on more hosts than the
path check it replaced. Suffixes derive from FileTypeEnum, shared with the
janitor; an unreadable archive fails its import with comicbox's reason.

The credential validator uses OnlineSource.probe() instead of hand-rolled
mokkari and simyan calls: Metron's goes through comicbox's rate gate and
Comic Vine's counts against the real shared bucket. Adopting it exposed that
_build_credentials passed an unset Metron key as "", which mokkari turns into
a blank Bearer header that replaces the username and password, so legacy
logins failed on every real run while the old validator passed them. Unset
fields are now None.

Also: the chosen-match replay passes codex's online config so it reads the
cache the search filled; the reader imports pdffile lazily behind
is_pdf_supported() so a broken pymupdf disables PDFs instead of failing
server start, as comicbox does; str() of a StrEnum MatchMode is its value.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Move the Doctor section from the Jobs tab to the top of the Stats tab,
above the Platform readout it extends: Jobs is for actions, and an admin
asking what this install is goes to Stats.

codex/doctor is now a package. checks.py adds a "Codex" section of rows,
in comicbox's row shape so the panel and the startup log treat them alike:

- database: SQLite version, FTS5 (proved with a temp virtual table, since
  not every build records compile options) and the journal mode in effect.
- config dir: writable, with free space; warns under 1 GiB, since the
  database, backups, logs and cover cache all grow there.
- one row per library: missing, the unmounted docker volume sentinel,
  unreadable, not writable unless read only, or empty.
- watcher: Folder rows under event-enabled libraries against the kernel's
  inotify watch limit on Linux, with a sysctl to run on the host.
- credentials: the stored tagging credentials read raw through Cast so the
  field's converter cannot hand back ciphertext, decrypted with the live
  key; a changed key file is otherwise invisible until a run fails.

The view runs the report through channels' database_sync_to_async now
that it queries the database.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The report opened the Stats tab, which is the telemetry preview; a health
report deserves a page of its own. Doctor is the last tab in the bar, at
/admin/doctor. The heading is the verdict, "No problems" or "N problems",
coloured by it, with the host line under it and Re-check on the right, so
the one thing an admin came to read is the first thing on the page. The
Stats tab is as it was.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
comicbox 5.3.1 accepts MatchMode.ASK from a session that has a prompt
handler or defers its prompts, which codex always supplies. Ask auto-writes
nothing and prompts for every match: review everything.

The match modes now derive from comicbox's enum instead of a hand-written
copy, on the model (migration 0056 adds ask to the choices) and in the UI
choices. The start endpoint validates the mode with a ChoiceField, so a
bad one is a 400 here rather than an error inside the librarian. The
launcher and the Tagging tab describe Ask in their hints.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The report carried codex's checks as one more section among comicbox's.
They answer different questions, so the report now keeps them apart:
DoctorReport holds comicbox's rows and codex's rows as two tuples, the API
returns them as two lists, and the tab renders each under its own heading,
comicbox's grouped by section and codex's flat. The table is its own
component so both headings share one look.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
`make ty` runs apart from `make lint`, and 25 diagnostics had collected,
all in code untouched by this branch. Most sit on lines that already waive
the matching pyright rule for the same django-stubs gap (implicit `<fk>_id`
attributes, nullable foreign keys, reverse relations), so they gain the ty
twin. Two are real fixes: the foreign-key query built its field list with
filter(bool, ...), whose signature widens the elements to object, which
values_list refuses; a comprehension keeps the type. The stats view's
permission override cannot satisfy both checkers from a class that inherits
DRF's instance-variable declaration and the admin mixin's ClassVar, so it
waives ty's override rule and says why.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@ajslater
ajslater merged commit c120c28 into develop Oct 7, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant