@meshline/sdk 0.0.0-stage → 0.1.0-alpha.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 (338) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +43 -2
  3. package/dist/channels/repository.d.ts +73 -0
  4. package/dist/channels/repository.d.ts.map +1 -0
  5. package/dist/channels/repository.js +367 -0
  6. package/dist/channels/repository.js.map +1 -0
  7. package/dist/client/account-operations.d.ts +41 -0
  8. package/dist/client/account-operations.d.ts.map +1 -0
  9. package/dist/client/account-operations.js +304 -0
  10. package/dist/client/account-operations.js.map +1 -0
  11. package/dist/client/conversations.d.ts +36 -0
  12. package/dist/client/conversations.d.ts.map +1 -0
  13. package/dist/client/conversations.js +144 -0
  14. package/dist/client/conversations.js.map +1 -0
  15. package/dist/client.d.ts +53 -0
  16. package/dist/client.d.ts.map +1 -0
  17. package/dist/client.js +162 -0
  18. package/dist/client.js.map +1 -0
  19. package/dist/components/account.d.ts +38 -0
  20. package/dist/components/account.d.ts.map +1 -0
  21. package/dist/components/account.js +243 -0
  22. package/dist/components/account.js.map +1 -0
  23. package/dist/components/channel.d.ts +78 -0
  24. package/dist/components/channel.d.ts.map +1 -0
  25. package/dist/components/channel.js +475 -0
  26. package/dist/components/channel.js.map +1 -0
  27. package/dist/components/component.d.ts +49 -0
  28. package/dist/components/component.d.ts.map +1 -0
  29. package/dist/components/component.js +194 -0
  30. package/dist/components/component.js.map +1 -0
  31. package/dist/components/device.d.ts +60 -0
  32. package/dist/components/device.d.ts.map +1 -0
  33. package/dist/components/device.js +648 -0
  34. package/dist/components/device.js.map +1 -0
  35. package/dist/components/group.d.ts +141 -0
  36. package/dist/components/group.d.ts.map +1 -0
  37. package/dist/components/group.js +933 -0
  38. package/dist/components/group.js.map +1 -0
  39. package/dist/components/message.d.ts +63 -0
  40. package/dist/components/message.d.ts.map +1 -0
  41. package/dist/components/message.js +439 -0
  42. package/dist/components/message.js.map +1 -0
  43. package/dist/components/profile.d.ts +37 -0
  44. package/dist/components/profile.d.ts.map +1 -0
  45. package/dist/components/profile.js +232 -0
  46. package/dist/components/profile.js.map +1 -0
  47. package/dist/crypto/groups.d.ts +56 -0
  48. package/dist/crypto/groups.d.ts.map +1 -0
  49. package/dist/crypto/groups.js +163 -0
  50. package/dist/crypto/groups.js.map +1 -0
  51. package/dist/crypto/messages.d.ts +52 -0
  52. package/dist/crypto/messages.d.ts.map +1 -0
  53. package/dist/crypto/messages.js +180 -0
  54. package/dist/crypto/messages.js.map +1 -0
  55. package/dist/crypto/primitives.d.ts +30 -0
  56. package/dist/crypto/primitives.d.ts.map +1 -0
  57. package/dist/crypto/primitives.js +102 -0
  58. package/dist/crypto/primitives.js.map +1 -0
  59. package/dist/errors.d.ts +11 -0
  60. package/dist/errors.d.ts.map +1 -0
  61. package/dist/errors.js +14 -0
  62. package/dist/errors.js.map +1 -0
  63. package/dist/groups/account-sync.d.ts +28 -0
  64. package/dist/groups/account-sync.d.ts.map +1 -0
  65. package/dist/groups/account-sync.js +235 -0
  66. package/dist/groups/account-sync.js.map +1 -0
  67. package/dist/groups/messages.d.ts +39 -0
  68. package/dist/groups/messages.d.ts.map +1 -0
  69. package/dist/groups/messages.js +141 -0
  70. package/dist/groups/messages.js.map +1 -0
  71. package/dist/groups/operations.d.ts +57 -0
  72. package/dist/groups/operations.d.ts.map +1 -0
  73. package/dist/groups/operations.js +225 -0
  74. package/dist/groups/operations.js.map +1 -0
  75. package/dist/groups/repository.d.ts +56 -0
  76. package/dist/groups/repository.d.ts.map +1 -0
  77. package/dist/groups/repository.js +254 -0
  78. package/dist/groups/repository.js.map +1 -0
  79. package/dist/groups/secrets.d.ts +67 -0
  80. package/dist/groups/secrets.d.ts.map +1 -0
  81. package/dist/groups/secrets.js +452 -0
  82. package/dist/groups/secrets.js.map +1 -0
  83. package/dist/groups/state.d.ts +39 -0
  84. package/dist/groups/state.d.ts.map +1 -0
  85. package/dist/groups/state.js +201 -0
  86. package/dist/groups/state.js.map +1 -0
  87. package/dist/identity/identifiers.d.ts +9 -0
  88. package/dist/identity/identifiers.d.ts.map +1 -0
  89. package/dist/identity/identifiers.js +37 -0
  90. package/dist/identity/identifiers.js.map +1 -0
  91. package/dist/identity/neo.d.ts +11 -0
  92. package/dist/identity/neo.d.ts.map +1 -0
  93. package/dist/identity/neo.js +77 -0
  94. package/dist/identity/neo.js.map +1 -0
  95. package/dist/index.d.ts +53 -0
  96. package/dist/index.d.ts.map +1 -0
  97. package/dist/index.js +46 -0
  98. package/dist/index.js.map +1 -0
  99. package/dist/interactions.d.ts +31 -0
  100. package/dist/interactions.d.ts.map +1 -0
  101. package/dist/interactions.js +2 -0
  102. package/dist/interactions.js.map +1 -0
  103. package/dist/messages/account-sender.d.ts +9 -0
  104. package/dist/messages/account-sender.d.ts.map +1 -0
  105. package/dist/messages/account-sender.js +46 -0
  106. package/dist/messages/account-sender.js.map +1 -0
  107. package/dist/messages/contacts.d.ts +103 -0
  108. package/dist/messages/contacts.d.ts.map +1 -0
  109. package/dist/messages/contacts.js +525 -0
  110. package/dist/messages/contacts.js.map +1 -0
  111. package/dist/messages/outbox.d.ts +66 -0
  112. package/dist/messages/outbox.d.ts.map +1 -0
  113. package/dist/messages/outbox.js +167 -0
  114. package/dist/messages/outbox.js.map +1 -0
  115. package/dist/messages/receiver.d.ts +35 -0
  116. package/dist/messages/receiver.d.ts.map +1 -0
  117. package/dist/messages/receiver.js +113 -0
  118. package/dist/messages/receiver.js.map +1 -0
  119. package/dist/messages/repository.d.ts +89 -0
  120. package/dist/messages/repository.d.ts.map +1 -0
  121. package/dist/messages/repository.js +295 -0
  122. package/dist/messages/repository.js.map +1 -0
  123. package/dist/models/authentication.d.ts +37 -0
  124. package/dist/models/authentication.d.ts.map +1 -0
  125. package/dist/models/authentication.js +53 -0
  126. package/dist/models/authentication.js.map +1 -0
  127. package/dist/models/channels.d.ts +141 -0
  128. package/dist/models/channels.d.ts.map +1 -0
  129. package/dist/models/channels.js +258 -0
  130. package/dist/models/channels.js.map +1 -0
  131. package/dist/models/contacts.d.ts +68 -0
  132. package/dist/models/contacts.d.ts.map +1 -0
  133. package/dist/models/contacts.js +186 -0
  134. package/dist/models/contacts.js.map +1 -0
  135. package/dist/models/content.d.ts +37 -0
  136. package/dist/models/content.d.ts.map +1 -0
  137. package/dist/models/content.js +137 -0
  138. package/dist/models/content.js.map +1 -0
  139. package/dist/models/device-state.d.ts +8 -0
  140. package/dist/models/device-state.d.ts.map +1 -0
  141. package/dist/models/device-state.js +22 -0
  142. package/dist/models/device-state.js.map +1 -0
  143. package/dist/models/group-admission.d.ts +111 -0
  144. package/dist/models/group-admission.d.ts.map +1 -0
  145. package/dist/models/group-admission.js +153 -0
  146. package/dist/models/group-admission.js.map +1 -0
  147. package/dist/models/group-keys.d.ts +30 -0
  148. package/dist/models/group-keys.d.ts.map +1 -0
  149. package/dist/models/group-keys.js +52 -0
  150. package/dist/models/group-keys.js.map +1 -0
  151. package/dist/models/group-management.d.ts +190 -0
  152. package/dist/models/group-management.d.ts.map +1 -0
  153. package/dist/models/group-management.js +263 -0
  154. package/dist/models/group-management.js.map +1 -0
  155. package/dist/models/groups.d.ts +81 -0
  156. package/dist/models/groups.d.ts.map +1 -0
  157. package/dist/models/groups.js +127 -0
  158. package/dist/models/groups.js.map +1 -0
  159. package/dist/models/identity.d.ts +47 -0
  160. package/dist/models/identity.d.ts.map +1 -0
  161. package/dist/models/identity.js +136 -0
  162. package/dist/models/identity.js.map +1 -0
  163. package/dist/models/messages.d.ts +104 -0
  164. package/dist/models/messages.d.ts.map +1 -0
  165. package/dist/models/messages.js +168 -0
  166. package/dist/models/messages.js.map +1 -0
  167. package/dist/models/profile.d.ts +24 -0
  168. package/dist/models/profile.d.ts.map +1 -0
  169. package/dist/models/profile.js +47 -0
  170. package/dist/models/profile.js.map +1 -0
  171. package/dist/models/relay.d.ts +39 -0
  172. package/dist/models/relay.d.ts.map +1 -0
  173. package/dist/models/relay.js +160 -0
  174. package/dist/models/relay.js.map +1 -0
  175. package/dist/protocol/codec.d.ts +36 -0
  176. package/dist/protocol/codec.d.ts.map +1 -0
  177. package/dist/protocol/codec.js +144 -0
  178. package/dist/protocol/codec.js.map +1 -0
  179. package/dist/protocol/context.d.ts +14 -0
  180. package/dist/protocol/context.d.ts.map +1 -0
  181. package/dist/protocol/context.js +43 -0
  182. package/dist/protocol/context.js.map +1 -0
  183. package/dist/protocol/encoding.d.ts +15 -0
  184. package/dist/protocol/encoding.d.ts.map +1 -0
  185. package/dist/protocol/encoding.js +133 -0
  186. package/dist/protocol/encoding.js.map +1 -0
  187. package/dist/protocol/json.d.ts +16 -0
  188. package/dist/protocol/json.d.ts.map +1 -0
  189. package/dist/protocol/json.js +172 -0
  190. package/dist/protocol/json.js.map +1 -0
  191. package/dist/protocol/validation.d.ts +4 -0
  192. package/dist/protocol/validation.d.ts.map +1 -0
  193. package/dist/protocol/validation.js +18 -0
  194. package/dist/protocol/validation.js.map +1 -0
  195. package/dist/runtime/abort.d.ts +6 -0
  196. package/dist/runtime/abort.d.ts.map +1 -0
  197. package/dist/runtime/abort.js +32 -0
  198. package/dist/runtime/abort.js.map +1 -0
  199. package/dist/runtime/async-gate.d.ts +6 -0
  200. package/dist/runtime/async-gate.d.ts.map +1 -0
  201. package/dist/runtime/async-gate.js +15 -0
  202. package/dist/runtime/async-gate.js.map +1 -0
  203. package/dist/runtime/async-pulse.d.ts +7 -0
  204. package/dist/runtime/async-pulse.d.ts.map +1 -0
  205. package/dist/runtime/async-pulse.js +23 -0
  206. package/dist/runtime/async-pulse.js.map +1 -0
  207. package/dist/runtime/clock.d.ts +16 -0
  208. package/dist/runtime/clock.d.ts.map +1 -0
  209. package/dist/runtime/clock.js +62 -0
  210. package/dist/runtime/clock.js.map +1 -0
  211. package/dist/runtime/events.d.ts +11 -0
  212. package/dist/runtime/events.d.ts.map +1 -0
  213. package/dist/runtime/events.js +45 -0
  214. package/dist/runtime/events.js.map +1 -0
  215. package/dist/runtime/url.d.ts +3 -0
  216. package/dist/runtime/url.d.ts.map +1 -0
  217. package/dist/runtime/url.js +23 -0
  218. package/dist/runtime/url.js.map +1 -0
  219. package/dist/storage/signed-request.d.ts +14 -0
  220. package/dist/storage/signed-request.d.ts.map +1 -0
  221. package/dist/storage/signed-request.js +26 -0
  222. package/dist/storage/signed-request.js.map +1 -0
  223. package/dist/storage/store.d.ts +58 -0
  224. package/dist/storage/store.d.ts.map +1 -0
  225. package/dist/storage/store.js +52 -0
  226. package/dist/storage/store.js.map +1 -0
  227. package/dist/storage/transaction.d.ts +7 -0
  228. package/dist/storage/transaction.d.ts.map +1 -0
  229. package/dist/storage/transaction.js +22 -0
  230. package/dist/storage/transaction.js.map +1 -0
  231. package/dist/transport/client.d.ts +61 -0
  232. package/dist/transport/client.d.ts.map +1 -0
  233. package/dist/transport/client.js +392 -0
  234. package/dist/transport/client.js.map +1 -0
  235. package/dist/transport/discovery.d.ts +19 -0
  236. package/dist/transport/discovery.d.ts.map +1 -0
  237. package/dist/transport/discovery.js +75 -0
  238. package/dist/transport/discovery.js.map +1 -0
  239. package/dist/transport/endpoint.d.ts +6 -0
  240. package/dist/transport/endpoint.d.ts.map +1 -0
  241. package/dist/transport/endpoint.js +35 -0
  242. package/dist/transport/endpoint.js.map +1 -0
  243. package/dist/transport/http.d.ts +52 -0
  244. package/dist/transport/http.d.ts.map +1 -0
  245. package/dist/transport/http.js +128 -0
  246. package/dist/transport/http.js.map +1 -0
  247. package/dist/transport/pool.d.ts +31 -0
  248. package/dist/transport/pool.d.ts.map +1 -0
  249. package/dist/transport/pool.js +137 -0
  250. package/dist/transport/pool.js.map +1 -0
  251. package/dist/transport/relay-error.d.ts +23 -0
  252. package/dist/transport/relay-error.d.ts.map +1 -0
  253. package/dist/transport/relay-error.js +47 -0
  254. package/dist/transport/relay-error.js.map +1 -0
  255. package/dist/transport/rpc.d.ts +31 -0
  256. package/dist/transport/rpc.d.ts.map +1 -0
  257. package/dist/transport/rpc.js +56 -0
  258. package/dist/transport/rpc.js.map +1 -0
  259. package/dist/transport/session.d.ts +49 -0
  260. package/dist/transport/session.d.ts.map +1 -0
  261. package/dist/transport/session.js +169 -0
  262. package/dist/transport/session.js.map +1 -0
  263. package/dist/transport/socket.d.ts +55 -0
  264. package/dist/transport/socket.d.ts.map +1 -0
  265. package/dist/transport/socket.js +266 -0
  266. package/dist/transport/socket.js.map +1 -0
  267. package/dist/transport/subscription.d.ts +36 -0
  268. package/dist/transport/subscription.d.ts.map +1 -0
  269. package/dist/transport/subscription.js +169 -0
  270. package/dist/transport/subscription.js.map +1 -0
  271. package/package.json +35 -4
  272. package/src/channels/repository.ts +244 -0
  273. package/src/client/account-operations.ts +183 -0
  274. package/src/client/conversations.ts +95 -0
  275. package/src/client.ts +108 -0
  276. package/src/components/account.ts +206 -0
  277. package/src/components/channel.ts +253 -0
  278. package/src/components/component.ts +151 -0
  279. package/src/components/device.ts +455 -0
  280. package/src/components/group.ts +546 -0
  281. package/src/components/message.ts +253 -0
  282. package/src/components/profile.ts +179 -0
  283. package/src/crypto/groups.ts +107 -0
  284. package/src/crypto/messages.ts +129 -0
  285. package/src/crypto/primitives.ts +103 -0
  286. package/src/errors.ts +13 -0
  287. package/src/groups/account-sync.ts +144 -0
  288. package/src/groups/messages.ts +89 -0
  289. package/src/groups/operations.ts +145 -0
  290. package/src/groups/repository.ts +161 -0
  291. package/src/groups/secrets.ts +256 -0
  292. package/src/groups/state.ts +138 -0
  293. package/src/identity/identifiers.ts +41 -0
  294. package/src/identity/neo.ts +72 -0
  295. package/src/index.ts +52 -0
  296. package/src/interactions.ts +35 -0
  297. package/src/messages/account-sender.ts +33 -0
  298. package/src/messages/contacts.ts +379 -0
  299. package/src/messages/outbox.ts +152 -0
  300. package/src/messages/receiver.ts +86 -0
  301. package/src/messages/repository.ts +230 -0
  302. package/src/models/authentication.ts +63 -0
  303. package/src/models/channels.ts +155 -0
  304. package/src/models/contacts.ts +141 -0
  305. package/src/models/content.ts +105 -0
  306. package/src/models/device-state.ts +18 -0
  307. package/src/models/group-admission.ts +110 -0
  308. package/src/models/group-keys.ts +34 -0
  309. package/src/models/group-management.ts +182 -0
  310. package/src/models/groups.ts +100 -0
  311. package/src/models/identity.ts +164 -0
  312. package/src/models/messages.ts +139 -0
  313. package/src/models/profile.ts +46 -0
  314. package/src/models/relay.ts +151 -0
  315. package/src/protocol/codec.ts +144 -0
  316. package/src/protocol/context.ts +39 -0
  317. package/src/protocol/encoding.ts +106 -0
  318. package/src/protocol/json.ts +140 -0
  319. package/src/protocol/validation.ts +13 -0
  320. package/src/runtime/abort.ts +27 -0
  321. package/src/runtime/async-gate.ts +16 -0
  322. package/src/runtime/async-pulse.ts +20 -0
  323. package/src/runtime/clock.ts +63 -0
  324. package/src/runtime/events.ts +31 -0
  325. package/src/runtime/url.ts +17 -0
  326. package/src/storage/signed-request.ts +26 -0
  327. package/src/storage/store.ts +90 -0
  328. package/src/storage/transaction.ts +17 -0
  329. package/src/transport/client.ts +328 -0
  330. package/src/transport/discovery.ts +64 -0
  331. package/src/transport/endpoint.ts +32 -0
  332. package/src/transport/http.ts +129 -0
  333. package/src/transport/pool.ts +115 -0
  334. package/src/transport/relay-error.ts +46 -0
  335. package/src/transport/rpc.ts +56 -0
  336. package/src/transport/session.ts +154 -0
  337. package/src/transport/socket.ts +248 -0
  338. package/src/transport/subscription.ts +117 -0
@@ -0,0 +1,232 @@
1
+ import { ProtocolError, StateConflictError } from '../errors.js';
2
+ import { validateAccountId } from '../identity/neo.js';
3
+ import { contentReferenceCodec } from '../models/content.js';
4
+ import { deviceCertificateCodec } from '../models/identity.js';
5
+ import { accountProfileCodec, profileInput, profileResolveResultCodec, validateProfile, validateProfileResult } from '../models/profile.js';
6
+ import { canonicalJson } from '../protocol/json.js';
7
+ import { AsyncGate } from '../runtime/async-gate.js';
8
+ import { EventHub } from '../runtime/events.js';
9
+ import { finishSignedRequest, putSignedRequest, readSignedRequest, requestKey } from '../storage/signed-request.js';
10
+ import { updateStore } from '../storage/transaction.js';
11
+ import { RelayError } from '../transport/relay-error.js';
12
+ import { ClientComponent } from './component.js';
13
+ const method = 'profile.publish';
14
+ const profileKey = (account) => ({ collection: 'profiles', key: account });
15
+ const clone = (value) => accountProfileCodec.decode(accountProfileCodec.encode(value));
16
+ const fingerprint = (value) => canonicalJson(value ?? null);
17
+ function copyUpdate(value) {
18
+ for (const key of Object.keys(value))
19
+ if (!['nickname', 'bio', 'avatar', 'publicDiscovery'].includes(key))
20
+ throw new TypeError(`Unknown profile update field ${key}.`);
21
+ if (value.publicDiscovery !== undefined && typeof value.publicDiscovery !== 'boolean')
22
+ throw new TypeError('publicDiscovery must be boolean and cannot be deleted.');
23
+ for (const field of [value.nickname, value.bio])
24
+ if (field !== undefined && field !== null && typeof field !== 'string')
25
+ throw new TypeError('Profile text must be a string or null.');
26
+ return { ...value, ...(value.avatar == null ? {} : { avatar: contentReferenceCodec.decode(contentReferenceCodec.encode(value.avatar)) }) };
27
+ }
28
+ function apply(update, basis) {
29
+ const document = accountProfileCodec.encode(basis);
30
+ for (const field of ['nickname', 'bio', 'avatar']) {
31
+ const value = update[field];
32
+ if (value === null)
33
+ delete document[field];
34
+ else if (value !== undefined)
35
+ document[field] = typeof value === 'string' ? value : contentReferenceCodec.encode(value);
36
+ }
37
+ if (update.publicDiscovery !== undefined)
38
+ document.public_discovery = update.publicDiscovery;
39
+ return accountProfileCodec.decode(document);
40
+ }
41
+ export class ProfileManager extends ClientComponent {
42
+ #store;
43
+ #pool;
44
+ #account;
45
+ #signer;
46
+ #gate = new AsyncGate();
47
+ #events = new EventHub();
48
+ #profile;
49
+ constructor(options) {
50
+ super(options);
51
+ for (const dependency of [options.relayClients, options.accountManager])
52
+ if (dependency.accountId !== this.accountId || dependency.context.toString() !== this.context.toString())
53
+ throw new ProtocolError('invalid_context', 'Profile dependencies belong to another account or network.');
54
+ this.#store = options.store;
55
+ this.#pool = options.relayClients;
56
+ this.#account = options.accountManager;
57
+ this.#signer = options.deviceSigner;
58
+ }
59
+ get profile() { return this.#profile && clone(this.#profile); }
60
+ on(event, listener) { return this.#events.on(event, listener); }
61
+ async onInitialize(signal) {
62
+ this.#account.ensureInitialized();
63
+ await this.#store.initialize({ context: this.context.toString(), accountId: this.accountId }, signal);
64
+ const saved = (await this.#store.read([profileKey(this.accountId)], signal)).sets[0][0]?.value;
65
+ if (saved) {
66
+ const result = profileResolveResultCodec.decode(saved);
67
+ validateProfileResult(result, this.context, this.accountId);
68
+ this.#profile = result.profile;
69
+ }
70
+ }
71
+ #accept(profile) {
72
+ const changed = (profile && accountProfileCodec.stringify(profile)) !== (this.#profile && accountProfileCodec.stringify(this.#profile));
73
+ this.#profile = profile && clone(profile);
74
+ return changed;
75
+ }
76
+ #changed() { this.#events.notify('profileChanged', this.profile, error => this.notifyBackgroundError({ operation: 'observer', resource: 'profileChanged', error })); }
77
+ async getProfile(accountId = this.accountId, signal) {
78
+ validateAccountId(accountId);
79
+ let changed = false;
80
+ const profile = await this.runOperation(scope => this.#gate.run(async () => {
81
+ const result = await this.#resolve(accountId, await this.#home(scope), scope);
82
+ if (result)
83
+ await this.#save(result, scope);
84
+ if (accountId === this.accountId)
85
+ changed = this.#accept(result?.profile);
86
+ return result?.profile;
87
+ }, scope), signal);
88
+ if (changed)
89
+ this.#changed();
90
+ return profile && clone(profile);
91
+ }
92
+ async updateProfile(update, signal) {
93
+ const copied = copyUpdate(update);
94
+ let changed = false;
95
+ const result = await this.runOperation(scope => this.#gate.run(async () => {
96
+ const result = await this.#publish(copied, undefined, scope);
97
+ changed = this.#accept(result);
98
+ return result;
99
+ }, scope), signal);
100
+ if (changed)
101
+ this.#changed();
102
+ return clone(result);
103
+ }
104
+ /** Republish the newest known local/pending/supplied snapshot, including during home-relay migration. */
105
+ async publishProfile(profile, signal) {
106
+ const supplied = profile && clone(profile);
107
+ if (supplied) {
108
+ validateProfile(supplied);
109
+ if (supplied.account !== this.accountId)
110
+ throw new ProtocolError('invalid_identity', 'Profile belongs to another account.');
111
+ }
112
+ let changed = false;
113
+ const result = await this.runOperation(scope => this.#gate.run(async () => {
114
+ const snapshot = await this.#store.read([profileKey(this.accountId), requestKey(method)], scope);
115
+ const local = snapshot.sets[0][0]?.value;
116
+ const signed = readSignedRequest(snapshot.sets[1][0]?.value);
117
+ let latest = local && profileResolveResultCodec.decode(local).profile;
118
+ if (signed?.pending && (!latest || signed.revision >= latest.updatedAt))
119
+ latest = accountProfileCodec.decode(signed.document);
120
+ if (supplied && (!latest || supplied.updatedAt > latest.updatedAt))
121
+ latest = supplied;
122
+ if (!latest)
123
+ return undefined;
124
+ const published = await this.#publish({}, latest, scope);
125
+ changed = this.#accept(published);
126
+ return published;
127
+ }, scope), signal);
128
+ if (changed)
129
+ this.#changed();
130
+ return result && clone(result);
131
+ }
132
+ async #home(signal) {
133
+ const route = await this.#account.getRoute(undefined, signal);
134
+ if (!route)
135
+ throw new ProtocolError('route_required', 'Establish or recover the account route before publishing profiles.');
136
+ return route.relayId;
137
+ }
138
+ async #resolve(account, relayId, signal) {
139
+ const client = await this.#pool.get(relayId, { mode: 'device', signer: this.#signer }, signal);
140
+ let response;
141
+ try {
142
+ response = await client.requestHttp('GET', 'profile.resolve', { account }, { signal });
143
+ }
144
+ catch (error) {
145
+ if (error instanceof RelayError && error.code === 'not_found')
146
+ return undefined;
147
+ throw error;
148
+ }
149
+ if (response === undefined)
150
+ throw new ProtocolError('invalid_response', 'Profile resolution returned no document.');
151
+ const result = profileResolveResultCodec.decode(response);
152
+ validateProfileResult(result, this.context, account);
153
+ return result;
154
+ }
155
+ async #publish(update, restored, signal) {
156
+ const certificate = deviceCertificateCodec.decode(deviceCertificateCodec.encode(this.#signer.certificate));
157
+ if (certificate.account !== this.accountId)
158
+ throw new ProtocolError('invalid_identity', 'Device signer belongs to another account.');
159
+ const relayId = await this.#home(signal);
160
+ const queries = [profileKey(this.accountId), requestKey(method)];
161
+ const snapshot = await this.#store.read(queries, signal);
162
+ const local = snapshot.sets[0][0]?.value;
163
+ const saved = snapshot.sets[1][0]?.value;
164
+ let signed = readSignedRequest(saved);
165
+ let request;
166
+ if (signed?.pending && (!restored || signed.relayId === relayId)) {
167
+ request = accountProfileCodec.decode(signed.document);
168
+ if (signed.relayId !== relayId || accountProfileCodec.stringify(apply(update, request)) !== accountProfileCodec.stringify(request))
169
+ throw new StateConflictError('A profile publication has an unknown result. Retry the original update or resolve it first.');
170
+ }
171
+ else {
172
+ const current = await this.#resolve(this.accountId, relayId, signal);
173
+ const cached = local && profileResolveResultCodec.decode(local).profile;
174
+ let basis = current?.profile;
175
+ if (basis && cached && basis.updatedAt < cached.updatedAt)
176
+ throw new ProtocolError('stale_profile', 'Relay returned an older profile.');
177
+ for (const candidate of [cached, restored, signed?.pending ? accountProfileCodec.decode(signed.document) : undefined])
178
+ if (candidate && (!basis || candidate.updatedAt > basis.updatedAt))
179
+ basis = candidate;
180
+ basis ??= { account: this.accountId, publicDiscovery: false, updatedAt: 0, deviceSignature: new Uint8Array(64) };
181
+ request = { ...apply(update, basis), updatedAt: Math.max(this.clock.nowSeconds(), basis.updatedAt), deviceSignature: new Uint8Array(64) };
182
+ validateProfile(request);
183
+ request = { ...request, deviceSignature: (await this.#signer.sign(profileInput(request, this.context), signal)).slice() };
184
+ validateProfileResult({ profile: request, signerCertificate: certificate }, this.context, this.accountId);
185
+ const prepared = { relayId, revision: request.updatedAt, document: accountProfileCodec.encode(request), pending: true };
186
+ await updateStore(this.#store, queries, state => {
187
+ if (fingerprint(state.sets[0][0]?.value) !== fingerprint(local) || fingerprint(state.sets[1][0]?.value) !== fingerprint(saved))
188
+ throw new StateConflictError('Profile changed while signing. Resolve current state before retrying.');
189
+ return { mutations: [putSignedRequest(method, prepared)], result: undefined };
190
+ }, signal);
191
+ signed = prepared;
192
+ }
193
+ // A renewed certificate with the same key is valid; a replaced signing identity cannot replay the old request.
194
+ validateProfileResult({ profile: request, signerCertificate: certificate }, this.context, this.accountId);
195
+ const currentCertificate = this.#signer.certificate;
196
+ if (currentCertificate.account !== certificate.account || canonicalJson(deviceCertificateCodec.encode(currentCertificate)) !== canonicalJson(deviceCertificateCodec.encode(certificate)))
197
+ throw new StateConflictError('Device signer changed during profile publication.');
198
+ const client = await this.#pool.get(relayId, { mode: 'device', signer: this.#signer }, signal);
199
+ try {
200
+ await client.requestHttp('PUT', method, signed.document, { signal });
201
+ }
202
+ catch (error) {
203
+ if (error instanceof RelayError && error.isDefinitiveRejection) {
204
+ try {
205
+ await finishSignedRequest(this.#store, method, signed);
206
+ }
207
+ catch (storageError) {
208
+ throw new AggregateError([error, storageError], 'Profile rejection could not be persisted.');
209
+ }
210
+ }
211
+ throw error;
212
+ }
213
+ await this.#save({ profile: request, signerCertificate: certificate }, signal);
214
+ return request;
215
+ }
216
+ async #save(result, signal) {
217
+ const profile = result.profile;
218
+ await updateStore(this.#store, [profileKey(profile.account), requestKey(method)], snapshot => {
219
+ const previous = snapshot.sets[0][0]?.value;
220
+ if (previous && profile.updatedAt < profileResolveResultCodec.decode(previous).profile.updatedAt)
221
+ throw new ProtocolError('stale_profile', 'Returned profile is older than the known profile.');
222
+ const mutations = [{ ...profileKey(profile.account), kind: 'put', value: profileResolveResultCodec.encode(result) }];
223
+ const signed = readSignedRequest(snapshot.sets[1][0]?.value);
224
+ if (profile.account === this.accountId && signed?.pending && (profile.updatedAt > signed.revision
225
+ || profile.updatedAt === signed.revision && accountProfileCodec.stringify(profile) === canonicalJson(signed.document)))
226
+ mutations.push(putSignedRequest(method, { ...signed, pending: false }));
227
+ return { mutations, result: undefined };
228
+ }, signal);
229
+ }
230
+ async onDispose() { this.#events.clear(); }
231
+ }
232
+ //# sourceMappingURL=profile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile.js","sourceRoot":"","sources":["../../src/components/profile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ import type { DeviceSigner } from '../interactions.js';
2
+ import { type DeviceCertificate } from '../models/identity.js';
3
+ import { type GroupMessageEnvelope, type GroupSecretBox } from '../models/groups.js';
4
+ import { type NetworkContext } from '../protocol/context.js';
5
+ import { type JsonObject } from '../protocol/json.js';
6
+ import { type RandomSource } from './primitives.js';
7
+ /** Local protection/key-access failures remain retryable and never reject remote group messages. */
8
+ export declare class GroupKeyAccessError extends Error {
9
+ readonly name = "GroupKeyAccessError";
10
+ }
11
+ /** Hash the complete signed management object, including its device signature; timeline metadata is external. */
12
+ export declare function groupManagementHash(value: JsonObject, context: NetworkContext): string;
13
+ export declare function groupClientSecretCommitment(groupId: string, secret: Uint8Array, context: NetworkContext): string;
14
+ export interface GroupClientSecretBoxHeader {
15
+ readonly groupId: string;
16
+ readonly account: string;
17
+ readonly memberEncryptionPublicKey: Uint8Array;
18
+ readonly clientSecretCommitment: string;
19
+ }
20
+ export declare function groupClientSecretBoxAad(value: GroupClientSecretBoxHeader, context: NetworkContext): Uint8Array;
21
+ export interface GroupRelaySecretBoxHeader {
22
+ readonly groupId: string;
23
+ readonly account: string;
24
+ readonly deviceId: string;
25
+ readonly epoch: number;
26
+ }
27
+ export declare function groupRelaySecretBoxAad(value: GroupRelaySecretBoxHeader, context: NetworkContext): Uint8Array;
28
+ /** Low-level secret wrapping with a protocol AAD projection; caller-owned secret and public key are never erased. */
29
+ export declare function sealGroupSecret(secret: Uint8Array, publicKey: Uint8Array, aad: Uint8Array, random?: RandomSource): GroupSecretBox;
30
+ /** Caller owns both the supplied shared secret and the returned plaintext; erase them after use. */
31
+ export declare function openGroupSecret(box: GroupSecretBox, shared: Uint8Array, aad: Uint8Array): Uint8Array;
32
+ export declare function sealGroupClientSecret(header: GroupClientSecretBoxHeader, secret: Uint8Array, context: NetworkContext, random?: RandomSource): GroupSecretBox;
33
+ /** Validates the client half before combining both independently supplied 32-byte secrets. */
34
+ export declare function deriveGroupApplicationSecret(groupId: string, epoch: number, clientSecretCommitment: string, clientSecret: Uint8Array, relaySecret: Uint8Array, context: NetworkContext): Uint8Array;
35
+ export type GroupMessageHeader = Pick<GroupMessageEnvelope, 'groupId' | 'epoch' | 'messageId' | 'createdAt'>;
36
+ export declare function groupMessageAad(value: GroupMessageHeader, account: string, deviceId: string, context: NetworkContext): Uint8Array;
37
+ export declare function deriveGroupMessageKey(applicationSecret: Uint8Array, aad: Uint8Array): Uint8Array;
38
+ export interface EncryptGroupMessageOptions extends GroupMessageHeader {
39
+ readonly context: NetworkContext;
40
+ readonly signer: DeviceSigner;
41
+ readonly applicationSecret: Uint8Array;
42
+ readonly payload: JsonObject;
43
+ readonly random?: RandomSource;
44
+ readonly signal?: AbortSignal;
45
+ }
46
+ export declare function encryptGroupMessage(options: EncryptGroupMessageOptions): Promise<GroupMessageEnvelope>;
47
+ export interface DecryptGroupMessageOptions {
48
+ readonly context: NetworkContext;
49
+ readonly envelope: GroupMessageEnvelope;
50
+ readonly sender: DeviceCertificate;
51
+ readonly signerDeviceId: string;
52
+ readonly applicationSecret: Uint8Array;
53
+ }
54
+ /** Authenticates the signature, sender account and device before returning typed content. Membership validation remains mandatory in the receiver. */
55
+ export declare function decryptGroupMessage(options: DecryptGroupMessageOptions): JsonObject;
56
+ //# sourceMappingURL=groups.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"groups.d.ts","sourceRoot":"","sources":["../../src/crypto/groups.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,163 @@
1
+ import { ProtocolError } from '../errors.js';
2
+ import { validateIdentifier } from '../identity/identifiers.js';
3
+ import { validateAccountId } from '../identity/neo.js';
4
+ import { contentHashBytes } from '../models/content.js';
5
+ import { certificateId, deviceCertificateCodec, validateCertificate } from '../models/identity.js';
6
+ import { groupMessageEnvelopeCodec, groupMessageEnvelopeInput, groupPayloadCodec, validateGroupPayload, validateGroupSecretBox, verifyGroupMessageEnvelope } from '../models/groups.js';
7
+ import { signingInput } from '../protocol/context.js';
8
+ import { concatBytes, encodeBase64Url, encodeUtf8 } from '../protocol/encoding.js';
9
+ import { canonicalBytes, parseJson, requireSafeInteger } from '../protocol/json.js';
10
+ import { throwIfAborted } from '../runtime/clock.js';
11
+ import { agreeKey, decryptAes, deriveKey, encryptAes, encryptionPublicKey, requireLength, sha256, systemRandom } from './primitives.js';
12
+ const boxSalt = sha256(encodeUtf8('Meshline/keybox-salt/v1'));
13
+ const epochSalt = sha256(encodeUtf8('Meshline/group-epoch-salt/v1'));
14
+ const messageSalt = sha256(encodeUtf8('Meshline/group-message-salt/v1'));
15
+ /** Local protection/key-access failures remain retryable and never reject remote group messages. */
16
+ export class GroupKeyAccessError extends Error {
17
+ name = 'GroupKeyAccessError';
18
+ }
19
+ /** Hash the complete signed management object, including its device signature; timeline metadata is external. */
20
+ export function groupManagementHash(value, context) {
21
+ if (typeof value.$type !== 'string')
22
+ throw new ProtocolError('invalid_type', 'Management hashes require a typed protocol object.');
23
+ return `sha256:${encodeBase64Url(sha256(signingInput(value, context)))}`;
24
+ }
25
+ export function groupClientSecretCommitment(groupId, secret, context) {
26
+ validateIdentifier('group', groupId);
27
+ requireLength(secret, 32, 'Client group secret');
28
+ return groupManagementHash({ $type: 'meshline.group.client_secret.commitment', group_id: groupId, secret: encodeBase64Url(secret) }, context);
29
+ }
30
+ export function groupClientSecretBoxAad(value, context) {
31
+ validateIdentifier('group', value.groupId);
32
+ validateAccountId(value.account);
33
+ requireLength(value.memberEncryptionPublicKey, 32, 'Member encryption public key');
34
+ contentHashBytes(value.clientSecretCommitment);
35
+ return signingInput({ $type: 'meshline.group.client_secret_box.aad', group_id: value.groupId, account: value.account,
36
+ member_encryption_public_key: encodeBase64Url(value.memberEncryptionPublicKey), client_secret_commitment: value.clientSecretCommitment }, context);
37
+ }
38
+ export function groupRelaySecretBoxAad(value, context) {
39
+ validateIdentifier('group', value.groupId);
40
+ validateAccountId(value.account);
41
+ validateIdentifier('device', value.deviceId);
42
+ requireSafeInteger(value.epoch, 0);
43
+ return signingInput({ $type: 'meshline.group.relay_secret_box.aad', group_id: value.groupId, account: value.account, device_id: value.deviceId, epoch: value.epoch }, context);
44
+ }
45
+ /** Low-level secret wrapping with a protocol AAD projection; caller-owned secret and public key are never erased. */
46
+ export function sealGroupSecret(secret, publicKey, aad, random = systemRandom) {
47
+ requireLength(secret, 32, 'Group secret');
48
+ requireLength(publicKey, 32, 'Secret recipient public key');
49
+ let ephemeral;
50
+ let shared;
51
+ let key;
52
+ try {
53
+ ephemeral = random.bytes(32);
54
+ requireLength(ephemeral, 32, 'Ephemeral private key');
55
+ const enc = encryptionPublicKey(ephemeral);
56
+ shared = agreeKey(ephemeral, publicKey);
57
+ key = deriveKey(shared, boxSalt, aad);
58
+ const nonce = random.bytes(12);
59
+ requireLength(nonce, 12, 'Secret box nonce');
60
+ return { alg: 'X25519-HKDF-SHA256-AES256GCM', enc, sealedSecret: concatBytes(nonce, encryptAes(key, nonce, secret, aad)) };
61
+ }
62
+ finally {
63
+ ephemeral?.fill(0);
64
+ shared?.fill(0);
65
+ key?.fill(0);
66
+ }
67
+ }
68
+ /** Caller owns both the supplied shared secret and the returned plaintext; erase them after use. */
69
+ export function openGroupSecret(box, shared, aad) {
70
+ validateGroupSecretBox(box);
71
+ requireLength(shared, 32, 'Secret box shared secret');
72
+ if (shared.every(byte => byte === 0))
73
+ throw new ProtocolError('invalid_key', 'An all-zero shared secret is forbidden.');
74
+ const key = deriveKey(shared, boxSalt, aad);
75
+ try {
76
+ return decryptAes(key, box.sealedSecret.subarray(0, 12), box.sealedSecret.subarray(12), aad);
77
+ }
78
+ finally {
79
+ key.fill(0);
80
+ }
81
+ }
82
+ export function sealGroupClientSecret(header, secret, context, random = systemRandom) {
83
+ const aad = groupClientSecretBoxAad(header, context);
84
+ if (groupClientSecretCommitment(header.groupId, secret, context) !== header.clientSecretCommitment)
85
+ throw new ProtocolError('invalid_commitment', 'Client group secret does not match its commitment.');
86
+ return sealGroupSecret(secret, header.memberEncryptionPublicKey, aad, random);
87
+ }
88
+ /** Validates the client half before combining both independently supplied 32-byte secrets. */
89
+ export function deriveGroupApplicationSecret(groupId, epoch, clientSecretCommitment, clientSecret, relaySecret, context) {
90
+ validateIdentifier('group', groupId);
91
+ requireSafeInteger(epoch, 0);
92
+ contentHashBytes(clientSecretCommitment);
93
+ requireLength(clientSecret, 32, 'Client group secret');
94
+ requireLength(relaySecret, 32, 'Relay epoch secret');
95
+ if (groupClientSecretCommitment(groupId, clientSecret, context) !== clientSecretCommitment)
96
+ throw new ProtocolError('invalid_commitment', 'Client group secret does not match its commitment.');
97
+ const material = concatBytes(clientSecret, relaySecret);
98
+ try {
99
+ return deriveKey(material, epochSalt, signingInput({ $type: 'meshline.group.epoch_secret', group_id: groupId, epoch, client_secret_commitment: clientSecretCommitment }, context));
100
+ }
101
+ finally {
102
+ material.fill(0);
103
+ }
104
+ }
105
+ export function groupMessageAad(value, account, deviceId, context) {
106
+ validateIdentifier('group', value.groupId);
107
+ validateIdentifier('message', value.messageId);
108
+ requireSafeInteger(value.epoch, 0);
109
+ requireSafeInteger(value.createdAt, 0);
110
+ validateAccountId(account);
111
+ validateIdentifier('device', deviceId);
112
+ return signingInput({ $type: 'meshline.group.message.aad', group_id: value.groupId, epoch: value.epoch, message_id: value.messageId, created_at: value.createdAt, from: account, from_device_id: deviceId }, context);
113
+ }
114
+ export function deriveGroupMessageKey(applicationSecret, aad) { requireLength(applicationSecret, 32, 'Epoch application secret'); return deriveKey(applicationSecret, messageSalt, aad); }
115
+ export async function encryptGroupMessage(options) {
116
+ const { context, signer, signal } = options;
117
+ throwIfAborted(signal);
118
+ const certificate = deviceCertificateCodec.decode(deviceCertificateCodec.encode(signer.certificate));
119
+ validateCertificate(certificate, context);
120
+ const signerId = certificateId(certificate, context);
121
+ const header = { groupId: options.groupId, epoch: options.epoch, messageId: options.messageId, createdAt: options.createdAt };
122
+ if (header.createdAt < certificate.notBefore || header.createdAt >= certificate.expiresAt)
123
+ throw new ProtocolError('unauthorized_device', 'Group signer certificate is outside its validity window.');
124
+ const payload = groupPayloadCodec.decode(options.payload);
125
+ validateGroupPayload(payload);
126
+ const aad = groupMessageAad(header, certificate.account, signerId, context);
127
+ const key = deriveGroupMessageKey(options.applicationSecret, aad);
128
+ let plaintext;
129
+ try {
130
+ plaintext = canonicalBytes(payload);
131
+ const nonce = (options.random ?? systemRandom).bytes(12);
132
+ requireLength(nonce, 12, 'Group message nonce');
133
+ let envelope = { ...header, payload: { alg: 'AES-256-GCM', nonce, ciphertext: encryptAes(key, nonce, plaintext, aad) }, deviceSignature: new Uint8Array(64) };
134
+ envelope = { ...envelope, deviceSignature: (await signer.sign(groupMessageEnvelopeInput(envelope, context), signal)).slice() };
135
+ throwIfAborted(signal);
136
+ if (certificateId(signer.certificate, context) !== signerId)
137
+ throw new ProtocolError('invalid_identity', 'Group signer changed identity during signing.');
138
+ verifyGroupMessageEnvelope(envelope, certificate, signerId, context);
139
+ return envelope;
140
+ }
141
+ finally {
142
+ key.fill(0);
143
+ plaintext?.fill(0);
144
+ }
145
+ }
146
+ /** Authenticates the signature, sender account and device before returning typed content. Membership validation remains mandatory in the receiver. */
147
+ export function decryptGroupMessage(options) {
148
+ const { context, signerDeviceId } = options;
149
+ const envelope = groupMessageEnvelopeCodec.decode(groupMessageEnvelopeCodec.encode(options.envelope));
150
+ const sender = deviceCertificateCodec.decode(deviceCertificateCodec.encode(options.sender));
151
+ verifyGroupMessageEnvelope(envelope, sender, signerDeviceId, context);
152
+ const key = deriveGroupMessageKey(options.applicationSecret, groupMessageAad(envelope, sender.account, signerDeviceId, context));
153
+ let plaintext;
154
+ try {
155
+ plaintext = decryptAes(key, envelope.payload.nonce, envelope.payload.ciphertext, groupMessageAad(envelope, sender.account, signerDeviceId, context));
156
+ return groupPayloadCodec.decode(parseJson(plaintext));
157
+ }
158
+ finally {
159
+ key.fill(0);
160
+ plaintext?.fill(0);
161
+ }
162
+ }
163
+ //# sourceMappingURL=groups.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"groups.js","sourceRoot":"","sources":["../../src/crypto/groups.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ import type { DeviceSigner } from '../interactions.js';
2
+ import { type ContactAuthorization } from '../models/contacts.js';
3
+ import { type DeviceCertificate } from '../models/identity.js';
4
+ import { type MessageEnvelope, type MessageKeyBox, type MessageSendRequest } from '../models/messages.js';
5
+ import { type NetworkContext } from '../protocol/context.js';
6
+ import { type JsonObject } from '../protocol/json.js';
7
+ import { type RandomSource } from './primitives.js';
8
+ type MessageHeader = Pick<MessageEnvelope, 'messageId' | 'createdAt' | 'from' | 'fromDeviceId' | 'to'>;
9
+ /** Fixed protocol projection; envelope extensions are signed but are not part of payload AAD. */
10
+ export declare function messageAad(value: MessageHeader, context: NetworkContext): Uint8Array;
11
+ /** Fixed projection shared by HKDF info and AES-GCM key wrapping AAD. */
12
+ export declare function messageKeyBoxAad(value: MessageHeader & {
13
+ readonly payload: {
14
+ readonly alg: string;
15
+ };
16
+ }, box: Pick<MessageKeyBox, 'alg' | 'deviceId' | 'enc'>, account: string, context: NetworkContext): Uint8Array;
17
+ export interface EncryptMessageOptions {
18
+ readonly context: NetworkContext;
19
+ readonly signer: DeviceSigner;
20
+ readonly messageId: string;
21
+ readonly createdAt: number;
22
+ readonly recipient: string;
23
+ readonly payload: JsonObject;
24
+ readonly recipientDevices: readonly DeviceCertificate[];
25
+ readonly senderDevices?: readonly DeviceCertificate[];
26
+ readonly authorization?: ContactAuthorization;
27
+ readonly random?: RandomSource;
28
+ readonly signal?: AbortSignal;
29
+ }
30
+ /** Builds immutable delivery material. Device lists must come from current authoritative states, checked by the calling manager. */
31
+ export declare function encryptMessage(options: EncryptMessageOptions): Promise<MessageSendRequest>;
32
+ /** Implementations return a fresh 32-byte shared secret; this function owns and erases that buffer. */
33
+ export interface MessageDecryptor {
34
+ readonly certificate: DeviceCertificate;
35
+ deriveSharedSecret(peerPublicKey: Uint8Array, signal?: AbortSignal): Promise<Uint8Array>;
36
+ }
37
+ /** Local key access failures are retryable reception failures, never grounds for discarding a remote message. */
38
+ export declare class MessageKeyAccessError extends Error {
39
+ readonly name = "MessageKeyAccessError";
40
+ }
41
+ export interface DecryptMessageOptions {
42
+ readonly context: NetworkContext;
43
+ readonly receiver: MessageDecryptor;
44
+ readonly envelope: MessageEnvelope;
45
+ readonly keyBox: MessageKeyBox;
46
+ readonly sender: DeviceCertificate;
47
+ readonly signal?: AbortSignal;
48
+ }
49
+ /** Verifies signature before key agreement and returns no plaintext until both GCM authentications and complete JSON validation pass. */
50
+ export declare function decryptMessage(options: DecryptMessageOptions): Promise<JsonObject>;
51
+ export {};
52
+ //# sourceMappingURL=messages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/crypto/messages.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGvD,OAAO,EAA6B,KAAK,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7F,OAAO,EAA8D,KAAK,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC3H,OAAO,EACH,KAAK,eAAe,EAAE,KAAK,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AACrG,OAAO,EAAgB,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE3E,OAAO,EAAiD,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAErG,OAAO,EAAyG,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAG3J,KAAK,aAAa,GAAG,IAAI,CAAC,eAAe,EAAE,WAAW,GAAG,WAAW,GAAG,MAAM,GAAG,cAAc,GAAG,IAAI,CAAC,CAAC;AAIvG,iGAAiG;AACjG,wBAAgB,UAAU,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,cAAc,GAAG,UAAU,CAGpF;AACD,yEAAyE;AACzE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,aAAa,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE;QAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,EAAE,GAAG,EAAE,IAAI,CAAC,aAAa,EAAE,KAAK,GAAG,UAAU,GAAG,KAAK,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,UAAU,CAMlN;AACD,MAAM,WAAW,qBAAqB;IAClC,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IACxH,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,gBAAgB,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAClH,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,oBAAoB,CAAC;IAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;CACvK;AACD,oIAAoI;AACpI,wBAAsB,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA2BhG;AAuBD,uGAAuG;AACvG,MAAM,WAAW,gBAAgB;IAAG,QAAQ,CAAC,WAAW,EAAE,iBAAiB,CAAC;IAAC,kBAAkB,CAAC,aAAa,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAAA;CAAE;AACvK,iHAAiH;AACjH,qBAAa,qBAAsB,SAAQ,KAAK;IAAG,SAAkB,IAAI,2BAA2B;CAAE;AACtG,MAAM,WAAW,qBAAqB;IAClC,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC1I,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;CACrE;AACD,yIAAyI;AACzI,wBAAsB,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,UAAU,CAAC,CA+BxF"}