@oxy.so/core 1.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/LICENSE +202 -0
- package/NOTICE +16 -0
- package/README.md +221 -0
- package/dist/cjs/.tsbuildinfo +1 -0
- package/dist/cjs/HttpService.js +1270 -0
- package/dist/cjs/OxyServices.base.js +390 -0
- package/dist/cjs/OxyServices.errors.js +95 -0
- package/dist/cjs/OxyServices.js +72 -0
- package/dist/cjs/boot/sessionColdBoot.js +395 -0
- package/dist/cjs/constants/version.js +16 -0
- package/dist/cjs/crypto/aead.js +79 -0
- package/dist/cjs/crypto/ecdh.js +35 -0
- package/dist/cjs/crypto/identityMarker.js +255 -0
- package/dist/cjs/crypto/kdf.js +39 -0
- package/dist/cjs/crypto/keyManager.js +2234 -0
- package/dist/cjs/crypto/polyfill.js +131 -0
- package/dist/cjs/crypto/recoveryPhrase.js +242 -0
- package/dist/cjs/crypto/signatureService.js +273 -0
- package/dist/cjs/i18n/accountCategoryLabels.js +44 -0
- package/dist/cjs/i18n/accountRoleLabels.js +27 -0
- package/dist/cjs/i18n/index.js +90 -0
- package/dist/cjs/i18n/locales/ar-SA.json +282 -0
- package/dist/cjs/i18n/locales/ca-ES.json +282 -0
- package/dist/cjs/i18n/locales/de-DE.json +282 -0
- package/dist/cjs/i18n/locales/en-US.json +2161 -0
- package/dist/cjs/i18n/locales/es-ES.json +2161 -0
- package/dist/cjs/i18n/locales/fr-FR.json +282 -0
- package/dist/cjs/i18n/locales/it-IT.json +282 -0
- package/dist/cjs/i18n/locales/ja-JP.json +282 -0
- package/dist/cjs/i18n/locales/ko-KR.json +282 -0
- package/dist/cjs/i18n/locales/locales/ar-SA.json +282 -0
- package/dist/cjs/i18n/locales/locales/ca-ES.json +282 -0
- package/dist/cjs/i18n/locales/locales/de-DE.json +282 -0
- package/dist/cjs/i18n/locales/locales/en-US.json +2161 -0
- package/dist/cjs/i18n/locales/locales/es-ES.json +2161 -0
- package/dist/cjs/i18n/locales/locales/fr-FR.json +282 -0
- package/dist/cjs/i18n/locales/locales/it-IT.json +282 -0
- package/dist/cjs/i18n/locales/locales/ja-JP.json +282 -0
- package/dist/cjs/i18n/locales/locales/ko-KR.json +282 -0
- package/dist/cjs/i18n/locales/locales/pt-PT.json +282 -0
- package/dist/cjs/i18n/locales/locales/zh-CN.json +282 -0
- package/dist/cjs/i18n/locales/pt-PT.json +282 -0
- package/dist/cjs/i18n/locales/zh-CN.json +282 -0
- package/dist/cjs/i18n/reputationCategoryLabels.js +20 -0
- package/dist/cjs/i18n/trustTierLabels.js +19 -0
- package/dist/cjs/index.js +498 -0
- package/dist/cjs/inference/OxyInferenceClient.js +544 -0
- package/dist/cjs/logger/index.js +149 -0
- package/dist/cjs/mixins/OxyServices.accounts.js +555 -0
- package/dist/cjs/mixins/OxyServices.analytics.js +49 -0
- package/dist/cjs/mixins/OxyServices.appData.js +108 -0
- package/dist/cjs/mixins/OxyServices.assets.js +764 -0
- package/dist/cjs/mixins/OxyServices.auth.js +1254 -0
- package/dist/cjs/mixins/OxyServices.chains.js +73 -0
- package/dist/cjs/mixins/OxyServices.civic.js +611 -0
- package/dist/cjs/mixins/OxyServices.connectedApps.js +78 -0
- package/dist/cjs/mixins/OxyServices.contacts.js +50 -0
- package/dist/cjs/mixins/OxyServices.deviceBoot.js +191 -0
- package/dist/cjs/mixins/OxyServices.deviceTransfer.js +314 -0
- package/dist/cjs/mixins/OxyServices.devices.js +116 -0
- package/dist/cjs/mixins/OxyServices.features.js +335 -0
- package/dist/cjs/mixins/OxyServices.followGraph.js +221 -0
- package/dist/cjs/mixins/OxyServices.identity.js +461 -0
- package/dist/cjs/mixins/OxyServices.identityBackup.js +172 -0
- package/dist/cjs/mixins/OxyServices.inference.js +59 -0
- package/dist/cjs/mixins/OxyServices.language.js +125 -0
- package/dist/cjs/mixins/OxyServices.links.js +72 -0
- package/dist/cjs/mixins/OxyServices.location.js +43 -0
- package/dist/cjs/mixins/OxyServices.nodes.js +175 -0
- package/dist/cjs/mixins/OxyServices.notifications.js +63 -0
- package/dist/cjs/mixins/OxyServices.payment.js +158 -0
- package/dist/cjs/mixins/OxyServices.privacy.js +199 -0
- package/dist/cjs/mixins/OxyServices.reputation.js +289 -0
- package/dist/cjs/mixins/OxyServices.security.js +89 -0
- package/dist/cjs/mixins/OxyServices.store.js +266 -0
- package/dist/cjs/mixins/OxyServices.topics.js +137 -0
- package/dist/cjs/mixins/OxyServices.user.js +902 -0
- package/dist/cjs/mixins/OxyServices.utility.js +1098 -0
- package/dist/cjs/mixins/index.js +135 -0
- package/dist/cjs/mixins/mixinHelpers.js +53 -0
- package/dist/cjs/models/Topic.js +16 -0
- package/dist/cjs/models/interfaces.js +20 -0
- package/dist/cjs/models/session.js +2 -0
- package/dist/cjs/server/auth.js +167 -0
- package/dist/cjs/server/capabilityTicket.js +192 -0
- package/dist/cjs/server/cors.js +225 -0
- package/dist/cjs/server/index.js +97 -0
- package/dist/cjs/server/rateLimit.js +207 -0
- package/dist/cjs/server/safeFetch.js +458 -0
- package/dist/cjs/server/securityHeaders.js +377 -0
- package/dist/cjs/server/userInvalidation.js +156 -0
- package/dist/cjs/server/verifySecret.js +50 -0
- package/dist/cjs/session/SessionClient.js +865 -0
- package/dist/cjs/session/accountDelegationAccess.js +48 -0
- package/dist/cjs/session/accountDialogController.js +1131 -0
- package/dist/cjs/session/accountSwitchTargets.js +81 -0
- package/dist/cjs/session/authStateStore.js +404 -0
- package/dist/cjs/session/createSessionClient.js +32 -0
- package/dist/cjs/session/deviceDirectory.js +143 -0
- package/dist/cjs/session/deviceSwitcherRows.js +76 -0
- package/dist/cjs/session/identityPin.js +256 -0
- package/dist/cjs/session/identitySession.js +135 -0
- package/dist/cjs/session/projectSessionState.js +121 -0
- package/dist/cjs/session/refresh.js +398 -0
- package/dist/cjs/session/sessionClientHost.js +34 -0
- package/dist/cjs/session/sharedDeviceCredential.js +247 -0
- package/dist/cjs/session/socketLoader.js +55 -0
- package/dist/cjs/shared/utils/colorUtils.js +153 -0
- package/dist/cjs/shared/utils/errorUtils.js +183 -0
- package/dist/cjs/shared/utils/index.js +49 -0
- package/dist/cjs/shared/utils/networkUtils.js +183 -0
- package/dist/cjs/shared/utils/themeUtils.js +106 -0
- package/dist/cjs/utils/accountCacheSweep.js +80 -0
- package/dist/cjs/utils/accountUtils.js +140 -0
- package/dist/cjs/utils/activityId.js +6 -0
- package/dist/cjs/utils/apiUtils.js +91 -0
- package/dist/cjs/utils/asyncUtils.js +222 -0
- package/dist/cjs/utils/authHelpers.js +120 -0
- package/dist/cjs/utils/authWebUrl.js +19 -0
- package/dist/cjs/utils/avatarUtils.js +29 -0
- package/dist/cjs/utils/cache.js +235 -0
- package/dist/cjs/utils/cacheKey.js +85 -0
- package/dist/cjs/utils/coldBoot.js +122 -0
- package/dist/cjs/utils/commonsApproval.js +31 -0
- package/dist/cjs/utils/commonsDelivery.js +59 -0
- package/dist/cjs/utils/deviceManager.js +174 -0
- package/dist/cjs/utils/displayNamePolicyRanges.generated.js +60 -0
- package/dist/cjs/utils/edgeRegion.js +6 -0
- package/dist/cjs/utils/errorUtils.js +243 -0
- package/dist/cjs/utils/identityCacheSweep.js +97 -0
- package/dist/cjs/utils/languageUtils.js +224 -0
- package/dist/cjs/utils/oauthPkce.js +311 -0
- package/dist/cjs/utils/officialOrigins.js +64 -0
- package/dist/cjs/utils/oxyServiceEnvironment.js +19 -0
- package/dist/cjs/utils/platform.js +119 -0
- package/dist/cjs/utils/profileLinks.js +63 -0
- package/dist/cjs/utils/redactUrl.js +29 -0
- package/dist/cjs/utils/registrableApex.js +45 -0
- package/dist/cjs/utils/requestUtils.js +209 -0
- package/dist/cjs/utils/sessionUtils.js +181 -0
- package/dist/cjs/utils/textNormalization.js +158 -0
- package/dist/cjs/utils/userHandle.js +37 -0
- package/dist/cjs/utils/userIdentity.js +50 -0
- package/dist/cjs/utils/validationUtils.js +370 -0
- package/dist/cjs/utils/webauthnOrigin.js +51 -0
- package/dist/esm/.tsbuildinfo +1 -0
- package/dist/esm/HttpService.js +1266 -0
- package/dist/esm/OxyServices.base.js +386 -0
- package/dist/esm/OxyServices.errors.js +88 -0
- package/dist/esm/OxyServices.js +66 -0
- package/dist/esm/boot/sessionColdBoot.js +392 -0
- package/dist/esm/constants/version.js +13 -0
- package/dist/esm/crypto/aead.js +74 -0
- package/dist/esm/crypto/ecdh.js +32 -0
- package/dist/esm/crypto/identityMarker.js +248 -0
- package/dist/esm/crypto/kdf.js +36 -0
- package/dist/esm/crypto/keyManager.js +2227 -0
- package/dist/esm/crypto/polyfill.js +129 -0
- package/dist/esm/crypto/recoveryPhrase.js +238 -0
- package/dist/esm/crypto/signatureService.js +269 -0
- package/dist/esm/i18n/accountCategoryLabels.js +37 -0
- package/dist/esm/i18n/accountRoleLabels.js +20 -0
- package/dist/esm/i18n/index.js +83 -0
- package/dist/esm/i18n/locales/ar-SA.json +282 -0
- package/dist/esm/i18n/locales/ca-ES.json +282 -0
- package/dist/esm/i18n/locales/de-DE.json +282 -0
- package/dist/esm/i18n/locales/en-US.json +2161 -0
- package/dist/esm/i18n/locales/es-ES.json +2161 -0
- package/dist/esm/i18n/locales/fr-FR.json +282 -0
- package/dist/esm/i18n/locales/it-IT.json +282 -0
- package/dist/esm/i18n/locales/ja-JP.json +282 -0
- package/dist/esm/i18n/locales/ko-KR.json +282 -0
- package/dist/esm/i18n/locales/locales/ar-SA.json +282 -0
- package/dist/esm/i18n/locales/locales/ca-ES.json +282 -0
- package/dist/esm/i18n/locales/locales/de-DE.json +282 -0
- package/dist/esm/i18n/locales/locales/en-US.json +2161 -0
- package/dist/esm/i18n/locales/locales/es-ES.json +2161 -0
- package/dist/esm/i18n/locales/locales/fr-FR.json +282 -0
- package/dist/esm/i18n/locales/locales/it-IT.json +282 -0
- package/dist/esm/i18n/locales/locales/ja-JP.json +282 -0
- package/dist/esm/i18n/locales/locales/ko-KR.json +282 -0
- package/dist/esm/i18n/locales/locales/pt-PT.json +282 -0
- package/dist/esm/i18n/locales/locales/zh-CN.json +282 -0
- package/dist/esm/i18n/locales/pt-PT.json +282 -0
- package/dist/esm/i18n/locales/zh-CN.json +282 -0
- package/dist/esm/i18n/reputationCategoryLabels.js +13 -0
- package/dist/esm/i18n/trustTierLabels.js +12 -0
- package/dist/esm/index.js +254 -0
- package/dist/esm/inference/OxyInferenceClient.js +538 -0
- package/dist/esm/logger/index.js +140 -0
- package/dist/esm/mixins/OxyServices.accounts.js +543 -0
- package/dist/esm/mixins/OxyServices.analytics.js +46 -0
- package/dist/esm/mixins/OxyServices.appData.js +103 -0
- package/dist/esm/mixins/OxyServices.assets.js +761 -0
- package/dist/esm/mixins/OxyServices.auth.js +1247 -0
- package/dist/esm/mixins/OxyServices.chains.js +70 -0
- package/dist/esm/mixins/OxyServices.civic.js +605 -0
- package/dist/esm/mixins/OxyServices.connectedApps.js +75 -0
- package/dist/esm/mixins/OxyServices.contacts.js +47 -0
- package/dist/esm/mixins/OxyServices.deviceBoot.js +186 -0
- package/dist/esm/mixins/OxyServices.deviceTransfer.js +311 -0
- package/dist/esm/mixins/OxyServices.devices.js +113 -0
- package/dist/esm/mixins/OxyServices.features.js +332 -0
- package/dist/esm/mixins/OxyServices.followGraph.js +218 -0
- package/dist/esm/mixins/OxyServices.identity.js +457 -0
- package/dist/esm/mixins/OxyServices.identityBackup.js +169 -0
- package/dist/esm/mixins/OxyServices.inference.js +56 -0
- package/dist/esm/mixins/OxyServices.language.js +122 -0
- package/dist/esm/mixins/OxyServices.links.js +69 -0
- package/dist/esm/mixins/OxyServices.location.js +40 -0
- package/dist/esm/mixins/OxyServices.nodes.js +172 -0
- package/dist/esm/mixins/OxyServices.notifications.js +60 -0
- package/dist/esm/mixins/OxyServices.payment.js +155 -0
- package/dist/esm/mixins/OxyServices.privacy.js +196 -0
- package/dist/esm/mixins/OxyServices.reputation.js +286 -0
- package/dist/esm/mixins/OxyServices.security.js +86 -0
- package/dist/esm/mixins/OxyServices.store.js +263 -0
- package/dist/esm/mixins/OxyServices.topics.js +134 -0
- package/dist/esm/mixins/OxyServices.user.js +899 -0
- package/dist/esm/mixins/OxyServices.utility.js +1095 -0
- package/dist/esm/mixins/index.js +132 -0
- package/dist/esm/mixins/mixinHelpers.js +48 -0
- package/dist/esm/models/Topic.js +13 -0
- package/dist/esm/models/interfaces.js +17 -0
- package/dist/esm/models/session.js +1 -0
- package/dist/esm/server/auth.js +154 -0
- package/dist/esm/server/capabilityTicket.js +183 -0
- package/dist/esm/server/cors.js +220 -0
- package/dist/esm/server/index.js +47 -0
- package/dist/esm/server/rateLimit.js +201 -0
- package/dist/esm/server/safeFetch.js +447 -0
- package/dist/esm/server/securityHeaders.js +364 -0
- package/dist/esm/server/userInvalidation.js +152 -0
- package/dist/esm/server/verifySecret.js +47 -0
- package/dist/esm/session/SessionClient.js +861 -0
- package/dist/esm/session/accountDelegationAccess.js +45 -0
- package/dist/esm/session/accountDialogController.js +1126 -0
- package/dist/esm/session/accountSwitchTargets.js +77 -0
- package/dist/esm/session/authStateStore.js +398 -0
- package/dist/esm/session/createSessionClient.js +29 -0
- package/dist/esm/session/deviceDirectory.js +135 -0
- package/dist/esm/session/deviceSwitcherRows.js +72 -0
- package/dist/esm/session/identityPin.js +249 -0
- package/dist/esm/session/identitySession.js +131 -0
- package/dist/esm/session/projectSessionState.js +114 -0
- package/dist/esm/session/refresh.js +390 -0
- package/dist/esm/session/sessionClientHost.js +31 -0
- package/dist/esm/session/sharedDeviceCredential.js +239 -0
- package/dist/esm/session/socketLoader.js +19 -0
- package/dist/esm/shared/utils/colorUtils.js +143 -0
- package/dist/esm/shared/utils/errorUtils.js +170 -0
- package/dist/esm/shared/utils/index.js +15 -0
- package/dist/esm/shared/utils/networkUtils.js +173 -0
- package/dist/esm/shared/utils/themeUtils.js +98 -0
- package/dist/esm/utils/accountCacheSweep.js +75 -0
- package/dist/esm/utils/accountUtils.js +131 -0
- package/dist/esm/utils/activityId.js +2 -0
- package/dist/esm/utils/apiUtils.js +84 -0
- package/dist/esm/utils/asyncUtils.js +207 -0
- package/dist/esm/utils/authHelpers.js +111 -0
- package/dist/esm/utils/authWebUrl.js +16 -0
- package/dist/esm/utils/avatarUtils.js +26 -0
- package/dist/esm/utils/cache.js +227 -0
- package/dist/esm/utils/cacheKey.js +80 -0
- package/dist/esm/utils/coldBoot.js +119 -0
- package/dist/esm/utils/commonsApproval.js +27 -0
- package/dist/esm/utils/commonsDelivery.js +54 -0
- package/dist/esm/utils/deviceManager.js +170 -0
- package/dist/esm/utils/displayNamePolicyRanges.generated.js +57 -0
- package/dist/esm/utils/edgeRegion.js +2 -0
- package/dist/esm/utils/errorUtils.js +232 -0
- package/dist/esm/utils/identityCacheSweep.js +92 -0
- package/dist/esm/utils/languageUtils.js +212 -0
- package/dist/esm/utils/oauthPkce.js +297 -0
- package/dist/esm/utils/officialOrigins.js +59 -0
- package/dist/esm/utils/oxyServiceEnvironment.js +16 -0
- package/dist/esm/utils/platform.js +110 -0
- package/dist/esm/utils/profileLinks.js +60 -0
- package/dist/esm/utils/redactUrl.js +26 -0
- package/dist/esm/utils/registrableApex.js +42 -0
- package/dist/esm/utils/requestUtils.js +203 -0
- package/dist/esm/utils/sessionUtils.js +171 -0
- package/dist/esm/utils/textNormalization.js +154 -0
- package/dist/esm/utils/userHandle.js +33 -0
- package/dist/esm/utils/userIdentity.js +45 -0
- package/dist/esm/utils/validationUtils.js +350 -0
- package/dist/esm/utils/webauthnOrigin.js +48 -0
- package/dist/types/.tsbuildinfo +1 -0
- package/dist/types/HttpService.d.ts +413 -0
- package/dist/types/OxyServices.base.d.ts +187 -0
- package/dist/types/OxyServices.d.ts +139 -0
- package/dist/types/OxyServices.errors.d.ts +84 -0
- package/dist/types/boot/sessionColdBoot.d.ts +140 -0
- package/dist/types/constants/version.d.ts +13 -0
- package/dist/types/crypto/aead.d.ts +56 -0
- package/dist/types/crypto/ecdh.d.ts +29 -0
- package/dist/types/crypto/identityMarker.d.ts +94 -0
- package/dist/types/crypto/kdf.d.ts +25 -0
- package/dist/types/crypto/keyManager.d.ts +582 -0
- package/dist/types/crypto/polyfill.d.ts +25 -0
- package/dist/types/crypto/recoveryPhrase.d.ts +173 -0
- package/dist/types/crypto/signatureService.d.ts +136 -0
- package/dist/types/i18n/accountCategoryLabels.d.ts +34 -0
- package/dist/types/i18n/accountRoleLabels.d.ts +10 -0
- package/dist/types/i18n/index.d.ts +3 -0
- package/dist/types/i18n/reputationCategoryLabels.d.ts +10 -0
- package/dist/types/i18n/trustTierLabels.d.ts +9 -0
- package/dist/types/index.d.ts +145 -0
- package/dist/types/inference/OxyInferenceClient.d.ts +342 -0
- package/dist/types/logger/index.d.ts +104 -0
- package/dist/types/mixins/OxyServices.accounts.d.ts +868 -0
- package/dist/types/mixins/OxyServices.analytics.d.ts +72 -0
- package/dist/types/mixins/OxyServices.appData.d.ts +108 -0
- package/dist/types/mixins/OxyServices.assets.d.ts +329 -0
- package/dist/types/mixins/OxyServices.auth.d.ts +908 -0
- package/dist/types/mixins/OxyServices.chains.d.ts +156 -0
- package/dist/types/mixins/OxyServices.civic.d.ts +510 -0
- package/dist/types/mixins/OxyServices.connectedApps.d.ts +169 -0
- package/dist/types/mixins/OxyServices.contacts.d.ts +100 -0
- package/dist/types/mixins/OxyServices.deviceBoot.d.ts +185 -0
- package/dist/types/mixins/OxyServices.deviceTransfer.d.ts +149 -0
- package/dist/types/mixins/OxyServices.devices.d.ts +103 -0
- package/dist/types/mixins/OxyServices.features.d.ts +250 -0
- package/dist/types/mixins/OxyServices.followGraph.d.ts +223 -0
- package/dist/types/mixins/OxyServices.identity.d.ts +351 -0
- package/dist/types/mixins/OxyServices.identityBackup.d.ts +129 -0
- package/dist/types/mixins/OxyServices.inference.d.ts +95 -0
- package/dist/types/mixins/OxyServices.language.d.ts +87 -0
- package/dist/types/mixins/OxyServices.links.d.ts +104 -0
- package/dist/types/mixins/OxyServices.location.d.ts +70 -0
- package/dist/types/mixins/OxyServices.nodes.d.ts +198 -0
- package/dist/types/mixins/OxyServices.notifications.d.ts +143 -0
- package/dist/types/mixins/OxyServices.payment.d.ts +117 -0
- package/dist/types/mixins/OxyServices.privacy.d.ts +146 -0
- package/dist/types/mixins/OxyServices.reputation.d.ts +202 -0
- package/dist/types/mixins/OxyServices.security.d.ts +84 -0
- package/dist/types/mixins/OxyServices.store.d.ts +334 -0
- package/dist/types/mixins/OxyServices.topics.d.ts +110 -0
- package/dist/types/mixins/OxyServices.user.d.ts +558 -0
- package/dist/types/mixins/OxyServices.utility.d.ts +393 -0
- package/dist/types/mixins/index.d.ts +87 -0
- package/dist/types/mixins/mixinHelpers.d.ts +31 -0
- package/dist/types/models/Topic.d.ts +42 -0
- package/dist/types/models/interfaces.d.ts +675 -0
- package/dist/types/models/session.d.ts +51 -0
- package/dist/types/server/auth.d.ts +130 -0
- package/dist/types/server/capabilityTicket.d.ts +41 -0
- package/dist/types/server/cors.d.ts +98 -0
- package/dist/types/server/index.d.ts +35 -0
- package/dist/types/server/rateLimit.d.ts +40 -0
- package/dist/types/server/safeFetch.d.ts +137 -0
- package/dist/types/server/securityHeaders.d.ts +221 -0
- package/dist/types/server/userInvalidation.d.ts +114 -0
- package/dist/types/server/verifySecret.d.ts +29 -0
- package/dist/types/session/SessionClient.d.ts +418 -0
- package/dist/types/session/accountDelegationAccess.d.ts +40 -0
- package/dist/types/session/accountDialogController.d.ts +648 -0
- package/dist/types/session/accountSwitchTargets.d.ts +70 -0
- package/dist/types/session/authStateStore.d.ts +153 -0
- package/dist/types/session/createSessionClient.d.ts +30 -0
- package/dist/types/session/deviceDirectory.d.ts +182 -0
- package/dist/types/session/deviceSwitcherRows.d.ts +92 -0
- package/dist/types/session/identityPin.d.ts +87 -0
- package/dist/types/session/identitySession.d.ts +105 -0
- package/dist/types/session/projectSessionState.d.ts +74 -0
- package/dist/types/session/refresh.d.ts +179 -0
- package/dist/types/session/sessionClientHost.d.ts +18 -0
- package/dist/types/session/sharedDeviceCredential.d.ts +202 -0
- package/dist/types/session/socketLoader.d.ts +11 -0
- package/dist/types/shared/utils/colorUtils.d.ts +104 -0
- package/dist/types/shared/utils/errorUtils.d.ts +97 -0
- package/dist/types/shared/utils/index.d.ts +13 -0
- package/dist/types/shared/utils/networkUtils.d.ts +139 -0
- package/dist/types/shared/utils/themeUtils.d.ts +90 -0
- package/dist/types/utils/accountCacheSweep.d.ts +75 -0
- package/dist/types/utils/accountUtils.d.ts +100 -0
- package/dist/types/utils/activityId.d.ts +2 -0
- package/dist/types/utils/apiUtils.d.ts +95 -0
- package/dist/types/utils/asyncUtils.d.ts +62 -0
- package/dist/types/utils/authHelpers.d.ts +58 -0
- package/dist/types/utils/authWebUrl.d.ts +16 -0
- package/dist/types/utils/avatarUtils.d.ts +16 -0
- package/dist/types/utils/cache.d.ts +130 -0
- package/dist/types/utils/cacheKey.d.ts +66 -0
- package/dist/types/utils/coldBoot.d.ts +131 -0
- package/dist/types/utils/commonsApproval.d.ts +13 -0
- package/dist/types/utils/commonsDelivery.d.ts +105 -0
- package/dist/types/utils/deviceManager.d.ts +65 -0
- package/dist/types/utils/displayNamePolicyRanges.generated.d.ts +57 -0
- package/dist/types/utils/edgeRegion.d.ts +2 -0
- package/dist/types/utils/errorUtils.d.ts +125 -0
- package/dist/types/utils/identityCacheSweep.d.ts +80 -0
- package/dist/types/utils/languageUtils.d.ts +100 -0
- package/dist/types/utils/oauthPkce.d.ts +157 -0
- package/dist/types/utils/officialOrigins.d.ts +13 -0
- package/dist/types/utils/oxyServiceEnvironment.d.ts +17 -0
- package/dist/types/utils/platform.d.ts +49 -0
- package/dist/types/utils/profileLinks.d.ts +44 -0
- package/dist/types/utils/redactUrl.d.ts +17 -0
- package/dist/types/utils/registrableApex.d.ts +27 -0
- package/dist/types/utils/requestUtils.d.ts +123 -0
- package/dist/types/utils/sessionUtils.d.ts +54 -0
- package/dist/types/utils/textNormalization.d.ts +103 -0
- package/dist/types/utils/userHandle.d.ts +26 -0
- package/dist/types/utils/userIdentity.d.ts +21 -0
- package/dist/types/utils/validationUtils.d.ts +268 -0
- package/dist/types/utils/webauthnOrigin.d.ts +32 -0
- package/package.json +168 -0
- package/src/HttpService.ts +1553 -0
- package/src/OxyServices.base.ts +478 -0
- package/src/OxyServices.errors.ts +122 -0
- package/src/OxyServices.ts +172 -0
- package/src/__tests__/authSocket.test.ts +96 -0
- package/src/__tests__/httpServiceActivityId.test.ts +49 -0
- package/src/__tests__/httpServiceAuthSelfAwait.test.ts +108 -0
- package/src/__tests__/httpServiceCache.test.ts +318 -0
- package/src/__tests__/httpServiceCsrf.test.ts +235 -0
- package/src/__tests__/httpServiceFormEncoded.test.ts +142 -0
- package/src/__tests__/httpServiceQueueDeadlock.test.ts +128 -0
- package/src/__tests__/httpServiceUnwrapEnvelope.test.ts +115 -0
- package/src/__tests__/inSessionRefresh.test.ts +260 -0
- package/src/__tests__/linkedClient.test.ts +370 -0
- package/src/__tests__/parseHttpErrorBody.test.ts +116 -0
- package/src/__tests__/serverValueImportsDeclared.test.ts +120 -0
- package/src/__tests__/userIdentity.test.ts +143 -0
- package/src/boot/__tests__/sessionColdBoot.identity.test.ts +393 -0
- package/src/boot/__tests__/sessionColdBoot.sharedDevice.test.ts +325 -0
- package/src/boot/__tests__/sessionColdBoot.test.ts +570 -0
- package/src/boot/sessionColdBoot.ts +529 -0
- package/src/constants/version.ts +15 -0
- package/src/crypto/__tests__/backupMaterial.test.ts +86 -0
- package/src/crypto/__tests__/cryptoPrimitives.test.ts +226 -0
- package/src/crypto/__tests__/identityMocks.ts +125 -0
- package/src/crypto/__tests__/keyManager.atomicity.test.ts +272 -0
- package/src/crypto/__tests__/keyManager.cacheSafety.test.ts +175 -0
- package/src/crypto/__tests__/keyManager.identityStatus.test.ts +217 -0
- package/src/crypto/__tests__/keyManager.recoveryLadder.test.ts +179 -0
- package/src/crypto/__tests__/keyManager.recoveryMnemonic.test.ts +138 -0
- package/src/crypto/__tests__/keyManager.storageMigration.test.ts +227 -0
- package/src/crypto/__tests__/keyManager.test.ts +329 -0
- package/src/crypto/__tests__/polyfill.test.ts +109 -0
- package/src/crypto/__tests__/recoveryPhrase.test.ts +61 -0
- package/src/crypto/__tests__/scopedSeed.test.ts +126 -0
- package/src/crypto/__tests__/signChallengeShared.test.ts +63 -0
- package/src/crypto/__tests__/signedRecord.test.ts +230 -0
- package/src/crypto/aead.ts +97 -0
- package/src/crypto/ecdh.ts +37 -0
- package/src/crypto/identityMarker.ts +291 -0
- package/src/crypto/kdf.ts +43 -0
- package/src/crypto/keyManager.ts +2607 -0
- package/src/crypto/polyfill.ts +143 -0
- package/src/crypto/recoveryPhrase.ts +337 -0
- package/src/crypto/signatureService.ts +350 -0
- package/src/i18n/__tests__/accountCategoryLabels.test.ts +62 -0
- package/src/i18n/__tests__/accountRoleLabels.test.ts +54 -0
- package/src/i18n/__tests__/reputationCategoryLabels.test.ts +56 -0
- package/src/i18n/__tests__/trustTierLabels.test.ts +47 -0
- package/src/i18n/accountCategoryLabels.ts +44 -0
- package/src/i18n/accountRoleLabels.ts +26 -0
- package/src/i18n/index.ts +88 -0
- package/src/i18n/locales/ar-SA.json +282 -0
- package/src/i18n/locales/ca-ES.json +282 -0
- package/src/i18n/locales/de-DE.json +282 -0
- package/src/i18n/locales/en-US.json +2161 -0
- package/src/i18n/locales/es-ES.json +2161 -0
- package/src/i18n/locales/fr-FR.json +282 -0
- package/src/i18n/locales/it-IT.json +282 -0
- package/src/i18n/locales/ja-JP.json +282 -0
- package/src/i18n/locales/ko-KR.json +282 -0
- package/src/i18n/locales/pt-PT.json +282 -0
- package/src/i18n/locales/zh-CN.json +282 -0
- package/src/i18n/reputationCategoryLabels.ts +20 -0
- package/src/i18n/trustTierLabels.ts +18 -0
- package/src/index.ts +881 -0
- package/src/inference/OxyInferenceClient.ts +888 -0
- package/src/inference/__tests__/OxyInferenceClient.test.ts +834 -0
- package/src/logger/__tests__/logger.test.ts +207 -0
- package/src/logger/index.ts +217 -0
- package/src/mixins/OxyServices.accounts.ts +1330 -0
- package/src/mixins/OxyServices.analytics.ts +53 -0
- package/src/mixins/OxyServices.appData.ts +158 -0
- package/src/mixins/OxyServices.assets.ts +861 -0
- package/src/mixins/OxyServices.auth.ts +1858 -0
- package/src/mixins/OxyServices.chains.ts +134 -0
- package/src/mixins/OxyServices.civic.ts +945 -0
- package/src/mixins/OxyServices.connectedApps.ts +174 -0
- package/src/mixins/OxyServices.contacts.ts +73 -0
- package/src/mixins/OxyServices.deviceBoot.ts +210 -0
- package/src/mixins/OxyServices.deviceTransfer.ts +393 -0
- package/src/mixins/OxyServices.devices.ts +120 -0
- package/src/mixins/OxyServices.features.ts +454 -0
- package/src/mixins/OxyServices.followGraph.ts +293 -0
- package/src/mixins/OxyServices.identity.ts +705 -0
- package/src/mixins/OxyServices.identityBackup.ts +250 -0
- package/src/mixins/OxyServices.inference.ts +57 -0
- package/src/mixins/OxyServices.language.ts +144 -0
- package/src/mixins/OxyServices.links.ts +107 -0
- package/src/mixins/OxyServices.location.ts +46 -0
- package/src/mixins/OxyServices.nodes.ts +337 -0
- package/src/mixins/OxyServices.notifications.ts +142 -0
- package/src/mixins/OxyServices.payment.ts +163 -0
- package/src/mixins/OxyServices.privacy.ts +219 -0
- package/src/mixins/OxyServices.reputation.ts +436 -0
- package/src/mixins/OxyServices.security.ts +110 -0
- package/src/mixins/OxyServices.store.ts +585 -0
- package/src/mixins/OxyServices.topics.ts +169 -0
- package/src/mixins/OxyServices.user.ts +1137 -0
- package/src/mixins/OxyServices.utility.ts +1370 -0
- package/src/mixins/__tests__/OxyServices.civic.test.ts +1095 -0
- package/src/mixins/__tests__/OxyServices.deviceBoot.test.ts +124 -0
- package/src/mixins/__tests__/OxyServices.deviceTransfer.test.ts +271 -0
- package/src/mixins/__tests__/OxyServices.identity.test.ts +376 -0
- package/src/mixins/__tests__/OxyServices.links.test.ts +154 -0
- package/src/mixins/__tests__/OxyServices.nodes.test.ts +341 -0
- package/src/mixins/__tests__/OxyServices.rotateKey.test.ts +276 -0
- package/src/mixins/__tests__/OxyServices.serviceAssetMetadata.test.ts +192 -0
- package/src/mixins/__tests__/OxyServices.serviceAssetMetadataBySha.test.ts +135 -0
- package/src/mixins/__tests__/accounts.test.ts +727 -0
- package/src/mixins/__tests__/appData.test.ts +203 -0
- package/src/mixins/__tests__/assetCredentials.test.ts +47 -0
- package/src/mixins/__tests__/assetUpload.test.ts +191 -0
- package/src/mixins/__tests__/backgroundCredential.httpIntegration.test.ts +135 -0
- package/src/mixins/__tests__/chains.test.ts +113 -0
- package/src/mixins/__tests__/commonsSignIn.test.ts +1144 -0
- package/src/mixins/__tests__/connectedApps.test.ts +123 -0
- package/src/mixins/__tests__/deviceTokenMintPinned.test.ts +113 -0
- package/src/mixins/__tests__/discoveryErrorHandling.test.ts +266 -0
- package/src/mixins/__tests__/followCacheInvalidation.test.ts +173 -0
- package/src/mixins/__tests__/followGraph.test.ts +147 -0
- package/src/mixins/__tests__/followGraphPagination.test.ts +271 -0
- package/src/mixins/__tests__/getFileDownloadUrl.test.ts +346 -0
- package/src/mixins/__tests__/getFollowStatuses.test.ts +95 -0
- package/src/mixins/__tests__/getUsersByIds.test.ts +149 -0
- package/src/mixins/__tests__/identityBackup.test.ts +315 -0
- package/src/mixins/__tests__/identityWriteCacheInvalidation.test.ts +407 -0
- package/src/mixins/__tests__/inferenceFactory.test.ts +58 -0
- package/src/mixins/__tests__/onTokensChanged.test.ts +129 -0
- package/src/mixins/__tests__/preSessionSkipAuth.test.ts +284 -0
- package/src/mixins/__tests__/privacyCacheInvalidation.test.ts +155 -0
- package/src/mixins/__tests__/reputation.test.ts +522 -0
- package/src/mixins/__tests__/serviceAuth.test.ts +832 -0
- package/src/mixins/__tests__/serviceTokenJwks.test.ts +208 -0
- package/src/mixins/__tests__/store.test.ts +304 -0
- package/src/mixins/__tests__/topics.test.ts +156 -0
- package/src/mixins/__tests__/userReadCacheBypass.test.ts +129 -0
- package/src/mixins/__tests__/userTokenAuth.test.ts +746 -0
- package/src/mixins/__tests__/verifyChallenge.test.ts +130 -0
- package/src/mixins/__tests__/verifyServiceActingAs.test.ts +167 -0
- package/src/mixins/__tests__/webauthnAuth.test.ts +205 -0
- package/src/mixins/index.ts +201 -0
- package/src/mixins/mixinHelpers.ts +69 -0
- package/src/models/Topic.ts +46 -0
- package/src/models/interfaces.ts +786 -0
- package/src/models/session.ts +55 -0
- package/src/server/__tests__/auth.test.ts +78 -0
- package/src/server/__tests__/capabilityTicket.test.ts +111 -0
- package/src/server/__tests__/cors.socket.test.ts +225 -0
- package/src/server/__tests__/cors.test.ts +158 -0
- package/src/server/__tests__/rateLimit.test.ts +257 -0
- package/src/server/__tests__/safeFetch.test.ts +232 -0
- package/src/server/__tests__/securityHeaders.test.ts +348 -0
- package/src/server/__tests__/serviceTokenAttribution.test.ts +396 -0
- package/src/server/__tests__/userInvalidation.test.ts +203 -0
- package/src/server/__tests__/verifySecret.test.ts +40 -0
- package/src/server/auth.ts +271 -0
- package/src/server/capabilityTicket.ts +258 -0
- package/src/server/cors.ts +277 -0
- package/src/server/index.ts +136 -0
- package/src/server/rateLimit.ts +313 -0
- package/src/server/safeFetch.ts +586 -0
- package/src/server/securityHeaders.ts +467 -0
- package/src/server/userInvalidation.ts +199 -0
- package/src/server/verifySecret.ts +52 -0
- package/src/session/SessionClient.ts +1001 -0
- package/src/session/__tests__/SessionClient.additive.test.ts +153 -0
- package/src/session/__tests__/SessionClient.broadcastChannel.test.ts +114 -0
- package/src/session/__tests__/SessionClient.diagnostics.test.ts +91 -0
- package/src/session/__tests__/SessionClient.directory.test.ts +688 -0
- package/src/session/__tests__/SessionClient.httpIntegration.test.ts +65 -0
- package/src/session/__tests__/SessionClient.identityPin.test.ts +175 -0
- package/src/session/__tests__/SessionClient.rest.test.ts +119 -0
- package/src/session/__tests__/SessionClient.serverEvents.test.ts +72 -0
- package/src/session/__tests__/SessionClient.socket.test.ts +202 -0
- package/src/session/__tests__/SessionClient.socketFactory.test.ts +81 -0
- package/src/session/__tests__/SessionClient.state.test.ts +78 -0
- package/src/session/__tests__/SessionClient.switchTokenOrder.test.ts +170 -0
- package/src/session/__tests__/accountDelegationAccess.test.ts +104 -0
- package/src/session/__tests__/accountDialogController.test.ts +1969 -0
- package/src/session/__tests__/accountDialogShape.test.ts +118 -0
- package/src/session/__tests__/accountSwitchTargets.test.ts +137 -0
- package/src/session/__tests__/authStateStore.test.ts +451 -0
- package/src/session/__tests__/deviceDirectory.test.ts +422 -0
- package/src/session/__tests__/deviceSwitcherRows.test.ts +223 -0
- package/src/session/__tests__/identityPin.test.ts +131 -0
- package/src/session/__tests__/identitySession.test.ts +194 -0
- package/src/session/__tests__/projectSessionState.test.ts +105 -0
- package/src/session/__tests__/refresh.identityPin.test.ts +307 -0
- package/src/session/__tests__/refresh.test.ts +443 -0
- package/src/session/__tests__/sessionIntegration.test.ts +209 -0
- package/src/session/__tests__/sharedDeviceCredential.test.ts +300 -0
- package/src/session/accountDelegationAccess.ts +72 -0
- package/src/session/accountDialogController.ts +1494 -0
- package/src/session/accountSwitchTargets.ts +93 -0
- package/src/session/authStateStore.ts +502 -0
- package/src/session/createSessionClient.ts +39 -0
- package/src/session/deviceDirectory.ts +269 -0
- package/src/session/deviceSwitcherRows.ts +145 -0
- package/src/session/identityPin.ts +310 -0
- package/src/session/identitySession.ts +206 -0
- package/src/session/projectSessionState.ts +137 -0
- package/src/session/refresh.ts +517 -0
- package/src/session/sessionClientHost.ts +39 -0
- package/src/session/sharedDeviceCredential.ts +349 -0
- package/src/session/socketLoader.ts +30 -0
- package/src/shared/utils/colorUtils.ts +155 -0
- package/src/shared/utils/errorUtils.ts +181 -0
- package/src/shared/utils/index.ts +59 -0
- package/src/shared/utils/networkUtils.ts +248 -0
- package/src/shared/utils/themeUtils.ts +115 -0
- package/src/types/buffer.d.ts +97 -0
- package/src/types/expo-crypto.d.ts +16 -0
- package/src/types/expo-secure-store.d.ts +17 -0
- package/src/utils/__tests__/accountUtils.test.ts +151 -0
- package/src/utils/__tests__/activityId.test.ts +45 -0
- package/src/utils/__tests__/asyncUtils.test.ts +187 -0
- package/src/utils/__tests__/authWebUrl.test.ts +15 -0
- package/src/utils/__tests__/cacheKey.test.ts +0 -0
- package/src/utils/__tests__/coldBoot.test.ts +496 -0
- package/src/utils/__tests__/commonsApproval.test.ts +60 -0
- package/src/utils/__tests__/identityCacheSweep.test.ts +151 -0
- package/src/utils/__tests__/languageUtils.test.ts +219 -0
- package/src/utils/__tests__/oauthPkce.test.ts +272 -0
- package/src/utils/__tests__/officialOrigins.test.ts +31 -0
- package/src/utils/__tests__/oxyServiceEnvironment.test.ts +7 -0
- package/src/utils/__tests__/profileLinks.test.ts +180 -0
- package/src/utils/__tests__/redactUrl.test.ts +33 -0
- package/src/utils/__tests__/registrableApex.test.ts +62 -0
- package/src/utils/__tests__/textNormalization.test.ts +205 -0
- package/src/utils/__tests__/validationUtils.test.ts +703 -0
- package/src/utils/__tests__/webauthnOrigin.test.ts +83 -0
- package/src/utils/accountCacheSweep.ts +93 -0
- package/src/utils/accountUtils.ts +194 -0
- package/src/utils/activityId.ts +2 -0
- package/src/utils/apiUtils.ts +137 -0
- package/src/utils/asyncUtils.ts +280 -0
- package/src/utils/authHelpers.ts +148 -0
- package/src/utils/authWebUrl.ts +17 -0
- package/src/utils/avatarUtils.ts +39 -0
- package/src/utils/cache.ts +273 -0
- package/src/utils/cacheKey.ts +93 -0
- package/src/utils/coldBoot.ts +218 -0
- package/src/utils/commonsApproval.ts +39 -0
- package/src/utils/commonsDelivery.ts +132 -0
- package/src/utils/deviceManager.ts +203 -0
- package/src/utils/displayNamePolicyRanges.generated.ts +69 -0
- package/src/utils/edgeRegion.ts +2 -0
- package/src/utils/errorUtils.ts +352 -0
- package/src/utils/identityCacheSweep.ts +104 -0
- package/src/utils/languageUtils.ts +256 -0
- package/src/utils/oauthPkce.ts +392 -0
- package/src/utils/officialOrigins.ts +62 -0
- package/src/utils/oxyServiceEnvironment.ts +17 -0
- package/src/utils/platform.ts +139 -0
- package/src/utils/profileLinks.ts +91 -0
- package/src/utils/redactUrl.ts +28 -0
- package/src/utils/registrableApex.ts +41 -0
- package/src/utils/requestUtils.ts +237 -0
- package/src/utils/sessionUtils.ts +206 -0
- package/src/utils/textNormalization.ts +162 -0
- package/src/utils/userHandle.ts +49 -0
- package/src/utils/userIdentity.ts +60 -0
- package/src/utils/validationUtils.ts +390 -0
- package/src/utils/webauthnOrigin.ts +52 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Identity-bound session — pin reconciliation + establishment.
|
|
3
|
+
*
|
|
4
|
+
* This is the SDK half of "an identity vault's authenticated user is whoever
|
|
5
|
+
* owns the local primary key". Two operations, both consumed by the cold boot
|
|
6
|
+
* (`boot/sessionColdBoot.ts`) and the re-mint lane (`session/refresh.ts`):
|
|
7
|
+
*
|
|
8
|
+
* - {@link resolveIdentityPin} — read the persisted `{publicKey, accountId}`
|
|
9
|
+
* pin and reconcile it against the identity currently on this device. A
|
|
10
|
+
* definitive mismatch (the key was replaced, or is gone) CLEARS the pin; an
|
|
11
|
+
* INDETERMINATE read (keychain locked / storage threw) leaves it untouched.
|
|
12
|
+
* - {@link establishIdentitySession} — mint a session from the PRIMARY local
|
|
13
|
+
* key (`getPublicKey` → `requestChallenge` → `signChallenge` →
|
|
14
|
+
* `verifyChallenge`), persist the resulting device credential, and write the
|
|
15
|
+
* pin. This is the identity-mode replacement for the shared-keychain lane,
|
|
16
|
+
* which reads the CROSS-APP shared slot and may therefore hold a different
|
|
17
|
+
* identity than this device's primary.
|
|
18
|
+
*
|
|
19
|
+
* Both take their key/signature functions from an injectable {@link IdentityBinding}
|
|
20
|
+
* (defaulting to `KeyManager` / `SignatureService`) so the lanes above stay
|
|
21
|
+
* testable without a keychain.
|
|
22
|
+
*
|
|
23
|
+
* ESM-safe (no `require()`); no react/react-native/expo imports.
|
|
24
|
+
*/
|
|
25
|
+
import type { OxyServices } from '../OxyServices';
|
|
26
|
+
import type { AuthStateStore } from './authStateStore';
|
|
27
|
+
import type { SessionLoginResponse } from '../models/session';
|
|
28
|
+
import { type AuthChallenge } from '../crypto/signatureService';
|
|
29
|
+
import { type IdentityPin, type IdentityPinStore } from './identityPin';
|
|
30
|
+
/** Per-call transport overrides forwarded to the challenge/verify round-trips. */
|
|
31
|
+
export interface IdentityRequestOptions {
|
|
32
|
+
retry?: boolean;
|
|
33
|
+
timeout?: number;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Everything an identity-bound client needs to resolve and re-establish its
|
|
37
|
+
* session. `@oxy.so/services` builds one of these (platform-appropriate pin
|
|
38
|
+
* store) and passes it to the cold boot and the refresh handler.
|
|
39
|
+
*/
|
|
40
|
+
export interface IdentityBinding {
|
|
41
|
+
/** Where the `{publicKey, accountId}` pin is persisted. */
|
|
42
|
+
pinStore: IdentityPinStore;
|
|
43
|
+
/**
|
|
44
|
+
* Reads this device's PRIMARY identity public key. Defaults to
|
|
45
|
+
* `KeyManager.getPublicKey()`. NEVER the shared-slot key.
|
|
46
|
+
*/
|
|
47
|
+
readPublicKey?: () => Promise<string | null>;
|
|
48
|
+
/**
|
|
49
|
+
* Signs a server challenge with the PRIMARY local private key. Defaults to
|
|
50
|
+
* `SignatureService.signChallenge`.
|
|
51
|
+
*/
|
|
52
|
+
signChallenge?: (challenge: string) => Promise<AuthChallenge>;
|
|
53
|
+
/** Optional device labels forwarded to `verifyChallenge`. */
|
|
54
|
+
deviceName?: string;
|
|
55
|
+
deviceFingerprint?: string;
|
|
56
|
+
}
|
|
57
|
+
/** The result of a successful {@link establishIdentitySession}. */
|
|
58
|
+
export interface EstablishedIdentitySession {
|
|
59
|
+
session: SessionLoginResponse;
|
|
60
|
+
/** The pin as written: the local key plus the account the server resolved for it. */
|
|
61
|
+
pin: IdentityPin;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Read the persisted pin and reconcile it against the identity on this device.
|
|
65
|
+
*
|
|
66
|
+
* Returns the pin ONLY when the local primary public key still matches it — that
|
|
67
|
+
* is the single condition under which a client may bind its token and its
|
|
68
|
+
* rendered user to that account.
|
|
69
|
+
*
|
|
70
|
+
* Outcomes:
|
|
71
|
+
* - no pin stored → `null` (nothing to clear).
|
|
72
|
+
* - local key MATCHES → the pin (trusted).
|
|
73
|
+
* - local key read succeeded and differs / is absent → the identity was
|
|
74
|
+
* replaced or lost: CLEAR the pin and return `null`. Keeping it would pin the
|
|
75
|
+
* client to an account it can no longer prove control of.
|
|
76
|
+
* - the local key read THREW (keychain locked, storage unavailable) → return
|
|
77
|
+
* `null` WITHOUT clearing. A read that produced no verdict is never evidence
|
|
78
|
+
* of an identity change (the same rule `KeyManager` applies to its own
|
|
79
|
+
* transient errors); the caller falls through to the identity sign-in lane,
|
|
80
|
+
* which fails closed on a locked keychain rather than adopting a foreign
|
|
81
|
+
* account.
|
|
82
|
+
*/
|
|
83
|
+
export declare function resolveIdentityPin(binding: IdentityBinding): Promise<IdentityPin | null>;
|
|
84
|
+
/**
|
|
85
|
+
* Establish a session for the device's PRIMARY identity key and pin it.
|
|
86
|
+
*
|
|
87
|
+
* `requestChallenge` → `signChallenge` → `verifyChallenge`; `verifyChallenge`
|
|
88
|
+
* plants the access token itself. The server resolves the account from the
|
|
89
|
+
* VERIFIED SIGNER, so the returned session is identity-authoritative — it
|
|
90
|
+
* ignores the device's `activeAccountId` entirely.
|
|
91
|
+
*
|
|
92
|
+
* Side effects on success: the durable device credential is persisted (so the
|
|
93
|
+
* next boot can take the fast pinned-mint lane) and the pin is written.
|
|
94
|
+
*
|
|
95
|
+
* Returns `null` — never throws — for the two "nothing to do" cases: no local
|
|
96
|
+
* identity (including every web caller, where `KeyManager` has no key), and a
|
|
97
|
+
* verify that produced no access token. Network/crypto failures propagate so the
|
|
98
|
+
* caller can classify them.
|
|
99
|
+
*/
|
|
100
|
+
export declare function establishIdentitySession(args: {
|
|
101
|
+
oxy: OxyServices;
|
|
102
|
+
store: AuthStateStore;
|
|
103
|
+
binding: IdentityBinding;
|
|
104
|
+
requestOptions?: IdentityRequestOptions;
|
|
105
|
+
}): Promise<EstablishedIdentitySession | null>;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { DeviceSessionState } from '@oxy.so/contracts';
|
|
2
|
+
import type { ClientSession } from '../models/session';
|
|
3
|
+
import type { User } from '../models/interfaces';
|
|
4
|
+
/**
|
|
5
|
+
* Pure projection helpers: `DeviceSessionState` (the device-scoped
|
|
6
|
+
* multi-account session-sync state produced by `SessionClient`) -> the
|
|
7
|
+
* shapes `@oxy.so/services` consumers render today
|
|
8
|
+
* (`ClientSession[]`, an active session id, an active `User`).
|
|
9
|
+
*
|
|
10
|
+
* No I/O. The caller fetches profiles via
|
|
11
|
+
* `oxyServices.getUsersByIds(accountIdsOf(state))` and builds `usersById`
|
|
12
|
+
* from the result before calling `deviceStateToClientSessions` /
|
|
13
|
+
* `activeUserOf`.
|
|
14
|
+
*
|
|
15
|
+
* Each projection takes an OPTIONAL `pinnedAccountId`. Omit it (or pass `null`)
|
|
16
|
+
* and the projection resolves the device's `activeAccountId` exactly as before.
|
|
17
|
+
* Pass it — an IDENTITY-BOUND client, whose user is fixed by the local identity
|
|
18
|
+
* key — and the projection resolves THAT account instead, so an account switch
|
|
19
|
+
* made by another app on the same device changes `state` but never the user this
|
|
20
|
+
* client renders.
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* The account a projection should resolve: the pin when one is supplied and
|
|
24
|
+
* non-empty, else the device's active account. An empty-string pin is treated as
|
|
25
|
+
* "not pinned" rather than as an account that can never match.
|
|
26
|
+
*
|
|
27
|
+
* Exported so no other projection over the same state answers it a second,
|
|
28
|
+
* subtly different way. A null state with
|
|
29
|
+
* a pin still resolves to the pin: the pinned identity is bound by a local key,
|
|
30
|
+
* not by device membership.
|
|
31
|
+
*/
|
|
32
|
+
export declare function boundAccountIdOf(state: DeviceSessionState | null, pinnedAccountId?: string | null): string | null;
|
|
33
|
+
/**
|
|
34
|
+
* Maps every `SessionAccount` in `state.accounts` to a `ClientSession`.
|
|
35
|
+
*
|
|
36
|
+
* `DeviceSessionState` carries no per-account `expiresAt` / `lastActive` —
|
|
37
|
+
* both are set to `state.updatedAt` (converted to an ISO-8601 string; the
|
|
38
|
+
* wire value is an epoch-ms number) as a provisional value.
|
|
39
|
+
*
|
|
40
|
+
* `usersById` is accepted for signature symmetry with `activeUserOf` even
|
|
41
|
+
* though `ClientSession` only stores `userId` — a session is still
|
|
42
|
+
* projected for an account whose id is absent from `usersById` (no
|
|
43
|
+
* placeholder user is fabricated).
|
|
44
|
+
*
|
|
45
|
+
* `isCurrent` marks the PINNED account when one is supplied, so it can never
|
|
46
|
+
* disagree with {@link activeSessionIdOf} / {@link activeUserOf} for the same
|
|
47
|
+
* pin.
|
|
48
|
+
*/
|
|
49
|
+
export declare function deviceStateToClientSessions(state: DeviceSessionState, usersById: Map<string, User>, pinnedAccountId?: string | null): ClientSession[];
|
|
50
|
+
/**
|
|
51
|
+
* The bound account's `sessionId`, or `null` when there is no state, no bound
|
|
52
|
+
* account, or that account has no session on this device.
|
|
53
|
+
*
|
|
54
|
+
* A pinned account that is ABSENT from `state.accounts` yields `null` — the
|
|
55
|
+
* honest signal that this device no longer carries a session for the pinned
|
|
56
|
+
* identity, which the caller answers by re-establishing the identity session
|
|
57
|
+
* (never by adopting the device's active account).
|
|
58
|
+
*/
|
|
59
|
+
export declare function activeSessionIdOf(state: DeviceSessionState | null, pinnedAccountId?: string | null): string | null;
|
|
60
|
+
/**
|
|
61
|
+
* The bound account's `User`, resolved from `usersById`. `null` when there is no
|
|
62
|
+
* state, no bound account, or the bound account id is absent from `usersById`.
|
|
63
|
+
*
|
|
64
|
+
* A pinned user is resolved from `usersById` alone — deliberately NOT gated on
|
|
65
|
+
* device membership — so a transient device-state gap cannot flicker the
|
|
66
|
+
* identity vault's rendered user. Whether the pinned session still exists on the
|
|
67
|
+
* device is answered by {@link activeSessionIdOf}.
|
|
68
|
+
*/
|
|
69
|
+
export declare function activeUserOf(state: DeviceSessionState | null, usersById: Map<string, User>, pinnedAccountId?: string | null): User | null;
|
|
70
|
+
/**
|
|
71
|
+
* All account ids in `state`, suitable for an `oxyServices.getUsersByIds(...)`
|
|
72
|
+
* fetch. `[]` for `null` state.
|
|
73
|
+
*/
|
|
74
|
+
export declare function accountIdsOf(state: DeviceSessionState | null): string[];
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified token refresh — THE single access-token re-mint for web + native.
|
|
3
|
+
*
|
|
4
|
+
* The access token is short-lived; there is no refresh token. To keep a session
|
|
5
|
+
* alive past the access token's TTL the client re-mints via the zero-cookie
|
|
6
|
+
* device transport:
|
|
7
|
+
*
|
|
8
|
+
* - `refreshPersistedSession` — arm 1 mints a fresh access token from the
|
|
9
|
+
* persisted `deviceId` + `deviceSecret` (`POST /session/device/token`),
|
|
10
|
+
* planting + persisting the rotated secret; arm 2 (native only) re-mints via
|
|
11
|
+
* the shared-keychain identity when there is no usable secret. It is used BOTH
|
|
12
|
+
* reactively (wrapped as the `AuthRefreshHandler` installed on `HttpService`)
|
|
13
|
+
* AND proactively (the scheduler below calls it).
|
|
14
|
+
* - `createAuthRefreshHandler` / `installAuthRefreshHandler` wire arm 1+2 into
|
|
15
|
+
* `HttpService.setAuthRefreshHandler`, keeping that layer's single-flight
|
|
16
|
+
* dedup + cooldown (this module does NOT reimplement them).
|
|
17
|
+
* - `startTokenRefreshScheduler` — a proactive scheduler decoupled from any
|
|
18
|
+
* React type: re-mints ~60s before `exp`, re-arms on token change + web
|
|
19
|
+
* tab-focus, `.unref?.()`s its timer in Node.
|
|
20
|
+
*
|
|
21
|
+
* Framework-free; no module-level mutable state.
|
|
22
|
+
*/
|
|
23
|
+
import type { DeviceSessionState } from '@oxy.so/contracts';
|
|
24
|
+
import type { OxyServices } from '../OxyServices';
|
|
25
|
+
import type { AuthRefreshHandler } from '../HttpService';
|
|
26
|
+
import type { AuthStateStore } from './authStateStore';
|
|
27
|
+
import type { IdentityPin } from './identityPin';
|
|
28
|
+
import { type IdentityBinding } from './identitySession';
|
|
29
|
+
/**
|
|
30
|
+
* Lead time (ms) before access-token expiry at which the proactive scheduler
|
|
31
|
+
* re-mints. Mirrors `HttpService`'s per-request `TOKEN_REFRESH_LEAD_SECONDS`
|
|
32
|
+
* (60s) so the scheduled re-mint and the request-time preflight use the same
|
|
33
|
+
* window — the scheduler just fires it during idle/background.
|
|
34
|
+
*/
|
|
35
|
+
export declare const TOKEN_REFRESH_LEAD_MS = 60000;
|
|
36
|
+
export interface RefreshDeps {
|
|
37
|
+
oxy: OxyServices;
|
|
38
|
+
store: AuthStateStore;
|
|
39
|
+
/**
|
|
40
|
+
* Whether to fall back to the native shared-keychain re-mint (arm 2) when the
|
|
41
|
+
* persisted secret is absent / rejected. Defaults to `isNative()` — web has no
|
|
42
|
+
* shared keychain. Exposed for tests. IGNORED when {@link identity} is set: an
|
|
43
|
+
* identity-bound client must never adopt the CROSS-APP shared slot, which may
|
|
44
|
+
* hold a different identity than this device's primary key.
|
|
45
|
+
*/
|
|
46
|
+
allowSharedKeyFallback?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Identity-bound (pinned) mode. When present, every re-mint targets the
|
|
49
|
+
* PINNED account — resolved fresh from the pin store on each call, since a
|
|
50
|
+
* re-established session can move it — instead of the device's active
|
|
51
|
+
* account, and arm 2 becomes the PRIMARY-key identity sign-in rather than the
|
|
52
|
+
* shared-keychain one.
|
|
53
|
+
*/
|
|
54
|
+
identity?: IdentityBinding;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The outcome of ONE device-secret mint attempt (arm 1). Discriminated so both
|
|
58
|
+
* the re-mint handler and the cold boot can react per the transport contract
|
|
59
|
+
* without re-classifying the raw error:
|
|
60
|
+
* - `ok` — minted, persisted `nextDeviceSecret`, planted the token.
|
|
61
|
+
* - `no-secret` — the store holds no `deviceId` + `deviceSecret` to mint from.
|
|
62
|
+
* - `invalid-secret` — 401 `invalid_device_secret`: the presented secret
|
|
63
|
+
* no longer matches the server's stored hash.
|
|
64
|
+
* - `no-session` — 401 `no_active_session`: the device is known but has no live
|
|
65
|
+
* session (authoritative signed-out).
|
|
66
|
+
* - `account-not-on-device` — 401 `account_not_on_device` for a PINNED mint: the
|
|
67
|
+
* pinned account is not (or no longer) a live account of this device session.
|
|
68
|
+
* The device secret is FINE — it is the identity binding that went stale, so
|
|
69
|
+
* the caller must re-establish from the local key, never drop the credential.
|
|
70
|
+
* - `transient` — network / 5xx; keep the secret, a later attempt can succeed.
|
|
71
|
+
* - `persist-failed` — the mint succeeded but `nextDeviceSecret` could NOT be
|
|
72
|
+
* durably persisted. The token is deliberately NOT planted: advertising a
|
|
73
|
+
* healthy session on a secret that will not survive a reload is exactly the
|
|
74
|
+
* divergence that logs users out.
|
|
75
|
+
*/
|
|
76
|
+
export type DeviceSecretMintOutcome = {
|
|
77
|
+
status: 'ok';
|
|
78
|
+
token: string;
|
|
79
|
+
sessionId: string;
|
|
80
|
+
userId: string;
|
|
81
|
+
state: DeviceSessionState;
|
|
82
|
+
} | {
|
|
83
|
+
status: 'no-secret';
|
|
84
|
+
} | {
|
|
85
|
+
status: 'invalid-secret';
|
|
86
|
+
} | {
|
|
87
|
+
status: 'no-session';
|
|
88
|
+
} | {
|
|
89
|
+
status: 'account-not-on-device';
|
|
90
|
+
} | {
|
|
91
|
+
status: 'transient';
|
|
92
|
+
} | {
|
|
93
|
+
status: 'persist-failed';
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* Arm 1 — the device-secret mint, run under the owning client's PROCESS-WIDE
|
|
97
|
+
* single-flight (`httpService.runSingleFlightDeviceSecretMint`).
|
|
98
|
+
*
|
|
99
|
+
* Concurrent lanes (cold boot, the proactive scheduler, a request-time preflight,
|
|
100
|
+
* a 401 retry, the socket token transport, or a tab-focus reconcile) must not
|
|
101
|
+
* each persist a different view of the mint response. Routing EVERY lane through
|
|
102
|
+
* this one single-flight makes concurrent callers await the SAME in-flight mint
|
|
103
|
+
* and all receive its result, so the durable store converges on one credential.
|
|
104
|
+
*
|
|
105
|
+
* On success it persists `nextDeviceSecret` (read-back-verified) BEFORE planting
|
|
106
|
+
* the access token; a failed durable persist yields `persist-failed` WITHOUT
|
|
107
|
+
* planting. This function performs NO store mutation on failure — the caller
|
|
108
|
+
* applies the drop/clear policy (which differs web vs native) from the returned
|
|
109
|
+
* status.
|
|
110
|
+
*
|
|
111
|
+
* `pin` makes the mint IDENTITY-BOUND: the request carries the pinned
|
|
112
|
+
* `accountId` (so the server mints that account's token without touching
|
|
113
|
+
* `activeAccountId`), and the persisted `sessionId`/`userId` are resolved from
|
|
114
|
+
* the PINNED account entry — never from `state.activeAccountId`, whose drift is
|
|
115
|
+
* exactly what the pin exists to stop.
|
|
116
|
+
*/
|
|
117
|
+
export declare function refreshDeviceSecretArm(deps: {
|
|
118
|
+
oxy: OxyServices;
|
|
119
|
+
store: AuthStateStore;
|
|
120
|
+
/** The identity pin, when this client is identity-bound. */
|
|
121
|
+
pin?: IdentityPin | null;
|
|
122
|
+
}): Promise<DeviceSecretMintOutcome>;
|
|
123
|
+
/**
|
|
124
|
+
* Re-mint the persisted session and return the fresh access token, or `null`
|
|
125
|
+
* when no arm could produce one.
|
|
126
|
+
*
|
|
127
|
+
* Arm 1 (`POST /session/device/token`, via {@link refreshDeviceSecretArm}): mint
|
|
128
|
+
* from the persisted `deviceId` + `deviceSecret`. On a 401 the secret is diverged
|
|
129
|
+
* or the device has no live session: drop the secret so the mint lane stops (or
|
|
130
|
+
* clear the store on web, where there is no fallback), then fall to arm 2 on
|
|
131
|
+
* native. A transient error — or a durable-persist failure — leaves the store and
|
|
132
|
+
* returns `null` WITHOUT falling to shared-key (those are not bad-secret signals).
|
|
133
|
+
*
|
|
134
|
+
* Arm 2 (native shared-keychain): when the secret is absent or was just rejected,
|
|
135
|
+
* re-mint via `signInWithSharedIdentity` (which plants tokens). On success the
|
|
136
|
+
* recovered `{deviceId, deviceSecret, …}` is PERSISTED so the fast device-secret
|
|
137
|
+
* lane is repopulated (mirrors the cold boot's `shared-key-signin` step) — an
|
|
138
|
+
* in-session shared-key recovery must not leave the fast-lane credential empty.
|
|
139
|
+
*
|
|
140
|
+
* IDENTITY-BOUND clients (`deps.identity`) run a different arm 2: the
|
|
141
|
+
* shared-keychain lane is DISABLED (its cross-app slot may hold a different
|
|
142
|
+
* identity) and replaced by {@link establishIdentitySession}, which re-signs a
|
|
143
|
+
* challenge with the PRIMARY local key and rewrites the pin. Arm 1 is pinned.
|
|
144
|
+
*/
|
|
145
|
+
export declare function refreshPersistedSession(deps: RefreshDeps): Promise<string | null>;
|
|
146
|
+
/**
|
|
147
|
+
* Build the reactive `AuthRefreshHandler` (arm 1 + arm 2). Install it via
|
|
148
|
+
* {@link installAuthRefreshHandler} or directly on
|
|
149
|
+
* `oxy.httpService.setAuthRefreshHandler`. `HttpService` owns single-flight
|
|
150
|
+
* dedup + cooldown, so the timer, the request-time preflight, and a 401 all
|
|
151
|
+
* collapse to one network attempt.
|
|
152
|
+
*/
|
|
153
|
+
export declare function createAuthRefreshHandler(deps: RefreshDeps): AuthRefreshHandler;
|
|
154
|
+
/**
|
|
155
|
+
* Install the unified refresh handler on the owner client's `HttpService`.
|
|
156
|
+
* Returns a disposer that removes it.
|
|
157
|
+
*/
|
|
158
|
+
export declare function installAuthRefreshHandler(deps: RefreshDeps): () => void;
|
|
159
|
+
/** Handle returned by {@link startTokenRefreshScheduler}; `dispose()` tears it down. */
|
|
160
|
+
export interface TokenRefreshSchedulerHandle {
|
|
161
|
+
dispose(): void;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Start the proactive re-mint scheduler against `oxy`.
|
|
165
|
+
*
|
|
166
|
+
* Schedules a single timer to fire {@link TOKEN_REFRESH_LEAD_MS} before the
|
|
167
|
+
* current access token's `exp`, calling
|
|
168
|
+
* `oxy.httpService.refreshAccessToken('preflight')` (which runs the installed
|
|
169
|
+
* handler; deduped + cooldown-guarded). After every attempt it reschedules
|
|
170
|
+
* from the possibly-rotated token. It also reschedules whenever the token
|
|
171
|
+
* changes (a sign-out that clears the token cancels the timer) and, on web
|
|
172
|
+
* tab-focus, re-mints immediately if already inside the lead window (a
|
|
173
|
+
* long-hidden tab throttles timers, so the token can be expired on return).
|
|
174
|
+
*
|
|
175
|
+
* No-ops cleanly when there is no token or an opaque/no-`exp` token — the
|
|
176
|
+
* reactive 401 path stays the only re-mint trigger in that case. The timer is
|
|
177
|
+
* `.unref?.()`-ed so it never keeps a Node/Jest event loop alive.
|
|
178
|
+
*/
|
|
179
|
+
export declare function startTokenRefreshScheduler(oxy: OxyServices): TokenRefreshSchedulerHandle;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { OxyServices } from '../OxyServices';
|
|
2
|
+
import type { DeviceCredential, SessionClientHost } from './SessionClient';
|
|
3
|
+
/**
|
|
4
|
+
* Thin `SessionClientHost` adapter over an `OxyServices` instance.
|
|
5
|
+
*
|
|
6
|
+
* `SessionClient` is host-agnostic: it only needs a REST + token surface.
|
|
7
|
+
* `OxyServices` already exposes all of that except `getCurrentAccountId`,
|
|
8
|
+
* which has no direct equivalent — the adapter holds a mutable ref set by
|
|
9
|
+
* the caller (`OxyContext` in `@oxy.so/services`) via `setCurrentAccountId`.
|
|
10
|
+
*
|
|
11
|
+
* Shared here (rather than duplicated per consumer) because it is entirely
|
|
12
|
+
* platform-agnostic: every method it calls exists identically on
|
|
13
|
+
* `OxyServices` regardless of host (web, Expo/RN, Node).
|
|
14
|
+
*/
|
|
15
|
+
export declare function createSessionClientHost(oxyServices: OxyServices): SessionClientHost & {
|
|
16
|
+
setCurrentAccountId(id: string | null): void;
|
|
17
|
+
setDeviceCredential(credential: DeviceCredential | null): void;
|
|
18
|
+
};
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The shared native DeviceSession credential — one device, one session, many apps.
|
|
3
|
+
*
|
|
4
|
+
* ## What this is, and what it deliberately is NOT
|
|
5
|
+
*
|
|
6
|
+
* Two different secrets can make a native Oxy app boot signed in, and conflating
|
|
7
|
+
* them is the bug this module exists to end:
|
|
8
|
+
*
|
|
9
|
+
* Commons private identity key → identity and signed approval ONLY. It is
|
|
10
|
+
* self-custody, irreplaceable, and must never
|
|
11
|
+
* become the general app session transport.
|
|
12
|
+
* Shared DeviceSession credential → THIS module. An ordinary `deviceId` +
|
|
13
|
+
* `deviceSecret` pair that restores ordinary
|
|
14
|
+
* official apps, follows the device's active
|
|
15
|
+
* context, and is individually rotatable and
|
|
16
|
+
* revocable server-side.
|
|
17
|
+
*
|
|
18
|
+
* An ordinary app needs the second one. Handing it the first — which is what the
|
|
19
|
+
* `shared-key-signin` lane does today — gives every sibling app the ability to
|
|
20
|
+
* sign as the user's cryptographic identity to obtain something as mundane as a
|
|
21
|
+
* session. That lane stays as a recovery/compatibility path; this one supersedes
|
|
22
|
+
* it for the ordinary case.
|
|
23
|
+
*
|
|
24
|
+
* ## Why sharing one credential is safe against the server
|
|
25
|
+
*
|
|
26
|
+
* `POST /session/device/token` does NOT rotate: the response echoes the presented
|
|
27
|
+
* secret back as `nextDeviceSecret` precisely so several first-party apps sharing
|
|
28
|
+
* one `DeviceSession` can refresh concurrently without invalidating one another.
|
|
29
|
+
* So N apps holding one credential is a supported server state, not a race — and
|
|
30
|
+
* because they then share ONE `DeviceSession`, they automatically share its
|
|
31
|
+
* `activeContextId` and its token-free `session_state` broadcasts.
|
|
32
|
+
*
|
|
33
|
+
* ## The one safety rule everything here is built around
|
|
34
|
+
*
|
|
35
|
+
* A read that FAILED and a slot that is EMPTY must never be the same value. The
|
|
36
|
+
* empty answer authorises writes (seed the slot); the failed answer must
|
|
37
|
+
* authorise nothing. {@link SharedDeviceCredentialRead} keeps them apart at the
|
|
38
|
+
* type level, and every decision below fails closed on anything that is not a
|
|
39
|
+
* positive `absent`/`present`.
|
|
40
|
+
*
|
|
41
|
+
* Platform-agnostic: the actual keychain / keystore access is injected as a
|
|
42
|
+
* {@link SharedDeviceCredentialStore} by `@oxy.so/services`. ESM-safe, no
|
|
43
|
+
* `require()`, no react/react-native/expo imports.
|
|
44
|
+
*/
|
|
45
|
+
import type { AuthStateStore, PersistedAuthState } from './authStateStore';
|
|
46
|
+
/**
|
|
47
|
+
* The zero-cookie device credential, as shared between apps. Exactly the pair
|
|
48
|
+
* `POST /session/device/token` takes — nothing else travels through the shared
|
|
49
|
+
* slot: no access token, no account id, no user id, no identity key.
|
|
50
|
+
*/
|
|
51
|
+
export interface SharedDeviceCredential {
|
|
52
|
+
deviceId: string;
|
|
53
|
+
deviceSecret: string;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The outcome of reading the shared slot. FOUR states, and the distinction
|
|
57
|
+
* between the last two is load-bearing:
|
|
58
|
+
*
|
|
59
|
+
* - `present` — a well-formed credential was read.
|
|
60
|
+
* - `absent` — the read SUCCEEDED and the slot is empty. The only state that
|
|
61
|
+
* may authorise seeding the slot.
|
|
62
|
+
* - `unavailable` — the read failed (keychain locked, keystore unreadable, the
|
|
63
|
+
* bridge returned something unrecognisable). Authorises
|
|
64
|
+
* nothing: not adoption, and above all not a write.
|
|
65
|
+
* - `unsupported` — this build has no shared slot at all (web, or a native app
|
|
66
|
+
* without the module linked). Not an error; simply means the
|
|
67
|
+
* app keeps its own per-app credential.
|
|
68
|
+
*/
|
|
69
|
+
export type SharedDeviceCredentialRead = {
|
|
70
|
+
state: 'present';
|
|
71
|
+
credential: SharedDeviceCredential;
|
|
72
|
+
} | {
|
|
73
|
+
state: 'absent';
|
|
74
|
+
} | {
|
|
75
|
+
state: 'unavailable';
|
|
76
|
+
cause: unknown;
|
|
77
|
+
} | {
|
|
78
|
+
state: 'unsupported';
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* The platform seam. `@oxy.so/services` implements this over the iOS Keychain
|
|
82
|
+
* Access Group (a dedicated `keychainService`) or the Android signature-protected
|
|
83
|
+
* `OxyDeviceSession` broker.
|
|
84
|
+
*/
|
|
85
|
+
export interface SharedDeviceCredentialStore {
|
|
86
|
+
/** Never throws — a failure is reported as `unavailable`, never as `absent`. */
|
|
87
|
+
read(): Promise<SharedDeviceCredentialRead>;
|
|
88
|
+
/**
|
|
89
|
+
* Publish the credential. Resolves `true` only when a read-back confirmed the
|
|
90
|
+
* exact bytes landed; `false` on any failure. Never throws.
|
|
91
|
+
*/
|
|
92
|
+
publish(credential: SharedDeviceCredential): Promise<boolean>;
|
|
93
|
+
/** Drop this app's copy of the shared credential. Never throws. */
|
|
94
|
+
clear(): Promise<void>;
|
|
95
|
+
}
|
|
96
|
+
/** Why {@link decideSharedDeviceJoin} declined to adopt the shared credential. */
|
|
97
|
+
export type SharedDeviceJoinSkipReason = 'shared-unsupported' | 'shared-unreadable' | 'shared-empty' | 'local-credential-present';
|
|
98
|
+
/** What a booting app should do with the shared slot it just read. */
|
|
99
|
+
export type SharedDeviceJoinDecision = {
|
|
100
|
+
action: 'adopt';
|
|
101
|
+
credential: SharedDeviceCredential;
|
|
102
|
+
} | {
|
|
103
|
+
action: 'skip';
|
|
104
|
+
reason: SharedDeviceJoinSkipReason;
|
|
105
|
+
};
|
|
106
|
+
/** Why {@link decideSharedDevicePublish} declined to write the shared slot. */
|
|
107
|
+
export type SharedDevicePublishSkipReason = 'shared-unsupported' | 'shared-unreadable' | 'already-current' | 'owned-by-another-device';
|
|
108
|
+
/** What an app that just PROVED a credential should do with the shared slot. */
|
|
109
|
+
export type SharedDevicePublishDecision = {
|
|
110
|
+
action: 'publish';
|
|
111
|
+
} | {
|
|
112
|
+
action: 'skip';
|
|
113
|
+
reason: SharedDevicePublishSkipReason;
|
|
114
|
+
};
|
|
115
|
+
/** The usable `{deviceId, deviceSecret}` pair in a persisted state, or null. */
|
|
116
|
+
export declare function readLocalDeviceCredential(state: PersistedAuthState | null): SharedDeviceCredential | null;
|
|
117
|
+
/**
|
|
118
|
+
* Narrow an UNTRUSTED bridge payload into a {@link SharedDeviceCredentialRead}.
|
|
119
|
+
*
|
|
120
|
+
* Anything unrecognised resolves to `unavailable`, never `absent`. A native
|
|
121
|
+
* module returning a shape this build does not understand (an older app in the
|
|
122
|
+
* signing group, a partially-applied upgrade) means we do not KNOW whether the
|
|
123
|
+
* device has a shared session — and "do not know" must never authorise a write
|
|
124
|
+
* that would overwrite one.
|
|
125
|
+
*/
|
|
126
|
+
export declare function normalizeSharedDeviceSessionRead(raw: unknown): SharedDeviceCredentialRead;
|
|
127
|
+
/**
|
|
128
|
+
* Should this app adopt the shared credential? Pure.
|
|
129
|
+
*
|
|
130
|
+
* Adoption happens in exactly ONE case: the shared slot holds a credential and
|
|
131
|
+
* this app has none of its own. That single rule delivers the product
|
|
132
|
+
* requirement — a newly installed official app joins the device's existing
|
|
133
|
+
* session without another QR — while making the two failure modes that matter
|
|
134
|
+
* unreachable:
|
|
135
|
+
*
|
|
136
|
+
* - An app that is already signed in is NEVER moved onto another credential, so
|
|
137
|
+
* "no user is signed out merely because one app updates first" holds by
|
|
138
|
+
* construction, in both upgrade directions.
|
|
139
|
+
* - A failed read never looks like an empty slot, so a locked keychain resolves
|
|
140
|
+
* to "keep what I have" rather than "this is a fresh device".
|
|
141
|
+
*
|
|
142
|
+
* The cost is stated plainly: two apps that each already own a DIFFERENT device
|
|
143
|
+
* session stay on their own until one of them loses its credential. Converging
|
|
144
|
+
* them would mean signing one of them out or a server-side device merge, and
|
|
145
|
+
* neither is something a boot path may do silently.
|
|
146
|
+
*/
|
|
147
|
+
export declare function decideSharedDeviceJoin(local: PersistedAuthState | null, shared: SharedDeviceCredentialRead): SharedDeviceJoinDecision;
|
|
148
|
+
/**
|
|
149
|
+
* Should this app write the credential it just proved into the shared slot? Pure.
|
|
150
|
+
*
|
|
151
|
+
* `proven` means the server accepted it moments ago — a successful sign-in or a
|
|
152
|
+
* successful mint. Only a proven credential is ever published, so the slot can
|
|
153
|
+
* never be seeded with something no app could use.
|
|
154
|
+
*
|
|
155
|
+
* A slot already held by a DIFFERENT `deviceId` is left alone. Overwriting it
|
|
156
|
+
* would silently migrate every other app on this device onto our session at their
|
|
157
|
+
* next cold boot — a real, user-visible change of who they are signed in as, and
|
|
158
|
+
* not something a background persist may decide.
|
|
159
|
+
*/
|
|
160
|
+
export declare function decideSharedDevicePublish(proven: SharedDeviceCredential, shared: SharedDeviceCredentialRead): SharedDevicePublishDecision;
|
|
161
|
+
/** The result of {@link publishProvenDeviceCredential}, for logs and tests. */
|
|
162
|
+
export type SharedDevicePublishOutcome = {
|
|
163
|
+
status: 'published';
|
|
164
|
+
} | {
|
|
165
|
+
status: 'publish-failed';
|
|
166
|
+
} | {
|
|
167
|
+
status: 'skipped';
|
|
168
|
+
reason: SharedDevicePublishSkipReason;
|
|
169
|
+
};
|
|
170
|
+
/**
|
|
171
|
+
* Read the shared slot, apply {@link decideSharedDevicePublish}, and write when
|
|
172
|
+
* it says so. Best-effort by contract: the caller's own durable credential is
|
|
173
|
+
* already persisted, so a failure here only means a future install will have to
|
|
174
|
+
* sign in interactively.
|
|
175
|
+
*/
|
|
176
|
+
export declare function publishProvenDeviceCredential(deps: {
|
|
177
|
+
shared: SharedDeviceCredentialStore;
|
|
178
|
+
credential: SharedDeviceCredential;
|
|
179
|
+
}): Promise<SharedDevicePublishOutcome>;
|
|
180
|
+
/**
|
|
181
|
+
* Wrap a platform {@link AuthStateStore} so that every durable credential it
|
|
182
|
+
* persists is ALSO mirrored into the shared slot.
|
|
183
|
+
*
|
|
184
|
+
* Writes mirror automatically; reads do NOT adopt. That split is deliberate:
|
|
185
|
+
*
|
|
186
|
+
* - Mirroring on write is the right place because `save()` is where a proven
|
|
187
|
+
* credential lands, on every lane there is — interactive sign-in, the cold
|
|
188
|
+
* boot mint, the refresh scheduler, the 401 re-mint, shared-key recovery. One
|
|
189
|
+
* seam, no lane left out, and no new call site to forget.
|
|
190
|
+
* - Adopting on read would hide a change of WHO THIS APP IS SIGNED IN AS inside
|
|
191
|
+
* a storage primitive, and would run on every `load()`. Adoption is an
|
|
192
|
+
* explicit, once-per-boot cold-boot step instead (`shared-device-adopt`).
|
|
193
|
+
*
|
|
194
|
+
* `clear()` deliberately does NOT clear the shared slot. This app signing out is
|
|
195
|
+
* not authority over the device-wide join point: other apps may still be signed
|
|
196
|
+
* in on that same credential, and once the server session is really gone the
|
|
197
|
+
* credential mints `no_active_session` for everyone anyway.
|
|
198
|
+
*/
|
|
199
|
+
export declare function createSharedMirroringAuthStateStore(deps: {
|
|
200
|
+
local: AuthStateStore;
|
|
201
|
+
shared: SharedDeviceCredentialStore;
|
|
202
|
+
}): AuthStateStore;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface MinimalSocket {
|
|
2
|
+
connected: boolean;
|
|
3
|
+
on(event: string, handler: (...args: unknown[]) => void): void;
|
|
4
|
+
off(event: string, handler?: (...args: unknown[]) => void): void;
|
|
5
|
+
/** Client→server emit (e.g. joining the `/auth-session` room for a QR flow). */
|
|
6
|
+
emit(event: string, ...args: unknown[]): void;
|
|
7
|
+
connect(): void;
|
|
8
|
+
disconnect(): void;
|
|
9
|
+
}
|
|
10
|
+
export type SocketIOFactory = (uri: string, opts?: Record<string, unknown>) => MinimalSocket;
|
|
11
|
+
export declare function getSocketIO(): Promise<SocketIOFactory | null>;
|