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 <noreply@anthropic.com>
This commit is contained in:
parent
54576119f3
commit
34bac1a237
30
CLAUDE.md
30
CLAUDE.md
@ -25,6 +25,36 @@
|
||||
**Spec completa**: `STANDARD_TIMEZONE_CONVENTIONS.md` (slug `timezone-conventions` v1.0, owner VIGILE).
|
||||
<!-- STANDARD:timezone-conventions:v1.0:end -->
|
||||
|
||||
## 🔴 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 <container-fpm-prodotto> 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.
|
||||
|
||||
@ -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: "<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: <chiave>
|
||||
{
|
||||
"to": "user@example.com",
|
||||
"template": "demo-registration-verify",
|
||||
"data": { "name": "Mario", "verify_url": "..." },
|
||||
"product": "<TUO_PRODOTTO>",
|
||||
"tenantId": <N>
|
||||
}
|
||||
```
|
||||
|
||||
**Caso B — HTML grezzo** (per email one-off, alert, ecc.) — usare **`/emails/send-raw`**:
|
||||
```bash
|
||||
POST /api/emails/send-raw
|
||||
X-Internal-Key: <chiave>
|
||||
{
|
||||
"to": "user@example.com",
|
||||
"subject": "Oggetto",
|
||||
"html": "<html><body><p>Contenuto</p></body></html>",
|
||||
"product": "<TUO_PRODOTTO>",
|
||||
"tenantId": <N>
|
||||
}
|
||||
```
|
||||
|
||||
**Per envelope From per-tenant** (opzionale, multi-tenant):
|
||||
```json
|
||||
{
|
||||
"from": "noreply@<firm-slug>.agile.software",
|
||||
"fromName": "<Tenant Display Name>",
|
||||
"replyTo": "supporto@<firm-slug>.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 <container-fpm-prodotto> kill -USR2 1
|
||||
```
|
||||
|
||||
**Pattern per ogni modifica PHP**:
|
||||
```
|
||||
1. edit file.php (bind-mount filesystem -> sempre live)
|
||||
2. docker exec <container-fpm> kill -USR2 1 <-- ESSENZIALE: bytecode rilegge
|
||||
3. smoke: curl https://<dominio>/<endpoint> -> 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 <file> && 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, <prodotto> 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_<PRODOTTO>_...` doc nel pattern cross-suite, o tramite l'utente in chat.
|
||||
|
||||
---
|
||||
|
||||
**Fine documento.** Lavorate sicuri.
|
||||
Loading…
Reference in New Issue
Block a user