@dotrino/vaultd 0.105.2 → 0.105.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dotrino/vaultd",
3
- "version": "0.105.2",
3
+ "version": "0.105.3",
4
4
  "type": "module",
5
5
  "description": "Certificador personal de Dotrino: daemon headless que custodia la clave maestra y delega capacidades a tus dispositivos por el proxy. Tu CA propia.",
6
6
  "bin": {
@@ -342,6 +342,19 @@ export function openSecretsStore (dir, { sealer = null, recipients = null, signe
342
342
  schemaVersion: () => data.schemaVersion,
343
343
  /** ¿La privada de recuperación está sellada solo con la llave de esta máquina? */
344
344
  recoveryPub: () => data.recovery?.pub || null,
345
+ /**
346
+ * CREA LA LLAVE DE RECUPERACIÓN SI NO EXISTE. Se llama al ABRIR la bóveda, que es el
347
+ * único momento en que se puede: sellar su privada necesita la maestra.
348
+ *
349
+ * Nacía perezosamente, al escribir el primer secreto. En un perfil recién hecho eso
350
+ * significaba que la bóveda no tenía a quién envolver, y como crearla exige estar
351
+ * abierta, escribir el PERFIL con la bóveda cerrada era imposible — que es justo lo
352
+ * que el perfil en sobres viene a permitir. Lo encontró el escenario del navegador:
353
+ * «the vault did not say who to seal the profile for».
354
+ *
355
+ * Idempotente: si ya está, no toca nada.
356
+ */
357
+ async ensureRecovery (adminKey = null) { return enFila(async () => (await ensureRecovery(adminKey)).pub) },
345
358
 
346
359
  /**
347
360
  * MUCHAS ESCRITURAS, UN GUARDADO. Cargar la configuración de un servicio son veinte
package/src/vault.js CHANGED
@@ -2552,6 +2552,15 @@ export async function startVault ({ dir = dataDir(), proxyUrl, log = console.log
2552
2552
  // ANTES de reenvolver nada: si la copia de recuperación se quedó bajo la llave de la
2553
2553
  // máquina, se pasa a la frase. Sin esto, todo lo de abajo falla con «wrong password».
2554
2554
  if (adminKey) await migrarRecuperacionALaFrase(adminKey)
2555
+ // Y LA LLAVE DE RECUPERACIÓN EXISTE. Nacía al escribir el primer secreto, así que una
2556
+ // bóveda recién creada no tenía a quién envolver — y como crearla necesita la maestra,
2557
+ // cerrada ya no había manera. El síntoma: escribir el perfil con la bóveda cerrada
2558
+ // fallaba con «the vault did not say who to seal the profile for», en un perfil nuevo
2559
+ // y solo en el primero. Abrir la bóveda es el momento de saldarlo, y es idempotente.
2560
+ // …salvo en un almacén v3, que no tiene ese concepto: ahí lo que toca es `migrate`, y
2561
+ // escribir o leer un sobre ya se rechaza diciéndolo. Crearla antes de migrar sería
2562
+ // dejar una llave suelta en un formato que va a reescribirse entero.
2563
+ if (!secrets.isLegacy()) await secrets.ensureRecovery(adminKey)
2555
2564
  const out = { drawers: 0, wrapped: 0, sealed: 0, dropped: 0, sinLlave: [], failed: [] }
2556
2565
  for (const owner of secrets.owners?.() || []) {
2557
2566
  const before = new Set(secrets.recipientsIn(owner))