From 23253e6ddfd7ba0b286dbf09205d1b82721e5a2e Mon Sep 17 00:00:00 2001 From: Lawrence Chen <54008264+lawrencecchen@users.noreply.github.com> Date: Tue, 24 Mar 2026 22:58:27 -0700 Subject: [PATCH] Validate workspace color during cmux.json decode (#2112) Reject invalid color values at parse time with a clear error message instead of silently ignoring them. Colors are normalized to #RRGGBB via WorkspaceTabColorSettings.normalizedHex during decode. Co-authored-by: Lawrence Chen --- Sources/CmuxConfig.swift | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/Sources/CmuxConfig.swift b/Sources/CmuxConfig.swift index d57f8479..4fe7f8ec 100644 --- a/Sources/CmuxConfig.swift +++ b/Sources/CmuxConfig.swift @@ -95,6 +95,33 @@ struct CmuxWorkspaceDefinition: Codable, Sendable { var cwd: String? var color: String? var layout: CmuxLayoutNode? + + init(name: String? = nil, cwd: String? = nil, color: String? = nil, layout: CmuxLayoutNode? = nil) { + self.name = name + self.cwd = cwd + self.color = color + self.layout = layout + } + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + name = try container.decodeIfPresent(String.self, forKey: .name) + cwd = try container.decodeIfPresent(String.self, forKey: .cwd) + layout = try container.decodeIfPresent(CmuxLayoutNode.self, forKey: .layout) + + if let rawColor = try container.decodeIfPresent(String.self, forKey: .color) { + guard let normalized = WorkspaceTabColorSettings.normalizedHex(rawColor) else { + throw DecodingError.dataCorruptedError( + forKey: .color, + in: container, + debugDescription: "Invalid color \"\(rawColor)\". Expected 6-digit hex format: #RRGGBB" + ) + } + color = normalized + } else { + color = nil + } + } } indirect enum CmuxLayoutNode: Codable, Sendable {