[READ-ONLY] Mirror of https://github.com/openstatusHQ/openstatus. 🫖 Status page with uptime monitoring & API monitoring as code 🫖 openstatus.dev
bun drizzle-orm monitoring monitoring-as-code nextjs observability on-call open-source shadcn-ui status-page statuspage synthetic-monitoring tinybird turso uptime uptime-checker uptime-monitor

Add custom theme support for status pages (#2354) master

* feat(status-page): add custom CSS gated by new custom-css plan limit - add "custom-css" boolean limit (team + scale only) and page.custom_css column - add sanitizeCustomCss / hasCustomCss / generatePageStyles to theme-store with tests - add updatePageCustomCss service verb (scope check, plan gate, audit) + tRPC endpoint - add FormCustomCss dashboard card with upgrade overlay when not eligible - render custom CSS after the theme on status pages so it wins the cascade, nulled out server-side when the workspace plan no longer includes the limit Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011R5Sq8Hcmzw1n6QVpVGyNM * chore: retrigger CI (flaky subscriptions dispatcher test) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011R5Sq8Hcmzw1n6QVpVGyNM * feat(status-page): full css-var placeholder + custom css validation - generateCustomCssTemplate lists every THEME_VAR_NAMES entry pre-filled with the page's selected theme values; used as the textarea placeholder - validateCustomCss (theme-store) checks length, '<' breakouts, brace balance (comment/string aware) and presence of declaration blocks - wired into the dashboard form schema and UpdatePageCustomCssInput Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011R5Sq8Hcmzw1n6QVpVGyNM * fix(theme-store): linear-time css scan + align service test with validation - replace the lazy comment/string regexes with a single-pass scanner (CodeQL js/polynomial-redos on repeated unclosed "/*") and early-return on over-length input so the scan is bounded - update the service test: '<' in custom css is now rejected at the boundary instead of silently sanitized; add reject cases for breakout and unbalanced braces Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011R5Sq8Hcmzw1n6QVpVGyNM * chore: retrigger CI (flaky subscriptions dispatcher test) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011R5Sq8Hcmzw1n6QVpVGyNM * fix(theme-store): comment out unset vars in the custom css template An empty `--x: ;` from the saved template would override the global default with an empty value (custom css wins the cascade). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011R5Sq8Hcmzw1n6QVpVGyNM * chore: retrigger CI (flaky monitor quota test) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011R5Sq8Hcmzw1n6QVpVGyNM * wip: custom theme * fix(theme-store): linear declaration parser + drop duplicate migration - parseThemeVarsText: manual colon-split instead of a lazy regex that backtracks quadratically on hostile input (CodeQL js/polynomial-redos) - remove 0079_parched_sugar_man.sql — double-generate artifact not referenced by the drizzle journal Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011R5Sq8Hcmzw1n6QVpVGyNM * fix(subscriptions): deflake dispatcher entire-page assertion Package test suites run in parallel against the same seeded page, so an exact recipient count races with subscribers inserted by other suites. Assert against this suite's own subscriber emails instead. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011R5Sq8Hcmzw1n6QVpVGyNM * chore: changelog --------- Co-authored-by: Claude <noreply@anthropic.com>


+5713 -244
29 changed files