Guard the read-through renderer against SSRF
The public renderer fetches hostnames derived from untrusted input — the @handle
in the URL, a did:web host, and the PDS serviceEndpoint from a DID document.
Unguarded, a request like /@169.254.169.254/x or a did:web pointing at an
internal host would make the server fetch loopback / cloud-metadata / private
addresses.
Add src/lib/net/safe-fetch.ts: assertSafeUrl allows only https:// to
syntactically valid public domains (rejecting IP literals, single-label /
localhost, and reserved/internal TLDs), and safeFetch refuses to follow
redirects. Route every untrusted-host fetch through it — handle resolution
(.well-known + XRPC), DID-document resolution (did:web + the returned
serviceEndpoint), and getRecord/listRecords. Reader fetches now fail closed
(null/empty) on a bad host.
Verified: legit handles still render (200) while /@127.0.0.1/... and
/@169.254.169.254/... are rejected (404, no internal request). Unit-tested.
Residual DNS-rebinding (public domain -> private IP) is documented for
network-layer mitigation at deploy time (SP7). Flagged by automated commit
security review.