1.6.2: manifiesto firmado, tiempo estimado en tareas, pruebas automáticas

- firma.py: RSA-2048 PKCS#1 v1.5 SHA-256 sin dependencias; empaquetar.py firma
  el manifiesto y actualizador.py exige la firma (CLAVE_PUBLICA incrustada).
- Barra de tareas: tiempo restante estimado a partir del avance.
- Corregido: APLICANDO nunca llegaba al total y «Moviendo» quedaba fijo,
  bloqueando desconectar la carpeta.
- probar.py: reglas, firma y recorrido completo sobre una copia temporal.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Este commit está contenido en:
Labstream
2026-09-15 14:48:47 -05:00
padre 8c5153e8ed
commit 8b482af652
Se han modificado 9 ficheros con 414 adiciones y 14 borrados

Ver fichero

@@ -38,7 +38,7 @@ for d in ("build", "dist"):
subprocess.check_call([sys.executable, "-m", "PyInstaller", "--noconfirm", "--clean", "--onedir", "--windowed",
"--name", "OrganizadorLabstream", "--icon", os.path.join("static", "organilab.ico"),
"--hidden-import", "resolve_bridge", "--hidden-import", "reglas",
"--hidden-import", "asistente", "--hidden-import", "actualizador",
"--hidden-import", "asistente", "--hidden-import", "actualizador", "--hidden-import", "firma",
"--collect-all", "webview", "--collect-all", "clr_loader", "--collect-all", "pythonnet",
"--exclude-module", "tkinter", "organizador.py"])
dest = os.path.join("dist", "OrganizadorLabstream")
@@ -118,6 +118,18 @@ manifiesto = {
"app": {"archivo": app_zip, "size": os.path.getsize(app_zip), "sha256": sha(app_zip), "url": f"/api/herramientas/{app_zip}"},
"notes": notas,
}
import firma
if os.environ.get("FIRMA") == "no":
print("AVISO: manifiesto sin firmar (FIRMA=no); los .exe 1.6.2+ no lo aceptarán")
else:
if not os.path.exists(firma.RUTA_PRIVADA):
sys.exit(f"falta la clave de firma en {firma.RUTA_PRIVADA}: corre py -3.12 firma.py generar (o FIRMA=no para saltarlo)")
_priv = firma.cargar_privada()
manifiesto["firma"] = {"alg": "rsa2048-pkcs1v15-sha256", "valor": firma.firmar(firma.texto_manifiesto(manifiesto), _priv)}
import actualizador
if not firma.verificar(firma.texto_manifiesto(manifiesto), manifiesto["firma"]["valor"], actualizador.CLAVE_PUBLICA):
sys.exit("la clave privada no corresponde a CLAVE_PUBLICA de actualizador.py; el manifiesto no serviría")
print("manifiesto firmado")
ruta_os = os.path.join(os.path.dirname(AQUI), "labstream-os", "public", "herramientas", "organizador.json")
if os.path.isdir(os.path.dirname(ruta_os)):
previo = {}