From 34bac1a23731941c053eac662a23315558018d28 Mon Sep 17 00:00:00 2001 From: AgileHub VIGILE Date: Sun, 31 May 2026 10:35:37 +0200 Subject: [PATCH] docs(handover): aggiornamenti AgileHub 31/5 (email-ms fix + opcache USR2 cross-suite) Distribuzione cross-suite su direttiva utente "se devi segnalare aggiornamenti devi farlo per tutti i dockers dev". Doc completo in docs/INCOMING_FROM_AGILEHUB_2026_05_31_email_send_fix_and_php_opcache.md. Co-Authored-By: Claude Opus 4.7 --- CLAUDE.md | 30 ++++ ...26_05_31_email_send_fix_and_php_opcache.md | 140 ++++++++++++++++++ 2 files changed, 170 insertions(+) create mode 100644 docs/INCOMING_FROM_AGILEHUB_2026_05_31_email_send_fix_and_php_opcache.md diff --git a/CLAUDE.md b/CLAUDE.md index b178edf..a5650dd 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -25,6 +25,36 @@ **Spec completa**: `STANDARD_TIMEZONE_CONVENTIONS.md` (slug `timezone-conventions` v1.0, owner VIGILE). +## 🔴 AGGIORNAMENTI AGILEHUB 2026-05-31 (vincolanti) + +> Aggiunto da AgileHub-side (VIGILE) su direttiva utente: "se devi segnalare aggiornamenti devi farlo per tutti i dockers dev". Doc completo: `docs/INCOMING_FROM_AGILEHUB_2026_05_31_email_send_fix_and_php_opcache.md`. + +### 1. email-automation-ms — bug "invii silenti" CHIUSO (per TUTTI i prodotti che mandano email) + +Bug: `POST /api/emails/send` con payload `{to, subject, html: "..."}` (campo `html` invece del canonico `body`) rispondeva `201 success:true` ma spediva email **vuota** (solo subject). Fixed (agile-services commit `809ea53`): defense-in-depth in `emailService.send()` + alias `html` su `/emails/send` + 400 EMPTY_RENDERED_BODY. + +**Payload canonici da subito**: +- Template Handlebars: `POST /emails/send {to, template, data, product, tenantId}` +- HTML grezzo: `POST /emails/send-raw {to, subject, html, product, tenantId}` ← preferito per HTML diretto + +**Da controllare lato vostro**: caller che usano `html` su `/emails/send` (oggi alias-compat con header `Deprecation`) → migrare a `/emails/send-raw`; gestire `400 EMPTY_RENDERED_BODY` nel codice client; assicurarsi di usare `data` (non `variables`) per i template. + +### 2. PHP opcache USR2 + disciplina commit (solo prodotti PHP-FPM) + +**Hot-reload obbligatorio**: dopo OGNI edit `.php` → `docker exec kill -USR2 1`. Bind-mount NON basta (`opcache.validate_timestamps=Off` → vecchio bytecode in cache, gli utenti vedono ancora la versione precedente). USR2 = graceful FPM reload, zero downtime, ~10ms. + +**Commit-early**: appena una modifica funziona (smoke verde post-USR2), commit subito. Il cron `ticket-agent-cron.sh` può revertare WIP scoperte (caso reale NIS2 29/5: commit `d5d83bb` revertato `index.php` di una Feature 1 non committata). Per WIP attivo prolungato → semaforo manuale: +```bash +echo "USER=... STARTED=$(date -Iseconds)" > /tmp/agent-working.lock +# il cron salta i container con quel lock +rm /tmp/agent-working.lock +``` + +**Push se cache token vuota** (post-reboot container legacy, oggi solo `trpg-agile` migrato al vault helper): chiedere a VIGILE/AgileHub-side "pusha N commit dall'host" (helper vault). Fix definitivo = migrazione vault helper come `trpg-agile`. + +--- + + ## 🔴 ATTIVITÀ PRIMARIA — Workflow di rilascio + hot-reload PHP + disciplina commit > **VINCOLANTE per OGNI modifica di codice su NIS2.** Aggiunto 2026-05-30 da AgileHub-side (VIGILE) dopo che la sessione NIS2 ha scoperto sul campo che il bind-mount NON serve codice "live" e che le modifiche scoperte vengono revertate. diff --git a/docs/INCOMING_FROM_AGILEHUB_2026_05_31_email_send_fix_and_php_opcache.md b/docs/INCOMING_FROM_AGILEHUB_2026_05_31_email_send_fix_and_php_opcache.md new file mode 100644 index 0000000..c40f104 --- /dev/null +++ b/docs/INCOMING_FROM_AGILEHUB_2026_05_31_email_send_fix_and_php_opcache.md @@ -0,0 +1,140 @@ +# OUTGOING → TUTTI i container DevEnv — Aggiornamenti vincolanti (2026-05-31) + +> **Da**: AgileHub-side (VIGILE) +> **A**: ogni sessione Claude su `trpg-agile-devenv`, `taxai-agile-devenv` (ALLTAX), `nis2-agile-devenv`, `dfm-pro-agile-devenv`, `lg231-agile-devenv`, `sustainai-agile-devenv`, `marketing-agile-devenv`, `certisource-devenv`, `allrisk-agile-devenv`, `wms-agile-devenv`, `mktg-agile-devenv`, `madeby-cloud-devenv` (e qualunque sessione futura). +> **Trigger**: l'utente ha esplicitato la regola — *"Se devi segnalare aggiornamenti devi farlo per tutti i dockers dev"*. Codifico qui i 2 aggiornamenti pendenti. + +--- + +## TL;DR + +| Aggiornamento | A chi si applica | Cosa fare | +|---|---|---| +| **1. email-automation-ms fix + payload canonico** | **TUTTI** (chiunque manda email transazionali) | Aggiornare i client al payload canonico; il bug "html ignorato silente" è chiuso | +| **2. PHP opcache USR2 + disciplina commit** | **Solo prodotti PHP-FPM** (NIS2, ALLTAX, DFM-PRO, LG231, SUSTAINAI, ALLRISK, eventuali altri con php-fpm in produzione) | Dopo ogni edit `.php` → `kill -USR2 1` nel container FPM. Commit-early per evitare revert race del cron ticket-agent | + +--- + +## 1. email-automation-ms — fix bug invii silenti + payload canonico + +### Il bug (chiuso commit `809ea53` di agile-services, 31/5) + +Segnalato da TaxAi/AllTax: chiamando `POST /api/emails/send` con `{to, subject, html: "..."}` (cioè usando il campo `html` invece del canonico `body`), l'API rispondeva **`201 success: true`** con messageId e logId validi, ma l'**email veniva spedita VUOTA** (solo subject, body vuoto). Nessun errore, nessun warning, log come SENT. + +Causa: la destrutturazione di `/emails/send` accettava `body` ma **non `html`** → `html` ignorato senza warning → `body` undefined → `html = body || ''` → stringa vuota → invio procedeva. + +### Fix lato MS (già LIVE) + +1. **`emailService.send()`** ha defense-in-depth: se l'HTML dopo il rendering è vuoto/whitespace → log FAILED in `email_log` + return `success: false EMPTY_RENDERED_BODY`. Qualunque caller errato lo scopre subito. +2. **`/emails/send`** accetta ora `html` come alias di `body` (compatibilità con caller che usavano `html` per errore). Header response `Deprecation` segnala che il canonico per HTML grezzo resta `/emails/send-raw`. +3. Validazione irrobustita: serve **template OR body OR html** (prima bastava subject). + +### Payload canonici (a memoria, validi da subito) + +**Caso A — template Handlebars** (consigliato per tutto ciò che è ripetitivo): +```bash +POST /api/emails/send +X-Internal-Key: +{ + "to": "user@example.com", + "template": "demo-registration-verify", + "data": { "name": "Mario", "verify_url": "..." }, + "product": "", + "tenantId": +} +``` + +**Caso B — HTML grezzo** (per email one-off, alert, ecc.) — usare **`/emails/send-raw`**: +```bash +POST /api/emails/send-raw +X-Internal-Key: +{ + "to": "user@example.com", + "subject": "Oggetto", + "html": "

Contenuto

", + "product": "", + "tenantId": +} +``` + +**Per envelope From per-tenant** (opzionale, multi-tenant): +```json +{ + "from": "noreply@.agile.software", + "fromName": "", + "replyTo": "supporto@.agile.software" +} +``` + +### Cosa controllare lato vostro + +1. Cercare nel codice i caller di `/emails/send`. Se usano `html`, sostituire con `body` (canonico per quella route) **oppure** migrare a `/emails/send-raw`. Per non rompere la retrocompat, l'alias funziona; ma riceverete l'header `Deprecation`. +2. Cercare caller che si aspettavano `success: true` senza verificare il content. Ora con email vuote arriva `400 EMPTY_RENDERED_BODY` → aggiornare la gestione errore di conseguenza. +3. Se inviate via template Handlebars assicuratevi di passare `data: {...}` (non `variables: {...}`, non `params: {...}` — solo `data` è riconosciuto). + +### Riferimenti tecnici + +- File: `agile-services/email-automation-ms/src/services/emailService.js` + `src/index.js` +- Commit: `809ea53` (branch `feature/marketing-multichannel-ai`) +- Pattern canonico CLAUDE.md AgileServices §"REGOLA: Invio email — SOLO via email-automation-ms" + +--- + +## 2. PHP opcache USR2 + disciplina commit (prodotti PHP-FPM) + +> Già inviato a NIS2 il 30/5 ma ribroadcast a tutti i PHP-FPM per direttiva utente "in tutti i dev". + +### Hot-reload: `kill -USR2 1` dopo OGNI edit `.php` + +I prodotti PHP della suite girano con `opcache.validate_timestamps=Off` in produzione: opcache **NON rilegge i file da disco** anche se il bind-mount li ha aggiornati → il vecchio bytecode resta in cache e gli utenti vedono ancora la versione precedente. + +**Soluzione operativa** (graceful FPM reload, zero downtime, ~10ms): +```bash +docker exec kill -USR2 1 +``` + +**Pattern per ogni modifica PHP**: +``` +1. edit file.php (bind-mount filesystem -> sempre live) +2. docker exec kill -USR2 1 <-- ESSENZIALE: bytecode rilegge +3. smoke: curl https:/// -> conferma versione nuova +4. commit + push (vedi sotto) +``` + +**Quando applicare**: ogni edit `.php`; non serve per file statici (CSS/JS/HTML serviti da nginx/apache) o config JSON parsati a runtime. In dubbio → fai USR2 (costa poco). + +### Disciplina commit-early — non lasciare WIP scoperti + +Il cron `ticket-agent-cron.sh` (ogni 2 min sull'host) può lanciare `claude -p` nel container, che modifica file, committa, e **può rebasare/revertare working tree con changes scoperte**. **Caso reale NIS2 29/5**: commit automatico `d5d83bb` ha revertato `index.php` di una Feature 1 non committata → persa, da rifare. + +**Mitigazione**: +- Commit appena una modifica funziona (smoke verde post-USR2): `git add && git commit -m "[FEAT|FIX|DOCS] descrizione"`. +- WIP multi-step → branch dedicato. +- Lavoro attivo prolungato → semaforo manuale (il cron salta i container con quel lock): + ```bash + echo "USER=cristiano STARTED=$(date -Iseconds)" > /tmp/agent-working.lock + # ... lavori ... + rm /tmp/agent-working.lock + ``` + +### Git push senza credential-cache (post-reboot container) + +Container dev legacy (non ancora migrati all'helper credenziali vault, oggi solo `trpg-agile` è migrato): dopo un restart la `git credential-cache` in-memory è vuota → `git push` chiede il PAT Gitea interattivo. + +**Workaround senza `git-login`**: chiedere a AgileHub-side di pushare dall'host (l'host ha l'helper vault): +> "VIGILE, ha N commit su main da pushare, fallo tu dall'host" + +Fix definitivo per ogni dev container = migrazione vault helper, pattern `trpg-agile` documentato in CLAUDE.md AgileServices §"GIT PUSH: Vault-Backed Credential Helper" (richiede recreate container in finestra di manutenzione). + +--- + +## Cosa devono fare le sessioni Claude di ogni dev container + +1. **Leggere questo doc al boot** (sarà copiato in `docs/INCOMING_FROM_AGILEHUB_2026_05_31_*.md` del vostro repo). +2. **Aggiungere/aggiornare la sezione nel vostro `CLAUDE.md`** che riassume le 3 regole d'oro (per prodotti PHP) e il payload canonico email (per tutti). +3. **Aggiornare i client email** che inviano via `/emails/send`: passare al payload canonico (template+data **oppure** body raw, oppure migrazione a `/emails/send-raw` con `html`). +4. **Riferire problemi/dubbi** con un `INCOMING_FROM__...` doc nel pattern cross-suite, o tramite l'utente in chat. + +--- + +**Fine documento.** Lavorate sicuri.