@dotrino/vaultd 0.26.2 → 0.46.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/src/tui/i18n.js CHANGED
@@ -37,7 +37,7 @@ const es = {
37
37
  tabMe: 'Perfil',
38
38
  // PERMISOS de un dispositivo (§9.1: se dice el beneficio, no el scope del cert).
39
39
  titleCaps: 'Permisos del dispositivo',
40
- capsFor: (id, nombre) => `Permisos de ${id}${nombre ? ' · ' + nombre : ''}`,
40
+ capsFor: (id, name) => `Permisos de ${id}${name ? ' · ' + name : ''}`,
41
41
  capsNoMember: ' (este dispositivo ya no está en el acta)',
42
42
  capsApplyHint: 'Enter marca o desmarca. Cada cambio se aplica y se avisa a tus otros aparatos.',
43
43
  capName: {
@@ -63,7 +63,7 @@ const es = {
63
63
  loadingProfile: 'Cargando el perfil…',
64
64
  noProfile: ' (esta bóveda todavía no tiene perfil)',
65
65
  noProfileHint: ' Edita tu nombre o tu foto en un dispositivo emparejado y pulsa F5.',
66
- profileUpdated: (cuando) => ` actualizado ${cuando}`,
66
+ profileUpdated: (when) => ` actualizado ${when}`,
67
67
  fieldName: 'nombre',
68
68
  fieldPhoto: 'foto',
69
69
  fieldFirstName: 'nombres',
@@ -74,7 +74,6 @@ const es = {
74
74
  links: 'Enlaces',
75
75
  otherData: 'Otros datos',
76
76
  hidden: ' (oculto)',
77
- noName: '(sin nombre)',
78
77
  no: 'no',
79
78
  helpMe: ['←→ pestaña', 'F5 refrescar', 'Esc bóvedas', 'l English', 'q salir'],
80
79
  tabsHint: ' (←→ cambiar)',
@@ -84,10 +83,12 @@ const es = {
84
83
 
85
84
  // bóvedas (perfiles)
86
85
  noPassword: 'sin clave',
86
+ noPasswordWarn: 'Este perfil no tiene contraseña: una copia de este disco abre las variables privadas.',
87
+ pendingSeal: (owner, kind, who) => kind === 'rotate' ? `${owner}: sin rotar (salió un aparato). Guarda una variable con la contraseña.` : `${owner}: sin llave todavía en ${who}. Se reparte sola con otro aparato del grupo encendido, o al abrir la bóveda.`,
87
88
  locked: '🔒 bloqueada',
88
89
  unlocked: '🔓 abierta',
89
90
  passwordOf: (name) => `Contraseña de "${name}"`,
90
- passwordToEdit: 'necesaria para editar la bóveda',
91
+ passwordToEdit: 'necesaria para abrir la bóveda: sin ella no se ve ni se toca',
91
92
  unlocking: 'Desbloqueando…',
92
93
  loading: 'Cargando…',
93
94
  loadingDevices: 'Cargando dispositivos…',
@@ -110,7 +111,7 @@ const es = {
110
111
  deletingVault: 'Borrando bóveda…',
111
112
  vaultDeleted: 'Bóveda borrada',
112
113
  newPasswordLabel: (name) => `Contraseña nueva para "${name}" (mín. 4)`,
113
- passwordTooShort: 'La contraseña debe tener al menos 4 caracteres',
114
+ passwordTooShort: 'La contraseña debe tener al menos 12 caracteres: usa varias palabras al azar',
114
115
  repeatPassword: 'Repite la contraseña',
115
116
  passwordMismatch: 'Las contraseñas no coinciden',
116
117
  savingPassword: 'Guardando contraseña…',
@@ -130,6 +131,7 @@ const es = {
130
131
  noLabel: '(sin etiqueta)',
131
132
  // Está en el acta y no puede entrar: o le retiraron el certificado, o se le venció.
132
133
  deviceNoAccess: 'SIN ACCESO — está en el acta pero no puede entrar',
134
+ deviceDebt: (n) => `no abre ${n}`,
133
135
  thisVault: 'esta bóveda (manda ella)',
134
136
  cantRemoveMaster: 'Esta bóveda es la que manda: no se quita a sí misma.',
135
137
  revokedCount: (n) => ` Revocados: ${n}`,
@@ -170,17 +172,58 @@ const es = {
170
172
  savingVar: 'Guardando variable…',
171
173
  varSaved: (ns, key) => `Guardado ${ns}/${key}`,
172
174
 
175
+ // CARGAR VARIAS DE UNA VEZ (tecla c). Una a una, cada variable es un cambio de
176
+ // configuración y el servicio se reinicia a media carga; juntas, se reinicia una vez.
177
+ loadLabel: (ns) => `Cargar varias en "${ns}"`,
178
+ loadHint: 'CLAVE=valor CLAVE2=valor2 · o la ruta de un archivo .env',
179
+ loadNoFile: (f) => `No se pudo leer ${f}`,
180
+ loadingVars: 'Cargando variables…',
181
+ loadedVars: (n, ns) => `${n} variables cargadas en ${ns} · un solo aviso de cambio`,
182
+ envErr: {
183
+ shape: (e) => `línea ${e.line}: no tiene la forma CLAVE=valor`,
184
+ key: (e) => `línea ${e.line}: «${e.key}» va en MAYUSCULAS_CON_GUION_BAJO`,
185
+ novalue: (e) => `línea ${e.line}: ${e.key} no tiene valor`,
186
+ dup: (e) => `línea ${e.line}: ${e.key} ya venía en la línea ${e.first}`,
187
+ empty: () => 'No hay ninguna variable que cargar'
188
+ },
189
+ loadNothing: 'No se cargó nada:',
190
+ varPublic: 'pública',
191
+ newVarPublicAsk: '¿Que su valor se pueda VER desde la consola remota? (las demás no salen de esta máquina)',
192
+ makePublicConfirm: '¿Dejar que su valor se vea desde la consola remota?',
193
+ changingVisibility: 'Cambiando visibilidad…',
194
+ nowPublic: 'Ahora su valor se puede ver desde la consola remota',
195
+ nowPrivate: 'Ahora su valor no sale de esta máquina',
196
+
197
+ // variables de UN aparato (Dispositivos → tecla e). Las del scope las comparten todos
198
+ // los aparatos que sirven ese namespace; estas las lee solo él, y le ganan.
199
+ titleDevVars: 'Variables del dispositivo',
200
+ devVarsFor: (id, name) => `Variables de ${id}${name ? ' · ' + name : ''}`,
201
+ devVarsService: (cn) => `servicio «${cn}» — solo las lee este aparato, y pisan a las del scope`,
202
+ noDevVars: '(sin variables propias — pulsa N para agregar la primera)',
203
+ devVarsOnlyServices: 'Solo un servicio lee variables, y este aparato no lo es',
204
+ devVarsElsewhere: 'Las variables de UN aparato se ponen en Dispositivos (tecla e).',
205
+ removeDevVarConfirm: (id, key) => `¿Quitar la variable ${key} de ${id}?`,
206
+
173
207
  // emparejamiento — la PREGUNTA es del vault, que es quien lo inicia
174
208
  pairModeIntro: 'Un dispositivo puede entrar a una cuenta que ya vive aquí, o estrenar una.',
175
209
  pairModeHere: (name) => `Entrar a esta cuenta: ${name}`,
176
210
  pairModeHereHint: 'el dispositivo pasa a ver y firmar lo de esta cuenta',
177
211
  pairModeNew: 'Estrenar una cuenta nueva en este vault',
178
212
  pairModeNewHint: 'se crea aquí, vacía, y el dispositivo entra a ELLA (las otras no se tocan)',
213
+ pairModeService: 'Conectar un servicio (proxy, geo…)',
214
+ pairModeServiceHint: 'entra a esta cuenta pero solo lee SUS variables: no firma ni ve tu contenido',
179
215
  pairModeAdopt: 'Adoptar la cuenta que trae el dispositivo',
180
216
  pairModeAdoptSoon: 'todavía no: el dispositivo aún no sabe entregar la suya',
217
+ serviceNsLabel: '¿Qué servicio es? (proxy, geo, results…)',
218
+ serviceNsHint: 'minúsculas, sin espacios; es el nombre con el que ese programa pide su configuración',
219
+ serviceNsBad: 'Nombre no válido: minúsculas, números y guiones (hasta 32)',
220
+ pairService: (ns) => `Este QR entrega un SERVICIO «${ns}»: solo podrá leer las variables de ${ns}.`,
181
221
  newAccountLabel: 'Nombre de la cuenta nueva',
182
222
  newAccountHint: 'nace vacía; el dispositivo será su primer invitado',
183
223
  accountCreated: (name) => `Cuenta creada: ${name}`,
224
+ discardingAccount: 'Descartando la cuenta…',
225
+ accountDiscarded: 'Cuenta descartada: nadie llegó a entrar en ella',
226
+ confirmDiscardAccount: 'La cuenta se creó para este emparejamiento y quedó vacía. ¿La descarto?',
184
227
  // Cuenta + vigencia en UNA línea: cada línea de cabecera es una fila menos de QR
185
228
  // visible antes de tener que hacer scroll.
186
229
  pairAccount: (name, min) => `Cuenta que se comparte: ${name} · válido ~${min} min`,
@@ -205,21 +248,36 @@ const es = {
205
248
  // La barra dice lo que se PUEDE hacer AHORA, no todo lo que existe: aprobar/rechazar solo
206
249
  // valen si hay alguien esperando, y renombrar/revocar solo si hay un aparato seleccionado.
207
250
  // Anunciar teclas muertas confunde y además las quema para otros usos.
208
- helpDevices: ({ pendiente, hayAparatos } = {}) => [
251
+ // `e variables` solo en un SERVICIO: es el único que las lee, así que en un teléfono
252
+ // era una tecla que solo sabía decir que no.
253
+ helpDevices: ({ pending, hasDevices, isService } = {}) => [
209
254
  '←→ pestaña', '↑↓', 'p emparejar',
210
- ...(pendiente ? ['a aprobar', 'x rechazar'] : []),
211
- ...(hayAparatos ? ['r renombrar', 'c permisos', 'v revocar'] : []),
255
+ ...(pending ? ['a aprobar', 'x rechazar'] : []),
256
+ ...(hasDevices ? ['r renombrar', 'c permisos'] : []),
257
+ ...(isService ? ['e variables'] : []),
258
+ ...(hasDevices ? ['v revocar'] : []),
212
259
  'F5 refrescar', 'Esc bóvedas', 'l English', 'q salir'
213
260
  ],
214
261
  renameDeviceLabel: (id) => `¿Cómo quieres llamar a ${id}?`,
215
262
  renameDeviceHint: 'el nombre con el que lo reconoces (Esc cancela)',
216
- renaming: 'Renombrando…',
217
263
  deviceRenamed: (n) => `Ahora se llama «${n}»`,
218
- helpSecrets: ({ haySecretos } = {}) => [
219
- '←→ pestaña', '↑↓', 'n nueva variable',
220
- ...(haySecretos ? ['x quitar (variable/scope)'] : []),
264
+ helpSecrets: ({ hasSecrets } = {}) => [
265
+ '←→ pestaña', '↑↓', 'n nueva variable', 'i cargar varias',
266
+ ...(hasSecrets ? ['v ver valor', 't pública/privada', 'x quitar (variable/scope)'] : []),
221
267
  'F5 refrescar', 'Esc bóvedas', 'l English', 'q salir'
222
268
  ],
269
+ helpDevVars: ({ hasVars } = {}) => [
270
+ '↑↓', 'n nueva variable', 'i cargar varias',
271
+ ...(hasVars ? ['v ver valor', 't pública/privada', 'x quitar'] : []),
272
+ 'F5 refrescar', 'Esc dispositivos', 'l English', 'q salir'
273
+ ],
274
+ // Ver el valor de una privada: lo único que la contraseña guarda en esta máquina.
275
+ revealTitle: 'Ver el valor',
276
+ revealAsk: 'Contraseña del perfil (para ver el valor)',
277
+ revealHint: 'sin ella no se puede abrir: es lo único que la guarda (Esc cancela)',
278
+ revealing: 'abriendo…',
279
+ revealed: (k, v) => `${k} = ${v}`,
280
+ revealNoPwd: 'Este perfil no tiene contraseña: se abre con la llave de esta máquina.',
223
281
  helpPairing: ['a aprobar', 'x rechazar', 'r reiniciar', '↑↓ scroll', 'Esc atrás', 'l English'],
224
282
  helpPairMode: ['↑↓', 'Enter elegir', 'Esc atrás', 'l English', 'q salir'],
225
283
 
@@ -246,6 +304,13 @@ const es = {
246
304
  errNotApplied: 'El daemon no aplicó el cambio (revisa los logs del servicio).',
247
305
  errNotDeleted: 'El daemon no borró la variable (revisa los logs del servicio).',
248
306
  errPairFailed: 'El daemon no inició el emparejamiento.',
307
+ // El código NO es la contraseña de la bóveda: son los seis dígitos que el aparato
308
+ // enseña en su pantalla. Si no coincide, la bóveda no firma nada y el aparato sigue
309
+ // esperando ahí, así que se puede volver a intentar con A.
310
+ errWrongCode: 'El código no coincide con el que muestra el dispositivo: no se emitió ningún certificado. Míralo otra vez y pulsa A.',
311
+ errProfileLocked: 'Bóveda bloqueada: ábrela con su contraseña',
312
+ errWrongPassword: (n) => `Contraseña incorrecta${n ? ` — van ${n} intentos fallidos` : ''}`,
313
+ errTooManyTries: (s) => `Demasiados intentos: espera ${s || '?'} s antes de volver a probar`,
249
314
  errMasterWithMembers: 'Esta bóveda es el Master de esta cuenta y hay otros dispositivos: pásale primero el Master a uno que esté conectado. Si la borras así, se quedan con su llave y sin nadie que pueda volver a firmar el acta.'
250
315
  }
251
316
 
@@ -260,7 +325,6 @@ const en = {
260
325
  daemonRunning: 'running',
261
326
  daemonStopped: 'STOPPED',
262
327
  activeVault: 'Active vault: ',
263
- noName: '(unnamed)',
264
328
  tooSmall: 'Terminal too small',
265
329
  tooSmallHint: (cols, rows) => `Resize to ≥ 24×9 (now ${cols}×${rows}).`,
266
330
 
@@ -268,7 +332,7 @@ const en = {
268
332
  tabSecrets: 'Scopes & variables',
269
333
  tabMe: 'Profile',
270
334
  titleCaps: 'Device permissions',
271
- capsFor: (id, nombre) => `Permissions for ${id}${nombre ? ' · ' + nombre : ''}`,
335
+ capsFor: (id, name) => `Permissions for ${id}${name ? ' · ' + name : ''}`,
272
336
  capsNoMember: ' (this device is no longer in the record)',
273
337
  capsApplyHint: 'Enter ticks or unticks. Each change applies and your other devices are told.',
274
338
  capName: {
@@ -292,7 +356,7 @@ const en = {
292
356
  loadingProfile: 'Loading profile…',
293
357
  noProfile: ' (this vault has no profile yet)',
294
358
  noProfileHint: ' Edit your name or photo on a paired device and press F5.',
295
- profileUpdated: (cuando) => ` updated ${cuando}`,
359
+ profileUpdated: (when) => ` updated ${when}`,
296
360
  fieldName: 'name',
297
361
  fieldPhoto: 'photo',
298
362
  fieldFirstName: 'first name',
@@ -312,10 +376,12 @@ const en = {
312
376
  titlePairMode: 'Pairing: which account does it join?',
313
377
 
314
378
  noPassword: 'no password',
379
+ noPasswordWarn: 'This profile has no password: a copy of this disk opens the private variables.',
380
+ pendingSeal: (owner, kind, who) => kind === 'rotate' ? `${owner}: not rotated (a device left). Save a variable with the password.` : `${owner}: no key yet on ${who}. It is handed out by another device of the group that is on, or when the vault is opened.`,
315
381
  locked: '🔒 locked',
316
382
  unlocked: '🔓 unlocked',
317
383
  passwordOf: (name) => `Password for "${name}"`,
318
- passwordToEdit: 'needed to edit this vault',
384
+ passwordToEdit: 'needed to open this vault: without it, nothing is shown or touched',
319
385
  unlocking: 'Unlocking…',
320
386
  loading: 'Loading…',
321
387
  loadingDevices: 'Loading devices…',
@@ -338,7 +404,7 @@ const en = {
338
404
  deletingVault: 'Deleting vault…',
339
405
  vaultDeleted: 'Vault deleted',
340
406
  newPasswordLabel: (name) => `New password for "${name}" (min. 4)`,
341
- passwordTooShort: 'The password must be at least 4 characters',
407
+ passwordTooShort: 'The password must be at least 12 characters: use several random words',
342
408
  repeatPassword: 'Repeat the password',
343
409
  passwordMismatch: 'The passwords do not match',
344
410
  savingPassword: 'Saving password…',
@@ -356,6 +422,7 @@ const en = {
356
422
  noDevices: ' (no devices enrolled — press P to pair one)',
357
423
  noLabel: '(no label)',
358
424
  deviceNoAccess: 'NO ACCESS — it is on the record but cannot get in',
425
+ deviceDebt: (n) => `cannot open ${n}`,
359
426
  thisVault: 'this vault (it is the Master)',
360
427
  cantRemoveMaster: 'This vault is the Master: it does not remove itself.',
361
428
  revokedCount: (n) => ` Revoked: ${n}`,
@@ -395,16 +462,54 @@ const en = {
395
462
  savingVar: 'Saving variable…',
396
463
  varSaved: (ns, key) => `Saved ${ns}/${key}`,
397
464
 
465
+ loadLabel: (ns) => `Load several into "${ns}"`,
466
+ loadHint: 'KEY=value KEY2=value2 · or the path to a .env file',
467
+ loadNoFile: (f) => `Could not read ${f}`,
468
+ loadingVars: 'Loading variables…',
469
+ loadedVars: (n, ns) => `${n} variables loaded into ${ns} · a single change notice`,
470
+ envErr: {
471
+ shape: (e) => `line ${e.line}: not in the form KEY=value`,
472
+ key: (e) => `line ${e.line}: "${e.key}" must be UPPERCASE_WITH_UNDERSCORES`,
473
+ novalue: (e) => `line ${e.line}: ${e.key} has no value`,
474
+ dup: (e) => `line ${e.line}: ${e.key} already came on line ${e.first}`,
475
+ empty: () => 'There is no variable to load'
476
+ },
477
+ loadNothing: 'Nothing was loaded:',
478
+ varPublic: 'public',
479
+ newVarPublicAsk: 'Let its value be SEEN from the remote console? (the rest never leave this machine)',
480
+ makePublicConfirm: 'Let its value be seen from the remote console?',
481
+ changingVisibility: 'Changing visibility…',
482
+ nowPublic: 'Its value can now be seen from the remote console',
483
+ nowPrivate: 'Its value no longer leaves this machine',
484
+
485
+ // variables de UN aparato (Dispositivos → tecla e)
486
+ titleDevVars: 'Device variables',
487
+ devVarsFor: (id, name) => `Variables of ${id}${name ? ' · ' + name : ''}`,
488
+ devVarsService: (cn) => `“${cn}” service — only this device reads them, and they override the scope ones`,
489
+ noDevVars: '(no variables of its own — press N to add the first one)',
490
+ devVarsOnlyServices: 'Only a service reads variables, and this device is not one',
491
+ devVarsElsewhere: 'Variables for ONE device are set in Devices (key e).',
492
+ removeDevVarConfirm: (id, key) => `Remove variable ${key} from ${id}?`,
493
+
398
494
  pairModeIntro: 'A device can join an account that already lives here, or start a new one.',
399
495
  pairModeHere: (name) => `Join this account: ${name}`,
400
496
  pairModeHereHint: 'the device gets to see and sign for this account',
401
497
  pairModeNew: 'Start a new account in this vault',
402
498
  pairModeNewHint: 'created here, empty, and the device joins THAT one (the others are untouched)',
499
+ pairModeService: 'Connect a service (proxy, geo…)',
500
+ pairModeServiceHint: 'joins this account but only reads ITS variables: it neither signs nor sees your content',
403
501
  pairModeAdopt: 'Adopt the account the device brings',
404
502
  pairModeAdoptSoon: 'not yet: the device cannot hand its own over',
503
+ serviceNsLabel: 'Which service is it? (proxy, geo, results…)',
504
+ serviceNsHint: 'lowercase, no spaces; it is the name that program uses to ask for its settings',
505
+ serviceNsBad: 'Invalid name: lowercase letters, digits and dashes (up to 32)',
506
+ pairService: (ns) => `This QR hands out a SERVICE “${ns}”: it will only read ${ns}’s variables.`,
405
507
  newAccountLabel: 'Name of the new account',
406
508
  newAccountHint: 'born empty; the device will be its first guest',
407
509
  accountCreated: (name) => `Account created: ${name}`,
510
+ discardingAccount: 'Discarding the account…',
511
+ accountDiscarded: 'Account discarded: nobody got to join it',
512
+ confirmDiscardAccount: 'The account was created for this pairing and is empty. Discard it?',
408
513
  pairAccount: (name, min) => `Account being shared: ${name} · valid ~${min} min`,
409
514
  pairScan: 'Scan it, or open this address on the device:',
410
515
  pairUrl: 'URL: ',
@@ -419,21 +524,33 @@ const en = {
419
524
  helpConfirm: 'y confirm · n/Esc cancel',
420
525
 
421
526
  helpProfiles: ['↑↓', 'Enter open', 'p pair', 'n new', 'r rename', 'd delete', 'c password', 'x drop-password', 'u unlock', 'k lock', 'l Español', 'q quit'],
422
- helpDevices: ({ pendiente, hayAparatos } = {}) => [
527
+ helpDevices: ({ pending, hasDevices, isService } = {}) => [
423
528
  '←→ tab', '↑↓', 'p pair',
424
- ...(pendiente ? ['a approve', 'x reject'] : []),
425
- ...(hayAparatos ? ['r rename', 'c permissions', 'v revoke'] : []),
529
+ ...(pending ? ['a approve', 'x reject'] : []),
530
+ ...(hasDevices ? ['r rename', 'c permissions'] : []),
531
+ ...(isService ? ['e variables'] : []),
532
+ ...(hasDevices ? ['v revoke'] : []),
426
533
  'F5 refresh', 'Esc vaults', 'l Español', 'q quit'
427
534
  ],
428
535
  renameDeviceLabel: (id) => `What do you want to call ${id}?`,
429
536
  renameDeviceHint: 'the name you recognise it by (Esc cancels)',
430
- renaming: 'Renaming…',
431
537
  deviceRenamed: (n) => `Now called "${n}"`,
432
- helpSecrets: ({ haySecretos } = {}) => [
433
- '←→ tab', '↑↓', 'n new variable',
434
- ...(haySecretos ? ['x remove (variable/scope)'] : []),
538
+ helpSecrets: ({ hasSecrets } = {}) => [
539
+ '←→ tab', '↑↓', 'n new variable', 'i load several',
540
+ ...(hasSecrets ? ['v show value', 't public/private', 'x remove (variable/scope)'] : []),
435
541
  'F5 refresh', 'Esc vaults', 'l Español', 'q quit'
436
542
  ],
543
+ helpDevVars: ({ hasVars } = {}) => [
544
+ '↑↓', 'n new variable', 'i load several',
545
+ ...(hasVars ? ['v show value', 't public/private', 'x remove'] : []),
546
+ 'F5 refresh', 'Esc devices', 'l Español', 'q quit'
547
+ ],
548
+ revealTitle: 'Show the value',
549
+ revealAsk: 'Profile password (to show the value)',
550
+ revealHint: 'without it there is no way to open it: it is the only thing guarding it (Esc cancels)',
551
+ revealing: 'opening…',
552
+ revealed: (k, v) => `${k} = ${v}`,
553
+ revealNoPwd: 'This profile has no password: it opens with this machine key.',
437
554
  helpPairing: ['a approve', 'x reject', 'r restart', '↑↓ scroll', 'Esc back', 'l Español'],
438
555
  helpPairMode: ['↑↓', 'Enter choose', 'Esc back', 'l Español', 'q quit'],
439
556
 
@@ -458,6 +575,10 @@ const en = {
458
575
  errNotApplied: 'The daemon did not apply the change (check the service logs).',
459
576
  errNotDeleted: 'The daemon did not delete the variable (check the service logs).',
460
577
  errPairFailed: 'The daemon did not start the pairing.',
578
+ errWrongCode: 'The code does not match the one shown by the device: no certificate was issued. Check it and press A again.',
579
+ errProfileLocked: 'Vault locked: open it with its password',
580
+ errWrongPassword: (n) => `Wrong password${n ? ` — ${n} failed attempts so far` : ''}`,
581
+ errTooManyTries: (s) => `Too many attempts: wait ${s || '?'} s before trying again`,
461
582
  errMasterWithMembers: 'This vault is the Master of this account and it has other devices: hand the Master over to one that is online first. If you delete it like this, they keep their key with nobody able to sign the record again.'
462
583
  }
463
584