@dotrino/identity 0.104.1 → 0.104.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 +1 -1
- package/vault/nativeStore.js +0 -80
- package/vault/vault.js +2 -9
package/package.json
CHANGED
package/vault/nativeStore.js
CHANGED
|
@@ -79,83 +79,3 @@ export async function nativeBackends (bridge) {
|
|
|
79
79
|
return { kv, keyStore, peers, flush: () => chain }
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
const PROFILES = 'dotrino.identity.profiles'
|
|
83
|
-
const CURRENT = 'dotrino.identity.current'
|
|
84
|
-
const scopedKey = (pid, k) => `dotrino.identity.p.${pid}.${k}`
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* LOS PERFILES QUE SE QUEDARON EN LA PÁGINA pasan a la app (dueño, 2026-09-26: «todas las
|
|
88
|
-
* pestañas usan el mismo perfil, pero NO es el de Dotrino que está en Pedidos»).
|
|
89
|
-
*
|
|
90
|
-
* Antes de `nativeStore` cada página guardaba la identidad aparte, así que la cuenta que se
|
|
91
|
-
* emparejó en `vault.dotrino.com/d` quedó en el almacén de ESA página: su llave está en el
|
|
92
|
-
* chip (Pedidos la usa), pero su acta, su papel y su nombre no llegaron a la app, y la app
|
|
93
|
-
* estrenó un perfil vacío. Esto la trae.
|
|
94
|
-
*
|
|
95
|
-
* Solo se trae un perfil cuya llave VIVE en el chip (`open` contesta): uno de software no
|
|
96
|
-
* cabe, y uno cuya llave ya se borró no sirve para nada. Lo que la app ya tiene no se pisa.
|
|
97
|
-
* Y si el perfil activo de la app no está emparejado y el traído sí, pasa a ser el activo:
|
|
98
|
-
* el vacío se inventó justo porque faltaba este.
|
|
99
|
-
*
|
|
100
|
-
* `page`: lo que hay en el almacén de ESTA página — `kv` (entradas del localStorage),
|
|
101
|
-
* `keys` (registros del IndexedDB de llaves) y `peers` (libros de contactos).
|
|
102
|
-
*/
|
|
103
|
-
export async function adoptPageProfiles (native, bridge, page) {
|
|
104
|
-
const mine = JSON.parse(native.kv.getItem(PROFILES) || '[]')
|
|
105
|
-
const theirs = JSON.parse(page.kv.get(PROFILES) || '[]')
|
|
106
|
-
const adopted = []
|
|
107
|
-
for (const p of theirs) {
|
|
108
|
-
if (!p?.id || mine.some((m) => m.id === p.id)) continue
|
|
109
|
-
const sign = page.keys.get(scopedKey(p.id, 'keypair'))
|
|
110
|
-
const enc = page.keys.get(scopedKey(p.id, 'enc-keypair'))
|
|
111
|
-
if (!sign?.external) continue
|
|
112
|
-
try { await bridge.call('open', { kid: sign.external }) } catch (_) { continue }
|
|
113
|
-
const prefix = `dotrino.identity.p.${p.id}.`
|
|
114
|
-
for (const [k, v] of page.kv) if (k.startsWith(prefix)) native.kv.setItem(k, v)
|
|
115
|
-
await native.keyStore.set(scopedKey(p.id, 'keypair'), sign)
|
|
116
|
-
if (enc?.external) await native.keyStore.set(scopedKey(p.id, 'enc-keypair'), enc)
|
|
117
|
-
const book = page.peers.get(`peers.${p.id}.v1`)
|
|
118
|
-
if (book) await native.peers.put(`peers.${p.id}.v1`, book)
|
|
119
|
-
mine.push(p)
|
|
120
|
-
adopted.push(p.id)
|
|
121
|
-
}
|
|
122
|
-
if (!adopted.length) return adopted
|
|
123
|
-
native.kv.setItem(PROFILES, JSON.stringify(mine))
|
|
124
|
-
const cur = native.kv.getItem(CURRENT)
|
|
125
|
-
const paired = (pid) => !!native.kv.getItem(scopedKey(pid, 'vault.cert'))
|
|
126
|
-
if (!cur || !paired(cur)) {
|
|
127
|
-
const next = adopted.find(paired)
|
|
128
|
-
if (next) native.kv.setItem(CURRENT, next)
|
|
129
|
-
}
|
|
130
|
-
console.info(`[cc-identity] adopted ${adopted.length} profile(s) from this page's storage into the app: ${adopted.join(', ')}`)
|
|
131
|
-
return adopted
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/** Todo lo que la identidad guardó en el almacén de ESTA página (localStorage + sus dos IndexedDB). */
|
|
135
|
-
export async function readPageStorage () {
|
|
136
|
-
const kv = new Map()
|
|
137
|
-
for (let i = 0; i < localStorage.length; i++) {
|
|
138
|
-
const k = localStorage.key(i)
|
|
139
|
-
if (k && k.startsWith('dotrino.identity.')) kv.set(k, localStorage.getItem(k))
|
|
140
|
-
}
|
|
141
|
-
return { kv, keys: await idbAll('dotrino-identity-keys', 'keys'), peers: await idbAll('cc-identity', 'kv') }
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
function idbAll (dbName, store) {
|
|
145
|
-
return new Promise((resolve, reject) => {
|
|
146
|
-
const req = indexedDB.open(dbName)
|
|
147
|
-
req.onupgradeneeded = () => { if (!req.result.objectStoreNames.contains(store)) req.result.createObjectStore(store) }
|
|
148
|
-
req.onerror = () => reject(req.error)
|
|
149
|
-
req.onsuccess = () => {
|
|
150
|
-
const db = req.result
|
|
151
|
-
if (!db.objectStoreNames.contains(store)) { db.close(); resolve(new Map()); return }
|
|
152
|
-
const out = new Map()
|
|
153
|
-
const cur = db.transaction(store, 'readonly').objectStore(store).openCursor()
|
|
154
|
-
cur.onsuccess = () => {
|
|
155
|
-
const c = cur.result
|
|
156
|
-
if (c) { out.set(String(c.key), c.value); c.continue() } else { db.close(); resolve(out) }
|
|
157
|
-
}
|
|
158
|
-
cur.onerror = () => reject(cur.error)
|
|
159
|
-
}
|
|
160
|
-
})
|
|
161
|
-
}
|
package/vault/vault.js
CHANGED
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
import { createIdentityCore } from './core.js'
|
|
16
16
|
import { pubkeyId } from './capabilities.js'
|
|
17
17
|
import { withExternalKeys, appBridge } from './externalKeys.js'
|
|
18
|
-
import { nativeBackends
|
|
18
|
+
import { nativeBackends } from './nativeStore.js'
|
|
19
19
|
import { useBackend as usePeerBackend } from './peerStore.js'
|
|
20
20
|
|
|
21
21
|
;(async () => {
|
|
@@ -25,14 +25,7 @@ import { useBackend as usePeerBackend } from './peerStore.js'
|
|
|
25
25
|
// Y si la app GUARDA la identidad (`storage`, la de iOS): todo vive allí, uno para todas
|
|
26
26
|
// las páginas, porque WebKit parte el almacén de este iframe por página (`./nativeStore.js`).
|
|
27
27
|
const native = bridge && idKeys.storage === true ? await nativeBackends(bridge) : null
|
|
28
|
-
if (native)
|
|
29
|
-
usePeerBackend(native.peers)
|
|
30
|
-
// Lo que se emparejó cuando la identidad aún vivía en la página, a la app. Si no se puede
|
|
31
|
-
// leer el almacén de la página se dice (con su error) y se sigue: la identidad de la app
|
|
32
|
-
// funciona igual, solo que sin ese perfil.
|
|
33
|
-
try { await adoptPageProfiles(native, bridge, await readPageStorage()) }
|
|
34
|
-
catch (e) { console.error('[cc-identity] could not bring this page\'s profiles into the app:', e?.message || e) }
|
|
35
|
-
}
|
|
28
|
+
if (native) usePeerBackend(native.peers)
|
|
36
29
|
|
|
37
30
|
// kv estilo localStorage (síncrono) para me, nonces, delegaciones, certs.
|
|
38
31
|
const kv = native ? native.kv : {
|