@oxy.so/core 4.5.0-oxy-one.1 → 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.
- package/README.md +1 -1
- package/dist/cjs/HttpService.js +63 -19
- package/dist/cjs/api/accounts.js +10 -3
- package/dist/cjs/api/agency.js +3 -1
- package/dist/cjs/api/apps.js +15 -4
- package/dist/cjs/api/assets.js +39 -11
- package/dist/cjs/api/auth.js +28 -8
- package/dist/cjs/api/billing.js +24 -7
- package/dist/cjs/api/civic.js +14 -4
- package/dist/cjs/api/follows.js +9 -2
- package/dist/cjs/api/identity.js +31 -9
- package/dist/cjs/api/nodes.js +3 -1
- package/dist/cjs/api/privacy.js +8 -2
- package/dist/cjs/api/session.js +15 -4
- package/dist/cjs/api/store.js +15 -5
- package/dist/cjs/api/topics.js +10 -3
- package/dist/cjs/api/users.js +16 -4
- package/dist/cjs/boot/sessionColdBoot.js +40 -13
- package/dist/cjs/constants/version.js +6 -6
- package/dist/cjs/crypto/identityMarker.js +3 -1
- package/dist/cjs/crypto/identityProof.js +6 -1
- package/dist/cjs/crypto/keyManager.js +87 -32
- package/dist/cjs/crypto/recoveryPhrase.js +2 -2
- package/dist/cjs/crypto/signatureService.js +3 -4
- package/dist/cjs/i18n/index.js +16 -3
- package/dist/cjs/i18n/locales/ar-SA.js +366 -366
- package/dist/cjs/i18n/locales/ca-ES.js +366 -366
- package/dist/cjs/i18n/locales/de-DE.js +366 -366
- package/dist/cjs/i18n/locales/en-US.js +1994 -1994
- package/dist/cjs/i18n/locales/es-ES.js +1994 -1994
- package/dist/cjs/i18n/locales/fr-FR.js +366 -366
- package/dist/cjs/i18n/locales/it-IT.js +366 -366
- package/dist/cjs/i18n/locales/ja-JP.js +366 -366
- package/dist/cjs/i18n/locales/ko-KR.js +366 -366
- package/dist/cjs/i18n/locales/pt-PT.js +366 -366
- package/dist/cjs/i18n/locales/zh-CN.js +366 -366
- package/dist/cjs/inference/OxyInferenceClient.js +12 -18
- package/dist/cjs/models/interfaces.js +11 -11
- package/dist/cjs/server/OxyServer.js +86 -28
- package/dist/cjs/server/agentAccount.js +6 -2
- package/dist/cjs/server/aliaMachineCredential.js +39 -14
- package/dist/cjs/server/auth.js +5 -4
- package/dist/cjs/server/capabilityTicket.js +5 -5
- package/dist/cjs/server/index.js +2 -1
- package/dist/cjs/server/liveCapabilityTicket.js +4 -1
- package/dist/cjs/server/middleware.js +61 -42
- package/dist/cjs/server/namespaces.js +28 -7
- package/dist/cjs/server/requesterAssertion.js +36 -30
- package/dist/cjs/server/serviceTokenLifetime.js +7 -4
- package/dist/cjs/server/traffic.js +53 -14
- package/dist/cjs/server/trafficNodeHttp.js +33 -8
- package/dist/cjs/server/workloadIdentity.client.js +4 -0
- package/dist/cjs/server/workloadIdentity.js +28 -1
- package/dist/cjs/session/SessionClient.js +54 -17
- package/dist/cjs/session/accountDelegationAccess.js +4 -6
- package/dist/cjs/session/accountDialogController.js +1 -1
- package/dist/cjs/session/authStateStore.js +18 -9
- package/dist/cjs/session/identityPin.js +6 -2
- package/dist/cjs/session/refresh.js +81 -23
- package/dist/cjs/session/sharedDeviceCredential.js +28 -15
- package/dist/cjs/shared/utils/errorUtils.js +1 -1
- package/dist/cjs/shared/utils/networkUtils.js +1 -1
- package/dist/cjs/shared/utils/themeUtils.js +1 -1
- package/dist/cjs/utils/accountCacheSweep.js +3 -1
- package/dist/cjs/utils/accountUtils.js +1 -3
- package/dist/cjs/utils/asyncUtils.js +1 -1
- package/dist/cjs/utils/authHelpers.js +2 -1
- package/dist/cjs/utils/avatarUtils.js +4 -2
- package/dist/cjs/utils/cache.js +1 -1
- package/dist/cjs/utils/cacheKey.js +3 -1
- package/dist/cjs/utils/deviceManager.js +4 -4
- package/dist/cjs/utils/errorUtils.js +6 -4
- package/dist/cjs/utils/languageUtils.js +404 -57
- package/dist/cjs/utils/profileLinks.js +1 -3
- package/dist/cjs/utils/requestUtils.js +7 -1
- package/dist/cjs/utils/userIdentity.js +1 -1
- package/dist/cjs/utils/validationUtils.js +5 -6
- package/dist/esm/HttpService.js +64 -20
- package/dist/esm/api/accounts.js +11 -4
- package/dist/esm/api/agency.js +3 -1
- package/dist/esm/api/apps.js +15 -4
- package/dist/esm/api/assets.js +39 -11
- package/dist/esm/api/auth.js +28 -8
- package/dist/esm/api/billing.js +25 -8
- package/dist/esm/api/civic.js +14 -4
- package/dist/esm/api/follows.js +9 -2
- package/dist/esm/api/identity.js +31 -9
- package/dist/esm/api/nodes.js +3 -1
- package/dist/esm/api/privacy.js +8 -2
- package/dist/esm/api/session.js +15 -4
- package/dist/esm/api/store.js +15 -5
- package/dist/esm/api/topics.js +10 -3
- package/dist/esm/api/users.js +16 -4
- package/dist/esm/boot/sessionColdBoot.js +41 -14
- package/dist/esm/constants/version.js +6 -6
- package/dist/esm/crypto/identityMarker.js +3 -1
- package/dist/esm/crypto/identityProof.js +6 -1
- package/dist/esm/crypto/internal.js +1 -1
- package/dist/esm/crypto/keyManager.js +87 -32
- package/dist/esm/crypto/recoveryPhrase.js +2 -2
- package/dist/esm/crypto/signatureService.js +3 -4
- package/dist/esm/i18n/index.js +16 -3
- package/dist/esm/i18n/locales/ar-SA.js +366 -366
- package/dist/esm/i18n/locales/ca-ES.js +366 -366
- package/dist/esm/i18n/locales/de-DE.js +366 -366
- package/dist/esm/i18n/locales/en-US.js +1994 -1994
- package/dist/esm/i18n/locales/es-ES.js +1994 -1994
- package/dist/esm/i18n/locales/fr-FR.js +366 -366
- package/dist/esm/i18n/locales/it-IT.js +366 -366
- package/dist/esm/i18n/locales/ja-JP.js +366 -366
- package/dist/esm/i18n/locales/ko-KR.js +366 -366
- package/dist/esm/i18n/locales/pt-PT.js +366 -366
- package/dist/esm/i18n/locales/zh-CN.js +366 -366
- package/dist/esm/index.js +1 -1
- package/dist/esm/inference/OxyInferenceClient.js +13 -19
- package/dist/esm/models/interfaces.js +11 -11
- package/dist/esm/server/OxyServer.js +87 -29
- package/dist/esm/server/agentAccount.js +6 -2
- package/dist/esm/server/aliaMachineCredential.js +39 -14
- package/dist/esm/server/auth.js +6 -5
- package/dist/esm/server/capabilityTicket.js +6 -6
- package/dist/esm/server/index.js +5 -5
- package/dist/esm/server/liveCapabilityTicket.js +6 -3
- package/dist/esm/server/middleware.js +62 -43
- package/dist/esm/server/namespaces.js +31 -10
- package/dist/esm/server/requesterAssertion.js +36 -30
- package/dist/esm/server/serviceTokenLifetime.js +7 -4
- package/dist/esm/server/traffic.js +55 -16
- package/dist/esm/server/trafficNodeHttp.js +34 -9
- package/dist/esm/server/userInvalidation.js +1 -1
- package/dist/esm/server/workloadIdentity.client.js +3 -0
- package/dist/esm/server/workloadIdentity.js +27 -1
- package/dist/esm/session/SessionClient.js +54 -17
- package/dist/esm/session/accountDelegationAccess.js +5 -7
- package/dist/esm/session/accountDialogController.js +1 -1
- package/dist/esm/session/authStateStore.js +18 -9
- package/dist/esm/session/identityPin.js +6 -2
- package/dist/esm/session/refresh.js +82 -24
- package/dist/esm/session/sharedDeviceCredential.js +28 -15
- package/dist/esm/shared/utils/errorUtils.js +1 -1
- package/dist/esm/shared/utils/networkUtils.js +1 -1
- package/dist/esm/shared/utils/themeUtils.js +1 -1
- package/dist/esm/utils/accountCacheSweep.js +3 -1
- package/dist/esm/utils/accountUtils.js +1 -3
- package/dist/esm/utils/asyncUtils.js +1 -1
- package/dist/esm/utils/authHelpers.js +2 -1
- package/dist/esm/utils/avatarUtils.js +4 -2
- package/dist/esm/utils/cache.js +1 -1
- package/dist/esm/utils/cacheKey.js +3 -1
- package/dist/esm/utils/deviceManager.js +4 -4
- package/dist/esm/utils/errorUtils.js +6 -4
- package/dist/esm/utils/languageUtils.js +404 -57
- package/dist/esm/utils/profileLinks.js +1 -3
- package/dist/esm/utils/requestUtils.js +7 -1
- package/dist/esm/utils/userIdentity.js +1 -1
- package/dist/esm/utils/validationUtils.js +5 -6
- package/dist/types/HttpService.d.ts +1 -1
- package/dist/types/api/accounts.d.ts +1 -1
- package/dist/types/api/apps.d.ts +4 -4
- package/dist/types/crypto/internal.d.ts +1 -1
- package/dist/types/index.d.ts +4 -4
- package/dist/types/server/index.d.ts +6 -6
- package/dist/types/server/workloadIdentity.client.d.ts +5 -1
- package/dist/types/server/workloadIdentity.d.ts +26 -0
- package/dist/types/session/accountDelegationAccess.d.ts +1 -1
- package/dist/types/session/index.d.ts +1 -1
- package/dist/types/utils/userIdentity.d.ts +1 -1
- package/dist/types/utils/validationUtils.d.ts +4 -5
- package/package.json +2 -3
- package/src/HttpService.ts +183 -53
- package/src/OxyServices.errors.ts +7 -3
- package/src/OxyServices.ts +6 -2
- package/src/api/accounts.ts +76 -26
- package/src/api/agency.ts +24 -9
- package/src/api/appData.ts +12 -2
- package/src/api/apps.ts +81 -31
- package/src/api/assets.ts +113 -43
- package/src/api/auth.ts +145 -77
- package/src/api/billing.ts +112 -65
- package/src/api/civic.ts +61 -19
- package/src/api/contacts.ts +4 -1
- package/src/api/devices.ts +54 -21
- package/src/api/follows.ts +88 -31
- package/src/api/identity.ts +101 -33
- package/src/api/linkedAccounts.ts +26 -8
- package/src/api/nodes.ts +18 -6
- package/src/api/notifications.ts +26 -6
- package/src/api/privacy.ts +42 -8
- package/src/api/reputation.ts +18 -7
- package/src/api/session.ts +23 -5
- package/src/api/store.ts +81 -31
- package/src/api/topics.ts +18 -6
- package/src/api/users.ts +98 -35
- package/src/boot/sessionColdBoot.ts +60 -19
- package/src/civic/payloads.ts +1 -4
- package/src/client/context.ts +6 -1
- package/src/constants/version.ts +7 -6
- package/src/crypto/aead.ts +1 -5
- package/src/crypto/ecdh.ts +1 -4
- package/src/crypto/identityDerivations.ts +5 -1
- package/src/crypto/identityMarker.ts +3 -1
- package/src/crypto/identityProof.ts +6 -1
- package/src/crypto/index.ts +11 -11
- package/src/crypto/internal.ts +6 -1
- package/src/crypto/keyManager.ts +348 -98
- package/src/crypto/recoveryPhrase.ts +14 -9
- package/src/crypto/registrationPow.ts +1 -1
- package/src/crypto/signatureService.ts +14 -6
- package/src/i18n/accountCategoryLabels.ts +1 -4
- package/src/i18n/accountRoleLabels.ts +1 -4
- package/src/i18n/index.ts +25 -7
- package/src/i18n/locales/ar-SA.ts +375 -366
- package/src/i18n/locales/ca-ES.ts +382 -366
- package/src/i18n/locales/de-DE.ts +387 -366
- package/src/i18n/locales/en-US.ts +2034 -1994
- package/src/i18n/locales/es-ES.ts +2043 -1994
- package/src/i18n/locales/fr-FR.ts +387 -366
- package/src/i18n/locales/it-IT.ts +380 -366
- package/src/i18n/locales/ja-JP.ts +380 -366
- package/src/i18n/locales/ko-KR.ts +377 -366
- package/src/i18n/locales/pt-PT.ts +383 -366
- package/src/i18n/locales/zh-CN.ts +373 -366
- package/src/i18n/trustTierLabels.ts +1 -4
- package/src/index.ts +371 -349
- package/src/inference/OxyInferenceClient.ts +784 -780
- package/src/models/interfaces.ts +30 -27
- package/src/server/OxyServer.ts +227 -68
- package/src/server/agentAccount.ts +8 -2
- package/src/server/aliaMachineCredential.ts +57 -16
- package/src/server/auth.ts +9 -5
- package/src/server/capabilityTicket.ts +30 -21
- package/src/server/index.ts +29 -6
- package/src/server/liveCapabilityTicket.ts +31 -9
- package/src/server/middleware.ts +212 -121
- package/src/server/namespaces.ts +247 -94
- package/src/server/rateLimit.ts +2 -4
- package/src/server/requesterAssertion.ts +93 -54
- package/src/server/serviceTokenLifetime.ts +9 -4
- package/src/server/traffic.ts +117 -23
- package/src/server/trafficNodeHttp.ts +61 -14
- package/src/server/userInvalidation.ts +1 -4
- package/src/server/workloadIdentity.client.ts +12 -1
- package/src/server/workloadIdentity.ts +52 -5
- package/src/session/SessionClient.ts +170 -49
- package/src/session/accountDelegationAccess.ts +24 -31
- package/src/session/accountDialogController.ts +59 -14
- package/src/session/accountSwitchTargets.ts +10 -15
- package/src/session/authStateStore.ts +121 -81
- package/src/session/deviceDirectory.ts +1 -3
- package/src/session/identityPin.ts +10 -11
- package/src/session/identitySession.ts +3 -1
- package/src/session/index.ts +87 -82
- package/src/session/refresh.ts +138 -44
- package/src/session/sessionClientHost.ts +1 -3
- package/src/session/sharedDeviceCredential.ts +35 -14
- package/src/session/socketLoader.ts +9 -2
- package/src/shared/utils/errorUtils.ts +5 -2
- package/src/shared/utils/networkUtils.ts +5 -8
- package/src/shared/utils/themeUtils.ts +2 -6
- package/src/types/buffer.d.ts +66 -21
- package/src/types/expo-secure-store.d.ts +5 -1
- package/src/utils/accountCacheSweep.ts +4 -5
- package/src/utils/accountUtils.ts +107 -108
- package/src/utils/apiUtils.ts +3 -3
- package/src/utils/asyncUtils.ts +2 -2
- package/src/utils/authHelpers.ts +10 -5
- package/src/utils/avatarUtils.ts +11 -6
- package/src/utils/cache.ts +9 -10
- package/src/utils/cacheKey.ts +5 -1
- package/src/utils/coldBoot.ts +1 -3
- package/src/utils/commonsDelivery.ts +1 -4
- package/src/utils/deviceManager.ts +15 -14
- package/src/utils/errorUtils.ts +68 -86
- package/src/utils/languageUtils.ts +407 -58
- package/src/utils/oauthPkce.ts +1 -4
- package/src/utils/platform.ts +0 -1
- package/src/utils/profileLinks.ts +2 -5
- package/src/utils/requestUtils.ts +18 -14
- package/src/utils/sessionUtils.ts +34 -33
- package/src/utils/userHandle.ts +3 -1
- package/src/utils/userIdentity.ts +1 -1
- 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 = {
|
|
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 = {
|
|
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
|
-
|
|
368
|
-
|
|
369
|
-
|
|
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
|
-
]
|
|
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 = {
|
|
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,
|
|
427
|
-
|
|
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
|
|
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
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
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
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
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
|
|
1145
|
-
*
|
|
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 ||
|
|
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
|
|
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 {
|
|
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 ||
|
|
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, {
|
|
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 === '' ||
|
|
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', {
|
|
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
|
|
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
|
-
})
|
|
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 ||
|
|
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
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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 ||
|
|
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
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
305
|
-
|
|
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
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
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' &&
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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',
|
|
62
|
-
|
|
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
|
|
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(() => {
|
|
102
|
+
const timer = setInterval(() => {
|
|
103
|
+
void flush();
|
|
104
|
+
}, 2000);
|
|
89
105
|
timer.unref?.();
|
|
90
106
|
void heartbeat();
|
|
91
|
-
const heartbeatTimer = setInterval(() => {
|
|
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(() => {
|
|
106
|
-
globalThis.fetch
|
|
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 = () => {
|
|
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 = () => {
|
|
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() {
|
|
132
|
-
|
|
133
|
-
|
|
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
|
}
|