@dotrino/vaultd 0.162.2 → 0.163.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/lib/src/core/libVersion.js +1 -1
- package/lib/src/core/transport.js +21 -1
- package/lib/src/core/vault.js +9 -2
- package/lib/src/deviceInfo.js +2 -4
- package/lib/src/kek.js +1 -1
- package/lib/src/loginClient.js +10 -1
- package/lib/src/passwordLogins.js +25 -2
- package/lib/src/service.js +2 -2
- package/package.json +4 -4
- package/src/client.js +2 -2
- package/src/ctl.js +8 -19
- package/src/replica.js +2 -2
- package/src/vault.js +6 -2
|
@@ -36,7 +36,7 @@ export async function masterPubkeyOf (identity) {
|
|
|
36
36
|
* @param {string} [opts.url] URL del proxy (default wss://proxy.dotrino.com).
|
|
37
37
|
* @returns {Promise<{ client, token:string, identify():Promise<void> }>}
|
|
38
38
|
*/
|
|
39
|
-
export async function createTransport ({ identity, url = DEFAULT_PROXY, commKey = null, log = () => {}, makeClient = null, announce = null, recheckMs = 60_000, patienceMs = 5 * 60_000, reannounceMs = 10 * 60_000 }) {
|
|
39
|
+
export async function createTransport ({ identity, url = DEFAULT_PROXY, commKey = null, log = () => {}, makeClient = null, announce = null, wakeUrl = null, recheckMs = 60_000, patienceMs = 5 * 60_000, reannounceMs = 10 * 60_000 }) {
|
|
40
40
|
// Import dinámico DESPUÉS de instalar los globals que el paquete usa.
|
|
41
41
|
// `WebSocketProxyClient` (la clase) y NO el helper `getWebSocketProxyClient`:
|
|
42
42
|
// ese es un SINGLETON de proceso, y con multi-perfil el vault necesita una
|
|
@@ -182,6 +182,25 @@ export async function createTransport ({ identity, url = DEFAULT_PROXY, commKey
|
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
184
|
|
|
185
|
+
/**
|
|
186
|
+
* DESPIÉRTAME AQUÍ (una bóveda que no vive conectada, `lambda/`). Si la plataforma da una
|
|
187
|
+
* URL, se registra en el proxio con la llave de comunicación y el acta, para que llame a esa
|
|
188
|
+
* URL cuando llegue algo para la cuenta y no haya nadie suyo conectado. Va pegado a
|
|
189
|
+
* `identify` por lo mismo que el anuncio: el acta puede haber cambiado. Si falla, se dice:
|
|
190
|
+
* lo que se pierde es que la despierten, y eso no se puede callar.
|
|
191
|
+
*/
|
|
192
|
+
const registerWake = async () => {
|
|
193
|
+
if (!wakeUrl || !identificado) return
|
|
194
|
+
const comm = commKey?.pub?.() || null
|
|
195
|
+
if (!comm || !actaVista) { log('[vault] cannot register the wake URL: no communication key in the record yet'); return }
|
|
196
|
+
try {
|
|
197
|
+
await client.registerWake({ publicKey: comm, sign: (d) => commKey.sign(d), url: wakeUrl, acta: actaVista, channel: announce || undefined })
|
|
198
|
+
log('[vault] wake URL registered on the proxy')
|
|
199
|
+
} catch (e) {
|
|
200
|
+
log(`[vault] could not register the wake URL (${e.code || ''} ${e.message}) — the proxy will not wake this vault`)
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
185
204
|
let reintento = null
|
|
186
205
|
let fallos = 0
|
|
187
206
|
const identifyWithRetry = async () => {
|
|
@@ -189,6 +208,7 @@ export async function createTransport ({ identity, url = DEFAULT_PROXY, commKey
|
|
|
189
208
|
try {
|
|
190
209
|
await identify()
|
|
191
210
|
await announceAccount()
|
|
211
|
+
await registerWake()
|
|
192
212
|
if (fallos) log(`[vault] identified on the proxy after ${fallos + 1} attempt(s)`)
|
|
193
213
|
fallos = 0
|
|
194
214
|
} catch (e) {
|
package/lib/src/core/vault.js
CHANGED
|
@@ -80,6 +80,8 @@ const MAX_REPLY_BYTES = 768 * 1024
|
|
|
80
80
|
* readProcContext(pid) lo que el sistema dice de un proceso; `null` si no se puede mirar
|
|
81
81
|
* openLocalDesk({ name, onMessage, channels, maxBytes, log }) el atajo en la misma máquina
|
|
82
82
|
* makeClient quién crea el cliente del proxio (opcional)
|
|
83
|
+
* wakeUrl la URL que despierta a esta bóveda si no vive conectada (opcional, `lambda/`)
|
|
84
|
+
* onActivity() llega un mensaje del proxio (opcional; la Lambda mide con esto su inactividad)
|
|
83
85
|
* noticeGroupMs cuánto se agrupan los avisos de cambio
|
|
84
86
|
* opaque el servidor de OPAQUE, si no vale el del paquete (opcional)
|
|
85
87
|
* servePasswords `false`: el almacén de contraseñas lo atiende quien monta la bóveda,
|
|
@@ -492,7 +494,7 @@ export async function startVault ({ platform, proxyUrl, log = console.log, onEnr
|
|
|
492
494
|
// ninguna llave y solo sabe la dirección `nombre@AB12-CD34-EF56`— pueda encontrar a quien
|
|
493
495
|
// la atiende. Lo construye la pieza compartida, porque quien lo busca es la extensión.
|
|
494
496
|
const { client, identify: reidentificar, isIdentified } = await createTransport({
|
|
495
|
-
identity, url: proxyUrl, commKey, log, announce: vaultChannel(fp), makeClient: platform.makeClient || null
|
|
497
|
+
identity, url: proxyUrl, commKey, log, announce: vaultChannel(fp), makeClient: platform.makeClient || null, wakeUrl: platform.wakeUrl || null
|
|
496
498
|
})
|
|
497
499
|
|
|
498
500
|
// El registro público de cadenas de selladores: deposita, si hay a dónde, los eslabones
|
|
@@ -2189,7 +2191,12 @@ export async function startVault ({ platform, proxyUrl, log = console.log, onEnr
|
|
|
2189
2191
|
reply(from, { type: MSG.INCIDENT_RESULT, id: pend.id, approvers, blocked: false })
|
|
2190
2192
|
}
|
|
2191
2193
|
|
|
2192
|
-
client.on('message', (from, payload) =>
|
|
2194
|
+
client.on('message', (from, payload) => {
|
|
2195
|
+
// Quien monta la bóveda puede querer saber que hay trabajo (la Lambda se apaga cuando
|
|
2196
|
+
// deja de haberlo). Es un aviso, no decide nada.
|
|
2197
|
+
try { platform.onActivity?.() } catch (_) {}
|
|
2198
|
+
onMessage(from, payload)
|
|
2199
|
+
})
|
|
2193
2200
|
|
|
2194
2201
|
// EL MOSTRADOR LOCAL, siempre que se pueda. Si no se puede abrir (un sistema sin sockets
|
|
2195
2202
|
// de archivo, un directorio de solo lectura) se dice y se sigue: los servicios usan el
|
package/lib/src/deviceInfo.js
CHANGED
|
@@ -14,12 +14,10 @@
|
|
|
14
14
|
* Sirve cualquier enlace con la forma común `{ device: { publickey }, cert, iss, proxy }`
|
|
15
15
|
* (el de remote-agent y el de un servicio de dotrino-env).
|
|
16
16
|
*/
|
|
17
|
-
import {
|
|
17
|
+
import { keyLabel } from '@dotrino/identity/capabilities'
|
|
18
18
|
|
|
19
19
|
/** El id corto de una llave, como lo enseña la bóveda: `AB12-CD34`. */
|
|
20
|
-
export
|
|
21
|
-
return (await pubkeyId(publickey)).slice(0, 8).toUpperCase().replace(/(.{4})(.{4})/, '$1-$2')
|
|
22
|
-
}
|
|
20
|
+
export const shortId = keyLabel
|
|
23
21
|
|
|
24
22
|
/**
|
|
25
23
|
* La información del aparato a partir de su enlace.
|
package/lib/src/kek.js
CHANGED
|
@@ -85,7 +85,7 @@ export function writeConfig (dir, cfg) {
|
|
|
85
85
|
* es a propósito el más tonto posible — cada CLI de KMS tiene sus manías con los binarios
|
|
86
86
|
* y sus flags, y se resuelven en un envoltorio de tres líneas en vez de aquí dentro.
|
|
87
87
|
*/
|
|
88
|
-
function runStep (step, input, what) {
|
|
88
|
+
export function runStep (step, input, what) {
|
|
89
89
|
if (!step || typeof step.cmd !== 'string' || !step.cmd) {
|
|
90
90
|
throw new KekError('kek-config', `kek provider "command": missing ${what}.cmd`)
|
|
91
91
|
}
|
package/lib/src/loginClient.js
CHANGED
|
@@ -44,6 +44,8 @@ const err = (code, message, extra = {}) => Object.assign(new Error(message), { c
|
|
|
44
44
|
|
|
45
45
|
/** Cuánto se espera a que una bóveda conteste antes de probar con la siguiente. */
|
|
46
46
|
export const REPLY_TIMEOUT_MS = 15_000
|
|
47
|
+
/** Lo que se espera a una bóveda que se está despertando: arrancar en frío y conectarse. */
|
|
48
|
+
export const WAKE_WAIT_MS = 30_000
|
|
47
49
|
|
|
48
50
|
/**
|
|
49
51
|
* Escucha UNA respuesta de un token concreto. El `off` se suelta siempre —también al
|
|
@@ -98,7 +100,14 @@ export async function loginWithPassword ({ transport, address, password, label =
|
|
|
98
100
|
if (typeof password !== 'string' || !password) throw err('no-password', 'loginWithPassword: password required')
|
|
99
101
|
const { user, code, address: dir } = parseLoginAddress(address)
|
|
100
102
|
|
|
101
|
-
|
|
103
|
+
let tokens = await transport.list(vaultChannel(code))
|
|
104
|
+
// UNA BÓVEDA QUE DUERME (la de una Lambda): el proxio la está despertando y lo dice. Se
|
|
105
|
+
// espera a que se anuncie en vez de contestar que esa cuenta no existe.
|
|
106
|
+
const hasta = Date.now() + WAKE_WAIT_MS
|
|
107
|
+
while (!tokens.length && tokens.waking && Date.now() < hasta) {
|
|
108
|
+
await new Promise((resolve) => setTimeout(resolve, 2000))
|
|
109
|
+
tokens = await transport.list(vaultChannel(code))
|
|
110
|
+
}
|
|
102
111
|
if (!tokens.length) {
|
|
103
112
|
throw err('no-vault', 'no vault is answering for that address right now: turn yours on, or check the address')
|
|
104
113
|
}
|
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
* binario, `lib/src/index.js` en la pestaña—. Lo único que no es puro es `registerLogin`, al
|
|
25
25
|
* final, porque hace falta la identidad que firma.
|
|
26
26
|
*/
|
|
27
|
-
import { server as opaquePorDefecto, suiteId as suitePorDefecto } from '@dotrino/opaque'
|
|
28
|
-
import { pubkeyId } from '@dotrino/identity/capabilities'
|
|
27
|
+
import { server as opaquePorDefecto, client as opaqueClientePorDefecto, suiteId as suitePorDefecto } from '@dotrino/opaque'
|
|
28
|
+
import { pubkeyId, makeDeviceKey, makeDeviceEncKey } from '@dotrino/identity/capabilities'
|
|
29
29
|
import { DEVICE_CAPS, capScope } from '@dotrino/identity/acta'
|
|
30
30
|
import { deviceIdOf } from './enroll.js'
|
|
31
31
|
import { bytesToB64url, b64urlToBytes } from './b64.js'
|
|
@@ -448,6 +448,29 @@ export function createLoginDesk ({ load, save, now = () => Date.now(), opaque =
|
|
|
448
448
|
* `caps` los PERMISOS del acta que lleva el aparato, cualquiera de `DEVICE_CAPS`;
|
|
449
449
|
* por defecto firmar, leer y guardar
|
|
450
450
|
*/
|
|
451
|
+
/**
|
|
452
|
+
* DAR DE ALTA UN USUARIO, DEL LADO DE QUIEN TIENE LA CONTRASEÑA: el registro OPAQUE se
|
|
453
|
+
* termina aquí y las llaves del aparato nacen aquí y salen ya cerradas. La bóveda solo ve
|
|
454
|
+
* `begin`/`finish`, que es su mitad; quien llama decide por dónde llegan (el canal local de
|
|
455
|
+
* la CLI, o la propia bóveda en el arranque de una Lambda).
|
|
456
|
+
*
|
|
457
|
+
* @param {object} opts
|
|
458
|
+
* `begin(req)` → `{ response }` (`register-begin` de la bóveda)
|
|
459
|
+
* `finish(req)` → lo que devuelva (`register-finish` de la bóveda)
|
|
460
|
+
*/
|
|
461
|
+
export async function createPasswordLogin ({ user, password, label, caps, begin, finish, opaque = opaqueClientePorDefecto } = {}) {
|
|
462
|
+
if (!isValidUser(user)) throw Object.assign(new Error('invalid user name'), { code: 'bad-user' })
|
|
463
|
+
if (typeof password !== 'string' || !password) throw Object.assign(new Error('a password is required'), { code: 'no-password' })
|
|
464
|
+
const start = opaque.registrationStart({ password })
|
|
465
|
+
const begun = await begin({ user, request: start.request })
|
|
466
|
+
// La bóveda contesta con su mitad; el registro se termina AQUÍ, con la contraseña.
|
|
467
|
+
const fin = opaque.registrationFinish({ state: start.state, response: begun.response, password })
|
|
468
|
+
const device = await makeDeviceKey({ label })
|
|
469
|
+
const enc = await makeDeviceEncKey()
|
|
470
|
+
const blob = await sealDeviceKeys(fin.exportKey, { sign: device.privateJwk, enc: enc.privateJwk })
|
|
471
|
+
return finish({ user, upload: fin.upload, pub: device.publickey, encPub: enc.publickey, label, blob, caps })
|
|
472
|
+
}
|
|
473
|
+
|
|
451
474
|
export async function registerLogin ({
|
|
452
475
|
identity, logins, user, upload, pub, encPub = null, label = '', blob,
|
|
453
476
|
caps = ['sign', 'read', 'store'], scope, replace = false
|
package/lib/src/service.js
CHANGED
|
@@ -23,7 +23,7 @@ import path from 'node:path'
|
|
|
23
23
|
import { createHash } from 'node:crypto'
|
|
24
24
|
import {
|
|
25
25
|
makeDeviceKey, makeDeviceEncKey, importDeviceEncKey, signWithDevice,
|
|
26
|
-
verifyDeviceSig, makePairingCode, commitCode, pubkeyId } from '@dotrino/identity/capabilities'
|
|
26
|
+
verifyDeviceSig, makePairingCode, commitCode, pubkeyId, keyLabel } from '@dotrino/identity/capabilities'
|
|
27
27
|
import { openWrap, wrapForMember, decryptWithCek } from '@dotrino/identity/content'
|
|
28
28
|
import { verifyActa, sealKeyAt, memberCan, checkVaultReply } from '@dotrino/identity/acta'
|
|
29
29
|
import { MSG, secretsScope, isValidSecretsNs, VAULT_PROTOCOL, VAULT_SPEAKS } from './protocol.js'
|
|
@@ -373,7 +373,7 @@ export async function enrollWithVault ({ qr, label = 'agent', expectedScope = nu
|
|
|
373
373
|
// aparato entra al acta pero no le llega ningún secreto, y no da error. Un replicador
|
|
374
374
|
// entra así A PROPÓSITO (ver `withEncKey`): reparte sobres cerrados y no abre ninguno.
|
|
375
375
|
const enc = withEncKey ? await makeDeviceEncKey() : null
|
|
376
|
-
const deviceId =
|
|
376
|
+
const deviceId = await keyLabel(device.publickey)
|
|
377
377
|
// Código de emparejamiento ALEATORIO: se muestra y NO se envía. La bóveda lo
|
|
378
378
|
// aprende solo cuando un humano lo tipea → aprobar exige TENER esta máquina.
|
|
379
379
|
const code = makePairingCode()
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dotrino/vaultd",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.163.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": {
|
|
@@ -22,10 +22,10 @@
|
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@dotrino/compat": "0.4.0",
|
|
25
|
-
"@dotrino/identity": "0.
|
|
25
|
+
"@dotrino/identity": "0.120.0",
|
|
26
26
|
"@dotrino/opaque": "0.1.0",
|
|
27
27
|
"@dotrino/passmanager": "0.18.4",
|
|
28
|
-
"@dotrino/proxy-client": "0.
|
|
28
|
+
"@dotrino/proxy-client": "0.38.0",
|
|
29
29
|
"@dotrino/roadmap": "0.4.30",
|
|
30
30
|
"@dotrino/store": "0.12.3",
|
|
31
31
|
"@dotrino/update": "0.9.0",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"!lib/src/types.d.ts"
|
|
52
52
|
],
|
|
53
53
|
"devDependencies": {
|
|
54
|
-
"@dotrino/remote-agent": "0.
|
|
54
|
+
"@dotrino/remote-agent": "0.21.0",
|
|
55
55
|
"@types/node": "^22.0.0",
|
|
56
56
|
"typescript": "5.9.3"
|
|
57
57
|
},
|
package/src/client.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* estrictamente (firmado por la maestra que vio en el QR, y para SU clave) antes de
|
|
12
12
|
* guardarlo. La maestra nunca sale del vault.
|
|
13
13
|
*/
|
|
14
|
-
import { makeDeviceKey, makeDeviceEncKey, importDeviceEncKey, signWithDevice, verifyDeviceSig, makePairingCode, commitCode,
|
|
14
|
+
import { makeDeviceKey, makeDeviceEncKey, importDeviceEncKey, signWithDevice, verifyDeviceSig, makePairingCode, commitCode, keyLabel } from '@dotrino/identity/capabilities'
|
|
15
15
|
import { myContentKey, encryptWithCek, decryptWithKeyring } from '@dotrino/identity/content'
|
|
16
16
|
// Con qué se juzga lo que devuelve la bóveda (papel + acta): la regla del pilar, una sola.
|
|
17
17
|
import { checkVaultReply } from '@dotrino/identity/acta'
|
|
@@ -65,7 +65,7 @@ export async function enroll ({ qr, label = '', dir, onChallenge, approveTimeout
|
|
|
65
65
|
// La llave de CIFRADO del aparato: con su pública en el acta, la bóveda le envuelve la
|
|
66
66
|
// clave de contenido al admitirlo. Sin ella no podría usar el almacén, que solo entra cifrado.
|
|
67
67
|
const enc = await makeDeviceEncKey()
|
|
68
|
-
const myDeviceId =
|
|
68
|
+
const myDeviceId = await keyLabel(device.publickey)
|
|
69
69
|
// ESTE dispositivo genera el código y lo MUESTRA; solo viaja su COMPROMISO. El vault
|
|
70
70
|
// lo aprende cuando un humano lo tipea, y solo firma el cert si el compromiso coincide.
|
|
71
71
|
const code = makePairingCode()
|
package/src/ctl.js
CHANGED
|
@@ -26,7 +26,7 @@ import path from 'node:path'
|
|
|
26
26
|
import { execFileSync } from 'node:child_process'
|
|
27
27
|
import tty from 'node:tty'
|
|
28
28
|
import crypto from 'node:crypto'
|
|
29
|
-
import { pubkeyId } from '@dotrino/identity/capabilities'
|
|
29
|
+
import { pubkeyId, keyLabel } from '@dotrino/identity/capabilities'
|
|
30
30
|
import { dataDir } from './paths.js'
|
|
31
31
|
// EL CANAL LOCAL VA CIFRADO (ver `ipc.js`): por aquí salen la contraseña y los valores.
|
|
32
32
|
import { ipcRead, ipcWrite } from './ipc.js'
|
|
@@ -133,10 +133,8 @@ function requireDaemon () {
|
|
|
133
133
|
if (!alive(s.pid)) { console.error('El daemon no está corriendo. Arráncalo: %s', START_HINT); process.exit(1) }
|
|
134
134
|
return s
|
|
135
135
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
return pubkeyId(sub).then((id) => id.slice(0, 8).toUpperCase().replace(/(.{4})(.{4})/, '$1-$2'))
|
|
139
|
-
}
|
|
136
|
+
// mismo formato que el daemon: AB12-CD34
|
|
137
|
+
const deviceIdOf = keyLabel
|
|
140
138
|
|
|
141
139
|
/** Lo que dijo un aprobador sobre sus avisos, para enseñarlo. No decide nada. */
|
|
142
140
|
function avisosTxt (notifiedAt) {
|
|
@@ -1708,21 +1706,12 @@ async function cmdLogins (rest) {
|
|
|
1708
1706
|
if (a[0] === '+') caps.add(cap); else caps.delete(cap)
|
|
1709
1707
|
}
|
|
1710
1708
|
const label = nombre.join(' ').trim() || 'equipo prestado'
|
|
1711
|
-
const {
|
|
1712
|
-
const { makeDeviceKey, makeDeviceEncKey } = await import('@dotrino/identity/capabilities')
|
|
1713
|
-
const { sealDeviceKeys } = await import('../lib/src/passwordLogins.js')
|
|
1709
|
+
const { createPasswordLogin } = await import('../lib/src/passwordLogins.js')
|
|
1714
1710
|
const password = await askNewPassword(user)
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
const fin = opaqueClient.registrationFinish({ state: start.state, response: begun.response, password })
|
|
1720
|
-
// Las llaves del aparato NACEN en esta terminal y salen de aquí ya cerradas.
|
|
1721
|
-
const device = await makeDeviceKey({ label })
|
|
1722
|
-
const enc = await makeDeviceEncKey()
|
|
1723
|
-
const blob = await sealDeviceKeys(fin.exportKey, { sign: device.privateJwk, enc: enc.privateJwk })
|
|
1724
|
-
const r = await loginsRequest('register-finish', {
|
|
1725
|
-
user, upload: fin.upload, pub: device.publickey, encPub: enc.publickey, label, blob, caps: [...caps]
|
|
1711
|
+
const r = await createPasswordLogin({
|
|
1712
|
+
user, password, label, caps: [...caps],
|
|
1713
|
+
begin: (req) => loginsRequest('register-begin', req),
|
|
1714
|
+
finish: (req) => loginsRequest('register-finish', req)
|
|
1726
1715
|
})
|
|
1727
1716
|
const { loginAddress } = await import('../lib/src/passwordLogins.js')
|
|
1728
1717
|
console.log('\nListo. Se entra con esta dirección y esa contraseña:')
|
package/src/replica.js
CHANGED
|
@@ -24,7 +24,7 @@ import fs from 'node:fs'
|
|
|
24
24
|
import path from 'node:path'
|
|
25
25
|
import os from 'node:os'
|
|
26
26
|
import { WebSocketProxyClient } from '@dotrino/proxy-client'
|
|
27
|
-
import { signWithDevice, verifyDeviceSig, verifyChain, pubkeyId } from '@dotrino/identity/capabilities'
|
|
27
|
+
import { signWithDevice, verifyDeviceSig, verifyChain, pubkeyId, keyLabel } from '@dotrino/identity/capabilities'
|
|
28
28
|
import { verifyActa, memberCan, memberCanReadSecrets, sealKeyAt, sealersOf } from '@dotrino/identity/acta'
|
|
29
29
|
import { MSG, secretsScope, isValidSecretsNs } from '../lib/src/protocol.js'
|
|
30
30
|
import { FRESH_WINDOW_MS } from '../lib/src/enroll.js'
|
|
@@ -156,7 +156,7 @@ export async function runReplica ({ dir = replicaDir(), proxyUrl, log = console.
|
|
|
156
156
|
{ code: 'replica-not-enrolled' })
|
|
157
157
|
}
|
|
158
158
|
const url = proxyUrl || link.proxy || process.env.PROXY_URL || 'wss://proxy.dotrino.com'
|
|
159
|
-
const id =
|
|
159
|
+
const id = await keyLabel(link.device.publickey)
|
|
160
160
|
|
|
161
161
|
const firmar = (data) => signWithDevice({ privateJwk: link.device.privateJwk, data })
|
|
162
162
|
// CONTESTAR es por la CONEXIÓN (`send`) y no por la llave (`sendByPubkey`): `from` es el
|
package/src/vault.js
CHANGED
|
@@ -7,8 +7,12 @@ import { startVault as startVaultCore } from '../lib/src/core/vault.js'
|
|
|
7
7
|
import { nodePlatform } from './platform.js'
|
|
8
8
|
import { dataDir } from './paths.js'
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
/**
|
|
11
|
+
* `platform` suma o cambia piezas de la del binario: la Lambda (`lambda/session.mjs`) pone
|
|
12
|
+
* la URL que la despierta y un cliente del proxio que le dice cuándo hay trabajo.
|
|
13
|
+
*/
|
|
14
|
+
export async function startVault ({ dir = dataDir(), platform = null, ...opts } = {}) {
|
|
15
|
+
return startVaultCore({ ...opts, platform: { ...nodePlatform(dir), ...(platform || {}) } })
|
|
12
16
|
}
|
|
13
17
|
|
|
14
18
|
export default { startVault }
|