Files
hechakuaa_bot/CHANGELOG.md
markosbenitez 5eb934d4a1 chore: release v0.3.1 — CHANGELOG + política de versiones en CLAUDE.md
- CHANGELOG.md: historial completo desde v0.1.0 hasta v0.3.1
- CLAUDE.md: sección 'Gestión de versiones' con reglas semver,
  tabla MAJOR/MINOR/PATCH, proceso de release copy-paste
- Scope y archivos del proyecto actualizados al estado real (v0.3.1)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 10:43:59 -03:00

7.4 KiB

Changelog — Pedrito Hechakuaa

Todos los cambios notables se documentan acá.

Formato: Keep a Changelog
Versiones: Semantic Versioning


[Unreleased]


[0.3.1] — 2026-05-26

Security

  • /health/history requiere authAuthorization: Bearer <HEALTH_AUTH_TOKEN>; sin token devuelve 401 con header WWW-Authenticate. Sin auth configurada, retorna 401 igualmente.
  • chat_ids enmascarados en historial — reemplazados por hash SHA256[:8] opaco (usr_a3b4c5d6); preserva correlación de eventos sin exponer Telegram IDs (PII).
  • /health público mínimo — sin auth devuelve solo {status, timestamp}. Con auth, respuesta completa con métricas internas. Elimina exposición de conteo de tenants y timing del poller.
  • Env vars borradas del proceso — después de cargar Settings(), se eliminan de os.environ: FERNET_KEY, TELEGRAM_BOT_TOKEN, PJ_USUARIO_ENC, PJ_PASSWORD_ENC, WEBHOOK_SECRET, HEALTH_AUTH_TOKEN, INVITE_CODE. Protege contra /proc/<pid>/environ.
  • Race condition TOCTOU en invite codes eliminadaSELECT + UPDATE reemplazado por UPDATE WHERE codigo=? AND usado=0; rowcount=0 indica código no válido o ya usado. Imposible que dos requests simultáneos consuman el mismo código.
  • Timing oracle en validación de código mitigado — delay mínimo garantizado de 800ms en _paso_codigo() independientemente del resultado; secrets.compare_digest() para comparación contra código del .env.
  • Respuestas a usuarios no registrados reducidas al mínimo_rechazar_no_registrado ya no revela la arquitectura de comandos; texto libre de usuarios sin registro recibe silencio total.
  • Webhook inválido devuelve 404 — en vez de 403, no confirma la existencia del endpoint.
  • Nginx rate limiting documentado en DEPLOY.md: limit_req_zone 30r/s para webhook, 10r/min para health; headers X-Content-Type-Options, X-Frame-Options.
  • HEALTH_AUTH_TOKEN agregado a config.py y a la guía de .env en DEPLOY.md.

[0.3.0] — 2026-05-25

Added

  • DockerDockerfile (imagen ghcr.io/astral-sh/uv:python3.12-bookworm-slim), docker-compose.yml con restart: unless-stopped y healthcheck, .dockerignore.
  • Health check HTTP (health.py) — servidor aiohttp en puerto 8080:
    • GET /health — estado del bot (ok/degraded)
    • GET /health/history — últimos N eventos del audit log
    • Watcher loop que alerta al admin via Telegram si el poller no actualiza en N horas
  • Schema migrations — directorio migrations/001_initial_schema.sql, función run_migrations() en database.py; idempotente con CREATE TABLE IF NOT EXISTS. Tabla schema_migrations lleva registro de versiones aplicadas.
  • Webhook opt-inPOST /webhook en aiohttp valida X-Telegram-Bot-Api-Secret-Token con compare_digest y pone el Update en application.update_queue de PTB. Se activa con WEBHOOK_URL en .env; vacío = long-polling.
  • aiohttp>=3.9 como nueva dependencia.
  • WEBHOOK_URL, WEBHOOK_SECRET, HEALTH_PORT, HEALTH_ALERT_HOURS en config.py.
  • Poller notifica a health vía callback on_poll_done(tenant_count).
  • revisar_ahora() retorna int (cantidad de tenants revisados).

Changed

  • init_db() reemplazado por run_migrations() en main.py; init_db() queda como alias para compatibilidad con scripts.
  • main.py arranca HealthServer antes del poller; elige polling vs webhook según config; registra webhook con Telegram en modo webhook; elimina webhook al detener.
  • DEPLOY.md actualizado con guía completa de 20 secciones: DNS Bluehost/cPanel (con mensaje exacto en inglés para delegar), Nginx, Certbot/SSL, Docker, webhook, health check, rate limiting.

[0.2.1] — 2026-05-25

Fixed

  • Campos del API del PJ corregidos — la API real usa fechaNotificacion (no fecha), descripcionDespacho (no juzgado), descripcionCircunscripcion (no circunscripcion). NotificacionPendiente.__init__ ahora usa fallback or para ambos nombres.
  • PDF callback — usaba cod_notificacion_origen como ID de actuación; corregido a cod_actuacion_caso (campo codActuacionCaso de la API).
  • 403 en listar_notificaciones — manejado explícitamente como CSJAuthError en vez de caer en raise_for_status() genérico.

[0.2.0] — 2026-05-25

Added

  • Multi-tenantdatabase.py con SQLite vía aiosqlite; tabla tenants con credenciales cifradas por chat_id; list_active_tenants(), save_tenant(), delete_tenant().
  • Onboarding flow (onboarding.py) — máquina de estados de 8 pasos: código de invitación → consentimiento → nombre → tono → timezone → cédula → password → guardado.
  • Códigos de invitación — tabla invite_codes, validación de un solo uso atómica, fallback al código maestro del .env; scripts/generar_codigo.py.
  • Audit log — tabla audit_log, función audit.log() fire-and-forget; cobertura de todos los eventos de onboarding, polling, comandos y errores.
  • Rate limiting (utils/rate_limiter.py) — ventana deslizante por chat_id, 20 req/60s; reset en /resetear.
  • FERNET_KEY rotation (scripts/rotar_fernet_key.py) — re-cifra todos los tenants de forma atómica; hace backup de .env antes de modificar; aborta si algún tenant falla.
  • Comando /exp — búsqueda de expedientes por número o carátula.
  • Comando /pdf — descarga PDF de la actuación más reciente via permisoFirmado.
  • Tono personalizable por abogado: formal / cotidiano / informal.
  • Zona horaria configurable por abogado.
  • TELEGRAM_EXTRA_IDS para autorizar IDs adicionales sin onboarding.
  • DEPLOY.md — primera versión de la guía de despliegue en VPS Ubuntu con systemd.

Changed

  • poller.py itera sobre todos los tenants activos (era single-tenant).
  • Snapshots por tenant: data/snapshot_{chat_id}.json (era data/snapshot.json global).
  • vault.py usa derivación de clave Fernet por chat_id: base64(SHA256(FERNET_KEY + str(chat_id))).

Security

  • Contraseña del PJ borrada de memoria inmediatamente tras cifrar (del password en onboarding).
  • Mensaje de Telegram con la contraseña eliminado del chat vía delete_message antes de procesar.

[0.1.0] — 2026-05-25

Added

  • Login al sistema judicial apps.csj.gov.py: GET /login → cookie cookiesession1POST /autenticador/login → bearer token (TTL 1h).
  • Polling de GET /Notificaciones/PorRecibir cada N minutos en horario hábil (lun-vie, 7-18hs).
  • Diff vs snapshot JSON local — solo notifica notificaciones con codNotificacionOrigen nuevo.
  • Relogin automático transparente al expirar el token.
  • Bot de Telegram con comandos: /start, /notif, /estado, /ayuda, /salir.
  • Credenciales del PJ cifradas con Fernet en .env (scripts/cifrar_credenciales.py).
  • scrub() en utils/sanitize.py — sanitiza bearer tokens, JWTs, cookies y passwords antes de pasar cualquier dato externo a los logs.
  • Logging estructurado con structlog (JSON en prod, ConsoleRenderer en dev vía isatty).
  • Configuración vía pydantic-settings — único punto de config de la app (config.py).
  • Stack base: httpx, python-telegram-bot[ext] v21, aiosqlite, cryptography, structlog, pydantic-settings, apscheduler.
  • Manejo de señales SIGINT/SIGTERM para shutdown limpio.