From 52eb37ceaf126bde963555f87ae2bb20c6921da1 Mon Sep 17 00:00:00 2001 From: Padreug Date: Fri, 12 Jun 2026 18:09:02 +0200 Subject: [PATCH] refactor(machine): drop electron theme allowlist, defer to renderer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The VALID_THEMES set in electron/main.ts duplicated the renderer's ThemeId list and silently coerced any unlisted branding.json theme to null — which is how darkmatter regressed to the localStorage theme after db074e2 added themes to the renderer but not this allowlist (fixed in a0c2f38). Remove the second list entirely: pass raw.theme through and let useTheme's applyBrandingTheme (themes[] + the 'custom' branch) be the single validation point. Unknown values are ignored downstream, so nothing reaches the DOM unvetted. Co-Authored-By: Claude Opus 4.8 (1M context) --- apps/machine/electron/main.ts | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/apps/machine/electron/main.ts b/apps/machine/electron/main.ts index 2ed9b12..fb5c84b 100644 --- a/apps/machine/electron/main.ts +++ b/apps/machine/electron/main.ts @@ -81,22 +81,6 @@ type BrandingConfig = { logoDarkDataUrl: string | null } -const VALID_THEMES = new Set([ - 'gruvbox', - 'catppuccin', - 'cyberpunk', - 'dracula', - 'nord', - 'tokyo-night', - 'countrysidecastle', - 'darkmatter', - 'emeraldforest', - 'lightgreen', - 'neobrut', - 'starrynight', - 'custom', -]) - function loadBranding(): BrandingConfig | null { const brandingDir = path.join( fs.existsSync('/var/lib/bitspire') ? '/var/lib/bitspire' : process.cwd(), @@ -116,7 +100,10 @@ function loadBranding(): BrandingConfig | null { try { const raw = JSON.parse(fs.readFileSync(jsonPath, 'utf-8')) if (typeof raw.title === 'string') title = raw.title - if (typeof raw.theme === 'string' && VALID_THEMES.has(raw.theme)) theme = raw.theme + // No theme-name validation here: the renderer's `themes` list (plus its + // 'custom' branch) is the single source of truth. Pass the string through + // and let useTheme's applyBrandingTheme ignore anything it doesn't know. + if (typeof raw.theme === 'string') theme = raw.theme if (raw.custom_colors && typeof raw.custom_colors === 'object') { const { dark, ...flat } = raw.custom_colors as Record const colors = Object.fromEntries(