@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,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Crypto Polyfills
|
|
3
|
+
*
|
|
4
|
+
* Ensures Buffer and crypto.getRandomValues are available
|
|
5
|
+
* across all platforms (Node.js, Browser, React Native).
|
|
6
|
+
*
|
|
7
|
+
* Guard order when installing a `getRandomValues` shim (see bottom of file and
|
|
8
|
+
* {@link cryptoPolyfill}):
|
|
9
|
+
*
|
|
10
|
+
* 1. A REAL `globalThis.crypto.getRandomValues` — used as-is (browser, Node
|
|
11
|
+
* >= 20, modern Hermes). The shim below is only installed when the host is
|
|
12
|
+
* missing it, so this branch is the install-time gate.
|
|
13
|
+
* 2. Node — backed by the built-in `node:crypto` module (`webcrypto`, else
|
|
14
|
+
* `randomFillSync`). This is what a Node runtime WITHOUT a global WebCrypto
|
|
15
|
+
* (Node 18 script entrypoints, some embedded hosts) falls back to.
|
|
16
|
+
* 3. React Native — `expo-crypto.getRandomBytes` (statically imported via the
|
|
17
|
+
* per-platform `platform/crypto` module in `@oxy.so/protocol`).
|
|
18
|
+
*
|
|
19
|
+
* Historically step (2) delegated to `@oxy.so/protocol`'s RN-only
|
|
20
|
+
* `getRandomBytesRN`, which THROWS on Node — so any Node host lacking a global
|
|
21
|
+
* WebCrypto crashed here instead of getting randomness. It is now a proper
|
|
22
|
+
* Node-backed implementation.
|
|
23
|
+
*/
|
|
24
|
+
import _cjs_buffer from 'buffer';
|
|
25
|
+
const { Buffer } = _cjs_buffer;
|
|
26
|
+
import { getRandomBytesRN, isNodeJS } from '@oxy.so/protocol';
|
|
27
|
+
const getGlobalObject = () => {
|
|
28
|
+
if (typeof globalThis !== 'undefined')
|
|
29
|
+
return globalThis;
|
|
30
|
+
if (typeof global !== 'undefined')
|
|
31
|
+
return global;
|
|
32
|
+
if (typeof window !== 'undefined')
|
|
33
|
+
return window;
|
|
34
|
+
if (typeof self !== 'undefined')
|
|
35
|
+
return self;
|
|
36
|
+
return {};
|
|
37
|
+
};
|
|
38
|
+
const globalObject = getGlobalObject();
|
|
39
|
+
// Make Buffer available globally for libraries that depend on it
|
|
40
|
+
if (!globalObject.Buffer) {
|
|
41
|
+
globalObject.Buffer = Buffer;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Lazily-resolved `node:crypto` module, cached after the first attempt.
|
|
45
|
+
* `undefined` = not tried yet; `null` = tried and unavailable (non-Node host).
|
|
46
|
+
*/
|
|
47
|
+
let cachedNodeCrypto;
|
|
48
|
+
/**
|
|
49
|
+
* Synchronously load `node:crypto` on a Node runtime, or `null` elsewhere.
|
|
50
|
+
*
|
|
51
|
+
* Uses a guarded, Node-only `require`. Every runtime that actually reaches this
|
|
52
|
+
* branch has a working CommonJS `require`: `@oxy.so/core` publishes no
|
|
53
|
+
* `"type": "module"`, so Node loads it as CommonJS and the `require` free
|
|
54
|
+
* variable is present. Browsers never reach here (they own `globalThis.crypto`,
|
|
55
|
+
* so this polyfill is never installed) and React Native takes the
|
|
56
|
+
* `getRandomBytesRN` branch — so the `node:crypto` reference is dead code in
|
|
57
|
+
* those bundles, and Expo's Metro resolver shims `node:*` builtins, keeping
|
|
58
|
+
* web/native bundles green.
|
|
59
|
+
*/
|
|
60
|
+
function loadNodeCryptoSync() {
|
|
61
|
+
if (cachedNodeCrypto !== undefined) {
|
|
62
|
+
return cachedNodeCrypto;
|
|
63
|
+
}
|
|
64
|
+
if (typeof require !== 'function') {
|
|
65
|
+
cachedNodeCrypto = null;
|
|
66
|
+
return cachedNodeCrypto;
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
cachedNodeCrypto = require('node:crypto');
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
// No Node crypto (unexpected on a real Node host) — degrade to the next
|
|
73
|
+
// mechanism rather than crash.
|
|
74
|
+
cachedNodeCrypto = null;
|
|
75
|
+
}
|
|
76
|
+
return cachedNodeCrypto;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Fill `array` with cryptographically-secure random bytes from `node:crypto`.
|
|
80
|
+
* Prefers `webcrypto.getRandomValues`; falls back to `randomFillSync`. Returns
|
|
81
|
+
* `false` when Node crypto is unavailable so the caller can try the next
|
|
82
|
+
* mechanism.
|
|
83
|
+
*/
|
|
84
|
+
function fillFromNodeCrypto(array) {
|
|
85
|
+
const nodeCrypto = loadNodeCryptoSync();
|
|
86
|
+
if (!nodeCrypto) {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
const webcrypto = nodeCrypto.webcrypto;
|
|
90
|
+
if (webcrypto && typeof webcrypto.getRandomValues === 'function') {
|
|
91
|
+
try {
|
|
92
|
+
webcrypto.getRandomValues(array);
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
// `webcrypto.getRandomValues` rejects non-integer views (Float*Array,
|
|
97
|
+
// DataView); fall through to `randomFillSync`, which accepts any view.
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (typeof nodeCrypto.randomFillSync === 'function') {
|
|
101
|
+
nodeCrypto.randomFillSync(array);
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
const cryptoPolyfill = {
|
|
107
|
+
getRandomValues(array) {
|
|
108
|
+
// Node: back the CSPRNG with `node:crypto`. This is the path that matters on
|
|
109
|
+
// Node runtimes shipping WITHOUT a global WebCrypto — where delegating to
|
|
110
|
+
// the RN-only expo-crypto stub would throw.
|
|
111
|
+
if (isNodeJS() && fillFromNodeCrypto(array)) {
|
|
112
|
+
return array;
|
|
113
|
+
}
|
|
114
|
+
// React Native (and any non-Node host without WebCrypto): synchronous
|
|
115
|
+
// expo-crypto via @oxy.so/protocol's RN `platform/crypto` variant.
|
|
116
|
+
const bytes = getRandomBytesRN(array.byteLength);
|
|
117
|
+
const uint8View = new Uint8Array(array.buffer, array.byteOffset, array.byteLength);
|
|
118
|
+
uint8View.set(bytes);
|
|
119
|
+
return array;
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
// Only polyfill if crypto or crypto.getRandomValues is not available
|
|
123
|
+
if (typeof globalObject.crypto === 'undefined') {
|
|
124
|
+
globalObject.crypto = cryptoPolyfill;
|
|
125
|
+
}
|
|
126
|
+
else if (typeof globalObject.crypto.getRandomValues !== 'function') {
|
|
127
|
+
globalObject.crypto.getRandomValues = cryptoPolyfill.getRandomValues;
|
|
128
|
+
}
|
|
129
|
+
export { Buffer };
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recovery Phrase Service - BIP39 Mnemonic Generation
|
|
3
|
+
*
|
|
4
|
+
* Handles generation and restoration of recovery phrases (mnemonic seeds)
|
|
5
|
+
* for backing up and restoring user identities.
|
|
6
|
+
*
|
|
7
|
+
* Note: This module requires the polyfill to be loaded first (done via crypto/index.ts)
|
|
8
|
+
*
|
|
9
|
+
* Oxy recovery phrases are English-only, so the English wordlist is imported by
|
|
10
|
+
* its own subpath. Never reach for a package that exposes its wordlists through
|
|
11
|
+
* a barrel: `bip39`'s `_wordlists` hard-requires all ten languages, which put
|
|
12
|
+
* ~265 KB of unreachable wordlists into the initial chunk of every consuming
|
|
13
|
+
* app. Adding another language means one more subpath import, ideally lazy.
|
|
14
|
+
*/
|
|
15
|
+
import { generateMnemonic, mnemonicToSeed, validateMnemonic } from '@scure/bip39';
|
|
16
|
+
import { wordlist } from '@scure/bip39/wordlists/english';
|
|
17
|
+
import { KeyManager } from './keyManager.js';
|
|
18
|
+
import { hkdfSha256 } from './kdf.js';
|
|
19
|
+
/**
|
|
20
|
+
* Convert Uint8Array or array-like to hexadecimal string
|
|
21
|
+
* Works in both Node.js and React Native without depending on Buffer
|
|
22
|
+
*/
|
|
23
|
+
function toHex(data) {
|
|
24
|
+
// Convert to array of numbers if needed
|
|
25
|
+
const bytes = data instanceof Uint8Array ? data : new Uint8Array(data);
|
|
26
|
+
return Array.from(bytes)
|
|
27
|
+
.map(b => b.toString(16).padStart(2, '0'))
|
|
28
|
+
.join('');
|
|
29
|
+
}
|
|
30
|
+
/** UTF-8 encode an ASCII label to bytes (for HKDF salt/info). */
|
|
31
|
+
function utf8(label) {
|
|
32
|
+
return new TextEncoder().encode(label);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* HKDF context tag for the encrypted-backup key schedule (b3 Feature 1). Used as
|
|
36
|
+
* the HKDF `salt`; distinct from any other Oxy key-derivation salt so the backup
|
|
37
|
+
* key schedule is independent. Versioned so a future scheme change is a new tag.
|
|
38
|
+
*/
|
|
39
|
+
export const BACKUP_KDF_SALT = 'oxy-identity-backup-v1';
|
|
40
|
+
/** HKDF `info` label that derives the symmetric AEAD key from the seed. */
|
|
41
|
+
export const BACKUP_KDF_ENCRYPTION_INFO = 'oxy-backup-encryption-key';
|
|
42
|
+
/** HKDF `info` label that derives the (server-hashed) backup locator from the seed. */
|
|
43
|
+
export const BACKUP_KDF_LOOKUP_INFO = 'oxy-backup-lookup-id';
|
|
44
|
+
/** Byte length of both the derived backup key and the derived lookup id (256-bit). */
|
|
45
|
+
export const BACKUP_MATERIAL_LENGTH = 32;
|
|
46
|
+
export class RecoveryPhraseService {
|
|
47
|
+
/**
|
|
48
|
+
* Generate a new identity with a recovery phrase.
|
|
49
|
+
* The mnemonic phrase MUST be shown to the user exactly once after this
|
|
50
|
+
* call resolves — if it is lost, the account becomes unrecoverable.
|
|
51
|
+
*
|
|
52
|
+
* Refuses to overwrite an existing identity unless `options.overwrite === true`.
|
|
53
|
+
*
|
|
54
|
+
* @throws IdentityAlreadyExistsError if an identity already exists and overwrite is not set
|
|
55
|
+
*/
|
|
56
|
+
static async generateIdentityWithRecovery(options) {
|
|
57
|
+
// Generate 128-bit entropy for 12-word mnemonic
|
|
58
|
+
const mnemonic = generateMnemonic(wordlist, 128);
|
|
59
|
+
// Derive private key from mnemonic
|
|
60
|
+
// Using the seed directly as the private key (simplified approach)
|
|
61
|
+
const seed = await mnemonicToSeed(mnemonic);
|
|
62
|
+
// Use first 32 bytes of seed as private key
|
|
63
|
+
const privateKeyHex = toHex(seed.subarray(0, 32));
|
|
64
|
+
// Import the derived key pair. KeyManager.importKeyPair will refuse to
|
|
65
|
+
// clobber an existing identity unless overwrite is explicitly requested.
|
|
66
|
+
const publicKey = await KeyManager.importKeyPair(privateKeyHex, {
|
|
67
|
+
overwrite: options?.overwrite === true,
|
|
68
|
+
});
|
|
69
|
+
return {
|
|
70
|
+
phrase: mnemonic,
|
|
71
|
+
words: mnemonic.split(' '),
|
|
72
|
+
publicKey,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Generate a 24-word recovery phrase for higher security.
|
|
77
|
+
*
|
|
78
|
+
* Same overwrite-protection semantics as `generateIdentityWithRecovery`.
|
|
79
|
+
*/
|
|
80
|
+
static async generateIdentityWithRecovery24(options) {
|
|
81
|
+
// Generate 256-bit entropy for 24-word mnemonic
|
|
82
|
+
const mnemonic = generateMnemonic(wordlist, 256);
|
|
83
|
+
const seed = await mnemonicToSeed(mnemonic);
|
|
84
|
+
const privateKeyHex = toHex(seed.subarray(0, 32));
|
|
85
|
+
const publicKey = await KeyManager.importKeyPair(privateKeyHex, {
|
|
86
|
+
overwrite: options?.overwrite === true,
|
|
87
|
+
});
|
|
88
|
+
return {
|
|
89
|
+
phrase: mnemonic,
|
|
90
|
+
words: mnemonic.split(' '),
|
|
91
|
+
publicKey,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Derive a brand-new identity + recovery phrase WITHOUT persisting anything.
|
|
96
|
+
*
|
|
97
|
+
* Pure: same derivation as {@link generateIdentityWithRecovery} (128-bit
|
|
98
|
+
* mnemonic → seed → first 32 bytes as the secp256k1 private key) but it stops
|
|
99
|
+
* BEFORE `KeyManager.importKeyPair`, so no on-device identity is touched. The
|
|
100
|
+
* caller decides if/when to commit the material (e.g. only after a server
|
|
101
|
+
* confirms a key rotation). Works on web too — it never reads or writes secure
|
|
102
|
+
* storage.
|
|
103
|
+
*
|
|
104
|
+
* The 12-word `phrase` MUST be shown to the user before the identity is
|
|
105
|
+
* committed anywhere — if it is lost the account becomes unrecoverable.
|
|
106
|
+
*/
|
|
107
|
+
static async derivePendingIdentity() {
|
|
108
|
+
const mnemonic = generateMnemonic(wordlist, 128);
|
|
109
|
+
const seed = await mnemonicToSeed(mnemonic);
|
|
110
|
+
const privateKey = toHex(seed.subarray(0, 32));
|
|
111
|
+
const publicKey = KeyManager.derivePublicKey(privateKey);
|
|
112
|
+
return {
|
|
113
|
+
phrase: mnemonic,
|
|
114
|
+
words: mnemonic.split(' '),
|
|
115
|
+
privateKey,
|
|
116
|
+
publicKey,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Derive the private key from a recovery phrase WITHOUT storing it.
|
|
121
|
+
*
|
|
122
|
+
* The private-key counterpart of {@link derivePublicKeyFromPhrase}. Used to
|
|
123
|
+
* re-derive a key in memory (e.g. to sign a rotation proof with the current
|
|
124
|
+
* key when the device has no SecureStore copy). Never persists — the returned
|
|
125
|
+
* material lives only in the caller's memory.
|
|
126
|
+
*/
|
|
127
|
+
static async derivePrivateKeyFromPhrase(phrase) {
|
|
128
|
+
const normalizedPhrase = phrase.trim().toLowerCase();
|
|
129
|
+
if (!validateMnemonic(normalizedPhrase, wordlist)) {
|
|
130
|
+
throw new Error('Invalid recovery phrase');
|
|
131
|
+
}
|
|
132
|
+
const seed = await mnemonicToSeed(normalizedPhrase);
|
|
133
|
+
return toHex(seed.subarray(0, 32));
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Derive the encrypted-backup key material from a recovery phrase (b3 Feature
|
|
137
|
+
* 1). PURE and additive — it does NOT touch the frozen phrase→privateKey
|
|
138
|
+
* derivation ({@link derivePrivateKeyFromPhrase} slices the first 32 seed
|
|
139
|
+
* bytes) and never reads or writes secure storage.
|
|
140
|
+
*
|
|
141
|
+
* Both outputs are derived from the FULL 64-byte BIP-39 seed via HKDF-SHA256
|
|
142
|
+
* with domain-separated `info` labels, so the domain separation is real: a
|
|
143
|
+
* device compromise that leaks only the raw 32-byte private key can compute
|
|
144
|
+
* NEITHER the backup key nor the lookup id (both need the whole seed). Locating
|
|
145
|
+
* AND decrypting a backup therefore requires the recovery phrase.
|
|
146
|
+
*
|
|
147
|
+
* @param phrase - The BIP-39 recovery phrase (validated + normalized here).
|
|
148
|
+
* @returns `{ backupKey, lookupId }` — the AEAD key (kept local) and the hex
|
|
149
|
+
* locator (uploaded; server stores only its hash).
|
|
150
|
+
* @throws if the phrase is not a valid BIP-39 mnemonic.
|
|
151
|
+
*/
|
|
152
|
+
static async deriveBackupMaterial(phrase) {
|
|
153
|
+
const normalizedPhrase = phrase.trim().toLowerCase();
|
|
154
|
+
if (!validateMnemonic(normalizedPhrase, wordlist)) {
|
|
155
|
+
throw new Error('Invalid recovery phrase. Please check the words and try again.');
|
|
156
|
+
}
|
|
157
|
+
const seed = await mnemonicToSeed(normalizedPhrase);
|
|
158
|
+
const salt = utf8(BACKUP_KDF_SALT);
|
|
159
|
+
const backupKey = hkdfSha256(seed, salt, utf8(BACKUP_KDF_ENCRYPTION_INFO), BACKUP_MATERIAL_LENGTH);
|
|
160
|
+
const lookupId = toHex(hkdfSha256(seed, salt, utf8(BACKUP_KDF_LOOKUP_INFO), BACKUP_MATERIAL_LENGTH));
|
|
161
|
+
return { backupKey, lookupId };
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Restore an identity from a recovery phrase.
|
|
165
|
+
*
|
|
166
|
+
* Refuses to overwrite a DIFFERENT existing identity unless
|
|
167
|
+
* `options.overwrite === true`. Re-importing the same phrase that
|
|
168
|
+
* matches the current identity is always allowed (it's a no-op refresh
|
|
169
|
+
* of the backup record).
|
|
170
|
+
*/
|
|
171
|
+
static async restoreFromPhrase(phrase, options) {
|
|
172
|
+
// Normalize and validate the phrase
|
|
173
|
+
const normalizedPhrase = phrase.trim().toLowerCase();
|
|
174
|
+
if (!validateMnemonic(normalizedPhrase, wordlist)) {
|
|
175
|
+
throw new Error('Invalid recovery phrase. Please check the words and try again.');
|
|
176
|
+
}
|
|
177
|
+
// Derive the same private key from the mnemonic
|
|
178
|
+
const seed = await mnemonicToSeed(normalizedPhrase);
|
|
179
|
+
const privateKeyHex = toHex(seed.subarray(0, 32));
|
|
180
|
+
// Import and store the key pair
|
|
181
|
+
const publicKey = await KeyManager.importKeyPair(privateKeyHex, {
|
|
182
|
+
overwrite: options?.overwrite === true,
|
|
183
|
+
});
|
|
184
|
+
return publicKey;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Validate a recovery phrase without importing it
|
|
188
|
+
*/
|
|
189
|
+
static validatePhrase(phrase) {
|
|
190
|
+
const normalizedPhrase = phrase.trim().toLowerCase();
|
|
191
|
+
return validateMnemonic(normalizedPhrase, wordlist);
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Get the word list for autocomplete/validation
|
|
195
|
+
*/
|
|
196
|
+
static getWordList() {
|
|
197
|
+
return wordlist;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Check if a word is valid in the BIP39 word list
|
|
201
|
+
*/
|
|
202
|
+
static isValidWord(word) {
|
|
203
|
+
return wordlist.includes(word.toLowerCase());
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Get suggestions for a partial word
|
|
207
|
+
*/
|
|
208
|
+
static getSuggestions(partial, limit = 5) {
|
|
209
|
+
const lowerPartial = partial.toLowerCase();
|
|
210
|
+
return wordlist.filter((word) => word.startsWith(lowerPartial)).slice(0, limit);
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Derive the public key from a phrase without storing
|
|
214
|
+
* Useful for verification before importing
|
|
215
|
+
*/
|
|
216
|
+
static async derivePublicKeyFromPhrase(phrase) {
|
|
217
|
+
const normalizedPhrase = phrase.trim().toLowerCase();
|
|
218
|
+
if (!validateMnemonic(normalizedPhrase, wordlist)) {
|
|
219
|
+
throw new Error('Invalid recovery phrase');
|
|
220
|
+
}
|
|
221
|
+
const seed = await mnemonicToSeed(normalizedPhrase);
|
|
222
|
+
const privateKeyHex = toHex(seed.subarray(0, 32));
|
|
223
|
+
return KeyManager.derivePublicKey(privateKeyHex);
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Convert a phrase to its word array
|
|
227
|
+
*/
|
|
228
|
+
static phraseToWords(phrase) {
|
|
229
|
+
return phrase.trim().toLowerCase().split(/\s+/);
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Convert a word array to a phrase string
|
|
233
|
+
*/
|
|
234
|
+
static wordsToPhrase(words) {
|
|
235
|
+
return words.map(w => w.toLowerCase().trim()).join(' ');
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
export default RecoveryPhraseService;
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Signature Service - ECDSA Digital Signatures (device-key bound)
|
|
3
|
+
*
|
|
4
|
+
* Handles signing and verification of messages with the user's DEVICE identity
|
|
5
|
+
* key (read from {@link KeyManager} / secure storage). All cryptography itself —
|
|
6
|
+
* canonical signing input, SHA-256, secp256k1 sign/verify, envelope assembly —
|
|
7
|
+
* is delegated to `@oxy.so/protocol`; this service only resolves the key from
|
|
8
|
+
* storage and orchestrates the protocol primitives.
|
|
9
|
+
*/
|
|
10
|
+
import { signEnvelope, signMessage, verifySignature, sha256, loadExpoCrypto, loadNodeCrypto, isReactNative, isNodeJS, } from '@oxy.so/protocol';
|
|
11
|
+
import { KeyManager } from './keyManager.js';
|
|
12
|
+
import { logger } from '../logger/index.js';
|
|
13
|
+
export class SignatureService {
|
|
14
|
+
/**
|
|
15
|
+
* Generate a random challenge string (for offline use)
|
|
16
|
+
* Uses expo-crypto in React Native, crypto.randomBytes in Node.js
|
|
17
|
+
*/
|
|
18
|
+
static async generateChallenge() {
|
|
19
|
+
// In React Native, use expo-crypto
|
|
20
|
+
if (isReactNative()) {
|
|
21
|
+
const Crypto = await loadExpoCrypto();
|
|
22
|
+
const randomBytes = await Crypto.getRandomBytesAsync(32);
|
|
23
|
+
return Array.from(new Uint8Array(randomBytes))
|
|
24
|
+
.map((b) => b.toString(16).padStart(2, '0'))
|
|
25
|
+
.join('');
|
|
26
|
+
}
|
|
27
|
+
if (isNodeJS()) {
|
|
28
|
+
try {
|
|
29
|
+
const nodeCrypto = await loadNodeCrypto();
|
|
30
|
+
return nodeCrypto.randomBytes(32).toString('hex');
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
// Node crypto failed to load — log and fall through to Web Crypto API
|
|
34
|
+
logger.warn('[oxy.crypto] Node crypto unavailable, falling back to Web Crypto', { component: 'SignatureService' }, error);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// Browser: use Web Crypto API
|
|
38
|
+
const bytes = new Uint8Array(32);
|
|
39
|
+
globalThis.crypto.getRandomValues(bytes);
|
|
40
|
+
return Array.from(bytes)
|
|
41
|
+
.map(b => b.toString(16).padStart(2, '0'))
|
|
42
|
+
.join('');
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Hash a message using SHA-256
|
|
46
|
+
*/
|
|
47
|
+
static async hashMessage(message) {
|
|
48
|
+
return sha256(message);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Sign a message using the stored device private key
|
|
52
|
+
* Returns the signature in DER format (hex encoded)
|
|
53
|
+
*/
|
|
54
|
+
static async sign(message) {
|
|
55
|
+
const privateKey = await KeyManager.getPrivateKey();
|
|
56
|
+
if (!privateKey) {
|
|
57
|
+
throw new Error('No identity found. Please create or import an identity first.');
|
|
58
|
+
}
|
|
59
|
+
return signMessage(message, privateKey);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Create a signed message object with metadata
|
|
63
|
+
*/
|
|
64
|
+
static async createSignedMessage(message) {
|
|
65
|
+
const publicKey = await KeyManager.getPublicKey();
|
|
66
|
+
if (!publicKey) {
|
|
67
|
+
throw new Error('No identity found. Please create or import an identity first.');
|
|
68
|
+
}
|
|
69
|
+
const timestamp = Date.now();
|
|
70
|
+
const messageWithTimestamp = `${message}:${timestamp}`;
|
|
71
|
+
const signature = await SignatureService.sign(messageWithTimestamp);
|
|
72
|
+
return {
|
|
73
|
+
message,
|
|
74
|
+
signature,
|
|
75
|
+
publicKey,
|
|
76
|
+
timestamp,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Verify a signed message object
|
|
81
|
+
* Checks both signature validity and timestamp freshness
|
|
82
|
+
*/
|
|
83
|
+
static async verifySignedMessage(signedMessage, maxAgeMs = 5 * 60 * 1000 // 5 minutes default
|
|
84
|
+
) {
|
|
85
|
+
const { message, signature, publicKey, timestamp } = signedMessage;
|
|
86
|
+
// Check timestamp freshness
|
|
87
|
+
const now = Date.now();
|
|
88
|
+
if (now - timestamp > maxAgeMs) {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
// Verify signature
|
|
92
|
+
const messageWithTimestamp = `${message}:${timestamp}`;
|
|
93
|
+
return verifySignature(messageWithTimestamp, signature, publicKey);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Create a signed authentication challenge response
|
|
97
|
+
* Used for challenge-response authentication
|
|
98
|
+
*/
|
|
99
|
+
static async signChallenge(challenge) {
|
|
100
|
+
const publicKey = await KeyManager.getPublicKey();
|
|
101
|
+
if (!publicKey) {
|
|
102
|
+
throw new Error('No identity found. Please create or import an identity first.');
|
|
103
|
+
}
|
|
104
|
+
const timestamp = Date.now();
|
|
105
|
+
const message = `auth:${publicKey}:${challenge}:${timestamp}`;
|
|
106
|
+
const signature = await SignatureService.sign(message);
|
|
107
|
+
return {
|
|
108
|
+
challenge: signature,
|
|
109
|
+
publicKey,
|
|
110
|
+
timestamp,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Create a signed authentication challenge response using the SHARED identity
|
|
115
|
+
* key (the cross-app `group.so.oxy.shared` keychain key), not the primary
|
|
116
|
+
* device key.
|
|
117
|
+
*
|
|
118
|
+
* Mirrors {@link signChallenge} exactly — same message format
|
|
119
|
+
* (`auth:${publicKey}:${challenge}:${timestamp}`) so the server verification
|
|
120
|
+
* path is unchanged — but sources the shared public/private key from
|
|
121
|
+
* `KeyManager` and signs with the protocol's explicit-key {@link signMessage}.
|
|
122
|
+
* Used by "Sign in with Oxy" same-device shared-keychain SSO (Mechanism A): a
|
|
123
|
+
* sibling native app proves control of the shared identity to mint its own
|
|
124
|
+
* session.
|
|
125
|
+
*
|
|
126
|
+
* Throws if no shared identity exists (native-only; the shared keychain is
|
|
127
|
+
* unavailable on web).
|
|
128
|
+
*/
|
|
129
|
+
static async signChallengeWithSharedKey(challenge) {
|
|
130
|
+
const publicKey = await KeyManager.getSharedPublicKey();
|
|
131
|
+
const privateKey = await KeyManager.getSharedPrivateKey();
|
|
132
|
+
if (!publicKey || !privateKey) {
|
|
133
|
+
throw new Error('No shared identity found. Cannot sign with the shared key.');
|
|
134
|
+
}
|
|
135
|
+
const timestamp = Date.now();
|
|
136
|
+
const message = `auth:${publicKey}:${challenge}:${timestamp}`;
|
|
137
|
+
const signature = await signMessage(message, privateKey);
|
|
138
|
+
return {
|
|
139
|
+
challenge: signature,
|
|
140
|
+
publicKey,
|
|
141
|
+
timestamp,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Verify a challenge response
|
|
146
|
+
*/
|
|
147
|
+
static async verifyChallengeResponse(originalChallenge, response, maxAgeMs = 5 * 60 * 1000) {
|
|
148
|
+
const { challenge: signature, publicKey, timestamp } = response;
|
|
149
|
+
// Check timestamp freshness
|
|
150
|
+
const now = Date.now();
|
|
151
|
+
if (now - timestamp > maxAgeMs) {
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
const message = `auth:${publicKey}:${originalChallenge}:${timestamp}`;
|
|
155
|
+
return verifySignature(message, signature, publicKey);
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Create a registration signature
|
|
159
|
+
* Used when registering a new identity with the server
|
|
160
|
+
* Format matches server expectation: oxy:register:{publicKey}:{timestamp}
|
|
161
|
+
*/
|
|
162
|
+
static async createRegistrationSignature() {
|
|
163
|
+
const publicKey = await KeyManager.getPublicKey();
|
|
164
|
+
if (!publicKey) {
|
|
165
|
+
throw new Error('No identity found. Please create or import an identity first.');
|
|
166
|
+
}
|
|
167
|
+
const timestamp = Date.now();
|
|
168
|
+
const message = `oxy:register:${publicKey}:${timestamp}`;
|
|
169
|
+
const signature = await SignatureService.sign(message);
|
|
170
|
+
return {
|
|
171
|
+
signature,
|
|
172
|
+
publicKey,
|
|
173
|
+
timestamp,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Sign arbitrary data for API requests
|
|
178
|
+
* Creates a canonical string representation and signs it
|
|
179
|
+
*/
|
|
180
|
+
static async signRequestData(data) {
|
|
181
|
+
const publicKey = await KeyManager.getPublicKey();
|
|
182
|
+
if (!publicKey) {
|
|
183
|
+
throw new Error('No identity found. Please create or import an identity first.');
|
|
184
|
+
}
|
|
185
|
+
const timestamp = Date.now();
|
|
186
|
+
// Create canonical string representation
|
|
187
|
+
const sortedKeys = Object.keys(data).sort();
|
|
188
|
+
const canonicalParts = sortedKeys.map(key => `${key}:${JSON.stringify(data[key])}`);
|
|
189
|
+
const canonicalString = canonicalParts.join('|');
|
|
190
|
+
const message = `request:${publicKey}:${timestamp}:${canonicalString}`;
|
|
191
|
+
const signature = await SignatureService.sign(message);
|
|
192
|
+
return {
|
|
193
|
+
signature,
|
|
194
|
+
publicKey,
|
|
195
|
+
timestamp,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Build a signed-record envelope for a self-issued identity/profile record.
|
|
200
|
+
*
|
|
201
|
+
* The envelope is self-issued: `issuer` equals `subject` (the signer's DID).
|
|
202
|
+
* The signature covers the canonical JSON of every field EXCEPT `publicKey`
|
|
203
|
+
* and `signature`; `alg` is `ES256K-DER-SHA256` (secp256k1 over the SHA-256 of
|
|
204
|
+
* the canonical bytes, DER-encoded). The cryptography is delegated to the
|
|
205
|
+
* protocol's {@link signEnvelope}, which derives the (uncompressed-hex)
|
|
206
|
+
* `publicKey` from the stored device key — identical to the registered
|
|
207
|
+
* verification method.
|
|
208
|
+
*
|
|
209
|
+
* Requires a stored identity (native secure storage); throws if none exists.
|
|
210
|
+
*
|
|
211
|
+
* @param type - The record category (`'identity'` or `'profile'`).
|
|
212
|
+
* @param subject - The subject DID the record is about (also the issuer).
|
|
213
|
+
* @param record - The arbitrary record payload to attest to.
|
|
214
|
+
*/
|
|
215
|
+
static async signRecord(type, subject, record) {
|
|
216
|
+
const privateKey = await KeyManager.getPrivateKey();
|
|
217
|
+
if (!privateKey) {
|
|
218
|
+
throw new Error('No identity found. Please create or import an identity first.');
|
|
219
|
+
}
|
|
220
|
+
return signEnvelope({
|
|
221
|
+
version: 1,
|
|
222
|
+
type,
|
|
223
|
+
subject,
|
|
224
|
+
issuer: subject,
|
|
225
|
+
record,
|
|
226
|
+
issuedAt: Date.now(),
|
|
227
|
+
}, privateKey);
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Build a signed-record envelope (v2) carrying the per-subject hash-chain
|
|
231
|
+
* fields.
|
|
232
|
+
*
|
|
233
|
+
* Identical to {@link signRecord} (self-issued: `issuer === subject`; same
|
|
234
|
+
* `ES256K-DER-SHA256` scheme) but `version` is `2` and the signed bytes
|
|
235
|
+
* additionally cover the chain fields:
|
|
236
|
+
*
|
|
237
|
+
* @param type - The record category.
|
|
238
|
+
* @param subject - The subject DID the record is about (also the issuer).
|
|
239
|
+
* @param record - The arbitrary record payload to attest to.
|
|
240
|
+
* @param chain - The hash-chain coordinates:
|
|
241
|
+
* - `seq` — strictly-increasing sequence number for this subject's chain.
|
|
242
|
+
* - `prev` — the `recordId` of the previous record, or `null` at genesis.
|
|
243
|
+
* - `collection` + `rkey` — the AtProto-style record key.
|
|
244
|
+
*
|
|
245
|
+
* The caller is responsible for fetching the current chain head (so `seq` /
|
|
246
|
+
* `prev` are correct) before signing. Requires a stored identity; throws if
|
|
247
|
+
* none exists.
|
|
248
|
+
*/
|
|
249
|
+
static async signRecordV2(type, subject, record, chain) {
|
|
250
|
+
const privateKey = await KeyManager.getPrivateKey();
|
|
251
|
+
if (!privateKey) {
|
|
252
|
+
throw new Error('No identity found. Please create or import an identity first.');
|
|
253
|
+
}
|
|
254
|
+
const { seq, prev, collection, rkey } = chain;
|
|
255
|
+
return signEnvelope({
|
|
256
|
+
version: 2,
|
|
257
|
+
type,
|
|
258
|
+
subject,
|
|
259
|
+
issuer: subject,
|
|
260
|
+
record,
|
|
261
|
+
issuedAt: Date.now(),
|
|
262
|
+
seq,
|
|
263
|
+
prev,
|
|
264
|
+
collection,
|
|
265
|
+
rkey,
|
|
266
|
+
}, privateKey);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
export default SignatureService;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import enUS from './locales/en-US.json' with { type: "json" };
|
|
2
|
+
import { translate } from './index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Every account category's English name, keyed by its stable id.
|
|
5
|
+
*
|
|
6
|
+
* **The annotation is the point.** The vocabulary lives in `@oxy.so/contracts`
|
|
7
|
+
* and the names live in `locales/en-US.json`, so they are two lists that must
|
|
8
|
+
* agree and nothing but a type can make them. Declaring the JSON node as a
|
|
9
|
+
* TOTAL `Record<AccountCategoryId, string>` turns "somebody added a category at
|
|
10
|
+
* Oxy and nobody wrote its English" into a `TS2741` naming the missing id, at
|
|
11
|
+
* build time, instead of a picker row that paints `accounts.accountCategory.<id>`
|
|
12
|
+
* at a user trying to choose one.
|
|
13
|
+
*
|
|
14
|
+
* That failure is not hypothetical. The screen previously wrote `t(key) || id`,
|
|
15
|
+
* whose author believed an unnamed id would degrade to its raw slug. It cannot:
|
|
16
|
+
* {@link translate} echoes the KEY when it resolves nothing, and a non-empty
|
|
17
|
+
* string is never falsy, so the `|| id` arm was unreachable and the output was
|
|
18
|
+
* the dotted key. A runtime fallback that cannot run is worse than none,
|
|
19
|
+
* because it reads as protection.
|
|
20
|
+
*
|
|
21
|
+
* Totality is over `ACCOUNT_CATEGORY_IDS`, which RETAINS withdrawn ids, so an
|
|
22
|
+
* account still carrying a retired category keeps rendering its name while no
|
|
23
|
+
* picker offers it again. Retired and unknown are different cases: only an id
|
|
24
|
+
* outside the union is unnameable, which is why this is keyed by
|
|
25
|
+
* `AccountCategoryId` and not by `string`.
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* Module-scoped, NOT re-exported from the package index: the annotation is the
|
|
29
|
+
* whole job, and it does that job without being public API. It carries no
|
|
30
|
+
* `Object.freeze` and no `Readonly<>` for the same reason — those existed only
|
|
31
|
+
* to make an exported reference safe from a consumer's stray write, and there
|
|
32
|
+
* is no such consumer. Exported from the MODULE so its own test can name it.
|
|
33
|
+
*/
|
|
34
|
+
export const EN_ACCOUNT_CATEGORY_LABELS = enUS.accounts.accountCategory;
|
|
35
|
+
export function accountCategoryLabel(locale, id) {
|
|
36
|
+
return translate(locale, `accounts.accountCategory.${id}`);
|
|
37
|
+
}
|