Regole per chi scrive codice che usa questo pacchetto. Sono i punti su cui si sbaglia sistematicamente: leggerle prima di scrivere l'integrazione fa risparmiare un giro di debug.
php artisan boost:add-skill iltuostudiodigitale/crm-connector
Save this content to: AGENTS.md
# Istruzioni per agenti AI
Regole per chi scrive codice che usa questo pacchetto. Sono i punti su cui si sbaglia
sistematicamente: leggerle prima di scrivere l'integrazione fa risparmiare un giro di debug.
## Non aggirare il contratto
- Costruisci sempre la submission con `CrmContactData`. Non fare mai una `Http::post()`
a mano verso l'endpoint del CRM: la validazione del pacchetto è l'unico motivo per cui
esiste.
- Se un campo non è nella tabella del contratto del README, **non esiste** come campo di
primo livello: il server scarta tutto ciò che non riconosce. Quello che il contratto non
prevede va dentro `custom`, che è fatto apposta.
- Per un questionario: `form_name` con il nome del modulo, e tutte le risposte dentro
`custom`. Non inventare campi di primo livello per le domande, e non concatenare le
risposte dentro `message`.
- Dentro `custom` un `null` significa «risposta lasciata in bianco»: non filtrarlo via.
- Il sito non invia mai: indirizzo IP, user agent, sito di provenienza, note interne.
Li determina il gestionale.
## `form_name` è obbligatorio e non va improvvisato
- Va valorizzato su **ogni** invio, anche per un modulo di contatto banale.
- Il modo consigliato è un campo nascosto nel form
(`<input type="hidden" name="form_name" value="…">`), non una stringa decisa al volo
nel controller.
- È la chiave con cui il gestionale raggruppa i dati e non esiste un elenco dei moduli:
**usa sempre la stessa identica scrittura** per lo stesso modulo. Non variarla fra un
invio e l'altro, non aggiungerci date o contatori, non generarla dinamicamente da titoli
di pagina o URL.
- Cambia il nome solo quando il modulo cambia in modo incompatibile (domande riscritte),
mai per motivi cosmetici.
## Il consenso privacy è un consenso, non un campo tecnico
- `privacy_accepted` deve venire da una checkbox realmente spuntata dall'utente.
- **Non passarlo mai hardcoded a `true`** per far passare la validazione. È l'errore più
frequente e l'unico con conseguenze legali: senza consenso reale il dato non va raccolto.
- Se la validazione fallisce su questo campo, la correzione è nel form, non nel payload.
## Il secret sta sul server
- `CRM_CLIENT_SECRET` non va mai in codice frontend, in una variabile esposta al browser,
in un file compilato dal bundler o in una pagina.
- Se il form è inviato da JavaScript, la richiesta deve passare da un controller del sito,
che poi chiama `Crm::submit()`. Il browser non parla mai direttamente con il CRM.
## Ogni modulo è protetto dallo spam
- Ogni modulo che arriva a `Crm::submit()` ha `<x-crm-connector::form-guard />` dentro il
`<form>` e, nel controller, `FormGuard::allows($request)` **prima** di qualunque invio:
se è falso si risponde come se fosse andato tutto bene e non si invia nulla.
- `allows()` è l'unico punto di controllo, anche con un FormRequest. Quando Turnstile non
conferma solleva una `ValidationException` sul campo `cf-turnstile-response`: lasciala
arrivare al modulo (o passala al gruppo di errori del modulo), non trasformarla in un
successo finto. Il token vale una volta sola: si torna al modulo con un redirect.
- Non aggiungere reCAPTCHA né altri captcha, non caricare lo script di Cloudflare nel
layout: lo carica il componente quando qualcuno tocca il modulo.
- Non reimplementare campo nascosto, tempo minimo o controllo dei link nel sito: sono qui.
Se un campo può contenere un link legittimo, passalo in `allows($request, ['campo'])`.
- Le chiavi stanno in `TURNSTILE_SITE_KEY` e `TURNSTILE_SECRET_KEY` e si leggono da
`config('crm-connector.turnstile.*')`. La secret key non va mai nella pagina.
- Il limite per IP (`throttle`) sulla rotta del modulo resta: è un'altra protezione.
## Errori: cosa ritentare e cosa no
- `422` è un errore di dati. **Non ritentare**: leggi `->errors` e correggi il form. Il
client ripete da solo solo gli errori di rete e i `5xx`.
- `401` è gestito dal client, che rinnova il token da solo. Non reimplementare il refresh
e non cachare il token a mano.
- `403` significa sito disattivato o header `Origin` non consentito: è una configurazione
da sistemare nel gestionale, non un problema di codice.
- `429` è il rate limit: rallenta, non moltiplicare i tentativi.
## Configurazione
- Le credenziali si leggono solo da `config('crm-connector.*')`, mai da `env()` diretto
nel codice applicativo: con la config cache `env()` restituisce `null` in produzione.
Regole per chi scrive codice che usa questo pacchetto. Sono i punti su cui si sbaglia sistematicamente: leggerle prima di scrivere l'integrazione fa risparmiare un giro di debug.
CrmContactData. Non fare mai una Http::post()
a mano verso l'endpoint del CRM: la validazione del pacchetto è l'unico motivo per cui
esiste.custom, che è fatto apposta.form_name con il nome del modulo, e tutte le risposte dentro
custom. Non inventare campi di primo livello per le domande, e non concatenare le
risposte dentro message.custom un null significa «risposta lasciata in bianco»: non filtrarlo via.form_name è obbligatorio e non va improvvisato<input type="hidden" name="form_name" value="…">), non una stringa decisa al volo
nel controller.privacy_accepted deve venire da una checkbox realmente spuntata dall'utente.true per far passare la validazione. È l'errore più
frequente e l'unico con conseguenze legali: senza consenso reale il dato non va raccolto.CRM_CLIENT_SECRET non va mai in codice frontend, in una variabile esposta al browser,
in un file compilato dal bundler o in una pagina.Crm::submit(). Il browser non parla mai direttamente con il CRM.Crm::submit() ha <x-crm-connector::form-guard /> dentro il
<form> e, nel controller, FormGuard::allows($request) prima di qualunque invio:
se è falso si risponde come se fosse andato tutto bene e non si invia nulla.allows() è l'unico punto di controllo, anche con un FormRequest. Quando Turnstile non
conferma solleva una ValidationException sul campo cf-turnstile-response: lasciala
arrivare al modulo (o passala al gruppo di errori del modulo), non trasformarla in un
successo finto. Il token vale una volta sola: si torna al modulo con un redirect.allows($request, ['campo']).TURNSTILE_SITE_KEY e TURNSTILE_SECRET_KEY e si leggono da
config('crm-connector.turnstile.*'). La secret key non va mai nella pagina.throttle) sulla rotta del modulo resta: è un'altra protezione.422 è un errore di dati. Non ritentare: leggi ->errors e correggi il form. Il
client ripete da solo solo gli errori di rete e i 5xx.401 è gestito dal client, che rinnova il token da solo. Non reimplementare il refresh
e non cachare il token a mano.403 significa sito disattivato o header Origin non consentito: è una configurazione
da sistemare nel gestionale, non un problema di codice.429 è il rate limit: rallenta, non moltiplicare i tentativi.config('crm-connector.*'), mai da env() diretto
nel codice applicativo: con la config cache env() restituisce null in produzione.How can I help you explore Laravel packages today?