First concurrent caller for a cache key does the relay; subsequent
callers subscribe to a broadcast channel and receive the same response.
Only applies to cacheable (GET/HEAD) requests without body.
- New cache.rs: FIFO-eviction cache with max_bytes cap
- Cacheable: GET/HEAD only, no-store/no-cache/private/Set-Cookie reject
- TTL from Cache-Control: max-age=, or heuristics by extension (css/js/fonts/images -> 1h)
- Hook in DomainFronter::relay: check cache before network, store after 2xx
- 10 new unit tests (23 total)