@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.
Files changed (743) hide show
  1. package/THIRD_PARTY_NOTICES.md +7 -9
  2. package/artifact-manifest.json +241 -41
  3. package/cloudflare-router-ab/build/deriver-a/build-stamp.json +1 -1
  4. package/cloudflare-router-ab/build/deriver-a/index.js +2 -2
  5. package/cloudflare-router-ab/build/deriver-a/index_bg.wasm +0 -0
  6. package/cloudflare-router-ab/build/deriver-b/build-stamp.json +1 -1
  7. package/cloudflare-router-ab/build/deriver-b/index.js +2 -2
  8. package/cloudflare-router-ab/build/deriver-b/index_bg.wasm +0 -0
  9. package/cloudflare-router-ab/build/local-tools/darwin-arm64/router_ab_local_init +0 -0
  10. package/cloudflare-router-ab/build/local-tools/darwin-x64/router_ab_local_init +0 -0
  11. package/cloudflare-router-ab/build/local-tools/linux-x64/router_ab_local_init +0 -0
  12. package/cloudflare-router-ab/build/router/build-stamp.json +1 -1
  13. package/cloudflare-router-ab/build/router/index.js +2 -2
  14. package/cloudflare-router-ab/build/router/index_bg.wasm +0 -0
  15. package/cloudflare-router-ab/build/signing-worker/build-stamp.json +1 -1
  16. package/cloudflare-router-ab/build/signing-worker/index.js +2 -2
  17. package/cloudflare-router-ab/build/signing-worker/index_bg.wasm +0 -0
  18. package/cloudflare-router-ab/build/tenant-root-control-plane/build-stamp.json +1 -1
  19. package/cloudflare-router-ab/build/tenant-root-control-plane/index.js +2 -2
  20. package/cloudflare-router-ab/build/tenant-root-control-plane/index_bg.wasm +0 -0
  21. package/cloudflare-router-ab/migrations/deriver-a/0019_wallet_object_addresses.sql +10 -0
  22. package/cloudflare-router-ab/migrations/deriver-b/0019_wallet_object_addresses.sql +10 -0
  23. package/cloudflare-router-ab/scripts/prepare-local-runtime-config.mjs +3 -119
  24. package/cloudflare-router-ab/scripts/start-local-role-workers.mjs +77 -20
  25. package/cloudflare-router-ab/wrangler.deriver-a.toml +0 -8
  26. package/cloudflare-router-ab/wrangler.deriver-b.toml +24 -8
  27. package/cloudflare-router-ab/wrangler.router.toml +0 -2
  28. package/cloudflare-router-ab/wrangler.signing-worker.toml +29 -0
  29. package/dist/esm/authorization/domain.js +3 -2
  30. package/dist/esm/authorization/lifecycleRouting.js +62 -0
  31. package/dist/esm/authorization/service.js +86 -35
  32. package/dist/esm/cloud-host.js +42 -39
  33. package/dist/esm/core/EmailOtpRecords.js +29 -222
  34. package/dist/esm/core/EmailOtpStores.js +0 -859
  35. package/dist/esm/core/IdentityStore.js +2 -339
  36. package/dist/esm/core/ThresholdService/config.js +1 -9
  37. package/dist/esm/core/ThresholdService/index.js +0 -4
  38. package/dist/esm/core/ThresholdService/kv.js +1 -66
  39. package/dist/esm/core/ThresholdService/routerAb/ecdsaDerivationPoolFillHandlers.js +3 -13
  40. package/dist/esm/core/ThresholdService/routerAb/ecdsaDerivationPresignBridge.js +10 -0
  41. package/dist/esm/core/ThresholdService/routerAb/internalServiceHttp.js +1 -0
  42. package/dist/esm/core/ThresholdService/routerAbNormalSigningPolicy.js +1 -11
  43. package/dist/esm/core/ThresholdService/stores/WalletSessionStore.js +0 -541
  44. package/dist/esm/core/ThresholdService/validation.js +3 -347
  45. package/dist/esm/core/WalletAuthMethodStore.js +2 -123
  46. package/dist/esm/core/WalletStore.js +3 -209
  47. package/dist/esm/core/WebAuthnAuthenticatorStore.js +0 -202
  48. package/dist/esm/core/WebAuthnCredentialBindingStore.js +2 -182
  49. package/dist/esm/core/WebAuthnLoginChallengeStore.js +0 -52
  50. package/dist/esm/core/WebAuthnSyncChallengeStore.js +0 -54
  51. package/dist/esm/core/authService/emailOtpConfig.js +1 -195
  52. package/dist/esm/core/authService/emailOtpEnrollment.js +0 -110
  53. package/dist/esm/core/authService/emailOtpSeal.js +0 -63
  54. package/dist/esm/core/authService/nearPrivateKeySigning.js +1 -1
  55. package/dist/esm/core/authService/nearTransactions.js +3 -98
  56. package/dist/esm/core/authService/rateLimits.js +0 -84
  57. package/dist/esm/core/authService/webauthn.js +3 -299
  58. package/dist/esm/core/authService/webauthnOidcHelpers.js +1 -24
  59. package/dist/esm/core/authService/webauthnWalletBinding.js +0 -37
  60. package/dist/esm/core/config.js +1 -95
  61. package/dist/esm/core/d1EcdsaSignerRead.js +1 -1
  62. package/dist/esm/core/d1Ed25519SignerRead.js +55 -0
  63. package/dist/esm/core/d1IdentityStore.js +1 -2
  64. package/dist/esm/core/d1TenantStore.js +1 -24
  65. package/dist/esm/core/d1WalletAuthMethodStore.js +2 -5
  66. package/dist/esm/core/d1WalletStore.js +16 -13
  67. package/dist/esm/core/deviceLinking/linkedDeviceBootstrap.js +13 -0
  68. package/dist/esm/core/deviceLinking/linkedDeviceEmailOtpGrant.js +2 -2
  69. package/dist/esm/core/deviceLinking/linkedDeviceManagement.js +1 -1
  70. package/dist/esm/core/deviceLinking/linkedDeviceSession.js +20 -14
  71. package/dist/esm/core/deviceLinking/linkedDeviceSessionRecord.js +2 -2
  72. package/dist/esm/core/deviceLinking/requestProof.js +9 -6
  73. package/dist/esm/core/emailOtpD1Statements.js +108 -94
  74. package/dist/esm/core/keyMaterialBrands.js +2 -12
  75. package/dist/esm/core/nearKeys.js +0 -1
  76. package/dist/esm/core/nearRelayerAccountProvisioning.js +7 -10
  77. package/dist/esm/core/passkeyCredentialClaims.js +8 -0
  78. package/dist/esm/core/routerAbSigning/RouterAbEcdsaPresignRuntime.js +6 -6
  79. package/dist/esm/core/routerAbSigning/RouterAbNormalSigningRuntime.js +2 -30
  80. package/dist/esm/core/signingLanes/WalletExecutionLaneProjection.js +1 -1
  81. package/dist/esm/core/signingMaterial/ordinaryInactiveSignerMaterialReservation.js +1 -0
  82. package/dist/esm/core/thresholdEcdsaChainTarget.js +1 -4
  83. package/dist/esm/hosted-wallet-gateway.js +158 -52
  84. package/dist/esm/index.js +6 -19
  85. package/dist/esm/localHostedWalletGatewayHandler.js +18 -3
  86. package/dist/esm/localIntendedYaoSigningFault.js +2 -30
  87. package/dist/esm/localRegistrationSetupAuthority.js +96 -0
  88. package/dist/esm/router/auth/authRequestValidation.js +8 -16
  89. package/dist/esm/router/auth/commonRouterUtils.js +17 -10
  90. package/dist/esm/router/auth/routerApiCredentialAuth.js +26 -7
  91. package/dist/esm/router/auth/walletRegistrationContext.js +49 -0
  92. package/dist/esm/router/auth/webAuthnCredentialCodecs.js +1 -2
  93. package/dist/esm/router/cloudflare/d1/auth/d1AuthorizationAssembly.js +88 -0
  94. package/dist/esm/router/cloudflare/d1/auth/d1AuthorizedOperationRouteService.js +2 -0
  95. package/dist/esm/router/cloudflare/d1/auth/d1EmailOtpRouteService.js +25 -0
  96. package/dist/esm/router/cloudflare/d1/auth/d1RouterApiAuthConfig.js +24 -6
  97. package/dist/esm/router/cloudflare/d1/auth/d1RouterApiAuthService.js +75 -320
  98. package/dist/esm/router/cloudflare/d1/auth/walletSessionCredentialReaders.js +17 -1
  99. package/dist/esm/router/cloudflare/d1/authorization/authorizedOperationStatements.js +57 -25
  100. package/dist/esm/router/cloudflare/d1/authorization/d1AuthorizationStore.js +265 -104
  101. package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceAuthorityInstallService.js +43 -17
  102. package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceEd25519ExportRootStore.js +6 -1
  103. package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceEmailOtpGrantStore.js +12 -2
  104. package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceEmailOtpTargetFactor.js +4 -4
  105. package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceOwnerAuthorizationProvider.js +2 -2
  106. package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceRequestProofNonceStore.js +3 -9
  107. package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceRouteService.js +2 -1
  108. package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceSessionRecords.js +1 -1
  109. package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceSessionStore.js +89 -7
  110. package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceTargetCredentialProvider.js +24 -15
  111. package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceTargetPlanner.js +1 -1
  112. package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceVerifiedLinkBuilder.js +1 -1
  113. package/dist/esm/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoCapabilityPersistence.js +9 -6
  114. package/dist/esm/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoLifecycleDecisionStore.js +11 -2
  115. package/dist/esm/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoProductRegistrationPartitionedStateStore.js +100 -10
  116. package/dist/esm/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoStateWriteFence.js +92 -0
  117. package/dist/esm/router/cloudflare/d1/ed25519Yao/d1WalletCeremonyActivity.js +77 -0
  118. package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeIssuer.js +14 -9
  119. package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeService.js +0 -1
  120. package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeStore.js +15 -9
  121. package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeVerifier.js +3 -2
  122. package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpEnrollmentStore.js +1 -1
  123. package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpGrantStore.js +1 -7
  124. package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRateLimitStore.js +62 -36
  125. package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRecords.js +27 -21
  126. package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRecoveryService.js +1 -1
  127. package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRegistrationEnrollmentFinalizer.js +2 -2
  128. package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpServerSealRuntime.js +0 -1
  129. package/dist/esm/router/cloudflare/d1/emailOtp/d1GoogleEmailOtpRegistrationAttemptStore.js +44 -12
  130. package/dist/esm/router/cloudflare/d1/emailOtp/d1GoogleEmailOtpRegistrationRecords.js +1 -49
  131. package/dist/esm/router/cloudflare/d1/emailOtp/d1GoogleEmailOtpSessionResolver.js +20 -31
  132. package/dist/esm/router/cloudflare/d1/emailOtp/d1GoogleRegistrationCompletion.js +85 -0
  133. package/dist/esm/router/cloudflare/d1/identity/d1IdentityRecords.js +0 -1
  134. package/dist/esm/router/cloudflare/d1/identity/d1IdentityService.js +0 -48
  135. package/dist/esm/router/cloudflare/d1/near/d1SponsoredNearAccount.js +242 -0
  136. package/dist/esm/router/cloudflare/d1/oidc/d1OidcBoundary.js +1 -2
  137. package/dist/esm/router/cloudflare/d1/oidc/d1OidcVerificationService.js +2 -29
  138. package/dist/esm/router/cloudflare/d1/oidc/googleOidcToken.js +41 -0
  139. package/dist/esm/router/cloudflare/d1/passkeyCustody/d1PasskeyCustodyRouteService.js +5 -0
  140. package/dist/esm/router/cloudflare/d1/passkeyCustody/d1WalletCustodyCommitStore.js +52 -7
  141. package/dist/esm/router/cloudflare/d1/registration/d1RegistrationCeremonyRecordStore.js +83 -16
  142. package/dist/esm/router/cloudflare/d1/registration/d1RegistrationCeremonyRecords.js +8 -14
  143. package/dist/esm/router/cloudflare/d1/registration/d1RegistrationCeremonyStore.js +60 -28
  144. package/dist/esm/router/cloudflare/d1/registration/d1RegistrationIntentService.js +0 -1
  145. package/dist/esm/router/cloudflare/d1/registration/d1RegistrationSessionTransaction.js +28 -0
  146. package/dist/esm/router/cloudflare/d1/registration/d1RegistrationSetupSupport.js +84 -0
  147. package/dist/esm/router/cloudflare/d1/registration/d1WalletExecutionAuthority.js +168 -0
  148. package/dist/esm/router/cloudflare/d1/registration/d1WalletOperationStore.js +53 -0
  149. package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationCommitStore.js +85 -38
  150. package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationInitialSession.js +33 -0
  151. package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationPreparation.js +16 -0
  152. package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationRead.js +58 -0
  153. package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationService.js +478 -708
  154. package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationSetup.js +13 -57
  155. package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationSetupExecution.js +169 -0
  156. package/dist/esm/router/cloudflare/d1/registration/walletRegistrationEstablishedSessionIssuer.js +79 -47
  157. package/dist/esm/router/cloudflare/d1/registration/walletRegistrationSessionCommitReceipt.js +11 -35
  158. package/dist/esm/router/cloudflare/d1/signingAdmission/d1RouterAbNormalSigningAdmissionStore.js +110 -45
  159. package/dist/esm/router/cloudflare/d1/versionedJson/d1VersionedJsonRecordStore.js +12 -9
  160. package/dist/esm/router/cloudflare/d1/wallet/authorizationSnapshotLayout.js +168 -0
  161. package/dist/esm/router/cloudflare/d1/wallet/d1WalletAddSignerFinalizeRecord.js +68 -0
  162. package/dist/esm/router/cloudflare/d1/wallet/d1WalletAddSignerService.js +22 -60
  163. package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthMethodService.js +12 -48
  164. package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorityStore.js +56 -143
  165. package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorizationCleanup.js +157 -0
  166. package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorizationFreeze.js +56 -0
  167. package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorizationHistory.js +238 -0
  168. package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorizationIntake.js +287 -0
  169. package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorizationSnapshot.js +295 -0
  170. package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationApprovals.js +140 -0
  171. package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationChallenges.js +170 -0
  172. package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationEmailOtp.js +60 -0
  173. package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationOwner.js +33 -0
  174. package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationOwnerRequest.js +74 -0
  175. package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationPasskey.js +77 -0
  176. package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationReadAccess.js +37 -0
  177. package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationSessions.js +97 -0
  178. package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationWriteBlock.js +133 -0
  179. package/dist/esm/router/cloudflare/d1/walletObjectAddresses.js +47 -0
  180. package/dist/esm/router/cloudflare/d1/webauthn/d1WebAuthnAuthService.js +26 -5
  181. package/dist/esm/router/cloudflare/d1/webauthn/d1WebAuthnRecords.js +4 -70
  182. package/dist/esm/router/cloudflare/d1/webauthn/d1WebAuthnStore.js +23 -7
  183. package/dist/esm/router/cloudflare/runtime/routerAbServiceBindings.js +32 -1
  184. package/dist/esm/router/cloudflare/runtime/staticWalletConsoleBinding.js +20 -7
  185. package/dist/esm/router/cloudflare/runtime/walletAuthorizationRelocationRoutes.js +488 -0
  186. package/dist/esm/router/cloudflare/runtime/walletConsoleOps.js +1 -0
  187. package/dist/esm/router/cloudflare/runtime/walletConsoleOpsClient.js +26 -1
  188. package/dist/esm/router/cloudflare/runtime/walletControlOps.js +3 -0
  189. package/dist/esm/router/cloudflare/runtime/walletGateway.js +1 -1
  190. package/dist/esm/router/cloudflare/runtime/walletObjectAddresses.js +105 -0
  191. package/dist/esm/router/cloudflare/runtime/walletPlacementRoutes.js +339 -0
  192. package/dist/esm/router/cloudflare/runtime/walletRelocationDeriver.js +244 -0
  193. package/dist/esm/router/cloudflare/runtime/walletRelocationEcdsa.js +212 -0
  194. package/dist/esm/router/cloudflare/runtime/walletRelocationEd25519.js +172 -0
  195. package/dist/esm/router/cloudflare/runtime/walletRelocationOps.js +183 -0
  196. package/dist/esm/router/cloudflare/runtime/walletRelocationPresign.js +185 -0
  197. package/dist/esm/router/cloudflare/runtime/walletRelocationSource.js +221 -0
  198. package/dist/esm/router/cloudflare/runtime/walletRuntimeOps.js +16 -4
  199. package/dist/esm/router/cloudflare/signingLanes/cloudflareOrdinaryInactiveSignerMaterialReservation.js +30 -8
  200. package/dist/esm/router/cloudflare-adaptor.js +8 -9
  201. package/dist/esm/router/cloudflare.js +33043 -31559
  202. package/dist/esm/router/domains/ecdsa/routerAbEcdsaStrictRegistration.js +35 -9
  203. package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoCapabilityCommit.js +42 -0
  204. package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistration.js +42 -13
  205. package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationPartitionedStateStore.js +64 -3
  206. package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationPartitioning.js +6 -6
  207. package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationPersistence.js +70 -3
  208. package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationRequestScopedRuntime.js +59 -87
  209. package/dist/esm/router/domains/ed25519Yao/export/routerAbEd25519YaoExport.js +58 -28
  210. package/dist/esm/router/domains/ed25519Yao/export/routerAbEd25519YaoExportRequestScopedCloudflare.js +13 -7
  211. package/dist/esm/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecovery.js +108 -78
  212. package/dist/esm/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecoveryRequestScopedCloudflare.js +27 -5
  213. package/dist/esm/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecoveryWalletSessionAuthorization.js +71 -22
  214. package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoHttpRegistrationBackend.js +37 -25
  215. package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistration.js +3 -3
  216. package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationExecutionRecord.js +2 -1
  217. package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationIntentAuthorization.js +24 -3
  218. package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationRequestScopedCloudflare.js +4 -3
  219. package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationSideEffectBoundary.js +20 -7
  220. package/dist/esm/router/domains/ed25519Yao/routerAbEd25519YaoGatewayEnvelope.js +7 -1
  221. package/dist/esm/router/domains/emailOtp/emailOtpRequestValidation.js +0 -1
  222. package/dist/esm/router/domains/emailOtp/emailOtpRouteHandlers.js +2 -2
  223. package/dist/esm/router/domains/passkeyCustody/passkeyCustodyEnvelopeRetrieval.js +3 -9
  224. package/dist/esm/router/domains/passkeyCustody/registrationCustodyOutcome.js +34 -18
  225. package/dist/esm/router/domains/passkeyCustody/walletCustodyRegistrationAdmission.js +2 -2
  226. package/dist/esm/router/domains/passkeyCustody/walletCustodyRegistrationCommit.js +18 -14
  227. package/dist/esm/router/domains/signingOperations/authorizedOperationWire.js +73 -0
  228. package/dist/esm/router/domains/signingOperations/ecdsaSigningResponse.js +31 -0
  229. package/dist/esm/router/domains/signingOperations/ed25519AuthorizedOperationReceipt.js +1 -1
  230. package/dist/esm/router/domains/signingOperations/routerAbEcdsaDerivationNormalSigningRoute.js +2 -1
  231. package/dist/esm/router/domains/signingOperations/routerAbEd25519NormalSigningRoute.js +31 -121
  232. package/dist/esm/router/domains/signingOperations/routerAbNormalSigningAdmission.js +2 -93
  233. package/dist/esm/router/domains/signingOperations/routerAbPrivateSigningWorker.js +6 -20
  234. package/dist/esm/router/domains/signingOperations/signingPrepareSession.js +33 -0
  235. package/dist/esm/router/domains/signingOperations/walletExecutionAdmission.js +2 -3
  236. package/dist/esm/router/domains/walletRegistration/registrationSessionSeal.js +121 -0
  237. package/dist/esm/router/domains/walletRegistration/walletRegistrationReservation.js +70 -0
  238. package/dist/esm/router/domains/walletRegistration/walletRegistrationRoutes.js +56 -168
  239. package/dist/esm/router/domains/walletRegistration/walletRegistrationSetupPayload.js +3 -4
  240. package/dist/esm/router/domains/walletUnlock/walletUnlockRouteHandlers.js +14 -0
  241. package/dist/esm/router/express.js +1453 -1488
  242. package/dist/esm/router/framework/http.js +4 -1
  243. package/dist/esm/router/framework/registrationSetupDispatch.js +14 -0
  244. package/dist/esm/router/framework/ror/normalize.js +0 -1
  245. package/dist/esm/router/framework/ror/options.js +0 -1
  246. package/dist/esm/router/framework/ror/provider.js +0 -1
  247. package/dist/esm/router/framework/ror/staticProvider.js +0 -1
  248. package/dist/esm/router/framework/routeDefinitions.js +1 -2
  249. package/dist/esm/router/framework/routerApiWebhooks.js +0 -1
  250. package/dist/esm/router/ror.js +0 -1
  251. package/dist/esm/router/transport/fetch/createFetchRouter.js +2 -4
  252. package/dist/esm/router/transport/fetch/routes/auth.js +3 -1
  253. package/dist/esm/router/transport/fetch/routes/deviceLinking.js +38 -149
  254. package/dist/esm/router/transport/fetch/routes/deviceLinkingOwnerAuthorization.js +5 -4
  255. package/dist/esm/router/transport/fetch/routes/deviceLinkingResponses.js +130 -0
  256. package/dist/esm/router/transport/fetch/routes/ecdsaOperationStepUpFactor.js +171 -0
  257. package/dist/esm/router/transport/fetch/routes/ed25519AuthorizedOperationRevalidation.js +65 -0
  258. package/dist/esm/router/transport/fetch/routes/normalSigningRouterProxy.js +13 -3
  259. package/dist/esm/router/transport/fetch/routes/passkeyCustody.js +4 -3
  260. package/dist/esm/router/transport/fetch/routes/sessions.js +3 -2
  261. package/dist/esm/router/transport/fetch/routes/syncAccount.js +7 -2
  262. package/dist/esm/router/transport/fetch/routes/thresholdEcdsa.js +86 -245
  263. package/dist/esm/router/transport/fetch/routes/thresholdEd25519.js +76 -212
  264. package/dist/esm/router/transport/fetch/routes/walletExecutionLanePreflight.js +18 -41
  265. package/dist/esm/router/transport/fetch/routes/walletRegistration.js +6 -3
  266. package/dist/esm/router/transport/fetch/routes/webauthnAuthenticators.js +1 -1
  267. package/dist/esm/shared-ts/src/authorization/index.js +1 -1
  268. package/dist/esm/shared-ts/src/authorization/walletAuthority.js +2 -2
  269. package/dist/esm/shared-ts/src/authorization/walletSessionIssuance.js +0 -1
  270. package/dist/esm/shared-ts/src/device-linking/activeWalletSession.js +12 -2
  271. package/dist/esm/shared-ts/src/device-linking/authorityActivation.js +0 -2
  272. package/dist/esm/shared-ts/src/device-linking/contracts.js +16 -1
  273. package/dist/esm/shared-ts/src/device-linking/digests.js +2 -9
  274. package/dist/esm/shared-ts/src/device-linking/ed25519ExportRoot.js +1 -1
  275. package/dist/esm/shared-ts/src/device-linking/index.js +1 -1
  276. package/dist/esm/shared-ts/src/device-linking/parsers.js +1 -1
  277. package/dist/esm/shared-ts/src/device-linking/sourceContribution.js +1 -1
  278. package/dist/esm/shared-ts/src/device-linking/wireFields.js +1 -1
  279. package/dist/esm/shared-ts/src/near/actions.js +0 -1
  280. package/dist/esm/shared-ts/src/near/nearClient.js +1 -3
  281. package/dist/esm/shared-ts/src/signing-lanes/evmFamilySigningKeySlotId.js +1 -1
  282. package/dist/esm/shared-ts/src/signing-lanes/index.js +1 -6
  283. package/dist/esm/shared-ts/src/signing-lanes/ownerContinuity.js +3 -3
  284. package/dist/esm/shared-ts/src/signing-lanes/participantDigest.js +2 -81
  285. package/dist/esm/shared-ts/src/signing-lanes/participants.js +1 -219
  286. package/dist/esm/shared-ts/src/signing-lanes/recordParsers.js +0 -3
  287. package/dist/esm/shared-ts/src/tenant-root/tenantRootOperationRecord.js +1 -2
  288. package/dist/esm/shared-ts/src/threshold/ecdsaDerivationRoleLocalBootstrap.js +0 -1
  289. package/dist/esm/shared-ts/src/threshold/keyMaterialBrands.js +1 -22
  290. package/dist/esm/shared-ts/src/threshold/participants.js +0 -1
  291. package/dist/esm/shared-ts/src/threshold/signingRootScope.js +0 -1
  292. package/dist/esm/shared-ts/src/utils/addWalletAuthMethod.js +4 -13
  293. package/dist/esm/shared-ts/src/utils/canonicalPrimitives.js +1 -7
  294. package/dist/esm/shared-ts/src/utils/domainIds.js +1 -16
  295. package/dist/esm/shared-ts/src/utils/ecdsaCapabilityActivation.js +1 -11
  296. package/dist/esm/shared-ts/src/utils/ecdsaKeyFactsInventory.js +0 -1
  297. package/dist/esm/shared-ts/src/utils/ecdsaServerTiming.js +6 -1
  298. package/dist/esm/shared-ts/src/utils/emailOtpDomain.js +4 -2
  299. package/dist/esm/shared-ts/src/utils/errors.js +1 -19
  300. package/dist/esm/shared-ts/src/utils/near.js +1 -1
  301. package/dist/esm/shared-ts/src/utils/registrationEstablishedSession.js +1 -1
  302. package/dist/esm/shared-ts/src/utils/registrationIds.js +1 -5
  303. package/dist/esm/shared-ts/src/utils/registrationIntent.js +0 -1
  304. package/dist/esm/shared-ts/src/utils/registrationSetupOperation.js +8 -0
  305. package/dist/esm/shared-ts/src/utils/registrationSignerPlan.js +1 -1
  306. package/dist/esm/shared-ts/src/utils/routerAbEcdsaDerivation.js +1 -2
  307. package/dist/esm/shared-ts/src/utils/routerAbPublicKeyset.js +0 -27
  308. package/dist/esm/shared-ts/src/utils/validation.js +1 -5
  309. package/dist/esm/shared-ts/src/utils/walletAuthAuthority.js +0 -1
  310. package/dist/esm/shared-ts/src/utils/walletManagementProtocol.js +6 -0
  311. package/dist/esm/shared-ts/src/utils/wireSchema.js +2 -13
  312. package/dist/esm/shared-ts/src/wallet-recovery/backupAcknowledgement.js +6 -24
  313. package/dist/esm/shared-ts/src/wallet-recovery/recoveryCodeLocator.js +0 -1
  314. package/dist/esm/shared-ts/src/wallet-recovery/recoveryKeyId.js +5 -6
  315. package/dist/esm/shared-ts/src/wallet-recovery/walletRecoveryEcdsaPossession.js +1 -1
  316. package/dist/esm/storage/d1Sql.js +1 -7
  317. package/dist/esm/threshold/session/signingSessionSeal/crypto/cipher.js +0 -1
  318. package/dist/esm/threshold/session/signingSessionSeal/guards/backends.js +1 -2
  319. package/dist/esm/threshold/session/signingSessionSeal/idempotencyBackends.js +0 -1
  320. package/dist/esm/threshold/session/signingSessionSeal/idempotencyRecords.js +0 -1
  321. package/dist/esm/threshold/session/signingSessionSeal/options.js +1 -2
  322. package/dist/esm/wasm/evm_crypto/pkg/evm_crypto_bg.wasm +0 -0
  323. package/dist/esm/wasm/near_signer/pkg/wasm_signer_worker.js +0 -611
  324. package/dist/esm/wasm/near_signer/pkg/wasm_signer_worker_bg.wasm +0 -0
  325. package/dist/esm/wasm/shamir3pass_runtime/pkg/shamir3pass_runtime_bg.wasm +0 -0
  326. package/dist/types/shared-ts/src/authorization/capabilityKinds.d.ts +0 -4
  327. package/dist/types/shared-ts/src/device-linking/activeWalletSession.d.ts +2 -1
  328. package/dist/types/shared-ts/src/device-linking/contracts.d.ts +11 -0
  329. package/dist/types/shared-ts/src/signing-lanes/evmFamilySigningKeySlotId.d.ts +0 -2
  330. package/dist/types/shared-ts/src/signing-lanes/execution.d.ts +0 -11
  331. package/dist/types/shared-ts/src/signing-lanes/ids.d.ts +2 -7
  332. package/dist/types/shared-ts/src/signing-lanes/index.d.ts +0 -4
  333. package/dist/types/shared-ts/src/signing-lanes/ownerContinuity.d.ts +0 -1
  334. package/dist/types/shared-ts/src/signing-lanes/participantDigest.d.ts +0 -18
  335. package/dist/types/shared-ts/src/signing-lanes/participants.d.ts +6 -35
  336. package/dist/types/shared-ts/src/signing-lanes/rotation.d.ts +6 -843
  337. package/dist/types/shared-ts/src/threshold/ed25519OperationFingerprint.d.ts +2 -1
  338. package/dist/types/shared-ts/src/threshold/keyMaterialBrands.d.ts +0 -10
  339. package/dist/types/shared-ts/src/threshold/participants.d.ts +1 -1
  340. package/dist/types/shared-ts/src/utils/addWalletAuthMethod.d.ts +1 -133
  341. package/dist/types/shared-ts/src/utils/addWalletAuthMethod.typecheck.d.ts +4 -18
  342. package/dist/types/shared-ts/src/utils/domainIds.d.ts +0 -12
  343. package/dist/types/shared-ts/src/utils/emailOtpDomain.d.ts +3 -1
  344. package/dist/types/shared-ts/src/utils/errors.d.ts +0 -4
  345. package/dist/types/shared-ts/src/utils/near.d.ts +0 -20
  346. package/dist/types/shared-ts/src/utils/normalize.d.ts +0 -2
  347. package/dist/types/shared-ts/src/utils/registrationSetupOperation.d.ts +3 -0
  348. package/dist/types/shared-ts/src/utils/routerAbPublicKeyset.d.ts +0 -9
  349. package/dist/types/shared-ts/src/utils/validation.d.ts +1 -3
  350. package/dist/types/shared-ts/src/utils/walletCapabilityBindings.d.ts +0 -1
  351. package/dist/types/shared-ts/src/utils/walletManagementProtocol.d.ts +3 -0
  352. package/dist/types/shared-ts/src/utils/wireSchema.d.ts +0 -2
  353. package/dist/types/shared-ts/src/wallet-recovery/backupAcknowledgement.d.ts +0 -1
  354. package/dist/types/shared-ts/src/wallet-recovery/recoveryCodeReservation.d.ts +1 -10
  355. package/dist/types/shared-ts/src/wallet-recovery/recoveryCodes.d.ts +1 -3
  356. package/dist/types/shared-ts/src/wallet-recovery/recoveryKeyId.d.ts +5 -21
  357. package/dist/types/wallet-server/src/authorization/domain.d.ts +17 -1
  358. package/dist/types/wallet-server/src/authorization/ecdsaWalletSessionAdmission.d.ts +1 -0
  359. package/dist/types/wallet-server/src/authorization/ed25519WalletSessionAdmission.d.ts +35 -0
  360. package/dist/types/wallet-server/src/authorization/ed25519WalletSessionAdmission.typecheck.d.ts +2 -0
  361. package/dist/types/wallet-server/src/authorization/lifecycleRouting.d.ts +32 -0
  362. package/dist/types/wallet-server/src/authorization/lifecycleRouting.typecheck.d.ts +2 -0
  363. package/dist/types/wallet-server/src/authorization/recoveryRouting.d.ts +22 -0
  364. package/dist/types/wallet-server/src/authorization/recoveryRouting.typecheck.d.ts +2 -0
  365. package/dist/types/wallet-server/src/authorization/service.d.ts +50 -5
  366. package/dist/types/wallet-server/src/authorization/sessionRouting.d.ts +22 -0
  367. package/dist/types/wallet-server/src/authorization/sessionRouting.typecheck.d.ts +2 -0
  368. package/dist/types/wallet-server/src/cloud-host.d.ts +36 -10
  369. package/dist/types/wallet-server/src/core/EmailOtpRecords.d.ts +2 -22
  370. package/dist/types/wallet-server/src/core/EmailOtpStores.d.ts +20 -84
  371. package/dist/types/wallet-server/src/core/IdentityStore.d.ts +0 -10
  372. package/dist/types/wallet-server/src/core/RegistrationCeremonyStore.d.ts +0 -1
  373. package/dist/types/wallet-server/src/core/ThresholdService/config.d.ts +0 -2
  374. package/dist/types/wallet-server/src/core/ThresholdService/index.d.ts +1 -3
  375. package/dist/types/wallet-server/src/core/ThresholdService/kv.d.ts +0 -7
  376. package/dist/types/wallet-server/src/core/ThresholdService/routerAb/ecdsaDerivationPoolFillHandlers.d.ts +1 -3
  377. package/dist/types/wallet-server/src/core/ThresholdService/routerAb/ecdsaDerivationPresignBridge.d.ts +6 -0
  378. package/dist/types/wallet-server/src/core/ThresholdService/routerAb/internalServiceHttp.d.ts +1 -0
  379. package/dist/types/wallet-server/src/core/ThresholdService/routerAbNormalSigningPolicy.d.ts +0 -1
  380. package/dist/types/wallet-server/src/core/ThresholdService/stores/WalletSessionStore.d.ts +7 -19
  381. package/dist/types/wallet-server/src/core/ThresholdService/validation.d.ts +0 -34
  382. package/dist/types/wallet-server/src/core/WalletAuthMethodStore.d.ts +1 -5
  383. package/dist/types/wallet-server/src/core/WalletStore.d.ts +0 -3
  384. package/dist/types/wallet-server/src/core/WebAuthnAuthenticatorStore.d.ts +0 -20
  385. package/dist/types/wallet-server/src/core/WebAuthnCredentialBindingStore.d.ts +1 -27
  386. package/dist/types/wallet-server/src/core/WebAuthnLoginChallengeStore.d.ts +2 -16
  387. package/dist/types/wallet-server/src/core/WebAuthnSyncChallengeStore.d.ts +22 -14
  388. package/dist/types/wallet-server/src/core/authService/emailOtpConfig.d.ts +0 -24
  389. package/dist/types/wallet-server/src/core/authService/emailOtpEnrollment.d.ts +1 -70
  390. package/dist/types/wallet-server/src/core/authService/emailOtpSeal.d.ts +0 -13
  391. package/dist/types/wallet-server/src/core/authService/githubOAuth.d.ts +2 -1
  392. package/dist/types/wallet-server/src/core/authService/nearTransactions.d.ts +1 -39
  393. package/dist/types/wallet-server/src/core/authService/rateLimits.d.ts +0 -17
  394. package/dist/types/wallet-server/src/core/authService/webauthn.d.ts +0 -125
  395. package/dist/types/wallet-server/src/core/authService/webauthnOidcHelpers.d.ts +0 -3
  396. package/dist/types/wallet-server/src/core/authService/webauthnVerificationOutcomes.d.ts +1 -1
  397. package/dist/types/wallet-server/src/core/authService/webauthnWalletBinding.d.ts +0 -12
  398. package/dist/types/wallet-server/src/core/config.d.ts +0 -10
  399. package/dist/types/wallet-server/src/core/d1Ed25519SignerRead.d.ts +17 -0
  400. package/dist/types/wallet-server/src/core/d1IdentityStore.d.ts +0 -2
  401. package/dist/types/wallet-server/src/core/d1TenantStore.d.ts +0 -7
  402. package/dist/types/wallet-server/src/core/d1WalletAuthMethodStore.d.ts +0 -1
  403. package/dist/types/wallet-server/src/core/d1WalletStore.d.ts +6 -0
  404. package/dist/types/wallet-server/src/core/deviceLinking/linkedDeviceBootstrap.d.ts +19 -0
  405. package/dist/types/wallet-server/src/core/deviceLinking/linkedDeviceSession.d.ts +8 -6
  406. package/dist/types/wallet-server/src/core/deviceLinking/requestProof.d.ts +2 -5
  407. package/dist/types/wallet-server/src/core/emailOtpD1Statements.d.ts +11 -7
  408. package/dist/types/wallet-server/src/core/keyMaterialBrands.d.ts +1 -5
  409. package/dist/types/wallet-server/src/core/nearRelayerAccountProvisioning.d.ts +0 -1
  410. package/dist/types/wallet-server/src/core/passkeyCredentialClaims.d.ts +9 -0
  411. package/dist/types/wallet-server/src/core/routerAbSigning/RouterAbEcdsaPresignRuntime.d.ts +5 -3
  412. package/dist/types/wallet-server/src/core/routerAbSigning/RouterAbNormalSigningRuntime.d.ts +0 -2
  413. package/dist/types/wallet-server/src/core/signingMaterial/ordinaryInactiveSignerMaterialReservation.d.ts +1 -0
  414. package/dist/types/wallet-server/src/core/threeRouteRegistrationContracts.d.ts +15 -140
  415. package/dist/types/wallet-server/src/core/threeRouteRegistrationContracts.typecheck.d.ts +4 -52
  416. package/dist/types/wallet-server/src/core/thresholdEcdsaChainTarget.d.ts +0 -1
  417. package/dist/types/wallet-server/src/core/types.d.ts +0 -299
  418. package/dist/types/wallet-server/src/hosted-wallet-gateway.d.ts +18 -5
  419. package/dist/types/wallet-server/src/index.d.ts +8 -13
  420. package/dist/types/wallet-server/src/localIntendedYaoSigningFault.d.ts +1 -16
  421. package/dist/types/wallet-server/src/localRegistrationSetupAuthority.d.ts +13 -0
  422. package/dist/types/wallet-server/src/router/auth/commonRouterUtils.d.ts +7 -1
  423. package/dist/types/wallet-server/src/router/auth/routerApiCredentialAuth.d.ts +11 -3
  424. package/dist/types/wallet-server/src/router/auth/walletRegistrationContext.d.ts +8 -0
  425. package/dist/types/wallet-server/src/router/cloudflare/d1/auth/d1AuthorizationAssembly.d.ts +23 -0
  426. package/dist/types/wallet-server/src/router/cloudflare/d1/auth/d1EmailOtpRouteService.d.ts +16 -0
  427. package/dist/types/wallet-server/src/router/cloudflare/d1/auth/d1RouterApiAuthConfig.d.ts +28 -3
  428. package/dist/types/wallet-server/src/router/cloudflare/d1/auth/d1RouterApiAuthService.d.ts +4 -1
  429. package/dist/types/wallet-server/src/router/cloudflare/d1/auth/walletSessionCredentialReaders.d.ts +7 -1
  430. package/dist/types/wallet-server/src/router/cloudflare/d1/authorization/d1AuthorizationStore.d.ts +33 -2
  431. package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceAuthorityInstallService.d.ts +5 -1
  432. package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceEmailOtpGrantStore.d.ts +7 -1
  433. package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceRequestProofNonceStore.d.ts +1 -10
  434. package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceRouteService.d.ts +4 -0
  435. package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceSessionStore.d.ts +6 -0
  436. package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceTargetPlanner.d.ts +1 -13
  437. package/dist/types/wallet-server/src/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoLifecycleDecisionStore.d.ts +3 -1
  438. package/dist/types/wallet-server/src/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoProductRegistrationPartitionedStateStore.d.ts +1 -0
  439. package/dist/types/wallet-server/src/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoStateWriteFence.d.ts +8 -0
  440. package/dist/types/wallet-server/src/router/cloudflare/d1/ed25519Yao/d1WalletCeremonyActivity.d.ts +15 -0
  441. package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeIssuer.d.ts +6 -1
  442. package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeService.d.ts +2 -2
  443. package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeStore.d.ts +2 -1
  444. package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeVerifier.d.ts +4 -1
  445. package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpCounters.typecheck.d.ts +2 -0
  446. package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpGrantStore.d.ts +0 -2
  447. package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpRateLimitStore.d.ts +6 -13
  448. package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpRecords.d.ts +21 -7
  449. package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1GoogleEmailOtpRegistrationAttemptStore.d.ts +29 -1
  450. package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1GoogleEmailOtpRegistrationRecords.d.ts +3 -16
  451. package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1GoogleEmailOtpSessionResolver.d.ts +7 -2
  452. package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1GoogleRegistrationCompletion.d.ts +23 -0
  453. package/dist/types/wallet-server/src/router/cloudflare/d1/identity/d1IdentityService.d.ts +0 -12
  454. package/dist/types/wallet-server/src/router/cloudflare/d1/near/d1SponsoredNearAccount.d.ts +24 -0
  455. package/dist/types/wallet-server/src/router/cloudflare/d1/near/d1SponsoredNearAccount.typecheck.d.ts +2 -0
  456. package/dist/types/wallet-server/src/router/cloudflare/d1/oidc/d1OidcVerificationService.d.ts +0 -1
  457. package/dist/types/wallet-server/src/router/cloudflare/d1/oidc/googleOidcToken.d.ts +4 -0
  458. package/dist/types/wallet-server/src/router/cloudflare/d1/passkeyCustody/d1PasskeyCustodyRouteService.d.ts +5 -0
  459. package/dist/types/wallet-server/src/router/cloudflare/d1/passkeyCustody/d1WalletCustodyCommitStore.d.ts +26 -1
  460. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationCeremonyRecordStore.d.ts +33 -8
  461. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationCeremonyRecords.d.ts +10 -11
  462. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationCeremonyStore.d.ts +17 -7
  463. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationSessionTransaction.d.ts +13 -0
  464. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationSetupSupport.d.ts +58 -0
  465. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletExecutionAuthority.d.ts +41 -0
  466. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletOperationStore.d.ts +28 -0
  467. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationCommitStore.d.ts +9 -9
  468. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationInitialSession.d.ts +17 -0
  469. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationPreparation.d.ts +12 -0
  470. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationRead.d.ts +43 -0
  471. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationService.d.ts +52 -90
  472. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationSetup.d.ts +3 -30
  473. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationSetupExecution.d.ts +16 -0
  474. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/walletRegistrationEstablishedSessionIssuer.d.ts +42 -14
  475. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/walletRegistrationSessionCommitReceipt.d.ts +5 -4
  476. package/dist/types/wallet-server/src/router/cloudflare/d1/signingAdmission/d1RouterAbNormalSigningAdmissionStore.d.ts +24 -1
  477. package/dist/types/wallet-server/src/router/cloudflare/d1/versionedJson/d1VersionedJsonRecordStore.d.ts +10 -4
  478. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/authorizationSnapshotLayout.d.ts +21 -0
  479. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAddSignerFinalizeRecord.d.ts +27 -0
  480. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAddSignerService.d.ts +4 -10
  481. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthMethodService.d.ts +5 -9
  482. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorityStore.d.ts +8 -4
  483. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorizationCleanup.d.ts +20 -0
  484. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorizationFreeze.d.ts +12 -0
  485. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorizationHistory.d.ts +20 -0
  486. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorizationIntake.d.ts +29 -0
  487. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorizationSnapshot.d.ts +31 -0
  488. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationApprovals.d.ts +49 -0
  489. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationChallenges.d.ts +47 -0
  490. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationEmailOtp.d.ts +25 -0
  491. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationOwner.d.ts +88 -0
  492. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationOwnerRequest.d.ts +37 -0
  493. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationPasskey.d.ts +12 -0
  494. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationReadAccess.d.ts +18 -0
  495. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationSessions.d.ts +23 -0
  496. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationWriteBlock.d.ts +16 -0
  497. package/dist/types/wallet-server/src/router/cloudflare/d1/walletObjectAddresses.d.ts +14 -0
  498. package/dist/types/wallet-server/src/router/cloudflare/d1/webauthn/d1WebAuthnAuthService.d.ts +3 -0
  499. package/dist/types/wallet-server/src/router/cloudflare/d1/webauthn/d1WebAuthnRecords.d.ts +0 -13
  500. package/dist/types/wallet-server/src/router/cloudflare/d1/webauthn/d1WebAuthnStore.d.ts +23 -10
  501. package/dist/types/wallet-server/src/router/cloudflare/d1/webauthn/d1WebAuthnStore.typecheck.d.ts +2 -0
  502. package/dist/types/wallet-server/src/router/cloudflare/runtime/cloudflare.types.d.ts +0 -2
  503. package/dist/types/wallet-server/src/router/cloudflare/runtime/routerAbServiceBindings.d.ts +13 -0
  504. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletAuthorizationRelocationRoutes.d.ts +21 -0
  505. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletConsoleOps.d.ts +1 -0
  506. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletConsoleOpsClient.d.ts +3 -1
  507. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletControlOps.d.ts +2 -1
  508. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletGateway.d.ts +3 -1
  509. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletObjectAddresses.d.ts +45 -0
  510. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletPlacementRoutes.d.ts +30 -0
  511. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRelocationDeriver.d.ts +11 -0
  512. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRelocationEcdsa.d.ts +7 -0
  513. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRelocationEd25519.d.ts +7 -0
  514. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRelocationOps.d.ts +11 -0
  515. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRelocationPresign.d.ts +7 -0
  516. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRelocationSource.d.ts +26 -0
  517. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRuntimeOps.d.ts +3 -0
  518. package/dist/types/wallet-server/src/router/cloudflare/signingLanes/cloudflareOrdinaryInactiveSignerMaterialReservation.d.ts +5 -0
  519. package/dist/types/wallet-server/src/router/cloudflare-adaptor.d.ts +0 -1
  520. package/dist/types/wallet-server/src/router/domains/ecdsa/routerAbEcdsaStrictRegistration.d.ts +3 -0
  521. package/dist/types/wallet-server/src/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoCapabilityCommit.d.ts +7 -0
  522. package/dist/types/wallet-server/src/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistration.d.ts +42 -8
  523. package/dist/types/wallet-server/src/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationPartitionedStateStore.d.ts +33 -2
  524. package/dist/types/wallet-server/src/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationPartitioning.d.ts +2 -2
  525. package/dist/types/wallet-server/src/router/domains/ed25519Yao/export/routerAbEd25519YaoExport.d.ts +14 -8
  526. package/dist/types/wallet-server/src/router/domains/ed25519Yao/export/routerAbEd25519YaoExport.typecheck.d.ts +2 -0
  527. package/dist/types/wallet-server/src/router/domains/ed25519Yao/export/routerAbEd25519YaoExportRequestScopedCloudflare.d.ts +2 -0
  528. package/dist/types/wallet-server/src/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecovery.d.ts +17 -9
  529. package/dist/types/wallet-server/src/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecoveryRequestScopedCloudflare.d.ts +2 -0
  530. package/dist/types/wallet-server/src/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecoveryWalletSessionAuthorization.d.ts +2 -0
  531. package/dist/types/wallet-server/src/router/domains/ed25519Yao/registration/routerAbEd25519YaoHttpRegistrationBackend.d.ts +13 -14
  532. package/dist/types/wallet-server/src/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistration.d.ts +7 -3
  533. package/dist/types/wallet-server/src/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationExecutionRecord.d.ts +1 -0
  534. package/dist/types/wallet-server/src/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationIntentAuthorization.d.ts +6 -1
  535. package/dist/types/wallet-server/src/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationSideEffectBoundary.d.ts +11 -0
  536. package/dist/types/wallet-server/src/router/domains/ed25519Yao/routerAbEd25519YaoGatewayEnvelope.d.ts +12 -3
  537. package/dist/types/wallet-server/src/router/domains/passkeyCustody/passkeyCustodyEnvelopeRetrieval.d.ts +0 -2
  538. package/dist/types/wallet-server/src/router/domains/passkeyCustody/registrationCustodyOutcome.d.ts +10 -6
  539. package/dist/types/wallet-server/src/router/domains/passkeyCustody/walletCustodyRegistrationAdmission.d.ts +10 -3
  540. package/dist/types/wallet-server/src/router/domains/passkeyCustody/walletCustodyRegistrationCommit.d.ts +12 -8
  541. package/dist/types/wallet-server/src/router/domains/signingOperations/authorizedOperationWire.d.ts +97 -0
  542. package/dist/types/wallet-server/src/router/domains/signingOperations/ecdsaSigningResponse.d.ts +13 -0
  543. package/dist/types/wallet-server/src/router/domains/signingOperations/routerAbNormalSigningAdmission.d.ts +9 -206
  544. package/dist/types/wallet-server/src/router/domains/signingOperations/routerAbPrivateSigningWorker.d.ts +0 -17
  545. package/dist/types/wallet-server/src/router/domains/signingOperations/signingPrepareSession.d.ts +23 -0
  546. package/dist/types/wallet-server/src/router/domains/signingOperations/walletExecutionAdmission.d.ts +1 -2
  547. package/dist/types/wallet-server/src/router/domains/walletRegistration/registrationSessionSeal.d.ts +36 -0
  548. package/dist/types/wallet-server/src/router/domains/walletRegistration/walletRegistrationInputs.d.ts +8 -7
  549. package/dist/types/wallet-server/src/router/domains/walletRegistration/walletRegistrationReservation.d.ts +125 -0
  550. package/dist/types/wallet-server/src/router/domains/walletRegistration/walletRegistrationRoutes.d.ts +17 -15
  551. package/dist/types/wallet-server/src/router/domains/walletRegistration/walletRegistrationSetupPayload.d.ts +2 -2
  552. package/dist/types/wallet-server/src/router/framework/apiCredentialPorts.d.ts +24 -0
  553. package/dist/types/wallet-server/src/router/framework/authServicePort.d.ts +35 -41
  554. package/dist/types/wallet-server/src/router/framework/googleLoginResolution.typecheck.d.ts +2 -0
  555. package/dist/types/wallet-server/src/router/framework/registrationSetupDispatch.d.ts +13 -0
  556. package/dist/types/wallet-server/src/router/framework/routerApi.d.ts +3 -12
  557. package/dist/types/wallet-server/src/router/transport/fetch/routes/deviceLinking.d.ts +1 -1
  558. package/dist/types/wallet-server/src/router/transport/fetch/routes/deviceLinkingResponses.d.ts +17 -0
  559. package/dist/types/wallet-server/src/router/transport/fetch/routes/ecdsaOperationStepUpFactor.d.ts +37 -0
  560. package/dist/types/wallet-server/src/router/transport/fetch/routes/ed25519AuthorizedOperationRevalidation.d.ts +37 -0
  561. package/dist/types/wallet-server/src/router/transport/fetch/routes/thresholdEcdsa.d.ts +1 -17
  562. package/dist/types/wallet-server/src/storage/d1Sql.d.ts +0 -1
  563. package/dist/types/wallet-server/src/storage/tenantRoute.d.ts +1 -1
  564. package/migrations/d1-signer/0040_namespace_home_challenges.sql +16 -0
  565. package/migrations/d1-signer/0041_step_up_admission_expiry.sql +28 -0
  566. package/migrations/d1-signer/0042_deployment_resource_challenges.sql +4 -0
  567. package/migrations/d1-signer/0043_google_registration_candidate_claim.sql +2 -0
  568. package/migrations/d1-signer/0044_linked_device_bootstrap_imports.sql +6 -0
  569. package/migrations/d1-signer/0045_wallet_owned_capability_receipts.sql +29 -0
  570. package/migrations/d1-signer/0046_wallet_owned_signing_abuse.sql +41 -0
  571. package/migrations/d1-signer/0047_remove_unused_near_public_keys.sql +2 -0
  572. package/migrations/d1-signer/0048_operation_owner_scope.sql +45 -0
  573. package/migrations/d1-signer/0049_wallet_relocation_challenges.sql +16 -0
  574. package/migrations/d1-signer/0050_wallet_relocation_approvals.sql +14 -0
  575. package/migrations/d1-signer/0051_wallet_relocation_email_otp.sql +92 -0
  576. package/migrations/d1-signer/0052_wallet_relocation_session_fences.sql +91 -0
  577. package/migrations/d1-signer/0053_wallet_hosted_history_import.sql +164 -0
  578. package/migrations/d1-signer/0054_wallet_authorization_freeze.sql +318 -0
  579. package/migrations/d1-signer/0055_wallet_authorization_snapshot.sql +120 -0
  580. package/migrations/d1-signer/0056_wallet_authorization_history_import.sql +424 -0
  581. package/migrations/d1-signer/0057_wallet_authorization_intake.sql +44 -0
  582. package/migrations/d1-signer/0058_wallet_ceremony_activity.sql +59 -0
  583. package/migrations/d1-signer/0059_wallet_authorization_activation.sql +45 -0
  584. package/migrations/d1-signer/0060_wallet_authorization_cleanup.sql +153 -0
  585. package/migrations/d1-signer/0061_wallet_session_operation_settlement.sql +28 -0
  586. package/migrations/d1-signer/0062_wallet_step_up_operation_settlement.sql +204 -0
  587. package/migrations/d1-signer/0063_wallet_operation_history_transfer.sql +466 -0
  588. package/migrations/d1-signer/0064_wallet_execution_generations.sql +93 -0
  589. package/migrations/d1-signer/0065_wallet_operation_execution_generation.sql +37 -0
  590. package/migrations/d1-signer/0066_regional_deployment_admission.sql +59 -0
  591. package/migrations/d1-signer/0067_registration_completion_decision.sql +12 -0
  592. package/migrations/d1-signer/0068_registration_cancellation_write_fence.sql +24 -0
  593. package/migrations/d1-signer/0069_cancelled_registration_session_fence.sql +11 -0
  594. package/migrations/d1-signer/0070_wallet_passkey_relocation.sql +369 -0
  595. package/migrations/d1-signer/0071_regional_wallet_otp_counters.sql +98 -0
  596. package/migrations/d1-signer/0072_linked_device_relocation_history.sql +899 -0
  597. package/migrations/d1-signer/0073_wallet_recovery_relocation.sql +86 -0
  598. package/migrations/d1-signer/0074_email_otp_relocation.sql +158 -0
  599. package/migrations/d1-signer/0075_wallet_authorization_return.sql +107 -0
  600. package/migrations/d1-signer/0076_wallet_relocation_write_block.sql +406 -0
  601. package/migrations/d1-signer/0077_wallet_object_addresses.sql +24 -0
  602. package/package.json +2 -3
  603. package/src/README.md +33 -3
  604. package/cloudflare-router-ab/scripts/local-key-material.mjs +0 -29
  605. package/dist/esm/core/AuthService.js +0 -2
  606. package/dist/esm/core/NearPublicKeyStore.js +0 -200
  607. package/dist/esm/core/ThresholdService/stores/CloudflareDurableObjectStore.js +0 -397
  608. package/dist/esm/core/ThresholdService/stores/KeyStore.js +0 -140
  609. package/dist/esm/core/ThresholdService/stores/SessionStore.js +0 -361
  610. package/dist/esm/core/ThresholdService/stores/StoreConfig.js +0 -13
  611. package/dist/esm/core/ThresholdService/stores/exportReplayGuard.js +0 -7
  612. package/dist/esm/core/authService/AuthService.js +0 -594
  613. package/dist/esm/core/authService/bytes.js +0 -19
  614. package/dist/esm/core/authService/configValues.js +0 -15
  615. package/dist/esm/core/authService/emailOtpChallengeOperations.js +0 -123
  616. package/dist/esm/core/authService/emailOtpChallengeProof.js +0 -183
  617. package/dist/esm/core/authService/emailOtpChallengeVerification.js +0 -264
  618. package/dist/esm/core/authService/emailOtpChallenges.js +0 -225
  619. package/dist/esm/core/authService/emailOtpDelivery.js +0 -134
  620. package/dist/esm/core/authService/emailOtpGrant.js +0 -43
  621. package/dist/esm/core/authService/emailOtpRegistrationEnrollment.js +0 -144
  622. package/dist/esm/core/authService/emailOtpUnlock.js +0 -174
  623. package/dist/esm/core/authService/googleEmailOtpOperations.js +0 -141
  624. package/dist/esm/core/authService/googleEmailOtpRegistration.js +0 -587
  625. package/dist/esm/core/authService/identity.js +0 -42
  626. package/dist/esm/core/authService/identityOperations.js +0 -32
  627. package/dist/esm/core/authService/nearAccountOperations.js +0 -229
  628. package/dist/esm/core/authService/nearPublicKeyMetadata.js +0 -108
  629. package/dist/esm/core/authService/oidcVerification.js +0 -249
  630. package/dist/esm/core/authService/registrationThresholdHelpers.js +0 -30
  631. package/dist/esm/core/authService/runtime.js +0 -45
  632. package/dist/esm/core/authService/storeRegistry.js +0 -102
  633. package/dist/esm/core/authService/thresholdStoreSummary.js +0 -32
  634. package/dist/esm/core/authService/webauthnAuthority.js +0 -17
  635. package/dist/esm/core/defaultConfigsServer.js +0 -9
  636. package/dist/esm/core/hostedAccountIds.js +0 -225
  637. package/dist/esm/core/routerAbSigning/createRouterAbSigningRuntimes.js +0 -84
  638. package/dist/esm/core/signingLanes/LaneAggregateRevocationApplicationService.js +0 -86
  639. package/dist/esm/core/signingLanes/LaneEnrollmentActivation.js +0 -324
  640. package/dist/esm/core/signingLanes/LaneEnrollmentRevocation.js +0 -173
  641. package/dist/esm/core/signingLanes/LaneLifecycleApplicationService.js +0 -198
  642. package/dist/esm/core/signingLanes/ecdsaServerRetirement.js +0 -73
  643. package/dist/esm/core/signingLanes/ed25519ServerRetirement.js +0 -68
  644. package/dist/esm/core/storeBackends.js +0 -208
  645. package/dist/esm/core/utils.js +0 -14
  646. package/dist/esm/core/webAuthnStoreBackends.js +0 -198
  647. package/dist/esm/router/cloudflare/d1/near/d1NearPublicKeyStore.js +0 -49
  648. package/dist/esm/router/cloudflare/d1/signingLanes/d1EcdsaLanePrivateBindingResolver.js +0 -10
  649. package/dist/esm/router/cloudflare/d1/signingLanes/d1LaneAggregateRevocationApplicationService.js +0 -22
  650. package/dist/esm/router/cloudflare/d1/signingLanes/d1LaneEffectJournalStore.js +0 -166
  651. package/dist/esm/router/cloudflare/d1/signingLanes/d1LaneEnrollmentGateway.js +0 -38
  652. package/dist/esm/router/cloudflare/d1/signingLanes/d1LaneLifecycleApplicationService.js +0 -20
  653. package/dist/esm/router/cloudflare/d1/signingLanes/d1LaneLifecycleStore.js +0 -1459
  654. package/dist/esm/router/cloudflare/d1/signingLanes/d1LaneLockStore.js +0 -114
  655. package/dist/esm/router/cloudflare/d1/signingLanes/d1LaneProtocolCommitter.js +0 -16
  656. package/dist/esm/router/cloudflare/d1/signingLanes/d1LaneRecords.js +0 -171
  657. package/dist/esm/router/cloudflare/d1/signingLanes/index.js +0 -10
  658. package/dist/esm/router/cloudflare/durableObjects/thresholdStore.js +0 -397
  659. package/dist/esm/router/cloudflare/signingLanes/cloudflareLaneCurveExecution.js +0 -597
  660. package/dist/esm/router/cloudflare/signingLanes/cloudflareLaneProtocolCommitter.js +0 -273
  661. package/dist/esm/router/cloudflare/signingLanes/index.js +0 -4
  662. package/dist/esm/router/cloudflare/signingLanes/linkedDeviceEd25519CeremonyBinding.js +0 -32
  663. package/dist/esm/router/transport/fetch/routes/nearPublicKeys.js +0 -27
  664. package/dist/esm/shared-ts/src/signing-lanes/rotation.js +0 -8
  665. package/dist/esm/shared-ts/src/signing-lanes/rotationDigests.js +0 -358
  666. package/dist/esm/shared-ts/src/signing-lanes/rotationLifecycle.js +0 -313
  667. package/dist/esm/shared-ts/src/signing-lanes/rotationParsers.js +0 -532
  668. package/dist/esm/shared-ts/src/signing-lanes/rotationProtocolParsers.js +0 -323
  669. package/dist/esm/shared-ts/src/signing-lanes/rotationWireFields.js +0 -59
  670. package/dist/types/shared-ts/src/signing-lanes/participantDigest.typecheck.d.ts +0 -2
  671. package/dist/types/shared-ts/src/signing-lanes/rotation.typecheck.d.ts +0 -2
  672. package/dist/types/shared-ts/src/signing-lanes/rotationDigests.d.ts +0 -13
  673. package/dist/types/shared-ts/src/signing-lanes/rotationLifecycle.d.ts +0 -78
  674. package/dist/types/shared-ts/src/signing-lanes/rotationParsers.d.ts +0 -27
  675. package/dist/types/shared-ts/src/signing-lanes/rotationProtocolParsers.d.ts +0 -6
  676. package/dist/types/shared-ts/src/signing-lanes/rotationWireFields.d.ts +0 -20
  677. package/dist/types/shared-ts/src/wallet-recovery/recoveryCodeAttempt.d.ts +0 -59
  678. package/dist/types/wallet-server/src/core/AuthService.d.ts +0 -3
  679. package/dist/types/wallet-server/src/core/NearPublicKeyStore.d.ts +0 -48
  680. package/dist/types/wallet-server/src/core/ThresholdService/stores/CloudflareDurableObjectStore.d.ts +0 -21
  681. package/dist/types/wallet-server/src/core/ThresholdService/stores/KeyStore.d.ts +0 -40
  682. package/dist/types/wallet-server/src/core/ThresholdService/stores/SessionStore.d.ts +0 -98
  683. package/dist/types/wallet-server/src/core/ThresholdService/stores/StoreConfig.d.ts +0 -4
  684. package/dist/types/wallet-server/src/core/ThresholdService/stores/ThresholdStoreConfig.typecheck.d.ts +0 -2
  685. package/dist/types/wallet-server/src/core/ThresholdService/stores/exportReplayGuard.d.ts +0 -3
  686. package/dist/types/wallet-server/src/core/authService/AuthService.d.ts +0 -490
  687. package/dist/types/wallet-server/src/core/authService/bytes.d.ts +0 -3
  688. package/dist/types/wallet-server/src/core/authService/configValues.d.ts +0 -7
  689. package/dist/types/wallet-server/src/core/authService/emailOtpChallengeOperations.d.ts +0 -109
  690. package/dist/types/wallet-server/src/core/authService/emailOtpChallengeProof.d.ts +0 -169
  691. package/dist/types/wallet-server/src/core/authService/emailOtpChallengeVerification.d.ts +0 -47
  692. package/dist/types/wallet-server/src/core/authService/emailOtpChallenges.d.ts +0 -86
  693. package/dist/types/wallet-server/src/core/authService/emailOtpDelivery.d.ts +0 -66
  694. package/dist/types/wallet-server/src/core/authService/emailOtpGrant.d.ts +0 -43
  695. package/dist/types/wallet-server/src/core/authService/emailOtpRegistrationEnrollment.d.ts +0 -49
  696. package/dist/types/wallet-server/src/core/authService/emailOtpUnlock.d.ts +0 -64
  697. package/dist/types/wallet-server/src/core/authService/googleEmailOtpOperations.d.ts +0 -126
  698. package/dist/types/wallet-server/src/core/authService/googleEmailOtpRegistration.d.ts +0 -169
  699. package/dist/types/wallet-server/src/core/authService/identity.d.ts +0 -25
  700. package/dist/types/wallet-server/src/core/authService/identityOperations.d.ts +0 -19
  701. package/dist/types/wallet-server/src/core/authService/nearAccountOperations.d.ts +0 -55
  702. package/dist/types/wallet-server/src/core/authService/nearPublicKeyMetadata.d.ts +0 -44
  703. package/dist/types/wallet-server/src/core/authService/oidcVerification.d.ts +0 -66
  704. package/dist/types/wallet-server/src/core/authService/registrationThresholdHelpers.d.ts +0 -11
  705. package/dist/types/wallet-server/src/core/authService/runtime.d.ts +0 -20
  706. package/dist/types/wallet-server/src/core/authService/storeRegistry.d.ts +0 -53
  707. package/dist/types/wallet-server/src/core/authService/thresholdStoreSummary.d.ts +0 -3
  708. package/dist/types/wallet-server/src/core/authService/webauthnAuthority.d.ts +0 -5
  709. package/dist/types/wallet-server/src/core/defaultConfigsServer.d.ts +0 -5
  710. package/dist/types/wallet-server/src/core/hostedAccountIds.d.ts +0 -16
  711. package/dist/types/wallet-server/src/core/routerAbSigning/createRouterAbSigningRuntimes.d.ts +0 -16
  712. package/dist/types/wallet-server/src/core/signingLanes/LaneAggregateRevocationApplicationService.d.ts +0 -36
  713. package/dist/types/wallet-server/src/core/signingLanes/LaneEffectJournalStore.d.ts +0 -62
  714. package/dist/types/wallet-server/src/core/signingLanes/LaneEnrollmentActivation.d.ts +0 -13
  715. package/dist/types/wallet-server/src/core/signingLanes/LaneEnrollmentRevocation.d.ts +0 -24
  716. package/dist/types/wallet-server/src/core/signingLanes/LaneLifecycleApplicationService.d.ts +0 -141
  717. package/dist/types/wallet-server/src/core/signingLanes/LaneLifecycleStore.d.ts +0 -228
  718. package/dist/types/wallet-server/src/core/signingLanes/ecdsaServerRetirement.d.ts +0 -58
  719. package/dist/types/wallet-server/src/core/signingLanes/ed25519ServerRetirement.d.ts +0 -30
  720. package/dist/types/wallet-server/src/core/signingLanes/signingWorkerLaneMaterialIdentity.d.ts +0 -4
  721. package/dist/types/wallet-server/src/core/storeBackends.d.ts +0 -83
  722. package/dist/types/wallet-server/src/core/utils.d.ts +0 -3
  723. package/dist/types/wallet-server/src/core/webAuthnStoreBackends.d.ts +0 -96
  724. package/dist/types/wallet-server/src/router/cloudflare/d1/near/d1NearPublicKeyStore.d.ts +0 -29
  725. package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/d1EcdsaLanePrivateBindingResolver.d.ts +0 -4
  726. package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/d1LaneAggregateRevocationApplicationService.d.ts +0 -4
  727. package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/d1LaneEffectJournalStore.d.ts +0 -24
  728. package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/d1LaneEnrollmentGateway.d.ts +0 -20
  729. package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/d1LaneLifecycleApplicationService.d.ts +0 -13
  730. package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/d1LaneLifecycleStore.d.ts +0 -51
  731. package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/d1LaneLockStore.d.ts +0 -28
  732. package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/d1LaneProtocolCommitter.d.ts +0 -5
  733. package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/d1LaneRecords.d.ts +0 -107
  734. package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/index.d.ts +0 -10
  735. package/dist/types/wallet-server/src/router/cloudflare/durableObjects/thresholdStore.d.ts +0 -18
  736. package/dist/types/wallet-server/src/router/cloudflare/signingLanes/cloudflareLaneCurveExecution.d.ts +0 -217
  737. package/dist/types/wallet-server/src/router/cloudflare/signingLanes/cloudflareLaneProtocolCommitter.d.ts +0 -73
  738. package/dist/types/wallet-server/src/router/cloudflare/signingLanes/index.d.ts +0 -4
  739. package/dist/types/wallet-server/src/router/cloudflare/signingLanes/linkedDeviceEd25519CeremonyBinding.d.ts +0 -6
  740. package/dist/types/wallet-server/src/router/transport/fetch/routes/nearPublicKeys.d.ts +0 -3
  741. /package/dist/esm/{core/signingLanes/LaneEffectJournalStore.js → authorization/ed25519WalletSessionAdmission.js} +0 -0
  742. /package/dist/esm/{core/signingLanes/LaneLifecycleStore.js → authorization/recoveryRouting.js} +0 -0
  743. /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
- if (headers.has("Server-Timing")) headers.set("Access-Control-Expose-Headers", "Server-Timing");
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
- async function resolvePublishableKeyApiCredentialAuth(input) {
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
- const authResult = await input.publishableKeyAuth.authenticate({
5606
- secret: publishableKey,
5607
- origin,
5608
- environmentId
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: authResult.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
- resolution = await resolveWalletSessionOperationCredentialAdmission({
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/framework/routeResponses.ts
6746
- function routeJson(status, body, options) {
6747
- return {
6748
- status,
6749
- body,
6750
- ...options?.headers ? { headers: options.headers } : {},
6751
- ...options?.usage ? { usage: options.usage } : {}
6752
- };
6753
- }
6754
- function routeError(status, code, message) {
6755
- return routeJson(status, {
6756
- ok: false,
6757
- code,
6758
- message
6759
- });
6760
- }
6761
- function toFetchRouteResponse(response) {
6762
- return new Response(JSON.stringify(response.body), {
6763
- status: response.status,
6764
- headers: {
6765
- "Content-Type": "application/json; charset=utf-8",
6766
- ...response.headers || {}
6767
- }
6768
- });
6769
- }
6770
- //#endregion
6771
- //#region ../shared-ts/src/passkey-custody/custodySecretBinding.ts
6772
- /** The only derivation scheme owner custody supports. */
6773
- const WALLET_SEED_DERIVATION_SCHEME_V1 = "wallet_seed_parallel_hkdf_sha256_v1";
6774
- function buildWalletCustodySeedBinding() {
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 publishableKeyAuth = input.services.publishableKeyAuth;
9187
- if (!publishableKeyAuth) return routeError(500, "route_auth_not_configured", "wallet registration setup requires publishable key auth on this server");
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: async () => await resolvePublishableKeyApiCredentialAuth({
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
- if (resolved.context.principal.kind !== "api_credentials") return routeError(500, "internal", "wallet registration setup requires API credentials");
9212
- const principal = resolved.context.principal.principal;
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
- environmentId: principal.environmentId,
9217
- projectId: principal.projectId,
9218
- envId: principal.envId
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
- const request = parseWalletRegistrationSetupRequest(input.body);
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
- ...runtimePolicyScope ? { runtimePolicyScope } : {},
9230
- ...runtimePolicyScope ? {
9231
- signingRootId: `${runtimePolicyScope.projectId}:${runtimePolicyScope.envId}`,
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" && planKind !== "near_ed25519") return routeError(400, "invalid_body", "kind must name the signer plan");
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 (!ed25519Only && (!ecdsa || typeof ecdsa.activationCorrelationId !== "string" || typeof ecdsa.activationRequestDigestB64u !== "string" || !isPlainObject(ecdsa.clientActivation))) return routeError(400, "invalid_body", "browser-verified clientActivation is required");
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
- if (ecdsa) try {
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
- ...parsedActivation ? { ecdsa: parsedActivation } : {},
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
- * `POST /wallets/register/near-provisioning` — the non-blocking completion
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
- }, serverTiming);
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 applyRegistrationPreparedSessionSeal({
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), sessionPrincipalRoute("near_public_keys", "GET", "/near/public-keys", "List NEAR public keys for current session", ROUTER_API_NEAR_PUBLIC_KEY_SERVICES), publicRoute("wallet_unlock_challenge", "POST", "/wallet/unlock/challenge", "Create wallet unlock challenge", {
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
- walletProjection: ctx.opts.walletProjection
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 ../shared-ts/src/utils/ecdsaServerTiming.ts
13574
- const ECDSA_TIMING_METRICS = new Set([
13575
- "ecdsa_sign_authorize",
13576
- "ecdsa_sign_admit",
13577
- "ecdsa_sign_proxy",
13578
- "ecdsa_sign_complete",
13579
- "ecdsa_sign_total",
13580
- "ecdsa_presign_authenticate",
13581
- "ecdsa_presign_material",
13582
- "ecdsa_presign_admit",
13583
- "ecdsa_presign_proxy",
13584
- "ecdsa_presign_total",
13585
- "ecdsa_presign_sw_material",
13586
- "ecdsa_presign_sw_session",
13587
- "ecdsa_presign_sw_do_total",
13588
- "ecdsa_presign_sw_admit",
13589
- "ecdsa_presign_sw_total"
13590
- ]);
13591
- function parseEcdsaServerTiming(header) {
13592
- const durations = /* @__PURE__ */ new Map();
13593
- if (!header) return durations;
13594
- for (const metric of header.split(",")) {
13595
- const [name, ...parameters] = metric.trim().split(";");
13596
- if (!ECDSA_TIMING_METRICS.has(name) || durations.has(name)) continue;
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 = input.materialSource ?? registrationMaterialSourceV1({
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/ecdsa/thresholdEcdsaRequestValidation.ts
15164
- const POOL_FILL_INIT_KEYS = [
15165
- "presignSessionId",
15166
- "firstMessageB64u",
15167
- "keyHandle",
15168
- "ecdsaThresholdKeyId",
15169
- "count",
15170
- "requestTag",
15171
- "poolFill",
15172
- "authorization",
15173
- "operation"
15174
- ];
15175
- const POOL_FILL_STEP_KEYS = [
15176
- "presignSessionId",
15177
- "ceremonyExpiresAtMs",
15178
- "materialExpiresAtMs",
15179
- "stage",
15180
- "outgoingMessagesB64u",
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
- function unexpectedThresholdEcdsaKey(record, allowedKeys) {
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 hasNonStringValue(values) {
15226
- return values.some((value) => !isStringValue(value));
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
- function parseRouterAbEcdsaDerivationPoolFillInitRouteRequest(raw) {
15229
- if (!isPlainObject(raw)) return invalidThresholdEcdsaBody("Expected JSON object body");
15230
- const unexpectedKey = unexpectedThresholdEcdsaKey(raw, POOL_FILL_INIT_KEYS);
15231
- if (unexpectedKey) return invalidThresholdEcdsaBody(`Unsupported threshold-ecdsa pool-fill init field: ${unexpectedKey}`);
15232
- if (!isPlainObject(raw.poolFill)) return invalidThresholdEcdsaBody("poolFill is required");
15233
- const unexpectedPoolFillKey = unexpectedThresholdEcdsaKey(raw.poolFill, POOL_FILL_ENVELOPE_KEYS);
15234
- if (unexpectedPoolFillKey) return invalidThresholdEcdsaBody(`Unsupported threshold-ecdsa poolFill field: ${unexpectedPoolFillKey}`);
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
- ...pinned,
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
- const commonAuthorizedOperation = {
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 resolution;
16081
+ let context;
15874
16082
  try {
15875
- resolution = await resolveWalletSessionOperationCredentialAdmission({
15876
- authorizationSessions: input.ctx.service.authorizationSessions,
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 (resolution.kind === "not_found") return { kind: "not_found" };
15888
- if (resolution.kind === "rejected") return {
16091
+ if (!context) return {
15889
16092
  kind: "rejected",
15890
- message: "ECDSA operation step-up Wallet Session authorization is invalid"
16093
+ message: "ECDSA operation step-up Wallet Session is unavailable"
15891
16094
  };
15892
- if (resolution.admission.curve !== "ecdsa") return {
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 family is invalid"
16112
+ message: "ECDSA operation step-up Wallet Session authorization is invalid"
15895
16113
  };
15896
- const session = resolution.admission.context.authorization.session;
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(resolution.admission.admission.materialActivation))) return {
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(resolution.admission.admission.materialActivation),
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
- admission: resolution.admission,
16145
+ context,
15929
16146
  activeMaterial
15930
16147
  };
15931
16148
  return {
15932
16149
  kind: "admitted",
15933
16150
  operationKind: "evm.export_key",
15934
- admission: resolution.admission,
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.admission.context.authorization.session;
15995
- const context = v2Resolution.admission.context;
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.admission.context.authorization.session.tenantId,
16024
- principalId: v2Resolution.admission.context.authorization.session.principalId,
16025
- sessionId: String(v2Resolution.admission.context.authorization.session.authorizationId),
16026
- walletId: String(v2Resolution.admission.context.authorization.session.walletId),
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" || !sameWalletSessionOperationCredentialAdmission(v2Resolution.admission, refreshedV2Resolution.admission)) return json$1({
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
- let emailOtpUnseal;
16102
- let factor;
16103
- switch (proof.kind) {
16104
- case "passkey": {
16105
- if (authenticated.session.laneAuthorization.authSource.kind !== "passkey" || proof.authority.factor.credentialIdB64u !== authenticated.session.laneAuthorization.authSource.credentialIdB64u) return json$1({
16106
- ok: false,
16107
- code: "scope_mismatch",
16108
- message: "Passkey authority changed"
16109
- }, { status: 403 });
16110
- const credential = proof.webauthn_authentication;
16111
- if (String(credential.rawId || credential.id).trim() !== authenticated.session.laneAuthorization.authSource.credentialIdB64u) return json$1({
16112
- ok: false,
16113
- code: "unauthorized",
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: nowMs
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: emailOtpUnseal ? {
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 (!sameWalletSessionOperationCredentialAdmission(input.authorization.v2Admission, resolution.admission)) return strictEcdsaExportFailure(403, "scope_mismatch", "ECDSA export operation step-up Wallet Session changed");
16903
- const session = resolution.admission.context.authorization.session;
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
- switch (result.code) {
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 === "internal" ? 500 : 400 });
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
- const receipt = parseEd25519ReusableAuthorizedOperationReceipt(input.body.authorized_operation);
19371
- return {
19372
- ok: true,
19373
- operation: {
19374
- phase: "finalize",
19375
- operationKind: receipt.operation_kind,
19376
- authorizationKind: "reusable_wallet_session",
19377
- receipt
19378
- }
19379
- };
19380
- }
19381
- case "operation_step_up": {
19382
- const receipt = parseEd25519VerifiedStepUpAuthorizedOperationReceipt(input.body.authorized_operation);
19383
- return {
19384
- ok: true,
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, projectEnvironmentId) {
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
- async function readPinnedEd25519WalletProjectEnvironmentId(ctx, authorization, operation) {
20072
- const session = ed25519ReusableWalletSession(authorization);
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.projectEnvironmentId;
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
- const commonAuthorizedOperation = {
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.admitAuthorizedOperation({ operation: {
20337
- tenantId: identity.tenantId,
20338
- authorizedOperationId,
20339
- auditEventId: requireAuthorizationValue(parseAuthorizationAuditEventId(`ed25519-operation-audit:${operation.operationId}`)),
20340
- operation: envelope,
20341
- authorization: {
20342
- kind: "authorization_grant",
20343
- authorizationGrantRef: buildAuthorizationGrantRef(identity.authorizationId)
20344
- },
20345
- quota: {
20346
- kind: "consume_reusable_wallet_session",
20347
- quotaId: identity.quotaId
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
- claimedAtMs: nowMs
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
- case "wallet_session_quota_exhausted":
20477
- case "material_mismatch": return {
20439
+ } catch (error) {
20440
+ return {
20478
20441
  ok: false,
20479
20442
  response: json$1({
20480
20443
  ok: false,
20481
- code: result.kind,
20482
- message: "Ed25519 operation admission failed"
20483
- }, { status: 409 })
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 fingerprint = await computeCapabilityOperationFingerprintDigest(buildCapabilityOperationEnvelope({
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 operationResult = await input.ctx.service.authorizedOperations.readAuthorizedOperation({
20530
- tenantId: identity.tenantId,
20531
- operationFingerprintDigest: fingerprint
20532
- });
20533
- if (!operationResult) return {
20534
- ok: false,
20535
- response: json$1({
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
- code: "authorized_operation_missing",
20538
- message: "Authorized operation is unavailable"
20539
- }, { status: 409 })
20540
- };
20541
- if (operationResult.authorizedOperationId !== requireAuthorizationValue(parseAuthorizedOperationId(receipt.authorized_operation_id)) || operationResult.operationFingerprintDigest !== fingerprint) throw new Error("Ed25519 authorized operation identity changed after prepare");
20542
- const revalidated = await revalidateEd25519AuthorizedOperation({
20543
- ctx: input.ctx,
20544
- operation: operationResult
20545
- });
20546
- return revalidated.ok ? {
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: revalidated.operation
20550
- } : revalidated;
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 revalidateEd25519AuthorizedOperation({
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
- return new Response(JSON.stringify({
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: new Headers(upstream.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: { ...buildEd25519GatewayOwnerWalletSessionBinding(authorization, await readPinnedEd25519WalletProjectEnvironmentId(input.ctx, authorization, execution.operation)) }
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
- return new Response(JSON.stringify({
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: new Headers(upstream.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: { ...buildEd25519GatewayOwnerWalletSessionBinding(authorization, await readPinnedEd25519WalletProjectEnvironmentId(input.ctx, authorization, validatedAuthorization.operation)) }
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 !== "ed25519" && raw.curve !== "ecdsa_secp256k1") throw new Error("owner execution-lane preflight curve is invalid");
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
- let walletIdRaw;
21491
- let authorization;
21492
- if (request.curve === "ed25519") {
21493
- const validated = await validateRouterAbEd25519WalletSessionInputs({
21494
- headers,
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.value,
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
- const parts = String(pathname || "").split("/").filter(Boolean);
21667
- if (parts.length !== 3 || parts[0] !== "auth") return null;
21668
- return parseAuthProviderAction({
21669
- provider: parts[1],
21670
- action: parts[2]
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
- //#endregion
22086
- //#region src/router/framework/ror/provider.ts
22087
- function validateRouterApiRorOptions(ror) {
22088
- if (!ror || typeof ror !== "object") throw new Error("[router.ror] Invalid ROR options: expected object");
22089
- if (!ror.provider || typeof ror.provider.getAllowedOrigins !== "function") throw new Error("[router.ror] Invalid ROR options: provider.getAllowedOrigins is required");
22090
- const staticRpId = normalizeOptionalTrimmedString(ror.rpId).toLowerCase();
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 resolveRorRpId(input) {
22102
- const ror = input.ror;
22103
- if (!ror) return null;
22104
- const staticRpId = normalizeOptionalTrimmedString(ror.rpId).toLowerCase();
22105
- if (staticRpId) return staticRpId;
22106
- const hostMap = ror.rpIdByHost;
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
- //#endregion
22113
- //#region src/router/transport/fetch/routes/wellKnown.ts
22114
- async function handleWellKnown(ctx) {
22115
- if (ctx.method !== "GET") return null;
22116
- 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/`) {
22117
- const keyset = ctx.opts.routerAbPublicKeyset;
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
- origins,
22147
- capabilities: { signingSessionSeal }
22148
- }, {
22149
- status: 200,
22150
- headers: { "Cache-Control": "max-age=60, stale-while-revalidate=600" }
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 readJsonBody(ctx.request);
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 readJsonBody(ctx.request.clone());
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 authDeniedResponse$2({
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
- return jsonFailure(value.code === "expired" ? 401 : value.code === "invalid" ? 403 : 401, value.code, value.message);
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
- admissionRequest: input.admissionRequest
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, admissionRequest, traceContext) {
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(admissionRequest) {
25197
+ async resolveRegistrationDispatchRoot(signingRootId) {
25260
25198
  return await routerAbEd25519YaoTenantRootWireV1(await this.config.resolveTenantRoot({
25261
25199
  operation: "registration",
25262
- admissionRequest
25200
+ ...signingRootId
25263
25201
  }));
25264
25202
  }
25265
- async executePinnedRegistration(request, admissionRequest, dispatchRoot, traceContext) {
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.tenantRoot,
25278
- wallet_id: input.walletId,
25279
- lifecycle_id: input.lifecycleId,
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, admissionRequest, dispatchRoot, attempt, replay, traceContext) {
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: this.headers(traceId),
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(authorization) {
25571
- if (authorization.kind === "wallet_recovery") return authorization;
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.authorization), traceContext.value);
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.authorization), traceContext.value);
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.authorization), traceContext.value);
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.authorizationNonces = /* @__PURE__ */ new Set();
25942
- this.authorizationUncertain = /* @__PURE__ */ new Set();
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.bindVerifiedIntent(input);
26210
+ const bound = await this.input.authorization.bindAndAuthorizeAdmission(input);
26251
26211
  if (!bound.ok) return bound;
26252
- return await this.input.registrationService.admit(bound.admissionRequest);
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
  }