# Configuration

> Chaque variable de la page de livraison, chaque clé du fichier de la CLI, chaque option de createBucket, et la forme des codes.

Canonical: https://colis-docs.vercel.app/docs/configuration · Markdown: https://colis-docs.vercel.app/docs/configuration.md

## La page de livraison

Le bucket se règle avec les variables que `@colis/core` lit déjà ; tout le reste est facultatif.

| Variable                     |  Requis  | Défaut                          | Effet                                                                                        |
| ---------------------------- | :------: | ------------------------------- | -------------------------------------------------------------------------------------------- |
| `COLIS_BUCKET`               |   oui    |                                 | Le nom du bucket.                                                                            |
| `COLIS_ENDPOINT`             |    R2    |                                 | Le point d’accès S3 du fournisseur. Vide pour AWS S3.                                        |
| `COLIS_REGION`               |          | `auto`                          | `auto` pour R2 et la plupart des fournisseurs ; une vraie région pour AWS et Scaleway.       |
| `AWS_ACCESS_KEY_ID`          |   oui    |                                 | La paire de clés. Sur AWS, un rôle peut la remplacer.                                        |
| `AWS_SECRET_ACCESS_KEY`      |   oui    |                                 |                                                                                              |
| `COLIS_PREFIX`               |          | `drop`                          | Le dossier du bucket où arrivent les colis. La règle de cycle de vie se pose dessus.         |
| `DROP_PASSWORD`              |          |                                 | Demandé avant chaque envoi. Le retrait ne le demande jamais. Sans lui : le mode ouvert.      |
| `DROP_EXPIRES_IN`            |          | `86400`                         | Durée de vie en secondes quand l’expéditeur ne choisit rien. Un jour.                        |
| `DROP_MAX_EXPIRES_IN`        |          | `604800`                        | La plus longue durée qu’un expéditeur peut choisir. Sept jours.                              |
| `DROP_MAX_SIZE_MB`           |          | `4`                             | Le plus gros fichier envoyé à travers la fonction. Vercel accepte 4,5 Mo par requête.        |
| `DROP_MAX_UPLOAD_MB`         |          | `2048`                          | Le plus gros fichier accepté. Au-delà de `DROP_MAX_SIZE_MB`, il va directement au bucket.    |
| `DROP_RAW_MODE`              |          | `stream`                        | `stream` fait passer les téléchargements par la fonction ; `redirect` les présigne.          |
| `DROP_PREVIEW`               |          | `true`                          | Montrer l’aperçu sur la page de retrait. `false` coupe aussi la route d’aperçu.              |
| `DROP_PREVIEW_MAX_MB`        |          | `16`                            | Le plus gros fichier dont on affiche un aperçu. Au-delà, la page le décrit.                  |
| `DROP_NAME`                  |          | `drop`                          | Le nom dans l’en-tête et le titre des pages.                                                 |
| `DROP_URL`                   |          | Vercel                          | L’adresse publique, pour les liens absolus. Le domaine de production Vercel sinon.           |
| `DROP_WEBHOOK_URL`           |          |                                 | Où partent les [webhooks](https://colis-docs.vercel.app/docs/webhooks). Plusieurs adresses séparées par des virgules.     |
| `DROP_WEBHOOK_SECRET`        | webhooks |                                 | Signe les webhooks. Obligatoire avec une adresse, 32 caractères au moins.                    |
| `DROP_UPLOADS_PER_HOUR`      |          | `20`                            | Mode ouvert : envois qu’une même adresse peut commencer par heure. Au-delà, `429`.           |
| `DROP_OPEN_MAX_UPLOAD_MB`    |          | `100`                           | Mode ouvert : le plus gros fichier accepté. Abaisse `DROP_MAX_UPLOAD_MB`, sans le relever.   |
| `DROP_OPEN_MAX_EXPIRES_IN`   |          | `86400`                         | Mode ouvert : la plus longue durée, en secondes. Abaisse `DROP_MAX_EXPIRES_IN`.              |
| `RESEND_API_KEY`             | comptes  |                                 | Active les [comptes](https://colis-docs.vercel.app/docs/compte) : la clé Resend qui envoie le lien de connexion.          |
| `COLIS_MAIL_FROM`            | comptes  |                                 | L’expéditeur de ce lien, `colis <connexion@votre-domaine>`, sur un domaine vérifié.          |
| `DROP_ACCOUNTS_PREFIX`       |          | `accounts`                      | Le dossier des comptes dans le bucket. Hors de portée de la règle de cycle de vie.           |
| `STRIPE_SECRET_KEY`          |   Pro    |                                 | Active la [formule Pro](https://colis-docs.vercel.app/docs/abonnement) : la clé secrète Stripe (`sk_…`). Jamais commitée. |
| `STRIPE_WEBHOOK_SECRET`      |   Pro    |                                 | Le secret de signature du webhook Stripe (`whsec_…`).                                        |
| `STRIPE_PRICE_MONTHLY`       |   Pro    |                                 | L’identifiant du prix mensuel créé dans Stripe (`price_…`).                                  |
| `STRIPE_PRICE_YEARLY`        |   Pro    |                                 | L’identifiant du prix annuel (`price_…`).                                                    |
| `DROP_PRO_MAX_UPLOAD_MB`     |          | `2048`                          | Formule Pro, mode ouvert : le plus gros fichier accepté.                                     |
| `DROP_PRO_MAX_EXPIRES_IN`    |          | `2592000`                       | Formule Pro, mode ouvert : la plus longue durée, en secondes. Trente jours.                  |
| `DROP_PRO_UPLOADS_PER_HOUR`  |          | `200`                           | Formule Pro, mode ouvert : envois par heure et par compte.                                   |
| `DROP_PRO_MONTHLY_LABEL`     |          | `6 €/mois`                      | Le prix mensuel tel que la page l’affiche. Le montant, lui, est chez Stripe.                 |
| `DROP_PRO_YEARLY_LABEL`      |          | `60 €/an`                       | Le prix annuel tel que la page l’affiche.                                                    |
| `NEXT_PUBLIC_COLIS_SITE_URL` |          | `https://colis-site.vercel.app` | Où l’en-tête, le pied de page et la page d’erreur renvoient vers colis. Lu au build.         |

Une durée par défaut plus longue que `DROP_MAX_EXPIRES_IN` est ramenée à ce maximum. Le formulaire
propose dix minutes, une heure, 6 h, 12 h, un jour, trois jours, sept jours, quatorze jours et trente
jours, dans la limite du maximum (celui de la formule de l’expéditeur), plus la durée par défaut.

`templates/drop/.env.example` reprend chaque variable avec un commentaire, et un bloc pour MinIO.

### Le mode ouvert

Sans `DROP_PASSWORD`, n’importe qui peut envoyer : le déploiement devient un service public, et trois
plafonds protègent le bucket et sa facture. Avec un mot de passe, aucun ne s’applique.

- **Envois par adresse** : `DROP_UPLOADS_PER_HOUR` (20) par heure d’horloge, comptés sur
  `POST /api/transfers` et au début d’un envoi en morceaux, un par fichier. Le suivant répond
  `429 RATE_LIMITED`, avec `retry-after` et un message qui dit dans combien de minutes réessayer.
- **Taille** : `DROP_OPEN_MAX_UPLOAD_MB` (100). Un fichier plus gros est refusé en `413 TOO_LARGE`
  avant l’envoi.
- **Durée de vie** : `DROP_OPEN_MAX_EXPIRES_IN` (86 400 secondes, un jour). Le formulaire ne propose
  rien de plus long.

Ce sont les limites de la formule gratuite. Un compte sur la [formule Pro](https://colis-docs.vercel.app/docs/abonnement) a les
siennes, `DROP_PRO_MAX_UPLOAD_MB`, `DROP_PRO_MAX_EXPIRES_IN` et `DROP_PRO_UPLOADS_PER_HOUR`, qui
ne descendent jamais sous celles de la formule gratuite. Quand le déploiement vend Pro, un envoi
gratuit qui dépasse la taille ou la durée, mais que Pro accepterait, est refusé en
`403 PLAN_LIMIT` plutôt qu’en `413` ou ramené en silence.

La page d’envoi affiche ces limites sous la zone de dépôt. Le compteur vit dans le bucket, sans base
de données : un petit objet par adresse et par heure sous `meta/uploads/`, mis à jour par écriture
conditionnelle, pour que toutes les instances voient le même. L’adresse est la première entrée de
`x-forwarded-for` (ou `x-real-ip`), écrite par Vercel ; elle n’est jamais stockée, seulement son HMAC.

## La CLI

### Le fichier

`colis.config.json`, `.colisrc.json` ou `.colisrc`, cherché en remontant depuis le dossier courant,
puis `~/.config/colis/config.json` (ou `$XDG_CONFIG_HOME/colis/config.json`). `--config` ou
`$COLIS_CONFIG` désignent un fichier précis, qui doit exister. Le premier fichier trouvé l’emporte :
deux fichiers ne sont jamais fusionnés.

| Clé              | Valeur                                                                                                               |
| ---------------- | -------------------------------------------------------------------------------------------------------------------- |
| `remote`         | L’adresse des routes d’une page de livraison : `https://…/api/transfers`. Sans elle ni `bucket` : le service public. |
| `token`          | Le jeton Bearer envoyé avec `remote`.                                                                                |
| `bucket`         | Le nom du bucket, en mode bucket.                                                                                    |
| `region`         | La région. `"auto"` pour les fournisseurs qui l’ignorent.                                                            |
| `endpoint`       | Le point d’accès compatible S3. Le définir active l’adressage par chemin.                                            |
| `forcePathStyle` | Force l’un ou l’autre adressage.                                                                                     |
| `prefix`         | Le préfixe des clés dans le bucket.                                                                                  |
| `publicUrl`      | Une adresse publique ou un CDN devant le bucket.                                                                     |
| `expiresIn`      | `3600`, `"24h"`, `"7d"`, ou `null` pour ne jamais expirer.                                                           |
| `credentials`    | `{ accessKeyId, secretAccessKey, sessionToken? }`. À omettre pour la chaîne d’AWS.                                   |
| `envFile`        | Un fichier `KEY=value` à lire avant de remplacer les `${…}`. Relatif au fichier de configuration.                    |
| `profiles`       | Des réglages nommés qui remplacent les clés de la racine, choisis avec `-p`.                                         |
| `$schema`        | Accepté et ignoré, pour un éditeur.                                                                                  |

Toute autre clé est refusée, avec la clé la plus proche en suggestion. `${VAR}` dans une chaîne est
lu dans l’environnement ; une variable manquante est signalée par son nom avant toute requête. Un
profil remplace la racine clé par clé, `credentials` comptant pour une seule clé.

### Qui l’emporte

Une option l’emporte sur une variable d’environnement, qui l’emporte sur le fichier.
`colis config` affiche la source de chaque valeur.

Quand rien ne nomme ni serveur (`remote`) ni bucket, la CLI envoie vers le service public,
`https://colis-tau.vercel.app/api/transfers`, sans jeton ; `colis config` l’indique par
`default (public service)`. Un bucket configuré garde le mode direct, et `remote` l’emporte sur tout.

| Réglage       | Option         | Environnement                                      |
| ------------- | -------------- | -------------------------------------------------- |
| `remote`      | `--remote`     | `COLIS_REMOTE`                                     |
| `token`       | `--token`      | `COLIS_TOKEN`                                      |
| `bucket`      | `--bucket`     | `COLIS_BUCKET`, `S3_BUCKET`                        |
| `region`      | `--region`     | `COLIS_REGION`, `AWS_REGION`, `AWS_DEFAULT_REGION` |
| `endpoint`    | `--endpoint`   | `COLIS_ENDPOINT`, `S3_ENDPOINT`                    |
| `prefix`      | `--prefix`     | `COLIS_PREFIX`                                     |
| `publicUrl`   | —              | `COLIS_PUBLIC_URL`, `S3_PUBLIC_URL`                |
| `expiresIn`   | `--expires-in` | `COLIS_EXPIRES_IN`                                 |
| `credentials` | —              | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`       |
| le fichier    | `--config`     | `COLIS_CONFIG`                                     |
| le profil     | `--profile`    | `COLIS_PROFILE`                                    |

Les clés n’ont pas d’option, exprès : un secret passé en argument se retrouve dans `ps` et dans
l’historique du shell.

## La bibliothèque

`createBucket()` de `@colis/core` :

```ts
import { createBucket } from '@colis/core'

const store = createBucket({
  bucket: 'livraisons', // ou COLIS_BUCKET / S3_BUCKET
  region: 'eu-west-3', // ou COLIS_REGION / AWS_REGION / AWS_DEFAULT_REGION
  credentials: { accessKeyId: '…', secretAccessKey: '…' }, // à omettre pour la chaîne d’AWS
  endpoint: 'https://…', // ou COLIS_ENDPOINT / S3_ENDPOINT
  forcePathStyle: true, // vrai par défaut quand endpoint est défini
  publicUrl: 'https://cdn…', // ou COLIS_PUBLIC_URL / S3_PUBLIC_URL
  prefix: 'drop', // appliqué à l’entrée et retiré à la sortie
  maxSize: 4 * 1024 * 1024, // refuse un corps plus gros avant tout appel réseau
  syncCode: { length: 8 }, // la forme des codes, voir plus bas
  client: myS3Client, // votre propre S3Client
})
```

| Option           | Variable de repli                                  | Notes                                                                     |
| ---------------- | -------------------------------------------------- | ------------------------------------------------------------------------- |
| `bucket`         | `COLIS_BUCKET`, `S3_BUCKET`                        | La seule option obligatoire.                                              |
| `region`         | `COLIS_REGION`, `AWS_REGION`, `AWS_DEFAULT_REGION` | `"auto"` par défaut quand `endpoint` est défini.                          |
| `credentials`    | —                                                  | À omettre pour la chaîne d’identifiants d’AWS.                            |
| `endpoint`       | `COLIS_ENDPOINT`, `S3_ENDPOINT`                    | Pour R2, MinIO, Scaleway, Wasabi…                                         |
| `forcePathStyle` | —                                                  | `true` avec un `endpoint`, `false` sinon.                                 |
| `publicUrl`      | `COLIS_PUBLIC_URL`, `S3_PUBLIC_URL`                | Une URL absolue.                                                          |
| `prefix`         | —                                                  | Appliqué par chaque méthode, modifiable appel par appel.                  |
| `maxSize`        | —                                                  | En octets, vérifié avant tout appel réseau.                               |
| `syncCode`       | —                                                  | `{ length, alphabet }`, voir ci-dessous.                                  |
| `client`         | —                                                  | Un `S3Client` que vous avez construit. `store.destroy()` ne le ferme pas. |

Le préfixe est un espace de noms, pas une partie de la clé : `store.put('K7QP2M4X', …)` écrit
`drop/K7QP2M4X` et renvoie `key: 'K7QP2M4X'`, `path: 'drop/K7QP2M4X'`.

## La forme des codes

Par défaut, huit caractères en base32 de Crockford : `0123456789ABCDEFGHJKMNPQRSTVWXYZ`, sans `I`,
`L`, `O` ni `U`. Les trois premiers se confondent à la lecture ; retirer le quatrième évite qu’un
code aléatoire forme un mot malheureux. Huit caractères de cinq bits font 40 bits.

```ts
import { createBucket, syncCodeAlphabets } from '@colis/core'

const store = createBucket({
  bucket: 'livraisons',
  syncCode: { length: 10, alphabet: syncCodeAlphabets.crockford },
})

store.codes.create() // "K7QP2M4XA9"
store.codes.entropyBits // 50
```

| Option     | Défaut                        |                                                                         |
| ---------- | ----------------------------- | ----------------------------------------------------------------------- |
| `length`   | `8`                           | De 1 à 64 caractères.                                                   |
| `alphabet` | `syncCodeAlphabets.crockford` | Au moins deux caractères distincts ; ni espace, ni tiret, ni tiret bas. |

`syncCodeAlphabets` fournit aussi `digits` (`0123456789`) et `alphanumeric` (A à Z et 0 à 9). Un code
plus court se dicte mieux mais se devine plus vite : il ne se justifie qu’avec une durée de vie courte
et une limite sur les recherches. La page de livraison utilise la forme par défaut.
