@rstreamlabs/tunnels 1.0.11 → 3.0.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/dist/index.mjs CHANGED
@@ -13,211 +13,13 @@ import {
13
13
  streamSummarySchema,
14
14
  streamTLSInfoSchema,
15
15
  tunnelFilterSchema,
16
- tunnelSchema,
17
16
  webhookEventsSchema,
18
17
  wsEventsSchema
19
- } from "./chunk-NHUJ3FYM.mjs";
18
+ } from "./chunk-UUZYVELQ.mjs";
20
19
 
21
20
  // src/auth-resource.ts
21
+ import { createAuthTokenParamsSchema } from "@rstreamlabs/rstream/auth-token";
22
22
  import { createClientCredentialsToken } from "@rstreamlabs/rstream";
23
-
24
- // src/zod.ts
25
- import * as z from "zod";
26
- var StringFilter = z.union([
27
- z.string(),
28
- z.object({ exact: z.string() }).strict(),
29
- z.object({ oneof: z.array(z.string()) }).strict(),
30
- z.object({ regex: z.string() }).strict()
31
- ]);
32
- function transform(field) {
33
- if (field instanceof z.ZodOptional) {
34
- return z.optional(transform(field.unwrap()));
35
- }
36
- if (field instanceof z.ZodString) {
37
- return z.optional(StringFilter);
38
- }
39
- if (field instanceof z.ZodRecord) {
40
- return z.optional(z.record(field.keyType, transform(field.valueType)));
41
- }
42
- return z.optional(field);
43
- }
44
- function filters(base) {
45
- const entries = Object.entries(base.shape).map(([key, field]) => [
46
- key,
47
- transform(field)
48
- ]);
49
- const shape = Object.fromEntries(entries);
50
- const node = z.lazy(
51
- () => z.union([
52
- z.object(shape).strict(),
53
- z.object({ AND: z.array(node) }).strict(),
54
- z.object({ OR: z.array(node) }).strict()
55
- ])
56
- );
57
- return node;
58
- }
59
- function select(base) {
60
- const entries = Object.entries(base.shape).map(([key]) => {
61
- return [key, z.boolean().optional()];
62
- });
63
- const shape = Object.fromEntries(entries);
64
- return z.object(shape).strict();
65
- }
66
-
67
- // src/auth.ts
68
- import * as z2 from "zod";
69
- var nonEmptyStringSchema = z2.string().trim().min(1);
70
- var authTokenPermissionsSchema = z2.array(z2.string());
71
- var authTokenTunnelsScopesSchema = z2.object({
72
- // Scopes for creating tunnels
73
- create: z2.union([
74
- z2.boolean(),
75
- z2.object({
76
- filters: filters(
77
- tunnelSchema.omit({
78
- client_id: true,
79
- user_id: true,
80
- workspace_id: true,
81
- project_id: true,
82
- cluster_id: true,
83
- plan: true,
84
- provider: true,
85
- region: true,
86
- status: true,
87
- id: true,
88
- creation_date: true
89
- })
90
- ).optional()
91
- }).strict()
92
- ]).optional(),
93
- // Scopes for connecting to tunnels
94
- connect: z2.union([
95
- z2.boolean(),
96
- z2.object({
97
- filters: filters(tunnelSchema).optional(),
98
- params: filters(
99
- z2.object({
100
- path: z2.string().optional()
101
- })
102
- ).optional()
103
- }).strict()
104
- ]).optional(),
105
- // Scopes for listing tunnels
106
- list: z2.union([
107
- z2.boolean(),
108
- z2.object({
109
- filters: filters(tunnelSchema).optional(),
110
- select: select(tunnelSchema).optional()
111
- }).strict()
112
- ]).optional()
113
- }).strict().superRefine((scopes, ctx) => {
114
- if (scopes.create === void 0 && scopes.connect === void 0 && scopes.list === void 0) {
115
- ctx.addIssue({
116
- code: z2.ZodIssueCode.custom,
117
- message: "At least one tunnel scope action is required."
118
- });
119
- }
120
- });
121
- var authTokenScopesSchema = z2.object({
122
- tunnels: authTokenTunnelsScopesSchema.optional()
123
- // Scopes related to tunnels
124
- }).strict().superRefine((scopes, ctx) => {
125
- if (scopes.tunnels === void 0) {
126
- ctx.addIssue({
127
- code: z2.ZodIssueCode.custom,
128
- message: "Tunnel scopes are required.",
129
- path: ["tunnels"]
130
- });
131
- }
132
- });
133
- var authTokenTunnelGrantLeafSchema = z2.object({
134
- workspaces: z2.array(nonEmptyStringSchema).min(1).optional(),
135
- projects: z2.array(nonEmptyStringSchema).min(1).optional(),
136
- scopes: authTokenScopesSchema.optional()
137
- }).strict().superRefine((grant, ctx) => {
138
- if (grant.workspaces !== void 0 && grant.projects !== void 0) {
139
- ctx.addIssue({
140
- code: z2.ZodIssueCode.custom,
141
- message: "A grant cannot target workspaces and projects at the same time.",
142
- path: ["projects"]
143
- });
144
- }
145
- if (grant.workspaces === void 0 && grant.projects === void 0 && grant.scopes === void 0) {
146
- ctx.addIssue({
147
- code: z2.ZodIssueCode.custom,
148
- message: "A grant must target workspaces, projects, or scopes.",
149
- path: ["workspaces"]
150
- });
151
- }
152
- });
153
- var authTokenTunnelGrantSchema = z2.lazy(
154
- () => z2.union([
155
- authTokenTunnelGrantLeafSchema,
156
- z2.object({ AND: z2.array(authTokenTunnelGrantSchema).min(1) }).strict(),
157
- z2.object({ OR: z2.array(authTokenTunnelGrantSchema).min(1) }).strict()
158
- ])
159
- );
160
- var authTokenCommonSchema = {
161
- aud: z2.union([z2.string(), z2.array(z2.string())]).optional(),
162
- exp: z2.number().optional(),
163
- tunnelsGrants: authTokenTunnelGrantSchema.optional(),
164
- iat: z2.number().optional(),
165
- iss: z2.string().optional(),
166
- jti: z2.string().optional(),
167
- metadata: z2.object({
168
- engine: z2.string().optional()
169
- }).strict().optional(),
170
- nbf: z2.number().optional(),
171
- sub: z2.string().optional()
172
- };
173
- var authTokenSchema = z2.union([
174
- z2.object({
175
- type: z2.literal("auth"),
176
- userId: z2.string(),
177
- permissions: authTokenPermissionsSchema.nullable(),
178
- ...authTokenCommonSchema
179
- }).strict(),
180
- z2.object({
181
- type: z2.literal("pat"),
182
- tokendpoint: z2.string().optional(),
183
- token_endpoint: z2.string().optional(),
184
- ...authTokenCommonSchema
185
- }).strict(),
186
- z2.object({
187
- type: z2.literal("app"),
188
- clientId: z2.string(),
189
- permissions: authTokenPermissionsSchema.nullable(),
190
- ...authTokenCommonSchema
191
- }).strict()
192
- ]);
193
- var tokenSchema = authTokenSchema;
194
- var createAuthTokenParamsSchema = z2.object({
195
- expires_in: z2.number().int().min(1).max(3600).default(60),
196
- scopes: authTokenScopesSchema.optional(),
197
- tunnelsGrants: authTokenTunnelGrantSchema.optional(),
198
- metadata: z2.unknown().optional()
199
- // Additional metadata
200
- }).strict().superRefine((params, ctx) => {
201
- if (params.scopes !== void 0 && params.tunnelsGrants !== void 0) {
202
- ctx.addIssue({
203
- code: z2.ZodIssueCode.custom,
204
- message: "Use either scopes or tunnelsGrants, not both.",
205
- path: ["tunnelsGrants"]
206
- });
207
- }
208
- if (params.scopes === void 0 && params.tunnelsGrants === void 0) {
209
- ctx.addIssue({
210
- code: z2.ZodIssueCode.custom,
211
- message: "Explicit scopes or tunnelsGrants are required.",
212
- path: ["scopes"]
213
- });
214
- }
215
- });
216
- var createAuthTokenResponseSchema = z2.object({
217
- token: z2.string()
218
- });
219
-
220
- // src/auth-resource.ts
221
23
  import { isClientCredentials } from "@rstreamlabs/rstream";
222
24
  var RstreamAuthResource = class {
223
25
  client;
@@ -246,7 +48,7 @@ var RstreamAuthResource = class {
246
48
  if (options?.projectId !== void 0 || options?.workspaceId !== void 0) {
247
49
  return options;
248
50
  }
249
- if (tokenParams.scopes === void 0 && !tunnelGrantsNeedDefaultTarget(tokenParams.tunnelsGrants)) {
51
+ if (!tunnelResourcesNeedDefaultTarget(tokenParams.resources?.tunnels)) {
250
52
  return options ?? {};
251
53
  }
252
54
  const target = await this.client.getEngineAuthTokenTarget();
@@ -263,8 +65,8 @@ function createAuthTokenFromClientCredentials(credentials, params, options) {
263
65
  metadata: {
264
66
  engine: options?.engine
265
67
  },
266
- tunnelsGrants: normalizeAuthTokenTunnelGrants(tokenParams, options),
267
- permissions: null
68
+ permissions: null,
69
+ resources: normalizeAuthTokenResources(tokenParams, options)
268
70
  };
269
71
  const { token } = createClientCredentialsToken(credentials, {
270
72
  claims: payload,
@@ -272,70 +74,73 @@ function createAuthTokenFromClientCredentials(credentials, params, options) {
272
74
  });
273
75
  return { token };
274
76
  }
275
- function normalizeAuthTokenTunnelGrants(params, options) {
276
- const tunnelsGrants = params.tunnelsGrants;
277
- if (tunnelsGrants !== void 0) {
278
- return applyDefaultTunnelGrantTarget(tunnelsGrants, options);
279
- }
280
- if (params.scopes) {
281
- return { ...normalizeTunnelGrantTarget(options), scopes: params.scopes };
282
- }
283
- return void 0;
77
+ function normalizeAuthTokenResources(params, options) {
78
+ return {
79
+ tunnels: applyDefaultTunnelResourceTarget(
80
+ requireTunnelResource(params),
81
+ options
82
+ )
83
+ };
284
84
  }
285
- function applyDefaultTunnelGrantTarget(grants, options, inheritedTarget = false) {
85
+ function requireTunnelResource(params) {
86
+ const tunnels = params.resources?.tunnels;
87
+ if (tunnels !== void 0) return tunnels;
88
+ throw new Error("Explicit resources.tunnels is required.");
89
+ }
90
+ function applyDefaultTunnelResourceTarget(resource, options, inheritedTarget = false) {
286
91
  if (options?.projectScoped === false) {
287
- return grants;
92
+ return resource;
288
93
  }
289
- if ("AND" in grants) {
290
- const branchHasTarget = inheritedTarget || grants.AND.some((grant) => tunnelGrantTreeHasTarget(grant));
94
+ if ("AND" in resource) {
95
+ const branchHasTarget = inheritedTarget || resource.AND.some((child) => tunnelResourceTreeHasTarget(child));
291
96
  return {
292
- AND: grants.AND.map(
293
- (grant) => applyDefaultTunnelGrantTarget(grant, options, branchHasTarget)
97
+ AND: resource.AND.map(
98
+ (child) => applyDefaultTunnelResourceTarget(child, options, branchHasTarget)
294
99
  )
295
100
  };
296
101
  }
297
- if ("OR" in grants) {
102
+ if ("OR" in resource) {
298
103
  return {
299
- OR: grants.OR.map(
300
- (grant) => applyDefaultTunnelGrantTarget(grant, options, inheritedTarget)
104
+ OR: resource.OR.map(
105
+ (child) => applyDefaultTunnelResourceTarget(child, options, inheritedTarget)
301
106
  )
302
107
  };
303
108
  }
304
- if (grants.scopes === void 0 || tunnelGrantHasTarget(grants) || inheritedTarget) {
305
- return grants;
109
+ if (resource.scopes === void 0 || tunnelResourceHasTarget(resource) || inheritedTarget) {
110
+ return resource;
306
111
  }
307
- return { ...normalizeTunnelGrantTarget(options), scopes: grants.scopes };
112
+ return { ...normalizeTunnelResourceTarget(options), scopes: resource.scopes };
308
113
  }
309
- function tunnelGrantsNeedDefaultTarget(grants, inheritedTarget = false) {
310
- if (grants === void 0) {
114
+ function tunnelResourcesNeedDefaultTarget(resource, inheritedTarget = false) {
115
+ if (resource === void 0) {
311
116
  return false;
312
117
  }
313
- if ("AND" in grants) {
314
- const branchHasTarget = inheritedTarget || grants.AND.some((grant) => tunnelGrantTreeHasTarget(grant));
315
- return grants.AND.some(
316
- (grant) => tunnelGrantsNeedDefaultTarget(grant, branchHasTarget)
118
+ if ("AND" in resource) {
119
+ const branchHasTarget = inheritedTarget || resource.AND.some((child) => tunnelResourceTreeHasTarget(child));
120
+ return resource.AND.some(
121
+ (child) => tunnelResourcesNeedDefaultTarget(child, branchHasTarget)
317
122
  );
318
123
  }
319
- if ("OR" in grants) {
320
- return grants.OR.some(
321
- (grant) => tunnelGrantsNeedDefaultTarget(grant, inheritedTarget)
124
+ if ("OR" in resource) {
125
+ return resource.OR.some(
126
+ (child) => tunnelResourcesNeedDefaultTarget(child, inheritedTarget)
322
127
  );
323
128
  }
324
- return grants.scopes !== void 0 && !tunnelGrantHasTarget(grants) && !inheritedTarget;
129
+ return resource.scopes !== void 0 && !tunnelResourceHasTarget(resource) && !inheritedTarget;
325
130
  }
326
- function tunnelGrantHasTarget(grant) {
327
- return grant.projects !== void 0 || grant.workspaces !== void 0;
131
+ function tunnelResourceHasTarget(resource) {
132
+ return resource.projects !== void 0 || resource.workspaces !== void 0;
328
133
  }
329
- function tunnelGrantTreeHasTarget(grants) {
330
- if ("AND" in grants) {
331
- return grants.AND.some((grant) => tunnelGrantTreeHasTarget(grant));
134
+ function tunnelResourceTreeHasTarget(resource) {
135
+ if ("AND" in resource) {
136
+ return resource.AND.some((child) => tunnelResourceTreeHasTarget(child));
332
137
  }
333
- if ("OR" in grants) {
334
- return grants.OR.some((grant) => tunnelGrantTreeHasTarget(grant));
138
+ if ("OR" in resource) {
139
+ return resource.OR.some((child) => tunnelResourceTreeHasTarget(child));
335
140
  }
336
- return tunnelGrantHasTarget(grants);
141
+ return tunnelResourceHasTarget(resource);
337
142
  }
338
- function normalizeTunnelGrantTarget(options) {
143
+ function normalizeTunnelResourceTarget(options) {
339
144
  const projectId = normalizeOptionalString(options?.projectId);
340
145
  const workspaceId = normalizeOptionalString(options?.workspaceId);
341
146
  if (projectId !== void 0 && workspaceId !== void 0) {
@@ -351,7 +156,7 @@ function normalizeTunnelGrantTarget(options) {
351
156
  return {};
352
157
  }
353
158
  throw new Error(
354
- "Project ID or workspace ID is required when using scope-only tunnel grants."
159
+ "Project ID or workspace ID is required when using scope-only tunnel resources."
355
160
  );
356
161
  }
357
162
  function normalizeOptionalString(value) {
@@ -508,6 +313,7 @@ async function resolveManagedTunnelsProject(config) {
508
313
  }
509
314
 
510
315
  // src/tunnels-resource.ts
316
+ import { tunnelSchema } from "@rstreamlabs/rstream/tunnel";
511
317
  function tunnelPathId(id) {
512
318
  const normalized = id.trim();
513
319
  if (!normalized) {
@@ -547,21 +353,21 @@ import { readEnvironment as readEnvironment2 } from "@rstreamlabs/rstream";
547
353
  import { isClientCredentials as isClientCredentials2 } from "@rstreamlabs/rstream";
548
354
  import { isTokenCredentials as isTokenCredentials2 } from "@rstreamlabs/rstream";
549
355
  import { RstreamClient as RstreamClient2 } from "@rstreamlabs/rstream";
550
- import { turnCredentialsSchema } from "@rstreamlabs/rstream";
551
- import * as z3 from "zod";
356
+ import { turnCredentialsSchema } from "@rstreamlabs/rstream/turn";
357
+ import * as z from "zod";
552
358
  import crypto from "crypto";
553
359
  var defaultTURNPort = 3478;
554
360
  var defaultTURNSPort = 5349;
555
361
  var defaultTURNCredentialTTLSeconds = 10 * 60;
556
362
  var maxTURNCredentialTTLSeconds = 60 * 60;
557
- var turnTokenClaimsSchema = z3.object({
558
- exp: z3.number().int().optional(),
559
- iat: z3.number().int().optional(),
560
- token_endpoint: z3.string().regex(/^[0-9a-f]{8}$/i).optional(),
561
- tokendpoint: z3.string().regex(/^[0-9a-f]{8}$/i).optional(),
562
- type: z3.enum(["app", "auth", "pat"])
363
+ var turnTokenClaimsSchema = z.object({
364
+ exp: z.number().int().optional(),
365
+ iat: z.number().int().optional(),
366
+ token_endpoint: z.string().regex(/^[0-9a-f]{8}$/i).optional(),
367
+ tokendpoint: z.string().regex(/^[0-9a-f]{8}$/i).optional(),
368
+ type: z.enum(["app", "auth", "pat"])
563
369
  });
564
- var turnCredentialModeSchema = z3.enum(["api", "app", "pat"]);
370
+ var turnCredentialModeSchema = z.enum(["api", "app", "pat"]);
565
371
  function normalizeOptionalString2(value) {
566
372
  const normalized = value?.trim();
567
373
  return normalized ? normalized : void 0;
@@ -587,6 +393,9 @@ function normalizeTTLSeconds(ttlSeconds) {
587
393
  }
588
394
  return ttl;
589
395
  }
396
+ function createAPITURNCredentialsParams(ttlSeconds) {
397
+ return ttlSeconds === void 0 ? {} : { ttlSeconds: normalizeTTLSeconds(ttlSeconds) };
398
+ }
590
399
  function normalizePort(port, fallback, name) {
591
400
  const normalized = port ?? fallback;
592
401
  if (!Number.isInteger(normalized) || normalized < 1 || normalized > 65535) {
@@ -616,19 +425,21 @@ function parseTURNTokenClaims(token) {
616
425
  if (!payloadPart) {
617
426
  throw new Error("Invalid token format.");
618
427
  }
619
- let decoded;
620
- try {
621
- const payload = Buffer.from(payloadPart, "base64url").toString("utf8");
622
- decoded = JSON.parse(payload);
623
- } catch {
624
- throw new Error("Invalid token format.");
625
- }
428
+ const decoded = parseTURNTokenPayload(payloadPart);
626
429
  const parsed = turnTokenClaimsSchema.safeParse(decoded);
627
430
  if (!parsed.success) {
628
431
  throw new Error("Invalid token format.");
629
432
  }
630
433
  return parsed.data;
631
434
  }
435
+ function parseTURNTokenPayload(payloadPart) {
436
+ try {
437
+ const payload = Buffer.from(payloadPart, "base64url").toString("utf8");
438
+ return JSON.parse(payload);
439
+ } catch {
440
+ throw new Error("Invalid token format.");
441
+ }
442
+ }
632
443
  function requirePATExpiration(claims, now) {
633
444
  const exp = claims.exp;
634
445
  if (typeof exp !== "number") {
@@ -702,8 +513,12 @@ async function createAPITURNCredentials(options) {
702
513
  apiUrl: options.apiUrl,
703
514
  credentials: options.credentials
704
515
  });
516
+ const params = createAPITURNCredentialsParams(options.ttlSeconds);
705
517
  if (projectId) {
706
- return await client.tunnels.projects.createTurnCredentials(projectId);
518
+ return await client.tunnels.projects.createTurnCredentials(
519
+ projectId,
520
+ params
521
+ );
707
522
  }
708
523
  if (!projectEndpoint) {
709
524
  throw new Error(
@@ -711,7 +526,8 @@ async function createAPITURNCredentials(options) {
711
526
  );
712
527
  }
713
528
  return await client.tunnels.projects.createTurnCredentialsByEndpoint(
714
- projectEndpoint
529
+ projectEndpoint,
530
+ params
715
531
  );
716
532
  }
717
533
  function createPATTURNCredentials(options) {
@@ -829,7 +645,8 @@ async function createTURNCredentials(options) {
829
645
  apiUrl: options.apiUrl,
830
646
  credentials: controlPlaneCredentials,
831
647
  projectEndpoint,
832
- projectId: options.projectId
648
+ projectId: options.projectId,
649
+ ttlSeconds: options.ttlSeconds
833
650
  });
834
651
  }
835
652
  const clusterDomain = normalizeClusterDomain(options.clusterDomain) ?? (projectEndpoint && options.engine ? deriveClusterDomainFromEngine(projectEndpoint, options.engine) : void 0);
@@ -1065,9 +882,11 @@ var RstreamTunnelsClient = class {
1065
882
  async getEngineAuthTokenParams() {
1066
883
  const target = await this.getEngineAuthTokenTarget();
1067
884
  return {
1068
- tunnelsGrants: {
1069
- ...target,
1070
- scopes: engineAuthTokenScopes
885
+ resources: {
886
+ tunnels: {
887
+ ...target,
888
+ scopes: engineAuthTokenScopes
889
+ }
1071
890
  }
1072
891
  };
1073
892
  }
@@ -1149,6 +968,7 @@ function normalizeOptionalString3(value) {
1149
968
  }
1150
969
 
1151
970
  // src/watch.ts
971
+ import { authTokenSchema } from "@rstreamlabs/rstream/auth-token";
1152
972
  import jwt from "jsonwebtoken";
1153
973
  var maxWatchTokenLifetimeSeconds = 3600;
1154
974
  var watchTokenIssuedAtSkewSeconds = 300;
@@ -1176,37 +996,38 @@ function validateWatchQueryToken(token) {
1176
996
  "Watch requires a token with a bounded lifetime of at most 3600 seconds."
1177
997
  );
1178
998
  }
1179
- if (!hasWatchOnlyTunnelGrants(parsed.data)) {
999
+ if (!hasWatchOnlyTunnelResources(parsed.data)) {
1180
1000
  throw new Error(
1181
- "Watch requires a fine-grained token limited to tunnel list grants for URL-based authentication."
1001
+ "Watch requires a fine-grained token limited to tunnel list resources for URL-based authentication."
1182
1002
  );
1183
1003
  }
1184
1004
  }
1185
- function hasWatchOnlyTunnelGrants(token) {
1005
+ function hasWatchOnlyTunnelResources(token) {
1186
1006
  if (!hasWatchOnlyPermissions(token.permissions)) {
1187
1007
  return false;
1188
1008
  }
1189
- if (token.tunnelsGrants === void 0) {
1009
+ const resource = token.resources?.tunnels;
1010
+ if (resource === void 0) {
1190
1011
  return false;
1191
1012
  }
1192
- return hasWatchOnlyTunnelGrant(token.tunnelsGrants);
1013
+ return hasWatchOnlyTunnelResource(resource);
1193
1014
  }
1194
- function hasWatchOnlyTunnelGrant(grant) {
1195
- return watchGrantBranches(grant).every(
1015
+ function hasWatchOnlyTunnelResource(resource) {
1016
+ return watchResourceBranches(resource).every(
1196
1017
  (branch) => branch.hasList && !branch.hasMutationOrConnect
1197
1018
  );
1198
1019
  }
1199
- function watchGrantBranches(grant) {
1200
- if ("AND" in grant) {
1201
- return grant.AND.reduce(
1202
- (branches, child) => combineWatchGrantBranches(branches, child),
1020
+ function watchResourceBranches(resource) {
1021
+ if ("AND" in resource) {
1022
+ return resource.AND.reduce(
1023
+ (branches, child) => combineWatchResourceBranches(branches, child),
1203
1024
  [{ hasList: false, hasMutationOrConnect: false }]
1204
1025
  );
1205
1026
  }
1206
- if ("OR" in grant) {
1207
- return grant.OR.flatMap(watchGrantBranches);
1027
+ if ("OR" in resource) {
1028
+ return resource.OR.flatMap(watchResourceBranches);
1208
1029
  }
1209
- const tunnels = grant.scopes?.tunnels;
1030
+ const tunnels = resource.scopes?.tunnels;
1210
1031
  if (tunnels === void 0) {
1211
1032
  return [{ hasList: false, hasMutationOrConnect: false }];
1212
1033
  }
@@ -1217,9 +1038,9 @@ function watchGrantBranches(grant) {
1217
1038
  }
1218
1039
  ];
1219
1040
  }
1220
- function combineWatchGrantBranches(branches, child) {
1041
+ function combineWatchResourceBranches(branches, child) {
1221
1042
  return branches.flatMap(
1222
- (branch) => watchGrantBranches(child).map((childBranch) => ({
1043
+ (branch) => watchResourceBranches(child).map((childBranch) => ({
1223
1044
  hasList: branch.hasList || childBranch.hasList,
1224
1045
  hasMutationOrConnect: branch.hasMutationOrConnect || childBranch.hasMutationOrConnect
1225
1046
  }))
@@ -1230,7 +1051,7 @@ function hasWatchOnlyPermissions(permissions) {
1230
1051
  return true;
1231
1052
  }
1232
1053
  return permissions.every(
1233
- (permission) => permission === "tunnels.resources.read-only" || permission === "network.resources.read-only"
1054
+ (permission) => permission === "tunnels.resources.read-only"
1234
1055
  );
1235
1056
  }
1236
1057
  var Watch = class {
@@ -1315,7 +1136,7 @@ var Watch = class {
1315
1136
  };
1316
1137
 
1317
1138
  // src/webtty.ts
1318
- import * as z4 from "zod";
1139
+ import * as z2 from "zod";
1319
1140
  var osFamilies = [
1320
1141
  "linux",
1321
1142
  "macos",
@@ -1324,25 +1145,25 @@ var osFamilies = [
1324
1145
  "openbsd",
1325
1146
  "freebsd"
1326
1147
  ];
1327
- var webttyServerSchema = z4.object({
1328
- tunnel_id: z4.string(),
1329
- host: z4.string(),
1330
- token_auth: z4.boolean(),
1331
- os_family: z4.enum(osFamilies).optional(),
1332
- arch: z4.string().optional(),
1333
- os_id: z4.string().optional(),
1148
+ var webttyServerSchema = z2.object({
1149
+ tunnel_id: z2.string(),
1150
+ host: z2.string(),
1151
+ token_auth: z2.boolean(),
1152
+ os_family: z2.enum(osFamilies).optional(),
1153
+ arch: z2.string().optional(),
1154
+ os_id: z2.string().optional(),
1334
1155
  // /etc/os-release::ID (ubuntu, debian, rocky, etc.)
1335
- os_version_id: z4.string().optional(),
1156
+ os_version_id: z2.string().optional(),
1336
1157
  // /etc/os-release::VERSION_ID (24.04, 22.04, 11, 10.0.19045, ...)
1337
- os_version_codename: z4.string().optional(),
1158
+ os_version_codename: z2.string().optional(),
1338
1159
  // /etc/os-release::VERSION_CODENAME (jammy, noble...)
1339
- os_pretty_name: z4.string().optional(),
1160
+ os_pretty_name: z2.string().optional(),
1340
1161
  // /etc/os-release::PRETTY_NAME
1341
- kernel_release: z4.string().optional(),
1162
+ kernel_release: z2.string().optional(),
1342
1163
  // uname -r
1343
- hostname: z4.string().optional(),
1164
+ hostname: z2.string().optional(),
1344
1165
  // uname -n
1345
- labels: z4.record(z4.string(), z4.string().optional()).optional()
1166
+ labels: z2.record(z2.string(), z2.string().optional()).optional()
1346
1167
  });
1347
1168
  function parser(tunnel) {
1348
1169
  if (tunnel.status !== "online") return null;
@@ -1394,18 +1215,11 @@ export {
1394
1215
  RstreamWebhookResource as RstreamWebhookRessource,
1395
1216
  RstreamTunnelsClient as Tunnels,
1396
1217
  Watch,
1397
- authTokenPermissionsSchema,
1398
- authTokenSchema,
1399
- authTokenScopesSchema,
1400
- authTokenTunnelGrantSchema,
1401
- authTokenTunnelsScopesSchema,
1402
1218
  clientFilterSchema,
1403
1219
  clientSchema,
1404
1220
  createAPITURNCredentials,
1405
1221
  createAPPTURNCredentials,
1406
1222
  createAuthTokenFromClientCredentials,
1407
- createAuthTokenParamsSchema,
1408
- createAuthTokenResponseSchema,
1409
1223
  createPATTURNCredentials,
1410
1224
  createTURNCredentials,
1411
1225
  engineOpenApiDocument,
@@ -1426,9 +1240,7 @@ export {
1426
1240
  streamEndpointSchema,
1427
1241
  streamSummarySchema,
1428
1242
  streamTLSInfoSchema,
1429
- tokenSchema,
1430
1243
  tunnelFilterSchema,
1431
- tunnelSchema,
1432
1244
  turnCredentialModeSchema,
1433
1245
  webhookEventsSchema,
1434
1246
  webttyServerSchema,