perf: stop blocking dashboard render on prefetches, bound /overview history master
`/overview` could exceed 2s TTFB. Three independent causes stacked, all of which get worse as a workspace ages — hence "some users". Nothing streamed. Every layout `await`ed its prefetches before returning JSX, and there was no loading.tsx or Suspense boundary anywhere in the app, so TTFB was the full depth of the query chain: proxy session lookup -> root layout session lookup -> resolveActiveWorkspace -> shell's 5 prefetches -> (barrier) -> overview's 5 prefetches. Roughly 16-19 libsql statements, ~7 of them strictly serial, since the http driver sends one request per statement. - Layouts now use the existing non-awaiting `prefetch` / `batchPrefetch` helpers. `shouldDehydrateQuery` was already configured to ship pending queries, so the promises stream to the client instead of gating the shell. - The two detail routes started their sibling prefetches before awaiting the `notFound()` gate, so the gate costs one round trip rather than two serial. - Added loading.tsx plus an overview skeleton; the client guards returned `null`, which would have streamed a blank screen. The root layout awaited `auth()` purely to seed a SessionProvider nothing reads — `useSession` appears nowhere, only `signOut`, which doesn't need the context. That was a database session lookup at the head of every render, and `cache()` could not dedupe it with the proxy's own lookup. Unbounded history fed scalars. Every list procedure passes a 10k sentinel with no period, so `/overview` loaded the workspace's entire incident, report and maintenance history to render five counts and two short tables: - New `activeOrClosedSince` filter on the incident / status-report / maintenance list verbs: keep everything still open regardless of age, plus what closed since the given date. An incident open for weeks still surfaces. Preferred over a dedicated overview verb because every count the page shows is derivable from that set, so it needs no extra queries and no duplicated enrichment. - `monitor.list` fetched every incident ever for every monitor, on every dashboard route via the sidebar, to render one date per row. It now selects open incidents plus each monitor's latest via a window function, and orders them so `incidents[0]` is the newest — that row was previously arbitrary. Not addressed here: Auth.js still uses database sessions (switching to JWT would drop the remaining lookups but gives up server-side revocation), Tinybird's `revalidate: 0`, and the status-page history query. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WLRLD6gwfDJsCrFcWAxDPp