@dharma-ai-labs/agent-fabric 0.2.109 → 0.2.111
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/README.md +41 -0
- package/dist/codexInboxSession.d.ts +1 -1
- package/dist/cooperativeInboxSession.d.ts +1 -1
- package/dist/demoDeviceTransport.d.ts +33 -0
- package/dist/demoDeviceTransport.d.ts.map +1 -0
- package/dist/demoDeviceTransport.js +52 -0
- package/dist/demoDeviceTransport.js.map +1 -0
- package/dist/demoDeviceTransport.test.d.ts +2 -0
- package/dist/demoDeviceTransport.test.d.ts.map +1 -0
- package/dist/demoDeviceTransport.test.js +178 -0
- package/dist/demoDeviceTransport.test.js.map +1 -0
- package/dist/demoEnrollment.d.ts +2 -1
- package/dist/demoEnrollment.d.ts.map +1 -1
- package/dist/demoEnrollment.js +99 -21
- package/dist/demoEnrollment.js.map +1 -1
- package/dist/demoEnrollment.test.js +288 -2
- package/dist/demoEnrollment.test.js.map +1 -1
- package/dist/demoPackage.js +1 -1
- package/dist/demoPackage.js.map +1 -1
- package/dist/demoSigningTrust.d.ts +24 -0
- package/dist/demoSigningTrust.d.ts.map +1 -0
- package/dist/demoSigningTrust.js +326 -0
- package/dist/demoSigningTrust.js.map +1 -0
- package/dist/demoSigningTrust.test.d.ts +2 -0
- package/dist/demoSigningTrust.test.d.ts.map +1 -0
- package/dist/demoSigningTrust.test.js +445 -0
- package/dist/demoSigningTrust.test.js.map +1 -0
- package/dist/demoSigningUpgradeProof.d.ts +52 -0
- package/dist/demoSigningUpgradeProof.d.ts.map +1 -0
- package/dist/demoSigningUpgradeProof.js +137 -0
- package/dist/demoSigningUpgradeProof.js.map +1 -0
- package/dist/demoSigningUpgradeProof.test.d.ts +2 -0
- package/dist/demoSigningUpgradeProof.test.d.ts.map +1 -0
- package/dist/demoSigningUpgradeProof.test.js +564 -0
- package/dist/demoSigningUpgradeProof.test.js.map +1 -0
- package/dist/demoSigningUpgradeSubmission.d.ts +21 -0
- package/dist/demoSigningUpgradeSubmission.d.ts.map +1 -0
- package/dist/demoSigningUpgradeSubmission.js +178 -0
- package/dist/demoSigningUpgradeSubmission.js.map +1 -0
- package/dist/demoSupervisor.d.ts.map +1 -1
- package/dist/demoSupervisor.js +2 -1
- package/dist/demoSupervisor.js.map +1 -1
- package/dist/demoSupervisor.test.js +35 -0
- package/dist/demoSupervisor.test.js.map +1 -1
- package/dist/demoTransportCommand.test.d.ts +2 -0
- package/dist/demoTransportCommand.test.d.ts.map +1 -0
- package/dist/demoTransportCommand.test.js +28 -0
- package/dist/demoTransportCommand.test.js.map +1 -0
- package/dist/demoTransportContinuity.d.ts +39 -0
- package/dist/demoTransportContinuity.d.ts.map +1 -0
- package/dist/demoTransportContinuity.js +82 -0
- package/dist/demoTransportContinuity.js.map +1 -0
- package/dist/demoTransportContinuity.test.d.ts +2 -0
- package/dist/demoTransportContinuity.test.d.ts.map +1 -0
- package/dist/demoTransportContinuity.test.js +145 -0
- package/dist/demoTransportContinuity.test.js.map +1 -0
- package/dist/demoTransportFetch.d.ts +12 -0
- package/dist/demoTransportFetch.d.ts.map +1 -0
- package/dist/demoTransportFetch.js +109 -0
- package/dist/demoTransportFetch.js.map +1 -0
- package/dist/demoTransportFetch.test.d.ts +2 -0
- package/dist/demoTransportFetch.test.d.ts.map +1 -0
- package/dist/demoTransportFetch.test.js +150 -0
- package/dist/demoTransportFetch.test.js.map +1 -0
- package/dist/demoTransportRequest.d.ts +35 -0
- package/dist/demoTransportRequest.d.ts.map +1 -0
- package/dist/demoTransportRequest.js +193 -0
- package/dist/demoTransportRequest.js.map +1 -0
- package/dist/demoTransportRequest.test.d.ts +2 -0
- package/dist/demoTransportRequest.test.d.ts.map +1 -0
- package/dist/demoTransportRequest.test.js +203 -0
- package/dist/demoTransportRequest.test.js.map +1 -0
- package/dist/demoTransportState.d.ts +31 -0
- package/dist/demoTransportState.d.ts.map +1 -0
- package/dist/demoTransportState.js +204 -0
- package/dist/demoTransportState.js.map +1 -0
- package/dist/demoTransportState.test.d.ts +2 -0
- package/dist/demoTransportState.test.d.ts.map +1 -0
- package/dist/demoTransportState.test.js +192 -0
- package/dist/demoTransportState.test.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +46 -13
- package/dist/index.js.map +1 -1
- package/dist/providerSessionReplyRecovery.d.ts +1 -1
- package/dist/relaySupervisor.test.js +3 -1
- package/dist/relaySupervisor.test.js.map +1 -1
- package/dist/schemas/demo-enrollment-approval.schema.json +19 -0
- package/dist/schemas/demo-signing-update.schema.json +18 -0
- package/dist/schemas/demo-transport-continuity.schema.json +27 -0
- package/dist/schemas/demo-transport-journal.schema.json +13 -0
- package/dist/schemas/demo-transport-request.schema.json +27 -0
- package/dist/schemas/demo-transport-state.schema.json +13 -0
- package/dist/schemas/lifecycle-event.schema.json +178 -0
- package/dist/schemas/signing-upgrade-context.schema.json +28 -0
- package/dist/schemas/signing-upgrade-source.schema.json +32 -0
- package/dist/usage.d.ts +1 -1
- package/dist/usage.d.ts.map +1 -1
- package/dist/usage.js +1 -1
- package/dist/usage.js.map +1 -1
- package/package.json +2 -1
package/dist/demoEnrollment.js
CHANGED
|
@@ -3,6 +3,7 @@ import { chmod, mkdir, readFile, rename, unlink, writeFile } from 'node:fs/promi
|
|
|
3
3
|
import { dirname, resolve } from 'node:path';
|
|
4
4
|
import { loadOrCreateDeviceIdentity, normalizeHqUrl } from '@dharma-ai-labs/agent-fabric-relay-client';
|
|
5
5
|
import { verifyInitialServerSigningKeyset } from '@dharma-ai-labs/agent-fabric-contracts';
|
|
6
|
+
import { acceptDemoSigningUpdate, recoverDemoSigningEnrollment, resolveDemoSigningTrust } from './demoSigningTrust.js';
|
|
6
7
|
const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
7
8
|
const CODE = /^[A-Za-z0-9_-]{43}$/;
|
|
8
9
|
const BROWSER_CODE = /^[0-9A-F]{20}$/;
|
|
@@ -54,9 +55,12 @@ export function scopePath(input, origin) {
|
|
|
54
55
|
.digest('hex').slice(0, 32);
|
|
55
56
|
return resolve(input.stateRoot, 'demo', scope, 'device.json');
|
|
56
57
|
}
|
|
57
|
-
export async function loadDemoSigningTrust(input) {
|
|
58
|
-
const
|
|
58
|
+
export async function loadDemoSigningTrust(input, deps = {}) {
|
|
59
|
+
const origin = normalizeHqUrl(input.hqUrl);
|
|
60
|
+
const configPath = scopePath(input, origin);
|
|
61
|
+
const config = JSON.parse(await readFile(configPath, 'utf8'));
|
|
59
62
|
if (config.schema !== 'dharma.demo-device/v1' || !config.signedReady
|
|
63
|
+
|| config.hqUrl !== origin || !UUID.test(config.deviceId)
|
|
60
64
|
|| config.organizationId !== input.organizationId || config.repositoryId !== input.repositoryId
|
|
61
65
|
|| config.normalizedRepository !== input.normalizedRepository
|
|
62
66
|
|| config.installationId !== input.installationId
|
|
@@ -64,12 +68,20 @@ export async function loadDemoSigningTrust(input) {
|
|
|
64
68
|
|| !config.serverSigningKeyset) {
|
|
65
69
|
throw new Error('Demo signing trust is not pinned to this approved device. Re-enroll through browser approval.');
|
|
66
70
|
}
|
|
71
|
+
const identity = await loadOrCreateDeviceIdentity({ hqUrl: origin,
|
|
72
|
+
organizationId: `${input.organizationId}:${input.repositoryId}`,
|
|
73
|
+
installationId: input.installationId, store: deps.store });
|
|
74
|
+
if (config.publicKeyEd25519 !== identity.publicKeyEd25519) {
|
|
75
|
+
throw new Error('Demo signing trust does not match its protected device identity.');
|
|
76
|
+
}
|
|
77
|
+
const trusted = await resolveDemoSigningTrust(config, deps);
|
|
78
|
+
if (trusted.serverPublicKeyEd25519 !== config.serverPublicKeyEd25519
|
|
79
|
+
|| JSON.stringify(trusted.serverSigningKeyset) !== JSON.stringify(config.serverSigningKeyset)) {
|
|
80
|
+
await writePrivateJson(configPath, trusted);
|
|
81
|
+
}
|
|
67
82
|
const publicKey = createPublicKey({ key: { kty: 'OKP', crv: 'Ed25519',
|
|
68
|
-
x:
|
|
69
|
-
|
|
70
|
-
if (!verification.ok)
|
|
71
|
-
throw new Error(`Demo signing trust is invalid: ${verification.reason}.`);
|
|
72
|
-
return { publicKey, keyset: config.serverSigningKeyset, deviceId: config.deviceId };
|
|
83
|
+
x: trusted.serverPublicKeyEd25519 }, format: 'jwk' });
|
|
84
|
+
return { publicKey, keyset: trusted.serverSigningKeyset, deviceId: config.deviceId };
|
|
73
85
|
}
|
|
74
86
|
async function writePrivateJson(path, value) {
|
|
75
87
|
const directory = dirname(path);
|
|
@@ -102,9 +114,11 @@ function approvalUri(value, origin, input) {
|
|
|
102
114
|
}
|
|
103
115
|
return url.toString();
|
|
104
116
|
}
|
|
105
|
-
function signedStatusRequest(origin, input, deviceId, privateJwk, sequence) {
|
|
117
|
+
function signedStatusRequest(origin, input, deviceId, privateJwk, sequence, signingGeneration) {
|
|
106
118
|
const url = new URL(`/api/demo/fabric/repositories/${input.repositoryId}/status`, origin);
|
|
107
119
|
url.searchParams.set('orgId', input.organizationId);
|
|
120
|
+
if (signingGeneration !== undefined)
|
|
121
|
+
url.searchParams.set('signingGeneration', String(signingGeneration));
|
|
108
122
|
const sessionId = randomUUID();
|
|
109
123
|
const messageId = randomUUID();
|
|
110
124
|
const timestamp = new Date().toISOString();
|
|
@@ -130,7 +144,7 @@ export async function verifyDemoDevice(input, deps = {}) {
|
|
|
130
144
|
const origin = normalizeHqUrl(input.hqUrl);
|
|
131
145
|
const configPath = scopePath(input, origin);
|
|
132
146
|
const pendingPath = `${configPath}.pending-status.json`;
|
|
133
|
-
|
|
147
|
+
let config = JSON.parse(await readFile(configPath, 'utf8'));
|
|
134
148
|
if (config.schema !== 'dharma.demo-device/v1' || config.hqUrl !== origin
|
|
135
149
|
|| config.organizationId !== input.organizationId || config.repositoryId !== input.repositoryId
|
|
136
150
|
|| config.normalizedRepository !== input.normalizedRepository
|
|
@@ -144,19 +158,25 @@ export async function verifyDemoDevice(input, deps = {}) {
|
|
|
144
158
|
if (config.publicKeyEd25519 !== identity.publicKeyEd25519) {
|
|
145
159
|
throw new Error('Demo device key does not match its protected local identity.');
|
|
146
160
|
}
|
|
161
|
+
if (config.serverSigningKeyset)
|
|
162
|
+
config = await resolveDemoSigningTrust(config, { store: deps.store });
|
|
147
163
|
let hasPending = false;
|
|
148
|
-
let pending = signedStatusRequest(origin, input, config.deviceId, identity.privateJwk, config.nextSequence);
|
|
164
|
+
let pending = signedStatusRequest(origin, input, config.deviceId, identity.privateJwk, config.nextSequence, config.serverSigningKeyset?.generation);
|
|
149
165
|
try {
|
|
150
166
|
const existing = JSON.parse(await readFile(pendingPath, 'utf8'));
|
|
151
|
-
|
|
167
|
+
const existingUrl = new URL(existing.url);
|
|
168
|
+
existingUrl.searchParams.delete('signingGeneration');
|
|
169
|
+
const expectedUrl = new URL(pending.url);
|
|
170
|
+
expectedUrl.searchParams.delete('signingGeneration');
|
|
171
|
+
if (existing.deviceId !== config.deviceId || existingUrl.toString() !== expectedUrl.toString()
|
|
152
172
|
|| !Number.isSafeInteger(existing.sequence) || existing.sequence < config.nextSequence
|
|
153
173
|
|| !Number.isFinite(Date.parse(existing.createdAt))) {
|
|
154
174
|
throw new Error('Pending Demo device status does not match this identity.');
|
|
155
175
|
}
|
|
156
176
|
hasPending = true;
|
|
157
|
-
pending = Date.now() - Date.parse(existing.createdAt) < 4 * 60_000
|
|
177
|
+
pending = Date.now() - Date.parse(existing.createdAt) < 4 * 60_000 && existing.url === pending.url
|
|
158
178
|
? existing
|
|
159
|
-
: signedStatusRequest(origin, input, config.deviceId, identity.privateJwk, existing.sequence);
|
|
179
|
+
: signedStatusRequest(origin, input, config.deviceId, identity.privateJwk, existing.sequence, config.serverSigningKeyset?.generation);
|
|
160
180
|
}
|
|
161
181
|
catch (error) {
|
|
162
182
|
if (error.code !== 'ENOENT') {
|
|
@@ -182,7 +202,7 @@ export async function verifyDemoDevice(input, deps = {}) {
|
|
|
182
202
|
.filter((sequence) => sequence >= config.nextSequence);
|
|
183
203
|
let recovered = false;
|
|
184
204
|
for (const sequence of candidates) {
|
|
185
|
-
pending = signedStatusRequest(origin, input, config.deviceId, identity.privateJwk, sequence);
|
|
205
|
+
pending = signedStatusRequest(origin, input, config.deviceId, identity.privateJwk, sequence, config.serverSigningKeyset?.generation);
|
|
186
206
|
try {
|
|
187
207
|
status = await requestStatus();
|
|
188
208
|
recovered = true;
|
|
@@ -205,6 +225,12 @@ export async function verifyDemoDevice(input, deps = {}) {
|
|
|
205
225
|
config.nextSequence = pending.sequence + 1;
|
|
206
226
|
await writePrivateJson(configPath, config);
|
|
207
227
|
await unlink(pendingPath).catch(() => { });
|
|
228
|
+
// Sequence consumption is saved even when a delivered trust update is rejected.
|
|
229
|
+
// No acknowledgement or package activation occurs until protected storage confirms it.
|
|
230
|
+
if (status.signingTrustUpdate !== undefined) {
|
|
231
|
+
config = await acceptDemoSigningUpdate(config, status.signingTrustUpdate, { store: deps.store });
|
|
232
|
+
await writePrivateJson(configPath, config);
|
|
233
|
+
}
|
|
208
234
|
return { ok: true, stage: 'device_signed_ready',
|
|
209
235
|
organizationId: input.organizationId, repositoryId: input.repositoryId,
|
|
210
236
|
normalizedRepository: input.normalizedRepository, deviceId: config.deviceId,
|
|
@@ -235,6 +261,8 @@ export async function connectDemoDevice(input, deps = {}) {
|
|
|
235
261
|
let deviceId = '';
|
|
236
262
|
let serverPublicKeyEd25519 = '';
|
|
237
263
|
let serverSigningKeyset;
|
|
264
|
+
let signingTrustUpdate;
|
|
265
|
+
let enrollmentApproval;
|
|
238
266
|
let transientFailures = 0;
|
|
239
267
|
while (Date.now() < deadline) {
|
|
240
268
|
let polled;
|
|
@@ -268,6 +296,8 @@ export async function connectDemoDevice(input, deps = {}) {
|
|
|
268
296
|
const verification = verifyInitialServerSigningKeyset(serverSigningKeyset, createPublicKey({ key: { kty: 'OKP', crv: 'Ed25519', x: serverPublicKeyEd25519 }, format: 'jwk' }), input.organizationId);
|
|
269
297
|
if (!verification.ok)
|
|
270
298
|
throw new Error(`Demo enrollment signing trust was rejected: ${verification.reason}.`);
|
|
299
|
+
signingTrustUpdate = polled.signingTrustUpdate;
|
|
300
|
+
enrollmentApproval = polled.enrollmentApproval;
|
|
271
301
|
break;
|
|
272
302
|
}
|
|
273
303
|
if (polled.status !== 'pending')
|
|
@@ -278,26 +308,74 @@ export async function connectDemoDevice(input, deps = {}) {
|
|
|
278
308
|
throw new Error('Demo device approval timed out. Resume from the same prompt while its grant is valid.');
|
|
279
309
|
const configPath = scopePath(input, origin);
|
|
280
310
|
try {
|
|
281
|
-
|
|
282
|
-
if (existing.
|
|
311
|
+
let existing = JSON.parse(await readFile(configPath, 'utf8'));
|
|
312
|
+
if (existing.schema !== 'dharma.demo-device/v1' || existing.hqUrl !== origin
|
|
313
|
+
|| existing.organizationId !== input.organizationId || existing.repositoryId !== input.repositoryId
|
|
314
|
+
|| existing.normalizedRepository !== input.normalizedRepository || existing.installationId !== input.installationId
|
|
315
|
+
|| existing.deviceId !== deviceId || existing.publicKeyEd25519 !== identity.publicKeyEd25519) {
|
|
283
316
|
throw new Error('Existing Demo device belongs to another approved identity.');
|
|
284
317
|
}
|
|
285
|
-
if (existing.
|
|
286
|
-
|
|
318
|
+
if (existing.serverSigningKeyset) {
|
|
319
|
+
try {
|
|
320
|
+
existing = await resolveDemoSigningTrust(existing, { store: deps.store });
|
|
321
|
+
}
|
|
322
|
+
catch (error) {
|
|
323
|
+
if (!(error instanceof Error) || !error.message.startsWith('Demo signing trust rejected: expired.'))
|
|
324
|
+
throw error;
|
|
325
|
+
existing = await recoverDemoSigningEnrollment(existing, { serverPublicKeyEd25519, serverSigningKeyset }, enrollmentApproval, { store: deps.store });
|
|
326
|
+
if (signingTrustUpdate !== undefined) {
|
|
327
|
+
existing = await acceptDemoSigningUpdate(existing, signingTrustUpdate, { store: deps.store });
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
await writePrivateJson(configPath, existing);
|
|
331
|
+
}
|
|
332
|
+
// Repeated approval polling must not replace a newer protected generation
|
|
333
|
+
// with the enrollment predecessor. Signed status reconciles from its head.
|
|
334
|
+
if (!existing.serverSigningKeyset) {
|
|
335
|
+
let restored = { ...existing, serverPublicKeyEd25519, serverSigningKeyset };
|
|
336
|
+
if (signingTrustUpdate !== undefined)
|
|
337
|
+
restored = await acceptDemoSigningUpdate(restored, signingTrustUpdate, { store: deps.store });
|
|
338
|
+
await writePrivateJson(configPath, restored);
|
|
287
339
|
}
|
|
288
|
-
await writePrivateJson(configPath, { ...existing, serverPublicKeyEd25519, serverSigningKeyset });
|
|
289
340
|
return verifyDemoDevice(input, deps);
|
|
290
341
|
}
|
|
291
342
|
catch (error) {
|
|
292
343
|
if (error.code !== 'ENOENT')
|
|
293
344
|
throw error;
|
|
294
345
|
}
|
|
295
|
-
|
|
346
|
+
let config = { schema: 'dharma.demo-device/v1',
|
|
296
347
|
hqUrl: origin, organizationId: input.organizationId, repositoryId: input.repositoryId,
|
|
297
348
|
normalizedRepository: input.normalizedRepository, installationId: input.installationId,
|
|
298
349
|
deviceId, publicKeyEd25519: identity.publicKeyEd25519,
|
|
299
350
|
enrolledAt: new Date().toISOString(), signedReady: false, nextSequence: 1,
|
|
300
|
-
serverPublicKeyEd25519, serverSigningKeyset }
|
|
351
|
+
serverPublicKeyEd25519, serverSigningKeyset };
|
|
352
|
+
const pendingEnrollmentPath = `${configPath}.pending-enrollment.json`;
|
|
353
|
+
try {
|
|
354
|
+
const pending = JSON.parse(await readFile(pendingEnrollmentPath, 'utf8'));
|
|
355
|
+
if (Object.keys(pending).length !== Object.keys(config).length
|
|
356
|
+
|| Object.keys(pending).some(key => !Object.hasOwn(config, key))
|
|
357
|
+
|| pending.schema !== config.schema || pending.signedReady !== false || pending.nextSequence !== 1
|
|
358
|
+
|| !Number.isFinite(Date.parse(pending.enrolledAt)) || !pending.serverSigningKeyset
|
|
359
|
+
|| ['hqUrl', 'organizationId', 'repositoryId', 'normalizedRepository', 'installationId',
|
|
360
|
+
'deviceId', 'publicKeyEd25519', 'serverPublicKeyEd25519'].some(key => pending[key] !== config[key])) {
|
|
361
|
+
throw new Error('Pending Demo enrollment does not match the approved identity. Preserve it for recovery.');
|
|
362
|
+
}
|
|
363
|
+
config = pending;
|
|
364
|
+
}
|
|
365
|
+
catch (error) {
|
|
366
|
+
if (error.code !== 'ENOENT')
|
|
367
|
+
throw error;
|
|
368
|
+
}
|
|
369
|
+
// Persist the credential-free enrollment binding before the protected trust
|
|
370
|
+
// write. A restart can recover its exact timestamp from this intent record.
|
|
371
|
+
await writePrivateJson(pendingEnrollmentPath, config);
|
|
372
|
+
const predecessorGeneration = config.serverSigningKeyset.generation;
|
|
373
|
+
config = await resolveDemoSigningTrust(config, { store: deps.store });
|
|
374
|
+
if (signingTrustUpdate !== undefined && config.serverSigningKeyset.generation === predecessorGeneration) {
|
|
375
|
+
config = await acceptDemoSigningUpdate(config, signingTrustUpdate, { store: deps.store });
|
|
376
|
+
}
|
|
377
|
+
await writePrivateJson(configPath, config);
|
|
378
|
+
await unlink(pendingEnrollmentPath);
|
|
301
379
|
return verifyDemoDevice(input, deps);
|
|
302
380
|
}
|
|
303
381
|
//# sourceMappingURL=demoEnrollment.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"demoEnrollment.js","sourceRoot":"","sources":["../src/demoEnrollment.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"demoEnrollment.js","sourceRoot":"","sources":["../src/demoEnrollment.ts"],"names":[],"mappings":"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"}
|
|
@@ -43,6 +43,78 @@ function options(stateRoot) {
|
|
|
43
43
|
installationId: '40000000-0000-4000-8000-000000000001',
|
|
44
44
|
stateRoot, maximumWaitMs: 1_000 };
|
|
45
45
|
}
|
|
46
|
+
test('fresh browser approval replaces expired trust without replacing device identity or resetting its sequence', async (t) => {
|
|
47
|
+
t.mock.timers.enable({ apis: ['Date'], now: new Date('2026-09-27T03:00:00Z') });
|
|
48
|
+
const stateRoot = await mkdtemp(resolve(tmpdir(), 'dharma-demo-reenroll-'));
|
|
49
|
+
const values = new Map();
|
|
50
|
+
let interruptReplacement = false;
|
|
51
|
+
const store = { backend: 'linux-secret-service',
|
|
52
|
+
async get(account) { return values.get(account) ?? null; },
|
|
53
|
+
async put(account, value) {
|
|
54
|
+
values.set(account, value);
|
|
55
|
+
if (interruptReplacement && /^demo-signing-[0-9a-f]{32}$/.test(account)) {
|
|
56
|
+
interruptReplacement = false;
|
|
57
|
+
throw new Error('interrupted after protected replacement');
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
async delete(account) { values.delete(account); } };
|
|
61
|
+
const initial = approvedEnrollment();
|
|
62
|
+
let approved = initial;
|
|
63
|
+
let approvals = 0;
|
|
64
|
+
const sequences = [];
|
|
65
|
+
let devicePublicKey = '';
|
|
66
|
+
const fetcher = async (resource, init) => {
|
|
67
|
+
const url = new URL(String(resource));
|
|
68
|
+
if (url.pathname.endsWith('/enrollments')) {
|
|
69
|
+
devicePublicKey = JSON.parse(String(init?.body)).publicKeyEd25519;
|
|
70
|
+
return new Response(JSON.stringify({ ok: true, status: 'pending', organizationId: orgId,
|
|
71
|
+
repositoryId, deviceCode, expiresAt: new Date(Date.now() + 60_000).toISOString(),
|
|
72
|
+
verificationUri: `${hqUrl}/demo/fabric/approve?orgId=${orgId}&repositoryId=${repositoryId}&code=${browserCode}` }));
|
|
73
|
+
}
|
|
74
|
+
if (url.pathname.endsWith('/poll'))
|
|
75
|
+
return new Response(JSON.stringify(approved));
|
|
76
|
+
sequences.push(Number(new Headers(init?.headers).get('x-dharma-sequence')));
|
|
77
|
+
return new Response(JSON.stringify({ ok: true, organizationId: orgId, repositoryId,
|
|
78
|
+
deviceId, normalizedRepository }));
|
|
79
|
+
};
|
|
80
|
+
const connected = await connectDemoDevice(options(stateRoot), { store, fetcher,
|
|
81
|
+
onApprovalRequired: async () => { approvals += 1; } });
|
|
82
|
+
const before = JSON.parse(await readFile(connected.configPath, 'utf8'));
|
|
83
|
+
const originalAnchor = [...values.values()].find(value => value.includes('dharma.demo-signing-anchor/v1'));
|
|
84
|
+
t.mock.timers.tick(48 * 60 * 60_000);
|
|
85
|
+
await assert.rejects(loadDemoSigningTrust(options(stateRoot), { store }), /expired/i);
|
|
86
|
+
const successor = generateKeyPairSync('ed25519');
|
|
87
|
+
const pin = successor.publicKey.export({ format: 'jwk' }).x;
|
|
88
|
+
const issuedAt = new Date(Date.now() - 1_000).toISOString();
|
|
89
|
+
const expiresAt = new Date(Date.now() + 24 * 60 * 60_000).toISOString();
|
|
90
|
+
const body = { ...initial.serverSigningKeyset, generation: 3, signedByKeyVersion: 'successor',
|
|
91
|
+
issuedAt, expiresAt, keys: [...initial.serverSigningKeyset.keys.map(key => ({ ...key, status: 'overlap' })),
|
|
92
|
+
{ keyVersion: 'successor', publicKeyEd25519: pin, status: 'active', notBefore: issuedAt, notAfter: expiresAt }] };
|
|
93
|
+
const { signature: _signature, ...unsigned } = body;
|
|
94
|
+
approved = { ...initial, serverPublicKeyEd25519: pin,
|
|
95
|
+
serverSigningKeyset: { ...unsigned, signature: signCanonicalObject(unsigned, successor.privateKey) },
|
|
96
|
+
enrollmentApproval: { schema: 'dharma.demo-enrollment-approval/v1', organizationId: orgId,
|
|
97
|
+
repositoryId, participantId: '20000000-0000-4000-8000-000000000001', deviceId,
|
|
98
|
+
enrollmentId: '50000000-0000-4000-8000-000000000002', publicKeyEd25519: devicePublicKey,
|
|
99
|
+
approvedAt: new Date().toISOString(), expiresAt: new Date(Date.now() + 60_000).toISOString() } };
|
|
100
|
+
interruptReplacement = true;
|
|
101
|
+
await assert.rejects(connectDemoDevice(options(stateRoot), { store, fetcher,
|
|
102
|
+
onApprovalRequired: async () => { approvals += 1; } }), /interrupted after protected replacement/);
|
|
103
|
+
const trusted = await loadDemoSigningTrust(options(stateRoot), { store });
|
|
104
|
+
assert.equal(trusted.publicKey.export({ format: 'jwk' }).x, pin);
|
|
105
|
+
const renewed = await verifyDemoDevice(options(stateRoot), { store, fetcher });
|
|
106
|
+
const after = JSON.parse(await readFile(renewed.configPath, 'utf8'));
|
|
107
|
+
assert.equal(approvals, 2);
|
|
108
|
+
assert.deepEqual(sequences, [1, 2]);
|
|
109
|
+
assert.equal(after.deviceId, before.deviceId);
|
|
110
|
+
assert.equal(after.publicKeyEd25519, before.publicKeyEd25519);
|
|
111
|
+
assert.equal(after.enrolledAt, before.enrolledAt);
|
|
112
|
+
assert.equal(after.nextSequence, 3);
|
|
113
|
+
assert.equal(after.serverPublicKeyEd25519, pin);
|
|
114
|
+
assert.equal(after.serverSigningKeyset.keys[0].notAfter, initial.serverSigningKeyset.keys[0].notAfter);
|
|
115
|
+
assert.ok([...values.values()].includes(originalAnchor), 'old protected trust must survive unchanged');
|
|
116
|
+
assert.doesNotMatch([...values.values()].filter(value => value.includes('demo-signing')).join(''), /grant|privateJwk|privateKey/i);
|
|
117
|
+
});
|
|
46
118
|
test('Demo enrollment verifies the browser origin, waits for approval and signs a scoped status request', async () => {
|
|
47
119
|
const stateRoot = await mkdtemp(resolve(tmpdir(), 'dharma-demo-cli-'));
|
|
48
120
|
const calls = [];
|
|
@@ -82,8 +154,9 @@ test('Demo enrollment verifies the browser origin, waits for approval and signs
|
|
|
82
154
|
deviceId, normalizedRepository }), { status: 200 });
|
|
83
155
|
};
|
|
84
156
|
const approvals = [];
|
|
157
|
+
const store = memoryStore();
|
|
85
158
|
const connected = await connectDemoDevice(options(stateRoot), {
|
|
86
|
-
store
|
|
159
|
+
store, fetcher, sleep: async () => { },
|
|
87
160
|
onApprovalRequired: async (url) => { approvals.push(url); },
|
|
88
161
|
});
|
|
89
162
|
assert.equal(connected.stage, 'device_signed_ready');
|
|
@@ -96,7 +169,7 @@ test('Demo enrollment verifies the browser origin, waits for approval and signs
|
|
|
96
169
|
assert.equal(config.deviceId, deviceId);
|
|
97
170
|
assert.equal(config.grant, undefined);
|
|
98
171
|
assert.equal(config.privateKey, undefined);
|
|
99
|
-
assert.equal((await loadDemoSigningTrust(options(stateRoot))).deviceId, deviceId);
|
|
172
|
+
assert.equal((await loadDemoSigningTrust(options(stateRoot), { store })).deviceId, deviceId);
|
|
100
173
|
if (process.platform !== 'win32')
|
|
101
174
|
assert.equal((await stat(connected.configPath)).mode & 0o777, 0o600);
|
|
102
175
|
});
|
|
@@ -119,6 +192,219 @@ test('Demo enrollment rejects missing and foreign signing anchors before saving
|
|
|
119
192
|
await assert.rejects(readFile(scopePath(options(stateRoot), hqUrl)), { code: 'ENOENT' });
|
|
120
193
|
}
|
|
121
194
|
});
|
|
195
|
+
test('fresh enrollment during preload protects the successor before status and resumes activation after restart', async () => {
|
|
196
|
+
const stateRoot = await mkdtemp(resolve(tmpdir(), 'dharma-demo-preload-enrollment-'));
|
|
197
|
+
const scope = options(stateRoot);
|
|
198
|
+
const store = memoryStore();
|
|
199
|
+
const approved = approvedEnrollment();
|
|
200
|
+
const initial = approved.serverSigningKeyset;
|
|
201
|
+
const successor = generateKeyPairSync('ed25519');
|
|
202
|
+
const nextExpiry = new Date(Date.now() + 48 * 60 * 60_000).toISOString();
|
|
203
|
+
const { signature: _signature, ...initialUnsigned } = initial;
|
|
204
|
+
const preloadUnsigned = { ...initialUnsigned, generation: 2, keys: [...initial.keys, {
|
|
205
|
+
keyVersion: 'successor', publicKeyEd25519: successor.publicKey.export({ format: 'jwk' }).x,
|
|
206
|
+
status: 'overlap', notBefore: initial.issuedAt, notAfter: nextExpiry
|
|
207
|
+
}] };
|
|
208
|
+
const preload = { ...preloadUnsigned, signature: signCanonicalObject(preloadUnsigned, signer.privateKey) };
|
|
209
|
+
const activeUnsigned = { ...preloadUnsigned, generation: 3, signedByKeyVersion: 'successor',
|
|
210
|
+
expiresAt: nextExpiry, keys: preload.keys.map(key => ({ ...key,
|
|
211
|
+
status: key.keyVersion === 'successor' ? 'active' : 'overlap' })) };
|
|
212
|
+
const active = { ...activeUnsigned, signature: signCanonicalObject(activeUnsigned, successor.privateKey) };
|
|
213
|
+
const envelope = (keysets) => ({ schema: 'dharma.demo-signing-update/v1',
|
|
214
|
+
organizationId: orgId, repositoryId, deviceId, issuedAt: new Date().toISOString(),
|
|
215
|
+
expiresAt: new Date(Date.now() + 60_000).toISOString(), keysets });
|
|
216
|
+
let activate = false;
|
|
217
|
+
const fetcher = async (resource) => {
|
|
218
|
+
const url = new URL(String(resource));
|
|
219
|
+
if (url.pathname.endsWith('/enrollments'))
|
|
220
|
+
return new Response(JSON.stringify({ ok: true,
|
|
221
|
+
status: 'pending', organizationId: orgId, repositoryId, deviceCode,
|
|
222
|
+
expiresAt: new Date(Date.now() + 60_000).toISOString(),
|
|
223
|
+
verificationUri: `${hqUrl}/demo/fabric/approve?orgId=${orgId}&repositoryId=${repositoryId}&code=${browserCode}` }));
|
|
224
|
+
if (url.pathname.endsWith('/poll'))
|
|
225
|
+
return new Response(JSON.stringify({ ...approved,
|
|
226
|
+
signingTrustUpdate: envelope([initial, preload]) }));
|
|
227
|
+
assert.equal(url.searchParams.get('signingGeneration'), '2');
|
|
228
|
+
return new Response(JSON.stringify({ ok: true, organizationId: orgId, repositoryId,
|
|
229
|
+
deviceId, normalizedRepository, ...(activate ? { signingTrustUpdate: envelope([preload, active]) } : {}) }));
|
|
230
|
+
};
|
|
231
|
+
const connected = await connectDemoDevice(scope, { store, fetcher });
|
|
232
|
+
assert.equal((await loadDemoSigningTrust(scope, { store })).keyset.generation, 2);
|
|
233
|
+
// The same approved enrollment may be returned on retry; it must not downgrade protected trust.
|
|
234
|
+
await connectDemoDevice(scope, { store, fetcher });
|
|
235
|
+
activate = true;
|
|
236
|
+
await verifyDemoDevice(scope, { store, fetcher });
|
|
237
|
+
const trust = await loadDemoSigningTrust(scope, { store,
|
|
238
|
+
now: new Date(Date.parse(initial.expiresAt) + 1_000) });
|
|
239
|
+
assert.equal(trust.keyset.generation, 3);
|
|
240
|
+
const saved = await readFile(connected.configPath, 'utf8');
|
|
241
|
+
assert.doesNotMatch(saved, /grant|signingTrustUpdate|privateKey|privateJwk/i);
|
|
242
|
+
assert.equal(JSON.parse(saved).serverPublicKeyEd25519, serverPublicKeyEd25519);
|
|
243
|
+
});
|
|
244
|
+
test('fresh enrollment rejects a foreign or corrupt preload before writing a device or requesting signed status', async () => {
|
|
245
|
+
for (const fault of ['foreign', 'corrupt', 'expired', 'unexpected']) {
|
|
246
|
+
const stateRoot = await mkdtemp(resolve(tmpdir(), 'dharma-demo-preload-reject-'));
|
|
247
|
+
const scope = options(stateRoot);
|
|
248
|
+
const approved = approvedEnrollment();
|
|
249
|
+
const update = { schema: 'dharma.demo-signing-update/v1', organizationId: orgId,
|
|
250
|
+
repositoryId, deviceId, issuedAt: new Date().toISOString(),
|
|
251
|
+
expiresAt: new Date(Date.now() + 60_000).toISOString(), keysets: [approved.serverSigningKeyset],
|
|
252
|
+
...(fault === 'unexpected' ? { grant: 'must-not-persist' } : {}) };
|
|
253
|
+
if (fault === 'foreign')
|
|
254
|
+
update.deviceId = '30000000-0000-4000-8000-000000000099';
|
|
255
|
+
if (fault === 'expired')
|
|
256
|
+
update.expiresAt = new Date(Date.now() - 1_000).toISOString();
|
|
257
|
+
if (fault === 'corrupt')
|
|
258
|
+
update.keysets = [{ ...approved.serverSigningKeyset, generation: 2, signature: 'invalid' }];
|
|
259
|
+
const fetcher = async (resource) => {
|
|
260
|
+
const pathname = new URL(String(resource)).pathname;
|
|
261
|
+
if (pathname.endsWith('/enrollments'))
|
|
262
|
+
return new Response(JSON.stringify({ ok: true,
|
|
263
|
+
status: 'pending', organizationId: orgId, repositoryId, deviceCode,
|
|
264
|
+
expiresAt: new Date(Date.now() + 60_000).toISOString(),
|
|
265
|
+
verificationUri: `${hqUrl}/demo/fabric/approve?orgId=${orgId}&repositoryId=${repositoryId}&code=${browserCode}` }));
|
|
266
|
+
assert.ok(pathname.endsWith('/poll'), 'a rejected preload must never dispatch signed status');
|
|
267
|
+
return new Response(JSON.stringify({ ...approved, signingTrustUpdate: update }));
|
|
268
|
+
};
|
|
269
|
+
await assert.rejects(connectDemoDevice(scope, { store: memoryStore(), fetcher }), /Demo signing/);
|
|
270
|
+
await assert.rejects(readFile(scopePath(scope, hqUrl)), { code: 'ENOENT' });
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
test('interrupted preload enrollment recovers its protected binding without a second approval or credential file', async () => {
|
|
274
|
+
const stateRoot = await mkdtemp(resolve(tmpdir(), 'dharma-demo-preload-interrupt-'));
|
|
275
|
+
const scope = options(stateRoot);
|
|
276
|
+
const store = memoryStore();
|
|
277
|
+
const approved = approvedEnrollment();
|
|
278
|
+
const initial = approved.serverSigningKeyset;
|
|
279
|
+
const successor = generateKeyPairSync('ed25519');
|
|
280
|
+
const { signature: _signature, ...body } = initial;
|
|
281
|
+
const unsigned = { ...body, generation: 2, keys: [...initial.keys, { keyVersion: 'successor',
|
|
282
|
+
publicKeyEd25519: successor.publicKey.export({ format: 'jwk' }).x, status: 'overlap',
|
|
283
|
+
notBefore: initial.issuedAt, notAfter: new Date(Date.now() + 48 * 60 * 60_000).toISOString() }] };
|
|
284
|
+
const preload = { ...unsigned, signature: signCanonicalObject(unsigned, signer.privateKey) };
|
|
285
|
+
const fetcher = async (resource) => {
|
|
286
|
+
const url = new URL(String(resource));
|
|
287
|
+
if (url.pathname.endsWith('/enrollments'))
|
|
288
|
+
return new Response(JSON.stringify({ ok: true,
|
|
289
|
+
status: 'approved', organizationId: orgId, repositoryId, deviceCode,
|
|
290
|
+
expiresAt: new Date(Date.now() + 60_000).toISOString(),
|
|
291
|
+
verificationUri: `${hqUrl}/demo/fabric/approve?orgId=${orgId}&repositoryId=${repositoryId}&code=${browserCode}` }));
|
|
292
|
+
if (url.pathname.endsWith('/poll'))
|
|
293
|
+
return new Response(JSON.stringify({ ...approved, signingTrustUpdate: {
|
|
294
|
+
schema: 'dharma.demo-signing-update/v1', organizationId: orgId, repositoryId, deviceId,
|
|
295
|
+
issuedAt: new Date().toISOString(), expiresAt: new Date(Date.now() + 60_000).toISOString(), keysets: [initial, preload]
|
|
296
|
+
} }));
|
|
297
|
+
assert.equal(url.searchParams.get('signingGeneration'), '2');
|
|
298
|
+
return new Response(JSON.stringify({ ok: true, organizationId: orgId, repositoryId, deviceId, normalizedRepository }));
|
|
299
|
+
};
|
|
300
|
+
const interruptedStore = { ...store, async put(account, value) {
|
|
301
|
+
await store.put(account, value);
|
|
302
|
+
if (account.startsWith('demo-signing-') && JSON.parse(value).serverSigningKeyset.generation === 2) {
|
|
303
|
+
throw new Error('simulated termination after protected write');
|
|
304
|
+
}
|
|
305
|
+
} };
|
|
306
|
+
await assert.rejects(connectDemoDevice(scope, { store: interruptedStore, fetcher }), /simulated termination/);
|
|
307
|
+
const path = scopePath(scope, hqUrl);
|
|
308
|
+
await assert.rejects(readFile(path), { code: 'ENOENT' });
|
|
309
|
+
const pending = JSON.parse(await readFile(`${path}.pending-enrollment.json`, 'utf8'));
|
|
310
|
+
assert.equal(pending.signedReady, false);
|
|
311
|
+
assert.doesNotMatch(JSON.stringify(pending), /grant|privateKey|privateJwk|signingTrustUpdate/i);
|
|
312
|
+
for (const change of [{ organizationId: 'org_foreign' }, { publicKeyEd25519: 'E'.repeat(43) },
|
|
313
|
+
{ deviceId: '30000000-0000-4000-8000-000000000099' }, { signedReady: true }, { nextSequence: 2 },
|
|
314
|
+
{ grant: 'must-not-persist' }]) {
|
|
315
|
+
const foreign = JSON.stringify({ ...pending, ...change });
|
|
316
|
+
await writeFile(`${path}.pending-enrollment.json`, foreign);
|
|
317
|
+
await assert.rejects(connectDemoDevice(scope, { store, fetcher }), /Pending Demo enrollment/);
|
|
318
|
+
assert.equal(await readFile(`${path}.pending-enrollment.json`, 'utf8'), foreign);
|
|
319
|
+
}
|
|
320
|
+
await writeFile(`${path}.pending-enrollment.json`, JSON.stringify(pending));
|
|
321
|
+
await new Promise(accept => setTimeout(accept, 10));
|
|
322
|
+
const result = await connectDemoDevice(scope, { store, fetcher,
|
|
323
|
+
onApprovalRequired: async () => { assert.fail('an approved interrupted enrollment must not ask for another approval'); } });
|
|
324
|
+
assert.equal(result.stage, 'device_signed_ready');
|
|
325
|
+
assert.equal(JSON.parse(await readFile(path, 'utf8')).enrolledAt, pending.enrolledAt);
|
|
326
|
+
assert.equal((await loadDemoSigningTrust(scope, { store })).keyset.generation, 2);
|
|
327
|
+
await assert.rejects(readFile(`${path}.pending-enrollment.json`), { code: 'ENOENT' });
|
|
328
|
+
});
|
|
329
|
+
test('signed status autonomously accepts a successor and reloads it from protected trust after bootstrap expiry', async () => {
|
|
330
|
+
const stateRoot = await mkdtemp(resolve(tmpdir(), 'dharma-demo-rotation-'));
|
|
331
|
+
const scope = options(stateRoot);
|
|
332
|
+
const store = memoryStore();
|
|
333
|
+
const approved = approvedEnrollment();
|
|
334
|
+
const initial = approved.serverSigningKeyset;
|
|
335
|
+
const successor = generateKeyPairSync('ed25519');
|
|
336
|
+
const nextExpiry = new Date(Date.now() + 48 * 60 * 60_000).toISOString();
|
|
337
|
+
const preloadBody = { ...initial, generation: 2, keys: [...initial.keys, {
|
|
338
|
+
keyVersion: 'successor', publicKeyEd25519: successor.publicKey.export({ format: 'jwk' }).x,
|
|
339
|
+
status: 'overlap', notBefore: initial.issuedAt, notAfter: nextExpiry
|
|
340
|
+
}] };
|
|
341
|
+
const { signature: _oldSignature, ...preloadUnsigned } = preloadBody;
|
|
342
|
+
const preload = { ...preloadUnsigned, signature: signCanonicalObject(preloadUnsigned, signer.privateKey) };
|
|
343
|
+
const activeUnsigned = { ...preloadUnsigned, generation: 3, signedByKeyVersion: 'successor',
|
|
344
|
+
expiresAt: nextExpiry, keys: preload.keys.map(key => ({ ...key,
|
|
345
|
+
status: key.keyVersion === 'successor' ? 'active' : 'overlap' })) };
|
|
346
|
+
const active = { ...activeUnsigned, signature: signCanonicalObject(activeUnsigned, successor.privateKey) };
|
|
347
|
+
let update;
|
|
348
|
+
const fetcher = async (resource) => {
|
|
349
|
+
const url = new URL(String(resource));
|
|
350
|
+
if (url.pathname.endsWith('/enrollments'))
|
|
351
|
+
return new Response(JSON.stringify({ ok: true,
|
|
352
|
+
status: 'pending', organizationId: orgId, repositoryId, deviceCode,
|
|
353
|
+
expiresAt: new Date(Date.now() + 60_000).toISOString(),
|
|
354
|
+
verificationUri: `${hqUrl}/demo/fabric/approve?orgId=${orgId}&repositoryId=${repositoryId}&code=${browserCode}` }));
|
|
355
|
+
if (url.pathname.endsWith('/poll'))
|
|
356
|
+
return new Response(JSON.stringify(approved));
|
|
357
|
+
assert.equal(url.searchParams.get('signingGeneration'), '1');
|
|
358
|
+
return new Response(JSON.stringify({ ok: true, organizationId: orgId, repositoryId,
|
|
359
|
+
deviceId, normalizedRepository, ...(update ? { signingTrustUpdate: update } : {}) }));
|
|
360
|
+
};
|
|
361
|
+
const connected = await connectDemoDevice(scope, { store, fetcher });
|
|
362
|
+
update = { schema: 'dharma.demo-signing-update/v1', organizationId: orgId, repositoryId, deviceId,
|
|
363
|
+
issuedAt: new Date().toISOString(), expiresAt: new Date(Date.now() + 60_000).toISOString(),
|
|
364
|
+
keysets: [preload, active] };
|
|
365
|
+
await verifyDemoDevice(scope, { store, fetcher });
|
|
366
|
+
const trusted = await loadDemoSigningTrust(scope, { store,
|
|
367
|
+
now: new Date(Date.parse(initial.expiresAt) + 1_000) });
|
|
368
|
+
assert.equal(trusted.keyset.generation, 3);
|
|
369
|
+
const config = JSON.parse(await readFile(connected.configPath, 'utf8'));
|
|
370
|
+
assert.equal(config.serverPublicKeyEd25519, approved.serverPublicKeyEd25519);
|
|
371
|
+
assert.equal(config.serverSigningKeyset.keys[0].notAfter, initial.keys[0].notAfter);
|
|
372
|
+
assert.equal(config.nextSequence, 3);
|
|
373
|
+
assert.doesNotMatch(JSON.stringify(config), /grant|privateJwk|privateKey/i);
|
|
374
|
+
});
|
|
375
|
+
test('a rejected status trust update preserves the sequence and last verified keyset', async () => {
|
|
376
|
+
const stateRoot = await mkdtemp(resolve(tmpdir(), 'dharma-demo-rotation-reject-'));
|
|
377
|
+
const scope = options(stateRoot);
|
|
378
|
+
const store = memoryStore();
|
|
379
|
+
const approved = approvedEnrollment();
|
|
380
|
+
let tamper = false;
|
|
381
|
+
const fetcher = async (resource) => {
|
|
382
|
+
const pathname = new URL(String(resource)).pathname;
|
|
383
|
+
if (pathname.endsWith('/enrollments'))
|
|
384
|
+
return new Response(JSON.stringify({ ok: true,
|
|
385
|
+
status: 'pending', organizationId: orgId, repositoryId, deviceCode,
|
|
386
|
+
expiresAt: new Date(Date.now() + 60_000).toISOString(),
|
|
387
|
+
verificationUri: `${hqUrl}/demo/fabric/approve?orgId=${orgId}&repositoryId=${repositoryId}&code=${browserCode}` }));
|
|
388
|
+
if (pathname.endsWith('/poll'))
|
|
389
|
+
return new Response(JSON.stringify(approved));
|
|
390
|
+
return new Response(JSON.stringify({ ok: true, organizationId: orgId, repositoryId,
|
|
391
|
+
deviceId, normalizedRepository, ...(tamper ? { signingTrustUpdate: {
|
|
392
|
+
schema: 'dharma.demo-signing-update/v1', organizationId: orgId, repositoryId, deviceId,
|
|
393
|
+
issuedAt: new Date().toISOString(), expiresAt: new Date(Date.now() + 60_000).toISOString(),
|
|
394
|
+
keysets: [{ ...approved.serverSigningKeyset, generation: 2, signature: 'invalid' }]
|
|
395
|
+
} } : {}) }));
|
|
396
|
+
};
|
|
397
|
+
const connected = await connectDemoDevice(scope, { store, fetcher });
|
|
398
|
+
tamper = true;
|
|
399
|
+
await assert.rejects(verifyDemoDevice(scope, { store, fetcher }), /Demo signing/);
|
|
400
|
+
const config = JSON.parse(await readFile(connected.configPath, 'utf8'));
|
|
401
|
+
assert.equal(config.nextSequence, 3);
|
|
402
|
+
assert.equal(config.serverSigningKeyset.generation, 1);
|
|
403
|
+
assert.deepEqual((await loadDemoSigningTrust(scope, { store })).keyset, approved.serverSigningKeyset);
|
|
404
|
+
tamper = false;
|
|
405
|
+
await verifyDemoDevice(scope, { store, fetcher });
|
|
406
|
+
assert.equal(JSON.parse(await readFile(connected.configPath, 'utf8')).nextSequence, 4);
|
|
407
|
+
});
|
|
122
408
|
test('Demo enrollment recovers from one transient poll failure without restarting enrollment', async () => {
|
|
123
409
|
const stateRoot = await mkdtemp(resolve(tmpdir(), 'dharma-demo-poll-retry-'));
|
|
124
410
|
const calls = [];
|