@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.
Files changed (100) hide show
  1. package/README.md +41 -0
  2. package/dist/codexInboxSession.d.ts +1 -1
  3. package/dist/cooperativeInboxSession.d.ts +1 -1
  4. package/dist/demoDeviceTransport.d.ts +33 -0
  5. package/dist/demoDeviceTransport.d.ts.map +1 -0
  6. package/dist/demoDeviceTransport.js +52 -0
  7. package/dist/demoDeviceTransport.js.map +1 -0
  8. package/dist/demoDeviceTransport.test.d.ts +2 -0
  9. package/dist/demoDeviceTransport.test.d.ts.map +1 -0
  10. package/dist/demoDeviceTransport.test.js +178 -0
  11. package/dist/demoDeviceTransport.test.js.map +1 -0
  12. package/dist/demoEnrollment.d.ts +2 -1
  13. package/dist/demoEnrollment.d.ts.map +1 -1
  14. package/dist/demoEnrollment.js +99 -21
  15. package/dist/demoEnrollment.js.map +1 -1
  16. package/dist/demoEnrollment.test.js +288 -2
  17. package/dist/demoEnrollment.test.js.map +1 -1
  18. package/dist/demoPackage.js +1 -1
  19. package/dist/demoPackage.js.map +1 -1
  20. package/dist/demoSigningTrust.d.ts +24 -0
  21. package/dist/demoSigningTrust.d.ts.map +1 -0
  22. package/dist/demoSigningTrust.js +326 -0
  23. package/dist/demoSigningTrust.js.map +1 -0
  24. package/dist/demoSigningTrust.test.d.ts +2 -0
  25. package/dist/demoSigningTrust.test.d.ts.map +1 -0
  26. package/dist/demoSigningTrust.test.js +445 -0
  27. package/dist/demoSigningTrust.test.js.map +1 -0
  28. package/dist/demoSigningUpgradeProof.d.ts +52 -0
  29. package/dist/demoSigningUpgradeProof.d.ts.map +1 -0
  30. package/dist/demoSigningUpgradeProof.js +137 -0
  31. package/dist/demoSigningUpgradeProof.js.map +1 -0
  32. package/dist/demoSigningUpgradeProof.test.d.ts +2 -0
  33. package/dist/demoSigningUpgradeProof.test.d.ts.map +1 -0
  34. package/dist/demoSigningUpgradeProof.test.js +564 -0
  35. package/dist/demoSigningUpgradeProof.test.js.map +1 -0
  36. package/dist/demoSigningUpgradeSubmission.d.ts +21 -0
  37. package/dist/demoSigningUpgradeSubmission.d.ts.map +1 -0
  38. package/dist/demoSigningUpgradeSubmission.js +178 -0
  39. package/dist/demoSigningUpgradeSubmission.js.map +1 -0
  40. package/dist/demoSupervisor.d.ts.map +1 -1
  41. package/dist/demoSupervisor.js +2 -1
  42. package/dist/demoSupervisor.js.map +1 -1
  43. package/dist/demoSupervisor.test.js +35 -0
  44. package/dist/demoSupervisor.test.js.map +1 -1
  45. package/dist/demoTransportCommand.test.d.ts +2 -0
  46. package/dist/demoTransportCommand.test.d.ts.map +1 -0
  47. package/dist/demoTransportCommand.test.js +28 -0
  48. package/dist/demoTransportCommand.test.js.map +1 -0
  49. package/dist/demoTransportContinuity.d.ts +39 -0
  50. package/dist/demoTransportContinuity.d.ts.map +1 -0
  51. package/dist/demoTransportContinuity.js +82 -0
  52. package/dist/demoTransportContinuity.js.map +1 -0
  53. package/dist/demoTransportContinuity.test.d.ts +2 -0
  54. package/dist/demoTransportContinuity.test.d.ts.map +1 -0
  55. package/dist/demoTransportContinuity.test.js +145 -0
  56. package/dist/demoTransportContinuity.test.js.map +1 -0
  57. package/dist/demoTransportFetch.d.ts +12 -0
  58. package/dist/demoTransportFetch.d.ts.map +1 -0
  59. package/dist/demoTransportFetch.js +109 -0
  60. package/dist/demoTransportFetch.js.map +1 -0
  61. package/dist/demoTransportFetch.test.d.ts +2 -0
  62. package/dist/demoTransportFetch.test.d.ts.map +1 -0
  63. package/dist/demoTransportFetch.test.js +150 -0
  64. package/dist/demoTransportFetch.test.js.map +1 -0
  65. package/dist/demoTransportRequest.d.ts +35 -0
  66. package/dist/demoTransportRequest.d.ts.map +1 -0
  67. package/dist/demoTransportRequest.js +193 -0
  68. package/dist/demoTransportRequest.js.map +1 -0
  69. package/dist/demoTransportRequest.test.d.ts +2 -0
  70. package/dist/demoTransportRequest.test.d.ts.map +1 -0
  71. package/dist/demoTransportRequest.test.js +203 -0
  72. package/dist/demoTransportRequest.test.js.map +1 -0
  73. package/dist/demoTransportState.d.ts +31 -0
  74. package/dist/demoTransportState.d.ts.map +1 -0
  75. package/dist/demoTransportState.js +204 -0
  76. package/dist/demoTransportState.js.map +1 -0
  77. package/dist/demoTransportState.test.d.ts +2 -0
  78. package/dist/demoTransportState.test.d.ts.map +1 -0
  79. package/dist/demoTransportState.test.js +192 -0
  80. package/dist/demoTransportState.test.js.map +1 -0
  81. package/dist/index.d.ts.map +1 -1
  82. package/dist/index.js +46 -13
  83. package/dist/index.js.map +1 -1
  84. package/dist/providerSessionReplyRecovery.d.ts +1 -1
  85. package/dist/relaySupervisor.test.js +3 -1
  86. package/dist/relaySupervisor.test.js.map +1 -1
  87. package/dist/schemas/demo-enrollment-approval.schema.json +19 -0
  88. package/dist/schemas/demo-signing-update.schema.json +18 -0
  89. package/dist/schemas/demo-transport-continuity.schema.json +27 -0
  90. package/dist/schemas/demo-transport-journal.schema.json +13 -0
  91. package/dist/schemas/demo-transport-request.schema.json +27 -0
  92. package/dist/schemas/demo-transport-state.schema.json +13 -0
  93. package/dist/schemas/lifecycle-event.schema.json +178 -0
  94. package/dist/schemas/signing-upgrade-context.schema.json +28 -0
  95. package/dist/schemas/signing-upgrade-source.schema.json +32 -0
  96. package/dist/usage.d.ts +1 -1
  97. package/dist/usage.d.ts.map +1 -1
  98. package/dist/usage.js +1 -1
  99. package/dist/usage.js.map +1 -1
  100. package/package.json +2 -1
@@ -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 config = JSON.parse(await readFile(scopePath(input, normalizeHqUrl(input.hqUrl)), 'utf8'));
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: config.serverPublicKeyEd25519 }, format: 'jwk' });
69
- const verification = verifyInitialServerSigningKeyset(config.serverSigningKeyset, publicKey, input.organizationId);
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
- const config = JSON.parse(await readFile(configPath, 'utf8'));
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
- if (existing.deviceId !== config.deviceId || existing.url !== pending.url
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
- const existing = JSON.parse(await readFile(configPath, 'utf8'));
282
- if (existing.deviceId !== deviceId || existing.publicKeyEd25519 !== identity.publicKeyEd25519) {
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.serverPublicKeyEd25519 && existing.serverPublicKeyEd25519 !== serverPublicKeyEd25519) {
286
- throw new Error('Existing Demo signing root differs. Use supported browser-authorized recovery.');
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
- await writePrivateJson(configPath, { schema: 'dharma.demo-device/v1',
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: memoryStore(), fetcher, sleep: async () => { },
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 = [];