Skip to content

[F3-04] Claves de proveedor del usuario (BYOK) cifradas #47

Open

Description

@JCCG-code

Fase: F3 · Tamaño: M · Depende de: #40 (F3-02), #32 (F2-07)
Decisiones: D-03 en #1

Objetivo

Que cada usuario guarde sus claves de IA de forma que ni un volcado de la base de datos ni los logs las expongan, dejando preparado el paso a créditos de plataforma.

Alcance

  • Modelo ProviderCredential: userId, providerId, label, source: 'user' | 'platform' (siempre user en v1), keyVersion, salt, iv, tag, ciphertext, last4, status (valid | invalid | unchecked), lastValidatedAt. Único (userId, providerId, label).
  • Cifrado AES-256-GCM (node:crypto); clave por registro derivada con HKDF-SHA256 de la clave maestra; AAD = userId|providerId|credentialId.
  • Claves maestras versionadas en CREDENTIAL_KEYS (JSON { "1": "<base64 32 bytes>" }), leídas del gestor de secretos del hosting.
  • API: GET /api/v1/credentials, POST /api/v1/credentials (valida con validateKey antes de guardar), POST /api/v1/credentials/:id/validate, DELETE /api/v1/credentials/:id.
  • La clave en claro nunca se devuelve ni se registra; los trabajos en Redis solo llevan credentialId; el worker descifra justo antes de usarla.
  • Si un proveedor responde auth durante un trabajo, la credencial pasa a invalid.

Criterios de aceptación

  • Test: cifrar → descifrar devuelve la clave original.
  • Test: copiar el ciphertext a otro userId hace fallar el descifrado.
  • Test: ninguna respuesta de /credentials contiene apiKey, ciphertext, iv ni tag.
  • Test: guardar una clave que validateKey rechaza → 422 y no se guarda nada.
  • Test: la clave de prueba no aparece en ninguna línea de log capturada durante la suite.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions