@seams/wallet-server 0.7.1 → 0.7.3
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/THIRD_PARTY_NOTICES.md +1 -105
- package/artifact-manifest.json +21 -21
- package/cloudflare-router-ab/build/deriver-a/build-stamp.json +1 -1
- package/cloudflare-router-ab/build/deriver-a/index_bg.wasm +0 -0
- package/cloudflare-router-ab/build/deriver-b/build-stamp.json +1 -1
- package/cloudflare-router-ab/build/deriver-b/index_bg.wasm +0 -0
- package/cloudflare-router-ab/build/local-tools/darwin-arm64/router_ab_local_init +0 -0
- package/cloudflare-router-ab/build/local-tools/darwin-x64/router_ab_local_init +0 -0
- package/cloudflare-router-ab/build/local-tools/linux-x64/router_ab_local_init +0 -0
- package/cloudflare-router-ab/build/router/build-stamp.json +1 -1
- package/cloudflare-router-ab/build/router/index_bg.wasm +0 -0
- package/cloudflare-router-ab/build/signing-worker/build-stamp.json +1 -1
- package/cloudflare-router-ab/build/signing-worker/index_bg.wasm +0 -0
- package/cloudflare-router-ab/build/tenant-root-control-plane/build-stamp.json +1 -1
- package/cloudflare-router-ab/build/tenant-root-control-plane/index_bg.wasm +0 -0
- package/dist/esm/authorization/service.js +8 -0
- package/dist/esm/authorization/vaultProxyUse.js +2 -6
- package/dist/esm/cloud-host.js +4 -4
- package/dist/esm/core/IdentityStore.js +23 -110
- package/dist/esm/core/SessionService.js +7 -30
- package/dist/esm/core/ThresholdService/routerAbNormalSigningPolicy.js +3 -10
- package/dist/esm/core/ThresholdService/stores/WalletSessionStore.js +21 -97
- package/dist/esm/core/ThresholdService/stores/exportReplayGuard.js +7 -0
- package/dist/esm/core/WalletStore.js +4 -6
- package/dist/esm/core/authService/bytes.js +1 -4
- package/dist/esm/core/authService/emailOtpChallengeOperations.js +2 -5
- package/dist/esm/core/authService/emailOtpChallengeProof.js +9 -40
- package/dist/esm/core/authService/emailOtpChallengeVerification.js +19 -90
- package/dist/esm/core/authService/emailOtpChallenges.js +10 -45
- package/dist/esm/core/authService/emailOtpDelivery.js +10 -45
- package/dist/esm/core/authService/emailOtpEnrollment.js +9 -40
- package/dist/esm/core/authService/emailOtpGrant.js +9 -40
- package/dist/esm/core/authService/emailOtpRegistrationEnrollment.js +9 -40
- package/dist/esm/core/authService/emailOtpSeal.js +5 -20
- package/dist/esm/core/authService/emailOtpUnlock.js +20 -110
- package/dist/esm/core/authService/googleEmailOtpRegistration.js +28 -115
- package/dist/esm/core/authService/identity.js +5 -20
- package/dist/esm/core/authService/nearPublicKeyMetadata.js +6 -25
- package/dist/esm/core/authService/oidcVerification.js +22 -34
- package/dist/esm/core/authService/rateLimits.js +2 -5
- package/dist/esm/core/authService/thresholdEcdsaKeyInventory.js +2 -1
- package/dist/esm/core/authService/webauthn.js +37 -191
- package/dist/esm/core/authService/webauthnVerificationOutcomes.js +5 -24
- package/dist/esm/core/d1EcdsaSignerRead.js +76 -0
- package/dist/esm/core/d1IdentityStore.js +16 -75
- package/dist/esm/core/d1TenantStore.js +1 -1
- package/dist/esm/core/d1WalletStore.js +15 -25
- package/dist/esm/core/deviceLinking/linkedDeviceEmailOtpGrant.js +1 -5
- package/dist/esm/core/deviceLinking/linkedDeviceSessionApproval.js +1 -3
- package/dist/esm/core/deviceLinking/linkedDeviceSessionRecord.js +2 -8
- package/dist/esm/core/deviceLinking/requestProof.js +13 -4
- package/dist/esm/core/ecdsaMaterialReadSnapshot.js +85 -0
- package/dist/esm/core/nearRelayerAccountProvisioning.js +2 -5
- package/dist/esm/core/signingLanes/WalletExecutionLaneProjection.js +3 -6
- package/dist/esm/core/signingMaterial/ordinaryInactiveSignerMaterialReservation.js +2 -5
- package/dist/esm/core/storeBackends.js +1 -1
- package/dist/esm/core/thresholdEcdsaChainTarget.js +1 -3
- package/dist/esm/hosted-wallet-gateway.js +2 -2
- package/dist/esm/localHostedWalletGatewayHandler.js +13 -0
- package/dist/esm/localIntendedMaterialAdmissionFault.js +176 -0
- package/dist/esm/localIntendedPresignCancellation.js +44 -0
- package/dist/esm/router/auth/commonRouterUtils.js +24 -10
- package/dist/esm/router/auth/walletSessionFailure.js +2 -5
- package/dist/esm/router/auth/webAuthnCredentialCodecs.js +4 -15
- package/dist/esm/router/cloudflare/d1/auth/d1AuthorizedOperationRouteService.js +1 -0
- package/dist/esm/router/cloudflare/d1/auth/d1RouterApiAuthBoundary.js +2 -6
- package/dist/esm/router/cloudflare/d1/auth/d1RouterApiAuthService.js +5 -27
- package/dist/esm/router/cloudflare/d1/auth/walletSessionCredentialReaders.js +76 -0
- package/dist/esm/router/cloudflare/d1/authorization/authorizedOperationStatements.js +28 -21
- package/dist/esm/router/cloudflare/d1/authorization/d1AuthorizationStore.js +209 -44
- package/dist/esm/router/cloudflare/d1/authorization/d1VaultProxyStore.js +8 -12
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceAuthorityInstallService.js +50 -8
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceTargetCredentialProvider.js +1 -1
- package/dist/esm/router/cloudflare/d1/deviceLinking/index.js +3 -3
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeIssuer.js +12 -55
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeService.js +17 -80
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpDeliveryRuntime.js +6 -25
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRecords.js +12 -47
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRecoveryService.js +24 -85
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRegistrationEnrollmentFinalizer.js +7 -30
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpServerSealRuntime.js +5 -20
- package/dist/esm/router/cloudflare/d1/emailOtp/d1GoogleEmailOtpSessionResolver.js +23 -110
- package/dist/esm/router/cloudflare/d1/identity/d1IdentityService.js +9 -40
- package/dist/esm/router/cloudflare/d1/near/d1NearPublicKeyStore.js +3 -10
- package/dist/esm/router/cloudflare/d1/oidc/d1OidcBoundary.js +18 -91
- package/dist/esm/router/cloudflare/d1/oidc/d1OidcVerificationService.js +6 -30
- package/dist/esm/router/cloudflare/d1/passkeyCustody/d1PasskeyCustodyRouteService.js +4 -15
- package/dist/esm/router/cloudflare/d1/passkeyCustody/d1WalletCustodyCommitStore.js +2 -7
- package/dist/esm/router/cloudflare/d1/passkeyCustody/d1WalletRecoveryGoogleEmailOtpRecords.js +9 -13
- package/dist/esm/router/cloudflare/d1/passkeyCustody/d1WalletRecoveryGoogleEmailOtpService.js +11 -50
- package/dist/esm/router/cloudflare/d1/registration/d1EvmFamilyEcdsaRegistrationBranch.js +5 -20
- package/dist/esm/router/cloudflare/d1/registration/d1RegistrationCeremonyRecordStore.js +4 -7
- package/dist/esm/router/cloudflare/d1/registration/d1RegistrationCeremonyRecords.js +2 -1
- package/dist/esm/router/cloudflare/d1/registration/d1RegistrationIntentService.js +7 -30
- package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationService.js +32 -22
- package/dist/esm/router/cloudflare/d1/registration/walletRegistrationSessionCommitReceipt.js +1 -4
- package/dist/esm/router/cloudflare/d1/signingAdmission/d1RouterAbNormalSigningAdmissionStore.js +119 -25
- package/dist/esm/router/cloudflare/d1/webauthn/d1WebAuthnAuthService.js +31 -168
- package/dist/esm/router/cloudflare/d1/webauthn/d1WebAuthnRecords.js +6 -9
- package/dist/esm/router/cloudflare/durableObjects/thresholdStore.js +59 -66
- package/dist/esm/router/cloudflare/runtime/routerAbPrewarm.js +2 -2
- package/dist/esm/router/cloudflare/runtime/staticWalletConsoleBinding.js +5 -20
- package/dist/esm/router/cloudflare/runtime/tenantRootCreationGrant.js +2 -9
- package/dist/esm/router/cloudflare/runtime/walletControlOps.js +2 -1
- package/dist/esm/router/cloudflare/signingLanes/cloudflareLaneCurveExecution.js +2 -1
- package/dist/esm/router/cloudflare/signingLanes/cloudflareLaneProtocolCommitter.js +2 -2
- package/dist/esm/router/cloudflare.js +2146 -1802
- package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationPersistence.js +5 -8
- package/dist/esm/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecoveryWalletSessionAuthorization.js +3 -6
- package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationIntentAuthorization.js +6 -25
- package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationSideEffectBoundary.js +39 -55
- package/dist/esm/router/domains/emailOtp/emailOtpRouteHandlers.js +15 -62
- package/dist/esm/router/domains/signingOperations/routerAbEcdsaDerivationNormalSigningRoute.js +83 -74
- package/dist/esm/router/domains/signingOperations/routerAbNormalSigningAdmission.js +1 -0
- package/dist/esm/router/domains/signingOperations/routerAbOperationStepUp.js +1 -0
- package/dist/esm/router/domains/signingOperations/walletExecutionAdmission.js +1 -4
- package/dist/esm/router/domains/tenantRoot/tenantRootIdentityResolution.js +7 -13
- package/dist/esm/router/domains/walletUnlock/walletUnlockRouteHandlers.js +41 -200
- package/dist/esm/router/express.js +317 -699
- package/dist/esm/router/framework/http.js +5 -1
- package/dist/esm/router/framework/runtimeSnapshotConsumer.js +8 -35
- package/dist/esm/router/transport/fetch/createFetchRouter.js +3 -6
- package/dist/esm/router/transport/fetch/routes/auth.js +9 -41
- package/dist/esm/router/transport/fetch/routes/deviceLinkingOwnerAuthorization.js +5 -22
- package/dist/esm/router/transport/fetch/routes/nearPublicKeys.js +4 -16
- package/dist/esm/router/transport/fetch/routes/sessions.js +1 -0
- package/dist/esm/router/transport/fetch/routes/syncAccount.js +8 -36
- package/dist/esm/router/transport/fetch/routes/thresholdEcdsa.js +27 -79
- package/dist/esm/router/transport/fetch/routes/walletExecutionLanePreflight.js +4 -1
- package/dist/esm/router/transport/fetch/routes/webauthnAuthenticators.js +4 -16
- package/dist/esm/shared-ts/src/authorization/walletSignerActivationEquality.js +12 -0
- package/dist/esm/shared-ts/src/device-linking/committedSignerPackages.js +2 -5
- package/dist/esm/shared-ts/src/device-linking/delegatedActivationPlan.js +1 -5
- package/dist/esm/shared-ts/src/device-linking/ed25519ExportRoot.js +12 -16
- package/dist/esm/shared-ts/src/device-linking/sourceContribution.js +5 -8
- package/dist/esm/shared-ts/src/passkey-custody/primitives.js +5 -1
- package/dist/esm/shared-ts/src/signing-lanes/ownerContinuity.js +4 -8
- package/dist/esm/shared-ts/src/tenant-root/tenantRootIdentifier.js +12 -0
- package/dist/esm/shared-ts/src/tenant-root/tenantRootIdentity.js +2 -9
- package/dist/esm/shared-ts/src/tenant-root/tenantRootOperationRecord.js +1 -4
- package/dist/esm/shared-ts/src/utils/ecdsaKeyFactsInventory.js +2 -4
- package/dist/esm/shared-ts/src/utils/ecdsaServerTiming.js +0 -1
- package/dist/esm/shared-ts/src/utils/emailOtpDomain.js +3 -1
- package/dist/esm/shared-ts/src/utils/exactKeys.js +17 -0
- package/dist/esm/shared-ts/src/utils/failure.js +20 -0
- package/dist/esm/shared-ts/src/utils/registrationIntent.js +3 -12
- package/dist/esm/shared-ts/src/utils/registrationSignerPlan.js +2 -5
- package/dist/esm/shared-ts/src/utils/routerAbEcdsaDerivation.js +1 -1
- package/dist/esm/shared-ts/src/utils/routerAbEd25519Yao.js +1 -1
- package/dist/esm/shared-ts/src/utils/thresholdEcdsaChainTarget.js +9 -0
- package/dist/esm/shared-ts/src/wallet-recovery/walletRecoveryCommittedProjection.js +1 -4
- package/dist/esm/threshold/session/signingSessionSeal/crypto/cipher.js +10 -32
- package/dist/esm/threshold/session/signingSessionSeal/idempotencyBackends.js +3 -3
- package/dist/esm/threshold/session/signingSessionSeal/idempotencyRecords.js +3 -9
- package/dist/esm/threshold/session/signingSessionSeal/service.js +8 -35
- package/dist/esm/threshold/session/signingSessionSeal/transport/express.js +18 -94
- package/dist/esm/threshold/session/signingSessionSeal/transport/fetch.js +6 -30
- package/dist/esm/threshold/session/signingSessionSeal/transport/shared.js +5 -20
- package/dist/esm/wasm/evm_crypto/pkg/evm_crypto_bg.wasm +0 -0
- package/dist/esm/wasm/near_signer/pkg/wasm_signer_worker_bg.wasm +0 -0
- package/dist/types/shared-ts/src/authorization/delegatedAuthority.d.ts +2 -1
- package/dist/types/shared-ts/src/authorization/walletSessionIssuance.d.ts +9 -2
- package/dist/types/shared-ts/src/authorization/walletSignerActivationEquality.d.ts +4 -0
- package/dist/types/shared-ts/src/device-linking/committedSignerPackages.d.ts +3 -4
- package/dist/types/shared-ts/src/device-linking/contracts.d.ts +5 -63
- package/dist/types/shared-ts/src/device-linking/sourceContribution.d.ts +2 -0
- package/dist/types/shared-ts/src/passkey-custody/custodyEnvelope.d.ts +5 -12
- package/dist/types/shared-ts/src/passkey-custody/primitives.d.ts +9 -0
- package/dist/types/shared-ts/src/signing-lanes/execution.d.ts +11 -1
- package/dist/types/shared-ts/src/signing-lanes/ids.d.ts +1 -10
- package/dist/types/shared-ts/src/signing-lanes/rotation.d.ts +3 -5
- package/dist/types/shared-ts/src/tenant-root/tenantRootIdentifier.d.ts +3 -0
- package/dist/types/shared-ts/src/tenant-root/tenantRootOperationRecord.d.ts +2 -1
- package/dist/types/shared-ts/src/threshold/ecdsaDerivationRoleLocalBootstrap.d.ts +6 -0
- package/dist/types/shared-ts/src/threshold/signingRootScope.d.ts +1 -0
- package/dist/types/shared-ts/src/utils/ecdsaKeyFactsInventory.d.ts +2 -11
- package/dist/types/shared-ts/src/utils/eip1559TxWasmJson.d.ts +16 -0
- package/dist/types/shared-ts/src/utils/emailOtpDomain.d.ts +2 -0
- package/dist/types/shared-ts/src/utils/exactKeys.d.ts +11 -0
- package/dist/types/shared-ts/src/utils/failure.d.ts +12 -0
- package/dist/types/shared-ts/src/utils/jsonRpc.d.ts +3 -4
- package/dist/types/shared-ts/src/utils/nearRpcResults.d.ts +1 -0
- package/dist/types/shared-ts/src/utils/registrationAuthMethodInput.d.ts +3 -8
- package/dist/types/shared-ts/src/utils/registrationSignerPlan.d.ts +7 -19
- package/dist/types/shared-ts/src/utils/routerAbEcdsaDerivation.d.ts +3 -1
- package/dist/types/shared-ts/src/utils/routerAbEd25519Yao.d.ts +1 -0
- package/dist/types/shared-ts/src/utils/routerAbEd25519YaoDigests.d.ts +3 -4
- package/dist/types/shared-ts/src/utils/routerAbNormalSigningIdentity.d.ts +30 -8
- package/dist/types/shared-ts/src/utils/routerApiKeyAuth.d.ts +2 -0
- package/dist/types/shared-ts/src/utils/signingSessionSeal.d.ts +10 -11
- package/dist/types/shared-ts/src/utils/thresholdEcdsaChainTarget.d.ts +25 -0
- package/dist/types/shared-ts/src/utils/variant.d.ts +18 -0
- package/dist/types/shared-ts/src/utils/walletAuthMethodRecord.d.ts +3 -6
- package/dist/types/shared-ts/src/utils/webauthnDeviceInfo.d.ts +4 -2
- package/dist/types/shared-ts/src/wallet-recovery/recoveryEnvelopes.d.ts +3 -16
- package/dist/types/shared-ts/src/wallet-recovery/walletRecoveryPreparation.d.ts +15 -0
- package/dist/types/shared-ts/src/wallet-recovery/walletRecoveryTarget.d.ts +3 -4
- package/dist/types/wallet-server/src/authorization/domain.d.ts +13 -2
- package/dist/types/wallet-server/src/authorization/ecdsaWalletSessionAdmission.d.ts +27 -3
- package/dist/types/wallet-server/src/authorization/service.d.ts +19 -0
- package/dist/types/wallet-server/src/core/ThresholdService/stores/SessionStore.d.ts +2 -2
- package/dist/types/wallet-server/src/core/ThresholdService/stores/WalletSessionStore.d.ts +1 -1
- package/dist/types/wallet-server/src/core/ThresholdService/stores/exportReplayGuard.d.ts +3 -0
- package/dist/types/wallet-server/src/core/ThresholdService/validation.d.ts +8 -101
- package/dist/types/wallet-server/src/core/WebAuthnAuthenticatorStore.d.ts +8 -0
- package/dist/types/wallet-server/src/core/authService/bytes.d.ts +0 -1
- package/dist/types/wallet-server/src/core/authService/emailOtpChallenges.d.ts +2 -10
- package/dist/types/wallet-server/src/core/authService/emailOtpSeal.d.ts +1 -1
- package/dist/types/wallet-server/src/core/authService/emailOtpUnlock.d.ts +3 -10
- package/dist/types/wallet-server/src/core/d1EcdsaSignerRead.d.ts +39 -0
- package/dist/types/wallet-server/src/core/d1WalletStore.d.ts +10 -0
- package/dist/types/wallet-server/src/core/deviceLinking/linkedDeviceSessionRecord.d.ts +3 -4
- package/dist/types/wallet-server/src/core/ecdsaMaterialReadSnapshot.d.ts +19 -0
- package/dist/types/wallet-server/src/core/routerAbSigning/RouterAbNormalSigningRuntime.d.ts +3 -5
- package/dist/types/wallet-server/src/core/rpcClients/near/NearClient.d.ts +1 -2
- package/dist/types/wallet-server/src/core/signingLanes/WalletExecutionLaneProjection.d.ts +2 -11
- package/dist/types/wallet-server/src/core/signingLanes/signingWorkerLaneMaterialIdentity.d.ts +2 -19
- package/dist/types/wallet-server/src/core/thresholdEcdsaChainTarget.d.ts +3 -11
- package/dist/types/wallet-server/src/core/types.d.ts +2 -6
- package/dist/types/wallet-server/src/localIntendedMaterialAdmissionFault.d.ts +38 -0
- package/dist/types/wallet-server/src/localIntendedPresignCancellation.d.ts +4 -0
- package/dist/types/wallet-server/src/router/auth/authRequestValidation.d.ts +4 -9
- package/dist/types/wallet-server/src/router/auth/commonRouterUtils.d.ts +15 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/auth/d1RouterApiAuthBoundary.d.ts +0 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/auth/d1RouterApiAuthService.d.ts +1 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/auth/walletSessionCredentialReaders.d.ts +9 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/authorization/authorizedOperationStatements.d.ts +4 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/authorization/d1AuthorizationStore.d.ts +10 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceAuthorityInstallService.d.ts +19 -2
- package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceSessionStore.d.ts +2 -6
- package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceTargetCredentialProvider.d.ts +5 -8
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpEnrollmentStore.d.ts +2 -8
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpRateLimitStore.d.ts +2 -9
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpRecords.d.ts +5 -5
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpServerSealRuntime.d.ts +4 -14
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationCeremonyRecordStore.d.ts +2 -6
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationService.d.ts +8 -6
- package/dist/types/wallet-server/src/router/cloudflare/d1/signingAdmission/d1RouterAbNormalSigningAdmissionStore.d.ts +14 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/webauthn/d1WebAuthnRecords.d.ts +10 -39
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletConsoleOps.d.ts +8 -34
- package/dist/types/wallet-server/src/router/domains/ecdsa/thresholdEcdsaRequestValidation.d.ts +3 -15
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/session/routerAbEd25519YaoWalletSession.d.ts +9 -50
- package/dist/types/wallet-server/src/router/domains/passkeyCustody/walletRecoveryKeyManifest.d.ts +1 -13
- package/dist/types/wallet-server/src/router/domains/signingOperations/routerAbEcdsaDerivationNormalSigningRoute.d.ts +8 -9
- package/dist/types/wallet-server/src/router/domains/signingOperations/routerAbNormalSigningAdmission.d.ts +13 -0
- package/dist/types/wallet-server/src/router/domains/signingOperations/routerAbOperationStepUp.d.ts +3 -4
- package/dist/types/wallet-server/src/router/domains/signingOperations/routerAbPrivateSigningWorker.d.ts +7 -16
- package/dist/types/wallet-server/src/router/domains/syncAccount/syncAccountRequestValidation.d.ts +2 -7
- package/dist/types/wallet-server/src/router/framework/apiCredentialPorts.d.ts +3 -1
- package/dist/types/wallet-server/src/router/framework/authServicePort.d.ts +25 -4
- package/dist/types/wallet-server/src/router/framework/http.d.ts +1 -0
- package/dist/types/wallet-server/src/router/framework/ror/normalize.d.ts +1 -9
- package/dist/types/wallet-server/src/router/transport/fetch/routes/deviceLinkingOwnerAuthorization.d.ts +3 -6
- package/dist/types/wallet-server/src/router/transport/fetch/routes/syncAccountBootstrap.d.ts +3 -5
- package/dist/types/wallet-server/src/router/transport/fetch/routes/thresholdEcdsa.d.ts +0 -1
- package/dist/types/wallet-server/src/threshold/session/signingSessionSeal/idempotencyRecords.d.ts +1 -2
- package/dist/types/wallet-server/src/threshold/session/signingSessionSeal/signingSessionSeal.types.d.ts +6 -8
- package/package.json +1 -1
- package/dist/esm/wasm/router_ab_ecdsa_signing_worker/pkg/router_ab_ecdsa_signing_worker_bg.wasm +0 -0
|
@@ -38,6 +38,15 @@ function normalizeLogger(logger) {
|
|
|
38
38
|
//#region src/router/framework/logger.ts
|
|
39
39
|
const coerceRouterLogger = normalizeLogger;
|
|
40
40
|
//#endregion
|
|
41
|
+
//#region ../shared-ts/src/utils/failure.ts
|
|
42
|
+
function failure(code, message) {
|
|
43
|
+
return {
|
|
44
|
+
ok: false,
|
|
45
|
+
code,
|
|
46
|
+
message
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
//#endregion
|
|
41
50
|
//#region src/core/SessionService.ts
|
|
42
51
|
function normalizeParsedCorsOrigin(url) {
|
|
43
52
|
const host = url.hostname.toLowerCase();
|
|
@@ -984,6 +993,10 @@ function requireCanonicalBase64Url(value, label) {
|
|
|
984
993
|
if (base64UrlEncode(decoded) !== value) throw new Error(`${label} must be canonical base64url`);
|
|
985
994
|
return decoded;
|
|
986
995
|
}
|
|
996
|
+
function requireParsed$2(result, label) {
|
|
997
|
+
if (result.ok) return result.value;
|
|
998
|
+
throw new Error(`${label} ${result.error.message}`);
|
|
999
|
+
}
|
|
987
1000
|
function parseDigestField$2(value, label) {
|
|
988
1001
|
try {
|
|
989
1002
|
return parseDigestB64u(value);
|
|
@@ -1204,11 +1217,11 @@ function parseLinkedDeviceEd25519ExportRootRecipientV1(raw) {
|
|
|
1204
1217
|
requireTransferAlg(record.transferAlg, "LinkedDeviceEd25519ExportRootRecipientV1.transferAlg");
|
|
1205
1218
|
return {
|
|
1206
1219
|
kind: "linked_device_ed25519_export_root_recipient_v1",
|
|
1207
|
-
linkSessionId:
|
|
1208
|
-
walletId:
|
|
1209
|
-
walletKeyId:
|
|
1210
|
-
enrollmentId:
|
|
1211
|
-
deviceId:
|
|
1220
|
+
linkSessionId: requireParsed$2(parseLinkDeviceSessionId(record.linkSessionId), "LinkedDeviceEd25519ExportRootRecipientV1.linkSessionId"),
|
|
1221
|
+
walletId: requireParsed$2(parseWalletId(record.walletId), "walletId"),
|
|
1222
|
+
walletKeyId: requireParsed$2(parseWalletKeyId(record.walletKeyId), "walletKeyId"),
|
|
1223
|
+
enrollmentId: requireParsed$2(parseLinkedDeviceEnrollmentId(record.enrollmentId), "enrollmentId"),
|
|
1224
|
+
deviceId: requireParsed$2(parseLinkedDeviceId(record.deviceId), "deviceId"),
|
|
1212
1225
|
transferAlg: LINKED_DEVICE_ED25519_EXPORT_ROOT_TRANSFER_ALG_V1,
|
|
1213
1226
|
applicationBindingDigestB64u: parseDigestField$2(record.applicationBindingDigestB64u, "applicationBindingDigestB64u"),
|
|
1214
1227
|
registeredPublicKeyB64u: parseEd25519PublicKeyB64u(record.registeredPublicKeyB64u, "registeredPublicKeyB64u"),
|
|
@@ -1227,11 +1240,11 @@ function parseLinkedDeviceEd25519ExportRootPackageV1(raw) {
|
|
|
1227
1240
|
if (recipientPublicKeyB64u === ephemeralPublicKeyB64u) throw new Error("ephemeralPublicKeyB64u repeats the recipient key");
|
|
1228
1241
|
return {
|
|
1229
1242
|
kind: "linked_device_ed25519_export_root_package_v1",
|
|
1230
|
-
linkSessionId:
|
|
1231
|
-
walletId:
|
|
1232
|
-
walletKeyId:
|
|
1233
|
-
enrollmentId:
|
|
1234
|
-
deviceId:
|
|
1243
|
+
linkSessionId: requireParsed$2(parseLinkDeviceSessionId(record.linkSessionId), "linkSessionId"),
|
|
1244
|
+
walletId: requireParsed$2(parseWalletId(record.walletId), "walletId"),
|
|
1245
|
+
walletKeyId: requireParsed$2(parseWalletKeyId(record.walletKeyId), "walletKeyId"),
|
|
1246
|
+
enrollmentId: requireParsed$2(parseLinkedDeviceEnrollmentId(record.enrollmentId), "enrollmentId"),
|
|
1247
|
+
deviceId: requireParsed$2(parseLinkedDeviceId(record.deviceId), "deviceId"),
|
|
1235
1248
|
transferAlg: LINKED_DEVICE_ED25519_EXPORT_ROOT_TRANSFER_ALG_V1,
|
|
1236
1249
|
applicationBindingDigestB64u: parseDigestField$2(record.applicationBindingDigestB64u, "applicationBindingDigestB64u"),
|
|
1237
1250
|
registeredPublicKeyB64u: parseEd25519PublicKeyB64u(record.registeredPublicKeyB64u, "registeredPublicKeyB64u"),
|
|
@@ -1251,7 +1264,7 @@ function parseLinkedDeviceEd25519ExportRootSubmissionV1(raw) {
|
|
|
1251
1264
|
if (record.kind !== "linked_device_ed25519_export_root_submission_v1") throw new Error("LinkedDeviceEd25519ExportRootSubmissionV1.kind is invalid");
|
|
1252
1265
|
return {
|
|
1253
1266
|
kind: "linked_device_ed25519_export_root_submission_v1",
|
|
1254
|
-
linkSessionId:
|
|
1267
|
+
linkSessionId: requireParsed$2(parseLinkDeviceSessionId(record.linkSessionId), "linkSessionId"),
|
|
1255
1268
|
package: parseLinkedDeviceEd25519ExportRootPackageV1(record.package)
|
|
1256
1269
|
};
|
|
1257
1270
|
}
|
|
@@ -1279,10 +1292,6 @@ function parseUnixMs(value, label) {
|
|
|
1279
1292
|
if (typeof value !== "number" || !Number.isSafeInteger(value) || value <= 0) throw new Error(`${label} must be a positive unix-millisecond timestamp`);
|
|
1280
1293
|
return value;
|
|
1281
1294
|
}
|
|
1282
|
-
function parseRequired(parsed, label) {
|
|
1283
|
-
if (!parsed.ok) throw new Error(`${label} ${parsed.error.message}`);
|
|
1284
|
-
return parsed.value;
|
|
1285
|
-
}
|
|
1286
1295
|
//#endregion
|
|
1287
1296
|
//#region ../shared-ts/src/device-linking/delegatedActivationPlan.ts
|
|
1288
1297
|
const MANIFEST_FIELDS = [
|
|
@@ -1406,10 +1415,6 @@ function exactRecord$2(raw, fields, label) {
|
|
|
1406
1415
|
for (const field of fields) if (!(field in record)) throw new Error(`${label}.${field} is required`);
|
|
1407
1416
|
return record;
|
|
1408
1417
|
}
|
|
1409
|
-
function requireParsed$2(parsed, label) {
|
|
1410
|
-
if (!parsed.ok) throw new Error(`${label} ${parsed.error.message}`);
|
|
1411
|
-
return parsed.value;
|
|
1412
|
-
}
|
|
1413
1418
|
//#endregion
|
|
1414
1419
|
//#region ../shared-ts/src/utils/addAuthMethodRegistration.ts
|
|
1415
1420
|
/**
|
|
@@ -3874,7 +3879,7 @@ function parseLinkedDeviceEd25519SourcePreservingReservationV1(raw) {
|
|
|
3874
3879
|
const participantIds = parseRouterAbEd25519YaoParticipantIdsV1(record.participant_ids);
|
|
3875
3880
|
const deriverA = parseEd25519ClientPackage(record.deriver_a_client_package, "deriver_a");
|
|
3876
3881
|
const deriverB = parseEd25519ClientPackage(record.deriver_b_client_package, "deriver_b");
|
|
3877
|
-
if (!
|
|
3882
|
+
if (!sameRouterAbEd25519YaoByteSequence(activationReceipt.transcript, deriverA.transcript) || !sameRouterAbEd25519YaoByteSequence(activationReceipt.transcript, deriverB.transcript)) throw new Error("linked-device Ed25519 reservation packages have mismatched transcripts");
|
|
3878
3883
|
return {
|
|
3879
3884
|
state: "inactive",
|
|
3880
3885
|
reservationId: requireText(record.reservation_id, "reservation_id"),
|
|
@@ -4033,10 +4038,10 @@ function parseEd25519Contribution(record) {
|
|
|
4033
4038
|
if (!sameEdStableIdentity(sourceBinding, targetBinding)) throw new Error("linked-device Ed25519 source contribution stable identity differs");
|
|
4034
4039
|
if (!mpcMaterialActivationRefsEqual(routerAbMpcMaterialActivationRefFromWire(activationReceipt.material_activation), targetMaterialActivation)) throw new Error("linked-device Ed25519 source contribution receipt activation differs");
|
|
4035
4040
|
const sourceRegisteredPublicKeyB64u = parseEd25519PublicKeyB64u(record.sourceRegisteredPublicKeyB64u, "sourceRegisteredPublicKeyB64u");
|
|
4036
|
-
if (!
|
|
4041
|
+
if (!sameRouterAbEd25519YaoByteSequence(activationReceipt.registered_public_key, Array.from(base64UrlDecode(sourceRegisteredPublicKeyB64u)))) throw new Error("linked-device Ed25519 source contribution receipt public key differs");
|
|
4037
4042
|
const deriverA = parseEd25519ClientPackage(record.deriver_a_client_package, "deriver_a");
|
|
4038
4043
|
const deriverB = parseEd25519ClientPackage(record.deriver_b_client_package, "deriver_b");
|
|
4039
|
-
if (!
|
|
4044
|
+
if (!sameRouterAbEd25519YaoByteSequence(activationReceipt.transcript, deriverA.transcript) || !sameRouterAbEd25519YaoByteSequence(activationReceipt.transcript, deriverB.transcript)) throw new Error("linked-device Ed25519 source contribution package transcript differs");
|
|
4040
4045
|
if (sourceBinding.material_activation.activation_id === targetMaterialActivation.activationId) throw new Error("linked-device Ed25519 source contribution reuses the source activation");
|
|
4041
4046
|
return {
|
|
4042
4047
|
kind: "linked_device_ed25519_source_contribution_v1",
|
|
@@ -4316,9 +4321,6 @@ function parseFixedBase64(raw, byteLength, label) {
|
|
|
4316
4321
|
if (decoded.length !== byteLength || base64UrlEncode(decoded) !== raw) throw new Error(`${label} must decode to ${byteLength} bytes`);
|
|
4317
4322
|
return raw;
|
|
4318
4323
|
}
|
|
4319
|
-
function sameBytes(left, right) {
|
|
4320
|
-
return left.length === right.length && left.every((value, index) => value === right[index]);
|
|
4321
|
-
}
|
|
4322
4324
|
function requireText(raw, label) {
|
|
4323
4325
|
if (typeof raw !== "string" || raw.length === 0 || raw.trim() !== raw || [...raw].some((character) => {
|
|
4324
4326
|
const code = character.charCodeAt(0);
|
|
@@ -5441,6 +5443,9 @@ function json$1(body, init, extraHeaders) {
|
|
|
5441
5443
|
headers
|
|
5442
5444
|
});
|
|
5443
5445
|
}
|
|
5446
|
+
function jsonFailure(status, code, message) {
|
|
5447
|
+
return json$1(failure(code, message), { status });
|
|
5448
|
+
}
|
|
5444
5449
|
function withCors(headers, opts, request) {
|
|
5445
5450
|
const pathname = request ? new URL(request.url).pathname : "";
|
|
5446
5451
|
if (pathname === "/healthz" || pathname === "/readyz") {
|
|
@@ -5479,6 +5484,13 @@ async function readJson(request) {
|
|
|
5479
5484
|
return null;
|
|
5480
5485
|
}
|
|
5481
5486
|
}
|
|
5487
|
+
function headersToRecord(headers) {
|
|
5488
|
+
const out = {};
|
|
5489
|
+
headers.forEach((v, k) => {
|
|
5490
|
+
out[k] = v;
|
|
5491
|
+
});
|
|
5492
|
+
return out;
|
|
5493
|
+
}
|
|
5482
5494
|
//#endregion
|
|
5483
5495
|
//#region src/router/transport/fetch/routes/health.ts
|
|
5484
5496
|
async function handleHealth(ctx) {
|
|
@@ -5611,6 +5623,12 @@ async function resolvePublishableKeyApiCredentialAuth(input) {
|
|
|
5611
5623
|
};
|
|
5612
5624
|
}
|
|
5613
5625
|
//#endregion
|
|
5626
|
+
//#region ../shared-ts/src/utils/thresholdEcdsaChainTarget.ts
|
|
5627
|
+
function thresholdEcdsaChainTargetKey(target) {
|
|
5628
|
+
if (target.kind === "evm") return `evm:eip155:${target.chainId}`;
|
|
5629
|
+
return `tempo:${target.chainId}`;
|
|
5630
|
+
}
|
|
5631
|
+
//#endregion
|
|
5614
5632
|
//#region src/core/thresholdEcdsaChainTarget.ts
|
|
5615
5633
|
function positiveSafeInteger(value) {
|
|
5616
5634
|
return typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? value : null;
|
|
@@ -5671,11 +5689,7 @@ function walletSessionFailureStatus(code) {
|
|
|
5671
5689
|
}
|
|
5672
5690
|
}
|
|
5673
5691
|
function walletSessionFailure(code) {
|
|
5674
|
-
return
|
|
5675
|
-
ok: false,
|
|
5676
|
-
code,
|
|
5677
|
-
message: walletSessionFailureMessage(code)
|
|
5678
|
-
};
|
|
5692
|
+
return failure(code, walletSessionFailureMessage(code));
|
|
5679
5693
|
}
|
|
5680
5694
|
//#endregion
|
|
5681
5695
|
//#region ../shared-ts/src/signing-lanes/participants.ts
|
|
@@ -5771,10 +5785,6 @@ const OWNER_LANE_PARTICIPANT_CONTINUITY_FIELDS = [
|
|
|
5771
5785
|
"custodyKeyManifestDigestB64u",
|
|
5772
5786
|
"sourceIdentityDigestB64u"
|
|
5773
5787
|
];
|
|
5774
|
-
function requireResult(result, label) {
|
|
5775
|
-
if (result.ok) return result.value;
|
|
5776
|
-
throw new Error(`${label} ${result.error.message}`);
|
|
5777
|
-
}
|
|
5778
5788
|
/** Parse the owner signer identity without widening it into a generic string. */
|
|
5779
5789
|
function parseWalletSignerId(raw, label = "walletSignerId") {
|
|
5780
5790
|
if (typeof raw !== "string") throw new Error(`${label} must be a string`);
|
|
@@ -5800,7 +5810,7 @@ function buildOwnerLaneParticipantContinuityV1(args) {
|
|
|
5800
5810
|
kind: "owner_lane_participant_continuity_v1",
|
|
5801
5811
|
signerId: parseWalletSignerId(args.signerId),
|
|
5802
5812
|
participantIds,
|
|
5803
|
-
signingWorkerId:
|
|
5813
|
+
signingWorkerId: requireParsed$2(parseMpcSigningWorkerRef(args.signingWorkerId), "signingWorkerId"),
|
|
5804
5814
|
custodyKeyManifestDigestB64u: parseDigestField$2(args.custodyKeyManifestDigestB64u, "custodyKeyManifestDigestB64u"),
|
|
5805
5815
|
sourceIdentityDigestB64u: parseDigestField$2(args.sourceIdentityDigestB64u, "sourceIdentityDigestB64u")
|
|
5806
5816
|
};
|
|
@@ -5812,7 +5822,7 @@ function parseOwnerLaneParticipantContinuityV1(raw, label = "ownerParticipantCon
|
|
|
5812
5822
|
return buildOwnerLaneParticipantContinuityV1({
|
|
5813
5823
|
signerId: parseWalletSignerId(record.signerId, `${label}.signerId`),
|
|
5814
5824
|
participantIds: parseParticipantIds$1(record.participantIds, `${label}.participantIds`),
|
|
5815
|
-
signingWorkerId:
|
|
5825
|
+
signingWorkerId: requireParsed$2(parseMpcSigningWorkerRef(record.signingWorkerId), `${label}.signingWorkerId`),
|
|
5816
5826
|
custodyKeyManifestDigestB64u: parseDigestField$2(record.custodyKeyManifestDigestB64u, `${label}.custodyKeyManifestDigestB64u`),
|
|
5817
5827
|
sourceIdentityDigestB64u: parseDigestField$2(record.sourceIdentityDigestB64u, `${label}.sourceIdentityDigestB64u`)
|
|
5818
5828
|
});
|
|
@@ -5830,7 +5840,7 @@ function ownerLaneParticipantContinuityCanonicalBytesV1(input) {
|
|
|
5830
5840
|
]);
|
|
5831
5841
|
}
|
|
5832
5842
|
async function computeOwnerLaneParticipantBindingDigestV1(input) {
|
|
5833
|
-
return
|
|
5843
|
+
return requireParsed$2(parseLaneParticipantBindingDigestB64u(base64UrlEncode(await sha256Bytes(ownerLaneParticipantContinuityCanonicalBytesV1(input)))), "owner participant digest");
|
|
5834
5844
|
}
|
|
5835
5845
|
new TextEncoder();
|
|
5836
5846
|
//#endregion
|
|
@@ -6225,7 +6235,7 @@ async function prepareOwnerWalletExecution(input) {
|
|
|
6225
6235
|
if (lane.walletKeyId !== input.evidence.walletKey.walletKeyId) return refused("wallet_key_mismatch");
|
|
6226
6236
|
if (!operationMatchesWalletKey(input.authorizedOperation, input.evidence.walletKey)) return refused("curve_mismatch");
|
|
6227
6237
|
if (String(claimedOperation.operation.capabilityId) !== String(input.evidence.materialActivation.capability)) return refused("capability_mismatch");
|
|
6228
|
-
if (!
|
|
6238
|
+
if (!mpcMaterialActivationRefsEqual(input.evidence.materialActivation, input.evidence.expectedMaterialActivation)) return refused("material_activation_mismatch");
|
|
6229
6239
|
if (lane.participantBindingDigestB64u !== input.evidence.verifiedLaneParticipantBindingDigestB64u || String(lane.ownerParticipantContinuity.signingWorkerId) !== String(input.evidence.materialActivation.signingWorker)) return refused("participant_binding_mismatch");
|
|
6230
6240
|
if (await computeOwnerLaneParticipantBindingDigestV1(lane.ownerParticipantContinuity) !== lane.participantBindingDigestB64u) return refused("participant_binding_mismatch");
|
|
6231
6241
|
if (lane.lifecycle.activationReceiptDigestB64u !== input.evidence.verifiedActivationReceiptDigestB64u) return refused("activation_receipt_mismatch");
|
|
@@ -6273,9 +6283,6 @@ function operationMatchesWalletKey(operation, walletKey) {
|
|
|
6273
6283
|
case "ecdsa_secp256k1": return operation.operation.operation.capabilityKind === CAPABILITY_KINDS.evmEcdsaMpcSigning;
|
|
6274
6284
|
}
|
|
6275
6285
|
}
|
|
6276
|
-
function sameMaterialActivation(left, right) {
|
|
6277
|
-
return left.activationId === right.activationId && left.capability === right.capability && left.materialOwner === right.materialOwner && left.keyBinding === right.keyBinding && left.lifecycleBinding === right.lifecycleBinding && left.signingWorker === right.signingWorker;
|
|
6278
|
-
}
|
|
6279
6286
|
function refused(reason) {
|
|
6280
6287
|
return {
|
|
6281
6288
|
kind: "refused",
|
|
@@ -6472,32 +6479,46 @@ async function validateRouterAbEcdsaDerivationWalletSessionInputs(input) {
|
|
|
6472
6479
|
const token = extractBearerCredential(input.headers);
|
|
6473
6480
|
if (!token) return walletSessionFailure("wallet_session_missing");
|
|
6474
6481
|
const nowMs = input.nowMs || Date.now;
|
|
6475
|
-
let
|
|
6482
|
+
let candidate;
|
|
6476
6483
|
try {
|
|
6477
|
-
|
|
6478
|
-
authorizationSessions,
|
|
6484
|
+
candidate = await authorizationSessions.readWalletSessionSigningCandidateByOperationCredential({
|
|
6485
|
+
tenantId: authorizationSessions.tenantId,
|
|
6479
6486
|
token,
|
|
6480
6487
|
nowMs: nowMs(),
|
|
6481
|
-
|
|
6482
|
-
keyFamily: "ecdsa_secp256k1",
|
|
6483
|
-
operationKind: input.operationKind
|
|
6484
|
-
}
|
|
6488
|
+
materialActivation: input.materialActivation
|
|
6485
6489
|
});
|
|
6486
6490
|
} catch {
|
|
6487
6491
|
return walletSessionFailure("wallet_session_unavailable");
|
|
6488
6492
|
}
|
|
6489
|
-
if (
|
|
6490
|
-
if (resolution.kind === "not_found") return {
|
|
6493
|
+
if (!candidate) return {
|
|
6491
6494
|
ok: false,
|
|
6492
6495
|
code: "wallet_session_invalid",
|
|
6493
6496
|
message: walletSessionFailureMessage("wallet_session_invalid")
|
|
6494
6497
|
};
|
|
6498
|
+
if (candidate.kind === "exhausted") return {
|
|
6499
|
+
ok: true,
|
|
6500
|
+
kind: "wallet_session_operation_credential_exhausted_candidate_v1",
|
|
6501
|
+
candidate: candidate.candidate,
|
|
6502
|
+
materialRead: candidate.materialRead,
|
|
6503
|
+
policyRead: candidate.policyRead
|
|
6504
|
+
};
|
|
6505
|
+
const resolution = resolveWalletSessionOperationCredentialAdmissionFromContext({
|
|
6506
|
+
context: candidate.context,
|
|
6507
|
+
nowMs: nowMs(),
|
|
6508
|
+
operation: {
|
|
6509
|
+
keyFamily: "ecdsa_secp256k1",
|
|
6510
|
+
operationKind: input.operationKind
|
|
6511
|
+
}
|
|
6512
|
+
});
|
|
6513
|
+
if (resolution.kind === "rejected") return walletSessionFailure("wallet_session_scope_mismatch");
|
|
6495
6514
|
if (resolution.admission.curve !== "ecdsa") return walletSessionFailure("wallet_session_scope_mismatch");
|
|
6496
6515
|
return {
|
|
6497
6516
|
ok: true,
|
|
6498
6517
|
kind: "wallet_session_operation_credential_v1",
|
|
6499
6518
|
admission: resolution.admission,
|
|
6500
|
-
context: resolution.admission.context
|
|
6519
|
+
context: resolution.admission.context,
|
|
6520
|
+
materialRead: candidate.materialRead,
|
|
6521
|
+
policyRead: candidate.policyRead
|
|
6501
6522
|
};
|
|
6502
6523
|
}
|
|
6503
6524
|
async function resolveThresholdRuntimePolicyScope(input) {
|
|
@@ -7217,9 +7238,6 @@ function parseWalletRegistrationSetupPolicy(value) {
|
|
|
7217
7238
|
}
|
|
7218
7239
|
//#endregion
|
|
7219
7240
|
//#region ../shared-ts/src/utils/ecdsaKeyFactsInventory.ts
|
|
7220
|
-
function chainTargetKey(target) {
|
|
7221
|
-
return target.kind === "evm" ? `evm:eip155:${target.chainId}` : `tempo:${target.chainId}`;
|
|
7222
|
-
}
|
|
7223
7241
|
function normalizeChainTarget(target) {
|
|
7224
7242
|
if (target.kind === "evm") return {
|
|
7225
7243
|
kind: "evm",
|
|
@@ -7237,7 +7255,7 @@ function canonicalizeWalletEcdsaKeyFactsInventoryChallenge(input) {
|
|
|
7237
7255
|
const keyTargets = input.keyTargets.map((target) => ({
|
|
7238
7256
|
keyHandle: target.keyHandle,
|
|
7239
7257
|
chainTarget: normalizeChainTarget(target.chainTarget),
|
|
7240
|
-
targetKey:
|
|
7258
|
+
targetKey: thresholdEcdsaChainTargetKey(target.chainTarget)
|
|
7241
7259
|
})).sort((left, right) => {
|
|
7242
7260
|
const leftKey = `${left.keyHandle}:${left.targetKey}`;
|
|
7243
7261
|
const rightKey = `${right.keyHandle}:${right.targetKey}`;
|
|
@@ -7317,11 +7335,8 @@ function registrationSignerBranchKeyFromString(value) {
|
|
|
7317
7335
|
function registrationNearEd25519BranchKey(signerSlot) {
|
|
7318
7336
|
return registrationSignerBranchKeyFromString(`near_ed25519:slot:${signerSlot}`);
|
|
7319
7337
|
}
|
|
7320
|
-
function registrationEvmFamilyEcdsaTargetKey(target) {
|
|
7321
|
-
return alphabetizeStringify(target);
|
|
7322
|
-
}
|
|
7323
7338
|
function registrationEvmFamilyEcdsaBranchKey(chainTargets) {
|
|
7324
|
-
return registrationSignerBranchKeyFromString(`evm_family_ecdsa:${chainTargets.map(
|
|
7339
|
+
return registrationSignerBranchKeyFromString(`evm_family_ecdsa:${chainTargets.map(alphabetizeStringify).join("|")}`);
|
|
7325
7340
|
}
|
|
7326
7341
|
function registrationSignerPlanFromRequests(signers) {
|
|
7327
7342
|
return registrationSignerPlanFromBranches(signers.map(registrationSignerPlanBranchFromRequest));
|
|
@@ -7405,7 +7420,7 @@ function findDuplicateRegistrationSignerBranch(branch, branchKeys) {
|
|
|
7405
7420
|
}
|
|
7406
7421
|
function findDuplicateRegistrationEcdsaTarget(branch, ecdsaTargetKeys) {
|
|
7407
7422
|
for (const target of branch.chainTargets) {
|
|
7408
|
-
const targetKey =
|
|
7423
|
+
const targetKey = alphabetizeStringify(target);
|
|
7409
7424
|
if (ecdsaTargetKeys.has(targetKey)) return {
|
|
7410
7425
|
ok: false,
|
|
7411
7426
|
code: "invalid_body",
|
|
@@ -7591,17 +7606,11 @@ function addAuthMethodIntentGrantFromString(value) {
|
|
|
7591
7606
|
function addSignerIntentGrantFromString(value) {
|
|
7592
7607
|
return String(value || "").trim();
|
|
7593
7608
|
}
|
|
7594
|
-
function serializeAddSignerIntentV1(intent) {
|
|
7595
|
-
return alphabetizeStringify(intent);
|
|
7596
|
-
}
|
|
7597
|
-
function serializeAddAuthMethodIntentV1(intent) {
|
|
7598
|
-
return alphabetizeStringify(intent);
|
|
7599
|
-
}
|
|
7600
7609
|
async function computeAddSignerIntentDigestB64u(intent) {
|
|
7601
|
-
return base64UrlEncode(await sha256BytesUtf8(
|
|
7610
|
+
return base64UrlEncode(await sha256BytesUtf8(alphabetizeStringify(intent)));
|
|
7602
7611
|
}
|
|
7603
7612
|
async function computeAddAuthMethodIntentDigestB64u(intent) {
|
|
7604
|
-
return base64UrlEncode(await sha256BytesUtf8(
|
|
7613
|
+
return base64UrlEncode(await sha256BytesUtf8(alphabetizeStringify(intent)));
|
|
7605
7614
|
}
|
|
7606
7615
|
function normalizeAddAuthMethodIntentCaller(raw) {
|
|
7607
7616
|
const record = inspectRawObject(raw);
|
|
@@ -10073,24 +10082,12 @@ function buildSigningSessionSealRemovePath(basePath) {
|
|
|
10073
10082
|
}
|
|
10074
10083
|
function parseSigningSessionSealApplyBody(body) {
|
|
10075
10084
|
const obj = asRecord(body);
|
|
10076
|
-
if (!obj) return
|
|
10077
|
-
ok: false,
|
|
10078
|
-
code: "invalid_body",
|
|
10079
|
-
message: "Request body must be a JSON object"
|
|
10080
|
-
};
|
|
10085
|
+
if (!obj) return failure("invalid_body", "Request body must be a JSON object");
|
|
10081
10086
|
const thresholdSessionId = readRequiredString(obj, "thresholdSessionId");
|
|
10082
10087
|
const ciphertext = readRequiredString(obj, "ciphertext");
|
|
10083
|
-
if (!thresholdSessionId || !ciphertext) return
|
|
10084
|
-
ok: false,
|
|
10085
|
-
code: "invalid_body",
|
|
10086
|
-
message: "thresholdSessionId and ciphertext are required"
|
|
10087
|
-
};
|
|
10088
|
+
if (!thresholdSessionId || !ciphertext) return failure("invalid_body", "thresholdSessionId and ciphertext are required");
|
|
10088
10089
|
const parsedThresholdSessionId = parseThresholdSessionId(thresholdSessionId);
|
|
10089
|
-
if (!parsedThresholdSessionId.ok) return
|
|
10090
|
-
ok: false,
|
|
10091
|
-
code: "invalid_body",
|
|
10092
|
-
message: "thresholdSessionId is invalid"
|
|
10093
|
-
};
|
|
10090
|
+
if (!parsedThresholdSessionId.ok) return failure("invalid_body", "thresholdSessionId is invalid");
|
|
10094
10091
|
return {
|
|
10095
10092
|
ok: true,
|
|
10096
10093
|
value: {
|
|
@@ -10113,11 +10110,7 @@ async function authorizeSigningSessionSealRequest(args) {
|
|
|
10113
10110
|
thresholdSessionId: args.thresholdSessionId
|
|
10114
10111
|
});
|
|
10115
10112
|
} catch (error) {
|
|
10116
|
-
return
|
|
10117
|
-
ok: false,
|
|
10118
|
-
code: "internal",
|
|
10119
|
-
message: error instanceof Error ? error.message : String(error || "Authorization failed")
|
|
10120
|
-
};
|
|
10113
|
+
return failure("internal", error instanceof Error ? error.message : String(error || "Authorization failed"));
|
|
10121
10114
|
}
|
|
10122
10115
|
return {
|
|
10123
10116
|
ok: false,
|
|
@@ -10982,6 +10975,8 @@ function requireVerificationWindow(verifiedAtMs, expiresAtMs) {
|
|
|
10982
10975
|
//#endregion
|
|
10983
10976
|
//#region ../shared-ts/src/utils/emailOtpDomain.ts
|
|
10984
10977
|
const EMAIL_OTP_CHANNEL = "email_otp";
|
|
10978
|
+
/** Domain label that opens the AAD binding a released Email OTP factor to its challenge. */
|
|
10979
|
+
const EMAIL_OTP_FACTOR_RELEASE_AAD_DOMAIN_V1 = "seams/email-otp/factor-release/v1";
|
|
10985
10980
|
const WALLET_UNLOCK_BACKENDS = ["passkey", EMAIL_OTP_CHANNEL];
|
|
10986
10981
|
const WALLET_EMAIL_OTP_LOGIN_OPERATIONS = [
|
|
10987
10982
|
"wallet_unlock",
|
|
@@ -12559,11 +12554,7 @@ async function refreshEmailOtpWalletUnlockSessionState(input) {
|
|
|
12559
12554
|
ok: false,
|
|
12560
12555
|
response: {
|
|
12561
12556
|
status: 500,
|
|
12562
|
-
body:
|
|
12563
|
-
ok: false,
|
|
12564
|
-
code: "internal",
|
|
12565
|
-
message: error instanceof Error ? error.message : "Email OTP authority refresh resolution failed"
|
|
12566
|
-
}
|
|
12557
|
+
body: failure("internal", error instanceof Error ? error.message : "Email OTP authority refresh resolution failed")
|
|
12567
12558
|
}
|
|
12568
12559
|
};
|
|
12569
12560
|
}
|
|
@@ -12571,11 +12562,7 @@ async function refreshEmailOtpWalletUnlockSessionState(input) {
|
|
|
12571
12562
|
ok: false,
|
|
12572
12563
|
response: {
|
|
12573
12564
|
status: authorityResolution.code === "internal" ? 500 : 403,
|
|
12574
|
-
body:
|
|
12575
|
-
ok: false,
|
|
12576
|
-
code: authorityResolution.code,
|
|
12577
|
-
message: authorityResolution.message
|
|
12578
|
-
}
|
|
12565
|
+
body: failure(authorityResolution.code, authorityResolution.message)
|
|
12579
12566
|
}
|
|
12580
12567
|
};
|
|
12581
12568
|
try {
|
|
@@ -12592,11 +12579,7 @@ async function refreshEmailOtpWalletUnlockSessionState(input) {
|
|
|
12592
12579
|
ok: false,
|
|
12593
12580
|
response: {
|
|
12594
12581
|
status: 500,
|
|
12595
|
-
body:
|
|
12596
|
-
ok: false,
|
|
12597
|
-
code: "internal",
|
|
12598
|
-
message: error instanceof Error ? error.message : "Email OTP Wallet Session authority projection refresh failed"
|
|
12599
|
-
}
|
|
12582
|
+
body: failure("internal", error instanceof Error ? error.message : "Email OTP Wallet Session authority projection refresh failed")
|
|
12600
12583
|
}
|
|
12601
12584
|
};
|
|
12602
12585
|
}
|
|
@@ -12607,11 +12590,7 @@ function walletUnlockCustodyUnavailableResponse(lookup, factor) {
|
|
|
12607
12590
|
ok: false,
|
|
12608
12591
|
response: {
|
|
12609
12592
|
status: lookup.kind === "manifest_unavailable" ? 503 : lookup.kind === "conflict" ? 409 : lookup.kind === "missing" ? 404 : 409,
|
|
12610
|
-
body: {
|
|
12611
|
-
ok: false,
|
|
12612
|
-
code: lookup.kind === "manifest_unavailable" ? "custody_manifest_unavailable" : "custody_envelope_unavailable",
|
|
12613
|
-
message: `${factor} wallet custody is unavailable`
|
|
12614
|
-
}
|
|
12593
|
+
body: failure(lookup.kind === "manifest_unavailable" ? "custody_manifest_unavailable" : "custody_envelope_unavailable", `${factor} wallet custody is unavailable`)
|
|
12615
12594
|
}
|
|
12616
12595
|
};
|
|
12617
12596
|
}
|
|
@@ -12626,11 +12605,7 @@ function projectEmailOtpCustody(verifiedUnlock, lookup) {
|
|
|
12626
12605
|
ok: false,
|
|
12627
12606
|
response: {
|
|
12628
12607
|
status: 500,
|
|
12629
|
-
body:
|
|
12630
|
-
ok: false,
|
|
12631
|
-
code: "custody_binding_mismatch",
|
|
12632
|
-
message: "Email OTP wallet custody binding is invalid"
|
|
12633
|
-
}
|
|
12608
|
+
body: failure("custody_binding_mismatch", "Email OTP wallet custody binding is invalid")
|
|
12634
12609
|
}
|
|
12635
12610
|
};
|
|
12636
12611
|
return {
|
|
@@ -12660,11 +12635,7 @@ function projectPasskeyCustody(verifiedUnlock, resolution) {
|
|
|
12660
12635
|
ok: false,
|
|
12661
12636
|
response: {
|
|
12662
12637
|
status: 500,
|
|
12663
|
-
body:
|
|
12664
|
-
ok: false,
|
|
12665
|
-
code: "custody_binding_mismatch",
|
|
12666
|
-
message: "Passkey wallet custody binding is invalid"
|
|
12667
|
-
}
|
|
12638
|
+
body: failure("custody_binding_mismatch", "Passkey wallet custody binding is invalid")
|
|
12668
12639
|
}
|
|
12669
12640
|
};
|
|
12670
12641
|
let ed25519 = { kind: "absent" };
|
|
@@ -12676,11 +12647,7 @@ function projectPasskeyCustody(verifiedUnlock, resolution) {
|
|
|
12676
12647
|
ok: false,
|
|
12677
12648
|
response: {
|
|
12678
12649
|
status: 500,
|
|
12679
|
-
body:
|
|
12680
|
-
ok: false,
|
|
12681
|
-
code: "custody_binding_mismatch",
|
|
12682
|
-
message: "Passkey Ed25519 custody binding is invalid"
|
|
12683
|
-
}
|
|
12650
|
+
body: failure("custody_binding_mismatch", "Passkey Ed25519 custody binding is invalid")
|
|
12684
12651
|
}
|
|
12685
12652
|
};
|
|
12686
12653
|
ed25519 = {
|
|
@@ -12711,11 +12678,7 @@ async function provisionFirstEcdsaWalletSession(input) {
|
|
|
12711
12678
|
ok: false,
|
|
12712
12679
|
response: {
|
|
12713
12680
|
status: 403,
|
|
12714
|
-
body:
|
|
12715
|
-
ok: false,
|
|
12716
|
-
code: "scope_mismatch",
|
|
12717
|
-
message: "Wallet unlock proof does not match the requested ECDSA wallet"
|
|
12718
|
-
}
|
|
12681
|
+
body: failure("scope_mismatch", "Wallet unlock proof does not match the requested ECDSA wallet")
|
|
12719
12682
|
}
|
|
12720
12683
|
};
|
|
12721
12684
|
const provisioned = await input.context.provisionWalletSession(input.authorization);
|
|
@@ -12723,11 +12686,7 @@ async function provisionFirstEcdsaWalletSession(input) {
|
|
|
12723
12686
|
ok: false,
|
|
12724
12687
|
response: {
|
|
12725
12688
|
status: provisioned.status,
|
|
12726
|
-
body:
|
|
12727
|
-
ok: false,
|
|
12728
|
-
code: provisioned.code,
|
|
12729
|
-
message: provisioned.message
|
|
12730
|
-
}
|
|
12689
|
+
body: failure(provisioned.code, provisioned.message)
|
|
12731
12690
|
}
|
|
12732
12691
|
};
|
|
12733
12692
|
return {
|
|
@@ -12755,11 +12714,7 @@ function walletUnlockScopeMismatchResponse() {
|
|
|
12755
12714
|
ok: false,
|
|
12756
12715
|
response: {
|
|
12757
12716
|
status: 403,
|
|
12758
|
-
body:
|
|
12759
|
-
ok: false,
|
|
12760
|
-
code: "scope_mismatch",
|
|
12761
|
-
message: "Email OTP unlock proof does not match the requested Ed25519 wallet"
|
|
12762
|
-
}
|
|
12717
|
+
body: failure("scope_mismatch", "Email OTP unlock proof does not match the requested Ed25519 wallet")
|
|
12763
12718
|
}
|
|
12764
12719
|
};
|
|
12765
12720
|
}
|
|
@@ -12823,11 +12778,7 @@ function planWalletUnlockAuthorityEcdsaSession(input) {
|
|
|
12823
12778
|
function walletUnlockDeviceLinkEcdsaSessionRejection() {
|
|
12824
12779
|
return {
|
|
12825
12780
|
status: 400,
|
|
12826
|
-
body:
|
|
12827
|
-
ok: false,
|
|
12828
|
-
code: "invalid_body",
|
|
12829
|
-
message: "ecdsaSessionPolicy is not supported for device-linked wallet unlock"
|
|
12830
|
-
}
|
|
12781
|
+
body: failure("invalid_body", "ecdsaSessionPolicy is not supported for device-linked wallet unlock")
|
|
12831
12782
|
};
|
|
12832
12783
|
}
|
|
12833
12784
|
function planWalletUnlockPasskeySession(input) {
|
|
@@ -12870,11 +12821,7 @@ async function provisionPasskeyEd25519YaoSession(input) {
|
|
|
12870
12821
|
ok: false,
|
|
12871
12822
|
response: {
|
|
12872
12823
|
status: 409,
|
|
12873
|
-
body:
|
|
12874
|
-
ok: false,
|
|
12875
|
-
code: "capability_unavailable",
|
|
12876
|
-
message: "Requested Ed25519 Wallet Session is unavailable"
|
|
12877
|
-
}
|
|
12824
|
+
body: failure("capability_unavailable", "Requested Ed25519 Wallet Session is unavailable")
|
|
12878
12825
|
}
|
|
12879
12826
|
};
|
|
12880
12827
|
const provisioned = await input.context.provisionWalletSession({
|
|
@@ -12928,11 +12875,7 @@ function walletUnlockEcdsaOperationCredential(input) {
|
|
|
12928
12875
|
function walletUnlockEcdsaCredentialUnavailableResponse() {
|
|
12929
12876
|
return {
|
|
12930
12877
|
status: 409,
|
|
12931
|
-
body:
|
|
12932
|
-
ok: false,
|
|
12933
|
-
code: "capability_unavailable",
|
|
12934
|
-
message: "ECDSA activation requires the exact Wallet Session operation credential"
|
|
12935
|
-
}
|
|
12878
|
+
body: failure("capability_unavailable", "ECDSA activation requires the exact Wallet Session operation credential")
|
|
12936
12879
|
};
|
|
12937
12880
|
}
|
|
12938
12881
|
/** The unlock response's Wallet Session, when the unlock holds one. */
|
|
@@ -12968,11 +12911,7 @@ function parseWalletUnlockRouteBody(body) {
|
|
|
12968
12911
|
ok: false,
|
|
12969
12912
|
response: {
|
|
12970
12913
|
status: 400,
|
|
12971
|
-
body:
|
|
12972
|
-
ok: false,
|
|
12973
|
-
code: "invalid_body",
|
|
12974
|
-
message: "Request body is required"
|
|
12975
|
-
}
|
|
12914
|
+
body: failure("invalid_body", "Request body is required")
|
|
12976
12915
|
}
|
|
12977
12916
|
};
|
|
12978
12917
|
const record = body;
|
|
@@ -12981,11 +12920,7 @@ function parseWalletUnlockRouteBody(body) {
|
|
|
12981
12920
|
ok: false,
|
|
12982
12921
|
response: {
|
|
12983
12922
|
status: 400,
|
|
12984
|
-
body:
|
|
12985
|
-
ok: false,
|
|
12986
|
-
code: "invalid_body",
|
|
12987
|
-
message: "unlockBackend is required"
|
|
12988
|
-
}
|
|
12923
|
+
body: failure("invalid_body", "unlockBackend is required")
|
|
12989
12924
|
}
|
|
12990
12925
|
};
|
|
12991
12926
|
return {
|
|
@@ -13002,11 +12937,7 @@ async function handleWalletUnlockChallengeRoute(input) {
|
|
|
13002
12937
|
const walletAuthMethodId = parseRequiredWalletAuthMethodId(body.walletAuthMethodId);
|
|
13003
12938
|
if (!walletAuthMethodId.ok) return {
|
|
13004
12939
|
status: 400,
|
|
13005
|
-
body:
|
|
13006
|
-
ok: false,
|
|
13007
|
-
code: "invalid_body",
|
|
13008
|
-
message: walletAuthMethodId.message
|
|
13009
|
-
}
|
|
12940
|
+
body: failure("invalid_body", walletAuthMethodId.message)
|
|
13010
12941
|
};
|
|
13011
12942
|
}
|
|
13012
12943
|
const result = unlockBackend === "passkey" ? await input.service.createWebAuthnLoginOptions({
|
|
@@ -13189,20 +13120,12 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13189
13120
|
const challengeId = String(body.challengeId || "").trim();
|
|
13190
13121
|
if (!challengeId) return {
|
|
13191
13122
|
status: 400,
|
|
13192
|
-
body:
|
|
13193
|
-
ok: false,
|
|
13194
|
-
code: "invalid_body",
|
|
13195
|
-
message: "challengeId is required"
|
|
13196
|
-
}
|
|
13123
|
+
body: failure("invalid_body", "challengeId is required")
|
|
13197
13124
|
};
|
|
13198
13125
|
if (unlockBackend === "passkey") {
|
|
13199
13126
|
if (input.capabilityContext.kind !== "passkey_unlock") return {
|
|
13200
13127
|
status: 400,
|
|
13201
|
-
body:
|
|
13202
|
-
ok: false,
|
|
13203
|
-
code: "invalid_body",
|
|
13204
|
-
message: "Passkey unlock context is invalid"
|
|
13205
|
-
}
|
|
13128
|
+
body: failure("invalid_body", "Passkey unlock context is invalid")
|
|
13206
13129
|
};
|
|
13207
13130
|
let ed25519SessionRequest;
|
|
13208
13131
|
try {
|
|
@@ -13210,11 +13133,7 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13210
13133
|
} catch (error) {
|
|
13211
13134
|
return {
|
|
13212
13135
|
status: 400,
|
|
13213
|
-
body:
|
|
13214
|
-
ok: false,
|
|
13215
|
-
code: "invalid_body",
|
|
13216
|
-
message: error instanceof Error ? error.message : "Ed25519 session request is invalid"
|
|
13217
|
-
}
|
|
13136
|
+
body: failure("invalid_body", error instanceof Error ? error.message : "Ed25519 session request is invalid")
|
|
13218
13137
|
};
|
|
13219
13138
|
}
|
|
13220
13139
|
const result = await verifyPasskeyWalletUnlock({
|
|
@@ -13233,11 +13152,7 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13233
13152
|
const userId = String(result.userId || "").trim();
|
|
13234
13153
|
if (!userId) return {
|
|
13235
13154
|
status: 500,
|
|
13236
|
-
body:
|
|
13237
|
-
ok: false,
|
|
13238
|
-
code: "internal",
|
|
13239
|
-
message: "Verified passkey user is missing"
|
|
13240
|
-
}
|
|
13155
|
+
body: failure("internal", "Verified passkey user is missing")
|
|
13241
13156
|
};
|
|
13242
13157
|
const walletId = parseWalletId(userId);
|
|
13243
13158
|
const walletAuthMethodId = parseWalletAuthMethodId(result.walletAuthMethodId);
|
|
@@ -13246,11 +13161,7 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13246
13161
|
const credentialIdB64u = parseWebAuthnCredentialIdB64u(result.credentialIdB64u);
|
|
13247
13162
|
if (!walletId.ok || !walletAuthMethodId.ok || !walletAuthorityId.ok || !rpId.ok || !credentialIdB64u.ok) return {
|
|
13248
13163
|
status: 500,
|
|
13249
|
-
body:
|
|
13250
|
-
ok: false,
|
|
13251
|
-
code: "internal",
|
|
13252
|
-
message: "Verified passkey identity is invalid"
|
|
13253
|
-
}
|
|
13164
|
+
body: failure("internal", "Verified passkey identity is invalid")
|
|
13254
13165
|
};
|
|
13255
13166
|
let authorization;
|
|
13256
13167
|
try {
|
|
@@ -13268,11 +13179,7 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13268
13179
|
} catch (error) {
|
|
13269
13180
|
return {
|
|
13270
13181
|
status: 403,
|
|
13271
|
-
body:
|
|
13272
|
-
ok: false,
|
|
13273
|
-
code: "owner_proof_rejected",
|
|
13274
|
-
message: error instanceof Error ? error.message : "Passkey owner proof is invalid"
|
|
13275
|
-
}
|
|
13182
|
+
body: failure("owner_proof_rejected", error instanceof Error ? error.message : "Passkey owner proof is invalid")
|
|
13276
13183
|
};
|
|
13277
13184
|
}
|
|
13278
13185
|
const resolvePasskeyAuthority = () => input.service.resolveActivePasskeyAuthorityForUnlock({
|
|
@@ -13290,11 +13197,7 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13290
13197
|
} catch (error) {
|
|
13291
13198
|
return {
|
|
13292
13199
|
status: 500,
|
|
13293
|
-
body:
|
|
13294
|
-
ok: false,
|
|
13295
|
-
code: "internal",
|
|
13296
|
-
message: error instanceof Error ? error.message : "Passkey authority resolution failed"
|
|
13297
|
-
}
|
|
13200
|
+
body: failure("internal", error instanceof Error ? error.message : "Passkey authority resolution failed")
|
|
13298
13201
|
};
|
|
13299
13202
|
}
|
|
13300
13203
|
if (authorityResolution.kind === "active_authority") {
|
|
@@ -13311,11 +13214,7 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13311
13214
|
switch (sessionPlan.kind) {
|
|
13312
13215
|
case "rejected": return {
|
|
13313
13216
|
status: walletUnlockIssuanceRejectionStatus(sessionPlan.authorityResolution),
|
|
13314
|
-
body:
|
|
13315
|
-
ok: false,
|
|
13316
|
-
code: sessionPlan.authorityResolution.code,
|
|
13317
|
-
message: sessionPlan.authorityResolution.message
|
|
13318
|
-
}
|
|
13217
|
+
body: failure(sessionPlan.authorityResolution.code, sessionPlan.authorityResolution.message)
|
|
13319
13218
|
};
|
|
13320
13219
|
case "wallet_registration":
|
|
13321
13220
|
passkeyCustodyRequired = true;
|
|
@@ -13337,11 +13236,7 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13337
13236
|
} catch (error) {
|
|
13338
13237
|
return {
|
|
13339
13238
|
status: 500,
|
|
13340
|
-
body:
|
|
13341
|
-
ok: false,
|
|
13342
|
-
code: "internal",
|
|
13343
|
-
message: error instanceof Error ? error.message : "Passkey Wallet Session issuance failed"
|
|
13344
|
-
}
|
|
13239
|
+
body: failure("internal", error instanceof Error ? error.message : "Passkey Wallet Session issuance failed")
|
|
13345
13240
|
};
|
|
13346
13241
|
}
|
|
13347
13242
|
switch (sessionResolution.kind) {
|
|
@@ -13362,11 +13257,7 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13362
13257
|
break;
|
|
13363
13258
|
case "rejected": return {
|
|
13364
13259
|
status: walletUnlockIssuanceRejectionStatus(sessionResolution),
|
|
13365
|
-
body:
|
|
13366
|
-
ok: false,
|
|
13367
|
-
code: sessionResolution.code,
|
|
13368
|
-
message: sessionResolution.message
|
|
13369
|
-
}
|
|
13260
|
+
body: failure(sessionResolution.code, sessionResolution.message)
|
|
13370
13261
|
};
|
|
13371
13262
|
}
|
|
13372
13263
|
break;
|
|
@@ -13385,11 +13276,7 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13385
13276
|
} catch (error) {
|
|
13386
13277
|
return {
|
|
13387
13278
|
status: 503,
|
|
13388
|
-
body:
|
|
13389
|
-
ok: false,
|
|
13390
|
-
code: "custody_unavailable",
|
|
13391
|
-
message: error instanceof Error ? error.message : "Passkey wallet custody is unavailable"
|
|
13392
|
-
}
|
|
13279
|
+
body: failure("custody_unavailable", error instanceof Error ? error.message : "Passkey wallet custody is unavailable")
|
|
13393
13280
|
};
|
|
13394
13281
|
}
|
|
13395
13282
|
const ed25519Session = await provisionPasskeyEd25519YaoSession({
|
|
@@ -13431,20 +13318,12 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13431
13318
|
} catch (error) {
|
|
13432
13319
|
return {
|
|
13433
13320
|
status: 500,
|
|
13434
|
-
body:
|
|
13435
|
-
ok: false,
|
|
13436
|
-
code: "internal",
|
|
13437
|
-
message: error instanceof Error ? error.message : "Passkey authority refresh resolution failed"
|
|
13438
|
-
}
|
|
13321
|
+
body: failure("internal", error instanceof Error ? error.message : "Passkey authority refresh resolution failed")
|
|
13439
13322
|
};
|
|
13440
13323
|
}
|
|
13441
13324
|
if (refreshedAuthority.kind === "rejected") return {
|
|
13442
13325
|
status: walletUnlockIssuanceRejectionStatus(refreshedAuthority),
|
|
13443
|
-
body:
|
|
13444
|
-
ok: false,
|
|
13445
|
-
code: refreshedAuthority.code,
|
|
13446
|
-
message: refreshedAuthority.message
|
|
13447
|
-
}
|
|
13326
|
+
body: failure(refreshedAuthority.code, refreshedAuthority.message)
|
|
13448
13327
|
};
|
|
13449
13328
|
try {
|
|
13450
13329
|
walletSessionState = await refreshWalletUnlockSessionState({
|
|
@@ -13455,11 +13334,7 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13455
13334
|
} catch (error) {
|
|
13456
13335
|
return {
|
|
13457
13336
|
status: 500,
|
|
13458
|
-
body:
|
|
13459
|
-
ok: false,
|
|
13460
|
-
code: "internal",
|
|
13461
|
-
message: error instanceof Error ? error.message : "Passkey Wallet Session authority projection refresh failed"
|
|
13462
|
-
}
|
|
13337
|
+
body: failure("internal", error instanceof Error ? error.message : "Passkey Wallet Session authority projection refresh failed")
|
|
13463
13338
|
};
|
|
13464
13339
|
}
|
|
13465
13340
|
}
|
|
@@ -13488,20 +13363,12 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13488
13363
|
}
|
|
13489
13364
|
if (input.capabilityContext.kind === "passkey_unlock") return {
|
|
13490
13365
|
status: 400,
|
|
13491
|
-
body:
|
|
13492
|
-
ok: false,
|
|
13493
|
-
code: "invalid_body",
|
|
13494
|
-
message: "Email OTP unlock context is invalid"
|
|
13495
|
-
}
|
|
13366
|
+
body: failure("invalid_body", "Email OTP unlock context is invalid")
|
|
13496
13367
|
};
|
|
13497
13368
|
const requestedWalletAuthMethodId = parseRequiredWalletAuthMethodId(body.walletAuthMethodId);
|
|
13498
13369
|
if (!requestedWalletAuthMethodId.ok) return {
|
|
13499
13370
|
status: 400,
|
|
13500
|
-
body:
|
|
13501
|
-
ok: false,
|
|
13502
|
-
code: "invalid_body",
|
|
13503
|
-
message: requestedWalletAuthMethodId.message
|
|
13504
|
-
}
|
|
13371
|
+
body: failure("invalid_body", requestedWalletAuthMethodId.message)
|
|
13505
13372
|
};
|
|
13506
13373
|
const result = await input.service.verifyEmailOtpUnlockProof({
|
|
13507
13374
|
walletId: body.walletId,
|
|
@@ -13528,11 +13395,7 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13528
13395
|
const walletId = parseWalletId(result.walletId);
|
|
13529
13396
|
if (!walletId.ok) return {
|
|
13530
13397
|
status: 500,
|
|
13531
|
-
body:
|
|
13532
|
-
ok: false,
|
|
13533
|
-
code: "internal",
|
|
13534
|
-
message: "Verified Email OTP wallet identity is invalid"
|
|
13535
|
-
}
|
|
13398
|
+
body: failure("internal", "Verified Email OTP wallet identity is invalid")
|
|
13536
13399
|
};
|
|
13537
13400
|
let authorityResolution;
|
|
13538
13401
|
try {
|
|
@@ -13545,20 +13408,12 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13545
13408
|
} catch (error) {
|
|
13546
13409
|
return {
|
|
13547
13410
|
status: 500,
|
|
13548
|
-
body:
|
|
13549
|
-
ok: false,
|
|
13550
|
-
code: "internal",
|
|
13551
|
-
message: error instanceof Error ? error.message : "Email OTP authority resolution failed"
|
|
13552
|
-
}
|
|
13411
|
+
body: failure("internal", error instanceof Error ? error.message : "Email OTP authority resolution failed")
|
|
13553
13412
|
};
|
|
13554
13413
|
}
|
|
13555
13414
|
if (authorityResolution.kind === "rejected") return {
|
|
13556
13415
|
status: authorityResolution.code === "internal" ? 500 : 403,
|
|
13557
|
-
body:
|
|
13558
|
-
ok: false,
|
|
13559
|
-
code: authorityResolution.code,
|
|
13560
|
-
message: authorityResolution.message
|
|
13561
|
-
}
|
|
13416
|
+
body: failure(authorityResolution.code, authorityResolution.message)
|
|
13562
13417
|
};
|
|
13563
13418
|
const exactEmailOtpAuthority = authorityResolution;
|
|
13564
13419
|
if (planWalletUnlockAuthorityEcdsaSession({
|
|
@@ -13592,11 +13447,7 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13592
13447
|
} catch (error) {
|
|
13593
13448
|
return {
|
|
13594
13449
|
status: 403,
|
|
13595
|
-
body:
|
|
13596
|
-
ok: false,
|
|
13597
|
-
code: "owner_proof_rejected",
|
|
13598
|
-
message: error instanceof Error ? error.message : "Email OTP owner proof is invalid"
|
|
13599
|
-
}
|
|
13450
|
+
body: failure("owner_proof_rejected", error instanceof Error ? error.message : "Email OTP owner proof is invalid")
|
|
13600
13451
|
};
|
|
13601
13452
|
}
|
|
13602
13453
|
let walletSessionState = { kind: "absent" };
|
|
@@ -13604,11 +13455,7 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13604
13455
|
const walletId = parseWalletId(result.walletId);
|
|
13605
13456
|
if (!walletId.ok) return {
|
|
13606
13457
|
status: 500,
|
|
13607
|
-
body:
|
|
13608
|
-
ok: false,
|
|
13609
|
-
code: "internal",
|
|
13610
|
-
message: "Verified Email OTP wallet identity is invalid"
|
|
13611
|
-
}
|
|
13458
|
+
body: failure("internal", "Verified Email OTP wallet identity is invalid")
|
|
13612
13459
|
};
|
|
13613
13460
|
let sessionResolution;
|
|
13614
13461
|
try {
|
|
@@ -13623,11 +13470,7 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13623
13470
|
} catch (error) {
|
|
13624
13471
|
return {
|
|
13625
13472
|
status: 500,
|
|
13626
|
-
body:
|
|
13627
|
-
ok: false,
|
|
13628
|
-
code: "internal",
|
|
13629
|
-
message: error instanceof Error ? error.message : "Email OTP Wallet Session issuance failed"
|
|
13630
|
-
}
|
|
13473
|
+
body: failure("internal", error instanceof Error ? error.message : "Email OTP Wallet Session issuance failed")
|
|
13631
13474
|
};
|
|
13632
13475
|
}
|
|
13633
13476
|
switch (sessionResolution.kind) {
|
|
@@ -13645,11 +13488,7 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13645
13488
|
case "wallet_registration": break;
|
|
13646
13489
|
case "rejected": return {
|
|
13647
13490
|
status: walletUnlockIssuanceRejectionStatus(sessionResolution),
|
|
13648
|
-
body:
|
|
13649
|
-
ok: false,
|
|
13650
|
-
code: sessionResolution.code,
|
|
13651
|
-
message: sessionResolution.message
|
|
13652
|
-
}
|
|
13491
|
+
body: failure(sessionResolution.code, sessionResolution.message)
|
|
13653
13492
|
};
|
|
13654
13493
|
}
|
|
13655
13494
|
}
|
|
@@ -13699,11 +13538,7 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13699
13538
|
});
|
|
13700
13539
|
if (!isWalletUnlockEd25519YaoRequestedContext(input.capabilityContext)) return {
|
|
13701
13540
|
status: 400,
|
|
13702
|
-
body:
|
|
13703
|
-
ok: false,
|
|
13704
|
-
code: "invalid_body",
|
|
13705
|
-
message: "Email OTP capability context is invalid"
|
|
13706
|
-
}
|
|
13541
|
+
body: failure("invalid_body", "Email OTP capability context is invalid")
|
|
13707
13542
|
};
|
|
13708
13543
|
const capabilityResult = await provisionEmailOtpEd25519YaoCapability({
|
|
13709
13544
|
context: input.capabilityContext,
|
|
@@ -13742,7 +13577,6 @@ const ECDSA_TIMING_METRICS = new Set([
|
|
|
13742
13577
|
"ecdsa_sign_proxy",
|
|
13743
13578
|
"ecdsa_sign_complete",
|
|
13744
13579
|
"ecdsa_sign_total",
|
|
13745
|
-
"ecdsa_presign_queue",
|
|
13746
13580
|
"ecdsa_presign_authenticate",
|
|
13747
13581
|
"ecdsa_presign_material",
|
|
13748
13582
|
"ecdsa_presign_admit",
|
|
@@ -13831,6 +13665,7 @@ async function evaluateRouterAbNormalSigningAdmission(input) {
|
|
|
13831
13665
|
});
|
|
13832
13666
|
return await input.adapter.evaluatePolicy({
|
|
13833
13667
|
curve: "ecdsa",
|
|
13668
|
+
policyReadSource: input.policyReadSource,
|
|
13834
13669
|
phase: input.phase,
|
|
13835
13670
|
walletId: input.walletId,
|
|
13836
13671
|
materialActivationId: requireMpcMaterialActivationId(input.admission.materialActivation.activation_id),
|
|
@@ -14104,6 +13939,7 @@ async function authenticateRouterAbWalletOperationStepUpIdentity(input) {
|
|
|
14104
13939
|
if (admission.curve === "ecdsa" && input.keyFamily === "ecdsa_secp256k1") {
|
|
14105
13940
|
const active = ecdsaStepUpActiveMaterial({
|
|
14106
13941
|
activeMaterial: await input.resolveEcdsaMaterialActivation({
|
|
13942
|
+
source: { kind: "database" },
|
|
14107
13943
|
walletId: input.walletId,
|
|
14108
13944
|
materialActivation: admittedMaterialActivation
|
|
14109
13945
|
}),
|
|
@@ -14663,6 +14499,7 @@ async function resolveRouterAbEcdsaOwnerOperationStepUpPreparation(input) {
|
|
|
14663
14499
|
const walletId = parseWalletId(request.scope.wallet_id);
|
|
14664
14500
|
if (!walletId.ok) return void 0;
|
|
14665
14501
|
const activeMaterial = await input.resolveEcdsaMaterialActivation({
|
|
14502
|
+
source: { kind: "database" },
|
|
14666
14503
|
walletId: walletId.value,
|
|
14667
14504
|
materialActivation: request.material_activation
|
|
14668
14505
|
});
|
|
@@ -14763,6 +14600,7 @@ function routerAbWalletSessionError(code) {
|
|
|
14763
14600
|
*/
|
|
14764
14601
|
async function resolveFreshRouterAbEcdsaMaterialActivation(input) {
|
|
14765
14602
|
const resolved = await input.resolveEcdsaMaterialActivation({
|
|
14603
|
+
source: { kind: "database" },
|
|
14766
14604
|
walletId: input.walletId,
|
|
14767
14605
|
materialActivation: input.expected
|
|
14768
14606
|
});
|
|
@@ -14782,15 +14620,7 @@ async function resolveFreshRouterAbEcdsaMaterialActivation(input) {
|
|
|
14782
14620
|
};
|
|
14783
14621
|
}
|
|
14784
14622
|
function validateRouterAbEcdsaV2NormalSigningRequestForSession(input) {
|
|
14785
|
-
|
|
14786
|
-
try {
|
|
14787
|
-
request = parseRouterAbEcdsaOperationStepUpRequest(input);
|
|
14788
|
-
} catch (error) {
|
|
14789
|
-
return {
|
|
14790
|
-
ok: false,
|
|
14791
|
-
error: routerAbStepUpError(400, "invalid_body", routerAbErrorMessage(error))
|
|
14792
|
-
};
|
|
14793
|
-
}
|
|
14623
|
+
const request = input.request;
|
|
14794
14624
|
if (request.authorization.kind !== "reusable_wallet_session" || request.authorization.wallet_session_id !== input.session.walletSessionId || request.scope.wallet_id !== String(input.session.walletId) || request.material_activation.material_owner !== String(input.session.walletId) || request.material_activation.signing_worker !== request.scope.signing_worker.server_id || !sameRouterAbMpcMaterialActivationRef(request.material_activation, request.scope.material_activation) || !sameRouterAbMpcMaterialActivationRef(request.material_activation, input.admittedMaterialActivation)) return {
|
|
14795
14625
|
ok: false,
|
|
14796
14626
|
error: routerAbWalletSessionError(WALLET_SESSION_FAILURE_CODES.scopeMismatch)
|
|
@@ -14819,7 +14649,7 @@ function validateRouterAbEcdsaV2NormalSigningRequestForSession(input) {
|
|
|
14819
14649
|
};
|
|
14820
14650
|
}
|
|
14821
14651
|
async function admitRouterAbEcdsaReusableWalletSessionOperation(input) {
|
|
14822
|
-
if (typeof input.authorizedOperations.admitEcdsaWalletSessionOperation !== "function") return {
|
|
14652
|
+
if (typeof input.authorizedOperations.admitEcdsaWalletSessionOperation !== "function" || typeof input.authorizedOperations.resolveEcdsaWalletSessionOperation !== "function") return {
|
|
14823
14653
|
ok: false,
|
|
14824
14654
|
error: routerAbStepUpError(501, "not_configured", "ECDSA atomic authorization is not configured")
|
|
14825
14655
|
};
|
|
@@ -14829,7 +14659,7 @@ async function admitRouterAbEcdsaReusableWalletSessionOperation(input) {
|
|
|
14829
14659
|
};
|
|
14830
14660
|
const nowMs = Date.now();
|
|
14831
14661
|
try {
|
|
14832
|
-
const session = input.binding.kind === "wallet_session_operation_credential_v1" ? input.binding.context.authorization.session : input.binding.candidate.status.session;
|
|
14662
|
+
const session = input.binding.kind === "wallet_session_operation_credential_v1" ? input.binding.validated.admission.context.authorization.session : input.binding.candidate.status.session;
|
|
14833
14663
|
const tenantId = session.tenantId;
|
|
14834
14664
|
const principalId = session.principalId;
|
|
14835
14665
|
const walletId = session.walletId;
|
|
@@ -14840,16 +14670,12 @@ async function admitRouterAbEcdsaReusableWalletSessionOperation(input) {
|
|
|
14840
14670
|
ok: false,
|
|
14841
14671
|
error: routerAbStepUpError(403, "wallet_session_mismatch", "Reusable Wallet Session identity does not match")
|
|
14842
14672
|
};
|
|
14843
|
-
const
|
|
14844
|
-
|
|
14845
|
-
walletId: String(walletId),
|
|
14846
|
-
expected: input.materialActivation
|
|
14847
|
-
});
|
|
14848
|
-
if (!freshMaterial.ok) return {
|
|
14673
|
+
const material = input.material;
|
|
14674
|
+
if (!sameRouterAbMpcMaterialActivationRef(material.materialActivation, input.request.material_activation)) return {
|
|
14849
14675
|
ok: false,
|
|
14850
|
-
error: routerAbStepUpError(
|
|
14676
|
+
error: routerAbStepUpError(403, "material_mismatch", "Signing material does not match the request")
|
|
14851
14677
|
};
|
|
14852
|
-
const capabilityId = requireAuthorizationValue$2(parseCapabilityId(
|
|
14678
|
+
const capabilityId = requireAuthorizationValue$2(parseCapabilityId(material.materialActivation.capability));
|
|
14853
14679
|
const operationId = requireAuthorizationValue$2(parseCapabilityOperationId(input.request.operation_id));
|
|
14854
14680
|
const envelope = buildCapabilityOperationEnvelope({
|
|
14855
14681
|
tenantId,
|
|
@@ -14863,13 +14689,11 @@ async function admitRouterAbEcdsaReusableWalletSessionOperation(input) {
|
|
|
14863
14689
|
displayDigest: parseDigestB64u(input.request.operation_digests.display_digest_b64u)
|
|
14864
14690
|
}
|
|
14865
14691
|
});
|
|
14866
|
-
const
|
|
14867
|
-
const auditEventId = requireAuthorizationValue$2(parseAuthorizationAuditEventId(`ecdsa-operation-audit:${operationId}`));
|
|
14868
|
-
const outcome = await input.authorizedOperations.admitEcdsaWalletSessionOperation({
|
|
14692
|
+
const admissionInput = {
|
|
14869
14693
|
operation: {
|
|
14870
14694
|
tenantId,
|
|
14871
|
-
authorizedOperationId,
|
|
14872
|
-
auditEventId,
|
|
14695
|
+
authorizedOperationId: requireAuthorizationValue$2(parseAuthorizedOperationId(`ecdsa-authorized-operation:${operationId}:${input.request.request_id}`)),
|
|
14696
|
+
auditEventId: requireAuthorizationValue$2(parseAuthorizationAuditEventId(`ecdsa-operation-audit:${operationId}`)),
|
|
14873
14697
|
operation: envelope,
|
|
14874
14698
|
authorization: {
|
|
14875
14699
|
kind: "authorization_grant",
|
|
@@ -14882,12 +14706,35 @@ async function admitRouterAbEcdsaReusableWalletSessionOperation(input) {
|
|
|
14882
14706
|
claimedAtMs: nowMs
|
|
14883
14707
|
},
|
|
14884
14708
|
material: {
|
|
14709
|
+
readSnapshot: material.readSnapshot,
|
|
14885
14710
|
walletId,
|
|
14886
|
-
keyHandle:
|
|
14887
|
-
runtimePolicyScope:
|
|
14888
|
-
materialActivation:
|
|
14711
|
+
keyHandle: material.keyHandle,
|
|
14712
|
+
runtimePolicyScope: material.runtimePolicyScope,
|
|
14713
|
+
materialActivation: material.materialActivation
|
|
14889
14714
|
}
|
|
14890
|
-
}
|
|
14715
|
+
};
|
|
14716
|
+
if (input.phase === "finalize") {
|
|
14717
|
+
const resolved = await input.authorizedOperations.resolveEcdsaWalletSessionOperation(admissionInput);
|
|
14718
|
+
if (resolved.kind === "authorized_operation_missing") return {
|
|
14719
|
+
ok: false,
|
|
14720
|
+
error: routerAbStepUpError(409, resolved.kind, "ECDSA finalize requires a claimed prepare operation")
|
|
14721
|
+
};
|
|
14722
|
+
const failure = routerAbReusableWalletSessionClaimFailure(resolved);
|
|
14723
|
+
if (failure) return {
|
|
14724
|
+
ok: false,
|
|
14725
|
+
error: failure
|
|
14726
|
+
};
|
|
14727
|
+
if (resolved.kind === "operation_in_progress" || resolved.kind === "replayed") return {
|
|
14728
|
+
ok: true,
|
|
14729
|
+
phase: "finalize",
|
|
14730
|
+
admission: resolved
|
|
14731
|
+
};
|
|
14732
|
+
return {
|
|
14733
|
+
ok: false,
|
|
14734
|
+
error: routerAbStepUpError(409, resolved.kind, "Authorized operation is unavailable")
|
|
14735
|
+
};
|
|
14736
|
+
}
|
|
14737
|
+
const outcome = await input.authorizedOperations.admitEcdsaWalletSessionOperation(admissionInput);
|
|
14891
14738
|
const claimFailure = routerAbReusableWalletSessionClaimFailure(outcome);
|
|
14892
14739
|
if (claimFailure) return {
|
|
14893
14740
|
ok: false,
|
|
@@ -14895,6 +14742,7 @@ async function admitRouterAbEcdsaReusableWalletSessionOperation(input) {
|
|
|
14895
14742
|
};
|
|
14896
14743
|
if (outcome.kind === "claimed" || outcome.kind === "operation_in_progress" || outcome.kind === "replayed") return {
|
|
14897
14744
|
ok: true,
|
|
14745
|
+
phase: "prepare",
|
|
14898
14746
|
admission: outcome
|
|
14899
14747
|
};
|
|
14900
14748
|
return {
|
|
@@ -14940,6 +14788,10 @@ async function authorizeRouterAbEcdsaWalletSessionRequest(input) {
|
|
|
14940
14788
|
result: validated.error
|
|
14941
14789
|
};
|
|
14942
14790
|
const activeMaterial = await input.resolveEcdsaMaterialActivation({
|
|
14791
|
+
source: {
|
|
14792
|
+
kind: "credential_snapshot",
|
|
14793
|
+
materialRead: input.materialRead
|
|
14794
|
+
},
|
|
14943
14795
|
walletId: String(input.session.walletId),
|
|
14944
14796
|
materialActivation: validated.admission.materialActivation
|
|
14945
14797
|
});
|
|
@@ -14957,6 +14809,10 @@ async function authorizeRouterAbEcdsaWalletSessionRequest(input) {
|
|
|
14957
14809
|
result: routerAbStepUpError(403, "wallet_session_scope_mismatch", "Wallet Session V2 scope does not match the active material")
|
|
14958
14810
|
};
|
|
14959
14811
|
const admissionDecision = await evaluateRouterAbNormalSigningAdmission({
|
|
14812
|
+
policyReadSource: {
|
|
14813
|
+
kind: "credential_snapshot",
|
|
14814
|
+
policyRead: input.policyRead
|
|
14815
|
+
},
|
|
14960
14816
|
adapter: input.admissionAdapter,
|
|
14961
14817
|
curve: "ecdsa",
|
|
14962
14818
|
authorizationKind: "wallet_session_operation_credential_v1",
|
|
@@ -14991,29 +14847,21 @@ async function authorizeRouterAbEcdsaWalletSessionRequest(input) {
|
|
|
14991
14847
|
};
|
|
14992
14848
|
}
|
|
14993
14849
|
async function resolveRouterAbEcdsaExhaustedCandidateAuthorization(input) {
|
|
14994
|
-
const
|
|
14995
|
-
|
|
14996
|
-
const
|
|
14997
|
-
|
|
14998
|
-
|
|
14999
|
-
operation: {
|
|
15000
|
-
keyFamily: "ecdsa_secp256k1",
|
|
15001
|
-
operationKind: "evm.sign_transaction"
|
|
15002
|
-
}
|
|
14850
|
+
const candidate = input.candidate;
|
|
14851
|
+
const session = candidate.status.session;
|
|
14852
|
+
const admission = walletSessionCandidateAdmission(session, candidate, {
|
|
14853
|
+
keyFamily: "ecdsa_secp256k1",
|
|
14854
|
+
operationKind: "evm.sign_transaction"
|
|
15003
14855
|
});
|
|
15004
|
-
if (!exhausted) return null;
|
|
15005
|
-
if (!exhausted.ok) return {
|
|
15006
|
-
ok: false,
|
|
15007
|
-
result: exhausted.error
|
|
15008
|
-
};
|
|
15009
|
-
const { candidate, session, admission } = exhausted;
|
|
15010
14856
|
if (!admission.ok || admission.keyFamily !== "ecdsa_secp256k1") return {
|
|
15011
14857
|
ok: false,
|
|
15012
14858
|
result: routerAbWalletSessionError(WALLET_SESSION_FAILURE_CODES.scopeMismatch)
|
|
15013
14859
|
};
|
|
15014
14860
|
const authorized = await authorizeRouterAbEcdsaWalletSessionRequest({
|
|
14861
|
+
materialRead: input.materialRead,
|
|
14862
|
+
policyRead: input.policyRead,
|
|
15015
14863
|
phase: input.phase,
|
|
15016
|
-
|
|
14864
|
+
request: input.request,
|
|
15017
14865
|
session,
|
|
15018
14866
|
admittedMaterialActivation: routerAbMpcMaterialActivationRefToWire(admission.materialActivation),
|
|
15019
14867
|
admissionAdapter: input.admissionAdapter,
|
|
@@ -15066,6 +14914,7 @@ async function authenticateRouterAbEcdsaOperationStepUp(input) {
|
|
|
15066
14914
|
let resolvedMaterial;
|
|
15067
14915
|
try {
|
|
15068
14916
|
resolvedMaterial = await input.resolveEcdsaMaterialActivation({
|
|
14917
|
+
source: { kind: "database" },
|
|
15069
14918
|
walletId: scope.wallet_id,
|
|
15070
14919
|
materialActivation: admittedMaterialActivation
|
|
15071
14920
|
});
|
|
@@ -15173,6 +15022,7 @@ async function handleRouterAbEcdsaOperationStepUpRoute(input) {
|
|
|
15173
15022
|
const materialActivationId = requireMpcMaterialActivationId(activeMaterial.materialActivation.activation_id);
|
|
15174
15023
|
if (!input.admissionAdapter) return routerAbStepUpError(501, "not_configured", "Router A/B ECDSA operation step-up admission is not configured");
|
|
15175
15024
|
const admission = await input.admissionAdapter.evaluatePolicy({
|
|
15025
|
+
policyReadSource: { kind: "database" },
|
|
15176
15026
|
curve: "ecdsa",
|
|
15177
15027
|
phase: input.phase,
|
|
15178
15028
|
walletId: authenticated.session.walletId,
|
|
@@ -15222,19 +15072,19 @@ async function handleRouterAbEcdsaOperationStepUpRoute(input) {
|
|
|
15222
15072
|
};
|
|
15223
15073
|
}
|
|
15224
15074
|
async function authorizeRouterAbEcdsaDerivationNormalSigningRoute(input) {
|
|
15225
|
-
let
|
|
15075
|
+
let parsedRequest;
|
|
15226
15076
|
try {
|
|
15227
|
-
|
|
15077
|
+
parsedRequest = parseRouterAbEcdsaOperationStepUpRequest({
|
|
15228
15078
|
phase: input.phase,
|
|
15229
15079
|
body: input.body
|
|
15230
|
-
})
|
|
15080
|
+
});
|
|
15231
15081
|
} catch (error) {
|
|
15232
15082
|
return {
|
|
15233
15083
|
ok: false,
|
|
15234
15084
|
result: routerAbStepUpError(400, "invalid_body", routerAbErrorMessage(error))
|
|
15235
15085
|
};
|
|
15236
15086
|
}
|
|
15237
|
-
if (
|
|
15087
|
+
if (parsedRequest.authorization.kind === "operation_step_up") {
|
|
15238
15088
|
const stepUp = await handleRouterAbEcdsaOperationStepUpRoute({
|
|
15239
15089
|
body: input.body,
|
|
15240
15090
|
headers: input.headers,
|
|
@@ -15258,22 +15108,12 @@ async function authorizeRouterAbEcdsaDerivationNormalSigningRoute(input) {
|
|
|
15258
15108
|
};
|
|
15259
15109
|
}
|
|
15260
15110
|
const validated = await validateRouterAbEcdsaDerivationWalletSessionInputs({
|
|
15111
|
+
materialActivation: parsedRequest.material_activation,
|
|
15261
15112
|
headers: input.headers,
|
|
15262
15113
|
authorizationSessions: input.authorizationSessions,
|
|
15263
15114
|
operationKind: "evm.sign_transaction"
|
|
15264
15115
|
});
|
|
15265
15116
|
if (!validated.ok) {
|
|
15266
|
-
if (validated.code === "wallet_session_unavailable" && input.authorizationSessions) {
|
|
15267
|
-
const exhaustedCandidate = await resolveRouterAbEcdsaExhaustedCandidateAuthorization({
|
|
15268
|
-
phase: input.phase,
|
|
15269
|
-
body: input.body,
|
|
15270
|
-
headers: input.headers,
|
|
15271
|
-
authorizationSessions: input.authorizationSessions,
|
|
15272
|
-
admissionAdapter: input.admissionAdapter,
|
|
15273
|
-
resolveEcdsaMaterialActivation: input.resolveEcdsaMaterialActivation
|
|
15274
|
-
});
|
|
15275
|
-
if (exhaustedCandidate) return exhaustedCandidate;
|
|
15276
|
-
}
|
|
15277
15117
|
const stepUp = await resolveRouterAbEcdsaOwnerOperationStepUpPreparation({
|
|
15278
15118
|
body: input.body,
|
|
15279
15119
|
phase: input.phase,
|
|
@@ -15290,10 +15130,21 @@ async function authorizeRouterAbEcdsaDerivationNormalSigningRoute(input) {
|
|
|
15290
15130
|
})
|
|
15291
15131
|
};
|
|
15292
15132
|
}
|
|
15133
|
+
if (validated.kind === "wallet_session_operation_credential_exhausted_candidate_v1") return await resolveRouterAbEcdsaExhaustedCandidateAuthorization({
|
|
15134
|
+
materialRead: validated.materialRead,
|
|
15135
|
+
policyRead: validated.policyRead,
|
|
15136
|
+
phase: input.phase,
|
|
15137
|
+
request: parsedRequest,
|
|
15138
|
+
candidate: validated.candidate,
|
|
15139
|
+
admissionAdapter: input.admissionAdapter,
|
|
15140
|
+
resolveEcdsaMaterialActivation: input.resolveEcdsaMaterialActivation
|
|
15141
|
+
});
|
|
15293
15142
|
const session = validated.admission.context.authorization.session;
|
|
15294
15143
|
const authorized = await authorizeRouterAbEcdsaWalletSessionRequest({
|
|
15144
|
+
materialRead: validated.materialRead,
|
|
15145
|
+
policyRead: validated.policyRead,
|
|
15295
15146
|
phase: input.phase,
|
|
15296
|
-
|
|
15147
|
+
request: parsedRequest,
|
|
15297
15148
|
session,
|
|
15298
15149
|
admittedMaterialActivation: routerAbMpcMaterialActivationRefToWire(validated.admission.admission.materialActivation),
|
|
15299
15150
|
admissionAdapter: input.admissionAdapter,
|
|
@@ -15860,18 +15711,13 @@ async function executeRouterAbEcdsaDerivationNormalSigningRoute(input, timing) {
|
|
|
15860
15711
|
binding: await ecdsaOperationStepUpBinding(input.ctx, authorization.session, authorizedOperation)
|
|
15861
15712
|
});
|
|
15862
15713
|
} else {
|
|
15714
|
+
const request = input.phase === "prepare" ? parseRouterAbEcdsaDerivationEvmDigestSigningRequestV1(input.body) : parseRouterAbEcdsaDerivationEvmDigestSigningFinalizeRequestV1(input.body);
|
|
15863
15715
|
const operation = await admitRouterAbEcdsaReusableWalletSessionOperation({
|
|
15864
|
-
|
|
15865
|
-
|
|
15866
|
-
|
|
15867
|
-
|
|
15868
|
-
|
|
15869
|
-
} : {
|
|
15870
|
-
kind: "wallet_session_operation_credential_exhausted_candidate_v1",
|
|
15871
|
-
candidate: authorization.candidate
|
|
15872
|
-
},
|
|
15873
|
-
authorizedOperations: input.ctx.service.authorizedOperations,
|
|
15874
|
-
resolveEcdsaMaterialActivation: input.ctx.service.walletRegistration.resolveEcdsaMaterialActivation.bind(input.ctx.service.walletRegistration)
|
|
15716
|
+
phase: input.phase,
|
|
15717
|
+
request,
|
|
15718
|
+
material: authorization.activeMaterial,
|
|
15719
|
+
binding: authorization,
|
|
15720
|
+
authorizedOperations: input.ctx.service.authorizedOperations
|
|
15875
15721
|
});
|
|
15876
15722
|
if (!operation.ok) {
|
|
15877
15723
|
const failureBody = operation.error.body;
|
|
@@ -15897,11 +15743,6 @@ async function executeRouterAbEcdsaDerivationNormalSigningRoute(input, timing) {
|
|
|
15897
15743
|
return json$1(failure.body, { status: failure.status });
|
|
15898
15744
|
}
|
|
15899
15745
|
if (operation.admission.kind === "replayed") return routerAbEcdsaReplayResponse(operation.admission.operation);
|
|
15900
|
-
if (operation.admission.kind === "claimed" && input.phase === "finalize") return json$1({
|
|
15901
|
-
ok: false,
|
|
15902
|
-
code: "authorized_operation_missing",
|
|
15903
|
-
message: "ECDSA finalize requires a claimed prepare operation"
|
|
15904
|
-
}, { status: 409 });
|
|
15905
15746
|
const ownerDecision = decideRouterAbEcdsaOwnerOperationAuthorization({ operation: operation.admission.operation });
|
|
15906
15747
|
switch (ownerDecision.kind) {
|
|
15907
15748
|
case "authorized": break;
|
|
@@ -16126,6 +15967,7 @@ async function issueEcdsaOperationStepUpAuthorization(input) {
|
|
|
16126
15967
|
message: v2Resolution.message
|
|
16127
15968
|
}, { status: 403 });
|
|
16128
15969
|
const activeMaterial = v2Resolution.kind === "admitted" ? v2Resolution.activeMaterial : await input.ctx.service.walletRegistration.resolveEcdsaMaterialActivation({
|
|
15970
|
+
source: { kind: "database" },
|
|
16129
15971
|
walletId: operation.wallet_id,
|
|
16130
15972
|
materialActivation: operation.material_activation
|
|
16131
15973
|
});
|
|
@@ -16444,7 +16286,6 @@ async function issueEcdsaOperationStepUpAuthorization(input) {
|
|
|
16444
16286
|
async function handleEcdsaPoolFillRoute(input) {
|
|
16445
16287
|
const startedAt = performance.now();
|
|
16446
16288
|
const timing = {
|
|
16447
|
-
queue: null,
|
|
16448
16289
|
authenticate: null,
|
|
16449
16290
|
material: null,
|
|
16450
16291
|
admit: null,
|
|
@@ -16479,31 +16320,24 @@ async function executeEcdsaPoolFillRoute(input, timing, workerTimings) {
|
|
|
16479
16320
|
const parsed = input.phase === "init" ? parseRouterAbEcdsaDerivationPoolFillInitRouteRequest(input.body) : parseRouterAbEcdsaDerivationPoolFillStepRouteRequest(input.body);
|
|
16480
16321
|
if (!parsed.ok) return json$1(parsed.body, { status: thresholdEcdsaStatusCode(parsed.body) });
|
|
16481
16322
|
const request = parsed.request;
|
|
16482
|
-
const
|
|
16483
|
-
|
|
16484
|
-
|
|
16485
|
-
|
|
16486
|
-
|
|
16487
|
-
|
|
16488
|
-
|
|
16489
|
-
|
|
16490
|
-
|
|
16491
|
-
|
|
16492
|
-
|
|
16493
|
-
|
|
16494
|
-
|
|
16495
|
-
|
|
16496
|
-
|
|
16497
|
-
|
|
16498
|
-
|
|
16499
|
-
|
|
16500
|
-
onServerTiming: collectEcdsaPresignWorkerTiming.bind(void 0, workerTimings)
|
|
16501
|
-
});
|
|
16502
|
-
timing.proxy = performance.now() - proxyStartedAt;
|
|
16503
|
-
return json$1(result, { status: thresholdEcdsaStatusCode(result) });
|
|
16504
|
-
} finally {
|
|
16505
|
-
gateTicket.release();
|
|
16506
|
-
}
|
|
16323
|
+
const authorized = await authorizeEcdsaPoolFill({
|
|
16324
|
+
ctx: input.ctx,
|
|
16325
|
+
request,
|
|
16326
|
+
timing
|
|
16327
|
+
});
|
|
16328
|
+
if (!authorized.ok) return json$1(authorized.error.body, { status: authorized.error.status });
|
|
16329
|
+
const proxyStartedAt = performance.now();
|
|
16330
|
+
const result = "poolFill" in request ? await runtime.initializePoolFill({
|
|
16331
|
+
binding: authorized.binding,
|
|
16332
|
+
request: ecdsaPoolFillInitRuntimeRequest(request),
|
|
16333
|
+
onServerTiming: collectEcdsaPresignWorkerTiming.bind(void 0, workerTimings)
|
|
16334
|
+
}) : await runtime.advancePoolFill({
|
|
16335
|
+
binding: authorized.binding,
|
|
16336
|
+
request: ecdsaPoolFillStepRuntimeRequest(request),
|
|
16337
|
+
onServerTiming: collectEcdsaPresignWorkerTiming.bind(void 0, workerTimings)
|
|
16338
|
+
});
|
|
16339
|
+
timing.proxy = performance.now() - proxyStartedAt;
|
|
16340
|
+
return json$1(result, { status: thresholdEcdsaStatusCode(result) });
|
|
16507
16341
|
}
|
|
16508
16342
|
function poolFillMaterialActivation(request) {
|
|
16509
16343
|
return "poolFill" in request ? request.poolFill.scope.material_activation : null;
|
|
@@ -16642,6 +16476,7 @@ async function authorizeEcdsaPoolFill(input) {
|
|
|
16642
16476
|
const admitted = validated;
|
|
16643
16477
|
const materialStartedAt = performance.now();
|
|
16644
16478
|
const activeMaterial = await input.ctx.service.walletRegistration.resolveEcdsaMaterialActivation({
|
|
16479
|
+
source: { kind: "database" },
|
|
16645
16480
|
walletId: String(session.walletId),
|
|
16646
16481
|
materialActivation: routerAbMpcMaterialActivationRefToWire(admitted.materialActivation)
|
|
16647
16482
|
});
|
|
@@ -16730,43 +16565,6 @@ function ecdsaPoolFillStepRuntimeRequest(request) {
|
|
|
16730
16565
|
...request.requestTag === void 0 ? {} : { requestTag: request.requestTag }
|
|
16731
16566
|
};
|
|
16732
16567
|
}
|
|
16733
|
-
function resolvePresignPriorityTurn(resolve) {
|
|
16734
|
-
setTimeout(resolve, 5);
|
|
16735
|
-
}
|
|
16736
|
-
function waitForPresignPriorityTurn() {
|
|
16737
|
-
return new Promise(resolvePresignPriorityTurn);
|
|
16738
|
-
}
|
|
16739
|
-
var PresignPriorityGate = class {
|
|
16740
|
-
constructor() {
|
|
16741
|
-
this.foregroundInFlight = 0;
|
|
16742
|
-
this.backgroundInFlight = 0;
|
|
16743
|
-
}
|
|
16744
|
-
async acquire(trafficClass) {
|
|
16745
|
-
if (trafficClass === "foreground") {
|
|
16746
|
-
this.foregroundInFlight += 1;
|
|
16747
|
-
return this.createTicket("foreground");
|
|
16748
|
-
}
|
|
16749
|
-
while (!this.canRunBackgroundNow()) await waitForPresignPriorityTurn();
|
|
16750
|
-
this.backgroundInFlight += 1;
|
|
16751
|
-
return this.createTicket("background");
|
|
16752
|
-
}
|
|
16753
|
-
createTicket(trafficClass) {
|
|
16754
|
-
let released = false;
|
|
16755
|
-
return { release: () => {
|
|
16756
|
-
if (released) return;
|
|
16757
|
-
released = true;
|
|
16758
|
-
if (trafficClass === "foreground") this.foregroundInFlight = Math.max(0, this.foregroundInFlight - 1);
|
|
16759
|
-
else this.backgroundInFlight = Math.max(0, this.backgroundInFlight - 1);
|
|
16760
|
-
} };
|
|
16761
|
-
}
|
|
16762
|
-
canRunBackgroundNow() {
|
|
16763
|
-
return this.foregroundInFlight === 0 && this.backgroundInFlight === 0;
|
|
16764
|
-
}
|
|
16765
|
-
};
|
|
16766
|
-
function resolvePresignTrafficClass(requestTag) {
|
|
16767
|
-
return requestTag === "background_presign_pool_refill" ? "background" : "foreground";
|
|
16768
|
-
}
|
|
16769
|
-
const presignPriorityGate = new PresignPriorityGate();
|
|
16770
16568
|
function strictEcdsaAuthorizationFailureStatus(failure) {
|
|
16771
16569
|
switch (failure.code) {
|
|
16772
16570
|
case "unauthorized": return 401;
|
|
@@ -17149,6 +16947,7 @@ async function authorizeStrictEcdsaExport(input) {
|
|
|
17149
16947
|
scope: operation.normal_signing_scope
|
|
17150
16948
|
})) return strictEcdsaExportFailure(403, "scope_mismatch", "ECDSA export operation scope does not match the request");
|
|
17151
16949
|
const activeMaterial = await input.ctx.service.walletRegistration.resolveEcdsaMaterialActivation({
|
|
16950
|
+
source: { kind: "database" },
|
|
17152
16951
|
walletId: operation.wallet_id,
|
|
17153
16952
|
materialActivation: input.request.material_activation
|
|
17154
16953
|
});
|
|
@@ -17453,7 +17252,6 @@ async function handleThresholdEcdsa(ctx) {
|
|
|
17453
17252
|
}
|
|
17454
17253
|
//#endregion
|
|
17455
17254
|
//#region src/router/domains/emailOtp/emailOtpRouteHandlers.ts
|
|
17456
|
-
const EMAIL_OTP_FACTOR_RELEASE_AAD_DOMAIN = "seams/email-otp/factor-release/v1";
|
|
17457
17255
|
function decodeEmailOtpFactorSecret32(value) {
|
|
17458
17256
|
const magnitude = base64UrlDecode(value);
|
|
17459
17257
|
if (magnitude.length === 0 || magnitude.length > 32) {
|
|
@@ -17467,7 +17265,7 @@ function decodeEmailOtpFactorSecret32(value) {
|
|
|
17467
17265
|
}
|
|
17468
17266
|
function emailOtpFactorReleaseAad(input) {
|
|
17469
17267
|
return new TextEncoder().encode([
|
|
17470
|
-
|
|
17268
|
+
EMAIL_OTP_FACTOR_RELEASE_AAD_DOMAIN_V1,
|
|
17471
17269
|
input.walletId,
|
|
17472
17270
|
input.enrollmentId,
|
|
17473
17271
|
input.enrollmentSealKeyVersion,
|
|
@@ -17481,19 +17279,11 @@ async function sealEmailOtpFactorSecretForWorker(input) {
|
|
|
17481
17279
|
factorSecret32 = decodeEmailOtpFactorSecret32(input.factorSecret32B64u);
|
|
17482
17280
|
workerPublicKey65 = base64UrlDecode(input.workerEphemeralPublicKey65B64u);
|
|
17483
17281
|
} catch {
|
|
17484
|
-
return
|
|
17485
|
-
ok: false,
|
|
17486
|
-
code: "invalid_body",
|
|
17487
|
-
message: "Email OTP factor release key is invalid"
|
|
17488
|
-
};
|
|
17282
|
+
return failure("invalid_body", "Email OTP factor release key is invalid");
|
|
17489
17283
|
}
|
|
17490
17284
|
if (workerPublicKey65.length !== 65 || workerPublicKey65[0] !== 4) {
|
|
17491
17285
|
factorSecret32.fill(0);
|
|
17492
|
-
return
|
|
17493
|
-
ok: false,
|
|
17494
|
-
code: "invalid_body",
|
|
17495
|
-
message: "Email OTP factor release key is invalid"
|
|
17496
|
-
};
|
|
17286
|
+
return failure("invalid_body", "Email OTP factor release key is invalid");
|
|
17497
17287
|
}
|
|
17498
17288
|
try {
|
|
17499
17289
|
const workerPublicKey = await crypto.subtle.importKey("raw", workerPublicKey65, {
|
|
@@ -17525,11 +17315,7 @@ async function sealEmailOtpFactorSecretForWorker(input) {
|
|
|
17525
17315
|
ciphertextB64u: base64UrlEncode(ciphertext)
|
|
17526
17316
|
};
|
|
17527
17317
|
} catch {
|
|
17528
|
-
return
|
|
17529
|
-
ok: false,
|
|
17530
|
-
code: "factor_release_failed",
|
|
17531
|
-
message: "Email OTP factor release encryption failed"
|
|
17532
|
-
};
|
|
17318
|
+
return failure("factor_release_failed", "Email OTP factor release encryption failed");
|
|
17533
17319
|
} finally {
|
|
17534
17320
|
factorSecret32.fill(0);
|
|
17535
17321
|
}
|
|
@@ -17541,11 +17327,7 @@ async function handleEmailOtpDevCleanupGoogleRegistrationRoute(input) {
|
|
|
17541
17327
|
const code = verified.code || "not_verified";
|
|
17542
17328
|
return {
|
|
17543
17329
|
status: code === "internal" ? 500 : code === "not_configured" || code === "unsupported" ? 501 : code === "invalid_body" ? 400 : 401,
|
|
17544
|
-
body:
|
|
17545
|
-
ok: false,
|
|
17546
|
-
code,
|
|
17547
|
-
message: verified.message || "Google login failed"
|
|
17548
|
-
}
|
|
17330
|
+
body: failure(code, verified.message || "Google login failed")
|
|
17549
17331
|
};
|
|
17550
17332
|
}
|
|
17551
17333
|
const runtimePolicyScope = isPlainObject(body.runtimePolicyScope) ? body.runtimePolicyScope : null;
|
|
@@ -17562,30 +17344,18 @@ async function handleEmailOtpDevCleanupGoogleRegistrationRoute(input) {
|
|
|
17562
17344
|
async function handleEmailOtpRegistrationSealRoute(input) {
|
|
17563
17345
|
if (!isPlainObject(input.body)) return {
|
|
17564
17346
|
status: 400,
|
|
17565
|
-
body:
|
|
17566
|
-
ok: false,
|
|
17567
|
-
code: "invalid_body",
|
|
17568
|
-
message: "Invalid body"
|
|
17569
|
-
}
|
|
17347
|
+
body: failure("invalid_body", "Invalid body")
|
|
17570
17348
|
};
|
|
17571
17349
|
const allowedFields = new Set(["walletId", "wrappedCiphertext"]);
|
|
17572
17350
|
for (const field of Object.keys(input.body)) if (!allowedFields.has(field)) return {
|
|
17573
17351
|
status: 400,
|
|
17574
|
-
body: {
|
|
17575
|
-
ok: false,
|
|
17576
|
-
code: "invalid_body",
|
|
17577
|
-
message: `Unsupported field: ${field}`
|
|
17578
|
-
}
|
|
17352
|
+
body: failure("invalid_body", `Unsupported field: ${field}`)
|
|
17579
17353
|
};
|
|
17580
17354
|
const walletId = normalizeOptionalTrimmedString(input.body.walletId);
|
|
17581
17355
|
const wrappedCiphertext = normalizeOptionalTrimmedString(input.body.wrappedCiphertext);
|
|
17582
17356
|
if (!walletId || !wrappedCiphertext) return {
|
|
17583
17357
|
status: 400,
|
|
17584
|
-
body:
|
|
17585
|
-
ok: false,
|
|
17586
|
-
code: "invalid_body",
|
|
17587
|
-
message: "Missing walletId or wrappedCiphertext"
|
|
17588
|
-
}
|
|
17358
|
+
body: failure("invalid_body", "Missing walletId or wrappedCiphertext")
|
|
17589
17359
|
};
|
|
17590
17360
|
const result = await input.service.applyEmailOtpServerSeal({ wrappedCiphertext });
|
|
17591
17361
|
return {
|
|
@@ -17599,11 +17369,7 @@ async function handleEmailOtpRegistrationSealRoute(input) {
|
|
|
17599
17369
|
async function handleEmailOtpDevOutboxRoute(input) {
|
|
17600
17370
|
if (!isPlainObject(input.body)) return {
|
|
17601
17371
|
status: 400,
|
|
17602
|
-
body:
|
|
17603
|
-
ok: false,
|
|
17604
|
-
code: "invalid_body",
|
|
17605
|
-
message: "Invalid body"
|
|
17606
|
-
}
|
|
17372
|
+
body: failure("invalid_body", "Invalid body")
|
|
17607
17373
|
};
|
|
17608
17374
|
const allowedFields = new Set([
|
|
17609
17375
|
"idToken",
|
|
@@ -17613,11 +17379,7 @@ async function handleEmailOtpDevOutboxRoute(input) {
|
|
|
17613
17379
|
]);
|
|
17614
17380
|
for (const field of Object.keys(input.body)) if (!allowedFields.has(field)) return {
|
|
17615
17381
|
status: 400,
|
|
17616
|
-
body: {
|
|
17617
|
-
ok: false,
|
|
17618
|
-
code: "invalid_body",
|
|
17619
|
-
message: `Unsupported field: ${field}`
|
|
17620
|
-
}
|
|
17382
|
+
body: failure("invalid_body", `Unsupported field: ${field}`)
|
|
17621
17383
|
};
|
|
17622
17384
|
const idToken = normalizeOptionalTrimmedString(input.body.idToken);
|
|
17623
17385
|
const walletId = normalizeOptionalTrimmedString(input.body.walletId);
|
|
@@ -17625,30 +17387,18 @@ async function handleEmailOtpDevOutboxRoute(input) {
|
|
|
17625
17387
|
const challengeSubjectId = normalizeOptionalTrimmedString(input.body.challengeSubjectId);
|
|
17626
17388
|
if (!idToken || !walletId) return {
|
|
17627
17389
|
status: 400,
|
|
17628
|
-
body:
|
|
17629
|
-
ok: false,
|
|
17630
|
-
code: "invalid_body",
|
|
17631
|
-
message: "Missing idToken or walletId"
|
|
17632
|
-
}
|
|
17390
|
+
body: failure("invalid_body", "Missing idToken or walletId")
|
|
17633
17391
|
};
|
|
17634
17392
|
if (challengeSubjectId && !challengeId) return {
|
|
17635
17393
|
status: 400,
|
|
17636
|
-
body:
|
|
17637
|
-
ok: false,
|
|
17638
|
-
code: "invalid_body",
|
|
17639
|
-
message: "challengeSubjectId requires the exact challengeId it belongs to"
|
|
17640
|
-
}
|
|
17394
|
+
body: failure("invalid_body", "challengeSubjectId requires the exact challengeId it belongs to")
|
|
17641
17395
|
};
|
|
17642
17396
|
const verified = await input.service.verifyGoogleLogin({ idToken });
|
|
17643
17397
|
if (!verified.ok || !verified.verified || !verified.userId) {
|
|
17644
17398
|
const code = verified.code || "not_verified";
|
|
17645
17399
|
return {
|
|
17646
17400
|
status: code === "internal" ? 500 : code === "not_configured" ? 501 : 401,
|
|
17647
|
-
body:
|
|
17648
|
-
ok: false,
|
|
17649
|
-
code,
|
|
17650
|
-
message: verified.message || "Google login failed"
|
|
17651
|
-
}
|
|
17401
|
+
body: failure(code, verified.message || "Google login failed")
|
|
17652
17402
|
};
|
|
17653
17403
|
}
|
|
17654
17404
|
const result = await input.service.readEmailOtpOutboxEntry({
|
|
@@ -17894,6 +17644,7 @@ async function resolveWalletEmailOtpChallengeSignerSelection(args) {
|
|
|
17894
17644
|
};
|
|
17895
17645
|
}
|
|
17896
17646
|
const resolved = await args.ctx.service.walletRegistration.resolveEcdsaMaterialActivation({
|
|
17647
|
+
source: { kind: "database" },
|
|
17897
17648
|
walletId: String(args.authority.walletId),
|
|
17898
17649
|
materialActivation: routerAbMpcMaterialActivationRefToWire(ecdsaActivation.materialActivation)
|
|
17899
17650
|
});
|
|
@@ -19120,11 +18871,7 @@ async function handleSyncAccount(ctx) {
|
|
|
19120
18871
|
let responseBody = result;
|
|
19121
18872
|
if (result.ok && result.verified && result.thresholdEd25519) {
|
|
19122
18873
|
const custodyKeyManifestDigestB64u = result.custodyKeyManifestDigestB64u;
|
|
19123
|
-
if (!custodyKeyManifestDigestB64u) return
|
|
19124
|
-
ok: false,
|
|
19125
|
-
code: "internal",
|
|
19126
|
-
message: "Sync verification did not resolve the wallet key manifest"
|
|
19127
|
-
}, { status: 500 });
|
|
18874
|
+
if (!custodyKeyManifestDigestB64u) return jsonFailure(500, "internal", "Sync verification did not resolve the wallet key manifest");
|
|
19128
18875
|
const thresholdEd25519 = result.thresholdEd25519;
|
|
19129
18876
|
const walletId = String(result.walletId || "").trim();
|
|
19130
18877
|
const nearAccountId = String(result.nearAccountId || "").trim();
|
|
@@ -19132,11 +18879,7 @@ async function handleSyncAccount(ctx) {
|
|
|
19132
18879
|
const signerSlot = Number(result.signerSlot);
|
|
19133
18880
|
const walletBinding = result.walletBinding;
|
|
19134
18881
|
const credentialIdB64u = String(result.credentialIdB64u || "").trim();
|
|
19135
|
-
if (!thresholdEd25519 || !walletId || !nearAccountId || !nearEd25519SigningKeyId || !Number.isSafeInteger(signerSlot) || signerSlot < 1 || !walletBinding || !credentialIdB64u || !String(result.publicKey || "").trim() || !String(result.credentialPublicKeyB64u || "").trim() || String(walletBinding.walletId) !== walletId || String(walletBinding.nearAccountId) !== nearAccountId || String(walletBinding.nearEd25519SigningKeyId) !== nearEd25519SigningKeyId || walletBinding.signerSlot !== signerSlot) return
|
|
19136
|
-
ok: false,
|
|
19137
|
-
code: "internal",
|
|
19138
|
-
message: "verified passkey wallet is missing its Ed25519 Yao identity"
|
|
19139
|
-
}, { status: 500 });
|
|
18882
|
+
if (!thresholdEd25519 || !walletId || !nearAccountId || !nearEd25519SigningKeyId || !Number.isSafeInteger(signerSlot) || signerSlot < 1 || !walletBinding || !credentialIdB64u || !String(result.publicKey || "").trim() || !String(result.credentialPublicKeyB64u || "").trim() || String(walletBinding.walletId) !== walletId || String(walletBinding.nearAccountId) !== nearAccountId || String(walletBinding.nearEd25519SigningKeyId) !== nearEd25519SigningKeyId || walletBinding.signerSlot !== signerSlot) return jsonFailure(500, "internal", "verified passkey wallet is missing its Ed25519 Yao identity");
|
|
19140
18883
|
const authority = passkeyWalletAuthAuthorityForMethod({
|
|
19141
18884
|
walletId: walletBinding.walletId,
|
|
19142
18885
|
rpId: walletBinding.rpId,
|
|
@@ -19148,29 +18891,17 @@ async function handleSyncAccount(ctx) {
|
|
|
19148
18891
|
rpId: authority.verifier.rpId,
|
|
19149
18892
|
credentialIdB64u: authority.factor.credentialIdB64u
|
|
19150
18893
|
});
|
|
19151
|
-
if (!activeAuthority.ok || activeAuthority.walletAuthority.authorityId !== result.walletAuthorityId || activeAuthority.authMethod.walletAuthMethodId !== result.walletAuthMethodId) return
|
|
19152
|
-
ok: false,
|
|
19153
|
-
code: "internal",
|
|
19154
|
-
message: "Verified passkey wallet authority is unavailable"
|
|
19155
|
-
}, { status: 500 });
|
|
18894
|
+
if (!activeAuthority.ok || activeAuthority.walletAuthority.authorityId !== result.walletAuthorityId || activeAuthority.authMethod.walletAuthMethodId !== result.walletAuthMethodId) return jsonFailure(500, "internal", "Verified passkey wallet authority is unavailable");
|
|
19156
18895
|
const authorityRef = await walletAuthAuthorityRef({ authority });
|
|
19157
18896
|
const principalId = parsePrincipalId(walletId);
|
|
19158
18897
|
const mintId = parseWalletSessionMintId(parsed.request.challengeId);
|
|
19159
|
-
if (!principalId.ok || !mintId.ok) return
|
|
19160
|
-
ok: false,
|
|
19161
|
-
code: "internal",
|
|
19162
|
-
message: "Verified passkey Wallet Session identity is invalid"
|
|
19163
|
-
}, { status: 500 });
|
|
18898
|
+
if (!principalId.ok || !mintId.ok) return jsonFailure(500, "internal", "Verified passkey Wallet Session identity is invalid");
|
|
19164
18899
|
const issuedAtMs = Date.now();
|
|
19165
18900
|
const expiresAtMs = issuedAtMs + DEFAULT_WALLET_SESSION_TTL_MS;
|
|
19166
18901
|
const origin = parseSessionOrigin(parsed.request.expected_origin);
|
|
19167
18902
|
const factorId = parseAuthFactorId(`passkey:${credentialIdB64u}`);
|
|
19168
18903
|
const credentialId = parseWebAuthnCredentialIdB64u(credentialIdB64u);
|
|
19169
|
-
if (!factorId.ok || !credentialId.ok) return
|
|
19170
|
-
ok: false,
|
|
19171
|
-
code: "internal",
|
|
19172
|
-
message: "Verified passkey factor identity is invalid"
|
|
19173
|
-
}, { status: 500 });
|
|
18904
|
+
if (!factorId.ok || !credentialId.ok) return jsonFailure(500, "internal", "Verified passkey factor identity is invalid");
|
|
19174
18905
|
const proof = await ctx.service.authorizedOperations.buildVerifiedOwnerProof({
|
|
19175
18906
|
purpose: "wallet_session",
|
|
19176
18907
|
proofId: parseVerifiedOwnerProofId(`sync-account:${parsed.request.challengeId}`),
|
|
@@ -19188,11 +18919,7 @@ async function handleSyncAccount(ctx) {
|
|
|
19188
18919
|
expiresAtMs
|
|
19189
18920
|
})
|
|
19190
18921
|
});
|
|
19191
|
-
if (proof.purpose !== "wallet_session") return
|
|
19192
|
-
ok: false,
|
|
19193
|
-
code: "internal",
|
|
19194
|
-
message: "Owner proof purpose is invalid"
|
|
19195
|
-
}, { status: 500 });
|
|
18922
|
+
if (proof.purpose !== "wallet_session") return jsonFailure(500, "internal", "Owner proof purpose is invalid");
|
|
19196
18923
|
const bootstrap = await issueSyncAccountBootstrapV1({
|
|
19197
18924
|
ctx,
|
|
19198
18925
|
result: {
|
|
@@ -19233,11 +18960,7 @@ async function handleSyncAccount(ctx) {
|
|
|
19233
18960
|
message: "Wallet Session sync is already committed; retry the exact method",
|
|
19234
18961
|
...bootstrap.committed
|
|
19235
18962
|
}, { status: 409 });
|
|
19236
|
-
if (bootstrap.kind === "error") return
|
|
19237
|
-
ok: false,
|
|
19238
|
-
code: bootstrap.code,
|
|
19239
|
-
message: bootstrap.message
|
|
19240
|
-
}, { status: bootstrap.status });
|
|
18963
|
+
if (bootstrap.kind === "error") return jsonFailure(bootstrap.status, bootstrap.code, bootstrap.message);
|
|
19241
18964
|
responseBody = bootstrap.body;
|
|
19242
18965
|
}
|
|
19243
18966
|
return json$1(responseBody, { status: syncAccountResponseStatus(result) });
|
|
@@ -21780,11 +21503,13 @@ async function handleOwnerWalletExecutionLanePreflight(ctx) {
|
|
|
21780
21503
|
};
|
|
21781
21504
|
} else {
|
|
21782
21505
|
const validated = await validateRouterAbEcdsaDerivationWalletSessionInputs({
|
|
21506
|
+
materialActivation: routerAbMpcMaterialActivationRefToWire(request.expectedMaterialActivation),
|
|
21783
21507
|
headers,
|
|
21784
21508
|
authorizationSessions: ctx.service.authorizationSessions,
|
|
21785
21509
|
operationKind: EVM_ECDSA_MPC_OPERATION_KINDS.signTransaction
|
|
21786
21510
|
});
|
|
21787
21511
|
if (!validated.ok) return validationFailure(validated);
|
|
21512
|
+
if (validated.kind === "wallet_session_operation_credential_exhausted_candidate_v1") return validationFailure(walletSessionFailure("wallet_session_unavailable"));
|
|
21788
21513
|
walletIdRaw = String(validated.admission.context.authorization.session.walletId);
|
|
21789
21514
|
authorization = {
|
|
21790
21515
|
kind: "wallet_auth_method",
|
|
@@ -21832,22 +21557,14 @@ async function handleWebAuthnAuthenticators(ctx) {
|
|
|
21832
21557
|
if (ctx.pathname !== "/webauthn/authenticators") return null;
|
|
21833
21558
|
try {
|
|
21834
21559
|
const token = extractBearerCredential(ctx.request.headers);
|
|
21835
|
-
if (!token) return
|
|
21836
|
-
ok: false,
|
|
21837
|
-
code: "unauthorized",
|
|
21838
|
-
message: "No valid Wallet Session"
|
|
21839
|
-
}, { status: 401 });
|
|
21560
|
+
if (!token) return jsonFailure(401, "unauthorized", "No valid Wallet Session");
|
|
21840
21561
|
const nowMs = Date.now();
|
|
21841
21562
|
const exact = await ctx.service.authorizationSessions.readWalletSessionAuthorizationV2ByOperationCredential({
|
|
21842
21563
|
tenantId: ctx.service.authorizationSessions.tenantId,
|
|
21843
21564
|
token,
|
|
21844
21565
|
nowMs
|
|
21845
21566
|
});
|
|
21846
|
-
if (!exact) return
|
|
21847
|
-
ok: false,
|
|
21848
|
-
code: "unauthorized",
|
|
21849
|
-
message: "No valid Wallet Session"
|
|
21850
|
-
}, { status: 401 });
|
|
21567
|
+
if (!exact) return jsonFailure(401, "unauthorized", "No valid Wallet Session");
|
|
21851
21568
|
const rpIdFromQuery = String(ctx.url.searchParams.get("rpId") || ctx.url.searchParams.get("rp_id") || "").trim();
|
|
21852
21569
|
const result = await ctx.service.webAuthn.listWebAuthnAuthenticatorsForUser({
|
|
21853
21570
|
userId: String(exact.authorization.session.walletId),
|
|
@@ -21856,11 +21573,7 @@ async function handleWebAuthnAuthenticators(ctx) {
|
|
|
21856
21573
|
if (!result.ok) return json$1(result, { status: result.code === "not_supported" ? 501 : result.code === "invalid_args" ? 400 : 500 });
|
|
21857
21574
|
return json$1(result, { status: 200 });
|
|
21858
21575
|
} catch (e) {
|
|
21859
|
-
return
|
|
21860
|
-
ok: false,
|
|
21861
|
-
code: "internal",
|
|
21862
|
-
message: e?.message || "Internal error"
|
|
21863
|
-
}, { status: 500 });
|
|
21576
|
+
return jsonFailure(500, "internal", e?.message || "Internal error");
|
|
21864
21577
|
}
|
|
21865
21578
|
}
|
|
21866
21579
|
//#endregion
|
|
@@ -22133,11 +21846,7 @@ async function requireExactWalletSession(ctx) {
|
|
|
22133
21846
|
const token = extractBearerCredential(ctx.request.headers);
|
|
22134
21847
|
if (!token) return {
|
|
22135
21848
|
ok: false,
|
|
22136
|
-
response:
|
|
22137
|
-
ok: false,
|
|
22138
|
-
code: "unauthorized",
|
|
22139
|
-
message: "No valid Wallet Session"
|
|
22140
|
-
}, { status: 401 })
|
|
21849
|
+
response: jsonFailure(401, "unauthorized", "No valid Wallet Session")
|
|
22141
21850
|
};
|
|
22142
21851
|
try {
|
|
22143
21852
|
const context = await ctx.service.authorizationSessions.readWalletSessionAuthorizationV2ByOperationCredential({
|
|
@@ -22147,11 +21856,7 @@ async function requireExactWalletSession(ctx) {
|
|
|
22147
21856
|
});
|
|
22148
21857
|
if (!context) return {
|
|
22149
21858
|
ok: false,
|
|
22150
|
-
response:
|
|
22151
|
-
ok: false,
|
|
22152
|
-
code: "unauthorized",
|
|
22153
|
-
message: "No valid Wallet Session"
|
|
22154
|
-
}, { status: 401 })
|
|
21859
|
+
response: jsonFailure(401, "unauthorized", "No valid Wallet Session")
|
|
22155
21860
|
};
|
|
22156
21861
|
return {
|
|
22157
21862
|
ok: true,
|
|
@@ -22160,11 +21865,7 @@ async function requireExactWalletSession(ctx) {
|
|
|
22160
21865
|
} catch {
|
|
22161
21866
|
return {
|
|
22162
21867
|
ok: false,
|
|
22163
|
-
response:
|
|
22164
|
-
ok: false,
|
|
22165
|
-
code: "wallet_session_unavailable",
|
|
22166
|
-
message: "Wallet Session is unavailable"
|
|
22167
|
-
}, { status: 503 })
|
|
21868
|
+
response: jsonFailure(503, "wallet_session_unavailable", "Wallet Session is unavailable")
|
|
22168
21869
|
};
|
|
22169
21870
|
}
|
|
22170
21871
|
}
|
|
@@ -22177,19 +21878,11 @@ async function requireExactPasskeyStepUp(input) {
|
|
|
22177
21878
|
const walletId = String(input.context.authorization.session.walletId);
|
|
22178
21879
|
if (String(result.userId).trim() !== walletId) return {
|
|
22179
21880
|
ok: false,
|
|
22180
|
-
response:
|
|
22181
|
-
ok: false,
|
|
22182
|
-
code: "forbidden",
|
|
22183
|
-
message: "Step-up user mismatch"
|
|
22184
|
-
}, { status: 403 })
|
|
21881
|
+
response: jsonFailure(403, "forbidden", "Step-up user mismatch")
|
|
22185
21882
|
};
|
|
22186
21883
|
if (result.walletAuthMethodId !== input.context.authMethod.walletAuthMethodId || result.walletAuthorityId !== input.context.authority.authorityId) return {
|
|
22187
21884
|
ok: false,
|
|
22188
|
-
response:
|
|
22189
|
-
ok: false,
|
|
22190
|
-
code: "forbidden",
|
|
22191
|
-
message: "Step-up authority mismatch"
|
|
22192
|
-
}, { status: 403 })
|
|
21885
|
+
response: jsonFailure(403, "forbidden", "Step-up authority mismatch")
|
|
22193
21886
|
};
|
|
22194
21887
|
return { ok: true };
|
|
22195
21888
|
}
|
|
@@ -22247,11 +21940,7 @@ async function handleAuth(ctx) {
|
|
|
22247
21940
|
default: assertNeverAuthIdentityMutation(command);
|
|
22248
21941
|
}
|
|
22249
21942
|
const subject = command.request.subject;
|
|
22250
|
-
if (subject.startsWith("near:")) return
|
|
22251
|
-
ok: false,
|
|
22252
|
-
code: "not_supported",
|
|
22253
|
-
message: "near: subjects cannot be unlinked"
|
|
22254
|
-
}, { status: 400 });
|
|
21943
|
+
if (subject.startsWith("near:")) return jsonFailure(400, "not_supported", "near: subjects cannot be unlinked");
|
|
22255
21944
|
const out = await ctx.service.identity.unlinkIdentity({
|
|
22256
21945
|
userId: walletId,
|
|
22257
21946
|
subject
|
|
@@ -22308,16 +21997,8 @@ async function handleAuth(ctx) {
|
|
|
22308
21997
|
publishableKeyAuth: ctx.opts.publishableKeyAuth,
|
|
22309
21998
|
orgProjectEnv: ctx.opts.orgProjectEnv
|
|
22310
21999
|
});
|
|
22311
|
-
if (!runtimePolicyScope.ok) return
|
|
22312
|
-
|
|
22313
|
-
code: runtimePolicyScope.code,
|
|
22314
|
-
message: runtimePolicyScope.message
|
|
22315
|
-
}, { status: runtimePolicyScope.status });
|
|
22316
|
-
if (!runtimePolicyScope.scope) return json$1({
|
|
22317
|
-
ok: false,
|
|
22318
|
-
code: "runtime_policy_scope_unavailable",
|
|
22319
|
-
message: "Google Email OTP requires an active managed runtime policy scope"
|
|
22320
|
-
}, { status: 500 });
|
|
22000
|
+
if (!runtimePolicyScope.ok) return jsonFailure(runtimePolicyScope.status, runtimePolicyScope.code, runtimePolicyScope.message);
|
|
22001
|
+
if (!runtimePolicyScope.scope) return jsonFailure(500, "runtime_policy_scope_unavailable", "Google Email OTP requires an active managed runtime policy scope");
|
|
22321
22002
|
const result = await ctx.service.identity.verifyGoogleLogin(parsed.request);
|
|
22322
22003
|
if (!result.ok || !result.verified || !result.providerSubject) return json$1(result, { status: result.code === "internal" ? 500 : 400 });
|
|
22323
22004
|
const resolution = await ctx.service.identity.resolveGoogleEmailOtpSession({
|
|
@@ -22340,31 +22021,19 @@ async function handleNearPublicKeys(ctx) {
|
|
|
22340
22021
|
if (ctx.pathname !== "/near/public-keys") return null;
|
|
22341
22022
|
try {
|
|
22342
22023
|
const token = extractBearerCredential(ctx.request.headers);
|
|
22343
|
-
if (!token) return
|
|
22344
|
-
ok: false,
|
|
22345
|
-
code: "unauthorized",
|
|
22346
|
-
message: "No valid Wallet Session"
|
|
22347
|
-
}, { status: 401 });
|
|
22024
|
+
if (!token) return jsonFailure(401, "unauthorized", "No valid Wallet Session");
|
|
22348
22025
|
const nowMs = Date.now();
|
|
22349
22026
|
const exact = await ctx.service.authorizationSessions.readWalletSessionAuthorizationV2ByOperationCredential({
|
|
22350
22027
|
tenantId: ctx.service.authorizationSessions.tenantId,
|
|
22351
22028
|
token,
|
|
22352
22029
|
nowMs
|
|
22353
22030
|
});
|
|
22354
|
-
if (!exact) return
|
|
22355
|
-
ok: false,
|
|
22356
|
-
code: "unauthorized",
|
|
22357
|
-
message: "No valid Wallet Session"
|
|
22358
|
-
}, { status: 401 });
|
|
22031
|
+
if (!exact) return jsonFailure(401, "unauthorized", "No valid Wallet Session");
|
|
22359
22032
|
const result = await ctx.service.nearFunding.listNearPublicKeysForUser({ userId: String(exact.authorization.session.walletId) });
|
|
22360
22033
|
if (!result.ok) return json$1(result, { status: result.code === "not_supported" ? 501 : result.code === "invalid_args" ? 400 : 500 });
|
|
22361
22034
|
return json$1(result, { status: 200 });
|
|
22362
22035
|
} catch (e) {
|
|
22363
|
-
return
|
|
22364
|
-
ok: false,
|
|
22365
|
-
code: "internal",
|
|
22366
|
-
message: e?.message || "Internal error"
|
|
22367
|
-
}, { status: 500 });
|
|
22036
|
+
return jsonFailure(500, "internal", e?.message || "Internal error");
|
|
22368
22037
|
}
|
|
22369
22038
|
}
|
|
22370
22039
|
//#endregion
|
|
@@ -22482,10 +22151,35 @@ async function handleWellKnown(ctx) {
|
|
|
22482
22151
|
});
|
|
22483
22152
|
}
|
|
22484
22153
|
//#endregion
|
|
22154
|
+
//#region ../shared-ts/src/utils/exactKeys.ts
|
|
22155
|
+
/**
|
|
22156
|
+
* True when `value` is a non-array object whose own enumerable string keys are exactly `keys`.
|
|
22157
|
+
*
|
|
22158
|
+
* A key whose value is `undefined` still counts as present. Symbol, non-enumerable and inherited
|
|
22159
|
+
* keys are not counted, and the prototype is not checked. A list that repeats a key never matches.
|
|
22160
|
+
* Kept apart from validation.ts, which the wallet iframe's boot path loads.
|
|
22161
|
+
*/
|
|
22162
|
+
function hasExactKeys$1(value, keys) {
|
|
22163
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
|
|
22164
|
+
const actual = Object.keys(value);
|
|
22165
|
+
return actual.length === keys.length && actual.every((key) => keys.includes(key));
|
|
22166
|
+
}
|
|
22167
|
+
//#endregion
|
|
22485
22168
|
//#region src/core/deviceLinking/requestProof.ts
|
|
22486
22169
|
function parseLinkedDeviceRequestProofV1(raw) {
|
|
22487
22170
|
if (raw === null || typeof raw !== "object" || Array.isArray(raw)) throw new Error("linked-device request proof must be an object");
|
|
22488
|
-
if (!
|
|
22171
|
+
if (!hasExactKeys$1(raw, [
|
|
22172
|
+
"kind",
|
|
22173
|
+
"linkSessionId",
|
|
22174
|
+
"devicePublicKeyDigestB64u",
|
|
22175
|
+
"requestNonceB64u",
|
|
22176
|
+
"method",
|
|
22177
|
+
"canonicalPath",
|
|
22178
|
+
"bodyDigestB64u",
|
|
22179
|
+
"issuedAtMs",
|
|
22180
|
+
"expiresAtMs",
|
|
22181
|
+
"signatureB64u"
|
|
22182
|
+
])) throw new Error("record contains invalid fields");
|
|
22489
22183
|
const record = raw;
|
|
22490
22184
|
if (record.kind !== "linked_device_request_proof_v1") throw new Error("linked-device request proof kind is invalid");
|
|
22491
22185
|
const linkSessionId = parseSessionId$1(record.linkSessionId);
|
|
@@ -22542,9 +22236,6 @@ function parseFixedB64u(raw, expectedBytes, field) {
|
|
|
22542
22236
|
if (bytes.length !== expectedBytes || base64UrlEncode(bytes) !== raw) throw new Error(`${field} is invalid`);
|
|
22543
22237
|
return raw;
|
|
22544
22238
|
}
|
|
22545
|
-
function isLinkedDeviceRequestProofRecordV1(value) {
|
|
22546
|
-
return Object.keys(value).sort().join("|") === "bodyDigestB64u|canonicalPath|devicePublicKeyDigestB64u|expiresAtMs|issuedAtMs|kind|linkSessionId|method|requestNonceB64u|signatureB64u";
|
|
22547
|
-
}
|
|
22548
22239
|
//#endregion
|
|
22549
22240
|
//#region src/router/transport/fetch/routes/deviceLinking.ts
|
|
22550
22241
|
const DEVICE_LINKING_BASE = "/wallet/device-linking/v1/sessions";
|
|
@@ -24039,11 +23730,7 @@ async function authenticateDeviceLinkingOwnerWalletSessionRequestV1(input) {
|
|
|
24039
23730
|
async function handleDeviceLinkingOwnerAuthorization(ctx, service) {
|
|
24040
23731
|
if (ctx.pathname !== "/wallet/device-linking/v1/owner-authorization") return null;
|
|
24041
23732
|
if (ctx.method !== "POST") return methodNotAllowedResponse();
|
|
24042
|
-
if (!service) return
|
|
24043
|
-
ok: false,
|
|
24044
|
-
code: "not_supported",
|
|
24045
|
-
message: "Linked-device owner authorization is not configured"
|
|
24046
|
-
}, { status: 501 });
|
|
23733
|
+
if (!service) return jsonFailure(501, "not_supported", "Linked-device owner authorization is not configured");
|
|
24047
23734
|
const nowV1 = Date.now;
|
|
24048
23735
|
let body;
|
|
24049
23736
|
let rawBody;
|
|
@@ -24053,11 +23740,7 @@ async function handleDeviceLinkingOwnerAuthorization(ctx, service) {
|
|
|
24053
23740
|
rawBody = await readJson(ctx.request.clone());
|
|
24054
23741
|
body = parseLinkedDeviceOwnerAuthorizationRequestV1(rawBody);
|
|
24055
23742
|
} catch (error) {
|
|
24056
|
-
return
|
|
24057
|
-
ok: false,
|
|
24058
|
-
code: "invalid_body",
|
|
24059
|
-
message: error instanceof Error ? error.message : "Owner authorization body is invalid"
|
|
24060
|
-
}, { status: 400 });
|
|
23743
|
+
return jsonFailure(400, "invalid_body", error instanceof Error ? error.message : "Owner authorization body is invalid");
|
|
24061
23744
|
}
|
|
24062
23745
|
const validated = await authenticateDeviceLinkingOwnerWalletSessionRequestV1({
|
|
24063
23746
|
request: ctx.request,
|
|
@@ -24077,11 +23760,7 @@ async function handleDeviceLinkingOwnerAuthorization(ctx, service) {
|
|
|
24077
23760
|
owner: validated.owner
|
|
24078
23761
|
}), { status: 200 });
|
|
24079
23762
|
} catch (error) {
|
|
24080
|
-
return
|
|
24081
|
-
ok: false,
|
|
24082
|
-
code: "internal",
|
|
24083
|
-
message: error instanceof Error ? error.message : String(error)
|
|
24084
|
-
}, { status: 500 });
|
|
23763
|
+
return jsonFailure(500, "internal", error instanceof Error ? error.message : String(error));
|
|
24085
23764
|
}
|
|
24086
23765
|
}
|
|
24087
23766
|
async function validateOwnerWalletSessionV1(input) {
|
|
@@ -24245,12 +23924,7 @@ function methodNotAllowedResponse() {
|
|
|
24245
23924
|
}, { status: 405 });
|
|
24246
23925
|
}
|
|
24247
23926
|
function authDeniedResponse(value) {
|
|
24248
|
-
|
|
24249
|
-
return json$1({
|
|
24250
|
-
ok: false,
|
|
24251
|
-
code: value.code,
|
|
24252
|
-
message: value.message
|
|
24253
|
-
}, { status });
|
|
23927
|
+
return jsonFailure(value.code === "expired" ? 401 : value.code === "invalid" ? 403 : 401, value.code, value.message);
|
|
24254
23928
|
}
|
|
24255
23929
|
//#endregion
|
|
24256
23930
|
//#region src/threshold/session/signingSessionSeal/transport/fetch.ts
|
|
@@ -24260,20 +23934,6 @@ function json(body, status = 200) {
|
|
|
24260
23934
|
headers: { "Content-Type": "application/json; charset=utf-8" }
|
|
24261
23935
|
});
|
|
24262
23936
|
}
|
|
24263
|
-
async function readJsonSafe(request) {
|
|
24264
|
-
try {
|
|
24265
|
-
return await request.json();
|
|
24266
|
-
} catch {
|
|
24267
|
-
return null;
|
|
24268
|
-
}
|
|
24269
|
-
}
|
|
24270
|
-
function headersToRecord(headers) {
|
|
24271
|
-
const out = {};
|
|
24272
|
-
headers.forEach((value, key) => {
|
|
24273
|
-
out[key] = value;
|
|
24274
|
-
});
|
|
24275
|
-
return out;
|
|
24276
|
-
}
|
|
24277
23937
|
function errMessage(error) {
|
|
24278
23938
|
return error instanceof Error ? error.message : String(error || "Internal error");
|
|
24279
23939
|
}
|
|
@@ -24293,7 +23953,7 @@ async function handleSigningSessionSealRoutes(ctx) {
|
|
|
24293
23953
|
route: isApply ? applyPath : removePath,
|
|
24294
23954
|
operation
|
|
24295
23955
|
});
|
|
24296
|
-
const body = await
|
|
23956
|
+
const body = await readJson(ctx.request);
|
|
24297
23957
|
const parsed = isApply ? parseSigningSessionSealApplyBody(body) : parseSigningSessionSealRemoveBody(body);
|
|
24298
23958
|
if (!parsed.ok) {
|
|
24299
23959
|
ctx.logger.warn("[threshold-signing-session-seal] invalid_body", {
|
|
@@ -24303,11 +23963,7 @@ async function handleSigningSessionSealRoutes(ctx) {
|
|
|
24303
23963
|
message: parsed.message,
|
|
24304
23964
|
durationMs: Math.max(0, Date.now() - startedAtMs)
|
|
24305
23965
|
});
|
|
24306
|
-
return json(
|
|
24307
|
-
ok: false,
|
|
24308
|
-
code: parsed.code,
|
|
24309
|
-
message: parsed.message
|
|
24310
|
-
}, 400);
|
|
23966
|
+
return json(failure(parsed.code, parsed.message), 400);
|
|
24311
23967
|
}
|
|
24312
23968
|
const authorized = await authorizeSigningSessionSealRequest({
|
|
24313
23969
|
options,
|
|
@@ -24323,11 +23979,7 @@ async function handleSigningSessionSealRoutes(ctx) {
|
|
|
24323
23979
|
message: authorized.message || "Unauthorized",
|
|
24324
23980
|
durationMs: Math.max(0, Date.now() - startedAtMs)
|
|
24325
23981
|
});
|
|
24326
|
-
return json(
|
|
24327
|
-
ok: false,
|
|
24328
|
-
code: authorized.code || "unauthorized",
|
|
24329
|
-
message: authorized.message || "Unauthorized"
|
|
24330
|
-
}, signingSessionSealAuthorizeStatusCode(authorized));
|
|
23982
|
+
return json(failure(authorized.code || "unauthorized", authorized.message || "Unauthorized"), signingSessionSealAuthorizeStatusCode(authorized));
|
|
24331
23983
|
}
|
|
24332
23984
|
const result = isApply ? await options.service.applyServerSeal(parsed.value, authorized.auth) : await options.service.removeServerSeal(parsed.value, authorized.auth);
|
|
24333
23985
|
const status = signingSessionSealStatusCode(result);
|
|
@@ -24347,11 +23999,7 @@ async function handleSigningSessionSealRoutes(ctx) {
|
|
|
24347
23999
|
message,
|
|
24348
24000
|
durationMs: Math.max(0, Date.now() - startedAtMs)
|
|
24349
24001
|
});
|
|
24350
|
-
return json(
|
|
24351
|
-
ok: false,
|
|
24352
|
-
code: "internal",
|
|
24353
|
-
message
|
|
24354
|
-
}, 500);
|
|
24002
|
+
return json(failure("internal", message), 500);
|
|
24355
24003
|
}
|
|
24356
24004
|
}
|
|
24357
24005
|
//#endregion
|
|
@@ -24496,6 +24144,7 @@ async function signingSessionSealRecordFromExactAdmission(input) {
|
|
|
24496
24144
|
switch (admission.curve) {
|
|
24497
24145
|
case "ecdsa": {
|
|
24498
24146
|
const active = await input.walletRegistration.resolveEcdsaMaterialActivation({
|
|
24147
|
+
source: { kind: "database" },
|
|
24499
24148
|
walletId,
|
|
24500
24149
|
materialActivation
|
|
24501
24150
|
});
|
|
@@ -24656,11 +24305,7 @@ function createFetchRouter(service, opts, runtime) {
|
|
|
24656
24305
|
async (context) => {
|
|
24657
24306
|
if (!context.pathname.startsWith("/wallet/device-linking/v1/devices")) return null;
|
|
24658
24307
|
const service = context.service.deviceManagement;
|
|
24659
|
-
if (!service) return
|
|
24660
|
-
ok: false,
|
|
24661
|
-
code: "not_supported",
|
|
24662
|
-
message: "Linked-device management is not configured"
|
|
24663
|
-
}, { status: 501 });
|
|
24308
|
+
if (!service) return jsonFailure(501, "not_supported", "Linked-device management is not configured");
|
|
24664
24309
|
return await handleDeviceManagement(context, service);
|
|
24665
24310
|
},
|
|
24666
24311
|
handlePasskeyCustody,
|
|
@@ -24900,45 +24545,17 @@ function parseExpectation(raw) {
|
|
|
24900
24545
|
}
|
|
24901
24546
|
async function validateRuntimeSnapshotExpectation(input) {
|
|
24902
24547
|
const expectationResult = parseExpectation(input.expectationRaw);
|
|
24903
|
-
if (expectationResult.error) return
|
|
24904
|
-
ok: false,
|
|
24905
|
-
code: "runtime_snapshot_invalid_expectation",
|
|
24906
|
-
message: expectationResult.error
|
|
24907
|
-
};
|
|
24548
|
+
if (expectationResult.error) return failure("runtime_snapshot_invalid_expectation", expectationResult.error);
|
|
24908
24549
|
const expectation = expectationResult.parsed;
|
|
24909
24550
|
if (!expectation) return { ok: true };
|
|
24910
24551
|
const scope = input.scope;
|
|
24911
|
-
if (!scope) return
|
|
24912
|
-
|
|
24913
|
-
code: "runtime_snapshot_scope_missing",
|
|
24914
|
-
message: "threshold session is missing runtimePolicyScope"
|
|
24915
|
-
};
|
|
24916
|
-
if (!input.runtimeSnapshots) return {
|
|
24917
|
-
ok: false,
|
|
24918
|
-
code: "runtime_snapshots_not_configured",
|
|
24919
|
-
message: "Runtime snapshot consumer is not configured on this server"
|
|
24920
|
-
};
|
|
24552
|
+
if (!scope) return failure("runtime_snapshot_scope_missing", "threshold session is missing runtimePolicyScope");
|
|
24553
|
+
if (!input.runtimeSnapshots) return failure("runtime_snapshots_not_configured", "Runtime snapshot consumer is not configured on this server");
|
|
24921
24554
|
const latest = await input.runtimeSnapshots.getLatestSnapshot(scope);
|
|
24922
|
-
if (!latest) return {
|
|
24923
|
-
|
|
24924
|
-
|
|
24925
|
-
|
|
24926
|
-
};
|
|
24927
|
-
if (expectation.snapshotId && latest.snapshotId !== expectation.snapshotId) return {
|
|
24928
|
-
ok: false,
|
|
24929
|
-
code: "runtime_snapshot_id_mismatch",
|
|
24930
|
-
message: `Runtime snapshot id mismatch: expected ${expectation.snapshotId}, got ${latest.snapshotId}`
|
|
24931
|
-
};
|
|
24932
|
-
if (expectation.version !== void 0 && latest.version !== expectation.version) return {
|
|
24933
|
-
ok: false,
|
|
24934
|
-
code: "runtime_snapshot_version_mismatch",
|
|
24935
|
-
message: `Runtime snapshot version mismatch: expected ${expectation.version}, got ${latest.version}`
|
|
24936
|
-
};
|
|
24937
|
-
if (expectation.checksum && latest.checksum !== expectation.checksum) return {
|
|
24938
|
-
ok: false,
|
|
24939
|
-
code: "runtime_snapshot_checksum_mismatch",
|
|
24940
|
-
message: `Runtime snapshot checksum mismatch: expected ${expectation.checksum}, got ${latest.checksum}`
|
|
24941
|
-
};
|
|
24555
|
+
if (!latest) return failure("runtime_snapshot_not_found", `No runtime snapshot found for org=${scope.orgId} project=${scope.projectId} env=${scope.envId}`);
|
|
24556
|
+
if (expectation.snapshotId && latest.snapshotId !== expectation.snapshotId) return failure("runtime_snapshot_id_mismatch", `Runtime snapshot id mismatch: expected ${expectation.snapshotId}, got ${latest.snapshotId}`);
|
|
24557
|
+
if (expectation.version !== void 0 && latest.version !== expectation.version) return failure("runtime_snapshot_version_mismatch", `Runtime snapshot version mismatch: expected ${expectation.version}, got ${latest.version}`);
|
|
24558
|
+
if (expectation.checksum && latest.checksum !== expectation.checksum) return failure("runtime_snapshot_checksum_mismatch", `Runtime snapshot checksum mismatch: expected ${expectation.checksum}, got ${latest.checksum}`);
|
|
24942
24559
|
return { ok: true };
|
|
24943
24560
|
}
|
|
24944
24561
|
function makeScopeKey(scope) {
|
|
@@ -25002,9 +24619,17 @@ function createInMemoryRouterApiRuntimeSnapshotConsumer() {
|
|
|
25002
24619
|
};
|
|
25003
24620
|
}
|
|
25004
24621
|
//#endregion
|
|
24622
|
+
//#region ../shared-ts/src/tenant-root/tenantRootIdentifier.ts
|
|
24623
|
+
function hasControlCharacters(value) {
|
|
24624
|
+
for (const character of value) {
|
|
24625
|
+
const codePoint = character.codePointAt(0) ?? 0;
|
|
24626
|
+
if (codePoint <= 31 || codePoint >= 127 && codePoint <= 159) return true;
|
|
24627
|
+
}
|
|
24628
|
+
return false;
|
|
24629
|
+
}
|
|
24630
|
+
//#endregion
|
|
25005
24631
|
//#region ../shared-ts/src/tenant-root/tenantRootIdentity.ts
|
|
25006
24632
|
const TENANT_ROOT_IDENTITY_DOMAIN_V1 = new TextEncoder().encode("seams/tenant-root-identity/v1");
|
|
25007
|
-
const TENANT_ROOT_IDENTITY_MAX_IDENTIFIER_BYTES_V1 = 256;
|
|
25008
24633
|
function concatenateBytes(parts) {
|
|
25009
24634
|
let length = 0;
|
|
25010
24635
|
for (const part of parts) length += part.length;
|
|
@@ -25023,13 +24648,6 @@ function hasLeadingOrTrailingRustWhitespace(value) {
|
|
|
25023
24648
|
const codePoints = Array.from(value, (character) => character.codePointAt(0) ?? 0);
|
|
25024
24649
|
return codePoints.length > 0 && (isRustWhitespace(codePoints[0]) || isRustWhitespace(codePoints[codePoints.length - 1]));
|
|
25025
24650
|
}
|
|
25026
|
-
function hasControlCharacters(value) {
|
|
25027
|
-
for (const character of value) {
|
|
25028
|
-
const codePoint = character.codePointAt(0) ?? 0;
|
|
25029
|
-
if (codePoint <= 31 || codePoint >= 127 && codePoint <= 159) return true;
|
|
25030
|
-
}
|
|
25031
|
-
return false;
|
|
25032
|
-
}
|
|
25033
24651
|
function hasUnpairedSurrogate(value) {
|
|
25034
24652
|
for (let index = 0; index < value.length; index += 1) {
|
|
25035
24653
|
const codeUnit = value.charCodeAt(index);
|
|
@@ -25047,7 +24665,7 @@ function isCanonicalTenantRootIdentityField(value) {
|
|
|
25047
24665
|
if (typeof value !== "string" || value.length === 0) return false;
|
|
25048
24666
|
if (hasLeadingOrTrailingRustWhitespace(value) || hasControlCharacters(value)) return false;
|
|
25049
24667
|
if (hasUnpairedSurrogate(value)) return false;
|
|
25050
|
-
return new TextEncoder().encode(value).length <=
|
|
24668
|
+
return new TextEncoder().encode(value).length <= 256;
|
|
25051
24669
|
}
|
|
25052
24670
|
function lengthPrefixTenantRootIdentityField(value) {
|
|
25053
24671
|
const output = new Uint8Array(4 + value.length);
|