@dotrino/vaultd 0.93.0 → 0.93.1
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 +1 -1
- package/src/ctl.js +5 -5
- package/src/vault.js +31 -31
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dotrino/vaultd",
|
|
3
|
-
"version": "0.93.
|
|
3
|
+
"version": "0.93.1",
|
|
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
|
@@ -573,7 +573,7 @@ async function cmdMembers () {
|
|
|
573
573
|
m.addedAt ? ` ${D}· conectado el ${fechaCorta(m.addedAt)}${Z}` : '',
|
|
574
574
|
marks.length ? ' [' + marks.join(' · ') + ']' : '', caps)
|
|
575
575
|
// Un servicio SIN llave de cifrado no puede leer ninguna variable privada: van
|
|
576
|
-
// selladas a esa llave. Se dice aquí, junto a él, porque es el único sitio
|
|
576
|
+
// selladas a esa llave. Se dice aquí, junto a él, porque es el único sitio donde
|
|
577
577
|
// se mira quién es quién — y en la lista de variables ya seria tarde.
|
|
578
578
|
if (m.cn && !m.canSeal) console.log(' %ssin llave de cifrado: NO puede leer sus variables%s', R, Z)
|
|
579
579
|
}
|
|
@@ -820,11 +820,11 @@ function cmdAtrest (rest) {
|
|
|
820
820
|
// versión vieja dejó en claro, con el verificador de la contraseña dentro— meses
|
|
821
821
|
// después de que su migración terminara. Se mira el perfil Y la raíz, porque el canal
|
|
822
822
|
// local con la CLI vive arriba.
|
|
823
|
-
for (const [
|
|
823
|
+
for (const [label, d] of [['este perfil', dir], ['la raíz de la bóveda', vaultRoot]]) {
|
|
824
824
|
const loose = plaintextFilesIn(d)
|
|
825
825
|
if (loose.length) {
|
|
826
826
|
console.log('')
|
|
827
|
-
console.log(`${R}En claro en ${
|
|
827
|
+
console.log(`${R}En claro en ${label}:${Z} ` + loose.join(', '))
|
|
828
828
|
console.log(' Si es un respaldo de una migración terminada, bórralo: no lo cifra nadie.')
|
|
829
829
|
}
|
|
830
830
|
}
|
|
@@ -958,7 +958,7 @@ function cmdActivity (n = 30) {
|
|
|
958
958
|
/**
|
|
959
959
|
* `KEY=valor KEY2=valor2` — la forma de CARGAR VARIAS de una vez. Devuelve `null` si no
|
|
960
960
|
* son todos pares, para que la forma clásica de tres argumentos (`set ns CLAVE valor`,
|
|
961
|
-
*
|
|
961
|
+
* donde el valor puede llevar espacios y hasta un `=`) siga funcionando igual.
|
|
962
962
|
*/
|
|
963
963
|
function asPairs (args) {
|
|
964
964
|
if (!args.length) return null
|
|
@@ -1395,7 +1395,7 @@ function reportProfiles (d) {
|
|
|
1395
1395
|
async function cmdProfile (rest) {
|
|
1396
1396
|
const [sub, ...rawArgs] = rest
|
|
1397
1397
|
// `--kms <archivo>` se saca ANTES de armar el nombre: el nombre se compone juntando
|
|
1398
|
-
// los argumentos
|
|
1398
|
+
// los argumentos sueltos, así que si no se quita acabaría llamándose «midevault --kms
|
|
1399
1399
|
// cfg.json».
|
|
1400
1400
|
const kmsAt = rawArgs.indexOf('--kms')
|
|
1401
1401
|
const kmsFile = kmsAt !== -1 ? rawArgs[kmsAt + 1] : null
|
package/src/vault.js
CHANGED
|
@@ -119,7 +119,7 @@ export async function startVault ({ dir = dataDir(), proxyUrl, log = console.log
|
|
|
119
119
|
* Lo dice el ACTA, con el permiso `unattended`: quien lo tiene se las lleva solo; quien
|
|
120
120
|
* no, espera a que un aparato con `approve` lo firme.
|
|
121
121
|
*
|
|
122
|
-
* Antes era al revés y vivía aquí: una
|
|
122
|
+
* Antes era al revés y vivía aquí: una lista local de «estos SÍ piden permiso», así que
|
|
123
123
|
* un aparato nuevo nacía pudiendo llevarse las claves y nadie elegía eso — se elegía por
|
|
124
124
|
* omisión. Ahora hay que conceder a propósito quién puede llevárselas solo, y **si falta
|
|
125
125
|
* el dato se pide permiso**, que es lo que hay que hacer cuando no se sabe (dueño,
|
|
@@ -135,7 +135,7 @@ export async function startVault ({ dir = dataDir(), proxyUrl, log = console.log
|
|
|
135
135
|
}
|
|
136
136
|
// LA BÓVEDA DE CONTRASEÑAS: entradas y su llave, en el dir del perfil y cifradas en
|
|
137
137
|
// reposo como todo lo demás. QUIÉN PUEDE PEDIR LO DICE EL ACTA (capacidad
|
|
138
|
-
// `passwords`), como cualquier otro permiso: aquí no hay una segunda
|
|
138
|
+
// `passwords`), como cualquier otro permiso: aquí no hay una segunda lista de
|
|
139
139
|
// aparatos. Tenerla obligaba a acordarse de dos sitios al quitar un aparato, y era
|
|
140
140
|
// además un emparejamiento paralelo al del ecosistema.
|
|
141
141
|
const passwordsFile = path.join(dir, 'passwords.json')
|
|
@@ -464,7 +464,7 @@ export async function startVault ({ dir = dataDir(), proxyUrl, log = console.log
|
|
|
464
464
|
*
|
|
465
465
|
* Sustituye a `trustedIssuer: master`, que comparaba contra UNA llave fija y por eso el
|
|
466
466
|
* multivault no podía existir — una segunda selladora sellaba el acta y luego sus papeles
|
|
467
|
-
* los rechazaban los diez mostradores. Ahora se compara contra la
|
|
467
|
+
* los rechazaban los diez mostradores. Ahora se compara contra la lista que dice el acta.
|
|
468
468
|
*
|
|
469
469
|
* Sin acta se devuelven nulos a propósito: `verifyDelegation` responde `no-acta` y el
|
|
470
470
|
* mostrador deniega. Es lo contrario de un repliegue — no hay con qué decidir, así que no
|
|
@@ -664,7 +664,7 @@ export async function startVault ({ dir = dataDir(), proxyUrl, log = console.log
|
|
|
664
664
|
* exactamente lo que el acta nombra, así que decir quién pregunta no necesita más.
|
|
665
665
|
*
|
|
666
666
|
* La respuesta es sí o no, y nada más: al que sigue dentro no se le manda el acta —no la
|
|
667
|
-
* pidió, y contarle el perfil entero a quien no trae papel es
|
|
667
|
+
* pidió, y contarle el perfil entero a quien no trae papel es attach de más—. Al que ya no
|
|
668
668
|
* está se le manda el aviso FIRMADO de expulsión, que es lo único que le borra la cuenta.
|
|
669
669
|
* Que un desconocido pregunte no cuesta nada: lo que se le puede contestar es un aviso a
|
|
670
670
|
* nombre de SU propia llave, que no le sirve contra nadie más (`verifyRevoke` exige que
|
|
@@ -710,7 +710,7 @@ export async function startVault ({ dir = dataDir(), proxyUrl, log = console.log
|
|
|
710
710
|
audit('devices', { device: await deviceIdOf(chk.device).catch(() => null), solo: 'revocaciones' })
|
|
711
711
|
return reply(from, { type: MSG.DEVICES_RESULT, devices: [], revoked, acta: record })
|
|
712
712
|
}
|
|
713
|
-
// El acta viaja con la
|
|
713
|
+
// El acta viaja con la lista: así cada dispositivo se entera de los cambios de
|
|
714
714
|
// política (quién manda, quién puede qué) sin un canal aparte.
|
|
715
715
|
// Si el dispositivo estuvo apagado y viene con un `seq` viejo, se le manda la CADENA
|
|
716
716
|
// que falta (ventana de retención, §1.3) para que compruebe el encadenamiento en vez
|
|
@@ -728,7 +728,7 @@ export async function startVault ({ dir = dataDir(), proxyUrl, log = console.log
|
|
|
728
728
|
}
|
|
729
729
|
// `sub` (pubkey completa) va incluida: es la DIRECCIÓN de cada dispositivo en el
|
|
730
730
|
// proxy → permite a las apps AUTODESCUBRIR tus máquinas (p. ej. la terminal
|
|
731
|
-
//
|
|
731
|
+
// lista tus agentes sin pegar nada). Solo la ve quien presenta un cert tuyo válido.
|
|
732
732
|
const devices = await Promise.all(issued.map(async (x) => ({
|
|
733
733
|
deviceId: x.sub ? await deviceIdOf(x.sub) : null, sub: x.sub || null, label: x.label || '', scope: x.scope, exp: x.exp, nonce: x.nonce
|
|
734
734
|
})))
|
|
@@ -773,7 +773,7 @@ export async function startVault ({ dir = dataDir(), proxyUrl, log = console.log
|
|
|
773
773
|
const prev = (issued || []).find((x) => x.nonce === p.cert.nonce)
|
|
774
774
|
// EL SCOPE SALE DEL ACTA, no del cert viejo. El acta es la política (lo que el dueño
|
|
775
775
|
// decidió con `caps`); el cert es su reflejo, y solo dura 30 días para poder cambiar.
|
|
776
|
-
// Copiar `p.cert.scope` congelaba la política en el momento del emparejamiento:
|
|
776
|
+
// Copiar `p.cert.scope` congelaba la política en el momento del emparejamiento: attach
|
|
777
777
|
// `administra` no llegaba nunca al cert (la consola remota no podía funcionar) y
|
|
778
778
|
// QUITARLO tampoco surtía efecto hasta que el cert caducara, hasta un mes después.
|
|
779
779
|
// Si el miembro ya no está en el acta, no se renueva nada: lo echaron.
|
|
@@ -1059,7 +1059,7 @@ export async function startVault ({ dir = dataDir(), proxyUrl, log = console.log
|
|
|
1059
1059
|
* NUNCA. El pedido solo se veía si al dueño se le ocurría abrir la app por su cuenta.
|
|
1060
1060
|
*
|
|
1061
1061
|
* El aviso no lleva nada que no esté ya en el pedido, y el timbre que sale de aquí sigue
|
|
1062
|
-
* sin contenido: quien lo recibe pregunta por la
|
|
1062
|
+
* sin contenido: quien lo recibe pregunta por la lista, no la lee del aviso.
|
|
1063
1063
|
*/
|
|
1064
1064
|
async function notifyApprovers (pend, record) {
|
|
1065
1065
|
try {
|
|
@@ -1170,7 +1170,7 @@ export async function startVault ({ dir = dataDir(), proxyUrl, log = console.log
|
|
|
1170
1170
|
cek: await passwordsKey(),
|
|
1171
1171
|
// UNA sola condición, y es del ACTA: el aparato tiene la capacidad `passwords`.
|
|
1172
1172
|
// Quitársela —o quitar el aparato— le corta esto en la siguiente pasada, sin
|
|
1173
|
-
// que haya una segunda
|
|
1173
|
+
// que haya una segunda lista que acordarse de tocar.
|
|
1174
1174
|
isAllowed: (pub) => !!actaCache && Acta.memberCan(actaCache, pub, 'passwords'),
|
|
1175
1175
|
encPubOf: (pub) => (actaCache?.members || []).find((m) => m.pub === pub)?.encPub || null,
|
|
1176
1176
|
// EN VIVO, no del caché: conceder o quitar `unattended` tiene que surtir efecto en
|
|
@@ -1348,11 +1348,11 @@ export async function startVault ({ dir = dataDir(), proxyUrl, log = console.log
|
|
|
1348
1348
|
// Esto avisaba únicamente por `issued` —las delegaciones que emitió esta bóveda—, y
|
|
1349
1349
|
// eso deja fuera exactamente el caso del multivault: la segunda bóveda entró por
|
|
1350
1350
|
// `join`, así que la delegación la emitió la PRIMERA. Cuando la segunda sellaba un
|
|
1351
|
-
// acta nueva (admitir un aparato con su permiso `sella`), su
|
|
1351
|
+
// acta nueva (admitir un aparato con su permiso `sella`), su lista de emitidas no
|
|
1352
1352
|
// tenía a la primera dentro y el cambio no llegaba a ninguna parte: las dos bóvedas
|
|
1353
1353
|
// quedaban con actas distintas y la del dueño sin enterarse de nada.
|
|
1354
1354
|
//
|
|
1355
|
-
// El acta es la
|
|
1355
|
+
// El acta es la lista de quién es del perfil: esa es la lista correcta. `issued` se
|
|
1356
1356
|
// suma porque cubre a quien tiene cert y todavía no aparece ahí.
|
|
1357
1357
|
const miembros = (await identity.profileMembers?.().catch(() => null))?.members || []
|
|
1358
1358
|
const yo = identity.me?.publickey || null
|
|
@@ -1417,7 +1417,7 @@ export async function startVault ({ dir = dataDir(), proxyUrl, log = console.log
|
|
|
1417
1417
|
// podría abrirlas, porque su envoltura no existe. Dos cerrojos para lo mismo, a
|
|
1418
1418
|
// propósito: que uno falle no basta para leerlas.
|
|
1419
1419
|
//
|
|
1420
|
-
// Se sella la
|
|
1420
|
+
// Se sella la lista ENTERA, no solo los valores: el proxy tampoco tiene por qué
|
|
1421
1421
|
// aprender cómo se llaman tus variables ni qué servicios corres.
|
|
1422
1422
|
return {
|
|
1423
1423
|
enc: await identity.sealContent(JSON.stringify({
|
|
@@ -1438,7 +1438,7 @@ export async function startVault ({ dir = dataDir(), proxyUrl, log = console.log
|
|
|
1438
1438
|
}
|
|
1439
1439
|
},
|
|
1440
1440
|
/**
|
|
1441
|
-
* PARA QUIÉN ENVOLVER. Lo contesta la bóveda porque la
|
|
1441
|
+
* PARA QUIÉN ENVOLVER. Lo contesta la bóveda porque la lista sale del ACTA
|
|
1442
1442
|
* (`recipientsOf`), y tener dos sitios respondiendo a «quién puede abrir este cajón» es
|
|
1443
1443
|
* exactamente cómo se acaba dejando fuera a alguien sin que nadie se entere.
|
|
1444
1444
|
*/
|
|
@@ -1622,7 +1622,7 @@ export async function startVault ({ dir = dataDir(), proxyUrl, log = console.log
|
|
|
1622
1622
|
// listar y borrar no la piden (ver `secretsStore.js`).
|
|
1623
1623
|
/**
|
|
1624
1624
|
* Los miembros que deben poder abrir un cajón: los SERVICIOS de ese namespace
|
|
1625
|
-
* (miembros del acta con ese `cn`). La bóveda NO entra en la
|
|
1625
|
+
* (miembros del acta con ese `cn`). La bóveda NO entra en la lista — envolverle la
|
|
1626
1626
|
* CEK a ella misma sería devolverle la capacidad de leerlo todo, que es justo lo
|
|
1627
1627
|
* que este diseño quita.
|
|
1628
1628
|
*/
|
|
@@ -1630,7 +1630,7 @@ export async function startVault ({ dir = dataDir(), proxyUrl, log = console.log
|
|
|
1630
1630
|
const record = (await identity.profileActa?.().catch(() => null))?.acta
|
|
1631
1631
|
if (!record) return []
|
|
1632
1632
|
// LLEVAR EL `cn` NO ES PODER LEER. El acta manda también aquí: un miembro entra en la
|
|
1633
|
-
//
|
|
1633
|
+
// lista si además puede leer los secretos de ese cajón (`memberCanReadSecrets`).
|
|
1634
1634
|
//
|
|
1635
1635
|
// Sin esa segunda mitad, el `cn` era la única puerta y `cn` es un texto libre: la LLAVE
|
|
1636
1636
|
// DE COMUNICACIÓN de la bóveda entra en el acta con `cn: 'vault'` y `caps: ['sign']`,
|
|
@@ -1648,7 +1648,7 @@ export async function startVault ({ dir = dataDir(), proxyUrl, log = console.log
|
|
|
1648
1648
|
* ningún sitio, que es todo el punto del §8.2 — la capacidad de leer se muda de una
|
|
1649
1649
|
* frase que se escribe en cualquier parte a una llave que no sale del aparato.
|
|
1650
1650
|
*
|
|
1651
|
-
* La bóveda NO entra en la
|
|
1651
|
+
* La bóveda NO entra en la lista, ni aquí ni en `nsMembers`: envolverle la llave a
|
|
1652
1652
|
* ella misma sería devolverle la capacidad de leerlo todo, que es justo lo que este
|
|
1653
1653
|
* diseño quita. Hay un test que lo afirma.
|
|
1654
1654
|
*/
|
|
@@ -1841,7 +1841,7 @@ export async function startVault ({ dir = dataDir(), proxyUrl, log = console.log
|
|
|
1841
1841
|
* hay quien la teclee.
|
|
1842
1842
|
*
|
|
1843
1843
|
* Que no puedan leer es CORRECTO y no se relaja. Lo que se arregla aquí es que se
|
|
1844
|
-
* vea: hasta ahora un servicio recién enrolado aparecía en la
|
|
1844
|
+
* vea: hasta ahora un servicio recién enrolado aparecía en la lista como cualquier
|
|
1845
1845
|
* otro y arrancaba sin configuración, repitiendo un error en su propio log que nadie
|
|
1846
1846
|
* mira. Con esto, la consola y la TUI pueden decir exactamente qué falta y qué hacer
|
|
1847
1847
|
* (`dotrino-vault secret settle`, que sí pide la frase).
|
|
@@ -1860,7 +1860,7 @@ export async function startVault ({ dir = dataDir(), proxyUrl, log = console.log
|
|
|
1860
1860
|
// «Ver» de la consola le fallaría sin explicar por qué.
|
|
1861
1861
|
// Un aparato que administra NO debe tener envoltura de los cajones con dueño
|
|
1862
1862
|
// (`recipientsOf`), así que no se le cuenta como falta: lo que ahí falta es a
|
|
1863
|
-
// propósito y ponerlo en la
|
|
1863
|
+
// propósito y ponerlo en la lista sería pedir que se «arregle» lo correcto.
|
|
1864
1864
|
const ownedNs = new Set((record?.members || []).filter((x) => x.cn).map((x) => x.cn))
|
|
1865
1865
|
const drawers = m.cn
|
|
1866
1866
|
? [`ns:${m.cn}`, `dev:${m.pub}`]
|
|
@@ -1960,7 +1960,7 @@ export async function startVault ({ dir = dataDir(), proxyUrl, log = console.log
|
|
|
1960
1960
|
* único que la frase guarda (§8.3).
|
|
1961
1961
|
*
|
|
1962
1962
|
* No lanza: devuelve qué pasó con cada cajón, porque una deuda que no se puede saldar
|
|
1963
|
-
* tiene que seguir viéndose en la
|
|
1963
|
+
* tiene que seguir viéndose en la lista en vez de tumbar la operación entera.
|
|
1964
1964
|
*/
|
|
1965
1965
|
/**
|
|
1966
1966
|
* PIDE AL SERVICIO QUE REPARTA la llave de su cajón a un miembro nuevo (§8.11).
|
|
@@ -2236,8 +2236,8 @@ export async function startVault ({ dir = dataDir(), proxyUrl, log = console.log
|
|
|
2236
2236
|
const out = { drawers: 0, wrapped: 0, dropped: 0, sinLlave: [], failed: [] }
|
|
2237
2237
|
for (const owner of secrets.owners?.() || []) {
|
|
2238
2238
|
const before = new Set(secrets.recipientsIn(owner))
|
|
2239
|
-
// POR VISIBILIDAD, no una
|
|
2240
|
-
// administra. Con una sola
|
|
2239
|
+
// POR VISIBILIDAD, no una lista fija: una pública lleva además la envoltura de quien
|
|
2240
|
+
// administra. Con una sola lista se le daría también la de una privada con dueño, que
|
|
2241
2241
|
// es justo lo que no puede pasar.
|
|
2242
2242
|
const members = (esPublica) => recipientsOf(owner, { public: esPublica })
|
|
2243
2243
|
try {
|
|
@@ -2300,7 +2300,7 @@ export async function startVault ({ dir = dataDir(), proxyUrl, log = console.log
|
|
|
2300
2300
|
if (!owed) return null
|
|
2301
2301
|
// QUIÉN RECIBE ENVOLTURA LO DICE `recipientsOf`, Y SOLO ÉL.
|
|
2302
2302
|
//
|
|
2303
|
-
// Antes cada llamador traía su propia
|
|
2303
|
+
// Antes cada llamador traía su propia lista (`nsMembers`, o el miembro suelto), y todas
|
|
2304
2304
|
// se dejaban fuera a los SELLADORES — que `recipientsOf` sí incluye. Resultado: escribir
|
|
2305
2305
|
// una variable envolvía para el servicio y dejaba al sellador con la generación vieja
|
|
2306
2306
|
// (dueño, 2026-09-01: «al envolver hay que envolver siempre para todos los selladores,
|
|
@@ -2406,9 +2406,9 @@ export async function startVault ({ dir = dataDir(), proxyUrl, log = console.log
|
|
|
2406
2406
|
* pública, y no se puede leer. Eso es cierto y se arregla abriendo la bóveda; inventarse
|
|
2407
2407
|
* un valor o esconder la fila sería peor.
|
|
2408
2408
|
*/
|
|
2409
|
-
const withEnvelopes = (
|
|
2410
|
-
if (!caller) return
|
|
2411
|
-
const
|
|
2409
|
+
const withEnvelopes = (entries, kind, caller) => {
|
|
2410
|
+
if (!caller) return entries
|
|
2411
|
+
const attach = (owner, k) => {
|
|
2412
2412
|
if (!k.public) return k
|
|
2413
2413
|
const e = secrets.entryOf?.(owner, k.key)
|
|
2414
2414
|
const wrap = e?.gen != null ? secrets.wrapOf?.(owner, e.gen, caller) : null
|
|
@@ -2416,10 +2416,10 @@ export async function startVault ({ dir = dataDir(), proxyUrl, log = console.log
|
|
|
2416
2416
|
}
|
|
2417
2417
|
if (kind === 'ns') {
|
|
2418
2418
|
const out = {}
|
|
2419
|
-
for (const [ns, keys] of Object.entries(
|
|
2419
|
+
for (const [ns, keys] of Object.entries(entries)) out[ns] = keys.map((k) => attach(`ns:${ns}`, k))
|
|
2420
2420
|
return out
|
|
2421
2421
|
}
|
|
2422
|
-
return
|
|
2422
|
+
return entries.map((row) => ({ ...row, keys: row.keys.map((k) => attach(`dev:${row.pub}`, k)) }))
|
|
2423
2423
|
}
|
|
2424
2424
|
|
|
2425
2425
|
function listSecrets () {
|
|
@@ -2549,10 +2549,10 @@ export async function startVault ({ dir = dataDir(), proxyUrl, log = console.log
|
|
|
2549
2549
|
stopPairing: desk.stopPairing,
|
|
2550
2550
|
listPending: desk.listPending,
|
|
2551
2551
|
// ¿Pide permiso este aparato para recibir claves privadas? Lo dice el ACTA
|
|
2552
|
-
// (`unattended`), no una
|
|
2552
|
+
// (`unattended`), no una lista de esta máquina — por eso ya no hay `setApproval` ni
|
|
2553
2553
|
// `supervised`: se concede y se quita como cualquier otro permiso, con `caps`.
|
|
2554
2554
|
needsApproval: async (pub) => needsApproval(pub, await refreshActa()),
|
|
2555
|
-
// La bóveda de contraseñas (`passwords.js`). Aquí SÍ se
|
|
2555
|
+
// La bóveda de contraseñas (`passwords.js`). Aquí SÍ se lista: es donde está la
|
|
2556
2556
|
// llave. Lo que no puede es listarla un aparato.
|
|
2557
2557
|
passwordDevices,
|
|
2558
2558
|
passwordsVault: () => passwords?.vault || null,
|
|
@@ -2599,7 +2599,7 @@ export async function startVault ({ dir = dataDir(), proxyUrl, log = console.log
|
|
|
2599
2599
|
// desbloquear: deja `secrets.json.v3.bak` para poder volver.
|
|
2600
2600
|
/**
|
|
2601
2601
|
* Convierte el archivo de secretos al formato nuevo. `membersOf` es opcional y lo
|
|
2602
|
-
* normal es NO pasarlo: por defecto se usa la misma
|
|
2602
|
+
* normal es NO pasarlo: por defecto se usa la misma lista de destinatarios que
|
|
2603
2603
|
* cualquier escritura —los servicios del cajón MÁS los aparatos que administran—.
|
|
2604
2604
|
*
|
|
2605
2605
|
* Pasarla a mano fue un error real: la conversión envolvía solo a los servicios, y
|
|
@@ -2644,7 +2644,7 @@ export async function startVault ({ dir = dataDir(), proxyUrl, log = console.log
|
|
|
2644
2644
|
isMaster: () => identity.isMaster(),
|
|
2645
2645
|
setCaps: async (pub, caps) => {
|
|
2646
2646
|
const r = await identity.setCaps(pub, caps)
|
|
2647
|
-
// ¿SE QUEDÓ ALGUNO POR EL CAMINO? El acta tiene una
|
|
2647
|
+
// ¿SE QUEDÓ ALGUNO POR EL CAMINO? El acta tiene una lista CERRADA de permisos y
|
|
2648
2648
|
// `cleanCaps` descarta los que no conoce — correcto al recibir un acta ajena, y
|
|
2649
2649
|
// pésimo aquí: conceder `+sella` con una versión del pilar que no sabe qué es
|
|
2650
2650
|
// devolvía «Listo», resellaba el acta y no concedía nada. Costó una tarde en un
|