@seams/wallet-server 0.7.3 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/THIRD_PARTY_NOTICES.md +7 -9
- package/artifact-manifest.json +241 -41
- package/cloudflare-router-ab/build/deriver-a/build-stamp.json +1 -1
- package/cloudflare-router-ab/build/deriver-a/index.js +2 -2
- 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.js +2 -2
- 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.js +2 -2
- 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.js +2 -2
- 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.js +2 -2
- package/cloudflare-router-ab/build/tenant-root-control-plane/index_bg.wasm +0 -0
- package/cloudflare-router-ab/migrations/deriver-a/0019_wallet_object_addresses.sql +10 -0
- package/cloudflare-router-ab/migrations/deriver-b/0019_wallet_object_addresses.sql +10 -0
- package/cloudflare-router-ab/scripts/prepare-local-runtime-config.mjs +3 -119
- package/cloudflare-router-ab/scripts/start-local-role-workers.mjs +77 -20
- package/cloudflare-router-ab/wrangler.deriver-a.toml +0 -8
- package/cloudflare-router-ab/wrangler.deriver-b.toml +24 -8
- package/cloudflare-router-ab/wrangler.router.toml +0 -2
- package/cloudflare-router-ab/wrangler.signing-worker.toml +29 -0
- package/dist/esm/authorization/domain.js +3 -2
- package/dist/esm/authorization/lifecycleRouting.js +62 -0
- package/dist/esm/authorization/service.js +86 -35
- package/dist/esm/cloud-host.js +42 -39
- package/dist/esm/core/EmailOtpRecords.js +29 -222
- package/dist/esm/core/EmailOtpStores.js +0 -859
- package/dist/esm/core/IdentityStore.js +2 -339
- package/dist/esm/core/ThresholdService/config.js +1 -9
- package/dist/esm/core/ThresholdService/index.js +0 -4
- package/dist/esm/core/ThresholdService/kv.js +1 -66
- package/dist/esm/core/ThresholdService/routerAb/ecdsaDerivationPoolFillHandlers.js +3 -13
- package/dist/esm/core/ThresholdService/routerAb/ecdsaDerivationPresignBridge.js +10 -0
- package/dist/esm/core/ThresholdService/routerAb/internalServiceHttp.js +1 -0
- package/dist/esm/core/ThresholdService/routerAbNormalSigningPolicy.js +1 -11
- package/dist/esm/core/ThresholdService/stores/WalletSessionStore.js +0 -541
- package/dist/esm/core/ThresholdService/validation.js +3 -347
- package/dist/esm/core/WalletAuthMethodStore.js +2 -123
- package/dist/esm/core/WalletStore.js +3 -209
- package/dist/esm/core/WebAuthnAuthenticatorStore.js +0 -202
- package/dist/esm/core/WebAuthnCredentialBindingStore.js +2 -182
- package/dist/esm/core/WebAuthnLoginChallengeStore.js +0 -52
- package/dist/esm/core/WebAuthnSyncChallengeStore.js +0 -54
- package/dist/esm/core/authService/emailOtpConfig.js +1 -195
- package/dist/esm/core/authService/emailOtpEnrollment.js +0 -110
- package/dist/esm/core/authService/emailOtpSeal.js +0 -63
- package/dist/esm/core/authService/nearPrivateKeySigning.js +1 -1
- package/dist/esm/core/authService/nearTransactions.js +3 -98
- package/dist/esm/core/authService/rateLimits.js +0 -84
- package/dist/esm/core/authService/webauthn.js +3 -299
- package/dist/esm/core/authService/webauthnOidcHelpers.js +1 -24
- package/dist/esm/core/authService/webauthnWalletBinding.js +0 -37
- package/dist/esm/core/config.js +1 -95
- package/dist/esm/core/d1EcdsaSignerRead.js +1 -1
- package/dist/esm/core/d1Ed25519SignerRead.js +55 -0
- package/dist/esm/core/d1IdentityStore.js +1 -2
- package/dist/esm/core/d1TenantStore.js +1 -24
- package/dist/esm/core/d1WalletAuthMethodStore.js +2 -5
- package/dist/esm/core/d1WalletStore.js +16 -13
- package/dist/esm/core/deviceLinking/linkedDeviceBootstrap.js +13 -0
- package/dist/esm/core/deviceLinking/linkedDeviceEmailOtpGrant.js +2 -2
- package/dist/esm/core/deviceLinking/linkedDeviceManagement.js +1 -1
- package/dist/esm/core/deviceLinking/linkedDeviceSession.js +20 -14
- package/dist/esm/core/deviceLinking/linkedDeviceSessionRecord.js +2 -2
- package/dist/esm/core/deviceLinking/requestProof.js +9 -6
- package/dist/esm/core/emailOtpD1Statements.js +108 -94
- package/dist/esm/core/keyMaterialBrands.js +2 -12
- package/dist/esm/core/nearKeys.js +0 -1
- package/dist/esm/core/nearRelayerAccountProvisioning.js +7 -10
- package/dist/esm/core/passkeyCredentialClaims.js +8 -0
- package/dist/esm/core/routerAbSigning/RouterAbEcdsaPresignRuntime.js +6 -6
- package/dist/esm/core/routerAbSigning/RouterAbNormalSigningRuntime.js +2 -30
- package/dist/esm/core/signingLanes/WalletExecutionLaneProjection.js +1 -1
- package/dist/esm/core/signingMaterial/ordinaryInactiveSignerMaterialReservation.js +1 -0
- package/dist/esm/core/thresholdEcdsaChainTarget.js +1 -4
- package/dist/esm/hosted-wallet-gateway.js +158 -52
- package/dist/esm/index.js +6 -19
- package/dist/esm/localHostedWalletGatewayHandler.js +18 -3
- package/dist/esm/localIntendedYaoSigningFault.js +2 -30
- package/dist/esm/localRegistrationSetupAuthority.js +96 -0
- package/dist/esm/router/auth/authRequestValidation.js +8 -16
- package/dist/esm/router/auth/commonRouterUtils.js +17 -10
- package/dist/esm/router/auth/routerApiCredentialAuth.js +26 -7
- package/dist/esm/router/auth/walletRegistrationContext.js +49 -0
- package/dist/esm/router/auth/webAuthnCredentialCodecs.js +1 -2
- package/dist/esm/router/cloudflare/d1/auth/d1AuthorizationAssembly.js +88 -0
- package/dist/esm/router/cloudflare/d1/auth/d1AuthorizedOperationRouteService.js +2 -0
- package/dist/esm/router/cloudflare/d1/auth/d1EmailOtpRouteService.js +25 -0
- package/dist/esm/router/cloudflare/d1/auth/d1RouterApiAuthConfig.js +24 -6
- package/dist/esm/router/cloudflare/d1/auth/d1RouterApiAuthService.js +75 -320
- package/dist/esm/router/cloudflare/d1/auth/walletSessionCredentialReaders.js +17 -1
- package/dist/esm/router/cloudflare/d1/authorization/authorizedOperationStatements.js +57 -25
- package/dist/esm/router/cloudflare/d1/authorization/d1AuthorizationStore.js +265 -104
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceAuthorityInstallService.js +43 -17
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceEd25519ExportRootStore.js +6 -1
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceEmailOtpGrantStore.js +12 -2
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceEmailOtpTargetFactor.js +4 -4
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceOwnerAuthorizationProvider.js +2 -2
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceRequestProofNonceStore.js +3 -9
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceRouteService.js +2 -1
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceSessionRecords.js +1 -1
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceSessionStore.js +89 -7
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceTargetCredentialProvider.js +24 -15
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceTargetPlanner.js +1 -1
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceVerifiedLinkBuilder.js +1 -1
- package/dist/esm/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoCapabilityPersistence.js +9 -6
- package/dist/esm/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoLifecycleDecisionStore.js +11 -2
- package/dist/esm/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoProductRegistrationPartitionedStateStore.js +100 -10
- package/dist/esm/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoStateWriteFence.js +92 -0
- package/dist/esm/router/cloudflare/d1/ed25519Yao/d1WalletCeremonyActivity.js +77 -0
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeIssuer.js +14 -9
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeService.js +0 -1
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeStore.js +15 -9
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeVerifier.js +3 -2
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpEnrollmentStore.js +1 -1
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpGrantStore.js +1 -7
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRateLimitStore.js +62 -36
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRecords.js +27 -21
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRecoveryService.js +1 -1
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRegistrationEnrollmentFinalizer.js +2 -2
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpServerSealRuntime.js +0 -1
- package/dist/esm/router/cloudflare/d1/emailOtp/d1GoogleEmailOtpRegistrationAttemptStore.js +44 -12
- package/dist/esm/router/cloudflare/d1/emailOtp/d1GoogleEmailOtpRegistrationRecords.js +1 -49
- package/dist/esm/router/cloudflare/d1/emailOtp/d1GoogleEmailOtpSessionResolver.js +20 -31
- package/dist/esm/router/cloudflare/d1/emailOtp/d1GoogleRegistrationCompletion.js +85 -0
- package/dist/esm/router/cloudflare/d1/identity/d1IdentityRecords.js +0 -1
- package/dist/esm/router/cloudflare/d1/identity/d1IdentityService.js +0 -48
- package/dist/esm/router/cloudflare/d1/near/d1SponsoredNearAccount.js +242 -0
- package/dist/esm/router/cloudflare/d1/oidc/d1OidcBoundary.js +1 -2
- package/dist/esm/router/cloudflare/d1/oidc/d1OidcVerificationService.js +2 -29
- package/dist/esm/router/cloudflare/d1/oidc/googleOidcToken.js +41 -0
- package/dist/esm/router/cloudflare/d1/passkeyCustody/d1PasskeyCustodyRouteService.js +5 -0
- package/dist/esm/router/cloudflare/d1/passkeyCustody/d1WalletCustodyCommitStore.js +52 -7
- package/dist/esm/router/cloudflare/d1/registration/d1RegistrationCeremonyRecordStore.js +83 -16
- package/dist/esm/router/cloudflare/d1/registration/d1RegistrationCeremonyRecords.js +8 -14
- package/dist/esm/router/cloudflare/d1/registration/d1RegistrationCeremonyStore.js +60 -28
- package/dist/esm/router/cloudflare/d1/registration/d1RegistrationIntentService.js +0 -1
- package/dist/esm/router/cloudflare/d1/registration/d1RegistrationSessionTransaction.js +28 -0
- package/dist/esm/router/cloudflare/d1/registration/d1RegistrationSetupSupport.js +84 -0
- package/dist/esm/router/cloudflare/d1/registration/d1WalletExecutionAuthority.js +168 -0
- package/dist/esm/router/cloudflare/d1/registration/d1WalletOperationStore.js +53 -0
- package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationCommitStore.js +85 -38
- package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationInitialSession.js +33 -0
- package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationPreparation.js +16 -0
- package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationRead.js +58 -0
- package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationService.js +478 -708
- package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationSetup.js +13 -57
- package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationSetupExecution.js +169 -0
- package/dist/esm/router/cloudflare/d1/registration/walletRegistrationEstablishedSessionIssuer.js +79 -47
- package/dist/esm/router/cloudflare/d1/registration/walletRegistrationSessionCommitReceipt.js +11 -35
- package/dist/esm/router/cloudflare/d1/signingAdmission/d1RouterAbNormalSigningAdmissionStore.js +110 -45
- package/dist/esm/router/cloudflare/d1/versionedJson/d1VersionedJsonRecordStore.js +12 -9
- package/dist/esm/router/cloudflare/d1/wallet/authorizationSnapshotLayout.js +168 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAddSignerFinalizeRecord.js +68 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAddSignerService.js +22 -60
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthMethodService.js +12 -48
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorityStore.js +56 -143
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorizationCleanup.js +157 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorizationFreeze.js +56 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorizationHistory.js +238 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorizationIntake.js +287 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorizationSnapshot.js +295 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationApprovals.js +140 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationChallenges.js +170 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationEmailOtp.js +60 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationOwner.js +33 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationOwnerRequest.js +74 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationPasskey.js +77 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationReadAccess.js +37 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationSessions.js +97 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationWriteBlock.js +133 -0
- package/dist/esm/router/cloudflare/d1/walletObjectAddresses.js +47 -0
- package/dist/esm/router/cloudflare/d1/webauthn/d1WebAuthnAuthService.js +26 -5
- package/dist/esm/router/cloudflare/d1/webauthn/d1WebAuthnRecords.js +4 -70
- package/dist/esm/router/cloudflare/d1/webauthn/d1WebAuthnStore.js +23 -7
- package/dist/esm/router/cloudflare/runtime/routerAbServiceBindings.js +32 -1
- package/dist/esm/router/cloudflare/runtime/staticWalletConsoleBinding.js +20 -7
- package/dist/esm/router/cloudflare/runtime/walletAuthorizationRelocationRoutes.js +488 -0
- package/dist/esm/router/cloudflare/runtime/walletConsoleOps.js +1 -0
- package/dist/esm/router/cloudflare/runtime/walletConsoleOpsClient.js +26 -1
- package/dist/esm/router/cloudflare/runtime/walletControlOps.js +3 -0
- package/dist/esm/router/cloudflare/runtime/walletGateway.js +1 -1
- package/dist/esm/router/cloudflare/runtime/walletObjectAddresses.js +105 -0
- package/dist/esm/router/cloudflare/runtime/walletPlacementRoutes.js +339 -0
- package/dist/esm/router/cloudflare/runtime/walletRelocationDeriver.js +244 -0
- package/dist/esm/router/cloudflare/runtime/walletRelocationEcdsa.js +212 -0
- package/dist/esm/router/cloudflare/runtime/walletRelocationEd25519.js +172 -0
- package/dist/esm/router/cloudflare/runtime/walletRelocationOps.js +183 -0
- package/dist/esm/router/cloudflare/runtime/walletRelocationPresign.js +185 -0
- package/dist/esm/router/cloudflare/runtime/walletRelocationSource.js +221 -0
- package/dist/esm/router/cloudflare/runtime/walletRuntimeOps.js +16 -4
- package/dist/esm/router/cloudflare/signingLanes/cloudflareOrdinaryInactiveSignerMaterialReservation.js +30 -8
- package/dist/esm/router/cloudflare-adaptor.js +8 -9
- package/dist/esm/router/cloudflare.js +33043 -31559
- package/dist/esm/router/domains/ecdsa/routerAbEcdsaStrictRegistration.js +35 -9
- package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoCapabilityCommit.js +42 -0
- package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistration.js +42 -13
- package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationPartitionedStateStore.js +64 -3
- package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationPartitioning.js +6 -6
- package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationPersistence.js +70 -3
- package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationRequestScopedRuntime.js +59 -87
- package/dist/esm/router/domains/ed25519Yao/export/routerAbEd25519YaoExport.js +58 -28
- package/dist/esm/router/domains/ed25519Yao/export/routerAbEd25519YaoExportRequestScopedCloudflare.js +13 -7
- package/dist/esm/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecovery.js +108 -78
- package/dist/esm/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecoveryRequestScopedCloudflare.js +27 -5
- package/dist/esm/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecoveryWalletSessionAuthorization.js +71 -22
- package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoHttpRegistrationBackend.js +37 -25
- package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistration.js +3 -3
- package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationExecutionRecord.js +2 -1
- package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationIntentAuthorization.js +24 -3
- package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationRequestScopedCloudflare.js +4 -3
- package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationSideEffectBoundary.js +20 -7
- package/dist/esm/router/domains/ed25519Yao/routerAbEd25519YaoGatewayEnvelope.js +7 -1
- package/dist/esm/router/domains/emailOtp/emailOtpRequestValidation.js +0 -1
- package/dist/esm/router/domains/emailOtp/emailOtpRouteHandlers.js +2 -2
- package/dist/esm/router/domains/passkeyCustody/passkeyCustodyEnvelopeRetrieval.js +3 -9
- package/dist/esm/router/domains/passkeyCustody/registrationCustodyOutcome.js +34 -18
- package/dist/esm/router/domains/passkeyCustody/walletCustodyRegistrationAdmission.js +2 -2
- package/dist/esm/router/domains/passkeyCustody/walletCustodyRegistrationCommit.js +18 -14
- package/dist/esm/router/domains/signingOperations/authorizedOperationWire.js +73 -0
- package/dist/esm/router/domains/signingOperations/ecdsaSigningResponse.js +31 -0
- package/dist/esm/router/domains/signingOperations/ed25519AuthorizedOperationReceipt.js +1 -1
- package/dist/esm/router/domains/signingOperations/routerAbEcdsaDerivationNormalSigningRoute.js +2 -1
- package/dist/esm/router/domains/signingOperations/routerAbEd25519NormalSigningRoute.js +31 -121
- package/dist/esm/router/domains/signingOperations/routerAbNormalSigningAdmission.js +2 -93
- package/dist/esm/router/domains/signingOperations/routerAbPrivateSigningWorker.js +6 -20
- package/dist/esm/router/domains/signingOperations/signingPrepareSession.js +33 -0
- package/dist/esm/router/domains/signingOperations/walletExecutionAdmission.js +2 -3
- package/dist/esm/router/domains/walletRegistration/registrationSessionSeal.js +121 -0
- package/dist/esm/router/domains/walletRegistration/walletRegistrationReservation.js +70 -0
- package/dist/esm/router/domains/walletRegistration/walletRegistrationRoutes.js +56 -168
- package/dist/esm/router/domains/walletRegistration/walletRegistrationSetupPayload.js +3 -4
- package/dist/esm/router/domains/walletUnlock/walletUnlockRouteHandlers.js +14 -0
- package/dist/esm/router/express.js +1453 -1488
- package/dist/esm/router/framework/http.js +4 -1
- package/dist/esm/router/framework/registrationSetupDispatch.js +14 -0
- package/dist/esm/router/framework/ror/normalize.js +0 -1
- package/dist/esm/router/framework/ror/options.js +0 -1
- package/dist/esm/router/framework/ror/provider.js +0 -1
- package/dist/esm/router/framework/ror/staticProvider.js +0 -1
- package/dist/esm/router/framework/routeDefinitions.js +1 -2
- package/dist/esm/router/framework/routerApiWebhooks.js +0 -1
- package/dist/esm/router/ror.js +0 -1
- package/dist/esm/router/transport/fetch/createFetchRouter.js +2 -4
- package/dist/esm/router/transport/fetch/routes/auth.js +3 -1
- package/dist/esm/router/transport/fetch/routes/deviceLinking.js +38 -149
- package/dist/esm/router/transport/fetch/routes/deviceLinkingOwnerAuthorization.js +5 -4
- package/dist/esm/router/transport/fetch/routes/deviceLinkingResponses.js +130 -0
- package/dist/esm/router/transport/fetch/routes/ecdsaOperationStepUpFactor.js +171 -0
- package/dist/esm/router/transport/fetch/routes/ed25519AuthorizedOperationRevalidation.js +65 -0
- package/dist/esm/router/transport/fetch/routes/normalSigningRouterProxy.js +13 -3
- package/dist/esm/router/transport/fetch/routes/passkeyCustody.js +4 -3
- package/dist/esm/router/transport/fetch/routes/sessions.js +3 -2
- package/dist/esm/router/transport/fetch/routes/syncAccount.js +7 -2
- package/dist/esm/router/transport/fetch/routes/thresholdEcdsa.js +86 -245
- package/dist/esm/router/transport/fetch/routes/thresholdEd25519.js +76 -212
- package/dist/esm/router/transport/fetch/routes/walletExecutionLanePreflight.js +18 -41
- package/dist/esm/router/transport/fetch/routes/walletRegistration.js +6 -3
- package/dist/esm/router/transport/fetch/routes/webauthnAuthenticators.js +1 -1
- package/dist/esm/shared-ts/src/authorization/index.js +1 -1
- package/dist/esm/shared-ts/src/authorization/walletAuthority.js +2 -2
- package/dist/esm/shared-ts/src/authorization/walletSessionIssuance.js +0 -1
- package/dist/esm/shared-ts/src/device-linking/activeWalletSession.js +12 -2
- package/dist/esm/shared-ts/src/device-linking/authorityActivation.js +0 -2
- package/dist/esm/shared-ts/src/device-linking/contracts.js +16 -1
- package/dist/esm/shared-ts/src/device-linking/digests.js +2 -9
- package/dist/esm/shared-ts/src/device-linking/ed25519ExportRoot.js +1 -1
- package/dist/esm/shared-ts/src/device-linking/index.js +1 -1
- package/dist/esm/shared-ts/src/device-linking/parsers.js +1 -1
- package/dist/esm/shared-ts/src/device-linking/sourceContribution.js +1 -1
- package/dist/esm/shared-ts/src/device-linking/wireFields.js +1 -1
- package/dist/esm/shared-ts/src/near/actions.js +0 -1
- package/dist/esm/shared-ts/src/near/nearClient.js +1 -3
- package/dist/esm/shared-ts/src/signing-lanes/evmFamilySigningKeySlotId.js +1 -1
- package/dist/esm/shared-ts/src/signing-lanes/index.js +1 -6
- package/dist/esm/shared-ts/src/signing-lanes/ownerContinuity.js +3 -3
- package/dist/esm/shared-ts/src/signing-lanes/participantDigest.js +2 -81
- package/dist/esm/shared-ts/src/signing-lanes/participants.js +1 -219
- package/dist/esm/shared-ts/src/signing-lanes/recordParsers.js +0 -3
- package/dist/esm/shared-ts/src/tenant-root/tenantRootOperationRecord.js +1 -2
- package/dist/esm/shared-ts/src/threshold/ecdsaDerivationRoleLocalBootstrap.js +0 -1
- package/dist/esm/shared-ts/src/threshold/keyMaterialBrands.js +1 -22
- package/dist/esm/shared-ts/src/threshold/participants.js +0 -1
- package/dist/esm/shared-ts/src/threshold/signingRootScope.js +0 -1
- package/dist/esm/shared-ts/src/utils/addWalletAuthMethod.js +4 -13
- package/dist/esm/shared-ts/src/utils/canonicalPrimitives.js +1 -7
- package/dist/esm/shared-ts/src/utils/domainIds.js +1 -16
- package/dist/esm/shared-ts/src/utils/ecdsaCapabilityActivation.js +1 -11
- package/dist/esm/shared-ts/src/utils/ecdsaKeyFactsInventory.js +0 -1
- package/dist/esm/shared-ts/src/utils/ecdsaServerTiming.js +6 -1
- package/dist/esm/shared-ts/src/utils/emailOtpDomain.js +4 -2
- package/dist/esm/shared-ts/src/utils/errors.js +1 -19
- package/dist/esm/shared-ts/src/utils/near.js +1 -1
- package/dist/esm/shared-ts/src/utils/registrationEstablishedSession.js +1 -1
- package/dist/esm/shared-ts/src/utils/registrationIds.js +1 -5
- package/dist/esm/shared-ts/src/utils/registrationIntent.js +0 -1
- package/dist/esm/shared-ts/src/utils/registrationSetupOperation.js +8 -0
- package/dist/esm/shared-ts/src/utils/registrationSignerPlan.js +1 -1
- package/dist/esm/shared-ts/src/utils/routerAbEcdsaDerivation.js +1 -2
- package/dist/esm/shared-ts/src/utils/routerAbPublicKeyset.js +0 -27
- package/dist/esm/shared-ts/src/utils/validation.js +1 -5
- package/dist/esm/shared-ts/src/utils/walletAuthAuthority.js +0 -1
- package/dist/esm/shared-ts/src/utils/walletManagementProtocol.js +6 -0
- package/dist/esm/shared-ts/src/utils/wireSchema.js +2 -13
- package/dist/esm/shared-ts/src/wallet-recovery/backupAcknowledgement.js +6 -24
- package/dist/esm/shared-ts/src/wallet-recovery/recoveryCodeLocator.js +0 -1
- package/dist/esm/shared-ts/src/wallet-recovery/recoveryKeyId.js +5 -6
- package/dist/esm/shared-ts/src/wallet-recovery/walletRecoveryEcdsaPossession.js +1 -1
- package/dist/esm/storage/d1Sql.js +1 -7
- package/dist/esm/threshold/session/signingSessionSeal/crypto/cipher.js +0 -1
- package/dist/esm/threshold/session/signingSessionSeal/guards/backends.js +1 -2
- package/dist/esm/threshold/session/signingSessionSeal/idempotencyBackends.js +0 -1
- package/dist/esm/threshold/session/signingSessionSeal/idempotencyRecords.js +0 -1
- package/dist/esm/threshold/session/signingSessionSeal/options.js +1 -2
- package/dist/esm/wasm/evm_crypto/pkg/evm_crypto_bg.wasm +0 -0
- package/dist/esm/wasm/near_signer/pkg/wasm_signer_worker.js +0 -611
- package/dist/esm/wasm/near_signer/pkg/wasm_signer_worker_bg.wasm +0 -0
- package/dist/esm/wasm/shamir3pass_runtime/pkg/shamir3pass_runtime_bg.wasm +0 -0
- package/dist/types/shared-ts/src/authorization/capabilityKinds.d.ts +0 -4
- package/dist/types/shared-ts/src/device-linking/activeWalletSession.d.ts +2 -1
- package/dist/types/shared-ts/src/device-linking/contracts.d.ts +11 -0
- package/dist/types/shared-ts/src/signing-lanes/evmFamilySigningKeySlotId.d.ts +0 -2
- package/dist/types/shared-ts/src/signing-lanes/execution.d.ts +0 -11
- package/dist/types/shared-ts/src/signing-lanes/ids.d.ts +2 -7
- package/dist/types/shared-ts/src/signing-lanes/index.d.ts +0 -4
- package/dist/types/shared-ts/src/signing-lanes/ownerContinuity.d.ts +0 -1
- package/dist/types/shared-ts/src/signing-lanes/participantDigest.d.ts +0 -18
- package/dist/types/shared-ts/src/signing-lanes/participants.d.ts +6 -35
- package/dist/types/shared-ts/src/signing-lanes/rotation.d.ts +6 -843
- package/dist/types/shared-ts/src/threshold/ed25519OperationFingerprint.d.ts +2 -1
- package/dist/types/shared-ts/src/threshold/keyMaterialBrands.d.ts +0 -10
- package/dist/types/shared-ts/src/threshold/participants.d.ts +1 -1
- package/dist/types/shared-ts/src/utils/addWalletAuthMethod.d.ts +1 -133
- package/dist/types/shared-ts/src/utils/addWalletAuthMethod.typecheck.d.ts +4 -18
- package/dist/types/shared-ts/src/utils/domainIds.d.ts +0 -12
- package/dist/types/shared-ts/src/utils/emailOtpDomain.d.ts +3 -1
- package/dist/types/shared-ts/src/utils/errors.d.ts +0 -4
- package/dist/types/shared-ts/src/utils/near.d.ts +0 -20
- package/dist/types/shared-ts/src/utils/normalize.d.ts +0 -2
- package/dist/types/shared-ts/src/utils/registrationSetupOperation.d.ts +3 -0
- package/dist/types/shared-ts/src/utils/routerAbPublicKeyset.d.ts +0 -9
- package/dist/types/shared-ts/src/utils/validation.d.ts +1 -3
- package/dist/types/shared-ts/src/utils/walletCapabilityBindings.d.ts +0 -1
- package/dist/types/shared-ts/src/utils/walletManagementProtocol.d.ts +3 -0
- package/dist/types/shared-ts/src/utils/wireSchema.d.ts +0 -2
- package/dist/types/shared-ts/src/wallet-recovery/backupAcknowledgement.d.ts +0 -1
- package/dist/types/shared-ts/src/wallet-recovery/recoveryCodeReservation.d.ts +1 -10
- package/dist/types/shared-ts/src/wallet-recovery/recoveryCodes.d.ts +1 -3
- package/dist/types/shared-ts/src/wallet-recovery/recoveryKeyId.d.ts +5 -21
- package/dist/types/wallet-server/src/authorization/domain.d.ts +17 -1
- package/dist/types/wallet-server/src/authorization/ecdsaWalletSessionAdmission.d.ts +1 -0
- package/dist/types/wallet-server/src/authorization/ed25519WalletSessionAdmission.d.ts +35 -0
- package/dist/types/wallet-server/src/authorization/ed25519WalletSessionAdmission.typecheck.d.ts +2 -0
- package/dist/types/wallet-server/src/authorization/lifecycleRouting.d.ts +32 -0
- package/dist/types/wallet-server/src/authorization/lifecycleRouting.typecheck.d.ts +2 -0
- package/dist/types/wallet-server/src/authorization/recoveryRouting.d.ts +22 -0
- package/dist/types/wallet-server/src/authorization/recoveryRouting.typecheck.d.ts +2 -0
- package/dist/types/wallet-server/src/authorization/service.d.ts +50 -5
- package/dist/types/wallet-server/src/authorization/sessionRouting.d.ts +22 -0
- package/dist/types/wallet-server/src/authorization/sessionRouting.typecheck.d.ts +2 -0
- package/dist/types/wallet-server/src/cloud-host.d.ts +36 -10
- package/dist/types/wallet-server/src/core/EmailOtpRecords.d.ts +2 -22
- package/dist/types/wallet-server/src/core/EmailOtpStores.d.ts +20 -84
- package/dist/types/wallet-server/src/core/IdentityStore.d.ts +0 -10
- package/dist/types/wallet-server/src/core/RegistrationCeremonyStore.d.ts +0 -1
- package/dist/types/wallet-server/src/core/ThresholdService/config.d.ts +0 -2
- package/dist/types/wallet-server/src/core/ThresholdService/index.d.ts +1 -3
- package/dist/types/wallet-server/src/core/ThresholdService/kv.d.ts +0 -7
- package/dist/types/wallet-server/src/core/ThresholdService/routerAb/ecdsaDerivationPoolFillHandlers.d.ts +1 -3
- package/dist/types/wallet-server/src/core/ThresholdService/routerAb/ecdsaDerivationPresignBridge.d.ts +6 -0
- package/dist/types/wallet-server/src/core/ThresholdService/routerAb/internalServiceHttp.d.ts +1 -0
- package/dist/types/wallet-server/src/core/ThresholdService/routerAbNormalSigningPolicy.d.ts +0 -1
- package/dist/types/wallet-server/src/core/ThresholdService/stores/WalletSessionStore.d.ts +7 -19
- package/dist/types/wallet-server/src/core/ThresholdService/validation.d.ts +0 -34
- package/dist/types/wallet-server/src/core/WalletAuthMethodStore.d.ts +1 -5
- package/dist/types/wallet-server/src/core/WalletStore.d.ts +0 -3
- package/dist/types/wallet-server/src/core/WebAuthnAuthenticatorStore.d.ts +0 -20
- package/dist/types/wallet-server/src/core/WebAuthnCredentialBindingStore.d.ts +1 -27
- package/dist/types/wallet-server/src/core/WebAuthnLoginChallengeStore.d.ts +2 -16
- package/dist/types/wallet-server/src/core/WebAuthnSyncChallengeStore.d.ts +22 -14
- package/dist/types/wallet-server/src/core/authService/emailOtpConfig.d.ts +0 -24
- package/dist/types/wallet-server/src/core/authService/emailOtpEnrollment.d.ts +1 -70
- package/dist/types/wallet-server/src/core/authService/emailOtpSeal.d.ts +0 -13
- package/dist/types/wallet-server/src/core/authService/githubOAuth.d.ts +2 -1
- package/dist/types/wallet-server/src/core/authService/nearTransactions.d.ts +1 -39
- package/dist/types/wallet-server/src/core/authService/rateLimits.d.ts +0 -17
- package/dist/types/wallet-server/src/core/authService/webauthn.d.ts +0 -125
- package/dist/types/wallet-server/src/core/authService/webauthnOidcHelpers.d.ts +0 -3
- package/dist/types/wallet-server/src/core/authService/webauthnVerificationOutcomes.d.ts +1 -1
- package/dist/types/wallet-server/src/core/authService/webauthnWalletBinding.d.ts +0 -12
- package/dist/types/wallet-server/src/core/config.d.ts +0 -10
- package/dist/types/wallet-server/src/core/d1Ed25519SignerRead.d.ts +17 -0
- package/dist/types/wallet-server/src/core/d1IdentityStore.d.ts +0 -2
- package/dist/types/wallet-server/src/core/d1TenantStore.d.ts +0 -7
- package/dist/types/wallet-server/src/core/d1WalletAuthMethodStore.d.ts +0 -1
- package/dist/types/wallet-server/src/core/d1WalletStore.d.ts +6 -0
- package/dist/types/wallet-server/src/core/deviceLinking/linkedDeviceBootstrap.d.ts +19 -0
- package/dist/types/wallet-server/src/core/deviceLinking/linkedDeviceSession.d.ts +8 -6
- package/dist/types/wallet-server/src/core/deviceLinking/requestProof.d.ts +2 -5
- package/dist/types/wallet-server/src/core/emailOtpD1Statements.d.ts +11 -7
- package/dist/types/wallet-server/src/core/keyMaterialBrands.d.ts +1 -5
- package/dist/types/wallet-server/src/core/nearRelayerAccountProvisioning.d.ts +0 -1
- package/dist/types/wallet-server/src/core/passkeyCredentialClaims.d.ts +9 -0
- package/dist/types/wallet-server/src/core/routerAbSigning/RouterAbEcdsaPresignRuntime.d.ts +5 -3
- package/dist/types/wallet-server/src/core/routerAbSigning/RouterAbNormalSigningRuntime.d.ts +0 -2
- package/dist/types/wallet-server/src/core/signingMaterial/ordinaryInactiveSignerMaterialReservation.d.ts +1 -0
- package/dist/types/wallet-server/src/core/threeRouteRegistrationContracts.d.ts +15 -140
- package/dist/types/wallet-server/src/core/threeRouteRegistrationContracts.typecheck.d.ts +4 -52
- package/dist/types/wallet-server/src/core/thresholdEcdsaChainTarget.d.ts +0 -1
- package/dist/types/wallet-server/src/core/types.d.ts +0 -299
- package/dist/types/wallet-server/src/hosted-wallet-gateway.d.ts +18 -5
- package/dist/types/wallet-server/src/index.d.ts +8 -13
- package/dist/types/wallet-server/src/localIntendedYaoSigningFault.d.ts +1 -16
- package/dist/types/wallet-server/src/localRegistrationSetupAuthority.d.ts +13 -0
- package/dist/types/wallet-server/src/router/auth/commonRouterUtils.d.ts +7 -1
- package/dist/types/wallet-server/src/router/auth/routerApiCredentialAuth.d.ts +11 -3
- package/dist/types/wallet-server/src/router/auth/walletRegistrationContext.d.ts +8 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/auth/d1AuthorizationAssembly.d.ts +23 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/auth/d1EmailOtpRouteService.d.ts +16 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/auth/d1RouterApiAuthConfig.d.ts +28 -3
- package/dist/types/wallet-server/src/router/cloudflare/d1/auth/d1RouterApiAuthService.d.ts +4 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/auth/walletSessionCredentialReaders.d.ts +7 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/authorization/d1AuthorizationStore.d.ts +33 -2
- package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceAuthorityInstallService.d.ts +5 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceEmailOtpGrantStore.d.ts +7 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceRequestProofNonceStore.d.ts +1 -10
- package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceRouteService.d.ts +4 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceSessionStore.d.ts +6 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceTargetPlanner.d.ts +1 -13
- package/dist/types/wallet-server/src/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoLifecycleDecisionStore.d.ts +3 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoProductRegistrationPartitionedStateStore.d.ts +1 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoStateWriteFence.d.ts +8 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/ed25519Yao/d1WalletCeremonyActivity.d.ts +15 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeIssuer.d.ts +6 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeService.d.ts +2 -2
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeStore.d.ts +2 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeVerifier.d.ts +4 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpCounters.typecheck.d.ts +2 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpGrantStore.d.ts +0 -2
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpRateLimitStore.d.ts +6 -13
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpRecords.d.ts +21 -7
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1GoogleEmailOtpRegistrationAttemptStore.d.ts +29 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1GoogleEmailOtpRegistrationRecords.d.ts +3 -16
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1GoogleEmailOtpSessionResolver.d.ts +7 -2
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1GoogleRegistrationCompletion.d.ts +23 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/identity/d1IdentityService.d.ts +0 -12
- package/dist/types/wallet-server/src/router/cloudflare/d1/near/d1SponsoredNearAccount.d.ts +24 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/near/d1SponsoredNearAccount.typecheck.d.ts +2 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/oidc/d1OidcVerificationService.d.ts +0 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/oidc/googleOidcToken.d.ts +4 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/passkeyCustody/d1PasskeyCustodyRouteService.d.ts +5 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/passkeyCustody/d1WalletCustodyCommitStore.d.ts +26 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationCeremonyRecordStore.d.ts +33 -8
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationCeremonyRecords.d.ts +10 -11
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationCeremonyStore.d.ts +17 -7
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationSessionTransaction.d.ts +13 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationSetupSupport.d.ts +58 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletExecutionAuthority.d.ts +41 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletOperationStore.d.ts +28 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationCommitStore.d.ts +9 -9
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationInitialSession.d.ts +17 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationPreparation.d.ts +12 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationRead.d.ts +43 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationService.d.ts +52 -90
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationSetup.d.ts +3 -30
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationSetupExecution.d.ts +16 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/walletRegistrationEstablishedSessionIssuer.d.ts +42 -14
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/walletRegistrationSessionCommitReceipt.d.ts +5 -4
- package/dist/types/wallet-server/src/router/cloudflare/d1/signingAdmission/d1RouterAbNormalSigningAdmissionStore.d.ts +24 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/versionedJson/d1VersionedJsonRecordStore.d.ts +10 -4
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/authorizationSnapshotLayout.d.ts +21 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAddSignerFinalizeRecord.d.ts +27 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAddSignerService.d.ts +4 -10
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthMethodService.d.ts +5 -9
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorityStore.d.ts +8 -4
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorizationCleanup.d.ts +20 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorizationFreeze.d.ts +12 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorizationHistory.d.ts +20 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorizationIntake.d.ts +29 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorizationSnapshot.d.ts +31 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationApprovals.d.ts +49 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationChallenges.d.ts +47 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationEmailOtp.d.ts +25 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationOwner.d.ts +88 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationOwnerRequest.d.ts +37 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationPasskey.d.ts +12 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationReadAccess.d.ts +18 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationSessions.d.ts +23 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationWriteBlock.d.ts +16 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/walletObjectAddresses.d.ts +14 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/webauthn/d1WebAuthnAuthService.d.ts +3 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/webauthn/d1WebAuthnRecords.d.ts +0 -13
- package/dist/types/wallet-server/src/router/cloudflare/d1/webauthn/d1WebAuthnStore.d.ts +23 -10
- package/dist/types/wallet-server/src/router/cloudflare/d1/webauthn/d1WebAuthnStore.typecheck.d.ts +2 -0
- package/dist/types/wallet-server/src/router/cloudflare/runtime/cloudflare.types.d.ts +0 -2
- package/dist/types/wallet-server/src/router/cloudflare/runtime/routerAbServiceBindings.d.ts +13 -0
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletAuthorizationRelocationRoutes.d.ts +21 -0
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletConsoleOps.d.ts +1 -0
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletConsoleOpsClient.d.ts +3 -1
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletControlOps.d.ts +2 -1
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletGateway.d.ts +3 -1
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletObjectAddresses.d.ts +45 -0
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletPlacementRoutes.d.ts +30 -0
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRelocationDeriver.d.ts +11 -0
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRelocationEcdsa.d.ts +7 -0
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRelocationEd25519.d.ts +7 -0
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRelocationOps.d.ts +11 -0
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRelocationPresign.d.ts +7 -0
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRelocationSource.d.ts +26 -0
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRuntimeOps.d.ts +3 -0
- package/dist/types/wallet-server/src/router/cloudflare/signingLanes/cloudflareOrdinaryInactiveSignerMaterialReservation.d.ts +5 -0
- package/dist/types/wallet-server/src/router/cloudflare-adaptor.d.ts +0 -1
- package/dist/types/wallet-server/src/router/domains/ecdsa/routerAbEcdsaStrictRegistration.d.ts +3 -0
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoCapabilityCommit.d.ts +7 -0
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistration.d.ts +42 -8
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationPartitionedStateStore.d.ts +33 -2
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationPartitioning.d.ts +2 -2
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/export/routerAbEd25519YaoExport.d.ts +14 -8
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/export/routerAbEd25519YaoExport.typecheck.d.ts +2 -0
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/export/routerAbEd25519YaoExportRequestScopedCloudflare.d.ts +2 -0
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecovery.d.ts +17 -9
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecoveryRequestScopedCloudflare.d.ts +2 -0
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecoveryWalletSessionAuthorization.d.ts +2 -0
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/registration/routerAbEd25519YaoHttpRegistrationBackend.d.ts +13 -14
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistration.d.ts +7 -3
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationExecutionRecord.d.ts +1 -0
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationIntentAuthorization.d.ts +6 -1
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationSideEffectBoundary.d.ts +11 -0
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/routerAbEd25519YaoGatewayEnvelope.d.ts +12 -3
- package/dist/types/wallet-server/src/router/domains/passkeyCustody/passkeyCustodyEnvelopeRetrieval.d.ts +0 -2
- package/dist/types/wallet-server/src/router/domains/passkeyCustody/registrationCustodyOutcome.d.ts +10 -6
- package/dist/types/wallet-server/src/router/domains/passkeyCustody/walletCustodyRegistrationAdmission.d.ts +10 -3
- package/dist/types/wallet-server/src/router/domains/passkeyCustody/walletCustodyRegistrationCommit.d.ts +12 -8
- package/dist/types/wallet-server/src/router/domains/signingOperations/authorizedOperationWire.d.ts +97 -0
- package/dist/types/wallet-server/src/router/domains/signingOperations/ecdsaSigningResponse.d.ts +13 -0
- package/dist/types/wallet-server/src/router/domains/signingOperations/routerAbNormalSigningAdmission.d.ts +9 -206
- package/dist/types/wallet-server/src/router/domains/signingOperations/routerAbPrivateSigningWorker.d.ts +0 -17
- package/dist/types/wallet-server/src/router/domains/signingOperations/signingPrepareSession.d.ts +23 -0
- package/dist/types/wallet-server/src/router/domains/signingOperations/walletExecutionAdmission.d.ts +1 -2
- package/dist/types/wallet-server/src/router/domains/walletRegistration/registrationSessionSeal.d.ts +36 -0
- package/dist/types/wallet-server/src/router/domains/walletRegistration/walletRegistrationInputs.d.ts +8 -7
- package/dist/types/wallet-server/src/router/domains/walletRegistration/walletRegistrationReservation.d.ts +125 -0
- package/dist/types/wallet-server/src/router/domains/walletRegistration/walletRegistrationRoutes.d.ts +17 -15
- package/dist/types/wallet-server/src/router/domains/walletRegistration/walletRegistrationSetupPayload.d.ts +2 -2
- package/dist/types/wallet-server/src/router/framework/apiCredentialPorts.d.ts +24 -0
- package/dist/types/wallet-server/src/router/framework/authServicePort.d.ts +35 -41
- package/dist/types/wallet-server/src/router/framework/googleLoginResolution.typecheck.d.ts +2 -0
- package/dist/types/wallet-server/src/router/framework/registrationSetupDispatch.d.ts +13 -0
- package/dist/types/wallet-server/src/router/framework/routerApi.d.ts +3 -12
- package/dist/types/wallet-server/src/router/transport/fetch/routes/deviceLinking.d.ts +1 -1
- package/dist/types/wallet-server/src/router/transport/fetch/routes/deviceLinkingResponses.d.ts +17 -0
- package/dist/types/wallet-server/src/router/transport/fetch/routes/ecdsaOperationStepUpFactor.d.ts +37 -0
- package/dist/types/wallet-server/src/router/transport/fetch/routes/ed25519AuthorizedOperationRevalidation.d.ts +37 -0
- package/dist/types/wallet-server/src/router/transport/fetch/routes/thresholdEcdsa.d.ts +1 -17
- package/dist/types/wallet-server/src/storage/d1Sql.d.ts +0 -1
- package/dist/types/wallet-server/src/storage/tenantRoute.d.ts +1 -1
- package/migrations/d1-signer/0040_namespace_home_challenges.sql +16 -0
- package/migrations/d1-signer/0041_step_up_admission_expiry.sql +28 -0
- package/migrations/d1-signer/0042_deployment_resource_challenges.sql +4 -0
- package/migrations/d1-signer/0043_google_registration_candidate_claim.sql +2 -0
- package/migrations/d1-signer/0044_linked_device_bootstrap_imports.sql +6 -0
- package/migrations/d1-signer/0045_wallet_owned_capability_receipts.sql +29 -0
- package/migrations/d1-signer/0046_wallet_owned_signing_abuse.sql +41 -0
- package/migrations/d1-signer/0047_remove_unused_near_public_keys.sql +2 -0
- package/migrations/d1-signer/0048_operation_owner_scope.sql +45 -0
- package/migrations/d1-signer/0049_wallet_relocation_challenges.sql +16 -0
- package/migrations/d1-signer/0050_wallet_relocation_approvals.sql +14 -0
- package/migrations/d1-signer/0051_wallet_relocation_email_otp.sql +92 -0
- package/migrations/d1-signer/0052_wallet_relocation_session_fences.sql +91 -0
- package/migrations/d1-signer/0053_wallet_hosted_history_import.sql +164 -0
- package/migrations/d1-signer/0054_wallet_authorization_freeze.sql +318 -0
- package/migrations/d1-signer/0055_wallet_authorization_snapshot.sql +120 -0
- package/migrations/d1-signer/0056_wallet_authorization_history_import.sql +424 -0
- package/migrations/d1-signer/0057_wallet_authorization_intake.sql +44 -0
- package/migrations/d1-signer/0058_wallet_ceremony_activity.sql +59 -0
- package/migrations/d1-signer/0059_wallet_authorization_activation.sql +45 -0
- package/migrations/d1-signer/0060_wallet_authorization_cleanup.sql +153 -0
- package/migrations/d1-signer/0061_wallet_session_operation_settlement.sql +28 -0
- package/migrations/d1-signer/0062_wallet_step_up_operation_settlement.sql +204 -0
- package/migrations/d1-signer/0063_wallet_operation_history_transfer.sql +466 -0
- package/migrations/d1-signer/0064_wallet_execution_generations.sql +93 -0
- package/migrations/d1-signer/0065_wallet_operation_execution_generation.sql +37 -0
- package/migrations/d1-signer/0066_regional_deployment_admission.sql +59 -0
- package/migrations/d1-signer/0067_registration_completion_decision.sql +12 -0
- package/migrations/d1-signer/0068_registration_cancellation_write_fence.sql +24 -0
- package/migrations/d1-signer/0069_cancelled_registration_session_fence.sql +11 -0
- package/migrations/d1-signer/0070_wallet_passkey_relocation.sql +369 -0
- package/migrations/d1-signer/0071_regional_wallet_otp_counters.sql +98 -0
- package/migrations/d1-signer/0072_linked_device_relocation_history.sql +899 -0
- package/migrations/d1-signer/0073_wallet_recovery_relocation.sql +86 -0
- package/migrations/d1-signer/0074_email_otp_relocation.sql +158 -0
- package/migrations/d1-signer/0075_wallet_authorization_return.sql +107 -0
- package/migrations/d1-signer/0076_wallet_relocation_write_block.sql +406 -0
- package/migrations/d1-signer/0077_wallet_object_addresses.sql +24 -0
- package/package.json +2 -3
- package/src/README.md +33 -3
- package/cloudflare-router-ab/scripts/local-key-material.mjs +0 -29
- package/dist/esm/core/AuthService.js +0 -2
- package/dist/esm/core/NearPublicKeyStore.js +0 -200
- package/dist/esm/core/ThresholdService/stores/CloudflareDurableObjectStore.js +0 -397
- package/dist/esm/core/ThresholdService/stores/KeyStore.js +0 -140
- package/dist/esm/core/ThresholdService/stores/SessionStore.js +0 -361
- package/dist/esm/core/ThresholdService/stores/StoreConfig.js +0 -13
- package/dist/esm/core/ThresholdService/stores/exportReplayGuard.js +0 -7
- package/dist/esm/core/authService/AuthService.js +0 -594
- package/dist/esm/core/authService/bytes.js +0 -19
- package/dist/esm/core/authService/configValues.js +0 -15
- package/dist/esm/core/authService/emailOtpChallengeOperations.js +0 -123
- package/dist/esm/core/authService/emailOtpChallengeProof.js +0 -183
- package/dist/esm/core/authService/emailOtpChallengeVerification.js +0 -264
- package/dist/esm/core/authService/emailOtpChallenges.js +0 -225
- package/dist/esm/core/authService/emailOtpDelivery.js +0 -134
- package/dist/esm/core/authService/emailOtpGrant.js +0 -43
- package/dist/esm/core/authService/emailOtpRegistrationEnrollment.js +0 -144
- package/dist/esm/core/authService/emailOtpUnlock.js +0 -174
- package/dist/esm/core/authService/googleEmailOtpOperations.js +0 -141
- package/dist/esm/core/authService/googleEmailOtpRegistration.js +0 -587
- package/dist/esm/core/authService/identity.js +0 -42
- package/dist/esm/core/authService/identityOperations.js +0 -32
- package/dist/esm/core/authService/nearAccountOperations.js +0 -229
- package/dist/esm/core/authService/nearPublicKeyMetadata.js +0 -108
- package/dist/esm/core/authService/oidcVerification.js +0 -249
- package/dist/esm/core/authService/registrationThresholdHelpers.js +0 -30
- package/dist/esm/core/authService/runtime.js +0 -45
- package/dist/esm/core/authService/storeRegistry.js +0 -102
- package/dist/esm/core/authService/thresholdStoreSummary.js +0 -32
- package/dist/esm/core/authService/webauthnAuthority.js +0 -17
- package/dist/esm/core/defaultConfigsServer.js +0 -9
- package/dist/esm/core/hostedAccountIds.js +0 -225
- package/dist/esm/core/routerAbSigning/createRouterAbSigningRuntimes.js +0 -84
- package/dist/esm/core/signingLanes/LaneAggregateRevocationApplicationService.js +0 -86
- package/dist/esm/core/signingLanes/LaneEnrollmentActivation.js +0 -324
- package/dist/esm/core/signingLanes/LaneEnrollmentRevocation.js +0 -173
- package/dist/esm/core/signingLanes/LaneLifecycleApplicationService.js +0 -198
- package/dist/esm/core/signingLanes/ecdsaServerRetirement.js +0 -73
- package/dist/esm/core/signingLanes/ed25519ServerRetirement.js +0 -68
- package/dist/esm/core/storeBackends.js +0 -208
- package/dist/esm/core/utils.js +0 -14
- package/dist/esm/core/webAuthnStoreBackends.js +0 -198
- package/dist/esm/router/cloudflare/d1/near/d1NearPublicKeyStore.js +0 -49
- package/dist/esm/router/cloudflare/d1/signingLanes/d1EcdsaLanePrivateBindingResolver.js +0 -10
- package/dist/esm/router/cloudflare/d1/signingLanes/d1LaneAggregateRevocationApplicationService.js +0 -22
- package/dist/esm/router/cloudflare/d1/signingLanes/d1LaneEffectJournalStore.js +0 -166
- package/dist/esm/router/cloudflare/d1/signingLanes/d1LaneEnrollmentGateway.js +0 -38
- package/dist/esm/router/cloudflare/d1/signingLanes/d1LaneLifecycleApplicationService.js +0 -20
- package/dist/esm/router/cloudflare/d1/signingLanes/d1LaneLifecycleStore.js +0 -1459
- package/dist/esm/router/cloudflare/d1/signingLanes/d1LaneLockStore.js +0 -114
- package/dist/esm/router/cloudflare/d1/signingLanes/d1LaneProtocolCommitter.js +0 -16
- package/dist/esm/router/cloudflare/d1/signingLanes/d1LaneRecords.js +0 -171
- package/dist/esm/router/cloudflare/d1/signingLanes/index.js +0 -10
- package/dist/esm/router/cloudflare/durableObjects/thresholdStore.js +0 -397
- package/dist/esm/router/cloudflare/signingLanes/cloudflareLaneCurveExecution.js +0 -597
- package/dist/esm/router/cloudflare/signingLanes/cloudflareLaneProtocolCommitter.js +0 -273
- package/dist/esm/router/cloudflare/signingLanes/index.js +0 -4
- package/dist/esm/router/cloudflare/signingLanes/linkedDeviceEd25519CeremonyBinding.js +0 -32
- package/dist/esm/router/transport/fetch/routes/nearPublicKeys.js +0 -27
- package/dist/esm/shared-ts/src/signing-lanes/rotation.js +0 -8
- package/dist/esm/shared-ts/src/signing-lanes/rotationDigests.js +0 -358
- package/dist/esm/shared-ts/src/signing-lanes/rotationLifecycle.js +0 -313
- package/dist/esm/shared-ts/src/signing-lanes/rotationParsers.js +0 -532
- package/dist/esm/shared-ts/src/signing-lanes/rotationProtocolParsers.js +0 -323
- package/dist/esm/shared-ts/src/signing-lanes/rotationWireFields.js +0 -59
- package/dist/types/shared-ts/src/signing-lanes/participantDigest.typecheck.d.ts +0 -2
- package/dist/types/shared-ts/src/signing-lanes/rotation.typecheck.d.ts +0 -2
- package/dist/types/shared-ts/src/signing-lanes/rotationDigests.d.ts +0 -13
- package/dist/types/shared-ts/src/signing-lanes/rotationLifecycle.d.ts +0 -78
- package/dist/types/shared-ts/src/signing-lanes/rotationParsers.d.ts +0 -27
- package/dist/types/shared-ts/src/signing-lanes/rotationProtocolParsers.d.ts +0 -6
- package/dist/types/shared-ts/src/signing-lanes/rotationWireFields.d.ts +0 -20
- package/dist/types/shared-ts/src/wallet-recovery/recoveryCodeAttempt.d.ts +0 -59
- package/dist/types/wallet-server/src/core/AuthService.d.ts +0 -3
- package/dist/types/wallet-server/src/core/NearPublicKeyStore.d.ts +0 -48
- package/dist/types/wallet-server/src/core/ThresholdService/stores/CloudflareDurableObjectStore.d.ts +0 -21
- package/dist/types/wallet-server/src/core/ThresholdService/stores/KeyStore.d.ts +0 -40
- package/dist/types/wallet-server/src/core/ThresholdService/stores/SessionStore.d.ts +0 -98
- package/dist/types/wallet-server/src/core/ThresholdService/stores/StoreConfig.d.ts +0 -4
- package/dist/types/wallet-server/src/core/ThresholdService/stores/ThresholdStoreConfig.typecheck.d.ts +0 -2
- package/dist/types/wallet-server/src/core/ThresholdService/stores/exportReplayGuard.d.ts +0 -3
- package/dist/types/wallet-server/src/core/authService/AuthService.d.ts +0 -490
- package/dist/types/wallet-server/src/core/authService/bytes.d.ts +0 -3
- package/dist/types/wallet-server/src/core/authService/configValues.d.ts +0 -7
- package/dist/types/wallet-server/src/core/authService/emailOtpChallengeOperations.d.ts +0 -109
- package/dist/types/wallet-server/src/core/authService/emailOtpChallengeProof.d.ts +0 -169
- package/dist/types/wallet-server/src/core/authService/emailOtpChallengeVerification.d.ts +0 -47
- package/dist/types/wallet-server/src/core/authService/emailOtpChallenges.d.ts +0 -86
- package/dist/types/wallet-server/src/core/authService/emailOtpDelivery.d.ts +0 -66
- package/dist/types/wallet-server/src/core/authService/emailOtpGrant.d.ts +0 -43
- package/dist/types/wallet-server/src/core/authService/emailOtpRegistrationEnrollment.d.ts +0 -49
- package/dist/types/wallet-server/src/core/authService/emailOtpUnlock.d.ts +0 -64
- package/dist/types/wallet-server/src/core/authService/googleEmailOtpOperations.d.ts +0 -126
- package/dist/types/wallet-server/src/core/authService/googleEmailOtpRegistration.d.ts +0 -169
- package/dist/types/wallet-server/src/core/authService/identity.d.ts +0 -25
- package/dist/types/wallet-server/src/core/authService/identityOperations.d.ts +0 -19
- package/dist/types/wallet-server/src/core/authService/nearAccountOperations.d.ts +0 -55
- package/dist/types/wallet-server/src/core/authService/nearPublicKeyMetadata.d.ts +0 -44
- package/dist/types/wallet-server/src/core/authService/oidcVerification.d.ts +0 -66
- package/dist/types/wallet-server/src/core/authService/registrationThresholdHelpers.d.ts +0 -11
- package/dist/types/wallet-server/src/core/authService/runtime.d.ts +0 -20
- package/dist/types/wallet-server/src/core/authService/storeRegistry.d.ts +0 -53
- package/dist/types/wallet-server/src/core/authService/thresholdStoreSummary.d.ts +0 -3
- package/dist/types/wallet-server/src/core/authService/webauthnAuthority.d.ts +0 -5
- package/dist/types/wallet-server/src/core/defaultConfigsServer.d.ts +0 -5
- package/dist/types/wallet-server/src/core/hostedAccountIds.d.ts +0 -16
- package/dist/types/wallet-server/src/core/routerAbSigning/createRouterAbSigningRuntimes.d.ts +0 -16
- package/dist/types/wallet-server/src/core/signingLanes/LaneAggregateRevocationApplicationService.d.ts +0 -36
- package/dist/types/wallet-server/src/core/signingLanes/LaneEffectJournalStore.d.ts +0 -62
- package/dist/types/wallet-server/src/core/signingLanes/LaneEnrollmentActivation.d.ts +0 -13
- package/dist/types/wallet-server/src/core/signingLanes/LaneEnrollmentRevocation.d.ts +0 -24
- package/dist/types/wallet-server/src/core/signingLanes/LaneLifecycleApplicationService.d.ts +0 -141
- package/dist/types/wallet-server/src/core/signingLanes/LaneLifecycleStore.d.ts +0 -228
- package/dist/types/wallet-server/src/core/signingLanes/ecdsaServerRetirement.d.ts +0 -58
- package/dist/types/wallet-server/src/core/signingLanes/ed25519ServerRetirement.d.ts +0 -30
- package/dist/types/wallet-server/src/core/signingLanes/signingWorkerLaneMaterialIdentity.d.ts +0 -4
- package/dist/types/wallet-server/src/core/storeBackends.d.ts +0 -83
- package/dist/types/wallet-server/src/core/utils.d.ts +0 -3
- package/dist/types/wallet-server/src/core/webAuthnStoreBackends.d.ts +0 -96
- package/dist/types/wallet-server/src/router/cloudflare/d1/near/d1NearPublicKeyStore.d.ts +0 -29
- package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/d1EcdsaLanePrivateBindingResolver.d.ts +0 -4
- package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/d1LaneAggregateRevocationApplicationService.d.ts +0 -4
- package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/d1LaneEffectJournalStore.d.ts +0 -24
- package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/d1LaneEnrollmentGateway.d.ts +0 -20
- package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/d1LaneLifecycleApplicationService.d.ts +0 -13
- package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/d1LaneLifecycleStore.d.ts +0 -51
- package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/d1LaneLockStore.d.ts +0 -28
- package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/d1LaneProtocolCommitter.d.ts +0 -5
- package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/d1LaneRecords.d.ts +0 -107
- package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/index.d.ts +0 -10
- package/dist/types/wallet-server/src/router/cloudflare/durableObjects/thresholdStore.d.ts +0 -18
- package/dist/types/wallet-server/src/router/cloudflare/signingLanes/cloudflareLaneCurveExecution.d.ts +0 -217
- package/dist/types/wallet-server/src/router/cloudflare/signingLanes/cloudflareLaneProtocolCommitter.d.ts +0 -73
- package/dist/types/wallet-server/src/router/cloudflare/signingLanes/index.d.ts +0 -4
- package/dist/types/wallet-server/src/router/cloudflare/signingLanes/linkedDeviceEd25519CeremonyBinding.d.ts +0 -6
- package/dist/types/wallet-server/src/router/transport/fetch/routes/nearPublicKeys.d.ts +0 -3
- /package/dist/esm/{core/signingLanes/LaneEffectJournalStore.js → authorization/ed25519WalletSessionAdmission.js} +0 -0
- /package/dist/esm/{core/signingLanes/LaneLifecycleStore.js → authorization/recoveryRouting.js} +0 -0
- /package/dist/esm/{core/signingLanes/signingWorkerLaneMaterialIdentity.js → authorization/sessionRouting.js} +0 -0
|
@@ -90,6 +90,21 @@ function buildCorsOrigins(...inputs) {
|
|
|
90
90
|
}
|
|
91
91
|
//#endregion
|
|
92
92
|
//#region ../shared-ts/src/device-linking/contracts.ts
|
|
93
|
+
function isLinkSessionTerminalFailureV1(state) {
|
|
94
|
+
switch (state.state) {
|
|
95
|
+
case "failed_before_commit":
|
|
96
|
+
case "cancelled":
|
|
97
|
+
case "expired": return true;
|
|
98
|
+
case "displaying_qr":
|
|
99
|
+
case "claimed":
|
|
100
|
+
case "awaiting_target_factor":
|
|
101
|
+
case "awaiting_source_contribution":
|
|
102
|
+
case "provisioning":
|
|
103
|
+
case "authority_pending_local_install":
|
|
104
|
+
case "active": return false;
|
|
105
|
+
default: return assertNeverLinkSessionStateV1(state);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
93
108
|
function assertNeverLinkSessionStateV1(value) {
|
|
94
109
|
throw new Error(`[LinkSessionStateV1] unsupported state: ${String(value)}`);
|
|
95
110
|
}
|
|
@@ -398,112 +413,6 @@ function toRorOriginOrNull(value) {
|
|
|
398
413
|
}
|
|
399
414
|
}
|
|
400
415
|
//#endregion
|
|
401
|
-
//#region ../shared-ts/src/utils/base58.ts
|
|
402
|
-
/**
|
|
403
|
-
* Encodes binary data to base58 string using Bitcoin's base58 alphabet.
|
|
404
|
-
*
|
|
405
|
-
* @param data - Binary data to encode (Uint8Array, ArrayBuffer, or number[])
|
|
406
|
-
* @returns Base58-encoded string
|
|
407
|
-
*/
|
|
408
|
-
const base58Encode = (data) => {
|
|
409
|
-
if (data instanceof ArrayBuffer) return bs58.encode(new Uint8Array(data));
|
|
410
|
-
if (Array.isArray(data)) return bs58.encode(new Uint8Array(data));
|
|
411
|
-
return bs58.encode(data);
|
|
412
|
-
};
|
|
413
|
-
/**
|
|
414
|
-
* Decodes a base58 string to binary data using Bitcoin's base58 alphabet.
|
|
415
|
-
* Returns a Uint8Array containing the decoded bytes.
|
|
416
|
-
*
|
|
417
|
-
* @param base58String - Base58-encoded string to decode
|
|
418
|
-
* @returns Uint8Array containing the decoded bytes
|
|
419
|
-
* @throws Error if input contains invalid base58 characters
|
|
420
|
-
*/
|
|
421
|
-
const base58Decode = (base58String) => {
|
|
422
|
-
return bs58.decode(base58String);
|
|
423
|
-
};
|
|
424
|
-
//#endregion
|
|
425
|
-
//#region ../shared-ts/src/utils/near.ts
|
|
426
|
-
/**
|
|
427
|
-
* NEAR-specific utility helpers.
|
|
428
|
-
*
|
|
429
|
-
* Keep chain-specific parsing and validation logic here so generic utility
|
|
430
|
-
* modules (`validation`, `errors`, `encoders`, etc.) stay chain-agnostic.
|
|
431
|
-
*/
|
|
432
|
-
/**
|
|
433
|
-
* Ensure a key string has the NEAR Ed25519 prefix (`ed25519:`).
|
|
434
|
-
*
|
|
435
|
-
* - Accepts either `ed25519:<base58>` or a bare `<base58>` string.
|
|
436
|
-
* - Canonicalizes `ED25519:` -> `ed25519:`.
|
|
437
|
-
* - If a different prefix is present (e.g. `secp256k1:`), returns the input unchanged.
|
|
438
|
-
*/
|
|
439
|
-
function ensureEd25519Prefix(value) {
|
|
440
|
-
const raw = String(value ?? "").trim();
|
|
441
|
-
if (!raw) return "";
|
|
442
|
-
if (/^[a-z0-9_]+:/i.test(raw)) {
|
|
443
|
-
if (/^ed25519:/i.test(raw)) return `ed25519:${raw.replace(/^ed25519:/i, "")}`;
|
|
444
|
-
return raw;
|
|
445
|
-
}
|
|
446
|
-
return `ed25519:${raw}`;
|
|
447
|
-
}
|
|
448
|
-
/**
|
|
449
|
-
* Lightweight NEAR account ID validation used by server-side helpers.
|
|
450
|
-
* - length: 2..64
|
|
451
|
-
* - chars: lowercase letters, digits, `_`, `.`, `-`
|
|
452
|
-
*/
|
|
453
|
-
function isValidAccountId(accountId) {
|
|
454
|
-
if (typeof accountId !== "string") return false;
|
|
455
|
-
if (!accountId || accountId.length < 2 || accountId.length > 64) return false;
|
|
456
|
-
return /^[a-z0-9_.-]+$/.test(accountId);
|
|
457
|
-
}
|
|
458
|
-
function isImplicitNearAccountId(value) {
|
|
459
|
-
return typeof value === "string" && /^[0-9a-f]{64}$/.test(value);
|
|
460
|
-
}
|
|
461
|
-
function parseImplicitNearAccountId(raw) {
|
|
462
|
-
const value = typeof raw === "string" ? raw.trim() : "";
|
|
463
|
-
if (!value) return {
|
|
464
|
-
ok: false,
|
|
465
|
-
code: "missing",
|
|
466
|
-
message: "implicit NEAR account ID is required"
|
|
467
|
-
};
|
|
468
|
-
if (!isImplicitNearAccountId(value)) return {
|
|
469
|
-
ok: false,
|
|
470
|
-
code: "invalid",
|
|
471
|
-
message: "implicit NEAR account ID must be 64 lowercase hex characters"
|
|
472
|
-
};
|
|
473
|
-
return {
|
|
474
|
-
ok: true,
|
|
475
|
-
value
|
|
476
|
-
};
|
|
477
|
-
}
|
|
478
|
-
function parseNamedNearAccountId(raw) {
|
|
479
|
-
const value = typeof raw === "string" ? raw.trim() : "";
|
|
480
|
-
if (!value) return {
|
|
481
|
-
ok: false,
|
|
482
|
-
code: "missing",
|
|
483
|
-
message: "named NEAR account ID is required"
|
|
484
|
-
};
|
|
485
|
-
if (isImplicitNearAccountId(value) || !isValidAccountId(value) || !value.includes(".")) return {
|
|
486
|
-
ok: false,
|
|
487
|
-
code: "invalid",
|
|
488
|
-
message: "named NEAR account ID must be a valid named account containing a dot"
|
|
489
|
-
};
|
|
490
|
-
return {
|
|
491
|
-
ok: true,
|
|
492
|
-
value
|
|
493
|
-
};
|
|
494
|
-
}
|
|
495
|
-
function bytesToLowerHex(bytes) {
|
|
496
|
-
return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
497
|
-
}
|
|
498
|
-
function deriveImplicitNearAccountIdFromEd25519PublicKey(publicKey) {
|
|
499
|
-
const normalized = ensureEd25519Prefix(publicKey);
|
|
500
|
-
const encoded = normalized.startsWith("ed25519:") ? normalized.slice(8) : "";
|
|
501
|
-
if (!encoded) throw new Error("Ed25519 public key is required");
|
|
502
|
-
const decoded = base58Decode(encoded);
|
|
503
|
-
if (decoded.length !== 32) throw new Error("Ed25519 public key must decode to 32 bytes");
|
|
504
|
-
return bytesToLowerHex(decoded);
|
|
505
|
-
}
|
|
506
|
-
//#endregion
|
|
507
416
|
//#region ../shared-ts/src/utils/validation.ts
|
|
508
417
|
function requireTrimmedString(value, label, message = "is required") {
|
|
509
418
|
const parsed = normalizeOptionalTrimmedString(value);
|
|
@@ -1083,15 +992,25 @@ function parseTargetEmail(raw, label) {
|
|
|
1083
992
|
}
|
|
1084
993
|
//#endregion
|
|
1085
994
|
//#region ../shared-ts/src/device-linking/activeWalletSession.ts
|
|
995
|
+
const walletSessionHome = wireUnion("kind", [wireObject({ kind: wireLiteral("direct") }), wireObject({
|
|
996
|
+
kind: wireLiteral("regional"),
|
|
997
|
+
region: wireLiteral("US", "WEUR", "APAC", "OC")
|
|
998
|
+
})]);
|
|
999
|
+
function parseWalletSessionHome(raw) {
|
|
1000
|
+
return walletSessionHome(raw, "Wallet Session home");
|
|
1001
|
+
}
|
|
1086
1002
|
function walletSessionOperationCredentialV1() {
|
|
1087
1003
|
return wireObject({
|
|
1088
1004
|
kind: wireLiteral("opaque_wallet_session_operation_credential_v1"),
|
|
1005
|
+
ownershipGeneration: parseNonNegativeSafeInteger,
|
|
1006
|
+
home: parseWalletSessionHome,
|
|
1089
1007
|
token: (raw, label) => {
|
|
1090
1008
|
if (typeof raw !== "string" || raw.length > 8192) throw new Error(`${label} is invalid`);
|
|
1091
1009
|
return raw;
|
|
1092
1010
|
},
|
|
1093
1011
|
walletSessionId: keyLabeled(walletSessionId)
|
|
1094
1012
|
}, (credential, label) => {
|
|
1013
|
+
if (credential.ownershipGeneration === 0) throw new Error(`${label} ownership generation must be positive`);
|
|
1095
1014
|
if (!/^wst_[A-Za-z0-9_-]{43}$/.test(credential.token)) throw new Error(`${label} opaque token is invalid`);
|
|
1096
1015
|
});
|
|
1097
1016
|
}
|
|
@@ -1536,11 +1455,6 @@ function requireSignerRole(value, label) {
|
|
|
1536
1455
|
default: throw new Error(`${label} must be signer_a or signer_b`);
|
|
1537
1456
|
}
|
|
1538
1457
|
}
|
|
1539
|
-
function requireLowerHex(value, label, byteLength) {
|
|
1540
|
-
const hex = coerceNonEmptyString(value, label);
|
|
1541
|
-
if (!new RegExp(`^[0-9a-f]{${byteLength * 2}}$`).test(hex)) throw new Error(`${label} must be ${byteLength} lowercase-hex bytes`);
|
|
1542
|
-
return hex;
|
|
1543
|
-
}
|
|
1544
1458
|
function requireRouterAbX25519PublicKey(value, label) {
|
|
1545
1459
|
const publicKey = coerceNonEmptyString(value, label);
|
|
1546
1460
|
if (!/^x25519:[0-9a-f]{64}$/.test(publicKey)) throw new Error(`${label} must use x25519:<64 lowercase hex chars> encoding`);
|
|
@@ -1595,26 +1509,6 @@ function parseSignerEnvelopeHpkeRotationPublicKeySet(value, label) {
|
|
|
1595
1509
|
previous_retire_at_ms: requirePositiveInteger(record.previous_retire_at_ms, `${label}.previous_retire_at_ms`)
|
|
1596
1510
|
};
|
|
1597
1511
|
}
|
|
1598
|
-
function parseSignerPeerVerifyingKey(value, label) {
|
|
1599
|
-
const record = requireRecord(value, label);
|
|
1600
|
-
requireExactKeys$5(record, ["role", "verifying_key_hex"], label);
|
|
1601
|
-
return {
|
|
1602
|
-
role: requireSignerRole(record.role, `${label}.role`),
|
|
1603
|
-
verifying_key_hex: requireLowerHex(record.verifying_key_hex, `${label}.verifying_key_hex`, 32)
|
|
1604
|
-
};
|
|
1605
|
-
}
|
|
1606
|
-
function parseSignerPeerVerifyingKeySet(value, label) {
|
|
1607
|
-
const record = requireRecord(value, label);
|
|
1608
|
-
requireExactKeys$5(record, ["deriver_a", "deriver_b"], label);
|
|
1609
|
-
const deriverA = parseSignerPeerVerifyingKey(record.deriver_a, `${label}.deriver_a`);
|
|
1610
|
-
const deriverB = parseSignerPeerVerifyingKey(record.deriver_b, `${label}.deriver_b`);
|
|
1611
|
-
if (deriverA.role !== "signer_a") throw new Error(`${label}.deriver_a.role must be signer_a`);
|
|
1612
|
-
if (deriverB.role !== "signer_b") throw new Error(`${label}.deriver_b.role must be signer_b`);
|
|
1613
|
-
return {
|
|
1614
|
-
deriver_a: deriverA,
|
|
1615
|
-
deriver_b: deriverB
|
|
1616
|
-
};
|
|
1617
|
-
}
|
|
1618
1512
|
function parsePublicHpkeKeyDescriptor(value, label) {
|
|
1619
1513
|
const record = requireRecord(value, label);
|
|
1620
1514
|
requireExactKeys$5(record, ["key_epoch", "public_key"], label);
|
|
@@ -1628,7 +1522,6 @@ function parseRouterAbPublicKeysetV2(value) {
|
|
|
1628
1522
|
requireExactKeys$5(record, [
|
|
1629
1523
|
"keyset_version",
|
|
1630
1524
|
"signer_envelope_hpke",
|
|
1631
|
-
"signer_peer_verifying_keys",
|
|
1632
1525
|
"signing_worker_server_output_hpke"
|
|
1633
1526
|
], "Router A/B public keyset");
|
|
1634
1527
|
const keysetVersion = coerceNonEmptyString(record.keyset_version, "keyset_version");
|
|
@@ -1636,7 +1529,6 @@ function parseRouterAbPublicKeysetV2(value) {
|
|
|
1636
1529
|
return {
|
|
1637
1530
|
keyset_version: ROUTER_AB_PUBLIC_KEYSET_VERSION_V2,
|
|
1638
1531
|
signer_envelope_hpke: parseSignerEnvelopeHpkeRotationPublicKeySet(record.signer_envelope_hpke, "signer_envelope_hpke"),
|
|
1639
|
-
signer_peer_verifying_keys: parseSignerPeerVerifyingKeySet(record.signer_peer_verifying_keys, "signer_peer_verifying_keys"),
|
|
1640
1532
|
signing_worker_server_output_hpke: parsePublicHpkeKeyDescriptor(record.signing_worker_server_output_hpke, "signing_worker_server_output_hpke")
|
|
1641
1533
|
};
|
|
1642
1534
|
}
|
|
@@ -5416,12 +5308,17 @@ function createRouterAbTraceContextV1() {
|
|
|
5416
5308
|
};
|
|
5417
5309
|
}
|
|
5418
5310
|
//#endregion
|
|
5311
|
+
//#region ../shared-ts/src/utils/walletManagementProtocol.ts
|
|
5312
|
+
const WALLET_MANAGEMENT_PROTOCOL_HEADER = "X-Seams-Wallet-Protocol";
|
|
5313
|
+
//#endregion
|
|
5419
5314
|
//#region src/router/framework/http.ts
|
|
5420
5315
|
const CORS_ALLOW_METHODS = "GET,POST,PUT,PATCH,DELETE,OPTIONS";
|
|
5421
5316
|
const CORS_PREFLIGHT_MAX_AGE_SECONDS = 600;
|
|
5422
5317
|
const CORS_ALLOW_HEADERS = [
|
|
5423
5318
|
"Content-Type",
|
|
5319
|
+
WALLET_MANAGEMENT_PROTOCOL_HEADER,
|
|
5424
5320
|
"Authorization",
|
|
5321
|
+
"X-Seams-Wallet-Region",
|
|
5425
5322
|
"X-Seams-Benchmark-Diagnostics",
|
|
5426
5323
|
LINKED_DEVICE_REQUEST_PROOF_HEADER_V1,
|
|
5427
5324
|
ROUTER_AB_ED25519_YAO_RECOVERY_CHALLENGE_ID_HEADER_V1,
|
|
@@ -5474,7 +5371,7 @@ function withCors(headers, opts, request) {
|
|
|
5474
5371
|
headers.set("Access-Control-Allow-Methods", CORS_ALLOW_METHODS);
|
|
5475
5372
|
headers.set("Access-Control-Allow-Headers", CORS_ALLOW_HEADERS);
|
|
5476
5373
|
if (allowedOrigin && request?.method === "OPTIONS") headers.set("Access-Control-Max-Age", String(CORS_PREFLIGHT_MAX_AGE_SECONDS));
|
|
5477
|
-
|
|
5374
|
+
headers.set("Access-Control-Expose-Headers", "Server-Timing, X-Seams-Wallet-Region");
|
|
5478
5375
|
if (allowedOrigin && allowedOrigin !== "*") headers.set("Access-Control-Allow-Credentials", "true");
|
|
5479
5376
|
}
|
|
5480
5377
|
async function readJson(request) {
|
|
@@ -5529,6 +5426,11 @@ async function handleReady(ctx) {
|
|
|
5529
5426
|
}
|
|
5530
5427
|
}
|
|
5531
5428
|
//#endregion
|
|
5429
|
+
//#region ../shared-ts/src/utils/registrationSetupOperation.ts
|
|
5430
|
+
function parseRegistrationSetupOperationId(value) {
|
|
5431
|
+
return typeof value === "string" && /^wreg_[A-Za-z0-9_-]{43}$/u.test(value) ? value : null;
|
|
5432
|
+
}
|
|
5433
|
+
//#endregion
|
|
5532
5434
|
//#region src/router/auth/routerApiKeyAuth.ts
|
|
5533
5435
|
function readHeader(headers, name) {
|
|
5534
5436
|
if (headers instanceof Headers) return String(headers.get(name) || "").trim();
|
|
@@ -5579,7 +5481,7 @@ function routeAuthNotConfigured(message) {
|
|
|
5579
5481
|
message
|
|
5580
5482
|
};
|
|
5581
5483
|
}
|
|
5582
|
-
|
|
5484
|
+
function parsePublishableKeyRequest(input) {
|
|
5583
5485
|
if (input.route.auth.plane !== "api_credentials") return routeAuthNotConfigured(input.routeAuthNotConfiguredMessage);
|
|
5584
5486
|
const publishableKey = extractBearerCredential(input.headers);
|
|
5585
5487
|
if (!publishableKey) return {
|
|
@@ -5602,23 +5504,42 @@ async function resolvePublishableKeyApiCredentialAuth(input) {
|
|
|
5602
5504
|
code: "forbidden",
|
|
5603
5505
|
message: `publishable_key_environment_mismatch: ${input.missingEnvironmentMessage}`
|
|
5604
5506
|
};
|
|
5605
|
-
|
|
5606
|
-
|
|
5607
|
-
|
|
5608
|
-
|
|
5507
|
+
return {
|
|
5508
|
+
ok: true,
|
|
5509
|
+
request: {
|
|
5510
|
+
secret: publishableKey,
|
|
5511
|
+
origin,
|
|
5512
|
+
environmentId
|
|
5513
|
+
}
|
|
5514
|
+
};
|
|
5515
|
+
}
|
|
5516
|
+
async function resolveWalletRegistrationContext(input) {
|
|
5517
|
+
const parsed = parsePublishableKeyRequest(input);
|
|
5518
|
+
if (!parsed.ok) return parsed;
|
|
5519
|
+
return input.registrationContext.resolve({
|
|
5520
|
+
...parsed.request,
|
|
5521
|
+
registration: input.registration
|
|
5609
5522
|
});
|
|
5523
|
+
}
|
|
5524
|
+
async function resolvePublishableKeyApiCredentialAuth(input) {
|
|
5525
|
+
const parsed = parsePublishableKeyRequest(input);
|
|
5526
|
+
if (!parsed.ok) return parsed;
|
|
5527
|
+
const authResult = await input.publishableKeyAuth.authenticate(parsed.request);
|
|
5610
5528
|
if (!authResult.ok) return {
|
|
5611
5529
|
ok: false,
|
|
5612
5530
|
status: authResult.status,
|
|
5613
5531
|
code: authResult.status === 403 ? "forbidden" : "unauthorized",
|
|
5614
5532
|
message: `${authResult.code}: ${authResult.message}`
|
|
5615
5533
|
};
|
|
5534
|
+
return publishableKeyRoutePrincipal(authResult.principal);
|
|
5535
|
+
}
|
|
5536
|
+
async function publishableKeyRoutePrincipal(principal) {
|
|
5616
5537
|
return {
|
|
5617
5538
|
ok: true,
|
|
5618
5539
|
principal: {
|
|
5619
5540
|
kind: "api_credentials",
|
|
5620
5541
|
credentialType: "publishable_key",
|
|
5621
|
-
principal
|
|
5542
|
+
principal
|
|
5622
5543
|
}
|
|
5623
5544
|
};
|
|
5624
5545
|
}
|
|
@@ -5729,22 +5650,6 @@ function parseLaneParticipantBindingDigestB64u(raw) {
|
|
|
5729
5650
|
return parseDigest(raw, "participantBindingDigestB64u", brandParticipantDigest);
|
|
5730
5651
|
}
|
|
5731
5652
|
//#endregion
|
|
5732
|
-
//#region ../shared-ts/src/utils/registrationIds.ts
|
|
5733
|
-
function walletIdFromString(value) {
|
|
5734
|
-
const parsed = parseWalletId(value);
|
|
5735
|
-
if (!parsed.ok) throw new Error(parsed.error.message);
|
|
5736
|
-
return parsed.value;
|
|
5737
|
-
}
|
|
5738
|
-
function nearEd25519SigningKeyIdFromString(value) {
|
|
5739
|
-
const normalized = String(value || "").trim();
|
|
5740
|
-
if (!normalized) throw new Error("nearEd25519SigningKeyId is required");
|
|
5741
|
-
return normalized;
|
|
5742
|
-
}
|
|
5743
|
-
function parseNearEd25519SigningKeyId(value) {
|
|
5744
|
-
if (typeof value !== "string") throw new Error("nearEd25519SigningKeyId must be a string");
|
|
5745
|
-
return nearEd25519SigningKeyIdFromString(value);
|
|
5746
|
-
}
|
|
5747
|
-
//#endregion
|
|
5748
5653
|
//#region ../shared-ts/src/signing-lanes/participantDigest.ts
|
|
5749
5654
|
function u32(value) {
|
|
5750
5655
|
if (!Number.isInteger(value) || value < 0 || value > 4294967295) throw new Error("canonical u32 must be an integer between 0 and 4294967295");
|
|
@@ -5775,6 +5680,17 @@ function encodeLaneCanonicalU64V1(value) {
|
|
|
5775
5680
|
return output;
|
|
5776
5681
|
}
|
|
5777
5682
|
//#endregion
|
|
5683
|
+
//#region ../shared-ts/src/signing-lanes/execution.ts
|
|
5684
|
+
function buildPreparedOwnerWalletExecution(input) {
|
|
5685
|
+
return {
|
|
5686
|
+
kind: "prepared_owner_wallet_execution",
|
|
5687
|
+
laneKind: input.lane.laneKind,
|
|
5688
|
+
authorization: input.authorization,
|
|
5689
|
+
materialActivation: input.materialActivation,
|
|
5690
|
+
lane: input.lane
|
|
5691
|
+
};
|
|
5692
|
+
}
|
|
5693
|
+
//#endregion
|
|
5778
5694
|
//#region ../shared-ts/src/signing-lanes/ownerContinuity.ts
|
|
5779
5695
|
const OWNER_LANE_PARTICIPANT_BINDING_DOMAIN_V1 = "seams/rotatable-signing-lanes/owner-lane-participant-continuity/v1";
|
|
5780
5696
|
const OWNER_LANE_PARTICIPANT_CONTINUITY_FIELDS = [
|
|
@@ -5842,18 +5758,6 @@ function ownerLaneParticipantContinuityCanonicalBytesV1(input) {
|
|
|
5842
5758
|
async function computeOwnerLaneParticipantBindingDigestV1(input) {
|
|
5843
5759
|
return requireParsed$2(parseLaneParticipantBindingDigestB64u(base64UrlEncode(await sha256Bytes(ownerLaneParticipantContinuityCanonicalBytesV1(input)))), "owner participant digest");
|
|
5844
5760
|
}
|
|
5845
|
-
new TextEncoder();
|
|
5846
|
-
//#endregion
|
|
5847
|
-
//#region ../shared-ts/src/signing-lanes/execution.ts
|
|
5848
|
-
function buildPreparedOwnerWalletExecution(input) {
|
|
5849
|
-
return {
|
|
5850
|
-
kind: "prepared_owner_wallet_execution",
|
|
5851
|
-
laneKind: input.lane.laneKind,
|
|
5852
|
-
authorization: input.authorization,
|
|
5853
|
-
materialActivation: input.materialActivation,
|
|
5854
|
-
lane: input.lane
|
|
5855
|
-
};
|
|
5856
|
-
}
|
|
5857
5761
|
//#endregion
|
|
5858
5762
|
//#region ../shared-ts/src/authorization/operationFingerprint.ts
|
|
5859
5763
|
const CAPABILITY_OPERATION_FINGERPRINT_DOMAIN_V1 = "seams:authorization:capability-operation-fingerprint:v1";
|
|
@@ -5906,6 +5810,30 @@ function parseSigningOperationFingerprintDigest(value) {
|
|
|
5906
5810
|
return parseDigestB64u(value.slice(7));
|
|
5907
5811
|
}
|
|
5908
5812
|
//#endregion
|
|
5813
|
+
//#region ../shared-ts/src/utils/base58.ts
|
|
5814
|
+
/**
|
|
5815
|
+
* Encodes binary data to base58 string using Bitcoin's base58 alphabet.
|
|
5816
|
+
*
|
|
5817
|
+
* @param data - Binary data to encode (Uint8Array, ArrayBuffer, or number[])
|
|
5818
|
+
* @returns Base58-encoded string
|
|
5819
|
+
*/
|
|
5820
|
+
const base58Encode = (data) => {
|
|
5821
|
+
if (data instanceof ArrayBuffer) return bs58.encode(new Uint8Array(data));
|
|
5822
|
+
if (Array.isArray(data)) return bs58.encode(new Uint8Array(data));
|
|
5823
|
+
return bs58.encode(data);
|
|
5824
|
+
};
|
|
5825
|
+
/**
|
|
5826
|
+
* Decodes a base58 string to binary data using Bitcoin's base58 alphabet.
|
|
5827
|
+
* Returns a Uint8Array containing the decoded bytes.
|
|
5828
|
+
*
|
|
5829
|
+
* @param base58String - Base58-encoded string to decode
|
|
5830
|
+
* @returns Uint8Array containing the decoded bytes
|
|
5831
|
+
* @throws Error if input contains invalid base58 characters
|
|
5832
|
+
*/
|
|
5833
|
+
const base58Decode = (base58String) => {
|
|
5834
|
+
return bs58.decode(base58String);
|
|
5835
|
+
};
|
|
5836
|
+
//#endregion
|
|
5909
5837
|
//#region src/authorization/domain.ts
|
|
5910
5838
|
/**
|
|
5911
5839
|
* The digest-free authorization projection published to the browser. It carries
|
|
@@ -6012,6 +5940,9 @@ function walletSessionCapabilitySubjectsV1Equal(left, right) {
|
|
|
6012
5940
|
}
|
|
6013
5941
|
return true;
|
|
6014
5942
|
}
|
|
5943
|
+
function walletSessionAuthorizationV2RecordsEqual(left, right) {
|
|
5944
|
+
return left.kind === right.kind && left.tenantId === right.tenantId && left.principalId === right.principalId && left.walletId === right.walletId && left.authorityId === right.authorityId && left.walletAuthMethodId === right.walletAuthMethodId && left.authorityDigestB64u === right.authorityDigestB64u && left.authorityRevocationEpoch === right.authorityRevocationEpoch && left.mintId === right.mintId && left.authorizationId === right.authorizationId && left.walletSessionId === right.walletSessionId && left.quotaId === right.quotaId && walletSessionCapabilitySubjectsV1Equal(left.capabilitySubjects, right.capabilitySubjects) && left.createdAtMs === right.createdAtMs && left.expiresAtMs === right.expiresAtMs;
|
|
5945
|
+
}
|
|
6015
5946
|
function parseAuthorizedOperationReplayResponse(value) {
|
|
6016
5947
|
if (!isAuthorizedOperationReplayResponseRecordV1(value)) throw new Error("authorized operation replay response must be an object");
|
|
6017
5948
|
const keys = Object.keys(value).sort();
|
|
@@ -6144,8 +6075,7 @@ function resolveWalletSessionAuthorizationV2AdministrationAdmission(input) {
|
|
|
6144
6075
|
if (!subject || subject.authorityId !== input.authority.authorityId) return admissionRefused("capability_subject_mismatch");
|
|
6145
6076
|
return {
|
|
6146
6077
|
ok: true,
|
|
6147
|
-
operationKind: "link_devices"
|
|
6148
|
-
authorityId: input.authority.authorityId
|
|
6078
|
+
operationKind: "link_devices"
|
|
6149
6079
|
};
|
|
6150
6080
|
}
|
|
6151
6081
|
default: return assertNeverWalletSessionAuthorizationV2AdministrationOperation(input.operation.kind);
|
|
@@ -6397,12 +6327,23 @@ async function validateRouterAbEd25519WalletSessionInputs(input) {
|
|
|
6397
6327
|
const token = extractBearerCredential(input.headers);
|
|
6398
6328
|
if (!token) return walletSessionFailure("wallet_session_missing");
|
|
6399
6329
|
const nowMs = input.nowMs || Date.now;
|
|
6330
|
+
let read;
|
|
6400
6331
|
let resolution;
|
|
6401
6332
|
try {
|
|
6402
|
-
|
|
6403
|
-
authorizationSessions,
|
|
6333
|
+
read = await authorizationSessions.readEd25519WalletSessionSigningReadByOperationCredential({
|
|
6334
|
+
tenantId: authorizationSessions.tenantId,
|
|
6404
6335
|
token,
|
|
6405
6336
|
nowMs: nowMs(),
|
|
6337
|
+
materialActivation: input.materialActivation
|
|
6338
|
+
});
|
|
6339
|
+
if (!read) return {
|
|
6340
|
+
ok: false,
|
|
6341
|
+
code: "wallet_session_invalid",
|
|
6342
|
+
message: walletSessionFailureMessage("wallet_session_invalid")
|
|
6343
|
+
};
|
|
6344
|
+
resolution = resolveWalletSessionOperationCredentialAdmissionFromContext({
|
|
6345
|
+
context: read.context,
|
|
6346
|
+
nowMs: nowMs(),
|
|
6406
6347
|
operation: {
|
|
6407
6348
|
keyFamily: "ed25519",
|
|
6408
6349
|
operationKind: input.operationKind
|
|
@@ -6411,18 +6352,14 @@ async function validateRouterAbEd25519WalletSessionInputs(input) {
|
|
|
6411
6352
|
} catch {
|
|
6412
6353
|
return walletSessionFailure("wallet_session_unavailable");
|
|
6413
6354
|
}
|
|
6414
|
-
if (resolution.kind === "rejected") return walletSessionFailure("wallet_session_scope_mismatch");
|
|
6415
|
-
if (resolution.kind === "not_found") return {
|
|
6416
|
-
ok: false,
|
|
6417
|
-
code: "wallet_session_invalid",
|
|
6418
|
-
message: walletSessionFailureMessage("wallet_session_invalid")
|
|
6419
|
-
};
|
|
6420
|
-
if (resolution.admission.curve !== "ed25519") return walletSessionFailure("wallet_session_scope_mismatch");
|
|
6355
|
+
if (resolution.kind === "rejected" || resolution.admission.curve !== "ed25519") return walletSessionFailure("wallet_session_scope_mismatch");
|
|
6421
6356
|
return {
|
|
6422
6357
|
ok: true,
|
|
6423
6358
|
kind: "wallet_session_operation_credential_v1",
|
|
6424
6359
|
admission: resolution.admission,
|
|
6425
|
-
context: resolution.admission.context
|
|
6360
|
+
context: resolution.admission.context,
|
|
6361
|
+
signerRead: read.signerRead,
|
|
6362
|
+
policyRead: read.policyRead
|
|
6426
6363
|
};
|
|
6427
6364
|
}
|
|
6428
6365
|
async function validateEcdsaPreprocessingSession(input) {
|
|
@@ -6742,36 +6679,169 @@ async function enforceRoutePolicy(input) {
|
|
|
6742
6679
|
};
|
|
6743
6680
|
}
|
|
6744
6681
|
//#endregion
|
|
6745
|
-
//#region src/router/
|
|
6746
|
-
|
|
6747
|
-
|
|
6748
|
-
|
|
6749
|
-
|
|
6750
|
-
|
|
6751
|
-
|
|
6752
|
-
}
|
|
6753
|
-
|
|
6754
|
-
|
|
6755
|
-
|
|
6756
|
-
|
|
6757
|
-
|
|
6758
|
-
|
|
6759
|
-
|
|
6760
|
-
|
|
6761
|
-
|
|
6762
|
-
|
|
6763
|
-
|
|
6764
|
-
|
|
6765
|
-
|
|
6766
|
-
|
|
6767
|
-
|
|
6768
|
-
|
|
6769
|
-
}
|
|
6770
|
-
|
|
6771
|
-
|
|
6772
|
-
|
|
6773
|
-
|
|
6774
|
-
|
|
6682
|
+
//#region src/router/domains/walletRegistration/registrationSessionSeal.ts
|
|
6683
|
+
/** Holds one request's computation until registration can publish its response. */
|
|
6684
|
+
var RegistrationPreparedSessionSeal = class {
|
|
6685
|
+
constructor(request, service) {
|
|
6686
|
+
this.request = request;
|
|
6687
|
+
this.service = service;
|
|
6688
|
+
this.prepared = null;
|
|
6689
|
+
}
|
|
6690
|
+
async prepare(session) {
|
|
6691
|
+
await this.finish(session);
|
|
6692
|
+
}
|
|
6693
|
+
async finish(session) {
|
|
6694
|
+
const tokens = session.tokens;
|
|
6695
|
+
const ed25519 = tokens.kind === "near_ed25519" || tokens.kind === "near_ed25519_and_evm_family_ecdsa" ? tokens.ed25519 : null;
|
|
6696
|
+
if (!ed25519 || String(ed25519.thresholdSessionId) !== this.request.thresholdSessionId) return {
|
|
6697
|
+
ok: false,
|
|
6698
|
+
code: "invalid_session_seal",
|
|
6699
|
+
message: "Prepared seal does not match the established Ed25519 session"
|
|
6700
|
+
};
|
|
6701
|
+
if (this.prepared === null) this.prepared = {
|
|
6702
|
+
walletId: String(session.walletId),
|
|
6703
|
+
walletSessionId: String(session.walletSessionId),
|
|
6704
|
+
expiresAtMs: session.expiresAtMs,
|
|
6705
|
+
result: applyRegistrationSessionSeal(this.service, this.request, session)
|
|
6706
|
+
};
|
|
6707
|
+
if (this.prepared.walletId !== String(session.walletId) || this.prepared.walletSessionId !== String(session.walletSessionId) || this.prepared.expiresAtMs !== session.expiresAtMs) return {
|
|
6708
|
+
ok: false,
|
|
6709
|
+
code: "invalid_session_seal",
|
|
6710
|
+
message: "Prepared seal does not match the committed Wallet Session"
|
|
6711
|
+
};
|
|
6712
|
+
const sealed = await this.prepared.result;
|
|
6713
|
+
if (!sealed.ok) return sealed;
|
|
6714
|
+
const keyVersion = String(sealed.keyVersion || "").trim();
|
|
6715
|
+
if (!keyVersion) return {
|
|
6716
|
+
ok: false,
|
|
6717
|
+
code: "invalid_session_seal",
|
|
6718
|
+
message: "Signing-session seal response is missing its key version"
|
|
6719
|
+
};
|
|
6720
|
+
const expiresAtMs = Math.min(sealed.expiresAtMs ?? session.expiresAtMs, session.expiresAtMs);
|
|
6721
|
+
if (expiresAtMs <= Date.now()) return {
|
|
6722
|
+
ok: false,
|
|
6723
|
+
code: "expired",
|
|
6724
|
+
message: "threshold session expired"
|
|
6725
|
+
};
|
|
6726
|
+
return {
|
|
6727
|
+
ok: true,
|
|
6728
|
+
value: {
|
|
6729
|
+
ciphertext: sealed.ciphertext,
|
|
6730
|
+
keyVersion,
|
|
6731
|
+
expiresAtMs,
|
|
6732
|
+
remainingUses: session.remainingUses
|
|
6733
|
+
}
|
|
6734
|
+
};
|
|
6735
|
+
}
|
|
6736
|
+
};
|
|
6737
|
+
async function applyRegistrationSessionSeal(service, request, session) {
|
|
6738
|
+
if (!service) return {
|
|
6739
|
+
ok: false,
|
|
6740
|
+
code: "signing_session_seal_unavailable",
|
|
6741
|
+
message: "Signing-session sealing is unavailable"
|
|
6742
|
+
};
|
|
6743
|
+
try {
|
|
6744
|
+
return await service.applyServerSeal(request, {
|
|
6745
|
+
userId: String(session.walletId),
|
|
6746
|
+
session: {
|
|
6747
|
+
kind: "exact_wallet_session_operation_credential",
|
|
6748
|
+
curve: "ed25519",
|
|
6749
|
+
thresholdSessionId: request.thresholdSessionId,
|
|
6750
|
+
userId: String(session.walletId),
|
|
6751
|
+
expiresAtMs: session.expiresAtMs
|
|
6752
|
+
}
|
|
6753
|
+
});
|
|
6754
|
+
} catch {
|
|
6755
|
+
return {
|
|
6756
|
+
ok: false,
|
|
6757
|
+
code: "signing_session_seal_unavailable",
|
|
6758
|
+
message: "Signing-session sealing failed"
|
|
6759
|
+
};
|
|
6760
|
+
}
|
|
6761
|
+
}
|
|
6762
|
+
function parseRegistrationPreparedSessionSeal(raw, service) {
|
|
6763
|
+
if (raw === void 0) return {
|
|
6764
|
+
ok: true,
|
|
6765
|
+
value: null
|
|
6766
|
+
};
|
|
6767
|
+
if (!isPlainObject(raw)) return {
|
|
6768
|
+
ok: false,
|
|
6769
|
+
code: "invalid_body",
|
|
6770
|
+
message: "sessionSeal must be an object"
|
|
6771
|
+
};
|
|
6772
|
+
for (const field of Object.keys(raw)) if (![
|
|
6773
|
+
"thresholdSessionId",
|
|
6774
|
+
"ciphertext",
|
|
6775
|
+
"keyVersion"
|
|
6776
|
+
].includes(field)) return {
|
|
6777
|
+
ok: false,
|
|
6778
|
+
code: "invalid_body",
|
|
6779
|
+
message: "sessionSeal has unknown fields"
|
|
6780
|
+
};
|
|
6781
|
+
const thresholdSessionId = String(raw.thresholdSessionId || "").trim();
|
|
6782
|
+
const ciphertext = String(raw.ciphertext || "").trim();
|
|
6783
|
+
const keyVersion = String(raw.keyVersion || "").trim();
|
|
6784
|
+
if (!thresholdSessionId || !ciphertext) return {
|
|
6785
|
+
ok: false,
|
|
6786
|
+
code: "invalid_body",
|
|
6787
|
+
message: "sessionSeal thresholdSessionId and ciphertext are required"
|
|
6788
|
+
};
|
|
6789
|
+
return {
|
|
6790
|
+
ok: true,
|
|
6791
|
+
value: new RegistrationPreparedSessionSeal({
|
|
6792
|
+
thresholdSessionId,
|
|
6793
|
+
ciphertext,
|
|
6794
|
+
...keyVersion ? { keyVersion } : {}
|
|
6795
|
+
}, service)
|
|
6796
|
+
};
|
|
6797
|
+
}
|
|
6798
|
+
//#endregion
|
|
6799
|
+
//#region src/router/framework/routeResponses.ts
|
|
6800
|
+
function routeJson(status, body, options) {
|
|
6801
|
+
return {
|
|
6802
|
+
status,
|
|
6803
|
+
body,
|
|
6804
|
+
...options?.headers ? { headers: options.headers } : {},
|
|
6805
|
+
...options?.usage ? { usage: options.usage } : {}
|
|
6806
|
+
};
|
|
6807
|
+
}
|
|
6808
|
+
function routeError(status, code, message) {
|
|
6809
|
+
return routeJson(status, {
|
|
6810
|
+
ok: false,
|
|
6811
|
+
code,
|
|
6812
|
+
message
|
|
6813
|
+
});
|
|
6814
|
+
}
|
|
6815
|
+
function toFetchRouteResponse(response) {
|
|
6816
|
+
return new Response(JSON.stringify(response.body), {
|
|
6817
|
+
status: response.status,
|
|
6818
|
+
headers: {
|
|
6819
|
+
"Content-Type": "application/json; charset=utf-8",
|
|
6820
|
+
...response.headers || {}
|
|
6821
|
+
}
|
|
6822
|
+
});
|
|
6823
|
+
}
|
|
6824
|
+
//#endregion
|
|
6825
|
+
//#region ../shared-ts/src/utils/registrationIds.ts
|
|
6826
|
+
function walletIdFromString(value) {
|
|
6827
|
+
const parsed = parseWalletId(value);
|
|
6828
|
+
if (!parsed.ok) throw new Error(parsed.error.message);
|
|
6829
|
+
return parsed.value;
|
|
6830
|
+
}
|
|
6831
|
+
function nearEd25519SigningKeyIdFromString(value) {
|
|
6832
|
+
const normalized = String(value || "").trim();
|
|
6833
|
+
if (!normalized) throw new Error("nearEd25519SigningKeyId is required");
|
|
6834
|
+
return normalized;
|
|
6835
|
+
}
|
|
6836
|
+
function parseNearEd25519SigningKeyId(value) {
|
|
6837
|
+
if (typeof value !== "string") throw new Error("nearEd25519SigningKeyId must be a string");
|
|
6838
|
+
return nearEd25519SigningKeyIdFromString(value);
|
|
6839
|
+
}
|
|
6840
|
+
//#endregion
|
|
6841
|
+
//#region ../shared-ts/src/passkey-custody/custodySecretBinding.ts
|
|
6842
|
+
/** The only derivation scheme owner custody supports. */
|
|
6843
|
+
const WALLET_SEED_DERIVATION_SCHEME_V1 = "wallet_seed_parallel_hkdf_sha256_v1";
|
|
6844
|
+
function buildWalletCustodySeedBinding() {
|
|
6775
6845
|
return {
|
|
6776
6846
|
kind: "wallet_custody_seed_v1",
|
|
6777
6847
|
derivationScheme: WALLET_SEED_DERIVATION_SCHEME_V1
|
|
@@ -7144,99 +7214,6 @@ function parsePasskeyCustodyEnvelopeRecord(raw, label = "walletCustodyEnvelope")
|
|
|
7144
7214
|
});
|
|
7145
7215
|
}
|
|
7146
7216
|
//#endregion
|
|
7147
|
-
//#region src/router/domains/walletRegistration/walletRegistrationSetupPayload.ts
|
|
7148
|
-
const WALLET_REGISTRATION_SETUP_CLAIM_KIND = "wallet_registration_setup_v1";
|
|
7149
|
-
/**
|
|
7150
|
-
* Verifies the payload and binds it to the ceremony the caller is driving.
|
|
7151
|
-
* A payload that verifies cryptographically but names a different ceremony,
|
|
7152
|
-
* wallet, or setup digest is rejected — signature validity alone is not
|
|
7153
|
-
* authorization for this request.
|
|
7154
|
-
*/
|
|
7155
|
-
/**
|
|
7156
|
-
* Verifies the payload's signature, ceremony binding, and expiry, and returns
|
|
7157
|
-
* its claims — without needing the ceremony row.
|
|
7158
|
-
*
|
|
7159
|
-
* Activate depends on this: a successful activation deletes the ceremony, so
|
|
7160
|
-
* an exact replay must be answerable from the operation row alone. The claims
|
|
7161
|
-
* are Gateway-signed, so the `setupDigestB64u` they carry is trustworthy
|
|
7162
|
-
* without recomputing it from storage.
|
|
7163
|
-
*/
|
|
7164
|
-
async function verifyWalletRegistrationSetupClaims(signer, token, expected) {
|
|
7165
|
-
const value = normalizeOptionalTrimmedString(token);
|
|
7166
|
-
if (!value) return {
|
|
7167
|
-
ok: false,
|
|
7168
|
-
code: "invalid_body",
|
|
7169
|
-
message: "signedSetup is required"
|
|
7170
|
-
};
|
|
7171
|
-
const verified = await signer.verifyJwt(value);
|
|
7172
|
-
if (!verified.valid) return {
|
|
7173
|
-
ok: false,
|
|
7174
|
-
code: "invalid_grant",
|
|
7175
|
-
message: "signedSetup is not valid"
|
|
7176
|
-
};
|
|
7177
|
-
const claims = parseWalletRegistrationSetupClaims(verified.payload);
|
|
7178
|
-
if (!claims) return {
|
|
7179
|
-
ok: false,
|
|
7180
|
-
code: "invalid_grant",
|
|
7181
|
-
message: "signedSetup claims are not valid"
|
|
7182
|
-
};
|
|
7183
|
-
if (claims.registrationCeremonyId !== expected.registrationCeremonyId) return {
|
|
7184
|
-
ok: false,
|
|
7185
|
-
code: "invalid_grant",
|
|
7186
|
-
message: "signedSetup belongs to a different registration ceremony"
|
|
7187
|
-
};
|
|
7188
|
-
if (claims.expiresAtMs <= expected.nowMs) return {
|
|
7189
|
-
ok: false,
|
|
7190
|
-
code: "invalid_grant",
|
|
7191
|
-
message: "signedSetup has expired"
|
|
7192
|
-
};
|
|
7193
|
-
return {
|
|
7194
|
-
ok: true,
|
|
7195
|
-
claims
|
|
7196
|
-
};
|
|
7197
|
-
}
|
|
7198
|
-
function parseWalletRegistrationSetupClaims(value) {
|
|
7199
|
-
if (typeof value !== "object" || value === null) return null;
|
|
7200
|
-
const record = value;
|
|
7201
|
-
if (record.kind !== WALLET_REGISTRATION_SETUP_CLAIM_KIND) return null;
|
|
7202
|
-
const registrationCeremonyId = normalizeOptionalTrimmedString(record.registrationCeremonyId);
|
|
7203
|
-
const walletId = normalizeOptionalTrimmedString(record.walletId);
|
|
7204
|
-
const orgId = normalizeOptionalTrimmedString(record.orgId);
|
|
7205
|
-
const signingRootId = normalizeOptionalTrimmedString(record.signingRootId);
|
|
7206
|
-
const signingRootVersion = normalizeOptionalTrimmedString(record.signingRootVersion);
|
|
7207
|
-
const setupDigestB64u = normalizeOptionalTrimmedString(record.setupDigestB64u);
|
|
7208
|
-
const expiresAtMs = Number(record.expiresAtMs);
|
|
7209
|
-
const policy = parseWalletRegistrationSetupPolicy(record.policy);
|
|
7210
|
-
if (!registrationCeremonyId || !walletId || !orgId || !signingRootId || !signingRootVersion || !setupDigestB64u || !policy || !Number.isSafeInteger(expiresAtMs)) return null;
|
|
7211
|
-
return {
|
|
7212
|
-
kind: WALLET_REGISTRATION_SETUP_CLAIM_KIND,
|
|
7213
|
-
registrationCeremonyId,
|
|
7214
|
-
walletId,
|
|
7215
|
-
orgId,
|
|
7216
|
-
signingRootId,
|
|
7217
|
-
signingRootVersion,
|
|
7218
|
-
policy,
|
|
7219
|
-
setupDigestB64u,
|
|
7220
|
-
expiresAtMs
|
|
7221
|
-
};
|
|
7222
|
-
}
|
|
7223
|
-
function parseWalletRegistrationSetupPolicy(value) {
|
|
7224
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) return null;
|
|
7225
|
-
const record = value;
|
|
7226
|
-
switch (record.kind) {
|
|
7227
|
-
case "runtime_policy_scope": try {
|
|
7228
|
-
return {
|
|
7229
|
-
kind: "runtime_policy_scope",
|
|
7230
|
-
scope: normalizeRuntimePolicyScope(record.scope)
|
|
7231
|
-
};
|
|
7232
|
-
} catch {
|
|
7233
|
-
return null;
|
|
7234
|
-
}
|
|
7235
|
-
case "signing_root_only": return record.scope === void 0 ? { kind: "signing_root_only" } : null;
|
|
7236
|
-
default: return null;
|
|
7237
|
-
}
|
|
7238
|
-
}
|
|
7239
|
-
//#endregion
|
|
7240
7217
|
//#region ../shared-ts/src/utils/ecdsaKeyFactsInventory.ts
|
|
7241
7218
|
function normalizeChainTarget(target) {
|
|
7242
7219
|
if (target.kind === "evm") return {
|
|
@@ -7274,6 +7251,88 @@ async function computeWalletEcdsaKeyFactsInventoryChallengeDigestB64u(input) {
|
|
|
7274
7251
|
return base64UrlEncode(await sha256BytesUtf8(canonicalizeWalletEcdsaKeyFactsInventoryChallenge(input)));
|
|
7275
7252
|
}
|
|
7276
7253
|
//#endregion
|
|
7254
|
+
//#region ../shared-ts/src/utils/near.ts
|
|
7255
|
+
/**
|
|
7256
|
+
* NEAR-specific utility helpers.
|
|
7257
|
+
*
|
|
7258
|
+
* Keep chain-specific parsing and validation logic here so generic utility
|
|
7259
|
+
* modules (`validation`, `errors`, `encoders`, etc.) stay chain-agnostic.
|
|
7260
|
+
*/
|
|
7261
|
+
/**
|
|
7262
|
+
* Ensure a key string has the NEAR Ed25519 prefix (`ed25519:`).
|
|
7263
|
+
*
|
|
7264
|
+
* - Accepts either `ed25519:<base58>` or a bare `<base58>` string.
|
|
7265
|
+
* - Canonicalizes `ED25519:` -> `ed25519:`.
|
|
7266
|
+
* - If a different prefix is present (e.g. `secp256k1:`), returns the input unchanged.
|
|
7267
|
+
*/
|
|
7268
|
+
function ensureEd25519Prefix(value) {
|
|
7269
|
+
const raw = String(value ?? "").trim();
|
|
7270
|
+
if (!raw) return "";
|
|
7271
|
+
if (/^[a-z0-9_]+:/i.test(raw)) {
|
|
7272
|
+
if (/^ed25519:/i.test(raw)) return `ed25519:${raw.replace(/^ed25519:/i, "")}`;
|
|
7273
|
+
return raw;
|
|
7274
|
+
}
|
|
7275
|
+
return `ed25519:${raw}`;
|
|
7276
|
+
}
|
|
7277
|
+
/**
|
|
7278
|
+
* Lightweight NEAR account ID validation used by server-side helpers.
|
|
7279
|
+
* - length: 2..64
|
|
7280
|
+
* - chars: lowercase letters, digits, `_`, `.`, `-`
|
|
7281
|
+
*/
|
|
7282
|
+
function isValidAccountId(accountId) {
|
|
7283
|
+
if (typeof accountId !== "string") return false;
|
|
7284
|
+
if (!accountId || accountId.length < 2 || accountId.length > 64) return false;
|
|
7285
|
+
return /^[a-z0-9_.-]+$/.test(accountId);
|
|
7286
|
+
}
|
|
7287
|
+
function isImplicitNearAccountId(value) {
|
|
7288
|
+
return typeof value === "string" && /^[0-9a-f]{64}$/.test(value);
|
|
7289
|
+
}
|
|
7290
|
+
function parseImplicitNearAccountId(raw) {
|
|
7291
|
+
const value = typeof raw === "string" ? raw.trim() : "";
|
|
7292
|
+
if (!value) return {
|
|
7293
|
+
ok: false,
|
|
7294
|
+
code: "missing",
|
|
7295
|
+
message: "implicit NEAR account ID is required"
|
|
7296
|
+
};
|
|
7297
|
+
if (!isImplicitNearAccountId(value)) return {
|
|
7298
|
+
ok: false,
|
|
7299
|
+
code: "invalid",
|
|
7300
|
+
message: "implicit NEAR account ID must be 64 lowercase hex characters"
|
|
7301
|
+
};
|
|
7302
|
+
return {
|
|
7303
|
+
ok: true,
|
|
7304
|
+
value
|
|
7305
|
+
};
|
|
7306
|
+
}
|
|
7307
|
+
function parseNamedNearAccountId(raw) {
|
|
7308
|
+
const value = typeof raw === "string" ? raw.trim() : "";
|
|
7309
|
+
if (!value) return {
|
|
7310
|
+
ok: false,
|
|
7311
|
+
code: "missing",
|
|
7312
|
+
message: "named NEAR account ID is required"
|
|
7313
|
+
};
|
|
7314
|
+
if (isImplicitNearAccountId(value) || !isValidAccountId(value) || !value.includes(".")) return {
|
|
7315
|
+
ok: false,
|
|
7316
|
+
code: "invalid",
|
|
7317
|
+
message: "named NEAR account ID must be a valid named account containing a dot"
|
|
7318
|
+
};
|
|
7319
|
+
return {
|
|
7320
|
+
ok: true,
|
|
7321
|
+
value
|
|
7322
|
+
};
|
|
7323
|
+
}
|
|
7324
|
+
function bytesToLowerHex(bytes) {
|
|
7325
|
+
return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
7326
|
+
}
|
|
7327
|
+
function deriveImplicitNearAccountIdFromEd25519PublicKey(publicKey) {
|
|
7328
|
+
const normalized = ensureEd25519Prefix(publicKey);
|
|
7329
|
+
const encoded = normalized.startsWith("ed25519:") ? normalized.slice(8) : "";
|
|
7330
|
+
if (!encoded) throw new Error("Ed25519 public key is required");
|
|
7331
|
+
const decoded = base58Decode(encoded);
|
|
7332
|
+
if (decoded.length !== 32) throw new Error("Ed25519 public key must decode to 32 bytes");
|
|
7333
|
+
return bytesToLowerHex(decoded);
|
|
7334
|
+
}
|
|
7335
|
+
//#endregion
|
|
7277
7336
|
//#region ../shared-ts/src/utils/registrationSignerPlan.ts
|
|
7278
7337
|
function normalizePositiveInteger(raw, fallback) {
|
|
7279
7338
|
const value = typeof raw === "number" ? raw : Number(raw);
|
|
@@ -7941,6 +8000,12 @@ function parseWalletRegistrationSetupWallet(raw) {
|
|
|
7941
8000
|
};
|
|
7942
8001
|
}
|
|
7943
8002
|
function parseWalletRegistrationSetupRequest(body) {
|
|
8003
|
+
const registrationOperationId = parseRegistrationSetupOperationId(body.registrationOperationId);
|
|
8004
|
+
if (!registrationOperationId) return {
|
|
8005
|
+
ok: false,
|
|
8006
|
+
code: "invalid_body",
|
|
8007
|
+
message: "registrationOperationId is required"
|
|
8008
|
+
};
|
|
7944
8009
|
const signerSelection = parseRegistrationSignerSet(body.signerSelection);
|
|
7945
8010
|
if (!signerSelection.ok) return signerSelection;
|
|
7946
8011
|
const authMethod = normalizeRegistrationAuthMethodInput(body.authMethod);
|
|
@@ -7954,6 +8019,7 @@ function parseWalletRegistrationSetupRequest(body) {
|
|
|
7954
8019
|
return {
|
|
7955
8020
|
ok: true,
|
|
7956
8021
|
value: {
|
|
8022
|
+
registrationOperationId,
|
|
7957
8023
|
...wallet.value ? { wallet: wallet.value } : {},
|
|
7958
8024
|
signerSelection: signerSelection.value.selection,
|
|
7959
8025
|
authMethod
|
|
@@ -9171,20 +9237,31 @@ async function handleRouterApiWalletAddSignerIntent(input) {
|
|
|
9171
9237
|
});
|
|
9172
9238
|
return routeJson(result.ok ? 200 : 400, result);
|
|
9173
9239
|
}
|
|
9174
|
-
/**
|
|
9175
|
-
* `POST /wallets/register/setup` — the single admitted entry point that
|
|
9176
|
-
* replaces the bootstrap grant, the intent, and start.
|
|
9177
|
-
*
|
|
9178
|
-
* Authentication is the same API-credential plane the intent route used, so
|
|
9179
|
-
* origin and environment binding are unchanged; what is gone is the stored
|
|
9180
|
-
* grant that used to sit between the check and its only reader.
|
|
9181
|
-
*/
|
|
9182
9240
|
async function handleRouterApiWalletRegistrationSetup(input) {
|
|
9183
9241
|
if (!isPlainObject(input.body)) return routeError(400, "invalid_body", "JSON body required");
|
|
9184
9242
|
const origin = normalizeCorsOrigin(input.origin);
|
|
9185
9243
|
if (!origin) return routeError(403, "forbidden", "Origin header is required and must be a valid exact origin");
|
|
9186
|
-
const
|
|
9187
|
-
if (!
|
|
9244
|
+
const registrationContext = input.services.registrationContext;
|
|
9245
|
+
if (!registrationContext) return routeError(500, "route_auth_not_configured", "Wallet registration context is not configured");
|
|
9246
|
+
const request = parseWalletRegistrationSetupRequest(input.body);
|
|
9247
|
+
if (!request.ok) return routeError(400, request.code, request.message);
|
|
9248
|
+
const context = await resolveWalletRegistrationContext({
|
|
9249
|
+
registration: request.value,
|
|
9250
|
+
environmentId: extractRouterApiEnvironmentId(input.headers) || void 0,
|
|
9251
|
+
headers: input.headers,
|
|
9252
|
+
missingEnvironmentMessage: "Environment header is required for wallet registration setup",
|
|
9253
|
+
missingOriginMessage: "Origin header is required and must be a valid exact origin",
|
|
9254
|
+
missingPublishableKeyMessage: "Missing publishable key",
|
|
9255
|
+
origin,
|
|
9256
|
+
registrationContext,
|
|
9257
|
+
route: input.route,
|
|
9258
|
+
routeAuthNotConfiguredMessage: "Wallet registration setup requires API credential auth policy"
|
|
9259
|
+
});
|
|
9260
|
+
if (!context.ok) {
|
|
9261
|
+
if (context.status === 401) return routeError(401, "unauthorized", `${context.code}: ${context.message}`);
|
|
9262
|
+
if (context.status === 403) return routeError(403, "forbidden", `${context.code}: ${context.message}`);
|
|
9263
|
+
return routeError(context.status, "internal", `${context.code}: ${context.message}`);
|
|
9264
|
+
}
|
|
9188
9265
|
const resolved = await enforceRoutePolicy({
|
|
9189
9266
|
headers: input.headers,
|
|
9190
9267
|
logger: input.logger,
|
|
@@ -9195,44 +9272,27 @@ async function handleRouterApiWalletRegistrationSetup(input) {
|
|
|
9195
9272
|
route: input.route,
|
|
9196
9273
|
services: walletRegistrationRoutePolicyServices(input),
|
|
9197
9274
|
sourceIp: input.sourceIp,
|
|
9198
|
-
resolvers: { apiCredentials:
|
|
9199
|
-
environmentId: extractRouterApiEnvironmentId(input.headers) || void 0,
|
|
9200
|
-
headers: input.headers,
|
|
9201
|
-
missingEnvironmentMessage: "Environment header is required for wallet registration setup",
|
|
9202
|
-
missingOriginMessage: "Origin header is required and must be a valid exact origin",
|
|
9203
|
-
missingPublishableKeyMessage: "Missing publishable key",
|
|
9204
|
-
origin,
|
|
9205
|
-
publishableKeyAuth,
|
|
9206
|
-
route: input.route,
|
|
9207
|
-
routeAuthNotConfiguredMessage: "Wallet registration setup requires API credential auth policy"
|
|
9208
|
-
}) }
|
|
9275
|
+
resolvers: { apiCredentials: publishableKeyRoutePrincipal.bind(void 0, context.principal) }
|
|
9209
9276
|
});
|
|
9210
9277
|
if (!resolved.ok) return routeJson(resolved.status, resolved.body);
|
|
9211
|
-
|
|
9212
|
-
const
|
|
9213
|
-
const runtimePolicyScope = await resolveActiveRuntimePolicyScopeForEnvironment({
|
|
9214
|
-
orgProjectEnv: input.services.orgProjectEnv || null,
|
|
9278
|
+
const principal = context.principal;
|
|
9279
|
+
const runtimePolicyScope = {
|
|
9215
9280
|
orgId: principal.orgId,
|
|
9216
|
-
|
|
9217
|
-
|
|
9218
|
-
|
|
9219
|
-
}
|
|
9281
|
+
projectId: context.environment.projectId,
|
|
9282
|
+
envId: context.environment.key,
|
|
9283
|
+
signingRootVersion: context.environment.signingRootVersion
|
|
9284
|
+
};
|
|
9220
9285
|
const session = input.services.session;
|
|
9221
9286
|
if (!session) return routeError(500, "internal", "wallet registration setup requires session signing");
|
|
9222
|
-
|
|
9223
|
-
if (!request.ok) return routeError(400, request.code, request.message);
|
|
9224
|
-
const result = await input.services.walletRegistration.setupWalletRegistration({
|
|
9287
|
+
return input.services.walletRegistration.setupWalletRegistration({
|
|
9225
9288
|
request: request.value,
|
|
9226
9289
|
orgId: principal.orgId,
|
|
9227
9290
|
expectedOrigin: origin,
|
|
9228
9291
|
signer: session,
|
|
9229
|
-
|
|
9230
|
-
|
|
9231
|
-
|
|
9232
|
-
signingRootVersion: runtimePolicyScope.signingRootVersion
|
|
9233
|
-
} : {}
|
|
9292
|
+
runtimePolicyScope,
|
|
9293
|
+
signingRootId: `${runtimePolicyScope.projectId}:${runtimePolicyScope.envId}`,
|
|
9294
|
+
signingRootVersion: runtimePolicyScope.signingRootVersion
|
|
9234
9295
|
});
|
|
9235
|
-
return routeJson(result.ok ? 200 : 400, result);
|
|
9236
9296
|
}
|
|
9237
9297
|
/**
|
|
9238
9298
|
* `POST /wallets/register/respond` — the authenticated leg.
|
|
@@ -9397,30 +9457,6 @@ function parseRegistrationRequestDigestB64u(raw) {
|
|
|
9397
9457
|
return null;
|
|
9398
9458
|
}
|
|
9399
9459
|
}
|
|
9400
|
-
async function projectActivatedWallet(input) {
|
|
9401
|
-
const walletProjection = input.services.walletProjection || null;
|
|
9402
|
-
if (!walletProjection) return null;
|
|
9403
|
-
const verifier = input.services.session;
|
|
9404
|
-
if (!verifier) return "wallet projection requires setup verification";
|
|
9405
|
-
const verified = await verifyWalletRegistrationSetupClaims(verifier, input.signedSetup, {
|
|
9406
|
-
registrationCeremonyId: input.registrationCeremonyId,
|
|
9407
|
-
nowMs: Date.now()
|
|
9408
|
-
});
|
|
9409
|
-
if (!verified.ok) return verified.message;
|
|
9410
|
-
if (verified.claims.policy.kind !== "runtime_policy_scope") return "wallet projection requires an exact runtime policy scope";
|
|
9411
|
-
if (verified.claims.policy.scope.orgId !== verified.claims.orgId) return "wallet projection scope does not match its organization";
|
|
9412
|
-
try {
|
|
9413
|
-
await walletProjection.recordCreatedWallet({
|
|
9414
|
-
orgId: verified.claims.orgId,
|
|
9415
|
-
runtimePolicyScope: verified.claims.policy.scope,
|
|
9416
|
-
walletId: verified.claims.walletId,
|
|
9417
|
-
occurredAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
9418
|
-
});
|
|
9419
|
-
return null;
|
|
9420
|
-
} catch (error) {
|
|
9421
|
-
return error instanceof Error ? error.message : String(error);
|
|
9422
|
-
}
|
|
9423
|
-
}
|
|
9424
9460
|
/**
|
|
9425
9461
|
* `POST /wallets/register/activate` — activation and finalization behind
|
|
9426
9462
|
* one Gateway operation row.
|
|
@@ -9439,9 +9475,7 @@ async function handleRouterApiWalletRegistrationActivate(input) {
|
|
|
9439
9475
|
const idempotencyKey = String(body.idempotencyKey || "").trim();
|
|
9440
9476
|
if (!idempotencyKey) return routeError(400, "invalid_body", "idempotencyKey is required");
|
|
9441
9477
|
const planKind = String(body.kind || "").trim();
|
|
9442
|
-
if (planKind !== "evm_family_ecdsa" && planKind !== "near_ed25519_and_evm_family_ecdsa"
|
|
9443
|
-
const ed25519Only = planKind === "near_ed25519";
|
|
9444
|
-
if (ed25519Only && body.ecdsa !== void 0) return routeError(400, "invalid_body", "an Ed25519-only activate carries no ECDSA activation");
|
|
9478
|
+
if (planKind !== "evm_family_ecdsa" && planKind !== "near_ed25519_and_evm_family_ecdsa") return routeError(400, "invalid_body", "activation requires an ECDSA signer plan");
|
|
9445
9479
|
const ecdsa = isPlainObject(body.ecdsa) ? body.ecdsa : null;
|
|
9446
9480
|
const unknownEcdsaField = ecdsa ? findUnknownField(ecdsa, [
|
|
9447
9481
|
"activationCorrelationId",
|
|
@@ -9449,9 +9483,9 @@ async function handleRouterApiWalletRegistrationActivate(input) {
|
|
|
9449
9483
|
"clientActivation"
|
|
9450
9484
|
]) : null;
|
|
9451
9485
|
if (unknownEcdsaField) return routeError(400, "invalid_body", `wallet registration ECDSA activation field ${unknownEcdsaField} is unsupported`);
|
|
9452
|
-
if (!
|
|
9486
|
+
if (!ecdsa || typeof ecdsa.activationCorrelationId !== "string" || typeof ecdsa.activationRequestDigestB64u !== "string" || !isPlainObject(ecdsa.clientActivation)) return routeError(400, "invalid_body", "browser-verified clientActivation is required");
|
|
9453
9487
|
let parsedActivation;
|
|
9454
|
-
|
|
9488
|
+
try {
|
|
9455
9489
|
const parsed = parseRouterAbEcdsaRegistrationActivationRequestV1({
|
|
9456
9490
|
registrationCeremonyId,
|
|
9457
9491
|
ecdsa: {
|
|
@@ -9474,25 +9508,17 @@ async function handleRouterApiWalletRegistrationActivate(input) {
|
|
|
9474
9508
|
signedSetup,
|
|
9475
9509
|
idempotencyKey,
|
|
9476
9510
|
planKind,
|
|
9477
|
-
|
|
9511
|
+
ecdsa: parsedActivation,
|
|
9478
9512
|
...body.emailOtpEnrollment ? { emailOtpEnrollment: body.emailOtpEnrollment } : {},
|
|
9479
9513
|
...body.walletCustodyCommit !== void 0 ? { walletCustodyCommit: body.walletCustodyCommit } : {},
|
|
9480
9514
|
verifier: session
|
|
9481
9515
|
}, traceContext.value ?? void 0, serverTiming);
|
|
9482
9516
|
if (!result.ok) return routeJson(400, result);
|
|
9483
9517
|
if (!isEmailOtpWalletRegistrationActivateSuccessV2(result) && !isPasskeyWalletRegistrationActivateSuccessV2(result)) return routeError(500, "internal", "Wallet registration activation returned an invalid authority");
|
|
9484
|
-
const projectionError = await projectActivatedWallet({
|
|
9485
|
-
registrationCeremonyId,
|
|
9486
|
-
services: input.services,
|
|
9487
|
-
signedSetup
|
|
9488
|
-
});
|
|
9489
|
-
if (projectionError) return routeError(500, "internal", `Wallet was created but its Console projection failed: ${projectionError}`);
|
|
9490
9518
|
return routeJson(200, result, { headers: ecdsaGatewayServerTimingHeaders(serverTiming) });
|
|
9491
9519
|
}
|
|
9492
9520
|
/**
|
|
9493
|
-
*
|
|
9494
|
-
* the client calls after activate, once its already-running Yao computation
|
|
9495
|
-
* produces an activation.
|
|
9521
|
+
* Commits a NEAR-only wallet or completes a mixed wallet's deferred signer.
|
|
9496
9522
|
*/
|
|
9497
9523
|
async function handleRouterApiWalletRegistrationNearProvisioning(input) {
|
|
9498
9524
|
if (!isPlainObject(input.body)) return routeError(400, "invalid_body", "JSON body required");
|
|
@@ -9505,7 +9531,7 @@ async function handleRouterApiWalletRegistrationNearProvisioning(input) {
|
|
|
9505
9531
|
if (!registrationCeremonyId || !signedSetup || !idempotencyKey) return routeError(400, "invalid_body", "registrationCeremonyId, signedSetup and idempotencyKey are required");
|
|
9506
9532
|
const ed25519 = parseWalletRegistrationEd25519Finalize(body.ed25519);
|
|
9507
9533
|
if (!ed25519.ok) return routeError(400, ed25519.code, ed25519.message);
|
|
9508
|
-
const sessionSeal = parseRegistrationPreparedSessionSeal(body.sessionSeal);
|
|
9534
|
+
const sessionSeal = parseRegistrationPreparedSessionSeal(body.sessionSeal, input.signingSessionSeal?.service ?? null);
|
|
9509
9535
|
if (!sessionSeal.ok) return routeError(400, sessionSeal.code, sessionSeal.message);
|
|
9510
9536
|
const serverTiming = [];
|
|
9511
9537
|
const result = await input.services.walletRegistration.completeWalletRegistrationNearProvisioning({
|
|
@@ -9516,17 +9542,14 @@ async function handleRouterApiWalletRegistrationNearProvisioning(input) {
|
|
|
9516
9542
|
ed25519: ed25519.value,
|
|
9517
9543
|
emailOtpEnrollment: body.emailOtpEnrollment,
|
|
9518
9544
|
...body.walletCustodyCommit !== void 0 ? { walletCustodyCommit: body.walletCustodyCommit } : {},
|
|
9519
|
-
verifier: session
|
|
9520
|
-
|
|
9545
|
+
verifier: session,
|
|
9546
|
+
onSessionCommitted: sessionSeal.value?.prepare.bind(sessionSeal.value)
|
|
9547
|
+
}, serverTiming, input.waitUntil);
|
|
9521
9548
|
if (!result.ok) return routeJson(400, result);
|
|
9522
9549
|
if (sessionSeal.value) {
|
|
9523
9550
|
if (!isPasskeyWalletRegistrationNearProvisioningSuccessV2(result)) return routeError(400, "invalid_body", "Registration session sealing requires a passkey authority");
|
|
9524
9551
|
const sealStartedAt = Date.now();
|
|
9525
|
-
const sealed = await
|
|
9526
|
-
options: input.signingSessionSeal,
|
|
9527
|
-
request: sessionSeal.value,
|
|
9528
|
-
response: result
|
|
9529
|
-
});
|
|
9552
|
+
const sealed = await sessionSeal.value.finish(result.registrationEstablishedSession.session);
|
|
9530
9553
|
serverTiming.push(["near_finalize_session_seal", Math.max(0, Date.now() - sealStartedAt)]);
|
|
9531
9554
|
if (!sealed.ok) return routeJson(503, {
|
|
9532
9555
|
ok: false,
|
|
@@ -9540,83 +9563,6 @@ async function handleRouterApiWalletRegistrationNearProvisioning(input) {
|
|
|
9540
9563
|
}
|
|
9541
9564
|
return routeJson(200, result, { headers: ecdsaGatewayServerTimingHeaders(serverTiming) });
|
|
9542
9565
|
}
|
|
9543
|
-
function parseRegistrationPreparedSessionSeal(raw) {
|
|
9544
|
-
if (raw === void 0) return {
|
|
9545
|
-
ok: true,
|
|
9546
|
-
value: void 0
|
|
9547
|
-
};
|
|
9548
|
-
if (!isPlainObject(raw)) return {
|
|
9549
|
-
ok: false,
|
|
9550
|
-
code: "invalid_body",
|
|
9551
|
-
message: "sessionSeal must be an object"
|
|
9552
|
-
};
|
|
9553
|
-
if (Object.keys(raw).some((field) => ![
|
|
9554
|
-
"thresholdSessionId",
|
|
9555
|
-
"ciphertext",
|
|
9556
|
-
"keyVersion"
|
|
9557
|
-
].includes(field))) return {
|
|
9558
|
-
ok: false,
|
|
9559
|
-
code: "invalid_body",
|
|
9560
|
-
message: "sessionSeal has unknown fields"
|
|
9561
|
-
};
|
|
9562
|
-
const thresholdSessionId = String(raw.thresholdSessionId || "").trim();
|
|
9563
|
-
const ciphertext = String(raw.ciphertext || "").trim();
|
|
9564
|
-
const keyVersion = String(raw.keyVersion || "").trim();
|
|
9565
|
-
if (!thresholdSessionId || !ciphertext) return {
|
|
9566
|
-
ok: false,
|
|
9567
|
-
code: "invalid_body",
|
|
9568
|
-
message: "sessionSeal thresholdSessionId and ciphertext are required"
|
|
9569
|
-
};
|
|
9570
|
-
return {
|
|
9571
|
-
ok: true,
|
|
9572
|
-
value: {
|
|
9573
|
-
thresholdSessionId,
|
|
9574
|
-
ciphertext,
|
|
9575
|
-
...keyVersion ? { keyVersion } : {}
|
|
9576
|
-
}
|
|
9577
|
-
};
|
|
9578
|
-
}
|
|
9579
|
-
async function applyRegistrationPreparedSessionSeal(args) {
|
|
9580
|
-
if (!args.options) return {
|
|
9581
|
-
ok: false,
|
|
9582
|
-
code: "signing_session_seal_unavailable",
|
|
9583
|
-
message: "Signing-session sealing is unavailable"
|
|
9584
|
-
};
|
|
9585
|
-
const session = args.response.registrationEstablishedSession.session;
|
|
9586
|
-
const tokens = session.tokens;
|
|
9587
|
-
const ed25519 = tokens.kind === "near_ed25519" || tokens.kind === "near_ed25519_and_evm_family_ecdsa" ? tokens.ed25519 : null;
|
|
9588
|
-
if (!ed25519 || String(ed25519.thresholdSessionId) !== args.request.thresholdSessionId) return {
|
|
9589
|
-
ok: false,
|
|
9590
|
-
code: "invalid_session_seal",
|
|
9591
|
-
message: "Prepared seal does not match the established Ed25519 session"
|
|
9592
|
-
};
|
|
9593
|
-
const sealed = await args.options.service.applyServerSeal(args.request, {
|
|
9594
|
-
userId: String(session.walletId),
|
|
9595
|
-
session: {
|
|
9596
|
-
kind: "exact_wallet_session_operation_credential",
|
|
9597
|
-
curve: "ed25519",
|
|
9598
|
-
thresholdSessionId: args.request.thresholdSessionId,
|
|
9599
|
-
userId: String(session.walletId),
|
|
9600
|
-
expiresAtMs: session.expiresAtMs
|
|
9601
|
-
}
|
|
9602
|
-
});
|
|
9603
|
-
if (!sealed.ok) return sealed;
|
|
9604
|
-
const keyVersion = String(sealed.keyVersion || "").trim();
|
|
9605
|
-
if (!keyVersion) return {
|
|
9606
|
-
ok: false,
|
|
9607
|
-
code: "invalid_session_seal",
|
|
9608
|
-
message: "Signing-session seal response is missing its key version"
|
|
9609
|
-
};
|
|
9610
|
-
return {
|
|
9611
|
-
ok: true,
|
|
9612
|
-
value: {
|
|
9613
|
-
ciphertext: sealed.ciphertext,
|
|
9614
|
-
keyVersion,
|
|
9615
|
-
expiresAtMs: Math.min(sealed.expiresAtMs ?? session.expiresAtMs, session.expiresAtMs),
|
|
9616
|
-
remainingUses: session.remainingUses
|
|
9617
|
-
}
|
|
9618
|
-
};
|
|
9619
|
-
}
|
|
9620
9566
|
function ecdsaGatewayServerTimingHeaders(serverTiming) {
|
|
9621
9567
|
if (serverTiming.length === 0) return void 0;
|
|
9622
9568
|
const header = serverTiming.map(([name, durationMs]) => `${name};dur=${Math.max(0, durationMs).toFixed(1)}`).join(", ");
|
|
@@ -10233,7 +10179,6 @@ const ROUTER_API_ECDSA_STRICT_LIFECYCLE_SERVICES = [
|
|
|
10233
10179
|
"session"
|
|
10234
10180
|
];
|
|
10235
10181
|
const ROUTER_API_WEBAUTHN_AUTHENTICATOR_SERVICES = ["webAuthn", "session"];
|
|
10236
|
-
const ROUTER_API_NEAR_PUBLIC_KEY_SERVICES = ["nearFunding", "session"];
|
|
10237
10182
|
const ROUTER_API_PASSKEY_CUSTODY_SERVICES = [
|
|
10238
10183
|
"passkeyCustody",
|
|
10239
10184
|
"walletAuthMethods",
|
|
@@ -10600,7 +10545,7 @@ function createRouterApiRouteDefinitions(options = {}) {
|
|
|
10600
10545
|
}, ROUTER_API_ED25519_WALLET_SESSION_SERVICES), sessionPrincipalRoute("router_ab_ed25519_sign_prepare", "POST", ROUTER_AB_ED25519_NORMAL_SIGNING_PREPARE_PATH, "Prepare Router A/B Ed25519 normal signing", ROUTER_API_NORMAL_SIGNING_PROXY_SERVICES), sessionPrincipalRoute("router_ab_ed25519_sign_finalize", "POST", ROUTER_AB_ED25519_NORMAL_SIGNING_PATH, "Finalize Router A/B Ed25519 normal signing", ROUTER_API_NORMAL_SIGNING_PROXY_SERVICES), publicRoute("router_ab_ecdsa_derivation_healthz", "GET", ROUTER_AB_ECDSA_DERIVATION_HEALTH_PATH, "Router A/B ECDSA derivation health probe", {
|
|
10601
10546
|
plane: "public",
|
|
10602
10547
|
rationale: "Router A/B health probes are intentionally public diagnostics."
|
|
10603
|
-
}, ROUTER_API_THRESHOLD_RUNTIME_SERVICES), sessionPrincipalRoute("router_ab_ecdsa_derivation_export", "POST", ROUTER_AB_ECDSA_DERIVATION_EXPORT_PATH, "Export authorized Router A/B ECDSA derivation material", ROUTER_API_ECDSA_STRICT_LIFECYCLE_SERVICES), sessionPrincipalRoute("router_ab_ecdsa_derivation_refresh", "POST", ROUTER_AB_ECDSA_DERIVATION_REFRESH_PATH, "Refresh Router A/B ECDSA derivation activation", ROUTER_API_ECDSA_STRICT_LIFECYCLE_SERVICES), sessionPrincipalRoute("router_ab_ecdsa_derivation_session_activate", "POST", ROUTER_AB_ECDSA_DERIVATION_SESSION_ACTIVATION_PATH, "Activate Router A/B ECDSA normal-signing session", ROUTER_API_THRESHOLD_SESSION_SERVICES), sessionPrincipalRoute("router_ab_ecdsa_derivation_sign_prepare", "POST", ROUTER_AB_ECDSA_DERIVATION_NORMAL_SIGNING_PREPARE_PATH, "Prepare Router A/B ECDSA derivation normal signing", ROUTER_API_NORMAL_SIGNING_PROXY_SERVICES), sessionPrincipalRoute("router_ab_ecdsa_derivation_sign_finalize", "POST", ROUTER_AB_ECDSA_DERIVATION_NORMAL_SIGNING_PATH, "Finalize Router A/B ECDSA derivation normal signing", ROUTER_API_NORMAL_SIGNING_PROXY_SERVICES), sessionPrincipalRoute("router_ab_ecdsa_derivation_presignature_pool_fill_init", "POST", ROUTER_AB_ECDSA_DERIVATION_PRESIGNATURE_POOL_FILL_INIT_PATH, "Begin Router A/B ECDSA derivation presignature pool-fill session", ROUTER_API_THRESHOLD_SESSION_SERVICES), sessionPrincipalRoute("router_ab_ecdsa_derivation_presignature_pool_fill_step", "POST", ROUTER_AB_ECDSA_DERIVATION_PRESIGNATURE_POOL_FILL_STEP_PATH, "Continue Router A/B ECDSA derivation presignature pool-fill session", ROUTER_API_THRESHOLD_SESSION_SERVICES), sessionPrincipalRoute("webauthn_authenticators", "GET", "/webauthn/authenticators", "List registered WebAuthn authenticators", ROUTER_API_WEBAUTHN_AUTHENTICATOR_SERVICES),
|
|
10548
|
+
}, ROUTER_API_THRESHOLD_RUNTIME_SERVICES), sessionPrincipalRoute("router_ab_ecdsa_derivation_export", "POST", ROUTER_AB_ECDSA_DERIVATION_EXPORT_PATH, "Export authorized Router A/B ECDSA derivation material", ROUTER_API_ECDSA_STRICT_LIFECYCLE_SERVICES), sessionPrincipalRoute("router_ab_ecdsa_derivation_refresh", "POST", ROUTER_AB_ECDSA_DERIVATION_REFRESH_PATH, "Refresh Router A/B ECDSA derivation activation", ROUTER_API_ECDSA_STRICT_LIFECYCLE_SERVICES), sessionPrincipalRoute("router_ab_ecdsa_derivation_session_activate", "POST", ROUTER_AB_ECDSA_DERIVATION_SESSION_ACTIVATION_PATH, "Activate Router A/B ECDSA normal-signing session", ROUTER_API_THRESHOLD_SESSION_SERVICES), sessionPrincipalRoute("router_ab_ecdsa_derivation_sign_prepare", "POST", ROUTER_AB_ECDSA_DERIVATION_NORMAL_SIGNING_PREPARE_PATH, "Prepare Router A/B ECDSA derivation normal signing", ROUTER_API_NORMAL_SIGNING_PROXY_SERVICES), sessionPrincipalRoute("router_ab_ecdsa_derivation_sign_finalize", "POST", ROUTER_AB_ECDSA_DERIVATION_NORMAL_SIGNING_PATH, "Finalize Router A/B ECDSA derivation normal signing", ROUTER_API_NORMAL_SIGNING_PROXY_SERVICES), sessionPrincipalRoute("router_ab_ecdsa_derivation_presignature_pool_fill_init", "POST", ROUTER_AB_ECDSA_DERIVATION_PRESIGNATURE_POOL_FILL_INIT_PATH, "Begin Router A/B ECDSA derivation presignature pool-fill session", ROUTER_API_THRESHOLD_SESSION_SERVICES), sessionPrincipalRoute("router_ab_ecdsa_derivation_presignature_pool_fill_step", "POST", ROUTER_AB_ECDSA_DERIVATION_PRESIGNATURE_POOL_FILL_STEP_PATH, "Continue Router A/B ECDSA derivation presignature pool-fill session", ROUTER_API_THRESHOLD_SESSION_SERVICES), sessionPrincipalRoute("webauthn_authenticators", "GET", "/webauthn/authenticators", "List registered WebAuthn authenticators", ROUTER_API_WEBAUTHN_AUTHENTICATOR_SERVICES), publicRoute("wallet_unlock_challenge", "POST", "/wallet/unlock/challenge", "Create wallet unlock challenge", {
|
|
10604
10549
|
plane: "public",
|
|
10605
10550
|
proof: "challenge_exchange",
|
|
10606
10551
|
rationale: "Wallet unlock challenge issuance is intentionally public."
|
|
@@ -10680,6 +10625,7 @@ function resolveWalletRegistrationRoute(ctx) {
|
|
|
10680
10625
|
async function handleWalletRegistration(ctx) {
|
|
10681
10626
|
const route = resolveWalletRegistrationRoute(ctx);
|
|
10682
10627
|
if (!route) return null;
|
|
10628
|
+
if (ctx.request.headers.get("X-Seams-Wallet-Protocol") !== "3") return jsonFailure(409, "wallet_protocol_mismatch", "Your wallet application needs an update. Reload this page and try again. If the problem continues, ask the application developer to upgrade the Wallet SDK.");
|
|
10683
10629
|
const common = {
|
|
10684
10630
|
body: await readJson(ctx.request),
|
|
10685
10631
|
headers: Object.fromEntries(ctx.request.headers.entries()),
|
|
@@ -10699,10 +10645,11 @@ async function handleWalletRegistration(ctx) {
|
|
|
10699
10645
|
routerAbPublicKeyset: ctx.opts.routerAbPublicKeyset,
|
|
10700
10646
|
session: ctx.opts.session,
|
|
10701
10647
|
publishableKeyAuth: ctx.opts.publishableKeyAuth,
|
|
10702
|
-
|
|
10648
|
+
registrationContext: ctx.opts.registrationContext
|
|
10703
10649
|
},
|
|
10704
10650
|
sourceIp: resolveSourceIpFromFetchHeaders(ctx.request.headers) || void 0,
|
|
10705
|
-
signingSessionSeal: ctx.opts.signingSessionSeal
|
|
10651
|
+
signingSessionSeal: ctx.opts.signingSessionSeal,
|
|
10652
|
+
waitUntil: ctx.runtime.kind === "background" ? ctx.runtime.waitUntil : void 0
|
|
10706
10653
|
};
|
|
10707
10654
|
let response;
|
|
10708
10655
|
switch (route.id) {
|
|
@@ -11748,6 +11695,7 @@ async function handleWalletRecoveryPrepare(ctx) {
|
|
|
11748
11695
|
case "refused": return toFetchRouteResponse(refusedSpend());
|
|
11749
11696
|
case "reserved":
|
|
11750
11697
|
case "consumed": return routeErrorResponse(401, "recovery_code_used", "that recovery code has already been used");
|
|
11698
|
+
case "routing_unavailable": return routeErrorResponse(503, "wallet_home_unavailable", "Wallet recovery routing is temporarily unavailable");
|
|
11751
11699
|
case "manifest_unavailable":
|
|
11752
11700
|
case "registration_unavailable": return routeErrorResponse(409, "recovery_preparation_conflict", "wallet recovery could not be prepared");
|
|
11753
11701
|
}
|
|
@@ -12949,6 +12897,20 @@ async function handleWalletUnlockChallengeRoute(input) {
|
|
|
12949
12897
|
orgId: body.orgId,
|
|
12950
12898
|
ttlMs: body.ttlMs
|
|
12951
12899
|
});
|
|
12900
|
+
if (!result.ok && result.code === "wallet_home_unavailable") return {
|
|
12901
|
+
status: 503,
|
|
12902
|
+
body: {
|
|
12903
|
+
...result,
|
|
12904
|
+
unlockBackend
|
|
12905
|
+
}
|
|
12906
|
+
};
|
|
12907
|
+
if (!result.ok && result.code === "wallet_home_conflict") return {
|
|
12908
|
+
status: 409,
|
|
12909
|
+
body: {
|
|
12910
|
+
...result,
|
|
12911
|
+
unlockBackend
|
|
12912
|
+
}
|
|
12913
|
+
};
|
|
12952
12914
|
return {
|
|
12953
12915
|
status: result.ok ? 200 : result.code === "internal" ? 500 : 400,
|
|
12954
12916
|
body: {
|
|
@@ -13570,41 +13532,47 @@ function walletUnlockIssuanceRejectionStatus(rejection) {
|
|
|
13570
13532
|
}
|
|
13571
13533
|
}
|
|
13572
13534
|
//#endregion
|
|
13573
|
-
//#region
|
|
13574
|
-
|
|
13575
|
-
|
|
13576
|
-
|
|
13577
|
-
|
|
13578
|
-
|
|
13579
|
-
|
|
13580
|
-
|
|
13581
|
-
|
|
13582
|
-
|
|
13583
|
-
|
|
13584
|
-
|
|
13585
|
-
|
|
13586
|
-
|
|
13587
|
-
|
|
13588
|
-
|
|
13589
|
-
|
|
13590
|
-
|
|
13591
|
-
|
|
13592
|
-
|
|
13593
|
-
|
|
13594
|
-
|
|
13595
|
-
|
|
13596
|
-
|
|
13597
|
-
for (const parameter of parameters) {
|
|
13598
|
-
const [key, rawValue] = parameter.trim().split("=");
|
|
13599
|
-
if (key !== "dur" || !rawValue?.trim()) continue;
|
|
13600
|
-
const duration = Number(rawValue);
|
|
13601
|
-
if (Number.isFinite(duration) && duration >= 0) durations.set(name, duration);
|
|
13602
|
-
break;
|
|
13535
|
+
//#region src/router/domains/signingOperations/signingPrepareSession.ts
|
|
13536
|
+
/** The session snapshot validated for this admission, before its quota claim. */
|
|
13537
|
+
function signingPrepareSessionResponse(signing, authorization) {
|
|
13538
|
+
switch (authorization.kind) {
|
|
13539
|
+
case "operation_step_up": return {
|
|
13540
|
+
kind: "operation_step_up",
|
|
13541
|
+
signing
|
|
13542
|
+
};
|
|
13543
|
+
case "wallet_session_operation_credential_v1": {
|
|
13544
|
+
const { session, quota } = authorization.validated.admission.context.authorization;
|
|
13545
|
+
return {
|
|
13546
|
+
kind: "reusable_wallet_session",
|
|
13547
|
+
signing,
|
|
13548
|
+
session_status: {
|
|
13549
|
+
ok: true,
|
|
13550
|
+
status: "active",
|
|
13551
|
+
walletSessionId: session.walletSessionId,
|
|
13552
|
+
quotaId: session.quotaId,
|
|
13553
|
+
remainingUses: quota.remainingUses,
|
|
13554
|
+
expiresAtMs: quota.expiresAtMs,
|
|
13555
|
+
quotaLifecycle: "active",
|
|
13556
|
+
authorization: projectExactWalletSessionAuthorizationV1(session)
|
|
13557
|
+
}
|
|
13558
|
+
};
|
|
13603
13559
|
}
|
|
13560
|
+
case "wallet_session_operation_credential_exhausted_candidate_v1": throw new Error("An exhausted Wallet Session cannot publish a fresh prepare response");
|
|
13604
13561
|
}
|
|
13605
|
-
return durations;
|
|
13606
13562
|
}
|
|
13607
13563
|
//#endregion
|
|
13564
|
+
//#region ../shared-ts/src/utils/walletSessionFailure.ts
|
|
13565
|
+
const WALLET_SESSION_FAILURE_CODES = {
|
|
13566
|
+
missing: "wallet_session_missing",
|
|
13567
|
+
signatureInvalid: "wallet_session_signature_invalid",
|
|
13568
|
+
claimsInvalid: "wallet_session_claims_invalid",
|
|
13569
|
+
invalid: "wallet_session_invalid",
|
|
13570
|
+
expired: "wallet_session_expired",
|
|
13571
|
+
scopeMismatch: "wallet_session_scope_mismatch",
|
|
13572
|
+
unavailable: "wallet_session_unavailable",
|
|
13573
|
+
budgetExhausted: "wallet_budget_exhausted"
|
|
13574
|
+
};
|
|
13575
|
+
//#endregion
|
|
13608
13576
|
//#region src/router/domains/signingOperations/routerAbNormalSigningAdmission.ts
|
|
13609
13577
|
function routerAbOwnerOperationStepUpDecision(input) {
|
|
13610
13578
|
const reason = (() => {
|
|
@@ -13651,6 +13619,7 @@ async function evaluateRouterAbNormalSigningAdmission(input) {
|
|
|
13651
13619
|
};
|
|
13652
13620
|
if (input.curve === "ed25519") return await input.adapter.evaluatePolicy({
|
|
13653
13621
|
curve: "ed25519",
|
|
13622
|
+
policyReadSource: input.policyReadSource,
|
|
13654
13623
|
authorityKind: "wallet_authority_v1",
|
|
13655
13624
|
authorityId: input.authorityId,
|
|
13656
13625
|
phase: input.phase,
|
|
@@ -14018,18 +13987,6 @@ function routerAbOperationStepUpClaimFailure(result) {
|
|
|
14018
13987
|
}
|
|
14019
13988
|
}
|
|
14020
13989
|
//#endregion
|
|
14021
|
-
//#region ../shared-ts/src/utils/walletSessionFailure.ts
|
|
14022
|
-
const WALLET_SESSION_FAILURE_CODES = {
|
|
14023
|
-
missing: "wallet_session_missing",
|
|
14024
|
-
signatureInvalid: "wallet_session_signature_invalid",
|
|
14025
|
-
claimsInvalid: "wallet_session_claims_invalid",
|
|
14026
|
-
invalid: "wallet_session_invalid",
|
|
14027
|
-
expired: "wallet_session_expired",
|
|
14028
|
-
scopeMismatch: "wallet_session_scope_mismatch",
|
|
14029
|
-
unavailable: "wallet_session_unavailable",
|
|
14030
|
-
budgetExhausted: "wallet_budget_exhausted"
|
|
14031
|
-
};
|
|
14032
|
-
//#endregion
|
|
14033
13990
|
//#region src/core/ThresholdService/routerAb/internalServiceHttp.ts
|
|
14034
13991
|
const ROUTER_AB_INTERNAL_SERVICE_AUTH_HEADER_V1 = "x-router-ab-internal-service-auth";
|
|
14035
13992
|
function normalizeRouterAbInternalServiceAuthSecret(input) {
|
|
@@ -14382,7 +14339,7 @@ async function buildRouterAbEd25519PrivateSigningWorkerBody(input) {
|
|
|
14382
14339
|
const scope = parseRouterAbEd25519NormalSigningScopeV2(input.body.scope);
|
|
14383
14340
|
const signingContext = privateSigningAuthorizationContext(scope, input.authorization);
|
|
14384
14341
|
const trustedSourceDigest = await privateSigningTrustedSourceDigest(input.headers);
|
|
14385
|
-
const materialSource =
|
|
14342
|
+
const materialSource = registrationMaterialSourceV1({
|
|
14386
14343
|
accountId: scope.account_id,
|
|
14387
14344
|
materialActivationId: scope.material_activation.activation_id,
|
|
14388
14345
|
signingWorkerId: scope.signing_worker_id
|
|
@@ -15160,78 +15117,215 @@ async function authorizeRouterAbEcdsaDerivationNormalSigningRoute(input) {
|
|
|
15160
15117
|
};
|
|
15161
15118
|
}
|
|
15162
15119
|
//#endregion
|
|
15163
|
-
//#region src/router/domains/
|
|
15164
|
-
|
|
15165
|
-
|
|
15166
|
-
"
|
|
15167
|
-
|
|
15168
|
-
|
|
15169
|
-
|
|
15170
|
-
|
|
15171
|
-
|
|
15172
|
-
|
|
15173
|
-
|
|
15174
|
-
|
|
15175
|
-
|
|
15176
|
-
|
|
15177
|
-
|
|
15178
|
-
|
|
15179
|
-
|
|
15180
|
-
|
|
15181
|
-
"requestTag",
|
|
15182
|
-
"authorization",
|
|
15183
|
-
"operation"
|
|
15184
|
-
];
|
|
15185
|
-
const POOL_FILL_ENVELOPE_KEYS = [
|
|
15186
|
-
"kind",
|
|
15187
|
-
"scope",
|
|
15188
|
-
"ceremonyExpiresAtMs",
|
|
15189
|
-
"materialExpiresAtMs"
|
|
15190
|
-
];
|
|
15191
|
-
function parsePoolFillAuthorization(raw) {
|
|
15192
|
-
const authorization = parseRouterAbNormalSigningAuthorization(raw.authorization);
|
|
15193
|
-
switch (authorization.kind) {
|
|
15194
|
-
case "reusable_wallet_session":
|
|
15195
|
-
if (raw.operation !== void 0) throw new Error("Reusable Wallet Session pool fill must not carry operation");
|
|
15196
|
-
return { authorization };
|
|
15197
|
-
case "operation_step_up": return {
|
|
15198
|
-
authorization,
|
|
15199
|
-
operation: parseRouterAbEcdsaOperationStepUpPreparationV1(raw.operation)
|
|
15200
|
-
};
|
|
15201
|
-
}
|
|
15202
|
-
}
|
|
15203
|
-
function invalidThresholdEcdsaBody(message) {
|
|
15204
|
-
return {
|
|
15205
|
-
ok: false,
|
|
15206
|
-
body: {
|
|
15207
|
-
ok: false,
|
|
15208
|
-
code: "invalid_body",
|
|
15209
|
-
message
|
|
15120
|
+
//#region src/router/domains/signingOperations/ecdsaSigningResponse.ts
|
|
15121
|
+
async function finishRouterAbEcdsaSigningResponse(input) {
|
|
15122
|
+
const upstream = input.upstream;
|
|
15123
|
+
const upstreamBodyText = await upstream.clone().text().catch(() => "");
|
|
15124
|
+
input.timing.proxy = performance.now() - input.proxyStartedAt;
|
|
15125
|
+
if (isRouterAbEcdsaOperationInProgressResponse({
|
|
15126
|
+
status: upstream.status,
|
|
15127
|
+
bodyText: upstreamBodyText
|
|
15128
|
+
})) return upstream;
|
|
15129
|
+
const completionStartedAt = performance.now();
|
|
15130
|
+
await completeRouterAbEcdsaOperation({
|
|
15131
|
+
authorizedOperations: input.authorizedOperations,
|
|
15132
|
+
operation: input.operation,
|
|
15133
|
+
result: upstream.ok ? "succeeded" : upstream.status < 500 ? "failed_before_side_effect" : "failed_after_side_effect",
|
|
15134
|
+
response: {
|
|
15135
|
+
status: upstream.status,
|
|
15136
|
+
contentType: upstream.headers.get("content-type") || "application/json",
|
|
15137
|
+
bodyText: upstreamBodyText
|
|
15210
15138
|
}
|
|
15211
|
-
};
|
|
15212
|
-
|
|
15213
|
-
|
|
15214
|
-
for (const key of Object.keys(record)) if (!allowedKeys.includes(key)) return key;
|
|
15215
|
-
return null;
|
|
15216
|
-
}
|
|
15217
|
-
function optionalStringField$1(record, field) {
|
|
15218
|
-
const value = record[field];
|
|
15219
|
-
if (typeof value !== "string") return void 0;
|
|
15220
|
-
return value.trim() || void 0;
|
|
15221
|
-
}
|
|
15222
|
-
function isStringValue(value) {
|
|
15223
|
-
return typeof value === "string";
|
|
15139
|
+
});
|
|
15140
|
+
input.timing.complete = performance.now() - completionStartedAt;
|
|
15141
|
+
return upstream;
|
|
15224
15142
|
}
|
|
15225
|
-
function
|
|
15226
|
-
return
|
|
15143
|
+
function isRouterAbEcdsaOperationInProgressResponse(input) {
|
|
15144
|
+
return input.status === 409 && input.bodyText.includes("ReplayedLocalRequest:") && input.bodyText.includes("SigningWorker ECDSA effect is already in progress");
|
|
15227
15145
|
}
|
|
15228
|
-
|
|
15229
|
-
|
|
15230
|
-
|
|
15231
|
-
|
|
15232
|
-
|
|
15233
|
-
|
|
15234
|
-
|
|
15146
|
+
//#endregion
|
|
15147
|
+
//#region src/router/domains/signingOperations/authorizedOperationWire.ts
|
|
15148
|
+
function buildAuthorizedOperationWire(input, commonAuthorizedOperation) {
|
|
15149
|
+
const operation = input.operation;
|
|
15150
|
+
switch (input.binding.kind) {
|
|
15151
|
+
case "reusable_wallet_session":
|
|
15152
|
+
if (operation.authorization.kind !== "authorization_grant" || operation.quota.kind !== "consume_reusable_wallet_session") throw new Error("Reusable Wallet Session authorized operation is invalid");
|
|
15153
|
+
return {
|
|
15154
|
+
binding: {
|
|
15155
|
+
kind: "reusable_wallet_session",
|
|
15156
|
+
authorization_id: operation.authorization.authorizationGrantRef.authorizationId,
|
|
15157
|
+
wallet_session_id: input.binding.walletSessionId,
|
|
15158
|
+
quota_id: input.binding.quotaId
|
|
15159
|
+
},
|
|
15160
|
+
authorized_operation: {
|
|
15161
|
+
kind: "reusable_wallet_session_authorized_operation_v1",
|
|
15162
|
+
...commonAuthorizedOperation
|
|
15163
|
+
}
|
|
15164
|
+
};
|
|
15165
|
+
case "gateway_owner_wallet_session":
|
|
15166
|
+
if (operation.authorization.kind !== "authorization_grant" || operation.quota.kind !== "consume_reusable_wallet_session") throw new Error("Gateway owner Wallet Session authorized operation is invalid");
|
|
15167
|
+
return {
|
|
15168
|
+
binding: {
|
|
15169
|
+
kind: "gateway_owner_wallet_session",
|
|
15170
|
+
ownership_generation: input.binding.ownershipGeneration,
|
|
15171
|
+
subject_id: input.binding.subjectId,
|
|
15172
|
+
account_id: input.binding.accountId,
|
|
15173
|
+
authorization_id: input.binding.authorizationId,
|
|
15174
|
+
wallet_session_id: input.binding.walletSessionId,
|
|
15175
|
+
quota_id: input.binding.quotaId,
|
|
15176
|
+
threshold_session_id: input.binding.thresholdSessionId,
|
|
15177
|
+
org_id: input.binding.orgId,
|
|
15178
|
+
project_id: input.binding.projectId,
|
|
15179
|
+
environment: input.binding.environment,
|
|
15180
|
+
project_environment_id: input.binding.projectEnvironmentId,
|
|
15181
|
+
signing_worker_id: input.binding.signingWorkerId,
|
|
15182
|
+
expires_at_ms: input.binding.expiresAtMs
|
|
15183
|
+
},
|
|
15184
|
+
authorized_operation: {
|
|
15185
|
+
kind: "reusable_wallet_session_authorized_operation_v1",
|
|
15186
|
+
...commonAuthorizedOperation
|
|
15187
|
+
}
|
|
15188
|
+
};
|
|
15189
|
+
case "operation_step_up":
|
|
15190
|
+
if (operation.authorization.kind !== "verified_step_up" || operation.quota.kind !== "quota_neutral") throw new Error("Verified step-up authorized operation is invalid");
|
|
15191
|
+
return {
|
|
15192
|
+
binding: {
|
|
15193
|
+
kind: "operation_step_up",
|
|
15194
|
+
ownership_generation: input.binding.ownershipGeneration,
|
|
15195
|
+
authorization_session_id: input.binding.authorizationSessionId,
|
|
15196
|
+
org_id: input.binding.orgId,
|
|
15197
|
+
project_id: input.binding.projectId,
|
|
15198
|
+
environment: input.binding.environment,
|
|
15199
|
+
project_environment_id: input.binding.projectEnvironmentId,
|
|
15200
|
+
subject_id: input.binding.subjectId,
|
|
15201
|
+
account_id: input.binding.accountId
|
|
15202
|
+
},
|
|
15203
|
+
authorized_operation: {
|
|
15204
|
+
kind: "verified_step_up_authorized_operation_v1",
|
|
15205
|
+
authorization_session_id: input.binding.authorizationSessionId,
|
|
15206
|
+
evidence_set_digest: operation.authorization.evidenceSetDigest,
|
|
15207
|
+
...commonAuthorizedOperation
|
|
15208
|
+
}
|
|
15209
|
+
};
|
|
15210
|
+
default: return assertNeverOperationBinding(input.binding);
|
|
15211
|
+
}
|
|
15212
|
+
}
|
|
15213
|
+
function assertNeverOperationBinding(_binding) {
|
|
15214
|
+
throw new Error("Unsupported authorized-operation binding");
|
|
15215
|
+
}
|
|
15216
|
+
//#endregion
|
|
15217
|
+
//#region ../shared-ts/src/utils/ecdsaServerTiming.ts
|
|
15218
|
+
const ECDSA_TIMING_METRICS = new Set([
|
|
15219
|
+
"wallet_gateway_binding",
|
|
15220
|
+
"wallet_gateway_total",
|
|
15221
|
+
"wallet_console_binding_d1",
|
|
15222
|
+
"wallet_console_binding_sql",
|
|
15223
|
+
"ecdsa_sign_authorize",
|
|
15224
|
+
"ecdsa_sign_admit",
|
|
15225
|
+
"ecdsa_sign_proxy",
|
|
15226
|
+
"ecdsa_sign_complete",
|
|
15227
|
+
"ecdsa_sign_total",
|
|
15228
|
+
"ecdsa_presign_authenticate",
|
|
15229
|
+
"ecdsa_presign_material",
|
|
15230
|
+
"ecdsa_presign_admit",
|
|
15231
|
+
"ecdsa_presign_proxy",
|
|
15232
|
+
"ecdsa_presign_total",
|
|
15233
|
+
"ecdsa_presign_sw_material",
|
|
15234
|
+
"ecdsa_presign_sw_session",
|
|
15235
|
+
"ecdsa_presign_sw_do_response_headers",
|
|
15236
|
+
"ecdsa_presign_sw_do_response_body",
|
|
15237
|
+
"ecdsa_presign_sw_admit",
|
|
15238
|
+
"ecdsa_presign_sw_total"
|
|
15239
|
+
]);
|
|
15240
|
+
function parseEcdsaServerTiming(header) {
|
|
15241
|
+
const durations = /* @__PURE__ */ new Map();
|
|
15242
|
+
if (!header) return durations;
|
|
15243
|
+
for (const metric of header.split(",")) {
|
|
15244
|
+
const [name, ...parameters] = metric.trim().split(";");
|
|
15245
|
+
if (!ECDSA_TIMING_METRICS.has(name) || durations.has(name)) continue;
|
|
15246
|
+
for (const parameter of parameters) {
|
|
15247
|
+
const [key, rawValue] = parameter.trim().split("=");
|
|
15248
|
+
if (key !== "dur" || !rawValue?.trim()) continue;
|
|
15249
|
+
const duration = Number(rawValue);
|
|
15250
|
+
if (Number.isFinite(duration) && duration >= 0) durations.set(name, duration);
|
|
15251
|
+
break;
|
|
15252
|
+
}
|
|
15253
|
+
}
|
|
15254
|
+
return durations;
|
|
15255
|
+
}
|
|
15256
|
+
//#endregion
|
|
15257
|
+
//#region src/router/domains/ecdsa/thresholdEcdsaRequestValidation.ts
|
|
15258
|
+
const POOL_FILL_INIT_KEYS = [
|
|
15259
|
+
"presignSessionId",
|
|
15260
|
+
"firstMessageB64u",
|
|
15261
|
+
"keyHandle",
|
|
15262
|
+
"ecdsaThresholdKeyId",
|
|
15263
|
+
"count",
|
|
15264
|
+
"requestTag",
|
|
15265
|
+
"poolFill",
|
|
15266
|
+
"authorization",
|
|
15267
|
+
"operation"
|
|
15268
|
+
];
|
|
15269
|
+
const POOL_FILL_STEP_KEYS = [
|
|
15270
|
+
"presignSessionId",
|
|
15271
|
+
"ceremonyExpiresAtMs",
|
|
15272
|
+
"materialExpiresAtMs",
|
|
15273
|
+
"stage",
|
|
15274
|
+
"outgoingMessagesB64u",
|
|
15275
|
+
"requestTag",
|
|
15276
|
+
"authorization",
|
|
15277
|
+
"operation"
|
|
15278
|
+
];
|
|
15279
|
+
const POOL_FILL_ENVELOPE_KEYS = [
|
|
15280
|
+
"kind",
|
|
15281
|
+
"scope",
|
|
15282
|
+
"ceremonyExpiresAtMs",
|
|
15283
|
+
"materialExpiresAtMs"
|
|
15284
|
+
];
|
|
15285
|
+
function parsePoolFillAuthorization(raw) {
|
|
15286
|
+
const authorization = parseRouterAbNormalSigningAuthorization(raw.authorization);
|
|
15287
|
+
switch (authorization.kind) {
|
|
15288
|
+
case "reusable_wallet_session":
|
|
15289
|
+
if (raw.operation !== void 0) throw new Error("Reusable Wallet Session pool fill must not carry operation");
|
|
15290
|
+
return { authorization };
|
|
15291
|
+
case "operation_step_up": return {
|
|
15292
|
+
authorization,
|
|
15293
|
+
operation: parseRouterAbEcdsaOperationStepUpPreparationV1(raw.operation)
|
|
15294
|
+
};
|
|
15295
|
+
}
|
|
15296
|
+
}
|
|
15297
|
+
function invalidThresholdEcdsaBody(message) {
|
|
15298
|
+
return {
|
|
15299
|
+
ok: false,
|
|
15300
|
+
body: {
|
|
15301
|
+
ok: false,
|
|
15302
|
+
code: "invalid_body",
|
|
15303
|
+
message
|
|
15304
|
+
}
|
|
15305
|
+
};
|
|
15306
|
+
}
|
|
15307
|
+
function unexpectedThresholdEcdsaKey(record, allowedKeys) {
|
|
15308
|
+
for (const key of Object.keys(record)) if (!allowedKeys.includes(key)) return key;
|
|
15309
|
+
return null;
|
|
15310
|
+
}
|
|
15311
|
+
function optionalStringField$1(record, field) {
|
|
15312
|
+
const value = record[field];
|
|
15313
|
+
if (typeof value !== "string") return void 0;
|
|
15314
|
+
return value.trim() || void 0;
|
|
15315
|
+
}
|
|
15316
|
+
function isStringValue(value) {
|
|
15317
|
+
return typeof value === "string";
|
|
15318
|
+
}
|
|
15319
|
+
function hasNonStringValue(values) {
|
|
15320
|
+
return values.some((value) => !isStringValue(value));
|
|
15321
|
+
}
|
|
15322
|
+
function parseRouterAbEcdsaDerivationPoolFillInitRouteRequest(raw) {
|
|
15323
|
+
if (!isPlainObject(raw)) return invalidThresholdEcdsaBody("Expected JSON object body");
|
|
15324
|
+
const unexpectedKey = unexpectedThresholdEcdsaKey(raw, POOL_FILL_INIT_KEYS);
|
|
15325
|
+
if (unexpectedKey) return invalidThresholdEcdsaBody(`Unsupported threshold-ecdsa pool-fill init field: ${unexpectedKey}`);
|
|
15326
|
+
if (!isPlainObject(raw.poolFill)) return invalidThresholdEcdsaBody("poolFill is required");
|
|
15327
|
+
const unexpectedPoolFillKey = unexpectedThresholdEcdsaKey(raw.poolFill, POOL_FILL_ENVELOPE_KEYS);
|
|
15328
|
+
if (unexpectedPoolFillKey) return invalidThresholdEcdsaBody(`Unsupported threshold-ecdsa poolFill field: ${unexpectedPoolFillKey}`);
|
|
15235
15329
|
if (raw.poolFill.kind !== "router_ab_ecdsa_derivation_signing_worker_pool") return invalidThresholdEcdsaBody("poolFill.kind must be router_ab_ecdsa_derivation_signing_worker_pool");
|
|
15236
15330
|
const scope = parseRouterAbEcdsaDerivationNormalSigningScopeV1(raw.poolFill.scope);
|
|
15237
15331
|
if (!scope) return invalidThresholdEcdsaBody("poolFill.scope is invalid");
|
|
@@ -15296,6 +15390,164 @@ function parseRouterAbEcdsaDerivationPoolFillStepRouteRequest(raw) {
|
|
|
15296
15390
|
};
|
|
15297
15391
|
}
|
|
15298
15392
|
//#endregion
|
|
15393
|
+
//#region src/router/transport/fetch/routes/ecdsaOperationStepUpFactor.ts
|
|
15394
|
+
async function verifyEcdsaOperationStepUpFactor(input) {
|
|
15395
|
+
const proof = input.proof;
|
|
15396
|
+
switch (proof.kind) {
|
|
15397
|
+
case "passkey": {
|
|
15398
|
+
if (input.authSource.kind !== "passkey" || proof.authority.factor.credentialIdB64u !== input.authSource.credentialIdB64u) return {
|
|
15399
|
+
ok: false,
|
|
15400
|
+
response: json$1({
|
|
15401
|
+
ok: false,
|
|
15402
|
+
code: "scope_mismatch",
|
|
15403
|
+
message: "Passkey authority changed"
|
|
15404
|
+
}, { status: 403 })
|
|
15405
|
+
};
|
|
15406
|
+
const credential = proof.webauthn_authentication;
|
|
15407
|
+
if (String(credential.rawId || credential.id).trim() !== input.authSource.credentialIdB64u) return {
|
|
15408
|
+
ok: false,
|
|
15409
|
+
response: json$1({
|
|
15410
|
+
ok: false,
|
|
15411
|
+
code: "unauthorized",
|
|
15412
|
+
message: "Passkey credential changed"
|
|
15413
|
+
}, { status: 401 })
|
|
15414
|
+
};
|
|
15415
|
+
const verified = await input.webAuthn.verifyWebAuthnAuthenticationLite({
|
|
15416
|
+
userId: input.walletId,
|
|
15417
|
+
rpId: proof.authority.verifier.rpId,
|
|
15418
|
+
expectedChallenge: input.expectedChallenge,
|
|
15419
|
+
expected_origin: input.requestOrigin,
|
|
15420
|
+
webauthn_authentication: credential
|
|
15421
|
+
});
|
|
15422
|
+
if (!verified.success || !verified.verified) return {
|
|
15423
|
+
ok: false,
|
|
15424
|
+
response: json$1({
|
|
15425
|
+
ok: false,
|
|
15426
|
+
code: verified.code || "not_verified",
|
|
15427
|
+
message: verified.message || "WebAuthn authentication verification failed"
|
|
15428
|
+
}, { status: 401 })
|
|
15429
|
+
};
|
|
15430
|
+
const assertionDigest = parseDigestB64u(base64UrlEncode(await sha256BytesUtf8(alphabetizeStringify(credential))));
|
|
15431
|
+
const verifiedAtMs = Date.now();
|
|
15432
|
+
if (input.expiresAtMs <= verifiedAtMs) return expiredStepUpFactor();
|
|
15433
|
+
const factorId = parseAuthFactorId(`passkey:${input.authSource.credentialIdB64u}`);
|
|
15434
|
+
if (!factorId.ok) throw new Error(factorId.error.message);
|
|
15435
|
+
return {
|
|
15436
|
+
ok: true,
|
|
15437
|
+
factor: buildVerifiedWalletOperationPasskeyFactorResult({
|
|
15438
|
+
tenantId: input.operation.tenantId,
|
|
15439
|
+
principalId: input.operation.principalId,
|
|
15440
|
+
walletId: input.walletId,
|
|
15441
|
+
requestOrigin: input.requestOrigin,
|
|
15442
|
+
audience: input.requestOrigin,
|
|
15443
|
+
factorId: factorId.value,
|
|
15444
|
+
authorityRef: input.authorityRef,
|
|
15445
|
+
operation: input.operation,
|
|
15446
|
+
credentialIdB64u: proof.authority.factor.credentialIdB64u,
|
|
15447
|
+
assertionDigest,
|
|
15448
|
+
verifiedAtMs,
|
|
15449
|
+
expiresAtMs: input.expiresAtMs
|
|
15450
|
+
}),
|
|
15451
|
+
unseal: { kind: "not_requested" }
|
|
15452
|
+
};
|
|
15453
|
+
}
|
|
15454
|
+
case "email_otp": {
|
|
15455
|
+
const isExport = input.operation.operation.operationKind === "evm.export_key";
|
|
15456
|
+
const emailOtpOperation = isExport ? WALLET_EMAIL_OTP_EXPORT_OPERATION : WALLET_EMAIL_OTP_TRANSACTION_SIGN_OPERATION;
|
|
15457
|
+
const operationBinding = await hashEmailOtpOperationBinding({
|
|
15458
|
+
walletId: input.walletId,
|
|
15459
|
+
providerUserId: proof.authority.factor.providerUserId,
|
|
15460
|
+
orgId: input.operation.tenantId,
|
|
15461
|
+
operation: emailOtpOperation,
|
|
15462
|
+
requestOrigin: input.requestOrigin,
|
|
15463
|
+
audience: input.requestOrigin,
|
|
15464
|
+
authorityRef: input.authorityRef,
|
|
15465
|
+
...isExport ? {} : { operationFingerprintDigest: input.operation.digests.laneDigest }
|
|
15466
|
+
});
|
|
15467
|
+
const verified = await input.emailOtp.verifyEmailOtpChallenge({
|
|
15468
|
+
userId: proof.authority.factor.providerUserId,
|
|
15469
|
+
walletId: input.walletId,
|
|
15470
|
+
orgId: input.operation.tenantId,
|
|
15471
|
+
challengeId: proof.challenge_id,
|
|
15472
|
+
otpCode: proof.otp_code,
|
|
15473
|
+
otpChannel: EMAIL_OTP_CHANNEL,
|
|
15474
|
+
ownerProofBindingDigest: operationBinding,
|
|
15475
|
+
operation: emailOtpOperation
|
|
15476
|
+
});
|
|
15477
|
+
if (!verified.ok) return {
|
|
15478
|
+
ok: false,
|
|
15479
|
+
response: json$1(verified, { status: verified.code === "invalid_body" ? 400 : 401 })
|
|
15480
|
+
};
|
|
15481
|
+
let verifiedChallengeId = verified.challengeId;
|
|
15482
|
+
if (!isExport) {
|
|
15483
|
+
const orgId = parseOrgId(input.operation.tenantId);
|
|
15484
|
+
const providerSubject = parseProviderSubject(proof.authority.factor.providerUserId);
|
|
15485
|
+
if (!orgId.ok) throw new Error(orgId.error.message);
|
|
15486
|
+
if (!providerSubject.ok) throw new Error(providerSubject.error.message);
|
|
15487
|
+
const consumed = await input.emailOtp.consumeEmailOtpGrant({
|
|
15488
|
+
subject: {
|
|
15489
|
+
kind: "provider_identity",
|
|
15490
|
+
orgId: orgId.value,
|
|
15491
|
+
providerSubject: providerSubject.value,
|
|
15492
|
+
walletId: input.walletId
|
|
15493
|
+
},
|
|
15494
|
+
loginGrant: verified.loginGrant,
|
|
15495
|
+
otpChannel: EMAIL_OTP_CHANNEL
|
|
15496
|
+
});
|
|
15497
|
+
if (!consumed.ok) return {
|
|
15498
|
+
ok: false,
|
|
15499
|
+
response: json$1(consumed, { status: consumed.code === "invalid_body" ? 400 : 401 })
|
|
15500
|
+
};
|
|
15501
|
+
verifiedChallengeId = consumed.challengeId;
|
|
15502
|
+
}
|
|
15503
|
+
const verificationReceiptDigest = parseDigestB64u(base64UrlEncode(await sha256BytesUtf8(alphabetizeStringify({
|
|
15504
|
+
challengeId: verifiedChallengeId,
|
|
15505
|
+
operationFingerprint: input.expectedChallenge
|
|
15506
|
+
}))));
|
|
15507
|
+
const verifiedAtMs = Date.now();
|
|
15508
|
+
const expiresAtMs = Math.min(input.expiresAtMs, verified.grantExpiresAtMs);
|
|
15509
|
+
if (expiresAtMs <= verifiedAtMs) return expiredStepUpFactor();
|
|
15510
|
+
const factorId = parseAuthFactorId(`email_otp:${proof.authority.factor.provider}:${proof.authority.factor.providerUserId}`);
|
|
15511
|
+
const challengeId = parseEmailOtpChallengeId(verifiedChallengeId);
|
|
15512
|
+
if (!factorId.ok) throw new Error(factorId.error.message);
|
|
15513
|
+
if (!challengeId.ok) throw new Error(challengeId.error.message);
|
|
15514
|
+
return {
|
|
15515
|
+
ok: true,
|
|
15516
|
+
factor: buildVerifiedWalletOperationEmailOtpFactorResult({
|
|
15517
|
+
tenantId: input.operation.tenantId,
|
|
15518
|
+
principalId: input.operation.principalId,
|
|
15519
|
+
walletId: input.walletId,
|
|
15520
|
+
requestOrigin: input.requestOrigin,
|
|
15521
|
+
audience: input.requestOrigin,
|
|
15522
|
+
factorId: factorId.value,
|
|
15523
|
+
authorityRef: input.authorityRef,
|
|
15524
|
+
operation: input.operation,
|
|
15525
|
+
challengeId: challengeId.value,
|
|
15526
|
+
verificationReceiptDigest,
|
|
15527
|
+
verifiedAtMs,
|
|
15528
|
+
expiresAtMs
|
|
15529
|
+
}),
|
|
15530
|
+
unseal: isExport ? {
|
|
15531
|
+
kind: "email_otp_grant",
|
|
15532
|
+
grant: verified.loginGrant,
|
|
15533
|
+
challenge_id: verified.challengeId
|
|
15534
|
+
} : { kind: "not_requested" }
|
|
15535
|
+
};
|
|
15536
|
+
}
|
|
15537
|
+
default: throw new Error("Unsupported ECDSA operation step-up proof");
|
|
15538
|
+
}
|
|
15539
|
+
}
|
|
15540
|
+
function expiredStepUpFactor() {
|
|
15541
|
+
return {
|
|
15542
|
+
ok: false,
|
|
15543
|
+
response: json$1({
|
|
15544
|
+
ok: false,
|
|
15545
|
+
code: "verified_step_up_rejected",
|
|
15546
|
+
message: "Operation step-up authorization expired"
|
|
15547
|
+
}, { status: 403 })
|
|
15548
|
+
};
|
|
15549
|
+
}
|
|
15550
|
+
//#endregion
|
|
15299
15551
|
//#region ../shared-ts/src/signing-lanes/recordParsers.ts
|
|
15300
15552
|
const WALLET_KEY_COMMON_FIELDS = [
|
|
15301
15553
|
"kind",
|
|
@@ -15402,6 +15654,27 @@ function walletAuthorityForAuthMethod(authMethod, authSource) {
|
|
|
15402
15654
|
};
|
|
15403
15655
|
}
|
|
15404
15656
|
//#endregion
|
|
15657
|
+
//#region src/router/cloudflare/runtime/walletObjectAddresses.ts
|
|
15658
|
+
const WALLET_OBJECT_IDENTITY_HEADER = "x-seams-wallet-object-identity";
|
|
15659
|
+
function walletObjectIdentity(wallet, generation, tenant) {
|
|
15660
|
+
const parsed = parseWalletId(wallet);
|
|
15661
|
+
if (!parsed.ok || typeof generation !== "number" || !Number.isSafeInteger(generation) || generation < 1) throw new Error("Wallet object identity requires a wallet and ownership generation");
|
|
15662
|
+
return {
|
|
15663
|
+
walletId: parsed.value,
|
|
15664
|
+
ownershipGeneration: generation,
|
|
15665
|
+
orgId: tenantPart(tenant.orgId),
|
|
15666
|
+
projectId: tenantPart(tenant.projectId),
|
|
15667
|
+
envId: tenantPart(tenant.envId)
|
|
15668
|
+
};
|
|
15669
|
+
}
|
|
15670
|
+
function walletObjectIdentityHeaders(identity) {
|
|
15671
|
+
return { [WALLET_OBJECT_IDENTITY_HEADER]: JSON.stringify(identity) };
|
|
15672
|
+
}
|
|
15673
|
+
function tenantPart(value) {
|
|
15674
|
+
if (typeof value !== "string" || !value || value.trim() !== value) throw new Error("Wallet object tenant is invalid");
|
|
15675
|
+
return value;
|
|
15676
|
+
}
|
|
15677
|
+
//#endregion
|
|
15405
15678
|
//#region src/router/transport/fetch/routes/normalSigningRouterProxy.ts
|
|
15406
15679
|
async function proxyNormalSigningRequestToMpcRouter(input) {
|
|
15407
15680
|
const proxy = input.proxy;
|
|
@@ -15412,6 +15685,14 @@ async function proxyNormalSigningRequestToMpcRouter(input) {
|
|
|
15412
15685
|
}, { status: 501 });
|
|
15413
15686
|
try {
|
|
15414
15687
|
const headers = new Headers(input.request.headers);
|
|
15688
|
+
const envelope = input.body?.authorized_operation;
|
|
15689
|
+
if (!isPlainObject(envelope) || !isPlainObject(envelope.binding)) throw new Error("Signing requires an admitted wallet binding");
|
|
15690
|
+
const identity = walletObjectIdentity(envelope.binding.account_id, envelope.binding.ownership_generation, {
|
|
15691
|
+
orgId: envelope.binding.org_id,
|
|
15692
|
+
projectId: envelope.binding.project_id,
|
|
15693
|
+
envId: envelope.binding.project_environment_id
|
|
15694
|
+
});
|
|
15695
|
+
for (const [name, value] of Object.entries(walletObjectIdentityHeaders(identity))) headers.set(name, value);
|
|
15415
15696
|
if (input.body && parseNormalSigningSessionAdmission(input.body)) headers.delete("authorization");
|
|
15416
15697
|
headers.set(ROUTER_AB_INTERNAL_SERVICE_AUTH_HEADER_V1, normalizeRouterAbInternalServiceAuthSecret(proxy.internalServiceAuthSecret));
|
|
15417
15698
|
const request = input.targetPath ? new Request(new URL(input.targetPath, input.request.url), input.request) : input.request;
|
|
@@ -15453,7 +15734,7 @@ function isNormalSigningReusableBindingRecord(value) {
|
|
|
15453
15734
|
}
|
|
15454
15735
|
function isNormalSigningGatewayOwnerBindingRecord(value) {
|
|
15455
15736
|
if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
|
|
15456
|
-
return Object.keys(value).sort().join("|") === "account_id|authorization_id|environment|expires_at_ms|kind|org_id|project_environment_id|project_id|quota_id|signing_worker_id|subject_id|threshold_session_id|wallet_session_id";
|
|
15737
|
+
return Object.keys(value).sort().join("|") === "account_id|authorization_id|environment|expires_at_ms|kind|org_id|ownership_generation|project_environment_id|project_id|quota_id|signing_worker_id|subject_id|threshold_session_id|wallet_session_id";
|
|
15457
15738
|
}
|
|
15458
15739
|
function isNormalSigningReusableReceiptRecord(value) {
|
|
15459
15740
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
@@ -15462,7 +15743,7 @@ function isNormalSigningReusableBindingValues(record) {
|
|
|
15462
15743
|
return typeof record.authorization_id === "string" && record.authorization_id.trim().length > 0 && typeof record.wallet_session_id === "string" && record.wallet_session_id.trim().length > 0 && typeof record.quota_id === "string" && record.quota_id.trim().length > 0;
|
|
15463
15744
|
}
|
|
15464
15745
|
function isNormalSigningGatewayOwnerBindingValues(record) {
|
|
15465
|
-
return typeof record.subject_id === "string" && record.subject_id.trim().length > 0 && typeof record.account_id === "string" && record.account_id.trim().length > 0 && typeof record.authorization_id === "string" && record.authorization_id.trim().length > 0 && typeof record.wallet_session_id === "string" && record.wallet_session_id.trim().length > 0 && typeof record.quota_id === "string" && record.quota_id.trim().length > 0 && typeof record.threshold_session_id === "string" && record.threshold_session_id.trim().length > 0 && typeof record.org_id === "string" && record.org_id.trim().length > 0 && typeof record.project_id === "string" && record.project_id.trim().length > 0 && typeof record.environment === "string" && record.environment.trim().length > 0 && typeof record.project_environment_id === "string" && record.project_environment_id.trim().length > 0 && typeof record.signing_worker_id === "string" && record.signing_worker_id.trim().length > 0 && typeof record.expires_at_ms === "number" && Number.isSafeInteger(record.expires_at_ms) && record.expires_at_ms > 0;
|
|
15746
|
+
return record.kind === "gateway_owner_wallet_session" && typeof record.ownership_generation === "number" && Number.isSafeInteger(record.ownership_generation) && record.ownership_generation > 0 && typeof record.subject_id === "string" && record.subject_id.trim().length > 0 && typeof record.account_id === "string" && record.account_id.trim().length > 0 && typeof record.authorization_id === "string" && record.authorization_id.trim().length > 0 && typeof record.wallet_session_id === "string" && record.wallet_session_id.trim().length > 0 && typeof record.quota_id === "string" && record.quota_id.trim().length > 0 && typeof record.threshold_session_id === "string" && record.threshold_session_id.trim().length > 0 && typeof record.org_id === "string" && record.org_id.trim().length > 0 && typeof record.project_id === "string" && record.project_id.trim().length > 0 && typeof record.environment === "string" && record.environment.trim().length > 0 && typeof record.project_environment_id === "string" && record.project_environment_id.trim().length > 0 && typeof record.signing_worker_id === "string" && record.signing_worker_id.trim().length > 0 && typeof record.expires_at_ms === "number" && Number.isSafeInteger(record.expires_at_ms) && record.expires_at_ms > 0;
|
|
15466
15747
|
}
|
|
15467
15748
|
async function proxyOwnerLaneAdmittedNormalSigningRequest(input) {
|
|
15468
15749
|
const expectedMaterialActivation = routerAbMpcMaterialActivationRefFromWire(input.expectedMaterialActivation);
|
|
@@ -15527,6 +15808,7 @@ async function ecdsaOperationStepUpBinding(ctx, session, operation) {
|
|
|
15527
15808
|
const pinned = await readPinnedEcdsaStepUpWalletScope(ctx, session, operation);
|
|
15528
15809
|
return {
|
|
15529
15810
|
kind: "operation_step_up",
|
|
15811
|
+
ownershipGeneration: pinned.ownershipGeneration,
|
|
15530
15812
|
authorizationSessionId: session.sessionId,
|
|
15531
15813
|
orgId: scope.orgId,
|
|
15532
15814
|
projectId: scope.projectId,
|
|
@@ -15546,7 +15828,10 @@ async function readPinnedEcdsaStepUpWalletScope(ctx, session, operation) {
|
|
|
15546
15828
|
const scope = session.runtimePolicyScope;
|
|
15547
15829
|
if (pinned.orgId !== scope.orgId || pinned.projectId !== scope.projectId) throw new Error("Step-up wallet scope differs from the Wallet Session scope");
|
|
15548
15830
|
return {
|
|
15549
|
-
|
|
15831
|
+
orgId: pinned.orgId,
|
|
15832
|
+
projectId: pinned.projectId,
|
|
15833
|
+
projectEnvironmentId: pinned.projectEnvironmentId,
|
|
15834
|
+
ownershipGeneration: pinned.ownershipGeneration,
|
|
15550
15835
|
walletId: session.walletId
|
|
15551
15836
|
};
|
|
15552
15837
|
}
|
|
@@ -15554,7 +15839,7 @@ function buildRouterAbEcdsaAuthorizedOperationWire(input) {
|
|
|
15554
15839
|
const operation = input.operation;
|
|
15555
15840
|
const operationRef = operation.operation.operation;
|
|
15556
15841
|
if (operationRef.capabilityKind !== "evm_ecdsa_mpc_signing" || operationRef.operationKind !== "evm.sign_transaction") throw new Error("ECDSA authorized operation capability or operation kind is invalid");
|
|
15557
|
-
|
|
15842
|
+
return buildAuthorizedOperationWire(input, {
|
|
15558
15843
|
authorized_operation_id: operation.authorizedOperationId,
|
|
15559
15844
|
operation_id: operation.operation.operationId,
|
|
15560
15845
|
capability_kind: "evm_ecdsa_mpc_signing",
|
|
@@ -15563,66 +15848,7 @@ function buildRouterAbEcdsaAuthorizedOperationWire(input) {
|
|
|
15563
15848
|
intent_digest_b64u: operation.operation.digests.intentDigest,
|
|
15564
15849
|
display_digest_b64u: operation.operation.digests.displayDigest,
|
|
15565
15850
|
operation_fingerprint_digest: operation.operationFingerprintDigest
|
|
15566
|
-
};
|
|
15567
|
-
switch (input.binding.kind) {
|
|
15568
|
-
case "reusable_wallet_session":
|
|
15569
|
-
if (operation.authorization.kind !== "authorization_grant" || operation.quota.kind !== "consume_reusable_wallet_session") throw new Error("Reusable Wallet Session authorized operation is invalid");
|
|
15570
|
-
return {
|
|
15571
|
-
binding: {
|
|
15572
|
-
kind: "reusable_wallet_session",
|
|
15573
|
-
authorization_id: operation.authorization.authorizationGrantRef.authorizationId,
|
|
15574
|
-
wallet_session_id: input.binding.walletSessionId,
|
|
15575
|
-
quota_id: input.binding.quotaId
|
|
15576
|
-
},
|
|
15577
|
-
authorized_operation: {
|
|
15578
|
-
kind: "reusable_wallet_session_authorized_operation_v1",
|
|
15579
|
-
...commonAuthorizedOperation
|
|
15580
|
-
}
|
|
15581
|
-
};
|
|
15582
|
-
case "gateway_owner_wallet_session":
|
|
15583
|
-
if (operation.authorization.kind !== "authorization_grant" || operation.quota.kind !== "consume_reusable_wallet_session") throw new Error("Gateway owner Wallet Session authorized operation is invalid");
|
|
15584
|
-
return {
|
|
15585
|
-
binding: {
|
|
15586
|
-
kind: "gateway_owner_wallet_session",
|
|
15587
|
-
subject_id: input.binding.subjectId,
|
|
15588
|
-
account_id: input.binding.accountId,
|
|
15589
|
-
authorization_id: input.binding.authorizationId,
|
|
15590
|
-
wallet_session_id: input.binding.walletSessionId,
|
|
15591
|
-
quota_id: input.binding.quotaId,
|
|
15592
|
-
threshold_session_id: input.binding.thresholdSessionId,
|
|
15593
|
-
org_id: input.binding.orgId,
|
|
15594
|
-
project_id: input.binding.projectId,
|
|
15595
|
-
environment: input.binding.environment,
|
|
15596
|
-
project_environment_id: input.binding.projectEnvironmentId,
|
|
15597
|
-
signing_worker_id: input.binding.signingWorkerId,
|
|
15598
|
-
expires_at_ms: input.binding.expiresAtMs
|
|
15599
|
-
},
|
|
15600
|
-
authorized_operation: {
|
|
15601
|
-
kind: "reusable_wallet_session_authorized_operation_v1",
|
|
15602
|
-
...commonAuthorizedOperation
|
|
15603
|
-
}
|
|
15604
|
-
};
|
|
15605
|
-
case "operation_step_up":
|
|
15606
|
-
if (operation.authorization.kind !== "verified_step_up" || operation.quota.kind !== "quota_neutral") throw new Error("Verified step-up authorized operation is invalid");
|
|
15607
|
-
return {
|
|
15608
|
-
binding: {
|
|
15609
|
-
kind: "operation_step_up",
|
|
15610
|
-
authorization_session_id: input.binding.authorizationSessionId,
|
|
15611
|
-
org_id: input.binding.orgId,
|
|
15612
|
-
project_id: input.binding.projectId,
|
|
15613
|
-
environment: input.binding.environment,
|
|
15614
|
-
project_environment_id: input.binding.projectEnvironmentId,
|
|
15615
|
-
subject_id: input.binding.subjectId,
|
|
15616
|
-
account_id: input.binding.accountId
|
|
15617
|
-
},
|
|
15618
|
-
authorized_operation: {
|
|
15619
|
-
kind: "verified_step_up_authorized_operation_v1",
|
|
15620
|
-
authorization_session_id: input.binding.authorizationSessionId,
|
|
15621
|
-
evidence_set_digest: operation.authorization.evidenceSetDigest,
|
|
15622
|
-
...commonAuthorizedOperation
|
|
15623
|
-
}
|
|
15624
|
-
};
|
|
15625
|
-
}
|
|
15851
|
+
});
|
|
15626
15852
|
}
|
|
15627
15853
|
function decideRouterAbEcdsaOperationStepUpExecution(input) {
|
|
15628
15854
|
if (input.admissionKind === "replayed") return {
|
|
@@ -15777,6 +16003,7 @@ async function executeRouterAbEcdsaDerivationNormalSigningRoute(input, timing) {
|
|
|
15777
16003
|
operation: authorizedOperation,
|
|
15778
16004
|
binding: {
|
|
15779
16005
|
kind: "gateway_owner_wallet_session",
|
|
16006
|
+
ownershipGeneration: pinnedOwnerScope.ownershipGeneration,
|
|
15780
16007
|
subjectId: String(session.principalId),
|
|
15781
16008
|
accountId: String(session.walletId),
|
|
15782
16009
|
authorizationId: String(session.authorizationId),
|
|
@@ -15823,8 +16050,18 @@ async function executeRouterAbEcdsaDerivationNormalSigningRoute(input, timing) {
|
|
|
15823
16050
|
walletRegistration: input.ctx.service.walletRegistration,
|
|
15824
16051
|
body: admittedBody
|
|
15825
16052
|
});
|
|
16053
|
+
if (input.phase === "prepare" && upstream.ok) {
|
|
16054
|
+
const body = signingPrepareSessionResponse(await upstream.json(), authorization);
|
|
16055
|
+
timing.proxy = performance.now() - proxyStartedAt;
|
|
16056
|
+
const headers = new Headers(upstream.headers);
|
|
16057
|
+
headers.delete("content-length");
|
|
16058
|
+
headers.delete("content-encoding");
|
|
16059
|
+
return new Response(JSON.stringify(body), {
|
|
16060
|
+
status: upstream.status,
|
|
16061
|
+
headers
|
|
16062
|
+
});
|
|
16063
|
+
}
|
|
15826
16064
|
return finishRouterAbEcdsaSigningResponse({
|
|
15827
|
-
phase: input.phase,
|
|
15828
16065
|
upstream,
|
|
15829
16066
|
operation: authorizedOperation,
|
|
15830
16067
|
authorizedOperations: input.ctx.service.authorizedOperations,
|
|
@@ -15832,35 +16069,6 @@ async function executeRouterAbEcdsaDerivationNormalSigningRoute(input, timing) {
|
|
|
15832
16069
|
proxyStartedAt
|
|
15833
16070
|
});
|
|
15834
16071
|
}
|
|
15835
|
-
async function finishRouterAbEcdsaSigningResponse(input) {
|
|
15836
|
-
const upstream = input.upstream;
|
|
15837
|
-
if (input.phase === "prepare" && upstream.ok) {
|
|
15838
|
-
input.timing.proxy = performance.now() - input.proxyStartedAt;
|
|
15839
|
-
return upstream;
|
|
15840
|
-
}
|
|
15841
|
-
const upstreamBodyText = await upstream.clone().text().catch(() => "");
|
|
15842
|
-
input.timing.proxy = performance.now() - input.proxyStartedAt;
|
|
15843
|
-
if (isRouterAbEcdsaOperationInProgressResponse({
|
|
15844
|
-
status: upstream.status,
|
|
15845
|
-
bodyText: upstreamBodyText
|
|
15846
|
-
})) return upstream;
|
|
15847
|
-
const completionStartedAt = performance.now();
|
|
15848
|
-
await completeRouterAbEcdsaOperation({
|
|
15849
|
-
authorizedOperations: input.authorizedOperations,
|
|
15850
|
-
operation: input.operation,
|
|
15851
|
-
result: upstream.ok ? "succeeded" : upstream.status < 500 ? "failed_before_side_effect" : "failed_after_side_effect",
|
|
15852
|
-
response: {
|
|
15853
|
-
status: upstream.status,
|
|
15854
|
-
contentType: upstream.headers.get("content-type") || "application/json",
|
|
15855
|
-
bodyText: upstreamBodyText
|
|
15856
|
-
}
|
|
15857
|
-
});
|
|
15858
|
-
input.timing.complete = performance.now() - completionStartedAt;
|
|
15859
|
-
return upstream;
|
|
15860
|
-
}
|
|
15861
|
-
function isRouterAbEcdsaOperationInProgressResponse(input) {
|
|
15862
|
-
return input.status === 409 && input.bodyText.includes("ReplayedLocalRequest:") && input.bodyText.includes("SigningWorker ECDSA effect is already in progress");
|
|
15863
|
-
}
|
|
15864
16072
|
function routerAbEcdsaReplayResponse(operation) {
|
|
15865
16073
|
const response = routerAbEcdsaReplayHttpResponse(operation);
|
|
15866
16074
|
if (response) return response;
|
|
@@ -15870,31 +16078,40 @@ function routerAbEcdsaReplayResponse(operation) {
|
|
|
15870
16078
|
async function resolveV2EcdsaOperationStepUpAdmission(input) {
|
|
15871
16079
|
const token = extractBearerCredential(input.ctx.request.headers);
|
|
15872
16080
|
if (!token) return { kind: "not_found" };
|
|
15873
|
-
let
|
|
16081
|
+
let context;
|
|
15874
16082
|
try {
|
|
15875
|
-
|
|
15876
|
-
|
|
16083
|
+
context = await input.ctx.service.authorizationSessions.readWalletSessionExactOperationContextByCredential({
|
|
16084
|
+
tenantId: input.ctx.service.authorizationSessions.tenantId,
|
|
15877
16085
|
token,
|
|
15878
|
-
nowMs: Date.now()
|
|
15879
|
-
operation: {
|
|
15880
|
-
keyFamily: "ecdsa_secp256k1",
|
|
15881
|
-
operationKind: input.operation.operation_kind
|
|
15882
|
-
}
|
|
16086
|
+
nowMs: Date.now()
|
|
15883
16087
|
});
|
|
15884
16088
|
} catch {
|
|
15885
16089
|
return { kind: "unavailable" };
|
|
15886
16090
|
}
|
|
15887
|
-
if (
|
|
15888
|
-
if (resolution.kind === "rejected") return {
|
|
16091
|
+
if (!context) return {
|
|
15889
16092
|
kind: "rejected",
|
|
15890
|
-
message: "ECDSA operation step-up Wallet Session
|
|
16093
|
+
message: "ECDSA operation step-up Wallet Session is unavailable"
|
|
15891
16094
|
};
|
|
15892
|
-
|
|
16095
|
+
const session = context.session;
|
|
16096
|
+
const admission = resolveWalletSessionAuthorizationV2Admission({
|
|
16097
|
+
authorization: session,
|
|
16098
|
+
authority: context.authority,
|
|
16099
|
+
authMethod: context.authMethod,
|
|
16100
|
+
retiredAtMs: context.retiredAtMs,
|
|
16101
|
+
nowMs: Date.now(),
|
|
16102
|
+
operation: {
|
|
16103
|
+
tenantId: session.tenantId,
|
|
16104
|
+
principalId: session.principalId,
|
|
16105
|
+
walletId: session.walletId,
|
|
16106
|
+
keyFamily: "ecdsa_secp256k1",
|
|
16107
|
+
operationKind: input.operation.operation_kind
|
|
16108
|
+
}
|
|
16109
|
+
});
|
|
16110
|
+
if (!admission.ok || admission.keyFamily !== "ecdsa_secp256k1") return {
|
|
15893
16111
|
kind: "rejected",
|
|
15894
|
-
message: "ECDSA operation step-up Wallet Session
|
|
16112
|
+
message: "ECDSA operation step-up Wallet Session authorization is invalid"
|
|
15895
16113
|
};
|
|
15896
|
-
const
|
|
15897
|
-
const admittedSigner = resolution.admission.admission.signer;
|
|
16114
|
+
const admittedSigner = admission.signer;
|
|
15898
16115
|
if (input.operation.wallet_id !== String(session.walletId) || input.operation.material_activation.material_owner !== String(session.walletId) || input.operation.expires_at_ms > session.expiresAtMs || input.operation.expires_at_ms <= Date.now()) return {
|
|
15899
16116
|
kind: "rejected",
|
|
15900
16117
|
message: "ECDSA operation step-up Wallet Session scope is invalid"
|
|
@@ -15910,13 +16127,13 @@ async function resolveV2EcdsaOperationStepUpAdmission(input) {
|
|
|
15910
16127
|
kind: "rejected",
|
|
15911
16128
|
message: "ECDSA operation step-up material is not uniquely active"
|
|
15912
16129
|
};
|
|
15913
|
-
if (input.operation.signing_worker_id !== input.operation.normal_signing_scope.signing_worker.server_id || !sameRouterAbMpcMaterialActivationRef(input.operation.material_activation, input.operation.normal_signing_scope.material_activation) || !sameRouterAbMpcMaterialActivationRef(input.operation.material_activation, routerAbMpcMaterialActivationRefToWire(
|
|
16130
|
+
if (input.operation.signing_worker_id !== input.operation.normal_signing_scope.signing_worker.server_id || !sameRouterAbMpcMaterialActivationRef(input.operation.material_activation, input.operation.normal_signing_scope.material_activation) || !sameRouterAbMpcMaterialActivationRef(input.operation.material_activation, routerAbMpcMaterialActivationRefToWire(admission.materialActivation))) return {
|
|
15914
16131
|
kind: "rejected",
|
|
15915
16132
|
message: "ECDSA operation step-up material activation is invalid"
|
|
15916
16133
|
};
|
|
15917
16134
|
const activeMaterial = {
|
|
15918
16135
|
ok: true,
|
|
15919
|
-
materialActivation: routerAbMpcMaterialActivationRefToWire(
|
|
16136
|
+
materialActivation: routerAbMpcMaterialActivationRefToWire(admission.materialActivation),
|
|
15920
16137
|
keyHandle: signer.walletKey.keyHandle,
|
|
15921
16138
|
relayerKeyId: signer.walletKey.relayerKeyId,
|
|
15922
16139
|
participantIds: signer.walletKey.participantIds,
|
|
@@ -15925,13 +16142,13 @@ async function resolveV2EcdsaOperationStepUpAdmission(input) {
|
|
|
15925
16142
|
if (input.operation.operation_kind === "evm.sign_transaction") return {
|
|
15926
16143
|
kind: "admitted",
|
|
15927
16144
|
operationKind: "evm.sign_transaction",
|
|
15928
|
-
|
|
16145
|
+
context,
|
|
15929
16146
|
activeMaterial
|
|
15930
16147
|
};
|
|
15931
16148
|
return {
|
|
15932
16149
|
kind: "admitted",
|
|
15933
16150
|
operationKind: "evm.export_key",
|
|
15934
|
-
|
|
16151
|
+
context,
|
|
15935
16152
|
activeMaterial,
|
|
15936
16153
|
exportTopology: {
|
|
15937
16154
|
signer_set: signer.walletKey.publicCapability.signer_set,
|
|
@@ -15991,8 +16208,8 @@ async function issueEcdsaOperationStepUpAuthorization(input) {
|
|
|
15991
16208
|
let v2AuthorityRef;
|
|
15992
16209
|
if (v2Resolution.kind === "admitted") {
|
|
15993
16210
|
v2AuthorityRef = await walletAuthAuthorityRef({ authority });
|
|
15994
|
-
const session = v2Resolution.
|
|
15995
|
-
const context = v2Resolution.
|
|
16211
|
+
const session = v2Resolution.context.session;
|
|
16212
|
+
const context = v2Resolution.context;
|
|
15996
16213
|
if (authority.walletId !== String(session.walletId) || authority.bindingId !== context.authMethod.walletAuthMethodId || context.authMethod.walletAuthorityId !== context.authority.authorityId) return json$1({
|
|
15997
16214
|
ok: false,
|
|
15998
16215
|
code: "scope_mismatch",
|
|
@@ -16020,10 +16237,10 @@ async function issueEcdsaOperationStepUpAuthorization(input) {
|
|
|
16020
16237
|
ok: true,
|
|
16021
16238
|
authorizedOperations: proofAuthenticated.authorizedOperations,
|
|
16022
16239
|
session: {
|
|
16023
|
-
tenantId: v2Resolution.
|
|
16024
|
-
principalId: v2Resolution.
|
|
16025
|
-
sessionId: String(v2Resolution.
|
|
16026
|
-
walletId: String(v2Resolution.
|
|
16240
|
+
tenantId: v2Resolution.context.session.tenantId,
|
|
16241
|
+
principalId: v2Resolution.context.session.principalId,
|
|
16242
|
+
sessionId: String(v2Resolution.context.session.authorizationId),
|
|
16243
|
+
walletId: String(v2Resolution.context.session.walletId),
|
|
16027
16244
|
runtimePolicyScope: activeMaterial.runtimePolicyScope,
|
|
16028
16245
|
laneAuthorization: {
|
|
16029
16246
|
kind: "authority_ref",
|
|
@@ -16057,7 +16274,6 @@ async function issueEcdsaOperationStepUpAuthorization(input) {
|
|
|
16057
16274
|
}, { status: 400 });
|
|
16058
16275
|
}
|
|
16059
16276
|
const expectedChallenge = await computeRouterAbEcdsaOperationStepUpChallengeB64u(operation);
|
|
16060
|
-
const nowMs = Date.now();
|
|
16061
16277
|
const requestId = operation.operation_id;
|
|
16062
16278
|
let freshMaterial;
|
|
16063
16279
|
if (v2Resolution.kind === "admitted") {
|
|
@@ -16070,7 +16286,7 @@ async function issueEcdsaOperationStepUpAuthorization(input) {
|
|
|
16070
16286
|
code: "wallet_session_unavailable",
|
|
16071
16287
|
message: "Wallet Session authorization is unavailable"
|
|
16072
16288
|
}, { status: 503 });
|
|
16073
|
-
if (refreshedV2Resolution.kind !== "admitted" || !
|
|
16289
|
+
if (refreshedV2Resolution.kind !== "admitted" || !walletSessionAuthorizationV2RecordsEqual(v2Resolution.context.session, refreshedV2Resolution.context.session)) return json$1({
|
|
16074
16290
|
ok: false,
|
|
16075
16291
|
code: "scope_mismatch",
|
|
16076
16292
|
message: "ECDSA operation step-up Wallet Session authorization changed"
|
|
@@ -16098,112 +16314,24 @@ async function issueEcdsaOperationStepUpAuthorization(input) {
|
|
|
16098
16314
|
const evidenceSetId = requireAuthorizationValue$1(parseAuthorizationEvidenceSetId(`ecdsa-step-up-evidence-set:${requestId}`));
|
|
16099
16315
|
const expiresAtMs = operation.expires_at_ms;
|
|
16100
16316
|
const requestOrigin = authenticated.requestOrigin;
|
|
16101
|
-
|
|
16102
|
-
|
|
16103
|
-
|
|
16104
|
-
|
|
16105
|
-
|
|
16106
|
-
|
|
16107
|
-
|
|
16108
|
-
|
|
16109
|
-
|
|
16110
|
-
|
|
16111
|
-
|
|
16112
|
-
|
|
16113
|
-
|
|
16114
|
-
message: "Passkey credential changed"
|
|
16115
|
-
}, { status: 401 });
|
|
16116
|
-
const verified = await input.ctx.service.webAuthn.verifyWebAuthnAuthenticationLite({
|
|
16117
|
-
userId: authenticated.session.walletId,
|
|
16118
|
-
rpId: proof.authority.verifier.rpId,
|
|
16119
|
-
expectedChallenge,
|
|
16120
|
-
expected_origin: requestOrigin,
|
|
16121
|
-
webauthn_authentication: credential
|
|
16122
|
-
});
|
|
16123
|
-
if (!verified.success || !verified.verified) return json$1({
|
|
16124
|
-
ok: false,
|
|
16125
|
-
code: verified.code || "not_verified",
|
|
16126
|
-
message: verified.message || "WebAuthn authentication verification failed"
|
|
16127
|
-
}, { status: 401 });
|
|
16128
|
-
factor = buildVerifiedWalletOperationPasskeyFactorResult({
|
|
16129
|
-
tenantId: authenticated.session.tenantId,
|
|
16130
|
-
principalId: authenticated.session.principalId,
|
|
16131
|
-
walletId: walletIdFromString(authenticated.session.walletId),
|
|
16132
|
-
requestOrigin,
|
|
16133
|
-
audience: requestOrigin,
|
|
16134
|
-
factorId: requireAuthorizationValue$1(parseAuthFactorId(`passkey:${authenticated.session.laneAuthorization.authSource.credentialIdB64u}`)),
|
|
16135
|
-
authorityRef: authenticated.authorityRef,
|
|
16136
|
-
operation: envelope,
|
|
16137
|
-
credentialIdB64u: proof.authority.factor.credentialIdB64u,
|
|
16138
|
-
assertionDigest: parseDigestB64u(base64UrlEncode(await sha256BytesUtf8(alphabetizeStringify(credential)))),
|
|
16139
|
-
verifiedAtMs: nowMs,
|
|
16140
|
-
expiresAtMs
|
|
16141
|
-
});
|
|
16142
|
-
break;
|
|
16143
|
-
}
|
|
16144
|
-
case "email_otp": {
|
|
16145
|
-
const operationBinding = await hashEmailOtpOperationBinding({
|
|
16146
|
-
walletId: authenticated.session.walletId,
|
|
16147
|
-
providerUserId: proof.authority.factor.providerUserId,
|
|
16148
|
-
orgId: authenticated.session.tenantId,
|
|
16149
|
-
operation: operation.operation_kind === "evm.export_key" ? WALLET_EMAIL_OTP_EXPORT_OPERATION : WALLET_EMAIL_OTP_TRANSACTION_SIGN_OPERATION,
|
|
16150
|
-
requestOrigin,
|
|
16151
|
-
audience: requestOrigin,
|
|
16152
|
-
authorityRef: authenticated.authorityRef,
|
|
16153
|
-
...operation.operation_kind === "evm.sign_transaction" ? { operationFingerprintDigest: envelope.digests.laneDigest } : {}
|
|
16154
|
-
});
|
|
16155
|
-
const verified = await input.ctx.service.emailOtp.verifyEmailOtpChallenge({
|
|
16156
|
-
userId: proof.authority.factor.providerUserId,
|
|
16157
|
-
walletId: authenticated.session.walletId,
|
|
16158
|
-
orgId: authenticated.session.tenantId,
|
|
16159
|
-
challengeId: proof.challenge_id,
|
|
16160
|
-
otpCode: proof.otp_code,
|
|
16161
|
-
otpChannel: EMAIL_OTP_CHANNEL,
|
|
16162
|
-
ownerProofBindingDigest: operationBinding,
|
|
16163
|
-
operation: operation.operation_kind === "evm.export_key" ? WALLET_EMAIL_OTP_EXPORT_OPERATION : WALLET_EMAIL_OTP_TRANSACTION_SIGN_OPERATION
|
|
16164
|
-
});
|
|
16165
|
-
if (!verified.ok) return json$1(verified, { status: verified.code === "invalid_body" ? 400 : 401 });
|
|
16166
|
-
const consumed = operation.operation_kind === "evm.export_key" ? null : await input.ctx.service.emailOtp.consumeEmailOtpGrant({
|
|
16167
|
-
subject: {
|
|
16168
|
-
kind: "provider_identity",
|
|
16169
|
-
orgId: requireAuthorizationValue$1(parseOrgId(authenticated.session.tenantId)),
|
|
16170
|
-
providerSubject: requireAuthorizationValue$1(parseProviderSubject(proof.authority.factor.providerUserId)),
|
|
16171
|
-
walletId: walletIdFromString(authenticated.session.walletId)
|
|
16172
|
-
},
|
|
16173
|
-
loginGrant: verified.loginGrant,
|
|
16174
|
-
otpChannel: EMAIL_OTP_CHANNEL
|
|
16175
|
-
});
|
|
16176
|
-
if (consumed && !consumed.ok) return json$1(consumed, { status: consumed.code === "invalid_body" ? 400 : 401 });
|
|
16177
|
-
if (operation.operation_kind === "evm.export_key") emailOtpUnseal = {
|
|
16178
|
-
grant: verified.loginGrant,
|
|
16179
|
-
challengeId: verified.challengeId
|
|
16180
|
-
};
|
|
16181
|
-
const verifiedChallengeId = consumed?.ok ? consumed.challengeId : verified.challengeId;
|
|
16182
|
-
factor = buildVerifiedWalletOperationEmailOtpFactorResult({
|
|
16183
|
-
tenantId: authenticated.session.tenantId,
|
|
16184
|
-
principalId: authenticated.session.principalId,
|
|
16185
|
-
walletId: walletIdFromString(authenticated.session.walletId),
|
|
16186
|
-
requestOrigin,
|
|
16187
|
-
audience: requestOrigin,
|
|
16188
|
-
factorId: requireAuthorizationValue$1(parseAuthFactorId(`email_otp:${proof.authority.factor.provider}:${proof.authority.factor.providerUserId}`)),
|
|
16189
|
-
authorityRef: authenticated.authorityRef,
|
|
16190
|
-
operation: envelope,
|
|
16191
|
-
challengeId: requireAuthorizationValue$1(parseEmailOtpChallengeId(verifiedChallengeId)),
|
|
16192
|
-
verificationReceiptDigest: parseDigestB64u(base64UrlEncode(await sha256BytesUtf8(alphabetizeStringify({
|
|
16193
|
-
challengeId: verifiedChallengeId,
|
|
16194
|
-
operationFingerprint: expectedChallenge
|
|
16195
|
-
})))),
|
|
16196
|
-
verifiedAtMs: nowMs,
|
|
16197
|
-
expiresAtMs: Math.min(expiresAtMs, verified.grantExpiresAtMs)
|
|
16198
|
-
});
|
|
16199
|
-
break;
|
|
16200
|
-
}
|
|
16201
|
-
}
|
|
16317
|
+
const verifiedFactor = await verifyEcdsaOperationStepUpFactor({
|
|
16318
|
+
proof,
|
|
16319
|
+
operation: envelope,
|
|
16320
|
+
walletId: walletIdFromString(authenticated.session.walletId),
|
|
16321
|
+
authorityRef: authenticated.authorityRef,
|
|
16322
|
+
authSource: authenticated.session.laneAuthorization.authSource,
|
|
16323
|
+
requestOrigin,
|
|
16324
|
+
expectedChallenge,
|
|
16325
|
+
expiresAtMs,
|
|
16326
|
+
webAuthn: input.ctx.service.webAuthn,
|
|
16327
|
+
emailOtp: input.ctx.service.emailOtp
|
|
16328
|
+
});
|
|
16329
|
+
if (!verifiedFactor.ok) return verifiedFactor.response;
|
|
16202
16330
|
const evidenceSet = await input.ctx.service.authorizedOperations.recordVerifiedWalletOperationFactorEvidenceSet({
|
|
16203
16331
|
operation: envelope,
|
|
16204
16332
|
evidenceId,
|
|
16205
16333
|
evidenceSetId,
|
|
16206
|
-
factor
|
|
16334
|
+
factor: verifiedFactor.factor
|
|
16207
16335
|
});
|
|
16208
16336
|
const authorizedOperationId = requireAuthorizationValue$1(parseAuthorizedOperationId(`ecdsa-step-up-authorized-operation:${operation.operation_id}`));
|
|
16209
16337
|
const atomicOperation = await input.ctx.service.authorizedOperations.admitAuthorizedOperation({
|
|
@@ -16217,7 +16345,7 @@ async function issueEcdsaOperationStepUpAuthorization(input) {
|
|
|
16217
16345
|
evidenceSetDigest: evidenceSet.evidenceSetDigest
|
|
16218
16346
|
},
|
|
16219
16347
|
quota: { kind: "quota_neutral" },
|
|
16220
|
-
claimedAtMs:
|
|
16348
|
+
claimedAtMs: Date.now()
|
|
16221
16349
|
},
|
|
16222
16350
|
material: {
|
|
16223
16351
|
walletId: walletIdFromString(authenticated.session.walletId),
|
|
@@ -16250,11 +16378,7 @@ async function issueEcdsaOperationStepUpAuthorization(input) {
|
|
|
16250
16378
|
const responseAuthorization = {
|
|
16251
16379
|
kind: "operation_step_up",
|
|
16252
16380
|
evidence_set_digest: evidenceSet.evidenceSetDigest,
|
|
16253
|
-
unseal:
|
|
16254
|
-
kind: "email_otp_grant",
|
|
16255
|
-
grant: emailOtpUnseal.grant,
|
|
16256
|
-
challenge_id: emailOtpUnseal.challengeId
|
|
16257
|
-
} : { kind: "not_requested" }
|
|
16381
|
+
unseal: verifiedFactor.unseal
|
|
16258
16382
|
};
|
|
16259
16383
|
if (operation.operation_kind === "evm.export_key") {
|
|
16260
16384
|
const exportTopology = v2Resolution.kind === "admitted" && v2Resolution.operationKind === "evm.export_key" ? v2Resolution.exportTopology : await resolveStrictEcdsaExportTopology({
|
|
@@ -16438,6 +16562,7 @@ async function authorizeEcdsaPoolFillOperationStepUp(input) {
|
|
|
16438
16562
|
materialExpiresAtMs: input.operation.expires_at_ms
|
|
16439
16563
|
},
|
|
16440
16564
|
ownerWalletScope,
|
|
16565
|
+
ownershipGeneration: ownerWalletScope.ownershipGeneration,
|
|
16441
16566
|
routerAbEcdsaDerivationNormalSigning: {
|
|
16442
16567
|
kind: ROUTER_AB_ECDSA_DERIVATION_NORMAL_SIGNING_STATE_KIND_V1,
|
|
16443
16568
|
scope: input.operation.normal_signing_scope
|
|
@@ -16517,6 +16642,7 @@ async function authorizeEcdsaPoolFill(input) {
|
|
|
16517
16642
|
thresholdExpiresAtMs: session.expiresAtMs,
|
|
16518
16643
|
authorization: { kind: "wallet_session" },
|
|
16519
16644
|
ownerWalletScope: validated.ownerWalletScope,
|
|
16645
|
+
ownershipGeneration: validated.ownerWalletScope.ownershipGeneration,
|
|
16520
16646
|
routerAbEcdsaDerivationNormalSigning: normalSigning
|
|
16521
16647
|
}
|
|
16522
16648
|
};
|
|
@@ -16885,11 +17011,6 @@ async function admitStrictEcdsaExportOperationStepUp(input) {
|
|
|
16885
17011
|
case "wallet_session_quota_exhausted": return strictEcdsaExportFailure(409, result.kind, "Operation step-up authorization is invalid");
|
|
16886
17012
|
}
|
|
16887
17013
|
}
|
|
16888
|
-
function sameWalletSessionOperationCredentialAdmission(left, right) {
|
|
16889
|
-
const leftSession = left.context.authorization.session;
|
|
16890
|
-
const rightSession = right.context.authorization.session;
|
|
16891
|
-
return leftSession.tenantId === rightSession.tenantId && leftSession.principalId === rightSession.principalId && leftSession.walletId === rightSession.walletId && leftSession.authorityId === rightSession.authorityId && leftSession.walletAuthMethodId === rightSession.walletAuthMethodId && leftSession.authorityDigestB64u === rightSession.authorityDigestB64u && leftSession.authorityRevocationEpoch === rightSession.authorityRevocationEpoch && leftSession.authorizationId === rightSession.authorizationId && leftSession.walletSessionId === rightSession.walletSessionId && leftSession.quotaId === rightSession.quotaId && leftSession.expiresAtMs === rightSession.expiresAtMs && left.context.authority.authorityId === right.context.authority.authorityId && left.context.authority.authorityDigestB64u === right.context.authority.authorityDigestB64u && left.context.authMethod.walletAuthMethodId === right.context.authMethod.walletAuthMethodId && left.context.authMethod.walletAuthorityId === right.context.authMethod.walletAuthorityId && left.context.retiredAtMs === right.context.retiredAtMs && sameRouterAbMpcMaterialActivationRef(routerAbMpcMaterialActivationRefToWire(left.admission.materialActivation), routerAbMpcMaterialActivationRefToWire(right.admission.materialActivation));
|
|
16892
|
-
}
|
|
16893
17014
|
async function authorizeStrictEcdsaV2ExportOperationStepUp(input) {
|
|
16894
17015
|
const operation = input.request.operation;
|
|
16895
17016
|
if (!operation) return strictEcdsaExportFailure(400, "invalid_body", "Operation step-up export requires operation preparation");
|
|
@@ -16899,8 +17020,8 @@ async function authorizeStrictEcdsaV2ExportOperationStepUp(input) {
|
|
|
16899
17020
|
});
|
|
16900
17021
|
if (resolution.kind === "unavailable") return strictEcdsaExportFailure(503, "wallet_session_unavailable", "Wallet Session authorization is unavailable");
|
|
16901
17022
|
if (resolution.kind !== "admitted") return strictEcdsaExportFailure(403, "scope_mismatch", "ECDSA export operation step-up Wallet Session authorization is invalid");
|
|
16902
|
-
if (!
|
|
16903
|
-
const session = resolution.
|
|
17023
|
+
if (!walletSessionAuthorizationV2RecordsEqual(input.authorization.v2Admission.context.authorization.session, resolution.context.session)) return strictEcdsaExportFailure(403, "scope_mismatch", "ECDSA export operation step-up Wallet Session changed");
|
|
17024
|
+
const session = resolution.context.session;
|
|
16904
17025
|
const activeMaterial = resolution.activeMaterial;
|
|
16905
17026
|
if (input.request.authorization.kind !== "operation_step_up" || operation.operation_kind !== "evm.export_key" || operation.wallet_id !== String(session.walletId) || operation.wallet_id !== input.request.lifecycle.account_id || operation.material_activation.material_owner !== String(session.walletId) || operation.material_activation.signing_worker !== input.request.lifecycle.selected_server_id || operation.signing_worker_id !== input.request.lifecycle.selected_server_id || !sameRouterAbMpcMaterialActivationRef(operation.material_activation, input.request.material_activation) || operation.expires_at_ms < input.request.expires_at_ms || !strictEcdsaExportScopeMatchesRequest({
|
|
16906
17027
|
request: input.request,
|
|
@@ -17787,6 +17908,7 @@ async function handleHostedWalletSessionExchangeIssue(ctx) {
|
|
|
17787
17908
|
ok: true,
|
|
17788
17909
|
delivery: {
|
|
17789
17910
|
exchangeCode: delivery.exchangeCode,
|
|
17911
|
+
home: delivery.home,
|
|
17790
17912
|
nonce: delivery.nonce,
|
|
17791
17913
|
appOrigin: delivery.appOrigin,
|
|
17792
17914
|
walletOrigin: delivery.walletOrigin,
|
|
@@ -18829,7 +18951,12 @@ function bootstrapError(code, message, status) {
|
|
|
18829
18951
|
//#region src/router/transport/fetch/routes/syncAccount.ts
|
|
18830
18952
|
function syncAccountResponseStatus(result) {
|
|
18831
18953
|
if (result.ok && result.verified) return 200;
|
|
18832
|
-
|
|
18954
|
+
return syncAccountFailureStatus(result.code);
|
|
18955
|
+
}
|
|
18956
|
+
function syncAccountFailureStatus(code) {
|
|
18957
|
+
switch (code) {
|
|
18958
|
+
case "wallet_home_unavailable": return 503;
|
|
18959
|
+
case "wallet_home_conflict": return 409;
|
|
18833
18960
|
case "internal": return 500;
|
|
18834
18961
|
case "ed25519_not_provisioned": return 409;
|
|
18835
18962
|
default: return 400;
|
|
@@ -18859,7 +18986,7 @@ async function handleSyncAccount(ctx) {
|
|
|
18859
18986
|
const parsed = parseSyncAccountOptionsRequest(await readJson(ctx.request));
|
|
18860
18987
|
if (!parsed.ok) return json$1(parsed.body, { status: parsed.status });
|
|
18861
18988
|
const result = await ctx.service.webAuthn.createWebAuthnSyncAccountOptions(parsed.request);
|
|
18862
|
-
return json$1(result, { status: result.ok ? 200 : result.code
|
|
18989
|
+
return json$1(result, { status: result.ok ? 200 : syncAccountFailureStatus(result.code) });
|
|
18863
18990
|
}
|
|
18864
18991
|
if (ctx.pathname === "/sync-account/verify") {
|
|
18865
18992
|
const parsed = parseSyncAccountVerifyRequest({
|
|
@@ -18968,6 +19095,67 @@ async function handleSyncAccount(ctx) {
|
|
|
18968
19095
|
return null;
|
|
18969
19096
|
}
|
|
18970
19097
|
//#endregion
|
|
19098
|
+
//#region src/router/transport/fetch/routes/ed25519AuthorizedOperationRevalidation.ts
|
|
19099
|
+
function rejected(code, message, status) {
|
|
19100
|
+
return {
|
|
19101
|
+
ok: false,
|
|
19102
|
+
response: json$1({
|
|
19103
|
+
ok: false,
|
|
19104
|
+
code,
|
|
19105
|
+
message
|
|
19106
|
+
}, { status })
|
|
19107
|
+
};
|
|
19108
|
+
}
|
|
19109
|
+
function rejectedAdmission(kind) {
|
|
19110
|
+
return kind === "authorization_grant_rejected" || kind === "verified_step_up_rejected" ? rejected(kind, "Ed25519 operation authorization is no longer active", 403) : rejected(kind, "Ed25519 operation admission failed", 409);
|
|
19111
|
+
}
|
|
19112
|
+
async function revalidateEd25519StepUpOperation(input) {
|
|
19113
|
+
const stored = input.operation;
|
|
19114
|
+
if (stored.authorization.kind !== "verified_step_up" || stored.quota.kind !== "quota_neutral") return rejected("verified_step_up_rejected", "Ed25519 operation step-up authorization has an invalid quota", 403);
|
|
19115
|
+
const result = await input.ctx.service.authorizedOperations.admitAuthorizedOperation({ operation: {
|
|
19116
|
+
tenantId: stored.tenantId,
|
|
19117
|
+
authorizedOperationId: stored.authorizedOperationId,
|
|
19118
|
+
auditEventId: stored.auditEventId,
|
|
19119
|
+
operation: stored.operation,
|
|
19120
|
+
authorization: stored.authorization,
|
|
19121
|
+
quota: stored.quota,
|
|
19122
|
+
claimedAtMs: Date.now()
|
|
19123
|
+
} });
|
|
19124
|
+
if (!("operation" in result)) return rejectedAdmission(result.kind);
|
|
19125
|
+
if (result.operation.authorizedOperationId !== stored.authorizedOperationId) throw new Error("Ed25519 authorized operation changed during revalidation");
|
|
19126
|
+
return {
|
|
19127
|
+
ok: true,
|
|
19128
|
+
operation: result.operation
|
|
19129
|
+
};
|
|
19130
|
+
}
|
|
19131
|
+
/**
|
|
19132
|
+
* Finds the operation a reusable Wallet Session prepared and checks that its
|
|
19133
|
+
* grant is still active. A live operation returns the owner scope its
|
|
19134
|
+
* admission row pinned. A completed operation returns none: it replays its
|
|
19135
|
+
* stored response. The operation is read by its fingerprint, so a receipt
|
|
19136
|
+
* that names another operation ID has no stored operation.
|
|
19137
|
+
*/
|
|
19138
|
+
async function resolveEd25519WalletSessionOperation(input) {
|
|
19139
|
+
const result = await input.ctx.service.authorizedOperations.resolveEd25519WalletSessionOperation({
|
|
19140
|
+
tenantId: input.tenantId,
|
|
19141
|
+
operationFingerprintDigest: input.operationFingerprintDigest,
|
|
19142
|
+
walletId: input.walletId,
|
|
19143
|
+
nowMs: Date.now()
|
|
19144
|
+
});
|
|
19145
|
+
if (result.kind === "authorized_operation_missing") return rejected("authorized_operation_missing", "Authorized operation is unavailable", 409);
|
|
19146
|
+
if (!result.operation) return rejectedAdmission(result.kind);
|
|
19147
|
+
const stored = result.operation;
|
|
19148
|
+
if (stored.authorizedOperationId !== input.authorizedOperationId) return rejected("authorized_operation_missing", "Authorized operation is unavailable", 409);
|
|
19149
|
+
if (stored.quota.kind !== "consume_reusable_wallet_session") return rejected("authorization_grant_rejected", "Ed25519 reusable operation authorization has an invalid quota", 403);
|
|
19150
|
+
const operation = stored.operation.operation;
|
|
19151
|
+
if (operation.capabilityKind !== "near_ed25519_mpc_signing" || operation.operationKind === "near.export_key") return rejected("authorization_grant_rejected", "Ed25519 reusable operation kind is invalid", 403);
|
|
19152
|
+
return {
|
|
19153
|
+
ok: true,
|
|
19154
|
+
operation: stored,
|
|
19155
|
+
ownerScope: result.ownerScope ?? null
|
|
19156
|
+
};
|
|
19157
|
+
}
|
|
19158
|
+
//#endregion
|
|
18971
19159
|
//#region src/router/domains/signingOperations/ed25519AuthorizedOperationReceipt.ts
|
|
18972
19160
|
function requireEd25519OperationKind(value) {
|
|
18973
19161
|
if (value !== "near.sign_transaction" && value !== "near.sign_delegate_action" && value !== "near.sign_nep413_message") throw new Error("authorized_operation.operation_kind is invalid");
|
|
@@ -19366,30 +19554,22 @@ function parseRouterAbEd25519NormalSigningOperationForAdmission(input) {
|
|
|
19366
19554
|
}
|
|
19367
19555
|
try {
|
|
19368
19556
|
switch (input.authorizationKind) {
|
|
19369
|
-
case "reusable_wallet_session": {
|
|
19370
|
-
|
|
19371
|
-
|
|
19372
|
-
|
|
19373
|
-
|
|
19374
|
-
|
|
19375
|
-
|
|
19376
|
-
|
|
19377
|
-
|
|
19378
|
-
|
|
19379
|
-
|
|
19380
|
-
|
|
19381
|
-
|
|
19382
|
-
|
|
19383
|
-
|
|
19384
|
-
|
|
19385
|
-
operation: {
|
|
19386
|
-
phase: "finalize",
|
|
19387
|
-
operationKind: receipt.operation_kind,
|
|
19388
|
-
authorizationKind: "operation_step_up",
|
|
19389
|
-
receipt
|
|
19390
|
-
}
|
|
19391
|
-
};
|
|
19392
|
-
}
|
|
19557
|
+
case "reusable_wallet_session": return {
|
|
19558
|
+
ok: true,
|
|
19559
|
+
operation: {
|
|
19560
|
+
phase: "finalize",
|
|
19561
|
+
operationKind: parseEd25519ReusableAuthorizedOperationReceipt(input.body.authorized_operation).operation_kind,
|
|
19562
|
+
authorizationKind: "reusable_wallet_session"
|
|
19563
|
+
}
|
|
19564
|
+
};
|
|
19565
|
+
case "operation_step_up": return {
|
|
19566
|
+
ok: true,
|
|
19567
|
+
operation: {
|
|
19568
|
+
phase: "finalize",
|
|
19569
|
+
operationKind: parseEd25519VerifiedStepUpAuthorizedOperationReceipt(input.body.authorized_operation).operation_kind,
|
|
19570
|
+
authorizationKind: "operation_step_up"
|
|
19571
|
+
}
|
|
19572
|
+
};
|
|
19393
19573
|
}
|
|
19394
19574
|
} catch (error) {
|
|
19395
19575
|
return {
|
|
@@ -19398,94 +19578,7 @@ function parseRouterAbEd25519NormalSigningOperationForAdmission(input) {
|
|
|
19398
19578
|
};
|
|
19399
19579
|
}
|
|
19400
19580
|
}
|
|
19401
|
-
async function validateRouterAbEd25519V2FinalizeAuthorizedOperation(input) {
|
|
19402
|
-
if (!input.authorizedOperations) return {
|
|
19403
|
-
ok: false,
|
|
19404
|
-
result: routerAbEd25519OwnerOperationFailureResult({
|
|
19405
|
-
status: 501,
|
|
19406
|
-
code: "not_configured",
|
|
19407
|
-
message: "Reusable Wallet Session authorization is not configured",
|
|
19408
|
-
phase: input.phase
|
|
19409
|
-
})
|
|
19410
|
-
};
|
|
19411
|
-
let authorizedOperationId;
|
|
19412
|
-
try {
|
|
19413
|
-
authorizedOperationId = requireAuthorizationValue$2(parseAuthorizedOperationId(input.receipt.authorized_operation_id));
|
|
19414
|
-
requireAuthorizationValue$2(parseCapabilityOperationId(input.receipt.operation_id));
|
|
19415
|
-
} catch (error) {
|
|
19416
|
-
return {
|
|
19417
|
-
ok: false,
|
|
19418
|
-
result: routerAbEd25519OwnerOperationFailureResult({
|
|
19419
|
-
status: 400,
|
|
19420
|
-
code: "invalid_authorized_operation",
|
|
19421
|
-
message: routerAbErrorMessage(error),
|
|
19422
|
-
phase: input.phase
|
|
19423
|
-
})
|
|
19424
|
-
};
|
|
19425
|
-
}
|
|
19426
|
-
let operation;
|
|
19427
|
-
try {
|
|
19428
|
-
operation = await input.authorizedOperations.readAuthorizedOperationById({
|
|
19429
|
-
tenantId: input.authorizedOperations.tenantId,
|
|
19430
|
-
authorizedOperationId
|
|
19431
|
-
});
|
|
19432
|
-
} catch (error) {
|
|
19433
|
-
return {
|
|
19434
|
-
ok: false,
|
|
19435
|
-
result: routerAbEd25519OwnerOperationFailureResult({
|
|
19436
|
-
status: 500,
|
|
19437
|
-
code: "internal",
|
|
19438
|
-
message: routerAbErrorMessage(error),
|
|
19439
|
-
phase: input.phase
|
|
19440
|
-
})
|
|
19441
|
-
};
|
|
19442
|
-
}
|
|
19443
|
-
if (!operation) return {
|
|
19444
|
-
ok: false,
|
|
19445
|
-
result: routerAbEd25519OwnerOperationFailureResult({
|
|
19446
|
-
status: 409,
|
|
19447
|
-
code: "authorized_operation_missing",
|
|
19448
|
-
message: "Authorized operation is unavailable",
|
|
19449
|
-
phase: input.phase
|
|
19450
|
-
})
|
|
19451
|
-
};
|
|
19452
|
-
const operationRef = operation.operation.operation;
|
|
19453
|
-
if (operation.tenantId !== input.authorizedOperations.tenantId || operation.authorizedOperationId !== authorizedOperationId || operation.operation.operationId !== input.receipt.operation_id || operation.operationFingerprintDigest !== input.receipt.operation_fingerprint_digest || operation.operation.digests.laneDigest !== input.receipt.lane_digest_b64u || operation.operation.digests.intentDigest !== input.receipt.intent_digest_b64u || operation.operation.digests.displayDigest !== input.receipt.display_digest_b64u || operationRef.capabilityKind !== "near_ed25519_mpc_signing" || operationRef.operationKind !== input.receipt.operation_kind) return {
|
|
19454
|
-
ok: false,
|
|
19455
|
-
result: routerAbEd25519OwnerOperationFailureResult({
|
|
19456
|
-
status: 400,
|
|
19457
|
-
code: "invalid_authorized_operation",
|
|
19458
|
-
message: "Ed25519 authorized operation does not match its receipt",
|
|
19459
|
-
phase: input.phase
|
|
19460
|
-
})
|
|
19461
|
-
};
|
|
19462
|
-
switch (operationRef.operationKind) {
|
|
19463
|
-
case "near.sign_transaction":
|
|
19464
|
-
case "near.sign_delegate_action":
|
|
19465
|
-
case "near.sign_nep413_message": return {
|
|
19466
|
-
ok: true,
|
|
19467
|
-
operationKind: operationRef.operationKind
|
|
19468
|
-
};
|
|
19469
|
-
}
|
|
19470
|
-
}
|
|
19471
19581
|
async function authorizeRouterAbEd25519WalletSessionRequest(input) {
|
|
19472
|
-
if (input.operation.phase === "finalize") {
|
|
19473
|
-
const exactOperation = await validateRouterAbEd25519V2FinalizeAuthorizedOperation({
|
|
19474
|
-
receipt: input.operation.receipt,
|
|
19475
|
-
authorizedOperations: input.authorizedOperations,
|
|
19476
|
-
phase: input.phase
|
|
19477
|
-
});
|
|
19478
|
-
if (!exactOperation.ok) return exactOperation;
|
|
19479
|
-
if (exactOperation.operationKind !== input.admission.operationKind) return {
|
|
19480
|
-
ok: false,
|
|
19481
|
-
result: routerAbEd25519OwnerOperationFailureResult({
|
|
19482
|
-
status: 403,
|
|
19483
|
-
code: "wallet_session_scope_mismatch",
|
|
19484
|
-
message: "Exact Wallet Session operation does not match the authorized operation",
|
|
19485
|
-
phase: input.phase
|
|
19486
|
-
})
|
|
19487
|
-
};
|
|
19488
|
-
}
|
|
19489
19582
|
const expectedMaterialActivation = routerAbMpcMaterialActivationRefFromWire(input.scope.material_activation);
|
|
19490
19583
|
const admittedMaterialActivation = routerAbMpcMaterialActivationRefToWire(input.admission.materialActivation);
|
|
19491
19584
|
const expiresAtMs = Number(input.body.expires_at_ms);
|
|
@@ -19518,7 +19611,8 @@ async function authorizeRouterAbEd25519WalletSessionRequest(input) {
|
|
|
19518
19611
|
};
|
|
19519
19612
|
const activeMaterial = await input.resolveEd25519MaterialActivation({
|
|
19520
19613
|
walletId: String(input.session.walletId),
|
|
19521
|
-
materialActivation: admittedMaterialActivation
|
|
19614
|
+
materialActivation: admittedMaterialActivation,
|
|
19615
|
+
...input.signerRead ? { signerRead: input.signerRead } : {}
|
|
19522
19616
|
});
|
|
19523
19617
|
if (!activeMaterial.ok || !sameRouterAbMpcMaterialActivationRef(activeMaterial.materialActivation, admittedMaterialActivation) || activeMaterial.signingWorkerId !== input.scope.signing_worker_id || base64UrlEncode(Uint8Array.from(activeMaterial.exportIdentity.registered_public_key)) !== input.admission.signer.registeredPublicKeyB64u) return {
|
|
19524
19618
|
ok: false,
|
|
@@ -19539,6 +19633,7 @@ async function authorizeRouterAbEd25519WalletSessionRequest(input) {
|
|
|
19539
19633
|
const admissionDecision = await evaluateRouterAbNormalSigningAdmission({
|
|
19540
19634
|
adapter: input.admissionAdapter,
|
|
19541
19635
|
curve: "ed25519",
|
|
19636
|
+
policyReadSource: input.policyReadSource,
|
|
19542
19637
|
authorizationKind: "wallet_session_operation_credential_v1",
|
|
19543
19638
|
phase: input.phase,
|
|
19544
19639
|
walletId: String(input.session.walletId),
|
|
@@ -19596,13 +19691,13 @@ async function resolveRouterAbEd25519ExhaustedCandidateAuthorization(input) {
|
|
|
19596
19691
|
phase: input.phase,
|
|
19597
19692
|
body: input.body,
|
|
19598
19693
|
scope: input.scope,
|
|
19599
|
-
operation: input.operation,
|
|
19600
19694
|
session,
|
|
19601
19695
|
authorityId: String(candidate.authority.authorityId),
|
|
19602
19696
|
admission,
|
|
19603
|
-
authorizedOperations: input.authorizedOperations,
|
|
19604
19697
|
admissionAdapter: input.admissionAdapter,
|
|
19605
|
-
resolveEd25519MaterialActivation: input.resolveEd25519MaterialActivation
|
|
19698
|
+
resolveEd25519MaterialActivation: input.resolveEd25519MaterialActivation,
|
|
19699
|
+
signerRead: null,
|
|
19700
|
+
policyReadSource: { kind: "database" }
|
|
19606
19701
|
});
|
|
19607
19702
|
if (!authorized.ok) return authorized;
|
|
19608
19703
|
return {
|
|
@@ -19665,7 +19760,8 @@ async function authorizeRouterAbEd25519NormalSigningRoute(input) {
|
|
|
19665
19760
|
const validated = await validateRouterAbEd25519WalletSessionInputs({
|
|
19666
19761
|
headers: input.headers,
|
|
19667
19762
|
authorizationSessions: input.authorizationSessions,
|
|
19668
|
-
operationKind: operationForAdmission.operation.operationKind
|
|
19763
|
+
operationKind: operationForAdmission.operation.operationKind,
|
|
19764
|
+
materialActivation: scope.material_activation
|
|
19669
19765
|
});
|
|
19670
19766
|
if (!validated.ok) {
|
|
19671
19767
|
const operation = operationForAdmission.operation;
|
|
@@ -19676,7 +19772,6 @@ async function authorizeRouterAbEd25519NormalSigningRoute(input) {
|
|
|
19676
19772
|
scope,
|
|
19677
19773
|
phase: input.phase,
|
|
19678
19774
|
operation,
|
|
19679
|
-
authorizedOperations: input.authorizedOperations,
|
|
19680
19775
|
authorizationSessions: input.authorizationSessions,
|
|
19681
19776
|
admissionAdapter: input.admissionAdapter,
|
|
19682
19777
|
resolveEd25519MaterialActivation: input.resolveEd25519MaterialActivation
|
|
@@ -19714,13 +19809,16 @@ async function authorizeRouterAbEd25519NormalSigningRoute(input) {
|
|
|
19714
19809
|
phase: input.phase,
|
|
19715
19810
|
body: input.body,
|
|
19716
19811
|
scope,
|
|
19717
|
-
operation,
|
|
19718
19812
|
session: validated.admission.context.authorization.session,
|
|
19719
19813
|
authorityId: String(validated.admission.context.authority.authorityId),
|
|
19720
19814
|
admission: validated.admission.admission,
|
|
19721
|
-
authorizedOperations: input.authorizedOperations,
|
|
19722
19815
|
admissionAdapter: input.admissionAdapter,
|
|
19723
|
-
resolveEd25519MaterialActivation: input.resolveEd25519MaterialActivation
|
|
19816
|
+
resolveEd25519MaterialActivation: input.resolveEd25519MaterialActivation,
|
|
19817
|
+
signerRead: validated.signerRead,
|
|
19818
|
+
policyReadSource: {
|
|
19819
|
+
kind: "credential_snapshot",
|
|
19820
|
+
policyRead: validated.policyRead
|
|
19821
|
+
}
|
|
19724
19822
|
});
|
|
19725
19823
|
if (!authorized.ok) return authorized;
|
|
19726
19824
|
return {
|
|
@@ -20049,11 +20147,12 @@ function ed25519ReusableWalletSessionIdentity(authorization) {
|
|
|
20049
20147
|
quotaId: session.quotaId
|
|
20050
20148
|
};
|
|
20051
20149
|
}
|
|
20052
|
-
function buildEd25519GatewayOwnerWalletSessionBinding(authorization,
|
|
20150
|
+
function buildEd25519GatewayOwnerWalletSessionBinding(authorization, pinned) {
|
|
20053
20151
|
const session = ed25519ReusableWalletSession(authorization);
|
|
20054
20152
|
const runtimePolicyScope = authorization.activeMaterial.runtimePolicyScope;
|
|
20055
20153
|
return {
|
|
20056
20154
|
kind: "gateway_owner_wallet_session",
|
|
20155
|
+
ownershipGeneration: pinned.ownershipGeneration,
|
|
20057
20156
|
subjectId: String(session.principalId),
|
|
20058
20157
|
accountId: String(session.walletId),
|
|
20059
20158
|
authorizationId: String(session.authorizationId),
|
|
@@ -20063,20 +20162,16 @@ function buildEd25519GatewayOwnerWalletSessionBinding(authorization, projectEnvi
|
|
|
20063
20162
|
orgId: runtimePolicyScope.orgId,
|
|
20064
20163
|
projectId: runtimePolicyScope.projectId,
|
|
20065
20164
|
environment: runtimePolicyScope.envId,
|
|
20066
|
-
projectEnvironmentId,
|
|
20165
|
+
projectEnvironmentId: pinned.projectEnvironmentId,
|
|
20067
20166
|
signingWorkerId: authorization.activeMaterial.signingWorkerId,
|
|
20068
20167
|
expiresAtMs: session.expiresAtMs
|
|
20069
20168
|
};
|
|
20070
20169
|
}
|
|
20071
|
-
|
|
20072
|
-
|
|
20170
|
+
/** The scope the operation's own admission pinned, checked against the active material. */
|
|
20171
|
+
function pinnedEd25519WalletScope(authorization, pinned) {
|
|
20073
20172
|
const scope = authorization.activeMaterial.runtimePolicyScope;
|
|
20074
|
-
const pinned = await ctx.service.authorizedOperations.readPinnedOwnerWalletScope({
|
|
20075
|
-
operation,
|
|
20076
|
-
walletId: session.walletId
|
|
20077
|
-
});
|
|
20078
20173
|
if (pinned.orgId !== scope.orgId || pinned.projectId !== scope.projectId) throw new Error("Pinned owner Wallet Session scope differs from active material");
|
|
20079
|
-
return pinned
|
|
20174
|
+
return pinned;
|
|
20080
20175
|
}
|
|
20081
20176
|
/**
|
|
20082
20177
|
* The Router binding for a verified step-up: the wallet it signs for and the
|
|
@@ -20092,6 +20187,7 @@ async function ed25519OperationStepUpBinding(ctx, session, operation) {
|
|
|
20092
20187
|
if (pinned.orgId !== scope.orgId || pinned.projectId !== scope.projectId) throw new Error("Step-up wallet scope differs from the Wallet Session scope");
|
|
20093
20188
|
return {
|
|
20094
20189
|
kind: "operation_step_up",
|
|
20190
|
+
ownershipGeneration: pinned.ownershipGeneration,
|
|
20095
20191
|
authorizationSessionId: session.sessionId,
|
|
20096
20192
|
orgId: scope.orgId,
|
|
20097
20193
|
projectId: scope.projectId,
|
|
@@ -20106,7 +20202,7 @@ function buildRouterAbEd25519AuthorizedOperationWire(input) {
|
|
|
20106
20202
|
const operationRef = operation.operation.operation;
|
|
20107
20203
|
if (operationRef.capabilityKind !== "near_ed25519_mpc_signing") throw new Error("Ed25519 authorized operation capability is invalid");
|
|
20108
20204
|
const operationKind = requireEd25519OperationKind(operationRef.operationKind);
|
|
20109
|
-
|
|
20205
|
+
return buildAuthorizedOperationWire(input, {
|
|
20110
20206
|
authorized_operation_id: operation.authorizedOperationId,
|
|
20111
20207
|
operation_id: operation.operation.operationId,
|
|
20112
20208
|
capability_kind: "near_ed25519_mpc_signing",
|
|
@@ -20115,66 +20211,7 @@ function buildRouterAbEd25519AuthorizedOperationWire(input) {
|
|
|
20115
20211
|
intent_digest_b64u: operation.operation.digests.intentDigest,
|
|
20116
20212
|
display_digest_b64u: operation.operation.digests.displayDigest,
|
|
20117
20213
|
operation_fingerprint_digest: operation.operationFingerprintDigest
|
|
20118
|
-
};
|
|
20119
|
-
switch (input.binding.kind) {
|
|
20120
|
-
case "reusable_wallet_session":
|
|
20121
|
-
if (operation.authorization.kind !== "authorization_grant" || operation.quota.kind !== "consume_reusable_wallet_session") throw new Error("Reusable Wallet Session authorized operation is invalid");
|
|
20122
|
-
return {
|
|
20123
|
-
binding: {
|
|
20124
|
-
kind: "reusable_wallet_session",
|
|
20125
|
-
authorization_id: operation.authorization.authorizationGrantRef.authorizationId,
|
|
20126
|
-
wallet_session_id: input.binding.walletSessionId,
|
|
20127
|
-
quota_id: input.binding.quotaId
|
|
20128
|
-
},
|
|
20129
|
-
authorized_operation: {
|
|
20130
|
-
kind: "reusable_wallet_session_authorized_operation_v1",
|
|
20131
|
-
...commonAuthorizedOperation
|
|
20132
|
-
}
|
|
20133
|
-
};
|
|
20134
|
-
case "gateway_owner_wallet_session":
|
|
20135
|
-
if (operation.authorization.kind !== "authorization_grant" || operation.quota.kind !== "consume_reusable_wallet_session") throw new Error("Gateway owner Wallet Session authorized operation is invalid");
|
|
20136
|
-
return {
|
|
20137
|
-
binding: {
|
|
20138
|
-
kind: "gateway_owner_wallet_session",
|
|
20139
|
-
subject_id: input.binding.subjectId,
|
|
20140
|
-
account_id: input.binding.accountId,
|
|
20141
|
-
authorization_id: input.binding.authorizationId,
|
|
20142
|
-
wallet_session_id: input.binding.walletSessionId,
|
|
20143
|
-
quota_id: input.binding.quotaId,
|
|
20144
|
-
threshold_session_id: input.binding.thresholdSessionId,
|
|
20145
|
-
org_id: input.binding.orgId,
|
|
20146
|
-
project_id: input.binding.projectId,
|
|
20147
|
-
environment: input.binding.environment,
|
|
20148
|
-
project_environment_id: input.binding.projectEnvironmentId,
|
|
20149
|
-
signing_worker_id: input.binding.signingWorkerId,
|
|
20150
|
-
expires_at_ms: input.binding.expiresAtMs
|
|
20151
|
-
},
|
|
20152
|
-
authorized_operation: {
|
|
20153
|
-
kind: "reusable_wallet_session_authorized_operation_v1",
|
|
20154
|
-
...commonAuthorizedOperation
|
|
20155
|
-
}
|
|
20156
|
-
};
|
|
20157
|
-
case "operation_step_up":
|
|
20158
|
-
if (operation.authorization.kind !== "verified_step_up" || operation.quota.kind !== "quota_neutral") throw new Error("Verified step-up authorized operation is invalid");
|
|
20159
|
-
return {
|
|
20160
|
-
binding: {
|
|
20161
|
-
kind: "operation_step_up",
|
|
20162
|
-
authorization_session_id: input.binding.authorizationSessionId,
|
|
20163
|
-
org_id: input.binding.orgId,
|
|
20164
|
-
project_id: input.binding.projectId,
|
|
20165
|
-
environment: input.binding.environment,
|
|
20166
|
-
project_environment_id: input.binding.projectEnvironmentId,
|
|
20167
|
-
subject_id: input.binding.subjectId,
|
|
20168
|
-
account_id: input.binding.accountId
|
|
20169
|
-
},
|
|
20170
|
-
authorized_operation: {
|
|
20171
|
-
kind: "verified_step_up_authorized_operation_v1",
|
|
20172
|
-
authorization_session_id: input.binding.authorizationSessionId,
|
|
20173
|
-
evidence_set_digest: operation.authorization.evidenceSetDigest,
|
|
20174
|
-
...commonAuthorizedOperation
|
|
20175
|
-
}
|
|
20176
|
-
};
|
|
20177
|
-
}
|
|
20214
|
+
});
|
|
20178
20215
|
}
|
|
20179
20216
|
async function releaseEmailOtpFactorForWorker(input) {
|
|
20180
20217
|
const unsealed = await input.emailOtp.removeEmailOtpServerSeal({ wrappedCiphertext: input.request.enrollment.serverSealedFactorCiphertextB64u });
|
|
@@ -20333,21 +20370,24 @@ async function authorizeEd25519ReusableWalletSessionOperation(input) {
|
|
|
20333
20370
|
}
|
|
20334
20371
|
});
|
|
20335
20372
|
const authorizedOperationId = requireAuthorizationValue(parseAuthorizedOperationId(`ed25519-operation:${operation.operationId}:${scope.request_id}`));
|
|
20336
|
-
const outcome = await input.ctx.service.authorizedOperations.
|
|
20337
|
-
|
|
20338
|
-
|
|
20339
|
-
|
|
20340
|
-
|
|
20341
|
-
|
|
20342
|
-
|
|
20343
|
-
|
|
20344
|
-
|
|
20345
|
-
|
|
20346
|
-
|
|
20347
|
-
|
|
20373
|
+
const outcome = await input.ctx.service.authorizedOperations.admitEd25519WalletSessionOperation({
|
|
20374
|
+
operation: {
|
|
20375
|
+
tenantId: identity.tenantId,
|
|
20376
|
+
authorizedOperationId,
|
|
20377
|
+
auditEventId: requireAuthorizationValue(parseAuthorizationAuditEventId(`ed25519-operation-audit:${operation.operationId}`)),
|
|
20378
|
+
operation: envelope,
|
|
20379
|
+
authorization: {
|
|
20380
|
+
kind: "authorization_grant",
|
|
20381
|
+
authorizationGrantRef: buildAuthorizationGrantRef(identity.authorizationId)
|
|
20382
|
+
},
|
|
20383
|
+
quota: {
|
|
20384
|
+
kind: "consume_reusable_wallet_session",
|
|
20385
|
+
quotaId: identity.quotaId
|
|
20386
|
+
},
|
|
20387
|
+
claimedAtMs: nowMs
|
|
20348
20388
|
},
|
|
20349
|
-
|
|
20350
|
-
}
|
|
20389
|
+
walletId: session.walletId
|
|
20390
|
+
});
|
|
20351
20391
|
if (outcome.kind !== "claimed" && outcome.kind !== "operation_in_progress" && outcome.kind !== "replayed") {
|
|
20352
20392
|
const stepUpMaterial = await input.ctx.service.walletRegistration.resolveEd25519MaterialActivation({
|
|
20353
20393
|
walletId: scope.account_id,
|
|
@@ -20382,125 +20422,31 @@ async function authorizeEd25519ReusableWalletSessionOperation(input) {
|
|
|
20382
20422
|
admission: {
|
|
20383
20423
|
kind: "claimed",
|
|
20384
20424
|
operation: outcome.operation,
|
|
20425
|
+
ownerScope: outcome.ownerScope,
|
|
20385
20426
|
receipt: {
|
|
20386
20427
|
kind: "reusable_wallet_session_authorized_operation_v1",
|
|
20387
20428
|
authorized_operation_id: outcome.operation.authorizedOperationId,
|
|
20388
20429
|
operation_id: outcome.operation.operation.operationId,
|
|
20389
20430
|
capability_kind: "near_ed25519_mpc_signing",
|
|
20390
|
-
operation_kind: requireEd25519OperationKind(outcome.operation.operation.operation.operationKind),
|
|
20391
|
-
lane_digest_b64u: laneDigest,
|
|
20392
|
-
intent_digest_b64u: intentDigest,
|
|
20393
|
-
display_digest_b64u: displayDigest,
|
|
20394
|
-
operation_fingerprint_digest: outcome.operation.operationFingerprintDigest
|
|
20395
|
-
}
|
|
20396
|
-
}
|
|
20397
|
-
};
|
|
20398
|
-
} catch (error) {
|
|
20399
|
-
return {
|
|
20400
|
-
ok: false,
|
|
20401
|
-
response: json$1({
|
|
20402
|
-
ok: false,
|
|
20403
|
-
code: "invalid_body",
|
|
20404
|
-
message: error instanceof Error ? error.message : "Ed25519 authorized operation is invalid"
|
|
20405
|
-
}, { status: 400 })
|
|
20406
|
-
};
|
|
20407
|
-
}
|
|
20408
|
-
}
|
|
20409
|
-
async function revalidateEd25519AuthorizedOperation(input) {
|
|
20410
|
-
let admission;
|
|
20411
|
-
if (input.operation.authorization.kind === "verified_step_up") {
|
|
20412
|
-
if (input.operation.quota.kind !== "quota_neutral") return {
|
|
20413
|
-
ok: false,
|
|
20414
|
-
response: json$1({
|
|
20415
|
-
ok: false,
|
|
20416
|
-
code: "verified_step_up_rejected",
|
|
20417
|
-
message: "Ed25519 operation step-up authorization has an invalid quota"
|
|
20418
|
-
}, { status: 403 })
|
|
20419
|
-
};
|
|
20420
|
-
admission = {
|
|
20421
|
-
tenantId: input.operation.tenantId,
|
|
20422
|
-
authorizedOperationId: input.operation.authorizedOperationId,
|
|
20423
|
-
auditEventId: input.operation.auditEventId,
|
|
20424
|
-
operation: input.operation.operation,
|
|
20425
|
-
authorization: input.operation.authorization,
|
|
20426
|
-
quota: input.operation.quota,
|
|
20427
|
-
claimedAtMs: Date.now()
|
|
20428
|
-
};
|
|
20429
|
-
} else {
|
|
20430
|
-
if (input.operation.quota.kind !== "consume_reusable_wallet_session") return {
|
|
20431
|
-
ok: false,
|
|
20432
|
-
response: json$1({
|
|
20433
|
-
ok: false,
|
|
20434
|
-
code: "authorization_grant_rejected",
|
|
20435
|
-
message: "Ed25519 reusable operation authorization has an invalid quota"
|
|
20436
|
-
}, { status: 403 })
|
|
20437
|
-
};
|
|
20438
|
-
const operation = buildEd25519ReusableOperationEnvelope(input.operation);
|
|
20439
|
-
if (!operation) return {
|
|
20440
|
-
ok: false,
|
|
20441
|
-
response: json$1({
|
|
20442
|
-
ok: false,
|
|
20443
|
-
code: "authorization_grant_rejected",
|
|
20444
|
-
message: "Ed25519 reusable operation kind is invalid"
|
|
20445
|
-
}, { status: 403 })
|
|
20446
|
-
};
|
|
20447
|
-
admission = {
|
|
20448
|
-
tenantId: input.operation.tenantId,
|
|
20449
|
-
authorizedOperationId: input.operation.authorizedOperationId,
|
|
20450
|
-
auditEventId: input.operation.auditEventId,
|
|
20451
|
-
operation,
|
|
20452
|
-
authorization: input.operation.authorization,
|
|
20453
|
-
quota: input.operation.quota,
|
|
20454
|
-
claimedAtMs: Date.now()
|
|
20455
|
-
};
|
|
20456
|
-
}
|
|
20457
|
-
const result = await input.ctx.service.authorizedOperations.admitAuthorizedOperation({ operation: admission });
|
|
20458
|
-
switch (result.kind) {
|
|
20459
|
-
case "claimed":
|
|
20460
|
-
case "operation_in_progress":
|
|
20461
|
-
case "replayed":
|
|
20462
|
-
if (result.operation.authorizedOperationId !== input.operation.authorizedOperationId) throw new Error("Ed25519 authorized operation changed during revalidation");
|
|
20463
|
-
return {
|
|
20464
|
-
ok: true,
|
|
20465
|
-
operation: result.operation
|
|
20466
|
-
};
|
|
20467
|
-
case "authorization_grant_rejected":
|
|
20468
|
-
case "verified_step_up_rejected": return {
|
|
20469
|
-
ok: false,
|
|
20470
|
-
response: json$1({
|
|
20471
|
-
ok: false,
|
|
20472
|
-
code: result.kind,
|
|
20473
|
-
message: "Ed25519 operation authorization is no longer active"
|
|
20474
|
-
}, { status: 403 })
|
|
20431
|
+
operation_kind: requireEd25519OperationKind(outcome.operation.operation.operation.operationKind),
|
|
20432
|
+
lane_digest_b64u: laneDigest,
|
|
20433
|
+
intent_digest_b64u: intentDigest,
|
|
20434
|
+
display_digest_b64u: displayDigest,
|
|
20435
|
+
operation_fingerprint_digest: outcome.operation.operationFingerprintDigest
|
|
20436
|
+
}
|
|
20437
|
+
}
|
|
20475
20438
|
};
|
|
20476
|
-
|
|
20477
|
-
|
|
20439
|
+
} catch (error) {
|
|
20440
|
+
return {
|
|
20478
20441
|
ok: false,
|
|
20479
20442
|
response: json$1({
|
|
20480
20443
|
ok: false,
|
|
20481
|
-
code:
|
|
20482
|
-
message: "Ed25519 operation
|
|
20483
|
-
}, { status:
|
|
20444
|
+
code: "invalid_body",
|
|
20445
|
+
message: error instanceof Error ? error.message : "Ed25519 authorized operation is invalid"
|
|
20446
|
+
}, { status: 400 })
|
|
20484
20447
|
};
|
|
20485
20448
|
}
|
|
20486
20449
|
}
|
|
20487
|
-
function buildEd25519ReusableOperationEnvelope(operation) {
|
|
20488
|
-
const operationRef = operation.operation.operation;
|
|
20489
|
-
if (operationRef.capabilityKind !== "near_ed25519_mpc_signing") return null;
|
|
20490
|
-
switch (operationRef.operationKind) {
|
|
20491
|
-
case "near.sign_transaction":
|
|
20492
|
-
case "near.sign_delegate_action":
|
|
20493
|
-
case "near.sign_nep413_message": return buildCapabilityOperationEnvelope({
|
|
20494
|
-
tenantId: operation.operation.tenantId,
|
|
20495
|
-
principalId: operation.operation.principalId,
|
|
20496
|
-
capabilityId: operation.operation.capabilityId,
|
|
20497
|
-
operationId: operation.operation.operationId,
|
|
20498
|
-
operation: buildNearEd25519MpcOperationRef(operationRef.operationKind),
|
|
20499
|
-
digests: operation.operation.digests
|
|
20500
|
-
});
|
|
20501
|
-
case "near.export_key": return null;
|
|
20502
|
-
}
|
|
20503
|
-
}
|
|
20504
20450
|
async function validateEd25519ReusableAuthorizedOperation(input) {
|
|
20505
20451
|
try {
|
|
20506
20452
|
const receipt = parseEd25519ReusableAuthorizedOperationReceipt(input.body.authorized_operation);
|
|
@@ -20509,7 +20455,7 @@ async function validateEd25519ReusableAuthorizedOperation(input) {
|
|
|
20509
20455
|
const identity = ed25519ReusableWalletSessionIdentity(input.authorization);
|
|
20510
20456
|
const capabilityId = requireAuthorizationValue(parseCapabilityId(scope.material_activation.capability));
|
|
20511
20457
|
const operationId = requireAuthorizationValue(parseCapabilityOperationId(receipt.operation_id));
|
|
20512
|
-
const
|
|
20458
|
+
const envelope = buildCapabilityOperationEnvelope({
|
|
20513
20459
|
tenantId: identity.tenantId,
|
|
20514
20460
|
principalId: identity.principalId,
|
|
20515
20461
|
capabilityId,
|
|
@@ -20523,31 +20469,39 @@ async function validateEd25519ReusableAuthorizedOperation(input) {
|
|
|
20523
20469
|
intentDigest: parseDigestB64u(receipt.intent_digest_b64u),
|
|
20524
20470
|
displayDigest: parseDigestB64u(receipt.display_digest_b64u)
|
|
20525
20471
|
}
|
|
20526
|
-
})
|
|
20472
|
+
});
|
|
20473
|
+
const fingerprint = await computeCapabilityOperationFingerprintDigest(envelope);
|
|
20527
20474
|
if (fingerprint !== parseCapabilityOperationFingerprintDigest(receipt.operation_fingerprint_digest)) throw new Error("Ed25519 authorized operation fingerprint changed");
|
|
20528
20475
|
if (digestWireB64u((isPlainObject(input.body.prepare_binding) ? input.body.prepare_binding : null)?.intent_digest, "prepare_binding.intent_digest") !== receipt.intent_digest_b64u) throw new Error("Ed25519 authorized operation intent changed after prepare");
|
|
20529
|
-
const
|
|
20530
|
-
|
|
20531
|
-
|
|
20532
|
-
|
|
20533
|
-
|
|
20534
|
-
|
|
20535
|
-
|
|
20476
|
+
const authorizedOperationId = requireAuthorizationValue(parseAuthorizedOperationId(receipt.authorized_operation_id));
|
|
20477
|
+
let resolved;
|
|
20478
|
+
try {
|
|
20479
|
+
resolved = await resolveEd25519WalletSessionOperation({
|
|
20480
|
+
ctx: input.ctx,
|
|
20481
|
+
tenantId: identity.tenantId,
|
|
20482
|
+
authorizedOperationId,
|
|
20483
|
+
operationFingerprintDigest: fingerprint,
|
|
20484
|
+
walletId: ed25519ReusableWalletSession(input.authorization).walletId
|
|
20485
|
+
});
|
|
20486
|
+
} catch {
|
|
20487
|
+
return {
|
|
20536
20488
|
ok: false,
|
|
20537
|
-
|
|
20538
|
-
|
|
20539
|
-
|
|
20540
|
-
|
|
20541
|
-
|
|
20542
|
-
|
|
20543
|
-
|
|
20544
|
-
|
|
20545
|
-
|
|
20546
|
-
|
|
20489
|
+
response: json$1({
|
|
20490
|
+
ok: false,
|
|
20491
|
+
code: "internal",
|
|
20492
|
+
message: "Authorized operation lookup failed"
|
|
20493
|
+
}, { status: 500 })
|
|
20494
|
+
};
|
|
20495
|
+
}
|
|
20496
|
+
if (!resolved.ok) return resolved;
|
|
20497
|
+
const operationResult = resolved.operation;
|
|
20498
|
+
if (operationResult.tenantId !== identity.tenantId || operationResult.tenantId !== input.ctx.service.authorizedOperations.tenantId || operationResult.operationFingerprintDigest !== fingerprint || operationResult.operation.operationId !== operationId || operationResult.operation.digests.laneDigest !== envelope.digests.laneDigest || operationResult.operation.digests.intentDigest !== envelope.digests.intentDigest || operationResult.operation.digests.displayDigest !== envelope.digests.displayDigest || operationResult.operation.operation.capabilityKind !== "near_ed25519_mpc_signing" || operationResult.operation.operation.operationKind !== receipt.operation_kind) throw new Error("Ed25519 authorized operation identity changed after prepare");
|
|
20499
|
+
return {
|
|
20547
20500
|
ok: true,
|
|
20548
20501
|
receipt,
|
|
20549
|
-
operation:
|
|
20550
|
-
|
|
20502
|
+
operation: operationResult,
|
|
20503
|
+
ownerScope: resolved.ownerScope
|
|
20504
|
+
};
|
|
20551
20505
|
} catch (error) {
|
|
20552
20506
|
return {
|
|
20553
20507
|
ok: false,
|
|
@@ -20613,7 +20567,7 @@ async function validateEd25519VerifiedStepUpAuthorizedOperation(input) {
|
|
|
20613
20567
|
};
|
|
20614
20568
|
if (operationResult.authorizedOperationId !== requireAuthorizationValue(parseAuthorizedOperationId(receipt.authorized_operation_id)) || operationResult.operationFingerprintDigest !== fingerprint) throw new Error("Operation step-up authorized operation identity changed after prepare");
|
|
20615
20569
|
if (operationResult.authorization.kind !== "verified_step_up" || operationResult.authorization.evidenceSetDigest !== parseDigestB64u(receipt.evidence_set_digest)) throw new Error("Operation step-up evidence changed after prepare");
|
|
20616
|
-
const revalidated = await
|
|
20570
|
+
const revalidated = await revalidateEd25519StepUpOperation({
|
|
20617
20571
|
ctx: input.ctx,
|
|
20618
20572
|
operation: operationResult
|
|
20619
20573
|
});
|
|
@@ -21076,13 +21030,15 @@ async function handleRouterAbEd25519NormalSigningRoute(input) {
|
|
|
21076
21030
|
bodyText: upstreamBodyText
|
|
21077
21031
|
})
|
|
21078
21032
|
}));
|
|
21079
|
-
|
|
21033
|
+
const headers = new Headers(upstream.headers);
|
|
21034
|
+
headers.delete("content-length");
|
|
21035
|
+
return new Response(JSON.stringify(signingPrepareSessionResponse({
|
|
21080
21036
|
...upstreamBody,
|
|
21081
21037
|
authorized_operation: buildEd25519VerifiedStepUpAuthorizedOperationReceipt({ authorization })
|
|
21082
|
-
}), {
|
|
21038
|
+
}, authorization)), {
|
|
21083
21039
|
status: upstream.status,
|
|
21084
21040
|
statusText: upstream.statusText,
|
|
21085
|
-
headers
|
|
21041
|
+
headers
|
|
21086
21042
|
});
|
|
21087
21043
|
}
|
|
21088
21044
|
if (authorization.phase !== "finalize") throw new Error("Operation step-up finalize authorization phase changed");
|
|
@@ -21156,7 +21112,7 @@ async function handleRouterAbEd25519NormalSigningRoute(input) {
|
|
|
21156
21112
|
...input.body,
|
|
21157
21113
|
authorized_operation: buildRouterAbEd25519AuthorizedOperationWire({
|
|
21158
21114
|
operation: execution.operation,
|
|
21159
|
-
binding:
|
|
21115
|
+
binding: buildEd25519GatewayOwnerWalletSessionBinding(authorization, pinnedEd25519WalletScope(authorization, authorized.admission.ownerScope))
|
|
21160
21116
|
})
|
|
21161
21117
|
}
|
|
21162
21118
|
});
|
|
@@ -21180,13 +21136,15 @@ async function handleRouterAbEd25519NormalSigningRoute(input) {
|
|
|
21180
21136
|
bodyText: upstreamBodyText
|
|
21181
21137
|
})
|
|
21182
21138
|
}));
|
|
21183
|
-
|
|
21139
|
+
const headers = new Headers(upstream.headers);
|
|
21140
|
+
headers.delete("content-length");
|
|
21141
|
+
return new Response(JSON.stringify(signingPrepareSessionResponse({
|
|
21184
21142
|
...upstreamBody,
|
|
21185
21143
|
authorized_operation: authorized.admission.receipt
|
|
21186
|
-
}), {
|
|
21144
|
+
}, authorization)), {
|
|
21187
21145
|
status: upstream.status,
|
|
21188
21146
|
statusText: upstream.statusText,
|
|
21189
|
-
headers
|
|
21147
|
+
headers
|
|
21190
21148
|
});
|
|
21191
21149
|
}
|
|
21192
21150
|
const validatedAuthorization = await validateEd25519ReusableAuthorizedOperation({
|
|
@@ -21197,6 +21155,7 @@ async function handleRouterAbEd25519NormalSigningRoute(input) {
|
|
|
21197
21155
|
if (!validatedAuthorization.ok) return validatedAuthorization.response;
|
|
21198
21156
|
const replay = replayCompletedEd25519Operation(validatedAuthorization.operation);
|
|
21199
21157
|
if (replay) return replay;
|
|
21158
|
+
if (!validatedAuthorization.ownerScope) throw new Error("Pinned owner Wallet Session scope is unavailable");
|
|
21200
21159
|
const upstream = await proxyEd25519OwnerLaneExecution({
|
|
21201
21160
|
ctx: input.ctx,
|
|
21202
21161
|
authorization,
|
|
@@ -21205,7 +21164,7 @@ async function handleRouterAbEd25519NormalSigningRoute(input) {
|
|
|
21205
21164
|
...input.body,
|
|
21206
21165
|
authorized_operation: buildRouterAbEd25519AuthorizedOperationWire({
|
|
21207
21166
|
operation: validatedAuthorization.operation,
|
|
21208
|
-
binding:
|
|
21167
|
+
binding: buildEd25519GatewayOwnerWalletSessionBinding(authorization, pinnedEd25519WalletScope(authorization, validatedAuthorization.ownerScope))
|
|
21209
21168
|
})
|
|
21210
21169
|
}
|
|
21211
21170
|
});
|
|
@@ -21337,7 +21296,7 @@ function parsePreflightRequest(raw) {
|
|
|
21337
21296
|
if (!isPlainObject(raw)) throw new Error("owner execution-lane preflight body is required");
|
|
21338
21297
|
const fields = Object.keys(raw).sort();
|
|
21339
21298
|
if (fields.length !== 2 || fields[0] !== "curve" || fields[1] !== "expectedMaterialActivation") throw new Error("owner execution-lane preflight body fields are invalid");
|
|
21340
|
-
if (raw.curve !== "
|
|
21299
|
+
if (raw.curve !== "ecdsa_secp256k1") throw new Error("owner execution-lane preflight curve is invalid");
|
|
21341
21300
|
const materialActivation = parseMpcMaterialActivationRef(raw.expectedMaterialActivation);
|
|
21342
21301
|
if (!materialActivation.ok) throw new Error(materialActivation.error.message);
|
|
21343
21302
|
return {
|
|
@@ -21487,46 +21446,24 @@ async function handleOwnerWalletExecutionLanePreflight(ctx) {
|
|
|
21487
21446
|
}, { status: 400 });
|
|
21488
21447
|
}
|
|
21489
21448
|
const headers = Object.fromEntries(ctx.request.headers.entries());
|
|
21490
|
-
|
|
21491
|
-
|
|
21492
|
-
|
|
21493
|
-
|
|
21494
|
-
|
|
21495
|
-
authorizationSessions: ctx.service.authorizationSessions,
|
|
21496
|
-
operationKind: NEAR_ED25519_MPC_OPERATION_KINDS.signTransaction
|
|
21497
|
-
});
|
|
21498
|
-
if (!validated.ok) return validationFailure(validated);
|
|
21499
|
-
walletIdRaw = String(validated.admission.context.authorization.session.walletId);
|
|
21500
|
-
authorization = {
|
|
21501
|
-
kind: "wallet_auth_method",
|
|
21502
|
-
walletAuthMethodId: validated.admission.context.authorization.session.walletAuthMethodId
|
|
21503
|
-
};
|
|
21504
|
-
} else {
|
|
21505
|
-
const validated = await validateRouterAbEcdsaDerivationWalletSessionInputs({
|
|
21506
|
-
materialActivation: routerAbMpcMaterialActivationRefToWire(request.expectedMaterialActivation),
|
|
21507
|
-
headers,
|
|
21508
|
-
authorizationSessions: ctx.service.authorizationSessions,
|
|
21509
|
-
operationKind: EVM_ECDSA_MPC_OPERATION_KINDS.signTransaction
|
|
21510
|
-
});
|
|
21511
|
-
if (!validated.ok) return validationFailure(validated);
|
|
21512
|
-
if (validated.kind === "wallet_session_operation_credential_exhausted_candidate_v1") return validationFailure(walletSessionFailure("wallet_session_unavailable"));
|
|
21513
|
-
walletIdRaw = String(validated.admission.context.authorization.session.walletId);
|
|
21514
|
-
authorization = {
|
|
21515
|
-
kind: "wallet_auth_method",
|
|
21516
|
-
walletAuthMethodId: validated.admission.context.authorization.session.walletAuthMethodId
|
|
21517
|
-
};
|
|
21518
|
-
}
|
|
21519
|
-
const walletId = parseWalletId(walletIdRaw);
|
|
21520
|
-
if (!walletId.ok) return validationFailure({
|
|
21521
|
-
code: WALLET_SESSION_FAILURE_CODES.invalid,
|
|
21522
|
-
message: "Wallet Session wallet identity is invalid"
|
|
21449
|
+
const validated = await validateRouterAbEcdsaDerivationWalletSessionInputs({
|
|
21450
|
+
materialActivation: routerAbMpcMaterialActivationRefToWire(request.expectedMaterialActivation),
|
|
21451
|
+
headers,
|
|
21452
|
+
authorizationSessions: ctx.service.authorizationSessions,
|
|
21453
|
+
operationKind: EVM_ECDSA_MPC_OPERATION_KINDS.signTransaction
|
|
21523
21454
|
});
|
|
21455
|
+
if (!validated.ok) return validationFailure(validated);
|
|
21456
|
+
if (validated.kind === "wallet_session_operation_credential_exhausted_candidate_v1") return validationFailure(walletSessionFailure("wallet_session_unavailable"));
|
|
21457
|
+
const session = validated.admission.context.authorization.session;
|
|
21524
21458
|
let resolved;
|
|
21525
21459
|
try {
|
|
21526
21460
|
resolved = await ctx.service.walletRegistration.resolveActiveOwnerWalletExecutionLane({
|
|
21527
|
-
walletId: walletId
|
|
21461
|
+
walletId: session.walletId,
|
|
21528
21462
|
expectedMaterialActivation: request.expectedMaterialActivation,
|
|
21529
|
-
authorization
|
|
21463
|
+
authorization: {
|
|
21464
|
+
kind: "wallet_auth_method",
|
|
21465
|
+
walletAuthMethodId: session.walletAuthMethodId
|
|
21466
|
+
}
|
|
21530
21467
|
});
|
|
21531
21468
|
} catch {
|
|
21532
21469
|
return json$1({
|
|
@@ -21652,23 +21589,15 @@ function parseOptionalPositiveInteger(raw, fieldName) {
|
|
|
21652
21589
|
value: Math.floor(value)
|
|
21653
21590
|
};
|
|
21654
21591
|
}
|
|
21655
|
-
function parseAuthProviderAction(input) {
|
|
21656
|
-
const provider = normalizeOptionalTrimmedString(input.provider);
|
|
21657
|
-
const action = normalizeOptionalTrimmedString(input.action);
|
|
21658
|
-
if (provider === "passkey" && action === "options") return { kind: "passkey_options" };
|
|
21659
|
-
if (provider === "passkey" && action === "verify") return { kind: "passkey_verify" };
|
|
21660
|
-
if (provider === "google" && action === "options") return { kind: "google_options" };
|
|
21661
|
-
if (provider === "google" && action === "verify") return { kind: "google_verify" };
|
|
21662
|
-
if (provider === "github" && action === "options") return { kind: "github_options" };
|
|
21663
|
-
return null;
|
|
21664
|
-
}
|
|
21665
21592
|
function parseAuthProviderActionPath(pathname) {
|
|
21666
|
-
|
|
21667
|
-
|
|
21668
|
-
|
|
21669
|
-
|
|
21670
|
-
|
|
21671
|
-
|
|
21593
|
+
switch (pathname) {
|
|
21594
|
+
case "/auth/passkey/options": return { kind: "passkey_options" };
|
|
21595
|
+
case "/auth/passkey/verify": return { kind: "passkey_verify" };
|
|
21596
|
+
case "/auth/google/options": return { kind: "google_options" };
|
|
21597
|
+
case "/auth/google/verify": return { kind: "google_verify" };
|
|
21598
|
+
case "/auth/github/options": return { kind: "github_options" };
|
|
21599
|
+
default: return null;
|
|
21600
|
+
}
|
|
21672
21601
|
}
|
|
21673
21602
|
function parsePasskeyLoginOptionsRequest(raw) {
|
|
21674
21603
|
const body = requireJsonObject(raw);
|
|
@@ -21963,6 +21892,8 @@ async function handleAuth(ctx) {
|
|
|
21963
21892
|
const parsed = parsePasskeyLoginOptionsRequest(await readJson(ctx.request));
|
|
21964
21893
|
if (!parsed.ok) return json$1(parsed.body, { status: parsed.status });
|
|
21965
21894
|
const result = await ctx.service.webAuthn.createWebAuthnLoginOptions(parsed.request);
|
|
21895
|
+
if (result.code === "wallet_home_unavailable") return json$1(result, { status: 503 });
|
|
21896
|
+
if (result.code === "wallet_home_conflict") return json$1(result, { status: 409 });
|
|
21966
21897
|
return json$1(result, { status: result.ok ? 200 : result.code === "internal" ? 500 : 400 });
|
|
21967
21898
|
}
|
|
21968
21899
|
case "passkey_verify": {
|
|
@@ -22015,28 +21946,6 @@ async function handleAuth(ctx) {
|
|
|
22015
21946
|
}
|
|
22016
21947
|
}
|
|
22017
21948
|
//#endregion
|
|
22018
|
-
//#region src/router/transport/fetch/routes/nearPublicKeys.ts
|
|
22019
|
-
async function handleNearPublicKeys(ctx) {
|
|
22020
|
-
if (ctx.method !== "GET") return null;
|
|
22021
|
-
if (ctx.pathname !== "/near/public-keys") return null;
|
|
22022
|
-
try {
|
|
22023
|
-
const token = extractBearerCredential(ctx.request.headers);
|
|
22024
|
-
if (!token) return jsonFailure(401, "unauthorized", "No valid Wallet Session");
|
|
22025
|
-
const nowMs = Date.now();
|
|
22026
|
-
const exact = await ctx.service.authorizationSessions.readWalletSessionAuthorizationV2ByOperationCredential({
|
|
22027
|
-
tenantId: ctx.service.authorizationSessions.tenantId,
|
|
22028
|
-
token,
|
|
22029
|
-
nowMs
|
|
22030
|
-
});
|
|
22031
|
-
if (!exact) return jsonFailure(401, "unauthorized", "No valid Wallet Session");
|
|
22032
|
-
const result = await ctx.service.nearFunding.listNearPublicKeysForUser({ userId: String(exact.authorization.session.walletId) });
|
|
22033
|
-
if (!result.ok) return json$1(result, { status: result.code === "not_supported" ? 501 : result.code === "invalid_args" ? 400 : 500 });
|
|
22034
|
-
return json$1(result, { status: 200 });
|
|
22035
|
-
} catch (e) {
|
|
22036
|
-
return jsonFailure(500, "internal", e?.message || "Internal error");
|
|
22037
|
-
}
|
|
22038
|
-
}
|
|
22039
|
-
//#endregion
|
|
22040
21949
|
//#region src/router/framework/ror/normalize.ts
|
|
22041
21950
|
function sanitizeRorOrigins(origins) {
|
|
22042
21951
|
const list = Array.isArray(origins) ? origins : [];
|
|
@@ -22078,77 +21987,208 @@ function normalizeWellKnownSigningSessionSealCapabilities(value) {
|
|
|
22078
21987
|
currentKeyVersion
|
|
22079
21988
|
};
|
|
22080
21989
|
}
|
|
22081
|
-
function resolveWellKnownSigningSessionSealCapabilities(signingSessionSealOptionsRaw) {
|
|
22082
|
-
if (!signingSessionSealOptionsRaw || typeof signingSessionSealOptionsRaw !== "object") return { mode: "none" };
|
|
22083
|
-
return normalizeWellKnownSigningSessionSealCapabilities(signingSessionSealOptionsRaw.capabilities) || { mode: "none" };
|
|
21990
|
+
function resolveWellKnownSigningSessionSealCapabilities(signingSessionSealOptionsRaw) {
|
|
21991
|
+
if (!signingSessionSealOptionsRaw || typeof signingSessionSealOptionsRaw !== "object") return { mode: "none" };
|
|
21992
|
+
return normalizeWellKnownSigningSessionSealCapabilities(signingSessionSealOptionsRaw.capabilities) || { mode: "none" };
|
|
21993
|
+
}
|
|
21994
|
+
//#endregion
|
|
21995
|
+
//#region src/router/framework/ror/provider.ts
|
|
21996
|
+
function validateRouterApiRorOptions(ror) {
|
|
21997
|
+
if (!ror || typeof ror !== "object") throw new Error("[router.ror] Invalid ROR options: expected object");
|
|
21998
|
+
if (!ror.provider || typeof ror.provider.getAllowedOrigins !== "function") throw new Error("[router.ror] Invalid ROR options: provider.getAllowedOrigins is required");
|
|
21999
|
+
const staticRpId = normalizeOptionalTrimmedString(ror.rpId).toLowerCase();
|
|
22000
|
+
const hasStaticRpId = Boolean(staticRpId);
|
|
22001
|
+
const hostMap = ror.rpIdByHost;
|
|
22002
|
+
const hasHostMap = Boolean(hostMap && typeof hostMap === "object" && Object.keys(hostMap).length > 0);
|
|
22003
|
+
if (hasStaticRpId === hasHostMap) throw new Error("[router.ror] Configure exactly one RP ID strategy: `rpId` or `rpIdByHost`");
|
|
22004
|
+
if (hasHostMap) for (const [rawHost, rawRpId] of Object.entries(hostMap || {})) {
|
|
22005
|
+
const host = normalizeRorHost(rawHost);
|
|
22006
|
+
const rpId = normalizeOptionalTrimmedString(rawRpId).toLowerCase();
|
|
22007
|
+
if (!host || !rpId) throw new Error("[router.ror] Invalid `rpIdByHost` entry: host and rpId must be non-empty strings");
|
|
22008
|
+
}
|
|
22009
|
+
}
|
|
22010
|
+
function resolveRorRpId(input) {
|
|
22011
|
+
const ror = input.ror;
|
|
22012
|
+
if (!ror) return null;
|
|
22013
|
+
const staticRpId = normalizeOptionalTrimmedString(ror.rpId).toLowerCase();
|
|
22014
|
+
if (staticRpId) return staticRpId;
|
|
22015
|
+
const hostMap = ror.rpIdByHost;
|
|
22016
|
+
if (!hostMap || typeof hostMap !== "object") return null;
|
|
22017
|
+
const host = normalizeRorHost(input.host);
|
|
22018
|
+
if (!host) return null;
|
|
22019
|
+
return normalizeOptionalTrimmedString(hostMap[host]).toLowerCase() || null;
|
|
22020
|
+
}
|
|
22021
|
+
//#endregion
|
|
22022
|
+
//#region src/router/transport/fetch/routes/wellKnown.ts
|
|
22023
|
+
async function handleWellKnown(ctx) {
|
|
22024
|
+
if (ctx.method !== "GET") return null;
|
|
22025
|
+
if (ctx.pathname === "/.well-known/router-ab/keyset" || ctx.pathname === `/.well-known/router-ab/keyset/` || ctx.pathname === "/router-ab/keyset" || ctx.pathname === `/router-ab/keyset/`) {
|
|
22026
|
+
const keyset = ctx.opts.routerAbPublicKeyset;
|
|
22027
|
+
if (!keyset) return json$1({
|
|
22028
|
+
ok: false,
|
|
22029
|
+
code: "router_ab_public_keyset_not_configured",
|
|
22030
|
+
message: "Router A/B public keyset is not configured"
|
|
22031
|
+
}, {
|
|
22032
|
+
status: 404,
|
|
22033
|
+
headers: { "Cache-Control": "max-age=60, stale-while-revalidate=600" }
|
|
22034
|
+
});
|
|
22035
|
+
return json$1(keyset, {
|
|
22036
|
+
status: 200,
|
|
22037
|
+
headers: { "Cache-Control": "max-age=60, stale-while-revalidate=600" }
|
|
22038
|
+
});
|
|
22039
|
+
}
|
|
22040
|
+
if (ctx.pathname !== "/.well-known/webauthn" && ctx.pathname !== "/.well-known/webauthn/") return null;
|
|
22041
|
+
let origins = [];
|
|
22042
|
+
const signingSessionSeal = resolveWellKnownSigningSessionSealCapabilities(ctx.opts.signingSessionSeal);
|
|
22043
|
+
try {
|
|
22044
|
+
const host = normalizeRorHost(ctx.request.headers.get("x-forwarded-host") || ctx.request.headers.get("host") || ctx.url.hostname);
|
|
22045
|
+
const rpId = resolveRorRpId({
|
|
22046
|
+
ror: ctx.opts.ror,
|
|
22047
|
+
host: host || void 0
|
|
22048
|
+
});
|
|
22049
|
+
origins = rpId && ctx.opts.ror ? sanitizeRorOrigins(await ctx.opts.ror.provider.getAllowedOrigins({
|
|
22050
|
+
rpId,
|
|
22051
|
+
...host ? { host } : {}
|
|
22052
|
+
})) : [];
|
|
22053
|
+
} catch {}
|
|
22054
|
+
return json$1({
|
|
22055
|
+
origins,
|
|
22056
|
+
capabilities: { signingSessionSeal }
|
|
22057
|
+
}, {
|
|
22058
|
+
status: 200,
|
|
22059
|
+
headers: { "Cache-Control": "max-age=60, stale-while-revalidate=600" }
|
|
22060
|
+
});
|
|
22061
|
+
}
|
|
22062
|
+
//#endregion
|
|
22063
|
+
//#region src/router/transport/fetch/routes/deviceLinkingResponses.ts
|
|
22064
|
+
function projectLinkSessionStateV1(state) {
|
|
22065
|
+
switch (state.state) {
|
|
22066
|
+
case "displaying_qr": return { state: "displaying_qr" };
|
|
22067
|
+
case "claimed":
|
|
22068
|
+
case "awaiting_target_factor":
|
|
22069
|
+
case "awaiting_source_contribution":
|
|
22070
|
+
case "provisioning": return {
|
|
22071
|
+
state: state.state,
|
|
22072
|
+
deviceId: state.deviceId
|
|
22073
|
+
};
|
|
22074
|
+
case "authority_pending_local_install": return {
|
|
22075
|
+
state: "authority_pending_local_install",
|
|
22076
|
+
deviceId: state.deviceId,
|
|
22077
|
+
authorityId: state.authorityId,
|
|
22078
|
+
packageSetDigestB64u: state.packageSetDigestB64u
|
|
22079
|
+
};
|
|
22080
|
+
case "active": return {
|
|
22081
|
+
state: "active",
|
|
22082
|
+
deviceId: state.deviceId,
|
|
22083
|
+
authorityId: state.authorityId,
|
|
22084
|
+
activatedAtMs: state.activatedAtMs
|
|
22085
|
+
};
|
|
22086
|
+
case "failed_before_commit": return {
|
|
22087
|
+
state: "failed_before_commit",
|
|
22088
|
+
error: state.error
|
|
22089
|
+
};
|
|
22090
|
+
case "cancelled": return {
|
|
22091
|
+
state: "cancelled",
|
|
22092
|
+
cancelledAtMs: state.cancelledAtMs
|
|
22093
|
+
};
|
|
22094
|
+
case "expired": return {
|
|
22095
|
+
state: "expired",
|
|
22096
|
+
expiredAtMs: state.expiredAtMs
|
|
22097
|
+
};
|
|
22098
|
+
default: return assertNeverLinkSessionStateV1(state);
|
|
22099
|
+
}
|
|
22100
|
+
}
|
|
22101
|
+
function projectSession(record) {
|
|
22102
|
+
return {
|
|
22103
|
+
kind: "linked_device_session_projection_v1",
|
|
22104
|
+
linkSessionId: record.linkSessionId,
|
|
22105
|
+
qrPayload: record.qrPayload,
|
|
22106
|
+
revision: record.revision,
|
|
22107
|
+
createdAtMs: record.createdAtMs,
|
|
22108
|
+
updatedAtMs: record.updatedAtMs,
|
|
22109
|
+
state: projectLinkSessionStateV1(record.state)
|
|
22110
|
+
};
|
|
22111
|
+
}
|
|
22112
|
+
function invalidStateResponse(record) {
|
|
22113
|
+
return json$1({
|
|
22114
|
+
ok: false,
|
|
22115
|
+
outcome: "invalid_state",
|
|
22116
|
+
state: record.state.state,
|
|
22117
|
+
session: projectSession(record)
|
|
22118
|
+
}, { status: 409 });
|
|
22119
|
+
}
|
|
22120
|
+
function sessionProjectionResponse(record, outcome) {
|
|
22121
|
+
return json$1({
|
|
22122
|
+
ok: true,
|
|
22123
|
+
outcome,
|
|
22124
|
+
session: projectSession(record)
|
|
22125
|
+
}, { status: 200 });
|
|
22126
|
+
}
|
|
22127
|
+
function targetCredentialResultResponse(record, outcome, targetCredential) {
|
|
22128
|
+
return json$1({
|
|
22129
|
+
ok: true,
|
|
22130
|
+
outcome,
|
|
22131
|
+
targetCredential,
|
|
22132
|
+
session: projectSession(record)
|
|
22133
|
+
}, { status: 200 });
|
|
22134
|
+
}
|
|
22135
|
+
function exportRootWriteResponse(result) {
|
|
22136
|
+
return result.outcome === "conflict" ? json$1({
|
|
22137
|
+
ok: false,
|
|
22138
|
+
code: result.reason ?? "conflict",
|
|
22139
|
+
message: "export-root relay conflict"
|
|
22140
|
+
}, { status: 409 }) : json$1({
|
|
22141
|
+
ok: true,
|
|
22142
|
+
outcome: result.outcome
|
|
22143
|
+
}, { status: 200 });
|
|
22144
|
+
}
|
|
22145
|
+
function invalidInputResponse(message) {
|
|
22146
|
+
return json$1({
|
|
22147
|
+
ok: false,
|
|
22148
|
+
outcome: "invalid_input",
|
|
22149
|
+
code: "invalid_input",
|
|
22150
|
+
message
|
|
22151
|
+
}, { status: 400 });
|
|
22152
|
+
}
|
|
22153
|
+
function notSupportedResponse(message = "Device linking is not configured") {
|
|
22154
|
+
return json$1({
|
|
22155
|
+
ok: false,
|
|
22156
|
+
code: "not_supported",
|
|
22157
|
+
message
|
|
22158
|
+
}, { status: 501 });
|
|
22084
22159
|
}
|
|
22085
|
-
|
|
22086
|
-
|
|
22087
|
-
|
|
22088
|
-
|
|
22089
|
-
|
|
22090
|
-
|
|
22091
|
-
const hasStaticRpId = Boolean(staticRpId);
|
|
22092
|
-
const hostMap = ror.rpIdByHost;
|
|
22093
|
-
const hasHostMap = Boolean(hostMap && typeof hostMap === "object" && Object.keys(hostMap).length > 0);
|
|
22094
|
-
if (hasStaticRpId === hasHostMap) throw new Error("[router.ror] Configure exactly one RP ID strategy: `rpId` or `rpIdByHost`");
|
|
22095
|
-
if (hasHostMap) for (const [rawHost, rawRpId] of Object.entries(hostMap || {})) {
|
|
22096
|
-
const host = normalizeRorHost(rawHost);
|
|
22097
|
-
const rpId = normalizeOptionalTrimmedString(rawRpId).toLowerCase();
|
|
22098
|
-
if (!host || !rpId) throw new Error("[router.ror] Invalid `rpIdByHost` entry: host and rpId must be non-empty strings");
|
|
22099
|
-
}
|
|
22160
|
+
function notFoundResponse() {
|
|
22161
|
+
return json$1({
|
|
22162
|
+
ok: false,
|
|
22163
|
+
code: "not_found",
|
|
22164
|
+
message: "Linked-device session not found"
|
|
22165
|
+
}, { status: 404 });
|
|
22100
22166
|
}
|
|
22101
|
-
function
|
|
22102
|
-
|
|
22103
|
-
|
|
22104
|
-
|
|
22105
|
-
|
|
22106
|
-
|
|
22107
|
-
if (!hostMap || typeof hostMap !== "object") return null;
|
|
22108
|
-
const host = normalizeRorHost(input.host);
|
|
22109
|
-
if (!host) return null;
|
|
22110
|
-
return normalizeOptionalTrimmedString(hostMap[host]).toLowerCase() || null;
|
|
22167
|
+
function methodNotAllowedResponse$2() {
|
|
22168
|
+
return json$1({
|
|
22169
|
+
ok: false,
|
|
22170
|
+
code: "method_not_allowed",
|
|
22171
|
+
message: "Method is not allowed"
|
|
22172
|
+
}, { status: 405 });
|
|
22111
22173
|
}
|
|
22112
|
-
|
|
22113
|
-
|
|
22114
|
-
|
|
22115
|
-
|
|
22116
|
-
|
|
22117
|
-
|
|
22118
|
-
if (!keyset) return json$1({
|
|
22119
|
-
ok: false,
|
|
22120
|
-
code: "router_ab_public_keyset_not_configured",
|
|
22121
|
-
message: "Router A/B public keyset is not configured"
|
|
22122
|
-
}, {
|
|
22123
|
-
status: 404,
|
|
22124
|
-
headers: { "Cache-Control": "max-age=60, stale-while-revalidate=600" }
|
|
22125
|
-
});
|
|
22126
|
-
return json$1(keyset, {
|
|
22127
|
-
status: 200,
|
|
22128
|
-
headers: { "Cache-Control": "max-age=60, stale-while-revalidate=600" }
|
|
22129
|
-
});
|
|
22130
|
-
}
|
|
22131
|
-
if (ctx.pathname !== "/.well-known/webauthn" && ctx.pathname !== "/.well-known/webauthn/") return null;
|
|
22132
|
-
let origins = [];
|
|
22133
|
-
const signingSessionSeal = resolveWellKnownSigningSessionSealCapabilities(ctx.opts.signingSessionSeal);
|
|
22134
|
-
try {
|
|
22135
|
-
const host = normalizeRorHost(ctx.request.headers.get("x-forwarded-host") || ctx.request.headers.get("host") || ctx.url.hostname);
|
|
22136
|
-
const rpId = resolveRorRpId({
|
|
22137
|
-
ror: ctx.opts.ror,
|
|
22138
|
-
host: host || void 0
|
|
22139
|
-
});
|
|
22140
|
-
origins = rpId && ctx.opts.ror ? sanitizeRorOrigins(await ctx.opts.ror.provider.getAllowedOrigins({
|
|
22141
|
-
rpId,
|
|
22142
|
-
...host ? { host } : {}
|
|
22143
|
-
})) : [];
|
|
22144
|
-
} catch {}
|
|
22174
|
+
function authDeniedResponse$2(result) {
|
|
22175
|
+
if (result.code === "unavailable") return json$1({
|
|
22176
|
+
ok: false,
|
|
22177
|
+
code: result.code,
|
|
22178
|
+
message: result.message
|
|
22179
|
+
}, { status: 503 });
|
|
22145
22180
|
return json$1({
|
|
22146
|
-
|
|
22147
|
-
|
|
22148
|
-
|
|
22149
|
-
|
|
22150
|
-
|
|
22151
|
-
|
|
22181
|
+
ok: false,
|
|
22182
|
+
outcome: "unauthorized",
|
|
22183
|
+
code: result.code,
|
|
22184
|
+
message: result.message
|
|
22185
|
+
}, { status: result.code === "expired" ? 410 : 401 });
|
|
22186
|
+
}
|
|
22187
|
+
//#endregion
|
|
22188
|
+
//#region src/core/deviceLinking/linkedDeviceBootstrap.ts
|
|
22189
|
+
function linkedDeviceBootstrapFailure(error) {
|
|
22190
|
+
if (error && typeof error === "object" && "code" in error && (error.code === "home_conflict" || error.code === "home_unavailable")) return error.code;
|
|
22191
|
+
return null;
|
|
22152
22192
|
}
|
|
22153
22193
|
//#endregion
|
|
22154
22194
|
//#region ../shared-ts/src/utils/exactKeys.ts
|
|
@@ -22272,6 +22312,11 @@ async function handleDeviceLinking(ctx) {
|
|
|
22272
22312
|
default: return assertNever$1(action);
|
|
22273
22313
|
}
|
|
22274
22314
|
} catch (error) {
|
|
22315
|
+
const bootstrapFailure = linkedDeviceBootstrapFailure(error);
|
|
22316
|
+
if (bootstrapFailure) return sessionResultResponse({
|
|
22317
|
+
outcome: bootstrapFailure,
|
|
22318
|
+
message: "Linked-device bootstrap authority failed"
|
|
22319
|
+
});
|
|
22275
22320
|
if (error instanceof DeviceLinkingInputError) return invalidInputResponse(error.message);
|
|
22276
22321
|
return json$1({
|
|
22277
22322
|
ok: false,
|
|
@@ -22283,7 +22328,7 @@ async function handleDeviceLinking(ctx) {
|
|
|
22283
22328
|
async function handleCreate(ctx, service, nowMs) {
|
|
22284
22329
|
if (ctx.method !== "POST") return methodNotAllowedResponse$2();
|
|
22285
22330
|
const bodyDigestB64u = await requestBodyDigest$1(ctx.request);
|
|
22286
|
-
const rawBody = await
|
|
22331
|
+
const rawBody = await readJson(ctx.request);
|
|
22287
22332
|
const body = parseBoundary$1(() => parseCreateRequest(rawBody));
|
|
22288
22333
|
const keyDigest = await computeDevicePublicKeyDigestB64u(body.payload.devicePublicKeyB64u);
|
|
22289
22334
|
const proof = parseBoundary$1(() => parseRequestProofHeader(ctx.request));
|
|
@@ -22360,7 +22405,7 @@ async function handleApproval(ctx, service, rawLinkSessionId, nowMs) {
|
|
|
22360
22405
|
});
|
|
22361
22406
|
if (!session) return notFoundResponse();
|
|
22362
22407
|
const ownerMismatch = requireOwnerMatchesClaimedWallet(authentication.owner, session);
|
|
22363
|
-
if (ownerMismatch) return ownerMismatch;
|
|
22408
|
+
if (ownerMismatch) return authDeniedResponse$2(ownerMismatch);
|
|
22364
22409
|
if (authentication.owner.walletId !== approval.walletId) return authDeniedResponse$2({
|
|
22365
22410
|
kind: "denied",
|
|
22366
22411
|
code: "unauthorized",
|
|
@@ -22444,6 +22489,7 @@ async function handleCredential(ctx, service, rawLinkSessionId, nowMs) {
|
|
|
22444
22489
|
async function handleSourceContributionPreparation(ctx, service, rawLinkSessionId, nowMs) {
|
|
22445
22490
|
const owner = await authenticateOwnerForSession(ctx, service, parseSessionId(rawLinkSessionId), nowMs);
|
|
22446
22491
|
if (owner.kind !== "authorized") return ownerSessionResponse(owner);
|
|
22492
|
+
if (isLinkSessionTerminalFailureV1(owner.session.state)) return invalidStateResponse(owner.session);
|
|
22447
22493
|
if (ctx.method !== "GET") return methodNotAllowedResponse$2();
|
|
22448
22494
|
const preparation = owner.session.sourceContributionPreparation;
|
|
22449
22495
|
if (!preparation) return new Response(null, { status: 204 });
|
|
@@ -22494,10 +22540,6 @@ async function handleSourceContribution(ctx, service, rawLinkSessionId, nowMs) {
|
|
|
22494
22540
|
}));
|
|
22495
22541
|
return sessionProjectionResponse(committed.session, committed.kind === "replayed" ? "replayed" : recorded.outcome);
|
|
22496
22542
|
}
|
|
22497
|
-
/**
|
|
22498
|
-
* A precommit failure's reason is a single token. The installer's message
|
|
22499
|
-
* keeps its words, joined, so the session still says what failed.
|
|
22500
|
-
*/
|
|
22501
22543
|
function precommitFailureReasonV1(message) {
|
|
22502
22544
|
const token = message.trim().replace(/\s+/g, "_").replace(/[\u0000-\u001f\u007f]/g, "");
|
|
22503
22545
|
return token.length > 0 ? token : "authority_commit_failed";
|
|
@@ -22506,6 +22548,7 @@ async function handleSourceContributionExecute(ctx, service, rawLinkSessionId, n
|
|
|
22506
22548
|
if (ctx.method !== "POST") return methodNotAllowedResponse$2();
|
|
22507
22549
|
const owner = await authenticateOwnerForSession(ctx, service, parseSessionId(rawLinkSessionId), nowMs);
|
|
22508
22550
|
if (owner.kind !== "authorized") return ownerSessionResponse(owner);
|
|
22551
|
+
if (isLinkSessionTerminalFailureV1(owner.session.state)) return invalidStateResponse(owner.session);
|
|
22509
22552
|
const router = service.sourceContributionRouter;
|
|
22510
22553
|
if (!router) return notSupportedResponse("Ed25519 source-preserving linking is not configured");
|
|
22511
22554
|
const preparation = requireEd25519SourceContributionPreparation(owner.session);
|
|
@@ -22578,8 +22621,6 @@ async function handleEmailOtpBaseFactor(ctx, service, rawLinkSessionId, nowMs) {
|
|
|
22578
22621
|
const authenticated = await authenticateOwnerForSession(ctx, service, parseSessionId(rawLinkSessionId), nowMs);
|
|
22579
22622
|
if (authenticated.kind !== "authorized") return ownerSessionResponse(authenticated);
|
|
22580
22623
|
const session = authenticated.session;
|
|
22581
|
-
const ownerMismatch = requireOwnerMatchesClaimedWallet(authenticated.owner, session);
|
|
22582
|
-
if (ownerMismatch) return ownerMismatch;
|
|
22583
22624
|
if (session.state.state !== "claimed" || session.qrPayload.targetFactor.kind !== "email_otp" || !session.claimTranscript) return invalidStateResponse(session);
|
|
22584
22625
|
const walletId = session.claimTranscript.value.walletId;
|
|
22585
22626
|
const request = parseBoundary$1(() => parseLinkedDeviceEmailOtpBaseFactorRequestV1(authenticated.body));
|
|
@@ -22607,8 +22648,6 @@ async function handleOwnerCancel(ctx, service, rawLinkSessionId, nowMs) {
|
|
|
22607
22648
|
if (authenticated.kind !== "authorized") return ownerSessionResponse(authenticated);
|
|
22608
22649
|
parseBoundary$1(() => parseOwnerCancelRequest(authenticated.body));
|
|
22609
22650
|
const session = authenticated.session;
|
|
22610
|
-
const ownerMismatch = requireOwnerMatchesClaimedWallet(authenticated.owner, session);
|
|
22611
|
-
if (ownerMismatch) return ownerMismatch;
|
|
22612
22651
|
if (session.state.state === "cancelled") return sessionProjectionResponse(session, "replayed");
|
|
22613
22652
|
return sessionResultResponse(await service.sessionService.cancelSessionV1({
|
|
22614
22653
|
linkSessionId,
|
|
@@ -22656,6 +22695,7 @@ async function handleExportRootRecipient(ctx, service, rawLinkSessionId, nowMs)
|
|
|
22656
22695
|
if (ctx.method === "GET") {
|
|
22657
22696
|
const owner = await authenticateOwnerForSession(ctx, service, sessionId, nowMs);
|
|
22658
22697
|
if (owner.kind !== "authorized") return ownerSessionResponse(owner);
|
|
22698
|
+
if (isLinkSessionTerminalFailureV1(owner.session.state)) return invalidStateResponse(owner.session);
|
|
22659
22699
|
const transfer = await port.readTransferV1(sessionId);
|
|
22660
22700
|
return transfer ? json$1(transfer.recipient, { status: 200 }) : new Response(null, { status: 204 });
|
|
22661
22701
|
}
|
|
@@ -22663,8 +22703,14 @@ async function handleExportRootRecipient(ctx, service, rawLinkSessionId, nowMs)
|
|
|
22663
22703
|
const authenticated = await authenticateDeviceForSession(ctx, service, rawLinkSessionId, nowMs);
|
|
22664
22704
|
if (authenticated.kind === "denied") return authDeniedResponse$2(authenticated);
|
|
22665
22705
|
if (authenticated.kind === "not_found") return notFoundResponse();
|
|
22706
|
+
if (isLinkSessionTerminalFailureV1(authenticated.session.state)) return invalidStateResponse(authenticated.session);
|
|
22666
22707
|
const recipient = parseBoundary$1(() => parseLinkedDeviceEd25519ExportRootRecipientV1(authenticated.body));
|
|
22667
22708
|
if (recipient.linkSessionId !== authenticated.linkSessionId) return invalidInputResponse("link session id does not match route");
|
|
22709
|
+
const session = authenticated.session;
|
|
22710
|
+
const preparation = await readTargetPreparation(service, session, requireApproval(session), { access: "replay_only" }, nowMs);
|
|
22711
|
+
if (preparation.kind === "conflict") return invalidStateResponse(session);
|
|
22712
|
+
const facts = preparation.ed25519ExportRoot;
|
|
22713
|
+
if (!facts || recipient.walletId !== preparation.walletId || recipient.enrollmentId !== preparation.enrollmentId || recipient.deviceId !== preparation.deviceId || recipient.targetFactor.kind !== preparation.targetFactor.kind || recipient.walletKeyId !== facts.walletKeyId || recipient.revocationEpoch !== facts.revocationEpoch || recipient.applicationBindingDigestB64u !== facts.applicationBindingDigestB64u || recipient.registeredPublicKeyB64u !== facts.registeredPublicKeyB64u) return invalidInputResponse("export-root recipient does not match target preparation");
|
|
22668
22714
|
return exportRootWriteResponse(await port.registerRecipientV1({ recipient }));
|
|
22669
22715
|
}
|
|
22670
22716
|
async function handleExportRootPackage(ctx, service, rawLinkSessionId, nowMs) {
|
|
@@ -22675,12 +22721,14 @@ async function handleExportRootPackage(ctx, service, rawLinkSessionId, nowMs) {
|
|
|
22675
22721
|
const authenticated = await authenticateDeviceForSession(ctx, service, rawLinkSessionId, nowMs);
|
|
22676
22722
|
if (authenticated.kind === "denied") return authDeniedResponse$2(authenticated);
|
|
22677
22723
|
if (authenticated.kind === "not_found") return notFoundResponse();
|
|
22724
|
+
if (isLinkSessionTerminalFailureV1(authenticated.session.state)) return invalidStateResponse(authenticated.session);
|
|
22678
22725
|
const transfer = await port.readTransferV1(sessionId);
|
|
22679
22726
|
return transfer?.state === "sealed" ? json$1(transfer.package, { status: 200 }) : new Response(null, { status: 204 });
|
|
22680
22727
|
}
|
|
22681
22728
|
if (ctx.method !== "POST") return methodNotAllowedResponse$2();
|
|
22682
22729
|
const owner = await authenticateOwnerForSession(ctx, service, sessionId, nowMs);
|
|
22683
22730
|
if (owner.kind !== "authorized") return ownerSessionResponse(owner);
|
|
22731
|
+
if (isLinkSessionTerminalFailureV1(owner.session.state)) return invalidStateResponse(owner.session);
|
|
22684
22732
|
const submission = parseBoundary$1(() => parseLinkedDeviceEd25519ExportRootSubmissionV1(owner.body));
|
|
22685
22733
|
if (submission.linkSessionId !== sessionId) return invalidInputResponse("link session id does not match route");
|
|
22686
22734
|
return exportRootWriteResponse(await port.submitPackageV1({
|
|
@@ -22692,7 +22740,7 @@ async function handleReceipt(ctx, service, rawLinkSessionId, nowMs) {
|
|
|
22692
22740
|
if (!service.installationReceipt) return notSupportedResponse("Installation receipt is not configured");
|
|
22693
22741
|
if (ctx.method !== "POST") return methodNotAllowedResponse$2();
|
|
22694
22742
|
const linkSessionId = parseSessionId(rawLinkSessionId);
|
|
22695
|
-
const rawBody = await
|
|
22743
|
+
const rawBody = await readJson(ctx.request.clone());
|
|
22696
22744
|
if (isFinalActivationAcknowledgement(rawBody)) {
|
|
22697
22745
|
const acknowledgement = parseBoundary$1(() => parseLocalAuthorityActivationFinalAckV1(rawBody));
|
|
22698
22746
|
if (acknowledgement.linkSessionId !== linkSessionId) return invalidInputResponse("activation acknowledgement session does not match the route");
|
|
@@ -22878,6 +22926,8 @@ async function authenticateOwnerForSession(ctx, service, linkSessionId, nowMs) {
|
|
|
22878
22926
|
});
|
|
22879
22927
|
if (!session) return { kind: "not_found" };
|
|
22880
22928
|
validateOwnerRequestBinding(authentication.binding, ctx, bodyDigestB64u, nowMs);
|
|
22929
|
+
const ownerMismatch = requireOwnerMatchesClaimedWallet(authentication.owner, session);
|
|
22930
|
+
if (ownerMismatch) return ownerMismatch;
|
|
22881
22931
|
return {
|
|
22882
22932
|
kind: "authorized",
|
|
22883
22933
|
body: authentication.body,
|
|
@@ -23082,69 +23132,6 @@ async function authenticateTargetPasskeyOriginV1(ctx, routeId) {
|
|
|
23082
23132
|
expectedOrigin
|
|
23083
23133
|
};
|
|
23084
23134
|
}
|
|
23085
|
-
function projectLinkSessionStateV1(state) {
|
|
23086
|
-
switch (state.state) {
|
|
23087
|
-
case "displaying_qr": return { state: "displaying_qr" };
|
|
23088
|
-
case "claimed":
|
|
23089
|
-
case "awaiting_target_factor":
|
|
23090
|
-
case "awaiting_source_contribution":
|
|
23091
|
-
case "provisioning": return {
|
|
23092
|
-
state: state.state,
|
|
23093
|
-
deviceId: state.deviceId
|
|
23094
|
-
};
|
|
23095
|
-
case "authority_pending_local_install": return {
|
|
23096
|
-
state: "authority_pending_local_install",
|
|
23097
|
-
deviceId: state.deviceId,
|
|
23098
|
-
authorityId: state.authorityId,
|
|
23099
|
-
packageSetDigestB64u: state.packageSetDigestB64u
|
|
23100
|
-
};
|
|
23101
|
-
case "active": return {
|
|
23102
|
-
state: "active",
|
|
23103
|
-
deviceId: state.deviceId,
|
|
23104
|
-
authorityId: state.authorityId,
|
|
23105
|
-
activatedAtMs: state.activatedAtMs
|
|
23106
|
-
};
|
|
23107
|
-
case "failed_before_commit": return {
|
|
23108
|
-
state: "failed_before_commit",
|
|
23109
|
-
error: state.error
|
|
23110
|
-
};
|
|
23111
|
-
case "cancelled": return {
|
|
23112
|
-
state: "cancelled",
|
|
23113
|
-
cancelledAtMs: state.cancelledAtMs
|
|
23114
|
-
};
|
|
23115
|
-
case "expired": return {
|
|
23116
|
-
state: "expired",
|
|
23117
|
-
expiredAtMs: state.expiredAtMs
|
|
23118
|
-
};
|
|
23119
|
-
default: return assertNeverLinkSessionStateV1(state);
|
|
23120
|
-
}
|
|
23121
|
-
}
|
|
23122
|
-
function projectSession(record) {
|
|
23123
|
-
return {
|
|
23124
|
-
kind: "linked_device_session_projection_v1",
|
|
23125
|
-
linkSessionId: record.linkSessionId,
|
|
23126
|
-
qrPayload: record.qrPayload,
|
|
23127
|
-
revision: record.revision,
|
|
23128
|
-
createdAtMs: record.createdAtMs,
|
|
23129
|
-
updatedAtMs: record.updatedAtMs,
|
|
23130
|
-
state: projectLinkSessionStateV1(record.state)
|
|
23131
|
-
};
|
|
23132
|
-
}
|
|
23133
|
-
function sessionProjectionResponse(record, outcome) {
|
|
23134
|
-
return json$1({
|
|
23135
|
-
ok: true,
|
|
23136
|
-
outcome,
|
|
23137
|
-
session: projectSession(record)
|
|
23138
|
-
}, { status: 200 });
|
|
23139
|
-
}
|
|
23140
|
-
function targetCredentialResultResponse(record, outcome, targetCredential) {
|
|
23141
|
-
return json$1({
|
|
23142
|
-
ok: true,
|
|
23143
|
-
outcome,
|
|
23144
|
-
targetCredential,
|
|
23145
|
-
session: projectSession(record)
|
|
23146
|
-
}, { status: 200 });
|
|
23147
|
-
}
|
|
23148
23135
|
function claimResultResponse(result) {
|
|
23149
23136
|
if (result.outcome !== "applied" && result.outcome !== "replayed") return sessionResultResponse(result);
|
|
23150
23137
|
const claim = result.record.claimTranscript?.value;
|
|
@@ -23173,6 +23160,16 @@ function approvalResultResponse(result) {
|
|
|
23173
23160
|
}
|
|
23174
23161
|
function sessionResultResponse(result) {
|
|
23175
23162
|
switch (result.outcome) {
|
|
23163
|
+
case "home_conflict": return json$1({
|
|
23164
|
+
ok: false,
|
|
23165
|
+
code: "wallet_home_conflict",
|
|
23166
|
+
message: result.message
|
|
23167
|
+
}, { status: 409 });
|
|
23168
|
+
case "home_unavailable": return json$1({
|
|
23169
|
+
ok: false,
|
|
23170
|
+
code: "wallet_home_unavailable",
|
|
23171
|
+
message: result.message
|
|
23172
|
+
}, { status: 503 });
|
|
23176
23173
|
case "applied":
|
|
23177
23174
|
case "replayed": return sessionProjectionResponse(result.record, result.outcome);
|
|
23178
23175
|
case "conflict": return json$1({
|
|
@@ -23213,49 +23210,19 @@ function sessionResultResponse(result) {
|
|
|
23213
23210
|
default: return assertNever$1(result);
|
|
23214
23211
|
}
|
|
23215
23212
|
}
|
|
23216
|
-
function invalidStateResponse(record) {
|
|
23217
|
-
return json$1({
|
|
23218
|
-
ok: false,
|
|
23219
|
-
outcome: "invalid_state",
|
|
23220
|
-
state: record.state.state,
|
|
23221
|
-
session: projectSession(record)
|
|
23222
|
-
}, { status: 409 });
|
|
23223
|
-
}
|
|
23224
|
-
function exportRootWriteResponse(result) {
|
|
23225
|
-
return result.outcome === "conflict" ? json$1({
|
|
23226
|
-
ok: false,
|
|
23227
|
-
code: result.reason ?? "conflict",
|
|
23228
|
-
message: "export-root relay conflict"
|
|
23229
|
-
}, { status: 409 }) : json$1({
|
|
23230
|
-
ok: true,
|
|
23231
|
-
outcome: result.outcome
|
|
23232
|
-
}, { status: 200 });
|
|
23233
|
-
}
|
|
23234
23213
|
function ownerSessionResponse(context) {
|
|
23235
23214
|
return context.kind === "denied" ? authDeniedResponse$2(context) : notFoundResponse();
|
|
23236
23215
|
}
|
|
23237
|
-
/**
|
|
23238
|
-
* The one owner-to-session binding, shared by every owner route on a claimed
|
|
23239
|
-
* session. It runs before any state is disclosed: an authenticated owner of a
|
|
23240
|
-
* DIFFERENT wallet must get the same denial for every state, not a projection
|
|
23241
|
-
* or an invalid-state body. An unclaimed session has no wallet to bind to yet,
|
|
23242
|
-
* so the caller's state checks answer instead.
|
|
23243
|
-
*/
|
|
23244
23216
|
function requireOwnerMatchesClaimedWallet(owner, session) {
|
|
23245
23217
|
const claimWalletId = session.claimTranscript?.value.walletId;
|
|
23246
23218
|
if (claimWalletId === void 0) return null;
|
|
23247
23219
|
if (owner.walletId === claimWalletId) return null;
|
|
23248
|
-
return
|
|
23220
|
+
return {
|
|
23249
23221
|
kind: "denied",
|
|
23250
23222
|
code: "unauthorized",
|
|
23251
23223
|
message: "owner session does not match link wallet"
|
|
23252
|
-
}
|
|
23224
|
+
};
|
|
23253
23225
|
}
|
|
23254
|
-
/**
|
|
23255
|
-
* Approval-time revalidation of the selected Email OTP base method. The same
|
|
23256
|
-
* eligibility question the dedicated base-factor route answers, asked once
|
|
23257
|
-
* more with the id the approval names, so the two paths cannot drift.
|
|
23258
|
-
*/
|
|
23259
23226
|
async function requireSelectedEmailOtpBaseFactorV1(service, session, input) {
|
|
23260
23227
|
const provider = service.emailOtpTargetFactor;
|
|
23261
23228
|
if (!provider) return notSupportedResponse("Email OTP linking is not configured");
|
|
@@ -23274,43 +23241,6 @@ async function requireSelectedEmailOtpBaseFactorV1(service, session, input) {
|
|
|
23274
23241
|
});
|
|
23275
23242
|
return null;
|
|
23276
23243
|
}
|
|
23277
|
-
function authDeniedResponse$2(result) {
|
|
23278
|
-
return json$1({
|
|
23279
|
-
ok: false,
|
|
23280
|
-
outcome: "unauthorized",
|
|
23281
|
-
code: result.code,
|
|
23282
|
-
message: result.message
|
|
23283
|
-
}, { status: result.code === "expired" ? 410 : 401 });
|
|
23284
|
-
}
|
|
23285
|
-
function invalidInputResponse(message) {
|
|
23286
|
-
return json$1({
|
|
23287
|
-
ok: false,
|
|
23288
|
-
outcome: "invalid_input",
|
|
23289
|
-
code: "invalid_input",
|
|
23290
|
-
message
|
|
23291
|
-
}, { status: 400 });
|
|
23292
|
-
}
|
|
23293
|
-
function notSupportedResponse(message = "Device linking is not configured") {
|
|
23294
|
-
return json$1({
|
|
23295
|
-
ok: false,
|
|
23296
|
-
code: "not_supported",
|
|
23297
|
-
message
|
|
23298
|
-
}, { status: 501 });
|
|
23299
|
-
}
|
|
23300
|
-
function notFoundResponse() {
|
|
23301
|
-
return json$1({
|
|
23302
|
-
ok: false,
|
|
23303
|
-
code: "not_found",
|
|
23304
|
-
message: "Linked-device session not found"
|
|
23305
|
-
}, { status: 404 });
|
|
23306
|
-
}
|
|
23307
|
-
function methodNotAllowedResponse$2() {
|
|
23308
|
-
return json$1({
|
|
23309
|
-
ok: false,
|
|
23310
|
-
code: "method_not_allowed",
|
|
23311
|
-
message: "Method is not allowed"
|
|
23312
|
-
}, { status: 405 });
|
|
23313
|
-
}
|
|
23314
23244
|
function parseCreateRequest(raw) {
|
|
23315
23245
|
const record = requireRecord(raw, "device-linking create request");
|
|
23316
23246
|
requireExactKeys$1(record, ["kind", "payload"]);
|
|
@@ -23375,9 +23305,6 @@ function parseB64uBytes(raw, field) {
|
|
|
23375
23305
|
if (bytes.length === 0 || base64UrlEncode(bytes) !== raw) throw new Error(`${field} is not canonical base64url`);
|
|
23376
23306
|
return bytes;
|
|
23377
23307
|
}
|
|
23378
|
-
async function readJsonBody(request) {
|
|
23379
|
-
return await readJson(request);
|
|
23380
|
-
}
|
|
23381
23308
|
function parseBoundary$1(parse) {
|
|
23382
23309
|
try {
|
|
23383
23310
|
return parse();
|
|
@@ -23924,7 +23851,8 @@ function methodNotAllowedResponse() {
|
|
|
23924
23851
|
}, { status: 405 });
|
|
23925
23852
|
}
|
|
23926
23853
|
function authDeniedResponse(value) {
|
|
23927
|
-
|
|
23854
|
+
if (value.code === "unavailable") return jsonFailure(503, value.code, value.message);
|
|
23855
|
+
return jsonFailure(value.code === "invalid" ? 403 : 401, value.code, value.message);
|
|
23928
23856
|
}
|
|
23929
23857
|
//#endregion
|
|
23930
23858
|
//#region src/threshold/session/signingSessionSeal/transport/fetch.ts
|
|
@@ -24330,7 +24258,6 @@ function createFetchRouter(service, opts, runtime) {
|
|
|
24330
24258
|
handleThresholdEcdsa,
|
|
24331
24259
|
handleExactWalletSigningSessionSeal,
|
|
24332
24260
|
handleWebAuthnAuthenticators,
|
|
24333
|
-
handleNearPublicKeys,
|
|
24334
24261
|
handleExactWalletSessionStatus,
|
|
24335
24262
|
handleHostedWalletSessionExchangeIssue,
|
|
24336
24263
|
handleHostedWalletSessionExchangeRedeem,
|
|
@@ -24739,6 +24666,12 @@ async function routerAbEd25519YaoTenantRootWireV1(root) {
|
|
|
24739
24666
|
custody_lineage_b64u: root.custodyLineageB64u
|
|
24740
24667
|
};
|
|
24741
24668
|
}
|
|
24669
|
+
function routerAbEd25519YaoRegistrationSigningRootIdV1(admissionRequest) {
|
|
24670
|
+
return {
|
|
24671
|
+
signing_root_id: admissionRequest.application_binding.signing_root_id,
|
|
24672
|
+
root_share_epoch: admissionRequest.scope.root_share_epoch
|
|
24673
|
+
};
|
|
24674
|
+
}
|
|
24742
24675
|
//#endregion
|
|
24743
24676
|
//#region src/router/domains/ed25519Yao/registration/routerAbEd25519YaoHttpRegistrationBackend.ts
|
|
24744
24677
|
const INTERNAL_AUTH_HEADER = "x-router-ab-internal-service-auth";
|
|
@@ -24946,6 +24879,7 @@ function registrationRouterExecuteRequest(input, tenantRoot) {
|
|
|
24946
24879
|
participant_ids: input.admissionRequest.participant_ids,
|
|
24947
24880
|
target: {
|
|
24948
24881
|
operation: "registration",
|
|
24882
|
+
ownership_generation: input.ownershipGeneration,
|
|
24949
24883
|
binding: input.request.binding,
|
|
24950
24884
|
deriver_a_input: input.request.deriver_a_input,
|
|
24951
24885
|
deriver_b_input: input.request.deriver_b_input
|
|
@@ -24959,6 +24893,7 @@ function recoveryRouterExecuteRequest(input, tenantRoot, attempt) {
|
|
|
24959
24893
|
participant_ids: input.admissionRequest.participant_ids,
|
|
24960
24894
|
target: {
|
|
24961
24895
|
operation: "recovery",
|
|
24896
|
+
ownership_generation: input.ownershipGeneration,
|
|
24962
24897
|
binding: input.request.binding,
|
|
24963
24898
|
attempt,
|
|
24964
24899
|
deriver_a_input: input.request.deriver_a_input,
|
|
@@ -24971,7 +24906,7 @@ async function routerExecuteRequest(input, resolveTenantRoot) {
|
|
|
24971
24906
|
switch (input.operation) {
|
|
24972
24907
|
case "registration": return registrationRouterExecuteRequest(input, await routerAbEd25519YaoTenantRootWireV1(await resolveTenantRoot({
|
|
24973
24908
|
operation: "registration",
|
|
24974
|
-
|
|
24909
|
+
...routerAbEd25519YaoRegistrationSigningRootIdV1(input.admissionRequest)
|
|
24975
24910
|
})));
|
|
24976
24911
|
case "export": return {
|
|
24977
24912
|
tenant_root: await routerAbEd25519YaoTenantRootWireV1(await resolveTenantRoot({
|
|
@@ -24982,6 +24917,7 @@ async function routerExecuteRequest(input, resolveTenantRoot) {
|
|
|
24982
24917
|
participant_ids: input.admissionRequest.participant_ids,
|
|
24983
24918
|
target: {
|
|
24984
24919
|
operation: "export",
|
|
24920
|
+
ownership_generation: input.ownershipGeneration,
|
|
24985
24921
|
binding: input.request.binding,
|
|
24986
24922
|
deriver_a_input: input.request.deriver_a_input,
|
|
24987
24923
|
deriver_b_input: input.request.deriver_b_input
|
|
@@ -25178,11 +25114,12 @@ var RouterAbEd25519YaoHttpRegistrationBackend = class {
|
|
|
25178
25114
|
}
|
|
25179
25115
|
};
|
|
25180
25116
|
}
|
|
25181
|
-
async executeExport(request,
|
|
25117
|
+
async executeExport(request, claim, traceContext) {
|
|
25182
25118
|
return await this.executeRouterRequest({
|
|
25183
25119
|
operation: "export",
|
|
25184
25120
|
request,
|
|
25185
|
-
admissionRequest
|
|
25121
|
+
admissionRequest: claim.admissionRequest,
|
|
25122
|
+
ownershipGeneration: claim.ownershipGeneration
|
|
25186
25123
|
}, false, traceContext);
|
|
25187
25124
|
}
|
|
25188
25125
|
keyset() {
|
|
@@ -25249,34 +25186,37 @@ var RouterAbEd25519YaoHttpRegistrationBackend = class {
|
|
|
25249
25186
|
};
|
|
25250
25187
|
}
|
|
25251
25188
|
}
|
|
25252
|
-
async execute(request, admissionRequest, traceContext) {
|
|
25189
|
+
async execute(request, admissionRequest, ownershipGeneration, traceContext) {
|
|
25253
25190
|
return await this.executeRouterRequest({
|
|
25254
25191
|
operation: "registration",
|
|
25255
25192
|
request,
|
|
25256
|
-
admissionRequest
|
|
25193
|
+
admissionRequest,
|
|
25194
|
+
ownershipGeneration
|
|
25257
25195
|
}, false, traceContext);
|
|
25258
25196
|
}
|
|
25259
|
-
async resolveRegistrationDispatchRoot(
|
|
25197
|
+
async resolveRegistrationDispatchRoot(signingRootId) {
|
|
25260
25198
|
return await routerAbEd25519YaoTenantRootWireV1(await this.config.resolveTenantRoot({
|
|
25261
25199
|
operation: "registration",
|
|
25262
|
-
|
|
25200
|
+
...signingRootId
|
|
25263
25201
|
}));
|
|
25264
25202
|
}
|
|
25265
|
-
async executePinnedRegistration(request,
|
|
25203
|
+
async executePinnedRegistration(request, authority, traceContext) {
|
|
25266
25204
|
const routerInput = {
|
|
25267
25205
|
operation: "registration",
|
|
25268
25206
|
request,
|
|
25269
|
-
admissionRequest
|
|
25207
|
+
admissionRequest: authority.admissionRequest,
|
|
25208
|
+
ownershipGeneration: authority.ownershipGeneration
|
|
25270
25209
|
};
|
|
25271
|
-
return await this.sendRouterRequest(routerInput, registrationRouterExecuteRequest(routerInput, dispatchRoot), traceContext.value, "exact", false);
|
|
25210
|
+
return await this.sendRouterRequest(routerInput, registrationRouterExecuteRequest(routerInput, authority.dispatchRoot), traceContext.value, "exact", false);
|
|
25272
25211
|
}
|
|
25273
25212
|
async consumeRegistration(input) {
|
|
25274
25213
|
let response;
|
|
25275
25214
|
try {
|
|
25276
|
-
response = await this.post(ROUTER_REGISTRATION_CONSUME_PATH, {
|
|
25277
|
-
tenant_root: input.
|
|
25278
|
-
|
|
25279
|
-
|
|
25215
|
+
response = await this.post(ROUTER_REGISTRATION_CONSUME_PATH, walletObjectIdentity(input.authority.admissionReceipt.binding.lifecycle.account_id, input.authority.ownershipGeneration, input.authority.dispatchRoot.identity), {
|
|
25216
|
+
tenant_root: input.authority.dispatchRoot,
|
|
25217
|
+
ownership_generation: input.authority.ownershipGeneration,
|
|
25218
|
+
wallet_id: input.authority.admissionReceipt.binding.lifecycle.account_id,
|
|
25219
|
+
lifecycle_id: input.authority.lifecycleId,
|
|
25280
25220
|
session_id: Array.from(input.sessionId),
|
|
25281
25221
|
consumer_binding: input.consumerBinding
|
|
25282
25222
|
}, createRouterAbTraceContextV1().value, "exact");
|
|
@@ -25298,13 +25238,14 @@ var RouterAbEd25519YaoHttpRegistrationBackend = class {
|
|
|
25298
25238
|
admissionRequest
|
|
25299
25239
|
}));
|
|
25300
25240
|
}
|
|
25301
|
-
async executeRecovery(request,
|
|
25241
|
+
async executeRecovery(request, claim, traceContext) {
|
|
25302
25242
|
const routerInput = {
|
|
25303
25243
|
operation: "recovery",
|
|
25304
25244
|
request,
|
|
25305
|
-
admissionRequest
|
|
25245
|
+
admissionRequest: claim.admissionRequest,
|
|
25246
|
+
ownershipGeneration: claim.ownershipGeneration
|
|
25306
25247
|
};
|
|
25307
|
-
return await this.sendRouterRequest(routerInput, recoveryRouterExecuteRequest(routerInput, dispatchRoot, attempt), (traceContext ?? createRouterAbTraceContextV1()).value, "replay", replay);
|
|
25248
|
+
return await this.sendRouterRequest(routerInput, recoveryRouterExecuteRequest(routerInput, claim.dispatchRoot, claim.attempt), (traceContext ?? createRouterAbTraceContextV1()).value, "replay", claim.replay);
|
|
25308
25249
|
}
|
|
25309
25250
|
async executeRouterRequest(request, replay, traceContext) {
|
|
25310
25251
|
const traceId = (traceContext ?? createRouterAbTraceContextV1()).value;
|
|
@@ -25324,7 +25265,7 @@ var RouterAbEd25519YaoHttpRegistrationBackend = class {
|
|
|
25324
25265
|
const operation = request.operation;
|
|
25325
25266
|
const executeStartedAt = performance.now();
|
|
25326
25267
|
try {
|
|
25327
|
-
const response = await this.post(ROUTER_EXECUTE_PATH, routerRequest, traceId, retryAfterTransportFailure, replay);
|
|
25268
|
+
const response = await this.post(ROUTER_EXECUTE_PATH, walletObjectIdentity(request.admissionRequest.application_binding.wallet_id, request.ownershipGeneration, routerRequest.tenant_root.identity), routerRequest, traceId, retryAfterTransportFailure, replay);
|
|
25328
25269
|
this.lastRouterServerTiming = response.ok ? response.serverTiming : null;
|
|
25329
25270
|
const result = response.ok ? parseRouterExecuteResult(response.body, request.request) : response;
|
|
25330
25271
|
emitGatewaySpan(this.config.onSpan, "gateway.yao_execute", operation, traceId, executeStartedAt, result.ok ? "success" : "failure");
|
|
@@ -25334,10 +25275,11 @@ var RouterAbEd25519YaoHttpRegistrationBackend = class {
|
|
|
25334
25275
|
return unavailableFailure(error);
|
|
25335
25276
|
}
|
|
25336
25277
|
}
|
|
25337
|
-
async activateRecovery(request, dispatchRoot, traceContext) {
|
|
25338
|
-
const promoted = await this.post(ROUTER_RECOVERY_PROMOTE_PATH, {
|
|
25278
|
+
async activateRecovery(request, dispatchRoot, ownershipGeneration, traceContext) {
|
|
25279
|
+
const promoted = await this.post(ROUTER_RECOVERY_PROMOTE_PATH, walletObjectIdentity(request.binding.lifecycle.account_id, ownershipGeneration, dispatchRoot.identity), {
|
|
25339
25280
|
...request,
|
|
25340
|
-
tenant_root: dispatchRoot
|
|
25281
|
+
tenant_root: dispatchRoot,
|
|
25282
|
+
ownership_generation: ownershipGeneration
|
|
25341
25283
|
}, (traceContext ?? createRouterAbTraceContextV1()).value);
|
|
25342
25284
|
if (!promoted.ok) return promoted;
|
|
25343
25285
|
if (!activeReceiptMatchesRecoveryActivation(parseActiveSigningWorkerReceipt(promoted.body, request.binding.session_id, request.public_receipt.transcript), request)) return internalFailure("recovery_promotion_mismatch", "Router promotion receipt does not match the verified recovery result");
|
|
@@ -25346,10 +25288,13 @@ var RouterAbEd25519YaoHttpRegistrationBackend = class {
|
|
|
25346
25288
|
body: request
|
|
25347
25289
|
};
|
|
25348
25290
|
}
|
|
25349
|
-
async post(path, body, traceId, retryAfterTransportFailure = "none", replay = false) {
|
|
25291
|
+
async post(path, identity, body, traceId, retryAfterTransportFailure = "none", replay = false) {
|
|
25350
25292
|
const init = {
|
|
25351
25293
|
method: "POST",
|
|
25352
|
-
headers:
|
|
25294
|
+
headers: {
|
|
25295
|
+
...this.headers(traceId),
|
|
25296
|
+
...walletObjectIdentityHeaders(identity)
|
|
25297
|
+
},
|
|
25353
25298
|
body: JSON.stringify(body)
|
|
25354
25299
|
};
|
|
25355
25300
|
return await this.request(this.config.routerUrl, path, replay ? requestInitWithReplayHeader(init) : init, retryAfterTransportFailure);
|
|
@@ -25389,7 +25334,6 @@ function parseRouterServerTiming(value) {
|
|
|
25389
25334
|
const metrics = value.split(",").map((metric) => metric.trim());
|
|
25390
25335
|
const allowedNames = new Set([
|
|
25391
25336
|
"yao_router_prepare_pair",
|
|
25392
|
-
"yao_router_verify_readiness",
|
|
25393
25337
|
"yao_router_role_execution",
|
|
25394
25338
|
"yao_router_signing_worker_delivery"
|
|
25395
25339
|
]);
|
|
@@ -25536,7 +25480,7 @@ var RouterAbEd25519YaoRegistrationRouteExtension = class {
|
|
|
25536
25480
|
body: parsed.value
|
|
25537
25481
|
});
|
|
25538
25482
|
if (!authorization.ok) return routeFailureResponse$1(authorization);
|
|
25539
|
-
const result = await this.service.execute(parsed.value, traceContext.value);
|
|
25483
|
+
const result = await this.service.execute(parsed.value, authorization.ownershipGeneration, traceContext.value);
|
|
25540
25484
|
if (!result.ok) return routeFailureResponse$1(result);
|
|
25541
25485
|
return json$1(result.value, { status: result.status });
|
|
25542
25486
|
}
|
|
@@ -25567,11 +25511,17 @@ function resolveTraceContext$1(request) {
|
|
|
25567
25511
|
message: parsed.message
|
|
25568
25512
|
};
|
|
25569
25513
|
}
|
|
25570
|
-
function recoveryAuthorizationBinding(
|
|
25571
|
-
|
|
25514
|
+
function recoveryAuthorizationBinding(admitted) {
|
|
25515
|
+
const authorization = admitted.authorization;
|
|
25516
|
+
if (authorization.kind === "wallet_recovery") return {
|
|
25517
|
+
kind: "wallet_recovery",
|
|
25518
|
+
walletId: authorization.walletId,
|
|
25519
|
+
ownershipGeneration: admitted.ownershipGeneration
|
|
25520
|
+
};
|
|
25572
25521
|
const session = authorization.kind === "wallet_session_v2" ? authorization.context.authorization.session : authorization.context.status.session;
|
|
25573
25522
|
return {
|
|
25574
25523
|
kind: "wallet_session_v2",
|
|
25524
|
+
ownershipGeneration: admitted.ownershipGeneration,
|
|
25575
25525
|
tenantId: session.tenantId,
|
|
25576
25526
|
principalId: session.principalId,
|
|
25577
25527
|
walletId: session.walletId,
|
|
@@ -25864,7 +25814,7 @@ var RouterAbEd25519YaoRecoveryRouteExtension = class {
|
|
|
25864
25814
|
body: parsed.value
|
|
25865
25815
|
});
|
|
25866
25816
|
if (!authorization.ok) return routeFailureResponse(authorization);
|
|
25867
|
-
const result = await this.service.admitRecovery(parsed.value, recoveryAuthorizationBinding(authorization
|
|
25817
|
+
const result = await this.service.admitRecovery(parsed.value, recoveryAuthorizationBinding(authorization), traceContext.value);
|
|
25868
25818
|
if (!result.ok) return routeFailureResponse(result);
|
|
25869
25819
|
return json$1(result.value, { status: result.status });
|
|
25870
25820
|
}
|
|
@@ -25881,13 +25831,16 @@ var RouterAbEd25519YaoRecoveryRouteExtension = class {
|
|
|
25881
25831
|
code: parsed.code,
|
|
25882
25832
|
message: parsed.message
|
|
25883
25833
|
}, { status: 400 });
|
|
25834
|
+
const ownership = this.service.recoveryOwnershipGeneration(parsed.value.binding);
|
|
25835
|
+
if (!ownership.ok) return routeFailureResponse(ownership);
|
|
25884
25836
|
const authorization = await this.authorization.authorize({
|
|
25885
25837
|
kind: "execute",
|
|
25838
|
+
ownershipGeneration: ownership.value,
|
|
25886
25839
|
request,
|
|
25887
25840
|
body: parsed.value
|
|
25888
25841
|
});
|
|
25889
25842
|
if (!authorization.ok) return routeFailureResponse(authorization);
|
|
25890
|
-
const result = await this.service.executeRecovery(parsed.value, recoveryAuthorizationBinding(authorization
|
|
25843
|
+
const result = await this.service.executeRecovery(parsed.value, recoveryAuthorizationBinding(authorization), traceContext.value);
|
|
25891
25844
|
if (!result.ok) return routeFailureResponse(result);
|
|
25892
25845
|
return json$1(result.value, { status: result.status });
|
|
25893
25846
|
}
|
|
@@ -25904,13 +25857,16 @@ var RouterAbEd25519YaoRecoveryRouteExtension = class {
|
|
|
25904
25857
|
code: parsed.code,
|
|
25905
25858
|
message: parsed.message
|
|
25906
25859
|
}, { status: 400 });
|
|
25860
|
+
const ownership = this.service.recoveryOwnershipGeneration(parsed.value.binding);
|
|
25861
|
+
if (!ownership.ok) return routeFailureResponse(ownership);
|
|
25907
25862
|
const authorization = await this.authorization.authorize({
|
|
25908
25863
|
kind: "activate",
|
|
25864
|
+
ownershipGeneration: ownership.value,
|
|
25909
25865
|
request,
|
|
25910
25866
|
body: parsed.value
|
|
25911
25867
|
});
|
|
25912
25868
|
if (!authorization.ok) return routeFailureResponse(authorization);
|
|
25913
|
-
const result = await this.service.activateRecovery(parsed.value, recoveryAuthorizationBinding(authorization
|
|
25869
|
+
const result = await this.service.activateRecovery(parsed.value, recoveryAuthorizationBinding(authorization), traceContext.value);
|
|
25914
25870
|
if (!result.ok) return routeFailureResponse(result);
|
|
25915
25871
|
return json$1(result.value, { status: result.status });
|
|
25916
25872
|
}
|
|
@@ -25938,8 +25894,8 @@ function resolveTraceContext(request) {
|
|
|
25938
25894
|
var InMemoryRouterAbEd25519YaoExportStateV1 = class {
|
|
25939
25895
|
constructor() {
|
|
25940
25896
|
this.exports = /* @__PURE__ */ new Map();
|
|
25941
|
-
this.
|
|
25942
|
-
this.
|
|
25897
|
+
this.authorizationNonceOwners = /* @__PURE__ */ new Map();
|
|
25898
|
+
this.authorizationUncertainOwners = /* @__PURE__ */ new Map();
|
|
25943
25899
|
}
|
|
25944
25900
|
};
|
|
25945
25901
|
const ROUTES = Object.freeze([defineRoute({
|
|
@@ -26131,7 +26087,7 @@ var RouterAbEd25519YaoExportRouteExtension = class {
|
|
|
26131
26087
|
code: authorized.code,
|
|
26132
26088
|
message: authorized.message
|
|
26133
26089
|
}, { status: authorized.status });
|
|
26134
|
-
const result = await this.service.admitExport(parsed.protocol, authorized.authorizationIdentity, authorized.admission, authorized.factorRelease ?? null, traceContext.value);
|
|
26090
|
+
const result = await this.service.admitExport(parsed.protocol, authorized.authorizationIdentity, authorized.ownershipGeneration, authorized.admission, authorized.factorRelease ?? null, traceContext.value);
|
|
26135
26091
|
return result.ok ? json$1({
|
|
26136
26092
|
protocol: result.value,
|
|
26137
26093
|
...authorized.factorRelease ? { factorRelease: authorized.factorRelease } : {}
|
|
@@ -26246,17 +26202,26 @@ var RouterAbEd25519YaoProductRegistrationRuntime = class {
|
|
|
26246
26202
|
async bindVerifiedIntent(input) {
|
|
26247
26203
|
return await this.input.authorization.bindVerifiedIntent(input);
|
|
26248
26204
|
}
|
|
26205
|
+
/** The registration service of this runtime resolves the tenant root when it executes. */
|
|
26206
|
+
startRegistrationDispatchRoot() {
|
|
26207
|
+
return null;
|
|
26208
|
+
}
|
|
26249
26209
|
async bindAndAdmitVerifiedRegistration(input) {
|
|
26250
|
-
const bound = await this.input.authorization.
|
|
26210
|
+
const bound = await this.input.authorization.bindAndAuthorizeAdmission(input);
|
|
26251
26211
|
if (!bound.ok) return bound;
|
|
26252
|
-
|
|
26212
|
+
const admitted = await this.input.registrationService.admit(bound.admissionRequest);
|
|
26213
|
+
if (!admitted.ok) return admitted;
|
|
26214
|
+
return {
|
|
26215
|
+
ok: true,
|
|
26216
|
+
status: 200,
|
|
26217
|
+
admissionRequest: bound.admissionRequest,
|
|
26218
|
+
value: admitted.value,
|
|
26219
|
+
companionWrite: "not_committed"
|
|
26220
|
+
};
|
|
26253
26221
|
}
|
|
26254
26222
|
async consumeActivated(request) {
|
|
26255
26223
|
return await this.input.registrationService.consumeActivated(request);
|
|
26256
26224
|
}
|
|
26257
|
-
async installRegistrationFinalizeCapability(input) {
|
|
26258
|
-
return await this.input.capabilityInstaller.installRegistrationFinalizeCapability(input);
|
|
26259
|
-
}
|
|
26260
26225
|
async installPersistedActiveCapability(input) {
|
|
26261
26226
|
return await this.input.capabilityInstaller.installPersistedActiveCapability(input);
|
|
26262
26227
|
}
|