@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.
- package/dist/contracts/index.d.ts +1 -0
- package/dist/contracts/index.js +4 -1
- package/dist/contracts/system/index.d.ts +2 -0
- package/dist/contracts/system/index.js +5 -1
- package/dist/contracts/system/invites-contract.d.ts +121 -0
- package/dist/contracts/system/invites-contract.js +150 -0
- package/dist/data/create-group.d.ts +24 -0
- package/dist/data/create-group.js +61 -0
- package/dist/data/group-secret.d.ts +10 -0
- package/dist/data/group-secret.js +26 -0
- package/dist/data/group-share.d.ts +0 -20
- package/dist/data/group-share.js +0 -35
- package/dist/data/index.d.ts +2 -0
- package/dist/data/index.js +2 -0
- package/dist/data/invites.d.ts +350 -0
- package/dist/data/invites.js +99 -0
- package/dist/data/users.js +4 -0
- package/dist/device-pairing/constants.d.ts +27 -9
- package/dist/device-pairing/constants.js +28 -10
- package/dist/device-pairing/cpace.d.ts +46 -0
- package/dist/device-pairing/cpace.js +173 -0
- package/dist/device-pairing/cpace.test.js +116 -0
- package/dist/device-pairing/crypto.d.ts +40 -15
- package/dist/device-pairing/crypto.js +74 -33
- package/dist/device-pairing/device-pairing.test.js +156 -119
- package/dist/device-pairing/index.d.ts +3 -1
- package/dist/device-pairing/index.js +3 -1
- package/dist/device-pairing/pairing-code.d.ts +27 -0
- package/dist/device-pairing/pairing-code.js +84 -0
- package/dist/device-pairing/pgp-word-list.d.ts +14 -0
- package/dist/device-pairing/pgp-word-list.js +531 -0
- package/dist/device-pairing/signaling.d.ts +17 -6
- package/dist/device-pairing/signaling.js +31 -8
- package/dist/device-pairing/transcript.d.ts +3 -3
- package/dist/device-pairing/transcript.js +6 -13
- package/dist/device-pairing/types.d.ts +870 -224
- package/dist/device-pairing/types.js +186 -108
- package/dist/index.d.ts +1 -2
- package/dist/index.js +1 -2
- package/dist/invites/data-box-schema.d.ts +15 -0
- package/dist/invites/data-box-schema.js +15 -0
- package/dist/invites/group-approval.d.ts +43 -0
- package/dist/invites/group-approval.js +155 -0
- package/dist/invites/group-approval.test.js +221 -0
- package/dist/invites/index.d.ts +5 -0
- package/dist/{group-invite → invites}/index.js +5 -3
- package/dist/invites/invite-epoch.d.ts +18 -0
- package/dist/invites/invite-epoch.js +35 -0
- package/dist/invites/invite-messages.d.ts +1354 -0
- package/dist/invites/invite-messages.js +145 -0
- package/dist/invites/invite-token.d.ts +334 -0
- package/dist/invites/invite-token.js +178 -0
- package/dist/invites/invite-token.test.d.ts +1 -0
- package/dist/invites/invite-token.test.js +123 -0
- package/dist/rpc-types.d.ts +5 -4
- package/dist/rpc-types.js +2 -1
- package/dist/system-ids.d.ts +22 -0
- package/dist/system-ids.js +23 -1
- package/dist/types/peer-device.d.ts +15 -1
- package/dist/types/peer-device.js +15 -1
- package/package.json +1 -1
- package/dist/device-pairing/invitation.d.ts +0 -13
- package/dist/device-pairing/invitation.js +0 -85
- package/dist/group-invite/group-invite.d.ts +0 -53
- package/dist/group-invite/group-invite.js +0 -231
- package/dist/group-invite/group-invite.pvars.d.ts +0 -94
- package/dist/group-invite/group-invite.pvars.js +0 -139
- package/dist/group-invite/group-invite.types.d.ts +0 -124
- package/dist/group-invite/group-invite.types.js +0 -8
- package/dist/group-invite/index.d.ts +0 -3
- package/dist/user-connect/connection-code.d.ts +0 -67
- package/dist/user-connect/connection-code.js +0 -176
- package/dist/user-connect/connection-code.test.js +0 -213
- package/dist/user-connect/index.d.ts +0 -3
- package/dist/user-connect/index.js +0 -19
- package/dist/user-connect/user-connect.pvars.d.ts +0 -20
- package/dist/user-connect/user-connect.pvars.js +0 -63
- package/dist/user-connect/user-connect.pvars.test.js +0 -46
- package/dist/user-connect/user-connect.types.d.ts +0 -94
- package/dist/user-connect/user-connect.types.js +0 -68
- /package/dist/{user-connect/connection-code.test.d.ts → device-pairing/cpace.test.d.ts} +0 -0
- /package/dist/{user-connect/user-connect.pvars.test.d.ts → invites/group-approval.test.d.ts} +0 -0
|
@@ -1,36 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.devicePairingStateSchema = exports.devicePairingPhaseSchema = exports.signedPairingInstallationReceiptSchema = exports.pairingInstallationReceiptContentsSchema = exports.pairingCredentialEnvelopeSchema = exports.pairingCredentialContentsSchema = exports.
|
|
3
|
+
exports.devicePairingStateSchema = exports.devicePairingPhaseSchema = exports.signedPairingInstallationReceiptSchema = exports.pairingInstallationReceiptContentsSchema = exports.pairingCredentialEnvelopeSchema = exports.pairingCredentialContentsSchema = exports.pairingConfirmationSchema = exports.pairingConfirmationContentsSchema = exports.pairingDevicePresentationSchema = exports.devicePairingTranscriptSchema = exports.devicePairingIceServersAckSchema = exports.devicePairingRoomReadyAckSchema = exports.devicePairingRoomCreatedAckSchema = exports.devicePairingSignalingAckSchema = exports.devicePairingSignalingErrorCodeSchema = exports.devicePairingDeleteRoomRequestSchema = exports.devicePairingJoinRoomRequestSchema = exports.devicePairingCreateRoomRequestSchema = exports.pairingSignalSchema = exports.authenticatedPairingSignalSchema = exports.unsignedPairingSignalSchema = exports.pairingPakeSignalSchema = exports.pairingIceServerSchema = exports.pairingIceCandidateSchema = exports.pairingTransportChoiceSchema = exports.pairingTransportOptionsSchema = exports.pairingWebSocketUrlSchema = exports.pairingTransportSchema = exports.pairingSessionDescriptionSchema = exports.pairingRendezvousSchema = exports.pairingServiceOriginSchema = exports.pairingRoleSchema = exports.pairingNameplateSchema = exports.pairingPakeShareSchema = exports.pairingEndpointNonceSchema = exports.pairingHashSchema = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
const devices_1 = require("../data/devices");
|
|
6
6
|
const zod_types_1 = require("../types/zod-types");
|
|
7
7
|
const constants_1 = require("./constants");
|
|
8
8
|
const base64UrlSchema = zod_1.z.string().regex(/^[A-Za-z0-9_-]+$/);
|
|
9
|
-
/** A
|
|
10
|
-
exports.pairingRoomIdSchema = base64UrlSchema.length(22);
|
|
11
|
-
/** A random 256-bit pairing-room secret encoded as unpadded base64url. */
|
|
12
|
-
exports.pairingRoomSecretSchema = base64UrlSchema.length(43);
|
|
13
|
-
/** A SHA-256 value encoded as unpadded base64url. */
|
|
9
|
+
/** A SHA-256 value or 256-bit key encoded as unpadded base64url. */
|
|
14
10
|
exports.pairingHashSchema = base64UrlSchema.length(43);
|
|
15
11
|
/** A random 256-bit endpoint nonce encoded as unpadded base64url. */
|
|
16
12
|
exports.pairingEndpointNonceSchema = base64UrlSchema.length(43);
|
|
13
|
+
/** A 32-byte X25519 PAKE public share encoded as unpadded base64url. */
|
|
14
|
+
exports.pairingPakeShareSchema = base64UrlSchema.length(43);
|
|
15
|
+
/** Small integer that names a signaling room; the first element of a pairing code. */
|
|
16
|
+
exports.pairingNameplateSchema = zod_1.z.number().int().min(1).max(constants_1.DEVICE_PAIRING_MAX_NAMEPLATE);
|
|
17
17
|
/** Source and destination roles in a two-party pairing room. */
|
|
18
18
|
exports.pairingRoleSchema = zod_1.z.enum(["source", "destination"]);
|
|
19
|
-
/**
|
|
20
|
-
exports.
|
|
19
|
+
/** HTTP(S) origin of the signaling service without a path. */
|
|
20
|
+
exports.pairingServiceOriginSchema = zod_1.z
|
|
21
|
+
.string()
|
|
22
|
+
.url()
|
|
23
|
+
.max(2048)
|
|
24
|
+
.refine((value) => {
|
|
25
|
+
const url = new URL(value);
|
|
26
|
+
return (url.protocol === "https:" || url.protocol === "http:") && url.origin === value;
|
|
27
|
+
}, "Expected an HTTP(S) origin without a path");
|
|
28
|
+
/** Established rendezvous shared by both endpoints once the room exists. */
|
|
29
|
+
exports.pairingRendezvousSchema = zod_1.z
|
|
21
30
|
.object({
|
|
22
31
|
version: zod_1.z.literal(constants_1.DEVICE_PAIRING_PROTOCOL_VERSION),
|
|
23
|
-
|
|
24
|
-
|
|
32
|
+
serviceOrigin: exports.pairingServiceOriginSchema,
|
|
33
|
+
nameplate: exports.pairingNameplateSchema,
|
|
25
34
|
expiresAt: zod_1.z.number().int().positive(),
|
|
26
|
-
serviceOrigin: zod_1.z
|
|
27
|
-
.string()
|
|
28
|
-
.url()
|
|
29
|
-
.max(2048)
|
|
30
|
-
.refine((value) => {
|
|
31
|
-
const url = new URL(value);
|
|
32
|
-
return (url.protocol === "https:" || url.protocol === "http:") && url.origin === value;
|
|
33
|
-
}, "Expected an HTTP(S) origin without a path"),
|
|
34
35
|
})
|
|
35
36
|
.strict();
|
|
36
37
|
/** WebRTC session description carried inside an authenticated signaling message. */
|
|
@@ -41,9 +42,56 @@ exports.pairingSessionDescriptionSchema = zod_1.z
|
|
|
41
42
|
.string()
|
|
42
43
|
.min(1)
|
|
43
44
|
.max(64 * 1024),
|
|
45
|
+
})
|
|
46
|
+
.strict();
|
|
47
|
+
/** Data transports a pairing ceremony can negotiate after the PAKE. */
|
|
48
|
+
exports.pairingTransportSchema = zod_1.z.enum(["wrtc", "ws"]);
|
|
49
|
+
/** Socket.IO URL a destination hosts for the direct WebSocket transport. */
|
|
50
|
+
exports.pairingWebSocketUrlSchema = zod_1.z
|
|
51
|
+
.string()
|
|
52
|
+
.min(1)
|
|
53
|
+
.max(2048)
|
|
54
|
+
.refine((value) => {
|
|
55
|
+
try {
|
|
56
|
+
const url = new URL(value);
|
|
57
|
+
return ["http:", "https:", "ws:", "wss:"].includes(url.protocol) && url.hostname.length > 0;
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
}, "Expected an http(s) or ws(s) URL");
|
|
63
|
+
/**
|
|
64
|
+
* Destination's transport options, sent right after both PAKE shares. `websocket.urls` are the
|
|
65
|
+
* Socket.IO origins the destination is listening on for a source that can reach them directly.
|
|
66
|
+
*/
|
|
67
|
+
exports.pairingTransportOptionsSchema = zod_1.z
|
|
68
|
+
.object({
|
|
44
69
|
endpointNonce: exports.pairingEndpointNonceSchema,
|
|
70
|
+
webrtc: zod_1.z.boolean(),
|
|
71
|
+
websocket: zod_1.z
|
|
72
|
+
.object({
|
|
73
|
+
urls: zod_1.z.array(exports.pairingWebSocketUrlSchema).min(1).max(constants_1.DEVICE_PAIRING_MAX_WEBSOCKET_URLS),
|
|
74
|
+
})
|
|
75
|
+
.strict()
|
|
76
|
+
.optional(),
|
|
45
77
|
})
|
|
46
78
|
.strict();
|
|
79
|
+
/** Source's transport choice; `url` is the destination URL it connected to for `ws`. */
|
|
80
|
+
exports.pairingTransportChoiceSchema = zod_1.z.discriminatedUnion("selected", [
|
|
81
|
+
zod_1.z
|
|
82
|
+
.object({
|
|
83
|
+
endpointNonce: exports.pairingEndpointNonceSchema,
|
|
84
|
+
selected: zod_1.z.literal("wrtc"),
|
|
85
|
+
})
|
|
86
|
+
.strict(),
|
|
87
|
+
zod_1.z
|
|
88
|
+
.object({
|
|
89
|
+
endpointNonce: exports.pairingEndpointNonceSchema,
|
|
90
|
+
selected: zod_1.z.literal("ws"),
|
|
91
|
+
url: exports.pairingWebSocketUrlSchema,
|
|
92
|
+
})
|
|
93
|
+
.strict(),
|
|
94
|
+
]);
|
|
47
95
|
/** ICE candidate carried inside an authenticated signaling message. */
|
|
48
96
|
exports.pairingIceCandidateSchema = zod_1.z
|
|
49
97
|
.object({
|
|
@@ -70,84 +118,99 @@ exports.pairingIceServerSchema = zod_1.z
|
|
|
70
118
|
(value.username !== undefined && value.credential !== undefined), "TURN username and credential must be supplied together");
|
|
71
119
|
const pairingSignalBase = {
|
|
72
120
|
version: zod_1.z.literal(constants_1.DEVICE_PAIRING_PROTOCOL_VERSION),
|
|
73
|
-
|
|
121
|
+
nameplate: exports.pairingNameplateSchema,
|
|
74
122
|
senderRole: exports.pairingRoleSchema,
|
|
75
123
|
sequence: zod_1.z.number().int().positive(),
|
|
76
124
|
};
|
|
77
|
-
/**
|
|
125
|
+
/** PAKE share exchanged before any key exists; it is not MACed and carries no secrets. */
|
|
126
|
+
exports.pairingPakeSignalSchema = zod_1.z
|
|
127
|
+
.object({
|
|
128
|
+
...pairingSignalBase,
|
|
129
|
+
kind: zod_1.z.literal("pake"),
|
|
130
|
+
payload: zod_1.z.object({ share: exports.pairingPakeShareSchema }).strict(),
|
|
131
|
+
})
|
|
132
|
+
.strict();
|
|
133
|
+
const unsignedTransportOptionsSignal = zod_1.z
|
|
134
|
+
.object({
|
|
135
|
+
...pairingSignalBase,
|
|
136
|
+
kind: zod_1.z.literal("transport-options"),
|
|
137
|
+
payload: exports.pairingTransportOptionsSchema,
|
|
138
|
+
})
|
|
139
|
+
.strict();
|
|
140
|
+
const unsignedTransportChoiceSignal = zod_1.z
|
|
141
|
+
.object({
|
|
142
|
+
...pairingSignalBase,
|
|
143
|
+
kind: zod_1.z.literal("transport-choice"),
|
|
144
|
+
payload: exports.pairingTransportChoiceSchema,
|
|
145
|
+
})
|
|
146
|
+
.strict();
|
|
147
|
+
const unsignedOfferSignal = zod_1.z
|
|
148
|
+
.object({
|
|
149
|
+
...pairingSignalBase,
|
|
150
|
+
kind: zod_1.z.literal("offer"),
|
|
151
|
+
payload: exports.pairingSessionDescriptionSchema.extend({ type: zod_1.z.literal("offer") }).strict(),
|
|
152
|
+
})
|
|
153
|
+
.strict();
|
|
154
|
+
const unsignedAnswerSignal = zod_1.z
|
|
155
|
+
.object({
|
|
156
|
+
...pairingSignalBase,
|
|
157
|
+
kind: zod_1.z.literal("answer"),
|
|
158
|
+
payload: exports.pairingSessionDescriptionSchema.extend({ type: zod_1.z.literal("answer") }).strict(),
|
|
159
|
+
})
|
|
160
|
+
.strict();
|
|
161
|
+
const unsignedCandidateSignal = zod_1.z
|
|
162
|
+
.object({
|
|
163
|
+
...pairingSignalBase,
|
|
164
|
+
kind: zod_1.z.literal("candidate"),
|
|
165
|
+
payload: exports.pairingIceCandidateSchema,
|
|
166
|
+
})
|
|
167
|
+
.strict();
|
|
168
|
+
/**
|
|
169
|
+
* Unsigned transport, offer, answer, or ICE message before its signaling MAC is attached.
|
|
170
|
+
*
|
|
171
|
+
* Order after both PAKE shares: destination `transport-options`, source `transport-choice`, then
|
|
172
|
+
* (WebRTC only) source `offer`, destination `answer`, and `candidate`s from either role.
|
|
173
|
+
*/
|
|
78
174
|
exports.unsignedPairingSignalSchema = zod_1.z.discriminatedUnion("kind", [
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
})
|
|
85
|
-
.strict(),
|
|
86
|
-
zod_1.z
|
|
87
|
-
.object({
|
|
88
|
-
...pairingSignalBase,
|
|
89
|
-
kind: zod_1.z.literal("answer"),
|
|
90
|
-
payload: exports.pairingSessionDescriptionSchema.extend({ type: zod_1.z.literal("answer") }).strict(),
|
|
91
|
-
})
|
|
92
|
-
.strict(),
|
|
93
|
-
zod_1.z
|
|
94
|
-
.object({
|
|
95
|
-
...pairingSignalBase,
|
|
96
|
-
kind: zod_1.z.literal("candidate"),
|
|
97
|
-
payload: exports.pairingIceCandidateSchema,
|
|
98
|
-
})
|
|
99
|
-
.strict(),
|
|
175
|
+
unsignedTransportOptionsSignal,
|
|
176
|
+
unsignedTransportChoiceSignal,
|
|
177
|
+
unsignedOfferSignal,
|
|
178
|
+
unsignedAnswerSignal,
|
|
179
|
+
unsignedCandidateSignal,
|
|
100
180
|
]);
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
kind: zod_1.z.literal("answer"),
|
|
115
|
-
payload: exports.pairingSessionDescriptionSchema.extend({ type: zod_1.z.literal("answer") }).strict(),
|
|
116
|
-
mac: exports.pairingHashSchema,
|
|
117
|
-
})
|
|
118
|
-
.strict(),
|
|
119
|
-
zod_1.z
|
|
120
|
-
.object({
|
|
121
|
-
...pairingSignalBase,
|
|
122
|
-
kind: zod_1.z.literal("candidate"),
|
|
123
|
-
payload: exports.pairingIceCandidateSchema,
|
|
124
|
-
mac: exports.pairingHashSchema,
|
|
125
|
-
})
|
|
126
|
-
.strict(),
|
|
181
|
+
const macField = { mac: exports.pairingHashSchema };
|
|
182
|
+
/** HMAC-authenticated transport, offer, answer, or ICE signaling message. */
|
|
183
|
+
exports.authenticatedPairingSignalSchema = zod_1.z.discriminatedUnion("kind", [
|
|
184
|
+
unsignedTransportOptionsSignal.extend(macField).strict(),
|
|
185
|
+
unsignedTransportChoiceSignal.extend(macField).strict(),
|
|
186
|
+
unsignedOfferSignal.extend(macField).strict(),
|
|
187
|
+
unsignedAnswerSignal.extend(macField).strict(),
|
|
188
|
+
unsignedCandidateSignal.extend(macField).strict(),
|
|
189
|
+
]);
|
|
190
|
+
/** Any signaling message relayed by peers-services: the PAKE share or an authenticated signal. */
|
|
191
|
+
exports.pairingSignalSchema = zod_1.z.union([
|
|
192
|
+
exports.pairingPakeSignalSchema,
|
|
193
|
+
exports.authenticatedPairingSignalSchema,
|
|
127
194
|
]);
|
|
128
|
-
/** Request from the
|
|
195
|
+
/** Request from the destination to create a bounded signaling room and receive a nameplate. */
|
|
129
196
|
exports.devicePairingCreateRoomRequestSchema = zod_1.z
|
|
130
197
|
.object({
|
|
131
198
|
version: zod_1.z.literal(constants_1.DEVICE_PAIRING_PROTOCOL_VERSION),
|
|
132
|
-
roomId: exports.pairingRoomIdSchema,
|
|
133
199
|
expiresAt: zod_1.z.number().int().positive(),
|
|
134
|
-
roomAccessTokenHash: exports.pairingHashSchema,
|
|
135
200
|
})
|
|
136
201
|
.strict();
|
|
137
|
-
/** Request from the
|
|
202
|
+
/** Request from the source to occupy the room named by the typed or scanned nameplate. */
|
|
138
203
|
exports.devicePairingJoinRoomRequestSchema = zod_1.z
|
|
139
204
|
.object({
|
|
140
205
|
version: zod_1.z.literal(constants_1.DEVICE_PAIRING_PROTOCOL_VERSION),
|
|
141
|
-
|
|
142
|
-
roomAccessToken: exports.pairingHashSchema,
|
|
206
|
+
nameplate: exports.pairingNameplateSchema,
|
|
143
207
|
})
|
|
144
208
|
.strict();
|
|
145
|
-
/** Request from the
|
|
209
|
+
/** Request from the creating destination socket to tear down its signaling room. */
|
|
146
210
|
exports.devicePairingDeleteRoomRequestSchema = zod_1.z
|
|
147
211
|
.object({
|
|
148
212
|
version: zod_1.z.literal(constants_1.DEVICE_PAIRING_PROTOCOL_VERSION),
|
|
149
|
-
|
|
150
|
-
roomAccessToken: exports.pairingHashSchema,
|
|
213
|
+
nameplate: exports.pairingNameplateSchema,
|
|
151
214
|
})
|
|
152
215
|
.strict();
|
|
153
216
|
/** Public signaling-service error codes that do not echo attacker input. */
|
|
@@ -172,7 +235,18 @@ exports.devicePairingSignalingAckSchema = zod_1.z.discriminatedUnion("ok", [
|
|
|
172
235
|
zod_1.z.object({ ok: zod_1.z.literal(true) }).strict(),
|
|
173
236
|
devicePairingSignalingFailureSchema,
|
|
174
237
|
]);
|
|
175
|
-
/** Acknowledgement
|
|
238
|
+
/** Acknowledgement returned to the destination with its allocated nameplate and expiry. */
|
|
239
|
+
exports.devicePairingRoomCreatedAckSchema = zod_1.z.discriminatedUnion("ok", [
|
|
240
|
+
zod_1.z
|
|
241
|
+
.object({
|
|
242
|
+
ok: zod_1.z.literal(true),
|
|
243
|
+
nameplate: exports.pairingNameplateSchema,
|
|
244
|
+
expiresAt: zod_1.z.number().int().positive(),
|
|
245
|
+
})
|
|
246
|
+
.strict(),
|
|
247
|
+
devicePairingSignalingFailureSchema,
|
|
248
|
+
]);
|
|
249
|
+
/** Acknowledgement proving a room join and its service-authoritative expiry. */
|
|
176
250
|
exports.devicePairingRoomReadyAckSchema = zod_1.z.discriminatedUnion("ok", [
|
|
177
251
|
zod_1.z
|
|
178
252
|
.object({
|
|
@@ -192,17 +266,24 @@ exports.devicePairingIceServersAckSchema = zod_1.z.discriminatedUnion("ok", [
|
|
|
192
266
|
.strict(),
|
|
193
267
|
devicePairingSignalingFailureSchema,
|
|
194
268
|
]);
|
|
195
|
-
/**
|
|
269
|
+
/**
|
|
270
|
+
* Canonical transcript input derived independently by both endpoints.
|
|
271
|
+
*
|
|
272
|
+
* `transportBinding` pins the negotiated data channel: for `wrtc` it is the sorted SHA-256 DTLS
|
|
273
|
+
* fingerprints of the offer and answer (`offer|answer`); for `ws` it is the destination URL the
|
|
274
|
+
* source connected to, exactly as advertised in the MACed transport options.
|
|
275
|
+
*/
|
|
196
276
|
exports.devicePairingTranscriptSchema = zod_1.z
|
|
197
277
|
.object({
|
|
198
278
|
version: zod_1.z.literal(constants_1.DEVICE_PAIRING_PROTOCOL_VERSION),
|
|
199
|
-
|
|
279
|
+
serviceOrigin: exports.pairingServiceOriginSchema,
|
|
280
|
+
nameplate: exports.pairingNameplateSchema,
|
|
200
281
|
sourceIdentity: devices_1.deviceInfoSchema,
|
|
201
282
|
destinationIdentity: devices_1.deviceInfoSchema,
|
|
202
283
|
sourceEndpointNonce: exports.pairingEndpointNonceSchema,
|
|
203
284
|
destinationEndpointNonce: exports.pairingEndpointNonceSchema,
|
|
204
|
-
|
|
205
|
-
|
|
285
|
+
transport: exports.pairingTransportSchema,
|
|
286
|
+
transportBinding: zod_1.z.string().min(1).max(4096),
|
|
206
287
|
})
|
|
207
288
|
.strict();
|
|
208
289
|
/** Renderer-safe presentation of the remote endpoint. */
|
|
@@ -213,32 +294,22 @@ exports.pairingDevicePresentationSchema = zod_1.z
|
|
|
213
294
|
deviceType: zod_1.z.string().max(64).optional(),
|
|
214
295
|
})
|
|
215
296
|
.strict();
|
|
216
|
-
/**
|
|
217
|
-
exports.
|
|
297
|
+
/** Unauthenticated contents of a `pairing.confirm` message. */
|
|
298
|
+
exports.pairingConfirmationContentsSchema = zod_1.z
|
|
218
299
|
.object({
|
|
219
300
|
version: zod_1.z.literal(constants_1.DEVICE_PAIRING_PROTOCOL_VERSION),
|
|
301
|
+
role: exports.pairingRoleSchema,
|
|
220
302
|
transcriptHash: exports.pairingHashSchema,
|
|
221
303
|
device: devices_1.deviceInfoSchema,
|
|
222
304
|
presentation: exports.pairingDevicePresentationSchema,
|
|
223
305
|
})
|
|
224
306
|
.strict();
|
|
225
|
-
/**
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
role: exports.pairingRoleSchema,
|
|
232
|
-
expiresAt: zod_1.z.number().int().positive(),
|
|
233
|
-
})
|
|
234
|
-
.strict();
|
|
235
|
-
/** Signed approval bound to one transcript and endpoint identity. */
|
|
236
|
-
exports.signedPairingApprovalSchema = zod_1.z
|
|
237
|
-
.object({
|
|
238
|
-
contents: exports.pairingApprovalContentsSchema,
|
|
239
|
-
signature: base64UrlSchema.length(86),
|
|
240
|
-
publicKey: base64UrlSchema.length(43),
|
|
241
|
-
})
|
|
307
|
+
/**
|
|
308
|
+
* Payload exchanged by `pairing.confirm` after the Connection handshake. The MAC uses the
|
|
309
|
+
* PAKE-derived confirmation key, proving the peer knew the code and saw the same transcript.
|
|
310
|
+
*/
|
|
311
|
+
exports.pairingConfirmationSchema = exports.pairingConfirmationContentsSchema
|
|
312
|
+
.extend({ mac: exports.pairingHashSchema })
|
|
242
313
|
.strict();
|
|
243
314
|
/** Account credentials encrypted directly to the temporary destination identity. */
|
|
244
315
|
exports.pairingCredentialContentsSchema = zod_1.z
|
|
@@ -250,7 +321,7 @@ exports.pairingCredentialContentsSchema = zod_1.z
|
|
|
250
321
|
secretKey: base64UrlSchema.length(86),
|
|
251
322
|
})
|
|
252
323
|
.strict();
|
|
253
|
-
/** Signed-and-boxed credential envelope sent over the
|
|
324
|
+
/** Signed-and-boxed credential envelope sent over the pairing Connection. */
|
|
254
325
|
exports.pairingCredentialEnvelopeSchema = zod_1.z
|
|
255
326
|
.object({
|
|
256
327
|
contents: base64UrlSchema.min(1).max(4096),
|
|
@@ -275,12 +346,19 @@ exports.signedPairingInstallationReceiptSchema = zod_1.z
|
|
|
275
346
|
publicKey: base64UrlSchema.length(43),
|
|
276
347
|
})
|
|
277
348
|
.strict();
|
|
278
|
-
/**
|
|
349
|
+
/**
|
|
350
|
+
* Renderer-visible phases of the short-lived pairing ceremony.
|
|
351
|
+
*
|
|
352
|
+
* - `showing-code`: destination is displaying its code and waiting for a source to join.
|
|
353
|
+
* - `connecting`: room joined; transport negotiation and the Connection handshake are in progress.
|
|
354
|
+
* - `authenticating`: PAKE-derived confirmations are being exchanged.
|
|
355
|
+
* - `waiting-for-approval`: source must tap Approve; destination waits for it.
|
|
356
|
+
*/
|
|
279
357
|
exports.devicePairingPhaseSchema = zod_1.z.enum([
|
|
280
358
|
"idle",
|
|
281
|
-
"
|
|
359
|
+
"showing-code",
|
|
282
360
|
"connecting",
|
|
283
|
-
"
|
|
361
|
+
"authenticating",
|
|
284
362
|
"waiting-for-approval",
|
|
285
363
|
"transferring",
|
|
286
364
|
"complete",
|
|
@@ -295,10 +373,10 @@ exports.devicePairingStateSchema = zod_1.z
|
|
|
295
373
|
phase: exports.devicePairingPhaseSchema,
|
|
296
374
|
expiresAt: zod_1.z.number().int().positive().optional(),
|
|
297
375
|
remoteDevice: exports.pairingDevicePresentationSchema.optional(),
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
376
|
+
/** Destination only: the code to show as text and QR while `showing-code`. */
|
|
377
|
+
code: zod_1.z.string().max(128).optional(),
|
|
378
|
+
/** Non-fatal message shown alongside the current phase (e.g. why a code was rotated). */
|
|
379
|
+
notice: zod_1.z.string().max(256).optional(),
|
|
302
380
|
error: zod_1.z.string().max(256).optional(),
|
|
303
381
|
})
|
|
304
382
|
.strict();
|
package/dist/index.d.ts
CHANGED
|
@@ -15,8 +15,8 @@ export * from "./device/socket-io-binary-peer";
|
|
|
15
15
|
export * from "./device/tx-encoding";
|
|
16
16
|
export * from "./device-pairing";
|
|
17
17
|
export * from "./events";
|
|
18
|
-
export * from "./group-invite";
|
|
19
18
|
export * from "./hlc";
|
|
19
|
+
export * from "./invites";
|
|
20
20
|
export * from "./keys";
|
|
21
21
|
export * from "./logging";
|
|
22
22
|
export * from "./mentions";
|
|
@@ -39,7 +39,6 @@ export * from "./types/workflow";
|
|
|
39
39
|
export * from "./types/workflow-logger";
|
|
40
40
|
export * from "./types/workflow-run-context";
|
|
41
41
|
export * from "./types/zod-types";
|
|
42
|
-
export * from "./user-connect";
|
|
43
42
|
export * from "./users.query";
|
|
44
43
|
export * from "./utils";
|
|
45
44
|
export * from "./workflow-log-formatter";
|
package/dist/index.js
CHANGED
|
@@ -36,8 +36,8 @@ __exportStar(require("./device/socket-io-binary-peer"), exports);
|
|
|
36
36
|
__exportStar(require("./device/tx-encoding"), exports);
|
|
37
37
|
__exportStar(require("./device-pairing"), exports);
|
|
38
38
|
__exportStar(require("./events"), exports);
|
|
39
|
-
__exportStar(require("./group-invite"), exports);
|
|
40
39
|
__exportStar(require("./hlc"), exports);
|
|
40
|
+
__exportStar(require("./invites"), exports);
|
|
41
41
|
__exportStar(require("./keys"), exports);
|
|
42
42
|
__exportStar(require("./logging"), exports);
|
|
43
43
|
__exportStar(require("./mentions"), exports);
|
|
@@ -60,7 +60,6 @@ __exportStar(require("./types/workflow"), exports);
|
|
|
60
60
|
__exportStar(require("./types/workflow-logger"), exports);
|
|
61
61
|
__exportStar(require("./types/workflow-run-context"), exports);
|
|
62
62
|
__exportStar(require("./types/zod-types"), exports);
|
|
63
|
-
__exportStar(require("./user-connect"), exports);
|
|
64
63
|
__exportStar(require("./users.query"), exports);
|
|
65
64
|
__exportStar(require("./utils"), exports);
|
|
66
65
|
__exportStar(require("./workflow-log-formatter"), exports);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/** Encrypted box as produced by `boxDataWithKeys`. */
|
|
3
|
+
export declare const dataBoxSchema: z.ZodObject<{
|
|
4
|
+
contents: z.ZodString;
|
|
5
|
+
nonce: z.ZodString;
|
|
6
|
+
fromPublicKey: z.ZodString;
|
|
7
|
+
}, "strict", z.ZodTypeAny, {
|
|
8
|
+
nonce: string;
|
|
9
|
+
contents: string;
|
|
10
|
+
fromPublicKey: string;
|
|
11
|
+
}, {
|
|
12
|
+
nonce: string;
|
|
13
|
+
contents: string;
|
|
14
|
+
fromPublicKey: string;
|
|
15
|
+
}>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.dataBoxSchema = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
/** Encrypted box as produced by `boxDataWithKeys`. */
|
|
6
|
+
exports.dataBoxSchema = zod_1.z
|
|
7
|
+
.object({
|
|
8
|
+
contents: zod_1.z.string().min(1),
|
|
9
|
+
nonce: zod_1.z.string().min(1),
|
|
10
|
+
fromPublicKey: zod_1.z
|
|
11
|
+
.string()
|
|
12
|
+
.regex(/^[A-Za-z0-9_-]+$/)
|
|
13
|
+
.length(43),
|
|
14
|
+
})
|
|
15
|
+
.strict();
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { UserContext } from "../context/user-context";
|
|
2
|
+
import { GroupMemberRole } from "../data";
|
|
3
|
+
import { type IPublicPrivateKeys } from "../keys";
|
|
4
|
+
import type { GroupApproval } from "./invite-messages";
|
|
5
|
+
import type { InviteIdentity } from "./invite-token";
|
|
6
|
+
/** Inputs for building a {@link GroupApproval} on the approving member's device. */
|
|
7
|
+
export interface BuildGroupApprovalInput {
|
|
8
|
+
groupId: string;
|
|
9
|
+
joiner: InviteIdentity;
|
|
10
|
+
role: GroupMemberRole;
|
|
11
|
+
/** Nonce of the token or direct invite this approval answers. */
|
|
12
|
+
inviteNonce?: string;
|
|
13
|
+
/** The approving user's keys; the group secret is read and boxed with these. */
|
|
14
|
+
approverKeys: IPublicPrivateKeys;
|
|
15
|
+
approverDeviceId: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Builds the approval payload for a joiner: signs their membership row, gathers Admin+
|
|
19
|
+
* seed rows plus the approver's own Users/Devices records, and boxes the group secret to
|
|
20
|
+
* the joiner's box key.
|
|
21
|
+
*
|
|
22
|
+
* The approver must hold Admin+ in the group. The membership row is signed and saved in
|
|
23
|
+
* the approver's group context here; it syncs to the joiner when they connect and is also
|
|
24
|
+
* carried in the payload so the joiner can seed their copy immediately.
|
|
25
|
+
*
|
|
26
|
+
* @throws when the group is unknown, the approver is not Admin+, or the secret is unavailable
|
|
27
|
+
*/
|
|
28
|
+
export declare function buildGroupApproval(userContext: UserContext, input: BuildGroupApprovalInput): Promise<GroupApproval>;
|
|
29
|
+
/** Result of importing an approval on the joiner's device. */
|
|
30
|
+
export interface ImportGroupApprovalResult {
|
|
31
|
+
groupId: string;
|
|
32
|
+
approverUserId: string;
|
|
33
|
+
approverDeviceId: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Imports a {@link GroupApproval} on the joiner's device: records the group, seeds the group
|
|
37
|
+
* context with the signed rows, saves the approver as a contact, and stores the unboxed
|
|
38
|
+
* group secret in the personal context after validating it against the group's keys.
|
|
39
|
+
*
|
|
40
|
+
* Personal `Groups` is added only when missing so a local leave stays authoritative.
|
|
41
|
+
* `Devices` rows for the approver are left to the caller (device layer).
|
|
42
|
+
*/
|
|
43
|
+
export declare function importGroupApproval(userContext: UserContext, approval: GroupApproval, joinerKeys: IPublicPrivateKeys): Promise<ImportGroupApprovalResult>;
|