@dotrino/identity 0.102.0 → 0.102.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 +1 -1
- package/vault/core.js +14 -1
- package/vault/remote.js +7 -3
- package/vault/vendor/vault/VERSION.txt +1 -1
package/package.json
CHANGED
package/vault/core.js
CHANGED
|
@@ -1336,6 +1336,8 @@ export async function createIdentityCore ({ kv: hostKv, peers, makeSync = null,
|
|
|
1336
1336
|
// Un cert YA vencido o revocado no puede renovarse (ahí sí, re-emparejar).
|
|
1337
1337
|
// Ya no hay ventana de caducidad: el papel no vence. Lo único que obliga a pedir uno
|
|
1338
1338
|
// nuevo es que el ACTA diga algo distinto de lo que lleva escrito.
|
|
1339
|
+
/** Rechazos de la bóveda que se arreglan con un papel nuevo (el mismo juego que la app nativa). */
|
|
1340
|
+
const PAPER_REASONS = new Set(['scope', 'acta-vieja', 'untrusted-issuer', 'expired', 'legacy-cert-retirado', 'no-acta'])
|
|
1339
1341
|
const RENEW_RETRY_MS = 60 * 60 * 1000 // si falla (vault apagado), no insistir >1 vez/hora
|
|
1340
1342
|
let renewLastTry = 0
|
|
1341
1343
|
/**
|
|
@@ -3007,8 +3009,19 @@ export async function createIdentityCore ({ kv: hostKv, peers, makeSync = null,
|
|
|
3007
3009
|
const v = loadVaultCert(); const device = loadVaultDevice()
|
|
3008
3010
|
if (!v?.cert || !device) throw new Error('this device is not paired with a vault')
|
|
3009
3011
|
maybeRenewVaultCert()
|
|
3012
|
+
const ask = (cert) => remoteApproval({ master: v.master, proxy: v.proxy, device, cert, op, id, onRevoked: wipeVaultLink })
|
|
3010
3013
|
try {
|
|
3011
|
-
|
|
3014
|
+
let r
|
|
3015
|
+
try { r = await ask(v.cert) } catch (e) {
|
|
3016
|
+
// PAPEL VIEJO: tras `caps <ID> +aprueba` el papel que tengo no trae `vault:approve`,
|
|
3017
|
+
// y si el aviso del acta nueva no llegó (o llegó y el freno de una hora ya había
|
|
3018
|
+
// gastado su intento) no se renovaba nunca: el aprobador se quedaba en
|
|
3019
|
+
// «unauthorized: scope» para siempre. Se renueva UNA vez y se reintenta; la bóveda
|
|
3020
|
+
// decide qué papel toca según SU acta. Un aparato revocado o sin el permiso no se
|
|
3021
|
+
// reintenta: renovar no lo arregla y esconder el motivo sería peor.
|
|
3022
|
+
if (e?.code !== 'unauthorized' || !PAPER_REASONS.has(e.reason)) throw e
|
|
3023
|
+
r = await ask(await renovarCert())
|
|
3024
|
+
}
|
|
3012
3025
|
// El comando de cada pedido viene sellado a este aparato: se abre aquí, que es
|
|
3013
3026
|
// donde está la llave, y sale ya legible.
|
|
3014
3027
|
if (Array.isArray(r?.items)) return { ...r, items: await abrirContextos(r.items, currentPid) }
|
package/vault/remote.js
CHANGED
|
@@ -128,7 +128,7 @@ async function askVault (client, qr) {
|
|
|
128
128
|
* @param {(c:{deviceId:string, code:string})=>void} [opts.onChallenge] Para mostrar el código a tipear en el PC.
|
|
129
129
|
* @param {string} [opts.label]
|
|
130
130
|
* @param {number} [opts.approveTimeoutMs] Espera de la aprobación humana (def 3 min).
|
|
131
|
-
* @returns {Promise<{device, cert, master:string, proxy:string, deviceId:string}>}
|
|
131
|
+
* @returns {Promise<{device, cert, master:string, proxy:string, deviceId:string, account:string}>}
|
|
132
132
|
*/
|
|
133
133
|
export async function enrollDevice ({ qr, device, onChallenge, label = '', continuity = null, encPub = null, approveTimeoutMs = 180000, intent = 'join', profileId = null, onAdopt = null } = {}) {
|
|
134
134
|
if (!qr?.sn || !(qr.iss || qr.conn)) throw new Error('invalid qr: missing vault or nonce')
|
|
@@ -206,7 +206,7 @@ export async function enrollDevice ({ qr, device, onChallenge, label = '', conti
|
|
|
206
206
|
if (adopting) {
|
|
207
207
|
if (!res.acta) throw new Error('the vault did not return the adopted record')
|
|
208
208
|
if (res.acta.sealer !== qr.iss) throw new Error('the record is sealed by a vault other than the one you saw')
|
|
209
|
-
return { device: dev, cert: null, master: qr.iss, proxy: qr.proxy, deviceId, acta: res.acta, adopted: true }
|
|
209
|
+
return { device: dev, cert: null, master: qr.iss, proxy: qr.proxy, deviceId, acta: res.acta, adopted: true, account: qr.acct || '' }
|
|
210
210
|
}
|
|
211
211
|
|
|
212
212
|
// Validación estricta antes de guardar (cierra inyección de cert / sustitución de maestra).
|
|
@@ -225,7 +225,10 @@ export async function enrollDevice ({ qr, device, onChallenge, label = '', conti
|
|
|
225
225
|
// emparejaba con una segunda bóveda o con una que adoptó la cuenta (`checkVaultReply`).
|
|
226
226
|
const chk = await checkVaultReply({ acta: res.acta, cert: res.cert, vault: qr.iss, sub: dev.publickey, justSealed: true })
|
|
227
227
|
if (!chk.ok) throw new Error('the vault reply does not check out: ' + chk.reason)
|
|
228
|
-
|
|
228
|
+
// `account`: el nombre que la bóveda dio a la cuenta. Con la invitación corta no viene en
|
|
229
|
+
// el QR sino en el `hello`, así que solo lo sabe esto — y sin él, quien tiene varias
|
|
230
|
+
// cuentas en un aparato no sabe de cuál es cada cosa.
|
|
231
|
+
return { device: dev, cert: res.cert, master: qr.iss, proxy: qr.proxy, deviceId, acta: res.acta || null, account: qr.acct || '' }
|
|
229
232
|
} finally { try { client.close() } catch (_) {} }
|
|
230
233
|
}
|
|
231
234
|
|
|
@@ -267,6 +270,7 @@ const REVOKE_GRACE_MS = 1500
|
|
|
267
270
|
function vaultError (p) {
|
|
268
271
|
const e = new Error(p?.error || 'vault error')
|
|
269
272
|
if (p?.code) e.code = p.code
|
|
273
|
+
if (p?.reason) e.reason = p.reason
|
|
270
274
|
if (p?.tries != null) e.tries = p.tries
|
|
271
275
|
if (p?.waitSec != null) e.waitSec = p.waitSec
|
|
272
276
|
return e
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Copia vendorizada de @dotrino/vault@0.
|
|
1
|
+
Copia vendorizada de @dotrino/vault@0.73.0 (dotrino-vault/lib/src/{index,enroll,protocol,passwordLogins,loginClient,b64}.js).
|
|
2
2
|
NO se edita a mano: la escribe `node vendor.mjs` y la vigila test/vendor-up-to-date.test.mjs.
|
|
3
3
|
index.js importa ./enroll.js y ./protocol.js (relativos, van en esta misma copia),
|
|
4
4
|
@dotrino/identity/{capabilities,acta} (= ../../{capabilities,acta}.js) y
|