@oxy.so/core 1.18.1 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -7
- package/dist/cjs/HttpService.js +159 -111
- package/dist/cjs/OxyServices.errors.js +48 -1
- package/dist/cjs/OxyServices.js +263 -60
- package/dist/cjs/api/accounts.js +231 -0
- package/dist/cjs/api/agency.js +102 -0
- package/dist/cjs/api/appData.js +45 -0
- package/dist/cjs/api/apps.js +197 -0
- package/dist/cjs/api/assets.js +329 -0
- package/dist/cjs/api/auth.js +900 -0
- package/dist/cjs/api/billing.js +44 -0
- package/dist/cjs/api/civic.js +289 -0
- package/dist/cjs/api/contacts.js +16 -0
- package/dist/cjs/api/devices.js +351 -0
- package/dist/cjs/api/follows.js +240 -0
- package/dist/cjs/api/identity.js +569 -0
- package/dist/cjs/api/linkedAccounts.js +48 -0
- package/dist/cjs/api/nodes.js +75 -0
- package/dist/cjs/api/notifications.js +75 -0
- package/dist/cjs/api/privacy.js +105 -0
- package/dist/cjs/api/reputation.js +74 -0
- package/dist/cjs/api/session.js +177 -0
- package/dist/cjs/api/store.js +199 -0
- package/dist/cjs/api/topics.js +66 -0
- package/dist/cjs/api/users.js +309 -0
- package/dist/cjs/boot/sessionColdBoot.js +4 -4
- package/dist/cjs/civic/index.js +16 -0
- package/dist/cjs/civic/payloads.js +156 -0
- package/dist/cjs/client/context.js +2 -0
- package/dist/cjs/crypto/identityLink.js +5 -5
- package/dist/cjs/crypto/index.js +44 -0
- package/dist/cjs/crypto/internal.js +37 -0
- package/dist/cjs/crypto/keyManager.js +2 -2
- package/dist/cjs/crypto/polyfill.js +9 -80
- package/dist/cjs/crypto/recoveryPhrase.js +1 -0
- package/dist/cjs/crypto/registrationPow.js +1 -1
- package/dist/cjs/crypto/signatureService.js +1 -0
- package/dist/cjs/i18n/accountCategoryLabels.js +3 -3
- package/dist/cjs/i18n/accountRoleLabels.js +7 -7
- package/dist/cjs/i18n/index.js +130 -52
- package/dist/cjs/i18n/locales/{ar-SA.json → ar-SA.js} +134 -52
- package/dist/cjs/i18n/locales/{ca-ES.json → ca-ES.js} +134 -52
- package/dist/{esm/i18n/locales/de-DE.json → cjs/i18n/locales/de-DE.js} +136 -54
- package/dist/{esm/i18n/locales/en-US.json → cjs/i18n/locales/en-US.js} +163 -245
- package/dist/{esm/i18n/locales/es-ES.json → cjs/i18n/locales/es-ES.js} +163 -245
- package/dist/cjs/i18n/locales/{fr-FR.json → fr-FR.js} +134 -52
- package/dist/cjs/i18n/locales/{it-IT.json → it-IT.js} +134 -52
- package/dist/{esm/i18n/locales/ja-JP.json → cjs/i18n/locales/ja-JP.js} +134 -52
- package/dist/cjs/i18n/locales/{ko-KR.json → ko-KR.js} +134 -52
- package/dist/{esm/i18n/locales/pt-PT.json → cjs/i18n/locales/pt-PT.js} +136 -54
- package/dist/{esm/i18n/locales/zh-CN.json → cjs/i18n/locales/zh-CN.js} +135 -53
- package/dist/cjs/i18n/reputationCategoryLabels.js +2 -2
- package/dist/cjs/i18n/trustTierLabels.js +2 -2
- package/dist/cjs/index.js +55 -263
- package/dist/cjs/inference/index.js +21 -0
- package/dist/cjs/server/OxyServer.js +521 -0
- package/dist/cjs/server/auth.js +2 -2
- package/dist/cjs/server/index.js +23 -6
- package/dist/cjs/server/middleware.js +1154 -0
- package/dist/cjs/server/namespaces.js +214 -0
- package/dist/cjs/server/rateLimit.js +2 -2
- package/dist/cjs/server/requesterAssertion.js +5 -5
- package/dist/cjs/server/securityHeaders.js +3 -3
- package/dist/cjs/server/traffic.js +7 -6
- package/dist/cjs/server/trafficNodeHttp.js +9 -3
- package/dist/cjs/server/userInvalidation.js +5 -5
- package/dist/cjs/session/accountDialogController.js +23 -23
- package/dist/cjs/session/authStateStore.js +2 -2
- package/dist/cjs/session/identitySession.js +3 -3
- package/dist/cjs/session/index.js +131 -0
- package/dist/cjs/session/refresh.js +37 -30
- package/dist/cjs/session/sessionClientHost.js +5 -5
- package/dist/cjs/session/sharedDeviceCredential.js +3 -2
- package/dist/cjs/shared/utils/networkUtils.js +2 -2
- package/dist/cjs/utils/accountCacheSweep.js +11 -15
- package/dist/cjs/utils/asyncUtils.js +22 -163
- package/dist/cjs/utils/authHelpers.js +2 -2
- package/dist/cjs/utils/authWebUrl.js +3 -4
- package/dist/cjs/utils/avatarUtils.js +2 -2
- package/dist/cjs/utils/cache.js +32 -2
- package/dist/cjs/utils/cacheKey.js +5 -10
- package/dist/cjs/utils/deviceManager.js +17 -16
- package/dist/cjs/utils/edgeRegion.js +2 -3
- package/dist/cjs/utils/identityCacheSweep.js +6 -10
- package/dist/cjs/utils/oxyServiceEnvironment.js +3 -7
- package/dist/cjs/utils/requestUtils.js +40 -33
- package/dist/cjs/utils/sessionUtils.js +0 -2
- package/dist/cjs/utils/tokenClaims.js +34 -0
- package/dist/esm/HttpService.js +160 -112
- package/dist/esm/OxyServices.errors.js +45 -0
- package/dist/esm/OxyServices.js +262 -57
- package/dist/esm/api/accounts.js +218 -0
- package/dist/esm/api/agency.js +95 -0
- package/dist/esm/api/appData.js +40 -0
- package/dist/esm/api/apps.js +191 -0
- package/dist/esm/api/assets.js +324 -0
- package/dist/esm/api/auth.js +858 -0
- package/dist/esm/api/billing.js +40 -0
- package/dist/esm/api/civic.js +250 -0
- package/dist/esm/api/contacts.js +12 -0
- package/dist/esm/api/devices.js +346 -0
- package/dist/esm/api/follows.js +236 -0
- package/dist/esm/api/identity.js +527 -0
- package/dist/esm/api/linkedAccounts.js +44 -0
- package/dist/esm/api/nodes.js +71 -0
- package/dist/esm/api/notifications.js +71 -0
- package/dist/esm/api/privacy.js +101 -0
- package/dist/esm/api/reputation.js +70 -0
- package/dist/esm/api/session.js +173 -0
- package/dist/esm/api/store.js +192 -0
- package/dist/esm/api/topics.js +62 -0
- package/dist/esm/api/users.js +272 -0
- package/dist/esm/boot/sessionColdBoot.js +4 -4
- package/dist/esm/civic/index.js +10 -0
- package/dist/esm/civic/payloads.js +118 -0
- package/dist/esm/client/context.js +1 -0
- package/dist/esm/crypto/identityLink.js +5 -5
- package/dist/esm/crypto/index.js +24 -0
- package/dist/esm/crypto/internal.js +19 -0
- package/dist/esm/crypto/keyManager.js +2 -2
- package/dist/esm/crypto/polyfill.js +10 -81
- package/dist/esm/crypto/recoveryPhrase.js +1 -0
- package/dist/esm/crypto/registrationPow.js +1 -1
- package/dist/esm/crypto/signatureService.js +1 -0
- package/dist/esm/i18n/accountCategoryLabels.js +2 -2
- package/dist/esm/i18n/accountRoleLabels.js +1 -1
- package/dist/esm/i18n/index.js +93 -52
- package/dist/esm/i18n/locales/{ar-SA.json → ar-SA.js} +132 -52
- package/dist/esm/i18n/locales/{ca-ES.json → ca-ES.js} +132 -52
- package/dist/{cjs/i18n/locales/de-DE.json → esm/i18n/locales/de-DE.js} +134 -54
- package/dist/{cjs/i18n/locales/en-US.json → esm/i18n/locales/en-US.js} +161 -245
- package/dist/{cjs/i18n/locales/es-ES.json → esm/i18n/locales/es-ES.js} +161 -245
- package/dist/esm/i18n/locales/{fr-FR.json → fr-FR.js} +132 -52
- package/dist/esm/i18n/locales/{it-IT.json → it-IT.js} +132 -52
- package/dist/{cjs/i18n/locales/ja-JP.json → esm/i18n/locales/ja-JP.js} +132 -52
- package/dist/esm/i18n/locales/{ko-KR.json → ko-KR.js} +132 -52
- package/dist/{cjs/i18n/locales/pt-PT.json → esm/i18n/locales/pt-PT.js} +134 -54
- package/dist/{cjs/i18n/locales/zh-CN.json → esm/i18n/locales/zh-CN.js} +133 -53
- package/dist/esm/i18n/reputationCategoryLabels.js +1 -1
- package/dist/esm/i18n/trustTierLabels.js +1 -1
- package/dist/esm/index.js +30 -166
- package/dist/esm/inference/index.js +13 -0
- package/dist/esm/server/OxyServer.js +516 -0
- package/dist/esm/server/auth.js +2 -2
- package/dist/esm/server/index.js +10 -5
- package/dist/esm/server/middleware.js +1147 -0
- package/dist/esm/server/namespaces.js +206 -0
- package/dist/esm/server/rateLimit.js +2 -2
- package/dist/esm/server/requesterAssertion.js +5 -5
- package/dist/esm/server/securityHeaders.js +3 -3
- package/dist/esm/server/traffic.js +7 -6
- package/dist/esm/server/trafficNodeHttp.js +9 -3
- package/dist/esm/server/userInvalidation.js +5 -5
- package/dist/esm/session/accountDialogController.js +23 -23
- package/dist/esm/session/authStateStore.js +2 -2
- package/dist/esm/session/identitySession.js +3 -3
- package/dist/esm/session/index.js +82 -0
- package/dist/esm/session/refresh.js +37 -30
- package/dist/esm/session/sessionClientHost.js +5 -5
- package/dist/esm/session/sharedDeviceCredential.js +3 -2
- package/dist/esm/shared/utils/networkUtils.js +2 -2
- package/dist/esm/utils/accountCacheSweep.js +11 -15
- package/dist/esm/utils/asyncUtils.js +22 -151
- package/dist/esm/utils/authHelpers.js +2 -2
- package/dist/esm/utils/authWebUrl.js +3 -4
- package/dist/esm/utils/avatarUtils.js +2 -2
- package/dist/esm/utils/cache.js +32 -2
- package/dist/esm/utils/cacheKey.js +5 -10
- package/dist/esm/utils/deviceManager.js +17 -16
- package/dist/esm/utils/edgeRegion.js +1 -2
- package/dist/esm/utils/identityCacheSweep.js +6 -10
- package/dist/esm/utils/oxyServiceEnvironment.js +3 -7
- package/dist/esm/utils/requestUtils.js +40 -33
- package/dist/esm/utils/sessionUtils.js +0 -2
- package/dist/esm/utils/tokenClaims.js +31 -0
- package/dist/types/HttpService.d.ts +26 -9
- package/dist/types/OxyServices.d.ts +160 -131
- package/dist/types/OxyServices.errors.d.ts +42 -0
- package/dist/types/api/accounts.d.ts +415 -0
- package/dist/types/api/agency.d.ts +135 -0
- package/dist/types/api/appData.d.ts +27 -0
- package/dist/types/api/apps.d.ts +433 -0
- package/dist/types/api/assets.d.ts +174 -0
- package/dist/types/api/auth.d.ts +766 -0
- package/dist/types/api/billing.d.ts +113 -0
- package/dist/types/api/civic.d.ts +203 -0
- package/dist/types/api/contacts.d.ts +31 -0
- package/{src/mixins/OxyServices.deviceBoot.ts → dist/types/api/devices.d.ts} +130 -110
- package/dist/types/api/follows.d.ts +236 -0
- package/dist/types/api/identity.d.ts +275 -0
- package/dist/types/api/linkedAccounts.d.ts +48 -0
- package/dist/types/api/nodes.d.ts +102 -0
- package/dist/types/api/notifications.d.ts +77 -0
- package/dist/types/api/privacy.d.ts +43 -0
- package/dist/types/api/reputation.d.ts +50 -0
- package/dist/types/api/session.d.ts +85 -0
- package/dist/types/api/store.d.ts +278 -0
- package/dist/types/api/topics.d.ts +34 -0
- package/dist/types/api/users.d.ts +134 -0
- package/dist/types/boot/sessionColdBoot.d.ts +1 -1
- package/dist/types/civic/index.d.ts +10 -0
- package/dist/types/civic/payloads.d.ts +83 -0
- package/dist/types/client/context.d.ts +33 -0
- package/dist/types/crypto/identityLink.d.ts +5 -5
- package/dist/types/crypto/index.d.ts +24 -0
- package/dist/types/crypto/internal.d.ts +19 -0
- package/dist/types/crypto/polyfill.d.ts +6 -9
- package/dist/types/crypto/registrationPow.d.ts +1 -1
- package/dist/types/i18n/accountCategoryLabels.d.ts +1 -1
- package/dist/types/i18n/accountRoleLabels.d.ts +1 -1
- package/dist/types/i18n/index.d.ts +20 -1
- package/dist/types/i18n/locales/ar-SA.d.ts +386 -0
- package/dist/types/i18n/locales/ca-ES.d.ts +386 -0
- package/dist/types/i18n/locales/de-DE.d.ts +386 -0
- package/dist/types/i18n/locales/en-US.d.ts +2034 -0
- package/dist/types/i18n/locales/es-ES.d.ts +2034 -0
- package/dist/types/i18n/locales/fr-FR.d.ts +386 -0
- package/dist/types/i18n/locales/it-IT.d.ts +386 -0
- package/dist/types/i18n/locales/ja-JP.d.ts +386 -0
- package/dist/types/i18n/locales/ko-KR.d.ts +386 -0
- package/dist/types/i18n/locales/pt-PT.d.ts +386 -0
- package/dist/types/i18n/locales/zh-CN.d.ts +386 -0
- package/dist/types/index.d.ts +46 -95
- package/dist/types/inference/index.d.ts +22 -0
- package/dist/types/models/interfaces.d.ts +1 -22
- package/dist/types/server/OxyServer.d.ts +183 -0
- package/dist/types/server/auth.d.ts +10 -7
- package/dist/types/server/index.d.ts +10 -4
- package/dist/types/server/middleware.d.ts +291 -0
- package/dist/types/server/namespaces.d.ts +98 -0
- package/dist/types/server/rateLimit.d.ts +7 -5
- package/dist/types/server/requesterAssertion.d.ts +14 -11
- package/dist/types/server/securityHeaders.d.ts +4 -5
- package/dist/types/server/userInvalidation.d.ts +10 -8
- package/dist/types/session/accountDelegationAccess.d.ts +1 -1
- package/dist/types/session/accountDialogController.d.ts +8 -8
- package/dist/types/session/accountSwitchTargets.d.ts +1 -1
- package/dist/types/session/authStateStore.d.ts +7 -6
- package/dist/types/session/index.d.ts +40 -0
- package/dist/types/utils/accountCacheSweep.d.ts +7 -10
- package/dist/types/utils/apiUtils.d.ts +3 -3
- package/dist/types/utils/asyncUtils.d.ts +11 -58
- package/dist/types/utils/authWebUrl.d.ts +3 -4
- package/dist/types/utils/avatarUtils.d.ts +5 -6
- package/dist/types/utils/cache.d.ts +11 -3
- package/dist/types/utils/commonsApproval.d.ts +1 -1
- package/dist/types/utils/edgeRegion.d.ts +1 -2
- package/dist/types/utils/identityCacheSweep.d.ts +6 -4
- package/dist/types/utils/oauthPkce.d.ts +2 -2
- package/dist/types/utils/oxyServiceEnvironment.d.ts +3 -7
- package/dist/types/utils/requestUtils.d.ts +18 -14
- package/dist/types/utils/tokenClaims.d.ts +9 -0
- package/package.json +68 -7
- package/src/HttpService.ts +166 -131
- package/src/OxyServices.errors.ts +73 -0
- package/src/OxyServices.ts +289 -164
- package/src/api/accounts.ts +579 -0
- package/src/api/agency.ts +277 -0
- package/src/api/appData.ts +63 -0
- package/src/api/apps.ts +596 -0
- package/src/api/assets.ts +416 -0
- package/src/api/auth.ts +1457 -0
- package/src/api/billing.ts +144 -0
- package/src/api/civic.ts +428 -0
- package/src/api/contacts.ts +41 -0
- package/src/api/devices.ts +438 -0
- package/src/api/follows.ts +414 -0
- package/src/api/identity.ts +727 -0
- package/src/api/linkedAccounts.ts +78 -0
- package/src/api/nodes.ts +169 -0
- package/src/api/notifications.ts +135 -0
- package/src/api/privacy.ts +120 -0
- package/src/api/reputation.ts +134 -0
- package/src/api/session.ts +210 -0
- package/src/api/store.ts +435 -0
- package/src/api/topics.ts +83 -0
- package/src/api/users.ts +357 -0
- package/src/boot/sessionColdBoot.ts +4 -4
- package/src/civic/index.ts +12 -0
- package/src/civic/payloads.ts +175 -0
- package/src/client/context.ts +34 -0
- package/src/crypto/identityLink.ts +5 -5
- package/src/crypto/index.ts +39 -0
- package/src/crypto/internal.ts +20 -0
- package/src/crypto/keyManager.ts +2 -2
- package/src/crypto/polyfill.ts +9 -89
- package/src/crypto/recoveryPhrase.ts +1 -0
- package/src/crypto/registrationPow.ts +1 -1
- package/src/crypto/signatureService.ts +1 -0
- package/src/i18n/accountCategoryLabels.ts +2 -2
- package/src/i18n/accountRoleLabels.ts +2 -2
- package/src/i18n/index.ts +105 -54
- package/src/i18n/locales/{ar-SA.json → ar-SA.ts} +132 -52
- package/src/i18n/locales/{ca-ES.json → ca-ES.ts} +132 -52
- package/{dist/cjs/i18n/locales/locales/de-DE.json → src/i18n/locales/de-DE.ts} +134 -54
- package/src/i18n/locales/{en-US.json → en-US.ts} +161 -245
- package/{dist/cjs/i18n/locales/locales/es-ES.json → src/i18n/locales/es-ES.ts} +161 -245
- package/src/i18n/locales/{fr-FR.json → fr-FR.ts} +132 -52
- package/src/i18n/locales/{it-IT.json → it-IT.ts} +132 -52
- package/{dist/cjs/i18n/locales/locales/ja-JP.json → src/i18n/locales/ja-JP.ts} +132 -52
- package/src/i18n/locales/{ko-KR.json → ko-KR.ts} +132 -52
- package/src/i18n/locales/{pt-PT.json → pt-PT.ts} +134 -54
- package/src/i18n/locales/{zh-CN.json → zh-CN.ts} +133 -53
- package/src/i18n/reputationCategoryLabels.ts +1 -1
- package/src/i18n/trustTierLabels.ts +1 -1
- package/src/index.ts +170 -501
- package/src/inference/index.ts +48 -0
- package/src/models/interfaces.ts +1 -22
- package/src/server/OxyServer.ts +637 -0
- package/src/server/auth.ts +12 -8
- package/src/server/index.ts +28 -5
- package/src/server/middleware.ts +1520 -0
- package/src/server/namespaces.ts +257 -0
- package/src/server/rateLimit.ts +10 -9
- package/src/server/requesterAssertion.ts +13 -10
- package/src/server/securityHeaders.ts +7 -8
- package/src/server/traffic.ts +6 -6
- package/src/server/trafficNodeHttp.ts +7 -3
- package/src/server/userInvalidation.ts +9 -9
- package/src/session/accountDelegationAccess.ts +1 -1
- package/src/session/accountDialogController.ts +24 -24
- package/src/session/accountSwitchTargets.ts +1 -1
- package/src/session/authStateStore.ts +9 -8
- package/src/session/identitySession.ts +3 -3
- package/src/session/index.ts +210 -0
- package/src/session/refresh.ts +36 -30
- package/src/session/sessionClientHost.ts +5 -5
- package/src/session/sharedDeviceCredential.ts +3 -2
- package/src/shared/utils/networkUtils.ts +2 -2
- package/src/utils/accountCacheSweep.ts +11 -15
- package/src/utils/apiUtils.ts +3 -3
- package/src/utils/asyncUtils.ts +38 -235
- package/src/utils/authHelpers.ts +2 -2
- package/src/utils/authWebUrl.ts +3 -4
- package/src/utils/avatarUtils.ts +4 -7
- package/src/utils/cache.ts +36 -5
- package/src/utils/cacheKey.ts +5 -9
- package/src/utils/commonsApproval.ts +1 -1
- package/src/utils/deviceManager.ts +17 -16
- package/src/utils/edgeRegion.ts +1 -2
- package/src/utils/identityCacheSweep.ts +7 -12
- package/src/utils/oauthPkce.ts +2 -2
- package/src/utils/oxyServiceEnvironment.ts +3 -7
- package/src/utils/requestUtils.ts +48 -44
- package/src/utils/sessionUtils.ts +0 -2
- package/src/utils/tokenClaims.ts +38 -0
- package/dist/cjs/.tsbuildinfo +0 -1
- package/dist/cjs/OxyServices.base.js +0 -392
- package/dist/cjs/i18n/locales/locales/ar-SA.json +0 -306
- package/dist/cjs/i18n/locales/locales/ca-ES.json +0 -306
- package/dist/cjs/i18n/locales/locales/en-US.json +0 -2127
- package/dist/cjs/i18n/locales/locales/fr-FR.json +0 -306
- package/dist/cjs/i18n/locales/locales/it-IT.json +0 -306
- package/dist/cjs/i18n/locales/locales/ko-KR.json +0 -306
- package/dist/cjs/i18n/locales/locales/pt-PT.json +0 -306
- package/dist/cjs/i18n/locales/locales/zh-CN.json +0 -306
- package/dist/cjs/mixins/OxyServices.accounts.js +0 -555
- package/dist/cjs/mixins/OxyServices.agency.js +0 -154
- package/dist/cjs/mixins/OxyServices.analytics.js +0 -49
- package/dist/cjs/mixins/OxyServices.appData.js +0 -108
- package/dist/cjs/mixins/OxyServices.assets.js +0 -854
- package/dist/cjs/mixins/OxyServices.auth.js +0 -1495
- package/dist/cjs/mixins/OxyServices.chains.js +0 -73
- package/dist/cjs/mixins/OxyServices.civic.js +0 -611
- package/dist/cjs/mixins/OxyServices.connectedApps.js +0 -95
- package/dist/cjs/mixins/OxyServices.contacts.js +0 -50
- package/dist/cjs/mixins/OxyServices.deviceBoot.js +0 -191
- package/dist/cjs/mixins/OxyServices.devices.js +0 -116
- package/dist/cjs/mixins/OxyServices.features.js +0 -335
- package/dist/cjs/mixins/OxyServices.followGraph.js +0 -221
- package/dist/cjs/mixins/OxyServices.identity.js +0 -562
- package/dist/cjs/mixins/OxyServices.identityBackup.js +0 -172
- package/dist/cjs/mixins/OxyServices.inference.js +0 -59
- package/dist/cjs/mixins/OxyServices.language.js +0 -125
- package/dist/cjs/mixins/OxyServices.linkedAccounts.js +0 -79
- package/dist/cjs/mixins/OxyServices.location.js +0 -43
- package/dist/cjs/mixins/OxyServices.nodes.js +0 -175
- package/dist/cjs/mixins/OxyServices.notifications.js +0 -63
- package/dist/cjs/mixins/OxyServices.payment.js +0 -158
- package/dist/cjs/mixins/OxyServices.privacy.js +0 -199
- package/dist/cjs/mixins/OxyServices.reputation.js +0 -289
- package/dist/cjs/mixins/OxyServices.security.js +0 -89
- package/dist/cjs/mixins/OxyServices.store.js +0 -266
- package/dist/cjs/mixins/OxyServices.topics.js +0 -137
- package/dist/cjs/mixins/OxyServices.user.js +0 -954
- package/dist/cjs/mixins/OxyServices.utility.js +0 -1402
- package/dist/cjs/mixins/index.js +0 -136
- package/dist/cjs/mixins/mixinHelpers.js +0 -53
- package/dist/cjs/utils/webauthnOrigin.js +0 -51
- package/dist/esm/.tsbuildinfo +0 -1
- package/dist/esm/OxyServices.base.js +0 -388
- package/dist/esm/i18n/locales/locales/ar-SA.json +0 -306
- package/dist/esm/i18n/locales/locales/ca-ES.json +0 -306
- package/dist/esm/i18n/locales/locales/de-DE.json +0 -306
- package/dist/esm/i18n/locales/locales/en-US.json +0 -2127
- package/dist/esm/i18n/locales/locales/es-ES.json +0 -2127
- package/dist/esm/i18n/locales/locales/fr-FR.json +0 -306
- package/dist/esm/i18n/locales/locales/it-IT.json +0 -306
- package/dist/esm/i18n/locales/locales/ja-JP.json +0 -306
- package/dist/esm/i18n/locales/locales/ko-KR.json +0 -306
- package/dist/esm/i18n/locales/locales/pt-PT.json +0 -306
- package/dist/esm/i18n/locales/locales/zh-CN.json +0 -306
- package/dist/esm/mixins/OxyServices.accounts.js +0 -543
- package/dist/esm/mixins/OxyServices.agency.js +0 -151
- package/dist/esm/mixins/OxyServices.analytics.js +0 -46
- package/dist/esm/mixins/OxyServices.appData.js +0 -103
- package/dist/esm/mixins/OxyServices.assets.js +0 -851
- package/dist/esm/mixins/OxyServices.auth.js +0 -1455
- package/dist/esm/mixins/OxyServices.chains.js +0 -70
- package/dist/esm/mixins/OxyServices.civic.js +0 -605
- package/dist/esm/mixins/OxyServices.connectedApps.js +0 -92
- package/dist/esm/mixins/OxyServices.contacts.js +0 -47
- package/dist/esm/mixins/OxyServices.deviceBoot.js +0 -186
- package/dist/esm/mixins/OxyServices.devices.js +0 -113
- package/dist/esm/mixins/OxyServices.features.js +0 -332
- package/dist/esm/mixins/OxyServices.followGraph.js +0 -218
- package/dist/esm/mixins/OxyServices.identity.js +0 -558
- package/dist/esm/mixins/OxyServices.identityBackup.js +0 -169
- package/dist/esm/mixins/OxyServices.inference.js +0 -56
- package/dist/esm/mixins/OxyServices.language.js +0 -122
- package/dist/esm/mixins/OxyServices.linkedAccounts.js +0 -76
- package/dist/esm/mixins/OxyServices.location.js +0 -40
- package/dist/esm/mixins/OxyServices.nodes.js +0 -172
- package/dist/esm/mixins/OxyServices.notifications.js +0 -60
- package/dist/esm/mixins/OxyServices.payment.js +0 -155
- package/dist/esm/mixins/OxyServices.privacy.js +0 -196
- package/dist/esm/mixins/OxyServices.reputation.js +0 -286
- package/dist/esm/mixins/OxyServices.security.js +0 -86
- package/dist/esm/mixins/OxyServices.store.js +0 -263
- package/dist/esm/mixins/OxyServices.topics.js +0 -134
- package/dist/esm/mixins/OxyServices.user.js +0 -951
- package/dist/esm/mixins/OxyServices.utility.js +0 -1397
- package/dist/esm/mixins/index.js +0 -133
- package/dist/esm/mixins/mixinHelpers.js +0 -48
- package/dist/esm/utils/webauthnOrigin.js +0 -48
- package/dist/types/.tsbuildinfo +0 -1
- package/dist/types/OxyServices.base.d.ts +0 -189
- package/dist/types/mixins/OxyServices.accounts.d.ts +0 -868
- package/dist/types/mixins/OxyServices.agency.d.ts +0 -176
- package/dist/types/mixins/OxyServices.analytics.d.ts +0 -72
- package/dist/types/mixins/OxyServices.appData.d.ts +0 -108
- package/dist/types/mixins/OxyServices.assets.d.ts +0 -371
- package/dist/types/mixins/OxyServices.auth.d.ts +0 -998
- package/dist/types/mixins/OxyServices.chains.d.ts +0 -156
- package/dist/types/mixins/OxyServices.civic.d.ts +0 -520
- package/dist/types/mixins/OxyServices.connectedApps.d.ts +0 -184
- package/dist/types/mixins/OxyServices.contacts.d.ts +0 -100
- package/dist/types/mixins/OxyServices.deviceBoot.d.ts +0 -185
- package/dist/types/mixins/OxyServices.devices.d.ts +0 -103
- package/dist/types/mixins/OxyServices.features.d.ts +0 -250
- package/dist/types/mixins/OxyServices.followGraph.d.ts +0 -223
- package/dist/types/mixins/OxyServices.identity.d.ts +0 -337
- package/dist/types/mixins/OxyServices.identityBackup.d.ts +0 -129
- package/dist/types/mixins/OxyServices.inference.d.ts +0 -95
- package/dist/types/mixins/OxyServices.language.d.ts +0 -87
- package/dist/types/mixins/OxyServices.linkedAccounts.d.ts +0 -107
- package/dist/types/mixins/OxyServices.location.d.ts +0 -70
- package/dist/types/mixins/OxyServices.nodes.d.ts +0 -198
- package/dist/types/mixins/OxyServices.notifications.d.ts +0 -143
- package/dist/types/mixins/OxyServices.payment.d.ts +0 -117
- package/dist/types/mixins/OxyServices.privacy.d.ts +0 -146
- package/dist/types/mixins/OxyServices.reputation.d.ts +0 -202
- package/dist/types/mixins/OxyServices.security.d.ts +0 -84
- package/dist/types/mixins/OxyServices.store.d.ts +0 -334
- package/dist/types/mixins/OxyServices.topics.d.ts +0 -110
- package/dist/types/mixins/OxyServices.user.d.ts +0 -600
- package/dist/types/mixins/OxyServices.utility.d.ts +0 -526
- package/dist/types/mixins/index.d.ts +0 -87
- package/dist/types/mixins/mixinHelpers.d.ts +0 -31
- package/dist/types/utils/webauthnOrigin.d.ts +0 -32
- package/src/OxyServices.base.ts +0 -480
- package/src/__tests__/authSocket.test.ts +0 -96
- package/src/__tests__/fixEsmImports.test.ts +0 -132
- package/src/__tests__/httpServiceAbort.test.ts +0 -308
- package/src/__tests__/httpServiceActivityId.test.ts +0 -49
- package/src/__tests__/httpServiceAuthSelfAwait.test.ts +0 -108
- package/src/__tests__/httpServiceCache.test.ts +0 -318
- package/src/__tests__/httpServiceFormEncoded.test.ts +0 -139
- package/src/__tests__/httpServiceQueueDeadlock.test.ts +0 -128
- package/src/__tests__/httpServiceRateLimitedRefresh.test.ts +0 -160
- package/src/__tests__/httpServiceUnwrapEnvelope.test.ts +0 -115
- package/src/__tests__/httpServiceWrites.test.ts +0 -175
- package/src/__tests__/inSessionRefresh.test.ts +0 -313
- package/src/__tests__/linkedClient.test.ts +0 -363
- package/src/__tests__/nearExpiryMintStorm.test.ts +0 -165
- package/src/__tests__/parseHttpErrorBody.test.ts +0 -116
- package/src/__tests__/publicInterfaceParity.test.ts +0 -75
- package/src/__tests__/serverValueImportsDeclared.test.ts +0 -120
- package/src/__tests__/serviceIdentityWhenAnonymous.test.ts +0 -159
- package/src/__tests__/serviceTokenWorkloadFallback.test.ts +0 -85
- package/src/__tests__/userIdentity.test.ts +0 -143
- package/src/boot/__tests__/sessionColdBoot.identity.test.ts +0 -393
- package/src/boot/__tests__/sessionColdBoot.sharedDevice.test.ts +0 -325
- package/src/boot/__tests__/sessionColdBoot.test.ts +0 -570
- package/src/crypto/__tests__/backupMaterial.test.ts +0 -86
- package/src/crypto/__tests__/cryptoPrimitives.test.ts +0 -226
- package/src/crypto/__tests__/identityLink.test.ts +0 -18
- package/src/crypto/__tests__/identityMocks.ts +0 -125
- package/src/crypto/__tests__/identityProof.test.ts +0 -81
- package/src/crypto/__tests__/keyManager.atomicity.test.ts +0 -272
- package/src/crypto/__tests__/keyManager.cacheSafety.test.ts +0 -175
- package/src/crypto/__tests__/keyManager.deviceBackup.test.ts +0 -310
- package/src/crypto/__tests__/keyManager.identityStatus.test.ts +0 -217
- package/src/crypto/__tests__/keyManager.recoveryLadder.test.ts +0 -179
- package/src/crypto/__tests__/keyManager.recoveryMnemonic.test.ts +0 -138
- package/src/crypto/__tests__/keyManager.sharedSlotSync.test.ts +0 -150
- package/src/crypto/__tests__/keyManager.storageMigration.test.ts +0 -227
- package/src/crypto/__tests__/keyManager.test.ts +0 -329
- package/src/crypto/__tests__/polyfill.test.ts +0 -109
- package/src/crypto/__tests__/polyfillOrder.test.ts +0 -114
- package/src/crypto/__tests__/recoveryPhrase.test.ts +0 -61
- package/src/crypto/__tests__/registrationPow.test.ts +0 -61
- package/src/crypto/__tests__/scopedSeed.test.ts +0 -126
- package/src/crypto/__tests__/signChallengeShared.test.ts +0 -63
- package/src/crypto/__tests__/signedRecord.test.ts +0 -230
- package/src/i18n/__tests__/accountCategoryLabels.test.ts +0 -62
- package/src/i18n/__tests__/accountRoleLabels.test.ts +0 -54
- package/src/i18n/__tests__/reputationCategoryLabels.test.ts +0 -56
- package/src/i18n/__tests__/trustTierLabels.test.ts +0 -47
- package/src/i18n/locales/de-DE.json +0 -306
- package/src/i18n/locales/es-ES.json +0 -2127
- package/src/i18n/locales/ja-JP.json +0 -306
- package/src/inference/__tests__/OxyInferenceClient.test.ts +0 -899
- package/src/logger/__tests__/logger.test.ts +0 -207
- package/src/mixins/OxyServices.accounts.ts +0 -1330
- package/src/mixins/OxyServices.agency.ts +0 -353
- package/src/mixins/OxyServices.analytics.ts +0 -53
- package/src/mixins/OxyServices.appData.ts +0 -158
- package/src/mixins/OxyServices.assets.ts +0 -964
- package/src/mixins/OxyServices.auth.ts +0 -2083
- package/src/mixins/OxyServices.chains.ts +0 -134
- package/src/mixins/OxyServices.civic.ts +0 -945
- package/src/mixins/OxyServices.connectedApps.ts +0 -212
- package/src/mixins/OxyServices.contacts.ts +0 -73
- package/src/mixins/OxyServices.devices.ts +0 -120
- package/src/mixins/OxyServices.features.ts +0 -454
- package/src/mixins/OxyServices.followGraph.ts +0 -293
- package/src/mixins/OxyServices.identity.ts +0 -787
- package/src/mixins/OxyServices.identityBackup.ts +0 -250
- package/src/mixins/OxyServices.inference.ts +0 -57
- package/src/mixins/OxyServices.language.ts +0 -144
- package/src/mixins/OxyServices.linkedAccounts.ts +0 -129
- package/src/mixins/OxyServices.location.ts +0 -46
- package/src/mixins/OxyServices.nodes.ts +0 -337
- package/src/mixins/OxyServices.notifications.ts +0 -142
- package/src/mixins/OxyServices.payment.ts +0 -163
- package/src/mixins/OxyServices.privacy.ts +0 -219
- package/src/mixins/OxyServices.reputation.ts +0 -436
- package/src/mixins/OxyServices.security.ts +0 -110
- package/src/mixins/OxyServices.store.ts +0 -585
- package/src/mixins/OxyServices.topics.ts +0 -169
- package/src/mixins/OxyServices.user.ts +0 -1208
- package/src/mixins/OxyServices.utility.ts +0 -1803
- package/src/mixins/__tests__/OxyServices.civic.test.ts +0 -1095
- package/src/mixins/__tests__/OxyServices.deviceBoot.test.ts +0 -124
- package/src/mixins/__tests__/OxyServices.identity.test.ts +0 -301
- package/src/mixins/__tests__/OxyServices.nodes.test.ts +0 -341
- package/src/mixins/__tests__/OxyServices.rotateKey.test.ts +0 -323
- package/src/mixins/__tests__/OxyServices.serviceAssetMetadata.test.ts +0 -192
- package/src/mixins/__tests__/OxyServices.serviceAssetMetadataBySha.test.ts +0 -135
- package/src/mixins/__tests__/OxyServices.serviceLinkedDownloadUrl.test.ts +0 -139
- package/src/mixins/__tests__/accountEvents.test.ts +0 -158
- package/src/mixins/__tests__/accounts.test.ts +0 -727
- package/src/mixins/__tests__/agency.test.ts +0 -120
- package/src/mixins/__tests__/appData.test.ts +0 -203
- package/src/mixins/__tests__/assetCredentials.test.ts +0 -47
- package/src/mixins/__tests__/assetUpload.test.ts +0 -191
- package/src/mixins/__tests__/authRefusalObservability.test.ts +0 -396
- package/src/mixins/__tests__/backgroundCredential.httpIntegration.test.ts +0 -130
- package/src/mixins/__tests__/chains.test.ts +0 -113
- package/src/mixins/__tests__/commonsSignIn.test.ts +0 -1147
- package/src/mixins/__tests__/connectedApps.test.ts +0 -146
- package/src/mixins/__tests__/deviceTokenMintPinned.test.ts +0 -113
- package/src/mixins/__tests__/discoveryErrorHandling.test.ts +0 -265
- package/src/mixins/__tests__/followCacheInvalidation.test.ts +0 -173
- package/src/mixins/__tests__/followGraph.test.ts +0 -147
- package/src/mixins/__tests__/followGraphPagination.test.ts +0 -271
- package/src/mixins/__tests__/getFileDownloadUrl.test.ts +0 -346
- package/src/mixins/__tests__/getFollowStatuses.test.ts +0 -95
- package/src/mixins/__tests__/getUsersByIds.test.ts +0 -176
- package/src/mixins/__tests__/identityBackup.test.ts +0 -315
- package/src/mixins/__tests__/identityLink.test.ts +0 -89
- package/src/mixins/__tests__/identityWriteCacheInvalidation.test.ts +0 -407
- package/src/mixins/__tests__/inferenceFactory.test.ts +0 -58
- package/src/mixins/__tests__/linkedAccounts.test.ts +0 -109
- package/src/mixins/__tests__/notifications.read.test.ts +0 -82
- package/src/mixins/__tests__/onTokensChanged.test.ts +0 -129
- package/src/mixins/__tests__/preSessionSkipAuth.test.ts +0 -284
- package/src/mixins/__tests__/privacyCacheInvalidation.test.ts +0 -155
- package/src/mixins/__tests__/reputation.test.ts +0 -522
- package/src/mixins/__tests__/serviceAuth.test.ts +0 -889
- package/src/mixins/__tests__/serviceTokenJwks.test.ts +0 -208
- package/src/mixins/__tests__/store.test.ts +0 -304
- package/src/mixins/__tests__/topics.test.ts +0 -155
- package/src/mixins/__tests__/userReadCacheBypass.test.ts +0 -129
- package/src/mixins/__tests__/userTokenAuth.test.ts +0 -746
- package/src/mixins/__tests__/verifyChallenge.test.ts +0 -161
- package/src/mixins/__tests__/verifyServiceActingAs.test.ts +0 -167
- package/src/mixins/__tests__/webauthnAuth.test.ts +0 -279
- package/src/mixins/index.ts +0 -203
- package/src/mixins/mixinHelpers.ts +0 -69
- package/src/server/__tests__/auth.test.ts +0 -78
- package/src/server/__tests__/capabilityTicket.test.ts +0 -111
- package/src/server/__tests__/cors.socket.test.ts +0 -225
- package/src/server/__tests__/cors.test.ts +0 -158
- package/src/server/__tests__/rateLimit.test.ts +0 -257
- package/src/server/__tests__/requesterAssertion.test.ts +0 -359
- package/src/server/__tests__/safeFetch.test.ts +0 -232
- package/src/server/__tests__/securityHeaders.test.ts +0 -387
- package/src/server/__tests__/serviceTokenAttribution.test.ts +0 -396
- package/src/server/__tests__/traffic.test.ts +0 -180
- package/src/server/__tests__/trafficNodeHttp.test.ts +0 -38
- package/src/server/__tests__/userInvalidation.test.ts +0 -203
- package/src/server/__tests__/verifySecret.test.ts +0 -40
- package/src/server/__tests__/workloadIdentity.client.test.ts +0 -16
- package/src/server/__tests__/workloadIdentity.test.ts +0 -128
- package/src/session/__tests__/SessionClient.additive.test.ts +0 -153
- package/src/session/__tests__/SessionClient.broadcastChannel.test.ts +0 -114
- package/src/session/__tests__/SessionClient.diagnostics.test.ts +0 -91
- package/src/session/__tests__/SessionClient.directory.test.ts +0 -688
- package/src/session/__tests__/SessionClient.httpIntegration.test.ts +0 -65
- package/src/session/__tests__/SessionClient.identityPin.test.ts +0 -175
- package/src/session/__tests__/SessionClient.rest.test.ts +0 -119
- package/src/session/__tests__/SessionClient.serverEvents.test.ts +0 -72
- package/src/session/__tests__/SessionClient.socket.test.ts +0 -202
- package/src/session/__tests__/SessionClient.socketFactory.test.ts +0 -81
- package/src/session/__tests__/SessionClient.state.test.ts +0 -78
- package/src/session/__tests__/SessionClient.switchTokenOrder.test.ts +0 -170
- package/src/session/__tests__/accountDelegationAccess.test.ts +0 -104
- package/src/session/__tests__/accountDialogController.test.ts +0 -2502
- package/src/session/__tests__/accountDialogShape.test.ts +0 -120
- package/src/session/__tests__/accountSwitchTargets.test.ts +0 -137
- package/src/session/__tests__/authStateStore.test.ts +0 -451
- package/src/session/__tests__/deviceDirectory.test.ts +0 -422
- package/src/session/__tests__/deviceSwitcherRows.test.ts +0 -223
- package/src/session/__tests__/identityPin.test.ts +0 -131
- package/src/session/__tests__/identitySession.test.ts +0 -194
- package/src/session/__tests__/projectSessionState.test.ts +0 -105
- package/src/session/__tests__/refresh.identityPin.test.ts +0 -307
- package/src/session/__tests__/refresh.test.ts +0 -606
- package/src/session/__tests__/sessionIntegration.test.ts +0 -209
- package/src/session/__tests__/sharedDeviceCredential.test.ts +0 -300
- package/src/utils/__tests__/accountUtils.test.ts +0 -151
- package/src/utils/__tests__/activityId.test.ts +0 -45
- package/src/utils/__tests__/asyncUtils.test.ts +0 -279
- package/src/utils/__tests__/authWebUrl.test.ts +0 -15
- package/src/utils/__tests__/cacheKey.test.ts +0 -0
- package/src/utils/__tests__/cacheLifecycle.test.ts +0 -65
- package/src/utils/__tests__/coldBoot.test.ts +0 -496
- package/src/utils/__tests__/commonsApproval.test.ts +0 -60
- package/src/utils/__tests__/identityCacheSweep.test.ts +0 -151
- package/src/utils/__tests__/languageUtils.test.ts +0 -244
- package/src/utils/__tests__/oauthPkce.test.ts +0 -303
- package/src/utils/__tests__/officialOrigins.test.ts +0 -31
- package/src/utils/__tests__/oxyServiceEnvironment.test.ts +0 -7
- package/src/utils/__tests__/profileLinks.test.ts +0 -180
- package/src/utils/__tests__/redactUrl.test.ts +0 -33
- package/src/utils/__tests__/registrableApex.test.ts +0 -62
- package/src/utils/__tests__/requestUtilsAbort.test.ts +0 -155
- package/src/utils/__tests__/textNormalization.test.ts +0 -205
- package/src/utils/__tests__/validationUtils.test.ts +0 -703
- package/src/utils/__tests__/webauthnOrigin.test.ts +0 -83
- package/src/utils/webauthnOrigin.ts +0 -52
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it, jest } from '@jest/globals';
|
|
2
|
-
|
|
3
|
-
import { OxyServices } from '../OxyServices';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* How an official service stops holding a secret WITHOUT a code change.
|
|
7
|
-
*
|
|
8
|
-
* `getServiceToken()` has always required an api key and secret. It now falls
|
|
9
|
-
* back to workload identity (ADR 0026) when there is none — which means the
|
|
10
|
-
* migration for each of Oxy's own services is "delete two environment
|
|
11
|
-
* variables", not "edit and redeploy an app".
|
|
12
|
-
*
|
|
13
|
-
* Three things have to be true for that to be safe, and each is asserted below:
|
|
14
|
-
*
|
|
15
|
-
* 1. A configured credential still wins. The fallback must not quietly change
|
|
16
|
-
* how an already-working service authenticates.
|
|
17
|
-
* 2. With no credential AND no way to attest — a laptop, a CI box — the caller
|
|
18
|
-
* gets the same "no credentials" error as before, not a confusing failure
|
|
19
|
-
* from a container credentials endpoint that is not there.
|
|
20
|
-
* 3. The token is cached, so a service does not mint one per request.
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
jest.mock('../server/workloadIdentity', () => ({
|
|
24
|
-
canAttestWorkloadIdentity: () => Boolean(process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI),
|
|
25
|
-
requestWorkloadServiceToken: jest.fn(async () => ({
|
|
26
|
-
token: 'token-from-attestation',
|
|
27
|
-
expiresIn: 3600,
|
|
28
|
-
appName: 'Mention',
|
|
29
|
-
})),
|
|
30
|
-
}));
|
|
31
|
-
|
|
32
|
-
import { requestWorkloadServiceToken } from '../server/workloadIdentity';
|
|
33
|
-
|
|
34
|
-
const attestations = requestWorkloadServiceToken as unknown as jest.Mock;
|
|
35
|
-
|
|
36
|
-
function client() {
|
|
37
|
-
return new OxyServices({ baseURL: 'https://api.oxy.so' });
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
describe('service token — workload fallback', () => {
|
|
41
|
-
const previous = process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI;
|
|
42
|
-
|
|
43
|
-
beforeEach(() => {
|
|
44
|
-
attestations.mockClear();
|
|
45
|
-
process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI = '/v2/credentials/abc';
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
afterAll(() => {
|
|
49
|
-
// Cleared by assignment rather than `delete`: Biome refuses `delete` on a
|
|
50
|
-
// property access, and an empty value reads as "cannot attest" everywhere
|
|
51
|
-
// that matters here.
|
|
52
|
-
process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI = previous ?? '';
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it('attests when no credential is configured', async () => {
|
|
56
|
-
await expect(client().getServiceToken()).resolves.toBe('token-from-attestation');
|
|
57
|
-
expect(attestations).toHaveBeenCalledWith({ baseUrl: 'https://api.oxy.so' });
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it('mints once and serves the cached token afterwards', async () => {
|
|
61
|
-
const oxy = client();
|
|
62
|
-
|
|
63
|
-
await oxy.getServiceToken();
|
|
64
|
-
await oxy.getServiceToken();
|
|
65
|
-
|
|
66
|
-
expect(attestations).toHaveBeenCalledTimes(1);
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
it('leaves a configured credential alone', async () => {
|
|
70
|
-
const oxy = client();
|
|
71
|
-
oxy.configureServiceAuth('oxy_dk_example', 'secret-example');
|
|
72
|
-
// The credential path goes to the network; failing there is fine — what
|
|
73
|
-
// matters is that it did not silently attest instead.
|
|
74
|
-
await oxy.getServiceToken().catch(() => undefined);
|
|
75
|
-
|
|
76
|
-
expect(attestations).not.toHaveBeenCalled();
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it('still says "no credentials" where nothing can be attested', async () => {
|
|
80
|
-
process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI = '';
|
|
81
|
-
|
|
82
|
-
await expect(client().getServiceToken()).rejects.toThrow(/Service credentials not provided/);
|
|
83
|
-
expect(attestations).not.toHaveBeenCalled();
|
|
84
|
-
});
|
|
85
|
-
});
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
import { OxyServices } from '../OxyServices';
|
|
2
|
-
import { getNormalizedUserId, normalizeUserIdentity } from '../utils/userIdentity';
|
|
3
|
-
import { getCanonicalUserHandle, getNormalizedUserHandle } from '../utils/userHandle';
|
|
4
|
-
|
|
5
|
-
interface FetchCall {
|
|
6
|
-
url: string;
|
|
7
|
-
init: RequestInit | undefined;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
function jsonResponse(data: unknown): Response {
|
|
11
|
-
return new Response(JSON.stringify({ data }), {
|
|
12
|
-
status: 200,
|
|
13
|
-
headers: { 'content-type': 'application/json' },
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function createJwt(payload: Record<string, unknown>): string {
|
|
18
|
-
const encode = (value: unknown): string => Buffer.from(JSON.stringify(value)).toString('base64url');
|
|
19
|
-
return `${encode({ alg: 'HS256', typ: 'JWT' })}.${encode(payload)}.signature`;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
describe('user identity normalization', () => {
|
|
23
|
-
const originalFetch = globalThis.fetch;
|
|
24
|
-
|
|
25
|
-
afterEach(() => {
|
|
26
|
-
globalThis.fetch = originalFetch;
|
|
27
|
-
jest.restoreAllMocks();
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it('normalizes Mongo _id to id', () => {
|
|
31
|
-
expect(getNormalizedUserId({ _id: 'mongo_id' })).toBe('mongo_id');
|
|
32
|
-
expect(normalizeUserIdentity({ _id: 'mongo_id', username: 'nate' })).toEqual({
|
|
33
|
-
_id: 'mongo_id',
|
|
34
|
-
id: 'mongo_id',
|
|
35
|
-
username: 'nate',
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it('normalizes getCurrentUser responses before exposing them to apps', async () => {
|
|
40
|
-
const calls: FetchCall[] = [];
|
|
41
|
-
globalThis.fetch = async (input, init) => {
|
|
42
|
-
const url = String(input);
|
|
43
|
-
calls.push({ url, init });
|
|
44
|
-
return jsonResponse({ _id: 'user_1', username: 'nate', publicKey: 'pub_1' });
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
const oxy = new OxyServices({ baseURL: 'https://api.oxy.so' });
|
|
48
|
-
oxy.setTokens(createJwt({
|
|
49
|
-
userId: 'user_1',
|
|
50
|
-
exp: Math.floor(Date.now() / 1000) + 3600,
|
|
51
|
-
}));
|
|
52
|
-
const user = await oxy.getCurrentUser();
|
|
53
|
-
|
|
54
|
-
expect(user.id).toBe('user_1');
|
|
55
|
-
expect(user.username).toBe('nate');
|
|
56
|
-
expect(calls[0].url).toBe('https://api.oxy.so/users/me');
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it('normalizes validateSession users before services stores them', async () => {
|
|
60
|
-
globalThis.fetch = async () =>
|
|
61
|
-
jsonResponse({
|
|
62
|
-
valid: true,
|
|
63
|
-
expiresAt: '2099-01-01T00:00:00.000Z',
|
|
64
|
-
lastActivity: '2026-06-18T00:00:00.000Z',
|
|
65
|
-
user: { _id: 'user_1', username: 'nate', publicKey: 'pub_1' },
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
const oxy = new OxyServices({ baseURL: 'https://api.oxy.so' });
|
|
69
|
-
const validation = await oxy.validateSession('session_1', { useHeaderValidation: true });
|
|
70
|
-
|
|
71
|
-
expect(validation.user.id).toBe('user_1');
|
|
72
|
-
expect(validation.user.username).toBe('nate');
|
|
73
|
-
});
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
describe('getNormalizedUserHandle', () => {
|
|
77
|
-
it('normalizes local usernames without route prefixes', () => {
|
|
78
|
-
expect(getNormalizedUserHandle({ username: ' nate ' })).toBe('nate');
|
|
79
|
-
expect(getNormalizedUserHandle({ username: '@nate' })).toBe('nate');
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
it('falls back to handle when username is missing', () => {
|
|
83
|
-
expect(getNormalizedUserHandle({ handle: '@nate' })).toBe('nate');
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it('builds federated handles from username and instance', () => {
|
|
87
|
-
expect(getNormalizedUserHandle({
|
|
88
|
-
username: 'joannastern',
|
|
89
|
-
isFederated: true,
|
|
90
|
-
instance: 'threads.net',
|
|
91
|
-
})).toBe('joannastern@threads.net');
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
it('does not append an instance twice', () => {
|
|
95
|
-
expect(getNormalizedUserHandle({
|
|
96
|
-
username: '@joannastern@threads.net',
|
|
97
|
-
type: 'federated',
|
|
98
|
-
instance: 'threads.net',
|
|
99
|
-
})).toBe('joannastern@threads.net');
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
it('uses federation domain as the federated instance source', () => {
|
|
103
|
-
expect(getNormalizedUserHandle({
|
|
104
|
-
username: 'alice',
|
|
105
|
-
isFederated: true,
|
|
106
|
-
federation: { domain: '@example.social' },
|
|
107
|
-
})).toBe('alice@example.social');
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
it('does not use instance for local users', () => {
|
|
111
|
-
expect(getNormalizedUserHandle({
|
|
112
|
-
username: 'alice',
|
|
113
|
-
instance: 'example.social',
|
|
114
|
-
})).toBe('alice');
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
it('keeps case while normalizing whitespace', () => {
|
|
118
|
-
expect(getNormalizedUserHandle({
|
|
119
|
-
username: ' Alice ',
|
|
120
|
-
isFederated: true,
|
|
121
|
-
instance: ' Example.Social ',
|
|
122
|
-
})).toBe('Alice@Example.Social');
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
it('does not turn an invalid instance into a federated suffix', () => {
|
|
126
|
-
expect(getNormalizedUserHandle({
|
|
127
|
-
username: 'alice',
|
|
128
|
-
isFederated: true,
|
|
129
|
-
instance: 'example.social/users/alice',
|
|
130
|
-
})).toBe('alice');
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
it('rejects empty and route-like values', () => {
|
|
134
|
-
expect(getNormalizedUserHandle({ username: '' })).toBeNull();
|
|
135
|
-
expect(getNormalizedUserHandle({ username: 'alice/about' })).toBeNull();
|
|
136
|
-
expect(getNormalizedUserHandle({ username: 'alice?tab=posts' })).toBeNull();
|
|
137
|
-
expect(getNormalizedUserHandle({ username: 'alice#posts' })).toBeNull();
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
it('keeps the compatibility alias wired to the normalized implementation', () => {
|
|
141
|
-
expect(getCanonicalUserHandle({ username: '@nate' })).toBe('nate');
|
|
142
|
-
});
|
|
143
|
-
});
|
|
@@ -1,393 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Cold boot in IDENTITY mode — the identity vault's boot.
|
|
3
|
-
*
|
|
4
|
-
* Invariants under test:
|
|
5
|
-
* - a persisted warm token that belongs to ANOTHER account is never planted;
|
|
6
|
-
* the boot falls through to the PINNED mint instead;
|
|
7
|
-
* - the mint carries the pinned `accountId`, and the resolved session is the
|
|
8
|
-
* pinned account even while the device is switched elsewhere;
|
|
9
|
-
* - `identity-key-signin` (the PRIMARY local key) replaces `shared-key-signin`
|
|
10
|
-
* (the CROSS-APP shared slot) — and the reverse in account mode;
|
|
11
|
-
* - with no verified pin the (unpinned) mint lane is skipped entirely rather
|
|
12
|
-
* than adopting whichever account the device is currently switched to.
|
|
13
|
-
*/
|
|
14
|
-
import type { DeviceTokenMintResponse } from '@oxy.so/contracts';
|
|
15
|
-
import type { OxyServices } from '../../OxyServices';
|
|
16
|
-
import type { SessionLoginResponse } from '../../models/session';
|
|
17
|
-
import type { AuthChallenge } from '../../crypto/signatureService';
|
|
18
|
-
import { runSessionColdBoot } from '../sessionColdBoot';
|
|
19
|
-
import type { DeviceSecretMintOutcome } from '../../session/refresh';
|
|
20
|
-
import { createMemoryAuthStateStore, type PersistedAuthState } from '../../session/authStateStore';
|
|
21
|
-
import { createMemoryIdentityPinStore, type IdentityPin } from '../../session/identityPin';
|
|
22
|
-
import type { IdentityBinding } from '../../session/identitySession';
|
|
23
|
-
|
|
24
|
-
const PUBLIC_KEY = `02${'a'.repeat(64)}`;
|
|
25
|
-
const OTHER_PUBLIC_KEY = `03${'b'.repeat(64)}`;
|
|
26
|
-
const PIN: IdentityPin = { publicKey: PUBLIC_KEY, accountId: 'vault-user' };
|
|
27
|
-
|
|
28
|
-
const NATIVE = { isWeb: false, isNative: true };
|
|
29
|
-
|
|
30
|
-
/** A minimal jwt-decode-able token whose `userId` claim is `accountId`. */
|
|
31
|
-
function jwtFor(accountId: string): string {
|
|
32
|
-
const payload = Buffer.from(JSON.stringify({ userId: accountId })).toString('base64url');
|
|
33
|
-
return `h.${payload}.s`;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/** Comfortably beyond the 60s refresh lead window. */
|
|
37
|
-
const farFuture = (): string => new Date(Date.now() + 3_600_000).toISOString();
|
|
38
|
-
|
|
39
|
-
function makeMintSingleFlight(): (mint: () => Promise<DeviceSecretMintOutcome>) => Promise<DeviceSecretMintOutcome> {
|
|
40
|
-
let inFlight: Promise<DeviceSecretMintOutcome> | null = null;
|
|
41
|
-
return (mint) => {
|
|
42
|
-
if (!inFlight) {
|
|
43
|
-
inFlight = mint().finally(() => {
|
|
44
|
-
inFlight = null;
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
return inFlight;
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/** The device is switched to `other-user`; the pinned account is still a member. */
|
|
52
|
-
const MINT_WHILE_SWITCHED: DeviceTokenMintResponse = {
|
|
53
|
-
accessToken: jwtFor('vault-user'),
|
|
54
|
-
expiresAt: '2030-01-01T00:00:00.000Z',
|
|
55
|
-
nextDeviceSecret: 'ds-next-secret',
|
|
56
|
-
state: {
|
|
57
|
-
deviceId: 'dev-1',
|
|
58
|
-
accounts: [
|
|
59
|
-
{ accountId: 'vault-user', sessionId: 'sess-vault-new', authuser: 0 },
|
|
60
|
-
{ accountId: 'other-user', sessionId: 'sess-other', authuser: 1 },
|
|
61
|
-
],
|
|
62
|
-
activeAccountId: 'other-user',
|
|
63
|
-
revision: 9,
|
|
64
|
-
updatedAt: 1_700_000_000_000,
|
|
65
|
-
},
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
const IDENTITY_SESSION: SessionLoginResponse = {
|
|
69
|
-
sessionId: 'sess-identity',
|
|
70
|
-
deviceId: 'dev-1',
|
|
71
|
-
expiresAt: '2030-01-01T00:00:00.000Z',
|
|
72
|
-
accessToken: 'access-identity',
|
|
73
|
-
deviceSecret: 'ds-identity',
|
|
74
|
-
user: { id: 'vault-user', username: 'vault', name: {} },
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
const SHARED_SESSION: SessionLoginResponse = {
|
|
78
|
-
sessionId: 'sess-shared',
|
|
79
|
-
deviceId: 'dev-1',
|
|
80
|
-
expiresAt: '2030-01-01T00:00:00.000Z',
|
|
81
|
-
accessToken: 'access-shared',
|
|
82
|
-
user: { id: 'shared-user', username: 'shared', name: {} },
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
interface OxyOverrides {
|
|
86
|
-
mintFromDeviceSecret?: OxyServices['mintFromDeviceSecret'];
|
|
87
|
-
signInWithSharedIdentity?: OxyServices['signInWithSharedIdentity'];
|
|
88
|
-
requestChallenge?: OxyServices['requestChallenge'];
|
|
89
|
-
verifyChallenge?: OxyServices['verifyChallenge'];
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function makeOxy(overrides: OxyOverrides = {}): { oxy: OxyServices; setTokens: jest.Mock } {
|
|
93
|
-
const setTokens = jest.fn();
|
|
94
|
-
const oxy = {
|
|
95
|
-
getBaseURL: () => 'https://api.oxy.so',
|
|
96
|
-
setTokens,
|
|
97
|
-
mintFromDeviceSecret:
|
|
98
|
-
overrides.mintFromDeviceSecret
|
|
99
|
-
?? (async () => {
|
|
100
|
-
throw new Error('mintFromDeviceSecret not stubbed');
|
|
101
|
-
}),
|
|
102
|
-
signInWithSharedIdentity: overrides.signInWithSharedIdentity ?? (async () => null),
|
|
103
|
-
requestChallenge:
|
|
104
|
-
overrides.requestChallenge
|
|
105
|
-
?? (async () => ({ challenge: 'chal-1', expiresAt: '2030-01-01T00:00:00.000Z' })),
|
|
106
|
-
verifyChallenge: overrides.verifyChallenge ?? (async () => IDENTITY_SESSION),
|
|
107
|
-
httpService: { runSingleFlightDeviceSecretMint: makeMintSingleFlight(), getSessionEpoch: () => 0 },
|
|
108
|
-
} as unknown as OxyServices;
|
|
109
|
-
return { oxy, setTokens };
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
function signWith(publicKey: string): (challenge: string) => Promise<AuthChallenge> {
|
|
113
|
-
return async (challenge) => ({
|
|
114
|
-
challenge: `sig(${challenge})`,
|
|
115
|
-
publicKey,
|
|
116
|
-
timestamp: 1_700_000_000_000,
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/** An identity binding, optionally pre-seeded with a pin. */
|
|
121
|
-
async function makeBinding(options: { pin?: IdentityPin; publicKey?: string } = {}): Promise<IdentityBinding> {
|
|
122
|
-
const publicKey = options.publicKey ?? PUBLIC_KEY;
|
|
123
|
-
const pinStore = createMemoryIdentityPinStore();
|
|
124
|
-
if (options.pin) {
|
|
125
|
-
await pinStore.save(options.pin);
|
|
126
|
-
}
|
|
127
|
-
return { pinStore, readPublicKey: async () => publicKey, signChallenge: signWith(publicKey) };
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
async function seedStore(extra: Partial<PersistedAuthState> = {}) {
|
|
131
|
-
const store = createMemoryAuthStateStore();
|
|
132
|
-
await store.save({
|
|
133
|
-
sessionId: 'sess-vault',
|
|
134
|
-
userId: 'vault-user',
|
|
135
|
-
deviceId: 'dev-1',
|
|
136
|
-
deviceSecret: 'ds-secret-orig',
|
|
137
|
-
...extra,
|
|
138
|
-
});
|
|
139
|
-
return store;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
describe('runSessionColdBoot — identity mode: warm-token-plant', () => {
|
|
143
|
-
it('plants a warm token that belongs to the pinned account', async () => {
|
|
144
|
-
const store = await seedStore({ accessToken: jwtFor('vault-user'), expiresAt: farFuture() });
|
|
145
|
-
const { oxy, setTokens } = makeOxy();
|
|
146
|
-
|
|
147
|
-
const outcome = await runSessionColdBoot({
|
|
148
|
-
oxy,
|
|
149
|
-
store,
|
|
150
|
-
platform: NATIVE,
|
|
151
|
-
sessionMode: 'identity',
|
|
152
|
-
identity: await makeBinding({ pin: PIN }),
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
expect(outcome).toMatchObject({ kind: 'session', via: 'warm-token-plant' });
|
|
156
|
-
expect(setTokens).toHaveBeenCalledWith(jwtFor('vault-user'));
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
it('does NOT plant a warm token minted for ANOTHER account — falls through to the pinned mint', async () => {
|
|
160
|
-
// The durable drift: an account-mode re-mint rewrote the persisted session to
|
|
161
|
-
// `other-user` while the device was switched. Identity mode must reject it.
|
|
162
|
-
const store = await seedStore({
|
|
163
|
-
sessionId: 'sess-other',
|
|
164
|
-
userId: 'other-user',
|
|
165
|
-
accessToken: jwtFor('other-user'),
|
|
166
|
-
expiresAt: farFuture(),
|
|
167
|
-
});
|
|
168
|
-
const mintFromDeviceSecret = jest.fn(async () => MINT_WHILE_SWITCHED);
|
|
169
|
-
const { oxy, setTokens } = makeOxy({ mintFromDeviceSecret });
|
|
170
|
-
|
|
171
|
-
const outcome = await runSessionColdBoot({
|
|
172
|
-
oxy,
|
|
173
|
-
store,
|
|
174
|
-
platform: NATIVE,
|
|
175
|
-
sessionMode: 'identity',
|
|
176
|
-
identity: await makeBinding({ pin: PIN }),
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
expect(setTokens).not.toHaveBeenCalledWith(jwtFor('other-user'));
|
|
180
|
-
expect(outcome).toMatchObject({
|
|
181
|
-
kind: 'session',
|
|
182
|
-
via: 'device-secret-mint',
|
|
183
|
-
session: { sessionId: 'sess-vault-new', userId: 'vault-user' },
|
|
184
|
-
});
|
|
185
|
-
expect(mintFromDeviceSecret).toHaveBeenCalledWith('dev-1', 'ds-secret-orig', {
|
|
186
|
-
accountId: 'vault-user',
|
|
187
|
-
});
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
it('does NOT plant a warm token whose persisted identity matches but whose CLAIM does not', async () => {
|
|
191
|
-
// Belt-and-braces: `userId` says the pinned account, the token itself does not.
|
|
192
|
-
const store = await seedStore({ accessToken: jwtFor('other-user'), expiresAt: farFuture() });
|
|
193
|
-
const mintFromDeviceSecret = jest.fn(async () => MINT_WHILE_SWITCHED);
|
|
194
|
-
const { oxy, setTokens } = makeOxy({ mintFromDeviceSecret });
|
|
195
|
-
|
|
196
|
-
const outcome = await runSessionColdBoot({
|
|
197
|
-
oxy,
|
|
198
|
-
store,
|
|
199
|
-
platform: NATIVE,
|
|
200
|
-
sessionMode: 'identity',
|
|
201
|
-
identity: await makeBinding({ pin: PIN }),
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
expect(setTokens).not.toHaveBeenCalledWith(jwtFor('other-user'));
|
|
205
|
-
expect(outcome).toMatchObject({ kind: 'session', via: 'device-secret-mint' });
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
it('plants a warm token in ACCOUNT mode regardless of which account it belongs to (unchanged)', async () => {
|
|
209
|
-
const store = await seedStore({
|
|
210
|
-
sessionId: 'sess-other',
|
|
211
|
-
userId: 'other-user',
|
|
212
|
-
accessToken: jwtFor('other-user'),
|
|
213
|
-
expiresAt: farFuture(),
|
|
214
|
-
});
|
|
215
|
-
const { oxy, setTokens } = makeOxy();
|
|
216
|
-
|
|
217
|
-
const outcome = await runSessionColdBoot({ oxy, store, platform: NATIVE });
|
|
218
|
-
|
|
219
|
-
expect(outcome).toMatchObject({ kind: 'session', via: 'warm-token-plant' });
|
|
220
|
-
expect(setTokens).toHaveBeenCalledWith(jwtFor('other-user'));
|
|
221
|
-
});
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
describe('runSessionColdBoot — identity mode: device-secret-mint', () => {
|
|
225
|
-
it('skips the mint entirely when there is no verified pin', async () => {
|
|
226
|
-
const store = await seedStore();
|
|
227
|
-
const mintFromDeviceSecret = jest.fn(async () => MINT_WHILE_SWITCHED);
|
|
228
|
-
const { oxy } = makeOxy({ mintFromDeviceSecret });
|
|
229
|
-
|
|
230
|
-
const outcome = await runSessionColdBoot({
|
|
231
|
-
oxy,
|
|
232
|
-
store,
|
|
233
|
-
platform: NATIVE,
|
|
234
|
-
sessionMode: 'identity',
|
|
235
|
-
identity: await makeBinding(), // no pin seeded
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
// An unpinned mint would have resolved `other-user` — never acceptable here.
|
|
239
|
-
expect(mintFromDeviceSecret).not.toHaveBeenCalled();
|
|
240
|
-
expect(outcome).toMatchObject({
|
|
241
|
-
kind: 'session',
|
|
242
|
-
via: 'identity-key-signin',
|
|
243
|
-
session: { userId: 'vault-user' },
|
|
244
|
-
});
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
it('keeps the device secret and re-establishes when the pinned account left the device', async () => {
|
|
248
|
-
const store = await seedStore();
|
|
249
|
-
const mintFromDeviceSecret = jest.fn(async () => {
|
|
250
|
-
throw Object.assign(new Error('account_not_on_device'), { status: 401 });
|
|
251
|
-
});
|
|
252
|
-
const { oxy } = makeOxy({ mintFromDeviceSecret });
|
|
253
|
-
|
|
254
|
-
const outcome = await runSessionColdBoot({
|
|
255
|
-
oxy,
|
|
256
|
-
store,
|
|
257
|
-
platform: NATIVE,
|
|
258
|
-
sessionMode: 'identity',
|
|
259
|
-
identity: await makeBinding({ pin: PIN }),
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
expect(outcome).toMatchObject({ kind: 'session', via: 'identity-key-signin' });
|
|
263
|
-
// The healthy credential was never dropped over a stale identity binding
|
|
264
|
-
// (the identity sign-in then overwrote it with the freshly minted one).
|
|
265
|
-
expect(await store.load()).toMatchObject({ deviceSecret: 'ds-identity' });
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
it('clears a pin whose key no longer matches, then re-establishes from the current key', async () => {
|
|
269
|
-
const store = await seedStore();
|
|
270
|
-
const mintFromDeviceSecret = jest.fn(async () => MINT_WHILE_SWITCHED);
|
|
271
|
-
const { oxy } = makeOxy({ mintFromDeviceSecret });
|
|
272
|
-
const pinStore = createMemoryIdentityPinStore();
|
|
273
|
-
await pinStore.save(PIN);
|
|
274
|
-
|
|
275
|
-
const outcome = await runSessionColdBoot({
|
|
276
|
-
oxy,
|
|
277
|
-
store,
|
|
278
|
-
platform: NATIVE,
|
|
279
|
-
sessionMode: 'identity',
|
|
280
|
-
identity: {
|
|
281
|
-
pinStore,
|
|
282
|
-
readPublicKey: async () => OTHER_PUBLIC_KEY,
|
|
283
|
-
signChallenge: signWith(OTHER_PUBLIC_KEY),
|
|
284
|
-
},
|
|
285
|
-
});
|
|
286
|
-
|
|
287
|
-
expect(mintFromDeviceSecret).not.toHaveBeenCalled();
|
|
288
|
-
expect(outcome).toMatchObject({ kind: 'session', via: 'identity-key-signin' });
|
|
289
|
-
expect(await pinStore.load()).toEqual({ publicKey: OTHER_PUBLIC_KEY, accountId: 'vault-user' });
|
|
290
|
-
});
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
describe('runSessionColdBoot — identity-key-signin vs shared-key-signin', () => {
|
|
294
|
-
it('identity mode runs identity-key-signin and NEVER the shared-keychain lane', async () => {
|
|
295
|
-
const store = createMemoryAuthStateStore(); // no mint credential
|
|
296
|
-
const signInWithSharedIdentity = jest.fn(async () => SHARED_SESSION);
|
|
297
|
-
const requestChallenge = jest.fn(async () => ({
|
|
298
|
-
challenge: 'chal-1',
|
|
299
|
-
expiresAt: '2030-01-01T00:00:00.000Z',
|
|
300
|
-
}));
|
|
301
|
-
const verifyChallenge = jest.fn(async () => IDENTITY_SESSION);
|
|
302
|
-
const { oxy } = makeOxy({ signInWithSharedIdentity, requestChallenge, verifyChallenge });
|
|
303
|
-
const binding = await makeBinding();
|
|
304
|
-
const onSession = jest.fn();
|
|
305
|
-
|
|
306
|
-
const outcome = await runSessionColdBoot({
|
|
307
|
-
oxy,
|
|
308
|
-
store,
|
|
309
|
-
platform: NATIVE,
|
|
310
|
-
sessionMode: 'identity',
|
|
311
|
-
identity: binding,
|
|
312
|
-
onSession,
|
|
313
|
-
});
|
|
314
|
-
|
|
315
|
-
expect(signInWithSharedIdentity).not.toHaveBeenCalled();
|
|
316
|
-
expect(outcome).toMatchObject({ kind: 'session', via: 'identity-key-signin' });
|
|
317
|
-
expect(onSession).toHaveBeenCalledWith(
|
|
318
|
-
expect.objectContaining({
|
|
319
|
-
sessionId: 'sess-identity',
|
|
320
|
-
userId: 'vault-user',
|
|
321
|
-
via: 'identity-key-signin',
|
|
322
|
-
}),
|
|
323
|
-
);
|
|
324
|
-
// Boot-path network calls stay single-attempt.
|
|
325
|
-
expect(requestChallenge).toHaveBeenCalledWith(PUBLIC_KEY, { retry: false });
|
|
326
|
-
expect(verifyChallenge).toHaveBeenCalledWith(
|
|
327
|
-
PUBLIC_KEY,
|
|
328
|
-
'chal-1',
|
|
329
|
-
'sig(chal-1)',
|
|
330
|
-
1_700_000_000_000,
|
|
331
|
-
undefined,
|
|
332
|
-
undefined,
|
|
333
|
-
{ retry: false },
|
|
334
|
-
);
|
|
335
|
-
// The pin and the fast-lane credential are both written for the next boot.
|
|
336
|
-
expect(await binding.pinStore.load()).toEqual(PIN);
|
|
337
|
-
expect(await store.load()).toMatchObject({ userId: 'vault-user', deviceSecret: 'ds-identity' });
|
|
338
|
-
});
|
|
339
|
-
|
|
340
|
-
it('account mode runs shared-key-signin and NEVER the identity lane (unchanged)', async () => {
|
|
341
|
-
const store = createMemoryAuthStateStore();
|
|
342
|
-
const signInWithSharedIdentity = jest.fn(async () => SHARED_SESSION);
|
|
343
|
-
const requestChallenge = jest.fn(async () => ({ challenge: 'c', expiresAt: 'e' }));
|
|
344
|
-
const { oxy } = makeOxy({ signInWithSharedIdentity, requestChallenge });
|
|
345
|
-
|
|
346
|
-
const outcome = await runSessionColdBoot({ oxy, store, platform: NATIVE });
|
|
347
|
-
|
|
348
|
-
expect(outcome).toMatchObject({ kind: 'session', via: 'shared-key-signin' });
|
|
349
|
-
expect(signInWithSharedIdentity).toHaveBeenCalledWith({ requestOptions: { retry: false } });
|
|
350
|
-
expect(requestChallenge).not.toHaveBeenCalled();
|
|
351
|
-
});
|
|
352
|
-
|
|
353
|
-
it('is offline-gated like every other network step', async () => {
|
|
354
|
-
const store = createMemoryAuthStateStore();
|
|
355
|
-
const requestChallenge = jest.fn(async () => ({ challenge: 'c', expiresAt: 'e' }));
|
|
356
|
-
const { oxy } = makeOxy({ requestChallenge });
|
|
357
|
-
const onSignedOut = jest.fn();
|
|
358
|
-
|
|
359
|
-
const outcome = await runSessionColdBoot({
|
|
360
|
-
oxy,
|
|
361
|
-
store,
|
|
362
|
-
platform: NATIVE,
|
|
363
|
-
sessionMode: 'identity',
|
|
364
|
-
identity: await makeBinding(),
|
|
365
|
-
isOffline: () => true,
|
|
366
|
-
onSignedOut,
|
|
367
|
-
});
|
|
368
|
-
|
|
369
|
-
expect(requestChallenge).not.toHaveBeenCalled();
|
|
370
|
-
expect(outcome).toEqual({ kind: 'unauthenticated' });
|
|
371
|
-
expect(onSignedOut).toHaveBeenCalledWith('no_session');
|
|
372
|
-
});
|
|
373
|
-
|
|
374
|
-
it('ends signed out (never account-mode) when identity mode is requested without a binding', async () => {
|
|
375
|
-
const store = await seedStore({ accessToken: jwtFor('other-user'), expiresAt: farFuture() });
|
|
376
|
-
const mintFromDeviceSecret = jest.fn(async () => MINT_WHILE_SWITCHED);
|
|
377
|
-
const { oxy, setTokens } = makeOxy({ mintFromDeviceSecret });
|
|
378
|
-
const onSignedOut = jest.fn();
|
|
379
|
-
|
|
380
|
-
const outcome = await runSessionColdBoot({
|
|
381
|
-
oxy,
|
|
382
|
-
store,
|
|
383
|
-
platform: NATIVE,
|
|
384
|
-
sessionMode: 'identity',
|
|
385
|
-
onSignedOut,
|
|
386
|
-
});
|
|
387
|
-
|
|
388
|
-
expect(outcome).toEqual({ kind: 'unauthenticated' });
|
|
389
|
-
expect(onSignedOut).toHaveBeenCalledWith('error');
|
|
390
|
-
expect(setTokens).not.toHaveBeenCalled();
|
|
391
|
-
expect(mintFromDeviceSecret).not.toHaveBeenCalled();
|
|
392
|
-
});
|
|
393
|
-
});
|