ds-harness-remote 0.3.8
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/LICENSE +21 -0
- package/README.md +103 -0
- package/cordis.patch.yml +7 -0
- package/dist/adapters/agent-adapter.d.ts +35 -0
- package/dist/adapters/agent-adapter.d.ts.map +1 -0
- package/dist/adapters/agent-adapter.js +80 -0
- package/dist/adapters/agent-adapter.js.map +1 -0
- package/dist/adapters/permission-adapter.d.ts +13 -0
- package/dist/adapters/permission-adapter.d.ts.map +1 -0
- package/dist/adapters/permission-adapter.js +67 -0
- package/dist/adapters/permission-adapter.js.map +1 -0
- package/dist/adapters/session-adapter.d.ts +38 -0
- package/dist/adapters/session-adapter.d.ts.map +1 -0
- package/dist/adapters/session-adapter.js +230 -0
- package/dist/adapters/session-adapter.js.map +1 -0
- package/dist/adapters/workspace-adapter.d.ts +13 -0
- package/dist/adapters/workspace-adapter.d.ts.map +1 -0
- package/dist/adapters/workspace-adapter.js +21 -0
- package/dist/adapters/workspace-adapter.js.map +1 -0
- package/dist/api-proxy-switch.d.ts +33 -0
- package/dist/api-proxy-switch.d.ts.map +1 -0
- package/dist/api-proxy-switch.js +107 -0
- package/dist/api-proxy-switch.js.map +1 -0
- package/dist/bin/doctor.d.ts +3 -0
- package/dist/bin/doctor.d.ts.map +1 -0
- package/dist/bin/doctor.js +13 -0
- package/dist/bin/doctor.js.map +1 -0
- package/dist/client-runtime.d.ts +98 -0
- package/dist/client-runtime.d.ts.map +1 -0
- package/dist/client-runtime.js +421 -0
- package/dist/client-runtime.js.map +1 -0
- package/dist/client-secure-transport.d.ts +22 -0
- package/dist/client-secure-transport.d.ts.map +1 -0
- package/dist/client-secure-transport.js +129 -0
- package/dist/client-secure-transport.js.map +1 -0
- package/dist/client.d.ts +12 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.github.js +2938 -0
- package/dist/client.js +2938 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +33 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +80 -0
- package/dist/config.js.map +1 -0
- package/dist/connection-controller.d.ts +39 -0
- package/dist/connection-controller.d.ts.map +1 -0
- package/dist/connection-controller.js +170 -0
- package/dist/connection-controller.js.map +1 -0
- package/dist/control-runtime.d.ts +36 -0
- package/dist/control-runtime.d.ts.map +1 -0
- package/dist/control-runtime.js +265 -0
- package/dist/control-runtime.js.map +1 -0
- package/dist/event-sequencer.d.ts +23 -0
- package/dist/event-sequencer.d.ts.map +1 -0
- package/dist/event-sequencer.js +54 -0
- package/dist/event-sequencer.js.map +1 -0
- package/dist/harness-api-bridge.d.ts +55 -0
- package/dist/harness-api-bridge.d.ts.map +1 -0
- package/dist/harness-api-bridge.js +387 -0
- package/dist/harness-api-bridge.js.map +1 -0
- package/dist/identity-store.d.ts +45 -0
- package/dist/identity-store.d.ts.map +1 -0
- package/dist/identity-store.js +183 -0
- package/dist/identity-store.js.map +1 -0
- package/dist/ids.d.ts +2 -0
- package/dist/ids.d.ts.map +1 -0
- package/dist/ids.js +17 -0
- package/dist/ids.js.map +1 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16091 -0
- package/dist/index.js.map +7 -0
- package/dist/logging.d.ts +18 -0
- package/dist/logging.d.ts.map +1 -0
- package/dist/logging.js +30 -0
- package/dist/logging.js.map +1 -0
- package/dist/pairing-controller.d.ts +52 -0
- package/dist/pairing-controller.d.ts.map +1 -0
- package/dist/pairing-controller.js +73 -0
- package/dist/pairing-controller.js.map +1 -0
- package/dist/pending-approvals.d.ts +14 -0
- package/dist/pending-approvals.d.ts.map +1 -0
- package/dist/pending-approvals.js +52 -0
- package/dist/pending-approvals.js.map +1 -0
- package/dist/remote-api-proxy.d.ts +12 -0
- package/dist/remote-api-proxy.d.ts.map +1 -0
- package/dist/remote-api-proxy.js +191 -0
- package/dist/remote-api-proxy.js.map +1 -0
- package/dist/remote-directory-browser.d.ts +16 -0
- package/dist/remote-directory-browser.d.ts.map +1 -0
- package/dist/remote-directory-browser.js +48 -0
- package/dist/remote-directory-browser.js.map +1 -0
- package/dist/rpc-router.d.ts +21 -0
- package/dist/rpc-router.d.ts.map +1 -0
- package/dist/rpc-router.js +93 -0
- package/dist/rpc-router.js.map +1 -0
- package/dist/server-api.d.ts +80 -0
- package/dist/server-api.d.ts.map +1 -0
- package/dist/server-api.js +405 -0
- package/dist/server-api.js.map +1 -0
- package/dist/server-connection.d.ts +70 -0
- package/dist/server-connection.d.ts.map +1 -0
- package/dist/server-connection.js +759 -0
- package/dist/server-connection.js.map +1 -0
- package/dist/server-credentials.d.ts +46 -0
- package/dist/server-credentials.d.ts.map +1 -0
- package/dist/server-credentials.js +71 -0
- package/dist/server-credentials.js.map +1 -0
- package/dist/service.d.ts +56 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +162 -0
- package/dist/service.js.map +1 -0
- package/dist/typert-gateway-switch.d.ts +19 -0
- package/dist/typert-gateway-switch.d.ts.map +1 -0
- package/dist/typert-gateway-switch.js +41 -0
- package/dist/typert-gateway-switch.js.map +1 -0
- package/dist/types.d.ts +20 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/version.d.ts +12 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +12 -0
- package/dist/version.js.map +1 -0
- package/dist/werift-rtc.d.ts +85 -0
- package/dist/werift-rtc.d.ts.map +1 -0
- package/dist/werift-rtc.js +164 -0
- package/dist/werift-rtc.js.map +1 -0
- package/package.json +98 -0
- package/public.d.ts +19 -0
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
import { RemoteClientCore } from '@dsh-remote/client-core';
|
|
2
|
+
import { AdaptiveTransport } from '@dsh-remote/webrtc';
|
|
3
|
+
import { ApiProxySwitch } from './api-proxy-switch.js';
|
|
4
|
+
import { ClientSecureTransport } from './client-secure-transport.js';
|
|
5
|
+
import { uuidV7 } from './ids.js';
|
|
6
|
+
import { RemoteHarnessApiProxy } from './remote-api-proxy.js';
|
|
7
|
+
import { ServerApiError } from './server-api.js';
|
|
8
|
+
import { TypertGatewaySwitch } from './typert-gateway-switch.js';
|
|
9
|
+
export class ClientModeRuntime {
|
|
10
|
+
config;
|
|
11
|
+
identities;
|
|
12
|
+
server;
|
|
13
|
+
logger;
|
|
14
|
+
host;
|
|
15
|
+
identity;
|
|
16
|
+
connected;
|
|
17
|
+
proxySwitch;
|
|
18
|
+
gatewaySwitch;
|
|
19
|
+
closed = false;
|
|
20
|
+
constructor(config, identities, server, apiProxy, typertGateway, logger, host) {
|
|
21
|
+
this.config = config;
|
|
22
|
+
this.identities = identities;
|
|
23
|
+
this.server = server;
|
|
24
|
+
this.logger = logger;
|
|
25
|
+
this.host = host;
|
|
26
|
+
this.proxySwitch = new ApiProxySwitch(apiProxy);
|
|
27
|
+
this.gatewaySwitch = new TypertGatewaySwitch(typertGateway);
|
|
28
|
+
}
|
|
29
|
+
async start() {
|
|
30
|
+
if (this.closed)
|
|
31
|
+
throw new Error('client remote-mode runtime is closed');
|
|
32
|
+
this.identity = await this.identities.loadOrCreate(this.config.deviceName);
|
|
33
|
+
this.server.bindIdentity(this.identity);
|
|
34
|
+
this.proxySwitch.install();
|
|
35
|
+
this.gatewaySwitch.install();
|
|
36
|
+
this.logger.info('client remote-mode identity ready', {
|
|
37
|
+
deviceId: shortId(this.identity.deviceId),
|
|
38
|
+
fingerprint: this.identity.fingerprint,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
registerControl(connection) {
|
|
42
|
+
return connection.rpc.handle('/remote', (endpoint, payload, signal) => this.handleControl(endpoint, payload, signal), {
|
|
43
|
+
authority: 'loopback',
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
status() {
|
|
47
|
+
return {
|
|
48
|
+
available: this.config.serverUrl !== undefined,
|
|
49
|
+
identityReady: this.identity !== undefined,
|
|
50
|
+
deviceId: this.identity?.deviceId,
|
|
51
|
+
serverUrl: this.config.serverUrl,
|
|
52
|
+
...this.proxySwitch.status(),
|
|
53
|
+
connected: this.connected !== undefined,
|
|
54
|
+
transport: this.connected?.client.getStats().mode ?? 'Disconnected',
|
|
55
|
+
hostAuthorizationAvailable: this.host !== undefined,
|
|
56
|
+
...(this.host === undefined ? {} : { host: this.host.hostStatus() }),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
async devices() {
|
|
60
|
+
this.requireIdentity();
|
|
61
|
+
const serverDevices = await this.server.listDevices();
|
|
62
|
+
const remoteDevices = serverDevices.filter(device => device.deviceId !== this.host?.hostStatus().deviceId);
|
|
63
|
+
return Promise.all(remoteDevices.map(async (device) => {
|
|
64
|
+
await this.authorizeHostPeer(device);
|
|
65
|
+
const presence = await this.server.presenceFor(device.deviceId).catch(() => ({ online: false }));
|
|
66
|
+
return { ...device, ...presence };
|
|
67
|
+
}));
|
|
68
|
+
}
|
|
69
|
+
async authorizeClientWithAccount(email, password) {
|
|
70
|
+
let authorization;
|
|
71
|
+
try {
|
|
72
|
+
authorization = await this.server.authorizeWithAccount(this.requireIdentity(), email, password);
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
if (!(error instanceof ServerApiError) || error.code !== 'DEVICE_REVOKED')
|
|
76
|
+
throw error;
|
|
77
|
+
this.identity = await this.identities.reset(this.config.deviceName);
|
|
78
|
+
this.server.bindIdentity(this.identity);
|
|
79
|
+
authorization = await this.server.authorizeWithAccount(this.identity, email, password);
|
|
80
|
+
}
|
|
81
|
+
this.logger.info('Client account authorized');
|
|
82
|
+
return authorization;
|
|
83
|
+
}
|
|
84
|
+
async startClientOAuthQrLogin() {
|
|
85
|
+
return this.server.startOAuthQrLogin();
|
|
86
|
+
}
|
|
87
|
+
async pollClientOAuthQrLogin(qrId) {
|
|
88
|
+
try {
|
|
89
|
+
const result = await this.server.pollOAuthQrLogin(this.requireIdentity(), qrId);
|
|
90
|
+
if (result.status === 'complete')
|
|
91
|
+
this.logger.info('Client account authorized with QR login');
|
|
92
|
+
return result;
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
if (!(error instanceof ServerApiError) || error.code !== 'DEVICE_REVOKED')
|
|
96
|
+
throw error;
|
|
97
|
+
this.identity = await this.identities.reset(this.config.deviceName);
|
|
98
|
+
this.server.bindIdentity(this.identity);
|
|
99
|
+
this.logger.info('Rotated revoked Client identity before QR retry');
|
|
100
|
+
return { status: 'expired' };
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
async clearClientAuthorization() {
|
|
104
|
+
const previous = this.connected;
|
|
105
|
+
this.connected = undefined;
|
|
106
|
+
this.proxySwitch.selectLocal();
|
|
107
|
+
this.gatewaySwitch.selectLocal();
|
|
108
|
+
await previous?.client.close().catch(() => undefined);
|
|
109
|
+
await this.server.revokeCurrentDevice();
|
|
110
|
+
this.identity = await this.identities.reset(this.config.deviceName);
|
|
111
|
+
this.server.bindIdentity(this.identity);
|
|
112
|
+
}
|
|
113
|
+
async setHostAuthorization(enabled) {
|
|
114
|
+
if (this.host === undefined)
|
|
115
|
+
throw new ClientModeError('METHOD_NOT_ALLOWED', 'This plugin is not running as a Host.');
|
|
116
|
+
if (!enabled) {
|
|
117
|
+
await this.host.clearHostAuthorization();
|
|
118
|
+
return this.status();
|
|
119
|
+
}
|
|
120
|
+
const credentials = await this.server.authenticate(this.requireIdentity());
|
|
121
|
+
await this.host.authorizeHostAsOwned(credentials.accessToken, credentials.account);
|
|
122
|
+
return this.status();
|
|
123
|
+
}
|
|
124
|
+
async setMode(mode, targetDeviceId, signal) {
|
|
125
|
+
if (mode === 'local') {
|
|
126
|
+
this.proxySwitch.selectLocal();
|
|
127
|
+
this.gatewaySwitch.selectLocal();
|
|
128
|
+
const previous = this.connected;
|
|
129
|
+
this.connected = undefined;
|
|
130
|
+
await previous?.client.close().catch(() => undefined);
|
|
131
|
+
this.logger.info('Harness target switched', { mode: 'local' });
|
|
132
|
+
return this.status();
|
|
133
|
+
}
|
|
134
|
+
if (targetDeviceId === undefined || targetDeviceId.length === 0) {
|
|
135
|
+
throw new ClientModeError('INVALID_MESSAGE', 'A targetDeviceId is required for remote mode.');
|
|
136
|
+
}
|
|
137
|
+
const next = await this.connect(targetDeviceId, signal);
|
|
138
|
+
const previous = this.connected;
|
|
139
|
+
this.connected = next;
|
|
140
|
+
const remoteApi = new RemoteHarnessApiProxy(next.client).api;
|
|
141
|
+
this.proxySwitch.selectRemote(remoteApi, { deviceId: next.target.deviceId, name: next.target.name });
|
|
142
|
+
this.gatewaySwitch.selectRemote(request => invokeRemoteCommand(next.client, request));
|
|
143
|
+
await previous?.client.close().catch(() => undefined);
|
|
144
|
+
this.logger.info('Harness target switched', { mode: 'remote', targetDeviceId: shortId(next.target.deviceId) });
|
|
145
|
+
return this.status();
|
|
146
|
+
}
|
|
147
|
+
async listRemoteDirectory(targetDeviceId, path, signal) {
|
|
148
|
+
const remote = await this.ensureConnected(targetDeviceId, signal);
|
|
149
|
+
const api = new RemoteHarnessApiProxy(remote.client).api;
|
|
150
|
+
const response = await api.host.listDirectory({
|
|
151
|
+
rpcId: `remote-directory-${Date.now()}`,
|
|
152
|
+
payload: path === undefined ? {} : { path },
|
|
153
|
+
}, signal ?? new AbortController().signal);
|
|
154
|
+
return unwrapNativeResult(response);
|
|
155
|
+
}
|
|
156
|
+
async listRemoteWorkspaces(targetDeviceId, signal) {
|
|
157
|
+
const remote = await this.ensureConnected(targetDeviceId, signal);
|
|
158
|
+
const api = new RemoteHarnessApiProxy(remote.client).api;
|
|
159
|
+
const response = await api.workspace.list({
|
|
160
|
+
rpcId: `remote-workspaces-${Date.now()}`,
|
|
161
|
+
payload: {},
|
|
162
|
+
});
|
|
163
|
+
const value = unwrapNativeResult(response);
|
|
164
|
+
return value.items;
|
|
165
|
+
}
|
|
166
|
+
async openRemoteWorkspace(targetDeviceId, path, signal) {
|
|
167
|
+
if (path.trim() === '')
|
|
168
|
+
throw new ClientModeError('INVALID_MESSAGE', 'A remote working directory is required.');
|
|
169
|
+
const remote = await this.ensureConnected(targetDeviceId, signal);
|
|
170
|
+
const api = new RemoteHarnessApiProxy(remote.client).api;
|
|
171
|
+
const response = await api.workspace.create({
|
|
172
|
+
rpcId: `remote-workspace-${Date.now()}`,
|
|
173
|
+
payload: { path },
|
|
174
|
+
});
|
|
175
|
+
const workspace = unwrapNativeResult(response);
|
|
176
|
+
this.proxySwitch.selectRemote(api, { deviceId: remote.target.deviceId, name: remote.target.name });
|
|
177
|
+
this.gatewaySwitch.selectRemote(request => invokeRemoteCommand(remote.client, request));
|
|
178
|
+
this.logger.info('Remote workspace opened', { targetDeviceId: shortId(remote.target.deviceId) });
|
|
179
|
+
return { ...this.status(), workspace };
|
|
180
|
+
}
|
|
181
|
+
async close() {
|
|
182
|
+
if (this.closed)
|
|
183
|
+
return;
|
|
184
|
+
this.closed = true;
|
|
185
|
+
this.proxySwitch.selectLocal();
|
|
186
|
+
this.gatewaySwitch.selectLocal();
|
|
187
|
+
await this.connected?.client.close().catch(() => undefined);
|
|
188
|
+
this.connected = undefined;
|
|
189
|
+
this.proxySwitch.restore();
|
|
190
|
+
this.gatewaySwitch.restore();
|
|
191
|
+
}
|
|
192
|
+
async connect(targetDeviceId, signal) {
|
|
193
|
+
signal?.throwIfAborted();
|
|
194
|
+
const identity = this.requireIdentity();
|
|
195
|
+
const serverDevice = (await this.server.listDevices()).find(device => device.deviceId === targetDeviceId);
|
|
196
|
+
if (serverDevice === undefined) {
|
|
197
|
+
throw new ClientModeError('MEMBERSHIP_REQUIRED', 'The selected Host is not authorized for this account.');
|
|
198
|
+
}
|
|
199
|
+
const target = await this.authorizeHostPeer(serverDevice);
|
|
200
|
+
const presence = await this.server.presenceFor(targetDeviceId);
|
|
201
|
+
if (!presence.online)
|
|
202
|
+
throw new ClientModeError('HOST_OFFLINE', 'The selected Host is offline.', true);
|
|
203
|
+
const credentials = await this.server.authenticate(identity);
|
|
204
|
+
const transport = new AdaptiveTransport(websocketUrl(this.server.baseUrl), {
|
|
205
|
+
role: 'client',
|
|
206
|
+
deviceId: identity.deviceId,
|
|
207
|
+
accessToken: credentials.accessToken,
|
|
208
|
+
targetDeviceId,
|
|
209
|
+
forceRelay: this.config.forceRelay,
|
|
210
|
+
preferredTransports: this.config.forceRelay ? ['relay'] : ['p2p', 'turn', 'relay'],
|
|
211
|
+
fetchIceServers: async (connectionId) => this.server.turnCredentials(connectionId),
|
|
212
|
+
});
|
|
213
|
+
const client = new RemoteClientCore(new ClientSecureTransport(transport, identity, target), 60_000);
|
|
214
|
+
try {
|
|
215
|
+
await client.connect();
|
|
216
|
+
signal?.throwIfAborted();
|
|
217
|
+
client.onClose(() => {
|
|
218
|
+
if (this.connected?.client !== client)
|
|
219
|
+
return;
|
|
220
|
+
this.connected = undefined;
|
|
221
|
+
this.proxySwitch.selectLocal();
|
|
222
|
+
this.gatewaySwitch.selectLocal();
|
|
223
|
+
void client.close().catch(() => undefined);
|
|
224
|
+
this.logger.warn('remote Harness transport closed; falling back to local mode', {
|
|
225
|
+
targetDeviceId: shortId(target.deviceId),
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
return { client, target };
|
|
229
|
+
}
|
|
230
|
+
catch (error) {
|
|
231
|
+
await client.close().catch(() => undefined);
|
|
232
|
+
throw error;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
async ensureConnected(targetDeviceId, signal) {
|
|
236
|
+
if (this.connected?.target.deviceId === targetDeviceId)
|
|
237
|
+
return this.connected;
|
|
238
|
+
const next = await this.connect(targetDeviceId, signal);
|
|
239
|
+
const previous = this.connected;
|
|
240
|
+
this.connected = next;
|
|
241
|
+
await previous?.client.close().catch(() => undefined);
|
|
242
|
+
return next;
|
|
243
|
+
}
|
|
244
|
+
async handleControl(endpoint, payload, signal) {
|
|
245
|
+
try {
|
|
246
|
+
if (endpoint === 'status')
|
|
247
|
+
return ok(this.status());
|
|
248
|
+
if (endpoint === 'devices')
|
|
249
|
+
return ok(await this.devices());
|
|
250
|
+
if (endpoint === 'client.account.login') {
|
|
251
|
+
const value = record(payload);
|
|
252
|
+
if (typeof value.email !== 'string' || typeof value.password !== 'string') {
|
|
253
|
+
throw new ClientModeError('INVALID_MESSAGE', 'Email and password are required.');
|
|
254
|
+
}
|
|
255
|
+
return ok(await this.authorizeClientWithAccount(value.email, value.password));
|
|
256
|
+
}
|
|
257
|
+
if (endpoint === 'client.account.qr.start')
|
|
258
|
+
return ok(await this.startClientOAuthQrLogin());
|
|
259
|
+
if (endpoint === 'client.account.qr.poll') {
|
|
260
|
+
const value = record(payload);
|
|
261
|
+
if (typeof value.qrId !== 'string' || value.qrId.length < 20) {
|
|
262
|
+
throw new ClientModeError('INVALID_MESSAGE', 'A QR login session is required.');
|
|
263
|
+
}
|
|
264
|
+
return ok(await this.pollClientOAuthQrLogin(value.qrId));
|
|
265
|
+
}
|
|
266
|
+
if (endpoint === 'directory.list') {
|
|
267
|
+
const value = record(payload);
|
|
268
|
+
if (typeof value.targetDeviceId !== 'string')
|
|
269
|
+
throw new ClientModeError('INVALID_MESSAGE', 'A Host is required.');
|
|
270
|
+
return ok(await this.listRemoteDirectory(value.targetDeviceId, typeof value.path === 'string' ? value.path : undefined, signal));
|
|
271
|
+
}
|
|
272
|
+
if (endpoint === 'workspaces.list') {
|
|
273
|
+
const value = record(payload);
|
|
274
|
+
if (typeof value.targetDeviceId !== 'string')
|
|
275
|
+
throw new ClientModeError('INVALID_MESSAGE', 'A Host is required.');
|
|
276
|
+
return ok(await this.listRemoteWorkspaces(value.targetDeviceId, signal));
|
|
277
|
+
}
|
|
278
|
+
if (endpoint === 'workspace.open') {
|
|
279
|
+
const value = record(payload);
|
|
280
|
+
if (typeof value.targetDeviceId !== 'string' || typeof value.path !== 'string') {
|
|
281
|
+
throw new ClientModeError('INVALID_MESSAGE', 'A Host and working directory are required.');
|
|
282
|
+
}
|
|
283
|
+
return ok(await this.openRemoteWorkspace(value.targetDeviceId, value.path, signal));
|
|
284
|
+
}
|
|
285
|
+
if (endpoint === 'host.account.login') {
|
|
286
|
+
if (this.host === undefined)
|
|
287
|
+
throw new ClientModeError('METHOD_NOT_ALLOWED', 'This plugin is not running as a Host.');
|
|
288
|
+
const value = record(payload);
|
|
289
|
+
if (typeof value.email !== 'string' || typeof value.password !== 'string') {
|
|
290
|
+
throw new ClientModeError('INVALID_MESSAGE', 'Email and password are required.');
|
|
291
|
+
}
|
|
292
|
+
return ok(await this.host.authorizeHostWithAccount(value.email, value.password));
|
|
293
|
+
}
|
|
294
|
+
if (endpoint === 'host.authorization.set') {
|
|
295
|
+
const value = record(payload);
|
|
296
|
+
if (typeof value.enabled !== 'boolean') {
|
|
297
|
+
throw new ClientModeError('INVALID_MESSAGE', 'Host authorization state is required.');
|
|
298
|
+
}
|
|
299
|
+
return ok(await this.setHostAuthorization(value.enabled));
|
|
300
|
+
}
|
|
301
|
+
if (endpoint === 'host.registration-code.submit') {
|
|
302
|
+
if (this.host === undefined)
|
|
303
|
+
throw new ClientModeError('METHOD_NOT_ALLOWED', 'This plugin is not running as a Host.');
|
|
304
|
+
const value = record(payload);
|
|
305
|
+
if (typeof value.code !== 'string' || value.code.trim() === '') {
|
|
306
|
+
throw new ClientModeError('INVALID_MESSAGE', 'A Host registration code is required.');
|
|
307
|
+
}
|
|
308
|
+
return ok(await this.host.authorizeHostWithCode(value.code));
|
|
309
|
+
}
|
|
310
|
+
if (endpoint === 'mode.set') {
|
|
311
|
+
const value = record(payload);
|
|
312
|
+
if (value.mode !== 'local' && value.mode !== 'remote')
|
|
313
|
+
throw new ClientModeError('INVALID_MESSAGE', 'Mode must be local or remote.');
|
|
314
|
+
return ok(await this.setMode(value.mode, typeof value.targetDeviceId === 'string' ? value.targetDeviceId : undefined, signal));
|
|
315
|
+
}
|
|
316
|
+
throw new ClientModeError('METHOD_NOT_FOUND', 'The remote-mode control method does not exist.');
|
|
317
|
+
}
|
|
318
|
+
catch (error) {
|
|
319
|
+
return fail(error);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
requireIdentity() {
|
|
323
|
+
if (this.identity === undefined)
|
|
324
|
+
throw new ClientModeError('IDENTITY_INVALID', 'The client identity is not ready.');
|
|
325
|
+
return this.identity;
|
|
326
|
+
}
|
|
327
|
+
async authorizeHostPeer(serverDevice) {
|
|
328
|
+
const descriptor = await this.server.deviceFor(serverDevice.deviceId);
|
|
329
|
+
assertAuthorizedHost(serverDevice, descriptor);
|
|
330
|
+
const existing = this.identities.trustedPeer(descriptor.deviceId);
|
|
331
|
+
if (existing !== undefined && existing.publicKey !== descriptor.identityKey) {
|
|
332
|
+
throw new ClientModeError('PEER_IDENTITY_MISMATCH', 'The authorized Host identity key changed unexpectedly.');
|
|
333
|
+
}
|
|
334
|
+
if (existing !== undefined
|
|
335
|
+
&& existing.membershipId === descriptor.membershipId
|
|
336
|
+
&& existing.name === descriptor.name
|
|
337
|
+
&& existing.platform === descriptor.platform) {
|
|
338
|
+
return existing;
|
|
339
|
+
}
|
|
340
|
+
return this.identities.trustPeer({
|
|
341
|
+
deviceId: descriptor.deviceId,
|
|
342
|
+
name: descriptor.name,
|
|
343
|
+
platform: descriptor.platform,
|
|
344
|
+
publicKey: descriptor.identityKey,
|
|
345
|
+
membershipId: descriptor.membershipId,
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
export class ClientModeError extends Error {
|
|
350
|
+
code;
|
|
351
|
+
retryable;
|
|
352
|
+
constructor(code, message, retryable = false) {
|
|
353
|
+
super(message);
|
|
354
|
+
this.code = code;
|
|
355
|
+
this.retryable = retryable;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
function assertAuthorizedHost(listed, descriptor) {
|
|
359
|
+
if (descriptor.role !== 'host' || descriptor.deviceId !== listed.deviceId
|
|
360
|
+
|| descriptor.membershipId !== listed.membershipId) {
|
|
361
|
+
throw new ClientModeError('PEER_IDENTITY_MISMATCH', 'Server Host details do not match the authorized device list.');
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
function websocketUrl(baseUrl) {
|
|
365
|
+
const url = new URL(baseUrl);
|
|
366
|
+
url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
367
|
+
url.pathname = `${url.pathname.replace(/\/$/, '')}/ws/v1/connect`;
|
|
368
|
+
return url.toString();
|
|
369
|
+
}
|
|
370
|
+
function record(value) {
|
|
371
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
372
|
+
throw new ClientModeError('INVALID_MESSAGE', 'The control request payload is invalid.');
|
|
373
|
+
}
|
|
374
|
+
return value;
|
|
375
|
+
}
|
|
376
|
+
function ok(value) { return { ok: true, value }; }
|
|
377
|
+
async function invokeRemoteCommand(client, request) {
|
|
378
|
+
const rpcId = uuidV7();
|
|
379
|
+
const response = await client.rpc('harness.api.call', {
|
|
380
|
+
method: `${request.namespace}.${request.method}`,
|
|
381
|
+
rpcId,
|
|
382
|
+
payload: request.args,
|
|
383
|
+
}, request.signal);
|
|
384
|
+
if (response.rpcId !== rpcId) {
|
|
385
|
+
throw new ClientModeError('INVALID_MESSAGE', 'The remote Host returned an invalid command response.');
|
|
386
|
+
}
|
|
387
|
+
return unwrapNativeResult(response);
|
|
388
|
+
}
|
|
389
|
+
function unwrapNativeResult(response) {
|
|
390
|
+
const result = response.result;
|
|
391
|
+
if (typeof result !== 'object' || result === null || !('ok' in result)) {
|
|
392
|
+
throw new ClientModeError('INVALID_MESSAGE', 'The remote Host returned an invalid response.');
|
|
393
|
+
}
|
|
394
|
+
if (result.ok !== true || !('value' in result)) {
|
|
395
|
+
const message = 'error' in result && typeof result.error === 'object' && result.error !== null
|
|
396
|
+
&& 'message' in result.error && typeof result.error.message === 'string'
|
|
397
|
+
? result.error.message
|
|
398
|
+
: 'The remote Host rejected the request.';
|
|
399
|
+
throw new ClientModeError('REMOTE_API_ERROR', message);
|
|
400
|
+
}
|
|
401
|
+
return result.value;
|
|
402
|
+
}
|
|
403
|
+
function fail(error) {
|
|
404
|
+
const source = error instanceof Error ? error : undefined;
|
|
405
|
+
const remoteCode = source !== undefined && 'code' in source && typeof source.code === 'string'
|
|
406
|
+
? source.code
|
|
407
|
+
: source instanceof ClientModeError ? source.code : undefined;
|
|
408
|
+
const retryable = source !== undefined && 'retryable' in source && typeof source.retryable === 'boolean'
|
|
409
|
+
? source.retryable
|
|
410
|
+
: source instanceof ClientModeError ? source.retryable : false;
|
|
411
|
+
return {
|
|
412
|
+
ok: false,
|
|
413
|
+
error: {
|
|
414
|
+
code: 'internal',
|
|
415
|
+
message: source?.message ?? 'The remote-mode operation failed.',
|
|
416
|
+
details: remoteCode === undefined ? {} : { remoteCode, retryable },
|
|
417
|
+
},
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
function shortId(value) { return value.length <= 12 ? value : `${value.slice(0, 8)}…${value.slice(-4)}`; }
|
|
421
|
+
//# sourceMappingURL=client-runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-runtime.js","sourceRoot":"","sources":["../src/client-runtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { RemoteTransport, SecureHandshakeTransport } from '@dsh-remote/webrtc';
|
|
2
|
+
import type { HostIdentity, TrustedPeer } from './identity-store.js';
|
|
3
|
+
/** Client-side Noise IK wrapper used by the local Harness remote-mode runtime. */
|
|
4
|
+
export declare class ClientSecureTransport implements RemoteTransport {
|
|
5
|
+
private readonly inner;
|
|
6
|
+
private readonly identity;
|
|
7
|
+
private readonly host;
|
|
8
|
+
private noise?;
|
|
9
|
+
private unsubscribeInner?;
|
|
10
|
+
private readonly incoming;
|
|
11
|
+
private readonly outgoing;
|
|
12
|
+
private closed;
|
|
13
|
+
constructor(inner: SecureHandshakeTransport, identity: HostIdentity, host: TrustedPeer);
|
|
14
|
+
connect(): Promise<void>;
|
|
15
|
+
send(data: Uint8Array): Promise<void>;
|
|
16
|
+
onMessage(handler: (data: Uint8Array) => void): () => void;
|
|
17
|
+
onClose(handler: () => void): () => void;
|
|
18
|
+
close(): Promise<void>;
|
|
19
|
+
getStats(): import("@dsh-remote/protocol").TransportStats;
|
|
20
|
+
private requireNoise;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=client-secure-transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-secure-transport.d.ts","sourceRoot":"","sources":["../src/client-secure-transport.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAA;AACnF,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAEpE,kFAAkF;AAClF,qBAAa,qBAAsB,YAAW,eAAe;IAQzD,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,IAAI;IATvB,OAAO,CAAC,KAAK,CAAC,CAAgB;IAC9B,OAAO,CAAC,gBAAgB,CAAC,CAAY;IACrC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA2B;IACpD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA2B;IACpD,OAAO,CAAC,MAAM,CAAQ;gBAGH,KAAK,EAAE,wBAAwB,EAC/B,QAAQ,EAAE,YAAY,EACtB,IAAI,EAAE,WAAW;IAG9B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IA4BxB,IAAI,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAM3C,SAAS,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,GAAG,MAAM,IAAI;IAkB1D,OAAO,CAAC,OAAO,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;IAIlC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAY5B,QAAQ;IAER,OAAO,CAAC,YAAY;CAMrB"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { NoiseIkSession, createNoisePrologue } from '@dsh-remote/crypto';
|
|
2
|
+
import { SecureMessageCodec } from '@dsh-remote/protocol';
|
|
3
|
+
/** Client-side Noise IK wrapper used by the local Harness remote-mode runtime. */
|
|
4
|
+
export class ClientSecureTransport {
|
|
5
|
+
inner;
|
|
6
|
+
identity;
|
|
7
|
+
host;
|
|
8
|
+
noise;
|
|
9
|
+
unsubscribeInner;
|
|
10
|
+
incoming = new SecureMessageCodec();
|
|
11
|
+
outgoing = new SecureMessageCodec();
|
|
12
|
+
closed = false;
|
|
13
|
+
constructor(inner, identity, host) {
|
|
14
|
+
this.inner = inner;
|
|
15
|
+
this.identity = identity;
|
|
16
|
+
this.host = host;
|
|
17
|
+
}
|
|
18
|
+
async connect() {
|
|
19
|
+
this.closed = false;
|
|
20
|
+
this.incoming.reset();
|
|
21
|
+
this.outgoing.reset();
|
|
22
|
+
await this.inner.connect();
|
|
23
|
+
const info = this.inner.connectionInfo();
|
|
24
|
+
if (info.localDeviceId !== this.identity.deviceId || info.remoteDeviceId !== this.host.deviceId) {
|
|
25
|
+
await this.inner.close();
|
|
26
|
+
throw new Error('The relay connection is bound to an unexpected device.');
|
|
27
|
+
}
|
|
28
|
+
const noise = new NoiseIkSession({
|
|
29
|
+
role: 'initiator',
|
|
30
|
+
localPrivateKey: this.identity.privateKey,
|
|
31
|
+
localPublicKey: this.identity.publicKey,
|
|
32
|
+
remotePublicKey: this.host.publicKey,
|
|
33
|
+
prologue: createNoisePrologue(info.connectionId, this.host.deviceId, this.identity.deviceId),
|
|
34
|
+
});
|
|
35
|
+
this.noise = noise;
|
|
36
|
+
try {
|
|
37
|
+
await waitForResponder(this.inner, noise);
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
noise.destroy();
|
|
41
|
+
this.noise = undefined;
|
|
42
|
+
await this.inner.close();
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
async send(data) {
|
|
47
|
+
for (const plaintext of this.outgoing.encode(data)) {
|
|
48
|
+
await this.inner.send(this.requireNoise().encrypt(plaintext));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
onMessage(handler) {
|
|
52
|
+
this.unsubscribeInner?.();
|
|
53
|
+
this.unsubscribeInner = this.inner.onMessage(data => {
|
|
54
|
+
const noise = this.noise;
|
|
55
|
+
if (noise === undefined || !noise.complete || this.closed)
|
|
56
|
+
return;
|
|
57
|
+
try {
|
|
58
|
+
const message = this.incoming.decode(noise.decrypt(data));
|
|
59
|
+
if (message !== undefined)
|
|
60
|
+
handler(message);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
void this.close();
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
return () => {
|
|
67
|
+
this.unsubscribeInner?.();
|
|
68
|
+
this.unsubscribeInner = undefined;
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
onClose(handler) {
|
|
72
|
+
return this.inner.onClose?.(handler) ?? (() => undefined);
|
|
73
|
+
}
|
|
74
|
+
async close() {
|
|
75
|
+
if (this.closed)
|
|
76
|
+
return;
|
|
77
|
+
this.closed = true;
|
|
78
|
+
this.unsubscribeInner?.();
|
|
79
|
+
this.unsubscribeInner = undefined;
|
|
80
|
+
this.incoming.reset();
|
|
81
|
+
this.outgoing.reset();
|
|
82
|
+
this.noise?.destroy();
|
|
83
|
+
this.noise = undefined;
|
|
84
|
+
await this.inner.close();
|
|
85
|
+
}
|
|
86
|
+
getStats() { return this.inner.getStats(); }
|
|
87
|
+
requireNoise() {
|
|
88
|
+
if (this.noise === undefined || !this.noise.complete || this.closed) {
|
|
89
|
+
throw new Error('The authenticated Noise channel is not connected.');
|
|
90
|
+
}
|
|
91
|
+
return this.noise;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
async function waitForResponder(inner, noise) {
|
|
95
|
+
await new Promise((resolve, reject) => {
|
|
96
|
+
let settled = false;
|
|
97
|
+
const timer = setTimeout(() => finish(new Error('Noise IK handshake timed out.')), 10_000);
|
|
98
|
+
const unsubscribe = inner.onHandshake((step, data) => {
|
|
99
|
+
if (settled)
|
|
100
|
+
return;
|
|
101
|
+
try {
|
|
102
|
+
if (step !== 2)
|
|
103
|
+
throw new Error('Noise IK responder sent an out-of-order handshake message.');
|
|
104
|
+
noise.readHandshake(data);
|
|
105
|
+
if (!noise.complete)
|
|
106
|
+
throw new Error('Noise IK handshake did not complete.');
|
|
107
|
+
finish();
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
finish(error instanceof Error ? error : new Error('Noise IK handshake failed.'));
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
const finish = (error) => {
|
|
114
|
+
if (settled)
|
|
115
|
+
return;
|
|
116
|
+
settled = true;
|
|
117
|
+
clearTimeout(timer);
|
|
118
|
+
unsubscribe();
|
|
119
|
+
if (error === undefined)
|
|
120
|
+
resolve();
|
|
121
|
+
else
|
|
122
|
+
reject(error);
|
|
123
|
+
};
|
|
124
|
+
void inner.sendHandshake(1, noise.writeHandshake()).catch(error => {
|
|
125
|
+
finish(error instanceof Error ? error : new Error('Noise IK handshake failed.'));
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=client-secure-transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-secure-transport.js","sourceRoot":"","sources":["../src/client-secure-transport.ts"],"names":[],"mappings":"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"}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,gBAAgB,EAAE;YAChB,IAAI,CAAC,KAAK,EAAE;gBAAE,EAAE,EAAE,MAAM,CAAC;gBAAC,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,KAAK,OAAO,CAAA;aAAE,GAAG,IAAI,CAAA;SAC1F,CAAA;KACF;CACF"}
|