ftown 0.19.53 → 0.19.54
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/bridge-auth.d.ts +3 -0
- package/dist/bridge-auth.js.map +1 -1
- package/dist/command-rpc.js +21 -12
- package/dist/command-rpc.js.map +1 -1
- package/dist/index.js +49 -6
- package/dist/index.js.map +1 -1
- package/dist/pairing-client.d.ts +9 -12
- package/dist/pairing-client.js +34 -7
- package/dist/pairing-client.js.map +1 -1
- package/dist/security/account-crypto.d.ts +33 -0
- package/dist/security/account-crypto.js +649 -0
- package/dist/security/account-crypto.js.map +1 -0
- package/dist/security/account-protocol.d.ts +228 -0
- package/dist/security/account-protocol.js +2 -0
- package/dist/security/account-protocol.js.map +1 -0
- package/dist/security/bridge/account-client.d.ts +7 -0
- package/dist/security/bridge/account-client.js +87 -0
- package/dist/security/bridge/account-client.js.map +1 -0
- package/dist/security/bridge/account-state.d.ts +471 -0
- package/dist/security/bridge/account-state.js +78 -0
- package/dist/security/bridge/account-state.js.map +1 -0
- package/dist/security/bridge/execute.js +2 -1
- package/dist/security/bridge/execute.js.map +1 -1
- package/dist/security/bridge/identity.d.ts +436 -0
- package/dist/security/bridge/identity.js +27 -5
- package/dist/security/bridge/identity.js.map +1 -1
- package/dist/security/bridge/pending-enrollment.d.ts +12 -0
- package/dist/security/bridge/pending-enrollment.js +113 -0
- package/dist/security/bridge/pending-enrollment.js.map +1 -0
- package/dist/security/bridge/permissions.js +2 -2
- package/dist/security/bridge/permissions.js.map +1 -1
- package/dist/security/bridge/policy.d.ts +20 -0
- package/dist/security/bridge/policy.js +159 -7
- package/dist/security/bridge/policy.js.map +1 -1
- package/dist/security/bridge/security.d.ts +11 -0
- package/dist/security/bridge/security.js +93 -3
- package/dist/security/bridge/security.js.map +1 -1
- package/dist/security/bridge/snapshot.d.ts +1 -1
- package/dist/security/bridge/snapshot.js.map +1 -1
- package/dist/security/protocol.d.ts +12 -1
- package/dist/security-cli.js +7 -0
- package/dist/security-cli.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/package.json +2 -2
|
@@ -1,5 +1,441 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
1
2
|
import type { EndpointIdentity, EndpointKind } from '../protocol.js';
|
|
3
|
+
import type { VerifiedAccountTrust } from '../account-protocol.js';
|
|
4
|
+
export declare const identityRecordSchema: z.ZodObject<{
|
|
5
|
+
version: z.ZodLiteral<1>;
|
|
6
|
+
endpoint: z.ZodEffects<z.ZodObject<{
|
|
7
|
+
version: z.ZodLiteral<1>;
|
|
8
|
+
id: z.ZodString;
|
|
9
|
+
ownerId: z.ZodString;
|
|
10
|
+
kind: z.ZodEnum<["bridge", "browser", "mcp", "local-cli"]>;
|
|
11
|
+
publicKey: z.ZodString;
|
|
12
|
+
}, "strict", z.ZodTypeAny, {
|
|
13
|
+
id: string;
|
|
14
|
+
version: 1;
|
|
15
|
+
ownerId: string;
|
|
16
|
+
kind: "bridge" | "browser" | "mcp" | "local-cli";
|
|
17
|
+
publicKey: string;
|
|
18
|
+
}, {
|
|
19
|
+
id: string;
|
|
20
|
+
version: 1;
|
|
21
|
+
ownerId: string;
|
|
22
|
+
kind: "bridge" | "browser" | "mcp" | "local-cli";
|
|
23
|
+
publicKey: string;
|
|
24
|
+
}>, {
|
|
25
|
+
id: string;
|
|
26
|
+
version: 1;
|
|
27
|
+
ownerId: string;
|
|
28
|
+
kind: "bridge" | "browser" | "mcp" | "local-cli";
|
|
29
|
+
publicKey: string;
|
|
30
|
+
}, {
|
|
31
|
+
id: string;
|
|
32
|
+
version: 1;
|
|
33
|
+
ownerId: string;
|
|
34
|
+
kind: "bridge" | "browser" | "mcp" | "local-cli";
|
|
35
|
+
publicKey: string;
|
|
36
|
+
}>;
|
|
37
|
+
privateKey: z.ZodObject<{
|
|
38
|
+
kty: z.ZodLiteral<"EC">;
|
|
39
|
+
crv: z.ZodLiteral<"P-256">;
|
|
40
|
+
x: z.ZodString;
|
|
41
|
+
y: z.ZodString;
|
|
42
|
+
d: z.ZodString;
|
|
43
|
+
key_ops: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
44
|
+
ext: z.ZodOptional<z.ZodBoolean>;
|
|
45
|
+
}, "strict", z.ZodTypeAny, {
|
|
46
|
+
kty: "EC";
|
|
47
|
+
crv: "P-256";
|
|
48
|
+
x: string;
|
|
49
|
+
y: string;
|
|
50
|
+
d: string;
|
|
51
|
+
key_ops?: string[] | undefined;
|
|
52
|
+
ext?: boolean | undefined;
|
|
53
|
+
}, {
|
|
54
|
+
kty: "EC";
|
|
55
|
+
crv: "P-256";
|
|
56
|
+
x: string;
|
|
57
|
+
y: string;
|
|
58
|
+
d: string;
|
|
59
|
+
key_ops?: string[] | undefined;
|
|
60
|
+
ext?: boolean | undefined;
|
|
61
|
+
}>;
|
|
62
|
+
accountBootstrap: z.ZodOptional<z.ZodObject<{
|
|
63
|
+
history: z.ZodType<import("../account-protocol.js").AccountHistory, z.ZodTypeDef, import("../account-protocol.js").AccountHistory>;
|
|
64
|
+
checkpoint: z.ZodObject<{
|
|
65
|
+
version: z.ZodLiteral<1>;
|
|
66
|
+
ownerId: z.ZodString;
|
|
67
|
+
rootId: z.ZodString;
|
|
68
|
+
head: z.ZodString;
|
|
69
|
+
revision: z.ZodNumber;
|
|
70
|
+
devices: z.ZodArray<z.ZodObject<{
|
|
71
|
+
endpoint: z.ZodEffects<z.ZodObject<{
|
|
72
|
+
version: z.ZodLiteral<1>;
|
|
73
|
+
id: z.ZodString;
|
|
74
|
+
ownerId: z.ZodString;
|
|
75
|
+
kind: z.ZodEnum<["bridge", "browser", "mcp", "local-cli"]>;
|
|
76
|
+
publicKey: z.ZodString;
|
|
77
|
+
}, "strict", z.ZodTypeAny, {
|
|
78
|
+
id: string;
|
|
79
|
+
version: 1;
|
|
80
|
+
ownerId: string;
|
|
81
|
+
kind: "bridge" | "browser" | "mcp" | "local-cli";
|
|
82
|
+
publicKey: string;
|
|
83
|
+
}, {
|
|
84
|
+
id: string;
|
|
85
|
+
version: 1;
|
|
86
|
+
ownerId: string;
|
|
87
|
+
kind: "bridge" | "browser" | "mcp" | "local-cli";
|
|
88
|
+
publicKey: string;
|
|
89
|
+
}>, {
|
|
90
|
+
id: string;
|
|
91
|
+
version: 1;
|
|
92
|
+
ownerId: string;
|
|
93
|
+
kind: "bridge" | "browser" | "mcp" | "local-cli";
|
|
94
|
+
publicKey: string;
|
|
95
|
+
}, {
|
|
96
|
+
id: string;
|
|
97
|
+
version: 1;
|
|
98
|
+
ownerId: string;
|
|
99
|
+
kind: "bridge" | "browser" | "mcp" | "local-cli";
|
|
100
|
+
publicKey: string;
|
|
101
|
+
}>;
|
|
102
|
+
signingPublicKey: z.ZodString;
|
|
103
|
+
label: z.ZodString;
|
|
104
|
+
approvedAt: z.ZodString;
|
|
105
|
+
}, "strict", z.ZodTypeAny, {
|
|
106
|
+
endpoint: {
|
|
107
|
+
id: string;
|
|
108
|
+
version: 1;
|
|
109
|
+
ownerId: string;
|
|
110
|
+
kind: "bridge" | "browser" | "mcp" | "local-cli";
|
|
111
|
+
publicKey: string;
|
|
112
|
+
};
|
|
113
|
+
label: string;
|
|
114
|
+
approvedAt: string;
|
|
115
|
+
signingPublicKey: string;
|
|
116
|
+
}, {
|
|
117
|
+
endpoint: {
|
|
118
|
+
id: string;
|
|
119
|
+
version: 1;
|
|
120
|
+
ownerId: string;
|
|
121
|
+
kind: "bridge" | "browser" | "mcp" | "local-cli";
|
|
122
|
+
publicKey: string;
|
|
123
|
+
};
|
|
124
|
+
label: string;
|
|
125
|
+
approvedAt: string;
|
|
126
|
+
signingPublicKey: string;
|
|
127
|
+
}>, "many">;
|
|
128
|
+
bridges: z.ZodArray<z.ZodObject<{
|
|
129
|
+
bridgeId: z.ZodString;
|
|
130
|
+
endpoint: z.ZodEffects<z.ZodObject<{
|
|
131
|
+
version: z.ZodLiteral<1>;
|
|
132
|
+
id: z.ZodString;
|
|
133
|
+
ownerId: z.ZodString;
|
|
134
|
+
kind: z.ZodEnum<["bridge", "browser", "mcp", "local-cli"]>;
|
|
135
|
+
publicKey: z.ZodString;
|
|
136
|
+
}, "strict", z.ZodTypeAny, {
|
|
137
|
+
id: string;
|
|
138
|
+
version: 1;
|
|
139
|
+
ownerId: string;
|
|
140
|
+
kind: "bridge" | "browser" | "mcp" | "local-cli";
|
|
141
|
+
publicKey: string;
|
|
142
|
+
}, {
|
|
143
|
+
id: string;
|
|
144
|
+
version: 1;
|
|
145
|
+
ownerId: string;
|
|
146
|
+
kind: "bridge" | "browser" | "mcp" | "local-cli";
|
|
147
|
+
publicKey: string;
|
|
148
|
+
}>, {
|
|
149
|
+
id: string;
|
|
150
|
+
version: 1;
|
|
151
|
+
ownerId: string;
|
|
152
|
+
kind: "bridge" | "browser" | "mcp" | "local-cli";
|
|
153
|
+
publicKey: string;
|
|
154
|
+
}, {
|
|
155
|
+
id: string;
|
|
156
|
+
version: 1;
|
|
157
|
+
ownerId: string;
|
|
158
|
+
kind: "bridge" | "browser" | "mcp" | "local-cli";
|
|
159
|
+
publicKey: string;
|
|
160
|
+
}>;
|
|
161
|
+
label: z.ZodString;
|
|
162
|
+
approvedAt: z.ZodString;
|
|
163
|
+
}, "strict", z.ZodTypeAny, {
|
|
164
|
+
bridgeId: string;
|
|
165
|
+
endpoint: {
|
|
166
|
+
id: string;
|
|
167
|
+
version: 1;
|
|
168
|
+
ownerId: string;
|
|
169
|
+
kind: "bridge" | "browser" | "mcp" | "local-cli";
|
|
170
|
+
publicKey: string;
|
|
171
|
+
};
|
|
172
|
+
label: string;
|
|
173
|
+
approvedAt: string;
|
|
174
|
+
}, {
|
|
175
|
+
bridgeId: string;
|
|
176
|
+
endpoint: {
|
|
177
|
+
id: string;
|
|
178
|
+
version: 1;
|
|
179
|
+
ownerId: string;
|
|
180
|
+
kind: "bridge" | "browser" | "mcp" | "local-cli";
|
|
181
|
+
publicKey: string;
|
|
182
|
+
};
|
|
183
|
+
label: string;
|
|
184
|
+
approvedAt: string;
|
|
185
|
+
}>, "many">;
|
|
186
|
+
revokedDeviceIds: z.ZodArray<z.ZodString, "many">;
|
|
187
|
+
revokedBridgeIds: z.ZodArray<z.ZodString, "many">;
|
|
188
|
+
}, "strict", z.ZodTypeAny, {
|
|
189
|
+
version: 1;
|
|
190
|
+
ownerId: string;
|
|
191
|
+
rootId: string;
|
|
192
|
+
revision: number;
|
|
193
|
+
head: string;
|
|
194
|
+
devices: {
|
|
195
|
+
endpoint: {
|
|
196
|
+
id: string;
|
|
197
|
+
version: 1;
|
|
198
|
+
ownerId: string;
|
|
199
|
+
kind: "bridge" | "browser" | "mcp" | "local-cli";
|
|
200
|
+
publicKey: string;
|
|
201
|
+
};
|
|
202
|
+
label: string;
|
|
203
|
+
approvedAt: string;
|
|
204
|
+
signingPublicKey: string;
|
|
205
|
+
}[];
|
|
206
|
+
bridges: {
|
|
207
|
+
bridgeId: string;
|
|
208
|
+
endpoint: {
|
|
209
|
+
id: string;
|
|
210
|
+
version: 1;
|
|
211
|
+
ownerId: string;
|
|
212
|
+
kind: "bridge" | "browser" | "mcp" | "local-cli";
|
|
213
|
+
publicKey: string;
|
|
214
|
+
};
|
|
215
|
+
label: string;
|
|
216
|
+
approvedAt: string;
|
|
217
|
+
}[];
|
|
218
|
+
revokedDeviceIds: string[];
|
|
219
|
+
revokedBridgeIds: string[];
|
|
220
|
+
}, {
|
|
221
|
+
version: 1;
|
|
222
|
+
ownerId: string;
|
|
223
|
+
rootId: string;
|
|
224
|
+
revision: number;
|
|
225
|
+
head: string;
|
|
226
|
+
devices: {
|
|
227
|
+
endpoint: {
|
|
228
|
+
id: string;
|
|
229
|
+
version: 1;
|
|
230
|
+
ownerId: string;
|
|
231
|
+
kind: "bridge" | "browser" | "mcp" | "local-cli";
|
|
232
|
+
publicKey: string;
|
|
233
|
+
};
|
|
234
|
+
label: string;
|
|
235
|
+
approvedAt: string;
|
|
236
|
+
signingPublicKey: string;
|
|
237
|
+
}[];
|
|
238
|
+
bridges: {
|
|
239
|
+
bridgeId: string;
|
|
240
|
+
endpoint: {
|
|
241
|
+
id: string;
|
|
242
|
+
version: 1;
|
|
243
|
+
ownerId: string;
|
|
244
|
+
kind: "bridge" | "browser" | "mcp" | "local-cli";
|
|
245
|
+
publicKey: string;
|
|
246
|
+
};
|
|
247
|
+
label: string;
|
|
248
|
+
approvedAt: string;
|
|
249
|
+
}[];
|
|
250
|
+
revokedDeviceIds: string[];
|
|
251
|
+
revokedBridgeIds: string[];
|
|
252
|
+
}>;
|
|
253
|
+
}, "strict", z.ZodTypeAny, {
|
|
254
|
+
history: import("../account-protocol.js").AccountHistory;
|
|
255
|
+
checkpoint: {
|
|
256
|
+
version: 1;
|
|
257
|
+
ownerId: string;
|
|
258
|
+
rootId: string;
|
|
259
|
+
revision: number;
|
|
260
|
+
head: string;
|
|
261
|
+
devices: {
|
|
262
|
+
endpoint: {
|
|
263
|
+
id: string;
|
|
264
|
+
version: 1;
|
|
265
|
+
ownerId: string;
|
|
266
|
+
kind: "bridge" | "browser" | "mcp" | "local-cli";
|
|
267
|
+
publicKey: string;
|
|
268
|
+
};
|
|
269
|
+
label: string;
|
|
270
|
+
approvedAt: string;
|
|
271
|
+
signingPublicKey: string;
|
|
272
|
+
}[];
|
|
273
|
+
bridges: {
|
|
274
|
+
bridgeId: string;
|
|
275
|
+
endpoint: {
|
|
276
|
+
id: string;
|
|
277
|
+
version: 1;
|
|
278
|
+
ownerId: string;
|
|
279
|
+
kind: "bridge" | "browser" | "mcp" | "local-cli";
|
|
280
|
+
publicKey: string;
|
|
281
|
+
};
|
|
282
|
+
label: string;
|
|
283
|
+
approvedAt: string;
|
|
284
|
+
}[];
|
|
285
|
+
revokedDeviceIds: string[];
|
|
286
|
+
revokedBridgeIds: string[];
|
|
287
|
+
};
|
|
288
|
+
}, {
|
|
289
|
+
history: import("../account-protocol.js").AccountHistory;
|
|
290
|
+
checkpoint: {
|
|
291
|
+
version: 1;
|
|
292
|
+
ownerId: string;
|
|
293
|
+
rootId: string;
|
|
294
|
+
revision: number;
|
|
295
|
+
head: string;
|
|
296
|
+
devices: {
|
|
297
|
+
endpoint: {
|
|
298
|
+
id: string;
|
|
299
|
+
version: 1;
|
|
300
|
+
ownerId: string;
|
|
301
|
+
kind: "bridge" | "browser" | "mcp" | "local-cli";
|
|
302
|
+
publicKey: string;
|
|
303
|
+
};
|
|
304
|
+
label: string;
|
|
305
|
+
approvedAt: string;
|
|
306
|
+
signingPublicKey: string;
|
|
307
|
+
}[];
|
|
308
|
+
bridges: {
|
|
309
|
+
bridgeId: string;
|
|
310
|
+
endpoint: {
|
|
311
|
+
id: string;
|
|
312
|
+
version: 1;
|
|
313
|
+
ownerId: string;
|
|
314
|
+
kind: "bridge" | "browser" | "mcp" | "local-cli";
|
|
315
|
+
publicKey: string;
|
|
316
|
+
};
|
|
317
|
+
label: string;
|
|
318
|
+
approvedAt: string;
|
|
319
|
+
}[];
|
|
320
|
+
revokedDeviceIds: string[];
|
|
321
|
+
revokedBridgeIds: string[];
|
|
322
|
+
};
|
|
323
|
+
}>>;
|
|
324
|
+
}, "strict", z.ZodTypeAny, {
|
|
325
|
+
version: 1;
|
|
326
|
+
endpoint: {
|
|
327
|
+
id: string;
|
|
328
|
+
version: 1;
|
|
329
|
+
ownerId: string;
|
|
330
|
+
kind: "bridge" | "browser" | "mcp" | "local-cli";
|
|
331
|
+
publicKey: string;
|
|
332
|
+
};
|
|
333
|
+
privateKey: {
|
|
334
|
+
kty: "EC";
|
|
335
|
+
crv: "P-256";
|
|
336
|
+
x: string;
|
|
337
|
+
y: string;
|
|
338
|
+
d: string;
|
|
339
|
+
key_ops?: string[] | undefined;
|
|
340
|
+
ext?: boolean | undefined;
|
|
341
|
+
};
|
|
342
|
+
accountBootstrap?: {
|
|
343
|
+
history: import("../account-protocol.js").AccountHistory;
|
|
344
|
+
checkpoint: {
|
|
345
|
+
version: 1;
|
|
346
|
+
ownerId: string;
|
|
347
|
+
rootId: string;
|
|
348
|
+
revision: number;
|
|
349
|
+
head: string;
|
|
350
|
+
devices: {
|
|
351
|
+
endpoint: {
|
|
352
|
+
id: string;
|
|
353
|
+
version: 1;
|
|
354
|
+
ownerId: string;
|
|
355
|
+
kind: "bridge" | "browser" | "mcp" | "local-cli";
|
|
356
|
+
publicKey: string;
|
|
357
|
+
};
|
|
358
|
+
label: string;
|
|
359
|
+
approvedAt: string;
|
|
360
|
+
signingPublicKey: string;
|
|
361
|
+
}[];
|
|
362
|
+
bridges: {
|
|
363
|
+
bridgeId: string;
|
|
364
|
+
endpoint: {
|
|
365
|
+
id: string;
|
|
366
|
+
version: 1;
|
|
367
|
+
ownerId: string;
|
|
368
|
+
kind: "bridge" | "browser" | "mcp" | "local-cli";
|
|
369
|
+
publicKey: string;
|
|
370
|
+
};
|
|
371
|
+
label: string;
|
|
372
|
+
approvedAt: string;
|
|
373
|
+
}[];
|
|
374
|
+
revokedDeviceIds: string[];
|
|
375
|
+
revokedBridgeIds: string[];
|
|
376
|
+
};
|
|
377
|
+
} | undefined;
|
|
378
|
+
}, {
|
|
379
|
+
version: 1;
|
|
380
|
+
endpoint: {
|
|
381
|
+
id: string;
|
|
382
|
+
version: 1;
|
|
383
|
+
ownerId: string;
|
|
384
|
+
kind: "bridge" | "browser" | "mcp" | "local-cli";
|
|
385
|
+
publicKey: string;
|
|
386
|
+
};
|
|
387
|
+
privateKey: {
|
|
388
|
+
kty: "EC";
|
|
389
|
+
crv: "P-256";
|
|
390
|
+
x: string;
|
|
391
|
+
y: string;
|
|
392
|
+
d: string;
|
|
393
|
+
key_ops?: string[] | undefined;
|
|
394
|
+
ext?: boolean | undefined;
|
|
395
|
+
};
|
|
396
|
+
accountBootstrap?: {
|
|
397
|
+
history: import("../account-protocol.js").AccountHistory;
|
|
398
|
+
checkpoint: {
|
|
399
|
+
version: 1;
|
|
400
|
+
ownerId: string;
|
|
401
|
+
rootId: string;
|
|
402
|
+
revision: number;
|
|
403
|
+
head: string;
|
|
404
|
+
devices: {
|
|
405
|
+
endpoint: {
|
|
406
|
+
id: string;
|
|
407
|
+
version: 1;
|
|
408
|
+
ownerId: string;
|
|
409
|
+
kind: "bridge" | "browser" | "mcp" | "local-cli";
|
|
410
|
+
publicKey: string;
|
|
411
|
+
};
|
|
412
|
+
label: string;
|
|
413
|
+
approvedAt: string;
|
|
414
|
+
signingPublicKey: string;
|
|
415
|
+
}[];
|
|
416
|
+
bridges: {
|
|
417
|
+
bridgeId: string;
|
|
418
|
+
endpoint: {
|
|
419
|
+
id: string;
|
|
420
|
+
version: 1;
|
|
421
|
+
ownerId: string;
|
|
422
|
+
kind: "bridge" | "browser" | "mcp" | "local-cli";
|
|
423
|
+
publicKey: string;
|
|
424
|
+
};
|
|
425
|
+
label: string;
|
|
426
|
+
approvedAt: string;
|
|
427
|
+
}[];
|
|
428
|
+
revokedDeviceIds: string[];
|
|
429
|
+
revokedBridgeIds: string[];
|
|
430
|
+
};
|
|
431
|
+
} | undefined;
|
|
432
|
+
}>;
|
|
2
433
|
/** OS-local persisted keys; corruption/wrong owner never silently generates a replacement identity. */
|
|
3
434
|
export declare function loadOrCreateIdentity(dataDir: string, ownerId: string, kind: 'bridge' | 'local-cli'): Promise<EndpointIdentity>;
|
|
4
435
|
export declare function isLocalIdentityKind(kind: EndpointKind): kind is 'bridge' | 'local-cli';
|
|
5
436
|
export declare function loadLocalIdentity(dataDir: string, ownerId: string): Promise<EndpointIdentity>;
|
|
437
|
+
/** Absence alone permits virgin onboarding; corruption must never generate a new key/root. */
|
|
438
|
+
export declare function readBoundBridgeIdentity(dataDir: string): Promise<{
|
|
439
|
+
identity: EndpointIdentity;
|
|
440
|
+
bootstrap?: VerifiedAccountTrust;
|
|
441
|
+
} | null>;
|
|
@@ -5,16 +5,17 @@ import { generateEndpoint, importEndpoint } from '../crypto.js';
|
|
|
5
5
|
import { endpointSchema } from './metadata.js';
|
|
6
6
|
import { AtomicSnapshot } from './snapshot.js';
|
|
7
7
|
import { BridgeSecurityError } from './errors.js';
|
|
8
|
-
|
|
8
|
+
import { verifiedAccountSchema } from './account-state.js';
|
|
9
|
+
export const identityRecordSchema = z.object({ version: z.literal(1), endpoint: endpointSchema, privateKey: z.object({
|
|
9
10
|
kty: z.literal('EC'), crv: z.literal('P-256'), x: z.string(), y: z.string(), d: z.string(),
|
|
10
11
|
key_ops: z.array(z.string()).optional(), ext: z.boolean().optional(),
|
|
11
|
-
}).strict() }).strict();
|
|
12
|
+
}).strict(), accountBootstrap: verifiedAccountSchema.optional() }).strict();
|
|
12
13
|
/** OS-local persisted keys; corruption/wrong owner never silently generates a replacement identity. */
|
|
13
14
|
export async function loadOrCreateIdentity(dataDir, ownerId, kind) {
|
|
14
15
|
const generated = await generateEndpoint(ownerId, kind, true);
|
|
15
16
|
const jwk = await crypto.subtle.exportKey('jwk', generated.keyPair.privateKey);
|
|
16
|
-
const initial =
|
|
17
|
-
const store = new AtomicSnapshot(join(dataDir, 'security', `${kind}-identity.json`),
|
|
17
|
+
const initial = identityRecordSchema.parse({ version: 1, endpoint: generated.endpoint, privateKey: jwk });
|
|
18
|
+
const store = new AtomicSnapshot(join(dataDir, 'security', `${kind}-identity.json`), identityRecordSchema, () => initial);
|
|
18
19
|
const saved = await store.transact(state => {
|
|
19
20
|
if (state.endpoint.ownerId !== ownerId || state.endpoint.kind !== kind)
|
|
20
21
|
throw new BridgeSecurityError('wrong_context');
|
|
@@ -30,7 +31,7 @@ export async function loadOrCreateIdentity(dataDir, ownerId, kind) {
|
|
|
30
31
|
export function isLocalIdentityKind(kind) { return kind === 'bridge' || kind === 'local-cli'; }
|
|
31
32
|
export async function loadLocalIdentity(dataDir, ownerId) {
|
|
32
33
|
try {
|
|
33
|
-
const saved =
|
|
34
|
+
const saved = identityRecordSchema.parse(JSON.parse(await readFile(join(dataDir, 'security', 'local-cli-identity.json'), 'utf8')));
|
|
34
35
|
if (saved.endpoint.ownerId !== ownerId || saved.endpoint.kind !== 'local-cli')
|
|
35
36
|
throw new Error('Wrong local key');
|
|
36
37
|
return await importEndpoint(saved.endpoint, saved.privateKey, false);
|
|
@@ -39,4 +40,25 @@ export async function loadLocalIdentity(dataDir, ownerId) {
|
|
|
39
40
|
throw new BridgeSecurityError('key_unavailable');
|
|
40
41
|
}
|
|
41
42
|
}
|
|
43
|
+
/** Absence alone permits virgin onboarding; corruption must never generate a new key/root. */
|
|
44
|
+
export async function readBoundBridgeIdentity(dataDir) {
|
|
45
|
+
let raw;
|
|
46
|
+
try {
|
|
47
|
+
raw = await readFile(join(dataDir, 'security', 'bridge-identity.json'), 'utf8');
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
if (error.code === 'ENOENT')
|
|
51
|
+
return null;
|
|
52
|
+
throw new BridgeSecurityError('key_unavailable');
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
const record = identityRecordSchema.parse(JSON.parse(raw));
|
|
56
|
+
if (record.endpoint.kind !== 'bridge')
|
|
57
|
+
throw new BridgeSecurityError('wrong_context');
|
|
58
|
+
return { identity: await importEndpoint(record.endpoint, record.privateKey, false), bootstrap: record.accountBootstrap };
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
throw new BridgeSecurityError('key_unavailable');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
42
64
|
//# sourceMappingURL=identity.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"identity.js","sourceRoot":"","sources":["../../../src/security/bridge/identity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEhE,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"identity.js","sourceRoot":"","sources":["../../../src/security/bridge/identity.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { AccountEnrollmentLink, VerifiedAccountTrust } from '../account-protocol.js';
|
|
2
|
+
import type { EndpointIdentity } from '../protocol.js';
|
|
3
|
+
export interface PendingBridgeEnrollment {
|
|
4
|
+
identity: EndpointIdentity;
|
|
5
|
+
link: AccountEnrollmentLink;
|
|
6
|
+
}
|
|
7
|
+
export declare function prepareBridgeEnrollment(dataDir: string, bridgeId: string, label: string, now?: number): Promise<PendingBridgeEnrollment>;
|
|
8
|
+
/** URL is constructed from operator configuration, never a service-provided redirect. */
|
|
9
|
+
export declare function savePairingVerificationUrl(dataDir: string, apiUrl: string, userCode: string): Promise<string>;
|
|
10
|
+
export declare function pendingPairingLink(dataDir: string, now?: number): Promise<string>;
|
|
11
|
+
/** Save the normalized SAME private/public key and trusted bootstrap in one durable identity record. */
|
|
12
|
+
export declare function bindPendingBridgeIdentity(dataDir: string, trust: VerifiedAccountTrust): Promise<EndpointIdentity>;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { createAccountEnrollment, encodeAccountEnrollmentLink, generateAccountBridgeCandidate, importAccountBridgeCandidate, parseAccountEnrollmentLink, verifyAccountHistory } from '../account-crypto.js';
|
|
5
|
+
import { AtomicSnapshot } from './snapshot.js';
|
|
6
|
+
import { endpointSchema } from './metadata.js';
|
|
7
|
+
import { identityRecordSchema } from './identity.js';
|
|
8
|
+
import { importEndpoint } from '../crypto.js';
|
|
9
|
+
import { BridgeSecurityError } from './errors.js';
|
|
10
|
+
import { accountReadUrl } from './account-client.js';
|
|
11
|
+
const pendingSchema = z.object({ version: z.literal(1), bridgeId: z.string().regex(/^[A-Za-z0-9_-]{1,200}$/),
|
|
12
|
+
endpoint: endpointSchema, privateKey: identityRecordSchema.shape.privateKey,
|
|
13
|
+
link: z.custom(), verificationUrl: z.string().max(4096).nullable() }).strict();
|
|
14
|
+
const pendingPath = (dataDir) => join(dataDir, 'security', 'account-enrollment.json');
|
|
15
|
+
async function readPending(dataDir) {
|
|
16
|
+
let raw;
|
|
17
|
+
try {
|
|
18
|
+
raw = await readFile(pendingPath(dataDir), 'utf8');
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
if (error.code === 'ENOENT')
|
|
22
|
+
return null;
|
|
23
|
+
throw new BridgeSecurityError('account_storage_unavailable');
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
const saved = pendingSchema.parse(JSON.parse(raw));
|
|
27
|
+
encodeAccountEnrollmentLink(saved.link);
|
|
28
|
+
return saved;
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
throw new BridgeSecurityError('account_storage_unavailable');
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export async function prepareBridgeEnrollment(dataDir, bridgeId, label, now = Date.now()) {
|
|
35
|
+
const existing = await readPending(dataDir);
|
|
36
|
+
if (existing && existing.bridgeId !== bridgeId)
|
|
37
|
+
throw new BridgeSecurityError('wrong_context');
|
|
38
|
+
const unexpired = existing && typeof existing.link?.request?.expiresAt === 'string' && Date.parse(existing.link.request.expiresAt) > now;
|
|
39
|
+
let initial = existing;
|
|
40
|
+
if (!unexpired) {
|
|
41
|
+
// Expiring a request rotates its challenge/secret, never the pending bridge point.
|
|
42
|
+
// Approval may already exist remotely even when its response was lost.
|
|
43
|
+
const identity = existing ? await importAccountBridgeCandidate(existing.endpoint, existing.privateKey, false)
|
|
44
|
+
: await generateAccountBridgeCandidate(bridgeId, true);
|
|
45
|
+
initial = pendingSchema.parse({ version: 1, bridgeId, endpoint: identity.endpoint,
|
|
46
|
+
privateKey: existing?.privateKey ?? await crypto.subtle.exportKey('jwk', identity.keyPair.privateKey),
|
|
47
|
+
link: await createAccountEnrollment(identity, label.slice(0, 200), null, bridgeId, now), verificationUrl: null });
|
|
48
|
+
}
|
|
49
|
+
const store = new AtomicSnapshot(pendingPath(dataDir), pendingSchema, () => initial);
|
|
50
|
+
const saved = await store.transact(state => {
|
|
51
|
+
if (!unexpired && existing)
|
|
52
|
+
Object.assign(state, initial);
|
|
53
|
+
return state;
|
|
54
|
+
});
|
|
55
|
+
const link = await parseAccountEnrollmentLink(saved.link, now);
|
|
56
|
+
if (link.request.kind !== 'bridge' || link.request.bridgeId !== bridgeId || link.request.candidate.id !== saved.endpoint.id
|
|
57
|
+
|| link.request.candidate.publicKey !== saved.endpoint.publicKey || link.request.candidate.ownerId !== saved.endpoint.ownerId)
|
|
58
|
+
throw new BridgeSecurityError('account_enrollment_invalid');
|
|
59
|
+
return { identity: await importAccountBridgeCandidate(saved.endpoint, saved.privateKey, false), link };
|
|
60
|
+
}
|
|
61
|
+
/** URL is constructed from operator configuration, never a service-provided redirect. */
|
|
62
|
+
export async function savePairingVerificationUrl(dataDir, apiUrl, userCode) {
|
|
63
|
+
accountReadUrl(apiUrl);
|
|
64
|
+
if (!/^[A-Za-z0-9-]{1,100}$/.test(userCode))
|
|
65
|
+
throw new BridgeSecurityError('account_enrollment_invalid');
|
|
66
|
+
const url = new URL('/pair', apiUrl);
|
|
67
|
+
url.searchParams.set('code', userCode);
|
|
68
|
+
const existing = await readPending(dataDir);
|
|
69
|
+
if (!existing)
|
|
70
|
+
throw new BridgeSecurityError('account_enrollment_invalid');
|
|
71
|
+
const store = new AtomicSnapshot(pendingPath(dataDir), pendingSchema, () => existing);
|
|
72
|
+
await store.transact(state => { state.verificationUrl = url.href; });
|
|
73
|
+
return url.href;
|
|
74
|
+
}
|
|
75
|
+
export async function pendingPairingLink(dataDir, now = Date.now()) {
|
|
76
|
+
const saved = await readPending(dataDir);
|
|
77
|
+
if (!saved?.verificationUrl)
|
|
78
|
+
throw new BridgeSecurityError('account_enrollment_invalid');
|
|
79
|
+
const link = await parseAccountEnrollmentLink(saved.link, now);
|
|
80
|
+
const url = new URL(saved.verificationUrl);
|
|
81
|
+
accountReadUrl(url.origin);
|
|
82
|
+
if (url.pathname !== '/pair' || url.hash || url.username || url.password || [...url.searchParams.keys()].some(key => key !== 'code')) {
|
|
83
|
+
throw new BridgeSecurityError('account_enrollment_invalid');
|
|
84
|
+
}
|
|
85
|
+
url.hash = `account=${encodeAccountEnrollmentLink(link)}`;
|
|
86
|
+
return url.href;
|
|
87
|
+
}
|
|
88
|
+
/** Save the normalized SAME private/public key and trusted bootstrap in one durable identity record. */
|
|
89
|
+
export async function bindPendingBridgeIdentity(dataDir, trust) {
|
|
90
|
+
const pending = await readPending(dataDir);
|
|
91
|
+
if (!pending)
|
|
92
|
+
throw new BridgeSecurityError('account_enrollment_invalid');
|
|
93
|
+
const checkpoint = await verifyAccountHistory(trust.history, trust.checkpoint);
|
|
94
|
+
const own = checkpoint.bridges.find(item => item.bridgeId === pending.bridgeId);
|
|
95
|
+
if (!own || own.endpoint.id !== pending.endpoint.id || own.endpoint.publicKey !== pending.endpoint.publicKey)
|
|
96
|
+
throw new BridgeSecurityError('wrong_context');
|
|
97
|
+
await importAccountBridgeCandidate(pending.endpoint, pending.privateKey, false);
|
|
98
|
+
const record = identityRecordSchema.parse({ version: 1, endpoint: own.endpoint, privateKey: pending.privateKey,
|
|
99
|
+
accountBootstrap: { checkpoint, history: trust.history } });
|
|
100
|
+
const store = new AtomicSnapshot(join(dataDir, 'security', 'bridge-identity.json'), identityRecordSchema, () => record);
|
|
101
|
+
const saved = await store.transact(state => {
|
|
102
|
+
if (state.endpoint.id !== record.endpoint.id || state.endpoint.ownerId !== record.endpoint.ownerId
|
|
103
|
+
|| state.endpoint.publicKey !== record.endpoint.publicKey)
|
|
104
|
+
throw new BridgeSecurityError('wrong_context');
|
|
105
|
+
// A pre-existing bound identity is never repinned by repeating bootstrap.
|
|
106
|
+
if (state.accountBootstrap && state.accountBootstrap.checkpoint.rootId !== checkpoint.rootId)
|
|
107
|
+
throw new BridgeSecurityError('account_trust_rollback');
|
|
108
|
+
state.accountBootstrap ??= record.accountBootstrap;
|
|
109
|
+
return state;
|
|
110
|
+
});
|
|
111
|
+
return importEndpoint(saved.endpoint, saved.privateKey, false);
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=pending-enrollment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pending-enrollment.js","sourceRoot":"","sources":["../../../src/security/bridge/pending-enrollment.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,8 +3,8 @@ const session = /^[A-Za-z0-9_-]+$/;
|
|
|
3
3
|
const readCommands = new Set(['list_sessions', 'get_history', 'get_session_usage', 'get_sessions_usage', 'get_session_attention']);
|
|
4
4
|
const controlCommands = new Set(['create_session', 'stop_session', 'retry_session', 'send_message', 'rename_session', 'remove_session',
|
|
5
5
|
'bridge_exec', 'clear_terminal', 'update_session_parent', 'resolve_session_attention']);
|
|
6
|
-
const adminCommands = new Set(['security_devices', 'security_invite', 'security_revoke', 'security_approve_mcp', 'security_activity']);
|
|
7
|
-
const result = (permission, operation, sessionId = null) => ({ permission, mutating: permission === 'control' || ['security_invite', 'security_revoke', 'security_approve_mcp'].includes(operation), operation, sessionId });
|
|
6
|
+
const adminCommands = new Set(['security_devices', 'security_invite', 'security_revoke', 'security_approve_mcp', 'security_activity', 'security_account_adopt']);
|
|
7
|
+
const result = (permission, operation, sessionId = null) => ({ permission, mutating: permission === 'control' || ['security_invite', 'security_revoke', 'security_approve_mcp', 'security_account_adopt'].includes(operation), operation, sessionId });
|
|
8
8
|
const deny = () => { throw new BridgeSecurityError('permission_denied'); };
|
|
9
9
|
const object = (value) => value !== null && typeof value === 'object' && !Array.isArray(value) ? value : undefined;
|
|
10
10
|
/** Deliberately semantic: GET inbox consumes mail unless explicitly non-consuming. */
|