EmDash utiliza un pequeño conjunto de secretos para vistas previas, comentarios, autenticación, almacenamiento y plugins. Esta página es el inventario completo: de dónde viene cada secreto, dónde se almacena, cómo rotarlo y qué se rompe si se pierde.
Visión general
| Secreto | Fuente | Almacenado en | Impacto de pérdida |
|---|---|---|---|
EMDASH_ENCRYPTION_KEY | Operador (emdash secrets generate) | Solo entorno / secreto Worker | Los secretos de plugins cifrados se vuelven irrecuperables (cuando se lance el cifrado en reposo) |
| Secreto de vista previa | Auto-generado (override de env) | Tabla options (emdash:preview_secret) | Los enlaces de vista previa existentes dejan de funcionar; los nuevos están bien |
| Salt de IP | Auto-generado (override de env) | Tabla options (emdash:ip_salt) | La continuidad del rate-limit de comentarios se reinicia |
| Tokens de sesión y API | Generados por sesión/token | Almacén de sesiones / BD (solo hashes) | Nada — el texto plano nunca se almacena |
| Credenciales de proveedor OAuth | Tú (consola de Google/GitHub) | Entorno | El inicio de sesión vía ese proveedor se detiene hasta reemplazarlo |
| Secreto de Turnstile | Tú (panel de Cloudflare) | Entorno | La verificación CAPTCHA de comentarios falla |
| Credenciales S3 | Tú (proveedor de almacenamiento) | Entorno o configuración | La carga/descarga de medios falla hasta reemplazarlo |
| Secretos de plugins | Tú (UI de configuración de admin) | Base de datos (configuración / almacenamiento de plugins) | Re-ingresar en el admin |
| Credenciales CLI | Flujos de dispositivo emdash login / emdash plugin publish | ~/.config/emdash/auth.json (modo 0600) | Ejecutar el flujo de dispositivo de nuevo |
| Credenciales CLI del registro | emdash-plugin atproto OAuth | ~/.emdash/oauth/, ~/.emdash/credentials.json (modo 0600) | Iniciar sesión de nuevo; la identidad vive en tu PDS |
La clave de cifrado
EMDASH_ENCRYPTION_KEY es la clave del sitio para cifrar secretos de plugins en reposo. Es proporcionada por el operador y nunca almacenada en la base de datos — la base de datos solo contiene texto cifrado, por lo que una fuga de backup no expone la clave.
Genera una y configúrala como variable de entorno (o secreto Worker):
npx emdash secrets generate
# emdash_enc_v1_<43 caracteres base64url>
# Cloudflare:
wrangler secret put EMDASH_ENCRYPTION_KEY
El formato es emdash_enc_v1_ seguido de 32 bytes aleatorios como base64url sin relleno. La clave se valida al iniciar el runtime; un valor malformado registra un error orientado al operador sin interrumpir las rutas de solicitud.
Rotación
La variable acepta una lista separada por comas de claves. La primera entrada es la primaria y se usa para nuevas escrituras; todas las entradas se intentan para descifrado. Cada valor cifrado está etiquetado con una huella digital de clave de 8 caracteres (el kid, imprimible vía emdash secrets fingerprint <key>), por lo que el runtime selecciona la clave correcta automáticamente.
Para rotar: genera una nueva clave, anteponla a la lista (EMDASH_ENCRYPTION_KEY="nueva,antigua"), redespliega y elimina la antigua una vez que los valores existentes hayan sido re-cifrados.
Secretos de sitio generados
Dos secretos se generan automáticamente en el primer uso y se persisten en la tabla options, por lo que son estables entre solicitudes, despliegues y aislamientos. La generación es atómica — arranques en frío concurrentes convergen en un valor.
Secreto de vista previa
Firma URLs de vista previa (HMAC). Almacenado como emdash:preview_secret; 32 bytes aleatorios, base64url.
- Override: configura
EMDASH_PREVIEW_SECRET(alias heredado:PREVIEW_SECRET) si necesitas el mismo secreto en múltiples procesos o quieres fijarlo por razones de auditoría. El entorno siempre gana sobre el valor almacenado. - Rotación: elimina la fila
emdash:preview_secret(o cambia la variable de env) y redespliega. Impacto: los enlaces de vista previa emitidos previamente dejan de validar. Nada más se rompe — un secreto fresco se genera (o lee del env) en la siguiente solicitud de vista previa. - Si se pierde: nada es irrecuperable. Los enlaces de vista previa son efímeros por diseño.
Consulta la guía de vistas previas para cómo se construyen y verifican las URLs de vista previa.
Salt de IP
Sala el hash SHA-256 de las direcciones IP de los comentaristas (ip_hash en comentarios) usado para la limitación de tasa de comentarios. Almacenado como emdash:ip_salt. Específico del sitio, por lo que los hashes no son correlacionables entre instalaciones de EmDash.
- Override: configura
EMDASH_IP_SALT. Por compatibilidad retroactiva, también se consultanEMDASH_AUTH_SECRET/AUTH_SECRET— las instalaciones que históricamente derivaron el salt de estos mantienen hashes estables. - Rotación: cambia la variable de env o elimina la fila
emdash:ip_salt. Impacto: los nuevos envíos de comentarios generan valores hash diferentes, así que el conteo de rate-limit se reinicia para todos. Los comentarios existentes y sus hashes almacenados no se tocan. - Si se pierde: sin pérdida de datos. Solo se reinicia la continuidad del rate-limit.
Tokens de sesión y API
- Sesiones usan el almacén de sesiones de Astro (Workers KV en Cloudflare, sistema de archivos en Node). La cookie lleva un ID de sesión opaco; no hay secreto de firma que gestionar. Cierra sesión para terminar una sesión, o limpia el almacén de sesiones (ej. el namespace KV) para forzar a todos a iniciar sesión de nuevo.
- Tokens API (prefijos
ec_pat_,ec_oat_,ec_ort_) son valores aleatorios opacos de 256 bits; solo su hash SHA-256 se almacena. El texto plano se muestra una vez en la creación. Rotar revocando y recreando en el admin. - Tokens de invitación, magic-link y recuperación son de propósito único, almacenados como hashes SHA-256 en
auth_tokens, y con tiempo limitado (invitaciones 7 días, magic links 15 minutos).
No hay nada que respaldar o rotar proactivamente: una fuga de base de datos expone solo hashes, y cada token puede ser revocado o reemitido desde el admin.
Credenciales de servicio proporcionadas por el usuario
Las credenciales para servicios externos se leen del entorno y nunca se escriben en la base de datos. Rótalas en el proveedor, actualiza la variable, redespliega.
| Servicio | Variables |
|---|---|
| Inicio de sesión Google | EMDASH_OAUTH_GOOGLE_CLIENT_ID, EMDASH_OAUTH_GOOGLE_CLIENT_SECRET (o alias sin prefijo) |
| Inicio de sesión GitHub | EMDASH_OAUTH_GITHUB_CLIENT_ID, EMDASH_OAUTH_GITHUB_CLIENT_SECRET (o alias sin prefijo) |
| Publicación Marketplace (CI) | EMDASH_MARKETPLACE_TOKEN |
| Turnstile (comentarios) | EMDASH_TURNSTILE_SECRET_KEY (o TURNSTILE_SECRET_KEY) |
| Almacenamiento compatible S3 | S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY, S3_ENDPOINT, S3_BUCKET, S3_REGION |
En Cloudflare, configúralas con wrangler secret put; localmente, ponlas en .env. R2 vía binding no necesita credenciales — el acceso se otorga por el binding en wrangler.jsonc, que es la configuración recomendada en Workers. Consulta opciones de almacenamiento.
Secretos de plugins
Las configuraciones que un plugin declara con type: "secret" (claves API para proveedores de email, CAPTCHAs de formularios, etc.) se ingresan en la UI de admin y se almacenan en la base de datos — en la tabla options bajo plugin:<id>:settings:<key>, o en el almacenamiento key-value del plugin. Si un secreto almacenado se devuelve a la UI de admin depende del plugin; los plugins bien escritos devuelven solo un indicador “valor configurado” en lugar del secreto en sí (el plugin de formularios incluido hace esto).
- Rotación: rota la clave en el proveedor y pega el nuevo valor en la página de configuración del plugin. Toma efecto inmediatamente.
- Si se pierde: re-ingresa el valor en el admin. Nada más depende de él.
Credenciales CLI
La CLI emdash mantiene dos tipos de credenciales, ambas en ~/.config/emdash/auth.json (respetando XDG_CONFIG_HOME), creadas con permisos solo del propietario (0600):
- Tokens de sitio —
emdash loginse autentica contra tu instancia EmDash vía un flujo de dispositivo OAuth y almacena el token resultante indexado por URL de instancia.emdash logoutlo elimina; por invocación,--tokenoEMDASH_TOKENsobrescribe el token almacenado. - Tokens de Marketplace —
emdash plugin publishse autentica en el EmDash Marketplace vía un flujo de dispositivo GitHub y almacena el JWT resultante indexado comomarketplace:<origin>. Para publicación en CI, configuraEMDASH_MARKETPLACE_TOKENen su lugar — tiene prioridad sobre la credencial almacenada.
Perder el archivo es inofensivo: ejecuta emdash login (o emdash plugin publish, que re-ejecuta el flujo de dispositivo) de nuevo.
Credenciales CLI del registro de plugins
La CLI separada emdash-plugin (paquete @emdash-cms/plugin-cli) apunta al registro experimental del AT Protocol. La publicación allí está vinculada a tu identidad AT Protocol (tu DID de publicador) — el sitio en sí no contiene credenciales de publicación, y las instalaciones verifican artefactos contra checksums de registros de release atribuidos a ese DID.
- Se autentica vía atproto OAuth. Los blobs de sesión/estado OAuth viven en
~/.emdash/oauth/, y la identidad del publicador (DID, handle, PDS) se cachea en~/.emdash/credentials.json; ambos se escriben con permisos solo del propietario. - En CI, proporciona la identidad vía
EMDASH_PUBLISHER_DID,EMDASH_PUBLISHER_HANDLEyEMDASH_PUBLISHER_PDS;EMDASH_REGISTRY_URLsobrescribe el host del registro. Elpublishautomatizado desde CI aún necesita los archivos de sesión OAuth en~/.emdash/oauth/en el runner — las variables de env por sí solas no transportan la sesión OAuth. - Rotar o revocar el acceso de publicación ocurre en tu cuenta AT Protocol (ej. contraseñas de aplicación), no en EmDash. Consulta Atmosphere auth.
Referencia rápida de rotación
| Quiero… | Hacer esto |
|---|---|
| Rotar la clave de cifrado | Anteponer nueva clave: EMDASH_ENCRYPTION_KEY="nueva,antigua", redesplegar, eliminar antigua después |
| Invalidar todos los enlaces de vista previa | Eliminar la fila de opción emdash:preview_secret (o cambiar el override de env) |
| Reiniciar hashing de rate-limit de comentarios | Cambiar EMDASH_IP_SALT (o eliminar la fila de opción emdash:ip_salt) |
| Revocar un token API filtrado | Admin → Usuarios → Tokens API → revocar, luego crear reemplazo |
| Terminar todas las sesiones | Limpiar el almacén de sesiones (namespace Workers KV / directorio de sesiones) |
| Reemplazar una credencial de proveedor | Rotar en el proveedor, actualizar variable de env, redesplegar |
| Reemplazar una clave API de plugin | Rotar en el proveedor, re-ingresar en la configuración admin del plugin |