Codex adversarial pass on the implementation diff flagged five robustness
gaps, all fixed here:
- emoji-gate skipped green in CI when poppler/font prerequisites were absent,
which could let the tofu regression ship behind a green build. Missing
prerequisites are now a HARD FAILURE when process.env.CI is set; local dev
still skips cleanly.
- execFileSync children (make-pdf, pdffonts, pdftoppm, fc-match) had no
timeout; a wedged binary or hostile GSTACK_*_BIN override could hang the
job past Bun's test timeout. Each child now has a 25s ceiling.
- PPM parser trusted header tokens blindly; malformed/variant output gave a
silently-wrong count. Now validates magic/dimensions/maxval and pixel-buffer
length, handles header comments, throws a hard diagnostic on mismatch.
- predictable /tmp paths were collision/symlink-prone; now mkdtempSync under
/tmp (kept under /tmp for browse's validateOutputPath allowlist).
- only apt-get update was timeout-wrapped; dnf/pacman/apk installs and apt
install can hang on locks/mirrors. All package installs now timeout-bound.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
macOS and Windows ship a color-emoji font; most Linux distros/containers
ship none, so make-pdf emits tofu there. ensure_emoji_font() best-effort
installs fonts-noto-color-emoji (apt, with dnf/pacman/apk fallbacks) and
refreshes the fontconfig cache. Hardened: Linux-only guard, GSTACK_SKIP_FONTS
escape hatch, fc-match color=True detection (the broad fc-list query
false-matched LastResort), sudo -n so a password prompt fails fast instead
of hanging, DEBIAN_FRONTEND=noninteractive, timeout 30 on apt update, and
fc-cache under sudo. Warns instead of failing. After a fresh install,
refresh_browse_daemon_for_fonts() runs 'browse stop' so the next render
spawns a Chromium that sees the new font (font fallback is process-cached).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>