docs(state): Coolify configurato + mailer verificato; deploy fermo sul record DKIM
- RESEND_API_KEY e RESEND_FROM create su Coolify (production + preview)
- sendEmail() verificato con il template OTP reale: {ok:true}
- unico blocco residuo: TXT resend._domainkey.iamcavalli.net ha una chiave
vecchia, dominio Resend status=failed, invio dal dominio rifiutato 403
- valore DKIM corretto e sequenza di ripresa annotati in STATE.md
- note API Coolify: envs non accetta is_build_time (422)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+34
-13
@@ -3,9 +3,9 @@ gsd_state_version: 1.0
|
||||
milestone: v2.3
|
||||
milestone_name: Email & Accesso
|
||||
status: executing
|
||||
stopped_at: "v2.3 implementata e testata in locale; deploy BLOCCATO su RESEND_API_KEY + whitelist clienti"
|
||||
last_updated: "2026-07-28T20:45:00.000Z"
|
||||
last_activity: 2026-07-28 -- Phases 23/24/25 (OTP gate) implementate e verificate E2E; non ancora pushate
|
||||
stopped_at: "v2.3 pronta e Coolify configurato; deploy BLOCCATO sul record DKIM di iamcavalli.net (chiave vecchia)"
|
||||
last_updated: "2026-07-29T15:45:00.000Z"
|
||||
last_activity: 2026-07-29 -- Coolify configurato + mailer verificato; deploy fermo sul record DKIM (azione utente)
|
||||
progress:
|
||||
total_phases: 3
|
||||
completed_phases: 3
|
||||
@@ -31,13 +31,32 @@ Plan: `~/.claude/plans/si-ma-abbiamo-un-jaunty-micali.md`
|
||||
Status: **Bloccata sul deploy**, non sul codice. Vedi "Blocchi al deploy" qui sotto.
|
||||
Last activity: 2026-07-28 — gate OTP completo, 9/9 test E2E passati contro il DB di produzione
|
||||
|
||||
### ⛔ Blocchi al deploy (2026-07-28)
|
||||
### ⛔ Unico blocco residuo al deploy: record DKIM (2026-07-29)
|
||||
|
||||
Pushare così com'è **chiude fuori i clienti reali dal loro portale**. Prima del push servono, in quest'ordine:
|
||||
**Il record DKIM di `iamcavalli.net` contiene una chiave vecchia**, diversa da quella che Resend si aspetta → dominio `status: failed`, invio da `no-reply@iamcavalli.net` rifiutato con 403. SPF (TXT + MX su `send`) sono verificati, solo il DKIM no.
|
||||
|
||||
1. **`RESEND_API_KEY` + `RESEND_FROM` su Coolify** (production). Senza, nessuno riceve il codice e il portale è inaccessibile a tutti. Serve un account Resend con dominio verificato. In `.env.local` i due nomi ci sono ma il valore della key è vuoto.
|
||||
2. **Whitelist popolata per i 3 clienti reali.** La migration ha seedato `client_emails` da `clients.email`, ma solo 1 cliente su 4 aveva quel campo valorizzato (`mario@test.it`, cliente di test "Rossi Inc"). George Vlad / Protocollo Estetico, Gian Luca Caruso / Caruso Speaker e Gianfranco Barban / Teckell hanno **whitelist vuota** → gate senza via d'uscita. Da fare da `/admin/clients/<id>` → sezione "Accessi al portale".
|
||||
3. Solo dopo: push su `main` → auto-deploy Coolify → riverifica su `hub.iamcavalli.net`.
|
||||
Da sostituire — TXT, nome `resend._domainkey`:
|
||||
|
||||
```
|
||||
p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDFHKhBLdT31CDeh5R0MWQM1XRmxwQrXS6TJXNa1Id9KP+nDPree4EWvTal7o440MUp4vwbW07AONoNjuIT8gMaC3a+e4396kQ9ewUpApa26azNf4k1092N6kSfNhfmU+oM5c/VYFEuPqp0yf1ar3M8w8WA4BELL4VBq29xk4/m4QIDAQAB
|
||||
```
|
||||
|
||||
Finché non è sistemato, deployare renderebbe il portale inaccessibile a **tutti** i clienti (nessuno riceve il codice). Decisione dell'utente il 2026-07-29: **non pushare, si aspetta il DNS.** I token Hetzner/Cloudflare in `~/.coolify.env` sono vuoti → il DNS lo cambia l'utente a mano.
|
||||
|
||||
Sequenza alla ripresa:
|
||||
|
||||
1. Verificare propagazione: `dig +short TXT resend._domainkey.iamcavalli.net @8.8.8.8` deve restituire la chiave che inizia per `p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDFHKhB…`
|
||||
2. Ri-triggerare la verifica su Resend e controllare `status: verified` (`GET /domains/a2a80798-6f3a-42fe-8946-2c7f40f32c03`).
|
||||
3. Test d'invio dal dominio reale verso un indirizzo qualsiasi.
|
||||
4. Push su `main` → auto-deploy Coolify.
|
||||
5. Popolare la whitelist dei 3 clienti reali da `/admin/clients/<id>` → "Accessi al portale". L'utente ha detto che li re-invita, quindi non è bloccante: la migration ha seedato solo `mario@test.it` (cliente di test "Rossi Inc"), mentre Protocollo Estetico, Caruso Speaker e Teckell partono con whitelist vuota.
|
||||
6. Riverifica su `hub.iamcavalli.net`.
|
||||
|
||||
**Già fatto (2026-07-29):**
|
||||
|
||||
- `RESEND_API_KEY` + `RESEND_FROM` **configurate su Coolify** (production e preview) via API — verificate presenti.
|
||||
- **Mailer verificato funzionante**: `sendEmail()` con il template OTP reale ha restituito `{ok:true, id:…}` e Resend ha accettato l'email (consegna confermata verso `info@iamcavalli.net` usando `onboarding@resend.dev`, l'unica coppia mittente/destinatario permessa senza dominio verificato).
|
||||
- Verificato che quando Resend rifiuta, la route risponde comunque con il messaggio neutro e logga l'errore lato server — il comportamento no-enumeration tiene anche a provider guasto.
|
||||
|
||||
### Cosa è stato consegnato in v2.3 (codice locale, buildato e testato)
|
||||
|
||||
@@ -119,8 +138,10 @@ None yet.
|
||||
|
||||
### Blockers/Concerns
|
||||
|
||||
- **[BLOCCANTE] `RESEND_API_KEY` + `RESEND_FROM` su Coolify** — senza, il gate OTP deployato rende il portale inaccessibile a tutti i clienti. Stessa procedura di `ANTHROPIC_API_KEY` (2026-06-20). Serve un account Resend con dominio verificato.
|
||||
- **[BLOCCANTE] Whitelist vuota per 3 clienti su 4** — vedi "Blocchi al deploy". Da popolare da `/admin/clients/<id>` prima del push.
|
||||
- **[BLOCCANTE] Record DKIM di `iamcavalli.net` con chiave vecchia** — vedi "Unico blocco residuo al deploy". Finché non è corretto, nessun invio dal dominio è possibile e deployare il gate chiuderebbe fuori tutti i clienti.
|
||||
- ~~`RESEND_API_KEY` + `RESEND_FROM` su Coolify~~ — **fatto 2026-07-29**, production e preview.
|
||||
- **Whitelist vuota per 3 clienti su 4** (non bloccante: l'utente li re-invita) — da popolare da `/admin/clients/<id>` → "Accessi al portale".
|
||||
- **Coolify API**: credenziali in `~/.coolify.env` (`export COOLIFY_URL/COOLIFY_TOKEN`, va sorgentato con `set -a; . ~/.coolify.env`). App ClientHub uuid `xsksow44g4kcoo8wocsgkscc`. Il POST su `/api/v1/applications/<uuid>/envs` **non accetta** il campo `is_build_time` (422): mandare solo `key`, `value`, `is_preview`. I token Hetzner/Cloudflare nel file sono **vuoti** → il DNS non è modificabile via API.
|
||||
- **Migrations (sempre valido)**: ogni fase con schema DEVE avere la migration applicata a prod PRIMA di pushare il codice dipendente. `drizzle-kit generate` rotto → SQL a mano. La 0015 è già applicata. Due strade: `cat migration.sql | ssh root@178.104.27.55 "docker exec -i xwkk0040w0kk0gsgcgog8owk psql -U clienthub -d clienthub -v ON_ERROR_STOP=1 --single-transaction"` (autoritativa, nessun tunnel), oppure tunnel `ssh -f -N -L 54321:localhost:54321 root@178.104.27.55` con `DATABASE_URL` riscritto a `127.0.0.1:54321` se serve puntarci il tooling locale.
|
||||
- **`.env.local` punta al DB di PRODUZIONE** (178.104.27.55:54321, richiede il tunnel). Non esiste un DB di sviluppo separato: qualsiasi test in locale scrive su dati reali. Verificare sempre i conteggi delle tabelle protette prima e dopo.
|
||||
- **Debito tecnico (non bloccante)**: tabelle legacy `service_catalog`/`offer_services`/`offer_micro_services` restano come deadweight; `createService`/`serviceSchema` dead code in `catalog/actions.ts`.
|
||||
@@ -141,7 +162,7 @@ Items acknowledged and carried forward from previous milestone close:
|
||||
|
||||
## Session Continuity
|
||||
|
||||
Last session: 2026-07-28T20:45:00.000Z
|
||||
Stopped at: v2.3 implementata e verificata E2E in locale (9/9). **Non pushata**: mancano `RESEND_API_KEY` su Coolify e la whitelist dei 3 clienti reali.
|
||||
Next: configurare Resend → popolare le whitelist → push su `main` → riverifica su `hub.iamcavalli.net`.
|
||||
Last session: 2026-07-29T15:45:00.000Z
|
||||
Stopped at: v2.3 implementata, verificata E2E (9/9) e mailer confermato funzionante. Coolify configurato. **Non pushata**: manca solo la correzione del record DKIM, che deve fare l'utente a mano.
|
||||
Next: `dig +short TXT resend._domainkey.iamcavalli.net @8.8.8.8` → verifica Resend → push su `main` → whitelist dei 3 clienti → riverifica su `hub.iamcavalli.net`.
|
||||
Resume file: .planning/STATE.md
|
||||
|
||||
Reference in New Issue
Block a user