
# Disponibilité des formulaires

Les inscriptions ouvrent lundi. L'atelier compte quarante places. L'enquête ferme à la fin du trimestre. Chacune de ces phrases est une règle sur le _moment_ où un formulaire accepte des réponses, et chacune devient sinon un rappel d'agenda pour aller modifier la configuration à la main.

`availability` énonce la règle une fois et laisse le serveur l'appliquer :

```yaml
forms:
  - id: 1
    name: workshop-signup
    title: Spring Workshop
    submitTo: { table: registrations }
    availability:
      opensAt: '2026-03-01T09:00:00Z'
      closesAt: '2026-03-20T23:59:59Z'
      maxSubmissions: 40
    fields:
      - { kind: table-field, column: email, required: true }
```

## Propriétés de disponibilité

Toutes les propriétés sont optionnelles. Omettez le bloc et le formulaire est ouvert, indéfiniment, sans plafond.

| Propriété        | Description                                                                                 | Défaut                   |
| ---------------- | ------------------------------------------------------------------------------------------- | ------------------------ |
| `opensAt`        | Horodatage ISO 8601 à partir duquel le formulaire accepte les soumissions.                  | Ouvert immédiatement.    |
| `closesAt`       | Horodatage ISO 8601 auquel il cesse de les accepter.                                        | Ne ferme jamais.         |
| `maxSubmissions` | Plafond, entier positif. La soumission suivant le plafond est refusée.                      | Illimité.                |
| `closedPage`     | Page personnalisée affichée tant que le formulaire est fermé, pour l'une des trois raisons. | Titre + texte générique. |

Lorsque les deux horodatages sont définis, `opensAt` doit être strictement antérieur à `closesAt`. Une fenêtre qui ferme avant d'ouvrir n'accepte rien et relève presque toujours de la faute de frappe : elle échoue au décodage de la configuration, avec un message nommant le formulaire et les deux horodatages.

## Ce que répond un formulaire fermé

Ouvrir un formulaire fermé n'est pas une erreur — le visiteur reçoit une page qui explique la situation. Y envoyer une soumission est refusé avec un corps structuré, pour qu'un client programmatique distingue les trois cas.

| État             | `GET /forms/{name}`     | Statut `POST` | Corps d'erreur                                                        |
| ---------------- | ----------------------- | ------------- | --------------------------------------------------------------------- |
| Avant `opensAt`  | Page de fermeture       | `403`         | `{ error: 'form not yet open', opensAt }`                             |
| Après `closesAt` | Page de fermeture       | `403`         | `{ error: 'form closed', closedAt }`                                  |
| Plafond atteint  | Le formulaire s'affiche | `403`         | `{ error: 'submission limit reached', maxSubmissions, currentCount }` |

Une soumission refusée n'écrit rien — pas de ligne de registre, pas de ligne de table, pas d'exécution d'automatisation.

## La page de fermeture

Sans configuration, la page de fermeture affiche le titre du formulaire et une phrase expliquant qu'il n'est pas encore ouvert (en citant `opensAt`) ou qu'il n'accepte plus de réponses. `closedPage` remplace cela par votre propre texte et, si vous le souhaitez, une porte de sortie :

```yaml
availability:
  closesAt: '2026-03-20T23:59:59Z'
  closedPage:
    title: Registration has closed
    message: Spring places are full. The autumn cohort opens in July.
    cta:
      label: Join the waiting list
      href: /waiting-list
```

| Propriété   | Description                                                 | Défaut                                  |
| ----------- | ----------------------------------------------------------- | --------------------------------------- |
| `title`     | Titre de la page.                                           | Le `title` du formulaire.               |
| `message`   | Texte du corps.                                             | Explication par défaut selon la raison. |
| `cta.label` | Libellé du lien. Exige `cta.href`.                          | Aucun lien.                             |
| `cta.href`  | Cible du lien. Exige `cta.label`.                           | Aucun lien.                             |
| `type`      | Discriminant réservé ; seule la valeur `page` est acceptée. | `page`                                  |

La même page sert les trois états de fermeture : rédigez un texte qui se lit correctement aussi bien avant l'ouverture qu'une fois les places épuisées.

:::callout
**Seules les vraies soumissions consomment une place du plafond.** Une soumission rejetée comme indésirable — pot de miel déclenché, limite de débit dépassée — et une soumission qui a échoué en aval ne comptent jamais dans `maxSubmissions`. Un robot ne peut pas épuiser vos quarante places d'atelier en rafale, et une écriture ratée ne coûte pas discrètement sa place à un inscrit légitime. Le plafond est en outre appliqué de façon atomique : des soumissions concurrentes se disputant les dernières places ne peuvent pas le dépasser.
:::

## Pages associées

- [Anti-spam et attribution](/fr/docs/form-anti-spam) — la classification indésirable exclue du plafond.
- [Contrôle d'accès](/fr/docs/form-access) — l'autre raison pour laquelle un formulaire peut refuser un contributeur.
- [Soumissions](/fr/docs/form-submissions) — le statut de registre qu'une soumission refusée ne crée _pas_.
- [Présentation des formulaires](/fr/docs/forms-overview) — la place de `availability` dans le schéma complet.
