feat: one registry entry per Site, one shared Series-page read #95
Reference in New Issue
Block a user
Delete Branch "feat/94-site-registry"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #94.
What
Two phases per the spec, in three feature commits plus two review-fix commits:
Phase one — one registry entry per Site (
2d134fb)The six per-site comparison points that used to live across three files collapse
into one
sitesmap inbackend/internal/latest/sites.go: Latest Chapter parse,Cover parse, browser-backed list, fetcher route, host pins, and the browser
payload read all become lookups into it.
browserBackedSites()is derived fromthe registry (sorted, deterministic);
fetcherForandfetchableSeriesURLkeeptheir signatures and become lookups;
BrowserFetcher.Getdispatches through theentries'
Read/Donewhile the tab lifecycle stays inBrowserFetcher.run.Phase two — one shared Series-page read (
f215130)readSeriesPage(newread.go) performs the read the Poll and the Acquisitionhave in common: gate, route, fetch, parse Latest Chapter, parse Cover address.
It returns facts only — polling and persistence policies (stamp order, cooldowns,
cover policy) stay with the callers;
acquire.gogained the comment naming thedeliberate post-fetch stamp order. The poll's legacy cover heal and the
no-chapter byte-count diagnostic were restored after review (
d998f87) so theclaims "the Poll keeps its own Cover policy" and "pinning is the only
behavioural change" both hold.
Behaviour
accepted any https host. For asura this is a strict improvement: its dead old
domain redirects deep links to the site root and would parse the wrong
document.
and the gate table pass unmodified except the one deliberate exception — the
gate table gains the three new pin cases.
Security invariants preserved
https+ exact hostname match, all callers route through it. No fetch pathwas widened; asura/demonic/comix were narrowed.
(browser = strong SSRF primitive,
series_urlis client-supplied) and is notdeduplicated against the shared gate.
fetcherFornow fails closed for unknown site strings(previously fell through to the TLS fetcher on an unreachable path), and the
browser dispatch iterates a sorted list so outcomes cannot depend on map order.
url.Parseand does not hold: control characters are rejected anywhere in aURL, so a client-supplied value in a log line cannot carry a newline.
Review
Reviewed on three axes (spec, standards, security) by read-only subagents over
672c16f..f1b26f4. No blocking findings; all minor/nit findings addressed ind998f87and700de20. Verified end to end withgo test ./...(DockerPostgres per test package) on every commit.
Out of scope (tracked separately)
live env) — separate issue, per spec.