crewly 1.11.5 → 1.11.6
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 +22 -1
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +22 -1
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/services/backup/backup-archive.service.d.ts +90 -0
- package/dist/backend/backend/src/services/backup/backup-archive.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/backup/backup-archive.service.js +309 -0
- package/dist/backend/backend/src/services/backup/backup-archive.service.js.map +1 -0
- package/dist/backend/backend/src/services/backup/backup-cloud.client.d.ts +75 -0
- package/dist/backend/backend/src/services/backup/backup-cloud.client.d.ts.map +1 -0
- package/dist/backend/backend/src/services/backup/backup-cloud.client.js +134 -0
- package/dist/backend/backend/src/services/backup/backup-cloud.client.js.map +1 -0
- package/dist/backend/backend/src/services/backup/backup-restore.service.d.ts +78 -0
- package/dist/backend/backend/src/services/backup/backup-restore.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/backup/backup-restore.service.js +358 -0
- package/dist/backend/backend/src/services/backup/backup-restore.service.js.map +1 -0
- package/dist/backend/backend/src/services/backup/backup.types.d.ts +163 -0
- package/dist/backend/backend/src/services/backup/backup.types.d.ts.map +1 -0
- package/dist/backend/backend/src/services/backup/backup.types.js +13 -0
- package/dist/backend/backend/src/services/backup/backup.types.js.map +1 -0
- package/dist/backend/backend/src/services/cloud/cloud-sync.service.d.ts +29 -2
- package/dist/backend/backend/src/services/cloud/cloud-sync.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-sync.service.js +97 -13
- package/dist/backend/backend/src/services/cloud/cloud-sync.service.js.map +1 -1
- package/dist/cli/backend/src/constants.d.ts +22 -1
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +22 -1
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/controllers/cloud/cloud-google-auth.controller.d.ts +70 -0
- package/dist/cli/backend/src/controllers/cloud/cloud-google-auth.controller.d.ts.map +1 -0
- package/dist/cli/backend/src/controllers/cloud/cloud-google-auth.controller.js +427 -0
- package/dist/cli/backend/src/controllers/cloud/cloud-google-auth.controller.js.map +1 -0
- package/dist/cli/backend/src/services/backup/backup-archive.service.d.ts +90 -0
- package/dist/cli/backend/src/services/backup/backup-archive.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/backup/backup-archive.service.js +309 -0
- package/dist/cli/backend/src/services/backup/backup-archive.service.js.map +1 -0
- package/dist/cli/backend/src/services/backup/backup-cloud.client.d.ts +75 -0
- package/dist/cli/backend/src/services/backup/backup-cloud.client.d.ts.map +1 -0
- package/dist/cli/backend/src/services/backup/backup-cloud.client.js +134 -0
- package/dist/cli/backend/src/services/backup/backup-cloud.client.js.map +1 -0
- package/dist/cli/backend/src/services/backup/backup-restore.service.d.ts +78 -0
- package/dist/cli/backend/src/services/backup/backup-restore.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/backup/backup-restore.service.js +358 -0
- package/dist/cli/backend/src/services/backup/backup-restore.service.js.map +1 -0
- package/dist/cli/backend/src/services/backup/backup.types.d.ts +163 -0
- package/dist/cli/backend/src/services/backup/backup.types.d.ts.map +1 -0
- package/dist/cli/backend/src/services/backup/backup.types.js +13 -0
- package/dist/cli/backend/src/services/backup/backup.types.js.map +1 -0
- package/dist/cli/backend/src/services/cloud/cloud-client.service.d.ts +410 -0
- package/dist/cli/backend/src/services/cloud/cloud-client.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/cloud/cloud-client.service.js +863 -0
- package/dist/cli/backend/src/services/cloud/cloud-client.service.js.map +1 -0
- package/dist/cli/backend/src/services/cloud/cloud-sync.service.d.ts +292 -0
- package/dist/cli/backend/src/services/cloud/cloud-sync.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/cloud/cloud-sync.service.js +1093 -0
- package/dist/cli/backend/src/services/cloud/cloud-sync.service.js.map +1 -0
- package/dist/cli/backend/src/services/cloud/cloud-sync.types.d.ts +328 -0
- package/dist/cli/backend/src/services/cloud/cloud-sync.types.d.ts.map +1 -0
- package/dist/cli/backend/src/services/cloud/cloud-sync.types.js +171 -0
- package/dist/cli/backend/src/services/cloud/cloud-sync.types.js.map +1 -0
- package/dist/cli/backend/src/services/cloud/device-identity.service.d.ts +89 -0
- package/dist/cli/backend/src/services/cloud/device-identity.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/cloud/device-identity.service.js +148 -0
- package/dist/cli/backend/src/services/cloud/device-identity.service.js.map +1 -0
- package/dist/cli/backend/src/services/user/user-identity.service.d.ts +86 -0
- package/dist/cli/backend/src/services/user/user-identity.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/user/user-identity.service.js +190 -0
- package/dist/cli/backend/src/services/user/user-identity.service.js.map +1 -0
- package/dist/cli/cli/src/commands/backup.d.ts +31 -0
- package/dist/cli/cli/src/commands/backup.d.ts.map +1 -0
- package/dist/cli/cli/src/commands/backup.js +280 -0
- package/dist/cli/cli/src/commands/backup.js.map +1 -0
- package/dist/cli/cli/src/index.js +10 -0
- package/dist/cli/cli/src/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloud Client Service
|
|
3
|
+
*
|
|
4
|
+
* Singleton service responsible for all interactions with CrewlyAI Cloud.
|
|
5
|
+
* Handles authentication, premium template fetching, and subscription
|
|
6
|
+
* status synchronization.
|
|
7
|
+
*
|
|
8
|
+
* Premium templates are loaded into memory only — never written to disk
|
|
9
|
+
* to prevent IP leakage.
|
|
10
|
+
*
|
|
11
|
+
* @module services/cloud/cloud-client.service
|
|
12
|
+
*/
|
|
13
|
+
import { type CloudTier, type CloudConnectionStatus } from '../../constants.js';
|
|
14
|
+
/**
|
|
15
|
+
* Persisted cloud config stored at ~/.crewly/cloud/config.json.
|
|
16
|
+
* Enables auto-reconnect on backend restart.
|
|
17
|
+
*/
|
|
18
|
+
export interface PersistedCloudConfig {
|
|
19
|
+
cloudUrl: string;
|
|
20
|
+
token: string;
|
|
21
|
+
tier: string;
|
|
22
|
+
connectedAt: string;
|
|
23
|
+
/** Refresh token for auto-renewing expired access tokens */
|
|
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;
|
|
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;
|
|
43
|
+
/** Summary of a premium template returned by the cloud listing endpoint. */
|
|
44
|
+
export interface CloudTemplateSummary {
|
|
45
|
+
/** Unique template identifier */
|
|
46
|
+
id: string;
|
|
47
|
+
/** Human-readable template name */
|
|
48
|
+
name: string;
|
|
49
|
+
/** Short description */
|
|
50
|
+
description: string;
|
|
51
|
+
/** Minimum subscription tier required */
|
|
52
|
+
requiredTier: CloudTier;
|
|
53
|
+
/** Category tag (e.g. "dev-team", "marketing") */
|
|
54
|
+
category: string;
|
|
55
|
+
}
|
|
56
|
+
/** Full detail for a single premium template (in-memory only). */
|
|
57
|
+
export interface CloudTemplateDetail {
|
|
58
|
+
/** Unique template identifier */
|
|
59
|
+
id: string;
|
|
60
|
+
/** Human-readable template name */
|
|
61
|
+
name: string;
|
|
62
|
+
/** Full description */
|
|
63
|
+
description: string;
|
|
64
|
+
/** Minimum subscription tier required */
|
|
65
|
+
requiredTier: CloudTier;
|
|
66
|
+
/** Category tag */
|
|
67
|
+
category: string;
|
|
68
|
+
/** Team member role definitions */
|
|
69
|
+
roles: Array<{
|
|
70
|
+
role: string;
|
|
71
|
+
prompt: string;
|
|
72
|
+
}>;
|
|
73
|
+
/** Task orchestration config */
|
|
74
|
+
orchestration: Record<string, unknown>;
|
|
75
|
+
}
|
|
76
|
+
/** A relay device returned by the Cloud devices API. */
|
|
77
|
+
export interface CloudRelayDevice {
|
|
78
|
+
/** Device/session ID */
|
|
79
|
+
sessionId: string;
|
|
80
|
+
/** Device role */
|
|
81
|
+
role: 'orchestrator' | 'agent';
|
|
82
|
+
/** Device state */
|
|
83
|
+
state: 'waiting' | 'paired' | 'disconnected';
|
|
84
|
+
/** Paired peer device ID */
|
|
85
|
+
pairedWith: string | null;
|
|
86
|
+
/** ISO registration timestamp */
|
|
87
|
+
registeredAt: string;
|
|
88
|
+
/** ISO last heartbeat timestamp */
|
|
89
|
+
lastHeartbeatAt: string;
|
|
90
|
+
/** Human-readable device name (legacy field) */
|
|
91
|
+
name?: string;
|
|
92
|
+
/** Human-readable device name returned by Cloud API */
|
|
93
|
+
deviceName?: string;
|
|
94
|
+
/** Unique device identifier */
|
|
95
|
+
deviceId?: string;
|
|
96
|
+
}
|
|
97
|
+
/** Current cloud connection state exposed by getStatus(). */
|
|
98
|
+
export interface CloudStatus {
|
|
99
|
+
/** Whether the client is currently connected */
|
|
100
|
+
connectionStatus: CloudConnectionStatus;
|
|
101
|
+
/** Cloud API base URL (set after connect) */
|
|
102
|
+
cloudUrl: string | null;
|
|
103
|
+
/** Current subscription tier */
|
|
104
|
+
tier: CloudTier;
|
|
105
|
+
/** ISO timestamp of last successful sync */
|
|
106
|
+
lastSyncAt: string | null;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* CloudClientService singleton.
|
|
110
|
+
*
|
|
111
|
+
* Manages the lifecycle of the connection between a local Crewly instance
|
|
112
|
+
* and CrewlyAI Cloud. All cloud API calls are made via native fetch with
|
|
113
|
+
* bearer-token authentication.
|
|
114
|
+
*/
|
|
115
|
+
export declare class CloudClientService {
|
|
116
|
+
private static instance;
|
|
117
|
+
private readonly logger;
|
|
118
|
+
/** Cloud API base URL (e.g. "https://api.crewlyai.com") */
|
|
119
|
+
private cloudUrl;
|
|
120
|
+
/** Bearer token obtained during connect() */
|
|
121
|
+
private token;
|
|
122
|
+
/** Refresh token for auto-renewing expired access tokens */
|
|
123
|
+
private refreshToken;
|
|
124
|
+
/** Current connection status */
|
|
125
|
+
private connectionStatus;
|
|
126
|
+
/** Subscription tier reported by cloud */
|
|
127
|
+
private tier;
|
|
128
|
+
/** Timestamp of the most recent successful cloud API call */
|
|
129
|
+
private lastSyncAt;
|
|
130
|
+
/** Timer for proactive token refresh (fires 5 min before expiry) */
|
|
131
|
+
private refreshTimer;
|
|
132
|
+
/** Guard to prevent concurrent refresh attempts */
|
|
133
|
+
private refreshInProgress;
|
|
134
|
+
/** Callbacks invoked when the access token is refreshed */
|
|
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;
|
|
149
|
+
private constructor();
|
|
150
|
+
/**
|
|
151
|
+
* Get the singleton instance.
|
|
152
|
+
*
|
|
153
|
+
* @returns CloudClientService instance
|
|
154
|
+
*/
|
|
155
|
+
static getInstance(): CloudClientService;
|
|
156
|
+
/**
|
|
157
|
+
* Reset the singleton (for testing).
|
|
158
|
+
*/
|
|
159
|
+
static resetInstance(): void;
|
|
160
|
+
/**
|
|
161
|
+
* Connect to CrewlyAI Cloud by verifying the provided token.
|
|
162
|
+
*
|
|
163
|
+
* Calls the cloud auth endpoint to validate credentials and retrieve
|
|
164
|
+
* the subscription tier. On success the service transitions to
|
|
165
|
+
* "connected" status.
|
|
166
|
+
*
|
|
167
|
+
* @param cloudUrl - Base URL of the CrewlyAI Cloud API
|
|
168
|
+
* @param token - Authentication token (API key or JWT)
|
|
169
|
+
* @returns Object with connection result
|
|
170
|
+
* @throws Error when the auth request fails or token is invalid
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* ```ts
|
|
174
|
+
* const client = CloudClientService.getInstance();
|
|
175
|
+
* await client.connect('https://api.crewlyai.com', 'sk-abc123');
|
|
176
|
+
* ```
|
|
177
|
+
*/
|
|
178
|
+
connect(cloudUrl: string, token: string, refreshToken?: string): Promise<{
|
|
179
|
+
success: boolean;
|
|
180
|
+
tier: CloudTier;
|
|
181
|
+
}>;
|
|
182
|
+
/**
|
|
183
|
+
* Connect using a locally verified JWT (no remote API call needed).
|
|
184
|
+
*
|
|
185
|
+
* Used when the JWT was issued by this same instance or the JWT secret
|
|
186
|
+
* is shared between OSS and Cloud. Avoids the round-trip to the cloud
|
|
187
|
+
* auth endpoint.
|
|
188
|
+
*
|
|
189
|
+
* @param cloudUrl - Base URL of the CrewlyAI Cloud API
|
|
190
|
+
* @param token - JWT access token (already verified locally)
|
|
191
|
+
* @param tier - Subscription tier extracted from the JWT payload
|
|
192
|
+
* @param refreshToken - Optional refresh token for auto-renewal
|
|
193
|
+
*/
|
|
194
|
+
connectLocal(cloudUrl: string, token: string, tier: CloudTier, refreshToken?: string): void;
|
|
195
|
+
/**
|
|
196
|
+
* Disconnect from CrewlyAI Cloud.
|
|
197
|
+
*
|
|
198
|
+
* Clears stored credentials and resets the connection state.
|
|
199
|
+
*/
|
|
200
|
+
disconnect(): void;
|
|
201
|
+
/**
|
|
202
|
+
* Path to the persisted cloud config file.
|
|
203
|
+
*/
|
|
204
|
+
static getConfigPath(): string;
|
|
205
|
+
/**
|
|
206
|
+
* Load persisted cloud config from disk.
|
|
207
|
+
* Returns null if file doesn't exist or is invalid.
|
|
208
|
+
*/
|
|
209
|
+
loadPersistedConfig(): Promise<PersistedCloudConfig | null>;
|
|
210
|
+
/**
|
|
211
|
+
* Persist current cloud connection config to disk for auto-reconnect.
|
|
212
|
+
*/
|
|
213
|
+
private persistConfig;
|
|
214
|
+
/**
|
|
215
|
+
* Remove persisted cloud config from disk (on disconnect).
|
|
216
|
+
*/
|
|
217
|
+
private removePersistedConfig;
|
|
218
|
+
/**
|
|
219
|
+
* Fetch the list of premium templates available on CrewlyAI Cloud.
|
|
220
|
+
*
|
|
221
|
+
* Requires an active cloud connection.
|
|
222
|
+
*
|
|
223
|
+
* @returns Array of template summaries
|
|
224
|
+
* @throws Error when not connected or fetch fails
|
|
225
|
+
*
|
|
226
|
+
* @example
|
|
227
|
+
* ```ts
|
|
228
|
+
* const templates = await client.getTemplates();
|
|
229
|
+
* console.log(templates.map(t => t.name));
|
|
230
|
+
* ```
|
|
231
|
+
*/
|
|
232
|
+
getTemplates(): Promise<CloudTemplateSummary[]>;
|
|
233
|
+
/**
|
|
234
|
+
* Fetch full detail for a single premium template.
|
|
235
|
+
*
|
|
236
|
+
* The returned data is held in memory only and must never be
|
|
237
|
+
* persisted to disk.
|
|
238
|
+
*
|
|
239
|
+
* @param id - Template identifier
|
|
240
|
+
* @returns Template detail object
|
|
241
|
+
* @throws Error when not connected, template not found, or fetch fails
|
|
242
|
+
*
|
|
243
|
+
* @example
|
|
244
|
+
* ```ts
|
|
245
|
+
* const detail = await client.getTemplateDetail('tpl-tiktok-ops');
|
|
246
|
+
* ```
|
|
247
|
+
*/
|
|
248
|
+
getTemplateDetail(id: string): Promise<CloudTemplateDetail>;
|
|
249
|
+
/**
|
|
250
|
+
* Get the stored cloud API base URL (set during connect).
|
|
251
|
+
*
|
|
252
|
+
* @returns Cloud URL or null if not connected
|
|
253
|
+
*/
|
|
254
|
+
getCloudUrl(): string | null;
|
|
255
|
+
/**
|
|
256
|
+
* Get the current cloud connection status and subscription tier.
|
|
257
|
+
*
|
|
258
|
+
* @returns Current status snapshot
|
|
259
|
+
*/
|
|
260
|
+
getStatus(): CloudStatus;
|
|
261
|
+
/**
|
|
262
|
+
* Check whether the client is currently connected to cloud.
|
|
263
|
+
*
|
|
264
|
+
* @returns true if connected
|
|
265
|
+
*/
|
|
266
|
+
isConnected(): boolean;
|
|
267
|
+
/**
|
|
268
|
+
* Check whether the cloud token has expired (401/403 from cloud API).
|
|
269
|
+
*
|
|
270
|
+
* @returns true if the token has expired
|
|
271
|
+
*/
|
|
272
|
+
isTokenExpired(): boolean;
|
|
273
|
+
/**
|
|
274
|
+
* Get the current subscription tier.
|
|
275
|
+
*
|
|
276
|
+
* @returns Current tier value
|
|
277
|
+
*/
|
|
278
|
+
getTier(): CloudTier;
|
|
279
|
+
/**
|
|
280
|
+
* Fetch the list of devices registered to this user from Cloud.
|
|
281
|
+
*
|
|
282
|
+
* Proxies GET /api/v1/relay/devices on crewlyai.com and returns
|
|
283
|
+
* the device list for the authenticated user.
|
|
284
|
+
*
|
|
285
|
+
* @returns Array of cloud relay devices
|
|
286
|
+
* @throws Error when not connected or fetch fails
|
|
287
|
+
*/
|
|
288
|
+
fetchCloudDevices(): Promise<CloudRelayDevice[]>;
|
|
289
|
+
/**
|
|
290
|
+
* Set the refresh token for auto-renewal.
|
|
291
|
+
*
|
|
292
|
+
* Called by the connect controller after OAuth login provides a refresh token.
|
|
293
|
+
*
|
|
294
|
+
* @param refreshToken - Refresh token string
|
|
295
|
+
*/
|
|
296
|
+
setRefreshToken(refreshToken: string): void;
|
|
297
|
+
/**
|
|
298
|
+
* Get the current access token (for CloudSyncService token updates).
|
|
299
|
+
*
|
|
300
|
+
* @returns Current access token or null
|
|
301
|
+
*/
|
|
302
|
+
getToken(): string | null;
|
|
303
|
+
/**
|
|
304
|
+
* Register a callback to be invoked whenever the access token is refreshed.
|
|
305
|
+
* Used by BrowserProxyService to update its relay auth token in real-time.
|
|
306
|
+
*
|
|
307
|
+
* @param callback - Function receiving the new access token string
|
|
308
|
+
*/
|
|
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;
|
|
343
|
+
/**
|
|
344
|
+
* Attempt to refresh the access token using the stored refresh token.
|
|
345
|
+
*
|
|
346
|
+
* Issues a new access token locally (since both access and refresh tokens
|
|
347
|
+
* are signed with the same HMAC secret on this OSS instance).
|
|
348
|
+
*
|
|
349
|
+
* @returns true if refresh succeeded, false if no refresh token or refresh failed
|
|
350
|
+
*/
|
|
351
|
+
tryRefreshToken(): Promise<boolean>;
|
|
352
|
+
/**
|
|
353
|
+
* Schedule a proactive token refresh 5 minutes before expiry.
|
|
354
|
+
*
|
|
355
|
+
* Parses the JWT `exp` claim and sets a timer. If the token has
|
|
356
|
+
* less than 5 minutes remaining, refreshes immediately.
|
|
357
|
+
*
|
|
358
|
+
* @param token - JWT access token to extract expiry from
|
|
359
|
+
*/
|
|
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;
|
|
373
|
+
/**
|
|
374
|
+
* Fetch relay token by calling Cloud validate endpoint.
|
|
375
|
+
* Used after connectLocal() to get a Cloud-signed relay JWT
|
|
376
|
+
* without blocking the connection flow.
|
|
377
|
+
*
|
|
378
|
+
* @returns Promise that resolves when relay token is fetched (or skipped)
|
|
379
|
+
*/
|
|
380
|
+
private fetchRelayTokenFromValidate;
|
|
381
|
+
/**
|
|
382
|
+
* Throw if the client is not in a connected state.
|
|
383
|
+
*
|
|
384
|
+
* @throws Error when not connected
|
|
385
|
+
*/
|
|
386
|
+
private ensureConnected;
|
|
387
|
+
/**
|
|
388
|
+
* Build the standard authorization headers for cloud API requests.
|
|
389
|
+
*
|
|
390
|
+
* @returns Headers object with Authorization and Content-Type
|
|
391
|
+
*/
|
|
392
|
+
private authHeaders;
|
|
393
|
+
/**
|
|
394
|
+
* Check if an HTTP status code indicates an authentication/authorization failure.
|
|
395
|
+
*
|
|
396
|
+
* @param status - HTTP status code
|
|
397
|
+
* @returns true if the status is 401 or 403
|
|
398
|
+
*/
|
|
399
|
+
private isAuthError;
|
|
400
|
+
/**
|
|
401
|
+
* Handle a 401/403 response from the cloud API by transitioning
|
|
402
|
+
* the connection status to TOKEN_EXPIRED. This signals the frontend
|
|
403
|
+
* to show a reconnect prompt instead of a raw error.
|
|
404
|
+
*
|
|
405
|
+
* @param context - Description of the failed operation (for logging)
|
|
406
|
+
* @param status - HTTP status code from the cloud API
|
|
407
|
+
*/
|
|
408
|
+
private handleAuthFailure;
|
|
409
|
+
}
|
|
410
|
+
//# sourceMappingURL=cloud-client.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
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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"}
|