crewly 1.8.7 → 1.8.9
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/backend/backend/src/constants.d.ts +12 -0
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +12 -0
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/browser/browser.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/browser/browser.controller.js +17 -0
- package/dist/backend/backend/src/controllers/browser/browser.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/cloud/cloud.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/cloud/cloud.controller.js +8 -1
- package/dist/backend/backend/src/controllers/cloud/cloud.controller.js.map +1 -1
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +15 -7
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/services/browser/browser-bridge.service.d.ts +7 -0
- package/dist/backend/backend/src/services/browser/browser-bridge.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/browser/browser-bridge.service.js +69 -12
- package/dist/backend/backend/src/services/browser/browser-bridge.service.js.map +1 -1
- package/dist/backend/backend/src/services/browser/browser-proxy.service.d.ts +122 -1
- package/dist/backend/backend/src/services/browser/browser-proxy.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/browser/browser-proxy.service.js +252 -17
- package/dist/backend/backend/src/services/browser/browser-proxy.service.js.map +1 -1
- package/dist/backend/backend/src/services/browser/browser-relay-adapter.service.d.ts +37 -3
- package/dist/backend/backend/src/services/browser/browser-relay-adapter.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/browser/browser-relay-adapter.service.js +140 -23
- package/dist/backend/backend/src/services/browser/browser-relay-adapter.service.js.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-client.service.d.ts +75 -0
- package/dist/backend/backend/src/services/cloud/cloud-client.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-client.service.js +164 -12
- package/dist/backend/backend/src/services/cloud/cloud-client.service.js.map +1 -1
- package/dist/cli/backend/src/constants.d.ts +12 -0
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +12 -0
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/cli/src/index.js +0 -0
- package/package.json +1 -1
- package/config/constants.d.ts.map +0 -1
- package/config/index.d.ts.map +0 -1
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.d.ts +0 -169
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.d.ts.map +0 -1
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.js +0 -1779
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/agent-runner.service.d.ts +0 -513
- package/dist/backend/backend/src/services/agent/crewly-agent/agent-runner.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/agent-runner.service.js +0 -1568
- package/dist/backend/backend/src/services/agent/crewly-agent/agent-runner.service.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/agent-worker.d.ts +0 -86
- package/dist/backend/backend/src/services/agent/crewly-agent/agent-worker.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/agent-worker.js +0 -147
- package/dist/backend/backend/src/services/agent/crewly-agent/agent-worker.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/api-client.d.ts +0 -68
- package/dist/backend/backend/src/services/agent/crewly-agent/api-client.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/api-client.js +0 -131
- package/dist/backend/backend/src/services/agent/crewly-agent/api-client.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/audit-log.service.d.ts +0 -130
- package/dist/backend/backend/src/services/agent/crewly-agent/audit-log.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/audit-log.service.js +0 -263
- package/dist/backend/backend/src/services/agent/crewly-agent/audit-log.service.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/audit-trail.service.d.ts +0 -74
- package/dist/backend/backend/src/services/agent/crewly-agent/audit-trail.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/audit-trail.service.js +0 -140
- package/dist/backend/backend/src/services/agent/crewly-agent/audit-trail.service.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/auditor-tools.d.ts +0 -29
- package/dist/backend/backend/src/services/agent/crewly-agent/auditor-tools.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/auditor-tools.js +0 -279
- package/dist/backend/backend/src/services/agent/crewly-agent/auditor-tools.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-runtime.service.d.ts +0 -340
- package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-runtime.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-runtime.service.js +0 -1176
- package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-runtime.service.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/deepseek-sse-transform.d.ts +0 -79
- package/dist/backend/backend/src/services/agent/crewly-agent/deepseek-sse-transform.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/deepseek-sse-transform.js +0 -145
- package/dist/backend/backend/src/services/agent/crewly-agent/deepseek-sse-transform.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/env-isolation.service.d.ts +0 -79
- package/dist/backend/backend/src/services/agent/crewly-agent/env-isolation.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/env-isolation.service.js +0 -218
- package/dist/backend/backend/src/services/agent/crewly-agent/env-isolation.service.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/index.d.ts +0 -16
- package/dist/backend/backend/src/services/agent/crewly-agent/index.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/index.js +0 -16
- package/dist/backend/backend/src/services/agent/crewly-agent/index.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/mcp-tool-bridge.d.ts +0 -135
- package/dist/backend/backend/src/services/agent/crewly-agent/mcp-tool-bridge.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/mcp-tool-bridge.js +0 -185
- package/dist/backend/backend/src/services/agent/crewly-agent/mcp-tool-bridge.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.d.ts +0 -141
- package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.js +0 -310
- package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/output-filter.service.d.ts +0 -91
- package/dist/backend/backend/src/services/agent/crewly-agent/output-filter.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/output-filter.service.js +0 -143
- package/dist/backend/backend/src/services/agent/crewly-agent/output-filter.service.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/prompt-guard.service.d.ts +0 -103
- package/dist/backend/backend/src/services/agent/crewly-agent/prompt-guard.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/prompt-guard.service.js +0 -256
- package/dist/backend/backend/src/services/agent/crewly-agent/prompt-guard.service.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/rate-limiter.d.ts +0 -143
- package/dist/backend/backend/src/services/agent/crewly-agent/rate-limiter.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/rate-limiter.js +0 -264
- package/dist/backend/backend/src/services/agent/crewly-agent/rate-limiter.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/smoke-test.d.ts +0 -13
- package/dist/backend/backend/src/services/agent/crewly-agent/smoke-test.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/smoke-test.js +0 -91
- package/dist/backend/backend/src/services/agent/crewly-agent/smoke-test.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/tool-registry.d.ts +0 -135
- package/dist/backend/backend/src/services/agent/crewly-agent/tool-registry.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/tool-registry.js +0 -1937
- package/dist/backend/backend/src/services/agent/crewly-agent/tool-registry.js.map +0 -1
- package/dist/backend/backend/src/services/autonomous/auto-assign.service.d.ts +0 -429
- package/dist/backend/backend/src/services/autonomous/auto-assign.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/autonomous/auto-assign.service.js +0 -852
- package/dist/backend/backend/src/services/autonomous/auto-assign.service.js.map +0 -1
- package/dist/backend/backend/src/services/project/task-tracking.service.d.ts +0 -171
- package/dist/backend/backend/src/services/project/task-tracking.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/project/task-tracking.service.js +0 -725
- package/dist/backend/backend/src/services/project/task-tracking.service.js.map +0 -1
- package/dist/backend/backend/src/services/v3/project-task-watcher.service.d.ts +0 -118
- package/dist/backend/backend/src/services/v3/project-task-watcher.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/v3/project-task-watcher.service.js +0 -326
- package/dist/backend/backend/src/services/v3/project-task-watcher.service.js.map +0 -1
- package/dist/backend/backend/src/services/wiki/wiki-chat-subscriber.service.d.ts +0 -74
- package/dist/backend/backend/src/services/wiki/wiki-chat-subscriber.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/wiki/wiki-chat-subscriber.service.js +0 -154
- package/dist/backend/backend/src/services/wiki/wiki-chat-subscriber.service.js.map +0 -1
- package/dist/backend/backend/src/types/auto-assign.types.d.ts +0 -271
- package/dist/backend/backend/src/types/auto-assign.types.d.ts.map +0 -1
- package/dist/backend/backend/src/types/auto-assign.types.js +0 -136
- package/dist/backend/backend/src/types/auto-assign.types.js.map +0 -1
- package/dist/backend/backend/src/utils/esm-require.utils.d.ts +0 -111
- package/dist/backend/backend/src/utils/esm-require.utils.d.ts.map +0 -1
- package/dist/backend/backend/src/utils/esm-require.utils.js +0 -124
- package/dist/backend/backend/src/utils/esm-require.utils.js.map +0 -1
- package/dist/cli/backend/src/services/ai/prompt-modules/prompt-module.interface.d.ts +0 -220
- package/dist/cli/backend/src/services/ai/prompt-modules/prompt-module.interface.d.ts.map +0 -1
- package/dist/cli/backend/src/services/ai/prompt-modules/prompt-module.interface.js +0 -37
- package/dist/cli/backend/src/services/ai/prompt-modules/prompt-module.interface.js.map +0 -1
- package/dist/cli/backend/src/services/knowledge/fts5-search-strategy.d.ts +0 -56
- package/dist/cli/backend/src/services/knowledge/fts5-search-strategy.d.ts.map +0 -1
- package/dist/cli/backend/src/services/knowledge/fts5-search-strategy.js +0 -91
- package/dist/cli/backend/src/services/knowledge/fts5-search-strategy.js.map +0 -1
- package/dist/cli/backend/src/services/knowledge/learnings-index.service.d.ts +0 -159
- package/dist/cli/backend/src/services/knowledge/learnings-index.service.d.ts.map +0 -1
- package/dist/cli/backend/src/services/knowledge/learnings-index.service.js +0 -304
- package/dist/cli/backend/src/services/knowledge/learnings-index.service.js.map +0 -1
- package/dist/cli/backend/src/services/knowledge/wiki-compiler.service.d.ts +0 -115
- package/dist/cli/backend/src/services/knowledge/wiki-compiler.service.d.ts.map +0 -1
- package/dist/cli/backend/src/services/knowledge/wiki-compiler.service.js +0 -215
- package/dist/cli/backend/src/services/knowledge/wiki-compiler.service.js.map +0 -1
- package/dist/cli/backend/src/services/memory/embedding-provider.d.ts +0 -78
- package/dist/cli/backend/src/services/memory/embedding-provider.d.ts.map +0 -1
- package/dist/cli/backend/src/services/memory/embedding-provider.js +0 -179
- package/dist/cli/backend/src/services/memory/embedding-provider.js.map +0 -1
- package/dist/cli/backend/src/services/memory/vector-store.service.d.ts +0 -331
- package/dist/cli/backend/src/services/memory/vector-store.service.d.ts.map +0 -1
- package/dist/cli/backend/src/services/memory/vector-store.service.js +0 -814
- package/dist/cli/backend/src/services/memory/vector-store.service.js.map +0 -1
- package/dist/cli/backend/src/services/project/task-tracking.service.d.ts +0 -171
- package/dist/cli/backend/src/services/project/task-tracking.service.d.ts.map +0 -1
- package/dist/cli/backend/src/services/project/task-tracking.service.js +0 -725
- package/dist/cli/backend/src/services/project/task-tracking.service.js.map +0 -1
- package/dist/cli/backend/src/types/auto-assign.types.d.ts +0 -271
- package/dist/cli/backend/src/types/auto-assign.types.d.ts.map +0 -1
- package/dist/cli/backend/src/types/auto-assign.types.js +0 -136
- package/dist/cli/backend/src/types/auto-assign.types.js.map +0 -1
|
@@ -54,6 +54,18 @@ export class BrowserRelayAdapter {
|
|
|
54
54
|
boundDeviceOnlineHandler = null;
|
|
55
55
|
boundDeviceOfflineHandler = null;
|
|
56
56
|
boundDevicesUpdatedHandler = null;
|
|
57
|
+
/**
|
|
58
|
+
* Bound handlers for the BrowserProxy event channel — the primary
|
|
59
|
+
* signal source after 2026-05-23. The Sync handlers above remain wired
|
|
60
|
+
* as a belt-and-suspenders fallback for legacy code paths that still
|
|
61
|
+
* push browser devices through Sync, but in current production those
|
|
62
|
+
* events never fire (CloudSyncService only tracks orchestrator-role
|
|
63
|
+
* devices). The proxy listens directly to the Cloud relay's browser_list
|
|
64
|
+
* / browser_event channel, which is the canonical source of truth for
|
|
65
|
+
* extension presence.
|
|
66
|
+
*/
|
|
67
|
+
boundProxyConnectedHandler = null;
|
|
68
|
+
boundProxyDisconnectedHandler = null;
|
|
57
69
|
constructor() {
|
|
58
70
|
this.logger = LoggerService.getInstance().createComponentLogger('BrowserRelayAdapter');
|
|
59
71
|
}
|
|
@@ -96,17 +108,29 @@ export class BrowserRelayAdapter {
|
|
|
96
108
|
return this.extensionDeviceId;
|
|
97
109
|
}
|
|
98
110
|
/**
|
|
99
|
-
* Whether the relay adapter
|
|
100
|
-
*
|
|
111
|
+
* Whether the relay adapter has a known extension target via the
|
|
112
|
+
* BrowserProxy event channel.
|
|
113
|
+
*
|
|
114
|
+
* Single liveness definition (2026-05-28 browser-relay fix): availability is
|
|
115
|
+
* derived from the BrowserProxy — the canonical source of truth for browser
|
|
116
|
+
* presence on the Cloud relay — NOT from the CloudSyncService state. The
|
|
117
|
+
* former CloudSync `getState() === 'syncing'` gate was dead in production
|
|
118
|
+
* (Sync only tracks orchestrator-role devices, never browser-role), so it
|
|
119
|
+
* reported a liveness that disagreed with `proxy.isAvailable()`. Collapsing
|
|
120
|
+
* to the proxy removes that disagreement (REGISTRY-TRUTH invariant).
|
|
101
121
|
*
|
|
102
|
-
* @returns True if
|
|
122
|
+
* @returns True if the proxy reports a drivable browser and we have a target
|
|
103
123
|
*/
|
|
104
124
|
isAvailable() {
|
|
105
125
|
if (!this.extensionDeviceId)
|
|
106
126
|
return false;
|
|
107
127
|
try {
|
|
108
|
-
|
|
109
|
-
|
|
128
|
+
// Lazy require to avoid an import-time circular dep — proxy and adapter
|
|
129
|
+
// both live under backend/src/services/browser/.
|
|
130
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
131
|
+
const mod = require('./browser-proxy.service.js');
|
|
132
|
+
const proxy = mod?.BrowserProxyService?.getInstance?.();
|
|
133
|
+
return proxy ? proxy.isAvailable() : false;
|
|
110
134
|
}
|
|
111
135
|
catch {
|
|
112
136
|
return false;
|
|
@@ -196,28 +220,69 @@ export class BrowserRelayAdapter {
|
|
|
196
220
|
if (this.discoveryActive)
|
|
197
221
|
return;
|
|
198
222
|
try {
|
|
223
|
+
// ---- Primary signal source: BrowserProxy events (2026-05-23) ----
|
|
224
|
+
// The proxy listens directly to the Cloud relay's browser channel
|
|
225
|
+
// (browser_list / browser_event). It's the only path that reliably
|
|
226
|
+
// sees the extension; the Sync-driven path below is kept for
|
|
227
|
+
// backward compat but typically observes nothing.
|
|
228
|
+
// Dynamic import to avoid circular-dep at module load (proxy and
|
|
229
|
+
// adapter both live under backend/src/services/browser/).
|
|
230
|
+
void (async () => {
|
|
231
|
+
try {
|
|
232
|
+
const { BrowserProxyService } = await import('./browser-proxy.service.js');
|
|
233
|
+
const proxy = BrowserProxyService.getInstance();
|
|
234
|
+
this.boundProxyConnectedHandler = (evt) => {
|
|
235
|
+
this.onProxyInstanceConnected(evt);
|
|
236
|
+
};
|
|
237
|
+
this.boundProxyDisconnectedHandler = (evt) => {
|
|
238
|
+
this.onProxyInstanceDisconnected(evt);
|
|
239
|
+
};
|
|
240
|
+
proxy.events.on('instance_connected', this.boundProxyConnectedHandler);
|
|
241
|
+
proxy.events.on('instance_disconnected', this.boundProxyDisconnectedHandler);
|
|
242
|
+
// Catch-up scan: if the proxy already has instances at the time
|
|
243
|
+
// we subscribe (e.g. boot ordering or adapter restart), seed our
|
|
244
|
+
// target now so we don't wait for the next browser_event.
|
|
245
|
+
const seed = proxy.getInstances();
|
|
246
|
+
if (seed.length > 0 && this.extensionDeviceId === null) {
|
|
247
|
+
const first = seed[0];
|
|
248
|
+
this.extensionDeviceId = first.instanceId;
|
|
249
|
+
this.logger.info('Browser extension seeded from existing proxy instances', {
|
|
250
|
+
instanceId: first.instanceId,
|
|
251
|
+
instanceName: first.instanceName,
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
catch (err) {
|
|
256
|
+
this.logger.warn('Failed to subscribe to BrowserProxy events', {
|
|
257
|
+
error: err instanceof Error ? err.message : String(err),
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
})();
|
|
261
|
+
// ---- Fallback signal source: CloudSyncService device events ----
|
|
262
|
+
// Kept for compat with any deployment that still routes browser
|
|
263
|
+
// device announcements through Sync; harmless when Sync omits them.
|
|
199
264
|
const sync = CloudSyncService.getInstance();
|
|
200
265
|
if (!sync.isStarted()) {
|
|
201
|
-
this.logger.debug('CloudSync not started —
|
|
202
|
-
|
|
266
|
+
this.logger.debug('CloudSync not started — proxy events only');
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
this.boundDeviceOnlineHandler = (device) => {
|
|
270
|
+
this.onDeviceOnline(device);
|
|
271
|
+
};
|
|
272
|
+
this.boundDeviceOfflineHandler = (device) => {
|
|
273
|
+
this.onDeviceOffline(device);
|
|
274
|
+
};
|
|
275
|
+
this.boundDevicesUpdatedHandler = (devices) => {
|
|
276
|
+
this.onDevicesUpdated(devices);
|
|
277
|
+
};
|
|
278
|
+
sync.on('device_online', this.boundDeviceOnlineHandler);
|
|
279
|
+
sync.on('device_offline', this.boundDeviceOfflineHandler);
|
|
280
|
+
sync.on('devices_updated', this.boundDevicesUpdatedHandler);
|
|
281
|
+
// Scan existing device list for already-online browser extensions
|
|
282
|
+
const existingDevices = sync.getDevices();
|
|
283
|
+
this.scanForBrowserDevice(existingDevices);
|
|
203
284
|
}
|
|
204
|
-
// Bind event handlers
|
|
205
|
-
this.boundDeviceOnlineHandler = (device) => {
|
|
206
|
-
this.onDeviceOnline(device);
|
|
207
|
-
};
|
|
208
|
-
this.boundDeviceOfflineHandler = (device) => {
|
|
209
|
-
this.onDeviceOffline(device);
|
|
210
|
-
};
|
|
211
|
-
this.boundDevicesUpdatedHandler = (devices) => {
|
|
212
|
-
this.onDevicesUpdated(devices);
|
|
213
|
-
};
|
|
214
|
-
sync.on('device_online', this.boundDeviceOnlineHandler);
|
|
215
|
-
sync.on('device_offline', this.boundDeviceOfflineHandler);
|
|
216
|
-
sync.on('devices_updated', this.boundDevicesUpdatedHandler);
|
|
217
285
|
this.discoveryActive = true;
|
|
218
|
-
// Scan existing device list for already-online browser extensions
|
|
219
|
-
const existingDevices = sync.getDevices();
|
|
220
|
-
this.scanForBrowserDevice(existingDevices);
|
|
221
286
|
this.logger.info('Browser extension auto-discovery started');
|
|
222
287
|
}
|
|
223
288
|
catch (err) {
|
|
@@ -226,6 +291,36 @@ export class BrowserRelayAdapter {
|
|
|
226
291
|
});
|
|
227
292
|
}
|
|
228
293
|
}
|
|
294
|
+
/**
|
|
295
|
+
* Handle `instance_connected` from BrowserProxy — adopt as the relay
|
|
296
|
+
* target if we don't already have one (or if the existing one is gone).
|
|
297
|
+
*
|
|
298
|
+
* @param evt - Connected instance info
|
|
299
|
+
*/
|
|
300
|
+
onProxyInstanceConnected(evt) {
|
|
301
|
+
if (this.extensionDeviceId === evt.instanceId)
|
|
302
|
+
return;
|
|
303
|
+
this.extensionDeviceId = evt.instanceId;
|
|
304
|
+
this.logger.info('Browser extension auto-discovered (proxy event)', {
|
|
305
|
+
instanceId: evt.instanceId,
|
|
306
|
+
instanceName: evt.instanceName,
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Handle `instance_disconnected` from BrowserProxy — clear the relay
|
|
311
|
+
* target only if it matches the disconnecting instance.
|
|
312
|
+
*
|
|
313
|
+
* @param evt - Disconnected instance info
|
|
314
|
+
*/
|
|
315
|
+
onProxyInstanceDisconnected(evt) {
|
|
316
|
+
if (this.extensionDeviceId !== evt.instanceId)
|
|
317
|
+
return;
|
|
318
|
+
this.logger.info('Browser extension disconnected (proxy event), clearing relay target', {
|
|
319
|
+
instanceId: evt.instanceId,
|
|
320
|
+
instanceName: evt.instanceName,
|
|
321
|
+
});
|
|
322
|
+
this.extensionDeviceId = null;
|
|
323
|
+
}
|
|
229
324
|
/**
|
|
230
325
|
* Stop listening for device events.
|
|
231
326
|
*/
|
|
@@ -247,6 +342,28 @@ export class BrowserRelayAdapter {
|
|
|
247
342
|
catch {
|
|
248
343
|
// CloudSync may already be destroyed
|
|
249
344
|
}
|
|
345
|
+
// Unsubscribe from BrowserProxy events (best-effort dynamic import to
|
|
346
|
+
// match the subscribe path; if the proxy module already collapsed
|
|
347
|
+
// during shutdown, the listeners die with it anyway).
|
|
348
|
+
void (async () => {
|
|
349
|
+
try {
|
|
350
|
+
const { BrowserProxyService } = await import('./browser-proxy.service.js');
|
|
351
|
+
const proxy = BrowserProxyService.getInstance();
|
|
352
|
+
if (this.boundProxyConnectedHandler) {
|
|
353
|
+
proxy.events.removeListener('instance_connected', this.boundProxyConnectedHandler);
|
|
354
|
+
}
|
|
355
|
+
if (this.boundProxyDisconnectedHandler) {
|
|
356
|
+
proxy.events.removeListener('instance_disconnected', this.boundProxyDisconnectedHandler);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
catch {
|
|
360
|
+
// proxy may already be destroyed
|
|
361
|
+
}
|
|
362
|
+
finally {
|
|
363
|
+
this.boundProxyConnectedHandler = null;
|
|
364
|
+
this.boundProxyDisconnectedHandler = null;
|
|
365
|
+
}
|
|
366
|
+
})();
|
|
250
367
|
this.boundDeviceOnlineHandler = null;
|
|
251
368
|
this.boundDeviceOfflineHandler = null;
|
|
252
369
|
this.boundDevicesUpdatedHandler = null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-relay-adapter.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/browser/browser-relay-adapter.service.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"browser-relay-adapter.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/browser/browser-relay-adapter.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -22,7 +22,24 @@ export interface PersistedCloudConfig {
|
|
|
22
22
|
connectedAt: string;
|
|
23
23
|
/** Refresh token for auto-renewing expired access tokens */
|
|
24
24
|
refreshToken?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Relay-signed access JWT (distinct from the access `token`). Persisted so
|
|
27
|
+
* the BrowserProxy can re-register on backend restart without waiting for a
|
|
28
|
+
* fresh validate round-trip. Never the Google/Supabase token — see the
|
|
29
|
+
* RELAY-TOKEN-TYPE invariant in the long-term browser-relay fix design.
|
|
30
|
+
*/
|
|
31
|
+
relayToken?: string;
|
|
25
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Decode the `exp` (expiry, seconds since epoch) claim from a JWT without
|
|
35
|
+
* verifying its signature. Returns null when the token is malformed or has
|
|
36
|
+
* no `exp`. Used to schedule proactive relay-token refresh before expiry so
|
|
37
|
+
* a continuously-open relay socket never carries an expired token.
|
|
38
|
+
*
|
|
39
|
+
* @param token - JWT string (may be null)
|
|
40
|
+
* @returns The `exp` claim in seconds, or null when unavailable
|
|
41
|
+
*/
|
|
42
|
+
export declare function decodeJwtExp(token: string | null): number | null;
|
|
26
43
|
/** Summary of a premium template returned by the cloud listing endpoint. */
|
|
27
44
|
export interface CloudTemplateSummary {
|
|
28
45
|
/** Unique template identifier */
|
|
@@ -116,6 +133,19 @@ export declare class CloudClientService {
|
|
|
116
133
|
private refreshInProgress;
|
|
117
134
|
/** Callbacks invoked when the access token is refreshed */
|
|
118
135
|
private tokenRefreshCallbacks;
|
|
136
|
+
/**
|
|
137
|
+
* Relay-signed access JWT used by BrowserProxyService to register with the
|
|
138
|
+
* Cloud Relay as role 'agent'. First-class, stored credential — distinct
|
|
139
|
+
* from the access `token` and decoupled from socket lifetime. NEVER the
|
|
140
|
+
* Google/Supabase access token (RELAY-TOKEN-TYPE invariant).
|
|
141
|
+
*/
|
|
142
|
+
private relayToken;
|
|
143
|
+
/** Parsed `exp` (seconds) of {@link relayToken}, for proactive refresh. */
|
|
144
|
+
private relayTokenExp;
|
|
145
|
+
/** Timer for proactive relay-token refresh (fires SKEW before exp). */
|
|
146
|
+
private relayRefreshTimer;
|
|
147
|
+
/** Callbacks invoked when the relay token is refreshed (distinct channel). */
|
|
148
|
+
private relayTokenRefreshCallbacks;
|
|
119
149
|
private constructor();
|
|
120
150
|
/**
|
|
121
151
|
* Get the singleton instance.
|
|
@@ -277,6 +307,39 @@ export declare class CloudClientService {
|
|
|
277
307
|
* @param callback - Function receiving the new access token string
|
|
278
308
|
*/
|
|
279
309
|
onTokenRefresh(callback: (newToken: string) => void): void;
|
|
310
|
+
/**
|
|
311
|
+
* Get the current relay-signed token (for BrowserProxyService registration).
|
|
312
|
+
*
|
|
313
|
+
* This is DISTINCT from {@link getToken} (the access/HTTP token). The
|
|
314
|
+
* BrowserProxy must register with the relay token, never the access token —
|
|
315
|
+
* see the RELAY-TOKEN-TYPE invariant. Returns null until a relay token has
|
|
316
|
+
* been minted by the Cloud validate/refresh endpoint.
|
|
317
|
+
*
|
|
318
|
+
* @returns Current relay token or null
|
|
319
|
+
*/
|
|
320
|
+
getRelayToken(): string | null;
|
|
321
|
+
/**
|
|
322
|
+
* Register a callback invoked whenever the relay token is refreshed.
|
|
323
|
+
*
|
|
324
|
+
* Distinct subscription channel from {@link onTokenRefresh}: subscribers
|
|
325
|
+
* here (BrowserProxyService) receive the relay-signed token, never the
|
|
326
|
+
* access token. Decoupling the channels prevents the proxy from ever being
|
|
327
|
+
* fed the wrong token type on refresh.
|
|
328
|
+
*
|
|
329
|
+
* @param callback - Function receiving the new relay token string
|
|
330
|
+
*/
|
|
331
|
+
onRelayTokenRefresh(callback: (newRelayToken: string) => void): void;
|
|
332
|
+
/**
|
|
333
|
+
* Store a freshly-minted relay token as a first-class credential, parse its
|
|
334
|
+
* expiry, schedule proactive refresh, persist it, and notify subscribers.
|
|
335
|
+
*
|
|
336
|
+
* Centralizes relay-token handling so every code path that obtains one
|
|
337
|
+
* (connect, refresh, validate) treats it identically. Persistence is
|
|
338
|
+
* fire-and-forget; a persist failure must not break the refresh chain.
|
|
339
|
+
*
|
|
340
|
+
* @param relayToken - The relay-signed access JWT from Cloud
|
|
341
|
+
*/
|
|
342
|
+
private storeRelayToken;
|
|
280
343
|
/**
|
|
281
344
|
* Attempt to refresh the access token using the stored refresh token.
|
|
282
345
|
*
|
|
@@ -295,6 +358,18 @@ export declare class CloudClientService {
|
|
|
295
358
|
* @param token - JWT access token to extract expiry from
|
|
296
359
|
*/
|
|
297
360
|
private scheduleTokenRefresh;
|
|
361
|
+
/**
|
|
362
|
+
* Schedule a proactive relay-token refresh `RELAY_REFRESH_SKEW_S` seconds
|
|
363
|
+
* before the relay token's real `exp`.
|
|
364
|
+
*
|
|
365
|
+
* The relay token (~60min TTL) is decoupled from the access token, so it
|
|
366
|
+
* needs its own refresh schedule. When the timer fires it calls
|
|
367
|
+
* {@link fetchRelayTokenFromValidate}, which re-mints a relay token and
|
|
368
|
+
* stores it (re-arming this timer). This keeps a continuously-open relay
|
|
369
|
+
* socket from ever carrying an expired token — the DURABLE-CREDENTIAL
|
|
370
|
+
* invariant. Driven by the JWT `exp` claim, not a wall-clock heuristic.
|
|
371
|
+
*/
|
|
372
|
+
private scheduleRelayTokenRefresh;
|
|
298
373
|
/**
|
|
299
374
|
* Fetch relay token by calling Cloud validate endpoint.
|
|
300
375
|
* Used after connectLocal() to get a Cloud-signed relay JWT
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloud-client.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/cloud/cloud-client.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH,OAAO,EAGL,KAAK,SAAS,EACd,KAAK,qBAAqB,EAC3B,MAAM,oBAAoB,CAAC;AAE5B;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,YAAY,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"cloud-client.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/cloud/cloud-client.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,6 +15,29 @@ import * as path from 'path';
|
|
|
15
15
|
import { readFile, writeFile, mkdir, unlink } from 'fs/promises';
|
|
16
16
|
import { LoggerService } from '../core/logger.service.js';
|
|
17
17
|
import { CLOUD_CONSTANTS, AUTH_CONSTANTS, } from '../../constants.js';
|
|
18
|
+
/**
|
|
19
|
+
* Decode the `exp` (expiry, seconds since epoch) claim from a JWT without
|
|
20
|
+
* verifying its signature. Returns null when the token is malformed or has
|
|
21
|
+
* no `exp`. Used to schedule proactive relay-token refresh before expiry so
|
|
22
|
+
* a continuously-open relay socket never carries an expired token.
|
|
23
|
+
*
|
|
24
|
+
* @param token - JWT string (may be null)
|
|
25
|
+
* @returns The `exp` claim in seconds, or null when unavailable
|
|
26
|
+
*/
|
|
27
|
+
export function decodeJwtExp(token) {
|
|
28
|
+
if (!token)
|
|
29
|
+
return null;
|
|
30
|
+
try {
|
|
31
|
+
const parts = token.split('.');
|
|
32
|
+
if (parts.length !== 3)
|
|
33
|
+
return null;
|
|
34
|
+
const payload = JSON.parse(Buffer.from(parts[1], 'base64url').toString('utf8'));
|
|
35
|
+
return typeof payload.exp === 'number' ? payload.exp : null;
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
18
41
|
// ---------------------------------------------------------------------------
|
|
19
42
|
// Service
|
|
20
43
|
// ---------------------------------------------------------------------------
|
|
@@ -46,6 +69,19 @@ export class CloudClientService {
|
|
|
46
69
|
refreshInProgress = false;
|
|
47
70
|
/** Callbacks invoked when the access token is refreshed */
|
|
48
71
|
tokenRefreshCallbacks = [];
|
|
72
|
+
/**
|
|
73
|
+
* Relay-signed access JWT used by BrowserProxyService to register with the
|
|
74
|
+
* Cloud Relay as role 'agent'. First-class, stored credential — distinct
|
|
75
|
+
* from the access `token` and decoupled from socket lifetime. NEVER the
|
|
76
|
+
* Google/Supabase access token (RELAY-TOKEN-TYPE invariant).
|
|
77
|
+
*/
|
|
78
|
+
relayToken = null;
|
|
79
|
+
/** Parsed `exp` (seconds) of {@link relayToken}, for proactive refresh. */
|
|
80
|
+
relayTokenExp = null;
|
|
81
|
+
/** Timer for proactive relay-token refresh (fires SKEW before exp). */
|
|
82
|
+
relayRefreshTimer = null;
|
|
83
|
+
/** Callbacks invoked when the relay token is refreshed (distinct channel). */
|
|
84
|
+
relayTokenRefreshCallbacks = [];
|
|
49
85
|
constructor() {
|
|
50
86
|
this.logger = LoggerService.getInstance().createComponentLogger('CloudClientService');
|
|
51
87
|
}
|
|
@@ -115,13 +151,12 @@ export class CloudClientService {
|
|
|
115
151
|
this.tier = resolvedTier || CLOUD_CONSTANTS.TIERS.FREE;
|
|
116
152
|
this.connectionStatus = CLOUD_CONSTANTS.CONNECTION_STATUS.CONNECTED;
|
|
117
153
|
this.lastSyncAt = new Date().toISOString();
|
|
118
|
-
// Use relay token from Cloud validate response for BrowserProxyService
|
|
154
|
+
// Use relay token from Cloud validate response for BrowserProxyService.
|
|
155
|
+
// Store it as a first-class credential (not a transient callback arg) so
|
|
156
|
+
// it can be persisted, refreshed proactively, and re-fed on restart.
|
|
119
157
|
if (data.data?.relayToken) {
|
|
120
158
|
this.logger.info('Relay token received from Cloud');
|
|
121
|
-
|
|
122
|
-
for (const callback of this.tokenRefreshCallbacks) {
|
|
123
|
-
callback(data.data.relayToken);
|
|
124
|
-
}
|
|
159
|
+
this.storeRelayToken(data.data.relayToken);
|
|
125
160
|
}
|
|
126
161
|
this.logger.info('Connected to CrewlyAI Cloud', { tier: this.tier, hasRelayToken: !!data.data?.relayToken });
|
|
127
162
|
// Schedule proactive token refresh
|
|
@@ -183,10 +218,16 @@ export class CloudClientService {
|
|
|
183
218
|
this.connectionStatus = CLOUD_CONSTANTS.CONNECTION_STATUS.DISCONNECTED;
|
|
184
219
|
this.tier = CLOUD_CONSTANTS.TIERS.FREE;
|
|
185
220
|
this.lastSyncAt = null;
|
|
221
|
+
this.relayToken = null;
|
|
222
|
+
this.relayTokenExp = null;
|
|
186
223
|
if (this.refreshTimer) {
|
|
187
224
|
clearTimeout(this.refreshTimer);
|
|
188
225
|
this.refreshTimer = null;
|
|
189
226
|
}
|
|
227
|
+
if (this.relayRefreshTimer) {
|
|
228
|
+
clearTimeout(this.relayRefreshTimer);
|
|
229
|
+
this.relayRefreshTimer = null;
|
|
230
|
+
}
|
|
190
231
|
// Remove persisted config
|
|
191
232
|
this.removePersistedConfig().catch((err) => {
|
|
192
233
|
this.logger.warn('Failed to remove persisted cloud config (non-fatal)', {
|
|
@@ -212,6 +253,16 @@ export class CloudClientService {
|
|
|
212
253
|
const data = await readFile(CloudClientService.getConfigPath(), 'utf-8');
|
|
213
254
|
const config = JSON.parse(data);
|
|
214
255
|
if (config.cloudUrl && config.token && config.tier) {
|
|
256
|
+
// Restore the persisted relay token immediately so BrowserProxy can
|
|
257
|
+
// re-register on restart without waiting for a fresh validate
|
|
258
|
+
// round-trip. fetchRelayTokenFromValidate (kicked off by connectLocal)
|
|
259
|
+
// will refresh it shortly after. Do not broadcast here — connect/
|
|
260
|
+
// connectLocal own the wiring of subscribers; this just primes state.
|
|
261
|
+
if (config.relayToken) {
|
|
262
|
+
this.relayToken = config.relayToken;
|
|
263
|
+
this.relayTokenExp = decodeJwtExp(config.relayToken);
|
|
264
|
+
this.scheduleRelayTokenRefresh();
|
|
265
|
+
}
|
|
215
266
|
return config;
|
|
216
267
|
}
|
|
217
268
|
return null;
|
|
@@ -232,6 +283,7 @@ export class CloudClientService {
|
|
|
232
283
|
tier: this.tier,
|
|
233
284
|
connectedAt: new Date().toISOString(),
|
|
234
285
|
...(this.refreshToken && { refreshToken: this.refreshToken }),
|
|
286
|
+
...(this.relayToken && { relayToken: this.relayToken }),
|
|
235
287
|
};
|
|
236
288
|
const configPath = CloudClientService.getConfigPath();
|
|
237
289
|
await mkdir(path.dirname(configPath), { recursive: true });
|
|
@@ -454,6 +506,60 @@ export class CloudClientService {
|
|
|
454
506
|
onTokenRefresh(callback) {
|
|
455
507
|
this.tokenRefreshCallbacks.push(callback);
|
|
456
508
|
}
|
|
509
|
+
/**
|
|
510
|
+
* Get the current relay-signed token (for BrowserProxyService registration).
|
|
511
|
+
*
|
|
512
|
+
* This is DISTINCT from {@link getToken} (the access/HTTP token). The
|
|
513
|
+
* BrowserProxy must register with the relay token, never the access token —
|
|
514
|
+
* see the RELAY-TOKEN-TYPE invariant. Returns null until a relay token has
|
|
515
|
+
* been minted by the Cloud validate/refresh endpoint.
|
|
516
|
+
*
|
|
517
|
+
* @returns Current relay token or null
|
|
518
|
+
*/
|
|
519
|
+
getRelayToken() {
|
|
520
|
+
return this.relayToken;
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Register a callback invoked whenever the relay token is refreshed.
|
|
524
|
+
*
|
|
525
|
+
* Distinct subscription channel from {@link onTokenRefresh}: subscribers
|
|
526
|
+
* here (BrowserProxyService) receive the relay-signed token, never the
|
|
527
|
+
* access token. Decoupling the channels prevents the proxy from ever being
|
|
528
|
+
* fed the wrong token type on refresh.
|
|
529
|
+
*
|
|
530
|
+
* @param callback - Function receiving the new relay token string
|
|
531
|
+
*/
|
|
532
|
+
onRelayTokenRefresh(callback) {
|
|
533
|
+
this.relayTokenRefreshCallbacks.push(callback);
|
|
534
|
+
}
|
|
535
|
+
/**
|
|
536
|
+
* Store a freshly-minted relay token as a first-class credential, parse its
|
|
537
|
+
* expiry, schedule proactive refresh, persist it, and notify subscribers.
|
|
538
|
+
*
|
|
539
|
+
* Centralizes relay-token handling so every code path that obtains one
|
|
540
|
+
* (connect, refresh, validate) treats it identically. Persistence is
|
|
541
|
+
* fire-and-forget; a persist failure must not break the refresh chain.
|
|
542
|
+
*
|
|
543
|
+
* @param relayToken - The relay-signed access JWT from Cloud
|
|
544
|
+
*/
|
|
545
|
+
storeRelayToken(relayToken) {
|
|
546
|
+
this.relayToken = relayToken;
|
|
547
|
+
this.relayTokenExp = decodeJwtExp(relayToken);
|
|
548
|
+
// Schedule proactive refresh before this relay token's real exp so a
|
|
549
|
+
// continuously-open relay socket never carries an expired token.
|
|
550
|
+
this.scheduleRelayTokenRefresh();
|
|
551
|
+
// Persist alongside the access token for restart resilience.
|
|
552
|
+
this.persistConfig().catch(() => { });
|
|
553
|
+
// Notify subscribers (BrowserProxyService) on the relay-token channel.
|
|
554
|
+
for (const callback of this.relayTokenRefreshCallbacks) {
|
|
555
|
+
try {
|
|
556
|
+
callback(relayToken);
|
|
557
|
+
}
|
|
558
|
+
catch {
|
|
559
|
+
// Non-fatal — one bad callback must not break the refresh chain.
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
}
|
|
457
563
|
/**
|
|
458
564
|
* Attempt to refresh the access token using the stored refresh token.
|
|
459
565
|
*
|
|
@@ -551,17 +657,27 @@ export class CloudClientService {
|
|
|
551
657
|
catch {
|
|
552
658
|
// CloudSyncService may not be available — non-fatal
|
|
553
659
|
}
|
|
554
|
-
// Notify token refresh subscribers
|
|
555
|
-
//
|
|
556
|
-
|
|
660
|
+
// Notify access-token refresh subscribers with the ACCESS token only.
|
|
661
|
+
// The relay token has its own channel (storeRelayToken below) — never
|
|
662
|
+
// substitute the access token for the relay token (RELAY-TOKEN-TYPE
|
|
663
|
+
// invariant). Subscribers on this channel that need the relay token
|
|
664
|
+
// should subscribe via onRelayTokenRefresh instead.
|
|
557
665
|
for (const callback of this.tokenRefreshCallbacks) {
|
|
558
666
|
try {
|
|
559
|
-
callback(
|
|
667
|
+
callback(newAccessToken);
|
|
560
668
|
}
|
|
561
669
|
catch {
|
|
562
670
|
// Non-fatal — don't let one bad callback break the refresh chain
|
|
563
671
|
}
|
|
564
672
|
}
|
|
673
|
+
// Store the relay token as a first-class credential when the refresh
|
|
674
|
+
// returned one. If none was returned, keep the existing stored relay
|
|
675
|
+
// token rather than clobbering it with the access token — a continuing
|
|
676
|
+
// socket keeps working on its still-valid relay token until its own
|
|
677
|
+
// proactive refresh fires.
|
|
678
|
+
if (relayToken) {
|
|
679
|
+
this.storeRelayToken(relayToken);
|
|
680
|
+
}
|
|
565
681
|
this.logger.info('Access token auto-refreshed successfully', { hasRelayToken: !!relayToken });
|
|
566
682
|
return true;
|
|
567
683
|
}
|
|
@@ -623,6 +739,44 @@ export class CloudClientService {
|
|
|
623
739
|
this.logger.debug('Could not schedule token refresh (non-fatal)');
|
|
624
740
|
}
|
|
625
741
|
}
|
|
742
|
+
/**
|
|
743
|
+
* Schedule a proactive relay-token refresh `RELAY_REFRESH_SKEW_S` seconds
|
|
744
|
+
* before the relay token's real `exp`.
|
|
745
|
+
*
|
|
746
|
+
* The relay token (~60min TTL) is decoupled from the access token, so it
|
|
747
|
+
* needs its own refresh schedule. When the timer fires it calls
|
|
748
|
+
* {@link fetchRelayTokenFromValidate}, which re-mints a relay token and
|
|
749
|
+
* stores it (re-arming this timer). This keeps a continuously-open relay
|
|
750
|
+
* socket from ever carrying an expired token — the DURABLE-CREDENTIAL
|
|
751
|
+
* invariant. Driven by the JWT `exp` claim, not a wall-clock heuristic.
|
|
752
|
+
*/
|
|
753
|
+
scheduleRelayTokenRefresh() {
|
|
754
|
+
if (this.relayRefreshTimer) {
|
|
755
|
+
clearTimeout(this.relayRefreshTimer);
|
|
756
|
+
this.relayRefreshTimer = null;
|
|
757
|
+
}
|
|
758
|
+
if (!this.relayTokenExp)
|
|
759
|
+
return;
|
|
760
|
+
const now = Math.floor(Date.now() / 1000);
|
|
761
|
+
// Refresh 5 minutes (300s) before expiry — same skew as the access token.
|
|
762
|
+
const refreshAt = this.relayTokenExp - 300;
|
|
763
|
+
const delayMs = Math.max(0, (refreshAt - now) * 1000);
|
|
764
|
+
if (delayMs <= 0) {
|
|
765
|
+
// Already near expiry — refresh immediately.
|
|
766
|
+
this.logger.info('Relay token near expiry, refreshing immediately');
|
|
767
|
+
this.fetchRelayTokenFromValidate().catch(() => { });
|
|
768
|
+
return;
|
|
769
|
+
}
|
|
770
|
+
this.relayRefreshTimer = setTimeout(() => {
|
|
771
|
+
this.logger.info('Proactive relay-token refresh triggered');
|
|
772
|
+
this.fetchRelayTokenFromValidate().catch(() => { });
|
|
773
|
+
}, delayMs);
|
|
774
|
+
// Unref so the timer doesn't keep the process alive.
|
|
775
|
+
if (this.relayRefreshTimer.unref)
|
|
776
|
+
this.relayRefreshTimer.unref();
|
|
777
|
+
const minutesUntilRefresh = Math.round(delayMs / 60_000);
|
|
778
|
+
this.logger.debug('Relay token refresh scheduled', { minutesUntilRefresh });
|
|
779
|
+
}
|
|
626
780
|
// -------------------------------------------------------------------------
|
|
627
781
|
// Private helpers
|
|
628
782
|
// -------------------------------------------------------------------------
|
|
@@ -652,9 +806,7 @@ export class CloudClientService {
|
|
|
652
806
|
const data = await response.json();
|
|
653
807
|
if (data.data?.relayToken) {
|
|
654
808
|
this.logger.info('Relay token received from Cloud validate (after connectLocal)');
|
|
655
|
-
|
|
656
|
-
callback(data.data.relayToken);
|
|
657
|
-
}
|
|
809
|
+
this.storeRelayToken(data.data.relayToken);
|
|
658
810
|
}
|
|
659
811
|
}
|
|
660
812
|
/**
|