@dotrino/remote-agent 0.20.0 → 0.21.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.
Files changed (3) hide show
  1. package/e2e.js +5 -72
  2. package/package.json +5 -5
  3. package/src/agent.js +2 -2
package/e2e.js CHANGED
@@ -1,75 +1,8 @@
1
1
  /**
2
- * e2e.js — canal cifrado punto a punto entre el dispositivo enlazado y un agente
3
- * remoto del ecosistema Dotrino. Isomórfico: usa WebCrypto
4
- * (`globalThis.crypto.subtle`), disponible tanto en el navegador (PWA) como en
5
- * Node ≥ 18.
2
+ * e2e.js — el canal cifrado entre el dispositivo enlazado y el agente.
6
3
  *
7
- * NO reimplementa la identidad ni la firma del ecosistema: la AUTORIZACIÓN la da
8
- * el vault (cert de dispositivo verificado con `@dotrino/identity/capabilities`
9
- * → cadena hasta la maestra). Este módulo solo levanta un secreto de sesión
10
- * efímero (ECDH P-256 → HKDF → AES-256-GCM) para que el relay de transporte
11
- * (`proxy.dotrino.com`) vea únicamente texto cifrado. La identidad de las dos
12
- * puntas ya la garantizan las firmas del vault que envuelven las claves efímeras.
13
- *
14
- * Fuente única para `@dotrino/remote-agent` (consumido por terminal, ia y futuras
15
- * apps de agente remoto).
16
- */
17
-
18
- const subtle = () => globalThis.crypto.subtle
19
-
20
- const b64 = {
21
- enc (buf) {
22
- const b = new Uint8Array(buf)
23
- let s = ''
24
- for (let i = 0; i < b.length; i++) s += String.fromCharCode(b[i])
25
- return btoa(s)
26
- },
27
- dec (str) {
28
- const bin = atob(str)
29
- const out = new Uint8Array(bin.length)
30
- for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i)
31
- return out
32
- }
33
- }
34
-
35
- /** Genera un par ECDH P-256 efímero. Devuelve la pub en raw (base64) + privada. */
36
- export async function makeEphemeral () {
37
- const kp = await subtle().generateKey({ name: 'ECDH', namedCurve: 'P-256' }, false, ['deriveBits'])
38
- const raw = await subtle().exportKey('raw', kp.publicKey)
39
- return { privateKey: kp.privateKey, pub: b64.enc(raw) }
40
- }
41
-
42
- /**
43
- * Deriva la clave AES-256-GCM de la sesión a partir de la privada propia y la
44
- * pub efímera (base64 raw) del otro extremo. `salt` liga la clave a la sesión.
4
+ * Vive en `@dotrino/identity/channel` (identity ≥ 0.120.0): aquí solo se reexporta para que
5
+ * quien importaba `makeEphemeral`/`deriveKey`/`seal`/`open` de este paquete siga igual. El
6
+ * cable no cambió: mismo HKDF, mismo `info`, mismos sobres.
45
7
  */
46
- export async function deriveKey (privateKey, otherPubB64, salt) {
47
- const otherPub = await subtle().importKey(
48
- 'raw', b64.dec(otherPubB64), { name: 'ECDH', namedCurve: 'P-256' }, false, []
49
- )
50
- const bits = await subtle().deriveBits({ name: 'ECDH', public: otherPub }, privateKey, 256)
51
- const hkdfKey = await subtle().importKey('raw', bits, 'HKDF', false, ['deriveKey'])
52
- return subtle().deriveKey(
53
- { name: 'HKDF', hash: 'SHA-256', salt: new TextEncoder().encode(salt), info: new TextEncoder().encode('dotrino-remote-agent-e2e') },
54
- hkdfKey,
55
- { name: 'AES-GCM', length: 256 },
56
- false,
57
- ['encrypt', 'decrypt']
58
- )
59
- }
60
-
61
- /** Cifra un objeto JSON → sobre { iv, ct } (ambos base64). */
62
- export async function seal (key, obj) {
63
- const iv = globalThis.crypto.getRandomValues(new Uint8Array(12))
64
- const pt = new TextEncoder().encode(JSON.stringify(obj))
65
- const ct = await subtle().encrypt({ name: 'AES-GCM', iv }, key, pt)
66
- return { iv: b64.enc(iv), ct: b64.enc(ct) }
67
- }
68
-
69
- /** Descifra un sobre { iv, ct } → objeto JSON. Lanza si el tag GCM no valida. */
70
- export async function open (key, env) {
71
- const pt = await subtle().decrypt({ name: 'AES-GCM', iv: b64.dec(env.iv) }, key, b64.dec(env.ct))
72
- return JSON.parse(new TextDecoder().decode(pt))
73
- }
74
-
75
- export { b64 }
8
+ export { makeEphemeral, deriveKey, seal, open, b64 } from '@dotrino/identity/channel'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dotrino/remote-agent",
3
- "version": "0.20.0",
3
+ "version": "0.21.0",
4
4
  "description": "Middleware compartido del ecosistema Dotrino para apps de agente remoto cifrado punto a punto (handshake E2E, emparejamiento SAS con vault, revocación, descubrimiento). Lo consumen dotrino-terminal (PTY) y dotrino-ia (chat con IA).",
5
5
  "type": "module",
6
6
  "main": "./index.js",
@@ -46,13 +46,13 @@
46
46
  "p2p"
47
47
  ],
48
48
  "peerDependencies": {
49
- "@dotrino/identity": ">=0.117.2",
49
+ "@dotrino/identity": ">=0.120.0",
50
50
  "@dotrino/proxy-client": ">=0.36.1",
51
51
  "@dotrino/vault": ">=0.85.0"
52
52
  },
53
53
  "devDependencies": {
54
- "@dotrino/identity": "0.117.2",
55
- "@dotrino/proxy-client": "0.36.1",
56
- "@dotrino/vault": "0.86.1"
54
+ "@dotrino/identity": "0.120.0",
55
+ "@dotrino/proxy-client": "0.36.2",
56
+ "@dotrino/vault": "0.90.2"
57
57
  }
58
58
  }
package/src/agent.js CHANGED
@@ -21,7 +21,7 @@
21
21
  */
22
22
  import fs from 'node:fs'
23
23
  import path from 'node:path'
24
- import { verifyChain, signWithDevice, verifyDeviceSig, pubkeyId } from '@dotrino/identity/capabilities'
24
+ import { verifyChain, signWithDevice, verifyDeviceSig, pubkeyId, keyLabel } from '@dotrino/identity/capabilities'
25
25
  import { sealersOf, memberCan, checkVaultReply } from '@dotrino/identity/acta'
26
26
  import { adoptRecord } from './record.js'
27
27
  import { installNodeGlobals } from '../node-globals.js'
@@ -134,7 +134,7 @@ export async function startRemoteAgent (opts = {}) {
134
134
  }
135
135
  const master = link.iss
136
136
  const myPub = link.device.publickey
137
- const myId = (await pubkeyId(myPub)).slice(0, 8).toUpperCase().replace(/(.{4})(.{4})/, '$1-$2')
137
+ const myId = await keyLabel(myPub)
138
138
 
139
139
  installNodeGlobals(dir)
140
140