@peers-app/peers-sdk 0.23.13 → 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 (82) 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/dist/types/peer-device.d.ts +15 -1
  60. package/dist/types/peer-device.js +15 -1
  61. package/package.json +1 -1
  62. package/dist/device-pairing/invitation.d.ts +0 -13
  63. package/dist/device-pairing/invitation.js +0 -85
  64. package/dist/group-invite/group-invite.d.ts +0 -53
  65. package/dist/group-invite/group-invite.js +0 -231
  66. package/dist/group-invite/group-invite.pvars.d.ts +0 -94
  67. package/dist/group-invite/group-invite.pvars.js +0 -139
  68. package/dist/group-invite/group-invite.types.d.ts +0 -124
  69. package/dist/group-invite/group-invite.types.js +0 -8
  70. package/dist/group-invite/index.d.ts +0 -3
  71. package/dist/user-connect/connection-code.d.ts +0 -67
  72. package/dist/user-connect/connection-code.js +0 -176
  73. package/dist/user-connect/connection-code.test.js +0 -213
  74. package/dist/user-connect/index.d.ts +0 -3
  75. package/dist/user-connect/index.js +0 -19
  76. package/dist/user-connect/user-connect.pvars.d.ts +0 -20
  77. package/dist/user-connect/user-connect.pvars.js +0 -63
  78. package/dist/user-connect/user-connect.pvars.test.js +0 -46
  79. package/dist/user-connect/user-connect.types.d.ts +0 -94
  80. package/dist/user-connect/user-connect.types.js +0 -68
  81. /package/dist/{user-connect/connection-code.test.d.ts → device-pairing/cpace.test.d.ts} +0 -0
  82. /package/dist/{user-connect/user-connect.pvars.test.d.ts → invites/group-approval.test.d.ts} +0 -0
@@ -1,231 +0,0 @@
1
- "use strict";
2
- /**
3
- * Utilities for group invitation flow.
4
- *
5
- * Uses a simple password that users can edit or customize.
6
- * The password is hashed to create an alias for network discovery.
7
- */
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.generateInvitePassword = generateInvitePassword;
10
- exports.deriveAliasFromPassword = deriveAliasFromPassword;
11
- exports.encryptWithPassword = encryptWithPassword;
12
- exports.decryptWithPassword = decryptWithPassword;
13
- exports.isValidInvitePassword = isValidInvitePassword;
14
- exports.generateRequestId = generateRequestId;
15
- const sha2_1 = require("@noble/hashes/sha2");
16
- const nacl = require("tweetnacl");
17
- const tx_encoding_1 = require("../device/tx-encoding");
18
- const keys_1 = require("../keys");
19
- /**
20
- * Word list for generating memorable passphrases.
21
- * Using common, easy-to-spell words.
22
- */
23
- const WORD_LIST = [
24
- "apple",
25
- "banana",
26
- "cherry",
27
- "date",
28
- "elder",
29
- "fig",
30
- "grape",
31
- "honey",
32
- "iris",
33
- "jade",
34
- "kiwi",
35
- "lemon",
36
- "mango",
37
- "nectar",
38
- "olive",
39
- "peach",
40
- "quince",
41
- "rose",
42
- "sugar",
43
- "tulip",
44
- "umber",
45
- "violet",
46
- "willow",
47
- "yarrow",
48
- "zebra",
49
- "amber",
50
- "blaze",
51
- "coral",
52
- "dusk",
53
- "ember",
54
- "frost",
55
- "glow",
56
- "haze",
57
- "ivory",
58
- "jewel",
59
- "karma",
60
- "lunar",
61
- "maple",
62
- "nova",
63
- "opal",
64
- "prism",
65
- "quest",
66
- "river",
67
- "storm",
68
- "terra",
69
- "ultra",
70
- "vivid",
71
- "winter",
72
- "azure",
73
- "brave",
74
- "calm",
75
- "dawn",
76
- "echo",
77
- "fern",
78
- "gentle",
79
- "harbor",
80
- "island",
81
- "jungle",
82
- "kindle",
83
- "light",
84
- "meadow",
85
- "night",
86
- "ocean",
87
- "piano",
88
- "quiet",
89
- "rain",
90
- "silk",
91
- "tide",
92
- "unity",
93
- "velvet",
94
- "wave",
95
- "zenith",
96
- "arch",
97
- "beam",
98
- "cloud",
99
- "drift",
100
- "earth",
101
- "flame",
102
- "green",
103
- "hill",
104
- "ink",
105
- "jazz",
106
- "keen",
107
- "lake",
108
- "moon",
109
- "nest",
110
- "oak",
111
- "peak",
112
- "ruby",
113
- "sand",
114
- "tree",
115
- "vine",
116
- "wind",
117
- "year",
118
- "zone",
119
- "bold",
120
- "crisp",
121
- "deep",
122
- "fair",
123
- "glad",
124
- "warm",
125
- "pure",
126
- "safe",
127
- "true",
128
- ];
129
- /**
130
- * Generate a random memorable passphrase.
131
- * Format: "word-word-word-word" (4 words separated by dashes)
132
- *
133
- * @param wordCount Number of words to use (default 4)
134
- * @returns A memorable passphrase
135
- */
136
- function generateInvitePassword(wordCount = 4) {
137
- const words = [];
138
- const bytes = nacl.randomBytes(wordCount);
139
- for (let i = 0; i < wordCount; i++) {
140
- const index = bytes[i] % WORD_LIST.length;
141
- words.push(WORD_LIST[index]);
142
- }
143
- return words.join("-");
144
- }
145
- /**
146
- * Derive a network alias from a password.
147
- * Uses SHA-256 hash, takes first 8 characters as hex.
148
- *
149
- * @param password The password to derive from
150
- * @returns An 8-character hex alias
151
- */
152
- function deriveAliasFromPassword(password) {
153
- const normalized = password.toLowerCase().trim();
154
- const hash = (0, sha2_1.sha256)(new TextEncoder().encode(normalized));
155
- // Convert first 4 bytes to 8-char hex string
156
- const hexChars = Array.from(hash.slice(0, 4))
157
- .map((b) => b.toString(16).padStart(2, "0"))
158
- .join("")
159
- .toUpperCase();
160
- return hexChars;
161
- }
162
- /**
163
- * Derive a 32-byte encryption key from the password.
164
- * Uses SHA-256 of the password.
165
- *
166
- * @param password The password to derive key from
167
- * @returns A 32-byte encryption key
168
- */
169
- function deriveKeyFromPassword(password) {
170
- const normalized = password.toLowerCase().trim();
171
- return (0, sha2_1.sha256)(new TextEncoder().encode(normalized));
172
- }
173
- /**
174
- * Encrypt data using the invite password.
175
- * Uses NaCl secretbox with a key derived from the password.
176
- *
177
- * @param data Data to encrypt
178
- * @param password The invitation password
179
- * @returns Base64-encoded encrypted data with nonce
180
- */
181
- function encryptWithPassword(data, password) {
182
- const key = deriveKeyFromPassword(password);
183
- const nonce = nacl.randomBytes(24);
184
- const dataBytes = (0, tx_encoding_1.txEncode)(data);
185
- const encrypted = nacl.secretbox(dataBytes, nonce, key);
186
- // Combine nonce + encrypted data
187
- const combined = new Uint8Array(nonce.length + encrypted.length);
188
- combined.set(nonce);
189
- combined.set(encrypted, nonce.length);
190
- return (0, keys_1.encodeBase64)(combined);
191
- }
192
- /**
193
- * Decrypt data using the invite password.
194
- *
195
- * @param encrypted Base64-encoded encrypted data
196
- * @param password The invitation password
197
- * @returns Decrypted data
198
- */
199
- function decryptWithPassword(encrypted, password) {
200
- const key = deriveKeyFromPassword(password);
201
- const combined = (0, keys_1.decodeBase64)(encrypted);
202
- const nonce = combined.slice(0, 24);
203
- const ciphertext = combined.slice(24);
204
- const decrypted = nacl.secretbox.open(ciphertext, nonce, key);
205
- if (!decrypted) {
206
- throw new Error("Decryption failed - invalid password or corrupted data");
207
- }
208
- return (0, tx_encoding_1.txDecode)(decrypted);
209
- }
210
- /**
211
- * Validate a password format.
212
- * Passwords should be at least 4 characters.
213
- *
214
- * @param password Password to validate
215
- * @returns true if valid
216
- */
217
- function isValidInvitePassword(password) {
218
- const trimmed = password.trim();
219
- return trimmed.length >= 4;
220
- }
221
- /**
222
- * Generate a unique request ID for tracking join requests.
223
- *
224
- * @returns A unique request ID
225
- */
226
- function generateRequestId() {
227
- const bytes = nacl.randomBytes(8);
228
- return Array.from(bytes)
229
- .map((b) => b.toString(16).padStart(2, "0"))
230
- .join("");
231
- }
@@ -1,94 +0,0 @@
1
- /**
2
- * Persistent variables for group invitation state.
3
- *
4
- * These device-level variables track:
5
- * - Active invitation listeners (admin side)
6
- * - Pending join requests (admin side)
7
- * - Status messages for UI feedback
8
- * - Action triggers (UI sets these, device layer reacts)
9
- */
10
- import type { GroupMemberRole } from "../data/group-member-roles";
11
- import type { IGroupInviteListener, IGroupInviteListenerInfo, IGroupJoinRequest, IGroupJoinResult } from "./group-invite.types";
12
- /**
13
- * Active group invitation listeners.
14
- * Key is groupId, value contains the password and alias being listened for.
15
- *
16
- * Used by admins who are waiting for join requests.
17
- */
18
- export declare const groupInviteListeners: import("../data/persistent-vars").PersistentVar<Record<string, IGroupInviteListener>>;
19
- /**
20
- * Pending join requests that need admin approval.
21
- * Array of requests waiting to be approved or denied.
22
- *
23
- * These are shown to the admin in the group details UI.
24
- */
25
- export declare const groupInviteRequests: import("../data/persistent-vars").PersistentVar<IGroupJoinRequest[]>;
26
- /**
27
- * Status message for the group invite UI (admin side).
28
- * Used to show success/error messages to the user.
29
- */
30
- export declare const groupInviteStatus: import("../data/persistent-vars").PersistentVar<string>;
31
- /**
32
- * Status message for the join group UI (joiner side).
33
- * Used to show discovery/join status to the user.
34
- */
35
- export declare const groupJoinStatus: import("../data/persistent-vars").PersistentVar<string>;
36
- /**
37
- * Results from discovering group listeners.
38
- * Updated by the device layer after discovery completes.
39
- */
40
- export declare const groupInviteDiscoveryResult: import("../data/persistent-vars").PersistentVar<IGroupInviteListenerInfo[]>;
41
- /**
42
- * Result of joining a group.
43
- * Updated by the device layer after join completes.
44
- */
45
- export declare const groupInviteJoinResult: import("../data/persistent-vars").PersistentVar<IGroupJoinResult | null>;
46
- /**
47
- * Responses to join requests, keyed by requestId.
48
- * Written by processJoinRequest, read by handleJoinRequest.
49
- * Entries are cleaned up after being read.
50
- */
51
- export declare const groupInviteResponses: import("../data/persistent-vars").PersistentVar<Record<string, {
52
- statusCode: number;
53
- payload: string;
54
- }>>;
55
- /**
56
- * Trigger to start listening for invitations.
57
- * Set by UI: { groupId, password }
58
- * Device layer clears after processing.
59
- */
60
- export declare const groupInviteStartListening: import("../data/persistent-vars").PersistentVar<{
61
- groupId: string;
62
- password: string;
63
- } | null>;
64
- /**
65
- * Trigger to stop listening for invitations.
66
- * Set by UI: groupId
67
- * Device layer clears after processing.
68
- */
69
- export declare const groupInviteStopListening: import("../data/persistent-vars").PersistentVar<string | null>;
70
- /**
71
- * Trigger to discover groups with a password.
72
- * Set by UI: password
73
- * Device layer updates groupInviteDiscoveryResult and clears this.
74
- */
75
- export declare const groupInviteDiscover: import("../data/persistent-vars").PersistentVar<string | null>;
76
- /**
77
- * Trigger to send a join request.
78
- * Set by UI: { listener, password }
79
- * Device layer updates groupInviteJoinResult and clears this.
80
- */
81
- export declare const groupInviteSendRequest: import("../data/persistent-vars").PersistentVar<{
82
- listener: IGroupInviteListenerInfo;
83
- password: string;
84
- } | null>;
85
- /**
86
- * Trigger to process (approve/deny) a join request.
87
- * Set by UI: { requestId, approved, role }
88
- * Device layer processes and clears this.
89
- */
90
- export declare const groupInviteProcessRequest: import("../data/persistent-vars").PersistentVar<{
91
- requestId: string;
92
- approved: boolean;
93
- role: GroupMemberRole;
94
- } | null>;
@@ -1,139 +0,0 @@
1
- "use strict";
2
- /**
3
- * Persistent variables for group invitation state.
4
- *
5
- * These device-level variables track:
6
- * - Active invitation listeners (admin side)
7
- * - Pending join requests (admin side)
8
- * - Status messages for UI feedback
9
- * - Action triggers (UI sets these, device layer reacts)
10
- */
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.groupInviteProcessRequest = exports.groupInviteSendRequest = exports.groupInviteDiscover = exports.groupInviteStopListening = exports.groupInviteStartListening = exports.groupInviteResponses = exports.groupInviteJoinResult = exports.groupInviteDiscoveryResult = exports.groupJoinStatus = exports.groupInviteStatus = exports.groupInviteRequests = exports.groupInviteListeners = void 0;
13
- const persistent_vars_1 = require("../data/persistent-vars");
14
- // ============================================================================
15
- // STATE VARIABLES (read by both UI and device layer)
16
- // ============================================================================
17
- /**
18
- * Active group invitation listeners.
19
- * Key is groupId, value contains the password and alias being listened for.
20
- *
21
- * Used by admins who are waiting for join requests.
22
- */
23
- exports.groupInviteListeners = (0, persistent_vars_1.deviceVar)("groupInviteListeners", { defaultValue: {} });
24
- /**
25
- * Pending join requests that need admin approval.
26
- * Array of requests waiting to be approved or denied.
27
- *
28
- * These are shown to the admin in the group details UI.
29
- */
30
- exports.groupInviteRequests = (0, persistent_vars_1.deviceVar)("groupInviteRequests", {
31
- defaultValue: [],
32
- });
33
- /**
34
- * Status message for the group invite UI (admin side).
35
- * Used to show success/error messages to the user.
36
- */
37
- exports.groupInviteStatus = (0, persistent_vars_1.deviceVar)("groupInviteStatus", { defaultValue: "" });
38
- /**
39
- * Status message for the join group UI (joiner side).
40
- * Used to show discovery/join status to the user.
41
- */
42
- exports.groupJoinStatus = (0, persistent_vars_1.deviceVar)("groupJoinStatus", { defaultValue: "" });
43
- /**
44
- * Results from discovering group listeners.
45
- * Updated by the device layer after discovery completes.
46
- */
47
- exports.groupInviteDiscoveryResult = (0, persistent_vars_1.deviceVar)("groupInviteDiscoveryResult", { defaultValue: [] });
48
- /**
49
- * Result of joining a group.
50
- * Updated by the device layer after join completes.
51
- */
52
- exports.groupInviteJoinResult = (0, persistent_vars_1.deviceVar)("groupInviteJoinResult", {
53
- defaultValue: null,
54
- });
55
- /**
56
- * Responses to join requests, keyed by requestId.
57
- * Written by processJoinRequest, read by handleJoinRequest.
58
- * Entries are cleaned up after being read.
59
- */
60
- exports.groupInviteResponses = (0, persistent_vars_1.deviceVar)("groupInviteResponses", { defaultValue: {} });
61
- // ============================================================================
62
- // ACTION TRIGGERS (UI sets these, device layer reacts)
63
- // ============================================================================
64
- /**
65
- * Trigger to start listening for invitations.
66
- * Set by UI: { groupId, password }
67
- * Device layer clears after processing.
68
- */
69
- exports.groupInviteStartListening = (0, persistent_vars_1.deviceVar)("groupInviteStartListening", { defaultValue: null });
70
- /**
71
- * Trigger to stop listening for invitations.
72
- * Set by UI: groupId
73
- * Device layer clears after processing.
74
- */
75
- exports.groupInviteStopListening = (0, persistent_vars_1.deviceVar)("groupInviteStopListening", {
76
- defaultValue: null,
77
- });
78
- /**
79
- * Trigger to discover groups with a password.
80
- * Set by UI: password
81
- * Device layer updates groupInviteDiscoveryResult and clears this.
82
- */
83
- exports.groupInviteDiscover = (0, persistent_vars_1.deviceVar)("groupInviteDiscover", {
84
- defaultValue: null,
85
- });
86
- /**
87
- * Trigger to send a join request.
88
- * Set by UI: { listener, password }
89
- * Device layer updates groupInviteJoinResult and clears this.
90
- */
91
- exports.groupInviteSendRequest = (0, persistent_vars_1.deviceVar)("groupInviteSendRequest", { defaultValue: null });
92
- /**
93
- * Trigger to process (approve/deny) a join request.
94
- * Set by UI: { requestId, approved, role }
95
- * Device layer processes and clears this.
96
- */
97
- exports.groupInviteProcessRequest = (0, persistent_vars_1.deviceVar)("groupInviteProcessRequest", { defaultValue: null });
98
- // ============================================================================
99
- // AUTO-CLEANUP
100
- // ============================================================================
101
- // Auto-cleanup of expired listeners (10 minute expiry)
102
- exports.groupInviteListeners.loadingPromise.then(() => {
103
- // Check every minute for expired listeners
104
- setInterval(() => {
105
- const listeners = (0, exports.groupInviteListeners)();
106
- const now = Date.now();
107
- const expiredGroupIds = [];
108
- for (const [groupId, listener] of Object.entries(listeners)) {
109
- const startedAt = new Date(listener.startedAt).getTime();
110
- const elapsed = now - startedAt;
111
- // Expire after 10 minutes
112
- if (elapsed > 600_000) {
113
- expiredGroupIds.push(groupId);
114
- }
115
- }
116
- if (expiredGroupIds.length > 0) {
117
- const updated = { ...listeners };
118
- for (const groupId of expiredGroupIds) {
119
- delete updated[groupId];
120
- }
121
- (0, exports.groupInviteListeners)(updated);
122
- }
123
- }, 60_000);
124
- });
125
- // Clean up old requests after 10 minutes
126
- exports.groupInviteRequests.loadingPromise.then(() => {
127
- setInterval(() => {
128
- const requests = (0, exports.groupInviteRequests)();
129
- const now = Date.now();
130
- const validRequests = requests.filter((req) => {
131
- const receivedAt = new Date(req.receivedAt).getTime();
132
- const elapsed = now - receivedAt;
133
- return elapsed < 600_000; // Keep for 10 minutes
134
- });
135
- if (validRequests.length !== requests.length) {
136
- (0, exports.groupInviteRequests)(validRequests);
137
- }
138
- }, 60_000);
139
- });
@@ -1,124 +0,0 @@
1
- /**
2
- * Types for the group invitation flow.
3
- *
4
- * This flow allows admins to invite new members to a group using a simple
5
- * password. Multiple admins can listen for the same password simultaneously.
6
- */
7
- import type { GroupMemberRole } from "../data/group-member-roles";
8
- import type { IGroupMember } from "../data/group-members";
9
- import type { IGroupShare } from "../data/group-share";
10
- /**
11
- * Information about a group shared during the invitation flow.
12
- */
13
- export interface IGroupInviteGroupInfo {
14
- groupId: string;
15
- name: string;
16
- description?: string;
17
- iconClassName?: string;
18
- }
19
- /**
20
- * Information about the inviting admin shared during discovery.
21
- */
22
- export interface IGroupInviteListenerInfo {
23
- /** The admin's user ID */
24
- userId: string;
25
- /** The admin's display name */
26
- name: string;
27
- /** The admin's device ID */
28
- deviceId: string;
29
- /** Group information */
30
- group: IGroupInviteGroupInfo;
31
- /** The alias being listened on */
32
- alias: string;
33
- }
34
- /**
35
- * Information sent by a user requesting to join a group.
36
- */
37
- export interface IGroupJoinRequestInfo {
38
- /** Requesting user's ID */
39
- userId: string;
40
- /** Requesting user's display name */
41
- name?: string;
42
- /** Requesting user's public signing key */
43
- publicKey: string;
44
- /** Requesting user's public box key for encryption */
45
- publicBoxKey: string;
46
- /** Requesting user's device ID */
47
- deviceId: string;
48
- }
49
- /**
50
- * A pending join request shown to the admin.
51
- */
52
- export interface IGroupJoinRequest {
53
- /** Unique request ID */
54
- requestId: string;
55
- /** The group being joined */
56
- groupId: string;
57
- /** The alias this request came in on */
58
- alias: string;
59
- /** The password used (for encryption) */
60
- password: string;
61
- /** Information about the requesting user */
62
- requester: IGroupJoinRequestInfo;
63
- /** When the request was received */
64
- receivedAt: Date;
65
- }
66
- /**
67
- * Response sent by admin when approving a join request.
68
- */
69
- export interface IGroupJoinApprovalInfo {
70
- /** Whether the request was approved */
71
- approved: boolean;
72
- /** The role assigned to the new member (if approved) */
73
- role?: GroupMemberRole;
74
- /** Canonical group record plus Admin+ seed memberships */
75
- groupShare?: IGroupShare;
76
- /** Newly signed membership for the joiner, including Reader roles */
77
- newMember?: IGroupMember;
78
- /** Admin's user info for adding to contacts */
79
- adminInfo?: IGroupJoinRequestInfo;
80
- /** Error message if rejected */
81
- rejectionReason?: string;
82
- }
83
- /**
84
- * Signal that a joiner finished importing approval data and can connect to the admin.
85
- */
86
- export interface IGroupInviteJoinFinished {
87
- /** Group the joiner just imported */
88
- groupId: string;
89
- /** Approving admin device that should be contacted in that group context */
90
- adminDeviceId: string;
91
- }
92
- /**
93
- * Active invitation listener state.
94
- */
95
- export interface IGroupInviteListener {
96
- /** The group being invited to */
97
- groupId: string;
98
- /** The password being listened for */
99
- password: string;
100
- /** The derived alias for network discovery */
101
- alias: string;
102
- /** When listening started */
103
- startedAt: Date;
104
- }
105
- /**
106
- * Result of discovering group invite listeners.
107
- */
108
- export interface IGroupInviteDiscoveryResult {
109
- /** List of listeners found */
110
- listeners: IGroupInviteListenerInfo[];
111
- /** Any error that occurred */
112
- error?: string;
113
- }
114
- /**
115
- * Result of a join request.
116
- */
117
- export interface IGroupJoinResult {
118
- /** Whether the join was successful */
119
- success: boolean;
120
- /** The group ID if successful */
121
- groupId?: string;
122
- /** Error message if failed */
123
- error?: string;
124
- }
@@ -1,8 +0,0 @@
1
- "use strict";
2
- /**
3
- * Types for the group invitation flow.
4
- *
5
- * This flow allows admins to invite new members to a group using a simple
6
- * password. Multiple admins can listen for the same password simultaneously.
7
- */
8
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,3 +0,0 @@
1
- export * from "./group-invite";
2
- export * from "./group-invite.pvars";
3
- export * from "./group-invite.types";
@@ -1,67 +0,0 @@
1
- /**
2
- * Utilities for generating and handling connection codes.
3
- *
4
- * Connection codes are 12 characters of Crockford Base32:
5
- * - First 4 chars: device alias (rendezvous point)
6
- * - Last 8 chars: shared secret for encryption
7
- *
8
- * Displayed format: XXXX-YYYY-ZZZZ
9
- */
10
- import type { IUserConnectInfo } from "./user-connect.types";
11
- export interface IConnectionCode {
12
- /** Full 12-character code */
13
- code: string;
14
- /** First 4 characters - device alias for rendezvous */
15
- alias: string;
16
- /** Last 8 characters - shared secret for encryption */
17
- secret: string;
18
- }
19
- /**
20
- * Generate a new connection code.
21
- * @returns Object with full code, alias, and secret
22
- */
23
- export declare function generateConnectionCode(): IConnectionCode;
24
- /**
25
- * Format a connection code for display.
26
- * @param code 12-character code
27
- * @returns Formatted as "XXXX-YYYY-ZZZZ"
28
- */
29
- export declare function formatConnectionCode(code: string): string;
30
- /**
31
- * Parse a formatted connection code.
32
- * @param formatted Code in any format (with or without dashes)
33
- * @returns Object with alias and secret
34
- */
35
- export declare function parseConnectionCode(formatted: string): {
36
- code: string;
37
- alias: string;
38
- secret: string;
39
- };
40
- /**
41
- * Encrypt data using the shared secret.
42
- * @param data Data to encrypt
43
- * @param secret 8-character shared secret
44
- * @returns Base64-encoded encrypted data with nonce
45
- */
46
- export declare function encryptWithSecret(data: any, secret: string): string;
47
- /**
48
- * Decrypt data using the shared secret.
49
- * @param encrypted Base64-encoded encrypted data
50
- * @param secret 8-character shared secret
51
- * @returns Decrypted data
52
- */
53
- export declare function decryptWithSecret(encrypted: string, secret: string): any;
54
- /**
55
- * Generate a confirmation hash from both users' information.
56
- * Both parties should see the same hash if the exchange was successful.
57
- * @param userA First user's info
58
- * @param userB Second user's info
59
- * @returns 4-character confirmation code
60
- */
61
- export declare function generateConfirmationHash(userA: IUserConnectInfo, userB: IUserConnectInfo): string;
62
- /**
63
- * Validate that a string is a valid connection code format.
64
- * @param code Code to validate (with or without dashes)
65
- * @returns true if valid
66
- */
67
- export declare function isValidConnectionCode(code: string): boolean;