@dharma-ai-labs/agent-fabric 0.2.103 → 0.2.104
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/demoSupervisor.d.ts +34 -0
- package/dist/demoSupervisor.d.ts.map +1 -0
- package/dist/demoSupervisor.js +164 -0
- package/dist/demoSupervisor.js.map +1 -0
- package/dist/demoSupervisor.test.d.ts +2 -0
- package/dist/demoSupervisor.test.d.ts.map +1 -0
- package/dist/demoSupervisor.test.js +249 -0
- package/dist/demoSupervisor.test.js.map +1 -0
- package/dist/demoWatchControl.d.ts +60 -0
- package/dist/demoWatchControl.d.ts.map +1 -0
- package/dist/demoWatchControl.js +128 -0
- package/dist/demoWatchControl.js.map +1 -0
- package/dist/demoWatchControl.test.d.ts +2 -0
- package/dist/demoWatchControl.test.d.ts.map +1 -0
- package/dist/demoWatchControl.test.js +184 -0
- package/dist/demoWatchControl.test.js.map +1 -0
- package/dist/demoWatchHealth.d.ts +26 -0
- package/dist/demoWatchHealth.d.ts.map +1 -0
- package/dist/demoWatchHealth.js +177 -0
- package/dist/demoWatchHealth.js.map +1 -0
- package/dist/demoWatchHealth.test.d.ts +2 -0
- package/dist/demoWatchHealth.test.d.ts.map +1 -0
- package/dist/demoWatchHealth.test.js +175 -0
- package/dist/demoWatchHealth.test.js.map +1 -0
- package/dist/demoWatchRegistry.d.ts +17 -0
- package/dist/demoWatchRegistry.d.ts.map +1 -0
- package/dist/demoWatchRegistry.js +170 -0
- package/dist/demoWatchRegistry.js.map +1 -0
- package/dist/demoWatchRegistry.test.d.ts +2 -0
- package/dist/demoWatchRegistry.test.d.ts.map +1 -0
- package/dist/demoWatchRegistry.test.js +146 -0
- package/dist/demoWatchRegistry.test.js.map +1 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +236 -71
- package/dist/index.js.map +1 -1
- package/dist/index.test.js +68 -4
- package/dist/index.test.js.map +1 -1
- package/dist/pidLock.test.d.ts +2 -0
- package/dist/pidLock.test.d.ts.map +1 -0
- package/dist/pidLock.test.js +172 -0
- package/dist/pidLock.test.js.map +1 -0
- package/dist/relayAutostart.d.ts +17 -6
- package/dist/relayAutostart.d.ts.map +1 -1
- package/dist/relayAutostart.js +124 -19
- package/dist/relayAutostart.js.map +1 -1
- package/dist/relayAutostart.test.js +158 -1
- package/dist/relayAutostart.test.js.map +1 -1
- package/dist/relaySupervisor.test.js +75 -1
- package/dist/relaySupervisor.test.js.map +1 -1
- package/dist/repositoryOnboardingCaller.test.js +21 -0
- package/dist/repositoryOnboardingCaller.test.js.map +1 -1
- package/dist/schemas/demo-watch-control.v1.schema.json +27 -0
- package/dist/schemas/demo-watch-health.v1.schema.json +24 -0
- package/dist/schemas/demo-watch-registration.v1.schema.json +18 -0
- package/dist/schemas/relay-autostart.v2.schema.json +23 -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 +1 -1
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { mkdir, mkdtemp, readFile, rm, symlink, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { tmpdir } from 'node:os';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import test from 'node:test';
|
|
6
|
+
import { createDemoWatchHealthRecorder, readDemoWatchHealth, writeDemoWatchHealth } from './demoWatchHealth.js';
|
|
7
|
+
const key = 'a'.repeat(64);
|
|
8
|
+
const now = Date.parse('2026-09-26T03:00:00.000Z');
|
|
9
|
+
const receipt = { schema: 'dharma.demo-watch-health/v1', key, pid: 123,
|
|
10
|
+
version: '0.2.103', observedAt: new Date(now).toISOString(), state: 'completed',
|
|
11
|
+
stage: 'demo_repository_package_installed', sourceState: 'unchanged', code: null };
|
|
12
|
+
test('health recorder serializes writes, coalesces pending scopes and drains before lease release', async () => {
|
|
13
|
+
const rows = [];
|
|
14
|
+
let finish;
|
|
15
|
+
let concurrent = 0;
|
|
16
|
+
let maximum = 0;
|
|
17
|
+
const recorder = createDemoWatchHealthRecorder({ home: '/unused', pid: 123, version: '0.2.103',
|
|
18
|
+
now: () => now, write: async (_home, row) => {
|
|
19
|
+
maximum = Math.max(maximum, ++concurrent);
|
|
20
|
+
if (!rows.length)
|
|
21
|
+
await new Promise(resolve => { finish = resolve; });
|
|
22
|
+
rows.push(row);
|
|
23
|
+
concurrent -= 1;
|
|
24
|
+
} });
|
|
25
|
+
recorder.record(receipt);
|
|
26
|
+
await new Promise(resolve => setImmediate(resolve));
|
|
27
|
+
recorder.record({ ...receipt, key: 'b'.repeat(64), sourceState: 'pending' });
|
|
28
|
+
recorder.record({ ...receipt, key: 'b'.repeat(64), sourceState: 'unchanged' });
|
|
29
|
+
let drained = false;
|
|
30
|
+
const drain = recorder.drain().then(() => { drained = true; });
|
|
31
|
+
await new Promise(resolve => setImmediate(resolve));
|
|
32
|
+
assert.equal(drained, false);
|
|
33
|
+
finish();
|
|
34
|
+
await drain;
|
|
35
|
+
assert.equal(maximum, 1);
|
|
36
|
+
assert.equal(rows.length, 2);
|
|
37
|
+
assert.equal(rows[1]?.sourceState, 'unchanged');
|
|
38
|
+
assert.equal(recorder.available(), true);
|
|
39
|
+
});
|
|
40
|
+
test('a receipt arriving while the writer closes is drained rather than stranded', async () => {
|
|
41
|
+
const rows = [];
|
|
42
|
+
const recorder = createDemoWatchHealthRecorder({ home: '/unused', pid: 123, version: '0.2.103',
|
|
43
|
+
now: () => now, write: async (_home, row) => {
|
|
44
|
+
rows.push(row);
|
|
45
|
+
if (rows.length === 1)
|
|
46
|
+
queueMicrotask(() => queueMicrotask(() => {
|
|
47
|
+
recorder.record({ ...receipt, key: 'b'.repeat(64) });
|
|
48
|
+
}));
|
|
49
|
+
} });
|
|
50
|
+
recorder.record(receipt);
|
|
51
|
+
await recorder.drain();
|
|
52
|
+
assert.equal(rows.length, 2);
|
|
53
|
+
assert.equal(rows[1]?.key, 'b'.repeat(64));
|
|
54
|
+
});
|
|
55
|
+
test('health write failure gates cycles and a later recorded observation restores the gate', async () => {
|
|
56
|
+
let fail = true;
|
|
57
|
+
const recorder = createDemoWatchHealthRecorder({ home: '/unused', pid: 123, version: '0.2.103',
|
|
58
|
+
now: () => now, write: async () => { if (fail)
|
|
59
|
+
throw new Error('private filesystem error'); } });
|
|
60
|
+
recorder.record(receipt);
|
|
61
|
+
await recorder.drain();
|
|
62
|
+
assert.equal(recorder.available(), false);
|
|
63
|
+
fail = false;
|
|
64
|
+
recorder.record({ ...receipt, state: 'failed', stage: null, sourceState: null, code: 'demo_watch_health_unavailable' });
|
|
65
|
+
await recorder.drain();
|
|
66
|
+
assert.equal(recorder.available(), true);
|
|
67
|
+
});
|
|
68
|
+
test('success on another repository cannot clear a failed scope receipt', async () => {
|
|
69
|
+
let fail = true;
|
|
70
|
+
const otherKey = 'b'.repeat(64);
|
|
71
|
+
const recorder = createDemoWatchHealthRecorder({ home: '/unused', pid: 123, version: '0.2.103',
|
|
72
|
+
now: () => now, write: async (_home, row) => {
|
|
73
|
+
if (row.key === key && fail)
|
|
74
|
+
throw new Error('Single-scope write failed');
|
|
75
|
+
} });
|
|
76
|
+
recorder.record(receipt);
|
|
77
|
+
await recorder.drain();
|
|
78
|
+
recorder.record({ ...receipt, key: otherKey });
|
|
79
|
+
await recorder.drain();
|
|
80
|
+
assert.equal(recorder.available(), false);
|
|
81
|
+
assert.equal(recorder.available(key), false);
|
|
82
|
+
assert.equal(recorder.available(otherKey), true);
|
|
83
|
+
fail = false;
|
|
84
|
+
recorder.record(receipt);
|
|
85
|
+
await recorder.drain();
|
|
86
|
+
assert.equal(recorder.available(key), true);
|
|
87
|
+
assert.equal(recorder.available(), true);
|
|
88
|
+
});
|
|
89
|
+
test('health recorder rejects malformed observations and ignores unscoped registry failures', async () => {
|
|
90
|
+
let writes = 0;
|
|
91
|
+
const recorder = createDemoWatchHealthRecorder({ home: '/unused', pid: 123, version: '0.2.103',
|
|
92
|
+
now: () => now, write: async () => { writes += 1; } });
|
|
93
|
+
recorder.record({ ...receipt, key: null });
|
|
94
|
+
recorder.record({ ...receipt, key: 'bad-key' });
|
|
95
|
+
await recorder.drain();
|
|
96
|
+
assert.equal(writes, 0);
|
|
97
|
+
assert.equal(recorder.available(), false);
|
|
98
|
+
});
|
|
99
|
+
async function fixture() {
|
|
100
|
+
const home = await mkdtemp(join(tmpdir(), 'dharma-demo-watch-health-'));
|
|
101
|
+
await mkdir(join(home, 'relay'));
|
|
102
|
+
await writeFile(join(home, 'relay', 'supervisor.pid'), '123\n');
|
|
103
|
+
return home;
|
|
104
|
+
}
|
|
105
|
+
test('health is credential-free and fresh only for its current supervisor/version', async () => {
|
|
106
|
+
const home = await fixture();
|
|
107
|
+
try {
|
|
108
|
+
await writeDemoWatchHealth(home, receipt);
|
|
109
|
+
assert.deepEqual(await readDemoWatchHealth(home, key, { pid: 123, version: '0.2.103', now }), receipt);
|
|
110
|
+
assert.equal(await readDemoWatchHealth(home, key, { pid: 124, version: '0.2.103', now }), null);
|
|
111
|
+
assert.equal(await readDemoWatchHealth(home, key, { pid: 123, version: '0.2.104', now }), null);
|
|
112
|
+
assert.equal(await readDemoWatchHealth(home, key, { pid: 123, version: '0.2.103', now: now + 180_001 }), null);
|
|
113
|
+
assert.equal(await readDemoWatchHealth(home, key, { pid: 123, version: '0.2.103', now: now - 10_000 }), null);
|
|
114
|
+
const raw = await readFile(join(home, 'relay', 'demo-watch-health', `${key}.json`), 'utf8');
|
|
115
|
+
assert.doesNotMatch(raw, /token|grant|password|workspace|email|Authorization/);
|
|
116
|
+
}
|
|
117
|
+
finally {
|
|
118
|
+
await rm(home, { recursive: true, force: true });
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
test('a departed supervisor cannot overwrite its successor receipt', async () => {
|
|
122
|
+
const home = await fixture();
|
|
123
|
+
try {
|
|
124
|
+
await writeDemoWatchHealth(home, receipt);
|
|
125
|
+
await writeFile(join(home, 'relay', 'supervisor.pid'), '124\n');
|
|
126
|
+
const newer = { ...receipt, pid: 124, state: 'timed_out',
|
|
127
|
+
stage: null, sourceState: null, code: 'demo_watch_cycle_timeout' };
|
|
128
|
+
await writeDemoWatchHealth(home, newer);
|
|
129
|
+
await assert.rejects(writeDemoWatchHealth(home, receipt), /supervisor changed/);
|
|
130
|
+
assert.deepEqual(await readDemoWatchHealth(home, key, { pid: 124, version: '0.2.103', now }), newer);
|
|
131
|
+
}
|
|
132
|
+
finally {
|
|
133
|
+
await rm(home, { recursive: true, force: true });
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
test('missing, malformed and foreign-key health cannot establish readiness', async () => {
|
|
137
|
+
const home = await fixture();
|
|
138
|
+
try {
|
|
139
|
+
const expected = { pid: 123, version: '0.2.103', now };
|
|
140
|
+
assert.equal(await readDemoWatchHealth(home, key, expected), null);
|
|
141
|
+
await writeDemoWatchHealth(home, receipt);
|
|
142
|
+
const path = join(home, 'relay', 'demo-watch-health', `${key}.json`);
|
|
143
|
+
await writeFile(path, JSON.stringify({ ...receipt, key: 'b'.repeat(64) }));
|
|
144
|
+
await assert.rejects(readDemoWatchHealth(home, key, expected), /invalid/);
|
|
145
|
+
await writeFile(path, 'private malformed payload');
|
|
146
|
+
await assert.rejects(readDemoWatchHealth(home, key, expected), /^Error: Demo watch health receipt is invalid\.$/);
|
|
147
|
+
await assert.rejects(writeDemoWatchHealth(home, { ...receipt, grant: 'never-persist' }), /invalid/);
|
|
148
|
+
await assert.rejects(writeDemoWatchHealth(home, { ...receipt, stage: 'private content' }), /invalid/);
|
|
149
|
+
await assert.rejects(writeDemoWatchHealth(home, { ...receipt, code: 'failure_on_completed' }), /invalid/);
|
|
150
|
+
}
|
|
151
|
+
finally {
|
|
152
|
+
await rm(home, { recursive: true, force: true });
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
test('health never follows directory or leaf symlinks', { skip: process.platform === 'win32' }, async () => {
|
|
156
|
+
const home = await fixture();
|
|
157
|
+
const outside = await mkdtemp(join(tmpdir(), 'dharma-demo-watch-health-outside-'));
|
|
158
|
+
try {
|
|
159
|
+
await symlink(outside, join(home, 'relay', 'demo-watch-health'));
|
|
160
|
+
await assert.rejects(writeDemoWatchHealth(home, receipt), /symlink/);
|
|
161
|
+
await rm(join(home, 'relay', 'demo-watch-health'));
|
|
162
|
+
await mkdir(join(home, 'relay', 'demo-watch-health'));
|
|
163
|
+
const target = join(outside, 'preserve.json');
|
|
164
|
+
await writeFile(target, JSON.stringify(receipt));
|
|
165
|
+
await symlink(target, join(home, 'relay', 'demo-watch-health', `${key}.json`));
|
|
166
|
+
await assert.rejects(readDemoWatchHealth(home, key, { pid: 123, version: '0.2.103', now }), /symlink/);
|
|
167
|
+
await assert.rejects(writeDemoWatchHealth(home, receipt), /symlink/);
|
|
168
|
+
assert.equal(await readFile(target, 'utf8'), JSON.stringify(receipt));
|
|
169
|
+
}
|
|
170
|
+
finally {
|
|
171
|
+
await rm(home, { recursive: true, force: true });
|
|
172
|
+
await rm(outside, { recursive: true, force: true });
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
//# sourceMappingURL=demoWatchHealth.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"demoWatchHealth.test.js","sourceRoot":"","sources":["../src/demoWatchHealth.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type DemoWatchRegistration = {
|
|
2
|
+
schema: 'dharma.demo-watch/v1';
|
|
3
|
+
hqUrl: string;
|
|
4
|
+
organizationId: string;
|
|
5
|
+
repositoryId: string;
|
|
6
|
+
normalizedRepository: string;
|
|
7
|
+
provider: 'codex' | 'claude' | 'agy' | 'hermes';
|
|
8
|
+
workspace: string;
|
|
9
|
+
};
|
|
10
|
+
export declare function demoWatchRegistrationKey(registration: DemoWatchRegistration): string;
|
|
11
|
+
export declare function listDemoWatchRegistrations(home: string): Promise<DemoWatchRegistration[]>;
|
|
12
|
+
export declare function registerDemoWatch(home: string, input: DemoWatchRegistration): Promise<{
|
|
13
|
+
created: boolean;
|
|
14
|
+
key: string;
|
|
15
|
+
}>;
|
|
16
|
+
export declare function unregisterDemoWatch(home: string, input: DemoWatchRegistration): Promise<boolean>;
|
|
17
|
+
//# sourceMappingURL=demoWatchRegistry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"demoWatchRegistry.d.ts","sourceRoot":"","sources":["../src/demoWatchRegistry.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,EAAE,sBAAsB,CAAC;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,QAAQ,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,GAAG,QAAQ,CAAC;IAChD,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AA0BF,wBAAgB,wBAAwB,CAAC,YAAY,EAAE,qBAAqB,UAI3E;AAoCD,wBAAsB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAc/F;AAiBD,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,qBAAqB;;;GAyBjF;AAED,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,qBAAqB,oBAWnF"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { constants } from 'node:fs';
|
|
2
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
3
|
+
import { link, lstat, mkdir, open, readdir, realpath, unlink } from 'node:fs/promises';
|
|
4
|
+
import { isAbsolute, join, resolve } from 'node:path';
|
|
5
|
+
import { normalizeHqUrl } from '@dharma-ai-labs/agent-fabric-relay-client';
|
|
6
|
+
const MAXIMUM_REGISTRATIONS = 32;
|
|
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;
|
|
8
|
+
const FILE = /^[a-f0-9]{64}\.json$/;
|
|
9
|
+
function validate(value) {
|
|
10
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
11
|
+
throw new Error('Demo watch registration is invalid.');
|
|
12
|
+
}
|
|
13
|
+
const row = value;
|
|
14
|
+
const keys = ['schema', 'hqUrl', 'organizationId', 'repositoryId',
|
|
15
|
+
'normalizedRepository', 'provider', 'workspace'];
|
|
16
|
+
if (Object.keys(row).length !== keys.length || keys.some(key => !Object.hasOwn(row, key))
|
|
17
|
+
|| row.schema !== 'dharma.demo-watch/v1'
|
|
18
|
+
|| typeof row.hqUrl !== 'string' || normalizeHqUrl(row.hqUrl) !== row.hqUrl
|
|
19
|
+
|| typeof row.organizationId !== 'string' || !/^org_[A-Za-z0-9]+$/.test(row.organizationId)
|
|
20
|
+
|| typeof row.repositoryId !== 'string' || !UUID.test(row.repositoryId)
|
|
21
|
+
|| typeof row.normalizedRepository !== 'string' || row.normalizedRepository.length > 500
|
|
22
|
+
|| !/^[A-Za-z0-9.-]+\/[A-Za-z0-9._/-]+$/.test(row.normalizedRepository)
|
|
23
|
+
|| row.normalizedRepository.split('/').some(part => !part || part === '.' || part === '..')
|
|
24
|
+
|| typeof row.provider !== 'string' || !['codex', 'claude', 'agy', 'hermes'].includes(row.provider)
|
|
25
|
+
|| typeof row.workspace !== 'string' || !isAbsolute(row.workspace)
|
|
26
|
+
|| resolve(row.workspace) !== row.workspace || row.workspace.length > 4096
|
|
27
|
+
|| /[\r\n\0]/.test(row.workspace)) {
|
|
28
|
+
throw new Error('Demo watch registration is invalid or contains untrusted fields.');
|
|
29
|
+
}
|
|
30
|
+
return row;
|
|
31
|
+
}
|
|
32
|
+
export function demoWatchRegistrationKey(registration) {
|
|
33
|
+
const row = validate(registration);
|
|
34
|
+
return createHash('sha256').update(`${row.hqUrl}\0${row.organizationId}\0${row.repositoryId}`)
|
|
35
|
+
.digest('hex');
|
|
36
|
+
}
|
|
37
|
+
async function directory(home, create) {
|
|
38
|
+
let current = resolve(home);
|
|
39
|
+
for (const segment of ['', 'relay', 'demo-watches']) {
|
|
40
|
+
if (segment)
|
|
41
|
+
current = join(current, segment);
|
|
42
|
+
if (create && segment)
|
|
43
|
+
await mkdir(current, { mode: 0o700 }).catch((error) => {
|
|
44
|
+
if (error.code !== 'EEXIST')
|
|
45
|
+
throw error;
|
|
46
|
+
});
|
|
47
|
+
const stat = await lstat(current).catch((error) => {
|
|
48
|
+
if (!create && error.code === 'ENOENT')
|
|
49
|
+
return null;
|
|
50
|
+
throw error;
|
|
51
|
+
});
|
|
52
|
+
if (!stat)
|
|
53
|
+
return null;
|
|
54
|
+
if (!stat.isDirectory() || stat.isSymbolicLink()) {
|
|
55
|
+
throw new Error('Demo watch registry directory or symlink is invalid.');
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return current;
|
|
59
|
+
}
|
|
60
|
+
async function readRegistration(path) {
|
|
61
|
+
const entry = await lstat(path);
|
|
62
|
+
if (!entry.isFile() || entry.isSymbolicLink() || entry.size > 8192) {
|
|
63
|
+
throw new Error('Demo watch registry file or symlink is invalid.');
|
|
64
|
+
}
|
|
65
|
+
const handle = await open(path, constants.O_RDONLY | (constants.O_NOFOLLOW || 0));
|
|
66
|
+
try {
|
|
67
|
+
const actual = await handle.stat();
|
|
68
|
+
if (!actual.isFile() || actual.size > 8192 || (entry.ino !== 0 && actual.ino !== entry.ino)) {
|
|
69
|
+
throw new Error('Demo watch registry file changed during validation.');
|
|
70
|
+
}
|
|
71
|
+
return validate(JSON.parse(await handle.readFile({ encoding: 'utf8' })));
|
|
72
|
+
}
|
|
73
|
+
finally {
|
|
74
|
+
await handle.close();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
export async function listDemoWatchRegistrations(home) {
|
|
78
|
+
const root = await directory(home, false);
|
|
79
|
+
if (!root)
|
|
80
|
+
return [];
|
|
81
|
+
const names = (await readdir(root)).filter(name => FILE.test(name)).sort();
|
|
82
|
+
if (names.length > MAXIMUM_REGISTRATIONS)
|
|
83
|
+
throw new Error('Demo watch registration limit exceeded.');
|
|
84
|
+
const result = [];
|
|
85
|
+
for (const name of names) {
|
|
86
|
+
const row = await readRegistration(join(root, name));
|
|
87
|
+
if (name !== `${demoWatchRegistrationKey(row)}.json`) {
|
|
88
|
+
throw new Error('Demo watch registry identity does not match its filename.');
|
|
89
|
+
}
|
|
90
|
+
result.push(row);
|
|
91
|
+
}
|
|
92
|
+
return result;
|
|
93
|
+
}
|
|
94
|
+
function assertSame(existing, requested) {
|
|
95
|
+
if (existing.workspace !== requested.workspace) {
|
|
96
|
+
throw new Error('demo_watch_workspace_conflict: this repository is watched from another checkout.');
|
|
97
|
+
}
|
|
98
|
+
if (existing.provider !== requested.provider) {
|
|
99
|
+
throw new Error('demo_watch_provider_conflict: this repository has another provider registration.');
|
|
100
|
+
}
|
|
101
|
+
if (JSON.stringify(existing) !== JSON.stringify(requested)) {
|
|
102
|
+
const keys = Object.keys(requested);
|
|
103
|
+
if (keys.some(key => existing[key] !== requested[key])) {
|
|
104
|
+
throw new Error('Demo watch registration conflicts with its existing scope.');
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
export async function registerDemoWatch(home, input) {
|
|
109
|
+
const row = validate(input);
|
|
110
|
+
if (await realpath(row.workspace) !== row.workspace) {
|
|
111
|
+
throw new Error('Demo watch workspace must be its canonical path.');
|
|
112
|
+
}
|
|
113
|
+
const root = (await directory(home, true));
|
|
114
|
+
const key = demoWatchRegistrationKey(row);
|
|
115
|
+
const target = join(root, `${key}.json`);
|
|
116
|
+
const temporary = join(root, `.${key}.${randomUUID()}.tmp`);
|
|
117
|
+
const handle = await open(temporary, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | (constants.O_NOFOLLOW || 0), 0o600);
|
|
118
|
+
try {
|
|
119
|
+
await handle.writeFile(`${JSON.stringify(row)}\n`);
|
|
120
|
+
await handle.sync();
|
|
121
|
+
}
|
|
122
|
+
finally {
|
|
123
|
+
await handle.close();
|
|
124
|
+
}
|
|
125
|
+
let created = false;
|
|
126
|
+
try {
|
|
127
|
+
// A no-replace link makes simultaneous enrollment idempotent without overwriting another checkout.
|
|
128
|
+
try {
|
|
129
|
+
await link(temporary, target);
|
|
130
|
+
created = true;
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
if (error.code !== 'EEXIST')
|
|
134
|
+
throw error;
|
|
135
|
+
assertSame(await readRegistration(target), row);
|
|
136
|
+
}
|
|
137
|
+
try {
|
|
138
|
+
await listDemoWatchRegistrations(home);
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
if (created)
|
|
142
|
+
await unlink(target);
|
|
143
|
+
throw error;
|
|
144
|
+
}
|
|
145
|
+
return { created, key };
|
|
146
|
+
}
|
|
147
|
+
finally {
|
|
148
|
+
await unlink(temporary);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
export async function unregisterDemoWatch(home, input) {
|
|
152
|
+
const row = validate(input);
|
|
153
|
+
const root = await directory(home, false);
|
|
154
|
+
if (!root)
|
|
155
|
+
return false;
|
|
156
|
+
const target = join(root, `${demoWatchRegistrationKey(row)}.json`);
|
|
157
|
+
let existing;
|
|
158
|
+
try {
|
|
159
|
+
existing = await readRegistration(target);
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
if (error.code === 'ENOENT')
|
|
163
|
+
return false;
|
|
164
|
+
throw error;
|
|
165
|
+
}
|
|
166
|
+
assertSame(existing, row);
|
|
167
|
+
await unlink(target);
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=demoWatchRegistry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"demoWatchRegistry.js","sourceRoot":"","sources":["../src/demoWatchRegistry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"demoWatchRegistry.test.d.ts","sourceRoot":"","sources":["../src/demoWatchRegistry.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { mkdtemp, mkdir, readFile, realpath, rm, symlink, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { tmpdir } from 'node:os';
|
|
4
|
+
import { basename, join } from 'node:path';
|
|
5
|
+
import test from 'node:test';
|
|
6
|
+
import { demoWatchRegistrationKey, listDemoWatchRegistrations, registerDemoWatch, unregisterDemoWatch } from './demoWatchRegistry.js';
|
|
7
|
+
const scope = {
|
|
8
|
+
hqUrl: 'https://demo.example.test', organizationId: 'org_demo123',
|
|
9
|
+
repositoryId: '00000000-0000-4000-8000-000000000001',
|
|
10
|
+
normalizedRepository: 'github.com/example/repository', provider: 'codex',
|
|
11
|
+
};
|
|
12
|
+
async function fixture(parent = tmpdir()) {
|
|
13
|
+
const root = await realpath(await mkdtemp(join(parent, 'dharma-demo-watch-')));
|
|
14
|
+
const home = join(root, 'home');
|
|
15
|
+
const workspace = join(root, 'workspace');
|
|
16
|
+
await mkdir(home);
|
|
17
|
+
await mkdir(workspace);
|
|
18
|
+
return { root, home, workspace, registration: { schema: 'dharma.demo-watch/v1',
|
|
19
|
+
...scope, workspace } };
|
|
20
|
+
}
|
|
21
|
+
test('Demo watch registration is scoped, credential-free and idempotent', async () => {
|
|
22
|
+
const f = await fixture();
|
|
23
|
+
try {
|
|
24
|
+
assert.equal((await registerDemoWatch(f.home, f.registration)).created, true);
|
|
25
|
+
assert.equal((await registerDemoWatch(f.home, f.registration)).created, false);
|
|
26
|
+
assert.deepEqual(await listDemoWatchRegistrations(f.home), [f.registration]);
|
|
27
|
+
const bytes = await readFile(join(f.home, 'relay', 'demo-watches', `${demoWatchRegistrationKey(f.registration)}.json`), 'utf8');
|
|
28
|
+
assert.equal(bytes.includes('grant'), false);
|
|
29
|
+
assert.equal(bytes.includes('privateKey'), false);
|
|
30
|
+
assert.equal(bytes.includes('installationId'), false);
|
|
31
|
+
}
|
|
32
|
+
finally {
|
|
33
|
+
await rm(f.root, { recursive: true, force: true });
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
test('fixtures canonicalize an aliased temporary root without accepting an alias in a registration', async () => {
|
|
37
|
+
const root = await realpath(await mkdtemp(join(tmpdir(), 'dharma-watch-temp-alias-')));
|
|
38
|
+
const target = join(root, 'target');
|
|
39
|
+
const alias = join(root, 'alias');
|
|
40
|
+
try {
|
|
41
|
+
await mkdir(target);
|
|
42
|
+
await symlink(target, alias, process.platform === 'win32' ? 'junction' : 'dir');
|
|
43
|
+
const f = await fixture(alias);
|
|
44
|
+
assert.equal(f.workspace, await realpath(f.workspace));
|
|
45
|
+
await registerDemoWatch(f.home, f.registration);
|
|
46
|
+
await assert.rejects(registerDemoWatch(f.home, { ...f.registration,
|
|
47
|
+
workspace: join(alias, basename(f.root), 'workspace') }), /canonical path/);
|
|
48
|
+
assert.deepEqual(await listDemoWatchRegistrations(f.home), [f.registration]);
|
|
49
|
+
}
|
|
50
|
+
finally {
|
|
51
|
+
await rm(root, { recursive: true, force: true });
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
test('concurrent registration converges and never overwrites another checkout', async () => {
|
|
55
|
+
const f = await fixture();
|
|
56
|
+
try {
|
|
57
|
+
const results = await Promise.all(Array.from({ length: 10 }, () => registerDemoWatch(f.home, f.registration)));
|
|
58
|
+
assert.equal(results.filter(result => result.created).length, 1);
|
|
59
|
+
const other = join(f.root, 'other');
|
|
60
|
+
await mkdir(other);
|
|
61
|
+
await assert.rejects(registerDemoWatch(f.home, { ...f.registration, workspace: other }), /demo_watch_workspace_conflict/);
|
|
62
|
+
assert.deepEqual(await listDemoWatchRegistrations(f.home), [f.registration]);
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
await rm(f.root, { recursive: true, force: true });
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
test('registration rejects untrusted fields and invalid scope', async () => {
|
|
69
|
+
const f = await fixture();
|
|
70
|
+
try {
|
|
71
|
+
for (const override of [{ grant: 'never-save-me' }, { workspace: '../foreign' },
|
|
72
|
+
{ hqUrl: 'https://secret@example.test' }, { repositoryId: '../foreign' },
|
|
73
|
+
{ provider: 'shell' }, { normalizedRepository: 'repo\ncommand' }]) {
|
|
74
|
+
await assert.rejects(registerDemoWatch(f.home, { ...f.registration, ...override }));
|
|
75
|
+
}
|
|
76
|
+
assert.deepEqual(await listDemoWatchRegistrations(f.home), []);
|
|
77
|
+
}
|
|
78
|
+
finally {
|
|
79
|
+
await rm(f.root, { recursive: true, force: true });
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
test('registration and listing reject symlink redirection and forged filenames', async () => {
|
|
83
|
+
const f = await fixture();
|
|
84
|
+
try {
|
|
85
|
+
await mkdir(join(f.home, 'relay'));
|
|
86
|
+
await symlink(f.workspace, join(f.home, 'relay', 'demo-watches'), 'dir');
|
|
87
|
+
await assert.rejects(registerDemoWatch(f.home, f.registration), /symlink|directory/);
|
|
88
|
+
await rm(join(f.home, 'relay', 'demo-watches'));
|
|
89
|
+
await registerDemoWatch(f.home, f.registration);
|
|
90
|
+
const directory = join(f.home, 'relay', 'demo-watches');
|
|
91
|
+
await writeFile(join(directory, `${'a'.repeat(64)}.json`), JSON.stringify(f.registration));
|
|
92
|
+
await assert.rejects(listDemoWatchRegistrations(f.home), /identity/);
|
|
93
|
+
}
|
|
94
|
+
finally {
|
|
95
|
+
await rm(f.root, { recursive: true, force: true });
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
test('unregister removes only its scope and preserves workspace content', async () => {
|
|
99
|
+
const f = await fixture();
|
|
100
|
+
try {
|
|
101
|
+
await writeFile(join(f.workspace, 'preserve.txt'), 'customer work');
|
|
102
|
+
await registerDemoWatch(f.home, f.registration);
|
|
103
|
+
await registerDemoWatch(f.home, { ...f.registration,
|
|
104
|
+
repositoryId: '00000000-0000-4000-8000-000000000002' });
|
|
105
|
+
assert.equal(await unregisterDemoWatch(f.home, f.registration), true);
|
|
106
|
+
assert.equal(await unregisterDemoWatch(f.home, f.registration), false);
|
|
107
|
+
assert.equal((await listDemoWatchRegistrations(f.home)).length, 1);
|
|
108
|
+
assert.equal(await readFile(join(f.workspace, 'preserve.txt'), 'utf8'), 'customer work');
|
|
109
|
+
}
|
|
110
|
+
finally {
|
|
111
|
+
await rm(f.root, { recursive: true, force: true });
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
test('capacity is bounded and a rejected registration leaves existing scopes intact', async () => {
|
|
115
|
+
const f = await fixture();
|
|
116
|
+
try {
|
|
117
|
+
for (let index = 1; index <= 32; index += 1) {
|
|
118
|
+
await registerDemoWatch(f.home, { ...f.registration,
|
|
119
|
+
repositoryId: `00000000-0000-4000-8000-${String(index).padStart(12, '0')}` });
|
|
120
|
+
}
|
|
121
|
+
await assert.rejects(registerDemoWatch(f.home, { ...f.registration,
|
|
122
|
+
repositoryId: '00000000-0000-4000-8000-000000000033' }), /limit/);
|
|
123
|
+
assert.equal((await listDemoWatchRegistrations(f.home)).length, 32);
|
|
124
|
+
}
|
|
125
|
+
finally {
|
|
126
|
+
await rm(f.root, { recursive: true, force: true });
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
test('leaf symlink never supplies a registration or gets overwritten', async () => {
|
|
130
|
+
const f = await fixture();
|
|
131
|
+
try {
|
|
132
|
+
await registerDemoWatch(f.home, f.registration);
|
|
133
|
+
const target = join(f.home, 'relay', 'demo-watches', `${demoWatchRegistrationKey(f.registration)}.json`);
|
|
134
|
+
await rm(target);
|
|
135
|
+
const outside = join(f.workspace, 'outside.json');
|
|
136
|
+
await writeFile(outside, JSON.stringify(f.registration));
|
|
137
|
+
await symlink(outside, target, 'file');
|
|
138
|
+
await assert.rejects(listDemoWatchRegistrations(f.home), /symlink/);
|
|
139
|
+
await assert.rejects(registerDemoWatch(f.home, f.registration), /symlink/);
|
|
140
|
+
assert.deepEqual(JSON.parse(await readFile(outside, 'utf8')), f.registration);
|
|
141
|
+
}
|
|
142
|
+
finally {
|
|
143
|
+
await rm(f.root, { recursive: true, force: true });
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
//# sourceMappingURL=demoWatchRegistry.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"demoWatchRegistry.test.js","sourceRoot":"","sources":["../src/demoWatchRegistry.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC9F,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,wBAAwB,EAAE,0BAA0B,EAC3D,iBAAiB,EAAE,mBAAmB,EAA8B,MAAM,wBAAwB,CAAC;AAErG,MAAM,KAAK,GAAG;IACZ,KAAK,EAAE,2BAA2B,EAAE,cAAc,EAAE,aAAa;IACjE,YAAY,EAAE,sCAAsC;IACpD,oBAAoB,EAAE,+BAA+B,EAAE,QAAQ,EAAE,OAAgB;CAClF,CAAC;AAEF,KAAK,UAAU,OAAO,CAAC,MAAM,GAAG,MAAM,EAAE;IACtC,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC,CAAC,CAAC;IAC/E,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAChC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IAC1C,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;IAAC,MAAM,KAAK,CAAC,SAAS,CAAC,CAAC;IAC1C,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,YAAY,EAAE,EAAE,MAAM,EAAE,sBAA+B;YACrF,GAAG,KAAK,EAAE,SAAS,EAAE,EAAE,CAAC;AAC5B,CAAC;AAED,IAAI,CAAC,mEAAmE,EAAE,KAAK,IAAI,EAAE;IACnF,MAAM,CAAC,GAAG,MAAM,OAAO,EAAE,CAAC;IAC1B,IAAI,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,iBAAiB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAC9E,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,iBAAiB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAC/E,MAAM,CAAC,SAAS,CAAC,MAAM,0BAA0B,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC;QAC7E,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,cAAc,EAC/D,GAAG,wBAAwB,CAAC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,CAAC;QAC/D,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC,CAAC;QAC7C,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,KAAK,CAAC,CAAC;QAClD,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,KAAK,CAAC,CAAC;IACxD,CAAC;YAAS,CAAC;QAAC,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAAC,CAAC;AACnE,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,8FAA8F,EAAE,KAAK,IAAI,EAAE;IAC9G,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,0BAA0B,CAAC,CAAC,CAAC,CAAC;IACvF,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACpC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAClC,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC;QACpB,MAAM,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAChF,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,CAAC;QAC/B,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,EAAE,MAAM,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;QACvD,MAAM,iBAAiB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC;QAChD,MAAM,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC,YAAY;YAChE,SAAS,EAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC,EAAE,CAAC,EAAE,gBAAgB,CAAC,CAAC;QAC9E,MAAM,CAAC,SAAS,CAAC,MAAM,0BAA0B,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC;IAC/E,CAAC;YAAS,CAAC;QAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAAC,CAAC;AACjE,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,yEAAyE,EAAE,KAAK,IAAI,EAAE;IACzF,MAAM,CAAC,GAAG,MAAM,OAAO,EAAE,CAAC;IAC1B,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,CAChE,iBAAiB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC9C,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACjE,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAAC,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC;QACxD,MAAM,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC,YAAY,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,EACrF,+BAA+B,CAAC,CAAC;QACnC,MAAM,CAAC,SAAS,CAAC,MAAM,0BAA0B,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC;IAC/E,CAAC;YAAS,CAAC;QAAC,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAAC,CAAC;AACnE,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,yDAAyD,EAAE,KAAK,IAAI,EAAE;IACzE,MAAM,CAAC,GAAG,MAAM,OAAO,EAAE,CAAC;IAC1B,IAAI,CAAC;QACH,KAAK,MAAM,QAAQ,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,EAAE,EAAE,SAAS,EAAE,YAAY,EAAE;YAC7E,EAAE,KAAK,EAAE,6BAA6B,EAAE,EAAE,EAAE,YAAY,EAAE,YAAY,EAAE;YACxE,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,oBAAoB,EAAE,eAAe,EAAE,CAAC,EAAE,CAAC;YACpE,MAAM,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,EAC3C,EAAE,GAAG,CAAC,CAAC,YAAY,EAAE,GAAG,QAAQ,EAA2B,CAAC,CAAC,CAAC;QAClE,CAAC;QACD,MAAM,CAAC,SAAS,CAAC,MAAM,0BAA0B,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;IACjE,CAAC;YAAS,CAAC;QAAC,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAAC,CAAC;AACnE,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,0EAA0E,EAAE,KAAK,IAAI,EAAE;IAC1F,MAAM,CAAC,GAAG,MAAM,OAAO,EAAE,CAAC;IAC1B,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;QACnC,MAAM,OAAO,CAAC,CAAC,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,cAAc,CAAC,EAAE,KAAK,CAAC,CAAC;QACzE,MAAM,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC,EAAE,mBAAmB,CAAC,CAAC;QACrF,MAAM,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC;QAChD,MAAM,iBAAiB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC;QAChD,MAAM,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC;QACxD,MAAM,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC;QAC3F,MAAM,MAAM,CAAC,OAAO,CAAC,0BAA0B,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC,CAAC;IACvE,CAAC;YAAS,CAAC;QAAC,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAAC,CAAC;AACnE,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,mEAAmE,EAAE,KAAK,IAAI,EAAE;IACnF,MAAM,CAAC,GAAG,MAAM,OAAO,EAAE,CAAC;IAC1B,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,EAAE,cAAc,CAAC,EAAE,eAAe,CAAC,CAAC;QACpE,MAAM,iBAAiB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC;QAChD,MAAM,iBAAiB,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC,YAAY;YACjD,YAAY,EAAE,sCAAsC,EAAE,CAAC,CAAC;QAC1D,MAAM,CAAC,KAAK,CAAC,MAAM,mBAAmB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC,EAAE,IAAI,CAAC,CAAC;QACtE,MAAM,CAAC,KAAK,CAAC,MAAM,mBAAmB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC,EAAE,KAAK,CAAC,CAAC;QACvE,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,0BAA0B,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACnE,MAAM,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,EAAE,eAAe,CAAC,CAAC;IAC3F,CAAC;YAAS,CAAC;QAAC,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAAC,CAAC;AACnE,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,+EAA+E,EAAE,KAAK,IAAI,EAAE;IAC/F,MAAM,CAAC,GAAG,MAAM,OAAO,EAAE,CAAC;IAC1B,IAAI,CAAC;QACH,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,IAAI,EAAE,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;YAC5C,MAAM,iBAAiB,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC,YAAY;gBACjD,YAAY,EAAE,2BAA2B,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;QAClF,CAAC;QACD,MAAM,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC,YAAY;YAChE,YAAY,EAAE,sCAAsC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;QACpE,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,0BAA0B,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACtE,CAAC;YAAS,CAAC;QAAC,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAAC,CAAC;AACnE,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;IAChF,MAAM,CAAC,GAAG,MAAM,OAAO,EAAE,CAAC;IAC1B,IAAI,CAAC;QACH,MAAM,iBAAiB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC;QAChD,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,cAAc,EAAE,GAAG,wBAAwB,CAAC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QACzG,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC;QACjB,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;QAClD,MAAM,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC;QACzD,MAAM,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QACvC,MAAM,MAAM,CAAC,OAAO,CAAC,0BAA0B,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC,CAAC;QACpE,MAAM,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC,EAAE,SAAS,CAAC,CAAC;QAC3E,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC;IAChF,CAAC;YAAS,CAAC;QAAC,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAAC,CAAC;AACnE,CAAC,CAAC,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -88,6 +88,7 @@ export declare function materializeWorkspacePolicy(input: {
|
|
|
88
88
|
policy: OrganizationPolicy;
|
|
89
89
|
applied: boolean;
|
|
90
90
|
}>;
|
|
91
|
+
export declare function withRelayStartupMutation<T>(operation: () => Promise<T>, home?: string): Promise<T>;
|
|
91
92
|
export declare function withWorkspacePolicyRefreshLock<T>(workspaceId: string, operation: () => Promise<T>): Promise<T>;
|
|
92
93
|
export declare function withWorkspaceSkillActivationLock<T>(workspaceId: string, provider: ProviderId, operation: () => Promise<T>): Promise<T>;
|
|
93
94
|
export declare function applyServerEvidencePolicy(base: OrganizationPolicy, value: unknown, serverPublicKeyEd25519: string, organizationId: string, workspaceId: string, now?: Date): OrganizationPolicy;
|
|
@@ -141,7 +142,10 @@ export declare function deferUnavailableRelayRetention<T>(operation: () => Promi
|
|
|
141
142
|
reason: 'retention_not_ready';
|
|
142
143
|
}>;
|
|
143
144
|
export declare function requireCompletedBootstrapEvidence(result: BootstrapEvidenceSynchronization, discovered: number): void;
|
|
144
|
-
export declare function stableRepositoryLauncherContents(version?: string
|
|
145
|
+
export declare function stableRepositoryLauncherContents(version?: string, runtime?: {
|
|
146
|
+
platform: NodeJS.Platform;
|
|
147
|
+
nodeDirectory: string;
|
|
148
|
+
}): {
|
|
145
149
|
shell: string;
|
|
146
150
|
windows: string;
|
|
147
151
|
};
|