# Decisiones técnicas

## 2026-09-10 — Alcance de la base

Se sigue el paso 1 acordado en la conversación: estructura, configuración
documentada y backend verificable. La sección «Primera tarea para Codex»
del documento original es una propuesta más amplia; sus entregables de
WebSocket, vistas mock y esquema completo no forman parte de este paso.

## Backend inicial

PHP 8.3, sin framework ni dependencias para este endpoint. Front controller
en `backend/public/index.php`; respuestas en `backend/src/http.php`.
No se selecciona todavía un framework definitivo para la aplicación.
API `/api/v1`, errores JSON, timestamps UTC y respuestas sin caché.
`health` es una comprobación de proceso, no de disponibilidad de dependencias.

## Configuración y publicación

La fase actual no consume secretos. Las plantillas preparan los nombres
de variables; el cargador se implementará al introducir persistencia.
En producción, suministrar secretos desde configuración fuera del directorio
público. Nunca usar la raíz del repositorio como DocumentRoot.
La raíz incluye una denegación Apache porque está bajo el htdocs compartido.
La efectividad de `.htaccess` depende de AllowOverride; el despliegue deberá
garantizar la restricción en la configuración del virtual host.

## Propuestas para la fase 1 (todavía no implementadas)

- Sesiones PHP en servidor, cookie HttpOnly/Secure/SameSite y protección CSRF.
- PDO MySQL, consultas preparadas y migraciones SQL numeradas con registro
  de versiones aplicadas; sin ORM inicialmente.
- Membresía y rol comprobados en backend en cada acceso al hogar.
- IDs internos enteros; claves únicas de membresía `(home_id, user_id)`.
- Integridad de relaciones por hogar también al enlazar habitaciones y dispositivos.
- HTML/CSS/JavaScript con prioridad móvil; PWA posterior.

## Decisiones pendientes antes del dispositivo simulado

- Versión soportada de Node y biblioteca WebSocket, verificadas al instalarlas.
- Canal interno autenticado PHP ↔ Node y responsabilidad de persistencia.
- Política de heartbeat, reconexión y conexiones duplicadas.
- Caducidad de comandos, deduplicación y diferencia entre ACK y resultado.
- Retención e índices de telemetría; secretos de dispositivos y rotación.
- Automatizaciones locales/cloud, OTA y notificaciones quedan para sus fases.

## 2026-09-11 — Implementación de usuarios y hogares

Se concretan PHP sin framework, PDO MySQL y migraciones SQL versionadas.
Sesiones PHP con CSRF para todas las mutaciones, incluido login/registro;
cookies HttpOnly/SameSite y Secure fuera de desarrollo. Se configura una
carpeta privada de sesiones porque la carpeta CLI por defecto de Bitnami
pertenece a daemon. La configuración se inyecta mediante variables de
entorno; no se interpreta automáticamente un archivo .env.

Se añade una instancia MariaDB independiente para desarrollo, sin TCP y
con datos fuera de htdocs. No se obtienen credenciales de otros proyectos.
Compartir un hogar agrega cuentas existentes; invitaciones por correo y
aceptación quedan pendientes. Residentes/guest solo consultan en esta fase.
La pertenencia y los permisos se consultan en cada solicitud, de modo que
quitar un miembro revoca también el acceso desde sesiones abiertas.

La limitación de autenticación persiste por hash de IP en MariaDB (30
solicitudes/15 minutos, registro y login combinados). Pendiente para
publicación: recuperación/verificación de correo, política de limpieza
periódica de auth_attempts y ajuste de límites según uso real.

## Usuarios únicos y perfiles infantiles

Se añade `username` global único (3–32 caracteres ASCII, empieza con letra),
normalizado a minúsculas; email pasa a ser opcional. Las cuentas anteriores
conservan correo/contraseña y pueden elegir su usuario en Mi usuario.
Login y vinculación aceptan usuario o correo. Se mantiene compatibilidad
con clientes anteriores que envían `email` al login o al agregar miembros.

El propietario crea perfiles infantiles sin correo para un solo hogar.
Son cuentas de tipo `child` permanente en esta fase, con rol infantil;
no se pueden promover ni vincular desde los endpoints de miembros normales.
El acceso inicial a habitaciones se deniega salvo selección explícita.
Las habitaciones seleccionadas deben pertenecer al hogar administrado.
El propietario puede cambiar nombre/usuario, contraseña, habitaciones y
pausar/reactivar. Cada edición incrementa auth_version para invalidar las
sesiones anteriores. Solo consulta: sin configuración, miembros ni creación
de hogares. Los controles de dispositivos todavía no existen.

La migración 002 usa sintaxis de MariaDB (`ADD COLUMN IF NOT EXISTS`),
probada en la instancia instalada. Antes de usar MySQL, adaptar y verificar
esta sintaxis. Se mantiene copia de seguridad privada antes de migrar los
datos de desarrollo existentes. No se crean cuentas infantiles de muestra.

## Monitoreo ESP32 — transporte y datos

Se implementa un único servicio Node 24 LTS (`ws` y `mysql2`, versiones
exactas en package-lock.json), instalado para HomeCore fuera de htdocs.
Escucha en 127.0.0.1:8080; Apache terminará TLS para /ws. El dispositivo
inicia la conexión, se autentica con UID y secreto aleatorio de 256 bits;
solo se almacena SHA-256 del secreto. Se muestra al propietario una sola
vez al registrar o regenerar. Pausa/rotación revocan la conexión persistida.

PHP administra hogares, dispositivos y permisos. Node solo autentica las
conexiones de dispositivos y persiste presencia/telemetría mediante PDO's
esquema compartido, usando mysql2 y transacciones; no se crea un endpoint
HTTP interno ni se comparten sesiones de residentes. Antes de introducir
comandos se decidirá el canal PHP→Node. Un bloqueo de MariaDB asegura un
solo proceso de transporte por base. Cada socket posee una conexión con
identificador único que evita escrituras de sesiones sustituidas.

Telemetría v1 limitada a temperatura y humedad, con mensajes de máximo
4 KiB, ACK tras persistencia y deduplicación por dispositivo/message_id.
La hora de recepción UTC del servidor es autoritativa; no se aceptan cargas
históricas arbitrarias en esta etapa. Se conserva historial por 30 días con
script explícito de mantenimiento. La app consulta cada 5 segundos y
muestra separado estado de conexión y antigüedad de la lectura. Los datos
simulados siempre se identifican. Niños: filtro obligatorio de habitación
en listado, última lectura e historial; ningún permiso de configuración.

## Piloto en transbook.mx/homecore

El usuario eligió un subdirectorio del dominio existente, no un subdominio.
HOMECORE_BASE_PATH adapta rutas de API, recursos y cookie; no depende del
Host ni de un encabezado de usuario. Publicación por Apache/FastCGI con
PHP-FPM exclusivo y proxy WebSocket; el servidor integrado PHP sigue siendo
solo de desarrollo. Se habilitaron servicios systemd para mantener el piloto.
No se inicializa Git hasta que el usuario lo solicite.

La placa confirmada es DOIT ESP32 DevKit V1 (ESP-WROOM-32). Firmware Arduino
core 3.3.11, WebSockets 2.7.2, ArduinoJson 7.4.3, con CA ISRG Root X1 incluida
como certificado público. Cadena TLS actual de Transbook verificada contra
esa CA. Se comienza sin sensor físico; DHT22 queda como opción configurable.

Referencias consultadas:
- https://nodejs.org/dist/index.json (rama 24 LTS)
- https://github.com/websockets/ws (límites, eventos y autenticación)
- https://sidorares.github.io/node-mysql2/docs (pool y transacciones)
- https://httpd.apache.org/docs/2.4/mod/mod_proxy.html (Upgrade y FastCGI)
- https://www.php.net/manual/en/install.fpm.configuration.php
- https://docs.espressif.com/projects/arduino-esp32/en/latest/installing.html
- https://github.com/Links2004/arduinoWebSockets
- https://letsencrypt.org/certificates/ (cadena de confianza)

## Corrección de compatibilidad de la placa física

Los accesos reales de arduino-WebSocket-Client recibían 403 porque la
biblioteca WebSockets 2.7.2 incluye Origin: file:// por defecto. Se admite
ese valor exacto, además de la ausencia de Origin; otros orígenes se
rechazan. La autenticación UID/token permanece obligatoria y probada,
incluso cuando se presenta file://. No requiere modificar el firmware.

## ARD-360 confirmado: DHT11

Steren identifica ARD-360 como DHT11; usuario confirma cuatro patitas sin
placa adicional. Se introduce HOMECORE_SENSOR_TYPE: 0 simulado, 11 DHT11,
22 DHT22. Configuraciones anteriores siguen funcionando y el selector nuevo
tiene prioridad. GPIO27 para datos, 3V3 y resistencia externa de 10 kΩ.
No hay cambios de API o credenciales. Source sensor identifica nuevas
lecturas reales; el historial simulado permanece marcado. Fallos de lectura
o valores fuera del rango ARD-360 se omiten, nunca se reemplazan por datos
simulados. Se distribuye un ZIP específico con ejemplo de configuración11.
Fuente: https://www.steren.com.mx/sensor-de-temperatura-y-humedad.html

## Alertas de sensores — septiembre 2026

Por solicitud del usuario se implementan reglas y registro web antes de decidir
si habrá aplicación nativa. No se añade PWA, push ni proveedor externo.
Motor PHP independiente mediante timer systemd, con progreso transaccional en
MariaDB y eventos persistentes, separado del transporte WebSocket. Se reutilizan
credenciales DML de PHP. Permite evaluar falta de lecturas aun sin tráfico ni
navegadores abiertos y evita acoplar reglas a sesiones del dispositivo.

Se implementan tres reglas opcionales por dispositivo: temperatura, humedad,
falta de lecturas reales. Propietario configura, miembros consultan conforme a
sus permisos actuales; niños filtrados por habitación en backend. Una alerta
por episodio, resolución automática, sin recordatorios repetidos. Configurar
reinicia evaluación; no se imponen umbrales a los sensores existentes. Detalles,
limitaciones y operación en `docs/alerts.md`.
