@mycadet/gateway 0.12.10 → 0.13.0
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/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/__tests__/ingress.test.ts +10 -10
- package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/ingress.ts +3 -3
- package/node_modules/@mycadet/ces-client/src/http-credentials.ts +18 -1
- package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/__tests__/ingress.test.ts +10 -10
- package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/ingress.ts +3 -3
- package/node_modules/@mycadet/gateway-client/src/gateway-ipc-contracts.ts +0 -20
- package/node_modules/@mycadet/service-contracts/src/__tests__/ingress.test.ts +10 -10
- package/node_modules/@mycadet/service-contracts/src/ingress.ts +3 -3
- package/openapi.json +1 -1
- package/package.json +1 -1
- package/src/__tests__/actor-token-revocation.test.ts +41 -34
- package/src/__tests__/contact-store-mirror-op-missing.test.ts +33 -70
- package/src/__tests__/contacts-mirror-op-reporter.test.ts +33 -89
- package/src/__tests__/credential-requests.test.ts +4 -4
- package/src/__tests__/devices-mine.test.ts +187 -0
- package/src/__tests__/edge-auth.test.ts +1 -20
- package/src/__tests__/edge-guardian-auth.test.ts +1 -17
- package/src/__tests__/feature-flag-resolver.test.ts +2 -30
- package/src/__tests__/feature-flag-watcher-callback.test.ts +0 -22
- package/src/__tests__/feature-flags-route.test.ts +2 -191
- package/src/__tests__/guardian-bootstrap-lookups.test.ts +22 -29
- package/src/__tests__/guardian-init-lockfile.test.ts +2 -2
- package/src/__tests__/guardian-integrity-reporter.test.ts +51 -82
- package/src/__tests__/guardian-integrity.test.ts +16 -20
- package/src/__tests__/handle-inbound-trust-verdict.test.ts +1 -14
- package/src/__tests__/ipc-feature-flag-routes.test.ts +0 -56
- package/src/__tests__/lum-2783-recovery-e2e.test.ts +0 -12
- package/src/__tests__/post-assistant-ready-deferred.test.ts +0 -18
- package/src/__tests__/refresh-device-binding.test.ts +0 -12
- package/src/__tests__/remote-web-pairing-token.test.ts +5 -15
- package/src/__tests__/runtime-client.test.ts +7 -7
- package/src/__tests__/speech-relay-websocket.test.ts +4 -4
- package/src/__tests__/trust-verdict-resolver-guardian-integrity.test.ts +30 -36
- package/src/__tests__/twilio-webhooks.test.ts +2 -2
- package/src/auth/actor-token-revocation.ts +34 -9
- package/src/auth/guardian-bootstrap.ts +1 -1
- package/src/cli/__tests__/pairing.test.ts +95 -0
- package/src/cli/index.ts +1 -1
- package/src/cli/pairing.ts +81 -6
- package/src/contacts-mirror-op-reporter.ts +19 -36
- package/src/db/connection.ts +0 -10
- package/src/feature-flag-resolver.ts +2 -7
- package/src/feature-flag-watcher.ts +1 -14
- package/src/guardian-integrity-reporter.ts +19 -47
- package/src/http/middleware/auth.ts +33 -27
- package/src/http/routes/auth-token.ts +1 -1
- package/src/http/routes/devices-mine.ts +103 -0
- package/src/http/routes/feature-flags.ts +1 -8
- package/src/http/routes/guardian-pin.ts +2 -11
- package/src/http/routes/ipc-runtime-proxy.ts +1 -1
- package/src/http/routes/live-voice-websocket.ts +1 -1
- package/src/http/routes/runtime-audio-stream.ts +1 -1
- package/src/http/routes/runtime-proxy.ts +2 -2
- package/src/http/routes/speech-relay-websocket.ts +2 -2
- package/src/http/routes/twilio-voice-webhook.test.ts +13 -13
- package/src/index.ts +11 -198
- package/src/ipc/feature-flag-handlers.ts +2 -9
- package/src/remote-web/pairing-challenge-store.ts +15 -0
- package/src/risk/command-registry/commands/assistant.ts +0 -24
- package/src/risk/command-registry.test.ts +2 -4
- package/src/schema.ts +44 -372
- package/src/__tests__/auth-fallback-count-tracker.test.ts +0 -92
- package/src/__tests__/auth-fallback-reporter.test.ts +0 -101
- package/src/__tests__/backup-worker-cloud-mode.test.ts +0 -44
- package/src/__tests__/backup-worker-export-timeout.test.ts +0 -164
- package/src/__tests__/migration-teleport-gcs-proxy.test.ts +0 -216
- package/src/__tests__/remote-feature-flag-sync.test.ts +0 -961
- package/src/auth-fallback-count-tracker.ts +0 -113
- package/src/auth-fallback-reporter.ts +0 -127
- package/src/backup/backup-key.ts +0 -138
- package/src/backup/backup-routes.ts +0 -161
- package/src/backup/backup-worker.ts +0 -425
- package/src/backup/list-snapshots.ts +0 -97
- package/src/backup/local-writer.ts +0 -87
- package/src/backup/offsite-writer.ts +0 -182
- package/src/backup/paths.ts +0 -113
- package/src/backup/stream-crypt.ts +0 -258
- package/src/device-id.ts +0 -18
- package/src/feature-flag-remote-store.ts +0 -166
- package/src/http/routes/migration-proxy.ts +0 -636
- package/src/internal-telemetry-client.ts +0 -39
- package/src/ipc/debug-export-handlers.test.ts +0 -102
- package/src/ipc/debug-export-handlers.ts +0 -81
- package/src/remote-feature-flag-sync.ts +0 -440
- package/src/watchdog-reporter.ts +0 -110
|
@@ -11,7 +11,6 @@ import { z } from "zod";
|
|
|
11
11
|
|
|
12
12
|
import { loadFeatureFlagDefaults } from "../feature-flag-defaults.js";
|
|
13
13
|
import { readEnvFeatureFlagOverrides } from "../feature-flag-env-overrides.js";
|
|
14
|
-
import { readRemoteFeatureFlags } from "../feature-flag-remote-store.js";
|
|
15
14
|
import { readPersistedFeatureFlags } from "../feature-flag-store.js";
|
|
16
15
|
import type { IpcRoute } from "./server.js";
|
|
17
16
|
|
|
@@ -20,24 +19,18 @@ const GetFeatureFlagParamsSchema = z.object({
|
|
|
20
19
|
});
|
|
21
20
|
|
|
22
21
|
/**
|
|
23
|
-
* Compute the merged feature flag state: defaults <
|
|
22
|
+
* Compute the merged feature flag state: defaults < persisted.
|
|
24
23
|
* Returns a `Record<string, boolean | string>` keyed by flag name.
|
|
25
24
|
*/
|
|
26
25
|
export function getMergedFeatureFlags(): FeatureFlagsIpcResponse {
|
|
27
26
|
const defaults = loadFeatureFlagDefaults();
|
|
28
27
|
const persisted = readPersistedFeatureFlags();
|
|
29
|
-
const remote = readRemoteFeatureFlags();
|
|
30
28
|
|
|
31
29
|
const result: Record<string, boolean | string> = {};
|
|
32
30
|
for (const [key, def] of Object.entries(defaults)) {
|
|
33
31
|
const persistedValue = persisted[key];
|
|
34
|
-
const remoteValue = remote[key];
|
|
35
32
|
result[key] =
|
|
36
|
-
persistedValue !== undefined
|
|
37
|
-
? persistedValue
|
|
38
|
-
: remoteValue !== undefined
|
|
39
|
-
? remoteValue
|
|
40
|
-
: def.defaultEnabled;
|
|
33
|
+
persistedValue !== undefined ? persistedValue : def.defaultEnabled;
|
|
41
34
|
}
|
|
42
35
|
|
|
43
36
|
const envOverrides = readEnvFeatureFlagOverrides();
|
|
@@ -331,6 +331,21 @@ export function listPendingRemoteWebPairingChallenges(): RemoteWebPairingRequest
|
|
|
331
331
|
}));
|
|
332
332
|
}
|
|
333
333
|
|
|
334
|
+
/**
|
|
335
|
+
* Every persisted pairing challenge — pending, approved, exchanging,
|
|
336
|
+
* consumed, or past expiry — newest first. Unlike the pending-list route
|
|
337
|
+
* this deletes nothing: expired challenges linger until their own
|
|
338
|
+
* verification/exchange paths clean them up, and this list is how the
|
|
339
|
+
* operator sees that tail state. Liveness (active vs expired) is the
|
|
340
|
+
* caller's call — it compares expiresAtMs against its own clock.
|
|
341
|
+
*/
|
|
342
|
+
export function listPersistedRemoteWebPairingChallenges(): PendingRemoteWebPairingChallenge[] {
|
|
343
|
+
loadFromDisk();
|
|
344
|
+
return [...challengesByUserCodeHash.values()].sort(
|
|
345
|
+
(a, b) => b.createdAtMs - a.createdAtMs,
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
|
|
334
349
|
export function approveRemoteWebPairingChallengeById(
|
|
335
350
|
id: string,
|
|
336
351
|
): ApproveRemoteWebPairingChallengeResult {
|
|
@@ -33,19 +33,6 @@ const ASSISTANT_SUPPORTED_COMMAND_PATHS = [
|
|
|
33
33
|
"avatar character update",
|
|
34
34
|
"avatar character components",
|
|
35
35
|
"avatar character ascii",
|
|
36
|
-
"backup",
|
|
37
|
-
"backup enable",
|
|
38
|
-
"backup disable",
|
|
39
|
-
"backup destinations",
|
|
40
|
-
"backup destinations list",
|
|
41
|
-
"backup destinations add",
|
|
42
|
-
"backup destinations remove",
|
|
43
|
-
"backup destinations set-encrypt",
|
|
44
|
-
"backup status",
|
|
45
|
-
"backup list",
|
|
46
|
-
"backup create",
|
|
47
|
-
"backup restore",
|
|
48
|
-
"backup verify",
|
|
49
36
|
"bash",
|
|
50
37
|
"browser",
|
|
51
38
|
"browser navigate",
|
|
@@ -449,11 +436,6 @@ const riskOverrides: AssistantRiskOverride[] = [
|
|
|
449
436
|
reason: "Deletes API key material",
|
|
450
437
|
},
|
|
451
438
|
// Destructive assistant-state operations
|
|
452
|
-
{
|
|
453
|
-
path: "backup restore",
|
|
454
|
-
risk: "high",
|
|
455
|
-
reason: "Restores backup and overwrites workspace state",
|
|
456
|
-
},
|
|
457
439
|
{
|
|
458
440
|
path: "conversations clear",
|
|
459
441
|
risk: "medium",
|
|
@@ -471,12 +453,6 @@ const riskOverrides: AssistantRiskOverride[] = [
|
|
|
471
453
|
{ path: "avatar set", risk: "low" },
|
|
472
454
|
{ path: "avatar remove", risk: "low" },
|
|
473
455
|
{ path: "avatar character update", risk: "low" },
|
|
474
|
-
{ path: "backup enable", risk: "low" },
|
|
475
|
-
{ path: "backup disable", risk: "high" },
|
|
476
|
-
{ path: "backup destinations add", risk: "high" },
|
|
477
|
-
{ path: "backup destinations remove", risk: "high" },
|
|
478
|
-
{ path: "backup destinations set-encrypt", risk: "high" },
|
|
479
|
-
{ path: "backup create", risk: "low" },
|
|
480
456
|
{ path: "cache set", risk: "low" },
|
|
481
457
|
{ path: "cache delete", risk: "low" },
|
|
482
458
|
{ path: "channel-verification-sessions create", risk: "high" },
|
|
@@ -525,8 +525,8 @@ describe("command-registry", () => {
|
|
|
525
525
|
expect(assistantSubs.platform.baseRisk).toBe("low");
|
|
526
526
|
});
|
|
527
527
|
|
|
528
|
-
test("assistant backup is
|
|
529
|
-
expect(assistantSubs.backup
|
|
528
|
+
test("assistant backup is not registered", () => {
|
|
529
|
+
expect(assistantSubs.backup).toBeUndefined();
|
|
530
530
|
});
|
|
531
531
|
|
|
532
532
|
test("assistant help is low risk", () => {
|
|
@@ -585,7 +585,6 @@ describe("command-registry", () => {
|
|
|
585
585
|
"audit",
|
|
586
586
|
"auth",
|
|
587
587
|
"avatar",
|
|
588
|
-
"backup",
|
|
589
588
|
"bash",
|
|
590
589
|
"browser",
|
|
591
590
|
"cache",
|
|
@@ -649,7 +648,6 @@ describe("command-registry", () => {
|
|
|
649
648
|
expect(getAssistantPath("email send").baseRisk).toBe("high");
|
|
650
649
|
expect(getAssistantPath("domain register").baseRisk).toBe("medium");
|
|
651
650
|
expect(getAssistantPath("conversations clear").baseRisk).toBe("medium");
|
|
652
|
-
expect(getAssistantPath("backup restore").baseRisk).toBe("high");
|
|
653
651
|
expect(getAssistantPath("inference session open").baseRisk).toBe("low");
|
|
654
652
|
expect(getAssistantPath("inference session close").baseRisk).toBe("low");
|
|
655
653
|
expect(getAssistantPath("inference session list").baseRisk).toBe("low");
|
package/src/schema.ts
CHANGED
|
@@ -3989,309 +3989,6 @@ export function buildSchema(): Record<string, unknown> {
|
|
|
3989
3989
|
},
|
|
3990
3990
|
},
|
|
3991
3991
|
},
|
|
3992
|
-
"/v1/migrations/export": {
|
|
3993
|
-
post: {
|
|
3994
|
-
summary: "Export workspace backup",
|
|
3995
|
-
description:
|
|
3996
|
-
"Proxies a migration export request to the assistant daemon. Returns a binary .vbundle backup of the workspace. Authenticated with an edge JWT. Timeout is 120 seconds to accommodate large workspaces.",
|
|
3997
|
-
operationId: "migrationExport",
|
|
3998
|
-
security: [{ BearerAuth: [] }],
|
|
3999
|
-
requestBody: {
|
|
4000
|
-
required: false,
|
|
4001
|
-
content: {
|
|
4002
|
-
"application/json": {
|
|
4003
|
-
schema: { type: "object", additionalProperties: true },
|
|
4004
|
-
},
|
|
4005
|
-
},
|
|
4006
|
-
},
|
|
4007
|
-
responses: {
|
|
4008
|
-
"200": {
|
|
4009
|
-
description: "Binary .vbundle backup file",
|
|
4010
|
-
content: {
|
|
4011
|
-
"application/octet-stream": {
|
|
4012
|
-
schema: { type: "string", format: "binary" },
|
|
4013
|
-
},
|
|
4014
|
-
},
|
|
4015
|
-
},
|
|
4016
|
-
"401": {
|
|
4017
|
-
description: "Unauthorized — missing or invalid bearer token",
|
|
4018
|
-
},
|
|
4019
|
-
"502": { description: "Failed to reach assistant daemon" },
|
|
4020
|
-
"504": { description: "Assistant daemon request timed out" },
|
|
4021
|
-
},
|
|
4022
|
-
},
|
|
4023
|
-
},
|
|
4024
|
-
"/v1/migrations/import": {
|
|
4025
|
-
post: {
|
|
4026
|
-
summary: "Import workspace backup",
|
|
4027
|
-
description:
|
|
4028
|
-
"Proxies a migration import request to the assistant. Request shapes:\n" +
|
|
4029
|
-
"\n" +
|
|
4030
|
-
" - `application/octet-stream`: raw .vbundle body. The request is proxied synchronously and the caller's connection stays open for the full import duration (returns 200 on success).\n" +
|
|
4031
|
-
' - `application/json` with `{ "url": "<signed GCS URL>" }` or `{ "path": "<staged workspace path>" }`: the gateway generates a jobId, kicks off the upstream assistant call in the background, and returns `202 Accepted` with `{ job_id, status: "pending" }` immediately. Callers poll `GET /v1/migrations/import/{jobId}/status` for progress. The path form points at a `.vbundle` staged under the assistant workspace `.restore-staging` directory.\n' +
|
|
4032
|
-
"\n" +
|
|
4033
|
-
"Authenticated with an edge JWT. Synchronous-path timeout is 60 minutes to accommodate large 8 GB backups; the async path returns immediately.",
|
|
4034
|
-
operationId: "migrationImport",
|
|
4035
|
-
security: [{ BearerAuth: [] }],
|
|
4036
|
-
requestBody: {
|
|
4037
|
-
required: true,
|
|
4038
|
-
content: {
|
|
4039
|
-
"application/octet-stream": {
|
|
4040
|
-
schema: { type: "string", format: "binary" },
|
|
4041
|
-
},
|
|
4042
|
-
"application/json": {
|
|
4043
|
-
schema: {
|
|
4044
|
-
oneOf: [
|
|
4045
|
-
{
|
|
4046
|
-
type: "object",
|
|
4047
|
-
required: ["url"],
|
|
4048
|
-
properties: {
|
|
4049
|
-
url: {
|
|
4050
|
-
type: "string",
|
|
4051
|
-
format: "uri",
|
|
4052
|
-
description:
|
|
4053
|
-
"Signed GCS URL pointing at a .vbundle archive.",
|
|
4054
|
-
},
|
|
4055
|
-
},
|
|
4056
|
-
},
|
|
4057
|
-
{
|
|
4058
|
-
type: "object",
|
|
4059
|
-
required: ["path"],
|
|
4060
|
-
properties: {
|
|
4061
|
-
path: {
|
|
4062
|
-
type: "string",
|
|
4063
|
-
minLength: 1,
|
|
4064
|
-
description:
|
|
4065
|
-
"Workspace-relative or absolute path to a staged .vbundle under .restore-staging.",
|
|
4066
|
-
},
|
|
4067
|
-
},
|
|
4068
|
-
},
|
|
4069
|
-
],
|
|
4070
|
-
},
|
|
4071
|
-
},
|
|
4072
|
-
},
|
|
4073
|
-
},
|
|
4074
|
-
responses: {
|
|
4075
|
-
"200": {
|
|
4076
|
-
description:
|
|
4077
|
-
"Backup imported successfully (synchronous byte path).",
|
|
4078
|
-
},
|
|
4079
|
-
"202": {
|
|
4080
|
-
description:
|
|
4081
|
-
"Import accepted for async processing (JSON url or path body). Poll `/v1/migrations/import/{jobId}/status` for progress.",
|
|
4082
|
-
content: {
|
|
4083
|
-
"application/json": {
|
|
4084
|
-
schema: {
|
|
4085
|
-
type: "object",
|
|
4086
|
-
required: ["job_id", "status"],
|
|
4087
|
-
properties: {
|
|
4088
|
-
job_id: { type: "string" },
|
|
4089
|
-
status: { type: "string", enum: ["pending"] },
|
|
4090
|
-
},
|
|
4091
|
-
},
|
|
4092
|
-
},
|
|
4093
|
-
},
|
|
4094
|
-
},
|
|
4095
|
-
"401": {
|
|
4096
|
-
description: "Unauthorized — missing or invalid bearer token",
|
|
4097
|
-
},
|
|
4098
|
-
"502": { description: "Failed to reach assistant daemon" },
|
|
4099
|
-
"504": { description: "Assistant daemon request timed out" },
|
|
4100
|
-
},
|
|
4101
|
-
},
|
|
4102
|
-
},
|
|
4103
|
-
"/v1/migrations/import/{jobId}/status": {
|
|
4104
|
-
get: {
|
|
4105
|
-
summary: "Poll async import job status",
|
|
4106
|
-
description:
|
|
4107
|
-
"Returns the current status of an async `.vbundle` import kicked off by `POST /v1/migrations/import` with a JSON `{url}` or `{path}` body. Finished jobs remain queryable for 30 minutes before being pruned.",
|
|
4108
|
-
operationId: "migrationImportStatus",
|
|
4109
|
-
security: [{ BearerAuth: [] }],
|
|
4110
|
-
parameters: [
|
|
4111
|
-
{
|
|
4112
|
-
in: "path",
|
|
4113
|
-
name: "jobId",
|
|
4114
|
-
required: true,
|
|
4115
|
-
schema: { type: "string" },
|
|
4116
|
-
description:
|
|
4117
|
-
"The `job_id` returned by the 202 response from `POST /v1/migrations/import`.",
|
|
4118
|
-
},
|
|
4119
|
-
],
|
|
4120
|
-
responses: {
|
|
4121
|
-
"200": {
|
|
4122
|
-
description: "Current job status.",
|
|
4123
|
-
content: {
|
|
4124
|
-
"application/json": {
|
|
4125
|
-
schema: {
|
|
4126
|
-
type: "object",
|
|
4127
|
-
required: ["job_id", "status"],
|
|
4128
|
-
properties: {
|
|
4129
|
-
job_id: { type: "string" },
|
|
4130
|
-
status: {
|
|
4131
|
-
type: "string",
|
|
4132
|
-
enum: ["pending", "processing", "complete", "failed"],
|
|
4133
|
-
},
|
|
4134
|
-
error: { type: "string" },
|
|
4135
|
-
result: {},
|
|
4136
|
-
},
|
|
4137
|
-
},
|
|
4138
|
-
},
|
|
4139
|
-
},
|
|
4140
|
-
},
|
|
4141
|
-
"401": {
|
|
4142
|
-
description: "Unauthorized — missing or invalid bearer token",
|
|
4143
|
-
},
|
|
4144
|
-
"404": {
|
|
4145
|
-
description:
|
|
4146
|
-
"Unknown job — never issued, or pruned after 30-minute TTL.",
|
|
4147
|
-
},
|
|
4148
|
-
},
|
|
4149
|
-
},
|
|
4150
|
-
},
|
|
4151
|
-
"/v1/migrations/export-to-gcs": {
|
|
4152
|
-
post: {
|
|
4153
|
-
summary: "Kick off an async export-to-GCS job",
|
|
4154
|
-
description:
|
|
4155
|
-
"Transparent proxy to the assistant daemon's `POST /v1/migrations/export-to-gcs` endpoint. The daemon schedules a background export job that streams the workspace backup to the supplied signed GCS upload URL and returns `202 Accepted` with a `job_id`. Callers poll `GET /v1/migrations/jobs/{jobId}` for progress. Registered explicitly, not via the runtime-proxy catch-all, for dedicated auth and timeout handling.",
|
|
4156
|
-
operationId: "migrationExportToGcs",
|
|
4157
|
-
security: [{ BearerAuth: [] }],
|
|
4158
|
-
requestBody: {
|
|
4159
|
-
required: true,
|
|
4160
|
-
content: {
|
|
4161
|
-
"application/json": {
|
|
4162
|
-
schema: { type: "object", additionalProperties: true },
|
|
4163
|
-
},
|
|
4164
|
-
},
|
|
4165
|
-
},
|
|
4166
|
-
responses: {
|
|
4167
|
-
"202": {
|
|
4168
|
-
description: "Export job accepted.",
|
|
4169
|
-
content: {
|
|
4170
|
-
"application/json": {
|
|
4171
|
-
schema: {
|
|
4172
|
-
type: "object",
|
|
4173
|
-
required: ["job_id"],
|
|
4174
|
-
properties: { job_id: { type: "string" } },
|
|
4175
|
-
},
|
|
4176
|
-
},
|
|
4177
|
-
},
|
|
4178
|
-
},
|
|
4179
|
-
"401": {
|
|
4180
|
-
description: "Unauthorized — missing or invalid bearer token",
|
|
4181
|
-
},
|
|
4182
|
-
"409": {
|
|
4183
|
-
description: "Another export is already in flight.",
|
|
4184
|
-
},
|
|
4185
|
-
"502": { description: "Failed to reach assistant daemon" },
|
|
4186
|
-
"504": { description: "Assistant daemon request timed out" },
|
|
4187
|
-
},
|
|
4188
|
-
},
|
|
4189
|
-
},
|
|
4190
|
-
"/v1/migrations/import-from-gcs": {
|
|
4191
|
-
post: {
|
|
4192
|
-
summary: "Kick off an async import-from-GCS job",
|
|
4193
|
-
description:
|
|
4194
|
-
"Transparent proxy to the assistant daemon's `POST /v1/migrations/import-from-gcs` endpoint. The daemon schedules a background import job that fetches a `.vbundle` archive at the supplied `bundle_url` and streams it through the importer, returning `202 Accepted` with a `job_id`. Callers poll `GET /v1/migrations/jobs/{jobId}` for progress. Registered explicitly, not via the runtime-proxy catch-all, for dedicated auth and timeout handling.",
|
|
4195
|
-
operationId: "migrationImportFromGcs",
|
|
4196
|
-
security: [{ BearerAuth: [] }],
|
|
4197
|
-
requestBody: {
|
|
4198
|
-
required: true,
|
|
4199
|
-
content: {
|
|
4200
|
-
"application/json": {
|
|
4201
|
-
schema: {
|
|
4202
|
-
type: "object",
|
|
4203
|
-
required: ["bundle_url"],
|
|
4204
|
-
properties: {
|
|
4205
|
-
bundle_url: {
|
|
4206
|
-
type: "string",
|
|
4207
|
-
format: "uri",
|
|
4208
|
-
description:
|
|
4209
|
-
"Signed GCS URL pointing at a .vbundle archive.",
|
|
4210
|
-
},
|
|
4211
|
-
},
|
|
4212
|
-
},
|
|
4213
|
-
},
|
|
4214
|
-
},
|
|
4215
|
-
},
|
|
4216
|
-
responses: {
|
|
4217
|
-
"202": {
|
|
4218
|
-
description: "Import job accepted.",
|
|
4219
|
-
content: {
|
|
4220
|
-
"application/json": {
|
|
4221
|
-
schema: {
|
|
4222
|
-
type: "object",
|
|
4223
|
-
required: ["job_id"],
|
|
4224
|
-
properties: { job_id: { type: "string" } },
|
|
4225
|
-
},
|
|
4226
|
-
},
|
|
4227
|
-
},
|
|
4228
|
-
},
|
|
4229
|
-
"401": {
|
|
4230
|
-
description: "Unauthorized — missing or invalid bearer token",
|
|
4231
|
-
},
|
|
4232
|
-
"409": {
|
|
4233
|
-
description: "Another import is already in flight.",
|
|
4234
|
-
},
|
|
4235
|
-
"502": { description: "Failed to reach assistant daemon" },
|
|
4236
|
-
"504": { description: "Assistant daemon request timed out" },
|
|
4237
|
-
},
|
|
4238
|
-
},
|
|
4239
|
-
},
|
|
4240
|
-
"/v1/migrations/jobs/{jobId}": {
|
|
4241
|
-
get: {
|
|
4242
|
-
summary: "Poll unified migration job status",
|
|
4243
|
-
description:
|
|
4244
|
-
"Transparent proxy to the assistant daemon's `GET /v1/migrations/jobs/{job_id}` endpoint. Returns the current status of an async export-to-GCS or import-from-GCS job tracked by the daemon's migration job registry. Registered explicitly, not via the runtime-proxy catch-all, for dedicated auth and timeout handling.",
|
|
4245
|
-
operationId: "migrationJobStatus",
|
|
4246
|
-
security: [{ BearerAuth: [] }],
|
|
4247
|
-
parameters: [
|
|
4248
|
-
{
|
|
4249
|
-
in: "path",
|
|
4250
|
-
name: "jobId",
|
|
4251
|
-
required: true,
|
|
4252
|
-
schema: { type: "string" },
|
|
4253
|
-
description:
|
|
4254
|
-
"The `job_id` returned by the 202 response from `POST /v1/migrations/export-to-gcs` or `POST /v1/migrations/import-from-gcs`.",
|
|
4255
|
-
},
|
|
4256
|
-
],
|
|
4257
|
-
responses: {
|
|
4258
|
-
"200": {
|
|
4259
|
-
description: "Current job status.",
|
|
4260
|
-
content: {
|
|
4261
|
-
"application/json": {
|
|
4262
|
-
schema: {
|
|
4263
|
-
type: "object",
|
|
4264
|
-
required: ["job_id", "type", "status"],
|
|
4265
|
-
properties: {
|
|
4266
|
-
job_id: { type: "string" },
|
|
4267
|
-
type: {
|
|
4268
|
-
type: "string",
|
|
4269
|
-
enum: ["export", "import"],
|
|
4270
|
-
},
|
|
4271
|
-
status: {
|
|
4272
|
-
type: "string",
|
|
4273
|
-
enum: ["processing", "complete", "failed"],
|
|
4274
|
-
},
|
|
4275
|
-
result: {},
|
|
4276
|
-
error: { type: "string" },
|
|
4277
|
-
error_code: { type: "string" },
|
|
4278
|
-
upstream_status: { type: "integer" },
|
|
4279
|
-
},
|
|
4280
|
-
},
|
|
4281
|
-
},
|
|
4282
|
-
},
|
|
4283
|
-
},
|
|
4284
|
-
"401": {
|
|
4285
|
-
description: "Unauthorized — missing or invalid bearer token",
|
|
4286
|
-
},
|
|
4287
|
-
"404": {
|
|
4288
|
-
description: "Unknown job_id.",
|
|
4289
|
-
},
|
|
4290
|
-
"502": { description: "Failed to reach assistant daemon" },
|
|
4291
|
-
"504": { description: "Assistant daemon request timed out" },
|
|
4292
|
-
},
|
|
4293
|
-
},
|
|
4294
|
-
},
|
|
4295
3992
|
"/v1/admin/workspace-commit": {
|
|
4296
3993
|
post: {
|
|
4297
3994
|
summary: "Commit workspace changes",
|
|
@@ -4431,50 +4128,37 @@ export function buildSchema(): Record<string, unknown> {
|
|
|
4431
4128
|
},
|
|
4432
4129
|
},
|
|
4433
4130
|
},
|
|
4434
|
-
"/v1/
|
|
4131
|
+
"/v1/devices/mine": {
|
|
4435
4132
|
get: {
|
|
4436
|
-
summary: "
|
|
4133
|
+
summary: "The caller's own paired-device row",
|
|
4437
4134
|
description:
|
|
4438
|
-
"
|
|
4439
|
-
operationId: "
|
|
4135
|
+
"Returns the paired-device row matching the presenting bearer token, so the paired web UI can surface 'this device' for matching against the host-side `cadet devices` list. Browser-reachable: the bearer is the credential, and the route answers only for the token presenting it. Not available on cloud-hosted assistants (they have no paired-device rows).",
|
|
4136
|
+
operationId: "getMyDevice",
|
|
4440
4137
|
security: [{ BearerAuth: [] }],
|
|
4441
4138
|
responses: {
|
|
4442
4139
|
"200": {
|
|
4443
|
-
description: "
|
|
4140
|
+
description: "The caller's paired-device row",
|
|
4444
4141
|
content: {
|
|
4445
4142
|
"application/json": {
|
|
4446
4143
|
schema: {
|
|
4447
4144
|
type: "object",
|
|
4448
|
-
required: ["
|
|
4145
|
+
required: ["device"],
|
|
4449
4146
|
properties: {
|
|
4450
|
-
|
|
4147
|
+
device: {
|
|
4451
4148
|
type: "object",
|
|
4452
|
-
required: ["
|
|
4149
|
+
required: ["hashedDeviceId", "platform", "issuedAt"],
|
|
4453
4150
|
properties: {
|
|
4454
|
-
|
|
4455
|
-
|
|
4456
|
-
|
|
4457
|
-
|
|
4458
|
-
$ref: "#/components/schemas/BackupSnapshot",
|
|
4459
|
-
},
|
|
4151
|
+
hashedDeviceId: { type: "string" },
|
|
4152
|
+
platform: { type: "string" },
|
|
4153
|
+
pairingUserAgent: {
|
|
4154
|
+
type: ["string", "null"],
|
|
4460
4155
|
},
|
|
4461
|
-
|
|
4462
|
-
|
|
4463
|
-
offsite: {
|
|
4464
|
-
type: "array",
|
|
4465
|
-
items: {
|
|
4466
|
-
type: "object",
|
|
4467
|
-
required: ["directory", "encrypted", "snapshots"],
|
|
4468
|
-
properties: {
|
|
4469
|
-
directory: { type: "string" },
|
|
4470
|
-
encrypted: { type: "boolean" },
|
|
4471
|
-
snapshots: {
|
|
4472
|
-
type: "array",
|
|
4473
|
-
items: {
|
|
4474
|
-
$ref: "#/components/schemas/BackupSnapshot",
|
|
4475
|
-
},
|
|
4476
|
-
},
|
|
4156
|
+
clientReportedName: {
|
|
4157
|
+
type: ["string", "null"],
|
|
4477
4158
|
},
|
|
4159
|
+
issuedAt: { type: "string" },
|
|
4160
|
+
expiresAt: { type: ["string", "null"] },
|
|
4161
|
+
lastUsedAt: { type: ["string", "null"] },
|
|
4478
4162
|
},
|
|
4479
4163
|
},
|
|
4480
4164
|
},
|
|
@@ -4483,51 +4167,22 @@ export function buildSchema(): Record<string, unknown> {
|
|
|
4483
4167
|
},
|
|
4484
4168
|
},
|
|
4485
4169
|
"401": {
|
|
4486
|
-
description: "
|
|
4487
|
-
},
|
|
4488
|
-
"403": { description: "Insufficient scope" },
|
|
4489
|
-
"500": { description: "Internal server error" },
|
|
4490
|
-
},
|
|
4491
|
-
},
|
|
4492
|
-
},
|
|
4493
|
-
"/v1/backups/create": {
|
|
4494
|
-
post: {
|
|
4495
|
-
summary: "Create backup snapshot",
|
|
4496
|
-
description:
|
|
4497
|
-
"Triggers a manual backup snapshot. The gateway exports a plaintext vbundle from the daemon, writes it locally, and encrypts + mirrors to offsite destinations.",
|
|
4498
|
-
operationId: "backupsCreate",
|
|
4499
|
-
security: [{ BearerAuth: [] }],
|
|
4500
|
-
responses: {
|
|
4501
|
-
"200": {
|
|
4502
|
-
description: "Backup snapshot created",
|
|
4170
|
+
description: "Missing or invalid bearer token",
|
|
4503
4171
|
content: {
|
|
4504
4172
|
"application/json": {
|
|
4505
|
-
schema: {
|
|
4506
|
-
type: "object",
|
|
4507
|
-
required: ["success", "local", "offsite", "duration_ms"],
|
|
4508
|
-
properties: {
|
|
4509
|
-
success: { type: "boolean" },
|
|
4510
|
-
local: {
|
|
4511
|
-
$ref: "#/components/schemas/BackupSnapshot",
|
|
4512
|
-
},
|
|
4513
|
-
offsite: {
|
|
4514
|
-
type: "array",
|
|
4515
|
-
items: { type: "object", additionalProperties: true },
|
|
4516
|
-
},
|
|
4517
|
-
duration_ms: { type: "number" },
|
|
4518
|
-
},
|
|
4519
|
-
},
|
|
4173
|
+
schema: { $ref: "#/components/schemas/ErrorResponse" },
|
|
4520
4174
|
},
|
|
4521
4175
|
},
|
|
4522
4176
|
},
|
|
4523
|
-
"
|
|
4524
|
-
description:
|
|
4525
|
-
|
|
4526
|
-
|
|
4527
|
-
|
|
4528
|
-
|
|
4177
|
+
"404": {
|
|
4178
|
+
description:
|
|
4179
|
+
"No paired-device row for this token, or the gateway is cloud-hosted",
|
|
4180
|
+
content: {
|
|
4181
|
+
"application/json": {
|
|
4182
|
+
schema: { $ref: "#/components/schemas/ErrorResponse" },
|
|
4183
|
+
},
|
|
4184
|
+
},
|
|
4529
4185
|
},
|
|
4530
|
-
"500": { description: "Internal server error" },
|
|
4531
4186
|
},
|
|
4532
4187
|
},
|
|
4533
4188
|
},
|
|
@@ -4628,6 +4283,23 @@ export function buildSchema(): Record<string, unknown> {
|
|
|
4628
4283
|
},
|
|
4629
4284
|
},
|
|
4630
4285
|
},
|
|
4286
|
+
"404": {
|
|
4287
|
+
description: "Route not found on upstream runtime",
|
|
4288
|
+
content: {
|
|
4289
|
+
"application/json": {
|
|
4290
|
+
schema: { $ref: "#/components/schemas/ErrorResponse" },
|
|
4291
|
+
},
|
|
4292
|
+
},
|
|
4293
|
+
},
|
|
4294
|
+
"500": {
|
|
4295
|
+
description:
|
|
4296
|
+
"Server misconfigured (proxy auth enabled without token)",
|
|
4297
|
+
content: {
|
|
4298
|
+
"application/json": {
|
|
4299
|
+
schema: { $ref: "#/components/schemas/ErrorResponse" },
|
|
4300
|
+
},
|
|
4301
|
+
},
|
|
4302
|
+
},
|
|
4631
4303
|
"502": {
|
|
4632
4304
|
description: "Upstream connection failed",
|
|
4633
4305
|
content: {
|