Files
feadulta/docs/handoff-tecnico-rafa-issues-174-175-2026-07-15.md
T
rafa 5055e92143 Rescatar 10 docs/ del main local que nunca llegaron a Gitea (issue #194)
main local y origin/main son dos historias sin ancestro comun (ver #194).
Analisis del agente: de las 46 commits solo-en-local, el unico contenido que
no esta ya reflejado en origin/main via el snapshot de julio (PR #179) son
estos 10 ficheros de docs/ (guias, handoffs, planes, benchmark, revisiones de
issues). Copiados tal cual desde main con "git show main:docs/X > docs/X".

Redactada una password SSH y una password cPanel/FTP en texto plano que
tenia handoff-carta-46956-2026-06-17.md (servidor CDMON antiguo) antes de
subirlo -- ver .env, nunca en docs versionados.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-05 08:39:06 -04:00

6.2 KiB

Handoff técnico para Rafa — issues #174 y #175

Alcance

Preparación técnica solamente. No aplicar en producción desde aquí.


Issue #174 — cierre autónomo de la carta (publicar + rotar)

Regla funcional confirmada por Inma/Mixbot

La rotación que ya funcionó hoy manualmente por WP REST API para la carta 735 es esta, y solo para el post ES:

  1. nueva carta → añadir cat 6 (carta actual)
  2. la que estaba en cat 6 → quitar cat 6, añadir cat 22 (semana pasada), manteniendo cat 21 (archivo acumulativo)
  3. la que estaba en cat 22 → quitar cat 22, dejar solo cat 21
  4. no tocar traducciones en este paso

Decisión pendiente para Rafa

Hay dos caminos válidos:

Opción A — adaptar rotate_cartas.php a ES-only

Pros:

  • reutiliza lógica ya existente y conocida en el repo
  • más coherente con el toolkit actual de scripts
  • fácil dejar DRY-RUN + APPLY=1

Contras:

  • hay que modificar el script actual porque hoy rota todos los idiomas
  • si Mixbot publica por REST y la rotación la hace otro script aparte, el flujo queda repartido en dos piezas

Opción B — que Mixbot haga la rotación por WP REST API

Pros:

  • ya está validado en vivo hoy
  • mantiene toda la operación editorial en el mismo sitio donde ya se publica la carta
  • evita acoplar la decisión editorial a un script server-side adicional

Contras:

  • la lógica queda fuera del repo de scripts PHP si no se documenta bien
  • conviene dejarla muy explícita para no divergirse del comportamiento esperado

Recomendación técnica

Mi lectura: cualquiera vale, pero elegiría según quién vaya a mantenerlo:

  • si Rafa quiere la lógica versionada y centralizada en el repo, mejor A: rotate_cartas.php ES-only
  • si Inma/Mixbot ya tienen el flujo sólido y prefieren autonomía total desde su lado, mejor B: REST API desde Mixbot, con la lógica documentada en el issue/runbook

Si Rafa elige A (script ES-only), propuesta concreta

Crear una variante mínima o adaptar rotate_cartas.php con estas reglas:

  • entrada: CARTA=<es_id>
  • lookup solo en idioma es
  • localizar:
    • actual_es = post con cat 6
    • pasada_es = post con cat 22
    • nueva_es = CARTA
  • operaciones:
    • pasada_es pierde 22, conserva 21
    • actual_es pierde 6, gana 22, conserva 21
    • nueva_es gana 6 y conserva/gana 21
  • nunca tocar posts EN/FR/IT/PT
  • mantener modo DRY-RUN

Dry-run deseable para Rafa

Salida ideal del dry-run:

  • nueva_es=#54495 -> +6 (+21 si faltaba)
  • actual_es=#54254 -> -6 +22 (mantiene 21)
  • pasada_es=#53984 -> -22 (mantiene 21)
  • translations untouched

Decisión funcional que conviene dejar escrita

Para evitar ambigüedad futura, dejar explícito en el issue o en el script:

  • 21 es acumulativa y la conservan todas las cartas archivables
  • 6 y 22 son mutuamente excluyentes
  • la rotación editorial inicial afecta solo al ES
  • las traducciones rotan/publican en un paso posterior independiente

Issue #175 — endpoint subir-avatar

Base ya existente

El sistema actual ya tiene casi todo:

  • frontend lee user_meta('foto_perfil')
  • face_crop_avatar.py ya resuelve recorte/centrado de cara
  • regen_avatars.php ya existe para regeneración/ajustes
  • caso real listo para probar: Silvia Martínez Cano, user_id=1112, slug=silvia-mtnz

Contrato recomendado

Yo le propondría a Rafa este contrato por simplicidad operativa:

Endpoint

POST /wp-json/fea/v1/subir-avatar

Auth

La misma Application Password que ya usa crear-autor (#166), con el mismo criterio de permisos.

Identificador

user_id mejor que slug.

Motivo:

  • Mixbot ya lo tiene en el roster
  • evita ambigüedades por slug cambiado / transliteraciones / colisiones
  • simplifica el lookup

Formato de entrada

multipart/form-data mejor que base64.

Motivo:

  • más natural para subir imágenes
  • menos overhead
  • encaja mejor con media_handle_sideload / manejo típico WP
  • más fácil de depurar que base64

Campo esperado

  • user_id (obligatorio)
  • file (obligatorio)

Opcionalmente:

  • crop=server|client si Rafa quiere dejar ambas puertas abiertas, aunque probablemente es overkill de entrada

Recomendación de procesamiento

Mi recomendación clara: que el endpoint NO haga face-crop complejo en la primera versión.

Mejor v1:

  • Mixbot/Inma mandan la imagen ya cuadrada
  • estándar objetivo: 1254x1254 (el que ya usáis)
  • el endpoint solo:
    1. valida usuario
    2. guarda attachment
    3. actualiza foto_perfil
    4. devuelve attachment_id, user_id, url

Pros:

  • mucho menos riesgo y menos dependencias server-side
  • evita meter OpenCV/Pillow/lógica pesada dentro del endpoint
  • más fácil de testear e idempotente
  • si mañana queréis face-crop automático, se añade en v2

Comportamiento recomendado del endpoint

  • requiere login + permiso tipo edit_others_posts (igual filosofía que crear-autor)
  • valida que user_id exista
  • acepta solo imagen (jpg, jpeg, png, webp si WP lo admite ahí)
  • crea attachment en Media Library
  • hace update_user_meta($user_id, 'foto_perfil', $attachment_id)
  • respuesta JSON:
    • user_id
    • display_name
    • attachment_id
    • url
    • updated: true

Idempotencia mínima útil

No hace falta obsesionarse en v1, pero sí conviene:

  • si se vuelve a subir otra foto para el mismo user_id, simplemente reemplazar el foto_perfil al nuevo attachment
  • opcional: si el hash del fichero coincide con el ya asignado, devolver updated:false

Caso piloto sugerido

Primera prueba con:

  • user_id=1112
  • slug=silvia-mtnz
  • imagen ya recortada por Inma/Mixbot a 1254x1254

Así la prueba valida solo el endpoint, no el pipeline de crop.


Cierres administrativos

Por estado funcional, salvo sorpresa:

  • #166 → cerrable
  • #168 → cerrable
  • #170 → cerrable

Recomendación final para Rafa

Si quiere minimizar trabajo y riesgo:

  • #174: usar la lógica que ya validó Mixbot hoy, y solo portar al repo si él prefiere centralizar
  • #175: endpoint mínimo con user_id + multipart + imagen ya cuadrada a 1254x1254

Eso deja la autonomía mucho más cerca sin meterse en una refactor rara.