
# Présentation des formulaires

Les formulaires recueillent les saisies des contributeurs et les acheminent vers une destination utile — dans une table, via une automatisation, dans le registre de soumissions intégré, ou n'importe quelle combinaison des trois. Ils sont déclarés dans le tableau de premier niveau `forms`, chacun accessible à sa propre URL, intégrable dans une page et adressable depuis un déclencheur d'automatisation.

Un formulaire est le pendant public d'une table : là où une table définit _à quoi_ ressemblent les données, un formulaire définit _comment_ les gens y contribuent. Le même formulaire peut écrire directement dans une entrée `tables[]`, déclencher une automatisation `notify-sales`, ou simplement atterrir dans le registre `form_submissions` de la plateforme pour une révision ultérieure.

```yaml
forms:
  - id: 1
    name: contact
    title: Contact Sales
    path: /contact
    submitTo:
      table: leads
    fields:
      - { kind: table-field, column: email, required: true }
      - { kind: table-field, column: message }
```

## Propriétés du formulaire

Chaque entrée du tableau `forms` accepte les propriétés suivantes.

| Propriété      | Description                                                                                                                                                                                                         |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`           | Entier positif unique identifiant le formulaire. Doit être unique dans `forms[]`.                                                                                                                                   |
| `name`         | Identifiant unique en kebab-case (`^[a-z][a-z0-9-]*`, 1 à 64 caractères). Référencé par les composants de page (`formRef`) et le déclencheur d'automatisation de formulaire. Doit être unique dans `forms[]`.       |
| `title`        | Titre lisible affiché aux contributeurs. Prend en charge les clés i18n `$t:`.                                                                                                                                       |
| `description`  | Paragraphe d'introduction optionnel affiché au-dessus du premier champ.                                                                                                                                             |
| `path`         | URL publique conviviale optionnelle (par ex. `/contact`). Lorsqu'elle est définie, le formulaire est servi à cet emplacement _et_ à la route canonique `/forms/{name}`. Voir [Routes publiques](#routes-publiques). |
| `submitTo`     | Où la soumission est persistée et/ou acheminée : une table, une automatisation, le registre, ou une combinaison. Obligatoire. Voir [Cibles de soumission](#cibles-de-soumission).                                   |
| `fields`       | Liste ordonnée de définitions de champs affichés dans le formulaire. Au moins un requis. Voir [Champs de formulaire](/fr/docs/form-fields).                                                                         |
| `layout`       | Mode de rendu : `single-page` (par défaut), `multi-step` ou `one-question`. Voir [Formulaires multi-étapes](/fr/docs/form-multi-step).                                                                              |
| `steps`        | Définitions d'étapes pour les mises en page `multi-step` / `one-question`. Voir [Formulaires multi-étapes](/fr/docs/form-multi-step).                                                                               |
| `fieldGroups`  | Séparateurs de section libellés regroupant les champs au sein d'une mise en page sur une seule page.                                                                                                                |
| `display`      | Options cosmétiques (colonnes, barre de progression, libellé du bouton de soumission, thème par formulaire). Voir [Formulaires multi-étapes](/fr/docs/form-multi-step).                                             |
| `access`       | Contrôle d'accès : `all`, `authenticated`, ou une liste de rôles, avec un `redirectTo` optionnel. Voir [Contrôle d'accès](#contrôle-daccès).                                                                        |
| `availability` | Fenêtre de soumission (`opensAt`, `closesAt`) et plafond de soumissions (`maxSubmissions`), avec une page de formulaire fermé personnalisée optionnelle.                                                            |
| `antiSpam`     | Pot de miel, limites de débit à fenêtre glissante, et un stub de connexion CAPTCHA.                                                                                                                                 |
| `analytics`    | Désactivation par formulaire (`enabled: false`) excluant le formulaire des analyses agrégées. Activé par défaut.                                                                                                    |
| `prefill`      | Mappage champ de formulaire → référence `$query.{name}` / `$user.{prop}` / `$parent.{path}` ou valeur littérale par défaut. Voir [Champs de formulaire](/fr/docs/form-fields).                                      |
| `submitter`    | Règles d'enregistrement-et-reprise, de modification-après-soumission et de soumission unique.                                                                                                                       |
| `onSuccess`    | Comportement post-soumission (page de succès, redirection, réinitialisation, toast, message en ligne). Voir [Soumissions](/fr/docs/form-submissions).                                                               |
| `onError`      | Ce qu'il faut afficher quand une soumission échoue côté serveur (toast, message en ligne, page d'erreur). Voir [Soumissions](/fr/docs/form-submissions).                                                            |

## Cibles de soumission

L'objet `submitTo` découple un formulaire de tout modèle de persistance unique. Au moins l'un de `table`, `automation`, ou `storeSubmission: true` (la valeur par défaut) doit être défini — sinon la soumission serait silencieusement rejetée et le schéma rejette la configuration.

| Propriété         | Description                                                                                                                                                                                                                                  |
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `table`           | Persiste la soumission comme un enregistrement dans cette table. Référence un `tables[].name` ; validé par rapport au tableau `tables[]` de l'application.                                                                                   |
| `automation`      | Invoque cette automatisation _après_ la validation des écritures. Référence un `automations[].name` ; validé par rapport au tableau `automations[]` de l'application.                                                                        |
| `mapping`         | Mappe les noms de champs de formulaire vers les noms de colonnes de destination. Par défaut l'identité (nom du champ de formulaire = nom de la colonne de table). Une cible de mappage qui n'existe pas sur la table échoue à la validation. |
| `storeSubmission` | Persiste la soumission dans le registre intégré `form_submissions`. Vaut `true` par défaut — définissez `false` pour vous désinscrire (et alors `table` ou `automation` devient obligatoire).                                                |

```yaml
submitTo:
  table: support_tickets
  automation: page-on-call
  mapping:
    userEmail: email # form field 'userEmail' -> table column 'email'
```

:::callout
**Tables, automatisations, le registre — ou les trois.** Un formulaire peut écrire en double dans une `table` et le registre, déclencher une automatisation, ou tout faire à la fois. L'écriture dans la table et l'écriture dans le registre se produisent au sein d'une seule transaction ; l'automatisation ne s'exécute qu'après la validation des deux. Voir [Soumissions](/fr/docs/form-submissions) pour le contrat complet d'écriture double.
:::

## Routes publiques

Chaque formulaire est accessible à la route canonique `/forms/{name}` quelle que soit la configuration — un formulaire sans `path` n'est pas privé, il est simplement uniquement accessible à cet emplacement. Lorsque `path` est défini, le formulaire est servi à ce chemin personnalisé **et** à `/forms/{name}` simultanément (pas de redirection ; les deux URL affichent le même formulaire).

| Règle               | Description                                                                                                                                         |
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| Route canonique     | `/forms/{name}` sert toujours le formulaire (HTTP 200). Un nom inconnu renvoie 404.                                                                 |
| Chemin personnalisé | Optionnel. Doit commencer par `/`, 2 à 256 caractères compatibles URL ; statique (pas de segments dynamiques `:id`).                                |
| Préfixes réservés   | `/api/`, `/admin/`, `/forms/` et `/auth/` sont rejetés afin qu'un formulaire ne puisse pas masquer une route intégrée.                              |
| Règle de collision  | Un `forms[].path` NE DOIT PAS entrer en collision avec un `pages[].path`. Les collisions échouent à la validation avec une erreur nommant les deux. |
| Route d'intégration | `/forms/{name}/embed` sert une coquille HTML minimale pour l'intégration en iframe sur des sites tiers.                                             |

## Contrôle d'accès

L'objet `access` réutilise le modèle de permission partagé employé par les tables, les pages, les buckets, les automatisations et les agents.

| Propriété    | Description                                                                                                                                  |
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `require`    | `'all'` (tout le monde, y compris anonyme), `'authenticated'` (tout utilisateur connecté), ou une liste de rôles (`['admin', 'editor']`).    |
| `redirectTo` | Chemin optionnel (par ex. `/login`) vers lequel rediriger les contributeurs refusés, au lieu de renvoyer un 401/403. Doit commencer par `/`. |

```yaml
forms:
  - id: 2
    name: member-survey
    title: Member Survey
    access:
      require: authenticated
      redirectTo: /login
    submitTo: { table: survey_responses }
    fields:
      - { kind: standalone, name: rating, inputType: rating, required: true }
```

:::callout
**Les références `$user.*` nécessitent une authentification.** Un formulaire dont `access.require` vaut `'all'` (la valeur par défaut) ne peut pas porter de `defaultValue` par champ référençant `$user.*` — la valeur se résoudrait toujours à vide pour les visiteurs anonymes et pourrait divulguer l'état de session. Définissez `access.require` à `authenticated` ou une liste de rôles, ou utilisez le `prefill` de premier niveau (qui ignore silencieusement les références `$user` non résolvables sur les formulaires publics). Voir [Champs de formulaire](/fr/docs/form-fields).
:::

## Intégrer un formulaire dans une page

Un formulaire de premier niveau peut être affiché en ligne dans une page via le `formRef` du contrôle de formulaire. Le formulaire est défini une fois et réutilisé n'importe où — les champs, la validation, la logique conditionnelle, la mise en page multi-étapes, les téléversements de fichiers, et `onSuccess`/`onError` proviennent tous de `app.forms[]`. Le contrôle d'accès de la page hôte est croisé avec les propres règles du formulaire au moment du rendu.

```yaml
pages:
  - id: 1
    name: landing
    path: /
    components:
      - type: form
        formRef: contact # renders the top-level "contact" form inline
        props:
          label: Get in touch # display-only override of the submit label
```

Voir [Contrôles de formulaire](/fr/docs/form-controls) pour le côté composant de page de `formRef`.

## Pages associées

- [Champs de formulaire](/fr/docs/form-fields) — champs autonomes vs liés à une table, préremplissage, création de relation en ligne.
- [Logique conditionnelle](/fr/docs/form-conditional-logic) — règles visible / requis / désactivé.
- [Formulaires multi-étapes](/fr/docs/form-multi-step) — étapes, branchement, mises en page une question, surcharges d'affichage.
- [Soumissions](/fr/docs/form-submissions) — le registre d'écriture double, la gestion du succès et des erreurs.
- [Téléversements de fichiers](/fr/docs/form-file-uploads) — champs de pièce jointe adossés à des buckets.
- [Présentation des tables](/fr/docs/tables-overview) — les modèles de données dans lesquels les formulaires écrivent.
- [Contrôles de formulaire](/fr/docs/form-controls) — intégrer un formulaire dans une page.
- [Authentification](/fr/docs/auth-overview) — rôles et authentification derrière `access`.
