@mycadet/cli 0.12.7 → 0.12.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.
Files changed (179) hide show
  1. package/README.md +2 -2
  2. package/knip.json +1 -1
  3. package/node_modules/@mycadet/assistant-api/events/cloud-disconnected.ts +21 -0
  4. package/node_modules/@mycadet/assistant-api/events/host-bash.ts +1 -1
  5. package/node_modules/@mycadet/assistant-api/events/host-cu.ts +1 -1
  6. package/node_modules/@mycadet/assistant-api/events/host-file.ts +1 -1
  7. package/node_modules/@mycadet/assistant-api/events/notification-intent.ts +1 -1
  8. package/node_modules/@mycadet/assistant-api/events/show-cloud-login.ts +18 -0
  9. package/node_modules/@mycadet/assistant-api/index.ts +11 -11
  10. package/node_modules/@mycadet/assistant-api/node_modules/@mycadet/service-contracts/package.json +2 -2
  11. package/node_modules/@mycadet/{service-contracts/src/platform-credential.ts → assistant-api/node_modules/@mycadet/service-contracts/src/cloud-credential.ts} +9 -9
  12. package/node_modules/@mycadet/assistant-api/node_modules/@mycadet/service-contracts/src/handles.ts +3 -3
  13. package/node_modules/@mycadet/assistant-api/node_modules/@mycadet/service-contracts/src/index.ts +1 -1
  14. package/node_modules/@mycadet/assistant-api/node_modules/@mycadet/service-contracts/src/ingress.ts +11 -5
  15. package/node_modules/@mycadet/assistant-api/node_modules/@mycadet/service-contracts/src/remote-web-pairing.ts +1 -1
  16. package/node_modules/@mycadet/assistant-api/node_modules/@mycadet/service-contracts/src/rpc.ts +14 -14
  17. package/node_modules/@mycadet/assistant-api/node_modules/@mycadet/service-contracts/src/trust-rules.ts +5 -5
  18. package/node_modules/@mycadet/assistant-api/responses/home.ts +1 -1
  19. package/node_modules/@mycadet/assistant-api/surfaces.ts +4 -4
  20. package/node_modules/@mycadet/avatar-manifest/src/__tests__/notification-avatar.test.ts +1 -1
  21. package/node_modules/@mycadet/avatar-manifest/src/notification-avatar.ts +2 -2
  22. package/node_modules/@mycadet/environments/src/seeds.ts +6 -6
  23. package/node_modules/@mycadet/environments/src/shell.test.ts +1 -1
  24. package/node_modules/@mycadet/environments/src/types.ts +6 -6
  25. package/node_modules/@mycadet/local-mode/node_modules/@mycadet/avatar-manifest/src/__tests__/notification-avatar.test.ts +1 -1
  26. package/node_modules/@mycadet/local-mode/node_modules/@mycadet/avatar-manifest/src/notification-avatar.ts +2 -2
  27. package/node_modules/@mycadet/local-mode/node_modules/@mycadet/environments/src/seeds.ts +6 -6
  28. package/node_modules/@mycadet/local-mode/node_modules/@mycadet/environments/src/shell.test.ts +1 -1
  29. package/node_modules/@mycadet/local-mode/node_modules/@mycadet/environments/src/types.ts +6 -6
  30. package/node_modules/@mycadet/local-mode/node_modules/@mycadet/service-contracts/package.json +2 -2
  31. package/node_modules/@mycadet/{assistant-api/node_modules/@mycadet/service-contracts/src/platform-credential.ts → local-mode/node_modules/@mycadet/service-contracts/src/cloud-credential.ts} +9 -9
  32. package/node_modules/@mycadet/local-mode/node_modules/@mycadet/service-contracts/src/handles.ts +3 -3
  33. package/node_modules/@mycadet/local-mode/node_modules/@mycadet/service-contracts/src/index.ts +1 -1
  34. package/node_modules/@mycadet/local-mode/node_modules/@mycadet/service-contracts/src/ingress.ts +11 -5
  35. package/node_modules/@mycadet/local-mode/node_modules/@mycadet/service-contracts/src/remote-web-pairing.ts +1 -1
  36. package/node_modules/@mycadet/local-mode/node_modules/@mycadet/service-contracts/src/rpc.ts +14 -14
  37. package/node_modules/@mycadet/local-mode/node_modules/@mycadet/service-contracts/src/trust-rules.ts +5 -5
  38. package/node_modules/@mycadet/local-mode/src/__tests__/pair.test.ts +5 -5
  39. package/node_modules/@mycadet/local-mode/src/__tests__/retire.test.ts +1 -1
  40. package/node_modules/@mycadet/local-mode/src/config.ts +2 -2
  41. package/node_modules/@mycadet/local-mode/src/index.ts +1 -1
  42. package/node_modules/@mycadet/local-mode/src/lockfile-contract.test.ts +3 -3
  43. package/node_modules/@mycadet/local-mode/src/lockfile-contract.ts +10 -5
  44. package/node_modules/@mycadet/local-mode/src/lockfile.test.ts +15 -15
  45. package/node_modules/@mycadet/local-mode/src/lockfile.ts +9 -9
  46. package/node_modules/@mycadet/local-mode/src/pair.ts +2 -2
  47. package/node_modules/@mycadet/local-mode/src/retire.ts +3 -3
  48. package/node_modules/@mycadet/local-mode/src/teleport-backup-policy.ts +2 -2
  49. package/node_modules/@mycadet/local-mode/src/unpair.ts +2 -2
  50. package/node_modules/@mycadet/service-contracts/package.json +2 -2
  51. package/node_modules/@mycadet/{local-mode/node_modules/@mycadet/service-contracts/src/platform-credential.ts → service-contracts/src/cloud-credential.ts} +9 -9
  52. package/node_modules/@mycadet/service-contracts/src/handles.ts +3 -3
  53. package/node_modules/@mycadet/service-contracts/src/index.ts +1 -1
  54. package/node_modules/@mycadet/service-contracts/src/ingress.ts +11 -5
  55. package/node_modules/@mycadet/service-contracts/src/remote-web-pairing.ts +1 -1
  56. package/node_modules/@mycadet/service-contracts/src/rpc.ts +14 -14
  57. package/node_modules/@mycadet/service-contracts/src/trust-rules.ts +5 -5
  58. package/package.json +3 -2
  59. package/src/__tests__/assistant-api-key-resolution.test.ts +6 -6
  60. package/src/__tests__/{assistant-client-platform-auth.test.ts → assistant-client-cloud-auth.test.ts} +10 -10
  61. package/src/__tests__/assistant-client-refresh.test.ts +2 -2
  62. package/src/__tests__/backup.test.ts +86 -91
  63. package/src/__tests__/client-token.test.ts +1 -1
  64. package/src/__tests__/client-tui-refresh.test.ts +1 -1
  65. package/src/__tests__/client-web-config.test.ts +2 -2
  66. package/src/__tests__/{platform-client.test.ts → cloud-client.test.ts} +59 -59
  67. package/src/__tests__/{platform-releases.test.ts → cloud-releases.test.ts} +28 -18
  68. package/src/__tests__/{cloudflare-tunnel.test.ts → cloudflare.test.ts} +1 -1
  69. package/src/__tests__/connect-import.test.ts +55 -39
  70. package/src/__tests__/debug.test.ts +38 -38
  71. package/src/__tests__/ensure-binary.test.ts +182 -0
  72. package/src/__tests__/guardian-token.test.ts +149 -56
  73. package/src/__tests__/hatch-provider-secrets.test.ts +2 -2
  74. package/src/__tests__/helpers/guardian-token.ts +22 -0
  75. package/src/__tests__/helpers/http.ts +10 -0
  76. package/src/__tests__/nginx-ingress.test.ts +21 -20
  77. package/src/__tests__/ngrok-spawn.test.ts +49 -0
  78. package/src/__tests__/orphan-detection.test.ts +1 -1
  79. package/src/__tests__/pair.test.ts +1 -8
  80. package/src/__tests__/{ps-platform-status.test.ts → ps-cloud-status.test.ts} +79 -26
  81. package/src/__tests__/ps-table.test.ts +79 -0
  82. package/src/__tests__/{recover.test.ts → restore.test.ts} +29 -28
  83. package/src/__tests__/retire.test.ts +58 -199
  84. package/src/__tests__/root-process-lockfile.test.ts +99 -0
  85. package/src/__tests__/sleep.test.ts +19 -19
  86. package/src/__tests__/statefulset.test.ts +8 -8
  87. package/src/__tests__/{tailscale-tunnel.test.ts → tailscale.test.ts} +2 -2
  88. package/src/__tests__/teleport-backup.test.ts +3 -3
  89. package/src/__tests__/teleport.test.ts +181 -197
  90. package/src/__tests__/tunnel.test.ts +257 -222
  91. package/src/__tests__/uninstall.test.ts +13 -4
  92. package/src/__tests__/upgrade-local.test.ts +3 -3
  93. package/src/__tests__/upgrade-replay-env.test.ts +12 -12
  94. package/src/__tests__/wake.test.ts +260 -43
  95. package/src/__tests__/workos-pkce.test.ts +2 -2
  96. package/src/commands/backup.ts +24 -24
  97. package/src/commands/client.ts +76 -76
  98. package/src/commands/completions.test.ts +104 -0
  99. package/src/commands/completions.ts +87 -0
  100. package/src/commands/debug.ts +20 -20
  101. package/src/commands/exec.ts +12 -12
  102. package/src/commands/flags.ts +2 -2
  103. package/src/commands/hatch.ts +23 -23
  104. package/src/commands/login.ts +22 -22
  105. package/src/commands/logs.ts +8 -8
  106. package/src/commands/ps.ts +244 -86
  107. package/src/commands/restart.ts +30 -0
  108. package/src/commands/restore.ts +140 -22
  109. package/src/commands/retire.ts +48 -150
  110. package/src/commands/rollback.ts +20 -26
  111. package/src/commands/setup.ts +2 -2
  112. package/src/commands/sleep.ts +2 -2
  113. package/src/commands/teleport.ts +109 -109
  114. package/src/commands/terminal.ts +158 -18
  115. package/src/commands/tunnel.ts +138 -157
  116. package/src/commands/uninstall.ts +57 -9
  117. package/src/commands/unpair.ts +3 -3
  118. package/src/commands/upgrade.ts +30 -54
  119. package/src/commands/use.ts +1 -1
  120. package/src/commands/wake.ts +166 -50
  121. package/src/index.ts +18 -9
  122. package/src/lib/__tests__/{platform-client-signed-url.test.ts → cloud-client-signed-url.test.ts} +16 -16
  123. package/src/lib/__tests__/docker.test.ts +168 -20
  124. package/src/lib/__tests__/job-polling.test.ts +2 -2
  125. package/src/lib/__tests__/local-runtime-client.test.ts +4 -4
  126. package/src/lib/__tests__/runtime-url.test.ts +1 -1
  127. package/src/lib/assistant-api-key-resolution.ts +5 -5
  128. package/src/lib/assistant-client.ts +8 -8
  129. package/src/lib/assistant-config.ts +58 -12
  130. package/src/lib/{platform-client.ts → cloud-client.ts} +107 -98
  131. package/src/lib/cloud-login.ts +24 -24
  132. package/src/lib/{platform-releases.ts → cloud-releases.ts} +11 -9
  133. package/src/lib/cloud-values.ts +3 -0
  134. package/src/lib/config-utils.ts +1 -1
  135. package/src/lib/detached-process.ts +1 -1
  136. package/src/lib/docker.ts +260 -53
  137. package/src/lib/ensure-binary.ts +171 -0
  138. package/src/lib/environments/__tests__/paths.test.ts +2 -2
  139. package/src/lib/environments/__tests__/resolve.test.ts +26 -26
  140. package/src/lib/environments/resolve.ts +8 -8
  141. package/src/lib/flag-args.test.ts +1 -1
  142. package/src/lib/flag-args.ts +1 -1
  143. package/src/lib/guardian-token.ts +37 -5
  144. package/src/lib/hatch-local.ts +19 -23
  145. package/src/lib/health-check.ts +6 -6
  146. package/src/lib/ingress-config.ts +8 -35
  147. package/src/lib/job-polling.ts +2 -2
  148. package/src/lib/live-voice/connection.ts +12 -12
  149. package/src/lib/live-voice/tunnel.test.ts +11 -11
  150. package/src/lib/live-voice/tunnel.ts +15 -15
  151. package/src/lib/local-runtime-client.ts +20 -20
  152. package/src/lib/local.ts +10 -31
  153. package/src/lib/nginx-ingress.ts +42 -15
  154. package/src/lib/pair.ts +1 -1
  155. package/src/lib/process.ts +1 -1
  156. package/src/lib/provider-secrets.ts +3 -3
  157. package/src/lib/retire-apple-container.ts +1 -1
  158. package/src/lib/runtime-url.ts +8 -8
  159. package/src/lib/statefulset.ts +2 -2
  160. package/src/lib/sync-cloud-assistants.ts +19 -19
  161. package/src/lib/teleport-backup.ts +4 -4
  162. package/src/lib/terminal-client.ts +17 -17
  163. package/src/lib/terminal-session.ts +24 -24
  164. package/src/lib/{tunnel-edge.ts → tunnel.ts} +199 -11
  165. package/src/lib/tunnels/cadet.ts +29 -0
  166. package/src/lib/{cloudflare-tunnel.ts → tunnels/cloudflare.ts} +36 -15
  167. package/src/lib/tunnels/gateway-notify.ts +61 -0
  168. package/src/lib/{ngrok.ts → tunnels/ngrok.ts} +350 -89
  169. package/src/lib/{tailscale-tunnel.ts → tunnels/tailscale.ts} +53 -9
  170. package/src/lib/upgrade-lifecycle.ts +8 -21
  171. package/src/lib/upgrade-preflight.ts +2 -2
  172. package/src/lib/workos-pkce.ts +5 -5
  173. package/node_modules/@mycadet/assistant-api/events/platform-disconnected.ts +0 -21
  174. package/node_modules/@mycadet/assistant-api/events/show-platform-login.ts +0 -20
  175. package/src/commands/recover.ts +0 -131
  176. package/src/commands/roadmap.ts +0 -459
  177. package/src/commands/ssh.ts +0 -144
  178. package/src/commands/workflows.ts +0 -305
  179. package/src/lib/managed-cloud.ts +0 -3
@@ -5,6 +5,7 @@ import {
5
5
  describe,
6
6
  expect,
7
7
  mock,
8
+ type Mock,
8
9
  spyOn,
9
10
  test,
10
11
  } from "bun:test";
@@ -30,26 +31,26 @@ import * as backupOps from "../lib/backup-ops.js";
30
31
  import * as guardianToken from "../lib/guardian-token.js";
31
32
  import * as localRuntimeClient from "../lib/local-runtime-client.js";
32
33
  import { MigrationInProgressError } from "../lib/local-runtime-client.js";
33
- import * as platformClient from "../lib/platform-client.js";
34
+ import * as cloudClient from "../lib/cloud-client.js";
34
35
 
35
36
  const findAssistantByNameMock = spyOn(
36
37
  assistantConfig,
37
38
  "findAssistantByName",
38
39
  ).mockReturnValue(null);
39
40
 
40
- const readPlatformTokenMock = spyOn(
41
- platformClient,
42
- "readPlatformToken",
41
+ const readCloudTokenMock = spyOn(
42
+ cloudClient,
43
+ "readCloudToken",
43
44
  ).mockReturnValue("platform-token");
44
45
 
45
- const getPlatformUrlMock = spyOn(
46
- platformClient,
47
- "getPlatformUrl",
46
+ const getCloudUrlMock = spyOn(
47
+ cloudClient,
48
+ "getCloudUrl",
48
49
  ).mockReturnValue("https://cloud.mycadet.ai");
49
50
 
50
- const platformRequestSignedUrlMock = spyOn(
51
- platformClient,
52
- "platformRequestSignedUrl",
51
+ const cloudRequestSignedUrlMock = spyOn(
52
+ cloudClient,
53
+ "cloudRequestSignedUrl",
53
54
  ).mockImplementation(async (params) => ({
54
55
  url:
55
56
  params.operation === "upload"
@@ -79,6 +80,7 @@ const localRuntimePollJobStatusMock = spyOn(
79
80
  result: { manifest_sha256: "abc123def456" },
80
81
  });
81
82
 
83
+ /** A complete-but-fake guardian token; the SUT only reads the fields it sets. */
82
84
  // Mode 1 (runtime-direct local backup) uses guardian tokens. Don't exercise
83
85
  // it here, but the spies need to exist so the module under test can import
84
86
  // them without surprises. Saved to variables so afterAll can restore them —
@@ -87,31 +89,25 @@ const localRuntimePollJobStatusMock = spyOn(
87
89
  const loadGuardianTokenSpy = spyOn(
88
90
  guardianToken,
89
91
  "loadGuardianToken",
90
- ).mockReturnValue({
91
- accessToken: "local-token",
92
- accessTokenExpiresAt: new Date(Date.now() + 60_000).toISOString(),
93
- } as unknown as ReturnType<typeof guardianToken.loadGuardianToken>);
92
+ ).mockReturnValue(makeGuardianTokenData({ accessToken: "local-token" }));
94
93
  const leaseGuardianTokenSpy = spyOn(
95
94
  guardianToken,
96
95
  "leaseGuardianToken",
97
- ).mockResolvedValue({
98
- accessToken: "leased-token",
99
- accessTokenExpiresAt: new Date(Date.now() + 60_000).toISOString(),
100
- } as unknown as Awaited<ReturnType<typeof guardianToken.leaseGuardianToken>>);
96
+ ).mockResolvedValue(makeGuardianTokenData({ accessToken: "leased-token" }));
101
97
 
102
98
  const getBackupsDirMock = spyOn(backupOps, "getBackupsDir").mockReturnValue(
103
99
  "/tmp/backups-default",
104
100
  );
105
101
 
106
102
  const mkdirSyncMock = spyOn(fs, "mkdirSync").mockImplementation(
107
- (() => undefined) as never,
103
+ () => undefined,
108
104
  );
109
105
  const writeFileSyncMock = spyOn(fs, "writeFileSync").mockImplementation(
110
106
  () => undefined,
111
107
  );
112
108
 
113
109
  let originalFetch: typeof globalThis.fetch;
114
- let exitMock: ReturnType<typeof mock>;
110
+ let exitMock: Mock<(code?: number | string | undefined) => never>;
115
111
 
116
112
  const CADET_ENTRY = {
117
113
  assistantId: "11111111-2222-3333-4444-555555555555",
@@ -126,19 +122,19 @@ function setArgv(...rest: string[]) {
126
122
 
127
123
  beforeEach(() => {
128
124
  originalFetch = globalThis.fetch;
129
- exitMock = mock((code?: number) => {
125
+ exitMock = mock((code?: number | string | undefined): never => {
130
126
  throw new Error(`process.exit:${code}`);
131
127
  });
132
- process.exit = exitMock as unknown as typeof process.exit;
128
+ process.exit = exitMock;
133
129
 
134
130
  findAssistantByNameMock.mockReset();
135
131
  findAssistantByNameMock.mockReturnValue(null);
136
- readPlatformTokenMock.mockReset();
137
- readPlatformTokenMock.mockReturnValue("platform-token");
138
- getPlatformUrlMock.mockReset();
139
- getPlatformUrlMock.mockReturnValue("https://cloud.mycadet.ai");
140
- platformRequestSignedUrlMock.mockReset();
141
- platformRequestSignedUrlMock.mockImplementation(async (params) => ({
132
+ readCloudTokenMock.mockReset();
133
+ readCloudTokenMock.mockReturnValue("platform-token");
134
+ getCloudUrlMock.mockReset();
135
+ getCloudUrlMock.mockReturnValue("https://cloud.mycadet.ai");
136
+ cloudRequestSignedUrlMock.mockReset();
137
+ cloudRequestSignedUrlMock.mockImplementation(async (params) => ({
142
138
  url:
143
139
  params.operation === "upload"
144
140
  ? "https://storage.googleapis.com/bucket/signed-upload"
@@ -162,17 +158,15 @@ beforeEach(() => {
162
158
  getBackupsDirMock.mockReset();
163
159
  getBackupsDirMock.mockReturnValue("/tmp/backups-default");
164
160
  loadGuardianTokenSpy.mockReset();
165
- loadGuardianTokenSpy.mockReturnValue({
166
- accessToken: "local-token",
167
- accessTokenExpiresAt: new Date(Date.now() + 60_000).toISOString(),
168
- } as unknown as ReturnType<typeof guardianToken.loadGuardianToken>);
161
+ loadGuardianTokenSpy.mockReturnValue(
162
+ makeGuardianTokenData({ accessToken: "local-token" }),
163
+ );
169
164
  leaseGuardianTokenSpy.mockReset();
170
- leaseGuardianTokenSpy.mockResolvedValue({
171
- accessToken: "leased-token",
172
- accessTokenExpiresAt: new Date(Date.now() + 60_000).toISOString(),
173
- } as unknown as Awaited<ReturnType<typeof guardianToken.leaseGuardianToken>>);
165
+ leaseGuardianTokenSpy.mockResolvedValue(
166
+ makeGuardianTokenData({ accessToken: "leased-token" }),
167
+ );
174
168
  mkdirSyncMock.mockReset();
175
- mkdirSyncMock.mockImplementation((() => undefined) as never);
169
+ mkdirSyncMock.mockImplementation(() => undefined);
176
170
  writeFileSyncMock.mockReset();
177
171
  writeFileSyncMock.mockImplementation(() => undefined);
178
172
  });
@@ -185,9 +179,9 @@ afterAll(() => {
185
179
  // Restore module-level spies so they don't bleed into other test files
186
180
  // when bun test runs the whole suite.
187
181
  findAssistantByNameMock.mockRestore();
188
- readPlatformTokenMock.mockRestore();
189
- getPlatformUrlMock.mockRestore();
190
- platformRequestSignedUrlMock.mockRestore();
182
+ readCloudTokenMock.mockRestore();
183
+ getCloudUrlMock.mockRestore();
184
+ cloudRequestSignedUrlMock.mockRestore();
191
185
  localRuntimeExportToGcsMock.mockRestore();
192
186
  localRuntimeIdentityMock.mockRestore();
193
187
  localRuntimePollJobStatusMock.mockRestore();
@@ -200,20 +194,26 @@ afterAll(() => {
200
194
  });
201
195
 
202
196
  import { backup } from "../commands/backup.js";
197
+ import { withPreconnect } from "./helpers/http.js";
198
+ import { makeGuardianTokenData } from "./helpers/guardian-token.js";
203
199
 
204
200
  // ---------------------------------------------------------------------------
205
201
  // Helper: simulated GCS download response
206
202
  // ---------------------------------------------------------------------------
207
- function mockGcsDownload(body: Uint8Array, ok = true, status = 200) {
208
- globalThis.fetch = mock(async () => {
209
- const responseBody: BodyInit = ok
210
- ? new Blob([body as unknown as ArrayBuffer])
211
- : "boom";
203
+ function mockGcsDownload(
204
+ body: Uint8Array<ArrayBuffer>,
205
+ ok = true,
206
+ status = 200,
207
+ ) {
208
+ const gcsFetch = mock(async () => {
209
+ const responseBody: BodyInit = ok ? new Blob([body]) : "boom";
212
210
  return new Response(responseBody, {
213
211
  status,
214
212
  statusText: ok ? "OK" : "Error",
215
213
  });
216
- }) as unknown as typeof globalThis.fetch;
214
+ });
215
+ globalThis.fetch = withPreconnect(gcsFetch);
216
+ return gcsFetch;
217
217
  }
218
218
 
219
219
  describe("cadet backup <local>: guardian bootstrap secret", () => {
@@ -228,11 +228,9 @@ describe("cadet backup <local>: guardian bootstrap secret", () => {
228
228
  loadGuardianTokenSpy.mockReturnValue(null);
229
229
  setArgv("my-local", "--output", "/tmp/local-backup.vbundle");
230
230
 
231
- globalThis.fetch = mock(async () => {
232
- return new Response(new Uint8Array([1, 2, 3]), {
233
- status: 200,
234
- });
235
- }) as unknown as typeof globalThis.fetch;
231
+ globalThis.fetch = withPreconnect(
232
+ async () => new Response(new Uint8Array([1, 2, 3]), { status: 200 }),
233
+ );
236
234
 
237
235
  await backup();
238
236
 
@@ -294,9 +292,9 @@ describe("cadet backup: --export-timeout flag", () => {
294
292
  "/tmp/local-backup.vbundle",
295
293
  );
296
294
 
297
- globalThis.fetch = mock(async () => {
298
- return new Response(new Uint8Array([1, 2, 3]), { status: 200 });
299
- }) as unknown as typeof globalThis.fetch;
295
+ globalThis.fetch = withPreconnect(
296
+ async () => new Response(new Uint8Array([1, 2, 3]), { status: 200 }),
297
+ );
300
298
 
301
299
  await backup();
302
300
 
@@ -307,18 +305,18 @@ describe("cadet backup: --export-timeout flag", () => {
307
305
  });
308
306
  });
309
307
 
310
- describe("cadet backup <platform-managed>: GCS happy path", () => {
308
+ describe("cadet backup <cloud-managed>: GCS happy path", () => {
311
309
  test("requests upload URL → kicks off runtime export → polls → downloads from GCS → writes file", async () => {
312
310
  findAssistantByNameMock.mockReturnValue(CADET_ENTRY);
313
311
  setArgv("my-platform");
314
312
 
315
313
  const bytes = new Uint8Array([1, 2, 3, 4]);
316
- mockGcsDownload(bytes);
314
+ const gcsFetch = mockGcsDownload(bytes);
317
315
 
318
316
  await backup();
319
317
 
320
- // Upload-URL request to the platform.
321
- expect(platformRequestSignedUrlMock).toHaveBeenCalledWith(
318
+ // Upload-URL request to the cloud.
319
+ expect(cloudRequestSignedUrlMock).toHaveBeenCalledWith(
322
320
  expect.objectContaining({
323
321
  operation: "upload",
324
322
  minRuntimeVersion: "0.6.5",
@@ -357,7 +355,7 @@ describe("cadet backup <platform-managed>: GCS happy path", () => {
357
355
  // bundle to disk for offline storage; there is no target runtime to
358
356
  // gate against, and an older CLI must be able to download newer
359
357
  // assistant backups.
360
- expect(platformRequestSignedUrlMock).toHaveBeenCalledWith(
358
+ expect(cloudRequestSignedUrlMock).toHaveBeenCalledWith(
361
359
  expect.objectContaining({
362
360
  operation: "download",
363
361
  bundleKey: "uploads/org-1/bundle-abc.vbundle",
@@ -365,14 +363,13 @@ describe("cadet backup <platform-managed>: GCS happy path", () => {
365
363
  "platform-token",
366
364
  "https://cloud.mycadet.ai",
367
365
  );
368
- const downloadCall = platformRequestSignedUrlMock.mock.calls.find(
369
- (c) => (c[0] as { operation: string }).operation === "download",
366
+ const downloadCall = cloudRequestSignedUrlMock.mock.calls.find(
367
+ (c) => c[0].operation === "download",
370
368
  );
371
369
  expect(downloadCall).toBeDefined();
372
370
  expect(downloadCall![0]).not.toHaveProperty("targetRuntimeVersion");
373
371
 
374
372
  // GCS fetch went directly to the signed download URL with no auth.
375
- const gcsFetch = globalThis.fetch as unknown as ReturnType<typeof mock>;
376
373
  expect(gcsFetch).toHaveBeenCalledWith(
377
374
  "https://storage.googleapis.com/bucket/signed-download",
378
375
  );
@@ -382,7 +379,7 @@ describe("cadet backup <platform-managed>: GCS happy path", () => {
382
379
  const [outputPath, written] = writeFileSyncMock.mock.calls[0]!;
383
380
  expect(written).toEqual(bytes);
384
381
  expect(typeof outputPath).toBe("string");
385
- expect(outputPath as string).toMatch(
382
+ expect(outputPath).toMatch(
386
383
  /\/tmp\/backups-default\/my-platform-.*\.vbundle$/,
387
384
  );
388
385
  expect(mkdirSyncMock).toHaveBeenCalled();
@@ -411,22 +408,20 @@ describe("cadet backup <platform-managed>: GCS happy path", () => {
411
408
  await backup();
412
409
 
413
410
  const [outputPath] = writeFileSyncMock.mock.calls[0]!;
414
- expect(outputPath as string).toMatch(
415
- /^\/tmp\/backups-default\/my-platform-/,
416
- );
417
- expect(outputPath as string).toMatch(/\.vbundle$/);
411
+ expect(outputPath).toMatch(/^\/tmp\/backups-default\/my-platform-/);
412
+ expect(outputPath).toMatch(/\.vbundle$/);
418
413
  });
419
414
 
420
- test("signed-URL requests target entry.runtimeUrl, not getPlatformUrl() — regression for staging/dev assistants", async () => {
415
+ test("signed-URL requests target entry.runtimeUrl, not getCloudUrl() — regression for staging/dev assistants", async () => {
421
416
  // Assistant lives on a non-default platform instance (e.g. staging).
422
- // `getPlatformUrl()` still returns the default — picking it up for
417
+ // `getCloudUrl()` still returns the default — picking it up for
423
418
  // signed URLs would target the wrong GCS bucket.
424
419
  const stagingEntry = {
425
420
  ...CADET_ENTRY,
426
421
  runtimeUrl: "https://staging-cloud.mycadet.ai",
427
422
  };
428
423
  findAssistantByNameMock.mockReturnValue(stagingEntry);
429
- getPlatformUrlMock.mockReturnValue("https://cloud.mycadet.ai");
424
+ getCloudUrlMock.mockReturnValue("https://cloud.mycadet.ai");
430
425
  setArgv("my-platform");
431
426
 
432
427
  mockGcsDownload(new Uint8Array([9]));
@@ -434,9 +429,9 @@ describe("cadet backup <platform-managed>: GCS happy path", () => {
434
429
  await backup();
435
430
 
436
431
  // Both upload and download URL requests are pinned to the entry's
437
- // runtimeUrl. The signed URLs returned by the platform target the
432
+ // runtimeUrl. The signed URLs returned by the cloud target the
438
433
  // GCS bucket the runtime can reach, not the default platform's.
439
- expect(platformRequestSignedUrlMock).toHaveBeenCalledWith(
434
+ expect(cloudRequestSignedUrlMock).toHaveBeenCalledWith(
440
435
  expect.objectContaining({
441
436
  operation: "upload",
442
437
  minRuntimeVersion: "0.6.5",
@@ -445,13 +440,13 @@ describe("cadet backup <platform-managed>: GCS happy path", () => {
445
440
  "platform-token",
446
441
  "https://staging-cloud.mycadet.ai",
447
442
  );
448
- expect(platformRequestSignedUrlMock).toHaveBeenCalledWith(
443
+ expect(cloudRequestSignedUrlMock).toHaveBeenCalledWith(
449
444
  expect.objectContaining({ operation: "download" }),
450
445
  "platform-token",
451
446
  "https://staging-cloud.mycadet.ai",
452
447
  );
453
448
  // No call should have used the default platform URL.
454
- const calls = platformRequestSignedUrlMock.mock.calls;
449
+ const calls = cloudRequestSignedUrlMock.mock.calls;
455
450
  for (const call of calls) {
456
451
  expect(call[2]).toBe("https://staging-cloud.mycadet.ai");
457
452
  }
@@ -471,20 +466,20 @@ describe("cadet backup <platform-managed>: GCS happy path", () => {
471
466
  status: "complete",
472
467
  result: {},
473
468
  }));
474
- // Make readPlatformToken return a fresh value on the second call,
469
+ // Make readCloudToken return a fresh value on the second call,
475
470
  // mimicking the "user re-ran `cadet login` in another terminal"
476
471
  // scenario. The helper's pollJobUntilDone calls refreshOn401 only
477
472
  // when its own request 401s — for the test we drive the refresh
478
473
  // directly by overriding the mock to surface a fresh token at the
479
474
  // download-step boundary.
480
- readPlatformTokenMock.mockReset();
481
- readPlatformTokenMock.mockReturnValueOnce("platform-token-old");
482
- readPlatformTokenMock.mockReturnValue("platform-token-new");
475
+ readCloudTokenMock.mockReset();
476
+ readCloudTokenMock.mockReturnValueOnce("platform-token-old");
477
+ readCloudTokenMock.mockReturnValue("platform-token-new");
483
478
 
484
479
  // Hook into pollJobUntilDone via overriding poll to intercept the
485
480
  // refresh call. Easier: just verify the second-arg token to the
486
481
  // download signed-URL request equals the one we'll inject by
487
- // letting backup re-read the platform token mid-flight. The current
482
+ // letting backup re-read the cloud token mid-flight. The current
488
483
  // implementation only re-reads inside pollJobUntilDone's
489
484
  // `refreshOn401`, so we simulate a refresh by overriding poll to
490
485
  // throw-and-recover. Instead we directly assert the regression
@@ -499,13 +494,13 @@ describe("cadet backup <platform-managed>: GCS happy path", () => {
499
494
  // All four token-bearing platform calls (upload signed-URL, runtime
500
495
  // export-to-gcs kickoff, poll, download signed-URL) must use the
501
496
  // same token string. If the download step fell back to the captured
502
- // `platformToken` parameter instead of `exportPlatformToken`, a
497
+ // `cloudToken` parameter instead of `exportPlatformToken`, a
503
498
  // future poll-loop refresh would silently break this invariant.
504
- const uploadCallToken = platformRequestSignedUrlMock.mock.calls.find(
505
- (c) => (c[0] as { operation: string }).operation === "upload",
499
+ const uploadCallToken = cloudRequestSignedUrlMock.mock.calls.find(
500
+ (c) => c[0].operation === "upload",
506
501
  )![1];
507
- const downloadCallToken = platformRequestSignedUrlMock.mock.calls.find(
508
- (c) => (c[0] as { operation: string }).operation === "download",
502
+ const downloadCallToken = cloudRequestSignedUrlMock.mock.calls.find(
503
+ (c) => c[0].operation === "download",
509
504
  )![1];
510
505
  expect(downloadCallToken).toBe(uploadCallToken);
511
506
  const kickoffToken = localRuntimeExportToGcsMock.mock.calls[0]![1];
@@ -515,10 +510,10 @@ describe("cadet backup <platform-managed>: GCS happy path", () => {
515
510
  });
516
511
  });
517
512
 
518
- describe("cadet backup <platform-managed>: failure cases", () => {
513
+ describe("cadet backup <cloud-managed>: failure cases", () => {
519
514
  test("not logged in (no platform token) exits with 'Run cadet login'", async () => {
520
515
  findAssistantByNameMock.mockReturnValue(CADET_ENTRY);
521
- readPlatformTokenMock.mockReturnValue(null);
516
+ readCloudTokenMock.mockReturnValue(null);
522
517
  setArgv("my-platform");
523
518
 
524
519
  const consoleErrorSpy = spyOn(console, "error").mockImplementation(
@@ -611,7 +606,7 @@ describe("cadet backup <platform-managed>: failure cases", () => {
611
606
 
612
607
  // NOTE: The `VersionMismatchError handling` describe block was removed when
613
608
  // backup stopped sending `targetRuntimeVersion` on the download signed-URL
614
- // request — without that field the platform doesn't run the version gate,
609
+ // request — without that field the cloud doesn't run the version gate,
615
610
  // so 422 `version_mismatch` is no longer reachable from this code path.
616
611
 
617
612
  // ---------------------------------------------------------------------------
@@ -628,7 +623,7 @@ describe("upload signed-URL records source runtime version (not CLI version)", (
628
623
  callOrder.push("identity");
629
624
  return { version: "0.5.9" };
630
625
  });
631
- platformRequestSignedUrlMock.mockImplementationOnce(async (params) => {
626
+ cloudRequestSignedUrlMock.mockImplementationOnce(async (params) => {
632
627
  callOrder.push("signed-url");
633
628
  return {
634
629
  url: "https://storage.googleapis.com/bucket/signed-upload",
@@ -644,7 +639,7 @@ describe("upload signed-URL records source runtime version (not CLI version)", (
644
639
  expect(callOrder[0]).toBe("identity");
645
640
  expect(callOrder[1]).toBe("signed-url");
646
641
 
647
- expect(platformRequestSignedUrlMock).toHaveBeenCalledWith(
642
+ expect(cloudRequestSignedUrlMock).toHaveBeenCalledWith(
648
643
  expect.objectContaining({
649
644
  operation: "upload",
650
645
  minRuntimeVersion: "0.5.9",
@@ -655,7 +650,7 @@ describe("upload signed-URL records source runtime version (not CLI version)", (
655
650
  );
656
651
  });
657
652
 
658
- test("identity is fetched against the platform-managed runtime entry with the platform token", async () => {
653
+ test("identity is fetched against the cloud-managed runtime entry with the cloud token", async () => {
659
654
  findAssistantByNameMock.mockReturnValue(CADET_ENTRY);
660
655
  setArgv("my-platform");
661
656
 
@@ -688,7 +683,7 @@ describe("upload signed-URL records source runtime version (not CLI version)", (
688
683
  await expect(backup()).rejects.toThrow("process.exit:1");
689
684
 
690
685
  // Signed-URL must NOT have been requested.
691
- expect(platformRequestSignedUrlMock).not.toHaveBeenCalled();
686
+ expect(cloudRequestSignedUrlMock).not.toHaveBeenCalled();
692
687
  expect(localRuntimeExportToGcsMock).not.toHaveBeenCalled();
693
688
 
694
689
  expect(consoleErrorSpy).toHaveBeenCalledWith(
@@ -90,7 +90,7 @@ describe("client --token (ephemeral)", () => {
90
90
  expect(parsed.runtimeUrl).toBe(REMOTE_URL);
91
91
  expect(parsed.assistantId).toBe("self"); // DAEMON_INTERNAL_ASSISTANT_ID
92
92
  expect(parsed.bearerToken).toBe("test-jwt-token");
93
- expect(parsed.platformToken).toBeUndefined();
93
+ expect(parsed.cloudToken).toBeUndefined();
94
94
  });
95
95
 
96
96
  test("--assistant-id overrides the default 'self' segment", () => {
@@ -166,7 +166,7 @@ describe("resolveFreshBearerToken", () => {
166
166
  expect(refresh.hit()).toBe(false);
167
167
  });
168
168
 
169
- test("never refreshes on the platform session-auth path", async () => {
169
+ test("never refreshes on the cloud session-auth path", async () => {
170
170
  seed({ accessToken: "old-acc", refreshToken: "ref", refreshAfter: past() });
171
171
  const refresh = stubRefresh(true);
172
172
 
@@ -12,8 +12,8 @@ import { buildWebInterfaceConfig } from "../commands/client.js";
12
12
 
13
13
  const BASE = {
14
14
  webUrl: "https://app.example.com",
15
- platformUrl: "https://platform.example.com",
16
- disablePlatform: true,
15
+ cloudUrl: "https://platform.example.com",
16
+ disableCloud: true,
17
17
  };
18
18
 
19
19
  describe("cadet client web __config", () => {