backend/cuentas.py: restablece en bloque (todos menos leo y claude) y da de alta a varios desde backend/cuentas/2026-10-23_alta-sitios.json (jesush, miguel, joel, antonio, danielg); la contraseña la pide en la terminal. Miembros con sitio, correo y correo_alt; marca contrasena_inicial con aviso en el sitio hasta que la persona la cambie. Los ids de responsable se recalculan con el equipo de hoy. Lote 2026-10-23_usuarios-campo. Pruebas: tests-cuentas.sh (47). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016X4CAujMuib2tDqt9JRg6X
32 KiB
Despliegue — sitio, backend de actas y usuarios
Servidor: git.helgen.online · dominio público: https://drogheda.helgen.online
Qué vive dónde
| Parte | Ruta en el servidor | Cómo se actualiza |
|---|---|---|
| Sitio (docs, formularios, tableros) | /srv/projects/drogheda/hbox-docs/site |
./scripts/deploy.sh desde la Mac |
Backend de actas (app.py, tablero.py) |
/srv/projects/drogheda/hbox-docs/backend |
./scripts/deploy.sh lo copia (rsync, sin git en el servidor) + systemctl restart actas-hbox si cambió app.py |
| Actas recibidas (JSON + índice CSV) | /srv/projects/drogheda/actas |
las escribe el backend |
| Fotos de campo | /srv/projects/drogheda/adjuntos |
las escribe el backend |
| Pendientes del tablero (kanban) | /srv/projects/drogheda/tareas |
las escribe el backend — 13-oct |
| Inventario (ítems y movimientos) | /srv/projects/drogheda/inventario |
las escribe el backend — 13-oct |
| Sitios | /srv/projects/drogheda/sitios |
las escribe el backend — 13-oct |
| Plan de producción | /srv/projects/drogheda/plan-produccion.json |
lo escribe el backend (admin) — 13-oct |
| Equipo (miembros, bitácora de accesos) | /srv/projects/drogheda/equipo |
las escribe el backend — 14-oct |
| Enfoque de la semana (página de inicio) | /srv/projects/drogheda/enfoque.json |
lo escriben Leo y Adriana desde el inicio — 21-oct |
| Lotes del tablero ya aplicados | /srv/projects/drogheda/lotes-aplicados.json |
lo escribe backend/tablero.py al aplicar un lote de Claude — 21-oct |
| Foto del tablero (para Claude) | _estado/ en la Mac, fuera de git |
./scripts/tablero.sh foto y cada ./scripts/deploy.sh — 21-oct |
| Usuarios (HTTP Basic) | /etc/nginx/hbox-docs.htpasswd |
htpasswd |
Lo importante: deploy.sh publica el sitio y copia el backend (rsync; en el servidor el
backend no es un repositorio de git), pero no reinicia el servicio. Si cambió backend/app.py, hay
que hacer además el restart, o el sitio nuevo hablará con un backend viejo (las fotos darían 404 y el diagnóstico se bloquearía como si fuera un acta
de banco).
A · Despliegue de esta versión (diagnóstico en campo)
Los pasos 3, 4 y 5 son de una sola vez; los pasos 1 y 2 son el ciclo normal de siempre.
1 · Desde la Mac — publicar el sitio
cd ~/Documents/Claude/Projects/Drogheda/hbox-docs
git add -A && git commit -m "diagnóstico en campo: acta, fotos, tablero y procedimiento"
git push
./scripts/deploy.sh # mkdocs build --strict + rsync a /srv/.../site
2 · En el servidor — actualizar el backend
cd /srv/projects/drogheda/hbox-docs && git pull
sudo systemctl restart actas-hbox
curl -s http://127.0.0.1:8081/api/salud # {"ok":true,"servicio":"actas-hbox"}
3 · Carpeta de fotos (una sola vez)
sudo mkdir -p /srv/projects/drogheda/adjuntos
sudo chown -R leo:leo /srv/projects/drogheda/adjuntos
El backend la deduce sola de ACTAS_DIR; si prefieres fijarla, agrega a
/etc/systemd/system/actas-hbox.service (y luego daemon-reload + restart):
Environment=ADJUNTOS_DIR=/srv/projects/drogheda/adjuntos
Environment=ADJUNTO_MAX_MB=8
Environment=ARCHIVO_MAX_MB=20
Environment=ACTAS_REPETIBLES=diagnostico-campo,diagnostico-banco,instalacion-campo,reflasheo,dano,envio,recepcion,prueba-bateria-modem,prueba-ethernet-serie
4 · nginx — subida de fotos e identidad del técnico (una sola vez)
En el bloque server { listen 443 … } de drogheda.helgen.online, el location /api/ queda así:
location /api/ {
proxy_pass http://127.0.0.1:8081;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Remote-User $remote_user; # ← quién es el técnico
client_max_body_size 25m; # ← sin esto, las fotos dan 413
proxy_read_timeout 120s; # ← subidas con señal mala
}
Las dos líneas marcadas son nuevas y obligatorias:
- Sin
client_max_body_size, nginx corta la subida en 1 MB y el técnico ve "la foto pesa demasiado" aunque no lo pese. (El formulario ya reduce cada foto a ~1600 px / 300-400 kB antes de subirla; el margen es para ráfagas de varias fotos.) - Sin
X-Remote-User, el backend no sabe quién envió cada acta: el nombre no se precarga y —más serio— cualquier usuario autenticado podría mandar la cabecera a mano y hacerse pasar porleopara borrar actas. Al fijarla en nginx, el valor del cliente se sobrescribe siempre. Revisa si ya la tienes: es fácil que no, porque no venía en el README original.
sudo nginx -t && sudo systemctl reload nginx
5 · Usuarios de los técnicos (una sola vez)
sudo htpasswd /etc/nginx/hbox-docs.htpasswd alan
sudo htpasswd /etc/nginx/hbox-docs.htpasswd daniel
# (sin -c: -c CREA el archivo de cero y borraría a leo y a luz)
sudo cut -d: -f1 /etc/nginx/hbox-docs.htpasswd # lista de usuarios
Administradores (quién puede borrar o reabrir actas) = variable ACTAS_ADMINS del servicio,
hoy leo. Alan y Daniel quedan como técnicos: llenan y envían, no borran.
7 · Permisos para que los técnicos cambien su contraseña (una sola vez)
La página Mi cuenta (/cuenta.html) deja que cada quien cambie su propia contraseña, y que el
administrador restablezca la de otro. Para eso el servicio tiene que poder escribir el archivo de
usuarios que nginx solo lee:
# quién es el usuario de nginx (normalmente www-data)
grep -E "^\s*user" /etc/nginx/nginx.conf
sudo chown leo:www-data /etc/nginx/hbox-docs.htpasswd
sudo chmod 640 /etc/nginx/hbox-docs.htpasswd
sudo systemctl restart actas-hbox
Así: leo (el servicio) escribe, www-data (nginx) lee, y nadie más puede ni leerlo.
Comprueba que las contraseñas estén en el formato que el servicio sabe verificar:
sudo cut -d: -f2 /etc/nginx/hbox-docs.htpasswd | cut -c1-6
Todas deben decir $apr1$. Si alguna sale distinta ($2y$ es bcrypt), esa persona no va a poder
cambiar la suya sola: restablécesela desde la propia página, que la vuelve a guardar en $apr1$.
!!! note "Por qué no se usa el comando htpasswd desde el servicio"
Pasar una contraseña como argumento (htpasswd -b … clave) la deja visible en ps para
cualquiera con sesión en el servidor. El hash $apr1$ se calcula dentro del proceso; está
verificado carácter por carácter contra la salida de htpasswd, incluyendo acentos y espacios.
!!! tip "Al cambiar la contraseña, la sesión no se cae" HTTP Basic se guarda en el navegador: quien cambie la suya sigue navegando con la anterior hasta que cierre sesión o cierre el navegador. La página lo explica y ofrece la liga de Salir para probarla de inmediato. No es un error.
A2 · Despliegue 13-oct — tableros, inventario, sitios e instalación en campo
Esta versión agrega al backend cuatro colecciones nuevas (pendientes del tablero, plan de
producción, inventario con movimientos, sitios) y páginas que las usan (tableros/, inventario/,
sitios/, formularios/instalacion.html). Igual que siempre: el sitio se publica desde la Mac;
el backend se actualiza en el servidor. Si solo publicas el sitio, los tableros dirán «No se pudo
cargar» porque hablan con endpoints que el backend viejo no tiene.
1 · Desde la Mac — publicar el sitio
cd ~/Documents/Claude/Projects/Drogheda/hbox-docs
git add -A && git commit -m "tableros kanban, inventario, sitios, acta de instalación (13-oct)"
git push
./scripts/deploy.sh
2 · En el servidor — backend y carpetas (las carpetas, una sola vez)
ssh leo@git.helgen.online
cd /srv/projects/drogheda/hbox-docs && git pull
# carpetas de las colecciones nuevas (junto a /actas; el backend las deduce de ACTAS_DIR)
sudo mkdir -p /srv/projects/drogheda/{tareas,inventario/items,inventario/movimientos,sitios}
sudo chown -R leo:leo /srv/projects/drogheda/{tareas,inventario,sitios}
sudo chown leo:leo /srv/projects/drogheda # (sin -R) el backend escribe plan-produccion.json en esta carpeta
sudo systemctl restart actas-hbox
curl -s http://127.0.0.1:8081/api/salud # {"ok":true,"servicio":"actas-hbox"}
curl -s -H 'X-Remote-User: leo' http://127.0.0.1:8081/api/tareas/resumen # {"ok":true,"total":0,...}
Variables de entorno: no hace falta tocar el .service. Si quieres mover las carpetas, descomenta
en /etc/systemd/system/actas-hbox.service las líneas TAREAS_DIR, INVENTARIO_DIR, SITIOS_DIR,
PLAN_FILE (vienen comentadas en backend/actas-hbox.service) y luego daemon-reload + restart.
3 · Siembra inicial (una sola vez; repetirla no duplica nada)
cd /srv/projects/drogheda/hbox-docs
./backend/venv/bin/python3 backend/seed_1013.py --usuario leo
Crea: el plan (570 → 113 V5.6 / 327 V5.7 / 130 v6), los 4 sitios (icave, lzc, eit, timsa — ubicación
y contactos «por confirmar» donde no se sabe), 18 ítems de inventario con stock 0 (Jesús hace el
conteo físico con movimientos «ajuste») y los 12 pendientes del tablero del 13-oct. Lo que ya exista
con el mismo id se deja intacto. Para importar los pendientes del Task Tracker de Notion, exporta
una lista JSON con id, titulo, pista, estado, responsable y pásala con --extra archivo.json.
4 · Verificar
curl -s -u leo:PASS https://drogheda.helgen.online/api/tareas | head -c 300
curl -s -u leo:PASS https://drogheda.helgen.online/api/plan | head -c 200
curl -s -u leo:PASS https://drogheda.helgen.online/api/inventario | head -c 200
curl -s -u leo:PASS https://drogheda.helgen.online/api/sitios | head -c 200
Y desde el navegador: /tableros/kanban.html (arrastra un pendiente y revisa que el historial
anote quién lo movió), /inventario/inventario.html (registra un «ajuste» con el conteo real),
/sitios/sitio.html?id=icave, /formularios/instalacion.html con la unidad PRUEBA.
5 · Respaldo
Se suman tres carpetas y un archivo a la rutina de siempre:
rsync -az leo@git.helgen.online:/srv/projects/drogheda/tareas/ ~/respaldo-tareas/
rsync -az leo@git.helgen.online:/srv/projects/drogheda/inventario/ ~/respaldo-inventario/
rsync -az leo@git.helgen.online:/srv/projects/drogheda/sitios/ ~/respaldo-sitios/
rsync -az leo@git.helgen.online:/srv/projects/drogheda/plan-produccion.json ~/respaldo-plan/
A3 · 14-oct: equipo y usuarios
Agrega la colección equipo (quién es quién; los responsables de los pendientes), la administración
de accesos desde el sitio (/tableros/equipo.html, solo admin) y hace obligatorio el responsable en
cada pendiente. Compatible con lo ya desplegado: los pendientes viejos siguen funcionando; la siembra
les calcula responsable_ids y pone leo solo donde el responsable estaba vacío.
# Mac
cd ~/Documents/Claude/Projects/Drogheda/hbox-docs && git add -A && git commit -m "equipo, usuarios y responsables (14-oct)" && git push && ./scripts/deploy.sh
# servidor
ssh leo@git.helgen.online
cd /srv/projects/drogheda/hbox-docs && git pull
sudo systemctl restart actas-hbox
./backend/venv/bin/python3 backend/seed_1013.py --usuario leo # crea equipo/ (9 miembros, sin accesos) + el pendiente de ferretería; no duplica
curl -s -H 'X-Remote-User: leo' http://127.0.0.1:8081/api/equipo | head -c 200
La carpeta equipo/ la crea la siembra (o el backend al primer alta) junto a /actas; no hay
variables nuevas que fijar (EQUIPO_DIR, HTPASSWD_LOCK vienen comentadas en el .service).
Para crear o quitar accesos desde la página, el servicio tiene que poder escribir el htpasswd —
es lo mismo que ya pide «Mi cuenta» (§7): sudo chown leo:www-data /etc/nginx/hbox-docs.htpasswd && sudo chmod 640 /etc/nginx/hbox-docs.htpasswd. Si no está hecho, la página de Equipo lo avisa y solo
deja editar miembros. A partir de aquí los usuarios se crean en Equipo → Nuevo usuario / miembro
(la contraseña inicial se muestra una sola vez), no con htpasswd en el servidor. Las cuentas que ya
existen y no son miembro (p. ej. luz) aparecen como «cuentas con acceso que no están en el equipo»:
dales de alta como miembro sin marcar «crear acceso».
Verificar: /tableros/equipo.html como leo (botones) y como un técnico (solo lectura); crear un
pendiente sin responsable debe rechazarse; backend/tests-1014.sh reproduce todo con un htpasswd temporal.
| Síntoma | Causa | Arreglo |
|---|---|---|
| Los tableros dicen «No se pudo cargar (HTTP 404)» | backend viejo | paso 2 (git pull + restart) |
| «El servicio no tiene permiso de escribir el archivo de usuarios» al crear un acceso | falta el chown/chmod del htpasswd |
§7 |
| «Falta el responsable del pendiente» al crear | regla del 14-oct | elige a alguien del equipo (o escríbelo en texto libre) |
| «No puedo identificarte (falta X-Remote-User…)» al crear o mover | nginx no manda la cabecera | paso 4 del despliegue anterior |
| El tablero sale vacío | falta la siembra | paso 3 |
| «Solo un administrador…» al borrar o editar sitios/plan | ese usuario no está en ACTAS_ADMINS |
así debe ser; pide a Leo |
PermissionError al guardar el plan |
/srv/projects/drogheda no es de leo |
chown del paso 2 |
A4 · 21-oct: página de inicio, enfoque de la semana y actividad
El inicio deja de ser una página escrita a mano: lee docs/datos/proyecto.json (fase, ruta a
producción, fechas, sitios), el tablero y dos rutas nuevas del backend:
GET /api/hoy·PUT /api/hoy: el enfoque de la semana. Lo escribenHOY_EDITORES(por omisiónleo,adriana) y los administradores; se guarda enenfoque.jsonjunto a/actas, con sus 20 versiones anteriores.GET /api/actividad?dias=7&limite=30: lo que pasó, del historial de los pendientes y de las actas recibidas (sin las series PRUEBA). La usan el inicio y la Bitácora.
No hay carpetas ni variables nuevas que fijar (las dos vienen comentadas en el .service). Como
cambió backend/app.py, después del deploy hay que reiniciar el servicio:
# Mac
cd ~/Documents/Claude/Projects/Drogheda/hbox-docs && ./scripts/deploy.sh
ssh leo@git.helgen.online 'sudo systemctl restart actas-hbox'
# verificar (en el servidor)
curl -s -H 'X-Remote-User: leo' http://127.0.0.1:8081/api/hoy
curl -s -H 'X-Remote-User: leo' 'http://127.0.0.1:8081/api/actividad?dias=7&limite=3' | head -c 400
| Síntoma | Causa | Arreglo |
|---|---|---|
| En el inicio, el enfoque dice «El servidor no respondió» y la actividad, «HTTP 404» | backend viejo | el restart de arriba |
| «El enfoque de la semana lo escriben adriana y leo» al guardar | ese usuario no está en HOY_EDITORES |
así debe ser; para agregar a alguien, Environment=HOY_EDITORES=leo,adriana,… en el .service |
PermissionError al guardar el enfoque |
/srv/projects/drogheda no es de leo |
chown del paso 2 de A2 |
A5 · 21-oct: el sitio como centro de mando — lotes y foto del tablero
Regla de Leo (21-oct): si no está en el sitio, no pasó; cada tarea termina aquí. Claude no llega al
servidor, así que deja sus cambios al tablero en lotes (backend/lotes/AAAA-MM-DD_tema.json, uno por
tarea terminada) y lee el tablero en una foto (_estado/tablero.md, en la Mac). backend/tablero.py
hace las dos cosas en el servidor a través del mismo backend (127.0.0.1:8081): cada cambio pasa por
las mismas validaciones que el sitio y queda en el historial con su autor (claude) y su nota. No
cambia app.py ni pide reiniciar nada. Formato y reglas: backend/lotes/README.md.
# Mac — deploy.sh ya copia tablero.py y al final baja la foto
cd ~/Documents/Claude/Projects/Drogheda/hbox-docs
./scripts/deploy.sh # termina con «Foto del tablero en _estado/tablero.md» y «Tablero: N cambio(s)…»
./scripts/tablero.sh revisar # qué haría el lote 2026-10-21_pasada-6 contra el tablero real
./scripts/tablero.sh aplicar # lo aplica y baja la foto nueva
El primer lote (2026-10-21_pasada-6, cierre de la pasada 6) cierra lo que la pasada terminó
(pasadas 2 a 5 y la fuente de la V5.7), pone en curso la revisión y el Gerber del piloto, crea D-21-2
para Leo, el pedido del piloto (si no existe ya uno), la prueba de banco de la V5.7 (si no existe) y el
pendiente de D34 de la v6 para Michelle, y comenta los de la v6. Lo que no cuadra con el tablero real
(ya está en Hecho, no existe, hay uno parecido, el título coincide con varios) se salta, y revisar
dice por qué antes de escribir nada.
| Síntoma | Causa | Arreglo |
|---|---|---|
No contesta el backend en http://127.0.0.1:8081 |
el servicio está abajo | ssh leo@git.helgen.online 'sudo systemctl status actas-hbox' |
…/venv/bin/python3: No such file or directory |
el venv vive en otro lugar | BACKEND_PATH=/ruta/al/backend ./scripts/tablero.sh … |
PermissionError en lotes-aplicados.json |
/srv/projects/drogheda no es de leo |
chown del paso 2 de A2 |
| «los cambios N ya no son los que se aplicaron» | alguien editó un lote ya aplicado | un lote aplicado no se edita: Claude escribe otro |
| un cambio «se salta» y no debía | el título del pendiente real es distinto | pásale a Claude la línea de revisar; escribe un lote nuevo con el id correcto |
A6 · 22-oct: modo crisis — semáforo, sitio de cada pendiente y juntas
Qué cambia: la página de inicio muestra el semáforo del proyecto (rojo) y el color de cada sitio (docs/datos/proyecto.json);
cada pendiente lleva su sitio (sitios: icave, timsa, eit, lzc, qro; sin sitio = Querétaro), con filtro y vista Por sitio
en Pendientes; pista nueva Gestión; página nueva Juntas. backend/tablero.py acepta sitios en los lotes, salta un lote
con errores sin frenar los demás y recorta notas de más de 300 caracteres (lo avisa).
Cambió backend/app.py: hay que reiniciar el servicio ANTES de aplicar lotes con sitios. Con el backend viejo, revisar
marca esos cambios como inválidos («el backend todavía no conoce «sitios»: reinicia actas-hbox») y no los manda.
cd ~/Documents/Claude/Projects/Drogheda/hbox-docs
mkdocs build --strict
git add -A && git commit -m "Modo crisis: semáforo, sitio por pendiente, juntas" && git push
cd .. && git add hbox-docs && git commit -m "hbox-docs: modo crisis" && git push && cd hbox-docs # sube el submódulo
./scripts/deploy.sh # sitio + backend (rsync); la foto todavía con el backend viejo
ssh leo@git.helgen.online 'sudo systemctl restart actas-hbox'
curl -s -u leo:PASS 'https://drogheda.helgen.online/api/tareas?sitio=eit' | head -c 300 # «sitios» en la respuesta
./scripts/tablero.sh revisar # ya con sitios
./scripts/tablero.sh aplicar
| Síntoma | Causa | Arreglo |
|---|---|---|
| En Pendientes no aparecen los botones de sitio | navegador con el kanban.js viejo |
recarga (los .js llevan ?v= desde el 21-oct) |
Sitio inválido: … al guardar |
sitio que no existe | icave, timsa, eit, lzc o qro (también acepta Veracruz, Manzanillo, Ensenada, LCT, Querétaro) |
revisar dice «el backend todavía no conoce «sitios»» |
no se reinició el servicio | el restart de arriba |
A7 · 22-oct: tablero de Instalaciones por sitio y prueba en sitio
Qué cambia: página nueva Instalaciones (/tableros/instalaciones/, pestañas ICAVE · TIMSA · EIT · LCT): una tarjeta por
unidad con su vehículo, sus actas y su etapa (enviada → recibida → instalada → probada en sitio → en operación, más «con
falla») contra la meta de cada sitio. Acta nueva Prueba en sitio (formularios/prueba-sitio.html, tipo prueba-sitio).
El acta de instalación pide además 12/24 V, los tipos Reach Stacker y Empty Handler y el nombre en el monitor (H00xx). Los
formularios aceptan ?serie=…&sitio=… para abrir la siguiente acta ya llena (acta.js).
Backend: backend/instalaciones.py (nuevo; lo engancha el final de app.py) da GET /api/instalaciones[?sitio=eit] y vuelve
repetible prueba-sitio sin tocar ACTAS_REPETIBLES del servicio. deploy.sh ya copia el archivo nuevo.
Cambió backend/app.py: reinicia el servicio. Sin reiniciar, la página dice «falta reiniciar el servicio actas-hbox» y
la segunda prueba en sitio de una misma unidad daría «Ya existe un acta».
cd ~/Documents/Claude/Projects/Drogheda/hbox-docs
mkdocs build --strict
git add -A && git commit -m "Tablero de Instalaciones por sitio y acta de prueba en sitio" && git push
cd .. && git add hbox-docs && git commit -m "hbox-docs: tablero de Instalaciones" && git push && cd hbox-docs # sube el submódulo
./scripts/deploy.sh # sitio + backend (rsync, ya con instalaciones.py)
ssh leo@git.helgen.online 'sudo systemctl restart actas-hbox'
curl -s -u leo:PASS 'https://drogheda.helgen.online/api/instalaciones?sitio=icave' | head -c 300 # «"ok": true»
| Síntoma | Causa | Arreglo |
|---|---|---|
| «No se pudo leer el tablero de instalaciones (HTTP 404)» | servicio sin reiniciar, o falta backend/instalaciones.py en el servidor |
deploy.sh y el restart; si falta el archivo, journalctl -u actas-hbox dice «instalaciones.py no se cargó» |
| Una unidad instalada no aparece | no tiene acta, o su acta no trae el sitio ni el nombre del puerto | llenar el acta de instalación con el sitio y la fecha real |
| La unidad sale en otro sitio | cuenta en el sitio de su acta más reciente | revisar el sitio de esa acta en el expediente |
A8 · 22-oct: Adriana y Gibran pueden borrar pendientes
Qué cambia: borrar un pendiente ya no es solo de los administradores (ACTAS_ADMINS): también pueden los usuarios de
TAREAS_BORRAN, que por omisión son adriana y gibranlp (no hace falta tocar el servicio). No cambia ningún otro
permiso: actas, usuarios, sitios y plan siguen siendo solo de administradores.
Borrar ya no destruye: el pendiente pasa a /srv/projects/drogheda/tareas/_borrados/<id>__<AAAAMMDDhhmmss>.json con su
historial, sigue en la Actividad («Adriana borró …», sin liga) y quien lo esperaba («Espera a que terminen») deja de
esperarlo, con una nota en su historial.
Cambió backend/app.py: reinicia el servicio.
./scripts/deploy.sh
ssh leo@git.helgen.online 'sudo systemctl restart actas-hbox'
Para dar o quitar el permiso: en /etc/systemd/system/actas-hbox.service, la línea
Environment=TAREAS_BORRAN=adriana,gibranlp con los usuarios que sí (los administradores siempre pueden); después
sudo systemctl daemon-reload && sudo systemctl restart actas-hbox.
Recuperar un pendiente borrado (en el servidor):
cd /srv/projects/drogheda/tareas
ls _borrados/ # <id>__AAAAMMDDhhmmss.json
mv _borrados/<id>__<fecha>.json <id>.json # vuelve al tablero como estaba; las dependencias que se quitaron no regresan solas
| Síntoma | Causa | Arreglo |
|---|---|---|
| Adriana o Gibran no ven «Borrar» en el detalle | servicio sin reiniciar | el restart de arriba |
| «Solo … pueden borrar pendientes» | ese usuario no es administrador ni está en TAREAS_BORRAN |
así debe ser; si debe poder, agrégalo a TAREAS_BORRAN |
A9 · 23-oct: inventario por sitio
Qué cambia: Inventario (/tableros/inventario/) tiene una pestaña por sitio —ICAVE · TIMSA · EIT · LCT · Querétaro— y
Todo. Cada movimiento dice en qué sitio pasó. Tipo nuevo Envío: saca material de un sitio (o de «Proveedor o fuera
del inventario»: una compra en camino, o material que salió antes de que se contara) y lo deja en camino hasta que el
sitio que lo espera le da Recibir (tipo recepcion; si llegó menos, la diferencia baja del total). Cada ítem puede decir
cuánto lleva una instalación (Por instalación) y la pestaña de cada puerto calcula qué falta para instalar N unidades.
Categoría nueva Instalación (soportes, tornillería, cable de potencia). Instalaciones tiene un botón Material que abre
la pestaña del sitio. El CSV trae una columna por sitio y otra de lo que va en camino. Reglas para el equipo:
Política de inventario.
Datos: no hay migración. Los movimientos de antes no tienen sitio y cuentan como Querétaro; el total de cada ítem no
cambia. El primer paso del equipo es el conteo físico de cada sitio (lote 2026-10-23_inventario-sitios).
Cambió backend/app.py: reinicia el servicio. Sin reiniciar, la página muestra solo Todo y avisa que falta
reiniciar actas-hbox.
cd ~/Documents/Claude/Projects/Drogheda/hbox-docs
mkdocs build --strict
git add -A && git commit -m "Inventario por sitio: pestañas, envíos en camino y kit por instalación" && git push
cd .. && git add hbox-docs && git commit -m "hbox-docs: inventario por sitio" && git push && cd hbox-docs # sube el submódulo
./scripts/deploy.sh
ssh leo@git.helgen.online 'sudo systemctl restart actas-hbox'
curl -s -u leo:PASS https://drogheda.helgen.online/api/inventario | head -c 300 # debe traer «"sitios"» y «"envios"»
./scripts/tablero.sh revisar && ./scripts/tablero.sh aplicar
Pruebas en la Mac (opcional, necesita Flask): bash backend/tests-1023.sh . (35 revisiones: entrada por sitio, envío,
recepción completa y con faltante, conteo físico, envío desde fuera, errores y CSV).
| Síntoma | Causa | Arreglo |
|---|---|---|
| Solo se ve Todo y un aviso de reiniciar | servicio sin reiniciar | el restart de arriba |
| «No hay stock suficiente en EIT: hay 0 pza registrados» | ese sitio no tiene su conteo físico ni entradas | Conteo físico en ese sitio primero; si es material que ya salió sin contarse, envío desde «Proveedor o fuera del inventario» |
| Un envío no sale en la pestaña del sitio que lo espera | se registró con otro destino, o ya se recibió | tocar el código del ítem: sus movimientos dicen a dónde iba y quién lo recibió |
| El total de un ítem subió sin que llegara nada | un envío desde «Proveedor o fuera del inventario» entra al total al registrarse (va en camino) | así debe ser; si al recibir llega menos, la diferencia baja |
A10 · 23-oct: cuentas nuevas, contraseña inicial para todos y correo de cada quien
Qué cambia:
backend/cuentas.py(nuevo;deploy.shya lo copia junto conbackend/cuentas/): restablece contraseñas en bloque y da de alta a varios. Primera corrida (cuentas/2026-10-23_alta-sitios.json): altas de jesush (Jesús Honorato, TIMSA), miguel (Miguel Ángel Peña, EIT), joel (Joel Orantes, EIT), antonio (Antonio Ventura, LCT) y danielg (Daniel González Cruz, ensamble, Querétaro); el usuariojesuspasa a llamarse Jesús Romero; se llenan los correos que ya conocíamos; y todos menos leo y claude quedan con la misma contraseña inicial.- Equipo: columnas Sitio y Correo, filtro por sitio, campos «Sitio» y «Otro correo» (el del otro dominio) y, para el administrador, la marca contraseña inicial.
- Quien sigue con la contraseña inicial ve una franja arriba en todas las páginas, con la liga a Mi cuenta; se quita sola cuando la cambia.
- Los pendientes que tenían a alguien como texto libre («Miguel») ya cuentan como suyos en cuanto se da de alta.
Cambió backend/app.py: reinicia el servicio antes de correr cuentas.py y antes de aplicar el lote.
cd ~/Documents/Claude/Projects/Drogheda/hbox-docs
mkdocs build --strict
git add -A && git commit -m "Cuentas en bloque, contraseña inicial y sitio/correo en Equipo" && git push
cd .. && git add hbox-docs CLAUDE.md && git commit -m "hbox-docs: cuentas del 23-oct" && git push && cd hbox-docs
./scripts/deploy.sh
ssh leo@git.helgen.online 'sudo systemctl restart actas-hbox'
ssh -t leo@git.helgen.online 'cd /srv/projects/drogheda/hbox-docs/backend && venv/bin/python3 cuentas.py todo cuentas/2026-10-23_alta-sitios.json'
./scripts/tablero.sh revisar && ./scripts/tablero.sh aplicar # lote 2026-10-23_usuarios-campo
cuentas.py muestra el plan (altas, a quién restablece, qué datos llena) y pide «si»; luego la contraseña, dos veces y
sin eco. No la escribas en ningún archivo ni en un chat de grupo: pásala en persona o por mensaje directo. Para revisar
después (sin contraseñas ni hashes):
ssh leo@git.helgen.online 'cd /srv/projects/drogheda/hbox-docs/backend && venv/bin/python3 cuentas.py lista'.
Pruebas en la Mac (opcional, necesita Flask): bash backend/tests-cuentas.sh . (47 revisiones).
| Síntoma | Causa | Arreglo |
|---|---|---|
cuentas.py: «No encuentro el archivo de usuarios» o PermissionError |
no se corrió como leo, o el htpasswd no es de leo |
correr como leo; sudo chown leo:www-data /etc/nginx/hbox-docs.htpasswd && sudo chmod 640 /etc/nginx/hbox-docs.htpasswd |
| Alguien no puede entrar después | escribió otra contraseña, o su cuenta salió como «sin miembro activo» y no se tocó | cuentas.py lista; restablécesela en Mi cuenta (admin) |
| Hay que deshacer el restablecimiento | — | el archivo anterior quedó en /srv/projects/drogheda/equipo/_respaldos/htpasswd-AAAAMMDD-hhmmss: cópialo encima de /etc/nginx/hbox-docs.htpasswd como leo |
| No sale la franja de la contraseña ni la columna Sitio | servicio sin reiniciar | el restart de arriba |
B · Verificación después de desplegar
# 1. el backend responde y sabe quién eres
curl -s -u leo:PASS https://drogheda.helgen.online/api/whoami # {"user":"leo","admin":true}
curl -s -u alan:PASS https://drogheda.helgen.online/api/whoami # {"user":"alan","admin":false}
Si user sale vacío, falta la línea X-Remote-User del paso 4.
# 2. la subida de fotos funciona de punta a punta
curl -s -u alan:PASS -F tipo=diagnostico-campo -F serie=CAMPO-PRUEBA \
-F foto=@cualquier-foto.jpg \
https://drogheda.helgen.online/api/adjuntos
# → {"ok":true,"fotos":[{"ruta":"diagnostico-campo/CAMPO-PRUEBA/2026…jpg",…}]}
# 3. el acta de campo NO se bloquea al segundo envío
curl -s -u alan:PASS https://drogheda.helgen.online/api/historial\?tipo=diagnostico-campo\&serie=CAMPO-PRUEBA
Y la prueba que de verdad cuenta, desde un teléfono:
abrir https://drogheda.helgen.online/formularios/diagnostico.html, elegir la unidad
⚙ PRUEBA (no cuenta), tomar una foto y enviar. Las series con PRUEBA se guardan aparte,
en _pruebas/, y no ensucian el registro.
C · Ciclo normal a partir de aquí
# contenido nuevo desde el repo Drogheda (lista curada dentro del script)
./scripts/sync-docs.sh
git add -A && git commit -m "…" && git push
./scripts/deploy.sh # sitio + backend (rsync) + foto del tablero
./scripts/tablero.sh revisar # si Claude dejó un lote nuevo en backend/lotes/
./scripts/tablero.sh aplicar
# y SOLO si cambió backend/app.py (deploy.sh ya lo copió):
ssh leo@git.helgen.online 'sudo systemctl restart actas-hbox'
D · Respaldo
Todo lo que los técnicos generan son dos carpetas planas — cópialas y ya:
rsync -az leo@git.helgen.online:/srv/projects/drogheda/actas/ ~/respaldo-actas/
rsync -az leo@git.helgen.online:/srv/projects/drogheda/adjuntos/ ~/respaldo-fotos/
E · Problemas frecuentes
| Síntoma | Causa | Arreglo |
|---|---|---|
| "La foto pesa demasiado" con fotos normales | falta client_max_body_size |
paso 4 |
| El nombre del técnico no se precarga | falta X-Remote-User |
paso 4 |
| "Ya existe un acta para esta serie" en diagnóstico | backend viejo | paso 2 (git pull + restart) |
| Las fotos se ven rotas en el tablero | falta la carpeta adjuntos o su permiso |
paso 3 |
mkdocs build --strict falla |
un enlace del nav apunta a un archivo que no existe |
revisa mkdocs.yml |
| El técnico no puede entrar | usuario no creado, o se usó htpasswd -c y borró a los demás |
paso 5 |
| «El servicio no tiene permiso de escribir el archivo de usuarios» | falta el chown/chmod del htpasswd |
paso 7 |
| «Tu contraseña está guardada en un formato que no puedo verificar» | esa entrada es bcrypt, no $apr1$ |
restablecerla desde /cuenta.html como administrador |