zip 8.6.0 -> 9.1.2 with default-features = false, features = ["deflate"]: ugoira frame zips are stored/deflate only, so the default codec set was dead weight — and its zstd 0.13 stack (RUSTSEC-2026-0391, -0395..-0406, -0410) has no fixed release inside zip <=9.0.0's ^0.13.3 pin. ctutils 0.4.2 (RUSTSEC-2026-0385) leaves with zip's aes-crypto feature.
tokio 1.53.3 (RUSTSEC-2026-0386), rustls-webpki 0.103.16 (RUSTSEC-2026-0382), webpki-roots 1.0.10 (RUSTSEC-2026-0381).
cargo audit on the new lock reports only the unmaintained dotenv (RUSTSEC-2021-0141) and proc-macro-error2 (RUSTSEC-2026-0173) warnings, which denyWarnings: false does not fail on. A new pixiv test pins that both stored and deflate ugoira frames decode with the reduced zip feature set.
A handler whose row was re-leased while it sat between heartbeats (a
>=120 s stall) still ran the channel forward, opened the edit prompt and
released the keep-alive temp media the new holder was using; only the
terminal write was token-guarded, which left the side effects to run
twice. The lease is now exposed to the handler on a task-local
(Lease/lease_still_held) and the completion path re-reads it, since the
loss may have gone unnoticed by the heartbeat. The forward retry is gated
the same way.
A Permanent forward failure kept the prompt live, so the next Confirm
rebuilt the task with forward_offset 0 and copied the batches that had
already reached the channel a second time. A failure whose task offset is
non-zero now settles the prompt (as the retryable path does); a failure
that copied nothing still leaves it live for a retry.
The pipeline read settings through get(), which degrades a failed read to
defaults. A send then went out with the chat's channel forward and
edit-before-forward silently ignored, and the task it built carried those
defaults into the retry payload. try_get() is the strict read; an
unreadable row now drops the send and tells the user.
A heartbeat write error abandoned the attempt at once. The lease is still
valid until locked_until, so the attempt was dropped for nothing: the row
was recovered later and the task re-ran from the start, although its side
effects (a sent album, a copied post) may already have happened. A failed
beat now retries at the next tick; the attempt is abandoned only once the
next beat could land at or past the last confirmed expiry.
Three places disagreed with AGENTS' own level rules: get_chat/get_chat_administrators failures during /set_channel printed at error even though the usual cause is a mistyped channel name the user fixes on the spot (error is reserved for dead letters and the like — now warn, same as other user-served degradations); the edit-before-forward callback arrival line logged at info while the sibling arrival lines for commands and inline queries log at debug (now debug, still carries the escaped payload); and the two upload-fallback lines logged at info while photo.rs's parallel degradations log at warn (now warn both — Telegram failing to fetch our media is a degradation that leaves the user served). AGENTS' convention sentence is now explicit about all three instead of the ambiguous '(fallback, retry enqueue, dead-letter is error)'.