@private.me/xbind 1.2.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 (295) hide show
  1. package/AGENTS.md +778 -0
  2. package/LICENSE.md +27 -0
  3. package/README.md +400 -0
  4. package/dist-standalone/_deps/crypto/base64.d.ts +29 -0
  5. package/dist-standalone/_deps/crypto/base64.js +97 -0
  6. package/dist-standalone/_deps/crypto/cjs/base64.js +103 -0
  7. package/dist-standalone/_deps/crypto/cjs/errors.js +119 -0
  8. package/dist-standalone/_deps/crypto/cjs/hmac.js +71 -0
  9. package/dist-standalone/_deps/crypto/cjs/index.js +86 -0
  10. package/dist-standalone/_deps/crypto/cjs/padding.js +57 -0
  11. package/dist-standalone/_deps/crypto/cjs/share-header.js +68 -0
  12. package/dist-standalone/_deps/crypto/cjs/shares.js +152 -0
  13. package/dist-standalone/_deps/crypto/cjs/tlv.js +199 -0
  14. package/dist-standalone/_deps/crypto/cjs/uuid.js +61 -0
  15. package/dist-standalone/_deps/crypto/cjs/verify.js +24 -0
  16. package/dist-standalone/_deps/crypto/cjs/xorida.js +221 -0
  17. package/dist-standalone/_deps/crypto/errors.d.ts +51 -0
  18. package/dist-standalone/_deps/crypto/errors.js +109 -0
  19. package/dist-standalone/_deps/crypto/hmac.d.ts +39 -0
  20. package/dist-standalone/_deps/crypto/hmac.js +66 -0
  21. package/dist-standalone/_deps/crypto/index.d.ts +20 -0
  22. package/dist-standalone/_deps/crypto/index.js +45 -0
  23. package/dist-standalone/_deps/crypto/padding.d.ts +19 -0
  24. package/dist-standalone/_deps/crypto/padding.js +53 -0
  25. package/dist-standalone/_deps/crypto/share-header.d.ts +44 -0
  26. package/dist-standalone/_deps/crypto/share-header.js +63 -0
  27. package/dist-standalone/_deps/crypto/shares.d.ts +27 -0
  28. package/dist-standalone/_deps/crypto/shares.js +148 -0
  29. package/dist-standalone/_deps/crypto/tlv.d.ts +26 -0
  30. package/dist-standalone/_deps/crypto/tlv.js +195 -0
  31. package/dist-standalone/_deps/crypto/uuid.d.ts +22 -0
  32. package/dist-standalone/_deps/crypto/uuid.js +56 -0
  33. package/dist-standalone/_deps/crypto/verify.d.ts +15 -0
  34. package/dist-standalone/_deps/crypto/verify.js +15 -0
  35. package/dist-standalone/_deps/crypto/xorida.d.ts +44 -0
  36. package/dist-standalone/_deps/crypto/xorida.js +215 -0
  37. package/dist-standalone/_deps/mldsa-wasm/LICENSE +24 -0
  38. package/dist-standalone/_deps/mldsa-wasm/dist/mldsa.js +1920 -0
  39. package/dist-standalone/_deps/mldsa-wasm/package.json +46 -0
  40. package/dist-standalone/_deps/mldsa-wasm/types/mldsa.d.ts +30 -0
  41. package/dist-standalone/_deps/shared/cjs/errors.js +582 -0
  42. package/dist-standalone/_deps/shared/cjs/index.js +492 -0
  43. package/dist-standalone/_deps/shared/cjs/package.json +1 -0
  44. package/dist-standalone/_deps/shared/cjs/types.js +403 -0
  45. package/dist-standalone/_deps/shared/errors.d.ts +48 -0
  46. package/dist-standalone/_deps/shared/errors.d.ts.map +1 -0
  47. package/dist-standalone/_deps/shared/errors.js +192 -0
  48. package/dist-standalone/_deps/shared/errors.js.map +1 -0
  49. package/dist-standalone/_deps/shared/index.d.ts +4 -0
  50. package/dist-standalone/_deps/shared/index.d.ts.map +1 -0
  51. package/dist-standalone/_deps/shared/index.js +78 -0
  52. package/dist-standalone/_deps/shared/index.js.map +1 -0
  53. package/dist-standalone/_deps/shared/types.d.ts +1097 -0
  54. package/dist-standalone/_deps/shared/types.d.ts.map +1 -0
  55. package/dist-standalone/_deps/shared/types.js +89 -0
  56. package/dist-standalone/_deps/shared/types.js.map +1 -0
  57. package/dist-standalone/_deps/ux-helpers/cjs/errors.d.ts +115 -0
  58. package/dist-standalone/_deps/ux-helpers/cjs/errors.d.ts.map +1 -0
  59. package/dist-standalone/_deps/ux-helpers/cjs/errors.js +1 -0
  60. package/dist-standalone/_deps/ux-helpers/cjs/errors.js.map +1 -0
  61. package/dist-standalone/_deps/ux-helpers/cjs/index.d.ts +13 -0
  62. package/dist-standalone/_deps/ux-helpers/cjs/index.d.ts.map +1 -0
  63. package/dist-standalone/_deps/ux-helpers/cjs/index.js +1 -0
  64. package/dist-standalone/_deps/ux-helpers/cjs/index.js.map +1 -0
  65. package/dist-standalone/_deps/ux-helpers/cjs/package.json +1 -0
  66. package/dist-standalone/_deps/ux-helpers/cjs/pagination.d.ts +39 -0
  67. package/dist-standalone/_deps/ux-helpers/cjs/pagination.d.ts.map +1 -0
  68. package/dist-standalone/_deps/ux-helpers/cjs/pagination.js +83 -0
  69. package/dist-standalone/_deps/ux-helpers/cjs/pagination.js.map +1 -0
  70. package/dist-standalone/_deps/ux-helpers/cjs/progress.d.ts +99 -0
  71. package/dist-standalone/_deps/ux-helpers/cjs/progress.d.ts.map +1 -0
  72. package/dist-standalone/_deps/ux-helpers/cjs/progress.js +143 -0
  73. package/dist-standalone/_deps/ux-helpers/cjs/progress.js.map +1 -0
  74. package/dist-standalone/_deps/ux-helpers/cjs/search.d.ts +32 -0
  75. package/dist-standalone/_deps/ux-helpers/cjs/search.d.ts.map +1 -0
  76. package/dist-standalone/_deps/ux-helpers/cjs/search.js +119 -0
  77. package/dist-standalone/_deps/ux-helpers/cjs/search.js.map +1 -0
  78. package/dist-standalone/_deps/ux-helpers/cjs/types.d.ts +109 -0
  79. package/dist-standalone/_deps/ux-helpers/cjs/types.d.ts.map +1 -0
  80. package/dist-standalone/_deps/ux-helpers/cjs/types.js +8 -0
  81. package/dist-standalone/_deps/ux-helpers/cjs/types.js.map +1 -0
  82. package/dist-standalone/_deps/ux-helpers/errors.d.ts +115 -0
  83. package/dist-standalone/_deps/ux-helpers/errors.d.ts.map +1 -0
  84. package/dist-standalone/_deps/ux-helpers/errors.js +253 -0
  85. package/dist-standalone/_deps/ux-helpers/errors.js.map +1 -0
  86. package/dist-standalone/_deps/ux-helpers/index.d.ts +13 -0
  87. package/dist-standalone/_deps/ux-helpers/index.d.ts.map +1 -0
  88. package/dist-standalone/_deps/ux-helpers/index.js +16 -0
  89. package/dist-standalone/_deps/ux-helpers/index.js.map +1 -0
  90. package/dist-standalone/_deps/ux-helpers/pagination.d.ts +39 -0
  91. package/dist-standalone/_deps/ux-helpers/pagination.d.ts.map +1 -0
  92. package/dist-standalone/_deps/ux-helpers/pagination.js +79 -0
  93. package/dist-standalone/_deps/ux-helpers/pagination.js.map +1 -0
  94. package/dist-standalone/_deps/ux-helpers/progress.d.ts +99 -0
  95. package/dist-standalone/_deps/ux-helpers/progress.d.ts.map +1 -0
  96. package/dist-standalone/_deps/ux-helpers/progress.js +138 -0
  97. package/dist-standalone/_deps/ux-helpers/progress.js.map +1 -0
  98. package/dist-standalone/_deps/ux-helpers/search.d.ts +32 -0
  99. package/dist-standalone/_deps/ux-helpers/search.d.ts.map +1 -0
  100. package/dist-standalone/_deps/ux-helpers/search.js +116 -0
  101. package/dist-standalone/_deps/ux-helpers/search.js.map +1 -0
  102. package/dist-standalone/_deps/ux-helpers/types.d.ts +109 -0
  103. package/dist-standalone/_deps/ux-helpers/types.d.ts.map +1 -0
  104. package/dist-standalone/_deps/ux-helpers/types.js +7 -0
  105. package/dist-standalone/_deps/ux-helpers/types.js.map +1 -0
  106. package/dist-standalone/_deps/xchange/auto-accept.d.ts +127 -0
  107. package/dist-standalone/_deps/xchange/auto-accept.js +1 -0
  108. package/dist-standalone/_deps/xchange/cjs/auto-accept.js +1 -0
  109. package/dist-standalone/_deps/xchange/cjs/errors.js +1 -0
  110. package/dist-standalone/_deps/xchange/cjs/index.js +1 -0
  111. package/dist-standalone/_deps/xchange/cjs/invite-client.js +1 -0
  112. package/dist-standalone/_deps/xchange/cjs/lazy-init.js +1 -0
  113. package/dist-standalone/_deps/xchange/cjs/package.json +1 -0
  114. package/dist-standalone/_deps/xchange/cjs/trust-integration.js +1 -0
  115. package/dist-standalone/_deps/xchange/cjs/xchange.js +1 -0
  116. package/dist-standalone/_deps/xchange/errors.d.ts +69 -0
  117. package/dist-standalone/_deps/xchange/errors.js +1 -0
  118. package/dist-standalone/_deps/xchange/index.d.ts +15 -0
  119. package/dist-standalone/_deps/xchange/index.js +1 -0
  120. package/dist-standalone/_deps/xchange/invite-client.d.ts +178 -0
  121. package/dist-standalone/_deps/xchange/invite-client.js +1 -0
  122. package/dist-standalone/_deps/xchange/lazy-init.d.ts +176 -0
  123. package/dist-standalone/_deps/xchange/lazy-init.js +1 -0
  124. package/dist-standalone/_deps/xchange/trust-integration.d.ts +102 -0
  125. package/dist-standalone/_deps/xchange/trust-integration.js +1 -0
  126. package/dist-standalone/_deps/xchange/xchange.d.ts +60 -0
  127. package/dist-standalone/_deps/xchange/xchange.js +1 -0
  128. package/dist-standalone/_deps/xregistry/cjs/discovery.js +1 -0
  129. package/dist-standalone/_deps/xregistry/cjs/errors.js +1 -0
  130. package/dist-standalone/_deps/xregistry/cjs/index.js +1 -0
  131. package/dist-standalone/_deps/xregistry/cjs/package.json +1 -0
  132. package/dist-standalone/_deps/xregistry/cjs/registry.js +1 -0
  133. package/dist-standalone/_deps/xregistry/cjs/schema.js +1 -0
  134. package/dist-standalone/_deps/xregistry/cjs/types.js +1 -0
  135. package/dist-standalone/_deps/xregistry/discovery.d.ts +126 -0
  136. package/dist-standalone/_deps/xregistry/discovery.d.ts.map +1 -0
  137. package/dist-standalone/_deps/xregistry/discovery.js +1 -0
  138. package/dist-standalone/_deps/xregistry/discovery.js.map +1 -0
  139. package/dist-standalone/_deps/xregistry/errors.d.ts +41 -0
  140. package/dist-standalone/_deps/xregistry/errors.d.ts.map +1 -0
  141. package/dist-standalone/_deps/xregistry/errors.js +1 -0
  142. package/dist-standalone/_deps/xregistry/errors.js.map +1 -0
  143. package/dist-standalone/_deps/xregistry/index.d.ts +8 -0
  144. package/dist-standalone/_deps/xregistry/index.d.ts.map +1 -0
  145. package/dist-standalone/_deps/xregistry/index.js +1 -0
  146. package/dist-standalone/_deps/xregistry/index.js.map +1 -0
  147. package/dist-standalone/_deps/xregistry/registry.d.ts +85 -0
  148. package/dist-standalone/_deps/xregistry/registry.d.ts.map +1 -0
  149. package/dist-standalone/_deps/xregistry/registry.js +1 -0
  150. package/dist-standalone/_deps/xregistry/registry.js.map +1 -0
  151. package/dist-standalone/_deps/xregistry/schema.d.ts +81 -0
  152. package/dist-standalone/_deps/xregistry/schema.d.ts.map +1 -0
  153. package/dist-standalone/_deps/xregistry/schema.js +1 -0
  154. package/dist-standalone/_deps/xregistry/schema.js.map +1 -0
  155. package/dist-standalone/_deps/xregistry/types.d.ts +95 -0
  156. package/dist-standalone/_deps/xregistry/types.d.ts.map +1 -0
  157. package/dist-standalone/_deps/xregistry/types.js +1 -0
  158. package/dist-standalone/_deps/xregistry/types.js.map +1 -0
  159. package/dist-standalone/agent-call.d.ts +286 -0
  160. package/dist-standalone/agent-call.js +642 -0
  161. package/dist-standalone/agent-sdk.d.ts +207 -0
  162. package/dist-standalone/agent-sdk.js +328 -0
  163. package/dist-standalone/agent.d.ts +670 -0
  164. package/dist-standalone/agent.js +1529 -0
  165. package/dist-standalone/approval.d.ts +145 -0
  166. package/dist-standalone/approval.js +193 -0
  167. package/dist-standalone/auth.d.ts +75 -0
  168. package/dist-standalone/auth.js +219 -0
  169. package/dist-standalone/auto-accept.d.ts +102 -0
  170. package/dist-standalone/auto-accept.js +229 -0
  171. package/dist-standalone/backup-config.d.ts +150 -0
  172. package/dist-standalone/backup-config.js +201 -0
  173. package/dist-standalone/checkpoint.d.ts +125 -0
  174. package/dist-standalone/checkpoint.js +186 -0
  175. package/dist-standalone/cjs/agent-call.js +651 -0
  176. package/dist-standalone/cjs/agent-sdk.js +332 -0
  177. package/dist-standalone/cjs/agent.js +1566 -0
  178. package/dist-standalone/cjs/approval.js +199 -0
  179. package/dist-standalone/cjs/auth.js +225 -0
  180. package/dist-standalone/cjs/auto-accept.js +233 -0
  181. package/dist-standalone/cjs/backup-config.js +207 -0
  182. package/dist-standalone/cjs/checkpoint.js +193 -0
  183. package/dist-standalone/cjs/cli/init.js +487 -0
  184. package/dist-standalone/cjs/connect.js +312 -0
  185. package/dist-standalone/cjs/did-document.js +101 -0
  186. package/dist-standalone/cjs/did-privateme.js +130 -0
  187. package/dist-standalone/cjs/did-web.js +201 -0
  188. package/dist-standalone/cjs/discovery.js +462 -0
  189. package/dist-standalone/cjs/dual-mode.js +251 -0
  190. package/dist-standalone/cjs/email-templates.js +313 -0
  191. package/dist-standalone/cjs/email-transport.js +239 -0
  192. package/dist-standalone/cjs/envelope.js +510 -0
  193. package/dist-standalone/cjs/errors.js +562 -0
  194. package/dist-standalone/cjs/gateway-state.js +55 -0
  195. package/dist-standalone/cjs/gateway-transport.js +120 -0
  196. package/dist-standalone/cjs/guardrails.js +223 -0
  197. package/dist-standalone/cjs/http-compat.js +272 -0
  198. package/dist-standalone/cjs/identity.js +541 -0
  199. package/dist-standalone/cjs/index.js +224 -0
  200. package/dist-standalone/cjs/invitation.js +421 -0
  201. package/dist-standalone/cjs/invite.js +328 -0
  202. package/dist-standalone/cjs/key-agreement.js +246 -0
  203. package/dist-standalone/cjs/lazy-init.js +300 -0
  204. package/dist-standalone/cjs/mdns-discovery.js +202 -0
  205. package/dist-standalone/cjs/nonce-store.js +66 -0
  206. package/dist-standalone/cjs/package.json +3 -0
  207. package/dist-standalone/cjs/pairing-manager.js +223 -0
  208. package/dist-standalone/cjs/policy.js +320 -0
  209. package/dist-standalone/cjs/redis-nonce-store.js +76 -0
  210. package/dist-standalone/cjs/registry-middleware.js +50 -0
  211. package/dist-standalone/cjs/retry-transport.js +102 -0
  212. package/dist-standalone/cjs/security-policy.js +204 -0
  213. package/dist-standalone/cjs/split-channel.js +177 -0
  214. package/dist-standalone/cjs/subscription-proof.js +230 -0
  215. package/dist-standalone/cjs/succession.js +148 -0
  216. package/dist-standalone/cjs/transport.js +63 -0
  217. package/dist-standalone/cjs/trust-registry.js +742 -0
  218. package/dist-standalone/cjs/verify.js +25 -0
  219. package/dist-standalone/cjs/xfetch.js +252 -0
  220. package/dist-standalone/cli/init.d.ts +63 -0
  221. package/dist-standalone/cli/init.js +450 -0
  222. package/dist-standalone/connect.d.ts +143 -0
  223. package/dist-standalone/connect.js +274 -0
  224. package/dist-standalone/did-document.d.ts +65 -0
  225. package/dist-standalone/did-document.js +96 -0
  226. package/dist-standalone/did-privateme.d.ts +70 -0
  227. package/dist-standalone/did-privateme.js +121 -0
  228. package/dist-standalone/did-web.d.ts +73 -0
  229. package/dist-standalone/did-web.js +196 -0
  230. package/dist-standalone/discovery.d.ts +176 -0
  231. package/dist-standalone/discovery.js +458 -0
  232. package/dist-standalone/dual-mode.d.ts +145 -0
  233. package/dist-standalone/dual-mode.js +247 -0
  234. package/dist-standalone/email-templates.d.ts +41 -0
  235. package/dist-standalone/email-templates.js +309 -0
  236. package/dist-standalone/email-transport.d.ts +139 -0
  237. package/dist-standalone/email-transport.js +232 -0
  238. package/dist-standalone/envelope.d.ts +288 -0
  239. package/dist-standalone/envelope.js +497 -0
  240. package/dist-standalone/errors.d.ts +74 -0
  241. package/dist-standalone/errors.js +548 -0
  242. package/dist-standalone/gateway-state.d.ts +32 -0
  243. package/dist-standalone/gateway-state.js +51 -0
  244. package/dist-standalone/gateway-transport.d.ts +59 -0
  245. package/dist-standalone/gateway-transport.js +116 -0
  246. package/dist-standalone/guardrails.d.ts +136 -0
  247. package/dist-standalone/guardrails.js +216 -0
  248. package/dist-standalone/http-compat.d.ts +150 -0
  249. package/dist-standalone/http-compat.js +267 -0
  250. package/dist-standalone/identity.d.ts +176 -0
  251. package/dist-standalone/identity.js +516 -0
  252. package/dist-standalone/index.d.ts +83 -0
  253. package/dist-standalone/index.js +51 -0
  254. package/dist-standalone/invitation.d.ts +211 -0
  255. package/dist-standalone/invitation.js +415 -0
  256. package/dist-standalone/invite.d.ts +192 -0
  257. package/dist-standalone/invite.js +324 -0
  258. package/dist-standalone/key-agreement.d.ts +122 -0
  259. package/dist-standalone/key-agreement.js +236 -0
  260. package/dist-standalone/lazy-init.d.ts +167 -0
  261. package/dist-standalone/lazy-init.js +295 -0
  262. package/dist-standalone/mdns-discovery.d.ts +117 -0
  263. package/dist-standalone/mdns-discovery.js +195 -0
  264. package/dist-standalone/nonce-store.d.ts +39 -0
  265. package/dist-standalone/nonce-store.js +62 -0
  266. package/dist-standalone/package.json +11 -0
  267. package/dist-standalone/pairing-manager.d.ts +147 -0
  268. package/dist-standalone/pairing-manager.js +219 -0
  269. package/dist-standalone/policy.d.ts +150 -0
  270. package/dist-standalone/policy.js +315 -0
  271. package/dist-standalone/redis-nonce-store.d.ts +93 -0
  272. package/dist-standalone/redis-nonce-store.js +72 -0
  273. package/dist-standalone/registry-middleware.d.ts +38 -0
  274. package/dist-standalone/registry-middleware.js +47 -0
  275. package/dist-standalone/retry-transport.d.ts +76 -0
  276. package/dist-standalone/retry-transport.js +98 -0
  277. package/dist-standalone/security-policy.d.ts +146 -0
  278. package/dist-standalone/security-policy.js +198 -0
  279. package/dist-standalone/split-channel.d.ts +69 -0
  280. package/dist-standalone/split-channel.js +171 -0
  281. package/dist-standalone/subscription-proof.d.ts +103 -0
  282. package/dist-standalone/subscription-proof.js +224 -0
  283. package/dist-standalone/succession.d.ts +57 -0
  284. package/dist-standalone/succession.js +142 -0
  285. package/dist-standalone/transport.d.ts +50 -0
  286. package/dist-standalone/transport.js +59 -0
  287. package/dist-standalone/trust-registry.d.ts +286 -0
  288. package/dist-standalone/trust-registry.js +702 -0
  289. package/dist-standalone/verify.d.ts +16 -0
  290. package/dist-standalone/verify.js +16 -0
  291. package/dist-standalone/xfetch.d.ts +129 -0
  292. package/dist-standalone/xfetch.js +247 -0
  293. package/llms.txt +800 -0
  294. package/package.json +79 -0
  295. package/share1.dat +0 -0
@@ -0,0 +1,192 @@
1
+ /**
2
+ * @module invite
3
+ * Viral invite system for XBind connections.
4
+ *
5
+ * Enables one-click invites:
6
+ * - Generate: `xbind invite payments-service`
7
+ * - Accept: Click link or `xbind accept https://xbind.to/invite/abc123`
8
+ *
9
+ * The viral loop:
10
+ * 1. Service A invites Service B
11
+ * 2. Service B clicks link (< 60 sec setup)
12
+ * 3. Connection established
13
+ * 4. Service B invites Service C
14
+ */
15
+ import { Result } from '@private.me/shared';
16
+ import type { ServiceInfo } from './discovery.js';
17
+ /**
18
+ * Invite data structure.
19
+ */
20
+ export interface Invite {
21
+ /** Unique invite ID */
22
+ id: string;
23
+ /** Service that sent the invite */
24
+ from: {
25
+ name: string;
26
+ did: string;
27
+ endpoint: string;
28
+ publicKey: string;
29
+ x25519PublicKey?: string;
30
+ mlKemPublicKey?: string;
31
+ };
32
+ /** Target service (optional, can be open invite) */
33
+ to?: {
34
+ name?: string;
35
+ email?: string;
36
+ };
37
+ /** Suggested permissions/template */
38
+ template?: string;
39
+ /** Custom permissions */
40
+ permissions?: string[];
41
+ /** Invite expiration (ISO timestamp) */
42
+ expires: string;
43
+ /** Invite URL */
44
+ url: string;
45
+ /** QR code data URL (for airgapped) */
46
+ qr?: string;
47
+ }
48
+ /**
49
+ * Invite error codes.
50
+ */
51
+ export declare enum InviteErrorCode {
52
+ INVALID_INVITE = "INVITE_INVALID",
53
+ EXPIRED_INVITE = "INVITE_EXPIRED",
54
+ INVITE_NOT_FOUND = "INVITE_NOT_FOUND",
55
+ NETWORK_ERROR = "INVITE_NETWORK_ERROR",
56
+ ALREADY_CONNECTED = "INVITE_ALREADY_CONNECTED"
57
+ }
58
+ /**
59
+ * Invite error.
60
+ */
61
+ export interface InviteError {
62
+ code: InviteErrorCode;
63
+ message: string;
64
+ hint?: string;
65
+ }
66
+ /**
67
+ * Invite service for creating and accepting invites.
68
+ */
69
+ export declare class InviteService {
70
+ private inviteApiUrl;
71
+ /**
72
+ * Create invite service.
73
+ *
74
+ * @param options - Configuration
75
+ * @param options.inviteApiUrl - Invite API URL (default: https://xbind.to)
76
+ */
77
+ constructor(options?: {
78
+ inviteApiUrl?: string;
79
+ });
80
+ /**
81
+ * Create an invite.
82
+ *
83
+ * @param options - Invite options
84
+ * @param options.from - Sender service info
85
+ * @param options.target - Target service (optional)
86
+ * @param options.template - Suggested template (e.g., "payment-processing")
87
+ * @param options.permissions - Custom permissions
88
+ * @param options.expiresIn - Expiration in seconds (default: 7 days)
89
+ * @returns Invite or error
90
+ *
91
+ * @example
92
+ * ```ts
93
+ * const inviteService = new InviteService();
94
+ * const invite = await inviteService.create({
95
+ * from: {
96
+ * name: 'billing-service',
97
+ * did: 'did:key:z6Mk...',
98
+ * endpoint: 'https://billing.example.com',
99
+ * publicKey: '...',
100
+ * },
101
+ * target: {
102
+ * name: 'payments-service',
103
+ * },
104
+ * template: 'payment-processing',
105
+ * });
106
+ *
107
+ * // Share invite.value.url or invite.value.qr
108
+ * ```
109
+ */
110
+ create(options: {
111
+ from: ServiceInfo;
112
+ target?: {
113
+ name?: string;
114
+ email?: string;
115
+ };
116
+ template?: string;
117
+ permissions?: string[];
118
+ expiresIn?: number;
119
+ }): Promise<Result<Invite, InviteError>>;
120
+ /**
121
+ * Accept an invite.
122
+ *
123
+ * @param options - Accept options
124
+ * @param options.inviteUrl - Invite URL (e.g., https://xbind.to/invite/abc123)
125
+ * @param options.acceptor - Acceptor service info
126
+ * @returns Connection info or error
127
+ *
128
+ * @example
129
+ * ```ts
130
+ * const inviteService = new InviteService();
131
+ * const result = await inviteService.accept({
132
+ * inviteUrl: 'https://xbind.to/invite/abc123',
133
+ * acceptor: {
134
+ * name: 'payments-service',
135
+ * did: 'did:key:z6Mk...',
136
+ * endpoint: 'https://payments.example.com',
137
+ * publicKey: '...',
138
+ * }
139
+ * });
140
+ *
141
+ * if (result.ok) {
142
+ * console.log('Connected!');
143
+ * }
144
+ * ```
145
+ */
146
+ accept(options: {
147
+ inviteUrl: string;
148
+ acceptor: ServiceInfo;
149
+ }): Promise<Result<{
150
+ success: boolean;
151
+ connection: ServiceInfo;
152
+ }, InviteError>>;
153
+ /**
154
+ * Get invite details without accepting.
155
+ *
156
+ * @param inviteUrl - Invite URL
157
+ * @returns Invite details or error
158
+ */
159
+ get(inviteUrl: string): Promise<Result<Invite, InviteError>>;
160
+ /**
161
+ * Revoke an invite.
162
+ *
163
+ * @param inviteId - Invite ID to revoke
164
+ * @returns Success or error
165
+ *
166
+ * @example
167
+ * ```ts
168
+ * const inviteService = new InviteService();
169
+ * const result = await inviteService.revoke('inv_abc123');
170
+ *
171
+ * if (result.ok) {
172
+ * console.log('Invite revoked');
173
+ * }
174
+ * ```
175
+ */
176
+ revoke(inviteId: string): Promise<Result<{
177
+ success: boolean;
178
+ }, InviteError>>;
179
+ /**
180
+ * Extract invite ID from URL.
181
+ *
182
+ * @param url - Invite URL
183
+ * @returns Invite ID or null
184
+ *
185
+ * @example
186
+ * ```ts
187
+ * extractInviteId('https://xbind.to/invite/abc123') // 'abc123'
188
+ * extractInviteId('https://xbind.to/billing/invite/xyz') // 'xyz'
189
+ * ```
190
+ */
191
+ private extractInviteId;
192
+ }
@@ -0,0 +1,324 @@
1
+ /**
2
+ * @module invite
3
+ * Viral invite system for XBind connections.
4
+ *
5
+ * Enables one-click invites:
6
+ * - Generate: `xbind invite payments-service`
7
+ * - Accept: Click link or `xbind accept https://xbind.to/invite/abc123`
8
+ *
9
+ * The viral loop:
10
+ * 1. Service A invites Service B
11
+ * 2. Service B clicks link (< 60 sec setup)
12
+ * 3. Connection established
13
+ * 4. Service B invites Service C
14
+ */
15
+ import { ok, err } from"./_deps/shared/index.js";
16
+ /**
17
+ * Invite error codes.
18
+ */
19
+ export var InviteErrorCode;
20
+ (function (InviteErrorCode) {
21
+ InviteErrorCode["INVALID_INVITE"] = "INVITE_INVALID";
22
+ InviteErrorCode["EXPIRED_INVITE"] = "INVITE_EXPIRED";
23
+ InviteErrorCode["INVITE_NOT_FOUND"] = "INVITE_NOT_FOUND";
24
+ InviteErrorCode["NETWORK_ERROR"] = "INVITE_NETWORK_ERROR";
25
+ InviteErrorCode["ALREADY_CONNECTED"] = "INVITE_ALREADY_CONNECTED";
26
+ })(InviteErrorCode || (InviteErrorCode = {}));
27
+ /**
28
+ * Invite service for creating and accepting invites.
29
+ */
30
+ export class InviteService {
31
+ inviteApiUrl;
32
+ /**
33
+ * Create invite service.
34
+ *
35
+ * @param options - Configuration
36
+ * @param options.inviteApiUrl - Invite API URL (default: https://xbind.to)
37
+ */
38
+ constructor(options = {}) {
39
+ this.inviteApiUrl = options.inviteApiUrl || 'https://xbind.to';
40
+ }
41
+ /**
42
+ * Create an invite.
43
+ *
44
+ * @param options - Invite options
45
+ * @param options.from - Sender service info
46
+ * @param options.target - Target service (optional)
47
+ * @param options.template - Suggested template (e.g., "payment-processing")
48
+ * @param options.permissions - Custom permissions
49
+ * @param options.expiresIn - Expiration in seconds (default: 7 days)
50
+ * @returns Invite or error
51
+ *
52
+ * @example
53
+ * ```ts
54
+ * const inviteService = new InviteService();
55
+ * const invite = await inviteService.create({
56
+ * from: {
57
+ * name: 'billing-service',
58
+ * did: 'did:key:z6Mk...',
59
+ * endpoint: 'https://billing.example.com',
60
+ * publicKey: '...',
61
+ * },
62
+ * target: {
63
+ * name: 'payments-service',
64
+ * },
65
+ * template: 'payment-processing',
66
+ * });
67
+ *
68
+ * // Share invite.value.url or invite.value.qr
69
+ * ```
70
+ */
71
+ async create(options) {
72
+ const expiresIn = options.expiresIn || 7 * 24 * 60 * 60; // 7 days
73
+ const expires = new Date(Date.now() + expiresIn * 1000).toISOString();
74
+ try {
75
+ const response = await fetch(`${this.inviteApiUrl}/invites/create`, {
76
+ method: 'POST',
77
+ headers: {
78
+ 'Content-Type': 'application/json',
79
+ },
80
+ body: JSON.stringify({
81
+ from: {
82
+ name: options.from.name,
83
+ did: options.from.did,
84
+ endpoint: options.from.endpoint,
85
+ publicKey: options.from.publicKey,
86
+ x25519PublicKey: options.from.x25519PublicKey,
87
+ mlKemPublicKey: options.from.mlKemPublicKey,
88
+ },
89
+ to: options.target,
90
+ template: options.template,
91
+ permissions: options.permissions,
92
+ expires,
93
+ }),
94
+ });
95
+ if (!response.ok) {
96
+ return err({
97
+ code: InviteErrorCode.NETWORK_ERROR,
98
+ message: `Failed to create invite: ${response.status}`,
99
+ });
100
+ }
101
+ const data = await response.json();
102
+ return ok(data);
103
+ }
104
+ catch (error) {
105
+ return err({
106
+ code: InviteErrorCode.NETWORK_ERROR,
107
+ message: error instanceof Error ? error.message : 'Network error',
108
+ });
109
+ }
110
+ }
111
+ /**
112
+ * Accept an invite.
113
+ *
114
+ * @param options - Accept options
115
+ * @param options.inviteUrl - Invite URL (e.g., https://xbind.to/invite/abc123)
116
+ * @param options.acceptor - Acceptor service info
117
+ * @returns Connection info or error
118
+ *
119
+ * @example
120
+ * ```ts
121
+ * const inviteService = new InviteService();
122
+ * const result = await inviteService.accept({
123
+ * inviteUrl: 'https://xbind.to/invite/abc123',
124
+ * acceptor: {
125
+ * name: 'payments-service',
126
+ * did: 'did:key:z6Mk...',
127
+ * endpoint: 'https://payments.example.com',
128
+ * publicKey: '...',
129
+ * }
130
+ * });
131
+ *
132
+ * if (result.ok) {
133
+ * console.log('Connected!');
134
+ * }
135
+ * ```
136
+ */
137
+ async accept(options) {
138
+ try {
139
+ // Extract invite ID from URL
140
+ const inviteId = this.extractInviteId(options.inviteUrl);
141
+ if (!inviteId) {
142
+ return err({
143
+ code: InviteErrorCode.INVALID_INVITE,
144
+ message: 'Invalid invite URL',
145
+ hint: 'URL should be like: https://xbind.to/invite/abc123',
146
+ });
147
+ }
148
+ // Accept invite
149
+ const response = await fetch(`${this.inviteApiUrl}/invites/${inviteId}/accept`, {
150
+ method: 'POST',
151
+ headers: {
152
+ 'Content-Type': 'application/json',
153
+ },
154
+ body: JSON.stringify({
155
+ acceptor: {
156
+ name: options.acceptor.name,
157
+ did: options.acceptor.did,
158
+ endpoint: options.acceptor.endpoint,
159
+ publicKey: options.acceptor.publicKey,
160
+ x25519PublicKey: options.acceptor.x25519PublicKey,
161
+ mlKemPublicKey: options.acceptor.mlKemPublicKey,
162
+ },
163
+ }),
164
+ });
165
+ if (response.status === 404) {
166
+ return err({
167
+ code: InviteErrorCode.INVITE_NOT_FOUND,
168
+ message: 'Invite not found or expired',
169
+ hint: 'The invite may have been revoked or expired',
170
+ });
171
+ }
172
+ if (response.status === 410) {
173
+ const errorData = await response.json().catch(() => ({}));
174
+ return err({
175
+ code: InviteErrorCode.EXPIRED_INVITE,
176
+ message: errorData.message || 'Invite has expired',
177
+ hint: errorData.hint || 'Ask the sender to create a new invite',
178
+ });
179
+ }
180
+ if (response.status === 409) {
181
+ return err({
182
+ code: InviteErrorCode.ALREADY_CONNECTED,
183
+ message: 'Services are already connected',
184
+ hint: 'You are already connected to this service',
185
+ });
186
+ }
187
+ if (!response.ok) {
188
+ return err({
189
+ code: InviteErrorCode.NETWORK_ERROR,
190
+ message: `Failed to accept invite: ${response.status}`,
191
+ });
192
+ }
193
+ const data = await response.json();
194
+ return ok(data);
195
+ }
196
+ catch (error) {
197
+ return err({
198
+ code: InviteErrorCode.NETWORK_ERROR,
199
+ message: error instanceof Error ? error.message : 'Network error',
200
+ hint: 'Check your network connection and try again',
201
+ });
202
+ }
203
+ }
204
+ /**
205
+ * Get invite details without accepting.
206
+ *
207
+ * @param inviteUrl - Invite URL
208
+ * @returns Invite details or error
209
+ */
210
+ async get(inviteUrl) {
211
+ try {
212
+ const inviteId = this.extractInviteId(inviteUrl);
213
+ if (!inviteId) {
214
+ return err({
215
+ code: InviteErrorCode.INVALID_INVITE,
216
+ message: 'Invalid invite URL',
217
+ });
218
+ }
219
+ const response = await fetch(`${this.inviteApiUrl}/invites/${inviteId}`, {
220
+ headers: {
221
+ 'Accept': 'application/json',
222
+ },
223
+ });
224
+ if (response.status === 404) {
225
+ return err({
226
+ code: InviteErrorCode.INVITE_NOT_FOUND,
227
+ message: 'Invite not found',
228
+ });
229
+ }
230
+ if (!response.ok) {
231
+ return err({
232
+ code: InviteErrorCode.NETWORK_ERROR,
233
+ message: `Failed to get invite: ${response.status}`,
234
+ });
235
+ }
236
+ const data = await response.json();
237
+ return ok(data);
238
+ }
239
+ catch (error) {
240
+ return err({
241
+ code: InviteErrorCode.NETWORK_ERROR,
242
+ message: error instanceof Error ? error.message : 'Network error',
243
+ });
244
+ }
245
+ }
246
+ /**
247
+ * Revoke an invite.
248
+ *
249
+ * @param inviteId - Invite ID to revoke
250
+ * @returns Success or error
251
+ *
252
+ * @example
253
+ * ```ts
254
+ * const inviteService = new InviteService();
255
+ * const result = await inviteService.revoke('inv_abc123');
256
+ *
257
+ * if (result.ok) {
258
+ * console.log('Invite revoked');
259
+ * }
260
+ * ```
261
+ */
262
+ async revoke(inviteId) {
263
+ try {
264
+ const response = await fetch(`${this.inviteApiUrl}/invites/${inviteId}/revoke`, {
265
+ method: 'POST',
266
+ headers: {
267
+ 'Content-Type': 'application/json',
268
+ },
269
+ });
270
+ if (response.status === 404) {
271
+ return err({
272
+ code: InviteErrorCode.INVITE_NOT_FOUND,
273
+ message: 'Invite not found',
274
+ hint: 'The invite may have already been revoked or expired',
275
+ });
276
+ }
277
+ if (!response.ok) {
278
+ return err({
279
+ code: InviteErrorCode.NETWORK_ERROR,
280
+ message: `Failed to revoke invite: ${response.status}`,
281
+ });
282
+ }
283
+ const data = await response.json();
284
+ return ok(data);
285
+ }
286
+ catch (error) {
287
+ return err({
288
+ code: InviteErrorCode.NETWORK_ERROR,
289
+ message: error instanceof Error ? error.message : 'Network error',
290
+ });
291
+ }
292
+ }
293
+ /**
294
+ * Extract invite ID from URL.
295
+ *
296
+ * @param url - Invite URL
297
+ * @returns Invite ID or null
298
+ *
299
+ * @example
300
+ * ```ts
301
+ * extractInviteId('https://xbind.to/invite/abc123') // 'abc123'
302
+ * extractInviteId('https://xbind.to/billing/invite/xyz') // 'xyz'
303
+ * ```
304
+ */
305
+ extractInviteId(url) {
306
+ try {
307
+ const parsed = new URL(url);
308
+ const segments = parsed.pathname.split('/').filter(s => s.length > 0);
309
+ // Look for 'invite' segment followed by ID
310
+ const inviteIndex = segments.indexOf('invite');
311
+ if (inviteIndex !== -1 && segments[inviteIndex + 1]) {
312
+ return segments[inviteIndex + 1] ?? null;
313
+ }
314
+ // Fallback: last segment
315
+ if (segments.length > 0) {
316
+ return segments[segments.length - 1] ?? null;
317
+ }
318
+ return null;
319
+ }
320
+ catch {
321
+ return null;
322
+ }
323
+ }
324
+ }
@@ -0,0 +1,122 @@
1
+ import type { Result } from '@private.me/shared';
2
+ /** X25519 ephemeral key pair for ECDH key agreement. */
3
+ export interface EphemeralKeyPair {
4
+ /** Web Crypto private key handle (X25519). */
5
+ readonly privateKey: CryptoKey;
6
+ /** Web Crypto public key handle (X25519). */
7
+ readonly publicKey: CryptoKey;
8
+ /** Raw 32-byte X25519 public key for wire transport. */
9
+ readonly rawPublicKey: Uint8Array;
10
+ }
11
+ /** Result of ECDH key agreement. */
12
+ export interface KeyAgreementResult {
13
+ /** Derived AES-256-GCM shared key. */
14
+ readonly sharedKey: CryptoKey;
15
+ /** Ephemeral public key to include in envelope. */
16
+ readonly ephemeralPublicKey: Uint8Array;
17
+ }
18
+ /** Result of hybrid (X25519 + ML-KEM-768) key agreement. */
19
+ export interface HybridKeyAgreementResult {
20
+ /** Derived AES-256-GCM shared key (from HKDF over X25519 + ML-KEM shared secrets). */
21
+ readonly sharedKey: CryptoKey;
22
+ /** Ephemeral X25519 public key to include in envelope (32 bytes). */
23
+ readonly ephemeralPublicKey: Uint8Array;
24
+ /** ML-KEM-768 ciphertext to include in envelope (1088 bytes). */
25
+ readonly kemCiphertext: Uint8Array;
26
+ }
27
+ /** Error codes for key agreement operations. Sub-codes give context. */
28
+ export type KeyAgreementError = 'KEYGEN_FAILED' | 'DERIVE_FAILED' | 'IMPORT_FAILED' | 'INVALID_KEY_LENGTH' | 'INVALID_KEY_LENGTH:EXPECTED_32' | 'KEM_ENCAPSULATE_FAILED' | 'KEM_DECAPSULATE_FAILED' | 'HKDF_FAILED';
29
+ /**
30
+ * Generate an ephemeral X25519 key pair for ECDH key agreement.
31
+ *
32
+ * Uses Web Crypto API to generate a fresh X25519 key pair.
33
+ * The key pair is ephemeral -- it should be used for a single
34
+ * key agreement and then discarded.
35
+ *
36
+ * @returns Result containing the ephemeral key pair or error.
37
+ */
38
+ export declare function generateEphemeralKeyPair(): Promise<Result<EphemeralKeyPair, KeyAgreementError>>;
39
+ /**
40
+ * Import a raw 32-byte X25519 public key into a CryptoKey.
41
+ *
42
+ * Used by the receiver to import the sender's ephemeral public
43
+ * key from the envelope for ECDH derivation.
44
+ *
45
+ * @param rawPublicKey - Raw 32-byte X25519 public key.
46
+ * @returns Result containing the imported CryptoKey or error.
47
+ */
48
+ export declare function importX25519PublicKey(rawPublicKey: Uint8Array): Promise<Result<CryptoKey, KeyAgreementError>>;
49
+ /**
50
+ * Derive a shared AES-256-GCM key via X25519 ECDH.
51
+ *
52
+ * Performs ECDH key agreement between a local private key and a
53
+ * remote public key, producing 256 bits of shared secret that
54
+ * are imported as an AES-256-GCM key.
55
+ *
56
+ * @param localPrivateKey - Local X25519 private key.
57
+ * @param remotePublicKey - Remote X25519 public key (CryptoKey).
58
+ * @returns Result containing the derived AES-256-GCM key or error.
59
+ */
60
+ export declare function deriveSharedKeyECDH(localPrivateKey: CryptoKey, remotePublicKey: CryptoKey): Promise<Result<CryptoKey, KeyAgreementError>>;
61
+ /**
62
+ * Perform sender-side ECDH key agreement.
63
+ *
64
+ * Generates an ephemeral X25519 key pair, derives a shared key
65
+ * with the recipient's static X25519 public key, and returns
66
+ * both the shared key and the ephemeral public key to include
67
+ * in the envelope.
68
+ *
69
+ * @param recipientX25519PubKey - Recipient's static X25519 public key.
70
+ * @returns Result containing the key agreement result or error.
71
+ */
72
+ export declare function senderKeyAgreement(recipientX25519PubKey: CryptoKey): Promise<Result<KeyAgreementResult, KeyAgreementError>>;
73
+ /**
74
+ * Perform receiver-side ECDH key agreement.
75
+ *
76
+ * Imports the sender's ephemeral public key from the envelope
77
+ * and derives the shared key using the receiver's static X25519
78
+ * private key.
79
+ *
80
+ * @param receiverPrivateKey - Receiver's static X25519 private key.
81
+ * @param senderEphemeralPubRaw - Sender's ephemeral public key (raw bytes).
82
+ * @returns Result containing the derived AES-256-GCM key or error.
83
+ */
84
+ export declare function receiverKeyAgreement(receiverPrivateKey: CryptoKey, senderEphemeralPubRaw: Uint8Array): Promise<Result<CryptoKey, KeyAgreementError>>;
85
+ /**
86
+ * Combine X25519 and ML-KEM shared secrets via HKDF-SHA256.
87
+ *
88
+ * Concatenates 32B X25519 + 32B ML-KEM shared secrets, runs HKDF
89
+ * with zero salt and 'xail-hybrid-kem-v2' info, outputs 256-bit AES key.
90
+ * Secure as long as either X25519 OR ML-KEM remains unbroken.
91
+ *
92
+ * @param x25519Shared - 32-byte raw X25519 ECDH shared bits.
93
+ * @param mlKemShared - 32-byte ML-KEM-768 shared secret.
94
+ * @returns AES-256-GCM CryptoKey derived from both secrets.
95
+ */
96
+ export declare function combineSharedSecrets(x25519Shared: Uint8Array, mlKemShared: Uint8Array): Promise<Result<CryptoKey, KeyAgreementError>>;
97
+ /**
98
+ * Perform sender-side hybrid key agreement (X25519 + ML-KEM-768).
99
+ *
100
+ * 1. Generate ephemeral X25519, ECDH → x25519SharedBits
101
+ * 2. ML-KEM-768 encapsulate → kemCiphertext + mlKemShared
102
+ * 3. HKDF(x25519Shared || mlKemShared) → AES-256-GCM key
103
+ *
104
+ * @param recipientX25519Pub - Recipient's static X25519 public key.
105
+ * @param recipientMlKemPub - Recipient's ML-KEM-768 public key (1184B).
106
+ * @returns Hybrid key agreement result with shared key, ephemeral pub, and KEM ciphertext.
107
+ */
108
+ export declare function senderHybridKeyAgreement(recipientX25519Pub: CryptoKey, recipientMlKemPub: Uint8Array): Promise<Result<HybridKeyAgreementResult, KeyAgreementError>>;
109
+ /**
110
+ * Perform receiver-side hybrid key agreement (X25519 + ML-KEM-768).
111
+ *
112
+ * 1. Import ephemeral X25519, ECDH → x25519SharedBits
113
+ * 2. ML-KEM-768 decapsulate → mlKemShared
114
+ * 3. HKDF(x25519Shared || mlKemShared) → same AES-256-GCM key
115
+ *
116
+ * @param x25519PrivateKey - Receiver's static X25519 private key.
117
+ * @param ephPubRaw - Sender's ephemeral X25519 public key (32B).
118
+ * @param kemCiphertext - ML-KEM-768 ciphertext from sender (1088B).
119
+ * @param mlKemSecretKey - Receiver's ML-KEM-768 secret key (2400B).
120
+ * @returns AES-256-GCM shared key or error.
121
+ */
122
+ export declare function receiverHybridKeyAgreement(x25519PrivateKey: CryptoKey, ephPubRaw: Uint8Array, kemCiphertext: Uint8Array, mlKemSecretKey: Uint8Array): Promise<Result<CryptoKey, KeyAgreementError>>;