@dotrino/vaultd 0.15.0 → 0.16.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dotrino/vaultd",
3
- "version": "0.15.0",
3
+ "version": "0.16.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/ctl.js CHANGED
@@ -257,18 +257,14 @@ function cmdReject (deviceId) {
257
257
  * Distinto de `members` (quién es del perfil) y de `profile` (los perfiles del PC): esto
258
258
  * es el CONTENIDO, no la identidad.
259
259
  *
260
- * La foto no se imprime es un data-URI de hasta ~90 KB— sino que se resume;
261
- * `me --foto <archivo>` la escribe en disco para poder mirarla.
260
+ * De la foto solo se dice que la hay, de qué tipo y cuánto pesa: es un data-URI de hasta
261
+ * ~90 KB y una terminal no es sitio para volcarlo.
262
262
  */
263
- async function cmdMe (args = []) {
264
- const i = args.findIndex((a) => a === '--foto' || a === '--photo')
265
- const avatarPath = i >= 0 ? args[i + 1] : null
266
- if (i >= 0 && !avatarPath) { console.error('uso: dotrino-vault me --foto <archivo>'); process.exit(2) }
267
-
263
+ async function cmdMe () {
268
264
  const s = requireDaemon()
269
265
  const meFile = path.join(dir, 'me.json')
270
266
  try { fs.rmSync(meFile, { force: true }) } catch (_) {}
271
- writeReq('me-request.json', { ...(avatarPath ? { avatarPath: path.resolve(avatarPath) } : {}) })
267
+ writeReq('me-request.json', {})
272
268
  avisar(s.pid, 'SIGUSR2')
273
269
  let dump = null
274
270
  for (let n = 0; n < 50; n++) { await sleep(100); const d = readJson(meFile, null); if (d?.at) { dump = d; break } }
@@ -306,8 +302,6 @@ async function cmdMe (args = []) {
306
302
  for (const x of lista) console.log(' %s %s%s', (x.type || x.label || '').padEnd(12), x.value, x.visible === false ? ' (oculto)' : '')
307
303
  }
308
304
 
309
- if (dump.avatarGuardada) console.log('\n Foto escrita en: %s', dump.avatarGuardada)
310
- else if (me.avatar) console.log('\n Para verla: dotrino-vault me --foto ~/perfil.png')
311
305
  console.log('')
312
306
  }
313
307
 
@@ -691,7 +685,7 @@ export async function runCtl (argv) {
691
685
  case 'approve': return cmdApprove(rest[0])
692
686
  case 'reject': return cmdReject(rest[0])
693
687
  case 'devices': return cmdDevices()
694
- case 'me': return cmdMe(rest)
688
+ case 'me': return cmdMe()
695
689
  case 'members': return cmdMembers()
696
690
  case 'caps': return cmdCaps(rest)
697
691
  case 'revoke': return cmdRevoke(rest[0])
package/src/daemon.js CHANGED
@@ -257,7 +257,7 @@ export async function runDaemon () {
257
257
  // Solo se vuelca cuando se PIDE, no en cada señal: es contenido del usuario y no tiene
258
258
  // por qué quedar escrito en un archivo suelto cada vez que alguien mira los miembros.
259
259
  // La FOTO no entra en el volcado (son hasta ~90 KB de data-URI que nadie va a leer en
260
- // una terminal): se resume, y si la quieres, `--foto <archivo>` la escribe donde digas.
260
+ // una terminal): solo se dice que la hay, de qué tipo y cuánto pesa.
261
261
  const meReq = readJsonSafe(meReqFile)
262
262
  if (meReq) {
263
263
  rm(meReqFile)
@@ -265,15 +265,7 @@ export async function runDaemon () {
265
265
  const tm = resolveTarget(meReq) || { id: mgr.currentId(), vault: mgr.current() }
266
266
  const { me } = tm.vault.threads.methods.profileGet()
267
267
  const { avatar, ...resto } = me || {}
268
- let guardada = null
269
- if (meReq.avatarPath && typeof avatar === 'string') {
270
- const m = /^data:([^;,]+)?(?:;base64)?,(.*)$/s.exec(avatar)
271
- if (m) {
272
- fs.writeFileSync(meReq.avatarPath, Buffer.from(m[2], 'base64'), { mode: 0o600 })
273
- guardada = meReq.avatarPath
274
- }
275
- }
276
- writeJson(meFile, { v: 1, at: Date.now(), profile: tm.id, me: me ? { ...resto, avatar: avatarInfo(avatar) } : null, avatarGuardada: guardada })
268
+ writeJson(meFile, { v: 1, at: Date.now(), profile: tm.id, me: me ? { ...resto, avatar: avatarInfo(avatar) } : null })
277
269
  } catch (e) { console.error('[vault] could not dump the profile:', e.message) }
278
270
  }
279
271
  } catch (e) {
package/src/tui/app.js CHANGED
@@ -268,7 +268,6 @@ function meRows (st, t) {
268
268
  rows.push({ text: t.accent(' ▸ ' + titulo), sel: false })
269
269
  for (const x of lista) campo(x.type || x.label || '', x.value, x.visible === false)
270
270
  }
271
- if (me.avatar) { rows.push({ text: '', sel: false }); rows.push({ text: t.muted(i.savePhotoHint), sel: false }) }
272
271
  return rows
273
272
  }
274
273
 
@@ -603,27 +602,11 @@ async function onKeyPairing (term, st, key) {
603
602
  }
604
603
 
605
604
  /**
606
- * Teclas del PERFIL: refrescar y guardar la foto. Nada de editar — el perfil se edita en
607
- * el dispositivo que usas, no en la máquina donde vive la bóveda.
605
+ * Teclas del PERFIL: solo refrescar. Nada de editar — el perfil se edita en el dispositivo
606
+ * que usas, no en la máquina donde vive la bóveda.
608
607
  */
609
608
  async function onKeyMe (term, st, key) {
610
- const i = L(st)
611
- const ch = key.name === 'char' ? key.ch.toLowerCase() : null
612
- if (ch === 'r') {
613
- await refreshMe(term, st)
614
- } else if (ch === 'f' && st.me?.avatar) {
615
- setInput(st, {
616
- label: i.savePhotoLabel,
617
- hint: i.savePhotoHintInput,
618
- value: 'perfil.png',
619
- onSubmit: async (valor) => {
620
- const destino = String(valor || '').trim()
621
- if (!destino) return
622
- const r = await guard(term, st, i.savingPhoto, () => vc.saveAvatar(destino, activeId(st)))
623
- if (r.ok && r.v) flash(st, i.photoSaved(r.v))
624
- }
625
- })
626
- }
609
+ if (key.name === 'char' && key.ch.toLowerCase() === 'r') await refreshMe(term, st)
627
610
  return true
628
611
  }
629
612
 
package/src/tui/i18n.js CHANGED
@@ -53,12 +53,7 @@ const es = {
53
53
  hidden: ' (oculto)',
54
54
  noName: '(sin nombre)',
55
55
  no: 'no',
56
- savePhotoHint: ' Pulsa F para guardar la foto y poder verla.',
57
- savePhotoLabel: '¿Dónde guardo la foto?',
58
- savePhotoHintInput: 'ruta del archivo (Esc cancela)',
59
- savingPhoto: 'Guardando la foto…',
60
- photoSaved: (ruta) => `Foto guardada en ${ruta}`,
61
- helpMe: ['←→ pestaña', 'r refrescar', 'f guardar foto', 'Esc bóvedas', 'l English', 'q salir'],
56
+ helpMe: ['←→ pestaña', 'r refrescar', 'Esc bóvedas', 'l English', 'q salir'],
62
57
  tabsHint: ' (←→ cambiar)',
63
58
  titleProfiles: 'Bóvedas',
64
59
  titlePairing: 'Emparejar un dispositivo',
@@ -245,12 +240,7 @@ const en = {
245
240
  hidden: ' (hidden)',
246
241
  noName: '(no name)',
247
242
  no: 'no',
248
- savePhotoHint: ' Press F to save the photo so you can look at it.',
249
- savePhotoLabel: 'Where should I save the photo?',
250
- savePhotoHintInput: 'file path (Esc cancels)',
251
- savingPhoto: 'Saving the photo…',
252
- photoSaved: (ruta) => `Photo saved to ${ruta}`,
253
- helpMe: ['←→ tab', 'r refresh', 'f save photo', 'Esc vaults', 'l Español', 'q quit'],
243
+ helpMe: ['←→ tab', 'r refresh', 'Esc vaults', 'l Español', 'q quit'],
254
244
  tabsHint: ' (←→ switch)',
255
245
  titleProfiles: 'Vaults',
256
246
  titlePairing: 'Pair a device',
@@ -234,17 +234,6 @@ export async function getMe (profile) {
234
234
  return d.me || null
235
235
  }
236
236
 
237
- /** Escribe la foto de perfil en `destino` (para poder mirarla) y devuelve la ruta. */
238
- export async function saveAvatar (destino, profile) {
239
- requireAlive()
240
- rm(F.me)
241
- writeReq(F.meReq, { avatarPath: destino }, profile)
242
- signalOrCleanup('SIGUSR2', [F.meReq])
243
- const d = await waitFor(F.me)
244
- rm(F.me)
245
- if (!d) throw coded('the daemon did not reply', 'NO_REPLY')
246
- return d.avatarGuardada || null
247
- }
248
237
 
249
238
  // ---------------------------------------------------------------------------
250
239
  // Secretos: scopes (namespaces) y variables (claves)