Clave maestra LUX
LUX_MASTER_KEY_HEX es la clave de la que se derivan las claves por dispositivo y la
K de broadcast del protocolo LUX. Hay que aprovisionarla a mano en cada instancia:
es compartida con el firmware, así que no puede autogenerarse — una clave inventada por
el servidor no coincidiría con la que llevan los dispositivos.
Cómo se pone
En .env.secrets de la raíz del repo:
GLOBAL_LUX_MASTER_KEY_HEX=<32 caracteres hex>
La plantilla de things_extensions la lee de ahí
(LUX_MASTER_KEY_HEX=${GLOBAL_LUX_MASTER_KEY_HEX}). Después:
./infra env generate processing/things_extensions
./infra release <host> processing/things_extensions --remote-build
Formato: exactamente 32 caracteres hexadecimales (16 bytes). lux_mac.master_key()
rechaza cualquier otra longitud.
Por qué falla en silencio
Con la clave vacía, master_key() devuelve None y device_key_for() también: la
derivación de claves simplemente no ocurre, sin error ni aviso en los logs. No hay
ningún síntoma que apunte a la causa, así que conviene comprobarla explícitamente:
docker exec things-extensions python -c \
"from app.bridge.processing.protocols.lux_mac import master_key; \
k=master_key(); print('OK', len(k), 'bytes') if k else print('VACIA')"
Y quedó vacía de entrada por un detalle del generador de entornos: generate-env.sh
solo trata como secreto lo que termina en PASSWORD, SECRET, TOKEN, API_KEY,
ENCRYPTION_KEY y similares. LUX_MASTER_KEY_HEX termina en _HEX, así que no se
resolvía, ni se autogeneraba, ni se preguntaba: se copiaba el vacío de la plantilla.
Su vecina BRIDGE_WEBHOOK_TOKEN sí se rellenó sola precisamente por terminar en
TOKEN.
Si aparece otra clave con nombre acabado en _HEX, _B64 o parecido, va a caer en la
misma trampa. O se le pone el alias ${GLOBAL_...} en su plantilla, como aquí, o se
extiende el patrón de is_sensitive_key.
Relacionado: [[mosquitto-legacy-accounts]] — el otro caso de credencial que hay que aprovisionar a mano y que nadie reproduce sola.