@dotrino/remote-agent 0.6.0 → 0.6.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/agent.js +9 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dotrino/remote-agent",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
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",
package/src/agent.js CHANGED
@@ -22,7 +22,7 @@
22
22
  import fs from 'node:fs'
23
23
  import path from 'node:path'
24
24
  import { verifyChain, signWithDevice, verifyDeviceSig, verifyDelegation, pubkeyId } from '@dotrino/identity/capabilities'
25
- import { sealersOf } from '@dotrino/identity/acta'
25
+ import { sealersOf, memberCanSign } from '@dotrino/identity/acta'
26
26
  import { installNodeGlobals } from '../node-globals.js'
27
27
  import { makeEphemeral, deriveKey, seal, open } from '../e2e.js'
28
28
  import { HS, ACK, DATA, PING, PONG, ERROR, VMSG, SIGN_SCOPE, SESSION_TTL_MS, REVOKE_REFRESH_MS } from '../protocol.js'
@@ -251,6 +251,14 @@ export async function startRemoteAgent (opts = {}) {
251
251
  // qué decidir, así que no se decide que sí.
252
252
  const chk = await verifyChain({ data, signature, cert, expectedScope: SIGN_SCOPE, ...contextoActa(), revoked: revokedSet })
253
253
  if (!chk.ok) return send(from, { type: ERROR, error: 'no autorizado: ' + chk.reason })
254
+ // CERT ∩ ACTA. `verifyChain` comprueba QUIÉN EMITIÓ el papel; que el APARATO siga siendo
255
+ // miembro y pueda firmar lo dice el acta, y hay que preguntárselo aparte. Sin esto, un
256
+ // papel bien firmado por una selladora abría sesión aunque el acta no nombrara a ese
257
+ // aparato — o ya no lo nombrara. Bajo el modelo viejo daba igual, porque el papel ERA la
258
+ // autoridad y caducaba; con el papel atado al acta, el acta tiene que decidir.
259
+ if (!memberCanSign(link.acta, chk.device)) {
260
+ return send(from, { type: ERROR, error: 'no autorizado: acta — ese aparato no firma por este perfil' })
261
+ }
254
262
  if (data.op !== HS || typeof data.eph !== 'string') return send(from, { type: ERROR, error: 'handshake inválido' })
255
263
 
256
264
  const eph = await makeEphemeral()