Address review findings on the cover-path deletion (#63)

- Move the kagane cover URL shape into the extraction module (sites.go):
  browserOnlyCoverURL + kaganeImageURLRe now own the claim; the byte-fetch
  router and BrowserFetcher.Image reference it. One shape gate for producer
  and fetcher (the id regex is folded into the full-URL match), so no Site
  name appears in a cover path outside the extraction module and the
  producer cannot emit an address the fetch would refuse.
- Restore the serving-boundary guarantee: GET /covers/{addr} re-checks the
  stored media type via store.CoverContentType and 404s a poisoned row;
  TestPublicCoverNeverEchoesNonImage now seeds one directly behind the
  write gate and pins the refusal where bytes leave.
- Restore the SSRF rationale (client-supplied stored URL, headless browser
  as a strong primitive) on the URL regex.
This commit is contained in:
2026-08-10 11:36:54 +07:00
parent cce3d61799
commit 0a79e5f3d7
6 changed files with 60 additions and 34 deletions
+5 -5
View File
@@ -168,11 +168,11 @@ Guidance for OpenCode (and Claude Code) working under `backend/`. See root `AGEN
served by the one public `GET /covers/{addr}` route from content-addressed
bytes. There is no proxy, no per-Site rewrite, no second place that decides
a Cover's renderable address: the wire `cover` is it. The only place a Site
name still appears in cover code is the acquisition module, where kagane's
image URLs are claimed by `latest.BrowserFetcher` (`browserCoverURL`) because
they answer a plain fetch with a challenge and
`cross-origin-resource-policy: same-origin`; every other Site's CDN answers
plain TLS. Templates render `.Cover` — the wire value — never anything else.
name still appears in cover code is the extraction module (`latest`), where
kagane's image URLs are claimed by `browserOnlyCoverURL` — they answer a
plain fetch with a challenge and `cross-origin-resource-policy: same-origin`;
every other Site's CDN answers plain TLS. Templates render `.Cover` — the
wire value — never anything else.
- **Web UI also owns:** session-gated `GET /install/{manga,novel}-bookmark.user.js`
(renders the bindmounted script with the acting Reader's derived credential
substituted in — the credential never appears in page markup, the address