> ## Documentation Index
> Fetch the complete documentation index at: https://woku.app/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Gestión de secrets

> Cómo Woku almacena y entrega secrets a los servicios en producción, y qué se espera del entorno local

Todas las credenciales sensibles de Woku (cadenas de conexión a base
de datos, claves JWT, API keys de terceros, tokens de Stytch SSO,
etc.) se almacenan en **AWS SSM Parameter Store** como `SecureString`
y se inyectan al container en producción al momento de arrancar.

## Modelo

* **Almacenamiento**: AWS SSM Parameter Store, región `us-east-1`,
  bajo el prefijo `/shared/prod/secrets/`. Tipo `SecureString` (cifrado
  con KMS, llave `alias/aws/ssm`).
* **Inyección**: AWS Copilot lee cada parámetro y lo entrega al
  container como variable de entorno (`process.env`) al iniciar la
  tarea ECS. Sucede automáticamente vía el bloque `secrets:` del
  manifest de la aplicación.
* **Permisos**: el rol de ejecución de la tarea ECS tiene una policy
  acotada a `ssm:GetParameters` + `kms:Decrypt` solo sobre el prefijo
  `/shared/prod/secrets/*`. No puede leer otros parámetros de la
  cuenta.

## Auditabilidad

* Cada lectura de un parámetro queda en **AWS CloudTrail**.
* Cada cambio (`PutParameter`, `DeleteParameter`) queda en CloudTrail
  también, con identidad IAM del autor.
* KMS registra las operaciones `Decrypt` por separado en CloudTrail
  (data events si están habilitados).

## ¿Por qué no AWS Secrets Manager?

SSM Parameter Store SecureString ofrece **el mismo cifrado KMS** que
Secrets Manager y la misma garantía de aislamiento. La diferencia
principal es la **rotación automática integrada** (RDS / DocumentDB /
Lambda), que actualmente no necesitamos. La elección de SSM nos
ahorra el costo per-secret de Secrets Manager (\~\$0.40/mes c/u)
manteniendo las garantías de cifrado y auditoría.

## Lo que NO se hace

* ❌ **Nunca commiteamos secrets al repositorio.** Hay un
  `.dockerignore` que excluye `.env` y `.env.*` de la imagen Docker;
  los archivos locales jamás llegan a producción.
* ❌ **Nunca pasamos secrets como argumentos en CI/CLI inline.**
  Quedan en el shell history y en logs de CI. Se exportan al entorno
  antes de ejecutar el comando que los necesita.
* ❌ **Nunca se ponen secrets en `variables:` del manifest** (esa
  sección está en texto plano dentro del CloudFormation stack).

## Entornos

| Entorno        | Origen de secrets                                                                             |
| -------------- | --------------------------------------------------------------------------------------------- |
| **Producción** | SSM Parameter Store, leído por Copilot al arrancar el container. Esta es la fuente de verdad. |
| **Local dev**  | Archivo `.env` en `woku-server/` (cada desarrollador tiene el suyo).                          |

> **Estado actual:** algunas instalaciones locales tienen valores de
> producción mezclados con sandbox dentro de su `.env`. El objetivo es
> que el `.env` local contenga **solo valores de dev/sandbox** (Mongo
> local, Stytch sandbox project, Paddle sandbox, etc.) y que cualquier
> conexión a recursos productivos pase exclusivamente por SSM al
> levantar el container en AWS.

Si necesitas un secret nuevo en producción, sigue
[el procedimiento](#agregar-un-secret-nuevo).

## Agregar un secret nuevo

1. **Subir el valor a SSM.** Exporta el valor en tu shell y usa el
   helper que vive en el repo:

   ```bash theme={null}
   export MI_SECRET_NUEVO="..."
   ./scripts/upload-secrets-to-ssm.sh
   ```

   El script sube cada variable que esté exportada a
   `/shared/prod/secrets/<NOMBRE>` como `SecureString`. Skipea
   silenciosamente las que no estén seteadas.

2. **Referenciarlo desde el manifest** en
   `copilot/woku-server/manifest.yml`:

   ```yaml theme={null}
   secrets:
     MI_SECRET_NUEVO: /shared/prod/secrets/MI_SECRET_NUEVO
   ```

3. **Deploy.** Próximo `copilot deploy` levanta el container con la
   variable disponible en `process.env.MI_SECRET_NUEVO`.

## Rotar un secret

Para credenciales sin rotación automática (todo lo que tenemos hoy):

1. Genera el nuevo valor en el proveedor (ej: nuevo `STYTCH_SECRET`
   en el dashboard de Stytch).
2. `aws ssm put-parameter --overwrite --type SecureString ...` (el
   helper script ya lo hace).
3. Force-redeploy del servicio para que tome el valor nuevo:
   `copilot svc deploy --name woku-server`.
4. Revoca el valor anterior en el proveedor.

> El container **no** detecta cambios en SSM en vivo. Los valores se
> leen una sola vez al arrancar. Por eso siempre hay que
> redeployar después de rotar.

## Reportar un leak

Si descubres un secret expuesto (en un repo público, en logs, en un
PR, en un screenshot), envía el detalle a `team@woku.app`. El
proceso de respuesta:

1. **Rotación inmediata** del valor comprometido.
2. Investigación de uso del valor anterior en CloudTrail.
3. Notificación al cliente si la rotación afecta sus integraciones.

El SLA por defecto es 4 horas hábiles, o lo que pacte tu contrato
Corporate si exige un tiempo menor.
