Skip to content

codex-v2#782

Merged
ajslater merged 344 commits into
mainfrom
develop
Jun 18, 2026
Merged

codex-v2#782
ajslater merged 344 commits into
mainfrom
develop

Conversation

@ajslater

@ajslater ajslater commented Jun 18, 2026

Copy link
Copy Markdown
Owner
  • Notice
    • This is a major upgrade. A one-time database migration runs on first
      startup; back up your config directory before upgrading.
    • Editing tags writes to your comic files; the comics directory must be
      mounted writable with write permission for tag editing to work.
  • Breaking Changes
    • Admin settings (SMTP, rate limits, browser page size, cover upload size)
      moved from codex.toml into the Admin UI and are now editable without a
      restart. Existing values are imported automatically on upgrade; those
      codex.toml sections are deprecated.
    • Custom covers are now managed in the web UI. Legacy filesystem covers
      (in-library .codex-cover.* files and the covers-only library) migrate
      automatically on first startup.
    • The browser and reader page URLs changed; bookmarks to specific pages may
      need re-navigating from the home screen. OPDS apps reconnect on their own.
    • The HTTP API moved from /api/v3/ to /api/v4/.
  • Fixes
    • OPDS 1.2, 2.0, and OpenSearch feeds are now spec-compliant.
    • Folder covers respect favorites.
    • Critical ratings normalized to a consistent 0–5 scale.
    • The age-rating "As Tagged" panel hides when it has no entries.
    • Hovering a comic's tag icon no longer re-runs the on-demand tag importer
      forever on comics with few or no embedded tags.
    • Browser refreshes more often when comics change. container restarts.
  • Features
    • Edit the tags on one or many comics directly in the browser — credits,
      story arcs, identifiers, and more — written back to your comic files.
    • Online tagging: look up and apply metadata from online sources, with
      interactive match prompts, rate-limit display, and per-source credentials
      in the new Admin Tagging tab. Or tag a single comic directly by a known
      Metron or Comic Vine issue id or URL, skipping the search.
    • Upload, replace, and remove custom covers for any group from the web UI,
      plus a Custom Covers admin tab.
    • Back up and restore all user data — accounts, bookmarks, favorites,
      settings, libraries — via a user_data.sqlite sidecar, the Admin Restore
      tab, or codex restore_user_data. Snapshotted nightly.
    • Optional self-service password reset, and email verification for new
      sign-ups (both require SMTP).
    • New user Profile dialog for self-service username, email, and API token
      (moved here from the sidebar).
    • Database and user-data backups are now compressed, dated, and auto-pruned.
    • Redesigned admin panel has moves settings under relevant tabs.
  • Performance
    • Library imports are faster: forced re-imports run over 20x faster, fresh
      imports almost 4x, and polls that find nothing changed are now nearly
      instant — no more rewriting every comic, regenerating every cover, and
      refreshing every browser on a no-op poll.
    • Browsing large libraries is faster: table, search, and sorted folder views
      that could take minutes now load in about a second, metadata works on
      collections of any size, and browsing stays responsive during imports.

ajslater added 30 commits April 10, 2026 00:49
    Fix clear settings null bug, add global settings clear button

    - clearComicSettings was setting book.settings to null, causing
      Object.entries() to throw TypeError downstream in getBookSettings
    - Add null guard in getBookSettings as defense-in-depth
    - Add null guard in isClearDisabled computed
    - Add clearGlobalSettings action and clear button to Default Settings panel
    - Compare against READER_DEFAULTS to determine if global clear is disabled
ajslater and others added 29 commits May 20, 2026 23:19
vite-plugin-dynamic-base 1.4.1 dropped the leading `/` it used to add
inside template-element replacements. The codex publicPath stripped
APP_PATH's leading slash with `.substring(1)` to avoid a double `/`
with the old behavior; under 1.4.1 the strip made chunk URLs
relative, so deep routes like /admin/libraries fetched chunks from
/admin/static/... and got HTML from the Django catch-all, breaking
the admin panel and any lazy-loaded route.

Bump version to 1.12.6 and add news entry.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
a709a74 added a "." prefix to _IGNORED_BASENAME_PREFIXES so the
poller's walker, the watchfiles filter, and expand_dir_added all
skip hidden files before any cover predicate runs. User-supplied
folder covers named .codex-cover.jpg / .png / .webp / ... are
dotfiles by name but legitimate covers, so the dotfile filter
swallowed them and broke custom folder covers from v1.12.5 on.

is_ignored_basename now exempts a basename when match_folder_cover
claims it. .DS_Store, .git, .Trashes, .codex-cover (no extension),
.codex-cover.txt etc. still get filtered.

Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
DRF's ``SessionAuthentication`` enforces CSRF on unsafe methods, which
rejects proxy-authenticated API clients that legitimately carry no CSRF
token. Add ``HttpRemoteUserAuthentication`` (subclass of DRF's stock
``RemoteUserAuthentication`` reading ``HTTP_REMOTE_USER`` instead of
``REMOTE_USER``) and conditionally prepend it to
``DEFAULT_AUTHENTICATION_CLASSES`` when ``CODEX_AUTH_REMOTE_USER`` is
enabled, so proxy-forwarded ``Remote-User`` API requests authenticate
through the existing ``RemoteUserBackend`` without hitting CSRF.

Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
…vers

Vuetify 4's v-dialog defaults to location 'center center', which activates
the connected overlay location strategy. That strategy caps width with
parseFloat(props.maxWidth), so "20em" parses to 20 and the em is dropped,
collapsing dialogs to a ~20px sliver. Convert every em-based max-width/
min-width on a v-dialog (or forwarded via $attrs) to unitless px at 16px/em.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
The UNREAD filter used Q(bookmark=None), a multi-valued relationship
test for "comic has no bookmark from anyone" rather than "no bookmark
for me". Once any user finished a comic it dropped out of every other
user's (and anonymous visitors') unread view. UNREAD now negates the
per-user finished predicate (~(my_filter & finished=True)), compiling
to a per-user NOT-EXISTS subquery.

Also harden get_my_bookmark_filter: an anonymous visitor with no
established session_key resolved to `session_id IS NULL`, which matches
every authenticated user's bookmarks. Return a match-nothing filter
instead; a session key is minted only when a bookmark is written.

Adds tests/test_bookmark_filter_isolation.py covering cross-user and
anonymous isolation for READ/UNREAD/IN_PROGRESS.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Replace a stale `ty: ignore[no-matching-overload]` with an isinstance
guard so `settings` is a Mapping before `_copy_params_into`, clearing
the `invalid-argument-type` diagnostic from `make ty`.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Skipping super() left the class-level atomic from setUpTestData
uncommitted-but-unrolled-back, leaking the codex_init() "admin"
superuser into later test classes and causing UNIQUE constraint
failures (e.g. test_bookmark_filter_isolation) in full-suite runs.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
@ajslater ajslater merged commit ed3a36d into main Jun 18, 2026
4 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