@dotrino/identity 0.117.1 → 0.117.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dotrino/identity",
3
- "version": "0.117.1",
3
+ "version": "0.117.2",
4
4
  "description": "Identidad y rating de usuarios compartidos entre apps de Dotrino (vault iframe + postMessage)",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -1,4 +1,4 @@
1
- Copia vendorizada de @dotrino/proxy-client@0.35.0 (dotrino-proxy-client/src/{binpack,canonical,client,encpub,index,parts,sealing,signature,stats-log,stats,webrtc}.js).
1
+ Copia vendorizada de @dotrino/proxy-client@0.36.1 (dotrino-proxy-client/src/{binpack,canonical,client,encpub,index,parts,sealing,signature,stats-log,stats,webrtc}.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
  sealing.js resuelve @dotrino/identity/content de forma PEREZOSA (= ../../content.js
4
4
  por el import map): solo se carga si de verdad se sella algo.
@@ -24,6 +24,13 @@ import { pack, unpack, hasBinary, encodeFrame, decodeFrame } from './binpack.js'
24
24
  * proxio ya tiene atada a esta conexión desde `identify`. Nada del usuario viaja aquí.
25
25
  */
26
26
  const HELLO_TAG = '__cc_hello__'
27
+ /**
28
+ * Lo que este cliente entiende, y lo dice en el saludo (0.36.0). Hoy una cosa: `binary`, las
29
+ * tramas con bytes (binpack.js). Quien saluda sin decirlo es anterior y no las entiende, así
30
+ * que no se le mandan: se lanza `peer-no-binary` y la app lo enseña. La idea del dueño es que
31
+ * todo pase a binario con el tiempo, y esta lista es por donde se sabrá quién ya puede.
32
+ */
33
+ const SPEAKS = ['binary']
27
34
 
28
35
  function errorCon (mensaje, code) {
29
36
  const e = /** @type {Error & { code: string }} */ (new Error(mensaje))
@@ -136,6 +143,10 @@ export class WebSocketProxyClient {
136
143
  * son de nadie.
137
144
  */
138
145
  this._tokenPubkeys = new Map()
146
+ // Lo que dijo entender cada token en su saludo, y cada identidad (para lo que va por
147
+ // pubkey). Sin saludo no se sabe, y entonces no se frena nada.
148
+ this._tokenSpeaks = new Map()
149
+ this._pubkeySpeaks = new Map()
139
150
  this._helloSent = new Set()
140
151
 
141
152
  /** Mi propia identidad en el cable, la que `identify` dejó atada a este token. */
@@ -518,8 +529,9 @@ export class WebSocketProxyClient {
518
529
  if (m.len > queueMax) {
519
530
  throw errorCon(`sendSealed: ${m.len} ${m.bin ? 'bytes' : 'chars'} is more than can wait in the proxy (${queueMax}); send it by token while both ends are connected`, 'too-big-for-queue')
520
531
  }
521
- // Por pubkey todo va por el proxio: si no admite bytes, se dice antes de mandar nada.
522
- if (m.bin) this._needBinaryProxy()
532
+ // Por pubkey todo va por el proxio: si no admite bytes, se dice antes de mandar nada. Y
533
+ // si alguno de los destinatarios dijo que no los entiende, tampoco.
534
+ if (m.bin) { this._needBinaryProxy(); this._needPeerBinary(list) }
523
535
  const partSize = m.bin ? PROXY_PART_BYTES : PROXY_PART_CHARS
524
536
  const pieces = m.len <= partSize ? [m.bin ? m.whole : payload]
525
537
  : m.bin ? splitBinParts(m.whole, partSize) : splitParts(m.whole, partSize)
@@ -579,6 +591,9 @@ export class WebSocketProxyClient {
579
591
  const size = m.bin ? (direct ? DIRECT_PART_BYTES : PROXY_PART_BYTES) : (direct ? DIRECT_PART_CHARS : PROXY_PART_CHARS)
580
592
  const relayMax = m.bin ? RELAY_MAX_BYTES : RELAY_MAX_CHARS
581
593
  const queueMax = m.bin ? QUEUE_MAX_BYTES : QUEUE_MAX_CHARS
594
+ // Por token decide lo que dijo ESA conexión: lo recordado de la identidad puede ser de una
595
+ // versión que ya se actualizó.
596
+ if (m.bin) this._needPeerBinary(tokens)
582
597
  if (m.bin && !direct) this._needBinaryProxy()
583
598
  const sealPiece = await this._sealerFor(m.bin, peerEncPub, peerPubkey)
584
599
  if (m.len <= size) {
@@ -718,7 +733,8 @@ export class WebSocketProxyClient {
718
733
  * Un token es una dirección del proxio y no dice de quién es, así que sin esto no hay
719
734
  * a quién sellarle: una sala de desconocidos se queda muda o —lo que pasaba— hablando
720
735
  * en claro. El saludo lleva SOLO mi llave pública, la misma que el proxio ya tiene
721
- * atada a esta conexión desde `identify`; no hay nada del usuario dentro y por eso no
736
+ * atada a esta conexión desde `identify`, y lo que este cliente entiende (`SPEAKS`, que es
737
+ * lo mismo para todos los de esta versión); no hay nada del usuario dentro y por eso no
722
738
  * necesita sobre.
723
739
  *
724
740
  * Quien lo recibe contesta el suyo una vez, así que basta con que salude UNA de las
@@ -737,7 +753,7 @@ export class WebSocketProxyClient {
737
753
  for (const t of tokens) {
738
754
  if (!t || t === this.token) continue
739
755
  this._helloSent.add(t)
740
- this._proxySendOne(t, { t: HELLO_TAG, publickey: this.myPublickey })
756
+ this._proxySendOne(t, { t: HELLO_TAG, publickey: this.myPublickey, speaks: SPEAKS })
741
757
  }
742
758
  }
743
759
 
@@ -748,9 +764,34 @@ export class WebSocketProxyClient {
748
764
 
749
765
  /** Olvidar un token (se fue, o se quiere volver a preguntar). Sin argumento, todos. */
750
766
  forgetToken (token) {
751
- if (token == null) { this._tokenPubkeys.clear(); this._helloSent.clear(); return }
767
+ if (token == null) { this._tokenPubkeys.clear(); this._helloSent.clear(); this._tokenSpeaks.clear(); return }
752
768
  this._tokenPubkeys.delete(token)
753
769
  this._helloSent.delete(token)
770
+ this._tokenSpeaks.delete(token)
771
+ }
772
+
773
+ /**
774
+ * ¿Entiende esto la otra punta? `true` o `false` si lo dijo en su saludo, y `null` si
775
+ * todavía no ha saludado (no se sabe). Acepta un token o una pubkey.
776
+ * @param {string} who
777
+ * @param {string} [feature]
778
+ * @returns {boolean|null}
779
+ */
780
+ speaks (who, feature = 'binary') {
781
+ let set = this._tokenSpeaks.get(who) || this._pubkeySpeaks.get(who)
782
+ if (!set) {
783
+ for (const [pk, s] of this._pubkeySpeaks) if (samePubkey(pk, who)) { set = s; break }
784
+ }
785
+ return set ? set.has(feature) : null
786
+ }
787
+
788
+ /** Antes de mandar bytes: si alguno dijo que no los entiende, no sale nada y se dice. */
789
+ _needPeerBinary (targets) {
790
+ for (const t of targets) {
791
+ if (t && this.speaks(t, 'binary') === false) {
792
+ throw errorCon('the other side does not take binary messages (it needs @dotrino/proxy-client >= 0.36.0)', 'peer-no-binary')
793
+ }
794
+ }
754
795
  }
755
796
 
756
797
  _onHello (from, msg) {
@@ -764,6 +805,9 @@ export class WebSocketProxyClient {
764
805
  return
765
806
  }
766
807
  this._tokenPubkeys.set(from, msg.publickey)
808
+ const speaks = new Set(Array.isArray(msg.speaks) ? msg.speaks.filter((x) => typeof x === 'string').slice(0, 32) : [])
809
+ this._tokenSpeaks.set(from, speaks)
810
+ this._pubkeySpeaks.set(msg.publickey, speaks)
767
811
  // Contestar UNA vez: el saludo queda simétrico sin rebotar para siempre.
768
812
  if (!this._helloSent.has(from) && this.myPublickey) this.helloTo(from)
769
813
  this._emit('peer_identity', from, msg.publickey)
@@ -1,3 +1,3 @@
1
- Copia vendorizada de @dotrino/roadmap@0.4.17 (dotrino-roadmap/src/{index,manifests}.js).
1
+ Copia vendorizada de @dotrino/roadmap@0.4.18 (dotrino-roadmap/src/{index,manifests}.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
  El registro de versiones rotas que viaja con cada versión. Importa @dotrino/compat/ranges.
@@ -8,7 +8,7 @@
8
8
  export const MANIFESTS = Object.freeze({
9
9
  "dotrino": {
10
10
  "manifest": "dotrino",
11
- "seq": 27,
11
+ "seq": 28,
12
12
  "issued": "2026-10-15",
13
13
  "note": "Registro comun de compatibilidad del ecosistema. Se edita a mano en este repo y se consulta con @dotrino/roadmap. Rangos: ver @dotrino/compat/ranges (x.y.z, >= > <= <, «a - b», «*», o una lista que es un O).",
14
14
  "products": {
@@ -31,7 +31,7 @@ export const MANIFESTS = Object.freeze({
31
31
  "identity": {
32
32
  "repo": "imdotrino/dotrino-identity",
33
33
  "npm": "@dotrino/identity",
34
- "current": "0.116.0",
34
+ "current": "0.117.1",
35
35
  "protocol": 1,
36
36
  "requires": {}
37
37
  },
@@ -47,13 +47,13 @@ export const MANIFESTS = Object.freeze({
47
47
  },
48
48
  "messenger": {
49
49
  "repo": "imdotrino/dotrino-messenger",
50
- "current": "0.7.0",
50
+ "current": "0.8.0",
51
51
  "protocol": 2,
52
52
  "requires": {
53
- "identity": ">=0.108.0",
54
- "proxy-client": ">=0.34.0",
53
+ "identity": ">=0.117.0",
54
+ "proxy-client": ">=0.35.0",
55
55
  "store": ">=0.12.3",
56
- "proxy": "1.5.2+"
56
+ "proxy": "1.6.1+"
57
57
  }
58
58
  },
59
59
  "messenger-android": {
@@ -107,7 +107,7 @@ export const MANIFESTS = Object.freeze({
107
107
  },
108
108
  "proxy": {
109
109
  "repo": "imdotrino/dotrino-proxy",
110
- "current": "1.5.2",
110
+ "current": "1.6.1",
111
111
  "protocol": 2,
112
112
  "requires": {
113
113
  "vault": ">=0.86.0",
@@ -119,7 +119,7 @@ export const MANIFESTS = Object.freeze({
119
119
  "proxy-client": {
120
120
  "repo": "imdotrino/dotrino-proxy-client",
121
121
  "npm": "@dotrino/proxy-client",
122
- "current": "0.34.0",
122
+ "current": "0.35.0",
123
123
  "protocol": 2,
124
124
  "requires": {
125
125
  "identity": ">=0.53.0",
@@ -796,6 +796,12 @@ export const MANIFESTS = Object.freeze({
796
796
  "versions": "1.9.0",
797
797
  "why": "no tiene UI propia: sus tres superficies son iframes a messenger.dotrino.com con ?embed=, y el soporte de ese modo (puente de identidad, espejo de conversaciones, cola de salida, aviso de DM) se quitó del messenger después de la 0.1.0; la PWA servida siempre es la última, así que el panel se inventa una cuenta en cada sitio y no recibe nada",
798
798
  "fix": "no hay versión que funcione: hay que elegir el camino del README de dotrino-messenger-extension (extensión autónoma con los pilares, o un modo embed del ecosistema)"
799
+ },
800
+ {
801
+ "product": "proxy",
802
+ "versions": "1.6.0",
803
+ "why": "pasa a base64 los mensajes binarios para cruzar la malla, y una parte de 768 KB así pasa de la trama de 1 MB del otro nodo: el enlace se cae en cada reconexión al reenviarla y todo lo que va detrás entre los dos nodos se queda atascado",
804
+ "fix": "websocket-proxy 1.6.1"
799
805
  }
800
806
  ]
801
807
  }
@@ -5,4 +5,4 @@
5
5
  * si no coincide con la del paquete: una versión anunciada que no es la que corre es peor
6
6
  * que no anunciar ninguna.
7
7
  */
8
- export const LIB_VERSION = '0.86.0'
8
+ export const LIB_VERSION = '0.86.1'