Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message
Agents
iltuostudiodigitale/crm-connector
claude-code
cursor
crm-integration
form-validation
privacy-consent
server-side-secrets
spam-protection
custom-fields
form-name

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.

Install
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.

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.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast