@dotrino/vault 0.47.1 → 0.48.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 +1 -1
- package/src/service.js +33 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dotrino/vault",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.48.0",
|
|
4
4
|
"description": "Usa ESTE dispositivo (navegador) como bóveda/CA del ecosistema Dotrino: atiende enrolamientos por el proxy y firma certificados de delegación a tus máquinas. Incluye el cliente de SERVICIO (Node): un proyecto se enrola una vez y jala sus credenciales del vault en vez del .env (`import '@dotrino/vault/config'`).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
package/src/service.js
CHANGED
|
@@ -666,7 +666,17 @@ async function openSealedBundle (sealed, ident, acta = null, masterPubkey = null
|
|
|
666
666
|
const gen = e.gen ?? e.e?.gen ?? 0
|
|
667
667
|
await comprobarFirma(e.owner, key, gen, e.e, e.seal)
|
|
668
668
|
const cek = await cekDe(cual, gen)
|
|
669
|
-
if (!cek)
|
|
669
|
+
if (!cek) {
|
|
670
|
+
// NO ES UN TROPIEZO: ES UN ESTADO QUE HAY QUE ARREGLAR EN LA BÓVEDA.
|
|
671
|
+
//
|
|
672
|
+
// Un aparato que entra después de escrita una variable no tiene envoltura de ella, y
|
|
673
|
+
// NO PUEDE tenerla: envolver exige abrir la llave del cajón, y eso solo pasa cuando
|
|
674
|
+
// el dueño abre la bóveda. Reintentar no la crea. Lleva `code` porque el mensaje lo
|
|
675
|
+
// empareja otra capa y una frase no es un contrato (ver `dotrino-error-strings`).
|
|
676
|
+
throw Object.assign(
|
|
677
|
+
new Error(`no key to open ${key}: this device has no wrapping in its drawer — open the vault (dotrino-vault unlock) so it hands it the key`),
|
|
678
|
+
{ code: 'no-wrapping' })
|
|
679
|
+
}
|
|
670
680
|
out[key] = await decryptWithCek({ cek, envelope: e.e })
|
|
671
681
|
}
|
|
672
682
|
return out
|
|
@@ -991,16 +1001,34 @@ function fingerprintOf (secrets) {
|
|
|
991
1001
|
* servicio no opera hasta que esto resuelva — esa es la regla.
|
|
992
1002
|
* @returns {Promise<Record<string,string>>}
|
|
993
1003
|
*/
|
|
1004
|
+
/**
|
|
1005
|
+
* ¿ESTE FALLO SE ARREGLA SOLO ESPERANDO? Si no, reintentar es peor que rendirse.
|
|
1006
|
+
*
|
|
1007
|
+
* Lo NO transitorio exige que alguien haga algo: falta de enrolamiento, cert revocado o
|
|
1008
|
+
* vencido, scope equivocado → re-emparejar. Que te lo DENIEGUEN tampoco se reintenta: fue
|
|
1009
|
+
* una decisión, no un tropiezo.
|
|
1010
|
+
*
|
|
1011
|
+
* Y no tener ENVOLTURA en el cajón (`no-wrapping`) es el que costó una tarde. La bóveda
|
|
1012
|
+
* pedía aprobación, el teléfono timbraba, el dueño aprobaba, la bóveda contestaba un bundle
|
|
1013
|
+
* que este aparato no podía abrir, y el agente volvía a pedir — así que el teléfono
|
|
1014
|
+
* timbraba otra vez. «Sigo aprobando y aprobando», textual. Ninguna aprobación iba a crear
|
|
1015
|
+
* esa envoltura: envolver exige abrir la llave del cajón, o sea ABRIR la bóveda.
|
|
1016
|
+
*
|
|
1017
|
+
* Se decide por `e.code` donde lo hay: emparejar un mensaje por su texto se rompe en
|
|
1018
|
+
* silencio en cuanto alguien lo reescribe (ver `dotrino-error-strings`).
|
|
1019
|
+
*/
|
|
1020
|
+
export function isFinal (e) {
|
|
1021
|
+
if (e?.code === 'no-wrapping') return true
|
|
1022
|
+
return /not enrolled|invalid ns|unauthorized: (revoked|expired|scope|cn|untrusted-issuer|cert-device-mismatch|denied)/.test(e?.message || '')
|
|
1023
|
+
}
|
|
1024
|
+
|
|
994
1025
|
export async function waitForSecrets ({ dir, ns, proxyUrl, masterPubkey, device, cert, enc, retryMs = 5000, maxRetryMs = 60000, onRetry, onPending, onCert } = {}) {
|
|
995
1026
|
let delay = retryMs
|
|
996
1027
|
for (;;) {
|
|
997
1028
|
try {
|
|
998
1029
|
return await fetchSecrets({ dir, ns, proxyUrl, masterPubkey, device, cert, enc, onPending, onCert })
|
|
999
1030
|
} catch (e) {
|
|
1000
|
-
|
|
1001
|
-
// cert revocado/vencido o scope equivocado exigen re-emparejar → se corta.
|
|
1002
|
-
// Que te lo DENIEGUEN tampoco se reintenta: fue una decisión, no un tropiezo.
|
|
1003
|
-
if (/not enrolled|invalid ns|unauthorized: (revoked|expired|scope|cn|untrusted-issuer|cert-device-mismatch|denied)/.test(e.message)) throw e
|
|
1031
|
+
if (isFinal(e)) throw e
|
|
1004
1032
|
try { onRetry?.(e, delay) } catch (_) {}
|
|
1005
1033
|
await new Promise((r) => setTimeout(r, delay))
|
|
1006
1034
|
delay = Math.min(maxRetryMs, Math.round(delay * 1.6))
|