fix(dashboard): harden identity-name color helpers against undefined (bf-gcotl)

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.
This commit is contained in:
jedarden 2026-07-08 18:13:22 -04:00
parent 14e0d0712d
commit ce115e2f66
2 changed files with 10 additions and 0 deletions

View file

@ -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++) {

View file

@ -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) {