Conversation
Owner
ajslater
commented
May 10, 2026
- Features
- Fail2Ban support with a dedicated log.
- See README and codex.toml.default
- Fail2Ban support with a dedicated log.
- Fixes
- Comic filename parsing improvements.
* bump news * cirlcle ci no longer handles pre-release * remove alpha scripts for circleci" * fix lint-ci * fix pre-relase gha * fix default last route on start pages * bump version * fix default params * alpha2
…cker (#751) Previously the column picker always appended newly-toggled columns to the end of the order list. This adds canonical-rank-aware insertion: if the existing draft is in strictly-increasing canonical order (the order implicit in `_CATEGORIES`), splice the new column into the unique slot that keeps the sequence sorted. If the user has manually rearranged the draft out of canonical order, fall back to appending so we don't reshuffle their layout. Examples (against the default "p" group `[cover, name, child_count]`): toggle favorite → [cover, favorite, name, child_count] toggle imprint → [cover, imprint_name, name, child_count] toggle publisher → [cover, publisher_name, name, child_count] Covered by 16 new pure-function vitest cases. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
BROWSER_CHOICES is dumped to both browser-choices.json (Vuetify list) and browser-map.json (raw map), but each format is consumed selectively by the frontend. Add per-file include-key frozensets in codex/choices/browser.py and look them up from choices_to_json.py so the generator skips keys the frontend never reads. Removed orphans: - browser-choices.json: IDENTIFIER_SOURCES (frontend uses map form) - browser-map.json: BOOKMARK_FILTER, VUETIFY_NULL_CODE, SETTINGS_GROUP (frontend uses Vuetify form) Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The `.*` glob in `[tool.codespell].skip` matched every walked path
because `os.walk('.')` prefixes paths with `./`, so codespell scanned
nothing during `make lint` while nvim per-file checks still flagged
typos. Replace `.*` with explicit hidden-dir paths, fix the
`/uv.lock` typo, and add legitimate technical terms (wan, crate, iff,
ser, etc.) to ignore-words-list.
Also wire codespell into the frontend lint script so frontend code
gets spell-checked too, and fix one real typo uncovered (secifies →
specifies in opds/v2/progression.py).
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* audit and fix tool ignore/skip configs - fix eslint **/*min.css and **/*min.js globs that over-matched (e.g. admin.css) - fix [tool.vulture] test_results/ -> test-results/ typo - move stray builtin = "clear,code,rare" into [tool.codespell] - fix uv build-backend source-include typos (mkdocks.yml, .circlci/**) and drop dead entries (ci/**, top-level strange.jpg) - remove duplicate "site" in [tool.basedpyright] exclude - drop stale codex/_vendor references from all tool configs - simplify [tool.complexipy] exclude (paths gating made entries unreachable) - drop redundant entries from [tool.ruff] (dist already in defaults) and [tool.djlint] (covered by use_gitignore = true) - normalize codespell skip prefixes; replace bare "coverage" with htmlcov + .coverage*; add *.svg, frontend/src/choices - add coverage, htmlcov, .eslintcache to ESLint base ignores - add comics/* and vulture_ignorelist.py to radon exclude - normalize vulture */X* patterns to **/X so root-level matches work; align ty exclude with basedpyright - delete unused [tool.typos] block Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * update deps * fix remark for claude --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* bump version to alpha * bump news for favorites
* Add optional failed-login log for fail2ban et al. Adds a default-off feature that appends one parseable line per failed credential attempt to a dedicated file, so banning tools (fail2ban, CrowdSec, sshguard) can tail it via regex. Gated end-to-end on `auth.failed_login_log` so disabled deployments pay zero overhead. Hooks `django.contrib.auth.signals.user_login_failed`, which fires for both rest_registration's form login and DRF's BasicAuthentication (OPDS), covering both vectors with one receiver. rest_registration's default authenticator drops `request=`, so a small contextvar middleware stashes the active request to recover the client IP for form logins. XFF trust is configurable for direct-exposed deployments that can't trust the header. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Document failed-login log in README Add env-var references in the Authentication subsection plus a new "Failed-Login Log" section covering line format, XFF trust trade-off, and a worked fail2ban filter + jail example. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A fresh browser visit to Codex probes /api/v3/auth/profile/ before any
session cookie exists, which Django's BaseHandler.get_response logs as
a WARNING ("Forbidden: /api/v3/auth/profile/") for every first-time
visitor. That drowns the main log in routine noise.
Add a logging.Filter on django.request that downgrades records matching
that exact "Forbidden: <path>" pattern to DEBUG, parameterized by a
small frozenset of known-noisy paths so abuse on other endpoints still
surfaces at WARNING.
Also move django.request into the loggers dict where dictConfig will
actually see it — the old top-level placement was silently ignored.
Records still flow to the root loguru handler via propagation.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add not_failed_login_filter and attach it to the stdout / codex.log
sinks so the IP-bearing line is written only to failed_logins.log.
Django's own request logger still emits a bare WARNING for each
failed attempt ("Unauthorized: /api/v3/auth/login/" etc.) so the
failure remains visible in codex.log without exposing the client IP.
Concentrating IP + username in one file makes the privacy story
easier to reason about: one file to chmod, forward to a SIEM, or
retain on its own schedule.
The inverse filter is only attached when the feature is enabled —
when disabled, no records carry the tag and the filter would be a
no-op anyway.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.