@dotrino/vaultd 0.150.1 → 0.151.0

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.
@@ -522,8 +522,9 @@ export async function registerEncKey ({ dir, ns, proxyUrl, masterPubkey, device,
522
522
  * privadas al pasar.
523
523
  *
524
524
  * Lo que decide la bóveda, no este cliente:
525
- * · si hay quien apruebe, se pide aprobación siempre, y al aprobarse puede EDITAR;
526
- * · si nadie puede aprobar, solo AÑADE lo que falta (una que ya exista falla con `exists`);
525
+ * · AÑADIR una variable nueva es directo: se guarda en el acto;
526
+ * · EDITAR una que ya existe pide aprobación (la tanda entera queda en espera);
527
+ * · si nadie puede aprobar, una que ya exista falla con `exists`;
527
528
  * · BORRAR no existe por aquí.
528
529
  *
529
530
  * @param {object} o
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dotrino/vaultd",
3
- "version": "0.150.1",
3
+ "version": "0.151.0",
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": {
package/src/vault.js CHANGED
@@ -1477,9 +1477,9 @@ export async function startVault ({ dir = dataDir(), proxyUrl, log = console.log
1477
1477
  * firma del autor, las envolturas, la espera de aprobación. Aquí no hay otra puerta.
1478
1478
  *
1479
1479
  * Los límites (dueño, 2026-09-29):
1480
- * · si hay alguien que aprueba, SIEMPRE se pide aprobación —`unattended` no exime— y con
1481
- * el sí puede también EDITAR lo que ya existe;
1482
- * · si nadie puede aprobar, no se pide y solo puede AÑADIR lo que falta;
1480
+ * · AÑADIR una variable nueva es directo, haya o no quien apruebe (dueño, 2026-10-12);
1481
+ * · EDITAR una que ya existe pide aprobación —`unattended` no exime—;
1482
+ * · si nadie puede aprobar, no se pide y lo que ya existe no se toca (`exists`);
1483
1483
  * · BORRAR, nunca: eso es de la consola y del CLI de la bóveda.
1484
1484
  *
1485
1485
  * Dos operaciones: `store.recipients` (para quién se sella: solo públicas, nada que ocultar)
@@ -1696,7 +1696,7 @@ export async function startVault ({ dir = dataDir(), proxyUrl, log = console.log
1696
1696
  log(`[vault] ${ns}: ${deviceId || '????-????'} wants to store ${items.length} variable(s) — waiting for approval (${result.pending})`)
1697
1697
  } else {
1698
1698
  audit('store', { device: deviceId, ns, keys: result?.keys || [] })
1699
- log(`[vault] ${ns}: ${deviceId || '????-????'} stored ${(result?.keys || []).length} variable(s) (nobody can approve: add only)`)
1699
+ log(`[vault] ${ns}: ${deviceId || '????-????'} stored ${(result?.keys || []).length} new variable(s)`)
1700
1700
  await notifyMembers('vars', { by: deviceId, keys: result?.keys || [], ns })
1701
1701
  }
1702
1702
  return await answer({ op: 'store.result', ns, ts: Date.now(), keys: result?.keys || [], pending: result?.pending || null })
@@ -2811,13 +2811,18 @@ export async function startVault ({ dir = dataDir(), proxyUrl, log = console.log
2811
2811
  const owner = ns ? `ns:${ns}` : `dev:${pub}`
2812
2812
  const keys = []
2813
2813
  // ¿SE PIDE APROBACIÓN? Desde la mesa del admin, lo de siempre (`needsApproval`: quien
2814
- // tiene `unattended` escribe solo). Desde el propio SERVICIO que guarda en su cajón, se
2815
- // pide SIEMPRE que haya quien apruebe, tenga o no `unattended` (dueño, 2026-09-29:
2816
- // «el unattended también pediría aprobación»): `unattended` es para llevarse claves al
2817
- // arrancar, no para reescribir su propia configuración. Sin nadie que apruebe no se
2818
- // pide —la regla de siempre— y entonces solo puede añadir.
2814
+ // tiene `unattended` escribe solo). Desde el propio SERVICIO que guarda en su cajón, la
2815
+ // aprobación es SOLO PARA EDITAR (dueño, 2026-10-12: «la aprobación solamente es para
2816
+ // editar una env; para almacenarla es directo»): una variable nueva no le quita nada a
2817
+ // nadie y se guarda en el acto; reemplazar una que ya existe pide el sí de quien
2818
+ // aprueba, tenga o no `unattended` el servicio (dueño, 2026-09-29: «el unattended
2819
+ // también pediría aprobación»). Una tanda con alguna que ya existe se pide ENTERA: va
2820
+ // todo o nada. Sin nadie que apruebe no se pide —la regla de siempre— y lo que ya
2821
+ // existe falla con `exists`.
2819
2822
  const record = await refreshActa()
2820
- const ask = fromService ? hasApprover(record) : needsApproval(caller, record)
2823
+ const ask = fromService
2824
+ ? hasApprover(record) && items.some((it) => it?.key && secrets.has(owner, it.key))
2825
+ : needsApproval(caller, record)
2821
2826
  for (const it of items) {
2822
2827
  if (!it?.key || !it?.sealed) throw new Error('var.setMany: each variable needs its key and its sealed envelope')
2823
2828
  await checkAuthor(owner, it.key, it.sealed, caller, { allowOverwrite: ask })