Commit Graph
758 Commits
Author SHA1 Message Date
splitsec2 2254e2bf93 refactor: move the proxy-auth and API-key middleware into core/auth_middleware.py (#1641)
Row 8 of the plan in Discussion #1536 is the auth middleware. The API
key `before_request` hook, the proxy auth hook, the hook that strips the
session cookie from API key requests and `_proxy_default_is_admin` move
from `main.py` to `core/auth_middleware.py`, registered with
`register_auth_middleware(app, resolve_auth_mode=..., get_user_db=...)`.

This is the code that decides who a request is, so the first commit adds
41 tests before anything moves. They cover the hook order, the admin
group mapping (comma and pipe delimiters, a custom group header, the
WSGI fallback), proxy header handling in each auth mode, provisioning
once per session, the API key scope (exempt paths, a read only key only
on GET `/api/stats`, a wrong key) and the cookie stripping. They pass on
current `main`. The second commit is the move.

The call is made right after `register_security_headers`, so the
`before_request` and `after_request` order is the same as before. The
existing tests called `proxy_auth_middleware()` and
`api_key_auth_middleware()` on `shelfmark.main` directly, and those
names are gone, so 18 call lines in three test files now find the
registered hook by name through a small helper. No patch targets changed
since the auth mode and user database are still read from `main` at
request time.

The URL map and hook order are identical, and the full suite, ruff and
basedpyright are clean.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

<!-- coderabbit-ai-generated:v1 -->

## Summary by CodeRabbit

* **Authentication**
* API-key authentication supports admin and read-only access, with
read-only keys limited to statistics requests.
* Reverse-proxy authentication recognizes configured identity and group
information, and applies admin access according to the configured role
settings.
* Requests with invalid credentials, missing proxy identities, or
authentication errors receive appropriate error responses.
  * API-key requests no longer retain session cookies.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-11-01 18:50:36 -07:00
splitsec2 384adc4c75 refactor: move the queue routes into core/queue_routes.py (#1637)
Next from the route plan in Discussion #1536 are the queue routes:
status, cancel, retry, priority, reorder, queue order, active downloads,
the local file download and the cover proxy. They move from `main.py` to
`core/queue_routes.py`, registered with `register_queue_routes(app,
login_required, ...)`, and `main.py` is about 600 lines shorter.

The first commit adds 33 tests for what the guardrail tests did not
cover, mostly the local download in each shape, the admin paths, the
validation errors and the failure responses. They pass on current
`main`. The second commit is the move.

`resolve_status_scope` and the request update emitter stay in `main.py`
because the release routes and the request code still use them, so they
come in as parameters, with the user database and the history service as
callables evaluated per request. Two test lines changed: the patches of
`send_file` and of the delivery state sync now point at `queue_routes`,
since that is where they get looked up. Log lines from these routes now
name `shelfmark.core.queue_routes`.

The URL map is identical, all 77 rules. The full suite, ruff and
basedpyright are clean, and I ran the app from the branch and hit
status, queue order, active downloads, the local download and the cover
route, which answer as before. The exception text a few of them return
in a 500 is unchanged, that is for the follow-up on exception text.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
<!-- coderabbit-ai-generated:v1 -->

## Summary by CodeRabbit

* **Improvements**
* Queue status, downloads, and queue controls respect account ownership,
with administrative access retained.
* More specific errors clarify when queue items or files are missing or
unavailable.
* Queue actions support cancellation, retrying, prioritization, and
reordering.
  * Cover requests can use cached images when caching is enabled.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-11-01 18:28:10 -07:00
splitsec2 f06585aa01 refactor: move the secret key, session cookie, security headers and log filter into core/app_setup.py (#1639)
`main.py` also builds the app itself, and this moves the parts of that
which need no route into `core/app_setup.py`: the persisted secret key
and the session cookie settings, the security headers, and the filter
that keeps status polling and the WebSocket upgrade noise out of the
log. It is the app setup item in the plan from Discussion #1536.

The first commit adds 14 tests for them, since none existed: the key
reused, created with mode 600, replaced when too short, and still
returned when the config directory cannot be written, the cookie
settings, the headers on a real response and that a header a route set
itself is kept, and each case the log filter drops or keeps. They pass
on current `main`. The second commit is the move.

The security headers hook is registered from the same spot in `main.py`
as before, so the `after_request` order is unchanged. The secret key
function takes the config directory as a parameter instead of reading
`CONFIG_DIR`, which is the one change in the move, and the key tests
call it with a temp directory.

The URL map and the hook order are identical, and the full suite, ruff
and basedpyright are clean. I also ran the app from the branch: the
secret file is created with mode 600 and the four security headers come
back on a normal response.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
<!-- coderabbit-ai-generated:v1 -->

## Summary by CodeRabbit

* **Bug Fixes**
* Sessions now remain consistent across app restarts, and session
cookies use more protective browser settings, including HTTP-only access
and a seven-day lifetime.
* Responses include baseline security headers while preserving any
headers already set by the app.
* Routine status-polling and connection-upgrade messages are filtered
from application logs, reducing unrelated log noise.
* If saving a session key fails, the app can still start with a
generated key.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-11-01 18:21:49 -07:00
splitsec2 9ca1981d00 refactor: move the Socket.IO handlers into core/socket_handlers.py (#1638)
This one is small. The three Socket.IO handlers, connect, disconnect and
request_status, move from `main.py` to `core/socket_handlers.py`,
registered with `register_socket_handlers(socketio, ...)`. It is the
Socket.IO item in the plan from Discussion #1536.

They had no tests, so the first commit adds 9 that go through
Flask-SocketIO's test client: what a client gets on connect with no
auth, as an admin, as a user and as a visitor with no session, a failure
reading the status, the manual status request, and the room bookkeeping
on disconnect. They pass on current `main`. The second commit is the
move.

`resolve_status_scope` stays in `main.py` since the HTTP routes use it
too, so it is passed in. One test line changed, the patch of
`redact_status`, which now points at the new module. Log lines from the
handlers now name `shelfmark.core.socket_handlers`.

The URL map and the registered socket events are identical before and
after, and the full suite, ruff and basedpyright are clean. I also
started the app from the branch and the Socket.IO handshake answers.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

<!-- coderabbit-ai-generated:v1 -->

## Summary by CodeRabbit

* **Bug Fixes**
* Status requests now return a consistent empty update when access is
denied and an error message when status retrieval fails.
* Status visibility follows the requester’s access level, with non-admin
results redacted.
* **Refactor**
* Connection, disconnection, and status-request handling now follows
consistent room and connection-tracking behavior.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-11-01 18:13:11 -07:00
splitsec2 c6685feba5 fix(docker): drop ffmpeg from the default image; install on demand in Debug mode (#1631)
ffmpeg is in the default image for one thing, the Debug mode screen
recording (`_start_ffmpeg_recording`). Nothing else calls it,
SeleniumBase included, and it brings 93 packages with it. On real builds
that's 406 Trivy findings (149 High) and 78 MB of the gzipped amd64
image. This takes it out of the image and installs it when Debug mode
needs it.

It came out of the base image discussion on #1616 and helps on any base,
though on Wolfi the install line would need `apk`.

## What changed

- **Dockerfile:** ffmpeg is gone from the full image's install.
- **Guard:** `_start_ffmpeg_recording` checks `shutil.which("ffmpeg")`
first. If it's missing it logs a warning and returns, and the bypass
carries on. Without this, Debug on with no ffmpeg fails every bypass
with `FileNotFoundError`. There's a new test for it.
- **Entrypoint:** when Debug is on, the internal bypasser is in use and
ffmpeg isn't already there, it installs ffmpeg in the background so the
app doesn't wait for it. The download and the install each run under a
120 s `timeout` with `DEBIAN_FRONTEND=noninteractive`. Downloading first
means a hung mirror can only be killed before dpkg starts, and the next
start runs `dpkg --configure -a` in case a restart cut dpkg off. It logs
when it starts, succeeds, times out or fails.
- **Docs:** a short paragraph in `docs/troubleshooting.md` covering the
install and the non-root limit.

## Debug has two sources

Debug can come from the `DEBUG` env var or from the Debug Mode setting
in the UI, which is saved to `/config/plugins/advanced.json`. The
existing block in `entrypoint.sh` only reads the env var, so an install
keyed on `$DEBUG` would miss anyone who turned it on in the UI.

The new check asks the app instead (`shelfmark.config.env.DEBUG`), which
reads both. The UI setting is `requires_restart`, so the restart it
already asks for is what brings it through the entrypoint.

## Non-root mode

A container started as `1000:1000` can't run `apt-get`, so the
entrypoint logs that it can't install ffmpeg, the guard warns on each
bypass, and there's no recording. Everything else works. The workaround
for a debugging session is to start as root with `PUID`/`PGID`.

## Startup cost

None that I could measure. With Debug on, `/api/health` answers in the
same time as main (3-4 s with Debug only in config, 9-10 s from env),
and ffmpeg was ready 6-8 s later on the runners.

The trade-off is that the first bypass after startup may be unrecorded
while the install runs. It logs the warning and passes. I saw both
outcomes on a bypass started right after health.

From reading the code: the install lives in the container, so recreating
the container installs it again. It also runs after `tor.sh` and
`wireguard.sh`, so apt goes through whichever egress is active.

## Testing

Real Docker builds on GitHub Actions on my fork, amd64 and arm64, with
the same result on both for every case below.

| Case | Result |
|---|---|
| Debug off | No install, `/api/health` in 3-4 s, same as main |
| Debug only in config | Health in 3-4 s, ffmpeg ready 6-8 s later, real
mp4 after a bypass |
| Debug from env | Health in 9-10 s (same as main), real mp4 after a
bypass |
| Started as root, app dropped to uid 1000 | Smoke and bypass pass |
| Started with `--user 1000`, Debug on | Logs both messages, bypass
passes, no mp4 |
| apt blocked (closed proxy) | Logs `Could not install ffmpeg`, bypass
passes, no mp4 |
| apt's proxy on a dropped address, so no TCP reply at all | Health in
9-10 s, a bypass during the install passes with the warning and no mp4.
apt gives up by itself in under a minute. Nothing left running, `dpkg
--audit` clean |
| DNS server on a dropped address | Health in 9-10 s, `Timed out
installing ffmpeg after 120s`. Nothing left running, `dpkg --audit`
clean |
| `--network none`, Debug on | No hang, health 200 from inside the
container |
| Container restarted while dpkg was running | Next start finishes the
install, `dpkg --audit` clean, real mp4 |
| Fresh named volume, Debug only in config | Recording made, uid 1000
can write |
| Existing uid-1000 volume, Debug only in config | Same, nothing
root-owned afterwards |
| `find /config /var/log/shelfmark -user root` | 0 files, same as main |
| `find /app -user root` | 245, same count as main |
| `tests/e2e/platform/run-e2e.sh` with `dns-blocked` and `baseline` |
Pass |

The bypass checks ran against example.com. A real Cloudflare challenge
was served by a demo page in the same runs, and no build solved it,
including main, so that part doesn't say anything about this change.

Locally: 5494 Python tests pass, and `ruff`, `basedpyright`, `vulture`
and `shellcheck` are clean.

The full results are in [the base image
report](https://github.com/splitsec2/shelfmark/blob/7afcecfb76727724a71561cbc078f091569b58dc/docs/research/2026-11-01-base-image-report.md).
2026-11-01 18:09:11 -07:00
splitsec2 34c9e6dbd7 refactor: move the auth routes into core/auth_routes.py (#1625)
The auth routes are the next group from the plan in Discussion #1536:
`/api/auth/login`, `/logout` and `/check`, plus the login lockout
helpers, move from `main.py` to `core/auth_routes.py`, registered with
`register_auth_routes(app, ...)`. `main.py` is about 370 lines shorter.
This is the login path, so I kept it strictly to a move.

Two commits. The first adds 59 tests that pin the current behaviour
before anything moves: login in each mode (builtin, none, CWA and the
OIDC password fallback), wrong passwords, the lockout (the warning when
five attempts are left, the 429 and its text on the tenth failure,
per-user isolation, expiry), the local-auth switches, logout in each
mode and `/check`. They pass on current `main`, and I ran the same file
against `main` and against this branch. The second commit is the move,
and no existing test changed.

The lockout state is one dict, now living in `auth_routes`, and
`main.py` imports the same object so its other users (the
password-attempt limiter for the self-user routes, and the tests) see
it. Everything else that comes from `main` (the user database, the auth
mode, the client IP, the CWA database path, the local-auth settings and
the password check) is passed in as a callable evaluated per request, so
patches on `main` still apply.

Two things to know. `main.py` re-exports the lockout names and keeps
three lines assigning the view functions (`api_login =
app.view_functions["api_login"]` and the other two), because the e2e
tests call `main_module.api_login()` directly and I did not change tests
in this PR. If you would rather drop both, I can edit those e2e tests
instead. The other is that the lockout dict is no longer reset by a
reload of `main`, which only matters in tests, and they clear it
themselves.

The URL map is identical, all 77 rules, and the full suite, ruff and
basedpyright are clean. I also ran the app with builtin auth on a
scratch instance and went through it over HTTP: a wrong password gets a
401, login works and `/check` shows the session, logout clears it, the
tenth failed attempt gets the 429, and the right password is refused
while the account is locked.
2026-11-01 15:53:53 -07:00
splitsec2 d1e959758d refactor: move the system routes into core/system_routes.py (#1624)
The system routes are the next group from the plan in Discussion #1536:
`/api/config`, `/api/health`, `/api/debug`, `/api/restart` and the
routes that serve the frontend (`/`, the SPA catch-all, `/assets/...`,
the logo, the favicons and `theme-init.js`) move from `main.py` to
`core/system_routes.py`, registered with `register_system_routes(app,
login_required, ...)`. `main.py` is about 250 lines shorter.

Same two-commit layout as before. The first commit adds 14 tests for the
frontend-serving routes and the `/api/config` error paths, which had
none, and they pass on current `main`. The second commit is the move,
and no existing test changed.

The helpers only these routes use moved with them (`admin_required`,
built on the `login_required` that is passed in, plus `_base_href` and
`_serve_index_html`). What `main.py` still owns, the base path, the
frontend folder, the auth mode and the session user id, is passed in as
callables evaluated per request, so the tests that patch them on `main`
still work. The debug routes are only registered when debug is on, as
before, with the stop-GUI and run-script hooks handed in.

The thing to look at is the SPA catch-all, which is now registered
earlier in `main.py` than it used to be (the old comment said it must be
last). Werkzeug picks the most specific rule whatever the registration
order, and I checked it: all 76 rule and method pairs in the URL map
still match their own endpoint, on `main` and on this branch, and an
unknown `/api/...` path still gets the JSON 404.

The Flask URL map is identical before and after, all 77 rules, and with
debug on (79). The full suite, ruff and basedpyright are clean. I also
ran the app from this branch: health, config, the logo, the favicon and
the theme script answer as before, a client-side path like
`/library/books` gets the index page, an unknown `/api/` path gets the
JSON 404, and the page loads in a browser. I did not exercise
`/api/restart` or a real debug script run, since nothing tests them.
2026-11-01 14:12:11 -07:00
splitsec2 d41fa98749 refactor: move the metadata routes into core/metadata_routes.py (#1623)
The metadata routes are the next group from the plan in Discussion
#1536: the eight `/api/metadata/...` handlers (providers, config,
search, field-options, book and the three targets routes) move from
`main.py` to `core/metadata_routes.py`, registered with
`register_metadata_routes(app, ...)`. `main.py` is about 490 lines
shorter.

Same two-commit layout as the settings move (#1595). The first commit
adds 39 tests that pass on current `main` before anything moves. They
cover the 401 on all eight routes, the shape of the providers list and
the config, the search errors, the book lookup (200, 404, 400 and 503),
and how target errors map to 400, 502 and 500. The second commit is the
move, and no test changed in it.

Three helpers moved with the routes because nothing else uses them.
`_attach_library_ownership` stays in `main.py` since the releases routes
need it too, and is passed in along with the login decorator and the
auth mode, the way `activity_routes` takes them. The auth mode is a
callable evaluated per request, so the one test that patches it on
`main` still works.

The Flask URL map (every rule, its methods and its endpoint name) is
identical before and after, all 77 rules. The full suite, ruff and
basedpyright are clean. I also ran the app from this branch and hit the
routes over HTTP: providers and config answer 200, a book that doesn't
exist gets a 404, and search answers 503 with the "no metadata provider
configured" message on an instance with none enabled. I did not look at
it in a browser or run the e2e tests.

Log lines for these routes now come from
`shelfmark.core.metadata_routes`, and the error tuples are local copies
so the module doesn't import `main`. One thing to know when reading the
diff: the register call sits just after `_attach_library_ownership` and
not where the first route used to be, because that function has to be
defined before it can be passed in.
2026-11-01 14:11:33 -07:00
splitsec2 0a7e114681 docs(dev): new routes go in a register_<group>_routes module (#1622)
Nothing in the developer docs says where a new route goes, so the next
contributor adds it to `main.py` again. This writes down the convention
from Discussion #1536: a new route group gets its own
`register_<group>_routes` module under `shelfmark/core/`, and `main.py`
calls it once.

It is one paragraph on a new page, `docs/dev/routes.md`, with a line in
the developer index. It also says that a few older routes are still in
`main.py` and are being moved out one group at a time. The route moves
in that discussion will follow what this says, so this goes first.
2026-10-31 03:52:01 -06:00
splitsec2 9bd6c51388 fix(hardcover): read the featured series from a search result (#1589)
Closes #1585. @joeRob2468 traced this one to the parser, and the answer
turned out to be sitting in the search response already.

A Hardcover search hit carries the book's featured series as
`featured_series`, with the same shape as the `featured_book_series` of
a full record: the position and a nested series with its id, name and
book count. `_parse_search_result` never read it, so a book requested
from a search card was stored with `series_name: null` and the
`{Series}` folder and the custom script payload came out empty. It now
reads it, through a small helper that `_parse_book` uses too, so there
is no extra Hardcover call per request (the issue's other option was
fetching the full record, which costs one against the rate limit).

I checked it against a live search for "Mistborn The Final Empire". The
top hit parses to series "The Mistborn Saga: The Original Trilogy",
position 1, id 10001, and its search title is still "Mistborn".

That last part is on purpose. I left `_compute_search_title` alone,
since passing it the series would change what gets searched for everyone
and the series name here doesn't equal the "Mistborn" prefix anyway.

Two things that behave differently. A search result now has
`series_name` set, so anything in the UI that shows it for a full record
(the series link, the bigger cover in the release modal) will show it on
search results too. I ran the branch and looked at the release modal for
the top Mistborn result: it shows "#1 of 3 in The Mistborn Saga: The
Original Trilogy" with the View series link. The modal fetches the full
record when it opens, so I can't say how much of that is new on this
path. Requests already stored keep the empty series they were saved
with.

Tests: four in a new file (a hit with a series, hits with none or an
incomplete one, a hit nested in a `document`, and the search title
staying the same), the first and third fail on current main. The
metadata and core suites, ruff and basedpyright are clean.
v1.6.0
2026-10-31 01:35:37 -06:00
dependabot[bot] d95f663a92 build(deps): bump the gh-actions group with 5 updates (#1612)
Bumps the gh-actions group with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [docker/login-action](https://github.com/docker/login-action) |
`4.6.0` | `4.7.0` |
| [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) | `10.3.0`
| `10.3.2` |
| [github/codeql-action/init](https://github.com/github/codeql-action) |
`4.39.0` | `4.39.1` |
|
[github/codeql-action/autobuild](https://github.com/github/codeql-action)
| `4.39.0` | `4.39.1` |
|
[github/codeql-action/analyze](https://github.com/github/codeql-action)
| `4.39.0` | `4.39.1` |

Updates `docker/login-action` from 4.6.0 to 4.7.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/docker/login-action/releases">docker/login-action's
releases</a>.</em></p>
<blockquote>
<h2>v4.7.0</h2>
<ul>
<li>Preserve explicit ECR settings in <code>registry-auth</code> by <a
href="https://github.com/crazy-max"><code>@​crazy-max</code></a> in <a
href="https://redirect.github.com/docker/login-action/pull/1089">docker/login-action#1089</a></li>
<li>Use registry hosts for scoped credentials by <a
href="https://github.com/crazy-max"><code>@​crazy-max</code></a> in <a
href="https://redirect.github.com/docker/login-action/pull/1088">docker/login-action#1088</a></li>
<li>Raise Docker Hub OIDC max expiry to 6 hours by <a
href="https://github.com/crazy-max"><code>@​crazy-max</code></a> in <a
href="https://redirect.github.com/docker/login-action/pull/1068">docker/login-action#1068</a></li>
<li>Log Docker Hub OIDC token exchange progress by <a
href="https://github.com/crazy-max"><code>@​crazy-max</code></a> in <a
href="https://redirect.github.com/docker/login-action/pull/1061">docker/login-action#1061</a></li>
<li>Bump <code>@​aws-sdk/client-ecr</code> and
<code>@​aws-sdk/client-ecr-public</code> to 3.1154.0 in <a
href="https://redirect.github.com/docker/login-action/pull/1093">docker/login-action#1093</a></li>
<li>Bump <code>@​docker/actions-toolkit</code> from 0.94.0 to 0.107.0 in
<a
href="https://redirect.github.com/docker/login-action/pull/1100">docker/login-action#1100</a></li>
<li>Bump <code>@​humanfs/node</code> from 0.16.7 to 0.16.8 in <a
href="https://redirect.github.com/docker/login-action/pull/1077">docker/login-action#1077</a></li>
<li>Bump csv-parse from 7.0.1 to 7.0.3 in <a
href="https://redirect.github.com/docker/login-action/pull/1078">docker/login-action#1078</a></li>
<li>Bump handlebars from 4.7.9 to 4.7.10 in <a
href="https://redirect.github.com/docker/login-action/pull/1091">docker/login-action#1091</a></li>
<li>Bump js-yaml from 5.2.2 to 5.5.0 in <a
href="https://redirect.github.com/docker/login-action/pull/1066">docker/login-action#1066</a></li>
<li>Bump postcss from 8.5.22 to 8.5.26 in <a
href="https://redirect.github.com/docker/login-action/pull/1071">docker/login-action#1071</a></li>
<li>Bump postcss-selector-parser from 7.1.1 to 7.1.6 in <a
href="https://redirect.github.com/docker/login-action/pull/1092">docker/login-action#1092</a></li>
<li>Bump source-map-js from 1.2.1 to 1.2.2 in <a
href="https://redirect.github.com/docker/login-action/pull/1090">docker/login-action#1090</a></li>
<li>Bump undici from 6.27.0 to 6.29.1 in <a
href="https://redirect.github.com/docker/login-action/pull/1085">docker/login-action#1085</a></li>
<li>Bump uuid from 14.0.1 to 14.0.3 in <a
href="https://redirect.github.com/docker/login-action/pull/1096">docker/login-action#1096</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/docker/login-action/compare/v4.6.0...v4.7.0">https://github.com/docker/login-action/compare/v4.6.0...v4.7.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/docker/login-action/commit/81c6f93d4bc991e510b342a00b419b3bb4efc5c6"><code>81c6f93</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/login-action/issues/1100">#1100</a>
from docker/dependabot/npm_and_yarn/docker/actions-t...</li>
<li><a
href="https://github.com/docker/login-action/commit/1b16c8d1815e1d951d87a3522ff48a76d073735a"><code>1b16c8d</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/login-action/issues/1096">#1096</a>
from docker/dependabot/npm_and_yarn/uuid-14.0.3</li>
<li><a
href="https://github.com/docker/login-action/commit/ac86b5e9e9d2db43b12b2d3afb9140a427d69d65"><code>ac86b5e</code></a>
[dependabot skip] chore: update generated content</li>
<li><a
href="https://github.com/docker/login-action/commit/1476d845f08dd8309a938959a280f2e23c0cba14"><code>1476d84</code></a>
build(deps): bump <code>@​docker/actions-toolkit</code> from 0.94.0 to
0.107.0</li>
<li><a
href="https://github.com/docker/login-action/commit/503cee68d85e94275776fcc6f5315f19207f7567"><code>503cee6</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/login-action/issues/1095">#1095</a>
from docker/dependabot/github_actions/actions/create...</li>
<li><a
href="https://github.com/docker/login-action/commit/f0935357f5c539aeb7ff6b886ba5434ab76e9de3"><code>f093535</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/login-action/issues/1099">#1099</a>
from docker/dependabot/github_actions/codecov/codeco...</li>
<li><a
href="https://github.com/docker/login-action/commit/d5ae7f188776587b12b77b45e29ea21332462da9"><code>d5ae7f1</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/login-action/issues/1098">#1098</a>
from docker/dependabot/github_actions/docker/bake-ac...</li>
<li><a
href="https://github.com/docker/login-action/commit/6f9750797f6e7186f18c069a7e97abc1dcf1006b"><code>6f97507</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/login-action/issues/1097">#1097</a>
from docker/dependabot/github_actions/docker/bake-ac...</li>
<li><a
href="https://github.com/docker/login-action/commit/006d61fa598847d65f6670d1569545fa2af9cf02"><code>006d61f</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/login-action/issues/1094">#1094</a>
from docker/dependabot/github_actions/codeql-actions...</li>
<li><a
href="https://github.com/docker/login-action/commit/93f5f522eea5eacabf35cc89b9d19ec23e742471"><code>93f5f52</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/login-action/issues/1093">#1093</a>
from docker/dependabot/npm_and_yarn/aws-sdk-dependen...</li>
<li>Additional commits viewable in <a
href="https://github.com/docker/login-action/compare/dbcb813823bdd20940b903addbd779551569679f...81c6f93d4bc991e510b342a00b419b3bb4efc5c6">compare
view</a></li>
</ul>
</details>
<br />

Updates `astral-sh/setup-uv` from 10.3.0 to 10.3.2
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/setup-uv/releases">astral-sh/setup-uv's
releases</a>.</em></p>
<blockquote>
<h2>v10.3.2 🌈 update known checksums for 0.13.5</h2>
<h2>Changes</h2>
<h2>🧰 Maintenance</h2>
<ul>
<li>chore: update known checksums for 0.13.5 @<a
href="https://github.com/apps/github-actions">github-actions[bot]</a>
(<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1103">#1103</a>)</li>
</ul>
<h2>📚 Documentation</h2>
<ul>
<li>docs: update version references to v10.3.1 @<a
href="https://github.com/apps/github-actions">github-actions[bot]</a>
(<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1102">#1102</a>)</li>
</ul>
<h2>v10.3.1 🌈 preserve cache error class names in save-cache bundle</h2>
<h2>Changes</h2>
<p>This release includes a fix so that multiple concurrent workflows
trying to upload the same cache no longer warn</p>
<p><code>##[warning]Failed to save: Unable to reserve cache with key
..., another job may be creating this cache.</code></p>
<h2>🐛 Bug fixes</h2>
<ul>
<li>fix: preserve cache error class names in save-cache bundle <a
href="https://github.com/dannyward630"><code>@​dannyward630</code></a>
(<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1093">#1093</a>)</li>
</ul>
<h2>🧰 Maintenance</h2>
<ul>
<li>chore: update known checksums for 0.13.4 @<a
href="https://github.com/apps/github-actions">github-actions[bot]</a>
(<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1099">#1099</a>)</li>
<li>chore: update known checksums for 0.13.2/0.13.3 @<a
href="https://github.com/apps/github-actions">github-actions[bot]</a>
(<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1098">#1098</a>)</li>
<li>chore: update known checksums for 0.13.1 @<a
href="https://github.com/apps/github-actions">github-actions[bot]</a>
(<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1094">#1094</a>)</li>
<li>Verify npm dependency signatures before builds <a
href="https://github.com/zaniebot"><code>@​zaniebot</code></a> (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1027">#1027</a>)</li>
</ul>
<h2>📚 Documentation</h2>
<ul>
<li>docs: cache-dependency-glob matches relative to the working
directory <a
href="https://github.com/flange-ipb"><code>@​flange-ipb</code></a> (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1092">#1092</a>)</li>
<li>docs: update version references to v10.3.0 @<a
href="https://github.com/apps/github-actions">github-actions[bot]</a>
(<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1090">#1090</a>)</li>
</ul>
<h2>⬆️ Dependency updates</h2>
<ul>
<li>chore(deps): roll up Dependabot updates <a
href="https://github.com/eifinger"><code>@​eifinger</code></a> (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1101">#1101</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/07a047e608db84b3d8c06cd9a7c7dcc9c355c18e"><code>07a047e</code></a>
chore: update known checksums for 0.13.5 (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1103">#1103</a>)</li>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/e1b85369e72750369c935b004eccf97311bdf5dc"><code>e1b8536</code></a>
docs: update version references to v10.3.1 (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1102">#1102</a>)</li>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/18d369b23da25a81e9458561248e1aafff6a70fa"><code>18d369b</code></a>
chore(deps): roll up Dependabot updates (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1101">#1101</a>)</li>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/4ad2329c1e377d882fcae221cd1d17e7c0ad788e"><code>4ad2329</code></a>
chore: update known checksums for 0.13.4 (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1099">#1099</a>)</li>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/4bc6759c82322ff7efa28de54a45404ca6869912"><code>4bc6759</code></a>
chore: update known checksums for 0.13.2/0.13.3 (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1098">#1098</a>)</li>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/c97f06e356bcca1b426f396ef93ec35ce149ce7b"><code>c97f06e</code></a>
fix: preserve cache error class names in save-cache bundle (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1093">#1093</a>)</li>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/8ca4be000bfa5f8e6aaa01d8470878c90aa728d3"><code>8ca4be0</code></a>
chore: update known checksums for 0.13.1 (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1094">#1094</a>)</li>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/b627d85691ead579b598a36169571b1c7123526f"><code>b627d85</code></a>
docs: cache-dependency-glob matches relative to the working directory
(<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1092">#1092</a>)</li>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/f8c88970fcd8fff8e97bc62edc5f5c073a0527fe"><code>f8c8897</code></a>
Verify npm dependency signatures before builds (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1027">#1027</a>)</li>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/f64d32b1cd6cc11405a74665b3dfb7bb86fea9f0"><code>f64d32b</code></a>
docs: update version references to v10.3.0 (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1090">#1090</a>)</li>
<li>See full diff in <a
href="https://github.com/astral-sh/setup-uv/compare/1c37ad07a6a961277cf70c0d37d6f313000f5884...07a047e608db84b3d8c06cd9a7c7dcc9c355c18e">compare
view</a></li>
</ul>
</details>
<br />

Updates `github/codeql-action/init` from 4.39.0 to 4.39.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/github/codeql-action/releases">github/codeql-action/init's
releases</a>.</em></p>
<blockquote>
<h2>v4.39.1</h2>
<ul>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.3">2.27.3</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/4256">#4256</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/github/codeql-action/blob/main/CHANGELOG.md">github/codeql-action/init's
changelog</a>.</em></p>
<blockquote>
<h1>CodeQL Action Changelog</h1>
<p>See the <a
href="https://github.com/github/codeql-action/releases">releases
page</a> for the relevant changes to the CodeQL CLI and language
packs.</p>
<h2>[UNRELEASED]</h2>
<p>No user facing changes.</p>
<h2>4.39.1 - 21 Oct 2026</h2>
<ul>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.3">2.27.3</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/4256">#4256</a></li>
</ul>
<h2>4.39.0 - 15 Oct 2026</h2>
<ul>
<li><em>Breaking change</em>: Bump the minimum required CodeQL bundle
version to 2.20.7. <a
href="https://redirect.github.com/github/codeql-action/pull/4205">#4205</a></li>
<li>The <code>codeql-action/analyze</code> step now validates that a
correct argument for the <code>checkout_path</code> input has been
provided. The <code>checkout_path</code> input must be set to the path
where the repository that is being analyzed is checked out at on the
runner, if that path is something other than the workspace root. If the
path does not point to a repository checkout or is different from the
path that was used by <code>codeql-action/init</code>, then the CodeQL
Action now produces a warning. <a
href="https://redirect.github.com/github/codeql-action/pull/4148">#4148</a></li>
<li>Resolved an issue with third-party caching implementations that
prevented caches from being restored correctly. <a
href="https://redirect.github.com/github/codeql-action/pull/4206">#4206</a></li>
<li>The <code>codeql-action/start-proxy</code> step that is used in Code
Scanning Default Setup now finds CodeQL releases using the same logic as
<code>codeql-action/init</code>. This primarily benefits customers who
are using GitHub instances other than <code>github.com</code> where the
<code>codeql-action/start-proxy</code> step may previously have been
unable to locate recent releases and ended up using outdated versions of
the private registry authentication proxy as a result. <a
href="https://redirect.github.com/github/codeql-action/pull/4198">#4198</a></li>
</ul>
<h2>4.38.3 - 08 Oct 2026</h2>
<ul>
<li><em>Upcoming breaking change</em>: CodeQL version 2.21.2 and earlier
were discontinued on 24 September 2026 alongside GitHub Enterprise
Server 3.17, and will be unsupported by the next minor release of the
CodeQL Action. Added a deprecation warning for customers using these
versions of CodeQL. <a
href="https://redirect.github.com/github/codeql-action/pull/4188">#4188</a></li>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.2">2.27.2</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/4203">#4203</a></li>
<li>Fixed a bug where the decision of whether to use a per-language
bundle did not account for custom configurations that reference queries
outside of compiled CodeQL packs. This issue was caught during internal
testing and did not affect any customer repositories. We will resume the
roll out of per-language bundles in the coming weeks. <a
href="https://redirect.github.com/github/codeql-action/pull/4184">#4184</a></li>
</ul>
<h2>4.38.2 - 24 Sept 2026</h2>
<ul>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.1">2.27.1</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/4160">#4160</a></li>
</ul>
<h2>4.38.1 - 18 Sept 2026</h2>
<ul>
<li>The CodeQL Action now has experimental support for CodeQL releases
for which per-language bundles are available. Per-language bundles
support analysis for a single language and are therefore smaller than
the combined bundles that allow analysis for all supported languages. As
a result, per-language bundles take up less space on disk and are faster
to download. We expect to roll this change out to everyone in the coming
weeks. <a
href="https://redirect.github.com/github/codeql-action/pull/4146">#4146</a></li>
</ul>
<h2>4.38.0 - 09 Sept 2026</h2>
<ul>
<li>On GitHub-hosted runners, the CodeQL Action now deletes unused
CodeQL bundles from the toolcache before downloading a different bundle,
which frees up disk space for the analysis. We expect to roll this
change out to everyone in September. <a
href="https://redirect.github.com/github/codeql-action/pull/4124">#4124</a></li>
<li>The CodeQL Action now supports CodeQL releases that are compatible
with Linux Arm64 and downloads the native <code>linux-arm64</code>
CodeQL bundle when available. <a
href="https://redirect.github.com/github/codeql-action/pull/4072">#4072</a></li>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.0">2.27.0</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/4129">#4129</a></li>
</ul>
<h2>4.37.9 - 26 Aug 2026</h2>
<ul>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.4">2.26.4</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/4106">#4106</a></li>
</ul>
<h2>4.37.8 - 21 Aug 2026</h2>
<p>No user facing changes.</p>
<h2>4.37.7 - 13 Aug 2026</h2>
<ul>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.3">2.26.3</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/4085">#4085</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/github/codeql-action/commit/9b3254085494b55a0f7c4c2b3d2d52cc712ce370"><code>9b32540</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/4257">#4257</a>
from github/update-v4.39.1-c5a2f4b0f</li>
<li><a
href="https://github.com/github/codeql-action/commit/b5e1ed9574dcfa81c88c318140f3b3e5c199bfb3"><code>b5e1ed9</code></a>
Trigger workflows</li>
<li><a
href="https://github.com/github/codeql-action/commit/20f5ec39109073afe1789b098456b2be0164f4ee"><code>20f5ec3</code></a>
Update changelog for v4.39.1</li>
<li><a
href="https://github.com/github/codeql-action/commit/c5a2f4b0fe28ca06eaaeb86fb05a5f612ae293f9"><code>c5a2f4b</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/4245">#4245</a>
from github/henrymercer/graduate-overlay-trap-caching</li>
<li><a
href="https://github.com/github/codeql-action/commit/61a5a80dd98ad1b9679010141a46cace51065761"><code>61a5a80</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/4256">#4256</a>
from github/update-bundle/codeql-bundle-v2.27.3</li>
<li><a
href="https://github.com/github/codeql-action/commit/3dd33f8b69588bd9591684b2dca169eb612f5ed5"><code>3dd33f8</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/4249">#4249</a>
from github/mbg/upload-improvements-for-4223</li>
<li><a
href="https://github.com/github/codeql-action/commit/b96e3390db93dc46c2c3753a94b87c0d734b0b61"><code>b96e339</code></a>
Change comment for <code>getConfig</code> call in
<code>upload-sarif</code></li>
<li><a
href="https://github.com/github/codeql-action/commit/7fa45180db8d657b23ded3636b5d8583aec6ddfe"><code>7fa4518</code></a>
Use <code>shouldSkipSarifUpload</code> in
<code>analyze-action.ts</code></li>
<li><a
href="https://github.com/github/codeql-action/commit/a69c7cb332d56f616fcadef002884523c71e8d1c"><code>a69c7cb</code></a>
Document that setting the env vars to <code>false</code> takes
precedence</li>
<li><a
href="https://github.com/github/codeql-action/commit/74ddcd9f65683791ab07eccd074b4ba145d89ea6"><code>74ddcd9</code></a>
Fix typo in comment</li>
<li>Additional commits viewable in <a
href="https://github.com/github/codeql-action/compare/6f2ac81f5cd81fe351a197ba0b00d91d03cd2aee...9b3254085494b55a0f7c4c2b3d2d52cc712ce370">compare
view</a></li>
</ul>
</details>
<br />

Updates `github/codeql-action/autobuild` from 4.39.0 to 4.39.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/github/codeql-action/releases">github/codeql-action/autobuild's
releases</a>.</em></p>
<blockquote>
<h2>v4.39.1</h2>
<ul>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.3">2.27.3</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/4256">#4256</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/github/codeql-action/blob/main/CHANGELOG.md">github/codeql-action/autobuild's
changelog</a>.</em></p>
<blockquote>
<h1>CodeQL Action Changelog</h1>
<p>See the <a
href="https://github.com/github/codeql-action/releases">releases
page</a> for the relevant changes to the CodeQL CLI and language
packs.</p>
<h2>[UNRELEASED]</h2>
<p>No user facing changes.</p>
<h2>4.39.1 - 21 Oct 2026</h2>
<ul>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.3">2.27.3</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/4256">#4256</a></li>
</ul>
<h2>4.39.0 - 15 Oct 2026</h2>
<ul>
<li><em>Breaking change</em>: Bump the minimum required CodeQL bundle
version to 2.20.7. <a
href="https://redirect.github.com/github/codeql-action/pull/4205">#4205</a></li>
<li>The <code>codeql-action/analyze</code> step now validates that a
correct argument for the <code>checkout_path</code> input has been
provided. The <code>checkout_path</code> input must be set to the path
where the repository that is being analyzed is checked out at on the
runner, if that path is something other than the workspace root. If the
path does not point to a repository checkout or is different from the
path that was used by <code>codeql-action/init</code>, then the CodeQL
Action now produces a warning. <a
href="https://redirect.github.com/github/codeql-action/pull/4148">#4148</a></li>
<li>Resolved an issue with third-party caching implementations that
prevented caches from being restored correctly. <a
href="https://redirect.github.com/github/codeql-action/pull/4206">#4206</a></li>
<li>The <code>codeql-action/start-proxy</code> step that is used in Code
Scanning Default Setup now finds CodeQL releases using the same logic as
<code>codeql-action/init</code>. This primarily benefits customers who
are using GitHub instances other than <code>github.com</code> where the
<code>codeql-action/start-proxy</code> step may previously have been
unable to locate recent releases and ended up using outdated versions of
the private registry authentication proxy as a result. <a
href="https://redirect.github.com/github/codeql-action/pull/4198">#4198</a></li>
</ul>
<h2>4.38.3 - 08 Oct 2026</h2>
<ul>
<li><em>Upcoming breaking change</em>: CodeQL version 2.21.2 and earlier
were discontinued on 24 September 2026 alongside GitHub Enterprise
Server 3.17, and will be unsupported by the next minor release of the
CodeQL Action. Added a deprecation warning for customers using these
versions of CodeQL. <a
href="https://redirect.github.com/github/codeql-action/pull/4188">#4188</a></li>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.2">2.27.2</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/4203">#4203</a></li>
<li>Fixed a bug where the decision of whether to use a per-language
bundle did not account for custom configurations that reference queries
outside of compiled CodeQL packs. This issue was caught during internal
testing and did not affect any customer repositories. We will resume the
roll out of per-language bundles in the coming weeks. <a
href="https://redirect.github.com/github/codeql-action/pull/4184">#4184</a></li>
</ul>
<h2>4.38.2 - 24 Sept 2026</h2>
<ul>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.1">2.27.1</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/4160">#4160</a></li>
</ul>
<h2>4.38.1 - 18 Sept 2026</h2>
<ul>
<li>The CodeQL Action now has experimental support for CodeQL releases
for which per-language bundles are available. Per-language bundles
support analysis for a single language and are therefore smaller than
the combined bundles that allow analysis for all supported languages. As
a result, per-language bundles take up less space on disk and are faster
to download. We expect to roll this change out to everyone in the coming
weeks. <a
href="https://redirect.github.com/github/codeql-action/pull/4146">#4146</a></li>
</ul>
<h2>4.38.0 - 09 Sept 2026</h2>
<ul>
<li>On GitHub-hosted runners, the CodeQL Action now deletes unused
CodeQL bundles from the toolcache before downloading a different bundle,
which frees up disk space for the analysis. We expect to roll this
change out to everyone in September. <a
href="https://redirect.github.com/github/codeql-action/pull/4124">#4124</a></li>
<li>The CodeQL Action now supports CodeQL releases that are compatible
with Linux Arm64 and downloads the native <code>linux-arm64</code>
CodeQL bundle when available. <a
href="https://redirect.github.com/github/codeql-action/pull/4072">#4072</a></li>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.0">2.27.0</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/4129">#4129</a></li>
</ul>
<h2>4.37.9 - 26 Aug 2026</h2>
<ul>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.4">2.26.4</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/4106">#4106</a></li>
</ul>
<h2>4.37.8 - 21 Aug 2026</h2>
<p>No user facing changes.</p>
<h2>4.37.7 - 13 Aug 2026</h2>
<ul>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.3">2.26.3</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/4085">#4085</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/github/codeql-action/commit/9b3254085494b55a0f7c4c2b3d2d52cc712ce370"><code>9b32540</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/4257">#4257</a>
from github/update-v4.39.1-c5a2f4b0f</li>
<li><a
href="https://github.com/github/codeql-action/commit/b5e1ed9574dcfa81c88c318140f3b3e5c199bfb3"><code>b5e1ed9</code></a>
Trigger workflows</li>
<li><a
href="https://github.com/github/codeql-action/commit/20f5ec39109073afe1789b098456b2be0164f4ee"><code>20f5ec3</code></a>
Update changelog for v4.39.1</li>
<li><a
href="https://github.com/github/codeql-action/commit/c5a2f4b0fe28ca06eaaeb86fb05a5f612ae293f9"><code>c5a2f4b</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/4245">#4245</a>
from github/henrymercer/graduate-overlay-trap-caching</li>
<li><a
href="https://github.com/github/codeql-action/commit/61a5a80dd98ad1b9679010141a46cace51065761"><code>61a5a80</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/4256">#4256</a>
from github/update-bundle/codeql-bundle-v2.27.3</li>
<li><a
href="https://github.com/github/codeql-action/commit/3dd33f8b69588bd9591684b2dca169eb612f5ed5"><code>3dd33f8</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/4249">#4249</a>
from github/mbg/upload-improvements-for-4223</li>
<li><a
href="https://github.com/github/codeql-action/commit/b96e3390db93dc46c2c3753a94b87c0d734b0b61"><code>b96e339</code></a>
Change comment for <code>getConfig</code> call in
<code>upload-sarif</code></li>
<li><a
href="https://github.com/github/codeql-action/commit/7fa45180db8d657b23ded3636b5d8583aec6ddfe"><code>7fa4518</code></a>
Use <code>shouldSkipSarifUpload</code> in
<code>analyze-action.ts</code></li>
<li><a
href="https://github.com/github/codeql-action/commit/a69c7cb332d56f616fcadef002884523c71e8d1c"><code>a69c7cb</code></a>
Document that setting the env vars to <code>false</code> takes
precedence</li>
<li><a
href="https://github.com/github/codeql-action/commit/74ddcd9f65683791ab07eccd074b4ba145d89ea6"><code>74ddcd9</code></a>
Fix typo in comment</li>
<li>Additional commits viewable in <a
href="https://github.com/github/codeql-action/compare/6f2ac81f5cd81fe351a197ba0b00d91d03cd2aee...9b3254085494b55a0f7c4c2b3d2d52cc712ce370">compare
view</a></li>
</ul>
</details>
<br />

Updates `github/codeql-action/analyze` from 4.39.0 to 4.39.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/github/codeql-action/releases">github/codeql-action/analyze's
releases</a>.</em></p>
<blockquote>
<h2>v4.39.1</h2>
<ul>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.3">2.27.3</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/4256">#4256</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/github/codeql-action/blob/main/CHANGELOG.md">github/codeql-action/analyze's
changelog</a>.</em></p>
<blockquote>
<h1>CodeQL Action Changelog</h1>
<p>See the <a
href="https://github.com/github/codeql-action/releases">releases
page</a> for the relevant changes to the CodeQL CLI and language
packs.</p>
<h2>[UNRELEASED]</h2>
<p>No user facing changes.</p>
<h2>4.39.1 - 21 Oct 2026</h2>
<ul>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.3">2.27.3</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/4256">#4256</a></li>
</ul>
<h2>4.39.0 - 15 Oct 2026</h2>
<ul>
<li><em>Breaking change</em>: Bump the minimum required CodeQL bundle
version to 2.20.7. <a
href="https://redirect.github.com/github/codeql-action/pull/4205">#4205</a></li>
<li>The <code>codeql-action/analyze</code> step now validates that a
correct argument for the <code>checkout_path</code> input has been
provided. The <code>checkout_path</code> input must be set to the path
where the repository that is being analyzed is checked out at on the
runner, if that path is something other than the workspace root. If the
path does not point to a repository checkout or is different from the
path that was used by <code>codeql-action/init</code>, then the CodeQL
Action now produces a warning. <a
href="https://redirect.github.com/github/codeql-action/pull/4148">#4148</a></li>
<li>Resolved an issue with third-party caching implementations that
prevented caches from being restored correctly. <a
href="https://redirect.github.com/github/codeql-action/pull/4206">#4206</a></li>
<li>The <code>codeql-action/start-proxy</code> step that is used in Code
Scanning Default Setup now finds CodeQL releases using the same logic as
<code>codeql-action/init</code>. This primarily benefits customers who
are using GitHub instances other than <code>github.com</code> where the
<code>codeql-action/start-proxy</code> step may previously have been
unable to locate recent releases and ended up using outdated versions of
the private registry authentication proxy as a result. <a
href="https://redirect.github.com/github/codeql-action/pull/4198">#4198</a></li>
</ul>
<h2>4.38.3 - 08 Oct 2026</h2>
<ul>
<li><em>Upcoming breaking change</em>: CodeQL version 2.21.2 and earlier
were discontinued on 24 September 2026 alongside GitHub Enterprise
Server 3.17, and will be unsupported by the next minor release of the
CodeQL Action. Added a deprecation warning for customers using these
versions of CodeQL. <a
href="https://redirect.github.com/github/codeql-action/pull/4188">#4188</a></li>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.2">2.27.2</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/4203">#4203</a></li>
<li>Fixed a bug where the decision of whether to use a per-language
bundle did not account for custom configurations that reference queries
outside of compiled CodeQL packs. This issue was caught during internal
testing and did not affect any customer repositories. We will resume the
roll out of per-language bundles in the coming weeks. <a
href="https://redirect.github.com/github/codeql-action/pull/4184">#4184</a></li>
</ul>
<h2>4.38.2 - 24 Sept 2026</h2>
<ul>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.1">2.27.1</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/4160">#4160</a></li>
</ul>
<h2>4.38.1 - 18 Sept 2026</h2>
<ul>
<li>The CodeQL Action now has experimental support for CodeQL releases
for which per-language bundles are available. Per-language bundles
support analysis for a single language and are therefore smaller than
the combined bundles that allow analysis for all supported languages. As
a result, per-language bundles take up less space on disk and are faster
to download. We expect to roll this change out to everyone in the coming
weeks. <a
href="https://redirect.github.com/github/codeql-action/pull/4146">#4146</a></li>
</ul>
<h2>4.38.0 - 09 Sept 2026</h2>
<ul>
<li>On GitHub-hosted runners, the CodeQL Action now deletes unused
CodeQL bundles from the toolcache before downloading a different bundle,
which frees up disk space for the analysis. We expect to roll this
change out to everyone in September. <a
href="https://redirect.github.com/github/codeql-action/pull/4124">#4124</a></li>
<li>The CodeQL Action now supports CodeQL releases that are compatible
with Linux Arm64 and downloads the native <code>linux-arm64</code>
CodeQL bundle when available. <a
href="https://redirect.github.com/github/codeql-action/pull/4072">#4072</a></li>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.0">2.27.0</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/4129">#4129</a></li>
</ul>
<h2>4.37.9 - 26 Aug 2026</h2>
<ul>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.4">2.26.4</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/4106">#4106</a></li>
</ul>
<h2>4.37.8 - 21 Aug 2026</h2>
<p>No user facing changes.</p>
<h2>4.37.7 - 13 Aug 2026</h2>
<ul>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.3">2.26.3</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/4085">#4085</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/github/codeql-action/commit/9b3254085494b55a0f7c4c2b3d2d52cc712ce370"><code>9b32540</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/4257">#4257</a>
from github/update-v4.39.1-c5a2f4b0f</li>
<li><a
href="https://github.com/github/codeql-action/commit/b5e1ed9574dcfa81c88c318140f3b3e5c199bfb3"><code>b5e1ed9</code></a>
Trigger workflows</li>
<li><a
href="https://github.com/github/codeql-action/commit/20f5ec39109073afe1789b098456b2be0164f4ee"><code>20f5ec3</code></a>
Update changelog for v4.39.1</li>
<li><a
href="https://github.com/github/codeql-action/commit/c5a2f4b0fe28ca06eaaeb86fb05a5f612ae293f9"><code>c5a2f4b</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/4245">#4245</a>
from github/henrymercer/graduate-overlay-trap-caching</li>
<li><a
href="https://github.com/github/codeql-action/commit/61a5a80dd98ad1b9679010141a46cace51065761"><code>61a5a80</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/4256">#4256</a>
from github/update-bundle/codeql-bundle-v2.27.3</li>
<li><a
href="https://github.com/github/codeql-action/commit/3dd33f8b69588bd9591684b2dca169eb612f5ed5"><code>3dd33f8</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/4249">#4249</a>
from github/mbg/upload-improvements-for-4223</li>
<li><a
href="https://github.com/github/codeql-action/commit/b96e3390db93dc46c2c3753a94b87c0d734b0b61"><code>b96e339</code></a>
Change comment for <code>getConfig</code> call in
<code>upload-sarif</code></li>
<li><a
href="https://github.com/github/codeql-action/commit/7fa45180db8d657b23ded3636b5d8583aec6ddfe"><code>7fa4518</code></a>
Use <code>shouldSkipSarifUpload</code> in
<code>analyze-action.ts</code></li>
<li><a
href="https://github.com/github/codeql-action/commit/a69c7cb332d56f616fcadef002884523c71e8d1c"><code>a69c7cb</code></a>
Document that setting the env vars to <code>false</code> takes
precedence</li>
<li><a
href="https://github.com/github/codeql-action/commit/74ddcd9f65683791ab07eccd074b4ba145d89ea6"><code>74ddcd9</code></a>
Fix typo in comment</li>
<li>Additional commits viewable in <a
href="https://github.com/github/codeql-action/compare/6f2ac81f5cd81fe351a197ba0b00d91d03cd2aee...9b3254085494b55a0f7c4c2b3d2d52cc712ce370">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-31 01:35:03 -06:00
splitsec2 d04268c639 fix(docker): drop the unused selenium-manager binaries from the image (#1615)
Came out of looking at what is in the image after @wrycu's #1606. The
selenium package ships prebuilt `selenium-manager` binaries for four
platforms (about 22MB uncompressed), and none of them are used here.
They only run when selenium has to find a webdriver, and the bypasser
drives the browser through SeleniumBase's Pure-CDP driver, which doesn't
use one.

This deletes them (and their SBOM file) in the same `RUN` as `uv sync`,
so the layer doesn't carry them. As a side effect image scanners stop
reporting on the Rust crates compiled into those binaries.

To check nothing needs them, I deleted the files in a throwaway
container from the current `dev` image and ran `internal_bypasser.get()`
against example.com. It started the browser, loaded the page and
returned it, same as without the deletion. I haven't run a full image
build of this branch, so CI is the first time that exact `RUN` line gets
executed.

TL;DR dropping an unused feature from an included package lowering size
and eliminating flags for security vulnerabilities that don't get
exercised.

@calibrain this one is optional too, but I don't see a downside, your
call.
2026-10-31 01:21:05 -06:00
splitsec2 3d7d04256f fix(docker): bump Chromium pin to 156.0.8078.73 (#1614)
Debian has a newer Chromium in trixie-security (156.0.8078.73), so this
moves the pin from .47 to .73 and the snapshot to 20261029T020000Z, the
first one that has it for both amd64 and arm64. Same shape as #1601.

To check the bypasser still works on it, I started a throwaway container
from the current `dev` image, upgraded Chromium to .73 the way the
Dockerfile does, and ran `internal_bypasser.get()` against example.com.
It starts, loads the page and returns it, the same as on .47. I also
pointed both versions at the Cloudflare demo challenge page at
scrapingcourse.com. They behave the same there, but neither one solves
it from where I ran it (same challenge detected 4 times, then abort), so
that only shows no difference, not a working solve.

I also ran it against an Anna's Archive search page on both versions.
Both returned the full results page, but the log shows no bypass
attempts, so that mirror didn't serve a challenge from where I ran it
and the solver itself wasn't exercised.

@calibrain your call on if we should update to this, it is minor bump to
what has already been pushed.
2026-10-30 14:22:43 -04:00
splitsec2 cd5a478831 refactor: move the onboarding routes into core/onboarding_routes.py (#1594)
First of the route moves from Discussion #1536, following the plan table
there: the three onboarding routes (`GET` and `POST /api/onboarding`,
`POST /api/onboarding/skip`) leave `main.py` for
`core/onboarding_routes.py`, registered with
`register_onboarding_routes(app, login_required)` the way
`release_inspect_routes` takes it. `main.py` goes down by 72 lines and
the handler bodies are the same code (I diffed them after de-indenting:
the only difference is the local name of the error tuple).

There are two commits so the move can be reviewed on its own. The first
adds 15 tests for these routes, which had none, and they pass on current
`main` before anything moves. They pin the behaviour I most wanted to
keep: a 401 without a session when auth is on, a 403 for a signed-in
non-admin (that check lives in `login_required` and goes by path, which
is why the same decorator has to be passed in), the 400 on an empty
body, the result passed through on success and failure, the 500 with the
error text on an operational error, and open access when no auth is
configured. The second commit is the move, and no test changed in it.

What I checked on the move:

- The Flask URL map (every rule, its methods and its endpoint name) is
identical before and after: 77 rules, the three onboarding ones
included.
- Full suite, ruff and basedpyright are clean.
- I ran the app from this branch and stepped through the setup wizard in
a browser. It loads its steps from the moved route and goes from Search
Mode to Metadata Provider, and `POST /api/onboarding/skip` and the
empty-body 400 answer as before.

Two small things that do change. The log lines for these routes now come
from `shelfmark.core.onboarding_routes` instead of `main`, and the error
tuple is a local copy (`_ONBOARDING_ERRORS`, the same classes as
`_IMPORT_OPERATIONAL_ERRORS`) so the module does not import `main`.
Nothing else is different.
2026-10-30 12:10:04 -06:00
splitsec2 69cbf72698 refactor: move the settings routes into core/settings_routes.py (#1595)
Second route move from the plan in Discussion #1536: the four settings
routes (`GET /api/settings`, `GET` and `PUT /api/settings/<tab>`, and
`POST /api/settings/<tab>/action/<key>`) go from `main.py` to
`core/settings_routes.py`, registered with
`register_settings_routes(app, login_required)`. `main.py` is 143 lines
shorter. These handlers call `settings_registry` directly, so nothing
else has to be passed in. The handler bodies are the same code, and the
only difference I found after de-indenting them is that `ruff format`
wrapped one signature that no longer fits on a line.

Same two-commit layout as the onboarding one (#1594). The first commit
adds 27 tests for these routes and they pass on current `main` before
anything moves. They pin the 404 for an unknown tab, the 400 when a
`PUT` body is not a JSON object (a list, a string, a number, or no body
at all), the "No changes to save" answer for an empty object, the
unsaved form values reaching an action, the result passed through with a
400 on failure, the 500 with the error text on an operational error, a
401 without a session, a 403 for a signed-in non-admin on all four
routes, and open access with no auth. The second commit is the move and
no test changed in it. The admin check for these paths lives in
`login_required`, so the same decorator is passed in.

What I checked:

- The Flask URL map (every rule, its methods and its endpoint name) is
identical before and after, all 77 rules.
- Full suite, ruff and basedpyright are clean.
- I ran the app from this branch and opened Settings in a browser: the
modal lists every tab and the General tab shows its values, which come
from the moved `GET`. Over HTTP, a `PUT` of a new search page title
saved and read back, a list body got the 400 and an unknown tab the 404.

As with #1594, log lines for these routes now come from
`shelfmark.core.settings_routes`, and the error tuple is a local copy
(`_SETTINGS_ERRORS`) so the module does not import `main`. The two PRs
touch neighbouring lines of `main.py` and I checked that they merge
together without a conflict, in either order.
2026-10-30 12:08:00 -06:00
dependabot[bot] b2e3c1faf1 build(deps): bump python from 3.14.8-slim to 3.14.9-slim (#1610)
Bumps python from 3.14.8-slim to 3.14.9-slim.


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=python&package-manager=docker&previous-version=3.14.8-slim&new-version=3.14.9-slim)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-30 01:56:56 -04:00
dependabot[bot] 7bf6c8263b build(deps-dev): bump the npm-deps group in /src/frontend with 5 updates (#1611)
Bumps the npm-deps group in /src/frontend with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [knip](https://github.com/webpro-nl/knip/tree/HEAD/packages/knip) |
`6.42.1` | `6.43.0` |
| [oxfmt](https://github.com/oxc-project/oxc/tree/HEAD/npm/oxfmt) |
`0.74.0` | `0.75.0` |
| [oxlint](https://github.com/oxc-project/oxc/tree/HEAD/npm/oxlint) |
`1.89.0` | `1.90.0` |
| [oxlint-tsgolint](https://github.com/oxc-project/tsgolint) |
`7.0.2004` | `7.0.2005` |
| [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) |
`8.3.4` | `8.3.5` |

Updates `knip` from 6.42.1 to 6.43.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/webpro-nl/knip/releases">knip's
releases</a>.</em></p>
<blockquote>
<h2>Release 6.43.0</h2>
<ul>
<li>Document and pin exports that only keep each other alive (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/2160">#2160</a>)
(39af70abb32523a992a7d6152b8cd95ef317f237)</li>
<li>Don't add config files without an extension as entry files (resolve
<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/2168">#2168</a>)
(46a825ddf15d3073b899ed6ef34689e5da5508f2)</li>
<li>Recognize unscoped ~name workspace packages (resolve <a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/2172">#2172</a>)
(ba527f7386e7741507f2f18d84864058e02ac907)</li>
<li>Follow imports and re-exports in ambient modules (resolve <a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/2174">#2174</a>)
(dbd3a8b8b0429433e5385371c09e805b808a32c2) - thanks <a
href="https://github.com/tlq5l"><code>@​tlq5l</code></a>!</li>
<li>Follow <code>@reference</code> in Tailwind CSS compiler (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/2177">#2177</a>)
(219f16de95e174cdcfd6a90782bcef13cf79bd64) - thanks <a
href="https://github.com/mkantautas"><code>@​mkantautas</code></a>!</li>
<li>Support <code>{ find, replacement }</code> array form of Vite
<code>alias</code> (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/2179">#2179</a>)
(5d0779bc4cf8c0469c50d5b2cda1a6bd1f053d81) - thanks <a
href="https://github.com/mkantautas"><code>@​mkantautas</code></a>!</li>
<li>fix(expo): treat local config plugins as entry files (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/2176">#2176</a>)
(100ef491509a88b00ea9956ba40dbc1b0ac0c205) - thanks <a
href="https://github.com/Cayan"><code>@​Cayan</code></a>!</li>
<li>fix(next): detect Turbopack loaders in shared config factories (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/2161">#2161</a>)
(9cf928be5022928a38c12fe8001cec7bf467040c) - thanks <a
href="https://github.com/jakeleventhal"><code>@​jakeleventhal</code></a>!</li>
<li>Ignore osascript as global binary (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/2182">#2182</a>)
(c301e44c7975442d4d25595f084e6b853f07a434) - thanks <a
href="https://github.com/abrahamguo"><code>@​abrahamguo</code></a>!</li>
<li>Skip <code>--fix</code> for exports in multi-declarator variable
statements (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/2178">#2178</a>)
(326afd9c1e66eef04d986b83ed829b506f506c48) - thanks <a
href="https://github.com/mkantautas"><code>@​mkantautas</code></a>!</li>
<li>Watch the project directory instead of process.cwd() (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/2183">#2183</a>)
(16d9932d0239f649cf2c1349cc7bc893850cd4f0) - thanks <a
href="https://github.com/abrahamguo"><code>@​abrahamguo</code></a>!</li>
<li>Follow directory paths in tsconfig <code>references</code> (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/2186">#2186</a>)
(d741c46e3f2a9caaf6bf4e81e9d4c8cfca48623e) - thanks <a
href="https://github.com/mkantautas"><code>@​mkantautas</code></a>!</li>
<li>Handle <code>@plugin</code> options blocks in Tailwind CSS compiler
(<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/2187">#2187</a>)
(9fae773eb75bcba03e62f44ce3e9aa0b889bf4ac) - thanks <a
href="https://github.com/mkantautas"><code>@​mkantautas</code></a>!</li>
<li>Remove anonymous default-exported functions and classes in
<code>--fix</code> (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/2188">#2188</a>)
(6748259fbb2ea9a5940ea3861626f77677610a86) - thanks <a
href="https://github.com/mkantautas"><code>@​mkantautas</code></a>!</li>
<li>Recognize bun fmt as a built-in command (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/2189">#2189</a>)
(e971b0924bcb7ff8dcab01a180d3016cc08b675d) - thanks <a
href="https://github.com/TomasHubelbauer"><code>@​TomasHubelbauer</code></a>!</li>
<li>Add plugin for <code>@​bufbuild/buf</code> (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/2142">#2142</a>)
(90216c261c2273967125669beb611bf763d762c7) - thanks <a
href="https://github.com/ryanquinn3"><code>@​ryanquinn3</code></a>!</li>
<li>Pass <code>isSsrBuild</code> to Vite config functions (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/2191">#2191</a>)
(d2aa101c55e5d7e8d26548808ce008b214622099) - thanks <a
href="https://github.com/mkantautas"><code>@​mkantautas</code></a>!</li>
<li>Follow <code>src</code> of <code>&lt;script&gt;</code> and
<code>&lt;style&gt;</code> blocks in Vue SFCs (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/2193">#2193</a>)
(3d148393d5129a096a182fab36a873b9f710f388) - thanks <a
href="https://github.com/mkantautas"><code>@​mkantautas</code></a>!</li>
<li>Remove import attributes with emptied re-exports in
<code>--fix</code> (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/2192">#2192</a>)
(231026cf9c21cc7890f21d048f4af6ea7233d7b8) - thanks <a
href="https://github.com/mkantautas"><code>@​mkantautas</code></a>!</li>
<li>Update npmx.dev snapshot
(b2cc439006ec98ff5bbc1c99b99bc1ac5203b6b2)</li>
<li>Read string <code>parserOptions.parser</code> in ESLint flat configs
(<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/2198">#2198</a>)
(302f908aa135669d6fe96869ec6452b7570856a4) - thanks <a
href="https://github.com/mkantautas"><code>@​mkantautas</code></a>!</li>
<li>Resolve directory matches in Vitest <code>test.projects</code> to
their config (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/2195">#2195</a>)
(4d386138011c27e01e6e910be6d58266e07c9cf1) - thanks <a
href="https://github.com/fixfon"><code>@​fixfon</code></a>!</li>
<li>Ignore custom elements named <code>script-*</code> when extracting
script blocks (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/2199">#2199</a>)
(23e6479b233e1882ddaf29736390309d0f3f040f) - thanks <a
href="https://github.com/mkantautas"><code>@​mkantautas</code></a>!</li>
<li>feat(mcp): add MCP plugin (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/2180">#2180</a>)
(fc92470a9f687e2f1da60b84612ebf3e59a8bbb9) - thanks <a
href="https://github.com/jakeleventhal"><code>@​jakeleventhal</code></a>!</li>
<li>Handle non-Error plugin config failures
(8f21ea2182fac5a96edd7d6d4280a0fa1051e434)</li>
<li>Update articles list (6569cdcde1a79a6196a35a934b6c0d9d0e23faa4)</li>
<li>Skip <code>--fix</code> export ranges inside a larger removal
(204a8091baf91cb8cfb4e7a9aa70d461cc926baa)</li>
<li>Detect <code>.travis.yml</code> with a stat instead of a glob
(3601c6e32afef3d1d76a3944e540225da5190b9b)</li>
<li>Mark YAML catalog entries fixed only when their line is removed (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/2201">#2201</a>)
(813fa30e55ef3a8ed749d9d6d5a02a00810cfe72) - thanks <a
href="https://github.com/mkantautas"><code>@​mkantautas</code></a>!</li>
<li>Add Electron Forge plugin (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/2158">#2158</a>)
(12e4355a43ea63c417d3b9ebfbbac1c8510b139e) - thanks <a
href="https://github.com/mehdimirzafaruk"><code>@​mehdimirzafaruk</code></a>!</li>
<li>Resolve function and promise entries in Vitest
<code>test.projects</code> (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/2197">#2197</a>)
(ec293d1a33d30a8b0521725d1148e6e72c6e4220) - thanks <a
href="https://github.com/mkantautas"><code>@​mkantautas</code></a>!</li>
<li>Follow npm lifecycle scripts and run-script aliases (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/2202">#2202</a>)
(89dfdc881e6865aef326c2b9dc700cf5c46b73b4) - thanks <a
href="https://github.com/sushanta-neupane"><code>@​sushanta-neupane</code></a>!</li>
<li>Follow pnpm <code>t</code>, <code>tst</code> and
<code>run-script</code> aliases
(ce91e230e0823433dfcc1ee4562335c34d2b73ef)</li>
<li>Treat <code>vitest-environment-nuxt</code> as optional (it comes
with <code>@nuxt/test-utils</code>)
(db9aa7443c5b3839df5c0fe320d78ea42f0f3446)</li>
<li>Ignore tool output before the first report section in ecosystem
snapshots (9434bf678e60d16832f13e892d7c1ebc2b9e6ed1)</li>
<li>Update dependencies (21c3b75fc4ae94208311abb630ff129fcd9fe820)</li>
<li>Bump <code>engines.node</code> to follow Astro's
(9d7a5e07212b093f9d422cab813fad5d01273fc6)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/webpro-nl/knip/commit/07121567e60b73d1e640f395028c525a2b1d9778"><code>0712156</code></a>
Release knip@6.43.0</li>
<li><a
href="https://github.com/webpro-nl/knip/commit/21c3b75fc4ae94208311abb630ff129fcd9fe820"><code>21c3b75</code></a>
Update dependencies</li>
<li><a
href="https://github.com/webpro-nl/knip/commit/db9aa7443c5b3839df5c0fe320d78ea42f0f3446"><code>db9aa74</code></a>
Treat <code>vitest-environment-nuxt</code> as optional (it comes with
<code>@nuxt/test-utils</code>)</li>
<li><a
href="https://github.com/webpro-nl/knip/commit/ce91e230e0823433dfcc1ee4562335c34d2b73ef"><code>ce91e23</code></a>
Follow pnpm <code>t</code>, <code>tst</code> and <code>run-script</code>
aliases</li>
<li><a
href="https://github.com/webpro-nl/knip/commit/89dfdc881e6865aef326c2b9dc700cf5c46b73b4"><code>89dfdc8</code></a>
Follow npm lifecycle scripts and run-script aliases (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/2202">#2202</a>)</li>
<li><a
href="https://github.com/webpro-nl/knip/commit/ec293d1a33d30a8b0521725d1148e6e72c6e4220"><code>ec293d1</code></a>
Resolve function and promise entries in Vitest
<code>test.projects</code> (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/2197">#2197</a>)</li>
<li><a
href="https://github.com/webpro-nl/knip/commit/12e4355a43ea63c417d3b9ebfbbac1c8510b139e"><code>12e4355</code></a>
Add Electron Forge plugin (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/2158">#2158</a>)</li>
<li><a
href="https://github.com/webpro-nl/knip/commit/813fa30e55ef3a8ed749d9d6d5a02a00810cfe72"><code>813fa30</code></a>
Mark YAML catalog entries fixed only when their line is removed (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/2201">#2201</a>)</li>
<li><a
href="https://github.com/webpro-nl/knip/commit/3601c6e32afef3d1d76a3944e540225da5190b9b"><code>3601c6e</code></a>
Detect <code>.travis.yml</code> with a stat instead of a glob</li>
<li><a
href="https://github.com/webpro-nl/knip/commit/204a8091baf91cb8cfb4e7a9aa70d461cc926baa"><code>204a809</code></a>
Skip <code>--fix</code> export ranges inside a larger removal</li>
<li>Additional commits viewable in <a
href="https://github.com/webpro-nl/knip/commits/knip@6.43.0/packages/knip">compare
view</a></li>
</ul>
</details>
<br />

Updates `oxfmt` from 0.74.0 to 0.75.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/oxc-project/oxc/releases">oxfmt's
releases</a>.</em></p>
<blockquote>
<h2>oxfmt v0.75.0</h2>
<h3>🐛 Bug Fixes</h3>
<ul>
<li>5042019 formatter: Keep fill layout for array with comment after [
(<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxfmt/issues/28170">#28170</a>)
(leaysgur)</li>
<li>9d37ff6 formatter: Use position-based comment checks for concise
arrays (<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxfmt/issues/28169">#28169</a>)
(leaysgur)</li>
<li>016c4a2 formatter: Keep a comment before <code>}</code> inside a JSX
spread child (<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxfmt/issues/28103">#28103</a>)
(vidigoat)</li>
<li>190bb1e formatter: Keep parens around an instantiation expression
ending an operand through any tight parent (<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxfmt/issues/28168">#28168</a>)
(leaysgur)</li>
<li>a5314a1 formatter: Keep <code>;</code> before <code>in</code> and
<code>instanceof</code> class members (<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxfmt/issues/28166">#28166</a>)
(leaysgur)</li>
<li>3a56e7c formatter: Keep closing HTML comments at the start of a line
(<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxfmt/issues/28064">#28064</a>)
(Cameron)</li>
<li>23d23d6 formatter_markdown: Honor range ignore inside directives (<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxfmt/issues/28164">#28164</a>)
(leaysgur)</li>
<li>5f1fd3d formatter: Measure width heuristics by display width (<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxfmt/issues/28098">#28098</a>)
(leaysgur)</li>
<li>a5a52cf formatter: Keep parens around private <code>in</code>
expressions (<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxfmt/issues/28096">#28096</a>)
(leaysgur)</li>
<li>999496e formatter: Measure a short key by its display width (<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxfmt/issues/28026">#28026</a>)
(vidigoat)</li>
<li>7e9aa44 formatter: Keep parens around a looser operand of an
instantiation expression (<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxfmt/issues/28025">#28025</a>)
(vidigoat)</li>
<li>6912d1f formatter: Keep an arrow signature that exactly fills the
line for any body (<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxfmt/issues/27989">#27989</a>)
(leaysgur)</li>
<li>eb1d9f9 formatter_core: Count a flat <code>line</code> space in
<code>fits</code> only when text follows (<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxfmt/issues/27987">#27987</a>)
(leaysgur)</li>
</ul>
<h3>⚡ Performance</h3>
<ul>
<li>1ed93af data_structures: Copy short strings without a memcpy call
(<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxfmt/issues/27953">#27953</a>)
(leaysgur)</li>
<li>7948f0b formatter_core: Shrink <code>FormatElement</code> to 16B (<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxfmt/issues/28012">#28012</a>)
(leaysgur)</li>
<li>788af22 formatter: Keep <code>AstNode</code>s on the stack, and only
chain links in the arena (<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxfmt/issues/27963">#27963</a>)
(leaysgur)</li>
</ul>
<h3>📚 Documentation</h3>
<ul>
<li>068a8ea formatter: Fix up wording (<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxfmt/issues/28167">#28167</a>)
(leaysgur)</li>
<li>db55461 formatter_core: Document text width divergence (<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxfmt/issues/28095">#28095</a>)
(leaysgur)</li>
<li>880d229 formatter: Add vitest-test-call to known divergences (<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxfmt/issues/28006">#28006</a>)
(leaysgur)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/oxc-project/oxc/commit/9b6fff42fa6edf0bec55861b6f0764c7b9acd86b"><code>9b6fff4</code></a>
release(apps): oxlint v1.90.0 &amp;&amp; oxfmt v0.75.0 (<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxfmt/issues/28191">#28191</a>)</li>
<li><a
href="https://github.com/oxc-project/oxc/commit/3e7f0f5b73dfa921167061578afcfea31645eca5"><code>3e7f0f5</code></a>
chore(oxfmt): bump prettier-plugin-astro to 1.1.2 (<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxfmt/issues/28162">#28162</a>)</li>
<li>See full diff in <a
href="https://github.com/oxc-project/oxc/commits/oxfmt_v0.75.0/npm/oxfmt">compare
view</a></li>
</ul>
</details>
<br />

Updates `oxlint` from 1.89.0 to 1.90.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/oxc-project/oxc/releases">oxlint's
releases</a>.</em></p>
<blockquote>
<h2>oxlint v1.90.0</h2>
<h3>🚀 Features</h3>
<ul>
<li>cf34678 oxlint: Export <code>Oxlintrc</code> type (<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxlint/issues/28132">#28132</a>)
(Sysix)</li>
<li>831cdf1 oxlint: Require mininum oxlint-tsgolint version v7.0.2005
(<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxlint/issues/28118">#28118</a>)
(camc314)</li>
<li>d1b00f4 linter/typescript: Implement no-unsafe-enum-assignment rule
(<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxlint/issues/28117">#28117</a>)
(camc314)</li>
<li>165c91f linter/typescript/await-thenable: Support
<code>allowMixedPromiseArrays</code> option (<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxlint/issues/28116">#28116</a>)
(camc314)</li>
</ul>
<h3>🐛 Bug Fixes</h3>
<ul>
<li>7f3c908 linter/eslint/array-callback-return: Check callbacks passed
with extra arguments (<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxlint/issues/28133">#28133</a>)
(sarankumar)</li>
<li>53be530 linter: Filter by type aware rules when looking up tsgolint
rule severity (<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxlint/issues/28138">#28138</a>)
(NavpreetSSidhu)</li>
<li>e0f8937 react-compiler: Compile a <code>try</code> whose
<code>catch</code> is unreachable instead of panicking (<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxlint/issues/28066">#28066</a>)
(Dunqing)</li>
<li>f5b625f linter/eslint/no-useless-concat: See through parenthesized
expressions (<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxlint/issues/27984">#27984</a>)
(Rahul Kashyap)</li>
<li>4629bb2 linter/jest/no-conditional-expect: Check function expression
callbacks (<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxlint/issues/28055">#28055</a>)
(camc314)</li>
<li>5c84098 semantic,linter: Report names with lone surrogates in enum
and lint checks (<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxlint/issues/27991">#27991</a>)
(Dunqing)</li>
<li>f3705a9 linter/eslint/prefer-const: Skip fixers if any declarator is
reassigned (<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxlint/issues/28008">#28008</a>)
(Prince Jain)</li>
<li>4c0fa90 minifier,linter: Keep <code>delete</code> of constant
members and later JSX keys (<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxlint/issues/27990">#27990</a>)
(Dunqing)</li>
<li>0298062 linter/arrow-body-style: Keep type assertions when adding a
block body (<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxlint/issues/27978">#27978</a>)
(Yan Almeida)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/oxc-project/oxc/blob/main/npm/oxlint/CHANGELOG.md">oxlint's
changelog</a>.</em></p>
<blockquote>
<h2>[1.90.0] - 2026-10-27</h2>
<h3>🚀 Features</h3>
<ul>
<li>831cdf1 oxlint: Require mininum oxlint-tsgolint version v7.0.2005
(<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxlint/issues/28118">#28118</a>)
(camc314)</li>
<li>d1b00f4 linter/typescript: Implement no-unsafe-enum-assignment rule
(<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxlint/issues/28117">#28117</a>)
(camc314)</li>
<li>165c91f linter/typescript/await-thenable: Support
<code>allowMixedPromiseArrays</code> option (<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxlint/issues/28116">#28116</a>)
(camc314)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/oxc-project/oxc/commit/9b6fff42fa6edf0bec55861b6f0764c7b9acd86b"><code>9b6fff4</code></a>
release(apps): oxlint v1.90.0 &amp;&amp; oxfmt v0.75.0 (<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxlint/issues/28191">#28191</a>)</li>
<li><a
href="https://github.com/oxc-project/oxc/commit/831cdf19d4070d39128e771a926562280911e490"><code>831cdf1</code></a>
feat(oxlint): require mininum oxlint-tsgolint version v7.0.2005 (<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxlint/issues/28118">#28118</a>)</li>
<li><a
href="https://github.com/oxc-project/oxc/commit/d1b00f45ec3e44ed2ff6815ee8597615e532e681"><code>d1b00f4</code></a>
feat(linter/typescript): implement no-unsafe-enum-assignment rule (<a
href="https://github.com/oxc-project/oxc/tree/HEAD/npm/oxlint/issues/28117">#28117</a>)</li>
<li><a
href="https://github.com/oxc-project/oxc/commit/165c91f9c1021a4fac3da5fe6f794ee627a0d988"><code>165c91f</code></a>
feat(linter/typescript/await-thenable): support
<code>allowMixedPromiseArrays</code> opt...</li>
<li>See full diff in <a
href="https://github.com/oxc-project/oxc/commits/oxlint_v1.90.0/npm/oxlint">compare
view</a></li>
</ul>
</details>
<br />

Updates `oxlint-tsgolint` from 7.0.2004 to 7.0.2005
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/oxc-project/tsgolint/releases">oxlint-tsgolint's
releases</a>.</em></p>
<blockquote>
<h2>v7.0.2005</h2>
<h2>What's Changed</h2>
<ul>
<li>chore(deps): update github actions by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/oxc-project/tsgolint/pull/1273">oxc-project/tsgolint#1273</a></li>
<li>chore(deps): update gomod by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/oxc-project/tsgolint/pull/1274">oxc-project/tsgolint#1274</a></li>
<li>chore(deps): update npm packages by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/oxc-project/tsgolint/pull/1275">oxc-project/tsgolint#1275</a></li>
<li>chore(deps): update oxc-project/security-action action to v1.0.9 by
<a href="https://github.com/renovate"><code>@​renovate</code></a>[bot]
in <a
href="https://redirect.github.com/oxc-project/tsgolint/pull/1276">oxc-project/tsgolint#1276</a></li>
<li>fix(unbound-method): respect <code>this: void</code> on class
properties by <a
href="https://github.com/baevm"><code>@​baevm</code></a> in <a
href="https://redirect.github.com/oxc-project/tsgolint/pull/1277">oxc-project/tsgolint#1277</a></li>
<li>docs(security): inherit organization security policy by <a
href="https://github.com/Boshen"><code>@​Boshen</code></a> in <a
href="https://redirect.github.com/oxc-project/tsgolint/pull/1295">oxc-project/tsgolint#1295</a></li>
<li>chore(deps): update npm packages by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/oxc-project/tsgolint/pull/1301">oxc-project/tsgolint#1301</a></li>
<li>fix(no-deprecated): avoid infinite loop on circular alias chains by
<a href="https://github.com/magurotuna"><code>@​magurotuna</code></a> in
<a
href="https://redirect.github.com/oxc-project/tsgolint/pull/1309">oxc-project/tsgolint#1309</a></li>
<li>feat(await-thenable): add allowMixedPromiseArrays option by <a
href="https://github.com/camc314"><code>@​camc314</code></a> in <a
href="https://redirect.github.com/oxc-project/tsgolint/pull/1307">oxc-project/tsgolint#1307</a></li>
<li>chore: remove <code>update-typescript-go.yml</code> by <a
href="https://github.com/camc314"><code>@​camc314</code></a> in <a
href="https://redirect.github.com/oxc-project/tsgolint/pull/1311">oxc-project/tsgolint#1311</a></li>
<li>ci: pin just version in setup and autofix by <a
href="https://github.com/camc314"><code>@​camc314</code></a> in <a
href="https://redirect.github.com/oxc-project/tsgolint/pull/1312">oxc-project/tsgolint#1312</a></li>
<li>fix(no-unnecessary-type-parameters): count generic type arguments by
<a href="https://github.com/farnoodma"><code>@​farnoodma</code></a> in
<a
href="https://redirect.github.com/oxc-project/tsgolint/pull/1297">oxc-project/tsgolint#1297</a></li>
<li>feat(no-unsafe-enum-assignment): add rule by <a
href="https://github.com/camc314"><code>@​camc314</code></a> in <a
href="https://redirect.github.com/oxc-project/tsgolint/pull/1316">oxc-project/tsgolint#1316</a></li>
<li>fix(require-array-sort-compare): report tuples by <a
href="https://github.com/baevm"><code>@​baevm</code></a> in <a
href="https://redirect.github.com/oxc-project/tsgolint/pull/1317">oxc-project/tsgolint#1317</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/magurotuna"><code>@​magurotuna</code></a> made
their first contribution in <a
href="https://redirect.github.com/oxc-project/tsgolint/pull/1309">oxc-project/tsgolint#1309</a></li>
<li><a href="https://github.com/farnoodma"><code>@​farnoodma</code></a>
made their first contribution in <a
href="https://redirect.github.com/oxc-project/tsgolint/pull/1297">oxc-project/tsgolint#1297</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/oxc-project/tsgolint/compare/v7.0.2004...v7.0.2005">https://github.com/oxc-project/tsgolint/compare/v7.0.2004...v7.0.2005</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/oxc-project/tsgolint/commit/4ebf80fd2b166cba4890c6896220fec4a1462b29"><code>4ebf80f</code></a>
fix(require-array-sort-compare): report tuples (<a
href="https://redirect.github.com/oxc-project/tsgolint/issues/1317">#1317</a>)</li>
<li><a
href="https://github.com/oxc-project/tsgolint/commit/62e97c915725ca2263508dc91639669609bd4360"><code>62e97c9</code></a>
feat(no-unsafe-enum-assignment): add rule (<a
href="https://redirect.github.com/oxc-project/tsgolint/issues/1316">#1316</a>)</li>
<li><a
href="https://github.com/oxc-project/tsgolint/commit/e649c1ef6384513cb481a928218da8e5488ece22"><code>e649c1e</code></a>
fix(no-unnecessary-type-parameters): count generic type arguments (<a
href="https://redirect.github.com/oxc-project/tsgolint/issues/1297">#1297</a>)</li>
<li><a
href="https://github.com/oxc-project/tsgolint/commit/e3337870400c17398f56a545c29470015eb033d1"><code>e333787</code></a>
ci: pin just version in setup and autofix (<a
href="https://redirect.github.com/oxc-project/tsgolint/issues/1312">#1312</a>)</li>
<li><a
href="https://github.com/oxc-project/tsgolint/commit/bcab203a3b22c1701580b84f69ecb49fa3d45ed3"><code>bcab203</code></a>
chore: remove <code>update-typescript-go.yml</code> (<a
href="https://redirect.github.com/oxc-project/tsgolint/issues/1311">#1311</a>)</li>
<li><a
href="https://github.com/oxc-project/tsgolint/commit/bb8225c110f9288c92ed92881337c43a48fe1b11"><code>bb8225c</code></a>
feat(await-thenable): add allowMixedPromiseArrays option (<a
href="https://redirect.github.com/oxc-project/tsgolint/issues/1307">#1307</a>)</li>
<li><a
href="https://github.com/oxc-project/tsgolint/commit/086f19a14d1a8184c3607027e1dfb5c0e640e48f"><code>086f19a</code></a>
fix(no-deprecated): avoid infinite loop on circular alias chains (<a
href="https://redirect.github.com/oxc-project/tsgolint/issues/1309">#1309</a>)</li>
<li><a
href="https://github.com/oxc-project/tsgolint/commit/a18037134a44ca331e0e2451e50b2dd2e374acb3"><code>a180371</code></a>
chore(deps): update npm packages (<a
href="https://redirect.github.com/oxc-project/tsgolint/issues/1301">#1301</a>)</li>
<li><a
href="https://github.com/oxc-project/tsgolint/commit/8897346fff24a9bd0c719099dc1af8e7200572c1"><code>8897346</code></a>
docs(security): inherit organization security policy (<a
href="https://redirect.github.com/oxc-project/tsgolint/issues/1295">#1295</a>)</li>
<li><a
href="https://github.com/oxc-project/tsgolint/commit/69698fe8ebe234009db8a207cc84f1722c7bffb8"><code>69698fe</code></a>
fix(unbound-method): respect <code>this: void</code> on class properties
(<a
href="https://redirect.github.com/oxc-project/tsgolint/issues/1277">#1277</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/oxc-project/tsgolint/compare/v7.0.2004...v7.0.2005">compare
view</a></li>
</ul>
</details>
<br />

Updates `vite` from 8.3.4 to 8.3.5
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/vitejs/vite/releases">vite's
releases</a>.</em></p>
<blockquote>
<h2>v8.3.5</h2>
<h3>Bug Fixes</h3>
<ul>
<li><strong>build:</strong> handle missing chunk import maps (<a
href="https://redirect.github.com/vitejs/vite/issues/23777">#23777</a>)
(<a
href="https://github.com/vitejs/vite/commit/8d7623d9b5647714a5b20cbd787a5401ca846229">8d7623d</a>)</li>
<li><strong>build:</strong> include preload dependencies to chunk import
map hashing (<a
href="https://redirect.github.com/vitejs/vite/issues/23793">#23793</a>)
(<a
href="https://github.com/vitejs/vite/commit/4d16e7c14d5e1c361f148238b1e81131238ab8e9">4d16e7c</a>)</li>
<li><strong>bundled-dev:</strong> apply <code>server.origin</code> to
asset URLs (<a
href="https://redirect.github.com/vitejs/vite/issues/23683">#23683</a>)
(<a
href="https://github.com/vitejs/vite/commit/52ba877693c8633458d163117504a8259beb3cf5">52ba877</a>)</li>
<li><strong>bundled-dev:</strong> declare utf-8 charset in fallback page
(<a
href="https://redirect.github.com/vitejs/vite/issues/23846">#23846</a>)
(<a
href="https://github.com/vitejs/vite/commit/197daf6c4c7bfdaa005bebcc41dd2ff22fa3a5b6">197daf6</a>)</li>
<li><strong>bundled-dev:</strong> ignore build.chunkImportMap (<a
href="https://redirect.github.com/vitejs/vite/issues/23685">#23685</a>)
(<a
href="https://github.com/vitejs/vite/commit/cfe917d67d279a13f20ae9449e3befa736b64b07">cfe917d</a>)</li>
<li><strong>bundled-dev:</strong> include user
<code>import.meta.env.*</code> defines in the
<code>import.meta.env</code> object (<a
href="https://redirect.github.com/vitejs/vite/issues/23713">#23713</a>)
(<a
href="https://github.com/vitejs/vite/commit/6019aa79975465516da7c6f532d568422b019a25">6019aa7</a>)</li>
<li><strong>bundled-dev:</strong> map forwarded error stacks through the
bundle source maps (<a
href="https://redirect.github.com/vitejs/vite/issues/23741">#23741</a>)
(<a
href="https://github.com/vitejs/vite/commit/11fe1e46ff0c136cb90fbe263ba03993bc94df18">11fe1e4</a>)</li>
<li><strong>bundled-dev:</strong> normalize served output files (<a
href="https://redirect.github.com/vitejs/vite/issues/23684">#23684</a>)
(<a
href="https://github.com/vitejs/vite/commit/df4e02cc8317a62f21edefc79a9690571ffed1f3">df4e02c</a>)</li>
<li><strong>bundled-dev:</strong> stop hmr propagation at modules that
are no longer imported (<a
href="https://redirect.github.com/vitejs/vite/issues/23839">#23839</a>)
(<a
href="https://github.com/vitejs/vite/commit/7471e8c3b32d3d55243590bb7713e602c9fb0212">7471e8c</a>)</li>
<li><strong>css:</strong> don't fail on a literal <code>%</code> in
<code>url()</code> (<a
href="https://redirect.github.com/vitejs/vite/issues/23676">#23676</a>)
(<a
href="https://github.com/vitejs/vite/commit/50b382d31835b8b4bc8b6964738ac03146e44261">50b382d</a>)</li>
<li><strong>deps:</strong> update all non-major dependencies (<a
href="https://redirect.github.com/vitejs/vite/issues/23731">#23731</a>)
(<a
href="https://github.com/vitejs/vite/commit/cf80aa552cac02eac0293330ccd5fde3c7ae8d29">cf80aa5</a>)</li>
<li><strong>deps:</strong> update all non-major dependencies (<a
href="https://redirect.github.com/vitejs/vite/issues/23826">#23826</a>)
(<a
href="https://github.com/vitejs/vite/commit/77d8373510da1b26ce057eb2248e570b7f63fde9">77d8373</a>)</li>
<li><strong>deps:</strong> update rolldown-related dependencies (<a
href="https://redirect.github.com/vitejs/vite/issues/23733">#23733</a>)
(<a
href="https://github.com/vitejs/vite/commit/43f0d052e514c3ad2dea2f7dc44b0720e1f62f48">43f0d05</a>)</li>
<li><strong>deps:</strong> update rolldown-related dependencies (<a
href="https://redirect.github.com/vitejs/vite/issues/23827">#23827</a>)
(<a
href="https://github.com/vitejs/vite/commit/c2e04187e49aab7ab809989f0537b4906653acab">c2e0418</a>)</li>
<li><strong>optimizer:</strong> fall back to yarn.lock for lockfile hash
(<a
href="https://redirect.github.com/vitejs/vite/issues/23667">#23667</a>)
(<a
href="https://github.com/vitejs/vite/commit/f20609630faa93026924275115d1426fdc08629e">f206096</a>)</li>
<li><strong>optimizer:</strong> scan <code>oxc.jsxInject</code> imports
(<a
href="https://redirect.github.com/vitejs/vite/issues/23758">#23758</a>)
(<a
href="https://github.com/vitejs/vite/commit/38f3cb45b1490ed24775547ceafa677b91a57714">38f3cb4</a>)</li>
<li><strong>optimizer:</strong> skip patches dir check for yarn.lock
fallback (<a
href="https://redirect.github.com/vitejs/vite/issues/23725">#23725</a>)
(<a
href="https://github.com/vitejs/vite/commit/8e890e1ce438bfbc07ea4931ce332e40589940fa">8e890e1</a>)</li>
<li><strong>optimizer:</strong> skip patches dir hash for nub lockfile
(<a
href="https://redirect.github.com/vitejs/vite/issues/23761">#23761</a>)
(<a
href="https://github.com/vitejs/vite/commit/a7d56967ef0050a09c0507e63a18164bc7a0d486">a7d5696</a>)</li>
<li><strong>resolve:</strong> support subpath imports with multiple
<code>#</code> (<a
href="https://redirect.github.com/vitejs/vite/issues/23631">#23631</a>)
(<a
href="https://github.com/vitejs/vite/commit/0d86b3485fbbd0fcb9a1f70a14adedfcb7a1fff1">0d86b34</a>)</li>
<li><strong>resolve:</strong> update resolve.exports to 2.0.4 (<a
href="https://redirect.github.com/vitejs/vite/issues/23739">#23739</a>)
(<a
href="https://github.com/vitejs/vite/commit/4ea708a3ae9a324c6aabca59fade4082bf72f3e5">4ea708a</a>)</li>
<li><strong>server:</strong> handle socket errors on upgrade requests
not taken by the HMR server (<a
href="https://redirect.github.com/vitejs/vite/issues/23728">#23728</a>)
(<a
href="https://github.com/vitejs/vite/commit/c2c9ef4dcd05b3e4d88844ea3a13dc23819ca2a5">c2c9ef4</a>)</li>
<li><strong>server:</strong> only strip base when path matches a full
segment (<a
href="https://redirect.github.com/vitejs/vite/issues/23641">#23641</a>)
(<a
href="https://github.com/vitejs/vite/commit/3dfde87b90a9f80b125d710e3e5d4fc795662db6">3dfde87</a>)</li>
</ul>
<h3>Performance Improvements</h3>
<ul>
<li><strong>ssr:</strong> extract inline source maps without a regexp
(<a
href="https://redirect.github.com/vitejs/vite/issues/23775">#23775</a>)
(<a
href="https://github.com/vitejs/vite/commit/6a0278055d8501bbaf65b8d34ec094722b4e877a">6a02780</a>)</li>
</ul>
<h3>Miscellaneous Chores</h3>
<ul>
<li>migrate to Oxlint (<a
href="https://redirect.github.com/vitejs/vite/issues/23746">#23746</a>)
(<a
href="https://github.com/vitejs/vite/commit/5b73935881424ed5919571036dd89d3868590f92">5b73935</a>)</li>
</ul>
<h3>Code Refactoring</h3>
<ul>
<li><strong>deps:</strong> replace <code>@vercel/detect-agent</code>
with <code>std-env</code> (<a
href="https://redirect.github.com/vitejs/vite/issues/23744">#23744</a>)
(<a
href="https://github.com/vitejs/vite/commit/ce4293f15cc5cd221c5ed60f5cd64e82ca5cbaf5">ce4293f</a>)</li>
<li><strong>dev:</strong> consolidate moduleURL to file path utilities
(<a
href="https://redirect.github.com/vitejs/vite/issues/23828">#23828</a>)
(<a
href="https://github.com/vitejs/vite/commit/df7b40ee9d691e9f4e2413244f6665ef5482dce3">df7b40e</a>)</li>
<li><strong>dev:</strong> separate import resolution from URL conversion
(<a
href="https://redirect.github.com/vitejs/vite/issues/23791">#23791</a>)
(<a
href="https://github.com/vitejs/vite/commit/611668983d4b717f5e5e66cf9f7125bd94f92bf7">6116689</a>)</li>
<li><strong>dev:</strong> share ModuleURL and BrowserURL conversions (<a
href="https://redirect.github.com/vitejs/vite/issues/23790">#23790</a>)
(<a
href="https://github.com/vitejs/vite/commit/446954c69c806795c83fe2f97c28ae8f9ef83731">446954c</a>)</li>
<li><strong>dev:</strong> use ModuleURLs throughout HTML transforms (<a
href="https://redirect.github.com/vitejs/vite/issues/23815">#23815</a>)
(<a
href="https://github.com/vitejs/vite/commit/a16299092c0f0f3f90e05d4bb5f0168b293c2b52">a162990</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md">vite's
changelog</a>.</em></p>
<blockquote>
<h2><!-- raw HTML omitted --><a
href="https://github.com/vitejs/vite/compare/v8.3.4...v8.3.5">8.3.5</a>
(2026-10-21)<!-- raw HTML omitted --></h2>
<h3>Bug Fixes</h3>
<ul>
<li><strong>build:</strong> handle missing chunk import maps (<a
href="https://redirect.github.com/vitejs/vite/issues/23777">#23777</a>)
(<a
href="https://github.com/vitejs/vite/commit/8d7623d9b5647714a5b20cbd787a5401ca846229">8d7623d</a>)</li>
<li><strong>build:</strong> include preload dependencies to chunk import
map hashing (<a
href="https://redirect.github.com/vitejs/vite/issues/23793">#23793</a>)
(<a
href="https://github.com/vitejs/vite/commit/4d16e7c14d5e1c361f148238b1e81131238ab8e9">4d16e7c</a>)</li>
<li><strong>bundled-dev:</strong> apply <code>server.origin</code> to
asset URLs (<a
href="https://redirect.github.com/vitejs/vite/issues/23683">#23683</a>)
(<a
href="https://github.com/vitejs/vite/commit/52ba877693c8633458d163117504a8259beb3cf5">52ba877</a>)</li>
<li><strong>bundled-dev:</strong> declare utf-8 charset in fallback page
(<a
href="https://redirect.github.com/vitejs/vite/issues/23846">#23846</a>)
(<a
href="https://github.com/vitejs/vite/commit/197daf6c4c7bfdaa005bebcc41dd2ff22fa3a5b6">197daf6</a>)</li>
<li><strong>bundled-dev:</strong> ignore build.chunkImportMap (<a
href="https://redirect.github.com/vitejs/vite/issues/23685">#23685</a>)
(<a
href="https://github.com/vitejs/vite/commit/cfe917d67d279a13f20ae9449e3befa736b64b07">cfe917d</a>)</li>
<li><strong>bundled-dev:</strong> include user
<code>import.meta.env.*</code> defines in the
<code>import.meta.env</code> object (<a
href="https://redirect.github.com/vitejs/vite/issues/23713">#23713</a>)
(<a
href="https://github.com/vitejs/vite/commit/6019aa79975465516da7c6f532d568422b019a25">6019aa7</a>)</li>
<li><strong>bundled-dev:</strong> map forwarded error stacks through the
bundle source maps (<a
href="https://redirect.github.com/vitejs/vite/issues/23741">#23741</a>)
(<a
href="https://github.com/vitejs/vite/commit/11fe1e46ff0c136cb90fbe263ba03993bc94df18">11fe1e4</a>)</li>
<li><strong>bundled-dev:</strong> normalize served output files (<a
href="https://redirect.github.com/vitejs/vite/issues/23684">#23684</a>)
(<a
href="https://github.com/vitejs/vite/commit/df4e02cc8317a62f21edefc79a9690571ffed1f3">df4e02c</a>)</li>
<li><strong>bundled-dev:</strong> stop hmr propagation at modules that
are no longer imported (<a
href="https://redirect.github.com/vitejs/vite/issues/23839">#23839</a>)
(<a
href="https://github.com/vitejs/vite/commit/7471e8c3b32d3d55243590bb7713e602c9fb0212">7471e8c</a>)</li>
<li><strong>css:</strong> don't fail on a literal <code>%</code> in
<code>url()</code> (<a
href="https://redirect.github.com/vitejs/vite/issues/23676">#23676</a>)
(<a
href="https://github.com/vitejs/vite/commit/50b382d31835b8b4bc8b6964738ac03146e44261">50b382d</a>)</li>
<li><strong>deps:</strong> update all non-major dependencies (<a
href="https://redirect.github.com/vitejs/vite/issues/23731">#23731</a>)
(<a
href="https://github.com/vitejs/vite/commit/cf80aa552cac02eac0293330ccd5fde3c7ae8d29">cf80aa5</a>)</li>
<li><strong>deps:</strong> update all non-major dependencies (<a
href="https://redirect.github.com/vitejs/vite/issues/23826">#23826</a>)
(<a
href="https://github.com/vitejs/vite/commit/77d8373510da1b26ce057eb2248e570b7f63fde9">77d8373</a>)</li>
<li><strong>deps:</strong> update rolldown-related dependencies (<a
href="https://redirect.github.com/vitejs/vite/issues/23733">#23733</a>)
(<a
href="https://github.com/vitejs/vite/commit/43f0d052e514c3ad2dea2f7dc44b0720e1f62f48">43f0d05</a>)</li>
<li><strong>deps:</strong> update rolldown-related dependencies (<a
href="https://redirect.github.com/vitejs/vite/issues/23827">#23827</a>)
(<a
href="https://github.com/vitejs/vite/commit/c2e04187e49aab7ab809989f0537b4906653acab">c2e0418</a>)</li>
<li><strong>optimizer:</strong> fall back to yarn.lock for lockfile hash
(<a
href="https://redirect.github.com/vitejs/vite/issues/23667">#23667</a>)
(<a
href="https://github.com/vitejs/vite/commit/f20609630faa93026924275115d1426fdc08629e">f206096</a>)</li>
<li><strong>optimizer:</strong> scan <code>oxc.jsxInject</code> imports
(<a
href="https://redirect.github.com/vitejs/vite/issues/23758">#23758</a>)
(<a
href="https://github.com/vitejs/vite/commit/38f3cb45b1490ed24775547ceafa677b91a57714">38f3cb4</a>)</li>
<li><strong>optimizer:</strong> skip patches dir check for yarn.lock
fallback (<a
href="https://redirect.github.com/vitejs/vite/issues/23725">#23725</a>)
(<a
href="https://github.com/vitejs/vite/commit/8e890e1ce438bfbc07ea4931ce332e40589940fa">8e890e1</a>)</li>
<li><strong>optimizer:</strong> skip patches dir hash for nub lockfile
(<a
href="https://redirect.github.com/vitejs/vite/issues/23761">#23761</a>)
(<a
href="https://github.com/vitejs/vite/commit/a7d56967ef0050a09c0507e63a18164bc7a0d486">a7d5696</a>)</li>
<li><strong>resolve:</strong> support subpath imports with multiple
<code>#</code> (<a
href="https://redirect.github.com/vitejs/vite/issues/23631">#23631</a>)
(<a
href="https://github.com/vitejs/vite/commit/0d86b3485fbbd0fcb9a1f70a14adedfcb7a1fff1">0d86b34</a>)</li>
<li><strong>resolve:</strong> update resolve.exports to 2.0.4 (<a
href="https://redirect.github.com/vitejs/vite/issues/23739">#23739</a>)
(<a
href="https://github.com/vitejs/vite/commit/4ea708a3ae9a324c6aabca59fade4082bf72f3e5">4ea708a</a>)</li>
<li><strong>server:</strong> handle socket errors on upgrade requests
not taken by the HMR server (<a
href="https://redirect.github.com/vitejs/vite/issues/23728">#23728</a>)
(<a
href="https://github.com/vitejs/vite/commit/c2c9ef4dcd05b3e4d88844ea3a13dc23819ca2a5">c2c9ef4</a>)</li>
<li><strong>server:</strong> only strip base when path matches a full
segment (<a
href="https://redirect.github.com/vitejs/vite/issues/23641">#23641</a>)
(<a
href="https://github.com/vitejs/vite/commit/3dfde87b90a9f80b125d710e3e5d4fc795662db6">3dfde87</a>)</li>
</ul>
<h3>Performance Improvements</h3>
<ul>
<li><strong>ssr:</strong> extract inline source maps without a regexp
(<a
href="https://redirect.github.com/vitejs/vite/issues/23775">#23775</a>)
(<a
href="https://github.com/vitejs/vite/commit/6a0278055d8501bbaf65b8d34ec094722b4e877a">6a02780</a>)</li>
</ul>
<h3>Miscellaneous Chores</h3>
<ul>
<li>migrate to Oxlint (<a
href="https://redirect.github.com/vitejs/vite/issues/23746">#23746</a>)
(<a
href="https://github.com/vitejs/vite/commit/5b73935881424ed5919571036dd89d3868590f92">5b73935</a>)</li>
</ul>
<h3>Code Refactoring</h3>
<ul>
<li><strong>deps:</strong> replace <code>@vercel/detect-agent</code>
with <code>std-env</code> (<a
href="https://redirect.github.com/vitejs/vite/issues/23744">#23744</a>)
(<a
href="https://github.com/vitejs/vite/commit/ce4293f15cc5cd221c5ed60f5cd64e82ca5cbaf5">ce4293f</a>)</li>
<li><strong>dev:</strong> consolidate moduleURL to file path utilities
(<a
href="https://redirect.github.com/vitejs/vite/issues/23828">#23828</a>)
(<a
href="https://github.com/vitejs/vite/commit/df7b40ee9d691e9f4e2413244f6665ef5482dce3">df7b40e</a>)</li>
<li><strong>dev:</strong> separate import resolution from URL conversion
(<a
href="https://redirect.github.com/vitejs/vite/issues/23791">#23791</a>)
(<a
href="https://github.com/vitejs/vite/commit/611668983d4b717f5e5e66cf9f7125bd94f92bf7">6116689</a>)</li>
<li><strong>dev:</strong> share ModuleURL and BrowserURL conversions (<a
href="https://redirect.github.com/vitejs/vite/issues/23790">#23790</a>)
(<a
href="https://github.com/vitejs/vite/commit/446954c69c806795c83fe2f97c28ae8f9ef83731">446954c</a>)</li>
<li><strong>dev:</strong> use ModuleURLs throughout HTML transforms (<a
href="https://redirect.github.com/vitejs/vite/issues/23815">#23815</a>)
(<a
href="https://github.com/vitejs/vite/commit/a16299092c0f0f3f90e05d4bb5f0168b293c2b52">a162990</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/vitejs/vite/commit/981f07fa4580fb88b333c4450431e4715d2a0b82"><code>981f07f</code></a>
release: v8.3.5 (<a
href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23856">#23856</a>)</li>
<li><a
href="https://github.com/vitejs/vite/commit/0d86b3485fbbd0fcb9a1f70a14adedfcb7a1fff1"><code>0d86b34</code></a>
fix(resolve): support subpath imports with multiple <code>#</code> (<a
href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23631">#23631</a>)</li>
<li><a
href="https://github.com/vitejs/vite/commit/6a0278055d8501bbaf65b8d34ec094722b4e877a"><code>6a02780</code></a>
perf(ssr): extract inline source maps without a regexp (<a
href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23775">#23775</a>)</li>
<li><a
href="https://github.com/vitejs/vite/commit/8e890e1ce438bfbc07ea4931ce332e40589940fa"><code>8e890e1</code></a>
fix(optimizer): skip patches dir check for yarn.lock fallback (<a
href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23725">#23725</a>)</li>
<li><a
href="https://github.com/vitejs/vite/commit/197daf6c4c7bfdaa005bebcc41dd2ff22fa3a5b6"><code>197daf6</code></a>
fix(bundled-dev): declare utf-8 charset in fallback page (<a
href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23846">#23846</a>)</li>
<li><a
href="https://github.com/vitejs/vite/commit/4d16e7c14d5e1c361f148238b1e81131238ab8e9"><code>4d16e7c</code></a>
fix(build): include preload dependencies to chunk import map hashing (<a
href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23793">#23793</a>)</li>
<li><a
href="https://github.com/vitejs/vite/commit/df7b40ee9d691e9f4e2413244f6665ef5482dce3"><code>df7b40e</code></a>
refactor(dev): consolidate moduleURL to file path utilities (<a
href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23828">#23828</a>)</li>
<li><a
href="https://github.com/vitejs/vite/commit/a16299092c0f0f3f90e05d4bb5f0168b293c2b52"><code>a162990</code></a>
refactor(dev): use ModuleURLs throughout HTML transforms (<a
href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23815">#23815</a>)</li>
<li><a
href="https://github.com/vitejs/vite/commit/611668983d4b717f5e5e66cf9f7125bd94f92bf7"><code>6116689</code></a>
refactor(dev): separate import resolution from URL conversion (<a
href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23791">#23791</a>)</li>
<li><a
href="https://github.com/vitejs/vite/commit/446954c69c806795c83fe2f97c28ae8f9ef83731"><code>446954c</code></a>
refactor(dev): share ModuleURL and BrowserURL conversions (<a
href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23790">#23790</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/vitejs/vite/commits/v8.3.5/packages/vite">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-30 01:56:34 -04:00
dependabot[bot] 833698fd33 build(deps): bump astral-sh/uv from 0.13.5 to 0.13.6 in the docker-base-image-digests group (#1609)
> [!WARNING]
> Cooldown could not be applied because no publication date was
available from the registry.
>

Bumps the docker-base-image-digests group with 1 update:
[astral-sh/uv](https://github.com/astral-sh/uv).

Updates `astral-sh/uv` from 0.13.5 to 0.13.6
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/uv/releases">astral-sh/uv's
releases</a>.</em></p>
<blockquote>
<h2>0.13.6</h2>
<h2>Release Notes</h2>
<p>Released on 2026-10-26.</p>
<h3>Enhancements</h3>
<ul>
<li>Accept an empty <code>UV_RUN_RECURSION_DEPTH</code> as zero and
report invalid values consistently (<a
href="https://redirect.github.com/astral-sh/uv/pull/22814">#22814</a>)</li>
<li>Explain how to add project metadata when <code>uv init</code> finds
a <code>pyproject.toml</code> without a <code>[project]</code> table (<a
href="https://redirect.github.com/astral-sh/uv/pull/22916">#22916</a>)</li>
</ul>
<h3>Python</h3>
<ul>
<li>Add CPython 3.11.18, 3.12.16, 3.13.18, 3.14.10, and 3.15.2 (<a
href="https://redirect.github.com/astral-sh/uv/pull/22938">#22938</a>)</li>
</ul>
<h3>Preview features</h3>
<ul>
<li>Detect NVIDIA GPU capabilities when selecting compatible wheel
variants with <code>wheel-variants</code> (<a
href="https://redirect.github.com/astral-sh/uv/pull/22690">#22690</a>)</li>
<li>Nest each module's owners in an object in <code>uv workspace
metadata</code> output (<a
href="https://redirect.github.com/astral-sh/uv/pull/22638">#22638</a>)</li>
<li>Report the unsupported properties required by an incompatible wheel
variant (<a
href="https://redirect.github.com/astral-sh/uv/pull/22719">#22719</a>)</li>
</ul>
<h3>Performance</h3>
<ul>
<li>Reduce peak memory use when resolving large workspaces (<a
href="https://redirect.github.com/astral-sh/uv/pull/22860">#22860</a>,
<a
href="https://redirect.github.com/astral-sh/uv/pull/22863">#22863</a>,
<a
href="https://redirect.github.com/astral-sh/uv/pull/22864">#22864</a>,
<a
href="https://redirect.github.com/astral-sh/uv/pull/22866">#22866</a>,
<a
href="https://redirect.github.com/astral-sh/uv/pull/22870">#22870</a>)</li>
<li>Reduce peak memory use when locking or upgrading large projects (<a
href="https://redirect.github.com/astral-sh/uv/pull/22833">#22833</a>,
<a
href="https://redirect.github.com/astral-sh/uv/pull/22834">#22834</a>)</li>
<li>Speed up redirected output from <code>uv export</code> and <code>uv
pip compile</code> (<a
href="https://redirect.github.com/astral-sh/uv/pull/22840">#22840</a>)</li>
<li>Reuse cached or active environments when running PEP 723 scripts
without dependencies (<a
href="https://redirect.github.com/astral-sh/uv/pull/21458">#21458</a>)</li>
<li>Reduce parsing overhead for build dependency and build backend
settings (<a
href="https://redirect.github.com/astral-sh/uv/pull/22848">#22848</a>,
<a
href="https://redirect.github.com/astral-sh/uv/pull/22871">#22871</a>,
<a
href="https://redirect.github.com/astral-sh/uv/pull/22879">#22879</a>,
<a
href="https://redirect.github.com/astral-sh/uv/pull/22884">#22884</a>)</li>
<li>Reduce parsing overhead for project sources and workspace references
(<a
href="https://redirect.github.com/astral-sh/uv/pull/22880">#22880</a>,
<a
href="https://redirect.github.com/astral-sh/uv/pull/22883">#22883</a>)</li>
<li>Reduce parsing overhead for cache, exclusion, cutoff, and preview
settings (<a
href="https://redirect.github.com/astral-sh/uv/pull/22876">#22876</a>,
<a
href="https://redirect.github.com/astral-sh/uv/pull/22877">#22877</a>,
<a
href="https://redirect.github.com/astral-sh/uv/pull/22878">#22878</a>,
<a
href="https://redirect.github.com/astral-sh/uv/pull/22887">#22887</a>)</li>
<li>Reduce PyPI metadata parsing overhead (<a
href="https://redirect.github.com/astral-sh/uv/pull/22874">#22874</a>,
<a
href="https://redirect.github.com/astral-sh/uv/pull/22875">#22875</a>)</li>
<li>Speed up parsing tool receipt requirements (<a
href="https://redirect.github.com/astral-sh/uv/pull/22885">#22885</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>Prevent <code>uv run --active --script</code> and <code>uv sync
--active --script</code> from deleting non-virtual-environment
directories (<a
href="https://redirect.github.com/astral-sh/uv/pull/21464">#21464</a>)</li>
<li>Use <code>AMD64</code> for <code>platform_machine</code> when
resolving for x86-64 Windows (<a
href="https://redirect.github.com/astral-sh/uv/pull/22935">#22935</a>)</li>
<li>Preserve free-threaded and other non-default variants in <code>uv
python upgrade</code> (<a
href="https://redirect.github.com/astral-sh/uv/pull/22836">#22836</a>)</li>
<li>Allow <code>uv init --no-package</code> and <code>uv init
--script</code> when <code>UV_INIT_BUILD_BACKEND</code> is set (<a
href="https://redirect.github.com/astral-sh/uv/pull/22907">#22907</a>)</li>
<li>Prevent panics when rendering containment markers with local
versions (<a
href="https://redirect.github.com/astral-sh/uv/pull/22815">#22815</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>Update the Docker guide and reproduction examples to use uv 0.13.5
(<a
href="https://redirect.github.com/astral-sh/uv/pull/22867">#22867</a>)</li>
</ul>
<h2>Install uv 0.13.6</h2>
<h3>Install prebuilt binaries via shell script</h3>
<pre lang="sh"><code>curl --proto '=https' --tlsv1.2 -LsSf
https://releases.astral.sh/github/uv/releases/download/0.13.6/uv-installer.sh
| sh
&lt;/tr&gt;&lt;/table&gt; 
</code></pre>
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/uv/blob/main/CHANGELOG.md">astral-sh/uv's
changelog</a>.</em></p>
<blockquote>
<h2>0.13.6</h2>
<p>Released on 2026-10-26.</p>
<h3>Enhancements</h3>
<ul>
<li>Accept an empty <code>UV_RUN_RECURSION_DEPTH</code> as zero and
report invalid values consistently (<a
href="https://redirect.github.com/astral-sh/uv/pull/22814">#22814</a>)</li>
<li>Explain how to add project metadata when <code>uv init</code> finds
a <code>pyproject.toml</code> without a <code>[project]</code> table (<a
href="https://redirect.github.com/astral-sh/uv/pull/22916">#22916</a>)</li>
</ul>
<h3>Python</h3>
<ul>
<li>Add CPython 3.11.18, 3.12.16, 3.13.18, 3.14.10, and 3.15.2 (<a
href="https://redirect.github.com/astral-sh/uv/pull/22938">#22938</a>)</li>
</ul>
<h3>Preview features</h3>
<ul>
<li>Detect NVIDIA GPU capabilities when selecting compatible wheel
variants with <code>wheel-variants</code> (<a
href="https://redirect.github.com/astral-sh/uv/pull/22690">#22690</a>)</li>
<li>Nest each module's owners in an object in <code>uv workspace
metadata</code> output (<a
href="https://redirect.github.com/astral-sh/uv/pull/22638">#22638</a>)</li>
<li>Report the unsupported properties required by an incompatible wheel
variant (<a
href="https://redirect.github.com/astral-sh/uv/pull/22719">#22719</a>)</li>
</ul>
<h3>Performance</h3>
<ul>
<li>Reduce peak memory use when resolving large workspaces (<a
href="https://redirect.github.com/astral-sh/uv/pull/22860">#22860</a>,
<a
href="https://redirect.github.com/astral-sh/uv/pull/22863">#22863</a>,
<a
href="https://redirect.github.com/astral-sh/uv/pull/22864">#22864</a>,
<a
href="https://redirect.github.com/astral-sh/uv/pull/22866">#22866</a>,
<a
href="https://redirect.github.com/astral-sh/uv/pull/22870">#22870</a>)</li>
<li>Reduce peak memory use when locking or upgrading large projects (<a
href="https://redirect.github.com/astral-sh/uv/pull/22833">#22833</a>,
<a
href="https://redirect.github.com/astral-sh/uv/pull/22834">#22834</a>)</li>
<li>Speed up redirected output from <code>uv export</code> and <code>uv
pip compile</code> (<a
href="https://redirect.github.com/astral-sh/uv/pull/22840">#22840</a>)</li>
<li>Reuse cached or active environments when running PEP 723 scripts
without dependencies (<a
href="https://redirect.github.com/astral-sh/uv/pull/21458">#21458</a>)</li>
<li>Reduce parsing overhead for build dependency and build backend
settings (<a
href="https://redirect.github.com/astral-sh/uv/pull/22848">#22848</a>,
<a
href="https://redirect.github.com/astral-sh/uv/pull/22871">#22871</a>,
<a
href="https://redirect.github.com/astral-sh/uv/pull/22879">#22879</a>,
<a
href="https://redirect.github.com/astral-sh/uv/pull/22884">#22884</a>)</li>
<li>Reduce parsing overhead for project sources and workspace references
(<a
href="https://redirect.github.com/astral-sh/uv/pull/22880">#22880</a>,
<a
href="https://redirect.github.com/astral-sh/uv/pull/22883">#22883</a>)</li>
<li>Reduce parsing overhead for cache, exclusion, cutoff, and preview
settings (<a
href="https://redirect.github.com/astral-sh/uv/pull/22876">#22876</a>,
<a
href="https://redirect.github.com/astral-sh/uv/pull/22877">#22877</a>,
<a
href="https://redirect.github.com/astral-sh/uv/pull/22878">#22878</a>,
<a
href="https://redirect.github.com/astral-sh/uv/pull/22887">#22887</a>)</li>
<li>Reduce PyPI metadata parsing overhead (<a
href="https://redirect.github.com/astral-sh/uv/pull/22874">#22874</a>,
<a
href="https://redirect.github.com/astral-sh/uv/pull/22875">#22875</a>)</li>
<li>Speed up parsing tool receipt requirements (<a
href="https://redirect.github.com/astral-sh/uv/pull/22885">#22885</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>Prevent <code>uv run --active --script</code> and <code>uv sync
--active --script</code> from deleting non-virtual-environment
directories (<a
href="https://redirect.github.com/astral-sh/uv/pull/21464">#21464</a>)</li>
<li>Use <code>AMD64</code> for <code>platform_machine</code> when
resolving for x86-64 Windows (<a
href="https://redirect.github.com/astral-sh/uv/pull/22935">#22935</a>)</li>
<li>Preserve free-threaded and other non-default variants in <code>uv
python upgrade</code> (<a
href="https://redirect.github.com/astral-sh/uv/pull/22836">#22836</a>)</li>
<li>Allow <code>uv init --no-package</code> and <code>uv init
--script</code> when <code>UV_INIT_BUILD_BACKEND</code> is set (<a
href="https://redirect.github.com/astral-sh/uv/pull/22907">#22907</a>)</li>
<li>Prevent panics when rendering containment markers with local
versions (<a
href="https://redirect.github.com/astral-sh/uv/pull/22815">#22815</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>Update the Docker guide and reproduction examples to use uv 0.13.5
(<a
href="https://redirect.github.com/astral-sh/uv/pull/22867">#22867</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/astral-sh/uv/commit/329bf9448afd9f9088d14a4d57fbc61eb454f117"><code>329bf94</code></a>
Bump version to 0.13.6 (<a
href="https://redirect.github.com/astral-sh/uv/issues/22947">#22947</a>)</li>
<li><a
href="https://github.com/astral-sh/uv/commit/5b5a53e1803d426ba04f4af8ff7d6ff747548218"><code>5b5a53e</code></a>
Use checked-in Python download metadata for release preparation (<a
href="https://redirect.github.com/astral-sh/uv/issues/22945">#22945</a>)</li>
<li><a
href="https://github.com/astral-sh/uv/commit/b8b339fe4794e2919c7d2ef3214027aebc59d023"><code>b8b339f</code></a>
Update Rust crate h2 to v0.4.19 (<a
href="https://redirect.github.com/astral-sh/uv/issues/21873">#21873</a>)</li>
<li><a
href="https://github.com/astral-sh/uv/commit/1eb5989ea886d33add8c0ebc0adbfa54b1c32c82"><code>1eb5989</code></a>
Update Rust crate hyper to v1.11.1 (<a
href="https://redirect.github.com/astral-sh/uv/issues/20903">#20903</a>)</li>
<li><a
href="https://github.com/astral-sh/uv/commit/68677f5439c027db17b4db7821882a9881d376f6"><code>68677f5</code></a>
Update Rust crate reqwest to v0.13.5 (<a
href="https://redirect.github.com/astral-sh/uv/issues/22475">#22475</a>)</li>
<li><a
href="https://github.com/astral-sh/uv/commit/69e574e368d31145692b3e22e59285316566e6d7"><code>69e574e</code></a>
Cargo vet integration (<a
href="https://redirect.github.com/astral-sh/uv/issues/21610">#21610</a>)</li>
<li><a
href="https://github.com/astral-sh/uv/commit/acee8d938b52225be3e90ccfcbe69fa4eb8ed215"><code>acee8d9</code></a>
Sync latest Python releases, Python 3.11.18, 3.12.16, 3.13.18, 3.14.10,
3.15....</li>
<li><a
href="https://github.com/astral-sh/uv/commit/4b46af05893283739f94dea65e2bf667bda64d12"><code>4b46af0</code></a>
Fix <code>io-bound</code> Windows CI nextest grouping (<a
href="https://redirect.github.com/astral-sh/uv/issues/22939">#22939</a>)</li>
<li><a
href="https://github.com/astral-sh/uv/commit/d397ecbf703c00768a68d6fad0978cd20f45d8a6"><code>d397ecb</code></a>
Add hints when <code>uv init</code> finds <code>pyproject.toml</code>
without a project table (<a
href="https://redirect.github.com/astral-sh/uv/issues/22916">#22916</a>)</li>
<li><a
href="https://github.com/astral-sh/uv/commit/7b5d227102f51c311cdfed3370b473331144b2c6"><code>7b5d227</code></a>
Let <code>--no-package</code> and <code>--script</code> take precedence
over `UV_INIT_BUILD_BACKEND...</li>
<li>Additional commits viewable in <a
href="https://github.com/astral-sh/uv/compare/0.13.5...0.13.6">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=astral-sh/uv&package-manager=docker&previous-version=0.13.5&new-version=0.13.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-30 01:56:15 -04:00
dependabot[bot] bbdbaade84 build(deps): bump the python-deps group across 1 directory with 3 updates (#1608)
Bumps the python-deps group with 3 updates in the / directory:
[apprise](https://github.com/caronc/apprise),
[seleniumbase](https://github.com/seleniumbase/SeleniumBase) and
[ruff](https://github.com/astral-sh/ruff).

Updates `apprise` from 2.0.1 to 2.1.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/caronc/apprise/releases">apprise's
releases</a>.</em></p>
<blockquote>
<h2>Apprise v2.1.0</h2>
<h2>What's Changed</h2>
<p>First off, a huge kudos to the large increase in community support! A
lot of bugfixes from a number of very active contributors that make a
huge bulk of this release. 12 new services supported in this release
bringing the total (Apprise) supported plugin count to170! 🔥</p>
<h3>📣 New Notification Services:</h3>
<ul>
<li>GoAlert notification support in <a
href="https://redirect.github.com/caronc/apprise/pull/1767">caronc/apprise#1767</a></li>
<li>Added OneBot (QQ) Support in <a
href="https://redirect.github.com/caronc/apprise/pull/1768">caronc/apprise#1768</a></li>
<li>AMQP v0.9.1 and v1.0 support in <a
href="https://redirect.github.com/caronc/apprise/pull/1809">caronc/apprise#1809</a></li>
<li>GitHub issue, discussions and pull request notifications in <a
href="https://redirect.github.com/caronc/apprise/pull/1815">caronc/apprise#1815</a></li>
<li>Add Gorush push notification support in <a
href="https://redirect.github.com/caronc/apprise/pull/1818">caronc/apprise#1818</a></li>
<li>Add Better Stack support in <a
href="https://redirect.github.com/caronc/apprise/pull/1819">caronc/apprise#1819</a></li>
<li>incident.io support added in <a
href="https://redirect.github.com/caronc/apprise/pull/1822">caronc/apprise#1822</a></li>
<li>Squadcast support added in <a
href="https://redirect.github.com/caronc/apprise/pull/1830">caronc/apprise#1830</a></li>
<li>Added ilert support in <a
href="https://redirect.github.com/caronc/apprise/pull/1833">caronc/apprise#1833</a></li>
<li>LFG Alarm support added by <a
href="https://github.com/LFGWin"><code>@​LFGWin</code></a> in <a
href="https://redirect.github.com/caronc/apprise/pull/1832">caronc/apprise#1832</a></li>
<li>Added Zalo support in <a
href="https://redirect.github.com/caronc/apprise/pull/1836">caronc/apprise#1836</a></li>
<li>Zoho Cliq support added in <a
href="https://redirect.github.com/caronc/apprise/pull/1835">caronc/apprise#1835</a></li>
</ul>
<h3>🐞  Bugfixes</h3>
<ul>
<li>YAML config no longer drops plugin ?tags= from URLs by <a
href="https://github.com/TheFiZi"><code>@​TheFiZi</code></a> in <a
href="https://redirect.github.com/caronc/apprise/pull/1782">caronc/apprise#1782</a></li>
<li>tags= and tag= on urls not supported in <a
href="https://redirect.github.com/caronc/apprise/pull/1783">caronc/apprise#1783</a></li>
<li>notify decorator honours common URL options in <a
href="https://redirect.github.com/caronc/apprise/pull/1784">caronc/apprise#1784</a></li>
<li>Close MQTT connection when the notifier is freed by <a
href="https://github.com/LuisFigueroaG"><code>@​LuisFigueroaG</code></a>
in <a
href="https://redirect.github.com/caronc/apprise/pull/1773">caronc/apprise#1773</a></li>
<li>Matrix E2EE no longer publishes unused one-time keys by <a
href="https://github.com/Cassian433"><code>@​Cassian433</code></a> in <a
href="https://redirect.github.com/caronc/apprise/pull/1770">caronc/apprise#1770</a></li>
<li>Keep from=, flash= and label= in seven:// url() by <a
href="https://github.com/LuisFigueroaG"><code>@​LuisFigueroaG</code></a>
in <a
href="https://redirect.github.com/caronc/apprise/pull/1774">caronc/apprise#1774</a></li>
<li>Keep the from= sender address in Pingram url() by <a
href="https://github.com/SulimanAbdulrazzaq"><code>@​SulimanAbdulrazzaq</code></a>
in <a
href="https://redirect.github.com/caronc/apprise/pull/1776">caronc/apprise#1776</a></li>
<li>Keep the from= sender address in Mailgun url() by <a
href="https://github.com/SulimanAbdulrazzaq"><code>@​SulimanAbdulrazzaq</code></a>
in <a
href="https://redirect.github.com/caronc/apprise/pull/1777">caronc/apprise#1777</a></li>
<li>Do not re-send message pieces that were already accepted when
retrying by <a
href="https://github.com/SulimanAbdulrazzaq"><code>@​SulimanAbdulrazzaq</code></a>
in <a
href="https://redirect.github.com/caronc/apprise/pull/1779">caronc/apprise#1779</a></li>
<li>Clear LC_MESSAGES in translation tests by <a
href="https://github.com/wolfgang-aura"><code>@​wolfgang-aura</code></a>
in <a
href="https://redirect.github.com/caronc/apprise/pull/1775">caronc/apprise#1775</a></li>
<li>Hide a bare access token in matrix:// privacy url() by <a
href="https://github.com/LuisFigueroaG"><code>@​LuisFigueroaG</code></a>
in <a
href="https://redirect.github.com/caronc/apprise/pull/1786">caronc/apprise#1786</a></li>
<li>Improve persistent storage namespaces path handling in <a
href="https://redirect.github.com/caronc/apprise/pull/1796">caronc/apprise#1796</a></li>
<li>Hide the password in smpp:// privacy url() by <a
href="https://github.com/LuisFigueroaG"><code>@​LuisFigueroaG</code></a>
in <a
href="https://redirect.github.com/caronc/apprise/pull/1785">caronc/apprise#1785</a></li>
<li>fix(matrix): use standard Base64 for E2EE attachment IV by <a
href="https://github.com/vampywiz17"><code>@​vampywiz17</code></a> in <a
href="https://redirect.github.com/caronc/apprise/pull/1788">caronc/apprise#1788</a></li>
<li>Use the default file expiry as a cutoff date in disk_prune() by <a
href="https://github.com/cristianchiriac"><code>@​cristianchiriac</code></a>
in <a
href="https://redirect.github.com/caronc/apprise/pull/1808">caronc/apprise#1808</a></li>
<li>Fail for empty or invalid storage env variables by <a
href="https://github.com/cristianchiriac"><code>@​cristianchiriac</code></a>
in <a
href="https://redirect.github.com/caronc/apprise/pull/1807">caronc/apprise#1807</a></li>
<li>Do not send an empty piece when overflow=split breaks at a leading
line break or space by <a
href="https://github.com/SulimanAbdulrazzaq"><code>@​SulimanAbdulrazzaq</code></a>
in <a
href="https://redirect.github.com/caronc/apprise/pull/1792">caronc/apprise#1792</a></li>
<li>Keep an invalid backslash sequence as written when interpret_escapes
is on by <a
href="https://github.com/SulimanAbdulrazzaq"><code>@​SulimanAbdulrazzaq</code></a>
in <a
href="https://redirect.github.com/caronc/apprise/pull/1791">caronc/apprise#1791</a></li>
<li>Fix renewal of persistent files read with the default key by <a
href="https://github.com/Dcastroro"><code>@​Dcastroro</code></a> in <a
href="https://redirect.github.com/caronc/apprise/pull/1814">caronc/apprise#1814</a></li>
<li>Keep pending persistent writes after a non-persistent set() by <a
href="https://github.com/cristianchiriac"><code>@​cristianchiriac</code></a>
in <a
href="https://redirect.github.com/caronc/apprise/pull/1813">caronc/apprise#1813</a></li>
<li>Keep custom from= address in email url() round trips by <a
href="https://github.com/cestercian"><code>@​cestercian</code></a> in <a
href="https://redirect.github.com/caronc/apprise/pull/1811">caronc/apprise#1811</a></li>
<li>Keep cc/bcc/reply display names intact in email url() by <a
href="https://github.com/cristianchiriac"><code>@​cristianchiriac</code></a>
in <a
href="https://redirect.github.com/caronc/apprise/pull/1812">caronc/apprise#1812</a></li>
<li>Keep encoded slashes and other escapes intact in URL paths in <a
href="https://redirect.github.com/caronc/apprise/pull/1816">caronc/apprise#1816</a></li>
<li>Hide the API key in twilio:// privacy url() by <a
href="https://github.com/LuisFigueroaG"><code>@​LuisFigueroaG</code></a>
in <a
href="https://redirect.github.com/caronc/apprise/pull/1817">caronc/apprise#1817</a></li>
<li>Make incident plugins consistent and let PagerDuty, PagerTree and
SIGNL4 resolve alerts in <a
href="https://redirect.github.com/caronc/apprise/pull/1824">caronc/apprise#1824</a></li>
<li>Stop uppercasing name=, identifier= and sound_href= in strmlabs://
by <a
href="https://github.com/LuisFigueroaG"><code>@​LuisFigueroaG</code></a>
in <a
href="https://redirect.github.com/caronc/apprise/pull/1821">caronc/apprise#1821</a></li>
<li>Fix email reply= failing after the first recipient by <a
href="https://github.com/LuisFigueroaG"><code>@​LuisFigueroaG</code></a>
in <a
href="https://redirect.github.com/caronc/apprise/pull/1827">caronc/apprise#1827</a></li>
<li>Honor +Arg=Val and -Arg in ifttt:// URLs by <a
href="https://github.com/MaxFreedomPollard"><code>@​MaxFreedomPollard</code></a>
in <a
href="https://redirect.github.com/caronc/apprise/pull/1831">caronc/apprise#1831</a></li>
<li>Fix SendPulse sending only the last cc/bcc address by <a
href="https://github.com/LuisFigueroaG"><code>@​LuisFigueroaG</code></a>
in <a
href="https://redirect.github.com/caronc/apprise/pull/1834">caronc/apprise#1834</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/caronc/apprise/commit/736fcf36c5acabe153e5b0b0b444caea8dc4c235"><code>736fcf3</code></a>
bumped version to v2.1.0</li>
<li><a
href="https://github.com/caronc/apprise/commit/c8db34ef6a077abf7c14b73806b116b925507449"><code>c8db34e</code></a>
Zoho Cliq support added (<a
href="https://redirect.github.com/caronc/apprise/issues/1835">#1835</a>)</li>
<li><a
href="https://github.com/caronc/apprise/commit/8f2117168cbd169782322d74e718e97d8d90dd46"><code>8f21171</code></a>
Added Zalo support (<a
href="https://redirect.github.com/caronc/apprise/issues/1836">#1836</a>)</li>
<li><a
href="https://github.com/caronc/apprise/commit/f39501d011bc1853b88b47a5ed615ef9bb9887c7"><code>f39501d</code></a>
Fix SendPulse sending only the last cc/bcc address (<a
href="https://redirect.github.com/caronc/apprise/issues/1834">#1834</a>)</li>
<li><a
href="https://github.com/caronc/apprise/commit/8cae8d3071c2c0d48a0a28593045cae5e33bcdd4"><code>8cae8d3</code></a>
Update security policy to include version 2.0.1</li>
<li><a
href="https://github.com/caronc/apprise/commit/726055e1d789018004aac82e76f65e59530542c6"><code>726055e</code></a>
Revise supported versions in SECURITY.md</li>
<li><a
href="https://github.com/caronc/apprise/commit/80526d601c6f144f21d5ea1eaf0d57e1ddc6c879"><code>80526d6</code></a>
LFG Alarm support added (<a
href="https://redirect.github.com/caronc/apprise/issues/1832">#1832</a>)</li>
<li><a
href="https://github.com/caronc/apprise/commit/c6d3af32f69783eb4a40247d7c01b35534d3bf8a"><code>c6d3af3</code></a>
Honor +Arg=Val and -Arg in ifttt:// URLs (<a
href="https://redirect.github.com/caronc/apprise/issues/1831">#1831</a>)</li>
<li><a
href="https://github.com/caronc/apprise/commit/a915602d5a2c8e1dd5af493dba9e5db89bf000ef"><code>a915602</code></a>
Send Pushover markup with no text as plain text (<a
href="https://redirect.github.com/caronc/apprise/issues/1829">#1829</a>)</li>
<li><a
href="https://github.com/caronc/apprise/commit/1867c9aebf5d9c1ff88f8a5598246a61d1147395"><code>1867c9a</code></a>
Added ilert support (<a
href="https://redirect.github.com/caronc/apprise/issues/1833">#1833</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/caronc/apprise/compare/v2.0.1...v2.1.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `seleniumbase` from 4.56.3 to 4.56.4
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/seleniumbase/SeleniumBase/releases">seleniumbase's
releases</a>.</em></p>
<blockquote>
<h2>4.56.4 - CDP Mode: Patch 130</h2>
<h2>CDP Mode: Patch 130</h2>
<ul>
<li><a
href="https://github.com/seleniumbase/SeleniumBase/commit/8310a78ab3b7d356f4f75888cc74e5992ed92efc">Fix
issue with listing tabs in CDP Mode</a>
--&gt; This resolves <a
href="https://redirect.github.com/seleniumbase/SeleniumBase/issues/4533">seleniumbase/SeleniumBase#4533</a></li>
<li><a
href="https://github.com/seleniumbase/SeleniumBase/commit/1393a024a0d37d567acdcc3abfe262901acbe222">Refresh
Python dependencies</a>
--&gt; <code>certifi</code>
--&gt; <code>soupsieve</code>
--&gt; <code>coverage</code> (optional dependency)
--&gt; <code>playwright</code> (optional dependency)
--&gt; <code>pycparser</code> (optional dependency)
--&gt; <code>uv</code> (optional dependency)</li>
</ul>
<h2>What's Changed</h2>
<ul>
<li>CDP Mode: Patch 130 by <a
href="https://github.com/mdmintz"><code>@​mdmintz</code></a> in <a
href="https://redirect.github.com/seleniumbase/SeleniumBase/pull/4535">seleniumbase/SeleniumBase#4535</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/seleniumbase/SeleniumBase/compare/v4.56.3...v4.56.4">https://github.com/seleniumbase/SeleniumBase/compare/v4.56.3...v4.56.4</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/seleniumbase/SeleniumBase/commit/abf61932bc89bfbabd59eaa776b9d09f75618d2f"><code>abf6193</code></a>
Merge pull request <a
href="https://redirect.github.com/seleniumbase/SeleniumBase/issues/4535">#4535</a>
from seleniumbase/cdp-mode-patch-130</li>
<li><a
href="https://github.com/seleniumbase/SeleniumBase/commit/7a8363acb71f15c1ce7956295d63699b104f291f"><code>7a8363a</code></a>
Version 4.56.4</li>
<li><a
href="https://github.com/seleniumbase/SeleniumBase/commit/c71b7a24976a2f14a03bce5d0c05862d237510fa"><code>c71b7a2</code></a>
Update MCP server versioning</li>
<li><a
href="https://github.com/seleniumbase/SeleniumBase/commit/1393a024a0d37d567acdcc3abfe262901acbe222"><code>1393a02</code></a>
Refresh Python dependencies</li>
<li><a
href="https://github.com/seleniumbase/SeleniumBase/commit/8310a78ab3b7d356f4f75888cc74e5992ed92efc"><code>8310a78</code></a>
Fix issue with listing tabs in CDP Mode</li>
<li><a
href="https://github.com/seleniumbase/SeleniumBase/commit/c297e2dd8ed46b5a0b49226d37e1efda87bfbdb1"><code>c297e2d</code></a>
Refresh mkdocs dependencies</li>
<li><a
href="https://github.com/seleniumbase/SeleniumBase/commit/da6679741f65e34fb30db50b98742cfaf05b009b"><code>da66797</code></a>
Update images</li>
<li>See full diff in <a
href="https://github.com/seleniumbase/SeleniumBase/compare/v4.56.3...v4.56.4">compare
view</a></li>
</ul>
</details>
<br />

Updates `ruff` from 0.17.2 to 0.17.3
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ruff/releases">ruff's
releases</a>.</em></p>
<blockquote>
<h2>0.17.3</h2>
<h2>Release Notes</h2>
<p>Released on 2026-10-26.</p>
<h3>Preview features</h3>
<ul>
<li>[<code>suspicious</code>] Add <code>shared-clock-mock</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/29074">#29074</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>[<code>pyupgrade</code>] Avoid incorrect conversions to f-strings
(<code>UP032</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/25485">#25485</a>)</li>
</ul>
<h3>Performance</h3>
<ul>
<li>Buffer stdout in <code>ruff format</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/29631">#29631</a>)</li>
<li>Specialize ASCII identifier lexing (<a
href="https://redirect.github.com/astral-sh/ruff/pull/29503">#29503</a>)</li>
<li>Speed up identifier and keyword lexing (<a
href="https://redirect.github.com/astral-sh/ruff/pull/29463">#29463</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>[<code>flake8-bandit</code>] Describe what the rule actually checks
for <code>httpx</code> (<code>S113</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/27936">#27936</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/itsvedantkumar"><code>@​itsvedantkumar</code></a></li>
<li><a
href="https://github.com/charliermarsh"><code>@​charliermarsh</code></a></li>
<li><a
href="https://github.com/anishgirianish"><code>@​anishgirianish</code></a></li>
</ul>
<h2>Install ruff 0.17.3</h2>
<h3>Install prebuilt binaries via shell script</h3>
<pre lang="sh"><code>curl --proto '=https' --tlsv1.2 -LsSf
https://releases.astral.sh/github/ruff/releases/download/0.17.3/ruff-installer.sh
| sh
</code></pre>
<h3>Install prebuilt binaries via powershell script</h3>
<pre lang="sh"><code>powershell -ExecutionPolicy Bypass -c &quot;irm
https://releases.astral.sh/github/ruff/releases/download/0.17.3/ruff-installer.ps1
| iex&quot;
</code></pre>
<h2>Download ruff 0.17.3</h2>
<table>
<thead>
<tr>
<th>File</th>
<th>Platform</th>
<th>Checksum</th>
</tr>
</thead>
<tbody>
<tr>
<td><a
href="https://releases.astral.sh/github/ruff/releases/download/0.17.3/ruff-aarch64-apple-darwin.tar.gz">ruff-aarch64-apple-darwin.tar.gz</a></td>
<td>Apple Silicon macOS</td>
<td><a
href="https://releases.astral.sh/github/ruff/releases/download/0.17.3/ruff-aarch64-apple-darwin.tar.gz.sha256">checksum</a></td>
</tr>
<tr>
<td><a
href="https://releases.astral.sh/github/ruff/releases/download/0.17.3/ruff-x86_64-apple-darwin.tar.gz">ruff-x86_64-apple-darwin.tar.gz</a></td>
<td>Intel macOS</td>
<td><a
href="https://releases.astral.sh/github/ruff/releases/download/0.17.3/ruff-x86_64-apple-darwin.tar.gz.sha256">checksum</a></td>
</tr>
<tr>
<td><a
href="https://releases.astral.sh/github/ruff/releases/download/0.17.3/ruff-aarch64-pc-windows-msvc.zip">ruff-aarch64-pc-windows-msvc.zip</a></td>
<td>ARM64 Windows</td>
<td><a
href="https://releases.astral.sh/github/ruff/releases/download/0.17.3/ruff-aarch64-pc-windows-msvc.zip.sha256">checksum</a></td>
</tr>
</tbody>
</table>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md">ruff's
changelog</a>.</em></p>
<blockquote>
<h2>0.17.3</h2>
<p>Released on 2026-10-26.</p>
<h3>Preview features</h3>
<ul>
<li>[<code>suspicious</code>] Add <code>shared-clock-mock</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/29074">#29074</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>[<code>pyupgrade</code>] Avoid incorrect conversions to f-strings
(<code>UP032</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/25485">#25485</a>)</li>
</ul>
<h3>Performance</h3>
<ul>
<li>Buffer stdout in <code>ruff format</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/29631">#29631</a>)</li>
<li>Specialize ASCII identifier lexing (<a
href="https://redirect.github.com/astral-sh/ruff/pull/29503">#29503</a>)</li>
<li>Speed up identifier and keyword lexing (<a
href="https://redirect.github.com/astral-sh/ruff/pull/29463">#29463</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>[<code>flake8-bandit</code>] Describe what the rule actually checks
for <code>httpx</code> (<code>S113</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/27936">#27936</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/itsvedantkumar"><code>@​itsvedantkumar</code></a></li>
<li><a
href="https://github.com/charliermarsh"><code>@​charliermarsh</code></a></li>
<li><a
href="https://github.com/anishgirianish"><code>@​anishgirianish</code></a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/astral-sh/ruff/commit/ba65abf8ba7bfbcc059f7fb9712be5ba9cab6abc"><code>ba65abf</code></a>
Bump version to 0.17.3 (<a
href="https://redirect.github.com/astral-sh/ruff/issues/29745">#29745</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/fb2f9218793e3b0e979175d43d88dcac791e92d6"><code>fb2f921</code></a>
[ty] Fix narrowing of strings and integers compared with enum members
(<a
href="https://redirect.github.com/astral-sh/ruff/issues/29743">#29743</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/d1812878d5f81af6f5810d193ebc44413d1b21cc"><code>d181287</code></a>
[ty] Index nominal union alternatives (<a
href="https://redirect.github.com/astral-sh/ruff/issues/29196">#29196</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/07872adbafa7c00f42f1174d8aa3c3e324033009"><code>07872ad</code></a>
[ty] Preserve string literals in comparisons with
<code>LiteralString</code> (<a
href="https://redirect.github.com/astral-sh/ruff/issues/29741">#29741</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/95888b2edfaa34d0159732856b1466cf53b33e64"><code>95888b2</code></a>
[ty] Preserve narrowing after guarded match subject captures (<a
href="https://redirect.github.com/astral-sh/ruff/issues/29558">#29558</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/3c8166b683805aa89557b0739f5b9918ad58ea6d"><code>3c8166b</code></a>
[ty] Fix hang when negating recursive unions of instance types (<a
href="https://redirect.github.com/astral-sh/ruff/issues/29652">#29652</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/3fd20e08598ac345b8afd524d3f7086456e4e758"><code>3fd20e0</code></a>
[ty] Preserve generic callback specializations during return refinement
(<a
href="https://redirect.github.com/astral-sh/ruff/issues/29667">#29667</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/2f0a29ece1f1a539c65c0671c04c76bb886219fe"><code>2f0a29e</code></a>
[ty] Record predicate truthiness alongside expression inference (<a
href="https://redirect.github.com/astral-sh/ruff/issues/29706">#29706</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/60f104a1a2ec4e980198ff54c38ba6fe7045b29f"><code>60f104a</code></a>
[ty] Honor <a
href="https://github.com/override"><code>@​override</code></a> on
overload implementations in stubs (<a
href="https://redirect.github.com/astral-sh/ruff/issues/29470">#29470</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/207ec3affeb118fce03a65f9333959157e228312"><code>207ec3a</code></a>
[ty] Add diagnostic baseline support (<a
href="https://redirect.github.com/astral-sh/ruff/issues/27636">#27636</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/astral-sh/ruff/compare/0.17.2...0.17.3">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-30 01:42:22 -04:00
splitsec2 7583f997bb fix(oidc): catch joserfc's InvalidClaimError so the issuer guidance shows (#1603)
A wrong OIDC issuer, which is the usual IdP setup mistake, sends the
user back to the login page with a bare "Authentication failed". The
callback has a handler that explains it ("OIDC issuer validation failed.
Verify your discovery URL and IdP issuer/external URL configuration."),
and it never runs.

Authlib validates the ID token with joserfc now, so the error that comes
out of `authorize_access_token()` is `joserfc.errors.InvalidClaimError`.
The handler catches the one in `authlib.jose.errors`, which is a
different class with a different base, so the isinstance check is False.
I confirmed it by validating a real `CodeIDToken` with a wrong `iss` on
Authlib 1.9.1. I haven't run it against a live IdP.

The existing tests passed because they raise the old class from a mock.
The new one raises the error from a real `CodeIDToken`, and it fails on
the old import with `'Authentication failed'` in place of the guidance.

Two small things come with it:
- The new class names its attribute `claim` where the old one used
`claim_name`, so that read changes.
- `authlib.jose` is deprecated in favour of joserfc and Authlib's own
warning says it goes in 2.0. This was the only place Shelfmark used it,
so the import moving also takes us off the module that is going away.
joserfc is already installed as an Authlib requirement, so I added it to
`pyproject.toml` (`>=1.6.8`, Authlib's own floor) and the lock gets the
one entry. No new package.

Ruff, basedpyright and the backend suite pass (5424 passed).
2026-10-27 11:06:51 -06:00
CaliBrain 947ce7bfe5 test(e2e): serve the mock Prowlarr .torrent from Prowlarr's own origin (#1602)
The nightly client-deluge profile has failed since 61c7ad3 with "Failed
to
add to deluge: Failed to fetch torrent file: torrent fetch refused:
address
is not public". Shelfmark now fetches a .torrent only from the
configured
Prowlarr/Newznab/Jackett origin or from a public address, and the mock
Prowlarr's release linked straight to http://mock-aa/payload.torrent, a
private address on another origin. qBittorrent and Transmission hid this
by
handing the URL to the client; Deluge needs the file and failed.

Real Prowlarr rewrites indexer links to its own /{id}/download endpoint.
The
mock now does the same: the torznab link uses the host Shelfmark reached
it
on, and /{id}/download fetches the .torrent from mock-aa. Every client
now
gets the file through Shelfmark's own fetch.

tests/download/test_prowlarr_mock_torrent_fetch.py runs the real
extract_torrent_info against the mock in normal CI, so the link cannot
drift
off the Prowlarr origin again unnoticed; it fails on the old mock with
the
same error.
2026-10-27 11:25:49 -04:00
CaliBrain 16e20679b4 fix(docker): bump Chromium pin to 156.0.8078.47 (#1601) 2026-10-27 10:50:22 -04:00
dependabot[bot] c0b112f2f8 build(deps): bump publicsuffixlist from 1.1.2.20261021 to 1.1.2.20261023 (#1600)
Bumps [publicsuffixlist](https://github.com/ko-zu/psl) from
1.1.2.20261021 to 1.1.2.20261023.
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/ko-zu/psl/commits">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=publicsuffixlist&package-manager=uv&previous-version=1.1.2.20261021&new-version=1.1.2.20261023)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-27 10:36:13 -04:00
splitsec2 83e61975c4 fix(releases): apply the record policy to a provider named alongside a source (#1598)
Two small things I found while going back over what has landed since
1.5.0.

`/api/releases` takes a `provider` and a `source`, and the policy check
only looked at `source`. A user whose policy blocks one release source
but not another could pass the blocked one as `provider` with the
allowed one as `source`, and get the blocked source's record back. The
record route already refuses that with a 403, so the listing route now
applies the same refusal when `provider` names a source that is not
being listed. The normal case, where provider and source are the same,
is already gated and skips the extra check.

The second commit is wording only. The Automatic Downloads setting and
the Hardcover sync doc said "synced requests", but the pass picks up
every pending Hardcover request, including ones a user made themselves
with Request Book. The download is still queued as the user who asked
(the admin is only the reviewer, same as a manual approval), and admins
already see every user's requests. The text now says that, and a new
test pins the behaviour for a user's own request.

I opened a scratch instance and looked at the Hardcover Sync tab: the
Automatic Downloads heading and the checkbox description read as
intended and nothing else on the tab moved. Full suite, ruff and
basedpyright pass, and the new policy test fails without the fix.
2026-10-26 14:49:40 -06:00
splitsec2 cfba44b754 refactor: one module for taking credentials and links out of text (#1578)
Draft until #1571 merges: this is stacked on it, so the first two
commits here are that PR's and only the last one is new. I will rebase
once #1571 is in.

Shelfmark strips credentials and links out of text in five places,
written in different PRs with different patterns: the log formatter,
`_safe_url` and `_redact_urls_in_text` in `torrent_utils.py`,
`redact_status_message` in `viewer_redaction.py`, the `sed` rules in
`genDebug.sh`, and the password handling in the settings registry.
Between them there were three regexes that find a URL in text, two
separate userinfo patterns and no shared list of what counts as a
secret. #1571 made the gap visible, because every pattern added to the
logger had to be remembered somewhere else too.

This moves the text and URL part into `shelfmark/core/redaction.py`,
which imports nothing from the app so the logger can depend on it:

- `redact_secrets` (mask in place, for logs) moved from
`core/logger.py`, patterns unchanged. The logger imports it.
- `safe_url` and `redact_urls_in_text` (keep scheme, host and path, drop
the query) moved from `torrent_utils.py` and are public now, so
`alldebrid.py` no longer imports a private name from another module.
- `strip_links` (remove links entirely) is what `redact_status_message`
now calls. It and `redact_urls_in_text` share one link pattern, the one
the viewer redaction already used.

Two small behaviour changes come from sharing that pattern. A closing
bracket or quote right after a URL is no longer swallowed into it when
scrubbing an exception message. And the scheme-less path that requests
prints after `url: ` now keeps only what is before its query in
`redact_urls_in_text`, where before it passed through as it was (the log
formatter masked the key, but the path and query stayed in the message).

Also here: the two `sed` rules in `genDebug.sh` that mask userinfo now
stop at `?` and `#` like the logger pattern does, with a test that fails
on the old script.

Not in this PR: the debug bundle zips the live log directory as it is,
so log lines written before #1571 are not redacted in it. Fixing that
means copying the logs to a staging folder and running them through this
module, which I would do as a separate change.

Tests: a new file covers `safe_url`, `redact_urls_in_text` and
`strip_links` directly, and two checks that the viewer and the logger
really use these. Full suite passes.
2026-10-26 14:48:36 -06:00
splitsec2 7a4f1670dc fix(slskd): try a batch enqueue once more when slskd answers 500 (#1590)
slskd answers a bare 500 when the peer doesn't reply to a queue request
inside its own 5 second wait (its log says "The wait timed out after
5000 milliseconds"). The peer often answers a moment later, so a
Soulseek download that would have worked failed on the first try.

The batch enqueue is now tried twice with 5 seconds between. A 4xx or a
connection failure is not retried, only a 5xx. While it waits the card
reads "The peer did not answer, trying again", and cancelling during the
wait stops without the second try. If the second try fails too, the
error message carries what slskd said (trimmed to 160 characters).
Before, that text was dropped and the card only showed the status line.

It's been running on my instance since mid-October, and the timeouts
still show up in slskd's log, so I can't say how many it saved. The five
new tests cover the retry that works, giving up after the second 500, a
400 and a connection error not being retried, and cancelling mid-wait.
Ruff, basedpyright and the slskd tests pass.
2026-10-26 11:37:05 -06:00
splitsec2 e8b28d05e0 fix(sources): take the retry download URL from the release cache only (#1597)
Newznab and Jackett fell back to the download URL sent with the queue
request when the release was no longer in the cache. Prowlarr already
returns no URL in that case, so this makes the other two match it: the
retry URL comes from the cache and nothing else.

A request for a release that has expired from the cache now fails with
"Release not found in cache" instead of being queued with whatever URL
came along.

The new tests cover both handlers on a cache miss and with no source_id,
and they fail on main. Full suite, ruff and basedpyright pass.
2026-10-26 11:15:44 -06:00
splitsec2 8b80f32476 fix(sources): keep credentials out of a source-unavailable message (#1593)
Code scanning alert 106 (stack trace exposure on the release search 503)
turned out to be worth a look. Jackett sends its API key as `?apikey=`
in the query string, and when Jackett is unreachable the source builds
its "unavailable" message from the requests exception, whose text
includes the full request URL. `/api/releases` returns that message to
whoever ran the search, so any signed-in user could read the Jackett key
while Jackett was down. I reproduced it with Jackett pointed at a closed
port: the 503 body had `apikey=<the key>` in it.

Jackett was added in #1521 and isn't in a release yet, so nothing
shipped with this.

`SourceUnavailableError` now masks credentials in its message with the
same `redact_secrets` the log formatter uses (query parameters like
`apikey=`, `user:pass@` in URLs and so on). I did it in the exception
rather than at the two Jackett sites that build the text, since its
message is written for the user and any other source that ends up with a
key in a URL would hit the same thing. The rest of the message stays
readable, for example "Max retries exceeded with url:
...?apikey=(removed)&t=book".

Prowlarr and slskd send their keys in headers so they didn't leak a key,
but their messages do include the internal host and port. I left that
alone here.

Tests: two Jackett ones (a connection error on the search and on the
indexer lookup, with the key in the exception text) and three on the
exception itself. The four that check masking fail on current main. The
full suite, ruff and basedpyright are clean.
2026-10-26 10:34:17 -06:00
splitsec2 72b094db7a fix(qbittorrent): map the qBittorrent 5 stopped states and forcedMetaDL (#1570)
On qBittorrent 5 a stopped torrent shows up as an unknown state. 5.0
renamed `pausedDL` and `pausedUP` to `stoppedDL` and `stoppedUP`, and
`get_status` only knows the old names, so the torrent comes back as
state `unknown` with the raw state name as its message. The paused
handling in the download handler never applies to it, for example the
grace it gives a torrent that has not started. `forcedMetaDL` is missing
from the same table, so a force-started magnet fetching its metadata
also shows up as unknown, although it is already in the
incomplete-states set and the metadata wait.

The three missing states are now mapped like their neighbours: the two
stopped states as paused, `forcedMetaDL` as downloading with "Fetching
metadata". The state names are the ones `qbittorrent-api` lists in its
`TorrentState` enum.

Tests: one parametrized test covers the old and new paused names and
`forcedMetaDL` (the two old paused names are there as controls). The
three new cases fail without the change. Full suite passes.
2026-10-26 02:44:19 -06:00
dependabot[bot] 5d94e96bd9 build(deps): bump the python-deps group with 5 updates (#1586)
Bumps the python-deps group with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [qbittorrent-api](https://github.com/rmartin16/qbittorrent-api) |
`2026.10.0` | `2026.10.1` |
| [publicsuffixlist](https://github.com/ko-zu/psl) | `1.1.0.20261018` |
`1.1.2.20261021` |
| [seleniumbase](https://github.com/seleniumbase/SeleniumBase) |
`4.56.2` | `4.56.3` |
| [prek](https://github.com/j178/prek) | `0.5.6` | `0.5.7` |
| [ruff](https://github.com/astral-sh/ruff) | `0.17.1` | `0.17.2` |

Updates `qbittorrent-api` from 2026.10.0 to 2026.10.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/rmartin16/qbittorrent-api/releases">qbittorrent-api's
releases</a>.</em></p>
<blockquote>
<h2>release-2026.10.1</h2>
<h2>What's Changed</h2>
<h3>Features</h3>
<ul>
<li>feat: support qBittorrent v5.3.0 by <a
href="https://github.com/rmartin16"><code>@​rmartin16</code></a> in <a
href="https://redirect.github.com/rmartin16/qbittorrent-api/pull/689">rmartin16/qbittorrent-api#689</a></li>
</ul>
<h3>Chores</h3>
<ul>
<li>build(deps): bump uv from 0.11.18 to 0.13.4 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/rmartin16/qbittorrent-api/pull/687">rmartin16/qbittorrent-api#687</a></li>
<li>build(deps): bump certifi from 2026.5.20 to 2026.10.19 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/rmartin16/qbittorrent-api/pull/688">rmartin16/qbittorrent-api#688</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/rmartin16/qbittorrent-api/compare/v2026.10.0...v2026.10.1">https://github.com/rmartin16/qbittorrent-api/compare/v2026.10.0...v2026.10.1</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/rmartin16/qbittorrent-api/blob/main/CHANGELOG.md">qbittorrent-api's
changelog</a>.</em></p>
<blockquote>
<h3>v2026.10.1 (21 oct 2026)</h3>
<ul>
<li>Advertise support for qBittorrent v5.3.0 (<a
href="https://redirect.github.com/rmartin16/qbittorrent-api/issues/689">#689</a>)</li>
<li>Existing changes that are now supported in qBittorrent:
<ul>
<li>Add support for <code>app/getFreeSpaceAtPath</code> (<a
href="https://redirect.github.com/rmartin16/qbittorrent-api/issues/659">#659</a>)</li>
<li>Add support for <code>rss/cloneRule</code> (<a
href="https://redirect.github.com/rmartin16/qbittorrent-api/issues/659">#659</a>)</li>
<li>Add support for <code>rss/exportRules</code> and
<code>rss/importRules</code> (<a
href="https://redirect.github.com/rmartin16/qbittorrent-api/issues/686">#686</a>)</li>
<li>Add support for <code>torrents/downloadFile</code> (<a
href="https://redirect.github.com/rmartin16/qbittorrent-api/issues/659">#659</a>)</li>
<li>Add support for <code>transfer/getSpeedLimits</code> and
<code>transfer/setSpeedLimits</code> (<a
href="https://redirect.github.com/rmartin16/qbittorrent-api/issues/659">#659</a>)</li>
<li>Add support for <code>transfer/pauseSession</code> and
<code>transfer/resumeSession</code> (<a
href="https://redirect.github.com/rmartin16/qbittorrent-api/issues/678">#678</a>)</li>
<li>Add <code>share_limits_mode</code> for <code>torrents/add</code> (<a
href="https://redirect.github.com/rmartin16/qbittorrent-api/issues/659">#659</a>)</li>
<li>Add <code>ignore_dotfiles</code> for
<code>torrentcreator/addTask</code> (<a
href="https://redirect.github.com/rmartin16/qbittorrent-api/issues/678">#678</a>)</li>
<li>Add <code>ratio_limit</code>, <code>seeding_time_limit</code>,
<code>inactive_seeding_time_limit</code>,
<code>share_limits_mode</code>, and <code>share_limit_action</code> for
<code>torrents/createCategory</code> and
<code>torrents/editCategory</code> (<a
href="https://redirect.github.com/rmartin16/qbittorrent-api/issues/686">#686</a>)</li>
<li><code>save_path</code> is no longer required for
<code>torrents/editCategory</code> (<a
href="https://redirect.github.com/rmartin16/qbittorrent-api/issues/686">#686</a>)</li>
</ul>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/rmartin16/qbittorrent-api/commit/8f6f243b3f7591fcfdb40af128a8d5c1dde7e2bc"><code>8f6f243</code></a>
feat: support qBittorrent v5.3.0 (<a
href="https://redirect.github.com/rmartin16/qbittorrent-api/issues/689">#689</a>)</li>
<li><a
href="https://github.com/rmartin16/qbittorrent-api/commit/b11988e0d4c5bfe94b6104807be60c22f612b8ba"><code>b11988e</code></a>
build(deps): bump certifi from 2026.5.20 to 2026.10.19 (<a
href="https://redirect.github.com/rmartin16/qbittorrent-api/issues/688">#688</a>)</li>
<li><a
href="https://github.com/rmartin16/qbittorrent-api/commit/8fcff6c6da1ee1489e82f5cbd9f2d737ba7da0d1"><code>8fcff6c</code></a>
build(deps): bump uv from 0.11.18 to 0.13.4 (<a
href="https://redirect.github.com/rmartin16/qbittorrent-api/issues/687">#687</a>)</li>
<li>See full diff in <a
href="https://github.com/rmartin16/qbittorrent-api/compare/v2026.10.0...v2026.10.1">compare
view</a></li>
</ul>
</details>
<br />

Updates `publicsuffixlist` from 1.1.0.20261018 to 1.1.2.20261021
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/ko-zu/psl/blob/master/CHANGES.md">publicsuffixlist's
changelog</a>.</em></p>
<blockquote>
<h3>1.1.1, 1.1.2 (2026-10-21)</h3>
<p>No code changes. This release only refreshes CI and development
tooling.</p>
<ul>
<li>Update <code>astral-sh/setup-uv</code> to v10.3.0 in the GitHub
Actions workflows.</li>
<li>Refresh <code>uv.lock</code>, updating <code>certifi</code> to pick
up the bundled CA certificate
changes.</li>
<li>Fix the auto-release workflow so that it no longer bundles a stale
PSL file.</li>
</ul>
<h3>1.1.0 (2026-10-10)</h3>
<p>This version drops support for Python 3.5, 3.6 and 3.7, and now
requires
Python 3.8 or later.</p>
<p>Packaging has been migrated to PEP 621 metadata in
<code>pyproject.toml</code> using
hatchling, replacing <code>setup.py</code>, <code>setup.cfg</code> and
<code>MANIFEST.in</code>. The version is
now read from <code>publicsuffixlist.__version__</code>, and development
dependencies are
locked with uv.</p>
<ul>
<li>Add PEP 561 <code>py.typed</code> marker and complete type
annotations for the public
API, including <code>compat</code> and the update script.</li>
<li>Add an <code>accept_unknown</code> keyword argument to
<code>is_private()</code> and <code>is_public()</code>.</li>
<li>Fix <code>subdomain()</code> to honor the per-call
<code>accept_unknown</code> argument, and to
return <code>None</code> for invalid domains instead of raising
<code>TypeError</code>.</li>
<li>Correct the <code>subdomain()</code> and <code>privateparts()</code>
overload signatures.</li>
<li>Handle a malformed <code>Last-Modified</code> response header in the
update script.</li>
<li>Run tests with uv on Python 3.8 and 3.14, and update CI
actions.</li>
</ul>
<h3>1.0.2 (2024-07-13)</h3>
<ul>
<li>Use <a
href="https://github.com/typing"><code>@​typing</code></a>.overload to
indicate str-to-str domain input/output. <a
href="https://redirect.github.com/ko-zu/psl/issues/32">#32</a>.</li>
<li>Address deprecation of ByteString in python 3.14.</li>
</ul>
<h3>1.0.1 (2024-06-22)</h3>
<p>Fix internal logic where domain name passed as a tuple of bytes, that
contains
UTF-8 encoded non-ascii chars, unintentionally matched PSL. Fixes <a
href="https://redirect.github.com/ko-zu/psl/issues/31">#31</a>.</p>
<h3>1.0.0 (2024-06-20)</h3>
<p>This version drops support for Python 2.x and 3.4.</p>
<p>The internal logic has been slightly changed to address conflicting
evaluation
rules between the PSL wiki and the test data.
As with versions before 1.0.0, this module assumes that wildcards have
implicit public declarations on the wildcard root.</p>
<p>With the minimum Python version changed to 3.5, type annotations have
been added to exposed API methods to clarify expected input types.
For example, psl.publicsuffix() now accepts <code>str</code> or
<code>Tuple[bytes, ...]</code>.</p>
<ul>
<li>Add tuple of bytes style input</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/ko-zu/psl/commits">compare view</a></li>
</ul>
</details>
<br />

Updates `seleniumbase` from 4.56.2 to 4.56.3
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/seleniumbase/SeleniumBase/releases">seleniumbase's
releases</a>.</em></p>
<blockquote>
<h2>4.56.3 - Refresh dependencies for security</h2>
<h2>Refresh dependencies for security</h2>
<ul>
<li><a
href="https://github.com/seleniumbase/SeleniumBase/commit/ce39e995cd50d821b2b145b775ac4b06b775bf2b">Refresh
Python dependencies</a>
--&gt; This resolves <a
href="https://redirect.github.com/seleniumbase/SeleniumBase/issues/4531">seleniumbase/SeleniumBase#4531</a></li>
</ul>
<h2>What's Changed</h2>
<ul>
<li>Refresh dependencies for security by <a
href="https://github.com/mdmintz"><code>@​mdmintz</code></a> in <a
href="https://redirect.github.com/seleniumbase/SeleniumBase/pull/4532">seleniumbase/SeleniumBase#4532</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/seleniumbase/SeleniumBase/compare/v4.56.2...v4.56.3">https://github.com/seleniumbase/SeleniumBase/compare/v4.56.2...v4.56.3</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/seleniumbase/SeleniumBase/commit/ea0a30dc546fa82c11b6c5e2029f20238cd9cc75"><code>ea0a30d</code></a>
Merge pull request <a
href="https://redirect.github.com/seleniumbase/SeleniumBase/issues/4532">#4532</a>
from seleniumbase/refresh-dependencies-for-security</li>
<li><a
href="https://github.com/seleniumbase/SeleniumBase/commit/80bdd561374ab2a971ae6f0b1e443f5d0253d4c3"><code>80bdd56</code></a>
Version 4.56.3</li>
<li><a
href="https://github.com/seleniumbase/SeleniumBase/commit/31580882ad87b4435babc612c54878ec56c24e7a"><code>3158088</code></a>
Update MCP server versioning</li>
<li><a
href="https://github.com/seleniumbase/SeleniumBase/commit/ce39e995cd50d821b2b145b775ac4b06b775bf2b"><code>ce39e99</code></a>
Refresh Python dependencies</li>
<li><a
href="https://github.com/seleniumbase/SeleniumBase/commit/c314a34b85fe382c89e300e44caadaaaff4fb0e8"><code>c314a34</code></a>
Update Hacker News web-scraping examples</li>
<li><a
href="https://github.com/seleniumbase/SeleniumBase/commit/b82016faa306f499f73cdd4581d2965fbe04421b"><code>b82016f</code></a>
Update CDP Mode examples</li>
<li><a
href="https://github.com/seleniumbase/SeleniumBase/commit/effe113bead069ae40e4e93e14e00fa45b021c40"><code>effe113</code></a>
Update the mkdocs prepare script</li>
<li><a
href="https://github.com/seleniumbase/SeleniumBase/commit/5596ac6d2eda7689e59f5aa448b44ae8cea3be7d"><code>5596ac6</code></a>
Update the ReadMe</li>
<li>See full diff in <a
href="https://github.com/seleniumbase/SeleniumBase/compare/v4.56.2...v4.56.3">compare
view</a></li>
</ul>
</details>
<br />

Updates `prek` from 0.5.6 to 0.5.7
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/j178/prek/releases">prek's
releases</a>.</em></p>
<blockquote>
<h2>0.5.7</h2>
<h2>Release Notes</h2>
<p>Released on 2026-10-21.</p>
<h3>Enhancements</h3>
<ul>
<li>Support system Rust toolchains without rustup (<a
href="https://redirect.github.com/j178/prek/pull/2887">#2887</a>)</li>
</ul>
<h3>Performance</h3>
<ul>
<li>Use blocking file checks for CPU-heavy builtin hooks (<a
href="https://redirect.github.com/j178/prek/pull/2910">#2910</a>)</li>
</ul>
<h3>Other changes</h3>
<ul>
<li>Update CA root crates and uv for the eMudhra intermediate CA
compromise (<a
href="https://redirect.github.com/j178/prek/pull/2919">#2919</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/shaanmajid"><code>@​shaanmajid</code></a></li>
<li><a href="https://github.com/j178"><code>@​j178</code></a></li>
</ul>
<h2>Install prek 0.5.7</h2>
<h3>Install prebuilt binaries via shell script</h3>
<pre lang="sh"><code>curl --proto '=https' --tlsv1.2 -LsSf
https://github.com/j178/prek/releases/download/v0.5.7/prek-installer.sh
| sh
</code></pre>
<h3>Install prebuilt binaries via powershell script</h3>
<pre lang="sh"><code>powershell -ExecutionPolicy Bypass -c &quot;irm
https://github.com/j178/prek/releases/download/v0.5.7/prek-installer.ps1
| iex&quot;
</code></pre>
<h3>Install prebuilt binaries via Homebrew</h3>
<pre lang="sh"><code>brew install prek
</code></pre>
<h2>Download prek 0.5.7</h2>
<table>
<thead>
<tr>
<th>File</th>
<th>Platform</th>
<th>Checksum</th>
</tr>
</thead>
<tbody>
<tr>
<td><a
href="https://github.com/j178/prek/releases/download/v0.5.7/prek-aarch64-apple-darwin.tar.gz">prek-aarch64-apple-darwin.tar.gz</a></td>
<td>Apple Silicon macOS</td>
<td><a
href="https://github.com/j178/prek/releases/download/v0.5.7/prek-aarch64-apple-darwin.tar.gz.sha256">checksum</a></td>
</tr>
<tr>
<td><a
href="https://github.com/j178/prek/releases/download/v0.5.7/prek-x86_64-apple-darwin.tar.gz">prek-x86_64-apple-darwin.tar.gz</a></td>
<td>Intel macOS</td>
<td><a
href="https://github.com/j178/prek/releases/download/v0.5.7/prek-x86_64-apple-darwin.tar.gz.sha256">checksum</a></td>
</tr>
<tr>
<td><a
href="https://github.com/j178/prek/releases/download/v0.5.7/prek-aarch64-pc-windows-msvc.zip">prek-aarch64-pc-windows-msvc.zip</a></td>
<td>ARM64 Windows</td>
<td><a
href="https://github.com/j178/prek/releases/download/v0.5.7/prek-aarch64-pc-windows-msvc.zip.sha256">checksum</a></td>
</tr>
<tr>
<td><a
href="https://github.com/j178/prek/releases/download/v0.5.7/prek-x86_64-pc-windows-msvc.zip">prek-x86_64-pc-windows-msvc.zip</a></td>
<td>x64 Windows</td>
<td><a
href="https://github.com/j178/prek/releases/download/v0.5.7/prek-x86_64-pc-windows-msvc.zip.sha256">checksum</a></td>
</tr>
</tbody>
</table>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/j178/prek/blob/main/CHANGELOG.md">prek's
changelog</a>.</em></p>
<blockquote>
<h2>0.5.7</h2>
<p>Released on 2026-10-21.</p>
<h3>Enhancements</h3>
<ul>
<li>Support system Rust toolchains without rustup (<a
href="https://redirect.github.com/j178/prek/pull/2887">#2887</a>)</li>
</ul>
<h3>Performance</h3>
<ul>
<li>Use blocking file checks for CPU-heavy builtin hooks (<a
href="https://redirect.github.com/j178/prek/pull/2910">#2910</a>)</li>
</ul>
<h3>Other changes</h3>
<ul>
<li>Update CA root crates and uv for the eMudhra intermediate CA
compromise (<a
href="https://redirect.github.com/j178/prek/pull/2919">#2919</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/shaanmajid"><code>@​shaanmajid</code></a></li>
<li><a href="https://github.com/j178"><code>@​j178</code></a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/j178/prek/commit/8569a4ac59a79212fe152f3c815505775301ec1d"><code>8569a4a</code></a>
Bump version to 0.5.7 (<a
href="https://redirect.github.com/j178/prek/issues/2920">#2920</a>)</li>
<li><a
href="https://github.com/j178/prek/commit/c290bac7b2bc85e5d113bd3f20585b48f07c4cbe"><code>c290bac</code></a>
Bump certifi from 2026.7.22 to 2026.10.19 (<a
href="https://redirect.github.com/j178/prek/issues/2921">#2921</a>)</li>
<li><a
href="https://github.com/j178/prek/commit/40287b8205068b2a0c01448e59b9ac7116763c6d"><code>40287b8</code></a>
Temporarily skip Aliyun uv download in CI (<a
href="https://redirect.github.com/j178/prek/issues/2922">#2922</a>)</li>
<li><a
href="https://github.com/j178/prek/commit/062c8a0bd20cd04ea815fd1820671c42e748a39d"><code>062c8a0</code></a>
Update CA root crates and uv for the eMudhra intermediate CA compromise
(<a
href="https://redirect.github.com/j178/prek/issues/2919">#2919</a>)</li>
<li><a
href="https://github.com/j178/prek/commit/5b66378566f209aaaf71656540f2dac852ffb125"><code>5b66378</code></a>
Log download and archive extraction stages (<a
href="https://redirect.github.com/j178/prek/issues/2917">#2917</a>)</li>
<li><a
href="https://github.com/j178/prek/commit/c3693539c41d72323190d93ccab5cd312d8fcd2d"><code>c369353</code></a>
Share tar extraction across compression formats (<a
href="https://redirect.github.com/j178/prek/issues/2916">#2916</a>)</li>
<li><a
href="https://github.com/j178/prek/commit/1c82a0d0f01ecf06df2745bde2a997c742be3c90"><code>1c82a0d</code></a>
Move managed Rust toolchain discovery into the installer (<a
href="https://redirect.github.com/j178/prek/issues/2914">#2914</a>)</li>
<li><a
href="https://github.com/j178/prek/commit/2bf1958a626bd61f35c62f185aa4cf3681bf9dd2"><code>2bf1958</code></a>
Support system Rust toolchains without rustup (<a
href="https://redirect.github.com/j178/prek/issues/2887">#2887</a>)</li>
<li><a
href="https://github.com/j178/prek/commit/812e80f6d52d39db3627e0d666842919ed3ce864"><code>812e80f</code></a>
Move shared hook helpers and rename run to concurrency (<a
href="https://redirect.github.com/j178/prek/issues/2911">#2911</a>)</li>
<li><a
href="https://github.com/j178/prek/commit/615a0016fbad79be1cfb63b15cc7288ea9c6046b"><code>615a001</code></a>
Use blocking file checks for CPU-heavy builtin hooks (<a
href="https://redirect.github.com/j178/prek/issues/2910">#2910</a>)</li>
<li>See full diff in <a
href="https://github.com/j178/prek/compare/v0.5.6...v0.5.7">compare
view</a></li>
</ul>
</details>
<br />

Updates `ruff` from 0.17.1 to 0.17.2
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ruff/releases">ruff's
releases</a>.</em></p>
<blockquote>
<h2>0.17.2</h2>
<h2>Release Notes</h2>
<p>Released on 2026-10-22.</p>
<h3>Preview features</h3>
<ul>
<li>[<code>complexity</code>] Add
<code>unnecessary-regular-expression-compile</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/25533">#25533</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>Avoid syntax errors for type variables with starred constraints
(<code>UP040</code>, <code>UP046</code>, <code>UP047</code>,
<code>RUF053</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28362">#28362</a>)</li>
<li>[<code>pydocstyle</code>] Treat backslash-escaped <code>*args</code>
and <code>**kwargs</code> as documented (<code>D417</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/29536">#29536</a>)</li>
<li>[<code>pylint</code>] Avoid false positive on starred elements
(<code>PLE0643</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/29483">#29483</a>)</li>
<li>[<code>pylint</code>] Mark fixes unsafe when deleting comments
(<code>PLR5501</code>, <code>PLW0120</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/29414">#29414</a>)</li>
<li>[<code>pyupgrade</code>] Mark fix unsafe when deleting comments
(<code>UP035</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/29413">#29413</a>)</li>
</ul>
<h3>Performance</h3>
<ul>
<li>Avoid intermediate names in lint name resolution (<a
href="https://redirect.github.com/astral-sh/ruff/pull/29506">#29506</a>)</li>
<li>Prefilter bidirectional Unicode checks by UTF-8 leading bytes (<a
href="https://redirect.github.com/astral-sh/ruff/pull/29561">#29561</a>)</li>
<li>Share postfix parsing and reduce expression copies (<a
href="https://redirect.github.com/astral-sh/ruff/pull/29480">#29480</a>)</li>
</ul>
<h3>Configuration</h3>
<ul>
<li>[<code>pylint</code>] Add a configurable allowlist for
<code>magic-value-comparison</code> (<code>PLR2004</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18961">#18961</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>Clarify documentation and correct stale guidance (<a
href="https://redirect.github.com/astral-sh/ruff/pull/29374">#29374</a>)</li>
<li>[<code>pyupgrade</code>] Remove mentions of variance related to fix
safety (<code>UP040</code>, <code>UP047</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/29592">#29592</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a href="https://github.com/fixfon"><code>@​fixfon</code></a></li>
<li><a
href="https://github.com/MichaReiser"><code>@​MichaReiser</code></a></li>
<li><a
href="https://github.com/zaniebot"><code>@​zaniebot</code></a></li>
<li><a
href="https://github.com/FrancescoPezzella"><code>@​FrancescoPezzella</code></a></li>
<li><a
href="https://github.com/anishgirianish"><code>@​anishgirianish</code></a></li>
<li><a
href="https://github.com/rajveer3x"><code>@​rajveer3x</code></a></li>
<li><a
href="https://github.com/charliermarsh"><code>@​charliermarsh</code></a></li>
<li><a
href="https://github.com/LckyLke"><code>@​LckyLike</code></a></li>
<li><a
href="https://github.com/DaniBodor"><code>@​DaniBodor</code></a></li>
</ul>
<h2>Install ruff 0.17.2</h2>
<h3>Install prebuilt binaries via shell script</h3>
<pre lang="sh"><code>curl --proto '=https' --tlsv1.2 -LsSf
https://releases.astral.sh/github/ruff/releases/download/0.17.2/ruff-installer.sh
| sh
&lt;/tr&gt;&lt;/table&gt; 
</code></pre>
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md">ruff's
changelog</a>.</em></p>
<blockquote>
<h2>0.17.2</h2>
<p>Released on 2026-10-22.</p>
<h3>Preview features</h3>
<ul>
<li>[<code>complexity</code>] Add
<code>unnecessary-regular-expression-compile</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/25533">#25533</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>Avoid syntax errors for type variables with starred constraints
(<code>UP040</code>, <code>UP046</code>, <code>UP047</code>,
<code>RUF053</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28362">#28362</a>)</li>
<li>[<code>pydocstyle</code>] Treat backslash-escaped <code>*args</code>
and <code>**kwargs</code> as documented (<code>D417</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/29536">#29536</a>)</li>
<li>[<code>pylint</code>] Avoid false positive on starred elements
(<code>PLE0643</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/29483">#29483</a>)</li>
<li>[<code>pylint</code>] Mark fixes unsafe when deleting comments
(<code>PLR5501</code>, <code>PLW0120</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/29414">#29414</a>)</li>
<li>[<code>pyupgrade</code>] Mark fix unsafe when deleting comments
(<code>UP035</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/29413">#29413</a>)</li>
</ul>
<h3>Performance</h3>
<ul>
<li>Avoid intermediate names in lint name resolution (<a
href="https://redirect.github.com/astral-sh/ruff/pull/29506">#29506</a>)</li>
<li>Prefilter bidirectional Unicode checks by UTF-8 leading bytes (<a
href="https://redirect.github.com/astral-sh/ruff/pull/29561">#29561</a>)</li>
<li>Share postfix parsing and reduce expression copies (<a
href="https://redirect.github.com/astral-sh/ruff/pull/29480">#29480</a>)</li>
</ul>
<h3>Configuration</h3>
<ul>
<li>[<code>pylint</code>] Add a configurable allowlist for
<code>magic-value-comparison</code> (<code>PLR2004</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18961">#18961</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>Clarify documentation and correct stale guidance (<a
href="https://redirect.github.com/astral-sh/ruff/pull/29374">#29374</a>)</li>
<li>[<code>pyupgrade</code>] Remove mentions of variance related to fix
safety (<code>UP040</code>, <code>UP047</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/29592">#29592</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a href="https://github.com/fixfon"><code>@​fixfon</code></a></li>
<li><a
href="https://github.com/MichaReiser"><code>@​MichaReiser</code></a></li>
<li><a
href="https://github.com/zaniebot"><code>@​zaniebot</code></a></li>
<li><a
href="https://github.com/FrancescoPezzella"><code>@​FrancescoPezzella</code></a></li>
<li><a
href="https://github.com/anishgirianish"><code>@​anishgirianish</code></a></li>
<li><a
href="https://github.com/rajveer3x"><code>@​rajveer3x</code></a></li>
<li><a
href="https://github.com/charliermarsh"><code>@​charliermarsh</code></a></li>
<li><a
href="https://github.com/LckyLke"><code>@​LckyLike</code></a></li>
<li><a
href="https://github.com/DaniBodor"><code>@​DaniBodor</code></a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/astral-sh/ruff/commit/30516b42ab972ffa2569e5efcfee81135da466d3"><code>30516b4</code></a>
Bump version to 0.17.2 (<a
href="https://redirect.github.com/astral-sh/ruff/issues/29637">#29637</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/59a9e85a7b6dc4e4592cd29de32a214c150d663c"><code>59a9e85</code></a>
[ty] Generalize nested types in inferred return types (<a
href="https://redirect.github.com/astral-sh/ruff/issues/29488">#29488</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/0d562aac5d7c9adae13c8a4ac69dc106d2a331ff"><code>0d562aa</code></a>
[ty] Check inherited attribute conflicts (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28559">#28559</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/48dcdd0e65ee4320da2ceff3e76a8b10cbc5d53b"><code>48dcdd0</code></a>
[ty] Restrict range implications from gradual equivalence (<a
href="https://redirect.github.com/astral-sh/ruff/issues/29577">#29577</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/734d75ae5baf6471ac37dd9b766fceecd8a09497"><code>734d75a</code></a>
[ty] Check for unsatisfiable bodies before existentially quantifying (<a
href="https://redirect.github.com/astral-sh/ruff/issues/29504">#29504</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/b0f95269f9dc6e14dd4ac8738d99f211f75d73bc"><code>b0f9526</code></a>
[ty] Preserve checks for recursive descriptor setter types (<a
href="https://redirect.github.com/astral-sh/ruff/issues/29148">#29148</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/32869b468e607e77bc0331881e18f9c4f2d5fc6d"><code>32869b4</code></a>
Avoid creating deployments for automation jobs (<a
href="https://redirect.github.com/astral-sh/ruff/issues/29626">#29626</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/ec891bab3b4dbd18bee7ce5d61097044a8d62acd"><code>ec891ba</code></a>
Link the commit in pull request report footers (<a
href="https://redirect.github.com/astral-sh/ruff/issues/29621">#29621</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/895874820940b48192b7d3d27e55b7fd5ad136f2"><code>8958748</code></a>
[ty] Publish ecosystem reports from GitHub Actions (<a
href="https://redirect.github.com/astral-sh/ruff/issues/29609">#29609</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/01f539487f851a8fe7963388e22b147824df3a1f"><code>01f5394</code></a>
[ty] Publish typing conformance reports from GitHub Actions (<a
href="https://redirect.github.com/astral-sh/ruff/issues/29608">#29608</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/astral-sh/ruff/compare/0.17.1...0.17.2">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-26 02:40:31 -06:00
splitsec2 f02f0d7365 fix(notifications): say what applies on a user's own notification routes page (#1588)
This is the UI side of #1581. A non-admin looking at their own
notification routes reads the same help text the admin does, including
"or mailtos://...?to={Email} in the admin default". They can't set that
default, a personal route can't use mailtos (personal routes are limited
to ntfy, Gotify, Discord, Slack, Telegram, Pushover and PushBullet), and
nothing on the page says whether an admin default exists. The default's
URL is hidden from them on purpose since it can carry credentials, so
the page just shows an empty All row, the same as when nothing is set
up.

What changes, on the user's own page only (the admin's view of a user
keeps the full text):

- The help text drops the admin default and mailtos part and lists the
services a personal route can use.
- The edit-context response now carries `adminDefaultRoutesSet`, a
boolean that is true when an admin default route with a URL exists. The
URL itself is still not sent, and the existing test that checks nothing
from the admin's values leaks still passes.
- When that is true, the help text adds a line saying a default applies
until the user adds their own, and once they have, that theirs replace
it.

How routes are resolved is unchanged. A user's own routes still replace
the default and don't merge with it. I didn't try to add mailtos for
personal routes, since keeping SMTP credentials in a user's own URL is
what the admin default avoids.

Tests: two route tests (flag true with a URL in the admin default, false
with an empty row), a vitest file for the description text, and the full
frontend suite, oxlint, oxfmt, tsc, ruff and basedpyright are clean. I
haven't looked at the page in a browser.
2026-10-26 01:32:35 -06:00
splitsec2 46b9e7d8a3 fix(library): match a shelf title against the full title when the search title is only the series (#1587)
Fixes #1584. Thanks to @joeRob2468 for the write-up, which pinned this
down to the line.

Hardcover cuts a title like "Mistborn: The Final Empire" down to
"Mistborn" for searching when it can't tell the series prefix from a
title prefix, and search results don't carry the series. The library
check then matched the shelf title "Mistborn: The Final Empire" against
"Mistborn", saw "final empire" as extra words and took it for a longer,
different work (the "Dune" vs "Dune Messiah" rule), so the book got no
In library badge.

`match_entries` now tries the search title first as before and, if that
finds nothing and the full title is different, tries the full title too.
The full title is the more specific of the two so it should rarely add
false positives. Another book in the same series still doesn't match,
there is a test for that, and the Dune and Dune Messiah test passes
unchanged. The matching loop moved into a small helper to run it twice,
nothing in it changed.

This only touches the library check. The same short search title also
feeds release searches and auto-download matching, which I left alone
here because loosening or tightening those changes what gets searched
and downloaded for everyone.

Tests fail on current main without the change. The library tests, ruff
and basedpyright are clean.
2026-10-26 01:30:33 -06:00
Josh Theisen e3fd7898f6 fix(user-notifications): simplify row key serialization in TableField and clean up UserNo… (#1583)
- simplify row key serialization in TableField
- clean up userNotificationOverridesSection

Previously, after typing a single character, the browser would lose
focus due to the row keys changes on every new value. The fix makes the
row key independent of the URL’s changing text.

Additionally, fixed the per-user notification routes so that unchecking
"All" clears all event selections.
2026-10-26 00:51:41 -06:00
splitsec2 ac14e4dd24 fix(downloads): a swarm note change is not activity for the stall timer (#1572)
The torrent stall timer can be deferred for as long as the swarm keeps
changing. Since #1494 the torrent handler appends a note to its progress
message (`0% · 2 seeds`, and `· 0 seeds, giving up in 7m` while the
no-seeders clock runs). `update_download_status` treats any changed
message as activity, so a seed count that goes 2, 3, 1 between polls, or
the give-up countdown ticking down every minute, refreshes
`_last_activity` and the torrent never stalls. A torrent whose seed
count stays constant still stalls, which is why this is easy to miss.

`shelfmark/download/activity.py` already says what counts: a changed
status event or a changed progress value, and a message that changes on
a timer proves nothing. So `update_download_status` now compares
messages through a small `activity_key()` that drops that trailing seed
note. The card still gets every message and shows the live seed count,
only the stall clock ignores a change in the note. A new progress
percentage, a different client message or a status change still counts
as activity.

The handler builds the note in `_seed_note` and `activity_key` has to
match it, so one test builds the note for a range of seed counts and
countdowns and checks the key strips all of them. That also covers the
gap #1494 left, where no test connected a handler's message to the
orchestrator: the other two drive `update_download_status` with real
notes and a fake clock. Without the change the note test fails and the
key tests cannot even import `activity_key`. The other orchestrator test
is a control that a progress or status change still counts. Full suite
passes, and each new test also passes when run alone.
2026-10-26 00:45:28 -06:00
misko903andClaude Opus 5.5 d50440f6c2 fix(webshare): clear the "Resolving" status once the download starts (#1575)
## What

A Webshare.cz download shows "Resolving Webshare link" for its entire
duration, so a large download (e.g. a 1.3 GB audiobook archive) looks
stuck.

## Why

After the link was resolved, the handler called
`status_callback("downloading", None)`. `update_download_status` treats
a `None` message as "keep the current message", so the "Resolving
Webshare link" detail stayed in the activity panel. The HTTP handler
sends `""` for exactly this reason.

## How

- Report `downloading` with an empty message, which clears the resolving
text.
- When the download response has no `Content-Length`, use the release's
size (`task.size`, parsed with `parse_size_string`) as the total for
progress. Without it, progress never moved, and stall detection would
flag a healthy long download after 5 minutes.

## Testing

- New tests in `tests/webshare/test_handler.py`: the downloading status
clears the message, and progress is computed from the release size when
there is no Content-Length.
- `uv run pytest tests/webshare` is green (34 passed), and `ruff check`
and `ruff format --check` are clean.

Follow-up to #1543.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 11:00:15 -04:00
splitsec2 525b094b57 fix(clients): hand a finished wrong-type directory on instead of polling out the timeout (#1573)
A torrent that finishes with the wrong kind of files in it holds the
download for the whole completed-path timeout (60 seconds by default, up
to an hour) and then fails with "Completed download has no stable
supported files yet." An ebook task whose torrent holds only an `.m4b`,
an audiobook task that got an `.epub`, or a `.pdf`-only release with the
default format list all land here. In v1.4.0 these failed with the
specific format error from post-processing, but the wait for the sync to
settle (#1464) only counts files of the task's own type, so it keeps
polling for files that are never going to appear.

If the directory has no supported files, `_wait_for_completed_path` now
looks for finished book or audio files that this task does not accept
(the audiobook formats, the default ebook formats and pdf). When it
finds some and they are the same on two polls in a row, it returns the
path so post-processing can say what is wrong with the formats. Cover
art and notes alone do not count, because that is what a directory looks
like while the real files are still syncing over a remote mount, so
those keep waiting as before. A wrong-type file that is still growing
keeps waiting too. With no wait configured there is only one sample, and
a wrong-type file is handed on straight away.

The existing test that pins "no book files, no wait configured" uses a
jpg, so it stays as it is. I extended the test helper to take a content
type, which the wait tests never passed before. Four new cases fail
without the change (a wrong-type directory for ebook, audiobook and pdf
tasks), and two more check that sidecar-only and still-growing
directories keep waiting. Full suite passes.
2026-10-24 20:41:21 -06:00
splitsec2 47f0acdd31 fix(logging): mask userinfo and path-segment credentials, route stray loggers through the formatter (#1571)
Logs get pasted into issues, and the formatter from #1488 only masks
`?key=value` query parameters. I went through what else commonly ends up
in a log line and found these unmasked:

- credentials in a URL's userinfo, like a proxy's
`socks5://user:pass@host:1080` or `http://admin:secret@qbittorrent:8080`
- a passkey as a path segment, like `/rss/<key>` or
`/passkey/<key>/get.torrent`, which private trackers use
- the token in a Telegram bot, Discord webhook or Slack webhook URL,
which is what a notification URL looks like when it gets logged

All three are masked now, in `redact_secrets`, so they apply to every
handler. The path rule only fires after a segment that names a secret
(`passkey`, `apikey`, `rsskey`, `authkey`, `token`, `secret`, `rss`,
`torznab`) followed by 16 or more token characters. I left out generic
words like `download` on purpose, because `/api/download/<md5>/cancel`
appears in our own request log and the ids there are useful when
debugging. That is the tradeoff: a passkey in a `/download/<passkey>/`
path still gets through.

Separately, four modules created their logger with plain
`logging.getLogger`, so nothing they logged went through the formatter
at all: `api/websocket.py`, `download/clients/__init__.py`, and the
Jackett, Newznab and Prowlarr package inits. They use `setup_logger` now
like everything else.

Tests: ten cases, seven for the new shapes and three that must stay
readable (an md5 route id, a short `/rss/latest`, an email address),
plus two that check the stray modules now carry the redacting formatter.
Nine of them fail without the change. Full suite passes.

Not covered here: `/api/debug` still zips the existing log files as they
are on disk, so anything logged before this change rides along in a
bundle. That is a separate change in `genDebug.sh`.
2026-10-24 17:19:53 -06:00
splitsec2 ef40a38546 fix: report a stopped download coordinator in /api/health (#1568)
If the download coordinator thread dies, every task sits at "Queued" and
nothing says why. The rest of the app keeps answering, `/api/health`
stays green and the container looks fine. #823 and #1166 were both that,
and the loop's `except Exception` cannot catch everything that can end a
thread.

`/api/health` now reports it. The response gets a `coordinator` field,
`running` or `stopped`, and when it is stopped the status is `error` and
the HTTP code is 503. The Docker healthcheck in the Dockerfile and the
one in the readme both use `curl -f`, so the container shows as
unhealthy and anything watching health (Uptime Kuma, autoheal) can act
on it. It needs no login, same as before, and shows no queue contents.

That 503 is the one decision here. Keeping the 200 and only adding a
`degraded` entry would not trip a status-code health check, which is the
whole point, so I went with 503. Easy to flip if you would rather not.

The orchestrator gets a small `coordinator_running()` that asks whether
the thread is alive. `start()` already knows how to restart a dead
thread, so restarting it automatically would be the true fix, but I
would rather the failure be visible first and decide on that separately.

Tests: three for the route (ok, 503, no login needed) and three for
`coordinator_running` (never started, alive, dead). They fail without
the change. One existing test hits `/api/health` through an app that
never starts the coordinator, so it now patches that. The readme's
health section has a sentence about the 503. Full suite passes, ruff and
basedpyright are clean.
2026-10-24 17:12:58 -06:00
splitsec2 973cf472a2 test(image-cache): flush window test no longer depends on float rounding (#1580)
`test_cache_hit_flushes_the_index_once_the_window_has_passed` (from
#1544) failed on the first attempt of two of my PRs' Python Tests runs
today (#1576, #1579) and passed on rerun, with nothing in either PR
touching the image cache.

The test sets the clock to exactly `last_saved + ACCESS_FLUSH_SECONDS`
and expects a flush. `(now + 30) - now` isn't always 30.0 in floating
point. For example `105.65207077218265 + 30 - 105.65207077218265` is
`29.999999999999986`, so the `>=` check is false and the flush never
happens. That only shows up when the monotonic value is small, which
fits a freshly booted runner (on this box the uptime is in the millions
of seconds and it never fails). I haven't been able to see the runner's
actual uptime in the CI logs, so that part is an inference, but pinning
`_last_saved` to that value reproduces the exact failure (`assert [] ==
[1]`) locally.

The test now puts the clock one second past the window. The production
check is fine, real elapsed time doesn't have this edge, so only the
test changes.
2026-10-24 17:10:08 -06:00
splitsec2 b248bcd536 fix(clients): import a qBittorrent torrent only when every listed file is on disk (#1577)
Fixes #1561, with thanks to @tmussche for the write-up, which had the
cause and the fix. When the files reach Shelfmark through a sync
(Resilio in the report), the wait for the completed path accepts the
folder once two samples a few seconds apart look the same. A sync that
copies in batches can pause longer than that, so 10 of 23 files were
imported and some of those were still partial copies.

For qBittorrent the client can say what the finished download holds, so
the wait now checks that. `DownloadClient` gets an optional
`get_expected_files()` that returns `ExpectedFile(name, size)` entries,
or None when the client cannot say, which is the default and keeps every
other client as it was. qBittorrent answers it from
`/api/v2/torrents/files`, leaving out files the torrent does not
download (priority 0), zero-byte entries and BEP 47 padding files.
`_wait_for_completed_path` asks once, and while any of those files is
missing or smaller than its final size it keeps waiting, using the same
timeout as before. When the wait runs out the error now says how far it
got, for example "Completed download is not fully on disk yet (10 of 23
files)." Once everything is there the existing stability check still
runs, so nothing is accepted that was accepted before.

Names from the client start with the torrent's top-level folder, so each
file is looked up with and without it, which also covers a torrent saved
without a subfolder. A single-file torrent is checked by size too, since
a file that is still syncing exists at a smaller size.

Two things I would like a second look at: the comparison is on exact
size, so a setup where something rewrites the files after the torrent
finishes would never match and would run into the timeout; and the file
list is read once per wait, not on every poll. If the client does not
answer, nothing changes.

I also moved the nested authenticated GET in the path derivation into a
`_get_with_auth` method so both calls share it, and added a sentence
about this to `docs/configuration.md`. Tests: eight for the wait
(partial folder, truncated file, files arriving during the wait,
complete folder, no top-level folder, single file both ways, and a
client without a list), and six for the qBittorrent file list. The wait
tests that depend on the new behaviour fail on current main. Full suite
passes.
2026-10-24 17:08:04 -06:00
splitsec2 9011319ade refactor: one lookup for the supported formats, public names for two shared helpers (#1576)
Six places read the Supported Book Formats and Supported Audiobook
Formats settings on their own: post-processing, the post-process scan,
IRC, slskd, Prowlarr and direct download. For ebooks they already
agreed, since they all fall back to `DEFAULT_EBOOK_FORMATS`. For
audiobooks they did not. The settings registry and slskd fall back to
every audio format plus zip and rar, while post-processing and IRC fell
back to m4b and mp3 only.

They now share `shelfmark/core/formats.py`, with
`get_supported_formats`, `get_supported_audiobook_formats` and a
content-type aware `get_supported_formats_for`, and a shared
`DEFAULT_AUDIOBOOK_FORMATS` in `core/utils.py` next to the ebook one.
`policy.py` re-exports the same functions, so nothing that imports them
from there changes. It is not in `policy.py` itself because importing
the `postprocess` package pulls in the router, which imports the release
sources, so a source could not import from it without a cycle.

One behaviour difference, and only in the fallback: with the audiobook
setting unset, or emptied, post-processing and IRC used to accept m4b
and mp3 and now accept the full default list like slskd and the settings
page already did. A configured list is read exactly as before. Direct
download's own helper used the raw configured list and now reads the
same normalized one, which is identical for any list the settings page
can save.

Also public now: `parse_size` in the Prowlarr source (slskd and Newznab
imported it with the underscore) and
`coerce_completed_path_timeout_seconds` in the client base handler
(slskd imported that too).

Not changed on purpose: slskd's `_coerce_int` looks like a copy of
`coerce_int` but is not. It reads `"12.0"` as 12 and `True` as 0, where
`coerce_int` gives 0 and 1. And the `_parse_size` in the IRC source is a
different function, string to bytes.

Tests: a new set checks that post-processing, IRC and slskd all fall
back to the shared defaults and that the settings default is the shared
one, and the scan-archive and IRC tests now patch the shared config
instead of the per-module copies. Full suite passes.
2026-10-24 16:31:07 -06:00
splitsec2 606e94fde2 fix(settings): offer the seed settings for qBittorrent only (#1574)
The two seed settings, Give Up With No Seeders and Minimum Seeders, show
up for every torrent client, but only qBittorrent reports a seed count.
With Transmission, Deluge or rTorrent you can set both and nothing
happens. The first one says "Only qBittorrent reports seed counts" at
the end of its description, the second says nothing about it.

Both are now shown only when qBittorrent is the selected client, the
same `show_when` the other qBittorrent fields use, and Minimum Seeders
gets the same sentence. A value someone already saved for another client
stays in their config, it just is not shown, and it had no effect before
either.

`docs/environment-variables.md` is regenerated for the changed
description, which is two lines. One test checks that both fields are
tied to qBittorrent and say so, and it fails without the change.
2026-10-24 09:15:55 -06:00
splitsec2 70fe4b8c89 fix(hardcover): keep the scheduler alive on an unreadable interval, share one history connection per sync (#1569)
These are the follow-ups from the review notes on #1516 and #1534 that I
said I would do once the series had merged.

The scheduler waits for the next cycle outside the try that guards the
cycle itself, so an interval setting that raised would end the thread
and nothing would sync again until a restart. It now logs the error and
tries again after six hours. `docs/hardcover-sync.md` says so.

The history check in the sync opened a new SQLite connection for every
book on the shelf. It opens one per sync now and shares it, which adds
up on a slow disk or a small board.

The two test nits from #1534 are in as well: a `parametrize` with a
single case, and an unused argument on a helper.

The thread surviving a failed wait and the shared connection each have a
test that fails without the change. Ruff, basedpyright and the backend
suite pass (5297 passed).
2026-10-24 09:11:47 -06:00
splitsec2 a63d9e3e21 docs: regenerate the environment variable reference (#1565)
Sorry about this one. The environment variable references had also
fallen well behind, and again I was a big part of that. A bunch of the
gaps come from my own PRs (Hardcover sync, auto-download, the
Audiobookshelf library check) where I charged ahead with the
functionality and skipped the boring documentation part (did I mention
that documentation is boring?).

I again had Claude compare the docs to the code and generate the
updates, so it would be good to have another human look this over before
it merges. The doc diff is just the generator's output. The part worth a
real read is the handful of new entries in
`scripts/generate_env_docs.py`, since I wrote those descriptions from
`entrypoint.sh` and `tor.sh` and not from a settings definition.

What changed:

- Regenerated `docs/environment-variables.md`. It had 287 variables and
the generator now produces 311. The 21 that were missing are the
Hardcover Sync tab (6), auto-download (11) and the Audiobookshelf
library check (4). Nothing was removed and no existing default, type or
option changed.
- `SHELFMARK_API_KEY_READONLY` was only ever hand-edited into the doc,
so the generator did not know it and a plain regeneration would have
dropped the row. It is in the generator now.
- Added `UMASK`, `TOR_CHECK_INTERVAL` and `TOR_MAX_FAILURES`. The code
reads all three and no doc mentioned them.
- The table of contents built its anchors by lowercasing and swapping
spaces, so the Webshare.cz and Moly.hu links were already broken (GitHub
drops the dots) and Soulseek (slskd) would have broken with the
parentheses. They now follow GitHub's rule.

Two tests cover the new entries and the anchors, and both fail without
the generator change. To regenerate: `python
scripts/generate_env_docs.py` on Python 3.14.

A test that fails when the committed file differs from the generator
output would have caught this drift, but then every PR that adds a
setting has to regenerate the doc. I left that out, your call if you
want it.
2026-10-23 22:02:37 -06:00
splitsec2 e273e7b0ed docs(dev): bring the plugin guides in line with the current code (#1566)
This is the biggest of the docs batch, and this time I don't think it
was my PRs that caused it. The plugin guides fell behind as the plugin
API changed over several releases, and nobody updated them along the
way.

Same arrangement as the others: Claude compared the guides to the code
and wrote the changes, so another human look before this merges would be
good. Someone who knows the plugin API well would catch things I would
not. These are the parts I would read first: the search plan table, the
`SourceUnavailableError` advice in the error handling section, and the
`locating` status row.

What was wrong and is now fixed, all checked against the code:

Release sources guide
- `search` takes `(book, plan, *, expand_search, content_type)`. Every
sample had the old one-argument signature, so a source written from the
guide raised a TypeError on its first search. There is now a short table
of the search plan fields.
- A source is registered by adding its module to
`_BUILTIN_SOURCE_MODULES`. The guide said to add an import at the bottom
of `__init__.py`.
- `get_column_config` is an instance method, not a classmethod, and
`ColumnRenderType.SEEDERS` does not exist (the real members are listed).
- `download` can return a `HandoffResult`. `list_available_sources`
lists every source with an `enabled` flag, it does not filter.
- `group="sources"` is gone, since only `direct_download` and
`metadata_providers` exist.
- Field lists for `Release`, `DownloadTask`, `BookMetadata`,
`ColumnSchema` and `ReleaseColumnConfig` are brought up to date, with
the protocol enum and the `locating` status.
- The optional hooks that were not mentioned (`post_process_cleanup`,
`build_retry_resolution_fields`, `list_authors`, `seed_complaints`,
`get_record`, `get_destination_override`, `search_results_are_releases`)
are documented.

Plugin settings guide
- The examples imported from `shelfmark.metadata_providers.base` and
`shelfmark.release_sources.base`, which do not exist. The metadata
example also skipped the abstract `search_by_isbn` and the kwargs
factory.
- Value priority now starts with the environment variable, and
`search_mode` is listed next to `general` as using `settings.json`. The
`metadata_providers` group order is 12, not 50.
- Documented `TagListField`, `OrderableListField`, `TableField`,
`env_var`, `env_supported`, `user_overridable`, `universal_only`,
`filter_by_field`, `register_on_save` and the `current_values` argument
for action callbacks.

Also in here: `docs/dev/index.md` was a TODO stub and is now a short
index linked from `docs/index.md`, a dead link in the metadata providers
README is fixed, and the README table gains Databáze knih and Moly.hu.

To check the samples were not just plausible, I ran the quick start and
the full BookNet example against the real registry. Both register,
instantiate and return their column config. The old BookNet example
failed on import with a NameError, because the Test Connection callback
was defined below the settings function that references it. The
decorator calls that function straight away, so both settings snippets
now define the callback first.
2026-10-23 22:02:18 -06:00
splitsec2 20848a8774 docs: small fixes from a check of the docs against the code (#1567)
These are the leftovers from the docs check, the fixes that did not
belong in the other three.

Claude did the comparison and wrote the changes here too, so I would
still like a human look before it merges. The one new piece of prose
worth a read is `troubleshooting.md`. It was a TODO page that two other
pages link to, so I filled it with only what I could confirm in the
code: where the logs go, `LOG_LEVEL`, the `DEBUG=true` bundle from the
bug report template, and reporting an issue. Happy to drop it back to a
stub if you would rather write that one yourself.

- `configuration.md`, `custom-scripts.md`, `users-and-requests.md`:
Booklore is Grimmory in the UI now. The stored mode value is still
`booklore`, and the custom script doc says so. The hardlink heading now
matches the "Hardlink Book Torrents" and "Hardlink Audiobook Torrents"
checkboxes.
- `custom-scripts.md`: the email output runs scripts too
(`phase=post_email`, `output.mode=email`, details under
`output.details.email`). It was missing from the phase list.
- `users-and-requests.md`: a delivery that fails with no retry available
goes back to pending on its own, and the admin reopen action is for
rejected requests. The page said an admin reopens a failed delivery.
Also noted that rules cannot use Request Book.
- `hardcover-sync.md`: added the missing
`AUTO_DOWNLOAD_AUDIOBOOK_MIN_SIZE_PERCENT` row and a sentence in the
ranking paragraph.
- `api-access.md`: an admin session also reads `/api/stats`, and what
the 403 says.
- `installation.md`: points at the Lite, Tor and WireGuard variants.

Docs only, no code touched.
2026-10-23 22:01:54 -06:00
splitsec2 6b775cd9e8 refactor: move /api/stats into core/stats_routes.py (#1563)
The sample extraction from Discussion #1536: `/api/stats` moves out of
`main.py` into `shelfmark/core/stats_routes.py`, registered with
`register_stats_routes(app, ...)` like the other route modules. The
route logic is the same, and no test changed.

`main.py` passes two callables instead of values, one for the user
database and one for the auth mode. They are called per request, so the
tests that patch `main.user_db` and `main.get_auth_mode` after import
still work. The read-only key allowlist in the middleware now uses the
path constant from the new module, so the path lives in one place.

This is only the shape. If it looks right I'll move the route groups
from the 1.5.0 PRs the same way, one PR each. If you'd rather leave
`main.py` as it is, close this and no harm done.
2026-10-23 21:51:58 -06:00
splitsec2 61419451e4 docs(readme): bring the feature lists and project scope up to date (#1564)
Sorry, this one is overdue. The readme still describes Shelfmark as it
was a few releases ago. Part of that is on me: Hardcover Sync, Library
Check and a few other things I added came in through PRs where I charged
ahead with the functionality and skipped the boring documentation part.
The rest are features other people added (Jackett, Webshare.cz, DNB and
so on) that never made it into the readme either.

I had Claude compare the readme to the code and generate the updates, so
it would be good to have another human look this over before it merges.
The scope section in particular is your call, since it states what
Shelfmark is for.

What changed:

- **Project Scope** said Shelfmark doesn't know what you own, doesn't
integrate with library software and has no background automation.
Library Check and Hardcover Sync ship exactly those things, so the list
now says what is still true (it never edits your library, and Hardcover
Sync is the one optional background job) and links both docs. I kept the
four bullets and the "not missing features" line.
- **Sources and providers** now include Jackett, Webshare.cz and
OceanofPDF, and DNB, Databáze knih and Moly.hu.
- **Features** gain Library Check and Hardcover Sync, both linking to
their existing docs pages.
- **Settings list** gets the download clients (including the four debrid
services), Jackett and Webshare.cz, and the Library Link bullet mentions
the audiobook library URL.

Docs only, no code touched. Every name and link was checked against the
code and the docs folder.
2026-10-23 21:51:32 -06:00
splitsec2 d7a4b6b859 fix: keep exception text out of the status, config and release search responses (#1562)
Same idea as #1558, for three more places that hand `str(e)` to whoever
is logged in. These are code scanning alerts 106, 142 and 143.

`/api/status` and `/api/config` returned the raw exception text of an
OSError, RuntimeError and so on with the 500. They now return "Could not
read the download status" and "Could not load the configuration". The
full error is still logged with its trace.

For `/api/releases`, a source failing with an unexpected error put
`source: <exception text>` into the error list that goes back to the
caller. `search_source_releases` takes a new `include_error_detail`
flag. The route passes True for admins (and when auth is off, where
everyone is treated as an admin) and False for everyone else, who get
`source: search failed`. The message of a `SourceUnavailableError` is
written for the user, so it is kept either way, and the background
auto-download caller keeps the default and sees the full text as before.

Left alone on purpose: the `reason` in the release inspect response,
since a test covers that it carries the error text and it looks
intentional.

Tests: two for the routes and two for the helper. All four fail without
the change. Full suite passes (5295), ruff and basedpyright are clean.
2026-10-23 21:06:26 -06:00
23b3b3a9d8 feat: add Jackett release source (#1521)
## Summary
Adds Jackett as a separate release source (`jackett`), as requested in
#1443.

- New `shelfmark/release_sources/jackett/` package: API client, settings
tab, source and handler.
- Searches Jackett's Torznab endpoints: the `all` aggregate by default,
or each selected indexer individually. Failed or timed-out searches
raise `SourceUnavailableError` instead of reporting "no releases found".
- Reuses Prowlarr code rather than duplicating it: the Torznab parser
(now also reads `<jackettindexer>`), `_prowlarr_result_to_release` (new
optional `source`/`source_id` args), the release cache, URL/protocol
helpers, the timeout clamp and size-limit helper (new optional
config-key args), and the handler's `list_files` / retry-restore logic.
- Downloads use the existing shared torrent client settings.
- `JACKETT_URL` is a trusted origin for `.torrent` fetching (it is
usually on the LAN). Prowlarr's `X-Api-Key` is not sent to it.
- Added a Jackett section to `docs/environment-variables.md`.

## Screenshots

<img width="1117" height="936" alt="Screenshot 2026-10-21 at 13-45-34
Shelfmark"
src="https://github.com/user-attachments/assets/00339999-72c7-4226-bd9a-df8b325a7e22"
/>

<img width="1117" height="938" alt="Screenshot 2026-10-21 at 13-50-38
Shelfmark"
src="https://github.com/user-attachments/assets/3c9cd2b4-932a-4b5c-9e10-6ec22b5f987d"
/>

<img width="1117" height="937" alt="Screenshot 2026-10-21 at 13-50-57
Shelfmark"
src="https://github.com/user-attachments/assets/9c4d0ed9-da2f-4323-b188-341b45066efd"
/>

## Not included
- First-run onboarding does not offer Jackett yet.
- No Jackett-specific category settings; it uses the standard 7000 /
3030 categories.

## Testing
- New unit tests in `tests/jackett/` (client, source, handler) using
mocked responses.
- Full suite passes except 11 `tests/e2e` tests that also fail on a
clean tree here (cannot write `/var/log/shelfmark`).
- Tested against a live Jackett instance.

Closes #1443

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: CaliBrain <calibrain@l4n.xyz>
2026-10-23 17:46:41 -04:00