@mycadet/gateway 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 +3 -3
  2. package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/package.json +2 -2
  3. package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/{platform-credential.ts → cloud-credential.ts} +9 -9
  4. package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/handles.ts +3 -3
  5. package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/index.ts +1 -1
  6. package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/ingress.ts +11 -5
  7. package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/remote-web-pairing.ts +1 -1
  8. package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/rpc.ts +14 -14
  9. package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/trust-rules.ts +5 -5
  10. package/node_modules/@mycadet/ces-client/package.json +1 -1
  11. package/node_modules/@mycadet/ces-client/src/__tests__/ces-client.test.ts +14 -14
  12. package/node_modules/@mycadet/ces-client/src/rpc-client.ts +1 -1
  13. package/node_modules/@mycadet/environments/src/seeds.ts +6 -6
  14. package/node_modules/@mycadet/environments/src/shell.test.ts +1 -1
  15. package/node_modules/@mycadet/environments/src/types.ts +6 -6
  16. package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/package.json +2 -2
  17. package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/{platform-credential.ts → cloud-credential.ts} +9 -9
  18. package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/handles.ts +3 -3
  19. package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/index.ts +1 -1
  20. package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/ingress.ts +11 -5
  21. package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/remote-web-pairing.ts +1 -1
  22. package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/rpc.ts +14 -14
  23. package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/trust-rules.ts +5 -5
  24. package/node_modules/@mycadet/gateway-client/src/binding-strength-contract.ts +5 -5
  25. package/node_modules/@mycadet/gateway-client/src/gateway-ipc-contracts.ts +1 -1
  26. package/node_modules/@mycadet/gateway-client/src/inbound-contract.ts +2 -2
  27. package/node_modules/@mycadet/gateway-client/src/outbound-contract.ts +1 -1
  28. package/node_modules/@mycadet/service-contracts/package.json +2 -2
  29. package/node_modules/@mycadet/service-contracts/src/{platform-credential.ts → cloud-credential.ts} +9 -9
  30. package/node_modules/@mycadet/service-contracts/src/handles.ts +3 -3
  31. package/node_modules/@mycadet/service-contracts/src/index.ts +1 -1
  32. package/node_modules/@mycadet/service-contracts/src/ingress.ts +11 -5
  33. package/node_modules/@mycadet/service-contracts/src/remote-web-pairing.ts +1 -1
  34. package/node_modules/@mycadet/service-contracts/src/rpc.ts +14 -14
  35. package/node_modules/@mycadet/service-contracts/src/trust-rules.ts +5 -5
  36. package/openapi.json +17 -17
  37. package/package.json +1 -1
  38. package/scripts/generate-openapi.ts +1 -1
  39. package/src/__tests__/actor-token-revocation.test.ts +0 -1
  40. package/src/__tests__/{backup-worker-platform-mode.test.ts → backup-worker-cloud-mode.test.ts} +4 -4
  41. package/src/__tests__/channel-verification-session-proxy.test.ts +0 -1
  42. package/src/__tests__/{platform-identity.test.ts → cloud-identity.test.ts} +72 -86
  43. package/src/__tests__/config.test.ts +0 -24
  44. package/src/__tests__/contacts-control-plane-proxy.test.ts +0 -1
  45. package/src/__tests__/credential-requests.test.ts +6 -6
  46. package/src/__tests__/{credential-watcher-managed-bootstrap.test.ts → credential-watcher-cloud-bootstrap.test.ts} +1 -1
  47. package/src/__tests__/edge-auth.test.ts +18 -18
  48. package/src/__tests__/edge-guardian-auth.test.ts +10 -10
  49. package/src/__tests__/guardian-init-lockfile.test.ts +6 -8
  50. package/src/__tests__/guardian-pin.test.ts +8 -8
  51. package/src/__tests__/handle-inbound-admission.test.ts +0 -1
  52. package/src/__tests__/handle-inbound-app-context.test.ts +0 -1
  53. package/src/__tests__/handle-inbound-invite-intercept.test.ts +0 -1
  54. package/src/__tests__/handle-inbound-trust-verdict.test.ts +0 -1
  55. package/src/__tests__/inbound-contact-seed.test.ts +1 -1
  56. package/src/__tests__/live-voice-websocket.test.ts +12 -12
  57. package/src/__tests__/load-guards.test.ts +0 -1
  58. package/src/__tests__/migration-teleport-gcs-proxy.test.ts +0 -1
  59. package/src/__tests__/oauth-callback.test.ts +0 -1
  60. package/src/__tests__/remote-feature-flag-sync.test.ts +35 -45
  61. package/src/__tests__/resolve-assistant.test.ts +0 -1
  62. package/src/__tests__/route-schema-guard.test.ts +4 -1
  63. package/src/__tests__/runtime-client.test.ts +1 -2
  64. package/src/__tests__/runtime-health-proxy.test.ts +0 -1
  65. package/src/__tests__/runtime-proxy-auth.test.ts +3 -2
  66. package/src/__tests__/runtime-proxy-device-stamp.test.ts +0 -1
  67. package/src/__tests__/runtime-proxy-error-body.test.ts +0 -1
  68. package/src/__tests__/runtime-proxy.test.ts +0 -1
  69. package/src/__tests__/runtime-stream-test-utils.ts +0 -1
  70. package/src/__tests__/shared-invite-registration.test.ts +15 -32
  71. package/src/__tests__/slack-control-plane-proxy.test.ts +0 -1
  72. package/src/__tests__/slack-display-name.test.ts +0 -1
  73. package/src/__tests__/slack-normalize.test.ts +0 -1
  74. package/src/__tests__/slack-reaction-normalize.test.ts +0 -1
  75. package/src/__tests__/slack-socket-mode-catchup.test.ts +0 -1
  76. package/src/__tests__/slack-socket-mode-group-dm.test.ts +0 -1
  77. package/src/__tests__/slack-socket-mode-liveness.test.ts +0 -1
  78. package/src/__tests__/slack-socket-mode-outbound-root.test.ts +0 -1
  79. package/src/__tests__/slack-socket-mode-thread-tracking.test.ts +0 -1
  80. package/src/__tests__/speech-relay-websocket.test.ts +16 -14
  81. package/src/__tests__/stt-stream-websocket.test.ts +5 -5
  82. package/src/__tests__/telegram-control-plane-proxy.test.ts +0 -1
  83. package/src/__tests__/telegram-webhook-drop-visibility.test.ts +0 -1
  84. package/src/__tests__/telegram-webhook-handler.test.ts +0 -1
  85. package/src/__tests__/telegram-webhook-manager.test.ts +79 -80
  86. package/src/__tests__/twilio-media-websocket.test.ts +0 -1
  87. package/src/__tests__/twilio-webhooks.test.ts +6 -7
  88. package/src/__tests__/whatsapp-download.test.ts +0 -1
  89. package/src/__tests__/whatsapp-webhook.test.ts +0 -1
  90. package/src/attachments/ingest.test.ts +0 -1
  91. package/src/auth/guardian-bootstrap.ts +16 -15
  92. package/src/auth/scopes.ts +1 -1
  93. package/src/auth-fallback-reporter.ts +1 -1
  94. package/src/backup/backup-worker.ts +2 -2
  95. package/src/channels/inbound-event.ts +3 -3
  96. package/src/channels/ingress-inbound-vendors.test.ts +2 -2
  97. package/src/channels/ingress-inbound.ts +1 -1
  98. package/src/channels/ingress-verification.test.ts +2 -2
  99. package/src/channels/ingress-verification.ts +4 -4
  100. package/src/channels/plugin-ingress-approvals.test.ts +1 -1
  101. package/src/channels/plugin-ingress-approvals.ts +1 -1
  102. package/src/channels/plugin-ingress.test.ts +3 -3
  103. package/src/channels/plugin-ingress.ts +3 -3
  104. package/src/channels/room-admission.ts +2 -2
  105. package/src/cli/contacts.ts +3 -1
  106. package/src/cli/index.ts +1 -1
  107. package/src/{platform-identity.ts → cloud-identity.ts} +60 -68
  108. package/src/cloud-url.ts +25 -0
  109. package/src/{platform-user-id.ts → cloud-user-id.ts} +4 -4
  110. package/src/config.ts +2 -4
  111. package/src/credential-reader.ts +2 -2
  112. package/src/db/assistant-db-proxy.ts +1 -1
  113. package/src/discord/forward.ts +1 -1
  114. package/src/email/normalize.ts +4 -4
  115. package/src/email/register-callback.test.ts +27 -34
  116. package/src/email/register-callback.ts +21 -26
  117. package/src/feature-flag-registry.json +5 -5
  118. package/src/feature-flag-remote-store.ts +2 -2
  119. package/src/feature-flag-resolver.ts +5 -5
  120. package/src/http/cadet-signature.ts +1 -1
  121. package/src/http/edge-forwarded-header.ts +1 -1
  122. package/src/http/loopback-guard.ts +1 -1
  123. package/src/http/middleware/auth.ts +22 -22
  124. package/src/http/router.ts +1 -1
  125. package/src/http/routes/auto-approve-thresholds-routes.ts +1 -1
  126. package/src/http/routes/cadet-identity.ts +2 -2
  127. package/src/http/routes/channel-admission-policy-routes.ts +2 -2
  128. package/src/http/routes/channel-ingress-routes.ts +3 -3
  129. package/src/http/routes/channel-ingress.test.ts +13 -2
  130. package/src/http/routes/channel-permission-overrides-routes.ts +3 -3
  131. package/src/http/routes/channel-verification-session-proxy.ts +8 -22
  132. package/src/http/routes/{platform-push-proxy.test.ts → cloud-push-proxy.test.ts} +21 -22
  133. package/src/http/routes/{platform-push-proxy.ts → cloud-push-proxy.ts} +13 -14
  134. package/src/http/routes/contacts-control-plane-proxy.ts +3 -3
  135. package/src/http/routes/contacts-control-plane-routes.ts +5 -5
  136. package/src/http/routes/email-webhook.test.ts +2 -3
  137. package/src/http/routes/email-webhook.ts +4 -4
  138. package/src/http/routes/feature-flags.ts +1 -1
  139. package/src/http/routes/guardian-channel-create.ts +3 -3
  140. package/src/http/routes/guardian-pin.ts +9 -9
  141. package/src/http/routes/inbound-register.ts +2 -2
  142. package/src/http/routes/ingress-domains.test.ts +129 -0
  143. package/src/http/routes/ingress-domains.ts +73 -0
  144. package/src/http/routes/live-voice-websocket.ts +2 -2
  145. package/src/http/routes/log-export.test.ts +0 -1
  146. package/src/http/routes/log-tail.test.ts +0 -1
  147. package/src/http/routes/migration-proxy.ts +1 -1
  148. package/src/http/routes/plugin-webhook-websocket.test.ts +3 -3
  149. package/src/http/routes/plugin-webhook.test.ts +9 -8
  150. package/src/http/routes/plugin-webhook.ts +1 -1
  151. package/src/http/routes/speech-relay-websocket.ts +8 -11
  152. package/src/http/routes/stt-stream-websocket.ts +1 -1
  153. package/src/http/routes/telegram-webhook.test.ts +0 -1
  154. package/src/http/routes/trust-rules-routes.ts +2 -2
  155. package/src/http/routes/twilio-voice-verify-callback.ts +3 -3
  156. package/src/http/routes/twilio-voice-webhook.test.ts +3 -4
  157. package/src/http/routes/twilio-voice-webhook.ts +3 -3
  158. package/src/http/routes/whatsapp-webhook.test.ts +0 -1
  159. package/src/index.ts +57 -56
  160. package/src/ipc/credential-request-handlers.ts +4 -4
  161. package/src/ipc/debug-export-handlers.test.ts +0 -1
  162. package/src/ipc/log-tail-handlers.test.ts +0 -1
  163. package/src/ipc/risk-classification-handlers.test.ts +4 -4
  164. package/src/ipc/risk-classification-handlers.ts +2 -2
  165. package/src/remote-feature-flag-sync.ts +17 -19
  166. package/src/risk/command-registry/commands/assistant.ts +2 -2
  167. package/src/risk/skill-risk-classifier.test.ts +24 -24
  168. package/src/risk/skill-risk-classifier.ts +10 -10
  169. package/src/runtime/client.ts +17 -17
  170. package/src/schema.ts +29 -29
  171. package/src/telegram/send.test.ts +0 -1
  172. package/src/telegram/webhook-manager.ts +33 -38
  173. package/src/tunnel/allowed-paths.test.ts +3 -3
  174. package/src/tunnel/allowed-paths.ts +1 -1
  175. package/src/tunnel/client.test.ts +20 -21
  176. package/src/tunnel/client.ts +16 -17
  177. package/src/verification/shared-invite-registration.ts +22 -17
  178. package/src/version.ts +1 -1
  179. package/src/platform-url.ts +0 -24
@@ -19,10 +19,10 @@ describe("SkillLoadRiskClassifier", () => {
19
19
  expect(result.matchType).toBe("registry");
20
20
  });
21
21
 
22
- test("scaffold_managed_skill is always High risk", async () => {
22
+ test("scaffold_cloud_skill is always High risk", async () => {
23
23
  const classifier = new SkillLoadRiskClassifier();
24
24
  const result = await classifier.classify({
25
- toolName: "scaffold_managed_skill",
25
+ toolName: "scaffold_cloud_skill",
26
26
  });
27
27
  expect(result.riskLevel).toBe("high");
28
28
  expect(result.reason).toBe(
@@ -32,10 +32,10 @@ describe("SkillLoadRiskClassifier", () => {
32
32
  expect(result.matchType).toBe("registry");
33
33
  });
34
34
 
35
- test("delete_managed_skill is always High risk", async () => {
35
+ test("delete_cloud_skill is always High risk", async () => {
36
36
  const classifier = new SkillLoadRiskClassifier();
37
37
  const result = await classifier.classify({
38
- toolName: "delete_managed_skill",
38
+ toolName: "delete_cloud_skill",
39
39
  });
40
40
  expect(result.riskLevel).toBe("high");
41
41
  expect(result.reason).toBe(
@@ -55,19 +55,19 @@ describe("SkillLoadRiskClassifier", () => {
55
55
  expect(result.reason).toBe("Skill load (default)");
56
56
  });
57
57
 
58
- test("scaffold_managed_skill with skillSelector is still High risk", async () => {
58
+ test("scaffold_cloud_skill with skillSelector is still High risk", async () => {
59
59
  const classifier = new SkillLoadRiskClassifier();
60
60
  const result = await classifier.classify({
61
- toolName: "scaffold_managed_skill",
61
+ toolName: "scaffold_cloud_skill",
62
62
  skillSelector: "new-skill",
63
63
  });
64
64
  expect(result.riskLevel).toBe("high");
65
65
  });
66
66
 
67
- test("delete_managed_skill with skillSelector is still High risk", async () => {
67
+ test("delete_cloud_skill with skillSelector is still High risk", async () => {
68
68
  const classifier = new SkillLoadRiskClassifier();
69
69
  const result = await classifier.classify({
70
- toolName: "delete_managed_skill",
70
+ toolName: "delete_cloud_skill",
71
71
  skillSelector: "old-skill",
72
72
  });
73
73
  expect(result.riskLevel).toBe("high");
@@ -163,56 +163,56 @@ describe("allowlistOptions", () => {
163
163
  ]);
164
164
  });
165
165
 
166
- test("scaffold_managed_skill produces skill-specific + wildcard options", async () => {
166
+ test("scaffold_cloud_skill produces skill-specific + wildcard options", async () => {
167
167
  const classifier = new SkillLoadRiskClassifier();
168
168
  const result = await classifier.classify({
169
- toolName: "scaffold_managed_skill",
169
+ toolName: "scaffold_cloud_skill",
170
170
  skillSelector: "new-skill",
171
171
  });
172
172
  expect(result.allowlistOptions).toEqual([
173
173
  {
174
174
  label: "new-skill",
175
175
  description: "This skill only",
176
- pattern: "scaffold_managed_skill:new-skill",
176
+ pattern: "scaffold_cloud_skill:new-skill",
177
177
  },
178
178
  {
179
- label: "scaffold_managed_skill:*",
179
+ label: "scaffold_cloud_skill:*",
180
180
  description: "All managed skill scaffolds",
181
- pattern: "scaffold_managed_skill:*",
181
+ pattern: "scaffold_cloud_skill:*",
182
182
  },
183
183
  ]);
184
184
  });
185
185
 
186
- test("delete_managed_skill produces skill-specific + wildcard options", async () => {
186
+ test("delete_cloud_skill produces skill-specific + wildcard options", async () => {
187
187
  const classifier = new SkillLoadRiskClassifier();
188
188
  const result = await classifier.classify({
189
- toolName: "delete_managed_skill",
189
+ toolName: "delete_cloud_skill",
190
190
  skillSelector: "old-skill",
191
191
  });
192
192
  expect(result.allowlistOptions).toEqual([
193
193
  {
194
194
  label: "old-skill",
195
195
  description: "This skill only",
196
- pattern: "delete_managed_skill:old-skill",
196
+ pattern: "delete_cloud_skill:old-skill",
197
197
  },
198
198
  {
199
- label: "delete_managed_skill:*",
199
+ label: "delete_cloud_skill:*",
200
200
  description: "All managed skill deletes",
201
- pattern: "delete_managed_skill:*",
201
+ pattern: "delete_cloud_skill:*",
202
202
  },
203
203
  ]);
204
204
  });
205
205
 
206
- test("scaffold_managed_skill without selector produces only wildcard", async () => {
206
+ test("scaffold_cloud_skill without selector produces only wildcard", async () => {
207
207
  const classifier = new SkillLoadRiskClassifier();
208
208
  const result = await classifier.classify({
209
- toolName: "scaffold_managed_skill",
209
+ toolName: "scaffold_cloud_skill",
210
210
  });
211
211
  expect(result.allowlistOptions).toEqual([
212
212
  {
213
- label: "scaffold_managed_skill:*",
213
+ label: "scaffold_cloud_skill:*",
214
214
  description: "All managed skill scaffolds",
215
- pattern: "scaffold_managed_skill:*",
215
+ pattern: "scaffold_cloud_skill:*",
216
216
  },
217
217
  ]);
218
218
  });
@@ -228,8 +228,8 @@ describe("singleton", () => {
228
228
  test("singleton produces same results as fresh instance", async () => {
229
229
  const inputs: SkillClassifierInput[] = [
230
230
  { toolName: "skill_load" },
231
- { toolName: "scaffold_managed_skill" },
232
- { toolName: "delete_managed_skill" },
231
+ { toolName: "scaffold_cloud_skill" },
232
+ { toolName: "delete_cloud_skill" },
233
233
  ];
234
234
 
235
235
  const fresh = new SkillLoadRiskClassifier();
@@ -4,8 +4,8 @@
4
4
  * Implements RiskClassifier<SkillClassifierInput> with constant risk levels
5
5
  * for each skill tool type:
6
6
  * - skill_load: Low (read-only skill loading)
7
- * - scaffold_managed_skill: High (writes persistent skill source code)
8
- * - delete_managed_skill: High (removes persistent skill source code)
7
+ * - scaffold_cloud_skill: High (writes persistent skill source code)
8
+ * - delete_cloud_skill: High (removes persistent skill source code)
9
9
  *
10
10
  * Gateway adaptation: accepts pre-resolved skill metadata via
11
11
  * SkillClassifierInput.resolvedMetadata instead of importing the assistant's
@@ -50,7 +50,7 @@ export interface ResolvedSkillMetadata {
50
50
  /** Input to the skill risk classifier. */
51
51
  export interface SkillClassifierInput {
52
52
  /** Which skill tool is being invoked. */
53
- toolName: "skill_load" | "scaffold_managed_skill" | "delete_managed_skill";
53
+ toolName: "skill_load" | "scaffold_cloud_skill" | "delete_cloud_skill";
54
54
  /** Optional skill selector (e.g. skill name or path). */
55
55
  skillSelector?: string;
56
56
  /**
@@ -134,12 +134,12 @@ function buildSkillLoadAllowlistOptions(
134
134
  /**
135
135
  * Build allowlist options for scaffold/delete managed skill tools.
136
136
  */
137
- function buildManagedSkillAllowlistOptions(
137
+ function buildCloudSkillAllowlistOptions(
138
138
  toolName: string,
139
139
  skillId?: string,
140
140
  ): AllowlistOption[] {
141
141
  const toolLabel =
142
- toolName === "scaffold_managed_skill" ? "scaffold" : "delete";
142
+ toolName === "scaffold_cloud_skill" ? "scaffold" : "delete";
143
143
  const options: AllowlistOption[] = [];
144
144
  if (skillId) {
145
145
  options.push({
@@ -200,25 +200,25 @@ export class SkillLoadRiskClassifier implements RiskClassifier<SkillClassifierIn
200
200
  };
201
201
  break;
202
202
  }
203
- case "scaffold_managed_skill":
203
+ case "scaffold_cloud_skill":
204
204
  assessment = {
205
205
  riskLevel: "high",
206
206
  reason: "Skill scaffold — writes persistent skill source code",
207
207
  scopeOptions: [],
208
208
  matchType: "registry",
209
- allowlistOptions: buildManagedSkillAllowlistOptions(
209
+ allowlistOptions: buildCloudSkillAllowlistOptions(
210
210
  toolName,
211
211
  skillSelector,
212
212
  ),
213
213
  };
214
214
  break;
215
- case "delete_managed_skill":
215
+ case "delete_cloud_skill":
216
216
  assessment = {
217
217
  riskLevel: "high",
218
218
  reason: "Skill delete — removes persistent skill source code",
219
219
  scopeOptions: [],
220
220
  matchType: "registry",
221
- allowlistOptions: buildManagedSkillAllowlistOptions(
221
+ allowlistOptions: buildCloudSkillAllowlistOptions(
222
222
  toolName,
223
223
  skillSelector,
224
224
  ),
@@ -227,7 +227,7 @@ export class SkillLoadRiskClassifier implements RiskClassifier<SkillClassifierIn
227
227
  }
228
228
 
229
229
  // User override is applied after normal classification. This means a user-defined
230
- // rule CAN lower a security-escalated risk (e.g., scaffold_managed_skill).
230
+ // rule CAN lower a security-escalated risk (e.g., scaffold_cloud_skill).
231
231
  // This is intentional — user overrides are authoritative for users who explicitly
232
232
  // created them. Uses resolved skillId from metadata (when available), and
233
233
  // skill_load_dynamic as the tool key for dynamic skills.
@@ -397,12 +397,12 @@ function extractPlatformCallbackAssistantId(
397
397
 
398
398
  function resolveTunnelBaseWssUrl(
399
399
  config: GatewayConfig,
400
- platformAssistantId?: string,
400
+ cloudAssistantId?: string,
401
401
  ): string | undefined {
402
- if (!config.tunnelBaseUrl || !platformAssistantId) return undefined;
402
+ if (!config.tunnelBaseUrl || !cloudAssistantId) return undefined;
403
403
 
404
404
  const withPath =
405
- config.tunnelBaseUrl.replace(/\/+$/, "") + "/" + platformAssistantId;
405
+ config.tunnelBaseUrl.replace(/\/+$/, "") + "/" + cloudAssistantId;
406
406
  const normalizedTunnelUrl = normalizePublicBaseUrl(withPath);
407
407
  return normalizedTunnelUrl
408
408
  ? toWebSocketBaseUrl(normalizedTunnelUrl)
@@ -418,7 +418,7 @@ function resolveTunnelBaseWssUrl(
418
418
  * 2. `ingress.publicBaseUrl` from the config file when it is a real public
419
419
  * gateway base URL — written by Tunnel after tunnel registration, or set
420
420
  * manually for self-hosted.
421
- * 3. `TUNNEL_BASE_URL` + the platform assistant ID from a configured callback
421
+ * 3. `TUNNEL_BASE_URL` + the cloud assistant ID from a configured callback
422
422
  * URL or credential cache.
423
423
  *
424
424
  * Returns `undefined` when no source provides a value — the placeholder
@@ -428,7 +428,7 @@ function resolveTunnelBaseWssUrl(
428
428
  export function resolvePublicBaseWssUrl(
429
429
  config: GatewayConfig,
430
430
  configFile?: ConfigFileCache,
431
- platformAssistantId?: string,
431
+ cloudAssistantId?: string,
432
432
  validatedPublicUrl?: string,
433
433
  ): string | undefined {
434
434
  const raw = configFile?.getString("ingress", "publicBaseUrl");
@@ -450,7 +450,7 @@ export function resolvePublicBaseWssUrl(
450
450
 
451
451
  return resolveTunnelBaseWssUrl(
452
452
  config,
453
- configuredCallbackAssistantId ?? platformAssistantId,
453
+ configuredCallbackAssistantId ?? cloudAssistantId,
454
454
  );
455
455
  }
456
456
 
@@ -462,12 +462,12 @@ export function resolvePublicBaseWssUrl(
462
462
  * Sources (in priority order):
463
463
  * 1. `ingress.publicBaseUrl` from the config file — written by Tunnel after
464
464
  * tunnel registration, or set manually for self-hosted.
465
- * 2. `TUNNEL_BASE_URL` + the platform assistant ID. This mirrors the Twilio
465
+ * 2. `TUNNEL_BASE_URL` + the cloud assistant ID. This mirrors the Twilio
466
466
  * resolver's fallback and stays valid even while the tunnel is briefly
467
467
  * disconnected (Tunnel clears the config value on every reconnect), so
468
468
  * these links no longer break on a tunnel flap.
469
469
  *
470
- * The platform assistant ID is read through a lazy getter so callers that
470
+ * The cloud assistant ID is read through a lazy getter so callers that
471
471
  * resolve from the config value (self-hosted / manual URL) never load
472
472
  * identity. A transient credential-store outage must not fail those callers.
473
473
  *
@@ -476,14 +476,14 @@ export function resolvePublicBaseWssUrl(
476
476
  export async function resolvePublicHttpBaseUrl(
477
477
  config: GatewayConfig,
478
478
  configFile?: ConfigFileCache,
479
- getPlatformAssistantId?: () => Promise<string | undefined>,
479
+ getCloudAssistantId?: () => Promise<string | undefined>,
480
480
  ): Promise<string | undefined> {
481
481
  const resolved =
482
482
  normalizeHttpPublicBaseUrl(
483
483
  configFile?.getString("ingress", "publicBaseUrl"),
484
484
  ) ??
485
485
  normalizeHttpPublicBaseUrl(
486
- await resolveTunnelHttpFallback(config, getPlatformAssistantId),
486
+ await resolveTunnelHttpFallback(config, getCloudAssistantId),
487
487
  );
488
488
 
489
489
  // Drop a root-path trailing slash so callers can append `/…` without
@@ -492,18 +492,18 @@ export async function resolvePublicHttpBaseUrl(
492
492
  }
493
493
 
494
494
  /**
495
- * Build the `TUNNEL_BASE_URL/<platform-assistant-id>` fallback base URL. Only
496
- * reads the platform assistant ID (via the getter) when `tunnelBaseUrl` is
495
+ * Build the `TUNNEL_BASE_URL/<cloud-assistant-id>` fallback base URL. Only
496
+ * reads the cloud assistant ID (via the getter) when `tunnelBaseUrl` is
497
497
  * configured, so it's skipped entirely on self-hosted deployments.
498
498
  */
499
499
  async function resolveTunnelHttpFallback(
500
500
  config: GatewayConfig,
501
- getPlatformAssistantId?: () => Promise<string | undefined>,
501
+ getCloudAssistantId?: () => Promise<string | undefined>,
502
502
  ): Promise<string | undefined> {
503
- if (!config.tunnelBaseUrl || !getPlatformAssistantId) return undefined;
504
- const platformAssistantId = await getPlatformAssistantId();
505
- if (!platformAssistantId) return undefined;
506
- return config.tunnelBaseUrl.replace(/\/+$/, "") + "/" + platformAssistantId;
503
+ if (!config.tunnelBaseUrl || !getCloudAssistantId) return undefined;
504
+ const cloudAssistantId = await getCloudAssistantId();
505
+ if (!cloudAssistantId) return undefined;
506
+ return config.tunnelBaseUrl.replace(/\/+$/, "") + "/" + cloudAssistantId;
507
507
  }
508
508
 
509
509
  /**
package/src/schema.ts CHANGED
@@ -302,7 +302,7 @@ export function buildSchema(): Record<string, unknown> {
302
302
  },
303
303
  },
304
304
  "405": {
305
- description: "Method not allowed (only POST accepted)",
305
+ description: "Method not allowed, only POST accepted",
306
306
  content: {
307
307
  "application/json": {
308
308
  schema: { $ref: "#/components/schemas/ErrorResponse" },
@@ -368,7 +368,7 @@ export function buildSchema(): Record<string, unknown> {
368
368
  },
369
369
  },
370
370
  "405": {
371
- description: "Method not allowed (only POST accepted)",
371
+ description: "Method not allowed, only POST accepted",
372
372
  content: {
373
373
  "application/json": {
374
374
  schema: { $ref: "#/components/schemas/ErrorResponse" },
@@ -822,7 +822,7 @@ export function buildSchema(): Record<string, unknown> {
822
822
  "application/json": {
823
823
  schema: {
824
824
  type: "object",
825
- description: "Mailgun webhook payload (JSON).",
825
+ description: "Mailgun webhook payload as JSON.",
826
826
  },
827
827
  },
828
828
  },
@@ -945,7 +945,7 @@ export function buildSchema(): Record<string, unknown> {
945
945
  get: {
946
946
  summary: "Twilio Media Stream WebSocket",
947
947
  description:
948
- "Accepts a WebSocket upgrade from Twilio Media Streams and bidirectionally proxies frames to the assistant runtime's /v1/calls/media-stream endpoint. Handshake metadata (callSessionId and auth token) is carried in URL path segments (e.g. /webhooks/twilio/media-stream/<callSessionId>/<token>) because Twilio Media Streams does not reliably preserve query parameters across the WebSocket upgrade. Legacy query-parameter-based handshake is still supported as a fallback.",
948
+ "Accepts a WebSocket upgrade from Twilio Media Streams and bidirectionally proxies frames to the assistant runtime's /v1/calls/media-stream endpoint. Handshake metadata, the callSessionId and auth token, is carried in URL path segments, e.g. /webhooks/twilio/media-stream/<callSessionId>/<token>, because Twilio Media Streams does not reliably preserve query parameters across the WebSocket upgrade. Legacy query-parameter-based handshake is still supported as a fallback.",
949
949
  operationId: "twilioMediaStreamWebsocket",
950
950
  parameters: [
951
951
  {
@@ -1003,7 +1003,7 @@ export function buildSchema(): Record<string, unknown> {
1003
1003
  required: false,
1004
1004
  schema: { type: "string" },
1005
1005
  description:
1006
- "Optional STT provider identifier (e.g. 'deepgram', 'google-gemini'). Forwarded as compatibility metadata: the runtime resolves the transcriber from config (`services.stt.roles.dictation`, else `services.stt.provider`), not from this parameter. When supplied and it disagrees with the provider that resolves to, the runtime logs a mismatch warning.",
1006
+ "Optional STT provider identifier, e.g. 'deepgram' or 'google-gemini'. Forwarded as compatibility metadata: the runtime resolves the transcriber from config (`services.stt.roles.dictation`, else `services.stt.provider`), not from this parameter. When supplied and it disagrees with the provider that resolves to, the runtime logs a mismatch warning.",
1007
1007
  },
1008
1008
  {
1009
1009
  name: "mimeType",
@@ -1011,7 +1011,7 @@ export function buildSchema(): Record<string, unknown> {
1011
1011
  required: true,
1012
1012
  schema: { type: "string" },
1013
1013
  description:
1014
- "MIME type of the audio being streamed (e.g. 'audio/webm;codecs=opus').",
1014
+ "MIME type of the audio being streamed, e.g. 'audio/webm;codecs=opus'.",
1015
1015
  },
1016
1016
  {
1017
1017
  name: "sampleRate",
@@ -1035,7 +1035,7 @@ export function buildSchema(): Record<string, unknown> {
1035
1035
  "WebSocket upgrade successful — bidirectional STT audio/transcription frame proxying begins.",
1036
1036
  },
1037
1037
  "400": {
1038
- description: "Missing required query parameter (mimeType)",
1038
+ description: "Missing required query parameter: mimeType",
1039
1039
  content: {
1040
1040
  "text/plain": {
1041
1041
  schema: { type: "string" },
@@ -1084,7 +1084,7 @@ export function buildSchema(): Record<string, unknown> {
1084
1084
  required: true,
1085
1085
  schema: { type: "string" },
1086
1086
  description:
1087
- "MIME type of the narration audio being streamed (e.g. 'audio/pcm').",
1087
+ "MIME type of the narration audio being streamed, e.g. 'audio/pcm'.",
1088
1088
  },
1089
1089
  {
1090
1090
  name: "sampleRate",
@@ -1124,7 +1124,7 @@ export function buildSchema(): Record<string, unknown> {
1124
1124
  "WebSocket upgrade successful - bidirectional watch stream frame proxying begins.",
1125
1125
  },
1126
1126
  "400": {
1127
- description: "Missing required query parameter (mimeType)",
1127
+ description: "Missing required query parameter: mimeType",
1128
1128
  content: {
1129
1129
  "text/plain": {
1130
1130
  schema: { type: "string" },
@@ -1739,7 +1739,7 @@ export function buildSchema(): Record<string, unknown> {
1739
1739
  "404": { description: "Channel not found" },
1740
1740
  "409": {
1741
1741
  description:
1742
- "Invalid state transition (e.g. revoking a blocked channel)",
1742
+ "Invalid state transition, e.g. revoking a blocked channel",
1743
1743
  },
1744
1744
  "503": { description: "Bearer token not configured" },
1745
1745
  "502": { description: "Failed to reach assistant runtime" },
@@ -1751,7 +1751,7 @@ export function buildSchema(): Record<string, unknown> {
1751
1751
  post: {
1752
1752
  summary: "Mark a contact channel as verified by guardian attestation",
1753
1753
  description:
1754
- "Guardian-only endpoint that attests a contact channel as verified without exchanging a challenge code. The caller must be the bound guardian — verified either by JWT actor principal (laptop / docker) or by `X-Cadet-User-Id` matching the stored platform user id (platform-managed). Idempotent: an already-verified channel returns 200 without re-writing. Mutation is gateway-DB primary with a best-effort dual-write to the assistant daemon DB for sync during the gateway-security-migration transition.",
1754
+ "Guardian-only endpoint that attests a contact channel as verified without exchanging a challenge code. The caller must be the bound guardian — verified either by JWT actor principal (laptop / docker) or by `X-Cadet-User-Id` matching the stored platform user id (cloud-managed). Idempotent: an already-verified channel returns 200 without re-writing. Mutation is gateway-DB primary with a best-effort dual-write to the assistant daemon DB for sync during the gateway-security-migration transition.",
1755
1755
  operationId: "contactsChannelVerify",
1756
1756
  security: [{ BearerAuth: [] }],
1757
1757
  parameters: [
@@ -1983,7 +1983,7 @@ export function buildSchema(): Record<string, unknown> {
1983
1983
  required: false,
1984
1984
  schema: { type: "string" },
1985
1985
  description:
1986
- "Optional verification purpose (e.g. guardian, trusted-contact).",
1986
+ "Optional verification purpose, e.g. guardian or trusted-contact.",
1987
1987
  },
1988
1988
  {
1989
1989
  name: "contactChannelId",
@@ -2126,7 +2126,7 @@ export function buildSchema(): Record<string, unknown> {
2126
2126
  "Loopback-only endpoint that removes the guardian-init lock file so that /v1/guardian/init can be called again. When bootstrap secrets are configured, callers must provide a valid x-bootstrap-secret header. Used by the desktop app to recover from a lost actor token.",
2127
2127
  operationId: "guardianResetBootstrap",
2128
2128
  responses: {
2129
- "200": { description: "Lock file removed (or already absent)" },
2129
+ "200": { description: "Lock file removed, or already absent" },
2130
2130
  "403": {
2131
2131
  description:
2132
2132
  "Forbidden — non-loopback origin or invalid bootstrap secret",
@@ -2183,7 +2183,7 @@ export function buildSchema(): Record<string, unknown> {
2183
2183
  responses: {
2184
2184
  "200": { description: "New access token returned" },
2185
2185
  "400": {
2186
- description: "Missing required field (refreshToken or deviceId)",
2186
+ description: "Missing required field: refreshToken or deviceId",
2187
2187
  },
2188
2188
  "401": { description: "Unauthorized — invalid token" },
2189
2189
  "403": {
@@ -2407,7 +2407,7 @@ export function buildSchema(): Record<string, unknown> {
2407
2407
  operationId: "oauthProvidersList",
2408
2408
  parameters: [
2409
2409
  {
2410
- name: "supports_managed_mode",
2410
+ name: "supports_cloud_mode",
2411
2411
  in: "query",
2412
2412
  required: false,
2413
2413
  schema: { type: "boolean" },
@@ -2509,7 +2509,7 @@ export function buildSchema(): Record<string, unknown> {
2509
2509
  post: {
2510
2510
  summary: "Create OAuth app",
2511
2511
  description:
2512
- "Authenticated gateway endpoint that creates or updates a user-managed OAuth app by proxying to the assistant runtime.",
2512
+ "Authenticated gateway endpoint that creates or updates a user-cloud OAuth app by proxying to the assistant runtime.",
2513
2513
  operationId: "oauthAppsCreate",
2514
2514
  security: [{ BearerAuth: [] }],
2515
2515
  requestBody: {
@@ -2546,7 +2546,7 @@ export function buildSchema(): Record<string, unknown> {
2546
2546
  delete: {
2547
2547
  summary: "Delete OAuth app",
2548
2548
  description:
2549
- "Authenticated gateway endpoint that deletes a user-managed OAuth app and disconnects its linked accounts by proxying to the assistant runtime.",
2549
+ "Authenticated gateway endpoint that deletes a user-cloud OAuth app and disconnects its linked accounts by proxying to the assistant runtime.",
2550
2550
  operationId: "oauthAppsDelete",
2551
2551
  parameters: [
2552
2552
  {
@@ -3314,11 +3314,11 @@ export function buildSchema(): Record<string, unknown> {
3314
3314
  properties: {
3315
3315
  startTime: {
3316
3316
  type: "number",
3317
- description: "Start of time range (epoch ms)",
3317
+ description: "Start of time range, in epoch ms",
3318
3318
  },
3319
3319
  endTime: {
3320
3320
  type: "number",
3321
- description: "End of time range (epoch ms)",
3321
+ description: "End of time range, in epoch ms",
3322
3322
  },
3323
3323
  auditLimit: {
3324
3324
  type: "number",
@@ -3381,7 +3381,7 @@ export function buildSchema(): Record<string, unknown> {
3381
3381
  enum: ["trace", "debug", "info", "warn", "error", "fatal"],
3382
3382
  default: "info",
3383
3383
  },
3384
- description: "Minimum pino level name (default: info)",
3384
+ description: "Minimum pino level name, defaults to info",
3385
3385
  },
3386
3386
  {
3387
3387
  name: "module",
@@ -3427,7 +3427,7 @@ export function buildSchema(): Record<string, unknown> {
3427
3427
  get: {
3428
3428
  summary: "List trust rules",
3429
3429
  description:
3430
- "Authenticated gateway endpoint that lists trust rules from the SQLite-backed store. By default returns user-relevant rules (user_defined + user-modified defaults). Supports `origin`, `tool`, and `include_deleted` query filters.",
3430
+ "Authenticated gateway endpoint that lists trust rules from the SQLite-backed store. By default returns user-relevant rules: user_defined + user-modified defaults. Supports `origin`, `tool`, and `include_deleted` query filters.",
3431
3431
  operationId: "trustRulesGet",
3432
3432
  security: [{ BearerAuth: [] }],
3433
3433
  parameters: [
@@ -3752,7 +3752,7 @@ export function buildSchema(): Record<string, unknown> {
3752
3752
  post: {
3753
3753
  summary: "Resolve the effective channel-permission threshold",
3754
3754
  description:
3755
- "Authenticated gateway endpoint that resolves the cascade for one coordinate (adapter, optional channelType/channelExternalId, contact-type) and returns the winning cell's threshold and scope, or null when no cell matches so the caller falls through to the global thresholds. Read-only; a POST verb path because the composite query travels in the body, same rationale as /delete.",
3755
+ "Authenticated gateway endpoint that resolves the cascade for one coordinate — adapter, optional channelType/channelExternalId, contact-type — and returns the winning cell's threshold and scope, or null when no cell matches so the caller falls through to the global thresholds. Read-only; a POST verb path because the composite query travels in the body, same rationale as /delete.",
3756
3756
  operationId: "channelPermissionResolve",
3757
3757
  security: [{ BearerAuth: [] }],
3758
3758
  requestBody: {
@@ -3764,7 +3764,7 @@ export function buildSchema(): Record<string, unknown> {
3764
3764
  },
3765
3765
  },
3766
3766
  responses: {
3767
- "200": { description: "Resolution returned (resolved or null)" },
3767
+ "200": { description: "Resolution returned — resolved or null" },
3768
3768
  "400": { description: "Invalid request payload or adapter" },
3769
3769
  "401": {
3770
3770
  description: "Unauthorized — missing or invalid bearer token",
@@ -3777,7 +3777,7 @@ export function buildSchema(): Record<string, unknown> {
3777
3777
  post: {
3778
3778
  summary: "Delete a channel-permission matrix cell",
3779
3779
  description:
3780
- "Authenticated gateway endpoint that removes one channel-permission cell by its composite key (selector × contact-type), letting the next cascade tier up win. A POST verb path because cells have no row id and DELETE request bodies are unreliable through proxies.",
3780
+ "Authenticated gateway endpoint that removes one channel-permission cell by its composite key, selector × contact-type, letting the next cascade tier up win. A POST verb path because cells have no row id and DELETE request bodies are unreliable through proxies.",
3781
3781
  operationId: "channelPermissionOverrideDelete",
3782
3782
  security: [{ BearerAuth: [] }],
3783
3783
  requestBody: {
@@ -4152,7 +4152,7 @@ export function buildSchema(): Record<string, unknown> {
4152
4152
  post: {
4153
4153
  summary: "Kick off an async export-to-GCS job",
4154
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.",
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
4156
  operationId: "migrationExportToGcs",
4157
4157
  security: [{ BearerAuth: [] }],
4158
4158
  requestBody: {
@@ -4191,7 +4191,7 @@ export function buildSchema(): Record<string, unknown> {
4191
4191
  post: {
4192
4192
  summary: "Kick off an async import-from-GCS job",
4193
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.",
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
4195
  operationId: "migrationImportFromGcs",
4196
4196
  security: [{ BearerAuth: [] }],
4197
4197
  requestBody: {
@@ -4241,7 +4241,7 @@ export function buildSchema(): Record<string, unknown> {
4241
4241
  get: {
4242
4242
  summary: "Poll unified migration job status",
4243
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.",
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
4245
  operationId: "migrationJobStatus",
4246
4246
  security: [{ BearerAuth: [] }],
4247
4247
  parameters: [
@@ -4346,7 +4346,7 @@ export function buildSchema(): Record<string, unknown> {
4346
4346
  post: {
4347
4347
  summary: "Auto-verify guardian email",
4348
4348
  description:
4349
- "Called by the platform to auto-verify the guardian's email channel. For BYO providers (resend, mailgun), validates the provider API key. For platform-managed email (cadet), the route's auth is sufficient. Creates a guardian email channel binding.",
4349
+ "Called by the cloud to auto-verify the guardian's email channel. For BYO providers (resend, mailgun), validates the provider API key. For cloud-managed email (cadet), the route's auth is sufficient. Creates a guardian email channel binding.",
4350
4350
  operationId: "inboundRegister",
4351
4351
  security: [{ BearerAuth: [] }],
4352
4352
  requestBody: {
@@ -4360,7 +4360,7 @@ export function buildSchema(): Record<string, unknown> {
4360
4360
  type: {
4361
4361
  type: "string",
4362
4362
  description:
4363
- "Email provider type (e.g. resend, mailgun, cadet)",
4363
+ "Email provider type, e.g. resend, mailgun, cadet",
4364
4364
  },
4365
4365
  guardian_email: {
4366
4366
  type: "string",
@@ -39,7 +39,6 @@ const baseConfig: GatewayConfig = {
39
39
  runtimeMaxRetries: 2,
40
40
  runtimeProxyRequireAuth: true,
41
41
  runtimeTimeoutMs: 30000,
42
- shutdownDrainMs: 5000,
43
42
  trustProxy: false,
44
43
  };
45
44