@peers-app/peers-sdk 0.23.14 → 0.24.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 (80) hide show
  1. package/dist/contracts/index.d.ts +1 -0
  2. package/dist/contracts/index.js +4 -1
  3. package/dist/contracts/system/index.d.ts +2 -0
  4. package/dist/contracts/system/index.js +5 -1
  5. package/dist/contracts/system/invites-contract.d.ts +121 -0
  6. package/dist/contracts/system/invites-contract.js +150 -0
  7. package/dist/data/create-group.d.ts +24 -0
  8. package/dist/data/create-group.js +61 -0
  9. package/dist/data/group-secret.d.ts +10 -0
  10. package/dist/data/group-secret.js +26 -0
  11. package/dist/data/group-share.d.ts +0 -20
  12. package/dist/data/group-share.js +0 -35
  13. package/dist/data/index.d.ts +2 -0
  14. package/dist/data/index.js +2 -0
  15. package/dist/data/invites.d.ts +350 -0
  16. package/dist/data/invites.js +99 -0
  17. package/dist/data/users.js +4 -0
  18. package/dist/device-pairing/constants.d.ts +27 -9
  19. package/dist/device-pairing/constants.js +28 -10
  20. package/dist/device-pairing/cpace.d.ts +46 -0
  21. package/dist/device-pairing/cpace.js +173 -0
  22. package/dist/device-pairing/cpace.test.js +116 -0
  23. package/dist/device-pairing/crypto.d.ts +40 -15
  24. package/dist/device-pairing/crypto.js +74 -33
  25. package/dist/device-pairing/device-pairing.test.js +156 -119
  26. package/dist/device-pairing/index.d.ts +3 -1
  27. package/dist/device-pairing/index.js +3 -1
  28. package/dist/device-pairing/pairing-code.d.ts +27 -0
  29. package/dist/device-pairing/pairing-code.js +84 -0
  30. package/dist/device-pairing/pgp-word-list.d.ts +14 -0
  31. package/dist/device-pairing/pgp-word-list.js +531 -0
  32. package/dist/device-pairing/signaling.d.ts +17 -6
  33. package/dist/device-pairing/signaling.js +31 -8
  34. package/dist/device-pairing/transcript.d.ts +3 -3
  35. package/dist/device-pairing/transcript.js +6 -13
  36. package/dist/device-pairing/types.d.ts +870 -224
  37. package/dist/device-pairing/types.js +186 -108
  38. package/dist/index.d.ts +1 -2
  39. package/dist/index.js +1 -2
  40. package/dist/invites/data-box-schema.d.ts +15 -0
  41. package/dist/invites/data-box-schema.js +15 -0
  42. package/dist/invites/group-approval.d.ts +43 -0
  43. package/dist/invites/group-approval.js +155 -0
  44. package/dist/invites/group-approval.test.js +221 -0
  45. package/dist/invites/index.d.ts +5 -0
  46. package/dist/{group-invite → invites}/index.js +5 -3
  47. package/dist/invites/invite-epoch.d.ts +18 -0
  48. package/dist/invites/invite-epoch.js +35 -0
  49. package/dist/invites/invite-messages.d.ts +1354 -0
  50. package/dist/invites/invite-messages.js +145 -0
  51. package/dist/invites/invite-token.d.ts +334 -0
  52. package/dist/invites/invite-token.js +178 -0
  53. package/dist/invites/invite-token.test.d.ts +1 -0
  54. package/dist/invites/invite-token.test.js +123 -0
  55. package/dist/rpc-types.d.ts +5 -4
  56. package/dist/rpc-types.js +2 -1
  57. package/dist/system-ids.d.ts +22 -0
  58. package/dist/system-ids.js +23 -1
  59. package/package.json +1 -1
  60. package/dist/device-pairing/invitation.d.ts +0 -13
  61. package/dist/device-pairing/invitation.js +0 -85
  62. package/dist/group-invite/group-invite.d.ts +0 -53
  63. package/dist/group-invite/group-invite.js +0 -231
  64. package/dist/group-invite/group-invite.pvars.d.ts +0 -94
  65. package/dist/group-invite/group-invite.pvars.js +0 -139
  66. package/dist/group-invite/group-invite.types.d.ts +0 -124
  67. package/dist/group-invite/group-invite.types.js +0 -8
  68. package/dist/group-invite/index.d.ts +0 -3
  69. package/dist/user-connect/connection-code.d.ts +0 -67
  70. package/dist/user-connect/connection-code.js +0 -176
  71. package/dist/user-connect/connection-code.test.js +0 -213
  72. package/dist/user-connect/index.d.ts +0 -3
  73. package/dist/user-connect/index.js +0 -19
  74. package/dist/user-connect/user-connect.pvars.d.ts +0 -20
  75. package/dist/user-connect/user-connect.pvars.js +0 -63
  76. package/dist/user-connect/user-connect.pvars.test.js +0 -46
  77. package/dist/user-connect/user-connect.types.d.ts +0 -94
  78. package/dist/user-connect/user-connect.types.js +0 -68
  79. /package/dist/{user-connect/connection-code.test.d.ts → device-pairing/cpace.test.d.ts} +0 -0
  80. /package/dist/{user-connect/user-connect.pvars.test.d.ts → invites/group-approval.test.d.ts} +0 -0
@@ -1,213 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const connection_code_1 = require("./connection-code");
4
- describe("connection-code", () => {
5
- describe("generateConnectionCode", () => {
6
- it("should generate a code with 12 characters", () => {
7
- const result = (0, connection_code_1.generateConnectionCode)();
8
- expect(result.code).toHaveLength(12);
9
- });
10
- it("should have alias of 4 characters", () => {
11
- const result = (0, connection_code_1.generateConnectionCode)();
12
- expect(result.alias).toHaveLength(4);
13
- });
14
- it("should have secret of 8 characters", () => {
15
- const result = (0, connection_code_1.generateConnectionCode)();
16
- expect(result.secret).toHaveLength(8);
17
- });
18
- it("should have code = alias + secret", () => {
19
- const result = (0, connection_code_1.generateConnectionCode)();
20
- expect(result.code).toBe(result.alias + result.secret);
21
- });
22
- it("should only contain valid Crockford Base32 characters", () => {
23
- const validChars = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
24
- for (let i = 0; i < 10; i++) {
25
- const result = (0, connection_code_1.generateConnectionCode)();
26
- for (const char of result.code) {
27
- expect(validChars).toContain(char);
28
- }
29
- }
30
- });
31
- it("should generate different codes each time", () => {
32
- const codes = new Set();
33
- for (let i = 0; i < 100; i++) {
34
- codes.add((0, connection_code_1.generateConnectionCode)().code);
35
- }
36
- expect(codes.size).toBe(100);
37
- });
38
- });
39
- describe("formatConnectionCode", () => {
40
- it("should format a 12-character code as XXXX-YYYY-ZZZZ", () => {
41
- expect((0, connection_code_1.formatConnectionCode)("ABCD1234EFGH")).toBe("ABCD-1234-EFGH");
42
- });
43
- it("should handle lowercase input", () => {
44
- expect((0, connection_code_1.formatConnectionCode)("abcd1234efgh")).toBe("ABCD-1234-EFGH");
45
- });
46
- it("should handle input with existing dashes", () => {
47
- expect((0, connection_code_1.formatConnectionCode)("ABCD-1234-EFGH")).toBe("ABCD-1234-EFGH");
48
- });
49
- it("should handle input with spaces", () => {
50
- expect((0, connection_code_1.formatConnectionCode)("ABCD 1234 EFGH")).toBe("ABCD-1234-EFGH");
51
- });
52
- it("should throw for codes that are too short", () => {
53
- expect(() => (0, connection_code_1.formatConnectionCode)("ABCD1234")).toThrow("must be 12 characters");
54
- });
55
- it("should throw for codes that are too long", () => {
56
- expect(() => (0, connection_code_1.formatConnectionCode)("ABCD1234EFGH5678")).toThrow("must be 12 characters");
57
- });
58
- });
59
- describe("parseConnectionCode", () => {
60
- it("should parse a plain 12-character code", () => {
61
- const result = (0, connection_code_1.parseConnectionCode)("ABCD12345678");
62
- expect(result.alias).toBe("ABCD");
63
- expect(result.secret).toBe("12345678");
64
- });
65
- it("should parse a formatted code with dashes", () => {
66
- const result = (0, connection_code_1.parseConnectionCode)("ABCD-1234-5678");
67
- expect(result.alias).toBe("ABCD");
68
- expect(result.secret).toBe("12345678");
69
- });
70
- it("should handle lowercase input", () => {
71
- const result = (0, connection_code_1.parseConnectionCode)("abcd-1234-5678");
72
- expect(result.alias).toBe("ABCD");
73
- expect(result.secret).toBe("12345678");
74
- });
75
- it("should handle mixed case and spaces", () => {
76
- const result = (0, connection_code_1.parseConnectionCode)("AbCd 1234 5678");
77
- expect(result.alias).toBe("ABCD");
78
- expect(result.secret).toBe("12345678");
79
- });
80
- it("should throw for invalid length", () => {
81
- expect(() => (0, connection_code_1.parseConnectionCode)("ABCD1234")).toThrow("must be 12 characters");
82
- });
83
- it("should be the inverse of formatConnectionCode", () => {
84
- const original = (0, connection_code_1.generateConnectionCode)();
85
- const formatted = (0, connection_code_1.formatConnectionCode)(original.code);
86
- const parsed = (0, connection_code_1.parseConnectionCode)(formatted);
87
- expect(parsed.alias).toBe(original.alias);
88
- expect(parsed.secret).toBe(original.secret);
89
- });
90
- });
91
- describe("encryptWithSecret and decryptWithSecret", () => {
92
- it("should round-trip a simple string", () => {
93
- const secret = "ABCD1234";
94
- const data = "Hello, World!";
95
- const encrypted = (0, connection_code_1.encryptWithSecret)(data, secret);
96
- const decrypted = (0, connection_code_1.decryptWithSecret)(encrypted, secret);
97
- expect(decrypted).toBe(data);
98
- });
99
- it("should round-trip an object", () => {
100
- const secret = "ZYXW9876";
101
- const data = { userId: "user123", name: "Test User", count: 42 };
102
- const encrypted = (0, connection_code_1.encryptWithSecret)(data, secret);
103
- const decrypted = (0, connection_code_1.decryptWithSecret)(encrypted, secret);
104
- expect(decrypted).toEqual(data);
105
- });
106
- it("should round-trip user connect info", () => {
107
- const secret = "TESTCODE";
108
- const userInfo = {
109
- userId: "user123",
110
- publicKey: "pk_abc123",
111
- publicBoxKey: "pbk_xyz789",
112
- deviceId: "device456",
113
- };
114
- const encrypted = (0, connection_code_1.encryptWithSecret)(userInfo, secret);
115
- const decrypted = (0, connection_code_1.decryptWithSecret)(encrypted, secret);
116
- expect(decrypted).toEqual(userInfo);
117
- });
118
- it("should produce different ciphertext for same data (due to random nonce)", () => {
119
- const secret = "ABCD1234";
120
- const data = "Same data";
121
- const encrypted1 = (0, connection_code_1.encryptWithSecret)(data, secret);
122
- const encrypted2 = (0, connection_code_1.encryptWithSecret)(data, secret);
123
- expect(encrypted1).not.toBe(encrypted2);
124
- });
125
- it("should fail decryption with wrong secret", () => {
126
- const data = "Secret message";
127
- const encrypted = (0, connection_code_1.encryptWithSecret)(data, "CORRECT1");
128
- expect(() => (0, connection_code_1.decryptWithSecret)(encrypted, "WRONGKEY")).toThrow("Decryption failed");
129
- });
130
- it("should fail decryption with corrupted data", () => {
131
- const secret = "ABCD1234";
132
- const data = "Hello";
133
- const encrypted = (0, connection_code_1.encryptWithSecret)(data, secret);
134
- const corrupted = `${encrypted.slice(0, -5)}XXXXX`;
135
- expect(() => (0, connection_code_1.decryptWithSecret)(corrupted, secret)).toThrow();
136
- });
137
- });
138
- describe("generateConfirmationHash", () => {
139
- const userA = {
140
- userId: "userA123",
141
- publicKey: "pkA",
142
- publicBoxKey: "pbkA",
143
- deviceId: "deviceA",
144
- };
145
- const userB = {
146
- userId: "userB456",
147
- publicKey: "pkB",
148
- publicBoxKey: "pbkB",
149
- deviceId: "deviceB",
150
- };
151
- it("should return a 4-character hash", () => {
152
- const hash = (0, connection_code_1.generateConfirmationHash)(userA, userB);
153
- expect(hash).toHaveLength(4);
154
- });
155
- it("should only contain valid Crockford Base32 characters", () => {
156
- const validChars = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
157
- const hash = (0, connection_code_1.generateConfirmationHash)(userA, userB);
158
- for (const char of hash) {
159
- expect(validChars).toContain(char);
160
- }
161
- });
162
- it("should produce same hash regardless of argument order", () => {
163
- const hashAB = (0, connection_code_1.generateConfirmationHash)(userA, userB);
164
- const hashBA = (0, connection_code_1.generateConfirmationHash)(userB, userA);
165
- expect(hashAB).toBe(hashBA);
166
- });
167
- it("should produce different hash for different users", () => {
168
- const userC = {
169
- userId: "userC789",
170
- publicKey: "pkC",
171
- publicBoxKey: "pbkC",
172
- deviceId: "deviceC",
173
- };
174
- const hashAB = (0, connection_code_1.generateConfirmationHash)(userA, userB);
175
- const hashAC = (0, connection_code_1.generateConfirmationHash)(userA, userC);
176
- expect(hashAB).not.toBe(hashAC);
177
- });
178
- it("should be deterministic", () => {
179
- const hash1 = (0, connection_code_1.generateConfirmationHash)(userA, userB);
180
- const hash2 = (0, connection_code_1.generateConfirmationHash)(userA, userB);
181
- expect(hash1).toBe(hash2);
182
- });
183
- });
184
- describe("isValidConnectionCode", () => {
185
- it("should return true for valid 12-character codes", () => {
186
- expect((0, connection_code_1.isValidConnectionCode)("ABCD1234EFGH")).toBe(true);
187
- });
188
- it("should return true for codes with dashes", () => {
189
- expect((0, connection_code_1.isValidConnectionCode)("ABCD-1234-EFGH")).toBe(true);
190
- });
191
- it("should return true for lowercase codes", () => {
192
- expect((0, connection_code_1.isValidConnectionCode)("abcd1234efgh")).toBe(true);
193
- });
194
- it("should return true for generated codes", () => {
195
- const code = (0, connection_code_1.generateConnectionCode)();
196
- expect((0, connection_code_1.isValidConnectionCode)(code.code)).toBe(true);
197
- expect((0, connection_code_1.isValidConnectionCode)((0, connection_code_1.formatConnectionCode)(code.code))).toBe(true);
198
- });
199
- it("should return false for codes that are too short", () => {
200
- expect((0, connection_code_1.isValidConnectionCode)("ABCD1234")).toBe(false);
201
- });
202
- it("should return false for codes that are too long", () => {
203
- expect((0, connection_code_1.isValidConnectionCode)("ABCD1234EFGH5678")).toBe(false);
204
- });
205
- it("should return false for codes with invalid characters", () => {
206
- // I, L, O, U are not in Crockford Base32
207
- expect((0, connection_code_1.isValidConnectionCode)("ABCDILOU1234")).toBe(false);
208
- });
209
- it("should return false for empty string", () => {
210
- expect((0, connection_code_1.isValidConnectionCode)("")).toBe(false);
211
- });
212
- });
213
- });
@@ -1,3 +0,0 @@
1
- export * from "./connection-code";
2
- export * from "./user-connect.pvars";
3
- export * from "./user-connect.types";
@@ -1,19 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./connection-code"), exports);
18
- __exportStar(require("./user-connect.pvars"), exports);
19
- __exportStar(require("./user-connect.types"), exports);
@@ -1,20 +0,0 @@
1
- import { type UserConnectStatus } from "./user-connect.types";
2
- /**
3
- * Shared lifetime for connection codes, aliases, invite intents, and UI countdowns.
4
- * Ten minutes from creation or capture.
5
- */
6
- export declare const USER_CONNECT_TTL_MS = 600000;
7
- /**
8
- * Current structured status of the local user-connect ceremony.
9
- * Prefer reading through {@link normalizeUserConnectStatus} when consuming
10
- * values that may have been persisted before the structured type existed.
11
- */
12
- export declare const userConnectStatus: import("../data/persistent-vars").PersistentVar<UserConnectStatus>;
13
- /**
14
- * Active offer connection code (12 Crockford chars). Cleared after {@link USER_CONNECT_TTL_MS}.
15
- */
16
- export declare const userConnectCodeOffer: import("../data/persistent-vars").PersistentVar<string>;
17
- /**
18
- * Active answer connection code (12 Crockford chars). Cleared after {@link USER_CONNECT_TTL_MS}.
19
- */
20
- export declare const userConnectCodeAnswer: import("../data/persistent-vars").PersistentVar<string>;
@@ -1,63 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.userConnectCodeAnswer = exports.userConnectCodeOffer = exports.userConnectStatus = exports.USER_CONNECT_TTL_MS = void 0;
4
- const persistent_vars_1 = require("../data/persistent-vars");
5
- const user_connect_types_1 = require("./user-connect.types");
6
- /**
7
- * Shared lifetime for connection codes, aliases, invite intents, and UI countdowns.
8
- * Ten minutes from creation or capture.
9
- */
10
- exports.USER_CONNECT_TTL_MS = 600_000;
11
- /**
12
- * Current structured status of the local user-connect ceremony.
13
- * Prefer reading through {@link normalizeUserConnectStatus} when consuming
14
- * values that may have been persisted before the structured type existed.
15
- */
16
- exports.userConnectStatus = (0, persistent_vars_1.deviceVar)("userConnectStatus", {
17
- defaultValue: user_connect_types_1.USER_CONNECT_IDLE_STATUS,
18
- });
19
- /**
20
- * Active offer connection code (12 Crockford chars). Cleared after {@link USER_CONNECT_TTL_MS}.
21
- */
22
- exports.userConnectCodeOffer = (0, persistent_vars_1.deviceVar)("userConnectCodeOffer", { defaultValue: "" });
23
- exports.userConnectCodeOffer.loadingPromise.then(() => {
24
- let codeTimeout;
25
- if ((0, exports.userConnectCodeOffer)()) {
26
- (0, exports.userConnectCodeOffer)("");
27
- }
28
- (0, exports.userConnectStatus)(user_connect_types_1.USER_CONNECT_IDLE_STATUS);
29
- exports.userConnectCodeOffer.subscribe(() => {
30
- (0, exports.userConnectStatus)(user_connect_types_1.USER_CONNECT_IDLE_STATUS);
31
- clearTimeout(codeTimeout);
32
- if ((0, exports.userConnectCodeOffer)()) {
33
- codeTimeout = setTimeout(() => {
34
- (0, exports.userConnectCodeOffer)("");
35
- }, exports.USER_CONNECT_TTL_MS);
36
- }
37
- });
38
- });
39
- /**
40
- * Active answer connection code (12 Crockford chars). Cleared after {@link USER_CONNECT_TTL_MS}.
41
- */
42
- exports.userConnectCodeAnswer = (0, persistent_vars_1.deviceVar)("userConnectCodeAnswer", {
43
- defaultValue: "",
44
- });
45
- exports.userConnectCodeAnswer.loadingPromise.then(() => {
46
- let codeTimeout;
47
- if ((0, exports.userConnectCodeAnswer)()) {
48
- (0, exports.userConnectCodeAnswer)("");
49
- }
50
- (0, exports.userConnectStatus)(user_connect_types_1.USER_CONNECT_IDLE_STATUS);
51
- exports.userConnectCodeAnswer.subscribe(() => {
52
- (0, exports.userConnectStatus)(user_connect_types_1.USER_CONNECT_IDLE_STATUS);
53
- clearTimeout(codeTimeout);
54
- if ((0, exports.userConnectCodeAnswer)()) {
55
- codeTimeout = setTimeout(() => {
56
- (0, exports.userConnectCodeAnswer)("");
57
- }, exports.USER_CONNECT_TTL_MS);
58
- }
59
- });
60
- });
61
- exports.userConnectStatus.loadingPromise.then(() => {
62
- (0, exports.userConnectStatus)(user_connect_types_1.USER_CONNECT_IDLE_STATUS);
63
- });
@@ -1,46 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const user_connect_types_1 = require("./user-connect.types");
4
- describe("normalizeUserConnectStatus", () => {
5
- it("clears legacy string and malformed persisted statuses", () => {
6
- expect((0, user_connect_types_1.normalizeUserConnectStatus)("")).toEqual(user_connect_types_1.USER_CONNECT_IDLE_STATUS);
7
- expect((0, user_connect_types_1.normalizeUserConnectStatus)("Error: old error")).toEqual(user_connect_types_1.USER_CONNECT_IDLE_STATUS);
8
- expect((0, user_connect_types_1.normalizeUserConnectStatus)("old-remote-user-id")).toEqual(user_connect_types_1.USER_CONNECT_IDLE_STATUS);
9
- expect((0, user_connect_types_1.normalizeUserConnectStatus)(null)).toEqual(user_connect_types_1.USER_CONNECT_IDLE_STATUS);
10
- expect((0, user_connect_types_1.normalizeUserConnectStatus)({ kind: "connected" })).toEqual(user_connect_types_1.USER_CONNECT_IDLE_STATUS);
11
- expect((0, user_connect_types_1.normalizeUserConnectStatus)({ kind: "error", code: "unknown" })).toEqual(user_connect_types_1.USER_CONNECT_IDLE_STATUS);
12
- });
13
- it("preserves valid structured statuses", () => {
14
- expect((0, user_connect_types_1.normalizeUserConnectStatus)({ kind: "offer-ready" })).toEqual({
15
- kind: "offer-ready",
16
- });
17
- expect((0, user_connect_types_1.normalizeUserConnectStatus)({ kind: "connecting", attempt: 3 })).toEqual({
18
- kind: "connecting",
19
- attempt: 3,
20
- });
21
- expect((0, user_connect_types_1.normalizeUserConnectStatus)({
22
- kind: "connected",
23
- remoteUserId: "remote-user",
24
- remoteDeviceId: "remote-device",
25
- })).toEqual({
26
- kind: "connected",
27
- remoteUserId: "remote-user",
28
- remoteDeviceId: "remote-device",
29
- });
30
- expect((0, user_connect_types_1.normalizeUserConnectStatus)({
31
- kind: "error",
32
- code: "remote-not-waiting",
33
- detail: "diagnostic",
34
- })).toEqual({
35
- kind: "error",
36
- code: "remote-not-waiting",
37
- detail: "diagnostic",
38
- });
39
- });
40
- it("normalizes invalid connection attempt numbers to the first attempt", () => {
41
- expect((0, user_connect_types_1.normalizeUserConnectStatus)({ kind: "connecting", attempt: 0 })).toEqual({
42
- kind: "connecting",
43
- attempt: 1,
44
- });
45
- });
46
- });
@@ -1,94 +0,0 @@
1
- /**
2
- * Types for the user connection flow.
3
- *
4
- * This flow allows two users to securely exchange user information
5
- * using a 12-character code (4-char rendezvous alias + 8-char shared secret).
6
- */
7
- /**
8
- * Stable protocol error codes for the user-connect exchange.
9
- * The UI owns presentation text; the device layer reports these codes.
10
- */
11
- export type UserConnectErrorCode = "invalid-code" | "no-route" | "not-found-or-expired" | "remote-not-waiting" | "canceled" | "protocol-error";
12
- /**
13
- * Discriminated status published by the device layer during a user-connect ceremony.
14
- */
15
- export type UserConnectStatus = {
16
- kind: "idle";
17
- } | {
18
- kind: "offer-registering";
19
- } | {
20
- kind: "offer-ready";
21
- } | {
22
- kind: "connecting";
23
- attempt: number;
24
- } | {
25
- kind: "connected";
26
- remoteUserId: string;
27
- remoteDeviceId: string;
28
- } | {
29
- kind: "error";
30
- code: UserConnectErrorCode;
31
- detail?: string;
32
- };
33
- /** Default idle status for a quiet connection ceremony. */
34
- export declare const USER_CONNECT_IDLE_STATUS: UserConnectStatus;
35
- /**
36
- * Normalize a persisted or in-memory status value to the structured shape.
37
- * Clears legacy string statuses (`""`, `"Error: …"`, bare user IDs) to idle so
38
- * callers never treat stale strings as protocol facts.
39
- * @param value Raw pvar value
40
- * @returns A valid {@link UserConnectStatus}
41
- */
42
- export declare function normalizeUserConnectStatus(value: unknown): UserConnectStatus;
43
- /**
44
- * User information exchanged during the connection flow.
45
- */
46
- export interface IUserConnectInfo {
47
- userId: string;
48
- name?: string;
49
- publicKey: string;
50
- publicBoxKey: string;
51
- deviceId: string;
52
- }
53
- /**
54
- * Message sent by the responder to initiate the connection.
55
- * The payload is encrypted with the shared secret from the connection code.
56
- */
57
- export interface IUserConnectRequest {
58
- type: "user-connect-request";
59
- /** User info encrypted with the shared secret */
60
- encryptedUserInfo: string;
61
- /** The responder's deviceId so the initiator can respond directly */
62
- responseDeviceId: string;
63
- }
64
- /**
65
- * Message sent by the initiator in response to a connection request.
66
- * The payload is encrypted with the shared secret.
67
- */
68
- export interface IUserConnectResponse {
69
- type: "user-connect-response";
70
- /** User info encrypted with the shared secret */
71
- encryptedUserInfo: string;
72
- }
73
- /**
74
- * Message broadcast to register a short-lived device alias.
75
- * Other devices store this mapping for routing purposes.
76
- */
77
- export interface IDeviceAliasMessage {
78
- type: "device-alias";
79
- /** The short alias (4 chars Crockford Base32) */
80
- alias: string;
81
- /** The actual deviceId this alias maps to */
82
- deviceId: string;
83
- /** TTL in milliseconds (typically 10 minutes) */
84
- ttlMs: number;
85
- }
86
- /**
87
- * Result of a successful user connection.
88
- */
89
- export interface IUserConnectResult {
90
- /** The remote user's information */
91
- remoteUser: IUserConnectInfo;
92
- /** Confirmation hash (first 4 chars) for visual verification */
93
- confirmationHash: string;
94
- }
@@ -1,68 +0,0 @@
1
- "use strict";
2
- /**
3
- * Types for the user connection flow.
4
- *
5
- * This flow allows two users to securely exchange user information
6
- * using a 12-character code (4-char rendezvous alias + 8-char shared secret).
7
- */
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.USER_CONNECT_IDLE_STATUS = void 0;
10
- exports.normalizeUserConnectStatus = normalizeUserConnectStatus;
11
- /** Default idle status for a quiet connection ceremony. */
12
- exports.USER_CONNECT_IDLE_STATUS = { kind: "idle" };
13
- /**
14
- * Normalize a persisted or in-memory status value to the structured shape.
15
- * Clears legacy string statuses (`""`, `"Error: …"`, bare user IDs) to idle so
16
- * callers never treat stale strings as protocol facts.
17
- * @param value Raw pvar value
18
- * @returns A valid {@link UserConnectStatus}
19
- */
20
- function normalizeUserConnectStatus(value) {
21
- if (!value || typeof value !== "object" || Array.isArray(value)) {
22
- return exports.USER_CONNECT_IDLE_STATUS;
23
- }
24
- const candidate = value;
25
- switch (candidate.kind) {
26
- case "idle":
27
- case "offer-registering":
28
- case "offer-ready":
29
- return { kind: candidate.kind };
30
- case "connecting": {
31
- const attempt = value.attempt;
32
- return {
33
- kind: "connecting",
34
- attempt: typeof attempt === "number" && attempt > 0 ? attempt : 1,
35
- };
36
- }
37
- case "connected": {
38
- const remoteUserId = value.remoteUserId;
39
- const remoteDeviceId = value.remoteDeviceId;
40
- if (typeof remoteUserId === "string" &&
41
- remoteUserId.length > 0 &&
42
- typeof remoteDeviceId === "string" &&
43
- remoteDeviceId.length > 0) {
44
- return { kind: "connected", remoteUserId, remoteDeviceId };
45
- }
46
- return exports.USER_CONNECT_IDLE_STATUS;
47
- }
48
- case "error": {
49
- const code = value.code;
50
- const detail = value.detail;
51
- if (code === "invalid-code" ||
52
- code === "no-route" ||
53
- code === "not-found-or-expired" ||
54
- code === "remote-not-waiting" ||
55
- code === "canceled" ||
56
- code === "protocol-error") {
57
- return {
58
- kind: "error",
59
- code,
60
- detail: typeof detail === "string" ? detail : undefined,
61
- };
62
- }
63
- return exports.USER_CONNECT_IDLE_STATUS;
64
- }
65
- default:
66
- return exports.USER_CONNECT_IDLE_STATUS;
67
- }
68
- }