harden: relay timeouts, DNS resolver reuse, cache hygiene + frontend polish

Server (relay/SSRF):
- Bound connect+TLS+request under CONNECT_TIMEOUT and body download under
  BODY_TIMEOUT so a stalling upstream can't pin a relay permit indefinitely
- Add inbound header_read_timeout to defeat slow-loris connections
- Allowlist relayed Content-Type (fall back to octet-stream) to block
  content-confusion from attacker-controlled stream origins
- Reuse one DNS resolver process-wide instead of rebuilding it per request
  (restores hickory's DNS cache; drops per-segment resolver setup)
- Probe cache: random per-process hash seed (DefaultHasher was deterministic)
  + bounded growth with expired-entry eviction
- Real Ctrl-C handler for a clean shutdown (honours the banner)
- Collapse the wrap_raw no-op alias into wrap

Frontend:
- Guide: visible focus ring tracking arrow-key navigation
- Player: buffering/tuning indicator while <video> is stalled
- prefers-contrast: more pass (lifts --ink-dim to meet WCAG AA)
- Service worker: date-stamped cache names so shell updates propagate

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-15 14:20:06 -04:00
parent a1e3e6852f
commit 0b761f684b
7 changed files with 218 additions and 72 deletions
+21 -1
View File
@@ -27,6 +27,7 @@ export class Player {
this._fallbackIdx = 0;
this._wireControls();
this._wireActivity();
this._wireBuffering();
}
/**
@@ -93,12 +94,31 @@ export class Player {
if (this.hls) { try { this.hls.destroy(); } catch {} this.hls = null; }
this.video.removeAttribute('src');
try { this.video.load(); } catch {}
this._setBuffering(false); // never leave the indicator stuck across a zap
}
destroy() { this._teardown(); }
// ---------- buffering / stall indicator ----------
// Bridge the gap between the scrying static clearing and the first frame:
// without a hint, a slow-loading stream is indistinguishable from a dead one.
_wireBuffering() {
const v = this.video;
const on = () => this._setBuffering(true);
const off = () => this._setBuffering(false);
v.addEventListener('waiting', on);
v.addEventListener('stalled', on);
v.addEventListener('playing', off);
v.addEventListener('canplay', off);
v.addEventListener('pause', off);
v.addEventListener('emptied', off);
}
_setBuffering(on) {
if (this.els.screen) this.els.screen.classList.toggle('buffering', on);
}
// ---------- dead-stream "the orb clouds over" ----------
_showNoSignal() { this.els.nosignal.hidden = false; }
_showNoSignal() { this.els.nosignal.hidden = false; this._setBuffering(false); }
_hideNoSignal() { this.els.nosignal.hidden = true; }
// ---------- live-aware chrome ----------