@oxy.so/core 4.5.0-oxy-one.0 → 4.5.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 (285) 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 +49 -12
  7. package/dist/cjs/api/auth.js +37 -11
  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 +49 -12
  83. package/dist/esm/api/auth.js +37 -11
  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 +1 -1
  159. package/dist/types/api/apps.d.ts +4 -4
  160. package/dist/types/api/assets.d.ts +2 -0
  161. package/dist/types/api/auth.d.ts +8 -3
  162. package/dist/types/crypto/internal.d.ts +1 -1
  163. package/dist/types/index.d.ts +4 -4
  164. package/dist/types/server/index.d.ts +6 -6
  165. package/dist/types/server/requesterAssertion.d.ts +2 -2
  166. package/dist/types/server/workloadIdentity.client.d.ts +5 -1
  167. package/dist/types/server/workloadIdentity.d.ts +26 -0
  168. package/dist/types/session/accountDelegationAccess.d.ts +1 -1
  169. package/dist/types/session/index.d.ts +1 -1
  170. package/dist/types/utils/userIdentity.d.ts +1 -1
  171. package/dist/types/utils/validationUtils.d.ts +4 -5
  172. package/package.json +2 -3
  173. package/src/HttpService.ts +183 -53
  174. package/src/OxyServices.errors.ts +7 -3
  175. package/src/OxyServices.ts +6 -2
  176. package/src/api/accounts.ts +76 -26
  177. package/src/api/agency.ts +24 -9
  178. package/src/api/appData.ts +12 -2
  179. package/src/api/apps.ts +81 -31
  180. package/src/api/assets.ts +122 -40
  181. package/src/api/auth.ts +154 -79
  182. package/src/api/billing.ts +112 -65
  183. package/src/api/civic.ts +61 -19
  184. package/src/api/contacts.ts +4 -1
  185. package/src/api/devices.ts +54 -21
  186. package/src/api/follows.ts +88 -31
  187. package/src/api/identity.ts +101 -33
  188. package/src/api/linkedAccounts.ts +26 -8
  189. package/src/api/nodes.ts +18 -6
  190. package/src/api/notifications.ts +26 -6
  191. package/src/api/privacy.ts +42 -8
  192. package/src/api/reputation.ts +18 -7
  193. package/src/api/session.ts +23 -5
  194. package/src/api/store.ts +81 -31
  195. package/src/api/topics.ts +18 -6
  196. package/src/api/users.ts +98 -35
  197. package/src/boot/sessionColdBoot.ts +60 -19
  198. package/src/civic/payloads.ts +1 -4
  199. package/src/client/context.ts +6 -1
  200. package/src/constants/version.ts +7 -6
  201. package/src/crypto/aead.ts +1 -5
  202. package/src/crypto/ecdh.ts +1 -4
  203. package/src/crypto/identityDerivations.ts +5 -1
  204. package/src/crypto/identityMarker.ts +3 -1
  205. package/src/crypto/identityProof.ts +6 -1
  206. package/src/crypto/index.ts +11 -11
  207. package/src/crypto/internal.ts +6 -1
  208. package/src/crypto/keyManager.ts +348 -98
  209. package/src/crypto/recoveryPhrase.ts +14 -9
  210. package/src/crypto/registrationPow.ts +1 -1
  211. package/src/crypto/signatureService.ts +14 -6
  212. package/src/i18n/accountCategoryLabels.ts +1 -4
  213. package/src/i18n/accountRoleLabels.ts +1 -4
  214. package/src/i18n/index.ts +25 -7
  215. package/src/i18n/locales/ar-SA.ts +375 -366
  216. package/src/i18n/locales/ca-ES.ts +382 -366
  217. package/src/i18n/locales/de-DE.ts +387 -366
  218. package/src/i18n/locales/en-US.ts +2034 -1994
  219. package/src/i18n/locales/es-ES.ts +2043 -1994
  220. package/src/i18n/locales/fr-FR.ts +387 -366
  221. package/src/i18n/locales/it-IT.ts +380 -366
  222. package/src/i18n/locales/ja-JP.ts +380 -366
  223. package/src/i18n/locales/ko-KR.ts +377 -366
  224. package/src/i18n/locales/pt-PT.ts +383 -366
  225. package/src/i18n/locales/zh-CN.ts +373 -366
  226. package/src/i18n/trustTierLabels.ts +1 -4
  227. package/src/index.ts +371 -349
  228. package/src/inference/OxyInferenceClient.ts +784 -780
  229. package/src/models/interfaces.ts +30 -27
  230. package/src/server/OxyServer.ts +227 -68
  231. package/src/server/agentAccount.ts +8 -2
  232. package/src/server/aliaMachineCredential.ts +57 -16
  233. package/src/server/auth.ts +9 -5
  234. package/src/server/capabilityTicket.ts +30 -21
  235. package/src/server/index.ts +29 -6
  236. package/src/server/liveCapabilityTicket.ts +31 -9
  237. package/src/server/middleware.ts +212 -121
  238. package/src/server/namespaces.ts +247 -94
  239. package/src/server/rateLimit.ts +2 -4
  240. package/src/server/requesterAssertion.ts +93 -54
  241. package/src/server/serviceTokenLifetime.ts +9 -4
  242. package/src/server/traffic.ts +117 -23
  243. package/src/server/trafficNodeHttp.ts +61 -14
  244. package/src/server/userInvalidation.ts +1 -4
  245. package/src/server/workloadIdentity.client.ts +12 -1
  246. package/src/server/workloadIdentity.ts +52 -5
  247. package/src/session/SessionClient.ts +170 -49
  248. package/src/session/accountDelegationAccess.ts +24 -31
  249. package/src/session/accountDialogController.ts +59 -14
  250. package/src/session/accountSwitchTargets.ts +10 -15
  251. package/src/session/authStateStore.ts +121 -81
  252. package/src/session/deviceDirectory.ts +1 -3
  253. package/src/session/identityPin.ts +10 -11
  254. package/src/session/identitySession.ts +3 -1
  255. package/src/session/index.ts +87 -82
  256. package/src/session/refresh.ts +138 -44
  257. package/src/session/sessionClientHost.ts +1 -3
  258. package/src/session/sharedDeviceCredential.ts +35 -14
  259. package/src/session/socketLoader.ts +9 -2
  260. package/src/shared/utils/errorUtils.ts +5 -2
  261. package/src/shared/utils/networkUtils.ts +5 -8
  262. package/src/shared/utils/themeUtils.ts +2 -6
  263. package/src/types/buffer.d.ts +66 -21
  264. package/src/types/expo-secure-store.d.ts +5 -1
  265. package/src/utils/accountCacheSweep.ts +4 -5
  266. package/src/utils/accountUtils.ts +107 -108
  267. package/src/utils/apiUtils.ts +3 -3
  268. package/src/utils/asyncUtils.ts +2 -2
  269. package/src/utils/authHelpers.ts +10 -5
  270. package/src/utils/avatarUtils.ts +11 -6
  271. package/src/utils/cache.ts +9 -10
  272. package/src/utils/cacheKey.ts +5 -1
  273. package/src/utils/coldBoot.ts +1 -3
  274. package/src/utils/commonsDelivery.ts +1 -4
  275. package/src/utils/deviceManager.ts +15 -14
  276. package/src/utils/errorUtils.ts +68 -86
  277. package/src/utils/languageUtils.ts +407 -58
  278. package/src/utils/oauthPkce.ts +1 -4
  279. package/src/utils/platform.ts +0 -1
  280. package/src/utils/profileLinks.ts +2 -5
  281. package/src/utils/requestUtils.ts +18 -14
  282. package/src/utils/sessionUtils.ts +34 -33
  283. package/src/utils/userHandle.ts +3 -1
  284. package/src/utils/userIdentity.ts +1 -1
  285. package/src/utils/validationUtils.ts +11 -9
@@ -53,8 +53,7 @@ class ServiceTokenClaimError extends Error {
53
53
  }
54
54
  }
55
55
  function isOxyServiceEnvironment(value) {
56
- return (typeof value === 'string' &&
57
- oxyServiceEnvironment_1.OXY_SERVICE_ENVIRONMENTS.includes(value));
56
+ return (typeof value === 'string' && oxyServiceEnvironment_1.OXY_SERVICE_ENVIRONMENTS.includes(value));
58
57
  }
59
58
  /** Build the middleware set for one server. See `OxyServer.middleware`. */
60
59
  function createOxyMiddleware(host) {
@@ -202,7 +201,7 @@ function createOxyMiddleware(host) {
202
201
  error: 'MISSING_TOKEN',
203
202
  message: 'Access token required',
204
203
  code: 'MISSING_TOKEN',
205
- status: 401
204
+ status: 401,
206
205
  };
207
206
  if (onError)
208
207
  return onError(error);
@@ -235,7 +234,7 @@ function createOxyMiddleware(host) {
235
234
  error: 'INVALID_TOKEN_FORMAT',
236
235
  message: 'Invalid token format',
237
236
  code: 'INVALID_TOKEN_FORMAT',
238
- status: 401
237
+ status: 401,
239
238
  };
240
239
  if (onError)
241
240
  return onError(error);
@@ -334,7 +333,12 @@ function createOxyMiddleware(host) {
334
333
  req.user = null;
335
334
  return next();
336
335
  }
337
- const error = { error: 'TOKEN_EXPIRED', message: 'Service token expired', code: 'TOKEN_EXPIRED', status: 401 };
336
+ const error = {
337
+ error: 'TOKEN_EXPIRED',
338
+ message: 'Service token expired',
339
+ code: 'TOKEN_EXPIRED',
340
+ status: 401,
341
+ };
338
342
  if (onError)
339
343
  return onError(error);
340
344
  return res.status(401).json(error);
@@ -346,7 +350,12 @@ function createOxyMiddleware(host) {
346
350
  reason: 'Service token is not yet valid (nbf)',
347
351
  status: 401,
348
352
  });
349
- const error = { error: 'INVALID_SERVICE_TOKEN_CLAIMS', message: 'Service token is not yet valid', code: 'INVALID_SERVICE_TOKEN_CLAIMS', status: 401 };
353
+ const error = {
354
+ error: 'INVALID_SERVICE_TOKEN_CLAIMS',
355
+ message: 'Service token is not yet valid',
356
+ code: 'INVALID_SERVICE_TOKEN_CLAIMS',
357
+ status: 401,
358
+ };
350
359
  if (onError)
351
360
  return onError(error);
352
361
  return res.status(401).json(error);
@@ -363,10 +372,10 @@ function createOxyMiddleware(host) {
363
372
  !isExactNonEmptyServiceClaim(decoded.appName) ||
364
373
  !isExactNonEmptyServiceClaim(credentialId) ||
365
374
  !isExactNonEmptyServiceClaim(ownerAccountId) ||
366
- !isOxyServiceEnvironment(environment)
367
- || !Array.isArray(decoded.scopes)
368
- || !decoded.scopes.every((scope) => typeof scope === 'string' && scope.length > 0 && scope === scope.trim())
369
- || new Set(decoded.scopes).size !== decoded.scopes.length) {
375
+ !isOxyServiceEnvironment(environment) ||
376
+ !Array.isArray(decoded.scopes) ||
377
+ !decoded.scopes.every((scope) => typeof scope === 'string' && scope.length > 0 && scope === scope.trim()) ||
378
+ new Set(decoded.scopes).size !== decoded.scopes.length) {
370
379
  recordRefusal(req, {
371
380
  code: 'INVALID_SERVICE_TOKEN',
372
381
  stage: 'service-token',
@@ -380,7 +389,9 @@ function createOxyMiddleware(host) {
380
389
  !isExactNonEmptyServiceClaim(ownerAccountId) ? 'ownerAccountId' : null,
381
390
  !isOxyServiceEnvironment(environment) ? 'environment' : null,
382
391
  !Array.isArray(decoded.scopes) ? 'scopes' : null,
383
- ].filter((field) => field !== null).join(', ') || 'scopes'})`,
392
+ ]
393
+ .filter((field) => field !== null)
394
+ .join(', ') || 'scopes'})`,
384
395
  status: 401,
385
396
  });
386
397
  if (optional) {
@@ -388,7 +399,12 @@ function createOxyMiddleware(host) {
388
399
  req.user = null;
389
400
  return next();
390
401
  }
391
- const error = { error: 'INVALID_SERVICE_TOKEN', message: 'Invalid service token: missing required claims', code: 'INVALID_SERVICE_TOKEN', status: 401 };
402
+ const error = {
403
+ error: 'INVALID_SERVICE_TOKEN',
404
+ message: 'Invalid service token: missing required claims',
405
+ code: 'INVALID_SERVICE_TOKEN',
406
+ status: 401,
407
+ };
392
408
  if (onError)
393
409
  return onError(error);
394
410
  return res.status(401).json(error);
@@ -423,8 +439,10 @@ function createOxyMiddleware(host) {
423
439
  // `req.userId = oxyUserId` would let any service impersonate
424
440
  // any user simply by setting the header.
425
441
  const grant = await host.verifyActingAs(appId, oxyUserId, {
426
- cache: false, credentialId: decoded.credentialId,
427
- ownerAccountId: decoded.ownerAccountId, environment: decoded.environment,
442
+ cache: false,
443
+ credentialId: decoded.credentialId,
444
+ ownerAccountId: decoded.ownerAccountId,
445
+ environment: decoded.environment,
428
446
  });
429
447
  if (!grant || !grant.authorized) {
430
448
  logger_1.logger.warn('[oxy.auth] Service token rejected — no delegation grant', {
@@ -504,7 +522,7 @@ function createOxyMiddleware(host) {
504
522
  error: 'INVALID_TOKEN_PAYLOAD',
505
523
  message: 'Token missing user ID',
506
524
  code: 'INVALID_TOKEN_PAYLOAD',
507
- status: 401
525
+ status: 401,
508
526
  };
509
527
  if (onError)
510
528
  return onError(error);
@@ -528,7 +546,7 @@ function createOxyMiddleware(host) {
528
546
  error: 'TOKEN_EXPIRED',
529
547
  message: 'Token expired',
530
548
  code: 'TOKEN_EXPIRED',
531
- status: 401
549
+ status: 401,
532
550
  };
533
551
  if (onError)
534
552
  return onError(error);
@@ -556,7 +574,7 @@ function createOxyMiddleware(host) {
556
574
  error: 'SESSION_REQUIRED',
557
575
  message: 'Access token is not bound to a session',
558
576
  code: 'SESSION_REQUIRED',
559
- status: 401
577
+ status: 401,
560
578
  };
561
579
  if (onError)
562
580
  return onError(error);
@@ -584,7 +602,7 @@ function createOxyMiddleware(host) {
584
602
  error: 'INVALID_SESSION',
585
603
  message: 'Session invalid or expired',
586
604
  code: 'INVALID_SESSION',
587
- status: 401
605
+ status: 401,
588
606
  };
589
607
  if (onError)
590
608
  return onError(error);
@@ -608,7 +626,7 @@ function createOxyMiddleware(host) {
608
626
  error: 'INVALID_SESSION',
609
627
  message: 'Session did not resolve to a usable identity',
610
628
  code: 'INVALID_SESSION',
611
- status: 401
629
+ status: 401,
612
630
  };
613
631
  if (onError)
614
632
  return onError(error);
@@ -639,7 +657,7 @@ function createOxyMiddleware(host) {
639
657
  error: 'SESSION_USER_MISMATCH',
640
658
  message: 'Token user does not match the session',
641
659
  code: 'SESSION_USER_MISMATCH',
642
- status: 401
660
+ status: 401,
643
661
  };
644
662
  if (onError)
645
663
  return onError(error);
@@ -674,7 +692,7 @@ function createOxyMiddleware(host) {
674
692
  error: 'SESSION_ACTOR_MISMATCH',
675
693
  message: 'Session actor does not match the session',
676
694
  code: 'SESSION_ACTOR_MISMATCH',
677
- status: 401
695
+ status: 401,
678
696
  };
679
697
  if (onError)
680
698
  return onError(error);
@@ -687,7 +705,9 @@ function createOxyMiddleware(host) {
687
705
  // Session validation already returned the full user, so `loadUser`
688
706
  // costs no extra round-trip.
689
707
  // One id source: the one `getUserIdentityId` validated (`id`, else `_id`).
690
- req.user = loadUser ? { ...validationResult.user, id: validatedUserId } : { id: validatedUserId };
708
+ req.user = loadUser
709
+ ? { ...validationResult.user, id: validatedUserId }
710
+ : { id: validatedUserId };
691
711
  if (debug) {
692
712
  logger_1.logger.debug(`[oxy.auth] OK user=${validatedUserId} session=${sessionId}`, {
693
713
  component: 'auth',
@@ -721,7 +741,7 @@ function createOxyMiddleware(host) {
721
741
  error: 'SESSION_VALIDATION_ERROR',
722
742
  message: 'Session validation failed',
723
743
  code: 'SESSION_VALIDATION_ERROR',
724
- status: 401
744
+ status: 401,
725
745
  };
726
746
  if (onError)
727
747
  return onError(error);
@@ -1003,16 +1023,16 @@ function parseServiceTokenJwks(value) {
1003
1023
  if (typeof value !== 'object' || value === null || Array.isArray(value))
1004
1024
  throw new ServiceTokenSignatureError('Oxy JWKS contains a malformed key');
1005
1025
  const key = value;
1006
- if (key.kty !== 'OKP'
1007
- || key.crv !== 'Ed25519'
1008
- || typeof key.x !== 'string'
1009
- || key.x.length === 0
1010
- || key.use !== 'sig'
1011
- || key.alg !== 'EdDSA'
1012
- || typeof key.kid !== 'string'
1013
- || !/^[A-Za-z0-9._-]{1,128}$/.test(key.kid)
1014
- || Object.prototype.hasOwnProperty.call(key, 'd')
1015
- || result.has(key.kid))
1026
+ if (key.kty !== 'OKP' ||
1027
+ key.crv !== 'Ed25519' ||
1028
+ typeof key.x !== 'string' ||
1029
+ key.x.length === 0 ||
1030
+ key.use !== 'sig' ||
1031
+ key.alg !== 'EdDSA' ||
1032
+ typeof key.kid !== 'string' ||
1033
+ !/^[A-Za-z0-9._-]{1,128}$/.test(key.kid) ||
1034
+ Object.prototype.hasOwnProperty.call(key, 'd') ||
1035
+ result.has(key.kid))
1016
1036
  throw new ServiceTokenSignatureError('Oxy JWKS contains an unsupported or duplicate key');
1017
1037
  const x = Buffer.from(key.x, 'base64url');
1018
1038
  if (x.length !== 32 || x.toString('base64url') !== key.x) {
@@ -1093,11 +1113,11 @@ async function verifyServiceTokenSignature(token, options) {
1093
1113
  throw new ServiceTokenStructureError('Service token has empty segment');
1094
1114
  }
1095
1115
  const header = parseJsonSegment(headerB64);
1096
- if (Object.keys(header).length !== 3
1097
- || header.alg !== 'EdDSA'
1098
- || header.typ !== 'JWT'
1099
- || typeof header.kid !== 'string'
1100
- || !/^[A-Za-z0-9._-]{1,128}$/.test(header.kid))
1116
+ if (Object.keys(header).length !== 3 ||
1117
+ header.alg !== 'EdDSA' ||
1118
+ header.typ !== 'JWT' ||
1119
+ typeof header.kid !== 'string' ||
1120
+ !/^[A-Za-z0-9._-]{1,128}$/.test(header.kid))
1101
1121
  throw new ServiceTokenStructureError('Service token JOSE header is not supported');
1102
1122
  const jwk = await resolveServiceTokenPublicKey(header.kid, options.jwksUrl, options.cache);
1103
1123
  let publicKey;
@@ -1141,13 +1161,12 @@ function readStringClaim(value) {
1141
1161
  /**
1142
1162
  * Resolve the canonical user id from a validated session's user object.
1143
1163
  *
1144
- * The API serializer emits `id`, but some upstream shapes carry the raw Mongo
1145
- * `_id` instead. We accept either, but only a non-empty string — anything else
1164
+ * The API serializer emits `id`, but some upstream shapes carry a raw `_id`
1165
+ * instead. We accept either, but only a non-empty string — anything else
1146
1166
  * means the validated identity is unusable and the caller must reject.
1147
1167
  */
1148
1168
  function getUserIdentityId(user) {
1149
- const candidate = user.id
1150
- ?? user._id;
1169
+ const candidate = user.id ?? user._id;
1151
1170
  return typeof candidate === 'string' && candidate.length > 0 ? candidate : null;
1152
1171
  }
1153
1172
  /**
@@ -47,7 +47,9 @@ class ServerAppsApi extends apps_1.AppsApi {
47
47
  const record = answer;
48
48
  if (record.active === false && Object.keys(record).length === 1)
49
49
  return { active: false };
50
- if (record.active !== true || Object.keys(record).length !== 2 || !(0, aliaMachineCredential_1.isOxyAliaMachinePrincipal)(record.principal)) {
50
+ if (record.active !== true ||
51
+ Object.keys(record).length !== 2 ||
52
+ !(0, aliaMachineCredential_1.isOxyAliaMachinePrincipal)(record.principal)) {
51
53
  throw new Error('Invalid machine credential verdict');
52
54
  }
53
55
  return { active: true, principal: record.principal };
@@ -175,7 +177,9 @@ class ServerAssetsApi extends assets_1.AssetsApi {
175
177
  return [];
176
178
  const settled = await Promise.all(chunk(unique, SERVICE_ASSET_METADATA_BY_SHA_CHUNK_SIZE).map(async (part) => {
177
179
  try {
178
- const body = options.ownerUserId ? { sha256s: part, ownerUserId: options.ownerUserId } : { sha256s: part };
180
+ const body = options.ownerUserId
181
+ ? { sha256s: part, ownerUserId: options.ownerUserId }
182
+ : { sha256s: part };
179
183
  const entries = await lane(this.ctx).request('POST', '/assets/service/by-sha256', body);
180
184
  return Array.isArray(entries) ? entries : [];
181
185
  }
@@ -218,7 +222,14 @@ class ServerLinkedAccountsApi extends linkedAccounts_1.LinkedAccountsApi {
218
222
  exports.ServerLinkedAccountsApi = ServerLinkedAccountsApi;
219
223
  function agencyAuthorityOptions(signal) {
220
224
  signal?.throwIfAborted();
221
- return { cache: false, deduplicate: false, retry: false, skipAuth: true, timeout: 5000, ...(signal ? { signal } : {}) };
225
+ return {
226
+ cache: false,
227
+ deduplicate: false,
228
+ retry: false,
229
+ skipAuth: true,
230
+ timeout: 5000,
231
+ ...(signal ? { signal } : {}),
232
+ };
222
233
  }
223
234
  class ServerAgencyApi extends agency_1.AgencyApi {
224
235
  /** Live registry discovery with this service's existing capability scopes. */
@@ -256,15 +267,25 @@ class ServerAgencyApi extends agency_1.AgencyApi {
256
267
  options.signal?.throwIfAborted();
257
268
  if (!authorizationId || authorizationId.length > 255 || /\s/.test(authorizationId))
258
269
  throw new Error('An execution authorization id is required');
259
- if (!options.requesterToken || options.requesterToken.length > 16384 || /\s/.test(options.requesterToken))
270
+ if (!options.requesterToken ||
271
+ options.requesterToken.length > 16384 ||
272
+ /\s/.test(options.requesterToken))
260
273
  throw new Error('A requester bearer is required');
261
- await this.ctx.request('DELETE', `/capabilities/execution-authorizations/${encodeURIComponent(authorizationId)}`, undefined, { ...agencyAuthorityOptions(options.signal), headers: { Authorization: `Bearer ${options.requesterToken}` } });
274
+ await this.ctx.request('DELETE', `/capabilities/execution-authorizations/${encodeURIComponent(authorizationId)}`, undefined, {
275
+ ...agencyAuthorityOptions(options.signal),
276
+ headers: { Authorization: `Bearer ${options.requesterToken}` },
277
+ });
262
278
  }
263
279
  /** Independent service proof plus present requester bearer, sent only to Oxy. */
264
280
  async createForegroundExecutionAuthorization(input, options) {
265
- if (options.requesterToken === '' || options.requesterToken.length > 16384 || /\s/.test(options.requesterToken))
281
+ if (options.requesterToken === '' ||
282
+ options.requesterToken.length > 16384 ||
283
+ /\s/.test(options.requesterToken))
266
284
  throw new Error('A requester bearer is required');
267
- const result = await lane(this.ctx).request('POST', '/capabilities/foreground-execution-authorizations', { ...contracts_1.foregroundExecutionAuthorizationInputSchema.parse(input), subjectToken: options.requesterToken }, agencyAuthorityOptions(options.signal));
285
+ const result = await lane(this.ctx).request('POST', '/capabilities/foreground-execution-authorizations', {
286
+ ...contracts_1.foregroundExecutionAuthorizationInputSchema.parse(input),
287
+ subjectToken: options.requesterToken,
288
+ }, agencyAuthorityOptions(options.signal));
268
289
  return result.authorization;
269
290
  }
270
291
  /**
@@ -33,7 +33,8 @@ const KEY_ID_PATTERN = /^[A-Za-z0-9._-]{1,128}$/;
33
33
  const BASE64URL_PATTERN = /^[A-Za-z0-9_-]+$/;
34
34
  const MAX_ASSERTION_BYTES = 4096;
35
35
  const identifier = zod_1.z.string().min(1).max(128);
36
- exports.oxyRequesterAssertionClaimsSchema = zod_1.z.object({
36
+ exports.oxyRequesterAssertionClaimsSchema = zod_1.z
37
+ .object({
37
38
  iss: zod_1.z.string().min(1).max(256),
38
39
  aud: identifier,
39
40
  /** The requester account. */
@@ -47,7 +48,8 @@ exports.oxyRequesterAssertionClaimsSchema = zod_1.z.object({
47
48
  cid: identifier,
48
49
  /** The one native agent this requester may reach with it. */
49
50
  agentId: identifier,
50
- }).strict();
51
+ })
52
+ .strict();
51
53
  class OxyRequesterAssertionError extends Error {
52
54
  constructor(code) {
53
55
  super(`Requester assertion rejected: ${code}`);
@@ -80,7 +82,8 @@ function decodeObject(segment) {
80
82
  /** Signs an assertion. Oxy is the only intended caller. */
81
83
  function signOxyRequesterAssertion(claims, signing) {
82
84
  const parsed = exports.oxyRequesterAssertionClaimsSchema.parse(claims);
83
- if (parsed.exp <= parsed.iat || parsed.exp - parsed.iat > exports.OXY_REQUESTER_ASSERTION_MAX_TTL_SECONDS) {
85
+ if (parsed.exp <= parsed.iat ||
86
+ parsed.exp - parsed.iat > exports.OXY_REQUESTER_ASSERTION_MAX_TTL_SECONDS) {
84
87
  throw new OxyRequesterAssertionError('ttl_exceeded');
85
88
  }
86
89
  if (!KEY_ID_PATTERN.test(signing.keyId))
@@ -101,11 +104,11 @@ function readOxyRequesterAssertionKeyId(token) {
101
104
  throw new OxyRequesterAssertionError('malformed');
102
105
  }
103
106
  const header = decodeObject(segments[0]);
104
- if (Object.keys(header).length !== 3
105
- || header.alg !== ALGORITHM
106
- || header.typ !== exports.OXY_REQUESTER_ASSERTION_TYPE
107
- || typeof header.kid !== 'string'
108
- || !KEY_ID_PATTERN.test(header.kid)) {
107
+ if (Object.keys(header).length !== 3 ||
108
+ header.alg !== ALGORITHM ||
109
+ header.typ !== exports.OXY_REQUESTER_ASSERTION_TYPE ||
110
+ typeof header.kid !== 'string' ||
111
+ !KEY_ID_PATTERN.test(header.kid)) {
109
112
  throw new OxyRequesterAssertionError('malformed');
110
113
  }
111
114
  return header.kid;
@@ -144,7 +147,8 @@ function verifyOxyRequesterAssertion(token, options) {
144
147
  throw new OxyRequesterAssertionError('not_yet_valid');
145
148
  if (claims.exp <= now)
146
149
  throw new OxyRequesterAssertionError('expired');
147
- if (claims.exp <= claims.iat || claims.exp - claims.iat > exports.OXY_REQUESTER_ASSERTION_MAX_TTL_SECONDS) {
150
+ if (claims.exp <= claims.iat ||
151
+ claims.exp - claims.iat > exports.OXY_REQUESTER_ASSERTION_MAX_TTL_SECONDS) {
148
152
  throw new OxyRequesterAssertionError('ttl_exceeded');
149
153
  }
150
154
  return claims;
@@ -168,15 +172,15 @@ function parseJwks(value) {
168
172
  if (typeof entry !== 'object' || entry === null || Array.isArray(entry))
169
173
  throw new Error('JWKS key is malformed');
170
174
  const key = entry;
171
- if (key.kty !== 'OKP'
172
- || key.crv !== 'Ed25519'
173
- || key.alg !== 'EdDSA'
174
- || key.use !== 'sig'
175
- || typeof key.x !== 'string'
176
- || typeof key.kid !== 'string'
177
- || !KEY_ID_PATTERN.test(key.kid)
178
- || Object.prototype.hasOwnProperty.call(key, 'd')
179
- || result.has(key.kid))
175
+ if (key.kty !== 'OKP' ||
176
+ key.crv !== 'Ed25519' ||
177
+ key.alg !== 'EdDSA' ||
178
+ key.use !== 'sig' ||
179
+ typeof key.x !== 'string' ||
180
+ typeof key.kid !== 'string' ||
181
+ !KEY_ID_PATTERN.test(key.kid) ||
182
+ Object.prototype.hasOwnProperty.call(key, 'd') ||
183
+ result.has(key.kid))
180
184
  throw new Error('JWKS key is unsupported');
181
185
  const x = Buffer.from(key.x, 'base64url');
182
186
  if (x.length !== 32 || x.toString('base64url') !== key.x)
@@ -252,7 +256,9 @@ function reject(req, res, options, status, error, code) {
252
256
  status,
253
257
  applicationId: req.serviceApp?.appId ?? null,
254
258
  });
255
- res.status(status).json({ error, code, message: 'The requester assertion was not accepted', status });
259
+ res
260
+ .status(status)
261
+ .json({ error, code, message: 'The requester assertion was not accepted', status });
256
262
  }
257
263
  function singleHeader(req, name) {
258
264
  const value = req.headers[name];
@@ -276,8 +282,8 @@ function createOxyRequesterAssertionAuth(introspector, options) {
276
282
  let resolvePublicKey = options.resolvePublicKey;
277
283
  const resolver = () => {
278
284
  resolvePublicKey ?? (resolvePublicKey = createOxyJwksKeyResolver({
279
- jwksUrl: options.jwksUrl
280
- ?? new URL('/capabilities/.well-known/jwks.json', introspector.baseURL).toString(),
285
+ jwksUrl: options.jwksUrl ??
286
+ new URL('/capabilities/.well-known/jwks.json', introspector.baseURL).toString(),
281
287
  }));
282
288
  return resolvePublicKey;
283
289
  };
@@ -300,9 +306,9 @@ function createOxyRequesterAssertionAuth(introspector, options) {
300
306
  // One identity channel per request. An offline delegation header or an
301
307
  // identity some earlier middleware attached must never be combined with, or
302
308
  // silently replaced by, a present-requester assertion.
303
- if (req.headers['x-oxy-user-id'] !== undefined
304
- || request.serviceActingAs !== undefined
305
- || (request.userId !== undefined && request.userId !== null)) {
309
+ if (req.headers['x-oxy-user-id'] !== undefined ||
310
+ request.serviceActingAs !== undefined ||
311
+ (request.userId !== undefined && request.userId !== null)) {
306
312
  reject(req, res, options, 400, 'REQUESTER_ASSERTION_CONFLICT', 'identity_conflict');
307
313
  return;
308
314
  }
@@ -338,12 +344,12 @@ function createOxyRequesterAssertionAuth(introspector, options) {
338
344
  reject(req, res, options, 503, 'REQUESTER_ASSERTION_UNAVAILABLE', 'introspection_unavailable');
339
345
  return;
340
346
  }
341
- if (introspection.active !== true
342
- || introspection.requesterAccountId !== claims.sub
343
- || introspection.agentId !== claims.agentId
344
- || introspection.applicationId !== claims.azp
345
- || introspection.credentialId !== claims.cid
346
- || introspection.jti !== claims.jti) {
347
+ if (introspection.active !== true ||
348
+ introspection.requesterAccountId !== claims.sub ||
349
+ introspection.agentId !== claims.agentId ||
350
+ introspection.applicationId !== claims.azp ||
351
+ introspection.credentialId !== claims.cid ||
352
+ introspection.jti !== claims.jti) {
347
353
  reject(req, res, options, 401, 'REQUESTER_ASSERTION_INACTIVE', 'inactive');
348
354
  return;
349
355
  }
@@ -6,8 +6,11 @@ exports.hasBoundedServiceTokenLifetime = hasBoundedServiceTokenLifetime;
6
6
  exports.OXY_SERVICE_TOKEN_MAX_LIFETIME_SECONDS = 300;
7
7
  /** Call only after signature verification; cache checks alone confer no authority. */
8
8
  function hasBoundedServiceTokenLifetime(claims, nowSeconds = Math.floor(Date.now() / 1000)) {
9
- return typeof claims.iat === 'number' && Number.isSafeInteger(claims.iat)
10
- && typeof claims.exp === 'number' && Number.isSafeInteger(claims.exp)
11
- && claims.iat <= nowSeconds && claims.exp > claims.iat
12
- && claims.exp - claims.iat <= exports.OXY_SERVICE_TOKEN_MAX_LIFETIME_SECONDS;
9
+ return (typeof claims.iat === 'number' &&
10
+ Number.isSafeInteger(claims.iat) &&
11
+ typeof claims.exp === 'number' &&
12
+ Number.isSafeInteger(claims.exp) &&
13
+ claims.iat <= nowSeconds &&
14
+ claims.exp > claims.iat &&
15
+ claims.exp - claims.iat <= exports.OXY_SERVICE_TOKEN_MAX_LIFETIME_SECONDS);
13
16
  }
@@ -58,13 +58,15 @@ function createEcosystemTraffic(options) {
58
58
  const post = async (path, data) => {
59
59
  const token = await credential();
60
60
  const response = await fetcher(new URL(path, baseURL), {
61
- method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
62
- body: JSON.stringify(data), signal: AbortSignal.timeout(4000),
61
+ method: 'POST',
62
+ headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
63
+ body: JSON.stringify(data),
64
+ signal: AbortSignal.timeout(4000),
63
65
  });
64
66
  if (!response.ok)
65
67
  throw new Error('Activity collection failed');
66
68
  };
67
- const collector = (0, collector_1.createTrafficCollector)(events => post('/internal/activity', events));
69
+ const collector = (0, collector_1.createTrafficCollector)((events) => post('/internal/activity', events));
68
70
  let stopped = false;
69
71
  let heartbeatWork = Promise.resolve();
70
72
  let heartbeatPending = false;
@@ -73,7 +75,19 @@ function createEcosystemTraffic(options) {
73
75
  if (!removed && (stopped || heartbeatPending))
74
76
  return heartbeatWork;
75
77
  heartbeatPending = true;
76
- heartbeatWork = heartbeatWork.then(() => post('/internal/activity/infrastructure', { instanceId, service: options.service, region, ...location, status: options.ready?.() ? 'online' : 'unknown', removed })).catch(reportError).finally(() => { heartbeatPending = false; });
78
+ heartbeatWork = heartbeatWork
79
+ .then(() => post('/internal/activity/infrastructure', {
80
+ instanceId,
81
+ service: options.service,
82
+ region,
83
+ ...location,
84
+ status: options.ready?.() ? 'online' : 'unknown',
85
+ removed,
86
+ }))
87
+ .catch(reportError)
88
+ .finally(() => {
89
+ heartbeatPending = false;
90
+ });
77
91
  return heartbeatWork;
78
92
  };
79
93
  const flush = () => collector.flush().catch(reportError);
@@ -85,13 +99,17 @@ function createEcosystemTraffic(options) {
85
99
  return Object.assign((...args) => (0, trafficNodeHttp_1.withoutNodeHttpObservation)(() => wrapped(...args)), fetcher);
86
100
  };
87
101
  const observeHttp = (0, collector_1.trafficMiddleware)(collector, options.service, region);
88
- const timer = setInterval(() => { void flush(); }, 2000);
102
+ const timer = setInterval(() => {
103
+ void flush();
104
+ }, 2000);
89
105
  timer.unref?.();
90
106
  void heartbeat();
91
- const heartbeatTimer = setInterval(() => { void heartbeat(); }, 10000);
107
+ const heartbeatTimer = setInterval(() => {
108
+ void heartbeat();
109
+ }, 10000);
92
110
  heartbeatTimer.unref?.();
93
111
  return {
94
- record: flow => collector.record({ ...flow, service: options.service, region }),
112
+ record: (flow) => collector.record({ ...flow, service: options.service, region }),
95
113
  middleware: observeHttp,
96
114
  observeHttp,
97
115
  wrapFetch,
@@ -102,8 +120,10 @@ function createEcosystemTraffic(options) {
102
120
  const original = globalThis.fetch;
103
121
  const wrapped = wrapFetch(original);
104
122
  globalThis.fetch = wrapped;
105
- cleanups.add(() => { if (globalThis.fetch === wrapped)
106
- globalThis.fetch = original; });
123
+ cleanups.add(() => {
124
+ if (globalThis.fetch === wrapped)
125
+ globalThis.fetch = original;
126
+ });
107
127
  cleanups.add((0, trafficNodeHttp_1.observeNodeHttp)(collector, options.service, region, options.resolveEndpoint ?? collector_1.resolveOxyServiceEndpoint));
108
128
  },
109
129
  observeWebSocket(socket, socketOptions) {
@@ -111,7 +131,12 @@ function createEcosystemTraffic(options) {
111
131
  if (existing)
112
132
  return existing;
113
133
  const unobserve = (0, socket_1.observeTrafficWebSocket)(socket, collector, options.service, region, socketOptions);
114
- const cleanup = () => { unobserve(); socket.off('close', cleanup); cleanups.delete(cleanup); sockets.delete(socket); };
134
+ const cleanup = () => {
135
+ unobserve();
136
+ socket.off('close', cleanup);
137
+ cleanups.delete(cleanup);
138
+ sockets.delete(socket);
139
+ };
115
140
  sockets.set(socket, cleanup);
116
141
  socket.once('close', cleanup);
117
142
  cleanups.add(cleanup);
@@ -122,14 +147,28 @@ function createEcosystemTraffic(options) {
122
147
  if (existing)
123
148
  return existing;
124
149
  const unobserve = (0, socket_1.observeTrafficSocket)(socket, collector, options.service, region, socketOptions);
125
- const cleanup = () => { unobserve(); socket.off('disconnect', cleanup); cleanups.delete(cleanup); sockets.delete(socket); };
150
+ const cleanup = () => {
151
+ unobserve();
152
+ socket.off('disconnect', cleanup);
153
+ cleanups.delete(cleanup);
154
+ sockets.delete(socket);
155
+ };
126
156
  sockets.set(socket, cleanup);
127
157
  socket.once('disconnect', cleanup);
128
158
  cleanups.add(cleanup);
129
159
  return cleanup;
130
160
  },
131
- async stop() { if (stopped)
132
- return; stopped = true; for (const cleanup of cleanups)
133
- cleanup(); cleanups.clear(); clearInterval(timer); clearInterval(heartbeatTimer); await flush(); await heartbeat(true); },
161
+ async stop() {
162
+ if (stopped)
163
+ return;
164
+ stopped = true;
165
+ for (const cleanup of cleanups)
166
+ cleanup();
167
+ cleanups.clear();
168
+ clearInterval(timer);
169
+ clearInterval(heartbeatTimer);
170
+ await flush();
171
+ await heartbeat(true);
172
+ },
134
173
  };
135
174
  }