@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.
- package/README.md +3 -3
- package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/package.json +2 -2
- package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/{platform-credential.ts → cloud-credential.ts} +9 -9
- package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/handles.ts +3 -3
- package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/index.ts +1 -1
- package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/ingress.ts +11 -5
- package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/remote-web-pairing.ts +1 -1
- package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/rpc.ts +14 -14
- package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/trust-rules.ts +5 -5
- package/node_modules/@mycadet/ces-client/package.json +1 -1
- package/node_modules/@mycadet/ces-client/src/__tests__/ces-client.test.ts +14 -14
- package/node_modules/@mycadet/ces-client/src/rpc-client.ts +1 -1
- 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/gateway-client/node_modules/@mycadet/service-contracts/package.json +2 -2
- package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/{platform-credential.ts → cloud-credential.ts} +9 -9
- package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/handles.ts +3 -3
- package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/index.ts +1 -1
- package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/ingress.ts +11 -5
- package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/remote-web-pairing.ts +1 -1
- package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/rpc.ts +14 -14
- package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/trust-rules.ts +5 -5
- package/node_modules/@mycadet/gateway-client/src/binding-strength-contract.ts +5 -5
- package/node_modules/@mycadet/gateway-client/src/gateway-ipc-contracts.ts +1 -1
- package/node_modules/@mycadet/gateway-client/src/inbound-contract.ts +2 -2
- package/node_modules/@mycadet/gateway-client/src/outbound-contract.ts +1 -1
- package/node_modules/@mycadet/service-contracts/package.json +2 -2
- package/node_modules/@mycadet/service-contracts/src/{platform-credential.ts → 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/openapi.json +17 -17
- package/package.json +1 -1
- package/scripts/generate-openapi.ts +1 -1
- package/src/__tests__/actor-token-revocation.test.ts +0 -1
- package/src/__tests__/{backup-worker-platform-mode.test.ts → backup-worker-cloud-mode.test.ts} +4 -4
- package/src/__tests__/channel-verification-session-proxy.test.ts +0 -1
- package/src/__tests__/{platform-identity.test.ts → cloud-identity.test.ts} +72 -86
- package/src/__tests__/config.test.ts +0 -24
- package/src/__tests__/contacts-control-plane-proxy.test.ts +0 -1
- package/src/__tests__/credential-requests.test.ts +6 -6
- package/src/__tests__/{credential-watcher-managed-bootstrap.test.ts → credential-watcher-cloud-bootstrap.test.ts} +1 -1
- package/src/__tests__/edge-auth.test.ts +18 -18
- package/src/__tests__/edge-guardian-auth.test.ts +10 -10
- package/src/__tests__/guardian-init-lockfile.test.ts +6 -8
- package/src/__tests__/guardian-pin.test.ts +8 -8
- package/src/__tests__/handle-inbound-admission.test.ts +0 -1
- package/src/__tests__/handle-inbound-app-context.test.ts +0 -1
- package/src/__tests__/handle-inbound-invite-intercept.test.ts +0 -1
- package/src/__tests__/handle-inbound-trust-verdict.test.ts +0 -1
- package/src/__tests__/inbound-contact-seed.test.ts +1 -1
- package/src/__tests__/live-voice-websocket.test.ts +12 -12
- package/src/__tests__/load-guards.test.ts +0 -1
- package/src/__tests__/migration-teleport-gcs-proxy.test.ts +0 -1
- package/src/__tests__/oauth-callback.test.ts +0 -1
- package/src/__tests__/remote-feature-flag-sync.test.ts +35 -45
- package/src/__tests__/resolve-assistant.test.ts +0 -1
- package/src/__tests__/route-schema-guard.test.ts +4 -1
- package/src/__tests__/runtime-client.test.ts +1 -2
- package/src/__tests__/runtime-health-proxy.test.ts +0 -1
- package/src/__tests__/runtime-proxy-auth.test.ts +3 -2
- package/src/__tests__/runtime-proxy-device-stamp.test.ts +0 -1
- package/src/__tests__/runtime-proxy-error-body.test.ts +0 -1
- package/src/__tests__/runtime-proxy.test.ts +0 -1
- package/src/__tests__/runtime-stream-test-utils.ts +0 -1
- package/src/__tests__/shared-invite-registration.test.ts +15 -32
- package/src/__tests__/slack-control-plane-proxy.test.ts +0 -1
- package/src/__tests__/slack-display-name.test.ts +0 -1
- package/src/__tests__/slack-normalize.test.ts +0 -1
- package/src/__tests__/slack-reaction-normalize.test.ts +0 -1
- package/src/__tests__/slack-socket-mode-catchup.test.ts +0 -1
- package/src/__tests__/slack-socket-mode-group-dm.test.ts +0 -1
- package/src/__tests__/slack-socket-mode-liveness.test.ts +0 -1
- package/src/__tests__/slack-socket-mode-outbound-root.test.ts +0 -1
- package/src/__tests__/slack-socket-mode-thread-tracking.test.ts +0 -1
- package/src/__tests__/speech-relay-websocket.test.ts +16 -14
- package/src/__tests__/stt-stream-websocket.test.ts +5 -5
- package/src/__tests__/telegram-control-plane-proxy.test.ts +0 -1
- package/src/__tests__/telegram-webhook-drop-visibility.test.ts +0 -1
- package/src/__tests__/telegram-webhook-handler.test.ts +0 -1
- package/src/__tests__/telegram-webhook-manager.test.ts +79 -80
- package/src/__tests__/twilio-media-websocket.test.ts +0 -1
- package/src/__tests__/twilio-webhooks.test.ts +6 -7
- package/src/__tests__/whatsapp-download.test.ts +0 -1
- package/src/__tests__/whatsapp-webhook.test.ts +0 -1
- package/src/attachments/ingest.test.ts +0 -1
- package/src/auth/guardian-bootstrap.ts +16 -15
- package/src/auth/scopes.ts +1 -1
- package/src/auth-fallback-reporter.ts +1 -1
- package/src/backup/backup-worker.ts +2 -2
- package/src/channels/inbound-event.ts +3 -3
- package/src/channels/ingress-inbound-vendors.test.ts +2 -2
- package/src/channels/ingress-inbound.ts +1 -1
- package/src/channels/ingress-verification.test.ts +2 -2
- package/src/channels/ingress-verification.ts +4 -4
- package/src/channels/plugin-ingress-approvals.test.ts +1 -1
- package/src/channels/plugin-ingress-approvals.ts +1 -1
- package/src/channels/plugin-ingress.test.ts +3 -3
- package/src/channels/plugin-ingress.ts +3 -3
- package/src/channels/room-admission.ts +2 -2
- package/src/cli/contacts.ts +3 -1
- package/src/cli/index.ts +1 -1
- package/src/{platform-identity.ts → cloud-identity.ts} +60 -68
- package/src/cloud-url.ts +25 -0
- package/src/{platform-user-id.ts → cloud-user-id.ts} +4 -4
- package/src/config.ts +2 -4
- package/src/credential-reader.ts +2 -2
- package/src/db/assistant-db-proxy.ts +1 -1
- package/src/discord/forward.ts +1 -1
- package/src/email/normalize.ts +4 -4
- package/src/email/register-callback.test.ts +27 -34
- package/src/email/register-callback.ts +21 -26
- package/src/feature-flag-registry.json +5 -5
- package/src/feature-flag-remote-store.ts +2 -2
- package/src/feature-flag-resolver.ts +5 -5
- package/src/http/cadet-signature.ts +1 -1
- package/src/http/edge-forwarded-header.ts +1 -1
- package/src/http/loopback-guard.ts +1 -1
- package/src/http/middleware/auth.ts +22 -22
- package/src/http/router.ts +1 -1
- package/src/http/routes/auto-approve-thresholds-routes.ts +1 -1
- package/src/http/routes/cadet-identity.ts +2 -2
- package/src/http/routes/channel-admission-policy-routes.ts +2 -2
- package/src/http/routes/channel-ingress-routes.ts +3 -3
- package/src/http/routes/channel-ingress.test.ts +13 -2
- package/src/http/routes/channel-permission-overrides-routes.ts +3 -3
- package/src/http/routes/channel-verification-session-proxy.ts +8 -22
- package/src/http/routes/{platform-push-proxy.test.ts → cloud-push-proxy.test.ts} +21 -22
- package/src/http/routes/{platform-push-proxy.ts → cloud-push-proxy.ts} +13 -14
- package/src/http/routes/contacts-control-plane-proxy.ts +3 -3
- package/src/http/routes/contacts-control-plane-routes.ts +5 -5
- package/src/http/routes/email-webhook.test.ts +2 -3
- package/src/http/routes/email-webhook.ts +4 -4
- package/src/http/routes/feature-flags.ts +1 -1
- package/src/http/routes/guardian-channel-create.ts +3 -3
- package/src/http/routes/guardian-pin.ts +9 -9
- package/src/http/routes/inbound-register.ts +2 -2
- package/src/http/routes/ingress-domains.test.ts +129 -0
- package/src/http/routes/ingress-domains.ts +73 -0
- package/src/http/routes/live-voice-websocket.ts +2 -2
- package/src/http/routes/log-export.test.ts +0 -1
- package/src/http/routes/log-tail.test.ts +0 -1
- package/src/http/routes/migration-proxy.ts +1 -1
- package/src/http/routes/plugin-webhook-websocket.test.ts +3 -3
- package/src/http/routes/plugin-webhook.test.ts +9 -8
- package/src/http/routes/plugin-webhook.ts +1 -1
- package/src/http/routes/speech-relay-websocket.ts +8 -11
- package/src/http/routes/stt-stream-websocket.ts +1 -1
- package/src/http/routes/telegram-webhook.test.ts +0 -1
- package/src/http/routes/trust-rules-routes.ts +2 -2
- package/src/http/routes/twilio-voice-verify-callback.ts +3 -3
- package/src/http/routes/twilio-voice-webhook.test.ts +3 -4
- package/src/http/routes/twilio-voice-webhook.ts +3 -3
- package/src/http/routes/whatsapp-webhook.test.ts +0 -1
- package/src/index.ts +57 -56
- package/src/ipc/credential-request-handlers.ts +4 -4
- package/src/ipc/debug-export-handlers.test.ts +0 -1
- package/src/ipc/log-tail-handlers.test.ts +0 -1
- package/src/ipc/risk-classification-handlers.test.ts +4 -4
- package/src/ipc/risk-classification-handlers.ts +2 -2
- package/src/remote-feature-flag-sync.ts +17 -19
- package/src/risk/command-registry/commands/assistant.ts +2 -2
- package/src/risk/skill-risk-classifier.test.ts +24 -24
- package/src/risk/skill-risk-classifier.ts +10 -10
- package/src/runtime/client.ts +17 -17
- package/src/schema.ts +29 -29
- package/src/telegram/send.test.ts +0 -1
- package/src/telegram/webhook-manager.ts +33 -38
- package/src/tunnel/allowed-paths.test.ts +3 -3
- package/src/tunnel/allowed-paths.ts +1 -1
- package/src/tunnel/client.test.ts +20 -21
- package/src/tunnel/client.ts +16 -17
- package/src/verification/shared-invite-registration.ts +22 -17
- package/src/version.ts +1 -1
- package/src/platform-url.ts +0 -24
package/README.md
CHANGED
|
@@ -210,9 +210,9 @@ The assistant runtime uses this URL to construct all webhook and OAuth callback
|
|
|
210
210
|
|
|
211
211
|
### Tunnel for Twilio Testing
|
|
212
212
|
|
|
213
|
-
Tunnel is a
|
|
213
|
+
Tunnel is a cloud ingress transport for assistant-hosted HTTP and WebSocket traffic. The gateway starts the Tunnel only after Twilio setup has been started in the workspace, or when existing Twilio config shows it was set up before. When Tunnel registration succeeds, the gateway writes the registered public assistant URL to `ingress.publicBaseUrl` and marks it with `ingress.publicBaseUrlManagedBy: "tunnel"`. Twilio URL builders use that public base URL for voice, status, and media-stream endpoints.
|
|
214
214
|
|
|
215
|
-
Use Tunnel when testing Twilio voice webhooks or Twilio WebSocket upgrades through the
|
|
215
|
+
Use Tunnel when testing Twilio voice webhooks or Twilio WebSocket upgrades through the cloud-managed tunnel:
|
|
216
216
|
|
|
217
217
|
1. In `mycadet-platform`, start the local Tunnel service:
|
|
218
218
|
|
|
@@ -248,7 +248,7 @@ bun -e 'const ws = new WebSocket(process.argv[1]); ws.onopen = () => { console.l
|
|
|
248
248
|
"wss://<tunnel-host>/<assistant-id>/webhooks/twilio/media-stream/session-123/<edge-token>"
|
|
249
249
|
```
|
|
250
250
|
|
|
251
|
-
For a real Twilio call, expose local Tunnel with a public HTTPS/WSS tunnel and configure the
|
|
251
|
+
For a real Twilio call, expose local Tunnel with a public HTTPS/WSS tunnel and configure the cloud Tunnel service with that origin as `TUNNEL_PUBLIC_BASE_URL`. After the assistant re-registers, Twilio should fetch `/webhooks/twilio/voice` and open `/webhooks/twilio/media-stream/...` through the Tunnel URL. Use ngrok or another custom tunnel in `ingress.publicBaseUrl` only for local/self-hosted workflows that are not routed through Tunnel.
|
|
252
252
|
|
|
253
253
|
## Ingress Boundary Guarantees
|
|
254
254
|
|
package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/package.json
CHANGED
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"./error": "./src/error.ts",
|
|
27
27
|
"./reactions": "./src/reactions.ts",
|
|
28
28
|
"./guardian-requests": "./src/guardian-requests.ts",
|
|
29
|
-
"./
|
|
29
|
+
"./cloud-credential": "./src/cloud-credential.ts",
|
|
30
30
|
"./plan-credit": "./src/plan-credit.ts",
|
|
31
31
|
"./integration-categories": "./src/integration-categories.ts",
|
|
32
32
|
"./mcp-oauth": "./src/mcp-oauth.ts"
|
|
@@ -40,6 +40,6 @@
|
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@types/bun": "1.2.4",
|
|
43
|
-
"typescript": "5.
|
|
43
|
+
"typescript": "5.9.3"
|
|
44
44
|
}
|
|
45
45
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Wire contract for asking an assistant whether its stored
|
|
2
|
+
* Wire contract for asking an assistant whether its stored cloud-managed
|
|
3
3
|
* credential still authenticates.
|
|
4
4
|
*
|
|
5
5
|
* The daemon route is the authoritative serving side:
|
|
6
6
|
* - `POST /v1/platform/verify-credential`
|
|
7
|
-
* (`assistant/src/runtime/routes/
|
|
7
|
+
* (`assistant/src/runtime/routes/cloud-routes.ts`)
|
|
8
8
|
*
|
|
9
9
|
* The daemon's platform client produces the verdict, the route reports it,
|
|
10
10
|
* and the `cadet` CLI reads it before deciding whether a stored key can be
|
|
@@ -15,26 +15,26 @@
|
|
|
15
15
|
import { z } from "zod";
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
* What the
|
|
18
|
+
* What the cloud said about the stored credential, right now.
|
|
19
19
|
*
|
|
20
|
-
* - `valid`: the
|
|
21
|
-
* - `rejected`: the
|
|
20
|
+
* - `valid`: the cloud accepted it.
|
|
21
|
+
* - `rejected`: the cloud refused it (unauthorized or forbidden); the
|
|
22
22
|
* credential needs replacing.
|
|
23
23
|
* - `unknown`: the check itself could not run (no credential stored, the
|
|
24
24
|
* platform unreachable, a server error). Not evidence either way.
|
|
25
25
|
*/
|
|
26
|
-
export const
|
|
26
|
+
export const CloudCredentialVerificationStatusSchema = z.enum([
|
|
27
27
|
"valid",
|
|
28
28
|
"rejected",
|
|
29
29
|
"unknown",
|
|
30
30
|
]);
|
|
31
|
-
export type
|
|
32
|
-
typeof
|
|
31
|
+
export type CloudCredentialVerificationStatus = z.infer<
|
|
32
|
+
typeof CloudCredentialVerificationStatusSchema
|
|
33
33
|
>;
|
|
34
34
|
|
|
35
35
|
/** `POST /v1/platform/verify-credential` response body. */
|
|
36
36
|
export const PlatformVerifyCredentialResponseSchema = z.object({
|
|
37
|
-
status:
|
|
37
|
+
status: CloudCredentialVerificationStatusSchema,
|
|
38
38
|
});
|
|
39
39
|
export type PlatformVerifyCredentialResponse = z.infer<
|
|
40
40
|
typeof PlatformVerifyCredentialResponseSchema
|
package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/handles.ts
CHANGED
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
* Format: `local_oauth:<providerKey>/<connectionId>` where providerKey
|
|
16
16
|
* is the bare provider name (e.g. `google`).
|
|
17
17
|
*
|
|
18
|
-
* 3. **
|
|
18
|
+
* 3. **Cloud OAuth** — references an OAuth connection managed by the
|
|
19
19
|
* platform. Format: `platform_oauth:<connectionId>` where connectionId
|
|
20
|
-
* is the
|
|
20
|
+
* is the cloud-assigned connection identifier.
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
23
|
import { z } from "zod";
|
|
@@ -96,7 +96,7 @@ export function localOAuthHandle(
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
/**
|
|
99
|
-
* Build a
|
|
99
|
+
* Build a cloud (platform) OAuth credential handle from a connection ID.
|
|
100
100
|
*/
|
|
101
101
|
export function platformOAuthHandle(connectionId: string): string {
|
|
102
102
|
return `${HandleType.PlatformOAuth}:${connectionId}`;
|
package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/index.ts
CHANGED
|
@@ -31,7 +31,7 @@ export * from "./no-response.js";
|
|
|
31
31
|
export * from "./plan-credit.js";
|
|
32
32
|
export * from "./integration-categories.js";
|
|
33
33
|
export * from "./mcp-oauth.js";
|
|
34
|
-
export * from "./
|
|
34
|
+
export * from "./cloud-credential.js";
|
|
35
35
|
export * from "./remote-web-pairing.js";
|
|
36
36
|
export * from "./twilio-ingress.js";
|
|
37
37
|
export * from "./url-normalization.js";
|
package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/ingress.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* `{env}-cloud.mycadet.ai` → `tunnel-{env}.mycadet.ai`). Returns null for
|
|
5
5
|
* hosts outside that convention (localhost, custom domains). Shared by the
|
|
6
6
|
* gateway speech relay and the web live-voice client so the two ends of the
|
|
7
|
-
*
|
|
7
|
+
* cloud-speech transport can't drift.
|
|
8
8
|
*/
|
|
9
9
|
export function tunnelHostForPlatformHost(host: string): string | null {
|
|
10
10
|
if (host === "cloud.mycadet.ai") {
|
|
@@ -100,11 +100,17 @@ export const INGRESS_PAIRING_TUNNEL_KEY = "pairingTunnel";
|
|
|
100
100
|
export const INGRESS_ASSISTANT_ID_KEY = "assistantId";
|
|
101
101
|
|
|
102
102
|
/**
|
|
103
|
-
* The
|
|
104
|
-
* `cadet tunnel
|
|
105
|
-
*
|
|
103
|
+
* The tunnel providers the CLI offers, in the order they are presented —
|
|
104
|
+
* the managed `cadet` tunnel first (listed, not yet implemented), then the
|
|
105
|
+
* local ones. `cadet tunnel`'s accepted `--provider` values and the
|
|
106
|
+
* persisted-record validation below both derive from it.
|
|
106
107
|
*/
|
|
107
|
-
export const TUNNEL_PROVIDERS = [
|
|
108
|
+
export const TUNNEL_PROVIDERS = [
|
|
109
|
+
"cadet",
|
|
110
|
+
"ngrok",
|
|
111
|
+
"cloudflare",
|
|
112
|
+
"tailscale",
|
|
113
|
+
] as const;
|
|
108
114
|
|
|
109
115
|
export type TunnelProviderName = (typeof TUNNEL_PROVIDERS)[number];
|
|
110
116
|
|
|
@@ -152,7 +152,7 @@ export const DEFAULT_REMOTE_WEB_PAIRING_PLATFORM: RemoteWebPairingPlatform =
|
|
|
152
152
|
|
|
153
153
|
/**
|
|
154
154
|
* A requested platform coerced to a known value. The pairing-token route is
|
|
155
|
-
* publicly reachable and the
|
|
155
|
+
* publicly reachable and the cloud renders verbatim in the host's
|
|
156
156
|
* paired-devices list, so an unrecognized value never reaches the DB.
|
|
157
157
|
*/
|
|
158
158
|
export function resolveRemoteWebPairingPlatform(
|
|
@@ -34,7 +34,7 @@ import { RpcErrorSchema } from "./error.js";
|
|
|
34
34
|
|
|
35
35
|
export const CesRpcMethod = {
|
|
36
36
|
/** Push an updated assistant credential to CES after post-hatch provisioning. */
|
|
37
|
-
|
|
37
|
+
UpdateCloudCredential: "update_managed_credential",
|
|
38
38
|
/** Retrieve a single credential by account name. */
|
|
39
39
|
GetCredential: "get_credential",
|
|
40
40
|
/** Store or update a credential by account name. */
|
|
@@ -63,7 +63,7 @@ export type CesRpcMethod = (typeof CesRpcMethod)[keyof typeof CesRpcMethod];
|
|
|
63
63
|
// update_managed_credential
|
|
64
64
|
// ---------------------------------------------------------------------------
|
|
65
65
|
|
|
66
|
-
export const
|
|
66
|
+
export const UpdateCloudCredentialSchema = z.object({
|
|
67
67
|
/** The assistant API key to push to CES for platform credential materialization. */
|
|
68
68
|
assistantApiKey: z.string(), // nosemgrep: not-a-secret
|
|
69
69
|
/**
|
|
@@ -72,16 +72,16 @@ export const UpdateManagedCredentialSchema = z.object({
|
|
|
72
72
|
*/
|
|
73
73
|
assistantId: z.string().optional(),
|
|
74
74
|
});
|
|
75
|
-
export type
|
|
76
|
-
typeof
|
|
75
|
+
export type UpdateCloudCredential = z.infer<
|
|
76
|
+
typeof UpdateCloudCredentialSchema
|
|
77
77
|
>;
|
|
78
78
|
|
|
79
|
-
export const
|
|
80
|
-
/** Whether the
|
|
79
|
+
export const UpdateCloudCredentialResponseSchema = z.object({
|
|
80
|
+
/** Whether the cloud credential was successfully updated. */
|
|
81
81
|
updated: z.boolean(),
|
|
82
82
|
});
|
|
83
|
-
export type
|
|
84
|
-
typeof
|
|
83
|
+
export type UpdateCloudCredentialResponse = z.infer<
|
|
84
|
+
typeof UpdateCloudCredentialResponseSchema
|
|
85
85
|
>;
|
|
86
86
|
|
|
87
87
|
// ---------------------------------------------------------------------------
|
|
@@ -311,9 +311,9 @@ export type BulkSetCredentialRecordsResponse = z.infer<
|
|
|
311
311
|
* schemas. Useful for building type-safe RPC dispatch layers.
|
|
312
312
|
*/
|
|
313
313
|
export interface CesRpcContract {
|
|
314
|
-
[CesRpcMethod.
|
|
315
|
-
request:
|
|
316
|
-
response:
|
|
314
|
+
[CesRpcMethod.UpdateCloudCredential]: {
|
|
315
|
+
request: UpdateCloudCredential;
|
|
316
|
+
response: UpdateCloudCredentialResponse;
|
|
317
317
|
};
|
|
318
318
|
[CesRpcMethod.GetCredential]: {
|
|
319
319
|
request: GetCredential;
|
|
@@ -361,9 +361,9 @@ export interface CesRpcContract {
|
|
|
361
361
|
* Schema lookup map for runtime validation of RPC payloads.
|
|
362
362
|
*/
|
|
363
363
|
export const CesRpcSchemas = {
|
|
364
|
-
[CesRpcMethod.
|
|
365
|
-
request:
|
|
366
|
-
response:
|
|
364
|
+
[CesRpcMethod.UpdateCloudCredential]: {
|
|
365
|
+
request: UpdateCloudCredentialSchema,
|
|
366
|
+
response: UpdateCloudCredentialResponseSchema,
|
|
367
367
|
},
|
|
368
368
|
[CesRpcMethod.GetCredential]: {
|
|
369
369
|
request: GetCredentialSchema,
|
package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/trust-rules.ts
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* - **URL**: tools whose candidates include a URL (`web_fetch`,
|
|
16
16
|
* `network_request`).
|
|
17
17
|
* - **Managed skill**: tools that manage first-party skill packages
|
|
18
|
-
* (`
|
|
18
|
+
* (`scaffold_cloud_skill`, `delete_cloud_skill`).
|
|
19
19
|
* - **Skill load**: the `skill_load` tool, which uses a distinct candidate
|
|
20
20
|
* namespace (`skill_load:selector` or `skill_load_dynamic:selector`).
|
|
21
21
|
* - **Generic**: everything else (computer-use tools, UI surface tools,
|
|
@@ -58,8 +58,8 @@ export const URL_TOOLS = ["web_fetch", "network_request"] as const;
|
|
|
58
58
|
* Tools that manage first-party skill packages (scaffold/delete).
|
|
59
59
|
*/
|
|
60
60
|
export const MANAGED_SKILL_TOOLS = [
|
|
61
|
-
"
|
|
62
|
-
"
|
|
61
|
+
"scaffold_cloud_skill",
|
|
62
|
+
"delete_cloud_skill",
|
|
63
63
|
] as const;
|
|
64
64
|
|
|
65
65
|
/**
|
|
@@ -89,8 +89,8 @@ export function isUrlRule(rule: { tool: string }): boolean {
|
|
|
89
89
|
return URL_TOOLS_SET.has(rule.tool);
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
/** Returns true when the rule's tool belongs to the
|
|
93
|
-
export function
|
|
92
|
+
/** Returns true when the rule's tool belongs to the cloud-skill-tool family. */
|
|
93
|
+
export function isCloudSkillRule(rule: { tool: string }): boolean {
|
|
94
94
|
return MANAGED_SKILL_TOOLS_SET.has(rule.tool);
|
|
95
95
|
}
|
|
96
96
|
|
|
@@ -141,7 +141,7 @@ describe("CesHttpCredentialClient", () => {
|
|
|
141
141
|
Promise.resolve(
|
|
142
142
|
Response.json({ account: "test-acct", value: "secret-123" }),
|
|
143
143
|
),
|
|
144
|
-
) as typeof fetch;
|
|
144
|
+
) as unknown as typeof fetch;
|
|
145
145
|
|
|
146
146
|
const client = createCesHttpCredentialClient(
|
|
147
147
|
createTestConfig(),
|
|
@@ -156,7 +156,7 @@ describe("CesHttpCredentialClient", () => {
|
|
|
156
156
|
test("get returns not-found on 404", async () => {
|
|
157
157
|
globalThis.fetch = mock(() =>
|
|
158
158
|
Promise.resolve(new Response(null, { status: 404 })),
|
|
159
|
-
) as typeof fetch;
|
|
159
|
+
) as unknown as typeof fetch;
|
|
160
160
|
|
|
161
161
|
const client = createCesHttpCredentialClient(
|
|
162
162
|
createTestConfig(),
|
|
@@ -171,7 +171,7 @@ describe("CesHttpCredentialClient", () => {
|
|
|
171
171
|
test("get returns unreachable on 500", async () => {
|
|
172
172
|
globalThis.fetch = mock(() =>
|
|
173
173
|
Promise.resolve(new Response("internal error", { status: 500 })),
|
|
174
|
-
) as typeof fetch;
|
|
174
|
+
) as unknown as typeof fetch;
|
|
175
175
|
|
|
176
176
|
const client = createCesHttpCredentialClient(
|
|
177
177
|
createTestConfig(),
|
|
@@ -186,7 +186,7 @@ describe("CesHttpCredentialClient", () => {
|
|
|
186
186
|
test("get returns unreachable on network error", async () => {
|
|
187
187
|
globalThis.fetch = mock(() =>
|
|
188
188
|
Promise.reject(new Error("ECONNREFUSED")),
|
|
189
|
-
) as typeof fetch;
|
|
189
|
+
) as unknown as typeof fetch;
|
|
190
190
|
|
|
191
191
|
const client = createCesHttpCredentialClient(
|
|
192
192
|
createTestConfig(),
|
|
@@ -201,7 +201,7 @@ describe("CesHttpCredentialClient", () => {
|
|
|
201
201
|
test("delete returns deleted on 200", async () => {
|
|
202
202
|
globalThis.fetch = mock(() =>
|
|
203
203
|
Promise.resolve(Response.json({ ok: true, account: "acct" })),
|
|
204
|
-
) as typeof fetch;
|
|
204
|
+
) as unknown as typeof fetch;
|
|
205
205
|
|
|
206
206
|
const client = createCesHttpCredentialClient(
|
|
207
207
|
createTestConfig(),
|
|
@@ -215,7 +215,7 @@ describe("CesHttpCredentialClient", () => {
|
|
|
215
215
|
test("delete returns not-found on 404", async () => {
|
|
216
216
|
globalThis.fetch = mock(() =>
|
|
217
217
|
Promise.resolve(new Response(null, { status: 404 })),
|
|
218
|
-
) as typeof fetch;
|
|
218
|
+
) as unknown as typeof fetch;
|
|
219
219
|
|
|
220
220
|
const client = createCesHttpCredentialClient(
|
|
221
221
|
createTestConfig(),
|
|
@@ -229,7 +229,7 @@ describe("CesHttpCredentialClient", () => {
|
|
|
229
229
|
test("delete returns error on network failure", async () => {
|
|
230
230
|
globalThis.fetch = mock(() =>
|
|
231
231
|
Promise.reject(new Error("network down")),
|
|
232
|
-
) as typeof fetch;
|
|
232
|
+
) as unknown as typeof fetch;
|
|
233
233
|
|
|
234
234
|
const client = createCesHttpCredentialClient(
|
|
235
235
|
createTestConfig(),
|
|
@@ -243,7 +243,7 @@ describe("CesHttpCredentialClient", () => {
|
|
|
243
243
|
test("list returns accounts on 200", async () => {
|
|
244
244
|
globalThis.fetch = mock(() =>
|
|
245
245
|
Promise.resolve(Response.json({ accounts: ["a", "b", "c"] })),
|
|
246
|
-
) as typeof fetch;
|
|
246
|
+
) as unknown as typeof fetch;
|
|
247
247
|
|
|
248
248
|
const client = createCesHttpCredentialClient(
|
|
249
249
|
createTestConfig(),
|
|
@@ -258,7 +258,7 @@ describe("CesHttpCredentialClient", () => {
|
|
|
258
258
|
test("list returns unreachable on error", async () => {
|
|
259
259
|
globalThis.fetch = mock(() =>
|
|
260
260
|
Promise.reject(new Error("timeout")),
|
|
261
|
-
) as typeof fetch;
|
|
261
|
+
) as unknown as typeof fetch;
|
|
262
262
|
|
|
263
263
|
const client = createCesHttpCredentialClient(
|
|
264
264
|
createTestConfig(),
|
|
@@ -273,7 +273,7 @@ describe("CesHttpCredentialClient", () => {
|
|
|
273
273
|
test("bulkSet returns all-failed when request fails", async () => {
|
|
274
274
|
globalThis.fetch = mock(() =>
|
|
275
275
|
Promise.reject(new Error("network")),
|
|
276
|
-
) as typeof fetch;
|
|
276
|
+
) as unknown as typeof fetch;
|
|
277
277
|
|
|
278
278
|
const client = createCesHttpCredentialClient(
|
|
279
279
|
createTestConfig(),
|
|
@@ -311,7 +311,7 @@ describe("fetchCesLogExport", () => {
|
|
|
311
311
|
headers: { "Content-Type": "application/gzip" },
|
|
312
312
|
}),
|
|
313
313
|
),
|
|
314
|
-
) as typeof fetch;
|
|
314
|
+
) as unknown as typeof fetch;
|
|
315
315
|
|
|
316
316
|
const result = await fetchCesLogExport({
|
|
317
317
|
baseUrl: "http://ces-test:8090",
|
|
@@ -327,7 +327,7 @@ describe("fetchCesLogExport", () => {
|
|
|
327
327
|
test("returns error on non-OK status", async () => {
|
|
328
328
|
globalThis.fetch = mock(() =>
|
|
329
329
|
Promise.resolve(new Response("forbidden", { status: 403 })),
|
|
330
|
-
) as typeof fetch;
|
|
330
|
+
) as unknown as typeof fetch;
|
|
331
331
|
|
|
332
332
|
const result = await fetchCesLogExport({
|
|
333
333
|
baseUrl: "http://ces-test:8090",
|
|
@@ -343,7 +343,7 @@ describe("fetchCesLogExport", () => {
|
|
|
343
343
|
test("returns error on network failure", async () => {
|
|
344
344
|
globalThis.fetch = mock(() =>
|
|
345
345
|
Promise.reject(new Error("connection refused")),
|
|
346
|
-
) as typeof fetch;
|
|
346
|
+
) as unknown as typeof fetch;
|
|
347
347
|
|
|
348
348
|
const result = await fetchCesLogExport({
|
|
349
349
|
baseUrl: "http://ces-test:8090",
|
|
@@ -361,7 +361,7 @@ describe("fetchCesLogExport", () => {
|
|
|
361
361
|
globalThis.fetch = mock((url: string | URL | Request) => {
|
|
362
362
|
capturedUrl = typeof url === "string" ? url : url.toString();
|
|
363
363
|
return Promise.resolve(new Response(new ArrayBuffer(0), { status: 200 }));
|
|
364
|
-
}) as typeof fetch;
|
|
364
|
+
}) as unknown as typeof fetch;
|
|
365
365
|
|
|
366
366
|
await fetchCesLogExport(
|
|
367
367
|
{ baseUrl: "http://ces-test:8090", serviceToken: "tok" },
|
|
@@ -416,7 +416,7 @@ export function createCesRpcClient(
|
|
|
416
416
|
assistantApiKey: string,
|
|
417
417
|
assistantId?: string,
|
|
418
418
|
): Promise<{ updated: boolean }> {
|
|
419
|
-
return call(CesRpcMethod.
|
|
419
|
+
return call(CesRpcMethod.UpdateCloudCredential, {
|
|
420
420
|
assistantApiKey,
|
|
421
421
|
...(assistantId ? { assistantId } : {}),
|
|
422
422
|
});
|
|
@@ -64,12 +64,12 @@ export function cloudAssistantHubUrl(envName: string | undefined): string {
|
|
|
64
64
|
export const SEEDS: Record<string, EnvironmentDefinition> = {
|
|
65
65
|
production: {
|
|
66
66
|
name: "production",
|
|
67
|
-
|
|
67
|
+
cloudUrl: "https://cloud.mycadet.ai",
|
|
68
68
|
webUrl: "https://mycadet.ai",
|
|
69
69
|
},
|
|
70
70
|
staging: {
|
|
71
71
|
name: "staging",
|
|
72
|
-
|
|
72
|
+
cloudUrl: "https://staging-cloud.mycadet.ai",
|
|
73
73
|
webUrl: "https://staging.mycadet.ai",
|
|
74
74
|
portsOverride: portBlock(17000),
|
|
75
75
|
},
|
|
@@ -77,21 +77,21 @@ export const SEEDS: Record<string, EnvironmentDefinition> = {
|
|
|
77
77
|
name: "test",
|
|
78
78
|
// Non-functional URL — used only by unit tests for URL resolution, never
|
|
79
79
|
// hit in production.
|
|
80
|
-
|
|
80
|
+
cloudUrl: "https://test-cloud.mycadet.ai",
|
|
81
81
|
webUrl: "https://dev.mycadet.ai",
|
|
82
82
|
portsOverride: portBlock(19000),
|
|
83
83
|
},
|
|
84
84
|
dev: {
|
|
85
85
|
name: "dev",
|
|
86
|
-
|
|
86
|
+
cloudUrl: "https://dev-cloud.mycadet.ai",
|
|
87
87
|
webUrl: "https://dev.mycadet.ai",
|
|
88
88
|
portsOverride: portBlock(18000),
|
|
89
89
|
},
|
|
90
90
|
local: {
|
|
91
91
|
name: "local",
|
|
92
|
-
|
|
92
|
+
cloudUrl: "http://localhost:8000",
|
|
93
93
|
webUrl: "http://localhost:3000",
|
|
94
|
-
//
|
|
94
|
+
// assistantCloudUrl: "http://host.docker.internal:8000",
|
|
95
95
|
// ^ uncomment this once dockerized hatch path is live.
|
|
96
96
|
// The assistant runs in a different network namespace than the host.
|
|
97
97
|
portsOverride: portBlock(20000),
|
|
@@ -72,7 +72,7 @@ describe("buildShellSpawnFlags", () => {
|
|
|
72
72
|
});
|
|
73
73
|
|
|
74
74
|
describe("path list handling", () => {
|
|
75
|
-
test("uses the
|
|
75
|
+
test("uses the cloud delimiter", () => {
|
|
76
76
|
expect(pathListDelimiter("win32")).toBe(";");
|
|
77
77
|
expect(pathListDelimiter("linux")).toBe(":");
|
|
78
78
|
});
|
|
@@ -21,14 +21,14 @@ export interface PortMap {
|
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* A resolved environment definition. Required fields are `name` and
|
|
24
|
-
* `
|
|
24
|
+
* `cloudUrl`. All other fields are optional and declared upfront — new
|
|
25
25
|
* fields are additive, never breaking. `name` is intentionally typed as
|
|
26
26
|
* `string` (not `keyof SEEDS`) so custom environments can be represented by
|
|
27
27
|
* future layers (user config file, ad-hoc env vars, etc.).
|
|
28
28
|
*/
|
|
29
29
|
export interface EnvironmentDefinition {
|
|
30
30
|
name: string;
|
|
31
|
-
|
|
31
|
+
cloudUrl: string;
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
34
|
* The web app (Next.js) base URL for browser-facing pages like
|
|
@@ -41,13 +41,13 @@ export interface EnvironmentDefinition {
|
|
|
41
41
|
webUrl: string;
|
|
42
42
|
|
|
43
43
|
/**
|
|
44
|
-
* Override for the
|
|
45
|
-
* differs from `
|
|
44
|
+
* Override for the cloud URL the assistant process itself uses. Only
|
|
45
|
+
* differs from `cloudUrl` when the assistant runs in a different network
|
|
46
46
|
* namespace than the host (e.g. Docker on macOS, where the host's localhost
|
|
47
|
-
* is reached via `host.docker.internal`). Falls back to `
|
|
47
|
+
* is reached via `host.docker.internal`). Falls back to `cloudUrl` when
|
|
48
48
|
* unset.
|
|
49
49
|
*/
|
|
50
|
-
|
|
50
|
+
assistantCloudUrl?: string;
|
|
51
51
|
|
|
52
52
|
/** Human-readable label for UI surfaces. */
|
|
53
53
|
displayName?: string;
|
package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/package.json
CHANGED
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"./error": "./src/error.ts",
|
|
27
27
|
"./reactions": "./src/reactions.ts",
|
|
28
28
|
"./guardian-requests": "./src/guardian-requests.ts",
|
|
29
|
-
"./
|
|
29
|
+
"./cloud-credential": "./src/cloud-credential.ts",
|
|
30
30
|
"./plan-credit": "./src/plan-credit.ts",
|
|
31
31
|
"./integration-categories": "./src/integration-categories.ts",
|
|
32
32
|
"./mcp-oauth": "./src/mcp-oauth.ts"
|
|
@@ -40,6 +40,6 @@
|
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@types/bun": "1.2.4",
|
|
43
|
-
"typescript": "5.
|
|
43
|
+
"typescript": "5.9.3"
|
|
44
44
|
}
|
|
45
45
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Wire contract for asking an assistant whether its stored
|
|
2
|
+
* Wire contract for asking an assistant whether its stored cloud-managed
|
|
3
3
|
* credential still authenticates.
|
|
4
4
|
*
|
|
5
5
|
* The daemon route is the authoritative serving side:
|
|
6
6
|
* - `POST /v1/platform/verify-credential`
|
|
7
|
-
* (`assistant/src/runtime/routes/
|
|
7
|
+
* (`assistant/src/runtime/routes/cloud-routes.ts`)
|
|
8
8
|
*
|
|
9
9
|
* The daemon's platform client produces the verdict, the route reports it,
|
|
10
10
|
* and the `cadet` CLI reads it before deciding whether a stored key can be
|
|
@@ -15,26 +15,26 @@
|
|
|
15
15
|
import { z } from "zod";
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
* What the
|
|
18
|
+
* What the cloud said about the stored credential, right now.
|
|
19
19
|
*
|
|
20
|
-
* - `valid`: the
|
|
21
|
-
* - `rejected`: the
|
|
20
|
+
* - `valid`: the cloud accepted it.
|
|
21
|
+
* - `rejected`: the cloud refused it (unauthorized or forbidden); the
|
|
22
22
|
* credential needs replacing.
|
|
23
23
|
* - `unknown`: the check itself could not run (no credential stored, the
|
|
24
24
|
* platform unreachable, a server error). Not evidence either way.
|
|
25
25
|
*/
|
|
26
|
-
export const
|
|
26
|
+
export const CloudCredentialVerificationStatusSchema = z.enum([
|
|
27
27
|
"valid",
|
|
28
28
|
"rejected",
|
|
29
29
|
"unknown",
|
|
30
30
|
]);
|
|
31
|
-
export type
|
|
32
|
-
typeof
|
|
31
|
+
export type CloudCredentialVerificationStatus = z.infer<
|
|
32
|
+
typeof CloudCredentialVerificationStatusSchema
|
|
33
33
|
>;
|
|
34
34
|
|
|
35
35
|
/** `POST /v1/platform/verify-credential` response body. */
|
|
36
36
|
export const PlatformVerifyCredentialResponseSchema = z.object({
|
|
37
|
-
status:
|
|
37
|
+
status: CloudCredentialVerificationStatusSchema,
|
|
38
38
|
});
|
|
39
39
|
export type PlatformVerifyCredentialResponse = z.infer<
|
|
40
40
|
typeof PlatformVerifyCredentialResponseSchema
|
package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/handles.ts
CHANGED
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
* Format: `local_oauth:<providerKey>/<connectionId>` where providerKey
|
|
16
16
|
* is the bare provider name (e.g. `google`).
|
|
17
17
|
*
|
|
18
|
-
* 3. **
|
|
18
|
+
* 3. **Cloud OAuth** — references an OAuth connection managed by the
|
|
19
19
|
* platform. Format: `platform_oauth:<connectionId>` where connectionId
|
|
20
|
-
* is the
|
|
20
|
+
* is the cloud-assigned connection identifier.
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
23
|
import { z } from "zod";
|
|
@@ -96,7 +96,7 @@ export function localOAuthHandle(
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
/**
|
|
99
|
-
* Build a
|
|
99
|
+
* Build a cloud (platform) OAuth credential handle from a connection ID.
|
|
100
100
|
*/
|
|
101
101
|
export function platformOAuthHandle(connectionId: string): string {
|
|
102
102
|
return `${HandleType.PlatformOAuth}:${connectionId}`;
|
package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/index.ts
CHANGED
|
@@ -31,7 +31,7 @@ export * from "./no-response.js";
|
|
|
31
31
|
export * from "./plan-credit.js";
|
|
32
32
|
export * from "./integration-categories.js";
|
|
33
33
|
export * from "./mcp-oauth.js";
|
|
34
|
-
export * from "./
|
|
34
|
+
export * from "./cloud-credential.js";
|
|
35
35
|
export * from "./remote-web-pairing.js";
|
|
36
36
|
export * from "./twilio-ingress.js";
|
|
37
37
|
export * from "./url-normalization.js";
|
package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/ingress.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* `{env}-cloud.mycadet.ai` → `tunnel-{env}.mycadet.ai`). Returns null for
|
|
5
5
|
* hosts outside that convention (localhost, custom domains). Shared by the
|
|
6
6
|
* gateway speech relay and the web live-voice client so the two ends of the
|
|
7
|
-
*
|
|
7
|
+
* cloud-speech transport can't drift.
|
|
8
8
|
*/
|
|
9
9
|
export function tunnelHostForPlatformHost(host: string): string | null {
|
|
10
10
|
if (host === "cloud.mycadet.ai") {
|
|
@@ -100,11 +100,17 @@ export const INGRESS_PAIRING_TUNNEL_KEY = "pairingTunnel";
|
|
|
100
100
|
export const INGRESS_ASSISTANT_ID_KEY = "assistantId";
|
|
101
101
|
|
|
102
102
|
/**
|
|
103
|
-
* The
|
|
104
|
-
* `cadet tunnel
|
|
105
|
-
*
|
|
103
|
+
* The tunnel providers the CLI offers, in the order they are presented —
|
|
104
|
+
* the managed `cadet` tunnel first (listed, not yet implemented), then the
|
|
105
|
+
* local ones. `cadet tunnel`'s accepted `--provider` values and the
|
|
106
|
+
* persisted-record validation below both derive from it.
|
|
106
107
|
*/
|
|
107
|
-
export const TUNNEL_PROVIDERS = [
|
|
108
|
+
export const TUNNEL_PROVIDERS = [
|
|
109
|
+
"cadet",
|
|
110
|
+
"ngrok",
|
|
111
|
+
"cloudflare",
|
|
112
|
+
"tailscale",
|
|
113
|
+
] as const;
|
|
108
114
|
|
|
109
115
|
export type TunnelProviderName = (typeof TUNNEL_PROVIDERS)[number];
|
|
110
116
|
|
|
@@ -152,7 +152,7 @@ export const DEFAULT_REMOTE_WEB_PAIRING_PLATFORM: RemoteWebPairingPlatform =
|
|
|
152
152
|
|
|
153
153
|
/**
|
|
154
154
|
* A requested platform coerced to a known value. The pairing-token route is
|
|
155
|
-
* publicly reachable and the
|
|
155
|
+
* publicly reachable and the cloud renders verbatim in the host's
|
|
156
156
|
* paired-devices list, so an unrecognized value never reaches the DB.
|
|
157
157
|
*/
|
|
158
158
|
export function resolveRemoteWebPairingPlatform(
|