From ce115e2f664bc3670117801f0b69790c6aaa8458 Mon Sep 17 00:00:00 2001 From: jedarden Date: Wed, 8 Jul 2026 18:13:22 -0400 Subject: [PATCH] fix(dashboard): harden identity-name color helpers against undefined (bf-gcotl) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Audit bf-gcotl found every dashboard read of the blob identity fields (personName/assignedColor/identityResolved + snake_case aliases person_name/assigned_color/person_label/person_color) is already guarded at the call site — zero unguarded reads (full verdict table recorded on bf-2gmx). The only two spots that dereference an identity NAME (.length/.charCodeAt) without a local guard were the reusable color helpers, both safe today but hardened defensively so the guard contract holds for future callers: - ambient_renderer.js getPersonColor: if (!personName) return '#6b7280' - ble-panel.js getColorForPerson: if (!personName) return '#888888' Type contract unchanged and verified: tsc --noEmit -p dashboard/tsconfig.json passes; spaxel.d.ts still declares personName?/assignedColor?/identityResolved? optional with deprecated aliases; blob-identity.check.ts asserts the identityResolved true/false/undefined tri-state. --- dashboard/js/ambient_renderer.js | 5 +++++ dashboard/js/ble-panel.js | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/dashboard/js/ambient_renderer.js b/dashboard/js/ambient_renderer.js index a25aec2..5a84b89 100644 --- a/dashboard/js/ambient_renderer.js +++ b/dashboard/js/ambient_renderer.js @@ -766,6 +766,11 @@ } function getPersonColor(personName) { + // Identity name fields (personName/person_label) are optional on the wire; + // never dereference an undefined name. Today's sole caller guards with + // `if (personName)`, but harden the helper so the contract holds for any + // future caller (audit bf-gcotl / parent bf-2gmx). + if (!personName) return '#6b7280'; // Grey for unknown (matches line ~629) // Generate consistent color from name let hash = 0; for (let i = 0; i < personName.length; i++) { diff --git a/dashboard/js/ble-panel.js b/dashboard/js/ble-panel.js index 548002e..ff01ea1 100644 --- a/dashboard/js/ble-panel.js +++ b/dashboard/js/ble-panel.js @@ -825,6 +825,11 @@ } function getColorForPerson(personName) { + // Identity name fields (person_name/personName) are optional on the wire; + // never dereference an undefined name. Currently has no callers, but + // harden the helper so it is safe for any future caller + // (audit bf-gcotl / parent bf-2gmx). + if (!personName) return '#888888'; // device default color (matches line ~181) // Check if we have a person with this name in our people list var person = state.people.find(function(p) { return p.name === personName; }); if (person && person.color) {