Skip to content

Release 0.36.0 - #31

Merged
Dim145 merged 1 commit into
mainfrom
release/0.36.0
Sep 10, 2026
Merged

Dim145 merged 1 commit into
mainfrom
release/0.36.0

Conversation

@Dim145

@Dim145 Dim145 commented Sep 10, 2026

Copy link
Copy Markdown
Owner

28 commits since 0.35.0 — the torrent detail page and the catalogue rebuilt
around the questions their readers arrive with, and the review passes that
followed. As with 0.35.0, the findings that mattered came from probing the
running stack, not from static analysis
: semgrep and gitleaks were clean or
already arbitrated, while calling the changed routes without a session, then
with another member's session, is what turned up the leaks below.

The torrent detail page

The page used to answer "what is this release?" some 700px below the fold,
repeat every audio and subtitle track twice, and offer no way to say "wrong
film". It now opens on a hero band that names the work, with two columns where
the decision — download, cost, seed obligation — is pinned, swarm health read
from the collector, and a report affordance on the metadata itself. The work's
own colour, extracted from its poster, tints the band; the remaining motion is
limited to what carries meaning (the click, the fold, the numbers).

  • Hit & Run thresholds had no interface. The tracker and the API both read
    them; the 24 h shown on every torrent page was a code default. They are now
    in the admin panel, bounded, and read from one place.
  • A timed-out metadata lookup was cached as "no such record" for an hour.
    One network hiccup cost thirty posters until the entry expired. Timeouts,
    5xx, 429 and malformed JSON now share a 120 s error cache; only a real 404
    is remembered as an absence.
  • The poster relay accepted any client. No Sec-Fetch headers, any port,
    any image type — an SVG served from our own origin would have executed
    there. Now: same-origin image requests only, three CDN hosts, raster types,
    a 400 KB cap enforced during the stream, no redirects, 60/min per address.
  • A held-down D key downloaded on repeat; the shortcut now ignores key
    repeat, composition, open modals and editable targets.

The catalogue

A bar that understands what you type — s02e04, @member, a TMDb or IMDb
link, a resolution, a year — turning each into a removable chip; a rail of
facets that carry their counts; works before releases; and an empty state that
proposes what to drop rather than apologising.

A work card opens on its own header, with a chevron: the scope badge used to be
the only way in. Inside, seasons and episodes fold down to the releases, each
carrying its age with the exact date on hover.

  • Relevance ranking. A text search could only be sorted by age. Work titles
    are now indexed and searched, so a file named Sousou.no.Frieren.S01E10
    answers to "frieren", and a near miss gets a did-you-mean.
  • Saved searches match what the page filters — season, episode, year,
    uploader and tag families included — and their links replay exactly what was
    stored.
  • A hover menu on Torrents: shortcuts (everything, today, freeleech,
    favourites), this browser's recent searches, and the category tree. Opens on
    hover with an intention, on the chevron by click or keyboard, never on hover
    alone for a touch screen.
  • Per-instance catalogue defaults (view, sort, page size, visible facets), a
    record of searches that found nothing, and category merge — all in the admin
    panel.

Security and correctness

  • The abuse counter is per address, and the web container has one for the
    whole site.
    Four API calls per page view meant 25 page views in 10 seconds
    blacklisted the instance for everyone, for five minutes doubling to twenty-four
    hours. Server-side rendering is now recognised by a discriminant an Internet
    client cannot forge (private socket peer and no forwarding header), and
    only the coarse counter is relaxed — never the agent filter, the path
    validation, the address bans, the per-route limits or authentication.
  • anonymous_uploads was honoured by the detail page and the feeds but by
    none of the new catalogue paths.
    The listing returned the name,
    ?uploader=<name> listed an anonymous member's whole history, and a saved
    search on that name notified every one of their uploads.
  • "frieren" found one release out of nine. A dotted release name was a
    single token for the text-search parser, and the fuzzy fallback hid the hole
    whenever the exact search returned zero.
  • backdrop-filter written before its -webkit twin was dropped by the
    minifier.
    Five glass surfaces across the site had no blur in Chrome — a
    correct source and a stripped stylesheet.
  • Unbounded work, now bounded: tagGroups fanned out to one query per group on
    a pool of ten connections, search_misses grew a row per distinct empty
    search, and neither the listing nor the facets carried a rate limit.
  • Visibility: the did-you-mean read work titles with no veil, and two per-hash
    routes answered for a torrent the member cannot see.
  • Category merge failed with a 500 on its nominal case (both categories
    carrying an upload pattern), and could make an adult category's torrents
    visible to members who opted out.
  • Determinism: every sort now ends on a unique key, so a "load more" cannot
    repeat or drop a row; the year facet counts every year in a name with the
    same pattern the filter uses; and the metadata warmer no longer marks a work
    done for a week because the upstream was briefly unavailable.

Verified

nuxt typecheck and the API tsc clean; 558 API and 948 web unit tests; schema
parity between schema.ts and the 77 migrations; the end-to-end suite (13
scenarios, 543 checks) against images built from this branch; and a browser
pass at 1280 and 390, dark and light, with no horizontal scroll, no truncated
text, no dangling aria-controls and no failed asset.

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@Dim145
Dim145 merged commit 9519636 into main Sep 10, 2026
11 checks passed
@github-actions
github-actions Bot deleted the release/0.36.0 branch September 10, 2026 20:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant