@mycadet/cli 0.12.7 → 0.12.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/knip.json +1 -1
- package/node_modules/@mycadet/assistant-api/events/cloud-disconnected.ts +21 -0
- package/node_modules/@mycadet/assistant-api/events/host-bash.ts +1 -1
- package/node_modules/@mycadet/assistant-api/events/host-cu.ts +1 -1
- package/node_modules/@mycadet/assistant-api/events/host-file.ts +1 -1
- package/node_modules/@mycadet/assistant-api/events/notification-intent.ts +1 -1
- package/node_modules/@mycadet/assistant-api/events/{show-platform-login.ts → show-cloud-login.ts} +3 -5
- package/node_modules/@mycadet/assistant-api/index.ts +11 -11
- package/node_modules/@mycadet/assistant-api/node_modules/@mycadet/service-contracts/package.json +1 -1
- package/node_modules/@mycadet/{service-contracts/src/platform-credential.ts → assistant-api/node_modules/@mycadet/service-contracts/src/cloud-credential.ts} +9 -9
- package/node_modules/@mycadet/assistant-api/node_modules/@mycadet/service-contracts/src/handles.ts +3 -3
- package/node_modules/@mycadet/assistant-api/node_modules/@mycadet/service-contracts/src/index.ts +1 -1
- package/node_modules/@mycadet/assistant-api/node_modules/@mycadet/service-contracts/src/ingress.ts +11 -5
- package/node_modules/@mycadet/assistant-api/node_modules/@mycadet/service-contracts/src/remote-web-pairing.ts +1 -1
- package/node_modules/@mycadet/assistant-api/node_modules/@mycadet/service-contracts/src/rpc.ts +14 -14
- package/node_modules/@mycadet/assistant-api/node_modules/@mycadet/service-contracts/src/trust-rules.ts +5 -5
- package/node_modules/@mycadet/assistant-api/responses/home.ts +1 -1
- package/node_modules/@mycadet/assistant-api/surfaces.ts +4 -4
- package/node_modules/@mycadet/avatar-manifest/src/__tests__/notification-avatar.test.ts +1 -1
- package/node_modules/@mycadet/avatar-manifest/src/notification-avatar.ts +2 -2
- package/node_modules/@mycadet/environments/src/seeds.ts +6 -6
- package/node_modules/@mycadet/environments/src/shell.test.ts +1 -1
- package/node_modules/@mycadet/environments/src/types.ts +6 -6
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/avatar-manifest/src/__tests__/notification-avatar.test.ts +1 -1
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/avatar-manifest/src/notification-avatar.ts +2 -2
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/environments/src/seeds.ts +6 -6
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/environments/src/shell.test.ts +1 -1
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/environments/src/types.ts +6 -6
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/service-contracts/package.json +1 -1
- 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
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/service-contracts/src/handles.ts +3 -3
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/service-contracts/src/index.ts +1 -1
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/service-contracts/src/ingress.ts +11 -5
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/service-contracts/src/remote-web-pairing.ts +1 -1
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/service-contracts/src/rpc.ts +14 -14
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/service-contracts/src/trust-rules.ts +5 -5
- package/node_modules/@mycadet/local-mode/src/__tests__/pair.test.ts +5 -5
- package/node_modules/@mycadet/local-mode/src/__tests__/retire.test.ts +1 -1
- package/node_modules/@mycadet/local-mode/src/config.ts +2 -2
- package/node_modules/@mycadet/local-mode/src/index.ts +1 -1
- package/node_modules/@mycadet/local-mode/src/lockfile-contract.test.ts +3 -3
- package/node_modules/@mycadet/local-mode/src/lockfile-contract.ts +10 -5
- package/node_modules/@mycadet/local-mode/src/lockfile.test.ts +15 -15
- package/node_modules/@mycadet/local-mode/src/lockfile.ts +9 -9
- package/node_modules/@mycadet/local-mode/src/pair.ts +2 -2
- package/node_modules/@mycadet/local-mode/src/retire.ts +3 -3
- package/node_modules/@mycadet/local-mode/src/teleport-backup-policy.ts +2 -2
- package/node_modules/@mycadet/local-mode/src/unpair.ts +2 -2
- package/node_modules/@mycadet/service-contracts/package.json +1 -1
- package/node_modules/@mycadet/{local-mode/node_modules/@mycadet/service-contracts/src/platform-credential.ts → service-contracts/src/cloud-credential.ts} +9 -9
- package/node_modules/@mycadet/service-contracts/src/handles.ts +3 -3
- package/node_modules/@mycadet/service-contracts/src/index.ts +1 -1
- package/node_modules/@mycadet/service-contracts/src/ingress.ts +11 -5
- package/node_modules/@mycadet/service-contracts/src/remote-web-pairing.ts +1 -1
- package/node_modules/@mycadet/service-contracts/src/rpc.ts +14 -14
- package/node_modules/@mycadet/service-contracts/src/trust-rules.ts +5 -5
- package/package.json +3 -2
- package/src/__tests__/assistant-api-key-resolution.test.ts +6 -6
- package/src/__tests__/{assistant-client-platform-auth.test.ts → assistant-client-cloud-auth.test.ts} +10 -10
- package/src/__tests__/assistant-client-refresh.test.ts +2 -2
- package/src/__tests__/backup.test.ts +86 -91
- package/src/__tests__/client-token.test.ts +1 -1
- package/src/__tests__/client-tui-refresh.test.ts +1 -1
- package/src/__tests__/client-web-config.test.ts +2 -2
- package/src/__tests__/{platform-client.test.ts → cloud-client.test.ts} +59 -59
- package/src/__tests__/{platform-releases.test.ts → cloud-releases.test.ts} +5 -5
- package/src/__tests__/{cloudflare-tunnel.test.ts → cloudflare.test.ts} +1 -1
- package/src/__tests__/connect-import.test.ts +55 -39
- package/src/__tests__/debug.test.ts +38 -38
- package/src/__tests__/guardian-token.test.ts +149 -56
- package/src/__tests__/hatch-provider-secrets.test.ts +2 -2
- package/src/__tests__/helpers/guardian-token.ts +22 -0
- package/src/__tests__/helpers/http.ts +10 -0
- package/src/__tests__/nginx-ingress.test.ts +18 -18
- package/src/__tests__/orphan-detection.test.ts +1 -1
- package/src/__tests__/pair.test.ts +1 -8
- package/src/__tests__/{ps-platform-status.test.ts → ps-cloud-status.test.ts} +79 -26
- package/src/__tests__/{recover.test.ts → restore.test.ts} +29 -28
- package/src/__tests__/retire.test.ts +58 -199
- package/src/__tests__/root-process-lockfile.test.ts +99 -0
- package/src/__tests__/sleep.test.ts +19 -19
- package/src/__tests__/statefulset.test.ts +8 -8
- package/src/__tests__/{tailscale-tunnel.test.ts → tailscale.test.ts} +1 -1
- package/src/__tests__/teleport-backup.test.ts +3 -3
- package/src/__tests__/teleport.test.ts +180 -196
- package/src/__tests__/tunnel.test.ts +255 -227
- package/src/__tests__/uninstall.test.ts +13 -4
- package/src/__tests__/upgrade-local.test.ts +3 -3
- package/src/__tests__/upgrade-replay-env.test.ts +12 -12
- package/src/__tests__/wake.test.ts +258 -41
- package/src/__tests__/workos-pkce.test.ts +2 -2
- package/src/commands/backup.ts +22 -22
- package/src/commands/client.ts +76 -76
- package/src/commands/debug.ts +20 -20
- package/src/commands/exec.ts +5 -5
- package/src/commands/hatch.ts +22 -22
- package/src/commands/login.ts +22 -22
- package/src/commands/logs.ts +1 -1
- package/src/commands/ps.ts +188 -79
- package/src/commands/restart.ts +30 -0
- package/src/commands/restore.ts +138 -20
- package/src/commands/retire.ts +46 -148
- package/src/commands/rollback.ts +18 -24
- package/src/commands/setup.ts +2 -2
- package/src/commands/teleport.ts +93 -93
- package/src/commands/terminal.ts +157 -17
- package/src/commands/tunnel.ts +80 -122
- package/src/commands/uninstall.ts +55 -7
- package/src/commands/unpair.ts +3 -3
- package/src/commands/upgrade.ts +22 -46
- package/src/commands/wake.ts +162 -46
- package/src/index.ts +3 -9
- package/src/lib/__tests__/{platform-client-signed-url.test.ts → cloud-client-signed-url.test.ts} +16 -16
- package/src/lib/__tests__/job-polling.test.ts +1 -1
- package/src/lib/__tests__/local-runtime-client.test.ts +4 -4
- package/src/lib/__tests__/runtime-url.test.ts +1 -1
- package/src/lib/assistant-api-key-resolution.ts +5 -5
- package/src/lib/assistant-client.ts +8 -8
- package/src/lib/assistant-config.ts +58 -12
- package/src/lib/{platform-client.ts → cloud-client.ts} +107 -98
- package/src/lib/cloud-login.ts +24 -24
- package/src/lib/{platform-releases.ts → cloud-releases.ts} +5 -5
- package/src/lib/cloud-values.ts +3 -0
- package/src/lib/config-utils.ts +1 -1
- package/src/lib/detached-process.ts +1 -1
- package/src/lib/docker.ts +111 -10
- package/src/lib/environments/__tests__/paths.test.ts +2 -2
- package/src/lib/environments/__tests__/resolve.test.ts +26 -26
- package/src/lib/environments/resolve.ts +8 -8
- package/src/lib/guardian-token.ts +36 -4
- package/src/lib/hatch-local.ts +19 -23
- package/src/lib/health-check.ts +6 -6
- package/src/lib/ingress-config.ts +8 -35
- package/src/lib/job-polling.ts +1 -1
- package/src/lib/live-voice/connection.ts +12 -12
- package/src/lib/live-voice/tunnel.test.ts +11 -11
- package/src/lib/live-voice/tunnel.ts +15 -15
- package/src/lib/local-runtime-client.ts +20 -20
- package/src/lib/local.ts +9 -30
- package/src/lib/nginx-ingress.ts +41 -14
- package/src/lib/process.ts +1 -1
- package/src/lib/provider-secrets.ts +3 -3
- package/src/lib/retire-apple-container.ts +1 -1
- package/src/lib/runtime-url.ts +8 -8
- package/src/lib/statefulset.ts +2 -2
- package/src/lib/sync-cloud-assistants.ts +18 -18
- package/src/lib/teleport-backup.ts +4 -4
- package/src/lib/terminal-client.ts +17 -17
- package/src/lib/terminal-session.ts +24 -24
- package/src/lib/{tunnel-edge.ts → tunnel.ts} +199 -11
- package/src/lib/tunnels/cadet.ts +29 -0
- package/src/lib/{cloudflare-tunnel.ts → tunnels/cloudflare.ts} +15 -4
- package/src/lib/tunnels/gateway-notify.ts +61 -0
- package/src/lib/{ngrok.ts → tunnels/ngrok.ts} +201 -30
- package/src/lib/{tailscale-tunnel.ts → tunnels/tailscale.ts} +19 -5
- package/src/lib/upgrade-lifecycle.ts +3 -17
- package/src/lib/upgrade-preflight.ts +2 -2
- package/src/lib/workos-pkce.ts +5 -5
- package/node_modules/@mycadet/assistant-api/events/platform-disconnected.ts +0 -21
- package/src/commands/recover.ts +0 -131
- package/src/commands/roadmap.ts +0 -459
- package/src/commands/ssh.ts +0 -144
- package/src/commands/workflows.ts +0 -305
- package/src/lib/managed-cloud.ts +0 -3
package/src/lib/__tests__/{platform-client-signed-url.test.ts → cloud-client-signed-url.test.ts}
RENAMED
|
@@ -2,10 +2,10 @@ import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
|
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
platformPollJobStatus,
|
|
5
|
-
|
|
5
|
+
cloudRequestSignedUrl,
|
|
6
6
|
VersionMismatchError,
|
|
7
7
|
type UnifiedJobStatus,
|
|
8
|
-
} from "../
|
|
8
|
+
} from "../cloud-client.js";
|
|
9
9
|
|
|
10
10
|
const PLATFORM_URL = "https://platform.example.test";
|
|
11
11
|
const VAK_TOKEN = "vak_test_1234567890"; // API-key path skips org-ID fetch.
|
|
@@ -69,7 +69,7 @@ afterEach(() => {
|
|
|
69
69
|
globalThis.fetch = originalFetch;
|
|
70
70
|
});
|
|
71
71
|
|
|
72
|
-
describe("
|
|
72
|
+
describe("cloudRequestSignedUrl", () => {
|
|
73
73
|
test("upload operation with just operation → posts correct body and parses response", async () => {
|
|
74
74
|
const { calls, fetchMock } = captureFetch(() => {
|
|
75
75
|
return new Response(
|
|
@@ -83,7 +83,7 @@ describe("platformRequestSignedUrl", () => {
|
|
|
83
83
|
});
|
|
84
84
|
globalThis.fetch = fetchMock;
|
|
85
85
|
|
|
86
|
-
const result = await
|
|
86
|
+
const result = await cloudRequestSignedUrl(
|
|
87
87
|
{ operation: "upload" },
|
|
88
88
|
VAK_TOKEN,
|
|
89
89
|
PLATFORM_URL,
|
|
@@ -117,7 +117,7 @@ describe("platformRequestSignedUrl", () => {
|
|
|
117
117
|
});
|
|
118
118
|
globalThis.fetch = fetchMock;
|
|
119
119
|
|
|
120
|
-
const result = await
|
|
120
|
+
const result = await cloudRequestSignedUrl(
|
|
121
121
|
{
|
|
122
122
|
operation: "upload",
|
|
123
123
|
contentType: "application/octet-stream",
|
|
@@ -148,7 +148,7 @@ describe("platformRequestSignedUrl", () => {
|
|
|
148
148
|
});
|
|
149
149
|
globalThis.fetch = fetchMock;
|
|
150
150
|
|
|
151
|
-
const result = await
|
|
151
|
+
const result = await cloudRequestSignedUrl(
|
|
152
152
|
{ operation: "download", bundleKey: "bundles/xyz.tar.gz" },
|
|
153
153
|
VAK_TOKEN,
|
|
154
154
|
PLATFORM_URL,
|
|
@@ -182,7 +182,7 @@ describe("platformRequestSignedUrl", () => {
|
|
|
182
182
|
});
|
|
183
183
|
globalThis.fetch = fetchMock;
|
|
184
184
|
|
|
185
|
-
const result = await
|
|
185
|
+
const result = await cloudRequestSignedUrl(
|
|
186
186
|
{ operation: "upload" },
|
|
187
187
|
VAK_TOKEN,
|
|
188
188
|
PLATFORM_URL,
|
|
@@ -263,7 +263,7 @@ describe("platformRequestSignedUrl", () => {
|
|
|
263
263
|
);
|
|
264
264
|
globalThis.fetch = fetchMock as unknown as typeof globalThis.fetch;
|
|
265
265
|
|
|
266
|
-
const result = await
|
|
266
|
+
const result = await cloudRequestSignedUrl(
|
|
267
267
|
{ operation: "upload" },
|
|
268
268
|
SESSION_TOKEN,
|
|
269
269
|
PLATFORM_URL,
|
|
@@ -305,7 +305,7 @@ describe("platformRequestSignedUrl", () => {
|
|
|
305
305
|
});
|
|
306
306
|
globalThis.fetch = fetchMock;
|
|
307
307
|
|
|
308
|
-
await
|
|
308
|
+
await cloudRequestSignedUrl(
|
|
309
309
|
{
|
|
310
310
|
operation: "upload",
|
|
311
311
|
minRuntimeVersion: "1.2.3",
|
|
@@ -335,7 +335,7 @@ describe("platformRequestSignedUrl", () => {
|
|
|
335
335
|
});
|
|
336
336
|
globalThis.fetch = fetchMock;
|
|
337
337
|
|
|
338
|
-
await
|
|
338
|
+
await cloudRequestSignedUrl(
|
|
339
339
|
{
|
|
340
340
|
operation: "download",
|
|
341
341
|
bundleKey: "bundles/dl-v.tar.gz",
|
|
@@ -370,7 +370,7 @@ describe("platformRequestSignedUrl", () => {
|
|
|
370
370
|
|
|
371
371
|
let caught: unknown;
|
|
372
372
|
try {
|
|
373
|
-
await
|
|
373
|
+
await cloudRequestSignedUrl(
|
|
374
374
|
{
|
|
375
375
|
operation: "download",
|
|
376
376
|
bundleKey: "bundles/foo.tar.gz",
|
|
@@ -414,7 +414,7 @@ describe("platformRequestSignedUrl", () => {
|
|
|
414
414
|
|
|
415
415
|
let caught: unknown;
|
|
416
416
|
try {
|
|
417
|
-
await
|
|
417
|
+
await cloudRequestSignedUrl(
|
|
418
418
|
{
|
|
419
419
|
operation: "download",
|
|
420
420
|
bundleKey: "bundles/foo.tar.gz",
|
|
@@ -444,7 +444,7 @@ describe("platformRequestSignedUrl", () => {
|
|
|
444
444
|
|
|
445
445
|
let caught: unknown;
|
|
446
446
|
try {
|
|
447
|
-
await
|
|
447
|
+
await cloudRequestSignedUrl(
|
|
448
448
|
{ operation: "download", bundleKey: "bundles/foo.tar.gz" },
|
|
449
449
|
VAK_TOKEN,
|
|
450
450
|
PLATFORM_URL,
|
|
@@ -483,7 +483,7 @@ describe("platformRequestSignedUrl", () => {
|
|
|
483
483
|
|
|
484
484
|
let caught: unknown;
|
|
485
485
|
try {
|
|
486
|
-
await
|
|
486
|
+
await cloudRequestSignedUrl(
|
|
487
487
|
{
|
|
488
488
|
operation: "download",
|
|
489
489
|
bundleKey: "bundles/foo.tar.gz",
|
|
@@ -513,7 +513,7 @@ describe("platformRequestSignedUrl", () => {
|
|
|
513
513
|
});
|
|
514
514
|
globalThis.fetch = fetchMock;
|
|
515
515
|
|
|
516
|
-
const result = await
|
|
516
|
+
const result = await cloudRequestSignedUrl(
|
|
517
517
|
{ operation: "download", bundleKey: "bundles/xyz.tar.gz" },
|
|
518
518
|
VAK_TOKEN,
|
|
519
519
|
PLATFORM_URL,
|
|
@@ -535,7 +535,7 @@ describe("platformRequestSignedUrl", () => {
|
|
|
535
535
|
globalThis.fetch = fetchMock;
|
|
536
536
|
|
|
537
537
|
await expect(
|
|
538
|
-
|
|
538
|
+
cloudRequestSignedUrl(
|
|
539
539
|
{ operation: "upload" },
|
|
540
540
|
VAK_TOKEN,
|
|
541
541
|
PLATFORM_URL,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { afterEach, beforeEach, describe, expect, spyOn, test } from "bun:test";
|
|
2
2
|
|
|
3
3
|
import { pollJobUntilDone } from "../job-polling.js";
|
|
4
|
-
import type { UnifiedJobStatus } from "../
|
|
4
|
+
import type { UnifiedJobStatus } from "../cloud-client.js";
|
|
5
5
|
|
|
6
6
|
describe("pollJobUntilDone", () => {
|
|
7
7
|
test("returns terminal 'complete' after N processing polls", async () => {
|
|
@@ -14,7 +14,7 @@ const TOKEN = "local-bearer-token";
|
|
|
14
14
|
|
|
15
15
|
// All tests in this file exercise the local/docker code path (cloud="local"),
|
|
16
16
|
// which builds `{runtimeUrl}/v1/migrations/<subpath>` URLs and uses
|
|
17
|
-
// guardian-token bearer auth. The
|
|
17
|
+
// guardian-token bearer auth. The cloud path (cloud="cadet") is covered
|
|
18
18
|
// by `runtime-url.test.ts` (URL construction) and the teleport tests
|
|
19
19
|
// (call-site wiring).
|
|
20
20
|
const ENTRY: Pick<AssistantEntry, "cloud" | "runtimeUrl" | "assistantId"> = {
|
|
@@ -384,7 +384,7 @@ describe("localRuntimePollJobStatus", () => {
|
|
|
384
384
|
});
|
|
385
385
|
|
|
386
386
|
// ---------------------------------------------------------------------------
|
|
387
|
-
//
|
|
387
|
+
// Cloud assistants (cloud="cadet") route through the cloud's
|
|
388
388
|
// wildcard runtime proxy at `/v1/assistants/<id>/migrations/...` with
|
|
389
389
|
// platform-token auth (NOT guardian-token bearer). This block asserts the
|
|
390
390
|
// actual URL and headers built by the helpers — not mocked, not abstracted.
|
|
@@ -588,7 +588,7 @@ describe("localRuntimeIdentity", () => {
|
|
|
588
588
|
});
|
|
589
589
|
|
|
590
590
|
// ---------------------------------------------------------------------
|
|
591
|
-
// 401-retry parity with
|
|
591
|
+
// 401-retry parity with cloudRequestSignedUrl (Codex P2 regression
|
|
592
592
|
// guard). localRuntimeIdentity is the first network call in the
|
|
593
593
|
// backup/teleport export flow for cadet-cloud assistants, so a stale
|
|
594
594
|
// Cadet-Organization-Id cache entry would surface as a hard abort
|
|
@@ -613,7 +613,7 @@ describe("localRuntimeIdentity", () => {
|
|
|
613
613
|
orgIdFetchedAs.push(`org-${orgIdFetchedAs.length + 1}`);
|
|
614
614
|
return new Response(
|
|
615
615
|
JSON.stringify({
|
|
616
|
-
results: [{ id: orgIdFetchedAs[orgIdFetchedAs.length - 1]
|
|
616
|
+
results: [{ id: orgIdFetchedAs[orgIdFetchedAs.length - 1]!, name: "My Cadet" }],
|
|
617
617
|
}),
|
|
618
618
|
{ status: 200 },
|
|
619
619
|
);
|
|
@@ -49,7 +49,7 @@ describe("resolveRuntimeMigrationUrl", () => {
|
|
|
49
49
|
);
|
|
50
50
|
});
|
|
51
51
|
|
|
52
|
-
test("cadet (
|
|
52
|
+
test("cadet (cloud-managed) cloud uses wildcard-proxy /v1/assistants/<id>/migrations/<subpath>", () => {
|
|
53
53
|
const entry = makeEntry({
|
|
54
54
|
cloud: "cadet",
|
|
55
55
|
runtimeUrl: "https://cloud.mycadet.ai",
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
import {
|
|
9
9
|
readGatewayCredential,
|
|
10
10
|
reprovisionAssistantApiKey,
|
|
11
|
-
|
|
12
|
-
} from "./
|
|
11
|
+
verifyGatewayCloudCredential,
|
|
12
|
+
} from "./cloud-client.js";
|
|
13
13
|
|
|
14
14
|
/** Where the key came from, so callers can report what they did. */
|
|
15
15
|
export type AssistantApiKeySource =
|
|
@@ -39,13 +39,13 @@ export interface ResolvedAssistantApiKey {
|
|
|
39
39
|
* Three steps, in order: the key the registration just issued, the key the
|
|
40
40
|
* assistant already holds, then a rotation.
|
|
41
41
|
*
|
|
42
|
-
* A stored key the
|
|
42
|
+
* A stored key the cloud has rejected is skipped, because reinjecting it
|
|
43
43
|
* repairs nothing while looking like a repair. The verdict is asked for
|
|
44
44
|
* before the key is read, so the key returned is one the verdict covers: a
|
|
45
45
|
* repair that lands between the two requests is then read, not overwritten
|
|
46
46
|
* by the value it replaced. Rotation is still withheld when the gateway is
|
|
47
47
|
* merely unreachable: rotating without being able to store the replacement
|
|
48
|
-
* would start the
|
|
48
|
+
* would start the cloud's grace clock on a key the assistant still needs,
|
|
49
49
|
* with nothing to hand it in exchange.
|
|
50
50
|
*/
|
|
51
51
|
export async function resolveAssistantApiKeyForInjection(
|
|
@@ -55,7 +55,7 @@ export async function resolveAssistantApiKeyForInjection(
|
|
|
55
55
|
return { apiKey: args.registrationApiKey, source: "registration" };
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
const status = await
|
|
58
|
+
const status = await verifyGatewayCloudCredential(
|
|
59
59
|
args.runtimeUrl,
|
|
60
60
|
args.bearerToken,
|
|
61
61
|
);
|
|
@@ -14,10 +14,10 @@
|
|
|
14
14
|
* The auth scheme follows the assistant's topology, so callers never pick it.
|
|
15
15
|
* Platform-managed entries in particular have no local guardian token: they
|
|
16
16
|
* authenticate against the wildcard runtime proxy at
|
|
17
|
-
* `{
|
|
17
|
+
* `{cloudUrl}/v1/assistants/<id>/<rest>` with the stored cloud credential.
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
import {
|
|
20
|
+
import { isCloudHome } from "./cloud-values.js";
|
|
21
21
|
import { resolveAssistant } from "./assistant-config.js";
|
|
22
22
|
import { GATEWAY_PORT } from "./constants.js";
|
|
23
23
|
import {
|
|
@@ -29,8 +29,8 @@ import { loopbackSafeFetch } from "./loopback-fetch.js";
|
|
|
29
29
|
import {
|
|
30
30
|
authHeaders,
|
|
31
31
|
invalidateOrgIdCache,
|
|
32
|
-
|
|
33
|
-
} from "./
|
|
32
|
+
readCloudToken,
|
|
33
|
+
} from "./cloud-client.js";
|
|
34
34
|
|
|
35
35
|
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
36
36
|
const FALLBACK_RUNTIME_URL = `http://127.0.0.1:${GATEWAY_PORT}`;
|
|
@@ -54,7 +54,7 @@ export interface AssistantClientOpts {
|
|
|
54
54
|
* sent as `X-Session-Token: <sessionToken>` and the org id is
|
|
55
55
|
* sent via the `Cadet-Organization-Id` header.
|
|
56
56
|
*
|
|
57
|
-
*
|
|
57
|
+
* Cloud assistants do NOT need this: they are detected from the
|
|
58
58
|
* lockfile entry and authenticated from the stored platform token.
|
|
59
59
|
*/
|
|
60
60
|
sessionToken?: string;
|
|
@@ -75,7 +75,7 @@ export class AssistantClient {
|
|
|
75
75
|
private readonly _assistantId: string;
|
|
76
76
|
/**
|
|
77
77
|
* The credential for the current mode. Mutable: a 401 on the guardian path
|
|
78
|
-
* refreshes it in place (see request), and the
|
|
78
|
+
* refreshes it in place (see request), and the cloud path fills it in on
|
|
79
79
|
* first use (see resolveAuthHeaders).
|
|
80
80
|
*/
|
|
81
81
|
private token: string | undefined;
|
|
@@ -103,7 +103,7 @@ export class AssistantClient {
|
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
this._assistantId = entry.assistantId;
|
|
106
|
-
const platformManaged = !opts?.sessionToken &&
|
|
106
|
+
const platformManaged = !opts?.sessionToken && isCloudHome(entry.cloud);
|
|
107
107
|
const platformHost = stripTrailingSlashes(entry.runtimeUrl);
|
|
108
108
|
|
|
109
109
|
// SECURITY: a cloud credential is account-scoped, far broader than the
|
|
@@ -155,7 +155,7 @@ export class AssistantClient {
|
|
|
155
155
|
* error rather than letting an anonymous request fall through to a bare 403.
|
|
156
156
|
*/
|
|
157
157
|
private requirePlatformToken(): string {
|
|
158
|
-
const token =
|
|
158
|
+
const token = readCloudToken();
|
|
159
159
|
if (!token) {
|
|
160
160
|
throw new Error(
|
|
161
161
|
"Not logged in. Run `cadet login` first to authenticate with Cadet Cloud.",
|
|
@@ -63,19 +63,11 @@ export type LocalInstanceResources = Omit<
|
|
|
63
63
|
[key: string]: unknown;
|
|
64
64
|
};
|
|
65
65
|
|
|
66
|
-
/** Docker image metadata for the service group. Enables rollback to known-good
|
|
66
|
+
/** Docker image metadata for the service group. Enables rollback to known-good refs. */
|
|
67
67
|
export interface ContainerInfo {
|
|
68
68
|
assistantImage: string;
|
|
69
69
|
gatewayImage: string;
|
|
70
70
|
cesImage: string;
|
|
71
|
-
/** sha256 digest of the assistant image at time of hatch/upgrade */
|
|
72
|
-
assistantDigest?: string;
|
|
73
|
-
/** sha256 digest of the gateway image at time of hatch/upgrade */
|
|
74
|
-
gatewayDigest?: string;
|
|
75
|
-
/** sha256 digest of the CES image at time of hatch/upgrade */
|
|
76
|
-
cesDigest?: string;
|
|
77
|
-
/** Docker network name for the service group */
|
|
78
|
-
networkName?: string;
|
|
79
71
|
/**
|
|
80
72
|
* Host-side port the assistant HTTP API is published on. Dynamically
|
|
81
73
|
* allocated at hatch time so concurrent instances don't collide on the
|
|
@@ -159,10 +151,29 @@ export type AssistantLookupResult =
|
|
|
159
151
|
interface LockfileData {
|
|
160
152
|
assistants?: Record<string, unknown>[];
|
|
161
153
|
activeAssistant?: string;
|
|
162
|
-
|
|
154
|
+
cloudBaseUrl?: string;
|
|
155
|
+
tunnel?: RootProcessRecord;
|
|
156
|
+
app?: RootProcessRecord;
|
|
163
157
|
[key: string]: unknown;
|
|
164
158
|
}
|
|
165
159
|
|
|
160
|
+
/**
|
|
161
|
+
* A CLI-managed OS process recorded at the lockfile root, keyed by what it is
|
|
162
|
+
* for — `tunnel` (the auto-tunnel agent fronting the edge) and `app` (the
|
|
163
|
+
* nginx ingress edge). `cadet ps` renders these alongside the per-assistant
|
|
164
|
+
* process trees, and the stop paths verify the pid before signaling it.
|
|
165
|
+
*/
|
|
166
|
+
export interface RootProcessRecord {
|
|
167
|
+
pid: number;
|
|
168
|
+
/** Which tunnel provider owns the process; "tunnel" entries only. */
|
|
169
|
+
provider?: string;
|
|
170
|
+
/** The assistant the process fronts, so `cadet ps` can nest the row. */
|
|
171
|
+
assistantId?: string;
|
|
172
|
+
startedAt: string;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export type RootProcessKind = "tunnel" | "app";
|
|
176
|
+
|
|
166
177
|
/**
|
|
167
178
|
* Derive the daemon PID file path from a resources object. The PID file
|
|
168
179
|
* lives inside the instance's workspace directory. When no resources are
|
|
@@ -224,6 +235,40 @@ function withCliLockfileLock<T>(fn: () => T): T {
|
|
|
224
235
|
return locked.value;
|
|
225
236
|
}
|
|
226
237
|
|
|
238
|
+
/** Record a CLI-managed root process (tunnel agent, app edge) by pid. */
|
|
239
|
+
export function stampRootProcess(
|
|
240
|
+
kind: RootProcessKind,
|
|
241
|
+
record: RootProcessRecord,
|
|
242
|
+
): void {
|
|
243
|
+
withCliLockfileLock(() => {
|
|
244
|
+
const data = readLockfile();
|
|
245
|
+
data[kind] = record;
|
|
246
|
+
writeLockfileUnlocked(data);
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/** Drop the recorded root process entry, e.g. once the process is stopped. */
|
|
251
|
+
export function clearRootProcess(kind: RootProcessKind): void {
|
|
252
|
+
withCliLockfileLock(() => {
|
|
253
|
+
const data = readLockfile();
|
|
254
|
+
if (data[kind] === undefined) return;
|
|
255
|
+
delete data[kind];
|
|
256
|
+
writeLockfileUnlocked(data);
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Read the root-level process entries for `cadet ps`. Read-only: no lock, so
|
|
262
|
+
* a concurrently-updating lockfile is fine — the pid is verified separately.
|
|
263
|
+
*/
|
|
264
|
+
export function readRootProcesses(): {
|
|
265
|
+
tunnel?: RootProcessRecord;
|
|
266
|
+
app?: RootProcessRecord;
|
|
267
|
+
} {
|
|
268
|
+
const data = readLockfile();
|
|
269
|
+
return { tunnel: data.tunnel, app: data.app };
|
|
270
|
+
}
|
|
271
|
+
|
|
227
272
|
/**
|
|
228
273
|
* Try to extract a port number from a URL string (e.g. `http://localhost:7830`).
|
|
229
274
|
* Returns undefined if the URL is malformed or has no explicit port.
|
|
@@ -746,13 +791,14 @@ export async function allocateLocalResources(
|
|
|
746
791
|
}
|
|
747
792
|
|
|
748
793
|
/**
|
|
749
|
-
* Return `
|
|
794
|
+
* Return `cloudBaseUrl` from the lockfile, if set. This is the value
|
|
750
795
|
* persisted by {@link syncConfigToLockfile} the last time the active
|
|
751
796
|
* assistant was hatched/waked, and is the source of truth for "which
|
|
752
797
|
* platform does the currently-active assistant target".
|
|
753
798
|
*/
|
|
754
799
|
export function getLockfilePlatformBaseUrl(): string | undefined {
|
|
755
|
-
const
|
|
800
|
+
const lockfile = readLockfile();
|
|
801
|
+
const url = lockfile.cloudBaseUrl ?? lockfile.platformBaseUrl;
|
|
756
802
|
if (typeof url === "string" && url.trim()) return url.trim();
|
|
757
803
|
return undefined;
|
|
758
804
|
}
|