changelog

what shipped on runbot, newest first.

landing polish: sharp favicon, consolidated CTAs, cleaner bubbles

tab favicon now ships a pre-rendered 32x32 RB symbol (and 180x180 apple-touch-icon) so the icon stays crisp instead of muddy-downscale. 'save runbot to contacts' moved next to 'Message runbot' in one cohesive lockup. all three example bubbles share identical corner radii (the tail teardrop was dropped alongside the sender avatar earlier today). aria-labels that diverged from visible button text were removed so screen-reader names match what sighted users see. lighthouse stays 100/100/100/100 mobile.

landing hardening: XSS escapes, CSP nonces, CSRF Origin check

all three new public pages (stats, changelog, waitlist) now HTML-escape their interpolated content and carry per-request CSP nonces on inline styles. POST /v1/waitlist rejects cross-origin submits via Origin header check.

public stats page + admin vitals percentiles

added /stats showing aggregate runs, miles, and site-performance percentiles from real visitors. /admin/stats now includes LCP/CLS/INP p50/p75/p95 windows.

FAQ deep-links + Web Vitals beacon

FAQ entries now auto-open when linked from URL hash (/#android-q opens the android question with a gold highlight). landing pages emit Core Web Vitals via navigator.sendBeacon to /v1/landing-vitals so we can measure speed without third-party SDKs.

trust counter + full YTD leaderboard

landing now shows '194 mi tracked this week, N runners, M runs' beneath the preview, and the example bubble shows the full YTD leaderboard instead of top-5.

image payload optimized + CSS extracted

OG image cut to 29KB (8-bit downsample) with WebP variant at 10KB. CSS extracted from inline HTML into /v1/landing.css with content-hash cache-busting and immutable Cache-Control. landing HTML payload down ~95% post-Brotli.

CSP report-only + per-request nonces

Helmet middleware now enforces a strict Content-Security-Policy in report-only mode with per-request nonces on every <script> and <style>. violations flow to /v1/csp-report; will flip to enforce after a clean week of reports.

Fly cutover + MBA decommissioned

api + bot fully migrated to Fly (sjc region). DNS at GoDaddy. MBA daemons unloaded; canonical stack is now Fly + Mini relay + Tailscale Funnel. pg-boss cron (strava-resolver, follower-monitor) ported from launchd to Fly workers.

post-registration group backfill

users who paste their Strava link after being discovered in a chat now get backfilled into the right group via participant_fingerprint matching.

P0 batch: importCode IDOR fix, watchdog restore, observability

shipped six commits: closed an importCode IDOR, restored the bot-side watchdog, scaffolded observability for chatbot tool calls, bumped deps, hygiene cleanup.

429 sweep treadmill fix (Strava)

migration 0035 added an enrichment_backoff_state table; Strava-resolver now respects per-source backoffs so we stop sweeping the same 429-rate-limited rows in a tight loop.

send-failure hardening

parser hardened against malformed group payloads, daily log rotate, group-pause for runaway sends, dup sweep across activity inserts.

public launch readiness sprint

5-agent audit produced 47 findings; 11 P0/P1 fixes shipped in same week before broader release.

chatbot LIVE

general-purpose chatbot mode shipped F1 through F5 in a single day. 40-fixture test gate plus a watchdog that DMs the operator on any unexpected exit.

← back to runbot