@dotrino/vault 0.82.1 → 0.83.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.
@@ -297,8 +297,8 @@ async function cmdInfo () {
297
297
  /**
298
298
  * `import` y `set`: SUBIR VARIABLES AL CAJÓN DE ESTE SERVICIO (dueño, 2026-09-29: «para
299
299
  * facilitar la migración de ENVs a Dotrino»). El `.env` de la máquina sube tal cual; qué
300
- * se guarda y cuándo lo decide la bóveda (`storeVars`): con aprobación puede editar, sin
301
- * ella solo añade, y borrar no existe por aquí.
300
+ * se guarda y cuándo lo decide la bóveda (`storeVars`): añadir es directo, editar una que ya
301
+ * existe pide aprobación, y borrar no existe por aquí.
302
302
  */
303
303
  async function cmdStore (fromFile) {
304
304
  let parsed
@@ -360,11 +360,10 @@ async function cmdStore (fromFile) {
360
360
  process.exit(1)
361
361
  })
362
362
  if (r.pending) {
363
- console.log('\nPedido de aprobación enviado (%s). Apruébalo en un aparato con «aprueba»:', r.pending)
364
- console.log('se guardarán al aprobar. Con la aprobación también se pueden cambiar las que ya existían.')
363
+ console.log('\nAlguna de estas variables ya existe, y cambiarla pide aprobación.')
364
+ console.log('Pedido enviado (%s). Apruébalo en un aparato con «aprueba»: se guardan todas al aprobar.', r.pending)
365
365
  } else {
366
366
  console.log('\nGuardadas: %s', r.keys.join(', '))
367
- console.log('(nadie en tu cuenta puede aprobar, así que solo se añaden las que faltaban)')
368
367
  }
369
368
  }
370
369
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dotrino/vault",
3
- "version": "0.82.1",
3
+ "version": "0.83.0",
4
4
  "description": "Usa ESTE dispositivo (navegador) como bóveda/CA del ecosistema Dotrino: atiende enrolamientos por el proxy y firma certificados de delegación a tus máquinas. Incluye el cliente de SERVICIO (Node): un proyecto se enrola una vez y jala sus credenciales del vault en vez del .env (`import '@dotrino/vault/config'`).",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -59,7 +59,7 @@
59
59
  "pairing"
60
60
  ],
61
61
  "peerDependencies": {
62
- "@dotrino/identity": ">=0.99.0",
62
+ "@dotrino/identity": ">=0.111.0",
63
63
  "@dotrino/proxy-client": ">=0.23.1"
64
64
  },
65
65
  "license": "MIT",
package/src/enroll.js CHANGED
@@ -30,7 +30,7 @@
30
30
  * `docs/pairing-protocol.md`).
31
31
  */
32
32
  import { verifyDeviceSig, pubkeyId, commitCode } from '@dotrino/identity/capabilities'
33
- import { verifyContinuity, canSeal, DEVICE_CAPS } from '@dotrino/identity/acta'
33
+ import { verifyContinuity, canSeal, DEVICE_CAPS, VAULT_CN } from '@dotrino/identity/acta'
34
34
 
35
35
  /** Un token de emparejamiento vale 5 min. */
36
36
  export const PAIRING_TTL_MS = 5 * 60 * 1000
@@ -169,12 +169,16 @@ export function createEnrollDesk ({
169
169
  * el código, igual que hacía `caps` después.
170
170
  */
171
171
  async function startPairing ({ scope = defaultScope, ttlMs = defaultTtlMs, label = '', mode = 'join', account = '', caps = null } = {}) {
172
+ // El nombre de la propia bóveda no es un servicio: su llave firma con el perfil cerrado
173
+ // y no puede abrir ningún cajón. Un servicio que entrara con ese nombre tampoco podría.
174
+ if (scopeToCn(scope) === VAULT_CN) throw Object.assign(new Error(`"${VAULT_CN}" is the vault's own name: a service cannot use it`), { code: 'reserved-cn' })
172
175
  if (caps != null) {
173
176
  if (!Array.isArray(caps)) throw Object.assign(new Error('caps must be a list'), { code: 'bad-caps' })
174
177
  const cn = scopeToCn(scope)
175
- const bad = caps.filter((c) => !(DEVICE_CAPS.includes(c) || (c === 'secrets' && cn)))
178
+ const bad = caps.filter((c) => !DEVICE_CAPS.includes(c))
176
179
  if (bad.length) throw Object.assign(new Error('unknown permission(s): ' + bad.join(', ')), { code: 'bad-caps' })
177
- if (!caps.length) throw Object.assign(new Error('the pairing grants no permission'), { code: 'empty-scope' })
180
+ // Un servicio puede entrar sin ningún permiso: su cajón lo abre el CN.
181
+ if (!caps.length && !cn) throw Object.assign(new Error('the pairing grants no permission'), { code: 'empty-scope' })
178
182
  caps = [...new Set(caps)]
179
183
  }
180
184
  pending.clear() // uno a la vez: una sesión nueva supersede a la anterior
@@ -378,13 +382,14 @@ export function createEnrollDesk ({
378
382
  throw Object.assign(new Error('this vault cannot add devices to the account record: no certificate was issued'), { code: 'admit-unavailable' })
379
383
  }
380
384
  // PERMISOS, no tipos (2026-08-22): las capacidades son las del scope ENTERO. Un
381
- // cajón (`secrets:<ns>`) suma `secrets` y fija el CN; no borra lo demás — un bot
382
- // con `sign,secrets:eco` firma como aparato del acta Y lee solo su cajón.
385
+ // cajón (`secrets:<ns>`) fija el CN, que es lo que lo abre —no hay permiso aparte
386
+ // (dueño, 2026-10-13)—, y no borra lo demás: un bot con `sign,secrets:eco` firma como
387
+ // aparato del acta Y lee solo su cajón.
383
388
  // Si quien emparejó ELIGIÓ los permisos (`startPairing({ caps })`), entran esos y en
384
389
  // esta misma acta; si no, los que da el scope.
385
390
  const cn = scopeToCn(pend.scope)
386
- const caps = [...new Set([...(pend.caps || scopeToCaps(pend.scope)), ...(cn ? ['secrets'] : [])])]
387
- if (!caps.length) {
391
+ const caps = [...new Set(pend.caps || scopeToCaps(pend.scope))]
392
+ if (!caps.length && !cn) {
388
393
  throw Object.assign(new Error('the pairing scope grants no permission: no certificate was issued'), { code: 'empty-scope' })
389
394
  }
390
395
 
package/src/service.js CHANGED
@@ -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