@oxy.so/core 4.5.0-oxy-one.1 → 4.6.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.
Files changed (283) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/HttpService.js +63 -19
  3. package/dist/cjs/api/accounts.js +10 -3
  4. package/dist/cjs/api/agency.js +3 -1
  5. package/dist/cjs/api/apps.js +15 -4
  6. package/dist/cjs/api/assets.js +39 -11
  7. package/dist/cjs/api/auth.js +28 -8
  8. package/dist/cjs/api/billing.js +24 -7
  9. package/dist/cjs/api/civic.js +14 -4
  10. package/dist/cjs/api/follows.js +9 -2
  11. package/dist/cjs/api/identity.js +31 -9
  12. package/dist/cjs/api/nodes.js +3 -1
  13. package/dist/cjs/api/privacy.js +8 -2
  14. package/dist/cjs/api/session.js +15 -4
  15. package/dist/cjs/api/store.js +15 -5
  16. package/dist/cjs/api/topics.js +10 -3
  17. package/dist/cjs/api/users.js +16 -4
  18. package/dist/cjs/boot/sessionColdBoot.js +40 -13
  19. package/dist/cjs/constants/version.js +6 -6
  20. package/dist/cjs/crypto/identityMarker.js +3 -1
  21. package/dist/cjs/crypto/identityProof.js +6 -1
  22. package/dist/cjs/crypto/keyManager.js +87 -32
  23. package/dist/cjs/crypto/recoveryPhrase.js +2 -2
  24. package/dist/cjs/crypto/signatureService.js +3 -4
  25. package/dist/cjs/i18n/index.js +16 -3
  26. package/dist/cjs/i18n/locales/ar-SA.js +366 -366
  27. package/dist/cjs/i18n/locales/ca-ES.js +366 -366
  28. package/dist/cjs/i18n/locales/de-DE.js +366 -366
  29. package/dist/cjs/i18n/locales/en-US.js +1994 -1994
  30. package/dist/cjs/i18n/locales/es-ES.js +1994 -1994
  31. package/dist/cjs/i18n/locales/fr-FR.js +366 -366
  32. package/dist/cjs/i18n/locales/it-IT.js +366 -366
  33. package/dist/cjs/i18n/locales/ja-JP.js +366 -366
  34. package/dist/cjs/i18n/locales/ko-KR.js +366 -366
  35. package/dist/cjs/i18n/locales/pt-PT.js +366 -366
  36. package/dist/cjs/i18n/locales/zh-CN.js +366 -366
  37. package/dist/cjs/inference/OxyInferenceClient.js +12 -18
  38. package/dist/cjs/models/interfaces.js +11 -11
  39. package/dist/cjs/server/OxyServer.js +86 -28
  40. package/dist/cjs/server/agentAccount.js +6 -2
  41. package/dist/cjs/server/aliaMachineCredential.js +39 -14
  42. package/dist/cjs/server/auth.js +5 -4
  43. package/dist/cjs/server/capabilityTicket.js +5 -5
  44. package/dist/cjs/server/index.js +2 -1
  45. package/dist/cjs/server/liveCapabilityTicket.js +4 -1
  46. package/dist/cjs/server/middleware.js +61 -42
  47. package/dist/cjs/server/namespaces.js +28 -7
  48. package/dist/cjs/server/requesterAssertion.js +36 -30
  49. package/dist/cjs/server/serviceTokenLifetime.js +7 -4
  50. package/dist/cjs/server/traffic.js +53 -14
  51. package/dist/cjs/server/trafficNodeHttp.js +33 -8
  52. package/dist/cjs/server/workloadIdentity.client.js +4 -0
  53. package/dist/cjs/server/workloadIdentity.js +28 -1
  54. package/dist/cjs/session/SessionClient.js +54 -17
  55. package/dist/cjs/session/accountDelegationAccess.js +4 -6
  56. package/dist/cjs/session/accountDialogController.js +1 -1
  57. package/dist/cjs/session/authStateStore.js +18 -9
  58. package/dist/cjs/session/identityPin.js +6 -2
  59. package/dist/cjs/session/refresh.js +81 -23
  60. package/dist/cjs/session/sharedDeviceCredential.js +28 -15
  61. package/dist/cjs/shared/utils/errorUtils.js +1 -1
  62. package/dist/cjs/shared/utils/networkUtils.js +1 -1
  63. package/dist/cjs/shared/utils/themeUtils.js +1 -1
  64. package/dist/cjs/utils/accountCacheSweep.js +3 -1
  65. package/dist/cjs/utils/accountUtils.js +1 -3
  66. package/dist/cjs/utils/asyncUtils.js +1 -1
  67. package/dist/cjs/utils/authHelpers.js +2 -1
  68. package/dist/cjs/utils/avatarUtils.js +4 -2
  69. package/dist/cjs/utils/cache.js +1 -1
  70. package/dist/cjs/utils/cacheKey.js +3 -1
  71. package/dist/cjs/utils/deviceManager.js +4 -4
  72. package/dist/cjs/utils/errorUtils.js +6 -4
  73. package/dist/cjs/utils/languageUtils.js +404 -57
  74. package/dist/cjs/utils/profileLinks.js +1 -3
  75. package/dist/cjs/utils/requestUtils.js +7 -1
  76. package/dist/cjs/utils/userIdentity.js +1 -1
  77. package/dist/cjs/utils/validationUtils.js +5 -6
  78. package/dist/esm/HttpService.js +64 -20
  79. package/dist/esm/api/accounts.js +11 -4
  80. package/dist/esm/api/agency.js +3 -1
  81. package/dist/esm/api/apps.js +15 -4
  82. package/dist/esm/api/assets.js +39 -11
  83. package/dist/esm/api/auth.js +28 -8
  84. package/dist/esm/api/billing.js +25 -8
  85. package/dist/esm/api/civic.js +14 -4
  86. package/dist/esm/api/follows.js +9 -2
  87. package/dist/esm/api/identity.js +31 -9
  88. package/dist/esm/api/nodes.js +3 -1
  89. package/dist/esm/api/privacy.js +8 -2
  90. package/dist/esm/api/session.js +15 -4
  91. package/dist/esm/api/store.js +15 -5
  92. package/dist/esm/api/topics.js +10 -3
  93. package/dist/esm/api/users.js +16 -4
  94. package/dist/esm/boot/sessionColdBoot.js +41 -14
  95. package/dist/esm/constants/version.js +6 -6
  96. package/dist/esm/crypto/identityMarker.js +3 -1
  97. package/dist/esm/crypto/identityProof.js +6 -1
  98. package/dist/esm/crypto/internal.js +1 -1
  99. package/dist/esm/crypto/keyManager.js +87 -32
  100. package/dist/esm/crypto/recoveryPhrase.js +2 -2
  101. package/dist/esm/crypto/signatureService.js +3 -4
  102. package/dist/esm/i18n/index.js +16 -3
  103. package/dist/esm/i18n/locales/ar-SA.js +366 -366
  104. package/dist/esm/i18n/locales/ca-ES.js +366 -366
  105. package/dist/esm/i18n/locales/de-DE.js +366 -366
  106. package/dist/esm/i18n/locales/en-US.js +1994 -1994
  107. package/dist/esm/i18n/locales/es-ES.js +1994 -1994
  108. package/dist/esm/i18n/locales/fr-FR.js +366 -366
  109. package/dist/esm/i18n/locales/it-IT.js +366 -366
  110. package/dist/esm/i18n/locales/ja-JP.js +366 -366
  111. package/dist/esm/i18n/locales/ko-KR.js +366 -366
  112. package/dist/esm/i18n/locales/pt-PT.js +366 -366
  113. package/dist/esm/i18n/locales/zh-CN.js +366 -366
  114. package/dist/esm/index.js +1 -1
  115. package/dist/esm/inference/OxyInferenceClient.js +13 -19
  116. package/dist/esm/models/interfaces.js +11 -11
  117. package/dist/esm/server/OxyServer.js +87 -29
  118. package/dist/esm/server/agentAccount.js +6 -2
  119. package/dist/esm/server/aliaMachineCredential.js +39 -14
  120. package/dist/esm/server/auth.js +6 -5
  121. package/dist/esm/server/capabilityTicket.js +6 -6
  122. package/dist/esm/server/index.js +5 -5
  123. package/dist/esm/server/liveCapabilityTicket.js +6 -3
  124. package/dist/esm/server/middleware.js +62 -43
  125. package/dist/esm/server/namespaces.js +31 -10
  126. package/dist/esm/server/requesterAssertion.js +36 -30
  127. package/dist/esm/server/serviceTokenLifetime.js +7 -4
  128. package/dist/esm/server/traffic.js +55 -16
  129. package/dist/esm/server/trafficNodeHttp.js +34 -9
  130. package/dist/esm/server/userInvalidation.js +1 -1
  131. package/dist/esm/server/workloadIdentity.client.js +3 -0
  132. package/dist/esm/server/workloadIdentity.js +27 -1
  133. package/dist/esm/session/SessionClient.js +54 -17
  134. package/dist/esm/session/accountDelegationAccess.js +5 -7
  135. package/dist/esm/session/accountDialogController.js +1 -1
  136. package/dist/esm/session/authStateStore.js +18 -9
  137. package/dist/esm/session/identityPin.js +6 -2
  138. package/dist/esm/session/refresh.js +82 -24
  139. package/dist/esm/session/sharedDeviceCredential.js +28 -15
  140. package/dist/esm/shared/utils/errorUtils.js +1 -1
  141. package/dist/esm/shared/utils/networkUtils.js +1 -1
  142. package/dist/esm/shared/utils/themeUtils.js +1 -1
  143. package/dist/esm/utils/accountCacheSweep.js +3 -1
  144. package/dist/esm/utils/accountUtils.js +1 -3
  145. package/dist/esm/utils/asyncUtils.js +1 -1
  146. package/dist/esm/utils/authHelpers.js +2 -1
  147. package/dist/esm/utils/avatarUtils.js +4 -2
  148. package/dist/esm/utils/cache.js +1 -1
  149. package/dist/esm/utils/cacheKey.js +3 -1
  150. package/dist/esm/utils/deviceManager.js +4 -4
  151. package/dist/esm/utils/errorUtils.js +6 -4
  152. package/dist/esm/utils/languageUtils.js +404 -57
  153. package/dist/esm/utils/profileLinks.js +1 -3
  154. package/dist/esm/utils/requestUtils.js +7 -1
  155. package/dist/esm/utils/userIdentity.js +1 -1
  156. package/dist/esm/utils/validationUtils.js +5 -6
  157. package/dist/types/HttpService.d.ts +1 -1
  158. package/dist/types/api/accounts.d.ts +16 -3
  159. package/dist/types/api/apps.d.ts +4 -4
  160. package/dist/types/crypto/internal.d.ts +1 -1
  161. package/dist/types/index.d.ts +4 -4
  162. package/dist/types/models/interfaces.d.ts +9 -1
  163. package/dist/types/server/index.d.ts +6 -6
  164. package/dist/types/server/workloadIdentity.client.d.ts +5 -1
  165. package/dist/types/server/workloadIdentity.d.ts +26 -0
  166. package/dist/types/session/accountDelegationAccess.d.ts +1 -1
  167. package/dist/types/session/index.d.ts +1 -1
  168. package/dist/types/utils/userIdentity.d.ts +1 -1
  169. package/dist/types/utils/validationUtils.d.ts +4 -5
  170. package/package.json +3 -4
  171. package/src/HttpService.ts +183 -53
  172. package/src/OxyServices.errors.ts +7 -3
  173. package/src/OxyServices.ts +6 -2
  174. package/src/api/accounts.ts +96 -28
  175. package/src/api/agency.ts +24 -9
  176. package/src/api/appData.ts +12 -2
  177. package/src/api/apps.ts +81 -31
  178. package/src/api/assets.ts +113 -43
  179. package/src/api/auth.ts +145 -77
  180. package/src/api/billing.ts +112 -65
  181. package/src/api/civic.ts +61 -19
  182. package/src/api/contacts.ts +4 -1
  183. package/src/api/devices.ts +54 -21
  184. package/src/api/follows.ts +88 -31
  185. package/src/api/identity.ts +101 -33
  186. package/src/api/linkedAccounts.ts +26 -8
  187. package/src/api/nodes.ts +18 -6
  188. package/src/api/notifications.ts +26 -6
  189. package/src/api/privacy.ts +42 -8
  190. package/src/api/reputation.ts +18 -7
  191. package/src/api/session.ts +23 -5
  192. package/src/api/store.ts +81 -31
  193. package/src/api/topics.ts +18 -6
  194. package/src/api/users.ts +98 -35
  195. package/src/boot/sessionColdBoot.ts +60 -19
  196. package/src/civic/payloads.ts +1 -4
  197. package/src/client/context.ts +6 -1
  198. package/src/constants/version.ts +7 -6
  199. package/src/crypto/aead.ts +1 -5
  200. package/src/crypto/ecdh.ts +1 -4
  201. package/src/crypto/identityDerivations.ts +5 -1
  202. package/src/crypto/identityMarker.ts +3 -1
  203. package/src/crypto/identityProof.ts +6 -1
  204. package/src/crypto/index.ts +11 -11
  205. package/src/crypto/internal.ts +6 -1
  206. package/src/crypto/keyManager.ts +348 -98
  207. package/src/crypto/recoveryPhrase.ts +14 -9
  208. package/src/crypto/registrationPow.ts +1 -1
  209. package/src/crypto/signatureService.ts +14 -6
  210. package/src/i18n/accountCategoryLabels.ts +1 -4
  211. package/src/i18n/accountRoleLabels.ts +1 -4
  212. package/src/i18n/index.ts +25 -7
  213. package/src/i18n/locales/ar-SA.ts +375 -366
  214. package/src/i18n/locales/ca-ES.ts +382 -366
  215. package/src/i18n/locales/de-DE.ts +387 -366
  216. package/src/i18n/locales/en-US.ts +2034 -1994
  217. package/src/i18n/locales/es-ES.ts +2043 -1994
  218. package/src/i18n/locales/fr-FR.ts +387 -366
  219. package/src/i18n/locales/it-IT.ts +380 -366
  220. package/src/i18n/locales/ja-JP.ts +380 -366
  221. package/src/i18n/locales/ko-KR.ts +377 -366
  222. package/src/i18n/locales/pt-PT.ts +383 -366
  223. package/src/i18n/locales/zh-CN.ts +373 -366
  224. package/src/i18n/trustTierLabels.ts +1 -4
  225. package/src/index.ts +371 -349
  226. package/src/inference/OxyInferenceClient.ts +784 -780
  227. package/src/models/interfaces.ts +39 -27
  228. package/src/server/OxyServer.ts +227 -68
  229. package/src/server/agentAccount.ts +8 -2
  230. package/src/server/aliaMachineCredential.ts +57 -16
  231. package/src/server/auth.ts +9 -5
  232. package/src/server/capabilityTicket.ts +30 -21
  233. package/src/server/index.ts +29 -6
  234. package/src/server/liveCapabilityTicket.ts +31 -9
  235. package/src/server/middleware.ts +212 -121
  236. package/src/server/namespaces.ts +247 -94
  237. package/src/server/rateLimit.ts +2 -4
  238. package/src/server/requesterAssertion.ts +93 -54
  239. package/src/server/serviceTokenLifetime.ts +9 -4
  240. package/src/server/traffic.ts +117 -23
  241. package/src/server/trafficNodeHttp.ts +61 -14
  242. package/src/server/userInvalidation.ts +1 -4
  243. package/src/server/workloadIdentity.client.ts +12 -1
  244. package/src/server/workloadIdentity.ts +52 -5
  245. package/src/session/SessionClient.ts +170 -49
  246. package/src/session/accountDelegationAccess.ts +24 -31
  247. package/src/session/accountDialogController.ts +59 -14
  248. package/src/session/accountSwitchTargets.ts +10 -15
  249. package/src/session/authStateStore.ts +121 -81
  250. package/src/session/deviceDirectory.ts +1 -3
  251. package/src/session/identityPin.ts +10 -11
  252. package/src/session/identitySession.ts +3 -1
  253. package/src/session/index.ts +87 -82
  254. package/src/session/refresh.ts +138 -44
  255. package/src/session/sessionClientHost.ts +1 -3
  256. package/src/session/sharedDeviceCredential.ts +35 -14
  257. package/src/session/socketLoader.ts +9 -2
  258. package/src/shared/utils/errorUtils.ts +5 -2
  259. package/src/shared/utils/networkUtils.ts +5 -8
  260. package/src/shared/utils/themeUtils.ts +2 -6
  261. package/src/types/buffer.d.ts +66 -21
  262. package/src/types/expo-secure-store.d.ts +5 -1
  263. package/src/utils/accountCacheSweep.ts +4 -5
  264. package/src/utils/accountUtils.ts +107 -108
  265. package/src/utils/apiUtils.ts +3 -3
  266. package/src/utils/asyncUtils.ts +2 -2
  267. package/src/utils/authHelpers.ts +10 -5
  268. package/src/utils/avatarUtils.ts +11 -6
  269. package/src/utils/cache.ts +9 -10
  270. package/src/utils/cacheKey.ts +5 -1
  271. package/src/utils/coldBoot.ts +1 -3
  272. package/src/utils/commonsDelivery.ts +1 -4
  273. package/src/utils/deviceManager.ts +15 -14
  274. package/src/utils/errorUtils.ts +68 -86
  275. package/src/utils/languageUtils.ts +407 -58
  276. package/src/utils/oauthPkce.ts +1 -4
  277. package/src/utils/platform.ts +0 -1
  278. package/src/utils/profileLinks.ts +2 -5
  279. package/src/utils/requestUtils.ts +18 -14
  280. package/src/utils/sessionUtils.ts +34 -33
  281. package/src/utils/userHandle.ts +3 -1
  282. package/src/utils/userIdentity.ts +1 -1
  283. package/src/utils/validationUtils.ts +11 -9
@@ -14,7 +14,10 @@ import type { ApiError, User } from '../models/interfaces';
14
14
  import { loadNodeCrypto } from '@oxy.so/protocol';
15
15
  import { logger } from '../logger';
16
16
  import { toOxyApiError } from '../OxyServices.errors';
17
- import { OXY_SERVICE_ENVIRONMENTS, type OxyServiceEnvironment } from '../utils/oxyServiceEnvironment';
17
+ import {
18
+ OXY_SERVICE_ENVIRONMENTS,
19
+ type OxyServiceEnvironment,
20
+ } from '../utils/oxyServiceEnvironment';
18
21
 
19
22
  interface JwtPayload {
20
23
  exp?: number;
@@ -245,8 +248,7 @@ class ServiceTokenClaimError extends Error {
245
248
 
246
249
  function isOxyServiceEnvironment(value: unknown): value is OxyServiceEnvironment {
247
250
  return (
248
- typeof value === 'string' &&
249
- (OXY_SERVICE_ENVIRONMENTS as readonly string[]).includes(value)
251
+ typeof value === 'string' && (OXY_SERVICE_ENVIRONMENTS as readonly string[]).includes(value)
250
252
  );
251
253
  }
252
254
 
@@ -290,7 +292,6 @@ export interface AuthMiddlewareOptions {
290
292
  expectedAudience?: string;
291
293
  }
292
294
 
293
-
294
295
  /**
295
296
  * What the middleware needs from the server it is mounted on. `OxyServer`
296
297
  * builds it; every member is resolved at call time, so a test can spy on the
@@ -303,9 +304,16 @@ export interface OxyMiddlewareHost {
303
304
  sessionId: string,
304
305
  options?: { deviceFingerprint?: string; useHeaderValidation?: boolean },
305
306
  ): Promise<{ valid: boolean; user?: User; actor?: unknown } | null>;
306
- verifyActingAs(appId: string, userId: string, options?: {
307
- cache?: boolean; credentialId?: string; ownerAccountId?: string; environment?: string;
308
- }): Promise<ServiceActingAsVerification | null>;
307
+ verifyActingAs(
308
+ appId: string,
309
+ userId: string,
310
+ options?: {
311
+ cache?: boolean;
312
+ credentialId?: string;
313
+ ownerAccountId?: string;
314
+ environment?: string;
315
+ },
316
+ ): Promise<ServiceActingAsVerification | null>;
309
317
  }
310
318
 
311
319
  /** Build the middleware set for one server. See `OxyServer.middleware`. */
@@ -434,10 +442,14 @@ export function createOxyMiddleware(host: OxyMiddlewareHost) {
434
442
  try {
435
443
  onRefusal(recorded);
436
444
  } catch (observerError) {
437
- logger.warn('[oxy.auth] onRefusal observer threw', {
438
- component: 'auth',
439
- method: 'auth',
440
- }, observerError);
445
+ logger.warn(
446
+ '[oxy.auth] onRefusal observer threw',
447
+ {
448
+ component: 'auth',
449
+ method: 'auth',
450
+ },
451
+ observerError,
452
+ );
441
453
  }
442
454
  }
443
455
  };
@@ -470,7 +482,7 @@ export function createOxyMiddleware(host: OxyMiddlewareHost) {
470
482
  error: 'MISSING_TOKEN',
471
483
  message: 'Access token required',
472
484
  code: 'MISSING_TOKEN',
473
- status: 401
485
+ status: 401,
474
486
  };
475
487
  if (onError) return onError(error);
476
488
  return res.status(401).json(error);
@@ -488,10 +500,14 @@ export function createOxyMiddleware(host: OxyMiddlewareHost) {
488
500
  status: 401,
489
501
  });
490
502
  if (debug) {
491
- logger.debug('[oxy.auth] Token decode failed', {
492
- component: 'auth',
493
- method: 'auth',
494
- }, decodeError);
503
+ logger.debug(
504
+ '[oxy.auth] Token decode failed',
505
+ {
506
+ component: 'auth',
507
+ method: 'auth',
508
+ },
509
+ decodeError,
510
+ );
495
511
  }
496
512
  if (optional) {
497
513
  req.userId = null;
@@ -503,7 +519,7 @@ export function createOxyMiddleware(host: OxyMiddlewareHost) {
503
519
  error: 'INVALID_TOKEN_FORMAT',
504
520
  message: 'Invalid token format',
505
521
  code: 'INVALID_TOKEN_FORMAT',
506
- status: 401
522
+ status: 401,
507
523
  };
508
524
  if (onError) return onError(error);
509
525
  return res.status(401).json(error);
@@ -536,9 +552,10 @@ export function createOxyMiddleware(host: OxyMiddlewareHost) {
536
552
  verifyError instanceof ServiceTokenSignatureError ||
537
553
  verifyError instanceof ServiceTokenClaimError
538
554
  ) {
539
- const code = verifyError instanceof ServiceTokenClaimError
540
- ? 'INVALID_SERVICE_TOKEN_CLAIMS'
541
- : 'INVALID_SERVICE_TOKEN';
555
+ const code =
556
+ verifyError instanceof ServiceTokenClaimError
557
+ ? 'INVALID_SERVICE_TOKEN_CLAIMS'
558
+ : 'INVALID_SERVICE_TOKEN';
542
559
  // The SDK's own message is the whole diagnostic value here —
543
560
  // "signing key is unknown" (rotated/unpublished kid), "key set
544
561
  // is unavailable" (JWKS empty, unreachable or malformed) and
@@ -573,10 +590,14 @@ export function createOxyMiddleware(host: OxyMiddlewareHost) {
573
590
  return res.status(401).json(error);
574
591
  }
575
592
 
576
- logger.error('[oxy.auth] Unexpected error during service token verification', verifyError, {
577
- component: 'auth',
578
- method: 'auth.serviceToken',
579
- });
593
+ logger.error(
594
+ '[oxy.auth] Unexpected error during service token verification',
595
+ verifyError,
596
+ {
597
+ component: 'auth',
598
+ method: 'auth.serviceToken',
599
+ },
600
+ );
580
601
  const error = {
581
602
  error: 'AUTH_INTERNAL_ERROR',
582
603
  message: 'Internal authentication error',
@@ -603,7 +624,12 @@ export function createOxyMiddleware(host: OxyMiddlewareHost) {
603
624
  req.user = null;
604
625
  return next();
605
626
  }
606
- const error = { error: 'TOKEN_EXPIRED', message: 'Service token expired', code: 'TOKEN_EXPIRED', status: 401 };
627
+ const error = {
628
+ error: 'TOKEN_EXPIRED',
629
+ message: 'Service token expired',
630
+ code: 'TOKEN_EXPIRED',
631
+ status: 401,
632
+ };
607
633
  if (onError) return onError(error);
608
634
  return res.status(401).json(error);
609
635
  }
@@ -614,7 +640,12 @@ export function createOxyMiddleware(host: OxyMiddlewareHost) {
614
640
  reason: 'Service token is not yet valid (nbf)',
615
641
  status: 401,
616
642
  });
617
- const error = { error: 'INVALID_SERVICE_TOKEN_CLAIMS', message: 'Service token is not yet valid', code: 'INVALID_SERVICE_TOKEN_CLAIMS', status: 401 };
643
+ const error = {
644
+ error: 'INVALID_SERVICE_TOKEN_CLAIMS',
645
+ message: 'Service token is not yet valid',
646
+ code: 'INVALID_SERVICE_TOKEN_CLAIMS',
647
+ status: 401,
648
+ };
618
649
  if (onError) return onError(error);
619
650
  return res.status(401).json(error);
620
651
  }
@@ -632,10 +663,12 @@ export function createOxyMiddleware(host: OxyMiddlewareHost) {
632
663
  !isExactNonEmptyServiceClaim(decoded.appName) ||
633
664
  !isExactNonEmptyServiceClaim(credentialId) ||
634
665
  !isExactNonEmptyServiceClaim(ownerAccountId) ||
635
- !isOxyServiceEnvironment(environment)
636
- || !Array.isArray(decoded.scopes)
637
- || !decoded.scopes.every((scope) => typeof scope === 'string' && scope.length > 0 && scope === scope.trim())
638
- || new Set(decoded.scopes).size !== decoded.scopes.length
666
+ !isOxyServiceEnvironment(environment) ||
667
+ !Array.isArray(decoded.scopes) ||
668
+ !decoded.scopes.every(
669
+ (scope) => typeof scope === 'string' && scope.length > 0 && scope === scope.trim(),
670
+ ) ||
671
+ new Set(decoded.scopes).size !== decoded.scopes.length
639
672
  ) {
640
673
  recordRefusal(req, {
641
674
  code: 'INVALID_SERVICE_TOKEN',
@@ -643,14 +676,18 @@ export function createOxyMiddleware(host: OxyMiddlewareHost) {
643
676
  // Names the field rather than its value: an exact-match claim
644
677
  // failing on invisible whitespace reads as "present" in a log
645
678
  // that only says which claims were missing.
646
- reason: `Service token claims unusable (${[
647
- !isExactNonEmptyServiceClaim(appId) ? 'appId' : null,
648
- !isExactNonEmptyServiceClaim(decoded.appName) ? 'appName' : null,
649
- !isExactNonEmptyServiceClaim(credentialId) ? 'credentialId' : null,
650
- !isExactNonEmptyServiceClaim(ownerAccountId) ? 'ownerAccountId' : null,
651
- !isOxyServiceEnvironment(environment) ? 'environment' : null,
652
- !Array.isArray(decoded.scopes) ? 'scopes' : null,
653
- ].filter((field) => field !== null).join(', ') || 'scopes'})`,
679
+ reason: `Service token claims unusable (${
680
+ [
681
+ !isExactNonEmptyServiceClaim(appId) ? 'appId' : null,
682
+ !isExactNonEmptyServiceClaim(decoded.appName) ? 'appName' : null,
683
+ !isExactNonEmptyServiceClaim(credentialId) ? 'credentialId' : null,
684
+ !isExactNonEmptyServiceClaim(ownerAccountId) ? 'ownerAccountId' : null,
685
+ !isOxyServiceEnvironment(environment) ? 'environment' : null,
686
+ !Array.isArray(decoded.scopes) ? 'scopes' : null,
687
+ ]
688
+ .filter((field) => field !== null)
689
+ .join(', ') || 'scopes'
690
+ })`,
654
691
  status: 401,
655
692
  });
656
693
  if (optional) {
@@ -658,7 +695,12 @@ export function createOxyMiddleware(host: OxyMiddlewareHost) {
658
695
  req.user = null;
659
696
  return next();
660
697
  }
661
- const error = { error: 'INVALID_SERVICE_TOKEN', message: 'Invalid service token: missing required claims', code: 'INVALID_SERVICE_TOKEN', status: 401 };
698
+ const error = {
699
+ error: 'INVALID_SERVICE_TOKEN',
700
+ message: 'Invalid service token: missing required claims',
701
+ code: 'INVALID_SERVICE_TOKEN',
702
+ status: 401,
703
+ };
662
704
  if (onError) return onError(error);
663
705
  return res.status(401).json(error);
664
706
  }
@@ -694,8 +736,10 @@ export function createOxyMiddleware(host: OxyMiddlewareHost) {
694
736
  // `req.userId = oxyUserId` would let any service impersonate
695
737
  // any user simply by setting the header.
696
738
  const grant = await host.verifyActingAs(appId, oxyUserId, {
697
- cache: false, credentialId: decoded.credentialId as string,
698
- ownerAccountId: decoded.ownerAccountId as string, environment: decoded.environment as string,
739
+ cache: false,
740
+ credentialId: decoded.credentialId as string,
741
+ ownerAccountId: decoded.ownerAccountId as string,
742
+ environment: decoded.environment as string,
699
743
  });
700
744
  if (!grant || !grant.authorized) {
701
745
  logger.warn('[oxy.auth] Service token rejected — no delegation grant', {
@@ -750,10 +794,13 @@ export function createOxyMiddleware(host: OxyMiddlewareHost) {
750
794
  };
751
795
 
752
796
  if (debug) {
753
- logger.debug(`[oxy.auth] Service token OK app=${decoded.appName} delegateUser=${oxyUserId || '(none)'}`, {
754
- component: 'auth',
755
- method: 'auth.serviceToken',
756
- });
797
+ logger.debug(
798
+ `[oxy.auth] Service token OK app=${decoded.appName} delegateUser=${oxyUserId || '(none)'}`,
799
+ {
800
+ component: 'auth',
801
+ method: 'auth.serviceToken',
802
+ },
803
+ );
757
804
  }
758
805
 
759
806
  return next();
@@ -779,7 +826,7 @@ export function createOxyMiddleware(host: OxyMiddlewareHost) {
779
826
  error: 'INVALID_TOKEN_PAYLOAD',
780
827
  message: 'Token missing user ID',
781
828
  code: 'INVALID_TOKEN_PAYLOAD',
782
- status: 401
829
+ status: 401,
783
830
  };
784
831
  if (onError) return onError(error);
785
832
  return res.status(401).json(error);
@@ -804,7 +851,7 @@ export function createOxyMiddleware(host: OxyMiddlewareHost) {
804
851
  error: 'TOKEN_EXPIRED',
805
852
  message: 'Token expired',
806
853
  code: 'TOKEN_EXPIRED',
807
- status: 401
854
+ status: 401,
808
855
  };
809
856
  if (onError) return onError(error);
810
857
  return res.status(401).json(error);
@@ -833,7 +880,7 @@ export function createOxyMiddleware(host: OxyMiddlewareHost) {
833
880
  error: 'SESSION_REQUIRED',
834
881
  message: 'Access token is not bound to a session',
835
882
  code: 'SESSION_REQUIRED',
836
- status: 401
883
+ status: 401,
837
884
  };
838
885
  if (onError) return onError(error);
839
886
  return res.status(401).json(error);
@@ -863,7 +910,7 @@ export function createOxyMiddleware(host: OxyMiddlewareHost) {
863
910
  error: 'INVALID_SESSION',
864
911
  message: 'Session invalid or expired',
865
912
  code: 'INVALID_SESSION',
866
- status: 401
913
+ status: 401,
867
914
  };
868
915
  if (onError) return onError(error);
869
916
  return res.status(401).json(error);
@@ -888,7 +935,7 @@ export function createOxyMiddleware(host: OxyMiddlewareHost) {
888
935
  error: 'INVALID_SESSION',
889
936
  message: 'Session did not resolve to a usable identity',
890
937
  code: 'INVALID_SESSION',
891
- status: 401
938
+ status: 401,
892
939
  };
893
940
  if (onError) return onError(error);
894
941
  return res.status(401).json(error);
@@ -921,7 +968,7 @@ export function createOxyMiddleware(host: OxyMiddlewareHost) {
921
968
  error: 'SESSION_USER_MISMATCH',
922
969
  message: 'Token user does not match the session',
923
970
  code: 'SESSION_USER_MISMATCH',
924
- status: 401
971
+ status: 401,
925
972
  };
926
973
  if (onError) return onError(error);
927
974
  return res.status(401).json(error);
@@ -957,7 +1004,7 @@ export function createOxyMiddleware(host: OxyMiddlewareHost) {
957
1004
  error: 'SESSION_ACTOR_MISMATCH',
958
1005
  message: 'Session actor does not match the session',
959
1006
  code: 'SESSION_ACTOR_MISMATCH',
960
- status: 401
1007
+ status: 401,
961
1008
  };
962
1009
  if (onError) return onError(error);
963
1010
  return res.status(401).json(error);
@@ -970,7 +1017,9 @@ export function createOxyMiddleware(host: OxyMiddlewareHost) {
970
1017
  // Session validation already returned the full user, so `loadUser`
971
1018
  // costs no extra round-trip.
972
1019
  // One id source: the one `getUserIdentityId` validated (`id`, else `_id`).
973
- req.user = loadUser ? ({ ...validationResult.user, id: validatedUserId } as OxyRequestUser) : { id: validatedUserId };
1020
+ req.user = loadUser
1021
+ ? ({ ...validationResult.user, id: validatedUserId } as OxyRequestUser)
1022
+ : { id: validatedUserId };
974
1023
 
975
1024
  if (debug) {
976
1025
  logger.debug(`[oxy.auth] OK user=${validatedUserId} session=${sessionId}`, {
@@ -991,10 +1040,14 @@ export function createOxyMiddleware(host: OxyMiddlewareHost) {
991
1040
  status: 401,
992
1041
  });
993
1042
  if (debug) {
994
- logger.debug('[oxy.auth] Session validation failed', {
995
- component: 'auth',
996
- method: 'auth',
997
- }, validationError);
1043
+ logger.debug(
1044
+ '[oxy.auth] Session validation failed',
1045
+ {
1046
+ component: 'auth',
1047
+ method: 'auth',
1048
+ },
1049
+ validationError,
1050
+ );
998
1051
  }
999
1052
 
1000
1053
  if (optional) {
@@ -1007,7 +1060,7 @@ export function createOxyMiddleware(host: OxyMiddlewareHost) {
1007
1060
  error: 'SESSION_VALIDATION_ERROR',
1008
1061
  message: 'Session validation failed',
1009
1062
  code: 'SESSION_VALIDATION_ERROR',
1010
- status: 401
1063
+ status: 401,
1011
1064
  };
1012
1065
  if (onError) return onError(error);
1013
1066
  return res.status(401).json(error);
@@ -1026,10 +1079,14 @@ export function createOxyMiddleware(host: OxyMiddlewareHost) {
1026
1079
  };
1027
1080
 
1028
1081
  if (debug) {
1029
- logger.debug('[oxy.auth] Error', {
1030
- component: 'auth',
1031
- method: 'auth',
1032
- }, apiError);
1082
+ logger.debug(
1083
+ '[oxy.auth] Error',
1084
+ {
1085
+ component: 'auth',
1086
+ method: 'auth',
1087
+ },
1088
+ apiError,
1089
+ );
1033
1090
  }
1034
1091
 
1035
1092
  if (onError) return onError(apiError);
@@ -1078,10 +1135,14 @@ export function createOxyMiddleware(host: OxyMiddlewareHost) {
1078
1135
  decoded = jwtDecode<JwtPayload>(token);
1079
1136
  } catch (decodeError) {
1080
1137
  if (debug) {
1081
- logger.debug('[oxy.authSocket] Token decode failed', {
1082
- component: 'auth',
1083
- method: 'authSocket',
1084
- }, decodeError);
1138
+ logger.debug(
1139
+ '[oxy.authSocket] Token decode failed',
1140
+ {
1141
+ component: 'auth',
1142
+ method: 'authSocket',
1143
+ },
1144
+ decodeError,
1145
+ );
1085
1146
  }
1086
1147
  return next(new Error('Invalid token'));
1087
1148
  }
@@ -1124,10 +1185,14 @@ export function createOxyMiddleware(host: OxyMiddlewareHost) {
1124
1185
  userId = validatedUserId;
1125
1186
  } catch (validateErr) {
1126
1187
  if (debug) {
1127
- logger.debug('[oxy.authSocket] Session validation failed', {
1128
- component: 'auth',
1129
- method: 'authSocket',
1130
- }, validateErr);
1188
+ logger.debug(
1189
+ '[oxy.authSocket] Session validation failed',
1190
+ {
1191
+ component: 'auth',
1192
+ method: 'authSocket',
1193
+ },
1194
+ validateErr,
1195
+ );
1131
1196
  }
1132
1197
  return next(new Error('Session validation failed'));
1133
1198
  }
@@ -1153,10 +1218,14 @@ export function createOxyMiddleware(host: OxyMiddlewareHost) {
1153
1218
  next();
1154
1219
  } catch (err) {
1155
1220
  if (debug) {
1156
- logger.debug('[oxy.authSocket] Error', {
1157
- component: 'auth',
1158
- method: 'authSocket',
1159
- }, err);
1221
+ logger.debug(
1222
+ '[oxy.authSocket] Error',
1223
+ {
1224
+ component: 'auth',
1225
+ method: 'authSocket',
1226
+ },
1227
+ err,
1228
+ );
1160
1229
  }
1161
1230
  next(new Error('Authentication error'));
1162
1231
  }
@@ -1178,14 +1247,16 @@ export function createOxyMiddleware(host: OxyMiddlewareHost) {
1178
1247
  * });
1179
1248
  * ```
1180
1249
  */
1181
- function service(options: {
1182
- debug?: boolean;
1183
- /** Observe refusals on the service lane; forwarded straight to `auth()`. */
1184
- onRefusal?: (refusal: OxyAuthRefusal) => void;
1185
- serviceTokenJwksUrl?: string;
1186
- expectedIssuer?: string;
1187
- expectedAudience?: string;
1188
- } = {}) {
1250
+ function service(
1251
+ options: {
1252
+ debug?: boolean;
1253
+ /** Observe refusals on the service lane; forwarded straight to `auth()`. */
1254
+ onRefusal?: (refusal: OxyAuthRefusal) => void;
1255
+ serviceTokenJwksUrl?: string;
1256
+ expectedIssuer?: string;
1257
+ expectedAudience?: string;
1258
+ } = {},
1259
+ ) {
1189
1260
  const innerAuth = auth({ ...options });
1190
1261
 
1191
1262
  return async (req: AuthReq, res: AuthRes, next: AuthNext) => {
@@ -1287,7 +1358,6 @@ export function createOxyMiddleware(host: OxyMiddlewareHost) {
1287
1358
  /** The middleware set `OxyServer.middleware` exposes. */
1288
1359
  export type OxyMiddleware = ReturnType<typeof createOxyMiddleware>;
1289
1360
 
1290
-
1291
1361
  // ---------------------------------------------------------------------------
1292
1362
  // Service token verification helpers
1293
1363
  // ---------------------------------------------------------------------------
@@ -1319,12 +1389,15 @@ const JWKS_MAX_BYTES = 64 * 1024;
1319
1389
  const JWKS_MAX_KEYS = 20;
1320
1390
 
1321
1391
  export function parseJsonSegment(segment: string): Record<string, unknown> {
1322
- if (!/^[A-Za-z0-9_-]+$/.test(segment)) throw new ServiceTokenStructureError('Service token segment is not base64url');
1392
+ if (!/^[A-Za-z0-9_-]+$/.test(segment))
1393
+ throw new ServiceTokenStructureError('Service token segment is not base64url');
1323
1394
  const bytes = Buffer.from(segment, 'base64url');
1324
- if (bytes.toString('base64url') !== segment) throw new ServiceTokenStructureError('Service token segment is not canonical base64url');
1395
+ if (bytes.toString('base64url') !== segment)
1396
+ throw new ServiceTokenStructureError('Service token segment is not canonical base64url');
1325
1397
  try {
1326
1398
  const value = JSON.parse(bytes.toString('utf8')) as unknown;
1327
- if (typeof value !== 'object' || value === null || Array.isArray(value)) throw new Error('not an object');
1399
+ if (typeof value !== 'object' || value === null || Array.isArray(value))
1400
+ throw new Error('not an object');
1328
1401
  return value as Record<string, unknown>;
1329
1402
  } catch {
1330
1403
  throw new ServiceTokenStructureError('Service token segment is not a JSON object');
@@ -1332,25 +1405,29 @@ export function parseJsonSegment(segment: string): Record<string, unknown> {
1332
1405
  }
1333
1406
 
1334
1407
  function parseServiceTokenJwks(value: unknown): Map<string, ServiceTokenPublicJwk> {
1335
- if (typeof value !== 'object' || value === null || Array.isArray(value)) throw new ServiceTokenSignatureError('Oxy JWKS is malformed');
1408
+ if (typeof value !== 'object' || value === null || Array.isArray(value))
1409
+ throw new ServiceTokenSignatureError('Oxy JWKS is malformed');
1336
1410
  const keys = (value as { keys?: unknown }).keys;
1337
- if (!Array.isArray(keys) || keys.length === 0 || keys.length > JWKS_MAX_KEYS) throw new ServiceTokenSignatureError('Oxy JWKS has an invalid key set');
1411
+ if (!Array.isArray(keys) || keys.length === 0 || keys.length > JWKS_MAX_KEYS)
1412
+ throw new ServiceTokenSignatureError('Oxy JWKS has an invalid key set');
1338
1413
  const result = new Map<string, ServiceTokenPublicJwk>();
1339
1414
  for (const value of keys) {
1340
- if (typeof value !== 'object' || value === null || Array.isArray(value)) throw new ServiceTokenSignatureError('Oxy JWKS contains a malformed key');
1415
+ if (typeof value !== 'object' || value === null || Array.isArray(value))
1416
+ throw new ServiceTokenSignatureError('Oxy JWKS contains a malformed key');
1341
1417
  const key = value as Record<string, unknown>;
1342
1418
  if (
1343
- key.kty !== 'OKP'
1344
- || key.crv !== 'Ed25519'
1345
- || typeof key.x !== 'string'
1346
- || key.x.length === 0
1347
- || key.use !== 'sig'
1348
- || key.alg !== 'EdDSA'
1349
- || typeof key.kid !== 'string'
1350
- || !/^[A-Za-z0-9._-]{1,128}$/.test(key.kid)
1351
- || Object.prototype.hasOwnProperty.call(key, 'd')
1352
- || result.has(key.kid)
1353
- ) throw new ServiceTokenSignatureError('Oxy JWKS contains an unsupported or duplicate key');
1419
+ key.kty !== 'OKP' ||
1420
+ key.crv !== 'Ed25519' ||
1421
+ typeof key.x !== 'string' ||
1422
+ key.x.length === 0 ||
1423
+ key.use !== 'sig' ||
1424
+ key.alg !== 'EdDSA' ||
1425
+ typeof key.kid !== 'string' ||
1426
+ !/^[A-Za-z0-9._-]{1,128}$/.test(key.kid) ||
1427
+ Object.prototype.hasOwnProperty.call(key, 'd') ||
1428
+ result.has(key.kid)
1429
+ )
1430
+ throw new ServiceTokenSignatureError('Oxy JWKS contains an unsupported or duplicate key');
1354
1431
  const x = Buffer.from(key.x, 'base64url');
1355
1432
  if (x.length !== 32 || x.toString('base64url') !== key.x) {
1356
1433
  throw new ServiceTokenSignatureError('Oxy JWKS contains an invalid Ed25519 key');
@@ -1373,9 +1450,11 @@ async function refreshServiceTokenJwks(url: string, cache: ServiceTokenJwksCache
1373
1450
  signal: controller.signal,
1374
1451
  redirect: 'error',
1375
1452
  });
1376
- if (!response.ok) throw new ServiceTokenSignatureError(`Oxy JWKS returned HTTP ${response.status}`);
1453
+ if (!response.ok)
1454
+ throw new ServiceTokenSignatureError(`Oxy JWKS returned HTTP ${response.status}`);
1377
1455
  const source = await response.text();
1378
- if (Buffer.byteLength(source, 'utf8') > JWKS_MAX_BYTES) throw new ServiceTokenSignatureError('Oxy JWKS exceeds the size limit');
1456
+ if (Buffer.byteLength(source, 'utf8') > JWKS_MAX_BYTES)
1457
+ throw new ServiceTokenSignatureError('Oxy JWKS exceeds the size limit');
1379
1458
  cache.keys = parseServiceTokenJwks(JSON.parse(source) as unknown);
1380
1459
  cache.expiresAt = Date.now() + JWKS_CACHE_MS;
1381
1460
  } finally {
@@ -1397,7 +1476,8 @@ export async function resolveServiceTokenPublicKey(
1397
1476
  const now = Date.now();
1398
1477
  const cached = cache.keys.get(kid);
1399
1478
  if (cached && cache.expiresAt > now) return cached;
1400
- const mayRefresh = cache.expiresAt <= now || now - cache.lastAttemptAt >= JWKS_UNKNOWN_KID_REFRESH_MS;
1479
+ const mayRefresh =
1480
+ cache.expiresAt <= now || now - cache.lastAttemptAt >= JWKS_UNKNOWN_KID_REFRESH_MS;
1401
1481
  if (mayRefresh) {
1402
1482
  try {
1403
1483
  await refreshServiceTokenJwks(url, cache);
@@ -1408,7 +1488,8 @@ export async function resolveServiceTokenPublicKey(
1408
1488
  }
1409
1489
  }
1410
1490
  const resolved = cache.keys.get(kid);
1411
- if (!resolved || cache.expiresAt <= Date.now()) throw new ServiceTokenSignatureError('Service token signing key is unknown');
1491
+ if (!resolved || cache.expiresAt <= Date.now())
1492
+ throw new ServiceTokenSignatureError('Service token signing key is unknown');
1412
1493
  return resolved;
1413
1494
  }
1414
1495
 
@@ -1432,12 +1513,13 @@ async function verifyServiceTokenSignature(
1432
1513
  }
1433
1514
  const header = parseJsonSegment(headerB64);
1434
1515
  if (
1435
- Object.keys(header).length !== 3
1436
- || header.alg !== 'EdDSA'
1437
- || header.typ !== 'JWT'
1438
- || typeof header.kid !== 'string'
1439
- || !/^[A-Za-z0-9._-]{1,128}$/.test(header.kid)
1440
- ) throw new ServiceTokenStructureError('Service token JOSE header is not supported');
1516
+ Object.keys(header).length !== 3 ||
1517
+ header.alg !== 'EdDSA' ||
1518
+ header.typ !== 'JWT' ||
1519
+ typeof header.kid !== 'string' ||
1520
+ !/^[A-Za-z0-9._-]{1,128}$/.test(header.kid)
1521
+ )
1522
+ throw new ServiceTokenStructureError('Service token JOSE header is not supported');
1441
1523
  const jwk = await resolveServiceTokenPublicKey(header.kid, options.jwksUrl, options.cache);
1442
1524
  let publicKey: Awaited<ReturnType<typeof nodeCrypto.createPublicKey>>;
1443
1525
  try {
@@ -1446,8 +1528,10 @@ async function verifyServiceTokenSignature(
1446
1528
  throw new ServiceTokenSignatureError('Service token public key is invalid');
1447
1529
  }
1448
1530
  const signature = Buffer.from(signatureB64, 'base64url');
1449
- if (signature.toString('base64url') !== signatureB64 || signature.length !== 64) throw new ServiceTokenStructureError('Service token signature is malformed');
1450
- if (!nodeCrypto.verify(null, Buffer.from(`${headerB64}.${payloadB64}`), publicKey, signature)) throw new ServiceTokenSignatureError();
1531
+ if (signature.toString('base64url') !== signatureB64 || signature.length !== 64)
1532
+ throw new ServiceTokenStructureError('Service token signature is malformed');
1533
+ if (!nodeCrypto.verify(null, Buffer.from(`${headerB64}.${payloadB64}`), publicKey, signature))
1534
+ throw new ServiceTokenSignatureError();
1451
1535
  }
1452
1536
 
1453
1537
  /**
@@ -1479,13 +1563,13 @@ function readStringClaim(value: unknown): string | null {
1479
1563
  /**
1480
1564
  * Resolve the canonical user id from a validated session's user object.
1481
1565
  *
1482
- * The API serializer emits `id`, but some upstream shapes carry the raw Mongo
1483
- * `_id` instead. We accept either, but only a non-empty string — anything else
1566
+ * The API serializer emits `id`, but some upstream shapes carry a raw `_id`
1567
+ * instead. We accept either, but only a non-empty string — anything else
1484
1568
  * means the validated identity is unusable and the caller must reject.
1485
1569
  */
1486
1570
  function getUserIdentityId(user: User): string | null {
1487
- const candidate = (user as { id?: unknown; _id?: unknown }).id
1488
- ?? (user as { id?: unknown; _id?: unknown })._id;
1571
+ const candidate =
1572
+ (user as { id?: unknown; _id?: unknown }).id ?? (user as { id?: unknown; _id?: unknown })._id;
1489
1573
  return typeof candidate === 'string' && candidate.length > 0 ? candidate : null;
1490
1574
  }
1491
1575
 
@@ -1501,21 +1585,29 @@ function verifyServiceTokenClaims(
1501
1585
  expected: { audience: string; issuer: string },
1502
1586
  ): void {
1503
1587
  if (!hasBoundedServiceTokenLifetime(decoded)) {
1504
- throw new ServiceTokenClaimError('Service token lifetime must be positive and at most 300 seconds');
1588
+ throw new ServiceTokenClaimError(
1589
+ 'Service token lifetime must be positive and at most 300 seconds',
1590
+ );
1505
1591
  }
1506
1592
  if (decoded.type !== 'service') {
1507
1593
  throw new ServiceTokenClaimError(`Service token has unexpected type '${String(decoded.type)}'`);
1508
1594
  }
1509
1595
  if (decoded.iss !== expected.issuer) {
1510
- throw new ServiceTokenClaimError(`Service token issuer mismatch: expected '${expected.issuer}', got '${String(decoded.iss)}'`);
1596
+ throw new ServiceTokenClaimError(
1597
+ `Service token issuer mismatch: expected '${expected.issuer}', got '${String(decoded.iss)}'`,
1598
+ );
1511
1599
  }
1512
1600
  const aud = decoded.aud;
1513
1601
  if (Array.isArray(aud)) {
1514
1602
  if (!aud.includes(expected.audience)) {
1515
- throw new ServiceTokenClaimError(`Service token audience does not include '${expected.audience}'`);
1603
+ throw new ServiceTokenClaimError(
1604
+ `Service token audience does not include '${expected.audience}'`,
1605
+ );
1516
1606
  }
1517
1607
  } else if (aud !== expected.audience) {
1518
- throw new ServiceTokenClaimError(`Service token audience mismatch: expected '${expected.audience}', got '${String(aud)}'`);
1608
+ throw new ServiceTokenClaimError(
1609
+ `Service token audience mismatch: expected '${expected.audience}', got '${String(aud)}'`,
1610
+ );
1519
1611
  }
1520
1612
  }
1521
1613
 
@@ -1568,4 +1660,3 @@ interface SocketLike {
1568
1660
  data?: Record<string, unknown>;
1569
1661
  user?: { id: string; userId: string; sessionId?: string | null };
1570
1662
  }
1571
-