@dotrino/vaultd 0.80.0 → 0.80.2

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.80.0",
3
+ "version": "0.80.2",
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/tui/app.js CHANGED
@@ -340,6 +340,19 @@ function pairModeRows (st, t) {
340
340
  */
341
341
  const CAPS_ORDER = ['sign', 'store', 'read', 'admin', 'approve', 'passwords', 'sealer', 'unattended']
342
342
 
343
+ /**
344
+ * Los permisos que se le pueden dar A ESTE miembro, en orden.
345
+ *
346
+ * `secrets` solo existe para un SERVICIO (los que tienen `cn`), y por eso faltaba: la
347
+ * lista era fija y no cabía algo que depende de quién sea. Pero para un servicio es EL
348
+ * permiso —el que decide si abre su cajón— y no verlo aquí hacía creer que no existe,
349
+ * igual que pasaba con `unattended`. Se enseña primero, que es su importancia real.
350
+ *
351
+ * A un aparato SIN `cn` no se le ofrece: no hay cajón que abrir, el acta lo filtra
352
+ * (`allowedCaps`) y enseñar una casilla que no hace nada es peor que no enseñarla.
353
+ */
354
+ const capsForMember = (member) => (member?.cn ? ['secrets', ...CAPS_ORDER] : CAPS_ORDER)
355
+
343
356
  function capsRows (st, t) {
344
357
  const i = L(st)
345
358
  const target = st.capsFor
@@ -356,16 +369,19 @@ function capsRows (st, t) {
356
369
  { text: '', sel: false }
357
370
  ]
358
371
  let tocados = 0
359
- for (const cap of CAPS_ORDER) {
372
+ for (const cap of capsForMember(member)) {
360
373
  const mark = has.has(cap) ? '[x]' : '[ ]'
361
- const name = i.capName[cap]
374
+ // El nombre de `secrets` lleva el cajón dentro: «las claves de proxy» dice qué abre,
375
+ // «lee sus claves» te deja preguntándote cuáles.
376
+ const name = typeof i.capName[cap] === 'function' ? i.capName[cap](member.cn) : i.capName[cap]
362
377
  // LO QUE CAMBIA SE SEÑALA. Sin esto el borrador es indistinguible del acta y no sabes
363
378
  // qué vas a firmar — que es justo lo que hace peligroso acumular cambios.
364
379
  const cambia = has.has(cap) !== real.has(cap)
365
380
  if (cambia) tocados++
366
381
  const line = ` ${mark}${cambia ? t.bold('*') : ' '} ${cap === 'admin' ? t.bold(name) : name}`
367
382
  rows.push({ text: line, sel: true, meta: { cap } })
368
- rows.push({ text: t.muted(' ' + i.capHint[cap]), sel: false })
383
+ const hint = typeof i.capHint[cap] === 'function' ? i.capHint[cap](member.cn) : i.capHint[cap]
384
+ rows.push({ text: t.muted(' ' + hint), sel: false })
369
385
  }
370
386
  rows.push({ text: '', sel: false })
371
387
  rows.push({
@@ -1056,7 +1072,15 @@ async function onKeyCaps (term, st, key) {
1056
1072
  else salir()
1057
1073
  return true
1058
1074
  }
1059
- if (key.name === 'f5') { st.capsDraft = null; await refreshMembers(term, st); return true }
1075
+ if (key.name === 'f5') {
1076
+ // F5 PREGUNTA IGUAL QUE ESC. Refrescar trae el acta de nuevo y el borrador deja de
1077
+ // tener con qué compararse, así que hay que tirarlo — pero tirarlo callando es perder
1078
+ // trabajo sin decirlo, que es lo mismo que Esc ya no hace.
1079
+ const refrescar = async () => { st.capsDraft = null; await refreshMembers(term, st) }
1080
+ if (sucio) setConfirm(st, { text: i.capsDiscard, onYes: refrescar })
1081
+ else await refrescar()
1082
+ return true
1083
+ }
1060
1084
 
1061
1085
  // GUARDAR: UNA sola acta con todo lo que hayas tocado.
1062
1086
  if (ch === 'g') {
package/src/tui/i18n.js CHANGED
@@ -46,6 +46,9 @@ const es = {
46
46
  capsNothing: 'No has cambiado nada',
47
47
  capsDiscard: '¿Descartar los cambios sin guardar?',
48
48
  capName: {
49
+ // Lleva el cajón dentro: «las claves de proxy» dice QUÉ abre; «lee sus claves» te deja
50
+ // preguntándote cuáles. Solo se le ofrece a un servicio (los que tienen `cn`).
51
+ secrets: (cn) => `Leer las claves de «${cn}»`,
49
52
  sign: 'Firmar como tú',
50
53
  store: 'Guardar tus datos',
51
54
  read: 'Leer tus datos',
@@ -56,6 +59,7 @@ const es = {
56
59
  unattended: 'Recibir claves sin aprobación'
57
60
  },
58
61
  capHint: {
62
+ secrets: (cn) => `abrir SU cajón y ninguno más: las variables de «${cn}»`,
59
63
  sign: 'usar tu identidad en las apps del ecosistema',
60
64
  store: 'escribir en tu bóveda (perfil, contenido, datos sensibles)',
61
65
  read: 'ver lo que guardaste',
@@ -362,6 +366,7 @@ const en = {
362
366
  capsNothing: 'You have not changed anything',
363
367
  capsDiscard: 'Discard the unsaved changes?',
364
368
  capName: {
369
+ secrets: (cn) => `Read the «${cn}» keys`,
365
370
  sign: 'Sign as you',
366
371
  store: 'Save your data',
367
372
  read: 'Read your data',