Utilisez cet inventaire pour décider quelles valeurs appartiennent à l’environnement d’exécution, lesquelles sont générées dans la base de données, et lesquelles sont stockées par les plugins. Chaque section indique comment la rotation affecte un site en cours d’exécution.
Sous Node.js, placez les secrets d’exécution dans le gestionnaire de secrets de la plateforme d’hébergement pour qu’ils entrent dans process.env au démarrage du processus. Pour un Worker, utilisez wrangler secret put. Ne mettez pas de valeurs secrètes dans astro.config.mjs, wrangler.jsonc ou import.meta.env ; Vite peut intégrer des valeurs de build dans le bundle serveur.
Vue d’ensemble
| Secret | Source | Stocké dans | Impact en cas de perte de clé |
|---|---|---|---|
EMDASH_ENCRYPTION_KEY | Opérateur (emdash secrets generate) | Environnement / secret Worker uniquement | Les paramètres de plugin chiffrés ne peuvent pas être lus tant que la clé correspondante n’est pas restaurée |
| Secret de preview | Auto-généré (override d’env) | Table options (emdash:preview_secret) | Les liens de preview en cours cessent de fonctionner ; les nouveaux sont corrects |
| Sel IP | Auto-généré (override d’env) | Table options (emdash:ip_salt) | La continuité du rate-limit des commentaires se réinitialise |
| Jetons de session et d’API | Générés par session/jeton | Magasin de session / base de données (hashes uniquement) | Rien — le texte en clair n’est jamais stocké |
| Identifiants de fournisseur OAuth | Vous (console Google/GitHub) | Environnement | La connexion via ce fournisseur s’arrête jusqu’au remplacement |
| Secret Turnstile | Vous (tableau de bord Cloudflare) | Environnement | La vérification CAPTCHA des commentaires échoue |
| Identifiants S3 | Vous (fournisseur de stockage) | Environnement d’exécution | L’upload/téléchargement des médias échoue jusqu’au remplacement |
| Secrets de plugin | Vous (UI des paramètres admin) | Paramètre de base de données chiffré | Restaurez la clé de chiffrement correspondante ou ressaisissez la valeur |
| Identifiants CLI | Flux d’appareil emdash login / emdash plugin publish | ~/.config/emdash/auth.json (mode 0600) | Relancez le flux d’appareil |
| Identifiants CLI du registre | OAuth atproto de emdash-plugin | ~/.emdash/oauth/, ~/.emdash/credentials.json (mode 0600) | Reconnectez-vous ; l’identité vit chez votre PDS |
La clé de chiffrement
EMDASH_ENCRYPTION_KEY chiffre les paramètres de plugin déclarés avec type: "secret". EmDash utilise AES-GCM avec l’ID du plugin et la clé du paramètre comme données authentifiées. Une valeur malformée produit un message de démarrage destiné à l’opérateur, et les opérations qui ont besoin de paramètres de plugin chiffrés échouent en fermeture. Les requêtes de site non liées continuent de fonctionner.
La commande suivante génère une valeur correctement formatée. Stockez-la dans l’environnement d’exécution ou comme secret Worker si votre déploiement utilise cette variable.
npx emdash secrets generate
# emdash_enc_v1_<43 base64url chars>
# Cloudflare:
wrangler secret put EMDASH_ENCRYPTION_KEY
Le format est emdash_enc_v1_ suivi de 32 octets aléatoires en base64url non rembourré. La valeur est fournie par l’opérateur et n’est pas stockée dans la base de données. Conservez-la dans un gestionnaire de secrets et dans une sauvegarde de récupération séparée.
Pour faire tourner la clé, préfixez une nouvelle valeur et conservez l’ancienne après une virgule :
EMDASH_ENCRYPTION_KEY=emdash_enc_v1_<new-key>,emdash_enc_v1_<old-key>
EmDash chiffre les valeurs nouvelles et réenregistrées avec la première clé. Il utilise l’empreinte kid stockée pour sélectionner une clé plus ancienne en lecture. Réenregistrez chaque secret de plugin avant de retirer l’ancienne clé, puis vérifiez ces intégrations depuis un déploiement qui ne contient que la nouvelle clé. EmDash ne signale pas actuellement quels IDs de clé restent en usage, donc tenez un inventaire des identifiants que vous réenregistrez et ne retirez une ancienne clé qu’après que chaque intégration a passé cette vérification.
Secrets de site générés
Deux secrets sont générés automatiquement à la première utilisation et persistés dans la table options, de sorte qu’ils sont stables entre requêtes, déploiements et isolates. La génération est atomique — les démarrages à froid concurrents convergent sur une valeur.
Secret de preview
Signe les URL de preview (HMAC). Stocké comme emdash:preview_secret ; 32 octets aléatoires, base64url.
- Override : définissez
EMDASH_PREVIEW_SECRET(alias hérité :PREVIEW_SECRET) si vous avez besoin du même secret sur plusieurs processus ou souhaitez le fixer pour l’audit. L’environnement gagne toujours sur la valeur stockée. - Rotation : supprimez la ligne
emdash:preview_secret(ou changez la variable d’env) et redéployez. Impact : les liens de preview émis auparavant cessent de valider. Rien d’autre ne casse — un secret frais est généré (ou lu depuis l’env) à la prochaine requête de preview. - En cas de perte : rien n’est irrécupérable. Les liens de preview sont de courte durée par conception.
Voir le guide de preview pour la construction et la vérification des URL de preview.
Sel IP
Sale le hash SHA-256 des adresses IP des commentateurs (ip_hash sur les commentaires) utilisé pour le rate-limit des commentaires. Stocké comme emdash:ip_salt. Spécifique au site, de sorte que les hashes ne sont pas corrélables entre installations EmDash.
- Override : définissez
EMDASH_IP_SALT. Pour la compatibilité ascendante,EMDASH_AUTH_SECRET/AUTH_SECRETsont aussi consultés — les installations qui dérivaient historiquement le sel de ceux-ci conservent des hashes stables. - Rotation : changez la variable d’env ou supprimez la ligne
emdash:ip_salt. Impact : les nouvelles soumissions de commentaires hachent vers des valeurs différentes, donc le comptage du rate-limit redémarre pour tout le monde. Les commentaires existants et leurs hashes stockés restent intacts. - En cas de perte : aucune perte de données. Seule la continuité du rate-limit se réinitialise.
Jetons de session et d’API
- Sessions utilisent le magasin de session d’Astro (Workers KV sur Cloudflare, système de fichiers sous Node). Le cookie porte un ID de session opaque ; il n’y a pas de secret de signature à gérer. Déconnectez-vous pour terminer une session, ou videz le magasin de session (p. ex. le namespace KV) pour forcer tout le monde à se reconnecter.
- Jetons d’API (préfixes
ec_pat_,ec_oat_,ec_ort_) sont des valeurs aléatoires opaques de 256 bits ; seul leur hash SHA-256 est stocké. Le texte en clair est montré une fois à la création. Faites tourner en révoquant et en recréant dans l’admin. - Jetons d’invitation, magic-link et de récupération sont à usage unique, stockés comme hashes SHA-256 dans
auth_tokens, et limités dans le temps (invitations 7 jours, magic links 15 minutes).
Il n’y a rien à sauvegarder ni à faire tourner de façon proactive : une fuite de base de données n’expose que des hashes, et chaque jeton peut être révoqué ou réémis depuis l’admin.
Identifiants de service fournis par l’utilisateur
Les identifiants pour les services externes sont lus depuis l’environnement et jamais écrits dans la base de données. Faites-les tourner chez le fournisseur, mettez à jour la variable, redéployez.
| Service | Variables |
|---|---|
| Connexion Google | EMDASH_OAUTH_GOOGLE_CLIENT_ID, EMDASH_OAUTH_GOOGLE_CLIENT_SECRET (ou alias sans préfixe) |
| Connexion GitHub | EMDASH_OAUTH_GITHUB_CLIENT_ID, EMDASH_OAUTH_GITHUB_CLIENT_SECRET (ou alias sans préfixe) |
| Publication Marketplace (CI) | EMDASH_MARKETPLACE_TOKEN |
| Turnstile (commentaires) | EMDASH_TURNSTILE_SECRET_KEY (ou TURNSTILE_SECRET_KEY) |
| Stockage compatible S3 | S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY, S3_ENDPOINT, S3_BUCKET, S3_REGION |
Sur Cloudflare, définissez-les avec wrangler secret put ; pour le développement local, mettez-les dans .env. Wrangler lit .dev.vars ou .env, pas les deux, et .dev.vars a la priorité lorsqu’il est présent. R2 via un binding n’a pas besoin de variables de clé d’accès car le binding accorde l’accès à l’exécution. Voir stockage des médias.
Secrets de plugin
Les paramètres qu’un plugin déclare avec type: "secret" (clés API pour les fournisseurs d’e-mail, CAPTCHA de formulaires, etc.) sont saisis dans l’UI admin et chiffrés dans la table options sous plugin:<id>:settings:<key>. L’admin ne reçoit que si un secret est défini, même lorsque la clé de chiffrement correspondante est indisponible, de sorte qu’un administrateur peut remplacer un identifiant illisible. Le code du plugin lit le texte en clair via ctx.settings dans son runtime isolé. Les valeurs stockées hors d’un schéma de paramètres déclaré, y compris les entrées KV et d’état arbitraires du plugin, n’utilisent pas ce chemin de chiffrement.
- Rotation d’identifiant : faites tourner l’identifiant chez le fournisseur et collez la nouvelle valeur dans la page de paramètres du plugin. L’enregistrement écrit une nouvelle enveloppe chiffrée.
- Migration du texte en clair : les secrets stockés par une version antérieure d’EmDash restent lisibles. Enregistrez chaque valeur à nouveau pour la chiffrer.
- Si la clé de chiffrement est perdue : restaurez le
EMDASH_ENCRYPTION_KEYcorrespondant depuis la sauvegarde séparée de la clé. Si aucune copie n’existe, remplacez chaque identifiant concerné chez son fournisseur et saisissez les remplacements après avoir configuré une nouvelle clé de chiffrement.
Identifiants CLI
La CLI emdash détient deux types d’identifiants, tous deux dans ~/.config/emdash/auth.json (en respectant XDG_CONFIG_HOME), créés avec des permissions propriétaire uniquement (0600) :
- Jetons de site —
emdash logins’authentifie auprès de votre instance EmDash via un flux d’appareil OAuth et stocke le jeton résultant indexé par URL d’instance.emdash logoutle retire ; par invocation,--tokenouEMDASH_TOKENremplace le jeton stocké. - Jetons Marketplace —
emdash plugin publishs’authentifie auprès du Marketplace EmDash via un flux d’appareil GitHub et stocke le JWT résultant indexé parmarketplace:<origin>. Pour la publication CI, définissez plutôtEMDASH_MARKETPLACE_TOKEN— il a priorité sur l’identifiant stocké.
Perdre le fichier est sans danger : relancez emdash login (ou emdash plugin publish, qui relance le flux d’appareil).
Identifiants CLI du registre de plugins
La CLI séparée emdash-plugin (paquet @emdash-cms/plugin-cli) cible le registre AT Protocol expérimental. Publier là est lié à votre identité AT Protocol (votre DID de publisher) — le site lui-même ne détient aucun identifiant de publication, et les installations vérifient les artefacts contre les sommes de contrôle des enregistrements de release attribués à ce DID.
- Elle s’authentifie via OAuth atproto. Les blobs de session/état OAuth vivent dans
~/.emdash/oauth/, et l’identité du publisher (DID, handle, PDS) est mise en cache dans~/.emdash/credentials.json; les deux sont écrits avec des permissions propriétaire uniquement. - En CI, fournissez l’identité via
EMDASH_PUBLISHER_DID,EMDASH_PUBLISHER_HANDLEetEMDASH_PUBLISHER_PDS;EMDASH_REGISTRY_URLremplace l’hôte du registre. Lepublishautomatisé depuis CI a encore besoin des fichiers de session OAuth dans~/.emdash/oauth/sur le runner — les variables d’env seules ne portent pas la session OAuth. - Faire tourner ou révoquer l’accès de publication se fait sur votre compte AT Protocol (p. ex. mots de passe d’app), pas dans EmDash. Voir auth Atmosphere.
Référence rapide de rotation
| Je veux… | Faites ceci |
|---|---|
| Faire tourner le chiffrement des paramètres de plugin | Préfixer la nouvelle clé, réenregistrer les secrets de plugin, puis retirer l’ancienne clé |
| Invalider tous les liens de preview | Supprimer la ligne d’option emdash:preview_secret (ou changer l’override d’env) |
| Réinitialiser le hachage du rate-limit des commentaires | Changer EMDASH_IP_SALT (ou supprimer la ligne d’option emdash:ip_salt) |
| Révoquer un jeton d’API divulgué | Admin → Users → API tokens → révoquer, puis créer un remplacement |
| Tuer toutes les sessions | Vider le magasin de session (namespace KV Workers / répertoire de session) |
| Remplacer un identifiant de fournisseur | Faire tourner chez le fournisseur, mettre à jour la variable d’env, redéployer |
| Remplacer une clé API de plugin | Faire tourner chez le fournisseur, ressaisir dans les paramètres admin du plugin |