@weaveprotocol/core 0.1.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 (430) hide show
  1. package/README.md +1106 -0
  2. package/dist/elements/auth-styles.d.ts +18 -0
  3. package/dist/elements/auth-styles.d.ts.map +1 -0
  4. package/dist/elements/auth-styles.js +150 -0
  5. package/dist/elements/auth-styles.js.map +1 -0
  6. package/dist/elements/dom.d.ts +28 -0
  7. package/dist/elements/dom.d.ts.map +1 -0
  8. package/dist/elements/dom.js +74 -0
  9. package/dist/elements/dom.js.map +1 -0
  10. package/dist/elements/index.d.ts +13 -0
  11. package/dist/elements/index.d.ts.map +1 -0
  12. package/dist/elements/index.js +11 -0
  13. package/dist/elements/index.js.map +1 -0
  14. package/dist/elements/weave-auth.d.ts +52 -0
  15. package/dist/elements/weave-auth.d.ts.map +1 -0
  16. package/dist/elements/weave-auth.js +427 -0
  17. package/dist/elements/weave-auth.js.map +1 -0
  18. package/dist/identity/account-store.d.ts +113 -0
  19. package/dist/identity/account-store.d.ts.map +1 -0
  20. package/dist/identity/account-store.js +305 -0
  21. package/dist/identity/account-store.js.map +1 -0
  22. package/dist/identity/account-vault.d.ts +199 -0
  23. package/dist/identity/account-vault.d.ts.map +1 -0
  24. package/dist/identity/account-vault.js +251 -0
  25. package/dist/identity/account-vault.js.map +1 -0
  26. package/dist/identity/agent-note.d.ts +19 -0
  27. package/dist/identity/agent-note.d.ts.map +1 -0
  28. package/dist/identity/agent-note.js +29 -0
  29. package/dist/identity/agent-note.js.map +1 -0
  30. package/dist/identity/crypto-p256.d.ts +7 -0
  31. package/dist/identity/crypto-p256.d.ts.map +1 -0
  32. package/dist/identity/crypto-p256.js +84 -0
  33. package/dist/identity/crypto-p256.js.map +1 -0
  34. package/dist/identity/device-key.d.ts +60 -0
  35. package/dist/identity/device-key.d.ts.map +1 -0
  36. package/dist/identity/device-key.js +103 -0
  37. package/dist/identity/device-key.js.map +1 -0
  38. package/dist/identity/did.d.ts +22 -0
  39. package/dist/identity/did.d.ts.map +1 -0
  40. package/dist/identity/did.js +37 -0
  41. package/dist/identity/did.js.map +1 -0
  42. package/dist/identity/folder-account.d.ts +65 -0
  43. package/dist/identity/folder-account.d.ts.map +1 -0
  44. package/dist/identity/folder-account.js +115 -0
  45. package/dist/identity/folder-account.js.map +1 -0
  46. package/dist/identity/identity-manager.d.ts +36 -0
  47. package/dist/identity/identity-manager.d.ts.map +1 -0
  48. package/dist/identity/identity-manager.js +115 -0
  49. package/dist/identity/identity-manager.js.map +1 -0
  50. package/dist/identity/index.d.ts +10 -0
  51. package/dist/identity/index.d.ts.map +1 -0
  52. package/dist/identity/index.js +10 -0
  53. package/dist/identity/index.js.map +1 -0
  54. package/dist/identity/keys.d.ts +24 -0
  55. package/dist/identity/keys.d.ts.map +1 -0
  56. package/dist/identity/keys.js +38 -0
  57. package/dist/identity/keys.js.map +1 -0
  58. package/dist/identity/pairing.d.ts +83 -0
  59. package/dist/identity/pairing.d.ts.map +1 -0
  60. package/dist/identity/pairing.js +120 -0
  61. package/dist/identity/pairing.js.map +1 -0
  62. package/dist/identity/passkey-diagnostics.d.ts +54 -0
  63. package/dist/identity/passkey-diagnostics.d.ts.map +1 -0
  64. package/dist/identity/passkey-diagnostics.js +178 -0
  65. package/dist/identity/passkey-diagnostics.js.map +1 -0
  66. package/dist/identity/recovery-code.d.ts +50 -0
  67. package/dist/identity/recovery-code.d.ts.map +1 -0
  68. package/dist/identity/recovery-code.js +116 -0
  69. package/dist/identity/recovery-code.js.map +1 -0
  70. package/dist/identity/root-signer.d.ts +59 -0
  71. package/dist/identity/root-signer.d.ts.map +1 -0
  72. package/dist/identity/root-signer.js +44 -0
  73. package/dist/identity/root-signer.js.map +1 -0
  74. package/dist/identity/ucan.d.ts +164 -0
  75. package/dist/identity/ucan.d.ts.map +1 -0
  76. package/dist/identity/ucan.js +273 -0
  77. package/dist/identity/ucan.js.map +1 -0
  78. package/dist/identity/webauthn.d.ts +87 -0
  79. package/dist/identity/webauthn.d.ts.map +1 -0
  80. package/dist/identity/webauthn.js +155 -0
  81. package/dist/identity/webauthn.js.map +1 -0
  82. package/dist/index.d.ts +116 -0
  83. package/dist/index.d.ts.map +1 -0
  84. package/dist/index.js +85 -0
  85. package/dist/index.js.map +1 -0
  86. package/dist/network/index.d.ts +17 -0
  87. package/dist/network/index.d.ts.map +1 -0
  88. package/dist/network/index.js +10 -0
  89. package/dist/network/index.js.map +1 -0
  90. package/dist/network/introductions.d.ts +85 -0
  91. package/dist/network/introductions.d.ts.map +1 -0
  92. package/dist/network/introductions.js +94 -0
  93. package/dist/network/introductions.js.map +1 -0
  94. package/dist/network/local-transport.d.ts +22 -0
  95. package/dist/network/local-transport.d.ts.map +1 -0
  96. package/dist/network/local-transport.js +55 -0
  97. package/dist/network/local-transport.js.map +1 -0
  98. package/dist/network/mesh.d.ts +31 -0
  99. package/dist/network/mesh.d.ts.map +1 -0
  100. package/dist/network/mesh.js +332 -0
  101. package/dist/network/mesh.js.map +1 -0
  102. package/dist/network/multi-signaling.d.ts +29 -0
  103. package/dist/network/multi-signaling.d.ts.map +1 -0
  104. package/dist/network/multi-signaling.js +125 -0
  105. package/dist/network/multi-signaling.js.map +1 -0
  106. package/dist/network/network-manager.d.ts +37 -0
  107. package/dist/network/network-manager.d.ts.map +1 -0
  108. package/dist/network/network-manager.js +64 -0
  109. package/dist/network/network-manager.js.map +1 -0
  110. package/dist/network/peer-auth.d.ts +98 -0
  111. package/dist/network/peer-auth.d.ts.map +1 -0
  112. package/dist/network/peer-auth.js +86 -0
  113. package/dist/network/peer-auth.js.map +1 -0
  114. package/dist/network/rtc-transport.d.ts +18 -0
  115. package/dist/network/rtc-transport.d.ts.map +1 -0
  116. package/dist/network/rtc-transport.js +149 -0
  117. package/dist/network/rtc-transport.js.map +1 -0
  118. package/dist/network/signaling.d.ts +40 -0
  119. package/dist/network/signaling.d.ts.map +1 -0
  120. package/dist/network/signaling.js +124 -0
  121. package/dist/network/signaling.js.map +1 -0
  122. package/dist/network/transport.d.ts +50 -0
  123. package/dist/network/transport.d.ts.map +1 -0
  124. package/dist/network/transport.js +13 -0
  125. package/dist/network/transport.js.map +1 -0
  126. package/dist/network/ws-transport.d.ts +42 -0
  127. package/dist/network/ws-transport.d.ts.map +1 -0
  128. package/dist/network/ws-transport.js +194 -0
  129. package/dist/network/ws-transport.js.map +1 -0
  130. package/dist/node/actions.d.ts +62 -0
  131. package/dist/node/actions.d.ts.map +1 -0
  132. package/dist/node/actions.js +500 -0
  133. package/dist/node/actions.js.map +1 -0
  134. package/dist/node/carrier.d.ts +85 -0
  135. package/dist/node/carrier.d.ts.map +1 -0
  136. package/dist/node/carrier.js +192 -0
  137. package/dist/node/carrier.js.map +1 -0
  138. package/dist/node/copy.d.ts +38 -0
  139. package/dist/node/copy.d.ts.map +1 -0
  140. package/dist/node/copy.js +53 -0
  141. package/dist/node/copy.js.map +1 -0
  142. package/dist/node/index.d.ts +16 -0
  143. package/dist/node/index.d.ts.map +1 -0
  144. package/dist/node/index.js +11 -0
  145. package/dist/node/index.js.map +1 -0
  146. package/dist/node/node.d.ts +12 -0
  147. package/dist/node/node.d.ts.map +1 -0
  148. package/dist/node/node.js +872 -0
  149. package/dist/node/node.js.map +1 -0
  150. package/dist/node/space-runtime.d.ts +144 -0
  151. package/dist/node/space-runtime.d.ts.map +1 -0
  152. package/dist/node/space-runtime.js +1221 -0
  153. package/dist/node/space-runtime.js.map +1 -0
  154. package/dist/node/stores.d.ts +45 -0
  155. package/dist/node/stores.d.ts.map +1 -0
  156. package/dist/node/stores.js +31 -0
  157. package/dist/node/stores.js.map +1 -0
  158. package/dist/node/types.d.ts +508 -0
  159. package/dist/node/types.d.ts.map +1 -0
  160. package/dist/node/types.js +2 -0
  161. package/dist/node/types.js.map +1 -0
  162. package/dist/privacy/index.d.ts +4 -0
  163. package/dist/privacy/index.d.ts.map +1 -0
  164. package/dist/privacy/index.js +4 -0
  165. package/dist/privacy/index.js.map +1 -0
  166. package/dist/privacy/key-distribution.d.ts +42 -0
  167. package/dist/privacy/key-distribution.d.ts.map +1 -0
  168. package/dist/privacy/key-distribution.js +50 -0
  169. package/dist/privacy/key-distribution.js.map +1 -0
  170. package/dist/privacy/privacy-guard.d.ts +24 -0
  171. package/dist/privacy/privacy-guard.d.ts.map +1 -0
  172. package/dist/privacy/privacy-guard.js +87 -0
  173. package/dist/privacy/privacy-guard.js.map +1 -0
  174. package/dist/privacy/space-encryption.d.ts +48 -0
  175. package/dist/privacy/space-encryption.d.ts.map +1 -0
  176. package/dist/privacy/space-encryption.js +61 -0
  177. package/dist/privacy/space-encryption.js.map +1 -0
  178. package/dist/query/engine.d.ts +27 -0
  179. package/dist/query/engine.d.ts.map +1 -0
  180. package/dist/query/engine.js +84 -0
  181. package/dist/query/engine.js.map +1 -0
  182. package/dist/query/filter.d.ts +15 -0
  183. package/dist/query/filter.d.ts.map +1 -0
  184. package/dist/query/filter.js +207 -0
  185. package/dist/query/filter.js.map +1 -0
  186. package/dist/query/types.d.ts +144 -0
  187. package/dist/query/types.d.ts.map +1 -0
  188. package/dist/query/types.js +22 -0
  189. package/dist/query/types.js.map +1 -0
  190. package/dist/react/context.d.ts +81 -0
  191. package/dist/react/context.d.ts.map +1 -0
  192. package/dist/react/context.js +95 -0
  193. package/dist/react/context.js.map +1 -0
  194. package/dist/react/index.d.ts +40 -0
  195. package/dist/react/index.d.ts.map +1 -0
  196. package/dist/react/index.js +36 -0
  197. package/dist/react/index.js.map +1 -0
  198. package/dist/react/use-live.d.ts +16 -0
  199. package/dist/react/use-live.d.ts.map +1 -0
  200. package/dist/react/use-live.js +55 -0
  201. package/dist/react/use-live.js.map +1 -0
  202. package/dist/react/use-query.d.ts +17 -0
  203. package/dist/react/use-query.d.ts.map +1 -0
  204. package/dist/react/use-query.js +23 -0
  205. package/dist/react/use-query.js.map +1 -0
  206. package/dist/react/use-space.d.ts +29 -0
  207. package/dist/react/use-space.d.ts.map +1 -0
  208. package/dist/react/use-space.js +48 -0
  209. package/dist/react/use-space.js.map +1 -0
  210. package/dist/react/use-spaces.d.ts +19 -0
  211. package/dist/react/use-spaces.d.ts.map +1 -0
  212. package/dist/react/use-spaces.js +55 -0
  213. package/dist/react/use-spaces.js.map +1 -0
  214. package/dist/react/use-weave-auth.d.ts +10 -0
  215. package/dist/react/use-weave-auth.d.ts.map +1 -0
  216. package/dist/react/use-weave-auth.js +15 -0
  217. package/dist/react/use-weave-auth.js.map +1 -0
  218. package/dist/react/weave-auth.d.ts +17 -0
  219. package/dist/react/weave-auth.d.ts.map +1 -0
  220. package/dist/react/weave-auth.js +38 -0
  221. package/dist/react/weave-auth.js.map +1 -0
  222. package/dist/records/describe.d.ts +38 -0
  223. package/dist/records/describe.d.ts.map +1 -0
  224. package/dist/records/describe.js +101 -0
  225. package/dist/records/describe.js.map +1 -0
  226. package/dist/records/links.d.ts +14 -0
  227. package/dist/records/links.d.ts.map +1 -0
  228. package/dist/records/links.js +25 -0
  229. package/dist/records/links.js.map +1 -0
  230. package/dist/records/rules.d.ts +59 -0
  231. package/dist/records/rules.d.ts.map +1 -0
  232. package/dist/records/rules.js +118 -0
  233. package/dist/records/rules.js.map +1 -0
  234. package/dist/records/version.d.ts +54 -0
  235. package/dist/records/version.d.ts.map +1 -0
  236. package/dist/records/version.js +70 -0
  237. package/dist/records/version.js.map +1 -0
  238. package/dist/schema/collection-def.d.ts +96 -0
  239. package/dist/schema/collection-def.d.ts.map +1 -0
  240. package/dist/schema/collection-def.js +272 -0
  241. package/dist/schema/collection-def.js.map +1 -0
  242. package/dist/schema/expression.d.ts +69 -0
  243. package/dist/schema/expression.d.ts.map +1 -0
  244. package/dist/schema/expression.js +92 -0
  245. package/dist/schema/expression.js.map +1 -0
  246. package/dist/schema/index.d.ts +4 -0
  247. package/dist/schema/index.d.ts.map +1 -0
  248. package/dist/schema/index.js +4 -0
  249. package/dist/schema/index.js.map +1 -0
  250. package/dist/schema/schema-engine.d.ts +42 -0
  251. package/dist/schema/schema-engine.d.ts.map +1 -0
  252. package/dist/schema/schema-engine.js +36 -0
  253. package/dist/schema/schema-engine.js.map +1 -0
  254. package/dist/schema/signer.d.ts +27 -0
  255. package/dist/schema/signer.d.ts.map +1 -0
  256. package/dist/schema/signer.js +36 -0
  257. package/dist/schema/signer.js.map +1 -0
  258. package/dist/schemas/apps.d.ts +88 -0
  259. package/dist/schemas/apps.d.ts.map +1 -0
  260. package/dist/schemas/apps.js +168 -0
  261. package/dist/schemas/apps.js.map +1 -0
  262. package/dist/schemas/index.d.ts +410 -0
  263. package/dist/schemas/index.d.ts.map +1 -0
  264. package/dist/schemas/index.js +208 -0
  265. package/dist/schemas/index.js.map +1 -0
  266. package/dist/schemas/screens.d.ts +67 -0
  267. package/dist/schemas/screens.d.ts.map +1 -0
  268. package/dist/schemas/screens.js +242 -0
  269. package/dist/schemas/screens.js.map +1 -0
  270. package/dist/session/agent-link.d.ts +79 -0
  271. package/dist/session/agent-link.d.ts.map +1 -0
  272. package/dist/session/agent-link.js +251 -0
  273. package/dist/session/agent-link.js.map +1 -0
  274. package/dist/session/auth.d.ts +233 -0
  275. package/dist/session/auth.d.ts.map +1 -0
  276. package/dist/session/auth.js +783 -0
  277. package/dist/session/auth.js.map +1 -0
  278. package/dist/session/connect.d.ts +211 -0
  279. package/dist/session/connect.d.ts.map +1 -0
  280. package/dist/session/connect.js +355 -0
  281. package/dist/session/connect.js.map +1 -0
  282. package/dist/session/connection.d.ts +70 -0
  283. package/dist/session/connection.d.ts.map +1 -0
  284. package/dist/session/connection.js +120 -0
  285. package/dist/session/connection.js.map +1 -0
  286. package/dist/session/credentials.d.ts +44 -0
  287. package/dist/session/credentials.d.ts.map +1 -0
  288. package/dist/session/credentials.js +60 -0
  289. package/dist/session/credentials.js.map +1 -0
  290. package/dist/session/index.d.ts +25 -0
  291. package/dist/session/index.d.ts.map +1 -0
  292. package/dist/session/index.js +18 -0
  293. package/dist/session/index.js.map +1 -0
  294. package/dist/session/pairing.d.ts +59 -0
  295. package/dist/session/pairing.d.ts.map +1 -0
  296. package/dist/session/pairing.js +144 -0
  297. package/dist/session/pairing.js.map +1 -0
  298. package/dist/session/places.d.ts +62 -0
  299. package/dist/session/places.d.ts.map +1 -0
  300. package/dist/session/places.js +101 -0
  301. package/dist/session/places.js.map +1 -0
  302. package/dist/session/stay-signed-in.d.ts +37 -0
  303. package/dist/session/stay-signed-in.d.ts.map +1 -0
  304. package/dist/session/stay-signed-in.js +124 -0
  305. package/dist/session/stay-signed-in.js.map +1 -0
  306. package/dist/space/account-registry.d.ts +64 -0
  307. package/dist/space/account-registry.d.ts.map +1 -0
  308. package/dist/space/account-registry.js +66 -0
  309. package/dist/space/account-registry.js.map +1 -0
  310. package/dist/space/index.d.ts +3 -0
  311. package/dist/space/index.d.ts.map +1 -0
  312. package/dist/space/index.js +3 -0
  313. package/dist/space/index.js.map +1 -0
  314. package/dist/space/pass.d.ts +63 -0
  315. package/dist/space/pass.d.ts.map +1 -0
  316. package/dist/space/pass.js +54 -0
  317. package/dist/space/pass.js.map +1 -0
  318. package/dist/space/presets.d.ts +31 -0
  319. package/dist/space/presets.d.ts.map +1 -0
  320. package/dist/space/presets.js +24 -0
  321. package/dist/space/presets.js.map +1 -0
  322. package/dist/space/roles.d.ts +186 -0
  323. package/dist/space/roles.d.ts.map +1 -0
  324. package/dist/space/roles.js +500 -0
  325. package/dist/space/roles.js.map +1 -0
  326. package/dist/space/space-access.d.ts +80 -0
  327. package/dist/space/space-access.d.ts.map +1 -0
  328. package/dist/space/space-access.js +135 -0
  329. package/dist/space/space-access.js.map +1 -0
  330. package/dist/space/space-manager.d.ts +87 -0
  331. package/dist/space/space-manager.d.ts.map +1 -0
  332. package/dist/space/space-manager.js +187 -0
  333. package/dist/space/space-manager.js.map +1 -0
  334. package/dist/storage/directory-access.d.ts +78 -0
  335. package/dist/storage/directory-access.d.ts.map +1 -0
  336. package/dist/storage/directory-access.js +164 -0
  337. package/dist/storage/directory-access.js.map +1 -0
  338. package/dist/storage/encrypted-adapter.d.ts +49 -0
  339. package/dist/storage/encrypted-adapter.d.ts.map +1 -0
  340. package/dist/storage/encrypted-adapter.js +106 -0
  341. package/dist/storage/encrypted-adapter.js.map +1 -0
  342. package/dist/storage/folder-adapter.d.ts +105 -0
  343. package/dist/storage/folder-adapter.d.ts.map +1 -0
  344. package/dist/storage/folder-adapter.js +280 -0
  345. package/dist/storage/folder-adapter.js.map +1 -0
  346. package/dist/storage/folder-reconcile.d.ts +53 -0
  347. package/dist/storage/folder-reconcile.d.ts.map +1 -0
  348. package/dist/storage/folder-reconcile.js +65 -0
  349. package/dist/storage/folder-reconcile.js.map +1 -0
  350. package/dist/storage/index.d.ts +10 -0
  351. package/dist/storage/index.d.ts.map +1 -0
  352. package/dist/storage/index.js +9 -0
  353. package/dist/storage/index.js.map +1 -0
  354. package/dist/storage/indexeddb-adapter.d.ts +12 -0
  355. package/dist/storage/indexeddb-adapter.d.ts.map +1 -0
  356. package/dist/storage/indexeddb-adapter.js +190 -0
  357. package/dist/storage/indexeddb-adapter.js.map +1 -0
  358. package/dist/storage/mst.d.ts +121 -0
  359. package/dist/storage/mst.d.ts.map +1 -0
  360. package/dist/storage/mst.js +402 -0
  361. package/dist/storage/mst.js.map +1 -0
  362. package/dist/storage/storage-provider.d.ts +85 -0
  363. package/dist/storage/storage-provider.d.ts.map +1 -0
  364. package/dist/storage/storage-provider.js +220 -0
  365. package/dist/storage/storage-provider.js.map +1 -0
  366. package/dist/sync/anti-entropy.d.ts +49 -0
  367. package/dist/sync/anti-entropy.d.ts.map +1 -0
  368. package/dist/sync/anti-entropy.js +62 -0
  369. package/dist/sync/anti-entropy.js.map +1 -0
  370. package/dist/sync/index.d.ts +4 -0
  371. package/dist/sync/index.d.ts.map +1 -0
  372. package/dist/sync/index.js +4 -0
  373. package/dist/sync/index.js.map +1 -0
  374. package/dist/sync/sync-engine.d.ts +71 -0
  375. package/dist/sync/sync-engine.d.ts.map +1 -0
  376. package/dist/sync/sync-engine.js +309 -0
  377. package/dist/sync/sync-engine.js.map +1 -0
  378. package/dist/sync/sync-messages.d.ts +75 -0
  379. package/dist/sync/sync-messages.d.ts.map +1 -0
  380. package/dist/sync/sync-messages.js +12 -0
  381. package/dist/sync/sync-messages.js.map +1 -0
  382. package/dist/types.d.ts +243 -0
  383. package/dist/types.d.ts.map +1 -0
  384. package/dist/types.js +7 -0
  385. package/dist/types.js.map +1 -0
  386. package/dist/utils/encoding.d.ts +63 -0
  387. package/dist/utils/encoding.d.ts.map +1 -0
  388. package/dist/utils/encoding.js +130 -0
  389. package/dist/utils/encoding.js.map +1 -0
  390. package/dist/utils/errors.d.ts +43 -0
  391. package/dist/utils/errors.d.ts.map +1 -0
  392. package/dist/utils/errors.js +28 -0
  393. package/dist/utils/errors.js.map +1 -0
  394. package/dist/utils/events.d.ts +19 -0
  395. package/dist/utils/events.d.ts.map +1 -0
  396. package/dist/utils/events.js +27 -0
  397. package/dist/utils/events.js.map +1 -0
  398. package/dist/utils/hash.d.ts +23 -0
  399. package/dist/utils/hash.d.ts.map +1 -0
  400. package/dist/utils/hash.js +49 -0
  401. package/dist/utils/hash.js.map +1 -0
  402. package/dist/utils/index.d.ts +9 -0
  403. package/dist/utils/index.d.ts.map +1 -0
  404. package/dist/utils/index.js +9 -0
  405. package/dist/utils/index.js.map +1 -0
  406. package/dist/validation/capability-gate.d.ts +50 -0
  407. package/dist/validation/capability-gate.d.ts.map +1 -0
  408. package/dist/validation/capability-gate.js +71 -0
  409. package/dist/validation/capability-gate.js.map +1 -0
  410. package/dist/validation/crypto-gate.d.ts +16 -0
  411. package/dist/validation/crypto-gate.d.ts.map +1 -0
  412. package/dist/validation/crypto-gate.js +37 -0
  413. package/dist/validation/crypto-gate.js.map +1 -0
  414. package/dist/validation/index.d.ts +6 -0
  415. package/dist/validation/index.d.ts.map +1 -0
  416. package/dist/validation/index.js +6 -0
  417. package/dist/validation/index.js.map +1 -0
  418. package/dist/validation/stateful-gate.d.ts +15 -0
  419. package/dist/validation/stateful-gate.d.ts.map +1 -0
  420. package/dist/validation/stateful-gate.js +50 -0
  421. package/dist/validation/stateful-gate.js.map +1 -0
  422. package/dist/validation/structural-gate.d.ts +18 -0
  423. package/dist/validation/structural-gate.d.ts.map +1 -0
  424. package/dist/validation/structural-gate.js +54 -0
  425. package/dist/validation/structural-gate.js.map +1 -0
  426. package/dist/validation/validation-engine.d.ts +28 -0
  427. package/dist/validation/validation-engine.d.ts.map +1 -0
  428. package/dist/validation/validation-engine.js +38 -0
  429. package/dist/validation/validation-engine.js.map +1 -0
  430. package/package.json +107 -0
@@ -0,0 +1,120 @@
1
+ /**
2
+ * @module pairing
3
+ * Handing an account to a phone.
4
+ *
5
+ * A phone cannot open a folder — no mobile browser has the File System Access
6
+ * API — so it keeps its own copy of the data, like any other peer. What it needs
7
+ * from the desktop is two things: who you are, and which lists exist.
8
+ *
9
+ * The first fits in a QR code. The second does not, and does not need to: once
10
+ * both sides know the seed they can each work out the same private meeting room
11
+ * and the same key, meet there over the ordinary peer connection, and hand the
12
+ * list of lists across encrypted. So the code stays small enough for a phone
13
+ * camera to read from across a desk.
14
+ *
15
+ * Deriving the room from the *seed* rather than from the DID matters. A DID
16
+ * appears in every expression the account has ever signed, so a room named after
17
+ * one would be a room anyone could find. A room named after the seed can only be
18
+ * found by someone who already has it.
19
+ *
20
+ * What this is not: the phone does not become a satellite of the desktop. It
21
+ * derives the same identity and becomes a full peer, syncing with anyone in the
22
+ * space. The desktop was a bootstrap, and can go offline immediately afterwards.
23
+ */
24
+ import { base64UrlEncode, base64UrlDecode, utf8Encode, utf8Decode, concatBytes } from '../utils/encoding.js';
25
+ import { cidFromBytes } from '../utils/hash.js';
26
+ import { protocolError } from '../utils/errors.js';
27
+ const ROOM_PREFIX = utf8Encode('weave-pairing-room-v1');
28
+ const PAIRING_KEY_INFO = utf8Encode('weave-pairing-key-v1');
29
+ const IV_BYTES = 12;
30
+ /**
31
+ * The room both devices meet in.
32
+ *
33
+ * Derived from the seed, so finding it already requires the secret. Both sides
34
+ * compute it independently and neither has to send it.
35
+ *
36
+ * @param seed The account seed
37
+ * @returns An opaque room id for the signaling relay
38
+ */
39
+ export async function pairingRoomId(seed) {
40
+ return cidFromBytes(concatBytes(ROOM_PREFIX, seed));
41
+ }
42
+ /**
43
+ * The key the handover is encrypted with.
44
+ *
45
+ * Separate from the vault key and from the signing key, so that a relay
46
+ * operator watching the room learns nothing but the size of the payload.
47
+ *
48
+ * @param seed The account seed
49
+ * @returns An AES-GCM key
50
+ */
51
+ export async function derivePairingKey(seed) {
52
+ const material = await globalThis.crypto.subtle.importKey('raw', seed, { name: 'HKDF' }, false, ['deriveKey']);
53
+ return globalThis.crypto.subtle.deriveKey({
54
+ name: 'HKDF',
55
+ hash: 'SHA-256',
56
+ salt: new Uint8Array(0),
57
+ info: PAIRING_KEY_INFO,
58
+ }, material, { name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt']);
59
+ }
60
+ /**
61
+ * Packs a ticket for a URL fragment.
62
+ *
63
+ * A fragment, because browsers never put one in a request — so the seed reaches
64
+ * the phone without passing through the server hosting the page, the same way a
65
+ * space invite carries its key.
66
+ *
67
+ * @param ticket What the phone needs to know
68
+ * @returns A compact string for after the `#`
69
+ */
70
+ export function encodePairingTicket(ticket) {
71
+ return base64UrlEncode(utf8Encode(JSON.stringify(ticket)));
72
+ }
73
+ /**
74
+ * Unpacks a ticket from a URL fragment.
75
+ * @param encoded The string after `#pair=`
76
+ * @returns The ticket it stands for
77
+ */
78
+ export function decodePairingTicket(encoded) {
79
+ try {
80
+ const ticket = JSON.parse(utf8Decode(base64UrlDecode(encoded.trim())));
81
+ if (ticket?.v !== 1 || typeof ticket.code !== 'string' || typeof ticket.relay !== 'string') {
82
+ throw new Error('unexpected shape');
83
+ }
84
+ return ticket;
85
+ }
86
+ catch {
87
+ throw protocolError('PAIRING_TICKET_UNREADABLE', 'That pairing link could not be read.', 'It may have been truncated, or produced by a different app. Show the code again.');
88
+ }
89
+ }
90
+ /**
91
+ * Encrypts the handover payload.
92
+ * @param plaintext What to send
93
+ * @param key From {@link derivePairingKey}
94
+ * @returns Nonce followed by ciphertext
95
+ */
96
+ export async function sealPairingPayload(plaintext, key) {
97
+ const iv = globalThis.crypto.getRandomValues(new Uint8Array(IV_BYTES));
98
+ const ciphertext = await globalThis.crypto.subtle.encrypt({ name: 'AES-GCM', iv: iv }, key, plaintext);
99
+ return concatBytes(iv, new Uint8Array(ciphertext));
100
+ }
101
+ /**
102
+ * Decrypts the handover payload.
103
+ * @param sealed What arrived
104
+ * @param key From {@link derivePairingKey}
105
+ * @returns The plaintext
106
+ */
107
+ export async function openPairingPayload(sealed, key) {
108
+ if (sealed.length <= IV_BYTES) {
109
+ throw protocolError('PAIRING_TICKET_UNREADABLE', 'That handover was too short to be real.');
110
+ }
111
+ try {
112
+ const plain = await globalThis.crypto.subtle.decrypt({ name: 'AES-GCM', iv: sealed.slice(0, IV_BYTES) }, key, sealed.slice(IV_BYTES));
113
+ return new Uint8Array(plain);
114
+ }
115
+ catch {
116
+ // Someone else in the room, or a ticket for a different account.
117
+ throw protocolError('PAIRING_TICKET_UNREADABLE', 'That handover was not meant for this account.');
118
+ }
119
+ }
120
+ //# sourceMappingURL=pairing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pairing.js","sourceRoot":"","sources":["../../src/identity/pairing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * @module passkey-diagnostics
3
+ * Reports what a browser and credential provider actually do with the PRF
4
+ * extension, so a failure can be pinned on a specific link in the chain rather
5
+ * than guessed at.
6
+ */
7
+ /** Where a ceremony's PRF request ended up */
8
+ export interface CeremonyReport {
9
+ readonly attempted: boolean;
10
+ /** Raw client extension results, with binary values summarized */
11
+ readonly extensionResults: Record<string, unknown> | null;
12
+ /** Bytes of PRF output this ceremony produced, or null for none */
13
+ readonly prfOutputBytes: number | null;
14
+ readonly error?: string;
15
+ }
16
+ export interface PasskeyDiagnostics {
17
+ readonly webauthnAvailable: boolean;
18
+ readonly platformAuthenticatorAvailable: boolean;
19
+ /** AAGUID of the authenticator that answered, and its name when recognized */
20
+ readonly provider: {
21
+ readonly aaguid: string | null;
22
+ readonly name: string | null;
23
+ };
24
+ /** Whether the creation ceremony reported `prf.enabled` */
25
+ readonly prfDeclaredAtCreate: boolean | undefined;
26
+ readonly create: CeremonyReport;
27
+ readonly assert: CeremonyReport;
28
+ /** The only question that matters: did a secret come back? */
29
+ readonly prfWorks: boolean;
30
+ /** A sentence naming the most likely culprit */
31
+ readonly summary: string;
32
+ readonly credentialId: string | null;
33
+ }
34
+ export interface DiagnosticsOptions {
35
+ readonly rpId?: string;
36
+ readonly rpName?: string;
37
+ /**
38
+ * Test this existing credential instead of creating one. Without it the run
39
+ * creates a throwaway passkey, which will appear in the user's authenticator.
40
+ */
41
+ readonly credentialId?: string;
42
+ readonly userName?: string;
43
+ }
44
+ /**
45
+ * Runs the PRF ceremonies and reports what came back at each step.
46
+ *
47
+ * Creating a passkey and asserting it are separate conversations with the
48
+ * provider, and PRF can be dropped in either — this shows which.
49
+ *
50
+ * @param options Which credential to test, and how to identify the site
51
+ * @returns A structured report, safe to display or copy into a bug report
52
+ */
53
+ export declare function inspectPasskeyPrf(options?: DiagnosticsOptions): Promise<PasskeyDiagnostics>;
54
+ //# sourceMappingURL=passkey-diagnostics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"passkey-diagnostics.d.ts","sourceRoot":"","sources":["../../src/identity/passkey-diagnostics.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,8CAA8C;AAC9C,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,kEAAkE;IAClE,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC1D,mEAAmE;IACnE,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;IACpC,QAAQ,CAAC,8BAA8B,EAAE,OAAO,CAAC;IACjD,8EAA8E;IAC9E,QAAQ,CAAC,QAAQ,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IACpF,2DAA2D;IAC3D,QAAQ,CAAC,mBAAmB,EAAE,OAAO,GAAG,SAAS,CAAC;IAClD,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,8DAA8D;IAC9D,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,gDAAgD;IAChD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CACtC;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AA8CD;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAwHjG"}
@@ -0,0 +1,178 @@
1
+ /**
2
+ * @module passkey-diagnostics
3
+ * Reports what a browser and credential provider actually do with the PRF
4
+ * extension, so a failure can be pinned on a specific link in the chain rather
5
+ * than guessed at.
6
+ */
7
+ import { base64UrlEncode, base64UrlDecode } from '../utils/encoding.js';
8
+ const PRF_SALT = new TextEncoder().encode('weave-protocol-key-v1');
9
+ /** AAGUIDs of providers common enough to be worth naming. */
10
+ const KNOWN_AAGUIDS = {
11
+ 'd548826e-79b4-db40-a3d8-11116f7e8349': 'Bitwarden',
12
+ 'bada5566-a7aa-401f-bd96-45619a55120d': '1Password',
13
+ 'fbfc3007-154e-4ecc-8c0b-6e020557d7bd': 'iCloud Keychain',
14
+ 'ea9b8d66-4d01-1d21-3ce4-b6b48cb575d4': 'Google Password Manager',
15
+ '08987058-cadc-4b81-b6e1-30de50dcbe96': 'Windows Hello',
16
+ '531126d6-e717-415c-9320-3d9aa6981239': 'Dashlane',
17
+ 'fdb141b2-5d84-443e-8a35-4698c205a502': 'KeePassXC',
18
+ '00000000-0000-0000-0000-000000000000': 'Platform authenticator (no AAGUID)',
19
+ };
20
+ /** Formats the 16 AAGUID bytes that sit at offset 37 of attested credential data. */
21
+ function readAaguid(authenticatorData) {
22
+ if (!authenticatorData || authenticatorData.byteLength < 53)
23
+ return null;
24
+ const bytes = new Uint8Array(authenticatorData).slice(37, 53);
25
+ const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');
26
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
27
+ }
28
+ /** Replaces binary values with a readable summary so the report can be shown or copied. */
29
+ function summarizeExtensions(results) {
30
+ if (!results || typeof results !== 'object')
31
+ return null;
32
+ const walk = (value) => {
33
+ if (value instanceof ArrayBuffer)
34
+ return `<${value.byteLength} bytes>`;
35
+ if (ArrayBuffer.isView(value))
36
+ return `<${value.byteLength} bytes>`;
37
+ if (Array.isArray(value))
38
+ return value.map(walk);
39
+ if (value && typeof value === 'object') {
40
+ return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, walk(v)]));
41
+ }
42
+ return value;
43
+ };
44
+ return walk(results);
45
+ }
46
+ function prfOutputLength(results) {
47
+ const first = results?.prf?.results?.first;
48
+ return first ? first.byteLength : null;
49
+ }
50
+ /**
51
+ * Runs the PRF ceremonies and reports what came back at each step.
52
+ *
53
+ * Creating a passkey and asserting it are separate conversations with the
54
+ * provider, and PRF can be dropped in either — this shows which.
55
+ *
56
+ * @param options Which credential to test, and how to identify the site
57
+ * @returns A structured report, safe to display or copy into a bug report
58
+ */
59
+ export async function inspectPasskeyPrf(options) {
60
+ const webauthnAvailable = !!globalThis.navigator?.credentials?.create;
61
+ const rpId = options?.rpId ?? (typeof globalThis.location !== 'undefined' ? globalThis.location.hostname : 'localhost');
62
+ let platformAuthenticatorAvailable = false;
63
+ try {
64
+ platformAuthenticatorAvailable =
65
+ (await globalThis.PublicKeyCredential?.isUserVerifyingPlatformAuthenticatorAvailable?.()) ?? false;
66
+ }
67
+ catch {
68
+ platformAuthenticatorAvailable = false;
69
+ }
70
+ const create = { attempted: false, extensionResults: null, prfOutputBytes: null };
71
+ const assert = { attempted: false, extensionResults: null, prfOutputBytes: null };
72
+ let credentialId = options?.credentialId ?? null;
73
+ let aaguid = null;
74
+ let prfDeclaredAtCreate;
75
+ if (!webauthnAvailable) {
76
+ return Object.freeze({
77
+ webauthnAvailable,
78
+ platformAuthenticatorAvailable,
79
+ provider: { aaguid: null, name: null },
80
+ prfDeclaredAtCreate: undefined,
81
+ create: Object.freeze(create),
82
+ assert: Object.freeze(assert),
83
+ prfWorks: false,
84
+ summary: 'WebAuthn is unavailable in this browser, so passkeys cannot be used at all.',
85
+ credentialId: null,
86
+ });
87
+ }
88
+ // 1. Creation — unless we were pointed at an existing credential.
89
+ if (!credentialId) {
90
+ create.attempted = true;
91
+ try {
92
+ const credential = (await globalThis.navigator.credentials.create({
93
+ publicKey: {
94
+ rp: { id: rpId, name: options?.rpName ?? 'PRF diagnostic' },
95
+ user: {
96
+ id: globalThis.crypto.getRandomValues(new Uint8Array(32)),
97
+ name: options?.userName ?? 'prf-diagnostic',
98
+ displayName: options?.userName ?? 'PRF diagnostic (safe to delete)',
99
+ },
100
+ challenge: globalThis.crypto.getRandomValues(new Uint8Array(32)),
101
+ pubKeyCredParams: [
102
+ { type: 'public-key', alg: -7 },
103
+ { type: 'public-key', alg: -257 },
104
+ ],
105
+ authenticatorSelection: {
106
+ residentKey: 'required',
107
+ requireResidentKey: true,
108
+ userVerification: 'required',
109
+ },
110
+ extensions: { prf: { eval: { first: PRF_SALT } } },
111
+ },
112
+ }));
113
+ const results = credential.getClientExtensionResults();
114
+ create.extensionResults = summarizeExtensions(results);
115
+ create.prfOutputBytes = prfOutputLength(results);
116
+ prfDeclaredAtCreate = results.prf?.enabled;
117
+ credentialId = base64UrlEncode(new Uint8Array(credential.rawId));
118
+ const response = credential.response;
119
+ aaguid = readAaguid(response.getAuthenticatorData?.());
120
+ }
121
+ catch (error) {
122
+ create.error = error instanceof Error ? `${error.name}: ${error.message}` : 'Creation failed';
123
+ }
124
+ }
125
+ // 2. Assertion — the ceremony that actually has to yield a secret.
126
+ if (credentialId) {
127
+ assert.attempted = true;
128
+ try {
129
+ const credential = (await globalThis.navigator.credentials.get({
130
+ publicKey: {
131
+ challenge: globalThis.crypto.getRandomValues(new Uint8Array(32)),
132
+ rpId,
133
+ userVerification: 'required',
134
+ allowCredentials: [{ type: 'public-key', id: base64UrlDecode(credentialId) }],
135
+ extensions: { prf: { eval: { first: PRF_SALT } } },
136
+ },
137
+ }));
138
+ const results = credential.getClientExtensionResults();
139
+ assert.extensionResults = summarizeExtensions(results);
140
+ assert.prfOutputBytes = prfOutputLength(results);
141
+ }
142
+ catch (error) {
143
+ assert.error = error instanceof Error ? `${error.name}: ${error.message}` : 'Assertion failed';
144
+ }
145
+ }
146
+ const prfWorks = (assert.prfOutputBytes ?? 0) > 0 || (create.prfOutputBytes ?? 0) > 0;
147
+ const providerName = aaguid ? (KNOWN_AAGUIDS[aaguid] ?? null) : null;
148
+ return Object.freeze({
149
+ webauthnAvailable,
150
+ platformAuthenticatorAvailable,
151
+ provider: Object.freeze({ aaguid, name: providerName }),
152
+ prfDeclaredAtCreate,
153
+ create: Object.freeze(create),
154
+ assert: Object.freeze(assert),
155
+ prfWorks,
156
+ summary: describe({ prfWorks, prfDeclaredAtCreate, create, assert, providerName }),
157
+ credentialId,
158
+ });
159
+ }
160
+ /** Turns the raw findings into one sentence naming the likely culprit. */
161
+ function describe(facts) {
162
+ const who = facts.providerName ? `${facts.providerName} ` : 'This provider ';
163
+ if (facts.create.error)
164
+ return `The passkey could not be created: ${facts.create.error}`;
165
+ if (facts.prfWorks)
166
+ return `${who}supports PRF — identity derivation will work with this passkey.`;
167
+ if (facts.assert.error)
168
+ return `The assertion failed before PRF could be evaluated: ${facts.assert.error}`;
169
+ const sawPrfKey = facts.create.extensionResults !== null && 'prf' in facts.create.extensionResults;
170
+ if (!sawPrfKey) {
171
+ return `${who}returned no \`prf\` entry at all, which usually means the extension was dropped before reaching the authenticator — the provider handling the ceremony does not implement PRF.`;
172
+ }
173
+ if (facts.prfDeclaredAtCreate === false) {
174
+ return `${who}explicitly reported PRF as unavailable for this credential (\`prf.enabled: false\`).`;
175
+ }
176
+ return `${who}acknowledged the PRF extension but evaluated no secret, so the credential has no hmac-secret to derive from.`;
177
+ }
178
+ //# sourceMappingURL=passkey-diagnostics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"passkey-diagnostics.js","sourceRoot":"","sources":["../../src/identity/passkey-diagnostics.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * @module recovery-code
3
+ * A PRF-free way to anchor an identity: 128 bits of entropy the user can write
4
+ * down, type on another device, and derive the exact same root key from.
5
+ *
6
+ * Encoded in Crockford base32 — no padding, no ambiguity between 0/O or 1/I/L,
7
+ * and case-insensitive, so it survives being copied by hand.
8
+ */
9
+ /** How many bytes a seed is. Anything else cannot be written as a code. */
10
+ export declare const RECOVERY_SEED_BYTES = 16;
11
+ /**
12
+ * Generates a fresh seed.
13
+ * @returns 128 bits of entropy, ready to derive an identity from
14
+ */
15
+ export declare function generateSeed(): Uint8Array;
16
+ /**
17
+ * Writes a seed out as a code a person can copy.
18
+ *
19
+ * The inverse of {@link recoveryCodeToSeed} — which matters once the seed is
20
+ * kept wrapped rather than written down, because showing the user their code
21
+ * then means encoding a seed that already exists rather than minting one.
22
+ *
23
+ * @param seed The seed bytes
24
+ * @returns A grouped code such as `K7M2-9QPX-...`
25
+ */
26
+ export declare function seedToRecoveryCode(seed: Uint8Array): string;
27
+ /**
28
+ * Generates a fresh recovery code.
29
+ * @returns A grouped code such as `K7M2-9QPX-...`
30
+ */
31
+ export declare function generateRecoveryCode(): string;
32
+ /**
33
+ * Strips formatting and resolves look-alike characters.
34
+ * @param code A code as typed by a user
35
+ * @returns The canonical, ungrouped form
36
+ */
37
+ export declare function normalizeRecoveryCode(code: string): string;
38
+ /**
39
+ * Checks whether a code could decode to a seed.
40
+ * @param code A code as typed by a user
41
+ * @returns Whether it is well formed
42
+ */
43
+ export declare function isValidRecoveryCode(code: string): boolean;
44
+ /**
45
+ * Decodes a recovery code into the seed bytes it stands for.
46
+ * @param code A code as typed by a user
47
+ * @returns The seed, ready for key derivation
48
+ */
49
+ export declare function recoveryCodeToSeed(code: string): Uint8Array;
50
+ //# sourceMappingURL=recovery-code.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recovery-code.d.ts","sourceRoot":"","sources":["../../src/identity/recovery-code.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAUH,2EAA2E;AAC3E,eAAO,MAAM,mBAAmB,KAAa,CAAC;AAE9C;;;GAGG;AACH,wBAAgB,YAAY,IAAI,UAAU,CAEzC;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAK3D;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAO1D;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAIzD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAqB3D"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * @module recovery-code
3
+ * A PRF-free way to anchor an identity: 128 bits of entropy the user can write
4
+ * down, type on another device, and derive the exact same root key from.
5
+ *
6
+ * Encoded in Crockford base32 — no padding, no ambiguity between 0/O or 1/I/L,
7
+ * and case-insensitive, so it survives being copied by hand.
8
+ */
9
+ const ALPHABET = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
10
+ /** Crockford's substitutions for characters people confuse when transcribing. */
11
+ const SUBSTITUTIONS = { O: '0', I: '1', L: '1', U: 'V' };
12
+ /** 128 bits: 16 bytes, 26 base32 characters, shown in groups of four. */
13
+ const SEED_BYTES = 16;
14
+ /** How many bytes a seed is. Anything else cannot be written as a code. */
15
+ export const RECOVERY_SEED_BYTES = SEED_BYTES;
16
+ /**
17
+ * Generates a fresh seed.
18
+ * @returns 128 bits of entropy, ready to derive an identity from
19
+ */
20
+ export function generateSeed() {
21
+ return globalThis.crypto.getRandomValues(new Uint8Array(SEED_BYTES));
22
+ }
23
+ /**
24
+ * Writes a seed out as a code a person can copy.
25
+ *
26
+ * The inverse of {@link recoveryCodeToSeed} — which matters once the seed is
27
+ * kept wrapped rather than written down, because showing the user their code
28
+ * then means encoding a seed that already exists rather than minting one.
29
+ *
30
+ * @param seed The seed bytes
31
+ * @returns A grouped code such as `K7M2-9QPX-...`
32
+ */
33
+ export function seedToRecoveryCode(seed) {
34
+ if (seed.length !== SEED_BYTES) {
35
+ throw new Error(`A recovery code carries exactly ${SEED_BYTES} bytes, not ${seed.length}.`);
36
+ }
37
+ return formatRecoveryCode(encodeBase32(seed));
38
+ }
39
+ /**
40
+ * Generates a fresh recovery code.
41
+ * @returns A grouped code such as `K7M2-9QPX-...`
42
+ */
43
+ export function generateRecoveryCode() {
44
+ return seedToRecoveryCode(generateSeed());
45
+ }
46
+ /**
47
+ * Strips formatting and resolves look-alike characters.
48
+ * @param code A code as typed by a user
49
+ * @returns The canonical, ungrouped form
50
+ */
51
+ export function normalizeRecoveryCode(code) {
52
+ return code
53
+ .toUpperCase()
54
+ .replace(/[\s-]/g, '')
55
+ .split('')
56
+ .map((char) => SUBSTITUTIONS[char] ?? char)
57
+ .join('');
58
+ }
59
+ /**
60
+ * Checks whether a code could decode to a seed.
61
+ * @param code A code as typed by a user
62
+ * @returns Whether it is well formed
63
+ */
64
+ export function isValidRecoveryCode(code) {
65
+ const normalized = normalizeRecoveryCode(code);
66
+ if (normalized.length !== Math.ceil((SEED_BYTES * 8) / 5))
67
+ return false;
68
+ return normalized.split('').every((char) => ALPHABET.includes(char));
69
+ }
70
+ /**
71
+ * Decodes a recovery code into the seed bytes it stands for.
72
+ * @param code A code as typed by a user
73
+ * @returns The seed, ready for key derivation
74
+ */
75
+ export function recoveryCodeToSeed(code) {
76
+ const normalized = normalizeRecoveryCode(code);
77
+ if (!isValidRecoveryCode(code)) {
78
+ throw new Error('That recovery code is not valid — check for a missing or mistyped character.');
79
+ }
80
+ const bytes = new Uint8Array(SEED_BYTES);
81
+ let buffer = 0;
82
+ let bitsInBuffer = 0;
83
+ let index = 0;
84
+ for (const char of normalized) {
85
+ buffer = (buffer << 5) | ALPHABET.indexOf(char);
86
+ bitsInBuffer += 5;
87
+ if (bitsInBuffer >= 8 && index < SEED_BYTES) {
88
+ bitsInBuffer -= 8;
89
+ bytes[index++] = (buffer >> bitsInBuffer) & 0xff;
90
+ }
91
+ }
92
+ return bytes;
93
+ }
94
+ /** Groups a code into readable blocks of four. */
95
+ function formatRecoveryCode(code) {
96
+ return (code.match(/.{1,4}/g) ?? []).join('-');
97
+ }
98
+ /** Encodes bytes as Crockford base32, most significant bit first. */
99
+ function encodeBase32(bytes) {
100
+ let out = '';
101
+ let buffer = 0;
102
+ let bitsInBuffer = 0;
103
+ for (const byte of bytes) {
104
+ buffer = (buffer << 8) | byte;
105
+ bitsInBuffer += 8;
106
+ while (bitsInBuffer >= 5) {
107
+ bitsInBuffer -= 5;
108
+ out += ALPHABET[(buffer >> bitsInBuffer) & 0x1f];
109
+ }
110
+ }
111
+ if (bitsInBuffer > 0) {
112
+ out += ALPHABET[(buffer << (5 - bitsInBuffer)) & 0x1f];
113
+ }
114
+ return out;
115
+ }
116
+ //# sourceMappingURL=recovery-code.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recovery-code.js","sourceRoot":"","sources":["../../src/identity/recovery-code.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * @module root-signer
3
+ * Who holds the identity key, and how a session gets permission from it.
4
+ *
5
+ * The root key signs exactly one thing: a note saying "this session key may
6
+ * write for me, until this time". Everything else is signed by the session key.
7
+ * That one signature is the only reason an app needs the identity at all — so
8
+ * it is the only thing that has to be abstracted for the key to live somewhere
9
+ * other than the page.
10
+ *
11
+ * Somewhere else means an account home in another window, or anything that
12
+ * will hold a secret and answer questions about it. The page asks for a delegation
13
+ * and gets back a token; the seed never crosses the boundary.
14
+ *
15
+ * Everything downstream — DIDs, expressions, validation, sync — is unchanged by
16
+ * this, because none of it ever sees the root key either.
17
+ */
18
+ import type { CryptoProvider } from '../types.js';
19
+ import type { Capability, Fact, UCANToken } from './ucan.js';
20
+ /** What a session needs from an identity, wherever that identity is kept */
21
+ export interface RootSigner {
22
+ /** The identity being acted for */
23
+ readonly did: string;
24
+ /**
25
+ * Where the key lives. Worth showing: "your key is in your account home" and
26
+ * "your key is in this tab" are different promises to make to someone.
27
+ */
28
+ readonly custody: 'local' | 'remote';
29
+ /**
30
+ * Signs a delegation from the identity to a session key.
31
+ *
32
+ * @param params.audience The session key's DID
33
+ * @param params.capabilities What it may do
34
+ * @param params.expiration Unix seconds after which the note is worthless
35
+ * @param params.facts Facts the note carries — that its key is an agent's, say
36
+ * @returns The signed token
37
+ */
38
+ delegate(params: {
39
+ audience: string;
40
+ capabilities: ReadonlyArray<Capability>;
41
+ expiration: number;
42
+ facts?: ReadonlyArray<Fact>;
43
+ }): Promise<UCANToken>;
44
+ }
45
+ /**
46
+ * A signer for a key this page is holding.
47
+ *
48
+ * The ordinary case: the seed was unlocked here, so the key is in memory and
49
+ * signing is a local operation.
50
+ *
51
+ * @param identity The unlocked identity
52
+ * @param provider Crypto provider for signing
53
+ * @returns A signer over it
54
+ */
55
+ export declare function createLocalRootSigner(identity: {
56
+ did: string;
57
+ privateKey: CryptoKey;
58
+ }, provider: CryptoProvider): RootSigner;
59
+ //# sourceMappingURL=root-signer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"root-signer.d.ts","sourceRoot":"","sources":["../../src/identity/root-signer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAG7D,4EAA4E;AAC5E,MAAM,WAAW,UAAU;IACzB,mCAAmC;IACnC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,CAAC;IACrC;;;;;;;;OAQG;IACH,QAAQ,CAAC,MAAM,EAAE;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,YAAY,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;QACxC,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,CAAC,EAAE,aAAa,CAAC,IAAI,CAAC,CAAC;KAC7B,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;CACxB;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,SAAS,CAAA;CAAE,EAChD,QAAQ,EAAE,cAAc,GACvB,UAAU,CAuBZ"}