@dharma-ai-labs/agent-fabric 0.2.80 → 0.2.82

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.
@@ -0,0 +1,41 @@
1
+ import { type SecureSecretStore } from '@dharma-ai-labs/agent-fabric-relay-client';
2
+ export interface DemoDeviceConnectOptions {
3
+ hqUrl: string;
4
+ organizationId: string;
5
+ repositoryId: string;
6
+ normalizedRepository: string;
7
+ installationId: string;
8
+ grant: string;
9
+ deviceName: string;
10
+ platform: 'windows' | 'wsl' | 'macos' | 'linux';
11
+ stateRoot: string;
12
+ maximumWaitMs?: number;
13
+ }
14
+ export type DemoDeviceScope = Pick<DemoDeviceConnectOptions, 'hqUrl' | 'organizationId' | 'repositoryId' | 'normalizedRepository' | 'installationId' | 'stateRoot'>;
15
+ export interface DemoDeviceConnectDependencies {
16
+ store?: SecureSecretStore;
17
+ fetcher?: typeof fetch;
18
+ sleep?: (milliseconds: number) => Promise<void>;
19
+ onApprovalRequired?: (url: string) => Promise<void>;
20
+ }
21
+ export declare function verifyDemoDevice(input: DemoDeviceScope, deps?: Pick<DemoDeviceConnectDependencies, 'store' | 'fetcher'>): Promise<{
22
+ ok: true;
23
+ stage: "device_signed_ready";
24
+ organizationId: string;
25
+ repositoryId: string;
26
+ normalizedRepository: string;
27
+ deviceId: string;
28
+ configPath: string;
29
+ repositoryPackageState: "not_connected";
30
+ }>;
31
+ export declare function connectDemoDevice(input: DemoDeviceConnectOptions, deps?: DemoDeviceConnectDependencies): Promise<{
32
+ ok: true;
33
+ stage: "device_signed_ready";
34
+ organizationId: string;
35
+ repositoryId: string;
36
+ normalizedRepository: string;
37
+ deviceId: string;
38
+ configPath: string;
39
+ repositoryPackageState: "not_connected";
40
+ }>;
41
+ //# sourceMappingURL=demoEnrollment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"demoEnrollment.d.ts","sourceRoot":"","sources":["../src/demoEnrollment.ts"],"names":[],"mappings":"AAGA,OAAO,EAA8C,KAAK,iBAAiB,EAAE,MAAM,2CAA2C,CAAC;AAM/H,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,SAAS,GAAG,KAAK,GAAG,OAAO,GAAG,OAAO,CAAC;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,wBAAwB,EACzD,OAAO,GAAG,gBAAgB,GAAG,cAAc,GAAG,sBAAsB,GAAG,gBAAgB,GAAG,WAAW,CAAC,CAAC;AAgBzG,MAAM,WAAW,6BAA6B;IAC5C,KAAK,CAAC,EAAE,iBAAiB,CAAC;IAC1B,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;IACvB,KAAK,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,kBAAkB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACrD;AAkGD,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,eAAe,EAC3D,IAAI,GAAE,IAAI,CAAC,6BAA6B,EAAE,OAAO,GAAG,SAAS,CAAM;;;;;;;;;GA8EpE;AAED,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,wBAAwB,EACrE,IAAI,GAAE,6BAAkC;;;;;;;;;GAuDzC"}
@@ -0,0 +1,247 @@
1
+ import { createHash, randomBytes, randomUUID, sign } from 'node:crypto';
2
+ import { chmod, mkdir, readFile, rename, unlink, writeFile } from 'node:fs/promises';
3
+ import { dirname, resolve } from 'node:path';
4
+ import { loadOrCreateDeviceIdentity, normalizeHqUrl } from '@dharma-ai-labs/agent-fabric-relay-client';
5
+ 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;
6
+ const CODE = /^[A-Za-z0-9_-]{43}$/;
7
+ const BROWSER_CODE = /^[0-9A-F]{20}$/;
8
+ function assertInput(input) {
9
+ if (!/^org_[A-Za-z0-9]+$/.test(input.organizationId)
10
+ || !UUID.test(input.repositoryId) || !UUID.test(input.installationId)
11
+ || !CODE.test(input.grant) || input.deviceName.trim().length < 2
12
+ || input.deviceName.length > 120 || !input.normalizedRepository
13
+ || !['windows', 'wsl', 'macos', 'linux'].includes(input.platform)) {
14
+ throw new Error('Demo device setup context is invalid. Copy a fresh repository-specific prompt.');
15
+ }
16
+ }
17
+ class DemoDeviceApiError extends Error {
18
+ code;
19
+ constructor(code, message) {
20
+ super(`${code}: ${message}`);
21
+ this.code = code;
22
+ }
23
+ }
24
+ function apiError(body, status) {
25
+ const item = body && typeof body === 'object' ? body : {};
26
+ const nested = item.error && typeof item.error === 'object' && !Array.isArray(item.error)
27
+ ? item.error : null;
28
+ const code = typeof nested?.code === 'string' ? nested.code
29
+ : typeof item.error === 'string' ? item.error : `http_${status}`;
30
+ const message = typeof nested?.message === 'string' ? nested.message
31
+ : typeof item.message === 'string' ? item.message : 'Demo device request failed.';
32
+ return new DemoDeviceApiError(code, message);
33
+ }
34
+ async function readJsonResponse(response) {
35
+ const body = await response.json().catch(() => null);
36
+ if (!response.ok)
37
+ throw apiError(body, response.status);
38
+ if (!body || typeof body !== 'object' || Array.isArray(body)
39
+ || body.ok !== true) {
40
+ throw new Error('Demo device response is not a JSON object.');
41
+ }
42
+ return body;
43
+ }
44
+ function scopePath(input, origin) {
45
+ const scope = createHash('sha256').update(`${origin}\0${input.organizationId}\0${input.repositoryId}`)
46
+ .digest('hex').slice(0, 32);
47
+ return resolve(input.stateRoot, 'demo', scope, 'device.json');
48
+ }
49
+ async function writePrivateJson(path, value) {
50
+ const directory = dirname(path);
51
+ await mkdir(directory, { recursive: true, mode: 0o700 });
52
+ const temporary = `${path}.${randomUUID()}.tmp`;
53
+ await writeFile(temporary, `${JSON.stringify(value)}\n`, { mode: 0o600, flag: 'wx' });
54
+ await rename(temporary, path);
55
+ if (process.platform !== 'win32')
56
+ await chmod(path, 0o600);
57
+ }
58
+ function approvalUri(value, origin, input) {
59
+ if (typeof value !== 'string')
60
+ throw new Error('Demo device verification origin is missing.');
61
+ let url;
62
+ try {
63
+ url = new URL(value);
64
+ }
65
+ catch {
66
+ throw new Error('Demo device verification origin is invalid.');
67
+ }
68
+ if (url.origin !== origin || url.pathname !== '/demo/fabric/approve'
69
+ || url.username || url.password || url.hash || url.searchParams.size !== 3
70
+ || url.searchParams.getAll('orgId').length !== 1
71
+ || url.searchParams.getAll('repositoryId').length !== 1
72
+ || url.searchParams.getAll('code').length !== 1
73
+ || url.searchParams.get('orgId') !== input.organizationId
74
+ || url.searchParams.get('repositoryId') !== input.repositoryId
75
+ || !BROWSER_CODE.test(url.searchParams.get('code') || '')) {
76
+ throw new Error('Demo device verification origin or repository scope is invalid.');
77
+ }
78
+ return url.toString();
79
+ }
80
+ function signedStatusRequest(origin, input, deviceId, privateJwk, sequence) {
81
+ const url = new URL(`/api/demo/fabric/repositories/${input.repositoryId}/status`, origin);
82
+ url.searchParams.set('orgId', input.organizationId);
83
+ const sessionId = randomUUID();
84
+ const messageId = randomUUID();
85
+ const timestamp = new Date().toISOString();
86
+ const nonce = randomBytes(24).toString('base64url');
87
+ const payload = Buffer.from(JSON.stringify({
88
+ bodyHash: `sha256:${createHash('sha256').update('').digest('hex')}`,
89
+ deviceId, messageId, method: 'GET', nonce,
90
+ organizationId: input.organizationId,
91
+ pathname: `${url.pathname}${url.search}`, sequence, sessionId, timestamp,
92
+ }));
93
+ const signature = sign(null, payload, { key: privateJwk, format: 'jwk' }).toString('base64url');
94
+ return { url: url.toString(), deviceId, sequence, createdAt: timestamp, headers: {
95
+ 'x-dharma-device-id': deviceId,
96
+ 'x-dharma-session-id': sessionId,
97
+ 'x-dharma-message-id': messageId,
98
+ 'x-dharma-timestamp': timestamp,
99
+ 'x-dharma-nonce': nonce,
100
+ 'x-dharma-sequence': String(sequence),
101
+ 'x-dharma-signature': signature,
102
+ } };
103
+ }
104
+ export async function verifyDemoDevice(input, deps = {}) {
105
+ const origin = normalizeHqUrl(input.hqUrl);
106
+ const configPath = scopePath(input, origin);
107
+ const pendingPath = `${configPath}.pending-status.json`;
108
+ const config = JSON.parse(await readFile(configPath, 'utf8'));
109
+ if (config.schema !== 'dharma.demo-device/v1' || config.hqUrl !== origin
110
+ || config.organizationId !== input.organizationId || config.repositoryId !== input.repositoryId
111
+ || config.normalizedRepository !== input.normalizedRepository
112
+ || config.installationId !== input.installationId || !UUID.test(config.deviceId)
113
+ || !Number.isSafeInteger(config.nextSequence) || config.nextSequence < 1) {
114
+ throw new Error('Demo device config does not match the requested repository and installation.');
115
+ }
116
+ const identity = await loadOrCreateDeviceIdentity({ hqUrl: origin,
117
+ organizationId: `${input.organizationId}:${input.repositoryId}`,
118
+ installationId: input.installationId, store: deps.store });
119
+ if (config.publicKeyEd25519 !== identity.publicKeyEd25519) {
120
+ throw new Error('Demo device key does not match its protected local identity.');
121
+ }
122
+ let hasPending = false;
123
+ let pending = signedStatusRequest(origin, input, config.deviceId, identity.privateJwk, config.nextSequence);
124
+ try {
125
+ const existing = JSON.parse(await readFile(pendingPath, 'utf8'));
126
+ if (existing.deviceId !== config.deviceId || existing.url !== pending.url
127
+ || !Number.isSafeInteger(existing.sequence) || existing.sequence < config.nextSequence
128
+ || !Number.isFinite(Date.parse(existing.createdAt))) {
129
+ throw new Error('Pending Demo device status does not match this identity.');
130
+ }
131
+ hasPending = true;
132
+ pending = Date.now() - Date.parse(existing.createdAt) < 4 * 60_000
133
+ ? existing
134
+ : signedStatusRequest(origin, input, config.deviceId, identity.privateJwk, existing.sequence);
135
+ }
136
+ catch (error) {
137
+ if (error.code !== 'ENOENT') {
138
+ throw new Error('Pending Demo device status is invalid; preserve it for recovery.', { cause: error });
139
+ }
140
+ }
141
+ const requestStatus = async () => {
142
+ await writePrivateJson(pendingPath, pending);
143
+ return readJsonResponse(await (deps.fetcher || fetch)(pending.url, {
144
+ method: 'GET', headers: pending.headers,
145
+ }));
146
+ };
147
+ let status = null;
148
+ try {
149
+ status = await requestStatus();
150
+ }
151
+ catch (error) {
152
+ if (!hasPending || !(error instanceof DemoDeviceApiError)
153
+ || error.code !== 'demo_fabric_sequence_out_of_order')
154
+ throw error;
155
+ const candidates = [pending.sequence - 1, pending.sequence + 1]
156
+ .filter((sequence) => sequence >= config.nextSequence);
157
+ let recovered = false;
158
+ for (const sequence of candidates) {
159
+ pending = signedStatusRequest(origin, input, config.deviceId, identity.privateJwk, sequence);
160
+ try {
161
+ status = await requestStatus();
162
+ recovered = true;
163
+ break;
164
+ }
165
+ catch (candidateError) {
166
+ if (!(candidateError instanceof DemoDeviceApiError)
167
+ || candidateError.code !== 'demo_fabric_sequence_out_of_order')
168
+ throw candidateError;
169
+ }
170
+ }
171
+ if (!recovered)
172
+ throw error;
173
+ }
174
+ if (!status || status.organizationId !== input.organizationId || status.repositoryId !== input.repositoryId
175
+ || status.deviceId !== config.deviceId || status.normalizedRepository !== input.normalizedRepository) {
176
+ throw new Error('Signed Demo status did not confirm the exact repository and device.');
177
+ }
178
+ config.signedReady = true;
179
+ config.nextSequence = pending.sequence + 1;
180
+ await writePrivateJson(configPath, config);
181
+ await unlink(pendingPath).catch(() => { });
182
+ return { ok: true, stage: 'device_signed_ready',
183
+ organizationId: input.organizationId, repositoryId: input.repositoryId,
184
+ normalizedRepository: input.normalizedRepository, deviceId: config.deviceId,
185
+ configPath, repositoryPackageState: 'not_connected' };
186
+ }
187
+ export async function connectDemoDevice(input, deps = {}) {
188
+ assertInput(input);
189
+ const origin = normalizeHqUrl(input.hqUrl);
190
+ const fetcher = deps.fetcher || fetch;
191
+ const sleep = deps.sleep || ((milliseconds) => new Promise((accept) => setTimeout(accept, milliseconds)));
192
+ const identity = await loadOrCreateDeviceIdentity({ hqUrl: origin,
193
+ organizationId: `${input.organizationId}:${input.repositoryId}`,
194
+ installationId: input.installationId, store: deps.store });
195
+ const started = await readJsonResponse(await fetcher(`${origin}/api/demo/fabric/enrollments`, {
196
+ method: 'POST', headers: { 'content-type': 'application/json' },
197
+ body: JSON.stringify({ orgId: input.organizationId, repositoryId: input.repositoryId,
198
+ grant: input.grant, name: input.deviceName.trim(), platform: input.platform,
199
+ publicKeyEd25519: identity.publicKeyEd25519 }),
200
+ }));
201
+ if (started.organizationId !== input.organizationId || started.repositoryId !== input.repositoryId
202
+ || !CODE.test(String(started.deviceCode || '')) || !Number.isFinite(Date.parse(String(started.expiresAt || '')))) {
203
+ throw new Error('Demo enrollment response does not match the requested repository.');
204
+ }
205
+ const verificationUri = approvalUri(started.verificationUri, origin, input);
206
+ if (started.status === 'pending')
207
+ await deps.onApprovalRequired?.(verificationUri);
208
+ const deadline = Math.min(Date.parse(String(started.expiresAt)), Date.now() + Math.min(Math.max(input.maximumWaitMs ?? 10 * 60_000, 1_000), 15 * 60_000));
209
+ let deviceId = '';
210
+ while (Date.now() < deadline) {
211
+ const polled = await readJsonResponse(await fetcher(`${origin}/api/demo/fabric/enrollments/poll`, {
212
+ method: 'POST', headers: { 'content-type': 'application/json' },
213
+ body: JSON.stringify({ orgId: input.organizationId, deviceCode: started.deviceCode }),
214
+ }));
215
+ if (polled.status === 'approved') {
216
+ if (polled.repositoryId !== input.repositoryId || !UUID.test(String(polled.deviceId || ''))) {
217
+ throw new Error('Approved Demo device does not match the requested repository.');
218
+ }
219
+ deviceId = String(polled.deviceId);
220
+ break;
221
+ }
222
+ if (polled.status !== 'pending')
223
+ throw new Error(`Demo device approval ended: ${String(polled.status || 'unknown')}.`);
224
+ await sleep(Math.min(2_000, Math.max(0, deadline - Date.now())));
225
+ }
226
+ if (!deviceId)
227
+ throw new Error('Demo device approval timed out. Resume from the same prompt while its grant is valid.');
228
+ const configPath = scopePath(input, origin);
229
+ try {
230
+ const existing = JSON.parse(await readFile(configPath, 'utf8'));
231
+ if (existing.deviceId !== deviceId || existing.publicKeyEd25519 !== identity.publicKeyEd25519) {
232
+ throw new Error('Existing Demo device belongs to another approved identity.');
233
+ }
234
+ return verifyDemoDevice(input, deps);
235
+ }
236
+ catch (error) {
237
+ if (error.code !== 'ENOENT')
238
+ throw error;
239
+ }
240
+ await writePrivateJson(configPath, { schema: 'dharma.demo-device/v1',
241
+ hqUrl: origin, organizationId: input.organizationId, repositoryId: input.repositoryId,
242
+ normalizedRepository: input.normalizedRepository, installationId: input.installationId,
243
+ deviceId, publicKeyEd25519: identity.publicKeyEd25519,
244
+ enrolledAt: new Date().toISOString(), signedReady: false, nextSequence: 1 });
245
+ return verifyDemoDevice(input, deps);
246
+ }
247
+ //# sourceMappingURL=demoEnrollment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"demoEnrollment.js","sourceRoot":"","sources":["../src/demoEnrollment.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=demoEnrollment.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"demoEnrollment.test.d.ts","sourceRoot":"","sources":["../src/demoEnrollment.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,274 @@
1
+ import assert from 'node:assert/strict';
2
+ import { execFileSync } from 'node:child_process';
3
+ import { createHash, createPublicKey, verify } from 'node:crypto';
4
+ import { mkdtemp, readFile, readdir, stat, writeFile } from 'node:fs/promises';
5
+ import { tmpdir } from 'node:os';
6
+ import { resolve } from 'node:path';
7
+ import test from 'node:test';
8
+ import { connectDemoDevice, verifyDemoDevice } from './demoEnrollment.js';
9
+ import { run } from './index.js';
10
+ const orgId = 'org_fixture';
11
+ const repositoryId = '10000000-0000-4000-8000-000000000001';
12
+ const deviceId = '30000000-0000-4000-8000-000000000001';
13
+ const grant = 'A'.repeat(43);
14
+ const deviceCode = 'B'.repeat(43);
15
+ const browserCode = 'ABCDEF0123456789ABCD';
16
+ const normalizedRepository = 'github.com/example/private';
17
+ const hqUrl = 'https://dharma.example';
18
+ function memoryStore() {
19
+ const values = new Map();
20
+ return { backend: 'linux-secret-service',
21
+ async get(account) { return values.get(account) || null; },
22
+ async put(account, value) { values.set(account, value); },
23
+ async delete(account) { values.delete(account); } };
24
+ }
25
+ function options(stateRoot) {
26
+ return { hqUrl, organizationId: orgId, repositoryId, normalizedRepository,
27
+ grant, deviceName: 'Fixture laptop', platform: 'linux',
28
+ installationId: '40000000-0000-4000-8000-000000000001',
29
+ stateRoot, maximumWaitMs: 1_000 };
30
+ }
31
+ test('Demo enrollment verifies the browser origin, waits for approval and signs a scoped status request', async () => {
32
+ const stateRoot = await mkdtemp(resolve(tmpdir(), 'dharma-demo-cli-'));
33
+ const calls = [];
34
+ let publicKey = '';
35
+ const fetcher = async (resource, init) => {
36
+ const url = new URL(String(resource));
37
+ calls.push(url.pathname);
38
+ if (url.pathname.endsWith('/enrollments')) {
39
+ const body = JSON.parse(String(init?.body));
40
+ assert.equal(body.grant, grant);
41
+ assert.equal(body.repositoryId, repositoryId);
42
+ publicKey = body.publicKeyEd25519;
43
+ return new Response(JSON.stringify({ ok: true, status: 'pending', organizationId: orgId,
44
+ repositoryId, deviceCode, expiresAt: new Date(Date.now() + 60_000).toISOString(),
45
+ verificationUri: `${hqUrl}/demo/fabric/approve?orgId=${orgId}&repositoryId=${repositoryId}&code=${browserCode}` }), { status: 202 });
46
+ }
47
+ if (url.pathname.endsWith('/poll')) {
48
+ assert.deepEqual(JSON.parse(String(init?.body)), { orgId, deviceCode });
49
+ return new Response(JSON.stringify({ ok: true, status: 'approved',
50
+ deviceId, repositoryId }), { status: 200 });
51
+ }
52
+ assert.equal(url.pathname, `/api/demo/fabric/repositories/${repositoryId}/status`);
53
+ const headers = new Headers(init?.headers);
54
+ const signingPayload = Buffer.from(JSON.stringify({
55
+ bodyHash: `sha256:${createHash('sha256').update('').digest('hex')}`,
56
+ deviceId,
57
+ messageId: headers.get('x-dharma-message-id'),
58
+ method: 'GET',
59
+ nonce: headers.get('x-dharma-nonce'),
60
+ organizationId: orgId,
61
+ pathname: `${url.pathname}${url.search}`,
62
+ sequence: Number(headers.get('x-dharma-sequence')),
63
+ sessionId: headers.get('x-dharma-session-id'),
64
+ timestamp: headers.get('x-dharma-timestamp'),
65
+ }));
66
+ assert.equal(verify(null, signingPayload, createPublicKey({ key: { kty: 'OKP', crv: 'Ed25519', x: publicKey }, format: 'jwk' }), Buffer.from(headers.get('x-dharma-signature'), 'base64url')), true);
67
+ return new Response(JSON.stringify({ ok: true, organizationId: orgId, repositoryId,
68
+ deviceId, normalizedRepository }), { status: 200 });
69
+ };
70
+ const approvals = [];
71
+ const connected = await connectDemoDevice(options(stateRoot), {
72
+ store: memoryStore(), fetcher, sleep: async () => { },
73
+ onApprovalRequired: async (url) => { approvals.push(url); },
74
+ });
75
+ assert.equal(connected.stage, 'device_signed_ready');
76
+ assert.equal(connected.deviceId, deviceId);
77
+ assert.deepEqual(calls, ['/api/demo/fabric/enrollments',
78
+ '/api/demo/fabric/enrollments/poll', `/api/demo/fabric/repositories/${repositoryId}/status`]);
79
+ assert.equal(approvals.length, 1);
80
+ assert.equal(new URL(approvals[0]).origin, hqUrl);
81
+ const config = JSON.parse(await readFile(connected.configPath, 'utf8'));
82
+ assert.equal(config.deviceId, deviceId);
83
+ assert.equal(config.grant, undefined);
84
+ assert.equal(config.privateKey, undefined);
85
+ if (process.platform !== 'win32')
86
+ assert.equal((await stat(connected.configPath)).mode & 0o777, 0o600);
87
+ });
88
+ test('Demo enrollment rejects an off-origin approval link before opening a browser or saving a device', async () => {
89
+ const stateRoot = await mkdtemp(resolve(tmpdir(), 'dharma-demo-cli-invalid-'));
90
+ let opened = false;
91
+ const fetcher = async () => new Response(JSON.stringify({ ok: true, status: 'pending',
92
+ organizationId: orgId, repositoryId, deviceCode,
93
+ expiresAt: new Date(Date.now() + 60_000).toISOString(),
94
+ verificationUri: `https://attacker.example/demo/fabric/approve?orgId=${orgId}&repositoryId=${repositoryId}&code=${browserCode}` }), { status: 202 });
95
+ await assert.rejects(connectDemoDevice(options(stateRoot), { store: memoryStore(), fetcher,
96
+ onApprovalRequired: async () => { opened = true; } }), /verification origin/i);
97
+ assert.equal(opened, false);
98
+ });
99
+ test('Demo command dry-run verifies the local repository without a grant or device write', async () => {
100
+ const root = await mkdtemp(resolve(tmpdir(), 'dharma-demo-repo-'));
101
+ const home = await mkdtemp(resolve(tmpdir(), 'dharma-demo-home-'));
102
+ execFileSync('git', ['init', root]);
103
+ execFileSync('git', ['-C', root, 'remote', 'add', 'origin', 'git@github.com:Example/Private.git']);
104
+ const previous = process.env.DHARMA_HOME;
105
+ process.env.DHARMA_HOME = home;
106
+ try {
107
+ const receipt = await run(['demo', 'connect', '--dry-run', '--workspace', root,
108
+ '--portal-url', hqUrl, '--organization-id', orgId,
109
+ '--repository-id', repositoryId, '--normalized-repository', normalizedRepository]);
110
+ assert.equal(receipt.stage, 'demo_device_plan');
111
+ await assert.rejects(stat(resolve(home, 'installation.json')), { code: 'ENOENT' });
112
+ await assert.rejects(run(['demo', 'connect', '--dry-run', '--workspace', root,
113
+ '--portal-url', hqUrl, '--organization-id', orgId,
114
+ '--repository-id', repositoryId, '--normalized-repository', 'github.com/other/repo']), /does not match/);
115
+ }
116
+ finally {
117
+ if (previous === undefined)
118
+ delete process.env.DHARMA_HOME;
119
+ else
120
+ process.env.DHARMA_HOME = previous;
121
+ }
122
+ });
123
+ test('lost status response resumes grant-free with exact replay, then retries an unseen expired sequence', async () => {
124
+ const stateRoot = await mkdtemp(resolve(tmpdir(), 'dharma-demo-recovery-'));
125
+ const store = memoryStore();
126
+ const signed = [];
127
+ let loseResponse = true;
128
+ const fetcher = async (resource, init) => {
129
+ const url = new URL(String(resource));
130
+ if (url.pathname.endsWith('/enrollments')) {
131
+ return new Response(JSON.stringify({ ok: true, status: 'pending', organizationId: orgId,
132
+ repositoryId, deviceCode, expiresAt: new Date(Date.now() + 60_000).toISOString(),
133
+ verificationUri: `${hqUrl}/demo/fabric/approve?orgId=${orgId}&repositoryId=${repositoryId}&code=${browserCode}` }), { status: 202 });
134
+ }
135
+ if (url.pathname.endsWith('/poll')) {
136
+ return new Response(JSON.stringify({ ok: true, status: 'approved', deviceId, repositoryId }), { status: 200 });
137
+ }
138
+ signed.push(new Headers(init?.headers));
139
+ if (loseResponse) {
140
+ loseResponse = false;
141
+ throw new Error('connection lost after dispatch');
142
+ }
143
+ return new Response(JSON.stringify({ ok: true, organizationId: orgId, repositoryId,
144
+ deviceId, normalizedRepository, duplicate: signed.length === 2 }), { status: 200 });
145
+ };
146
+ await assert.rejects(connectDemoDevice(options(stateRoot), { store, fetcher }), /connection lost/);
147
+ const directory = resolve(stateRoot, 'demo', (await readdir(resolve(stateRoot, 'demo')))[0]);
148
+ const configPath = resolve(directory, 'device.json');
149
+ assert.equal(JSON.parse(await readFile(configPath, 'utf8')).signedReady, false);
150
+ const scope = options(stateRoot);
151
+ const recovered = await verifyDemoDevice(scope, { store, fetcher });
152
+ assert.equal(recovered.stage, 'device_signed_ready');
153
+ assert.equal(signed[0].get('x-dharma-message-id'), signed[1].get('x-dharma-message-id'));
154
+ assert.equal(signed[1].get('x-dharma-sequence'), '1');
155
+ const pendingPath = `${configPath}.pending-status.json`;
156
+ const pending = { url: `${hqUrl}/api/demo/fabric/repositories/${repositoryId}/status?orgId=${orgId}`,
157
+ deviceId, sequence: 2, createdAt: new Date(Date.now() - 5 * 60_000).toISOString(),
158
+ headers: {} };
159
+ await writeFile(pendingPath, JSON.stringify(pending));
160
+ const recoveredAfterExpiry = await verifyDemoDevice(scope, { store, fetcher });
161
+ assert.equal(recoveredAfterExpiry.stage, 'device_signed_ready');
162
+ assert.equal(signed.at(-1).get('x-dharma-sequence'), '2');
163
+ assert.equal(JSON.parse(await readFile(configPath, 'utf8')).nextSequence, 3);
164
+ });
165
+ test('expired status advances once only after a typed sequence conflict', async () => {
166
+ const stateRoot = await mkdtemp(resolve(tmpdir(), 'dharma-demo-expired-'));
167
+ const store = memoryStore();
168
+ const sequences = [];
169
+ let acceptedSequence = 0;
170
+ const fetcher = async (resource, init) => {
171
+ const url = new URL(String(resource));
172
+ if (url.pathname.endsWith('/enrollments')) {
173
+ return new Response(JSON.stringify({ ok: true, status: 'pending', organizationId: orgId,
174
+ repositoryId, deviceCode, expiresAt: new Date(Date.now() + 60_000).toISOString(),
175
+ verificationUri: `${hqUrl}/demo/fabric/approve?orgId=${orgId}&repositoryId=${repositoryId}&code=${browserCode}` }), { status: 202 });
176
+ }
177
+ if (url.pathname.endsWith('/poll')) {
178
+ return new Response(JSON.stringify({ ok: true, status: 'approved', deviceId, repositoryId }), { status: 200 });
179
+ }
180
+ const sequence = Number(new Headers(init?.headers).get('x-dharma-sequence'));
181
+ sequences.push(sequence);
182
+ if (sequence !== acceptedSequence + 1) {
183
+ return new Response(JSON.stringify({ ok: false, error: {
184
+ code: 'demo_fabric_sequence_out_of_order', message: 'Device sequence is out of order.',
185
+ } }), { status: 409 });
186
+ }
187
+ acceptedSequence = sequence;
188
+ return new Response(JSON.stringify({ ok: true, organizationId: orgId, repositoryId,
189
+ deviceId, normalizedRepository }), { status: 200 });
190
+ };
191
+ const connected = await connectDemoDevice(options(stateRoot), { store, fetcher });
192
+ assert.equal(acceptedSequence, 1);
193
+ const configPath = connected.configPath;
194
+ const pendingPath = `${configPath}.pending-status.json`;
195
+ await writeFile(pendingPath, JSON.stringify({
196
+ url: `${hqUrl}/api/demo/fabric/repositories/${repositoryId}/status?orgId=${orgId}`,
197
+ deviceId, sequence: 2, createdAt: new Date(Date.now() - 5 * 60_000).toISOString(), headers: {},
198
+ }));
199
+ acceptedSequence = 2;
200
+ const recovered = await verifyDemoDevice(options(stateRoot), { store, fetcher });
201
+ assert.equal(recovered.stage, 'device_signed_ready');
202
+ assert.deepEqual(sequences, [1, 2, 3]);
203
+ assert.equal(JSON.parse(await readFile(configPath, 'utf8')).nextSequence, 4);
204
+ });
205
+ test('a 0.2.81 pending sequence that skipped an unseen request recovers without another grant', async () => {
206
+ const stateRoot = await mkdtemp(resolve(tmpdir(), 'dharma-demo-legacy-gap-'));
207
+ const store = memoryStore();
208
+ const sequences = [];
209
+ let lastAccepted = 0;
210
+ const fetcher = async (resource, init) => {
211
+ const url = new URL(String(resource));
212
+ if (url.pathname.endsWith('/enrollments')) {
213
+ return new Response(JSON.stringify({ ok: true, status: 'pending', organizationId: orgId,
214
+ repositoryId, deviceCode, expiresAt: new Date(Date.now() + 60_000).toISOString(),
215
+ verificationUri: `${hqUrl}/demo/fabric/approve?orgId=${orgId}&repositoryId=${repositoryId}&code=${browserCode}` }), { status: 202 });
216
+ }
217
+ if (url.pathname.endsWith('/poll')) {
218
+ return new Response(JSON.stringify({ ok: true, status: 'approved', deviceId, repositoryId }), { status: 200 });
219
+ }
220
+ const sequence = Number(new Headers(init?.headers).get('x-dharma-sequence'));
221
+ sequences.push(sequence);
222
+ if (sequence !== lastAccepted + 1) {
223
+ return new Response(JSON.stringify({ ok: false, error: {
224
+ code: 'demo_fabric_sequence_out_of_order', message: 'Device sequence is out of order.',
225
+ } }), { status: 409 });
226
+ }
227
+ lastAccepted = sequence;
228
+ return new Response(JSON.stringify({ ok: true, organizationId: orgId, repositoryId,
229
+ deviceId, normalizedRepository }), { status: 200 });
230
+ };
231
+ const connected = await connectDemoDevice(options(stateRoot), { store, fetcher });
232
+ await writeFile(`${connected.configPath}.pending-status.json`, JSON.stringify({
233
+ url: `${hqUrl}/api/demo/fabric/repositories/${repositoryId}/status?orgId=${orgId}`,
234
+ deviceId, sequence: 3, createdAt: new Date(Date.now() - 5 * 60_000).toISOString(), headers: {},
235
+ }));
236
+ const recovered = await verifyDemoDevice(options(stateRoot), { store, fetcher });
237
+ assert.equal(recovered.stage, 'device_signed_ready');
238
+ assert.deepEqual(sequences, [1, 3, 2]);
239
+ assert.equal(JSON.parse(await readFile(connected.configPath, 'utf8')).nextSequence, 3);
240
+ });
241
+ test('expired status does not advance on an unrelated conflict', async () => {
242
+ const stateRoot = await mkdtemp(resolve(tmpdir(), 'dharma-demo-conflict-'));
243
+ const store = memoryStore();
244
+ const sequences = [];
245
+ const fetcher = async (resource, init) => {
246
+ const url = new URL(String(resource));
247
+ if (url.pathname.endsWith('/enrollments')) {
248
+ return new Response(JSON.stringify({ ok: true, status: 'pending', organizationId: orgId,
249
+ repositoryId, deviceCode, expiresAt: new Date(Date.now() + 60_000).toISOString(),
250
+ verificationUri: `${hqUrl}/demo/fabric/approve?orgId=${orgId}&repositoryId=${repositoryId}&code=${browserCode}` }), { status: 202 });
251
+ }
252
+ if (url.pathname.endsWith('/poll')) {
253
+ return new Response(JSON.stringify({ ok: true, status: 'approved', deviceId, repositoryId }), { status: 200 });
254
+ }
255
+ const sequence = Number(new Headers(init?.headers).get('x-dharma-sequence'));
256
+ sequences.push(sequence);
257
+ if (sequence > 1)
258
+ return new Response(JSON.stringify({ ok: false, error: {
259
+ code: 'demo_fabric_message_replay_conflict', message: 'Message conflict.',
260
+ } }), { status: 409 });
261
+ return new Response(JSON.stringify({ ok: true, organizationId: orgId, repositoryId,
262
+ deviceId, normalizedRepository }), { status: 200 });
263
+ };
264
+ const connected = await connectDemoDevice(options(stateRoot), { store, fetcher });
265
+ const pendingPath = `${connected.configPath}.pending-status.json`;
266
+ await writeFile(pendingPath, JSON.stringify({
267
+ url: `${hqUrl}/api/demo/fabric/repositories/${repositoryId}/status?orgId=${orgId}`,
268
+ deviceId, sequence: 2, createdAt: new Date(Date.now() - 5 * 60_000).toISOString(), headers: {},
269
+ }));
270
+ await assert.rejects(verifyDemoDevice(options(stateRoot), { store, fetcher }), /demo_fabric_message_replay_conflict/);
271
+ assert.deepEqual(sequences, [1, 2]);
272
+ assert.equal(JSON.parse(await readFile(connected.configPath, 'utf8')).nextSequence, 2);
273
+ });
274
+ //# sourceMappingURL=demoEnrollment.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"demoEnrollment.test.js","sourceRoot":"","sources":["../src/demoEnrollment.test.ts"],"names":[],"mappings":"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"}