@seams/wallet-server 0.7.1 → 0.8.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 (643) hide show
  1. package/THIRD_PARTY_NOTICES.md +1 -113
  2. package/artifact-manifest.json +78 -33
  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/scripts/prepare-local-runtime-config.mjs +0 -2
  22. package/cloudflare-router-ab/scripts/start-local-role-workers.mjs +77 -20
  23. package/dist/esm/authorization/lifecycleRouting.js +62 -0
  24. package/dist/esm/authorization/service.js +43 -12
  25. package/dist/esm/authorization/vaultProxyUse.js +2 -6
  26. package/dist/esm/cloud-host.js +23 -25
  27. package/dist/esm/core/EmailOtpRecords.js +1 -217
  28. package/dist/esm/core/EmailOtpStores.js +0 -859
  29. package/dist/esm/core/IdentityStore.js +2 -426
  30. package/dist/esm/core/SessionService.js +7 -30
  31. package/dist/esm/core/ThresholdService/config.js +1 -9
  32. package/dist/esm/core/ThresholdService/index.js +0 -4
  33. package/dist/esm/core/ThresholdService/kv.js +1 -66
  34. package/dist/esm/core/ThresholdService/routerAb/ecdsaDerivationPoolFillHandlers.js +1 -13
  35. package/dist/esm/core/ThresholdService/routerAbNormalSigningPolicy.js +4 -21
  36. package/dist/esm/core/ThresholdService/stores/WalletSessionStore.js +0 -617
  37. package/dist/esm/core/ThresholdService/validation.js +2 -346
  38. package/dist/esm/core/WalletAuthMethodStore.js +2 -123
  39. package/dist/esm/core/WalletStore.js +6 -214
  40. package/dist/esm/core/WebAuthnAuthenticatorStore.js +0 -202
  41. package/dist/esm/core/WebAuthnCredentialBindingStore.js +2 -182
  42. package/dist/esm/core/WebAuthnLoginChallengeStore.js +0 -52
  43. package/dist/esm/core/WebAuthnSyncChallengeStore.js +0 -54
  44. package/dist/esm/core/authService/emailOtpConfig.js +1 -195
  45. package/dist/esm/core/authService/emailOtpEnrollment.js +0 -141
  46. package/dist/esm/core/authService/emailOtpSeal.js +0 -78
  47. package/dist/esm/core/authService/nearTransactions.js +3 -98
  48. package/dist/esm/core/authService/rateLimits.js +0 -87
  49. package/dist/esm/core/authService/thresholdEcdsaKeyInventory.js +2 -1
  50. package/dist/esm/core/authService/webauthn.js +14 -464
  51. package/dist/esm/core/authService/webauthnOidcHelpers.js +1 -24
  52. package/dist/esm/core/authService/webauthnVerificationOutcomes.js +5 -24
  53. package/dist/esm/core/authService/webauthnWalletBinding.js +0 -37
  54. package/dist/esm/core/config.js +1 -95
  55. package/dist/esm/core/d1EcdsaSignerRead.js +76 -0
  56. package/dist/esm/core/d1IdentityStore.js +17 -77
  57. package/dist/esm/core/d1TenantStore.js +1 -24
  58. package/dist/esm/core/d1WalletAuthMethodStore.js +2 -5
  59. package/dist/esm/core/d1WalletStore.js +15 -25
  60. package/dist/esm/core/deviceLinking/linkedDeviceBootstrap.js +13 -0
  61. package/dist/esm/core/deviceLinking/linkedDeviceEmailOtpGrant.js +1 -5
  62. package/dist/esm/core/deviceLinking/linkedDeviceSession.js +20 -14
  63. package/dist/esm/core/deviceLinking/linkedDeviceSessionApproval.js +1 -3
  64. package/dist/esm/core/deviceLinking/linkedDeviceSessionRecord.js +2 -8
  65. package/dist/esm/core/deviceLinking/requestProof.js +22 -10
  66. package/dist/esm/core/ecdsaMaterialReadSnapshot.js +85 -0
  67. package/dist/esm/core/emailOtpD1Statements.js +107 -94
  68. package/dist/esm/core/keyMaterialBrands.js +2 -12
  69. package/dist/esm/core/nearKeys.js +0 -1
  70. package/dist/esm/core/nearRelayerAccountProvisioning.js +8 -14
  71. package/dist/esm/core/passkeyCredentialClaims.js +8 -0
  72. package/dist/esm/core/routerAbSigning/RouterAbEcdsaPresignRuntime.js +2 -6
  73. package/dist/esm/core/routerAbSigning/RouterAbNormalSigningRuntime.js +2 -30
  74. package/dist/esm/core/signingLanes/WalletExecutionLaneProjection.js +3 -6
  75. package/dist/esm/core/signingMaterial/ordinaryInactiveSignerMaterialReservation.js +2 -5
  76. package/dist/esm/core/thresholdEcdsaChainTarget.js +2 -7
  77. package/dist/esm/hosted-wallet-gateway.js +68 -45
  78. package/dist/esm/index.js +6 -19
  79. package/dist/esm/localHostedWalletGatewayHandler.js +25 -0
  80. package/dist/esm/localIntendedMaterialAdmissionFault.js +176 -0
  81. package/dist/esm/localIntendedPresignCancellation.js +44 -0
  82. package/dist/esm/localRegistrationSetupAuthority.js +89 -0
  83. package/dist/esm/router/auth/authRequestValidation.js +8 -16
  84. package/dist/esm/router/auth/commonRouterUtils.js +24 -10
  85. package/dist/esm/router/auth/walletSessionFailure.js +2 -5
  86. package/dist/esm/router/auth/webAuthnCredentialCodecs.js +4 -16
  87. package/dist/esm/router/cloudflare/d1/auth/d1AuthorizationAssembly.js +87 -0
  88. package/dist/esm/router/cloudflare/d1/auth/d1AuthorizedOperationRouteService.js +1 -0
  89. package/dist/esm/router/cloudflare/d1/auth/d1RouterApiAuthBoundary.js +2 -6
  90. package/dist/esm/router/cloudflare/d1/auth/d1RouterApiAuthConfig.js +12 -2
  91. package/dist/esm/router/cloudflare/d1/auth/d1RouterApiAuthService.js +37 -308
  92. package/dist/esm/router/cloudflare/d1/auth/walletSessionCredentialReaders.js +76 -0
  93. package/dist/esm/router/cloudflare/d1/authorization/authorizedOperationStatements.js +52 -43
  94. package/dist/esm/router/cloudflare/d1/authorization/d1AuthorizationStore.js +217 -50
  95. package/dist/esm/router/cloudflare/d1/authorization/d1VaultProxyStore.js +8 -12
  96. package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceAuthorityInstallService.js +62 -21
  97. package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceEd25519ExportRootStore.js +6 -1
  98. package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceEmailOtpGrantStore.js +12 -2
  99. package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceEmailOtpTargetFactor.js +4 -4
  100. package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceOwnerAuthorizationProvider.js +1 -1
  101. package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceRequestProofNonceStore.js +3 -9
  102. package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceRouteService.js +2 -1
  103. package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceSessionStore.js +89 -7
  104. package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceTargetCredentialProvider.js +24 -15
  105. package/dist/esm/router/cloudflare/d1/deviceLinking/index.js +3 -3
  106. package/dist/esm/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoCapabilityPersistence.js +9 -6
  107. package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeIssuer.js +12 -56
  108. package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeService.js +17 -81
  109. package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeStore.js +1 -1
  110. package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeVerifier.js +0 -1
  111. package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpDeliveryRuntime.js +6 -25
  112. package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpEnrollmentStore.js +1 -1
  113. package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpGrantStore.js +1 -7
  114. package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRateLimitStore.js +19 -13
  115. package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRecords.js +12 -48
  116. package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRecoveryService.js +24 -86
  117. package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRegistrationEnrollmentFinalizer.js +9 -32
  118. package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpServerSealRuntime.js +5 -21
  119. package/dist/esm/router/cloudflare/d1/emailOtp/d1GoogleEmailOtpRegistrationAttemptStore.js +44 -12
  120. package/dist/esm/router/cloudflare/d1/emailOtp/d1GoogleEmailOtpRegistrationRecords.js +1 -49
  121. package/dist/esm/router/cloudflare/d1/emailOtp/d1GoogleEmailOtpSessionResolver.js +37 -136
  122. package/dist/esm/router/cloudflare/d1/emailOtp/d1GoogleRegistrationCompletion.js +85 -0
  123. package/dist/esm/router/cloudflare/d1/identity/d1IdentityRecords.js +0 -1
  124. package/dist/esm/router/cloudflare/d1/identity/d1IdentityService.js +9 -88
  125. package/dist/esm/router/cloudflare/d1/near/d1SponsoredNearAccount.js +242 -0
  126. package/dist/esm/router/cloudflare/d1/oidc/d1OidcBoundary.js +18 -92
  127. package/dist/esm/router/cloudflare/d1/oidc/d1OidcVerificationService.js +4 -55
  128. package/dist/esm/router/cloudflare/d1/oidc/googleOidcToken.js +41 -0
  129. package/dist/esm/router/cloudflare/d1/passkeyCustody/d1PasskeyCustodyRouteService.js +9 -15
  130. package/dist/esm/router/cloudflare/d1/passkeyCustody/d1WalletCustodyCommitStore.js +36 -7
  131. package/dist/esm/router/cloudflare/d1/passkeyCustody/d1WalletRecoveryGoogleEmailOtpRecords.js +9 -13
  132. package/dist/esm/router/cloudflare/d1/passkeyCustody/d1WalletRecoveryGoogleEmailOtpService.js +11 -50
  133. package/dist/esm/router/cloudflare/d1/registration/d1EvmFamilyEcdsaRegistrationBranch.js +5 -20
  134. package/dist/esm/router/cloudflare/d1/registration/d1RegistrationCeremonyRecordStore.js +13 -10
  135. package/dist/esm/router/cloudflare/d1/registration/d1RegistrationCeremonyRecords.js +9 -14
  136. package/dist/esm/router/cloudflare/d1/registration/d1RegistrationCeremonyStore.js +25 -13
  137. package/dist/esm/router/cloudflare/d1/registration/d1RegistrationIntentService.js +7 -31
  138. package/dist/esm/router/cloudflare/d1/registration/d1RegistrationSetupSupport.js +74 -0
  139. package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationCommitStore.js +7 -1
  140. package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationService.js +101 -260
  141. package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationSetup.js +12 -56
  142. package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationSetupExecution.js +155 -0
  143. package/dist/esm/router/cloudflare/d1/registration/walletRegistrationEstablishedSessionIssuer.js +1 -3
  144. package/dist/esm/router/cloudflare/d1/registration/walletRegistrationSessionCommitReceipt.js +1 -4
  145. package/dist/esm/router/cloudflare/d1/signingAdmission/d1RouterAbNormalSigningAdmissionStore.js +131 -31
  146. package/dist/esm/router/cloudflare/d1/wallet/d1WalletAddSignerFinalizeRecord.js +68 -0
  147. package/dist/esm/router/cloudflare/d1/wallet/d1WalletAddSignerService.js +7 -54
  148. package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthMethodService.js +9 -8
  149. package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorityStore.js +2 -142
  150. package/dist/esm/router/cloudflare/d1/webauthn/d1WebAuthnAuthService.js +55 -171
  151. package/dist/esm/router/cloudflare/d1/webauthn/d1WebAuthnRecords.js +10 -79
  152. package/dist/esm/router/cloudflare/d1/webauthn/d1WebAuthnStore.js +23 -7
  153. package/dist/esm/router/cloudflare/runtime/routerAbPrewarm.js +2 -2
  154. package/dist/esm/router/cloudflare/runtime/staticWalletConsoleBinding.js +6 -20
  155. package/dist/esm/router/cloudflare/runtime/tenantRootCreationGrant.js +2 -9
  156. package/dist/esm/router/cloudflare/runtime/walletConsoleOps.js +1 -0
  157. package/dist/esm/router/cloudflare/runtime/walletConsoleOpsClient.js +5 -0
  158. package/dist/esm/router/cloudflare/runtime/walletControlOps.js +2 -1
  159. package/dist/esm/router/cloudflare/runtime/walletGateway.js +1 -1
  160. package/dist/esm/router/cloudflare/runtime/walletRuntimeOps.js +16 -4
  161. package/dist/esm/router/cloudflare-adaptor.js +1 -2
  162. package/dist/esm/router/cloudflare.js +3390 -3437
  163. package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistration.js +11 -8
  164. package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationPartitionedStateStore.js +3 -2
  165. package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationPartitioning.js +6 -6
  166. package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationPersistence.js +5 -8
  167. package/dist/esm/router/domains/ed25519Yao/export/routerAbEd25519YaoExport.js +6 -6
  168. package/dist/esm/router/domains/ed25519Yao/export/routerAbEd25519YaoExportRequestScopedCloudflare.js +3 -0
  169. package/dist/esm/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecoveryRequestScopedCloudflare.js +8 -0
  170. package/dist/esm/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecoveryWalletSessionAuthorization.js +3 -6
  171. package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationIntentAuthorization.js +6 -25
  172. package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationSideEffectBoundary.js +39 -55
  173. package/dist/esm/router/domains/emailOtp/emailOtpRequestValidation.js +0 -1
  174. package/dist/esm/router/domains/emailOtp/emailOtpRouteHandlers.js +15 -62
  175. package/dist/esm/router/domains/passkeyCustody/passkeyCustodyEnvelopeRetrieval.js +2 -8
  176. package/dist/esm/router/domains/passkeyCustody/walletCustodyRegistrationCommit.js +2 -8
  177. package/dist/esm/router/domains/signingOperations/routerAbEcdsaDerivationNormalSigningRoute.js +83 -74
  178. package/dist/esm/router/domains/signingOperations/routerAbNormalSigningAdmission.js +1 -0
  179. package/dist/esm/router/domains/signingOperations/routerAbOperationStepUp.js +1 -0
  180. package/dist/esm/router/domains/signingOperations/routerAbPrivateSigningWorker.js +5 -19
  181. package/dist/esm/router/domains/signingOperations/walletExecutionAdmission.js +3 -7
  182. package/dist/esm/router/domains/tenantRoot/tenantRootIdentityResolution.js +7 -13
  183. package/dist/esm/router/domains/walletRegistration/walletRegistrationReservation.js +70 -0
  184. package/dist/esm/router/domains/walletRegistration/walletRegistrationRoutes.js +10 -11
  185. package/dist/esm/router/domains/walletRegistration/walletRegistrationSetupPayload.js +2 -3
  186. package/dist/esm/router/domains/walletUnlock/walletUnlockRouteHandlers.js +55 -200
  187. package/dist/esm/router/express.js +858 -1145
  188. package/dist/esm/router/framework/http.js +7 -1
  189. package/dist/esm/router/framework/registrationSetupDispatch.js +14 -0
  190. package/dist/esm/router/framework/ror/normalize.js +0 -1
  191. package/dist/esm/router/framework/ror/options.js +0 -1
  192. package/dist/esm/router/framework/ror/provider.js +0 -1
  193. package/dist/esm/router/framework/ror/staticProvider.js +0 -1
  194. package/dist/esm/router/framework/routeDefinitions.js +1 -2
  195. package/dist/esm/router/framework/routerApiWebhooks.js +0 -1
  196. package/dist/esm/router/framework/runtimeSnapshotConsumer.js +8 -35
  197. package/dist/esm/router/ror.js +0 -1
  198. package/dist/esm/router/transport/fetch/createFetchRouter.js +3 -8
  199. package/dist/esm/router/transport/fetch/routes/auth.js +11 -41
  200. package/dist/esm/router/transport/fetch/routes/deviceLinking.js +36 -147
  201. package/dist/esm/router/transport/fetch/routes/deviceLinkingOwnerAuthorization.js +7 -23
  202. package/dist/esm/router/transport/fetch/routes/deviceLinkingResponses.js +130 -0
  203. package/dist/esm/router/transport/fetch/routes/ecdsaOperationStepUpFactor.js +171 -0
  204. package/dist/esm/router/transport/fetch/routes/passkeyCustody.js +1 -0
  205. package/dist/esm/router/transport/fetch/routes/sessions.js +1 -0
  206. package/dist/esm/router/transport/fetch/routes/syncAccount.js +15 -38
  207. package/dist/esm/router/transport/fetch/routes/thresholdEcdsa.js +46 -194
  208. package/dist/esm/router/transport/fetch/routes/walletExecutionLanePreflight.js +4 -1
  209. package/dist/esm/router/transport/fetch/routes/walletRegistration.js +3 -1
  210. package/dist/esm/router/transport/fetch/routes/webauthnAuthenticators.js +4 -16
  211. package/dist/esm/shared-ts/src/authorization/walletSessionIssuance.js +0 -1
  212. package/dist/esm/shared-ts/src/authorization/walletSignerActivationEquality.js +12 -0
  213. package/dist/esm/shared-ts/src/device-linking/authorityActivation.js +0 -2
  214. package/dist/esm/shared-ts/src/device-linking/committedSignerPackages.js +2 -5
  215. package/dist/esm/shared-ts/src/device-linking/contracts.js +16 -1
  216. package/dist/esm/shared-ts/src/device-linking/delegatedActivationPlan.js +1 -5
  217. package/dist/esm/shared-ts/src/device-linking/digests.js +1 -8
  218. package/dist/esm/shared-ts/src/device-linking/ed25519ExportRoot.js +12 -16
  219. package/dist/esm/shared-ts/src/device-linking/sourceContribution.js +5 -8
  220. package/dist/esm/shared-ts/src/near/actions.js +0 -1
  221. package/dist/esm/shared-ts/src/near/nearClient.js +0 -2
  222. package/dist/esm/shared-ts/src/passkey-custody/primitives.js +5 -1
  223. package/dist/esm/shared-ts/src/signing-lanes/evmFamilySigningKeySlotId.js +1 -1
  224. package/dist/esm/shared-ts/src/signing-lanes/index.js +1 -6
  225. package/dist/esm/shared-ts/src/signing-lanes/ownerContinuity.js +5 -9
  226. package/dist/esm/shared-ts/src/signing-lanes/participantDigest.js +2 -81
  227. package/dist/esm/shared-ts/src/signing-lanes/participants.js +1 -219
  228. package/dist/esm/shared-ts/src/signing-lanes/recordParsers.js +0 -3
  229. package/dist/esm/shared-ts/src/tenant-root/tenantRootIdentifier.js +12 -0
  230. package/dist/esm/shared-ts/src/tenant-root/tenantRootIdentity.js +2 -9
  231. package/dist/esm/shared-ts/src/tenant-root/tenantRootOperationRecord.js +2 -6
  232. package/dist/esm/shared-ts/src/threshold/ecdsaDerivationRoleLocalBootstrap.js +0 -1
  233. package/dist/esm/shared-ts/src/threshold/keyMaterialBrands.js +1 -22
  234. package/dist/esm/shared-ts/src/threshold/participants.js +0 -1
  235. package/dist/esm/shared-ts/src/threshold/signingRootScope.js +0 -1
  236. package/dist/esm/shared-ts/src/utils/addWalletAuthMethod.js +4 -13
  237. package/dist/esm/shared-ts/src/utils/canonicalPrimitives.js +1 -7
  238. package/dist/esm/shared-ts/src/utils/domainIds.js +1 -16
  239. package/dist/esm/shared-ts/src/utils/ecdsaCapabilityActivation.js +1 -11
  240. package/dist/esm/shared-ts/src/utils/ecdsaKeyFactsInventory.js +2 -5
  241. package/dist/esm/shared-ts/src/utils/ecdsaServerTiming.js +0 -1
  242. package/dist/esm/shared-ts/src/utils/emailOtpDomain.js +3 -1
  243. package/dist/esm/shared-ts/src/utils/errors.js +1 -19
  244. package/dist/esm/shared-ts/src/utils/exactKeys.js +17 -0
  245. package/dist/esm/shared-ts/src/utils/failure.js +20 -0
  246. package/dist/esm/shared-ts/src/utils/near.js +1 -1
  247. package/dist/esm/shared-ts/src/utils/registrationEstablishedSession.js +1 -1
  248. package/dist/esm/shared-ts/src/utils/registrationIds.js +1 -5
  249. package/dist/esm/shared-ts/src/utils/registrationIntent.js +3 -13
  250. package/dist/esm/shared-ts/src/utils/registrationSetupOperation.js +8 -0
  251. package/dist/esm/shared-ts/src/utils/registrationSignerPlan.js +3 -6
  252. package/dist/esm/shared-ts/src/utils/routerAbEcdsaDerivation.js +1 -2
  253. package/dist/esm/shared-ts/src/utils/routerAbEd25519Yao.js +1 -1
  254. package/dist/esm/shared-ts/src/utils/thresholdEcdsaChainTarget.js +9 -0
  255. package/dist/esm/shared-ts/src/utils/validation.js +1 -5
  256. package/dist/esm/shared-ts/src/utils/walletAuthAuthority.js +0 -1
  257. package/dist/esm/shared-ts/src/utils/walletManagementProtocol.js +6 -0
  258. package/dist/esm/shared-ts/src/utils/wireSchema.js +2 -13
  259. package/dist/esm/shared-ts/src/wallet-recovery/backupAcknowledgement.js +6 -24
  260. package/dist/esm/shared-ts/src/wallet-recovery/recoveryCodeLocator.js +0 -1
  261. package/dist/esm/shared-ts/src/wallet-recovery/recoveryKeyId.js +5 -6
  262. package/dist/esm/shared-ts/src/wallet-recovery/walletRecoveryCommittedProjection.js +1 -4
  263. package/dist/esm/storage/d1Sql.js +1 -7
  264. package/dist/esm/threshold/session/signingSessionSeal/crypto/cipher.js +10 -33
  265. package/dist/esm/threshold/session/signingSessionSeal/guards/backends.js +1 -2
  266. package/dist/esm/threshold/session/signingSessionSeal/idempotencyBackends.js +3 -4
  267. package/dist/esm/threshold/session/signingSessionSeal/idempotencyRecords.js +3 -10
  268. package/dist/esm/threshold/session/signingSessionSeal/options.js +0 -1
  269. package/dist/esm/threshold/session/signingSessionSeal/service.js +8 -35
  270. package/dist/esm/threshold/session/signingSessionSeal/transport/express.js +18 -94
  271. package/dist/esm/threshold/session/signingSessionSeal/transport/fetch.js +6 -30
  272. package/dist/esm/threshold/session/signingSessionSeal/transport/shared.js +5 -20
  273. package/dist/esm/wasm/evm_crypto/pkg/evm_crypto_bg.wasm +0 -0
  274. package/dist/esm/wasm/near_signer/pkg/wasm_signer_worker.js +0 -611
  275. package/dist/esm/wasm/near_signer/pkg/wasm_signer_worker_bg.wasm +0 -0
  276. package/dist/esm/wasm/shamir3pass_runtime/pkg/shamir3pass_runtime_bg.wasm +0 -0
  277. package/dist/types/shared-ts/src/authorization/capabilityKinds.d.ts +0 -4
  278. package/dist/types/shared-ts/src/authorization/delegatedAuthority.d.ts +2 -1
  279. package/dist/types/shared-ts/src/authorization/walletSessionIssuance.d.ts +9 -2
  280. package/dist/types/shared-ts/src/authorization/walletSignerActivationEquality.d.ts +4 -0
  281. package/dist/types/shared-ts/src/device-linking/committedSignerPackages.d.ts +3 -4
  282. package/dist/types/shared-ts/src/device-linking/contracts.d.ts +6 -63
  283. package/dist/types/shared-ts/src/device-linking/sourceContribution.d.ts +2 -0
  284. package/dist/types/shared-ts/src/passkey-custody/custodyEnvelope.d.ts +5 -12
  285. package/dist/types/shared-ts/src/passkey-custody/primitives.d.ts +9 -0
  286. package/dist/types/shared-ts/src/signing-lanes/evmFamilySigningKeySlotId.d.ts +0 -2
  287. package/dist/types/shared-ts/src/signing-lanes/execution.d.ts +11 -12
  288. package/dist/types/shared-ts/src/signing-lanes/ids.d.ts +3 -17
  289. package/dist/types/shared-ts/src/signing-lanes/index.d.ts +0 -4
  290. package/dist/types/shared-ts/src/signing-lanes/ownerContinuity.d.ts +0 -1
  291. package/dist/types/shared-ts/src/signing-lanes/participantDigest.d.ts +0 -18
  292. package/dist/types/shared-ts/src/signing-lanes/participants.d.ts +6 -35
  293. package/dist/types/shared-ts/src/signing-lanes/rotation.d.ts +6 -845
  294. package/dist/types/shared-ts/src/tenant-root/tenantRootIdentifier.d.ts +3 -0
  295. package/dist/types/shared-ts/src/tenant-root/tenantRootOperationRecord.d.ts +2 -1
  296. package/dist/types/shared-ts/src/threshold/ecdsaDerivationRoleLocalBootstrap.d.ts +6 -0
  297. package/dist/types/shared-ts/src/threshold/keyMaterialBrands.d.ts +0 -10
  298. package/dist/types/shared-ts/src/threshold/participants.d.ts +1 -1
  299. package/dist/types/shared-ts/src/threshold/signingRootScope.d.ts +1 -0
  300. package/dist/types/shared-ts/src/utils/addWalletAuthMethod.d.ts +1 -133
  301. package/dist/types/shared-ts/src/utils/addWalletAuthMethod.typecheck.d.ts +4 -18
  302. package/dist/types/shared-ts/src/utils/domainIds.d.ts +0 -12
  303. package/dist/types/shared-ts/src/utils/ecdsaKeyFactsInventory.d.ts +2 -11
  304. package/dist/types/shared-ts/src/utils/eip1559TxWasmJson.d.ts +16 -0
  305. package/dist/types/shared-ts/src/utils/emailOtpDomain.d.ts +2 -0
  306. package/dist/types/shared-ts/src/utils/errors.d.ts +0 -4
  307. package/dist/types/shared-ts/src/utils/exactKeys.d.ts +11 -0
  308. package/dist/types/shared-ts/src/utils/failure.d.ts +12 -0
  309. package/dist/types/shared-ts/src/utils/jsonRpc.d.ts +3 -4
  310. package/dist/types/shared-ts/src/utils/near.d.ts +0 -20
  311. package/dist/types/shared-ts/src/utils/nearRpcResults.d.ts +1 -0
  312. package/dist/types/shared-ts/src/utils/normalize.d.ts +0 -2
  313. package/dist/types/shared-ts/src/utils/registrationAuthMethodInput.d.ts +3 -8
  314. package/dist/types/shared-ts/src/utils/registrationSetupOperation.d.ts +3 -0
  315. package/dist/types/shared-ts/src/utils/registrationSignerPlan.d.ts +7 -19
  316. package/dist/types/shared-ts/src/utils/routerAbEcdsaDerivation.d.ts +3 -1
  317. package/dist/types/shared-ts/src/utils/routerAbEd25519Yao.d.ts +1 -0
  318. package/dist/types/shared-ts/src/utils/routerAbEd25519YaoDigests.d.ts +3 -4
  319. package/dist/types/shared-ts/src/utils/routerAbNormalSigningIdentity.d.ts +30 -8
  320. package/dist/types/shared-ts/src/utils/routerApiKeyAuth.d.ts +2 -0
  321. package/dist/types/shared-ts/src/utils/signingSessionSeal.d.ts +10 -11
  322. package/dist/types/shared-ts/src/utils/thresholdEcdsaChainTarget.d.ts +25 -0
  323. package/dist/types/shared-ts/src/utils/validation.d.ts +1 -3
  324. package/dist/types/shared-ts/src/utils/variant.d.ts +18 -0
  325. package/dist/types/shared-ts/src/utils/walletAuthMethodRecord.d.ts +3 -6
  326. package/dist/types/shared-ts/src/utils/walletCapabilityBindings.d.ts +0 -1
  327. package/dist/types/shared-ts/src/utils/walletManagementProtocol.d.ts +3 -0
  328. package/dist/types/shared-ts/src/utils/webauthnDeviceInfo.d.ts +4 -2
  329. package/dist/types/shared-ts/src/utils/wireSchema.d.ts +0 -2
  330. package/dist/types/shared-ts/src/wallet-recovery/backupAcknowledgement.d.ts +0 -1
  331. package/dist/types/shared-ts/src/wallet-recovery/recoveryCodeReservation.d.ts +1 -10
  332. package/dist/types/shared-ts/src/wallet-recovery/recoveryCodes.d.ts +1 -3
  333. package/dist/types/shared-ts/src/wallet-recovery/recoveryEnvelopes.d.ts +3 -16
  334. package/dist/types/shared-ts/src/wallet-recovery/recoveryKeyId.d.ts +5 -21
  335. package/dist/types/shared-ts/src/wallet-recovery/walletRecoveryPreparation.d.ts +15 -0
  336. package/dist/types/shared-ts/src/wallet-recovery/walletRecoveryTarget.d.ts +3 -4
  337. package/dist/types/wallet-server/src/authorization/domain.d.ts +13 -2
  338. package/dist/types/wallet-server/src/authorization/ecdsaWalletSessionAdmission.d.ts +27 -3
  339. package/dist/types/wallet-server/src/authorization/lifecycleRouting.d.ts +32 -0
  340. package/dist/types/wallet-server/src/authorization/lifecycleRouting.typecheck.d.ts +2 -0
  341. package/dist/types/wallet-server/src/authorization/recoveryRouting.d.ts +22 -0
  342. package/dist/types/wallet-server/src/authorization/recoveryRouting.typecheck.d.ts +2 -0
  343. package/dist/types/wallet-server/src/authorization/service.d.ts +27 -1
  344. package/dist/types/wallet-server/src/authorization/sessionRouting.d.ts +20 -0
  345. package/dist/types/wallet-server/src/authorization/sessionRouting.typecheck.d.ts +2 -0
  346. package/dist/types/wallet-server/src/cloud-host.d.ts +31 -9
  347. package/dist/types/wallet-server/src/core/EmailOtpRecords.d.ts +1 -22
  348. package/dist/types/wallet-server/src/core/EmailOtpStores.d.ts +1 -79
  349. package/dist/types/wallet-server/src/core/IdentityStore.d.ts +0 -10
  350. package/dist/types/wallet-server/src/core/RegistrationCeremonyStore.d.ts +0 -1
  351. package/dist/types/wallet-server/src/core/ThresholdService/config.d.ts +0 -2
  352. package/dist/types/wallet-server/src/core/ThresholdService/index.d.ts +1 -3
  353. package/dist/types/wallet-server/src/core/ThresholdService/kv.d.ts +0 -7
  354. package/dist/types/wallet-server/src/core/ThresholdService/routerAb/ecdsaDerivationPoolFillHandlers.d.ts +0 -3
  355. package/dist/types/wallet-server/src/core/ThresholdService/routerAbNormalSigningPolicy.d.ts +0 -1
  356. package/dist/types/wallet-server/src/core/ThresholdService/stores/WalletSessionStore.d.ts +6 -18
  357. package/dist/types/wallet-server/src/core/ThresholdService/validation.d.ts +0 -127
  358. package/dist/types/wallet-server/src/core/WalletAuthMethodStore.d.ts +1 -5
  359. package/dist/types/wallet-server/src/core/WalletStore.d.ts +0 -3
  360. package/dist/types/wallet-server/src/core/WebAuthnAuthenticatorStore.d.ts +8 -20
  361. package/dist/types/wallet-server/src/core/WebAuthnCredentialBindingStore.d.ts +1 -27
  362. package/dist/types/wallet-server/src/core/WebAuthnLoginChallengeStore.d.ts +2 -16
  363. package/dist/types/wallet-server/src/core/WebAuthnSyncChallengeStore.d.ts +22 -14
  364. package/dist/types/wallet-server/src/core/authService/emailOtpConfig.d.ts +0 -24
  365. package/dist/types/wallet-server/src/core/authService/emailOtpEnrollment.d.ts +1 -70
  366. package/dist/types/wallet-server/src/core/authService/emailOtpSeal.d.ts +1 -14
  367. package/dist/types/wallet-server/src/core/authService/githubOAuth.d.ts +2 -1
  368. package/dist/types/wallet-server/src/core/authService/nearTransactions.d.ts +1 -39
  369. package/dist/types/wallet-server/src/core/authService/rateLimits.d.ts +0 -17
  370. package/dist/types/wallet-server/src/core/authService/webauthn.d.ts +0 -125
  371. package/dist/types/wallet-server/src/core/authService/webauthnOidcHelpers.d.ts +0 -3
  372. package/dist/types/wallet-server/src/core/authService/webauthnVerificationOutcomes.d.ts +1 -1
  373. package/dist/types/wallet-server/src/core/authService/webauthnWalletBinding.d.ts +0 -12
  374. package/dist/types/wallet-server/src/core/config.d.ts +0 -10
  375. package/dist/types/wallet-server/src/core/d1EcdsaSignerRead.d.ts +39 -0
  376. package/dist/types/wallet-server/src/core/d1IdentityStore.d.ts +0 -2
  377. package/dist/types/wallet-server/src/core/d1TenantStore.d.ts +0 -7
  378. package/dist/types/wallet-server/src/core/d1WalletAuthMethodStore.d.ts +0 -1
  379. package/dist/types/wallet-server/src/core/d1WalletStore.d.ts +10 -0
  380. package/dist/types/wallet-server/src/core/deviceLinking/linkedDeviceBootstrap.d.ts +19 -0
  381. package/dist/types/wallet-server/src/core/deviceLinking/linkedDeviceSession.d.ts +8 -6
  382. package/dist/types/wallet-server/src/core/deviceLinking/linkedDeviceSessionRecord.d.ts +3 -4
  383. package/dist/types/wallet-server/src/core/deviceLinking/requestProof.d.ts +2 -5
  384. package/dist/types/wallet-server/src/core/ecdsaMaterialReadSnapshot.d.ts +19 -0
  385. package/dist/types/wallet-server/src/core/emailOtpD1Statements.d.ts +10 -7
  386. package/dist/types/wallet-server/src/core/keyMaterialBrands.d.ts +1 -5
  387. package/dist/types/wallet-server/src/core/nearRelayerAccountProvisioning.d.ts +0 -1
  388. package/dist/types/wallet-server/src/core/passkeyCredentialClaims.d.ts +9 -0
  389. package/dist/types/wallet-server/src/core/routerAbSigning/RouterAbEcdsaPresignRuntime.d.ts +0 -2
  390. package/dist/types/wallet-server/src/core/routerAbSigning/RouterAbNormalSigningRuntime.d.ts +3 -7
  391. package/dist/types/wallet-server/src/core/rpcClients/near/NearClient.d.ts +1 -2
  392. package/dist/types/wallet-server/src/core/signingLanes/WalletExecutionLaneProjection.d.ts +2 -11
  393. package/dist/types/wallet-server/src/core/threeRouteRegistrationContracts.d.ts +1 -92
  394. package/dist/types/wallet-server/src/core/threeRouteRegistrationContracts.typecheck.d.ts +4 -52
  395. package/dist/types/wallet-server/src/core/thresholdEcdsaChainTarget.d.ts +3 -12
  396. package/dist/types/wallet-server/src/core/types.d.ts +2 -305
  397. package/dist/types/wallet-server/src/hosted-wallet-gateway.d.ts +15 -3
  398. package/dist/types/wallet-server/src/index.d.ts +8 -13
  399. package/dist/types/wallet-server/src/localIntendedMaterialAdmissionFault.d.ts +38 -0
  400. package/dist/types/wallet-server/src/localIntendedPresignCancellation.d.ts +4 -0
  401. package/dist/types/wallet-server/src/localRegistrationSetupAuthority.d.ts +13 -0
  402. package/dist/types/wallet-server/src/router/auth/authRequestValidation.d.ts +4 -9
  403. package/dist/types/wallet-server/src/router/auth/commonRouterUtils.d.ts +15 -1
  404. package/dist/types/wallet-server/src/router/cloudflare/d1/auth/d1AuthorizationAssembly.d.ts +23 -0
  405. package/dist/types/wallet-server/src/router/cloudflare/d1/auth/d1RouterApiAuthBoundary.d.ts +0 -1
  406. package/dist/types/wallet-server/src/router/cloudflare/d1/auth/d1RouterApiAuthConfig.d.ts +25 -3
  407. package/dist/types/wallet-server/src/router/cloudflare/d1/auth/d1RouterApiAuthService.d.ts +1 -1
  408. package/dist/types/wallet-server/src/router/cloudflare/d1/auth/walletSessionCredentialReaders.d.ts +9 -0
  409. package/dist/types/wallet-server/src/router/cloudflare/d1/authorization/authorizedOperationStatements.d.ts +4 -0
  410. package/dist/types/wallet-server/src/router/cloudflare/d1/authorization/d1AuthorizationStore.d.ts +11 -2
  411. package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceAuthorityInstallService.d.ts +22 -3
  412. package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceEmailOtpGrantStore.d.ts +7 -1
  413. package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceRequestProofNonceStore.d.ts +1 -10
  414. package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceRouteService.d.ts +4 -0
  415. package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceSessionStore.d.ts +8 -6
  416. package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceTargetCredentialProvider.d.ts +5 -8
  417. package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceTargetPlanner.d.ts +1 -13
  418. package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeService.d.ts +2 -2
  419. package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeStore.d.ts +1 -1
  420. package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpEnrollmentStore.d.ts +2 -8
  421. package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpGrantStore.d.ts +0 -2
  422. package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpRateLimitStore.d.ts +20 -11
  423. package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpRecords.d.ts +5 -5
  424. package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpServerSealRuntime.d.ts +4 -14
  425. package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1GoogleEmailOtpRegistrationAttemptStore.d.ts +29 -1
  426. package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1GoogleEmailOtpRegistrationRecords.d.ts +3 -16
  427. package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1GoogleEmailOtpSessionResolver.d.ts +7 -2
  428. package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1GoogleRegistrationCompletion.d.ts +23 -0
  429. package/dist/types/wallet-server/src/router/cloudflare/d1/identity/d1IdentityService.d.ts +0 -12
  430. package/dist/types/wallet-server/src/router/cloudflare/d1/near/d1SponsoredNearAccount.d.ts +24 -0
  431. package/dist/types/wallet-server/src/router/cloudflare/d1/near/d1SponsoredNearAccount.typecheck.d.ts +2 -0
  432. package/dist/types/wallet-server/src/router/cloudflare/d1/oidc/d1OidcVerificationService.d.ts +0 -1
  433. package/dist/types/wallet-server/src/router/cloudflare/d1/oidc/googleOidcToken.d.ts +4 -0
  434. package/dist/types/wallet-server/src/router/cloudflare/d1/passkeyCustody/d1PasskeyCustodyRouteService.d.ts +5 -0
  435. package/dist/types/wallet-server/src/router/cloudflare/d1/passkeyCustody/d1WalletCustodyCommitStore.d.ts +9 -0
  436. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationCeremonyRecordStore.d.ts +3 -7
  437. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationCeremonyRecords.d.ts +10 -11
  438. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationCeremonyStore.d.ts +3 -2
  439. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationSetupSupport.d.ts +51 -0
  440. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationCommitStore.d.ts +3 -0
  441. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationService.d.ts +35 -50
  442. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationSetup.d.ts +3 -30
  443. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationSetupExecution.d.ts +11 -0
  444. package/dist/types/wallet-server/src/router/cloudflare/d1/signingAdmission/d1RouterAbNormalSigningAdmissionStore.d.ts +14 -1
  445. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAddSignerFinalizeRecord.d.ts +27 -0
  446. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAddSignerService.d.ts +1 -10
  447. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthMethodService.d.ts +2 -2
  448. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorityStore.d.ts +0 -4
  449. package/dist/types/wallet-server/src/router/cloudflare/d1/webauthn/d1WebAuthnAuthService.d.ts +3 -0
  450. package/dist/types/wallet-server/src/router/cloudflare/d1/webauthn/d1WebAuthnRecords.d.ts +8 -50
  451. package/dist/types/wallet-server/src/router/cloudflare/d1/webauthn/d1WebAuthnStore.d.ts +23 -10
  452. package/dist/types/wallet-server/src/router/cloudflare/d1/webauthn/d1WebAuthnStore.typecheck.d.ts +2 -0
  453. package/dist/types/wallet-server/src/router/cloudflare/runtime/cloudflare.types.d.ts +0 -2
  454. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletConsoleOps.d.ts +9 -34
  455. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletConsoleOpsClient.d.ts +2 -0
  456. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletGateway.d.ts +1 -1
  457. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRuntimeOps.d.ts +3 -0
  458. package/dist/types/wallet-server/src/router/cloudflare-adaptor.d.ts +0 -1
  459. package/dist/types/wallet-server/src/router/domains/ecdsa/thresholdEcdsaRequestValidation.d.ts +3 -15
  460. package/dist/types/wallet-server/src/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistration.d.ts +1 -1
  461. package/dist/types/wallet-server/src/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationPartitioning.d.ts +2 -2
  462. package/dist/types/wallet-server/src/router/domains/ed25519Yao/export/routerAbEd25519YaoExport.d.ts +2 -2
  463. package/dist/types/wallet-server/src/router/domains/ed25519Yao/export/routerAbEd25519YaoExport.typecheck.d.ts +2 -0
  464. package/dist/types/wallet-server/src/router/domains/ed25519Yao/export/routerAbEd25519YaoExportRequestScopedCloudflare.d.ts +2 -0
  465. package/dist/types/wallet-server/src/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecoveryRequestScopedCloudflare.d.ts +2 -0
  466. package/dist/types/wallet-server/src/router/domains/ed25519Yao/session/routerAbEd25519YaoWalletSession.d.ts +9 -50
  467. package/dist/types/wallet-server/src/router/domains/passkeyCustody/passkeyCustodyEnvelopeRetrieval.d.ts +0 -2
  468. package/dist/types/wallet-server/src/router/domains/passkeyCustody/walletCustodyRegistrationCommit.d.ts +0 -3
  469. package/dist/types/wallet-server/src/router/domains/passkeyCustody/walletRecoveryKeyManifest.d.ts +1 -13
  470. package/dist/types/wallet-server/src/router/domains/signingOperations/routerAbEcdsaDerivationNormalSigningRoute.d.ts +8 -9
  471. package/dist/types/wallet-server/src/router/domains/signingOperations/routerAbNormalSigningAdmission.d.ts +13 -0
  472. package/dist/types/wallet-server/src/router/domains/signingOperations/routerAbOperationStepUp.d.ts +3 -4
  473. package/dist/types/wallet-server/src/router/domains/signingOperations/routerAbPrivateSigningWorker.d.ts +7 -33
  474. package/dist/types/wallet-server/src/router/domains/signingOperations/walletExecutionAdmission.d.ts +1 -2
  475. package/dist/types/wallet-server/src/router/domains/syncAccount/syncAccountRequestValidation.d.ts +2 -7
  476. package/dist/types/wallet-server/src/router/domains/walletRegistration/walletRegistrationInputs.d.ts +1 -0
  477. package/dist/types/wallet-server/src/router/domains/walletRegistration/walletRegistrationReservation.d.ts +51 -0
  478. package/dist/types/wallet-server/src/router/domains/walletRegistration/walletRegistrationRoutes.d.ts +2 -10
  479. package/dist/types/wallet-server/src/router/domains/walletRegistration/walletRegistrationSetupPayload.d.ts +2 -2
  480. package/dist/types/wallet-server/src/router/framework/apiCredentialPorts.d.ts +3 -1
  481. package/dist/types/wallet-server/src/router/framework/authServicePort.d.ts +39 -38
  482. package/dist/types/wallet-server/src/router/framework/googleLoginResolution.typecheck.d.ts +2 -0
  483. package/dist/types/wallet-server/src/router/framework/http.d.ts +1 -0
  484. package/dist/types/wallet-server/src/router/framework/registrationSetupDispatch.d.ts +13 -0
  485. package/dist/types/wallet-server/src/router/framework/ror/normalize.d.ts +1 -9
  486. package/dist/types/wallet-server/src/router/transport/fetch/routes/deviceLinking.d.ts +1 -1
  487. package/dist/types/wallet-server/src/router/transport/fetch/routes/deviceLinkingOwnerAuthorization.d.ts +3 -6
  488. package/dist/types/wallet-server/src/router/transport/fetch/routes/deviceLinkingResponses.d.ts +17 -0
  489. package/dist/types/wallet-server/src/router/transport/fetch/routes/ecdsaOperationStepUpFactor.d.ts +37 -0
  490. package/dist/types/wallet-server/src/router/transport/fetch/routes/syncAccountBootstrap.d.ts +3 -5
  491. package/dist/types/wallet-server/src/router/transport/fetch/routes/thresholdEcdsa.d.ts +0 -1
  492. package/dist/types/wallet-server/src/storage/d1Sql.d.ts +0 -1
  493. package/dist/types/wallet-server/src/threshold/session/signingSessionSeal/idempotencyRecords.d.ts +1 -2
  494. package/dist/types/wallet-server/src/threshold/session/signingSessionSeal/signingSessionSeal.types.d.ts +6 -8
  495. package/migrations/d1-signer/0040_namespace_home_challenges.sql +16 -0
  496. package/migrations/d1-signer/0041_step_up_admission_expiry.sql +28 -0
  497. package/migrations/d1-signer/0042_deployment_resource_challenges.sql +4 -0
  498. package/migrations/d1-signer/0043_google_registration_candidate_claim.sql +2 -0
  499. package/migrations/d1-signer/0044_linked_device_bootstrap_imports.sql +6 -0
  500. package/migrations/d1-signer/0045_wallet_owned_capability_receipts.sql +29 -0
  501. package/migrations/d1-signer/0046_wallet_owned_signing_abuse.sql +41 -0
  502. package/migrations/d1-signer/0047_remove_unused_near_public_keys.sql +2 -0
  503. package/migrations/d1-signer/0048_operation_owner_scope.sql +45 -0
  504. package/package.json +2 -3
  505. package/src/README.md +11 -3
  506. package/dist/esm/core/AuthService.js +0 -2
  507. package/dist/esm/core/NearPublicKeyStore.js +0 -200
  508. package/dist/esm/core/ThresholdService/stores/CloudflareDurableObjectStore.js +0 -397
  509. package/dist/esm/core/ThresholdService/stores/KeyStore.js +0 -140
  510. package/dist/esm/core/ThresholdService/stores/SessionStore.js +0 -361
  511. package/dist/esm/core/ThresholdService/stores/StoreConfig.js +0 -13
  512. package/dist/esm/core/authService/AuthService.js +0 -594
  513. package/dist/esm/core/authService/bytes.js +0 -22
  514. package/dist/esm/core/authService/configValues.js +0 -15
  515. package/dist/esm/core/authService/emailOtpChallengeOperations.js +0 -126
  516. package/dist/esm/core/authService/emailOtpChallengeProof.js +0 -214
  517. package/dist/esm/core/authService/emailOtpChallengeVerification.js +0 -335
  518. package/dist/esm/core/authService/emailOtpChallenges.js +0 -260
  519. package/dist/esm/core/authService/emailOtpDelivery.js +0 -169
  520. package/dist/esm/core/authService/emailOtpGrant.js +0 -74
  521. package/dist/esm/core/authService/emailOtpRegistrationEnrollment.js +0 -175
  522. package/dist/esm/core/authService/emailOtpUnlock.js +0 -264
  523. package/dist/esm/core/authService/googleEmailOtpOperations.js +0 -141
  524. package/dist/esm/core/authService/googleEmailOtpRegistration.js +0 -674
  525. package/dist/esm/core/authService/identity.js +0 -57
  526. package/dist/esm/core/authService/identityOperations.js +0 -32
  527. package/dist/esm/core/authService/nearAccountOperations.js +0 -229
  528. package/dist/esm/core/authService/nearPublicKeyMetadata.js +0 -127
  529. package/dist/esm/core/authService/oidcVerification.js +0 -261
  530. package/dist/esm/core/authService/registrationThresholdHelpers.js +0 -30
  531. package/dist/esm/core/authService/runtime.js +0 -45
  532. package/dist/esm/core/authService/storeRegistry.js +0 -102
  533. package/dist/esm/core/authService/thresholdStoreSummary.js +0 -32
  534. package/dist/esm/core/authService/webauthnAuthority.js +0 -17
  535. package/dist/esm/core/defaultConfigsServer.js +0 -9
  536. package/dist/esm/core/hostedAccountIds.js +0 -225
  537. package/dist/esm/core/routerAbSigning/createRouterAbSigningRuntimes.js +0 -84
  538. package/dist/esm/core/signingLanes/LaneAggregateRevocationApplicationService.js +0 -86
  539. package/dist/esm/core/signingLanes/LaneEnrollmentActivation.js +0 -324
  540. package/dist/esm/core/signingLanes/LaneEnrollmentRevocation.js +0 -173
  541. package/dist/esm/core/signingLanes/LaneLifecycleApplicationService.js +0 -198
  542. package/dist/esm/core/signingLanes/ecdsaServerRetirement.js +0 -73
  543. package/dist/esm/core/signingLanes/ed25519ServerRetirement.js +0 -68
  544. package/dist/esm/core/signingLanes/signingWorkerLaneMaterialIdentity.js +0 -0
  545. package/dist/esm/core/storeBackends.js +0 -208
  546. package/dist/esm/core/utils.js +0 -14
  547. package/dist/esm/core/webAuthnStoreBackends.js +0 -198
  548. package/dist/esm/router/cloudflare/d1/near/d1NearPublicKeyStore.js +0 -56
  549. package/dist/esm/router/cloudflare/d1/signingLanes/d1EcdsaLanePrivateBindingResolver.js +0 -10
  550. package/dist/esm/router/cloudflare/d1/signingLanes/d1LaneAggregateRevocationApplicationService.js +0 -22
  551. package/dist/esm/router/cloudflare/d1/signingLanes/d1LaneEffectJournalStore.js +0 -166
  552. package/dist/esm/router/cloudflare/d1/signingLanes/d1LaneEnrollmentGateway.js +0 -38
  553. package/dist/esm/router/cloudflare/d1/signingLanes/d1LaneLifecycleApplicationService.js +0 -20
  554. package/dist/esm/router/cloudflare/d1/signingLanes/d1LaneLifecycleStore.js +0 -1459
  555. package/dist/esm/router/cloudflare/d1/signingLanes/d1LaneLockStore.js +0 -114
  556. package/dist/esm/router/cloudflare/d1/signingLanes/d1LaneProtocolCommitter.js +0 -16
  557. package/dist/esm/router/cloudflare/d1/signingLanes/d1LaneRecords.js +0 -171
  558. package/dist/esm/router/cloudflare/d1/signingLanes/index.js +0 -10
  559. package/dist/esm/router/cloudflare/durableObjects/thresholdStore.js +0 -404
  560. package/dist/esm/router/cloudflare/signingLanes/cloudflareLaneCurveExecution.js +0 -596
  561. package/dist/esm/router/cloudflare/signingLanes/cloudflareLaneProtocolCommitter.js +0 -273
  562. package/dist/esm/router/cloudflare/signingLanes/index.js +0 -4
  563. package/dist/esm/router/cloudflare/signingLanes/linkedDeviceEd25519CeremonyBinding.js +0 -32
  564. package/dist/esm/router/transport/fetch/routes/nearPublicKeys.js +0 -39
  565. package/dist/esm/shared-ts/src/signing-lanes/rotation.js +0 -8
  566. package/dist/esm/shared-ts/src/signing-lanes/rotationDigests.js +0 -358
  567. package/dist/esm/shared-ts/src/signing-lanes/rotationLifecycle.js +0 -313
  568. package/dist/esm/shared-ts/src/signing-lanes/rotationParsers.js +0 -532
  569. package/dist/esm/shared-ts/src/signing-lanes/rotationProtocolParsers.js +0 -323
  570. package/dist/esm/shared-ts/src/signing-lanes/rotationWireFields.js +0 -59
  571. package/dist/esm/wasm/router_ab_ecdsa_signing_worker/pkg/router_ab_ecdsa_signing_worker_bg.wasm +0 -0
  572. package/dist/types/shared-ts/src/signing-lanes/participantDigest.typecheck.d.ts +0 -2
  573. package/dist/types/shared-ts/src/signing-lanes/rotation.typecheck.d.ts +0 -2
  574. package/dist/types/shared-ts/src/signing-lanes/rotationDigests.d.ts +0 -13
  575. package/dist/types/shared-ts/src/signing-lanes/rotationLifecycle.d.ts +0 -78
  576. package/dist/types/shared-ts/src/signing-lanes/rotationParsers.d.ts +0 -27
  577. package/dist/types/shared-ts/src/signing-lanes/rotationProtocolParsers.d.ts +0 -6
  578. package/dist/types/shared-ts/src/signing-lanes/rotationWireFields.d.ts +0 -20
  579. package/dist/types/shared-ts/src/wallet-recovery/recoveryCodeAttempt.d.ts +0 -59
  580. package/dist/types/wallet-server/src/core/AuthService.d.ts +0 -3
  581. package/dist/types/wallet-server/src/core/NearPublicKeyStore.d.ts +0 -48
  582. package/dist/types/wallet-server/src/core/ThresholdService/stores/CloudflareDurableObjectStore.d.ts +0 -21
  583. package/dist/types/wallet-server/src/core/ThresholdService/stores/KeyStore.d.ts +0 -40
  584. package/dist/types/wallet-server/src/core/ThresholdService/stores/SessionStore.d.ts +0 -98
  585. package/dist/types/wallet-server/src/core/ThresholdService/stores/StoreConfig.d.ts +0 -4
  586. package/dist/types/wallet-server/src/core/ThresholdService/stores/ThresholdStoreConfig.typecheck.d.ts +0 -2
  587. package/dist/types/wallet-server/src/core/authService/AuthService.d.ts +0 -490
  588. package/dist/types/wallet-server/src/core/authService/bytes.d.ts +0 -4
  589. package/dist/types/wallet-server/src/core/authService/configValues.d.ts +0 -7
  590. package/dist/types/wallet-server/src/core/authService/emailOtpChallengeOperations.d.ts +0 -109
  591. package/dist/types/wallet-server/src/core/authService/emailOtpChallengeProof.d.ts +0 -169
  592. package/dist/types/wallet-server/src/core/authService/emailOtpChallengeVerification.d.ts +0 -47
  593. package/dist/types/wallet-server/src/core/authService/emailOtpChallenges.d.ts +0 -94
  594. package/dist/types/wallet-server/src/core/authService/emailOtpDelivery.d.ts +0 -66
  595. package/dist/types/wallet-server/src/core/authService/emailOtpGrant.d.ts +0 -43
  596. package/dist/types/wallet-server/src/core/authService/emailOtpRegistrationEnrollment.d.ts +0 -49
  597. package/dist/types/wallet-server/src/core/authService/emailOtpUnlock.d.ts +0 -71
  598. package/dist/types/wallet-server/src/core/authService/googleEmailOtpOperations.d.ts +0 -126
  599. package/dist/types/wallet-server/src/core/authService/googleEmailOtpRegistration.d.ts +0 -169
  600. package/dist/types/wallet-server/src/core/authService/identity.d.ts +0 -25
  601. package/dist/types/wallet-server/src/core/authService/identityOperations.d.ts +0 -19
  602. package/dist/types/wallet-server/src/core/authService/nearAccountOperations.d.ts +0 -55
  603. package/dist/types/wallet-server/src/core/authService/nearPublicKeyMetadata.d.ts +0 -44
  604. package/dist/types/wallet-server/src/core/authService/oidcVerification.d.ts +0 -66
  605. package/dist/types/wallet-server/src/core/authService/registrationThresholdHelpers.d.ts +0 -11
  606. package/dist/types/wallet-server/src/core/authService/runtime.d.ts +0 -20
  607. package/dist/types/wallet-server/src/core/authService/storeRegistry.d.ts +0 -53
  608. package/dist/types/wallet-server/src/core/authService/thresholdStoreSummary.d.ts +0 -3
  609. package/dist/types/wallet-server/src/core/authService/webauthnAuthority.d.ts +0 -5
  610. package/dist/types/wallet-server/src/core/defaultConfigsServer.d.ts +0 -5
  611. package/dist/types/wallet-server/src/core/hostedAccountIds.d.ts +0 -16
  612. package/dist/types/wallet-server/src/core/routerAbSigning/createRouterAbSigningRuntimes.d.ts +0 -16
  613. package/dist/types/wallet-server/src/core/signingLanes/LaneAggregateRevocationApplicationService.d.ts +0 -36
  614. package/dist/types/wallet-server/src/core/signingLanes/LaneEffectJournalStore.d.ts +0 -62
  615. package/dist/types/wallet-server/src/core/signingLanes/LaneEnrollmentActivation.d.ts +0 -13
  616. package/dist/types/wallet-server/src/core/signingLanes/LaneEnrollmentRevocation.d.ts +0 -24
  617. package/dist/types/wallet-server/src/core/signingLanes/LaneLifecycleApplicationService.d.ts +0 -141
  618. package/dist/types/wallet-server/src/core/signingLanes/LaneLifecycleStore.d.ts +0 -228
  619. package/dist/types/wallet-server/src/core/signingLanes/ecdsaServerRetirement.d.ts +0 -58
  620. package/dist/types/wallet-server/src/core/signingLanes/ed25519ServerRetirement.d.ts +0 -30
  621. package/dist/types/wallet-server/src/core/signingLanes/signingWorkerLaneMaterialIdentity.d.ts +0 -21
  622. package/dist/types/wallet-server/src/core/storeBackends.d.ts +0 -83
  623. package/dist/types/wallet-server/src/core/utils.d.ts +0 -3
  624. package/dist/types/wallet-server/src/core/webAuthnStoreBackends.d.ts +0 -96
  625. package/dist/types/wallet-server/src/router/cloudflare/d1/near/d1NearPublicKeyStore.d.ts +0 -29
  626. package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/d1EcdsaLanePrivateBindingResolver.d.ts +0 -4
  627. package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/d1LaneAggregateRevocationApplicationService.d.ts +0 -4
  628. package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/d1LaneEffectJournalStore.d.ts +0 -24
  629. package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/d1LaneEnrollmentGateway.d.ts +0 -20
  630. package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/d1LaneLifecycleApplicationService.d.ts +0 -13
  631. package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/d1LaneLifecycleStore.d.ts +0 -51
  632. package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/d1LaneLockStore.d.ts +0 -28
  633. package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/d1LaneProtocolCommitter.d.ts +0 -5
  634. package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/d1LaneRecords.d.ts +0 -107
  635. package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/index.d.ts +0 -10
  636. package/dist/types/wallet-server/src/router/cloudflare/durableObjects/thresholdStore.d.ts +0 -18
  637. package/dist/types/wallet-server/src/router/cloudflare/signingLanes/cloudflareLaneCurveExecution.d.ts +0 -217
  638. package/dist/types/wallet-server/src/router/cloudflare/signingLanes/cloudflareLaneProtocolCommitter.d.ts +0 -73
  639. package/dist/types/wallet-server/src/router/cloudflare/signingLanes/index.d.ts +0 -4
  640. package/dist/types/wallet-server/src/router/cloudflare/signingLanes/linkedDeviceEd25519CeremonyBinding.d.ts +0 -6
  641. package/dist/types/wallet-server/src/router/transport/fetch/routes/nearPublicKeys.d.ts +0 -3
  642. /package/dist/esm/{core/signingLanes/LaneEffectJournalStore.js → authorization/recoveryRouting.js} +0 -0
  643. /package/dist/esm/{core/signingLanes/LaneLifecycleStore.js → authorization/sessionRouting.js} +0 -0
@@ -38,6 +38,15 @@ function normalizeLogger(logger) {
38
38
  //#region src/router/framework/logger.ts
39
39
  const coerceRouterLogger = normalizeLogger;
40
40
  //#endregion
41
+ //#region ../shared-ts/src/utils/failure.ts
42
+ function failure(code, message) {
43
+ return {
44
+ ok: false,
45
+ code,
46
+ message
47
+ };
48
+ }
49
+ //#endregion
41
50
  //#region src/core/SessionService.ts
42
51
  function normalizeParsedCorsOrigin(url) {
43
52
  const host = url.hostname.toLowerCase();
@@ -81,6 +90,21 @@ function buildCorsOrigins(...inputs) {
81
90
  }
82
91
  //#endregion
83
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
+ }
84
108
  function assertNeverLinkSessionStateV1(value) {
85
109
  throw new Error(`[LinkSessionStateV1] unsupported state: ${String(value)}`);
86
110
  }
@@ -389,112 +413,6 @@ function toRorOriginOrNull(value) {
389
413
  }
390
414
  }
391
415
  //#endregion
392
- //#region ../shared-ts/src/utils/base58.ts
393
- /**
394
- * Encodes binary data to base58 string using Bitcoin's base58 alphabet.
395
- *
396
- * @param data - Binary data to encode (Uint8Array, ArrayBuffer, or number[])
397
- * @returns Base58-encoded string
398
- */
399
- const base58Encode = (data) => {
400
- if (data instanceof ArrayBuffer) return bs58.encode(new Uint8Array(data));
401
- if (Array.isArray(data)) return bs58.encode(new Uint8Array(data));
402
- return bs58.encode(data);
403
- };
404
- /**
405
- * Decodes a base58 string to binary data using Bitcoin's base58 alphabet.
406
- * Returns a Uint8Array containing the decoded bytes.
407
- *
408
- * @param base58String - Base58-encoded string to decode
409
- * @returns Uint8Array containing the decoded bytes
410
- * @throws Error if input contains invalid base58 characters
411
- */
412
- const base58Decode = (base58String) => {
413
- return bs58.decode(base58String);
414
- };
415
- //#endregion
416
- //#region ../shared-ts/src/utils/near.ts
417
- /**
418
- * NEAR-specific utility helpers.
419
- *
420
- * Keep chain-specific parsing and validation logic here so generic utility
421
- * modules (`validation`, `errors`, `encoders`, etc.) stay chain-agnostic.
422
- */
423
- /**
424
- * Ensure a key string has the NEAR Ed25519 prefix (`ed25519:`).
425
- *
426
- * - Accepts either `ed25519:<base58>` or a bare `<base58>` string.
427
- * - Canonicalizes `ED25519:` -> `ed25519:`.
428
- * - If a different prefix is present (e.g. `secp256k1:`), returns the input unchanged.
429
- */
430
- function ensureEd25519Prefix(value) {
431
- const raw = String(value ?? "").trim();
432
- if (!raw) return "";
433
- if (/^[a-z0-9_]+:/i.test(raw)) {
434
- if (/^ed25519:/i.test(raw)) return `ed25519:${raw.replace(/^ed25519:/i, "")}`;
435
- return raw;
436
- }
437
- return `ed25519:${raw}`;
438
- }
439
- /**
440
- * Lightweight NEAR account ID validation used by server-side helpers.
441
- * - length: 2..64
442
- * - chars: lowercase letters, digits, `_`, `.`, `-`
443
- */
444
- function isValidAccountId(accountId) {
445
- if (typeof accountId !== "string") return false;
446
- if (!accountId || accountId.length < 2 || accountId.length > 64) return false;
447
- return /^[a-z0-9_.-]+$/.test(accountId);
448
- }
449
- function isImplicitNearAccountId(value) {
450
- return typeof value === "string" && /^[0-9a-f]{64}$/.test(value);
451
- }
452
- function parseImplicitNearAccountId(raw) {
453
- const value = typeof raw === "string" ? raw.trim() : "";
454
- if (!value) return {
455
- ok: false,
456
- code: "missing",
457
- message: "implicit NEAR account ID is required"
458
- };
459
- if (!isImplicitNearAccountId(value)) return {
460
- ok: false,
461
- code: "invalid",
462
- message: "implicit NEAR account ID must be 64 lowercase hex characters"
463
- };
464
- return {
465
- ok: true,
466
- value
467
- };
468
- }
469
- function parseNamedNearAccountId(raw) {
470
- const value = typeof raw === "string" ? raw.trim() : "";
471
- if (!value) return {
472
- ok: false,
473
- code: "missing",
474
- message: "named NEAR account ID is required"
475
- };
476
- if (isImplicitNearAccountId(value) || !isValidAccountId(value) || !value.includes(".")) return {
477
- ok: false,
478
- code: "invalid",
479
- message: "named NEAR account ID must be a valid named account containing a dot"
480
- };
481
- return {
482
- ok: true,
483
- value
484
- };
485
- }
486
- function bytesToLowerHex(bytes) {
487
- return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
488
- }
489
- function deriveImplicitNearAccountIdFromEd25519PublicKey(publicKey) {
490
- const normalized = ensureEd25519Prefix(publicKey);
491
- const encoded = normalized.startsWith("ed25519:") ? normalized.slice(8) : "";
492
- if (!encoded) throw new Error("Ed25519 public key is required");
493
- const decoded = base58Decode(encoded);
494
- if (decoded.length !== 32) throw new Error("Ed25519 public key must decode to 32 bytes");
495
- return bytesToLowerHex(decoded);
496
- }
497
- //#endregion
498
416
  //#region ../shared-ts/src/utils/validation.ts
499
417
  function requireTrimmedString(value, label, message = "is required") {
500
418
  const parsed = normalizeOptionalTrimmedString(value);
@@ -984,6 +902,10 @@ function requireCanonicalBase64Url(value, label) {
984
902
  if (base64UrlEncode(decoded) !== value) throw new Error(`${label} must be canonical base64url`);
985
903
  return decoded;
986
904
  }
905
+ function requireParsed$2(result, label) {
906
+ if (result.ok) return result.value;
907
+ throw new Error(`${label} ${result.error.message}`);
908
+ }
987
909
  function parseDigestField$2(value, label) {
988
910
  try {
989
911
  return parseDigestB64u(value);
@@ -1204,11 +1126,11 @@ function parseLinkedDeviceEd25519ExportRootRecipientV1(raw) {
1204
1126
  requireTransferAlg(record.transferAlg, "LinkedDeviceEd25519ExportRootRecipientV1.transferAlg");
1205
1127
  return {
1206
1128
  kind: "linked_device_ed25519_export_root_recipient_v1",
1207
- linkSessionId: parseRequired(parseLinkDeviceSessionId(record.linkSessionId), "LinkedDeviceEd25519ExportRootRecipientV1.linkSessionId"),
1208
- walletId: parseRequired(parseWalletId(record.walletId), "walletId"),
1209
- walletKeyId: parseRequired(parseWalletKeyId(record.walletKeyId), "walletKeyId"),
1210
- enrollmentId: parseRequired(parseLinkedDeviceEnrollmentId(record.enrollmentId), "enrollmentId"),
1211
- deviceId: parseRequired(parseLinkedDeviceId(record.deviceId), "deviceId"),
1129
+ linkSessionId: requireParsed$2(parseLinkDeviceSessionId(record.linkSessionId), "LinkedDeviceEd25519ExportRootRecipientV1.linkSessionId"),
1130
+ walletId: requireParsed$2(parseWalletId(record.walletId), "walletId"),
1131
+ walletKeyId: requireParsed$2(parseWalletKeyId(record.walletKeyId), "walletKeyId"),
1132
+ enrollmentId: requireParsed$2(parseLinkedDeviceEnrollmentId(record.enrollmentId), "enrollmentId"),
1133
+ deviceId: requireParsed$2(parseLinkedDeviceId(record.deviceId), "deviceId"),
1212
1134
  transferAlg: LINKED_DEVICE_ED25519_EXPORT_ROOT_TRANSFER_ALG_V1,
1213
1135
  applicationBindingDigestB64u: parseDigestField$2(record.applicationBindingDigestB64u, "applicationBindingDigestB64u"),
1214
1136
  registeredPublicKeyB64u: parseEd25519PublicKeyB64u(record.registeredPublicKeyB64u, "registeredPublicKeyB64u"),
@@ -1227,11 +1149,11 @@ function parseLinkedDeviceEd25519ExportRootPackageV1(raw) {
1227
1149
  if (recipientPublicKeyB64u === ephemeralPublicKeyB64u) throw new Error("ephemeralPublicKeyB64u repeats the recipient key");
1228
1150
  return {
1229
1151
  kind: "linked_device_ed25519_export_root_package_v1",
1230
- linkSessionId: parseRequired(parseLinkDeviceSessionId(record.linkSessionId), "linkSessionId"),
1231
- walletId: parseRequired(parseWalletId(record.walletId), "walletId"),
1232
- walletKeyId: parseRequired(parseWalletKeyId(record.walletKeyId), "walletKeyId"),
1233
- enrollmentId: parseRequired(parseLinkedDeviceEnrollmentId(record.enrollmentId), "enrollmentId"),
1234
- deviceId: parseRequired(parseLinkedDeviceId(record.deviceId), "deviceId"),
1152
+ linkSessionId: requireParsed$2(parseLinkDeviceSessionId(record.linkSessionId), "linkSessionId"),
1153
+ walletId: requireParsed$2(parseWalletId(record.walletId), "walletId"),
1154
+ walletKeyId: requireParsed$2(parseWalletKeyId(record.walletKeyId), "walletKeyId"),
1155
+ enrollmentId: requireParsed$2(parseLinkedDeviceEnrollmentId(record.enrollmentId), "enrollmentId"),
1156
+ deviceId: requireParsed$2(parseLinkedDeviceId(record.deviceId), "deviceId"),
1235
1157
  transferAlg: LINKED_DEVICE_ED25519_EXPORT_ROOT_TRANSFER_ALG_V1,
1236
1158
  applicationBindingDigestB64u: parseDigestField$2(record.applicationBindingDigestB64u, "applicationBindingDigestB64u"),
1237
1159
  registeredPublicKeyB64u: parseEd25519PublicKeyB64u(record.registeredPublicKeyB64u, "registeredPublicKeyB64u"),
@@ -1251,7 +1173,7 @@ function parseLinkedDeviceEd25519ExportRootSubmissionV1(raw) {
1251
1173
  if (record.kind !== "linked_device_ed25519_export_root_submission_v1") throw new Error("LinkedDeviceEd25519ExportRootSubmissionV1.kind is invalid");
1252
1174
  return {
1253
1175
  kind: "linked_device_ed25519_export_root_submission_v1",
1254
- linkSessionId: parseRequired(parseLinkDeviceSessionId(record.linkSessionId), "linkSessionId"),
1176
+ linkSessionId: requireParsed$2(parseLinkDeviceSessionId(record.linkSessionId), "linkSessionId"),
1255
1177
  package: parseLinkedDeviceEd25519ExportRootPackageV1(record.package)
1256
1178
  };
1257
1179
  }
@@ -1279,10 +1201,6 @@ function parseUnixMs(value, label) {
1279
1201
  if (typeof value !== "number" || !Number.isSafeInteger(value) || value <= 0) throw new Error(`${label} must be a positive unix-millisecond timestamp`);
1280
1202
  return value;
1281
1203
  }
1282
- function parseRequired(parsed, label) {
1283
- if (!parsed.ok) throw new Error(`${label} ${parsed.error.message}`);
1284
- return parsed.value;
1285
- }
1286
1204
  //#endregion
1287
1205
  //#region ../shared-ts/src/device-linking/delegatedActivationPlan.ts
1288
1206
  const MANIFEST_FIELDS = [
@@ -1406,10 +1324,6 @@ function exactRecord$2(raw, fields, label) {
1406
1324
  for (const field of fields) if (!(field in record)) throw new Error(`${label}.${field} is required`);
1407
1325
  return record;
1408
1326
  }
1409
- function requireParsed$2(parsed, label) {
1410
- if (!parsed.ok) throw new Error(`${label} ${parsed.error.message}`);
1411
- return parsed.value;
1412
- }
1413
1327
  //#endregion
1414
1328
  //#region ../shared-ts/src/utils/addAuthMethodRegistration.ts
1415
1329
  /**
@@ -3874,7 +3788,7 @@ function parseLinkedDeviceEd25519SourcePreservingReservationV1(raw) {
3874
3788
  const participantIds = parseRouterAbEd25519YaoParticipantIdsV1(record.participant_ids);
3875
3789
  const deriverA = parseEd25519ClientPackage(record.deriver_a_client_package, "deriver_a");
3876
3790
  const deriverB = parseEd25519ClientPackage(record.deriver_b_client_package, "deriver_b");
3877
- if (!sameBytes(activationReceipt.transcript, deriverA.transcript) || !sameBytes(activationReceipt.transcript, deriverB.transcript)) throw new Error("linked-device Ed25519 reservation packages have mismatched transcripts");
3791
+ if (!sameRouterAbEd25519YaoByteSequence(activationReceipt.transcript, deriverA.transcript) || !sameRouterAbEd25519YaoByteSequence(activationReceipt.transcript, deriverB.transcript)) throw new Error("linked-device Ed25519 reservation packages have mismatched transcripts");
3878
3792
  return {
3879
3793
  state: "inactive",
3880
3794
  reservationId: requireText(record.reservation_id, "reservation_id"),
@@ -4033,10 +3947,10 @@ function parseEd25519Contribution(record) {
4033
3947
  if (!sameEdStableIdentity(sourceBinding, targetBinding)) throw new Error("linked-device Ed25519 source contribution stable identity differs");
4034
3948
  if (!mpcMaterialActivationRefsEqual(routerAbMpcMaterialActivationRefFromWire(activationReceipt.material_activation), targetMaterialActivation)) throw new Error("linked-device Ed25519 source contribution receipt activation differs");
4035
3949
  const sourceRegisteredPublicKeyB64u = parseEd25519PublicKeyB64u(record.sourceRegisteredPublicKeyB64u, "sourceRegisteredPublicKeyB64u");
4036
- if (!sameBytes(activationReceipt.registered_public_key, Array.from(base64UrlDecode(sourceRegisteredPublicKeyB64u)))) throw new Error("linked-device Ed25519 source contribution receipt public key differs");
3950
+ if (!sameRouterAbEd25519YaoByteSequence(activationReceipt.registered_public_key, Array.from(base64UrlDecode(sourceRegisteredPublicKeyB64u)))) throw new Error("linked-device Ed25519 source contribution receipt public key differs");
4037
3951
  const deriverA = parseEd25519ClientPackage(record.deriver_a_client_package, "deriver_a");
4038
3952
  const deriverB = parseEd25519ClientPackage(record.deriver_b_client_package, "deriver_b");
4039
- if (!sameBytes(activationReceipt.transcript, deriverA.transcript) || !sameBytes(activationReceipt.transcript, deriverB.transcript)) throw new Error("linked-device Ed25519 source contribution package transcript differs");
3953
+ if (!sameRouterAbEd25519YaoByteSequence(activationReceipt.transcript, deriverA.transcript) || !sameRouterAbEd25519YaoByteSequence(activationReceipt.transcript, deriverB.transcript)) throw new Error("linked-device Ed25519 source contribution package transcript differs");
4040
3954
  if (sourceBinding.material_activation.activation_id === targetMaterialActivation.activationId) throw new Error("linked-device Ed25519 source contribution reuses the source activation");
4041
3955
  return {
4042
3956
  kind: "linked_device_ed25519_source_contribution_v1",
@@ -4316,9 +4230,6 @@ function parseFixedBase64(raw, byteLength, label) {
4316
4230
  if (decoded.length !== byteLength || base64UrlEncode(decoded) !== raw) throw new Error(`${label} must decode to ${byteLength} bytes`);
4317
4231
  return raw;
4318
4232
  }
4319
- function sameBytes(left, right) {
4320
- return left.length === right.length && left.every((value, index) => value === right[index]);
4321
- }
4322
4233
  function requireText(raw, label) {
4323
4234
  if (typeof raw !== "string" || raw.length === 0 || raw.trim() !== raw || [...raw].some((character) => {
4324
4235
  const code = character.charCodeAt(0);
@@ -5414,11 +5325,15 @@ function createRouterAbTraceContextV1() {
5414
5325
  };
5415
5326
  }
5416
5327
  //#endregion
5328
+ //#region ../shared-ts/src/utils/walletManagementProtocol.ts
5329
+ const WALLET_MANAGEMENT_PROTOCOL_HEADER = "X-Seams-Wallet-Protocol";
5330
+ //#endregion
5417
5331
  //#region src/router/framework/http.ts
5418
5332
  const CORS_ALLOW_METHODS = "GET,POST,PUT,PATCH,DELETE,OPTIONS";
5419
5333
  const CORS_PREFLIGHT_MAX_AGE_SECONDS = 600;
5420
5334
  const CORS_ALLOW_HEADERS = [
5421
5335
  "Content-Type",
5336
+ WALLET_MANAGEMENT_PROTOCOL_HEADER,
5422
5337
  "Authorization",
5423
5338
  "X-Seams-Benchmark-Diagnostics",
5424
5339
  LINKED_DEVICE_REQUEST_PROOF_HEADER_V1,
@@ -5441,6 +5356,9 @@ function json$1(body, init, extraHeaders) {
5441
5356
  headers
5442
5357
  });
5443
5358
  }
5359
+ function jsonFailure(status, code, message) {
5360
+ return json$1(failure(code, message), { status });
5361
+ }
5444
5362
  function withCors(headers, opts, request) {
5445
5363
  const pathname = request ? new URL(request.url).pathname : "";
5446
5364
  if (pathname === "/healthz" || pathname === "/readyz") {
@@ -5479,6 +5397,13 @@ async function readJson(request) {
5479
5397
  return null;
5480
5398
  }
5481
5399
  }
5400
+ function headersToRecord(headers) {
5401
+ const out = {};
5402
+ headers.forEach((v, k) => {
5403
+ out[k] = v;
5404
+ });
5405
+ return out;
5406
+ }
5482
5407
  //#endregion
5483
5408
  //#region src/router/transport/fetch/routes/health.ts
5484
5409
  async function handleHealth(ctx) {
@@ -5517,6 +5442,11 @@ async function handleReady(ctx) {
5517
5442
  }
5518
5443
  }
5519
5444
  //#endregion
5445
+ //#region ../shared-ts/src/utils/registrationSetupOperation.ts
5446
+ function parseRegistrationSetupOperationId(value) {
5447
+ return typeof value === "string" && /^wreg_[A-Za-z0-9_-]{43}$/u.test(value) ? value : null;
5448
+ }
5449
+ //#endregion
5520
5450
  //#region src/router/auth/routerApiKeyAuth.ts
5521
5451
  function readHeader(headers, name) {
5522
5452
  if (headers instanceof Headers) return String(headers.get(name) || "").trim();
@@ -5611,6 +5541,12 @@ async function resolvePublishableKeyApiCredentialAuth(input) {
5611
5541
  };
5612
5542
  }
5613
5543
  //#endregion
5544
+ //#region ../shared-ts/src/utils/thresholdEcdsaChainTarget.ts
5545
+ function thresholdEcdsaChainTargetKey(target) {
5546
+ if (target.kind === "evm") return `evm:eip155:${target.chainId}`;
5547
+ return `tempo:${target.chainId}`;
5548
+ }
5549
+ //#endregion
5614
5550
  //#region src/core/thresholdEcdsaChainTarget.ts
5615
5551
  function positiveSafeInteger(value) {
5616
5552
  return typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? value : null;
@@ -5671,11 +5607,7 @@ function walletSessionFailureStatus(code) {
5671
5607
  }
5672
5608
  }
5673
5609
  function walletSessionFailure(code) {
5674
- return {
5675
- ok: false,
5676
- code,
5677
- message: walletSessionFailureMessage(code)
5678
- };
5610
+ return failure(code, walletSessionFailureMessage(code));
5679
5611
  }
5680
5612
  //#endregion
5681
5613
  //#region ../shared-ts/src/signing-lanes/participants.ts
@@ -5715,22 +5647,6 @@ function parseLaneParticipantBindingDigestB64u(raw) {
5715
5647
  return parseDigest(raw, "participantBindingDigestB64u", brandParticipantDigest);
5716
5648
  }
5717
5649
  //#endregion
5718
- //#region ../shared-ts/src/utils/registrationIds.ts
5719
- function walletIdFromString(value) {
5720
- const parsed = parseWalletId(value);
5721
- if (!parsed.ok) throw new Error(parsed.error.message);
5722
- return parsed.value;
5723
- }
5724
- function nearEd25519SigningKeyIdFromString(value) {
5725
- const normalized = String(value || "").trim();
5726
- if (!normalized) throw new Error("nearEd25519SigningKeyId is required");
5727
- return normalized;
5728
- }
5729
- function parseNearEd25519SigningKeyId(value) {
5730
- if (typeof value !== "string") throw new Error("nearEd25519SigningKeyId must be a string");
5731
- return nearEd25519SigningKeyIdFromString(value);
5732
- }
5733
- //#endregion
5734
5650
  //#region ../shared-ts/src/signing-lanes/participantDigest.ts
5735
5651
  function u32(value) {
5736
5652
  if (!Number.isInteger(value) || value < 0 || value > 4294967295) throw new Error("canonical u32 must be an integer between 0 and 4294967295");
@@ -5761,6 +5677,17 @@ function encodeLaneCanonicalU64V1(value) {
5761
5677
  return output;
5762
5678
  }
5763
5679
  //#endregion
5680
+ //#region ../shared-ts/src/signing-lanes/execution.ts
5681
+ function buildPreparedOwnerWalletExecution(input) {
5682
+ return {
5683
+ kind: "prepared_owner_wallet_execution",
5684
+ laneKind: input.lane.laneKind,
5685
+ authorization: input.authorization,
5686
+ materialActivation: input.materialActivation,
5687
+ lane: input.lane
5688
+ };
5689
+ }
5690
+ //#endregion
5764
5691
  //#region ../shared-ts/src/signing-lanes/ownerContinuity.ts
5765
5692
  const OWNER_LANE_PARTICIPANT_BINDING_DOMAIN_V1 = "seams/rotatable-signing-lanes/owner-lane-participant-continuity/v1";
5766
5693
  const OWNER_LANE_PARTICIPANT_CONTINUITY_FIELDS = [
@@ -5771,10 +5698,6 @@ const OWNER_LANE_PARTICIPANT_CONTINUITY_FIELDS = [
5771
5698
  "custodyKeyManifestDigestB64u",
5772
5699
  "sourceIdentityDigestB64u"
5773
5700
  ];
5774
- function requireResult(result, label) {
5775
- if (result.ok) return result.value;
5776
- throw new Error(`${label} ${result.error.message}`);
5777
- }
5778
5701
  /** Parse the owner signer identity without widening it into a generic string. */
5779
5702
  function parseWalletSignerId(raw, label = "walletSignerId") {
5780
5703
  if (typeof raw !== "string") throw new Error(`${label} must be a string`);
@@ -5800,7 +5723,7 @@ function buildOwnerLaneParticipantContinuityV1(args) {
5800
5723
  kind: "owner_lane_participant_continuity_v1",
5801
5724
  signerId: parseWalletSignerId(args.signerId),
5802
5725
  participantIds,
5803
- signingWorkerId: requireResult(parseMpcSigningWorkerRef(args.signingWorkerId), "signingWorkerId"),
5726
+ signingWorkerId: requireParsed$2(parseMpcSigningWorkerRef(args.signingWorkerId), "signingWorkerId"),
5804
5727
  custodyKeyManifestDigestB64u: parseDigestField$2(args.custodyKeyManifestDigestB64u, "custodyKeyManifestDigestB64u"),
5805
5728
  sourceIdentityDigestB64u: parseDigestField$2(args.sourceIdentityDigestB64u, "sourceIdentityDigestB64u")
5806
5729
  };
@@ -5812,7 +5735,7 @@ function parseOwnerLaneParticipantContinuityV1(raw, label = "ownerParticipantCon
5812
5735
  return buildOwnerLaneParticipantContinuityV1({
5813
5736
  signerId: parseWalletSignerId(record.signerId, `${label}.signerId`),
5814
5737
  participantIds: parseParticipantIds$1(record.participantIds, `${label}.participantIds`),
5815
- signingWorkerId: requireResult(parseMpcSigningWorkerRef(record.signingWorkerId), `${label}.signingWorkerId`),
5738
+ signingWorkerId: requireParsed$2(parseMpcSigningWorkerRef(record.signingWorkerId), `${label}.signingWorkerId`),
5816
5739
  custodyKeyManifestDigestB64u: parseDigestField$2(record.custodyKeyManifestDigestB64u, `${label}.custodyKeyManifestDigestB64u`),
5817
5740
  sourceIdentityDigestB64u: parseDigestField$2(record.sourceIdentityDigestB64u, `${label}.sourceIdentityDigestB64u`)
5818
5741
  });
@@ -5830,19 +5753,7 @@ function ownerLaneParticipantContinuityCanonicalBytesV1(input) {
5830
5753
  ]);
5831
5754
  }
5832
5755
  async function computeOwnerLaneParticipantBindingDigestV1(input) {
5833
- return requireResult(parseLaneParticipantBindingDigestB64u(base64UrlEncode(await sha256Bytes(ownerLaneParticipantContinuityCanonicalBytesV1(input)))), "owner participant digest");
5834
- }
5835
- new TextEncoder();
5836
- //#endregion
5837
- //#region ../shared-ts/src/signing-lanes/execution.ts
5838
- function buildPreparedOwnerWalletExecution(input) {
5839
- return {
5840
- kind: "prepared_owner_wallet_execution",
5841
- laneKind: input.lane.laneKind,
5842
- authorization: input.authorization,
5843
- materialActivation: input.materialActivation,
5844
- lane: input.lane
5845
- };
5756
+ return requireParsed$2(parseLaneParticipantBindingDigestB64u(base64UrlEncode(await sha256Bytes(ownerLaneParticipantContinuityCanonicalBytesV1(input)))), "owner participant digest");
5846
5757
  }
5847
5758
  //#endregion
5848
5759
  //#region ../shared-ts/src/authorization/operationFingerprint.ts
@@ -5896,6 +5807,30 @@ function parseSigningOperationFingerprintDigest(value) {
5896
5807
  return parseDigestB64u(value.slice(7));
5897
5808
  }
5898
5809
  //#endregion
5810
+ //#region ../shared-ts/src/utils/base58.ts
5811
+ /**
5812
+ * Encodes binary data to base58 string using Bitcoin's base58 alphabet.
5813
+ *
5814
+ * @param data - Binary data to encode (Uint8Array, ArrayBuffer, or number[])
5815
+ * @returns Base58-encoded string
5816
+ */
5817
+ const base58Encode = (data) => {
5818
+ if (data instanceof ArrayBuffer) return bs58.encode(new Uint8Array(data));
5819
+ if (Array.isArray(data)) return bs58.encode(new Uint8Array(data));
5820
+ return bs58.encode(data);
5821
+ };
5822
+ /**
5823
+ * Decodes a base58 string to binary data using Bitcoin's base58 alphabet.
5824
+ * Returns a Uint8Array containing the decoded bytes.
5825
+ *
5826
+ * @param base58String - Base58-encoded string to decode
5827
+ * @returns Uint8Array containing the decoded bytes
5828
+ * @throws Error if input contains invalid base58 characters
5829
+ */
5830
+ const base58Decode = (base58String) => {
5831
+ return bs58.decode(base58String);
5832
+ };
5833
+ //#endregion
5899
5834
  //#region src/authorization/domain.ts
5900
5835
  /**
5901
5836
  * The digest-free authorization projection published to the browser. It carries
@@ -6134,8 +6069,7 @@ function resolveWalletSessionAuthorizationV2AdministrationAdmission(input) {
6134
6069
  if (!subject || subject.authorityId !== input.authority.authorityId) return admissionRefused("capability_subject_mismatch");
6135
6070
  return {
6136
6071
  ok: true,
6137
- operationKind: "link_devices",
6138
- authorityId: input.authority.authorityId
6072
+ operationKind: "link_devices"
6139
6073
  };
6140
6074
  }
6141
6075
  default: return assertNeverWalletSessionAuthorizationV2AdministrationOperation(input.operation.kind);
@@ -6225,7 +6159,7 @@ async function prepareOwnerWalletExecution(input) {
6225
6159
  if (lane.walletKeyId !== input.evidence.walletKey.walletKeyId) return refused("wallet_key_mismatch");
6226
6160
  if (!operationMatchesWalletKey(input.authorizedOperation, input.evidence.walletKey)) return refused("curve_mismatch");
6227
6161
  if (String(claimedOperation.operation.capabilityId) !== String(input.evidence.materialActivation.capability)) return refused("capability_mismatch");
6228
- if (!sameMaterialActivation(input.evidence.materialActivation, input.evidence.expectedMaterialActivation)) return refused("material_activation_mismatch");
6162
+ if (!mpcMaterialActivationRefsEqual(input.evidence.materialActivation, input.evidence.expectedMaterialActivation)) return refused("material_activation_mismatch");
6229
6163
  if (lane.participantBindingDigestB64u !== input.evidence.verifiedLaneParticipantBindingDigestB64u || String(lane.ownerParticipantContinuity.signingWorkerId) !== String(input.evidence.materialActivation.signingWorker)) return refused("participant_binding_mismatch");
6230
6164
  if (await computeOwnerLaneParticipantBindingDigestV1(lane.ownerParticipantContinuity) !== lane.participantBindingDigestB64u) return refused("participant_binding_mismatch");
6231
6165
  if (lane.lifecycle.activationReceiptDigestB64u !== input.evidence.verifiedActivationReceiptDigestB64u) return refused("activation_receipt_mismatch");
@@ -6273,9 +6207,6 @@ function operationMatchesWalletKey(operation, walletKey) {
6273
6207
  case "ecdsa_secp256k1": return operation.operation.operation.capabilityKind === CAPABILITY_KINDS.evmEcdsaMpcSigning;
6274
6208
  }
6275
6209
  }
6276
- function sameMaterialActivation(left, right) {
6277
- return left.activationId === right.activationId && left.capability === right.capability && left.materialOwner === right.materialOwner && left.keyBinding === right.keyBinding && left.lifecycleBinding === right.lifecycleBinding && left.signingWorker === right.signingWorker;
6278
- }
6279
6210
  function refused(reason) {
6280
6211
  return {
6281
6212
  kind: "refused",
@@ -6472,32 +6403,46 @@ async function validateRouterAbEcdsaDerivationWalletSessionInputs(input) {
6472
6403
  const token = extractBearerCredential(input.headers);
6473
6404
  if (!token) return walletSessionFailure("wallet_session_missing");
6474
6405
  const nowMs = input.nowMs || Date.now;
6475
- let resolution;
6406
+ let candidate;
6476
6407
  try {
6477
- resolution = await resolveWalletSessionOperationCredentialAdmission({
6478
- authorizationSessions,
6408
+ candidate = await authorizationSessions.readWalletSessionSigningCandidateByOperationCredential({
6409
+ tenantId: authorizationSessions.tenantId,
6479
6410
  token,
6480
6411
  nowMs: nowMs(),
6481
- operation: {
6482
- keyFamily: "ecdsa_secp256k1",
6483
- operationKind: input.operationKind
6484
- }
6412
+ materialActivation: input.materialActivation
6485
6413
  });
6486
6414
  } catch {
6487
6415
  return walletSessionFailure("wallet_session_unavailable");
6488
6416
  }
6489
- if (resolution.kind === "rejected") return walletSessionFailure("wallet_session_scope_mismatch");
6490
- if (resolution.kind === "not_found") return {
6417
+ if (!candidate) return {
6491
6418
  ok: false,
6492
6419
  code: "wallet_session_invalid",
6493
6420
  message: walletSessionFailureMessage("wallet_session_invalid")
6494
6421
  };
6422
+ if (candidate.kind === "exhausted") return {
6423
+ ok: true,
6424
+ kind: "wallet_session_operation_credential_exhausted_candidate_v1",
6425
+ candidate: candidate.candidate,
6426
+ materialRead: candidate.materialRead,
6427
+ policyRead: candidate.policyRead
6428
+ };
6429
+ const resolution = resolveWalletSessionOperationCredentialAdmissionFromContext({
6430
+ context: candidate.context,
6431
+ nowMs: nowMs(),
6432
+ operation: {
6433
+ keyFamily: "ecdsa_secp256k1",
6434
+ operationKind: input.operationKind
6435
+ }
6436
+ });
6437
+ if (resolution.kind === "rejected") return walletSessionFailure("wallet_session_scope_mismatch");
6495
6438
  if (resolution.admission.curve !== "ecdsa") return walletSessionFailure("wallet_session_scope_mismatch");
6496
6439
  return {
6497
6440
  ok: true,
6498
6441
  kind: "wallet_session_operation_credential_v1",
6499
6442
  admission: resolution.admission,
6500
- context: resolution.admission.context
6443
+ context: resolution.admission.context,
6444
+ materialRead: candidate.materialRead,
6445
+ policyRead: candidate.policyRead
6501
6446
  };
6502
6447
  }
6503
6448
  async function resolveThresholdRuntimePolicyScope(input) {
@@ -6747,6 +6692,22 @@ function toFetchRouteResponse(response) {
6747
6692
  });
6748
6693
  }
6749
6694
  //#endregion
6695
+ //#region ../shared-ts/src/utils/registrationIds.ts
6696
+ function walletIdFromString(value) {
6697
+ const parsed = parseWalletId(value);
6698
+ if (!parsed.ok) throw new Error(parsed.error.message);
6699
+ return parsed.value;
6700
+ }
6701
+ function nearEd25519SigningKeyIdFromString(value) {
6702
+ const normalized = String(value || "").trim();
6703
+ if (!normalized) throw new Error("nearEd25519SigningKeyId is required");
6704
+ return normalized;
6705
+ }
6706
+ function parseNearEd25519SigningKeyId(value) {
6707
+ if (typeof value !== "string") throw new Error("nearEd25519SigningKeyId must be a string");
6708
+ return nearEd25519SigningKeyIdFromString(value);
6709
+ }
6710
+ //#endregion
6750
6711
  //#region ../shared-ts/src/passkey-custody/custodySecretBinding.ts
6751
6712
  /** The only derivation scheme owner custody supports. */
6752
6713
  const WALLET_SEED_DERIVATION_SCHEME_V1 = "wallet_seed_parallel_hkdf_sha256_v1";
@@ -7217,9 +7178,6 @@ function parseWalletRegistrationSetupPolicy(value) {
7217
7178
  }
7218
7179
  //#endregion
7219
7180
  //#region ../shared-ts/src/utils/ecdsaKeyFactsInventory.ts
7220
- function chainTargetKey(target) {
7221
- return target.kind === "evm" ? `evm:eip155:${target.chainId}` : `tempo:${target.chainId}`;
7222
- }
7223
7181
  function normalizeChainTarget(target) {
7224
7182
  if (target.kind === "evm") return {
7225
7183
  kind: "evm",
@@ -7237,7 +7195,7 @@ function canonicalizeWalletEcdsaKeyFactsInventoryChallenge(input) {
7237
7195
  const keyTargets = input.keyTargets.map((target) => ({
7238
7196
  keyHandle: target.keyHandle,
7239
7197
  chainTarget: normalizeChainTarget(target.chainTarget),
7240
- targetKey: chainTargetKey(target.chainTarget)
7198
+ targetKey: thresholdEcdsaChainTargetKey(target.chainTarget)
7241
7199
  })).sort((left, right) => {
7242
7200
  const leftKey = `${left.keyHandle}:${left.targetKey}`;
7243
7201
  const rightKey = `${right.keyHandle}:${right.targetKey}`;
@@ -7256,8 +7214,90 @@ async function computeWalletEcdsaKeyFactsInventoryChallengeDigestB64u(input) {
7256
7214
  return base64UrlEncode(await sha256BytesUtf8(canonicalizeWalletEcdsaKeyFactsInventoryChallenge(input)));
7257
7215
  }
7258
7216
  //#endregion
7259
- //#region ../shared-ts/src/utils/registrationSignerPlan.ts
7260
- function normalizePositiveInteger(raw, fallback) {
7217
+ //#region ../shared-ts/src/utils/near.ts
7218
+ /**
7219
+ * NEAR-specific utility helpers.
7220
+ *
7221
+ * Keep chain-specific parsing and validation logic here so generic utility
7222
+ * modules (`validation`, `errors`, `encoders`, etc.) stay chain-agnostic.
7223
+ */
7224
+ /**
7225
+ * Ensure a key string has the NEAR Ed25519 prefix (`ed25519:`).
7226
+ *
7227
+ * - Accepts either `ed25519:<base58>` or a bare `<base58>` string.
7228
+ * - Canonicalizes `ED25519:` -> `ed25519:`.
7229
+ * - If a different prefix is present (e.g. `secp256k1:`), returns the input unchanged.
7230
+ */
7231
+ function ensureEd25519Prefix(value) {
7232
+ const raw = String(value ?? "").trim();
7233
+ if (!raw) return "";
7234
+ if (/^[a-z0-9_]+:/i.test(raw)) {
7235
+ if (/^ed25519:/i.test(raw)) return `ed25519:${raw.replace(/^ed25519:/i, "")}`;
7236
+ return raw;
7237
+ }
7238
+ return `ed25519:${raw}`;
7239
+ }
7240
+ /**
7241
+ * Lightweight NEAR account ID validation used by server-side helpers.
7242
+ * - length: 2..64
7243
+ * - chars: lowercase letters, digits, `_`, `.`, `-`
7244
+ */
7245
+ function isValidAccountId(accountId) {
7246
+ if (typeof accountId !== "string") return false;
7247
+ if (!accountId || accountId.length < 2 || accountId.length > 64) return false;
7248
+ return /^[a-z0-9_.-]+$/.test(accountId);
7249
+ }
7250
+ function isImplicitNearAccountId(value) {
7251
+ return typeof value === "string" && /^[0-9a-f]{64}$/.test(value);
7252
+ }
7253
+ function parseImplicitNearAccountId(raw) {
7254
+ const value = typeof raw === "string" ? raw.trim() : "";
7255
+ if (!value) return {
7256
+ ok: false,
7257
+ code: "missing",
7258
+ message: "implicit NEAR account ID is required"
7259
+ };
7260
+ if (!isImplicitNearAccountId(value)) return {
7261
+ ok: false,
7262
+ code: "invalid",
7263
+ message: "implicit NEAR account ID must be 64 lowercase hex characters"
7264
+ };
7265
+ return {
7266
+ ok: true,
7267
+ value
7268
+ };
7269
+ }
7270
+ function parseNamedNearAccountId(raw) {
7271
+ const value = typeof raw === "string" ? raw.trim() : "";
7272
+ if (!value) return {
7273
+ ok: false,
7274
+ code: "missing",
7275
+ message: "named NEAR account ID is required"
7276
+ };
7277
+ if (isImplicitNearAccountId(value) || !isValidAccountId(value) || !value.includes(".")) return {
7278
+ ok: false,
7279
+ code: "invalid",
7280
+ message: "named NEAR account ID must be a valid named account containing a dot"
7281
+ };
7282
+ return {
7283
+ ok: true,
7284
+ value
7285
+ };
7286
+ }
7287
+ function bytesToLowerHex(bytes) {
7288
+ return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
7289
+ }
7290
+ function deriveImplicitNearAccountIdFromEd25519PublicKey(publicKey) {
7291
+ const normalized = ensureEd25519Prefix(publicKey);
7292
+ const encoded = normalized.startsWith("ed25519:") ? normalized.slice(8) : "";
7293
+ if (!encoded) throw new Error("Ed25519 public key is required");
7294
+ const decoded = base58Decode(encoded);
7295
+ if (decoded.length !== 32) throw new Error("Ed25519 public key must decode to 32 bytes");
7296
+ return bytesToLowerHex(decoded);
7297
+ }
7298
+ //#endregion
7299
+ //#region ../shared-ts/src/utils/registrationSignerPlan.ts
7300
+ function normalizePositiveInteger(raw, fallback) {
7261
7301
  const value = typeof raw === "number" ? raw : Number(raw);
7262
7302
  return Number.isFinite(value) && value >= 1 ? Math.floor(value) : fallback;
7263
7303
  }
@@ -7317,11 +7357,8 @@ function registrationSignerBranchKeyFromString(value) {
7317
7357
  function registrationNearEd25519BranchKey(signerSlot) {
7318
7358
  return registrationSignerBranchKeyFromString(`near_ed25519:slot:${signerSlot}`);
7319
7359
  }
7320
- function registrationEvmFamilyEcdsaTargetKey(target) {
7321
- return alphabetizeStringify(target);
7322
- }
7323
7360
  function registrationEvmFamilyEcdsaBranchKey(chainTargets) {
7324
- return registrationSignerBranchKeyFromString(`evm_family_ecdsa:${chainTargets.map(registrationEvmFamilyEcdsaTargetKey).join("|")}`);
7361
+ return registrationSignerBranchKeyFromString(`evm_family_ecdsa:${chainTargets.map(alphabetizeStringify).join("|")}`);
7325
7362
  }
7326
7363
  function registrationSignerPlanFromRequests(signers) {
7327
7364
  return registrationSignerPlanFromBranches(signers.map(registrationSignerPlanBranchFromRequest));
@@ -7405,7 +7442,7 @@ function findDuplicateRegistrationSignerBranch(branch, branchKeys) {
7405
7442
  }
7406
7443
  function findDuplicateRegistrationEcdsaTarget(branch, ecdsaTargetKeys) {
7407
7444
  for (const target of branch.chainTargets) {
7408
- const targetKey = registrationEvmFamilyEcdsaTargetKey(target);
7445
+ const targetKey = alphabetizeStringify(target);
7409
7446
  if (ecdsaTargetKeys.has(targetKey)) return {
7410
7447
  ok: false,
7411
7448
  code: "invalid_body",
@@ -7591,17 +7628,11 @@ function addAuthMethodIntentGrantFromString(value) {
7591
7628
  function addSignerIntentGrantFromString(value) {
7592
7629
  return String(value || "").trim();
7593
7630
  }
7594
- function serializeAddSignerIntentV1(intent) {
7595
- return alphabetizeStringify(intent);
7596
- }
7597
- function serializeAddAuthMethodIntentV1(intent) {
7598
- return alphabetizeStringify(intent);
7599
- }
7600
7631
  async function computeAddSignerIntentDigestB64u(intent) {
7601
- return base64UrlEncode(await sha256BytesUtf8(serializeAddSignerIntentV1(intent)));
7632
+ return base64UrlEncode(await sha256BytesUtf8(alphabetizeStringify(intent)));
7602
7633
  }
7603
7634
  async function computeAddAuthMethodIntentDigestB64u(intent) {
7604
- return base64UrlEncode(await sha256BytesUtf8(serializeAddAuthMethodIntentV1(intent)));
7635
+ return base64UrlEncode(await sha256BytesUtf8(alphabetizeStringify(intent)));
7605
7636
  }
7606
7637
  function normalizeAddAuthMethodIntentCaller(raw) {
7607
7638
  const record = inspectRawObject(raw);
@@ -7932,6 +7963,12 @@ function parseWalletRegistrationSetupWallet(raw) {
7932
7963
  };
7933
7964
  }
7934
7965
  function parseWalletRegistrationSetupRequest(body) {
7966
+ const registrationOperationId = parseRegistrationSetupOperationId(body.registrationOperationId);
7967
+ if (!registrationOperationId) return {
7968
+ ok: false,
7969
+ code: "invalid_body",
7970
+ message: "registrationOperationId is required"
7971
+ };
7935
7972
  const signerSelection = parseRegistrationSignerSet(body.signerSelection);
7936
7973
  if (!signerSelection.ok) return signerSelection;
7937
7974
  const authMethod = normalizeRegistrationAuthMethodInput(body.authMethod);
@@ -7945,6 +7982,7 @@ function parseWalletRegistrationSetupRequest(body) {
7945
7982
  return {
7946
7983
  ok: true,
7947
7984
  value: {
7985
+ registrationOperationId,
7948
7986
  ...wallet.value ? { wallet: wallet.value } : {},
7949
7987
  signerSelection: signerSelection.value.selection,
7950
7988
  authMethod
@@ -9162,14 +9200,6 @@ async function handleRouterApiWalletAddSignerIntent(input) {
9162
9200
  });
9163
9201
  return routeJson(result.ok ? 200 : 400, result);
9164
9202
  }
9165
- /**
9166
- * `POST /wallets/register/setup` — the single admitted entry point that
9167
- * replaces the bootstrap grant, the intent, and start.
9168
- *
9169
- * Authentication is the same API-credential plane the intent route used, so
9170
- * origin and environment binding are unchanged; what is gone is the stored
9171
- * grant that used to sit between the check and its only reader.
9172
- */
9173
9203
  async function handleRouterApiWalletRegistrationSetup(input) {
9174
9204
  if (!isPlainObject(input.body)) return routeError(400, "invalid_body", "JSON body required");
9175
9205
  const origin = normalizeCorsOrigin(input.origin);
@@ -9212,7 +9242,7 @@ async function handleRouterApiWalletRegistrationSetup(input) {
9212
9242
  if (!session) return routeError(500, "internal", "wallet registration setup requires session signing");
9213
9243
  const request = parseWalletRegistrationSetupRequest(input.body);
9214
9244
  if (!request.ok) return routeError(400, request.code, request.message);
9215
- const result = await input.services.walletRegistration.setupWalletRegistration({
9245
+ return input.services.walletRegistration.setupWalletRegistration({
9216
9246
  request: request.value,
9217
9247
  orgId: principal.orgId,
9218
9248
  expectedOrigin: origin,
@@ -9223,7 +9253,6 @@ async function handleRouterApiWalletRegistrationSetup(input) {
9223
9253
  signingRootVersion: runtimePolicyScope.signingRootVersion
9224
9254
  } : {}
9225
9255
  });
9226
- return routeJson(result.ok ? 200 : 400, result);
9227
9256
  }
9228
9257
  /**
9229
9258
  * `POST /wallets/register/respond` — the authenticated leg.
@@ -10073,24 +10102,12 @@ function buildSigningSessionSealRemovePath(basePath) {
10073
10102
  }
10074
10103
  function parseSigningSessionSealApplyBody(body) {
10075
10104
  const obj = asRecord(body);
10076
- if (!obj) return {
10077
- ok: false,
10078
- code: "invalid_body",
10079
- message: "Request body must be a JSON object"
10080
- };
10105
+ if (!obj) return failure("invalid_body", "Request body must be a JSON object");
10081
10106
  const thresholdSessionId = readRequiredString(obj, "thresholdSessionId");
10082
10107
  const ciphertext = readRequiredString(obj, "ciphertext");
10083
- if (!thresholdSessionId || !ciphertext) return {
10084
- ok: false,
10085
- code: "invalid_body",
10086
- message: "thresholdSessionId and ciphertext are required"
10087
- };
10108
+ if (!thresholdSessionId || !ciphertext) return failure("invalid_body", "thresholdSessionId and ciphertext are required");
10088
10109
  const parsedThresholdSessionId = parseThresholdSessionId(thresholdSessionId);
10089
- if (!parsedThresholdSessionId.ok) return {
10090
- ok: false,
10091
- code: "invalid_body",
10092
- message: "thresholdSessionId is invalid"
10093
- };
10110
+ if (!parsedThresholdSessionId.ok) return failure("invalid_body", "thresholdSessionId is invalid");
10094
10111
  return {
10095
10112
  ok: true,
10096
10113
  value: {
@@ -10113,11 +10130,7 @@ async function authorizeSigningSessionSealRequest(args) {
10113
10130
  thresholdSessionId: args.thresholdSessionId
10114
10131
  });
10115
10132
  } catch (error) {
10116
- return {
10117
- ok: false,
10118
- code: "internal",
10119
- message: error instanceof Error ? error.message : String(error || "Authorization failed")
10120
- };
10133
+ return failure("internal", error instanceof Error ? error.message : String(error || "Authorization failed"));
10121
10134
  }
10122
10135
  return {
10123
10136
  ok: false,
@@ -10240,7 +10253,6 @@ const ROUTER_API_ECDSA_STRICT_LIFECYCLE_SERVICES = [
10240
10253
  "session"
10241
10254
  ];
10242
10255
  const ROUTER_API_WEBAUTHN_AUTHENTICATOR_SERVICES = ["webAuthn", "session"];
10243
- const ROUTER_API_NEAR_PUBLIC_KEY_SERVICES = ["nearFunding", "session"];
10244
10256
  const ROUTER_API_PASSKEY_CUSTODY_SERVICES = [
10245
10257
  "passkeyCustody",
10246
10258
  "walletAuthMethods",
@@ -10607,7 +10619,7 @@ function createRouterApiRouteDefinitions(options = {}) {
10607
10619
  }, 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", {
10608
10620
  plane: "public",
10609
10621
  rationale: "Router A/B health probes are intentionally public diagnostics."
10610
- }, 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", {
10622
+ }, 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", {
10611
10623
  plane: "public",
10612
10624
  proof: "challenge_exchange",
10613
10625
  rationale: "Wallet unlock challenge issuance is intentionally public."
@@ -10687,6 +10699,7 @@ function resolveWalletRegistrationRoute(ctx) {
10687
10699
  async function handleWalletRegistration(ctx) {
10688
10700
  const route = resolveWalletRegistrationRoute(ctx);
10689
10701
  if (!route) return null;
10702
+ if (ctx.request.headers.get("X-Seams-Wallet-Protocol") !== "2") 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.");
10690
10703
  const common = {
10691
10704
  body: await readJson(ctx.request),
10692
10705
  headers: Object.fromEntries(ctx.request.headers.entries()),
@@ -10982,6 +10995,8 @@ function requireVerificationWindow(verifiedAtMs, expiresAtMs) {
10982
10995
  //#endregion
10983
10996
  //#region ../shared-ts/src/utils/emailOtpDomain.ts
10984
10997
  const EMAIL_OTP_CHANNEL = "email_otp";
10998
+ /** Domain label that opens the AAD binding a released Email OTP factor to its challenge. */
10999
+ const EMAIL_OTP_FACTOR_RELEASE_AAD_DOMAIN_V1 = "seams/email-otp/factor-release/v1";
10985
11000
  const WALLET_UNLOCK_BACKENDS = ["passkey", EMAIL_OTP_CHANNEL];
10986
11001
  const WALLET_EMAIL_OTP_LOGIN_OPERATIONS = [
10987
11002
  "wallet_unlock",
@@ -11753,6 +11768,7 @@ async function handleWalletRecoveryPrepare(ctx) {
11753
11768
  case "refused": return toFetchRouteResponse(refusedSpend());
11754
11769
  case "reserved":
11755
11770
  case "consumed": return routeErrorResponse(401, "recovery_code_used", "that recovery code has already been used");
11771
+ case "routing_unavailable": return routeErrorResponse(503, "wallet_home_unavailable", "Wallet recovery routing is temporarily unavailable");
11756
11772
  case "manifest_unavailable":
11757
11773
  case "registration_unavailable": return routeErrorResponse(409, "recovery_preparation_conflict", "wallet recovery could not be prepared");
11758
11774
  }
@@ -12559,11 +12575,7 @@ async function refreshEmailOtpWalletUnlockSessionState(input) {
12559
12575
  ok: false,
12560
12576
  response: {
12561
12577
  status: 500,
12562
- body: {
12563
- ok: false,
12564
- code: "internal",
12565
- message: error instanceof Error ? error.message : "Email OTP authority refresh resolution failed"
12566
- }
12578
+ body: failure("internal", error instanceof Error ? error.message : "Email OTP authority refresh resolution failed")
12567
12579
  }
12568
12580
  };
12569
12581
  }
@@ -12571,11 +12583,7 @@ async function refreshEmailOtpWalletUnlockSessionState(input) {
12571
12583
  ok: false,
12572
12584
  response: {
12573
12585
  status: authorityResolution.code === "internal" ? 500 : 403,
12574
- body: {
12575
- ok: false,
12576
- code: authorityResolution.code,
12577
- message: authorityResolution.message
12578
- }
12586
+ body: failure(authorityResolution.code, authorityResolution.message)
12579
12587
  }
12580
12588
  };
12581
12589
  try {
@@ -12592,11 +12600,7 @@ async function refreshEmailOtpWalletUnlockSessionState(input) {
12592
12600
  ok: false,
12593
12601
  response: {
12594
12602
  status: 500,
12595
- body: {
12596
- ok: false,
12597
- code: "internal",
12598
- message: error instanceof Error ? error.message : "Email OTP Wallet Session authority projection refresh failed"
12599
- }
12603
+ body: failure("internal", error instanceof Error ? error.message : "Email OTP Wallet Session authority projection refresh failed")
12600
12604
  }
12601
12605
  };
12602
12606
  }
@@ -12607,11 +12611,7 @@ function walletUnlockCustodyUnavailableResponse(lookup, factor) {
12607
12611
  ok: false,
12608
12612
  response: {
12609
12613
  status: lookup.kind === "manifest_unavailable" ? 503 : lookup.kind === "conflict" ? 409 : lookup.kind === "missing" ? 404 : 409,
12610
- body: {
12611
- ok: false,
12612
- code: lookup.kind === "manifest_unavailable" ? "custody_manifest_unavailable" : "custody_envelope_unavailable",
12613
- message: `${factor} wallet custody is unavailable`
12614
- }
12614
+ body: failure(lookup.kind === "manifest_unavailable" ? "custody_manifest_unavailable" : "custody_envelope_unavailable", `${factor} wallet custody is unavailable`)
12615
12615
  }
12616
12616
  };
12617
12617
  }
@@ -12626,11 +12626,7 @@ function projectEmailOtpCustody(verifiedUnlock, lookup) {
12626
12626
  ok: false,
12627
12627
  response: {
12628
12628
  status: 500,
12629
- body: {
12630
- ok: false,
12631
- code: "custody_binding_mismatch",
12632
- message: "Email OTP wallet custody binding is invalid"
12633
- }
12629
+ body: failure("custody_binding_mismatch", "Email OTP wallet custody binding is invalid")
12634
12630
  }
12635
12631
  };
12636
12632
  return {
@@ -12660,11 +12656,7 @@ function projectPasskeyCustody(verifiedUnlock, resolution) {
12660
12656
  ok: false,
12661
12657
  response: {
12662
12658
  status: 500,
12663
- body: {
12664
- ok: false,
12665
- code: "custody_binding_mismatch",
12666
- message: "Passkey wallet custody binding is invalid"
12667
- }
12659
+ body: failure("custody_binding_mismatch", "Passkey wallet custody binding is invalid")
12668
12660
  }
12669
12661
  };
12670
12662
  let ed25519 = { kind: "absent" };
@@ -12676,11 +12668,7 @@ function projectPasskeyCustody(verifiedUnlock, resolution) {
12676
12668
  ok: false,
12677
12669
  response: {
12678
12670
  status: 500,
12679
- body: {
12680
- ok: false,
12681
- code: "custody_binding_mismatch",
12682
- message: "Passkey Ed25519 custody binding is invalid"
12683
- }
12671
+ body: failure("custody_binding_mismatch", "Passkey Ed25519 custody binding is invalid")
12684
12672
  }
12685
12673
  };
12686
12674
  ed25519 = {
@@ -12711,11 +12699,7 @@ async function provisionFirstEcdsaWalletSession(input) {
12711
12699
  ok: false,
12712
12700
  response: {
12713
12701
  status: 403,
12714
- body: {
12715
- ok: false,
12716
- code: "scope_mismatch",
12717
- message: "Wallet unlock proof does not match the requested ECDSA wallet"
12718
- }
12702
+ body: failure("scope_mismatch", "Wallet unlock proof does not match the requested ECDSA wallet")
12719
12703
  }
12720
12704
  };
12721
12705
  const provisioned = await input.context.provisionWalletSession(input.authorization);
@@ -12723,11 +12707,7 @@ async function provisionFirstEcdsaWalletSession(input) {
12723
12707
  ok: false,
12724
12708
  response: {
12725
12709
  status: provisioned.status,
12726
- body: {
12727
- ok: false,
12728
- code: provisioned.code,
12729
- message: provisioned.message
12730
- }
12710
+ body: failure(provisioned.code, provisioned.message)
12731
12711
  }
12732
12712
  };
12733
12713
  return {
@@ -12755,11 +12735,7 @@ function walletUnlockScopeMismatchResponse() {
12755
12735
  ok: false,
12756
12736
  response: {
12757
12737
  status: 403,
12758
- body: {
12759
- ok: false,
12760
- code: "scope_mismatch",
12761
- message: "Email OTP unlock proof does not match the requested Ed25519 wallet"
12762
- }
12738
+ body: failure("scope_mismatch", "Email OTP unlock proof does not match the requested Ed25519 wallet")
12763
12739
  }
12764
12740
  };
12765
12741
  }
@@ -12823,11 +12799,7 @@ function planWalletUnlockAuthorityEcdsaSession(input) {
12823
12799
  function walletUnlockDeviceLinkEcdsaSessionRejection() {
12824
12800
  return {
12825
12801
  status: 400,
12826
- body: {
12827
- ok: false,
12828
- code: "invalid_body",
12829
- message: "ecdsaSessionPolicy is not supported for device-linked wallet unlock"
12830
- }
12802
+ body: failure("invalid_body", "ecdsaSessionPolicy is not supported for device-linked wallet unlock")
12831
12803
  };
12832
12804
  }
12833
12805
  function planWalletUnlockPasskeySession(input) {
@@ -12870,11 +12842,7 @@ async function provisionPasskeyEd25519YaoSession(input) {
12870
12842
  ok: false,
12871
12843
  response: {
12872
12844
  status: 409,
12873
- body: {
12874
- ok: false,
12875
- code: "capability_unavailable",
12876
- message: "Requested Ed25519 Wallet Session is unavailable"
12877
- }
12845
+ body: failure("capability_unavailable", "Requested Ed25519 Wallet Session is unavailable")
12878
12846
  }
12879
12847
  };
12880
12848
  const provisioned = await input.context.provisionWalletSession({
@@ -12928,11 +12896,7 @@ function walletUnlockEcdsaOperationCredential(input) {
12928
12896
  function walletUnlockEcdsaCredentialUnavailableResponse() {
12929
12897
  return {
12930
12898
  status: 409,
12931
- body: {
12932
- ok: false,
12933
- code: "capability_unavailable",
12934
- message: "ECDSA activation requires the exact Wallet Session operation credential"
12935
- }
12899
+ body: failure("capability_unavailable", "ECDSA activation requires the exact Wallet Session operation credential")
12936
12900
  };
12937
12901
  }
12938
12902
  /** The unlock response's Wallet Session, when the unlock holds one. */
@@ -12968,11 +12932,7 @@ function parseWalletUnlockRouteBody(body) {
12968
12932
  ok: false,
12969
12933
  response: {
12970
12934
  status: 400,
12971
- body: {
12972
- ok: false,
12973
- code: "invalid_body",
12974
- message: "Request body is required"
12975
- }
12935
+ body: failure("invalid_body", "Request body is required")
12976
12936
  }
12977
12937
  };
12978
12938
  const record = body;
@@ -12981,11 +12941,7 @@ function parseWalletUnlockRouteBody(body) {
12981
12941
  ok: false,
12982
12942
  response: {
12983
12943
  status: 400,
12984
- body: {
12985
- ok: false,
12986
- code: "invalid_body",
12987
- message: "unlockBackend is required"
12988
- }
12944
+ body: failure("invalid_body", "unlockBackend is required")
12989
12945
  }
12990
12946
  };
12991
12947
  return {
@@ -13002,11 +12958,7 @@ async function handleWalletUnlockChallengeRoute(input) {
13002
12958
  const walletAuthMethodId = parseRequiredWalletAuthMethodId(body.walletAuthMethodId);
13003
12959
  if (!walletAuthMethodId.ok) return {
13004
12960
  status: 400,
13005
- body: {
13006
- ok: false,
13007
- code: "invalid_body",
13008
- message: walletAuthMethodId.message
13009
- }
12961
+ body: failure("invalid_body", walletAuthMethodId.message)
13010
12962
  };
13011
12963
  }
13012
12964
  const result = unlockBackend === "passkey" ? await input.service.createWebAuthnLoginOptions({
@@ -13018,6 +12970,20 @@ async function handleWalletUnlockChallengeRoute(input) {
13018
12970
  orgId: body.orgId,
13019
12971
  ttlMs: body.ttlMs
13020
12972
  });
12973
+ if (!result.ok && result.code === "wallet_home_unavailable") return {
12974
+ status: 503,
12975
+ body: {
12976
+ ...result,
12977
+ unlockBackend
12978
+ }
12979
+ };
12980
+ if (!result.ok && result.code === "wallet_home_conflict") return {
12981
+ status: 409,
12982
+ body: {
12983
+ ...result,
12984
+ unlockBackend
12985
+ }
12986
+ };
13021
12987
  return {
13022
12988
  status: result.ok ? 200 : result.code === "internal" ? 500 : 400,
13023
12989
  body: {
@@ -13189,20 +13155,12 @@ async function handleWalletUnlockVerifyRoute(input) {
13189
13155
  const challengeId = String(body.challengeId || "").trim();
13190
13156
  if (!challengeId) return {
13191
13157
  status: 400,
13192
- body: {
13193
- ok: false,
13194
- code: "invalid_body",
13195
- message: "challengeId is required"
13196
- }
13158
+ body: failure("invalid_body", "challengeId is required")
13197
13159
  };
13198
13160
  if (unlockBackend === "passkey") {
13199
13161
  if (input.capabilityContext.kind !== "passkey_unlock") return {
13200
13162
  status: 400,
13201
- body: {
13202
- ok: false,
13203
- code: "invalid_body",
13204
- message: "Passkey unlock context is invalid"
13205
- }
13163
+ body: failure("invalid_body", "Passkey unlock context is invalid")
13206
13164
  };
13207
13165
  let ed25519SessionRequest;
13208
13166
  try {
@@ -13210,11 +13168,7 @@ async function handleWalletUnlockVerifyRoute(input) {
13210
13168
  } catch (error) {
13211
13169
  return {
13212
13170
  status: 400,
13213
- body: {
13214
- ok: false,
13215
- code: "invalid_body",
13216
- message: error instanceof Error ? error.message : "Ed25519 session request is invalid"
13217
- }
13171
+ body: failure("invalid_body", error instanceof Error ? error.message : "Ed25519 session request is invalid")
13218
13172
  };
13219
13173
  }
13220
13174
  const result = await verifyPasskeyWalletUnlock({
@@ -13233,11 +13187,7 @@ async function handleWalletUnlockVerifyRoute(input) {
13233
13187
  const userId = String(result.userId || "").trim();
13234
13188
  if (!userId) return {
13235
13189
  status: 500,
13236
- body: {
13237
- ok: false,
13238
- code: "internal",
13239
- message: "Verified passkey user is missing"
13240
- }
13190
+ body: failure("internal", "Verified passkey user is missing")
13241
13191
  };
13242
13192
  const walletId = parseWalletId(userId);
13243
13193
  const walletAuthMethodId = parseWalletAuthMethodId(result.walletAuthMethodId);
@@ -13246,11 +13196,7 @@ async function handleWalletUnlockVerifyRoute(input) {
13246
13196
  const credentialIdB64u = parseWebAuthnCredentialIdB64u(result.credentialIdB64u);
13247
13197
  if (!walletId.ok || !walletAuthMethodId.ok || !walletAuthorityId.ok || !rpId.ok || !credentialIdB64u.ok) return {
13248
13198
  status: 500,
13249
- body: {
13250
- ok: false,
13251
- code: "internal",
13252
- message: "Verified passkey identity is invalid"
13253
- }
13199
+ body: failure("internal", "Verified passkey identity is invalid")
13254
13200
  };
13255
13201
  let authorization;
13256
13202
  try {
@@ -13268,11 +13214,7 @@ async function handleWalletUnlockVerifyRoute(input) {
13268
13214
  } catch (error) {
13269
13215
  return {
13270
13216
  status: 403,
13271
- body: {
13272
- ok: false,
13273
- code: "owner_proof_rejected",
13274
- message: error instanceof Error ? error.message : "Passkey owner proof is invalid"
13275
- }
13217
+ body: failure("owner_proof_rejected", error instanceof Error ? error.message : "Passkey owner proof is invalid")
13276
13218
  };
13277
13219
  }
13278
13220
  const resolvePasskeyAuthority = () => input.service.resolveActivePasskeyAuthorityForUnlock({
@@ -13290,11 +13232,7 @@ async function handleWalletUnlockVerifyRoute(input) {
13290
13232
  } catch (error) {
13291
13233
  return {
13292
13234
  status: 500,
13293
- body: {
13294
- ok: false,
13295
- code: "internal",
13296
- message: error instanceof Error ? error.message : "Passkey authority resolution failed"
13297
- }
13235
+ body: failure("internal", error instanceof Error ? error.message : "Passkey authority resolution failed")
13298
13236
  };
13299
13237
  }
13300
13238
  if (authorityResolution.kind === "active_authority") {
@@ -13311,11 +13249,7 @@ async function handleWalletUnlockVerifyRoute(input) {
13311
13249
  switch (sessionPlan.kind) {
13312
13250
  case "rejected": return {
13313
13251
  status: walletUnlockIssuanceRejectionStatus(sessionPlan.authorityResolution),
13314
- body: {
13315
- ok: false,
13316
- code: sessionPlan.authorityResolution.code,
13317
- message: sessionPlan.authorityResolution.message
13318
- }
13252
+ body: failure(sessionPlan.authorityResolution.code, sessionPlan.authorityResolution.message)
13319
13253
  };
13320
13254
  case "wallet_registration":
13321
13255
  passkeyCustodyRequired = true;
@@ -13337,11 +13271,7 @@ async function handleWalletUnlockVerifyRoute(input) {
13337
13271
  } catch (error) {
13338
13272
  return {
13339
13273
  status: 500,
13340
- body: {
13341
- ok: false,
13342
- code: "internal",
13343
- message: error instanceof Error ? error.message : "Passkey Wallet Session issuance failed"
13344
- }
13274
+ body: failure("internal", error instanceof Error ? error.message : "Passkey Wallet Session issuance failed")
13345
13275
  };
13346
13276
  }
13347
13277
  switch (sessionResolution.kind) {
@@ -13362,11 +13292,7 @@ async function handleWalletUnlockVerifyRoute(input) {
13362
13292
  break;
13363
13293
  case "rejected": return {
13364
13294
  status: walletUnlockIssuanceRejectionStatus(sessionResolution),
13365
- body: {
13366
- ok: false,
13367
- code: sessionResolution.code,
13368
- message: sessionResolution.message
13369
- }
13295
+ body: failure(sessionResolution.code, sessionResolution.message)
13370
13296
  };
13371
13297
  }
13372
13298
  break;
@@ -13385,11 +13311,7 @@ async function handleWalletUnlockVerifyRoute(input) {
13385
13311
  } catch (error) {
13386
13312
  return {
13387
13313
  status: 503,
13388
- body: {
13389
- ok: false,
13390
- code: "custody_unavailable",
13391
- message: error instanceof Error ? error.message : "Passkey wallet custody is unavailable"
13392
- }
13314
+ body: failure("custody_unavailable", error instanceof Error ? error.message : "Passkey wallet custody is unavailable")
13393
13315
  };
13394
13316
  }
13395
13317
  const ed25519Session = await provisionPasskeyEd25519YaoSession({
@@ -13431,20 +13353,12 @@ async function handleWalletUnlockVerifyRoute(input) {
13431
13353
  } catch (error) {
13432
13354
  return {
13433
13355
  status: 500,
13434
- body: {
13435
- ok: false,
13436
- code: "internal",
13437
- message: error instanceof Error ? error.message : "Passkey authority refresh resolution failed"
13438
- }
13356
+ body: failure("internal", error instanceof Error ? error.message : "Passkey authority refresh resolution failed")
13439
13357
  };
13440
13358
  }
13441
13359
  if (refreshedAuthority.kind === "rejected") return {
13442
13360
  status: walletUnlockIssuanceRejectionStatus(refreshedAuthority),
13443
- body: {
13444
- ok: false,
13445
- code: refreshedAuthority.code,
13446
- message: refreshedAuthority.message
13447
- }
13361
+ body: failure(refreshedAuthority.code, refreshedAuthority.message)
13448
13362
  };
13449
13363
  try {
13450
13364
  walletSessionState = await refreshWalletUnlockSessionState({
@@ -13455,11 +13369,7 @@ async function handleWalletUnlockVerifyRoute(input) {
13455
13369
  } catch (error) {
13456
13370
  return {
13457
13371
  status: 500,
13458
- body: {
13459
- ok: false,
13460
- code: "internal",
13461
- message: error instanceof Error ? error.message : "Passkey Wallet Session authority projection refresh failed"
13462
- }
13372
+ body: failure("internal", error instanceof Error ? error.message : "Passkey Wallet Session authority projection refresh failed")
13463
13373
  };
13464
13374
  }
13465
13375
  }
@@ -13488,20 +13398,12 @@ async function handleWalletUnlockVerifyRoute(input) {
13488
13398
  }
13489
13399
  if (input.capabilityContext.kind === "passkey_unlock") return {
13490
13400
  status: 400,
13491
- body: {
13492
- ok: false,
13493
- code: "invalid_body",
13494
- message: "Email OTP unlock context is invalid"
13495
- }
13401
+ body: failure("invalid_body", "Email OTP unlock context is invalid")
13496
13402
  };
13497
13403
  const requestedWalletAuthMethodId = parseRequiredWalletAuthMethodId(body.walletAuthMethodId);
13498
13404
  if (!requestedWalletAuthMethodId.ok) return {
13499
13405
  status: 400,
13500
- body: {
13501
- ok: false,
13502
- code: "invalid_body",
13503
- message: requestedWalletAuthMethodId.message
13504
- }
13406
+ body: failure("invalid_body", requestedWalletAuthMethodId.message)
13505
13407
  };
13506
13408
  const result = await input.service.verifyEmailOtpUnlockProof({
13507
13409
  walletId: body.walletId,
@@ -13528,11 +13430,7 @@ async function handleWalletUnlockVerifyRoute(input) {
13528
13430
  const walletId = parseWalletId(result.walletId);
13529
13431
  if (!walletId.ok) return {
13530
13432
  status: 500,
13531
- body: {
13532
- ok: false,
13533
- code: "internal",
13534
- message: "Verified Email OTP wallet identity is invalid"
13535
- }
13433
+ body: failure("internal", "Verified Email OTP wallet identity is invalid")
13536
13434
  };
13537
13435
  let authorityResolution;
13538
13436
  try {
@@ -13545,20 +13443,12 @@ async function handleWalletUnlockVerifyRoute(input) {
13545
13443
  } catch (error) {
13546
13444
  return {
13547
13445
  status: 500,
13548
- body: {
13549
- ok: false,
13550
- code: "internal",
13551
- message: error instanceof Error ? error.message : "Email OTP authority resolution failed"
13552
- }
13446
+ body: failure("internal", error instanceof Error ? error.message : "Email OTP authority resolution failed")
13553
13447
  };
13554
13448
  }
13555
13449
  if (authorityResolution.kind === "rejected") return {
13556
13450
  status: authorityResolution.code === "internal" ? 500 : 403,
13557
- body: {
13558
- ok: false,
13559
- code: authorityResolution.code,
13560
- message: authorityResolution.message
13561
- }
13451
+ body: failure(authorityResolution.code, authorityResolution.message)
13562
13452
  };
13563
13453
  const exactEmailOtpAuthority = authorityResolution;
13564
13454
  if (planWalletUnlockAuthorityEcdsaSession({
@@ -13592,11 +13482,7 @@ async function handleWalletUnlockVerifyRoute(input) {
13592
13482
  } catch (error) {
13593
13483
  return {
13594
13484
  status: 403,
13595
- body: {
13596
- ok: false,
13597
- code: "owner_proof_rejected",
13598
- message: error instanceof Error ? error.message : "Email OTP owner proof is invalid"
13599
- }
13485
+ body: failure("owner_proof_rejected", error instanceof Error ? error.message : "Email OTP owner proof is invalid")
13600
13486
  };
13601
13487
  }
13602
13488
  let walletSessionState = { kind: "absent" };
@@ -13604,11 +13490,7 @@ async function handleWalletUnlockVerifyRoute(input) {
13604
13490
  const walletId = parseWalletId(result.walletId);
13605
13491
  if (!walletId.ok) return {
13606
13492
  status: 500,
13607
- body: {
13608
- ok: false,
13609
- code: "internal",
13610
- message: "Verified Email OTP wallet identity is invalid"
13611
- }
13493
+ body: failure("internal", "Verified Email OTP wallet identity is invalid")
13612
13494
  };
13613
13495
  let sessionResolution;
13614
13496
  try {
@@ -13623,11 +13505,7 @@ async function handleWalletUnlockVerifyRoute(input) {
13623
13505
  } catch (error) {
13624
13506
  return {
13625
13507
  status: 500,
13626
- body: {
13627
- ok: false,
13628
- code: "internal",
13629
- message: error instanceof Error ? error.message : "Email OTP Wallet Session issuance failed"
13630
- }
13508
+ body: failure("internal", error instanceof Error ? error.message : "Email OTP Wallet Session issuance failed")
13631
13509
  };
13632
13510
  }
13633
13511
  switch (sessionResolution.kind) {
@@ -13645,11 +13523,7 @@ async function handleWalletUnlockVerifyRoute(input) {
13645
13523
  case "wallet_registration": break;
13646
13524
  case "rejected": return {
13647
13525
  status: walletUnlockIssuanceRejectionStatus(sessionResolution),
13648
- body: {
13649
- ok: false,
13650
- code: sessionResolution.code,
13651
- message: sessionResolution.message
13652
- }
13526
+ body: failure(sessionResolution.code, sessionResolution.message)
13653
13527
  };
13654
13528
  }
13655
13529
  }
@@ -13699,11 +13573,7 @@ async function handleWalletUnlockVerifyRoute(input) {
13699
13573
  });
13700
13574
  if (!isWalletUnlockEd25519YaoRequestedContext(input.capabilityContext)) return {
13701
13575
  status: 400,
13702
- body: {
13703
- ok: false,
13704
- code: "invalid_body",
13705
- message: "Email OTP capability context is invalid"
13706
- }
13576
+ body: failure("invalid_body", "Email OTP capability context is invalid")
13707
13577
  };
13708
13578
  const capabilityResult = await provisionEmailOtpEd25519YaoCapability({
13709
13579
  context: input.capabilityContext,
@@ -13742,7 +13612,6 @@ const ECDSA_TIMING_METRICS = new Set([
13742
13612
  "ecdsa_sign_proxy",
13743
13613
  "ecdsa_sign_complete",
13744
13614
  "ecdsa_sign_total",
13745
- "ecdsa_presign_queue",
13746
13615
  "ecdsa_presign_authenticate",
13747
13616
  "ecdsa_presign_material",
13748
13617
  "ecdsa_presign_admit",
@@ -13831,6 +13700,7 @@ async function evaluateRouterAbNormalSigningAdmission(input) {
13831
13700
  });
13832
13701
  return await input.adapter.evaluatePolicy({
13833
13702
  curve: "ecdsa",
13703
+ policyReadSource: input.policyReadSource,
13834
13704
  phase: input.phase,
13835
13705
  walletId: input.walletId,
13836
13706
  materialActivationId: requireMpcMaterialActivationId(input.admission.materialActivation.activation_id),
@@ -14104,6 +13974,7 @@ async function authenticateRouterAbWalletOperationStepUpIdentity(input) {
14104
13974
  if (admission.curve === "ecdsa" && input.keyFamily === "ecdsa_secp256k1") {
14105
13975
  const active = ecdsaStepUpActiveMaterial({
14106
13976
  activeMaterial: await input.resolveEcdsaMaterialActivation({
13977
+ source: { kind: "database" },
14107
13978
  walletId: input.walletId,
14108
13979
  materialActivation: admittedMaterialActivation
14109
13980
  }),
@@ -14546,7 +14417,7 @@ async function buildRouterAbEd25519PrivateSigningWorkerBody(input) {
14546
14417
  const scope = parseRouterAbEd25519NormalSigningScopeV2(input.body.scope);
14547
14418
  const signingContext = privateSigningAuthorizationContext(scope, input.authorization);
14548
14419
  const trustedSourceDigest = await privateSigningTrustedSourceDigest(input.headers);
14549
- const materialSource = input.materialSource ?? registrationMaterialSourceV1({
14420
+ const materialSource = registrationMaterialSourceV1({
14550
14421
  accountId: scope.account_id,
14551
14422
  materialActivationId: scope.material_activation.activation_id,
14552
14423
  signingWorkerId: scope.signing_worker_id
@@ -14663,6 +14534,7 @@ async function resolveRouterAbEcdsaOwnerOperationStepUpPreparation(input) {
14663
14534
  const walletId = parseWalletId(request.scope.wallet_id);
14664
14535
  if (!walletId.ok) return void 0;
14665
14536
  const activeMaterial = await input.resolveEcdsaMaterialActivation({
14537
+ source: { kind: "database" },
14666
14538
  walletId: walletId.value,
14667
14539
  materialActivation: request.material_activation
14668
14540
  });
@@ -14763,6 +14635,7 @@ function routerAbWalletSessionError(code) {
14763
14635
  */
14764
14636
  async function resolveFreshRouterAbEcdsaMaterialActivation(input) {
14765
14637
  const resolved = await input.resolveEcdsaMaterialActivation({
14638
+ source: { kind: "database" },
14766
14639
  walletId: input.walletId,
14767
14640
  materialActivation: input.expected
14768
14641
  });
@@ -14782,15 +14655,7 @@ async function resolveFreshRouterAbEcdsaMaterialActivation(input) {
14782
14655
  };
14783
14656
  }
14784
14657
  function validateRouterAbEcdsaV2NormalSigningRequestForSession(input) {
14785
- let request;
14786
- try {
14787
- request = parseRouterAbEcdsaOperationStepUpRequest(input);
14788
- } catch (error) {
14789
- return {
14790
- ok: false,
14791
- error: routerAbStepUpError(400, "invalid_body", routerAbErrorMessage(error))
14792
- };
14793
- }
14658
+ const request = input.request;
14794
14659
  if (request.authorization.kind !== "reusable_wallet_session" || request.authorization.wallet_session_id !== input.session.walletSessionId || request.scope.wallet_id !== String(input.session.walletId) || request.material_activation.material_owner !== String(input.session.walletId) || request.material_activation.signing_worker !== request.scope.signing_worker.server_id || !sameRouterAbMpcMaterialActivationRef(request.material_activation, request.scope.material_activation) || !sameRouterAbMpcMaterialActivationRef(request.material_activation, input.admittedMaterialActivation)) return {
14795
14660
  ok: false,
14796
14661
  error: routerAbWalletSessionError(WALLET_SESSION_FAILURE_CODES.scopeMismatch)
@@ -14819,7 +14684,7 @@ function validateRouterAbEcdsaV2NormalSigningRequestForSession(input) {
14819
14684
  };
14820
14685
  }
14821
14686
  async function admitRouterAbEcdsaReusableWalletSessionOperation(input) {
14822
- if (typeof input.authorizedOperations.admitEcdsaWalletSessionOperation !== "function") return {
14687
+ if (typeof input.authorizedOperations.admitEcdsaWalletSessionOperation !== "function" || typeof input.authorizedOperations.resolveEcdsaWalletSessionOperation !== "function") return {
14823
14688
  ok: false,
14824
14689
  error: routerAbStepUpError(501, "not_configured", "ECDSA atomic authorization is not configured")
14825
14690
  };
@@ -14829,7 +14694,7 @@ async function admitRouterAbEcdsaReusableWalletSessionOperation(input) {
14829
14694
  };
14830
14695
  const nowMs = Date.now();
14831
14696
  try {
14832
- const session = input.binding.kind === "wallet_session_operation_credential_v1" ? input.binding.context.authorization.session : input.binding.candidate.status.session;
14697
+ const session = input.binding.kind === "wallet_session_operation_credential_v1" ? input.binding.validated.admission.context.authorization.session : input.binding.candidate.status.session;
14833
14698
  const tenantId = session.tenantId;
14834
14699
  const principalId = session.principalId;
14835
14700
  const walletId = session.walletId;
@@ -14840,16 +14705,12 @@ async function admitRouterAbEcdsaReusableWalletSessionOperation(input) {
14840
14705
  ok: false,
14841
14706
  error: routerAbStepUpError(403, "wallet_session_mismatch", "Reusable Wallet Session identity does not match")
14842
14707
  };
14843
- const freshMaterial = await resolveFreshRouterAbEcdsaMaterialActivation({
14844
- resolveEcdsaMaterialActivation: input.resolveEcdsaMaterialActivation,
14845
- walletId: String(walletId),
14846
- expected: input.materialActivation
14847
- });
14848
- if (!freshMaterial.ok) return {
14708
+ const material = input.material;
14709
+ if (!sameRouterAbMpcMaterialActivationRef(material.materialActivation, input.request.material_activation)) return {
14849
14710
  ok: false,
14850
- error: routerAbStepUpError(freshMaterial.code === "internal" ? 500 : 403, freshMaterial.code === "internal" ? "internal" : "wallet_session_mismatch", freshMaterial.message)
14711
+ error: routerAbStepUpError(403, "material_mismatch", "Signing material does not match the request")
14851
14712
  };
14852
- const capabilityId = requireAuthorizationValue$2(parseCapabilityId(freshMaterial.materialActivation.capability));
14713
+ const capabilityId = requireAuthorizationValue$2(parseCapabilityId(material.materialActivation.capability));
14853
14714
  const operationId = requireAuthorizationValue$2(parseCapabilityOperationId(input.request.operation_id));
14854
14715
  const envelope = buildCapabilityOperationEnvelope({
14855
14716
  tenantId,
@@ -14863,13 +14724,11 @@ async function admitRouterAbEcdsaReusableWalletSessionOperation(input) {
14863
14724
  displayDigest: parseDigestB64u(input.request.operation_digests.display_digest_b64u)
14864
14725
  }
14865
14726
  });
14866
- const authorizedOperationId = requireAuthorizationValue$2(parseAuthorizedOperationId(`ecdsa-authorized-operation:${operationId}:${input.request.request_id}`));
14867
- const auditEventId = requireAuthorizationValue$2(parseAuthorizationAuditEventId(`ecdsa-operation-audit:${operationId}`));
14868
- const outcome = await input.authorizedOperations.admitEcdsaWalletSessionOperation({
14727
+ const admissionInput = {
14869
14728
  operation: {
14870
14729
  tenantId,
14871
- authorizedOperationId,
14872
- auditEventId,
14730
+ authorizedOperationId: requireAuthorizationValue$2(parseAuthorizedOperationId(`ecdsa-authorized-operation:${operationId}:${input.request.request_id}`)),
14731
+ auditEventId: requireAuthorizationValue$2(parseAuthorizationAuditEventId(`ecdsa-operation-audit:${operationId}`)),
14873
14732
  operation: envelope,
14874
14733
  authorization: {
14875
14734
  kind: "authorization_grant",
@@ -14882,12 +14741,35 @@ async function admitRouterAbEcdsaReusableWalletSessionOperation(input) {
14882
14741
  claimedAtMs: nowMs
14883
14742
  },
14884
14743
  material: {
14744
+ readSnapshot: material.readSnapshot,
14885
14745
  walletId,
14886
- keyHandle: freshMaterial.keyHandle,
14887
- runtimePolicyScope: freshMaterial.runtimePolicyScope,
14888
- materialActivation: freshMaterial.materialActivation
14746
+ keyHandle: material.keyHandle,
14747
+ runtimePolicyScope: material.runtimePolicyScope,
14748
+ materialActivation: material.materialActivation
14889
14749
  }
14890
- });
14750
+ };
14751
+ if (input.phase === "finalize") {
14752
+ const resolved = await input.authorizedOperations.resolveEcdsaWalletSessionOperation(admissionInput);
14753
+ if (resolved.kind === "authorized_operation_missing") return {
14754
+ ok: false,
14755
+ error: routerAbStepUpError(409, resolved.kind, "ECDSA finalize requires a claimed prepare operation")
14756
+ };
14757
+ const failure = routerAbReusableWalletSessionClaimFailure(resolved);
14758
+ if (failure) return {
14759
+ ok: false,
14760
+ error: failure
14761
+ };
14762
+ if (resolved.kind === "operation_in_progress" || resolved.kind === "replayed") return {
14763
+ ok: true,
14764
+ phase: "finalize",
14765
+ admission: resolved
14766
+ };
14767
+ return {
14768
+ ok: false,
14769
+ error: routerAbStepUpError(409, resolved.kind, "Authorized operation is unavailable")
14770
+ };
14771
+ }
14772
+ const outcome = await input.authorizedOperations.admitEcdsaWalletSessionOperation(admissionInput);
14891
14773
  const claimFailure = routerAbReusableWalletSessionClaimFailure(outcome);
14892
14774
  if (claimFailure) return {
14893
14775
  ok: false,
@@ -14895,6 +14777,7 @@ async function admitRouterAbEcdsaReusableWalletSessionOperation(input) {
14895
14777
  };
14896
14778
  if (outcome.kind === "claimed" || outcome.kind === "operation_in_progress" || outcome.kind === "replayed") return {
14897
14779
  ok: true,
14780
+ phase: "prepare",
14898
14781
  admission: outcome
14899
14782
  };
14900
14783
  return {
@@ -14940,6 +14823,10 @@ async function authorizeRouterAbEcdsaWalletSessionRequest(input) {
14940
14823
  result: validated.error
14941
14824
  };
14942
14825
  const activeMaterial = await input.resolveEcdsaMaterialActivation({
14826
+ source: {
14827
+ kind: "credential_snapshot",
14828
+ materialRead: input.materialRead
14829
+ },
14943
14830
  walletId: String(input.session.walletId),
14944
14831
  materialActivation: validated.admission.materialActivation
14945
14832
  });
@@ -14957,6 +14844,10 @@ async function authorizeRouterAbEcdsaWalletSessionRequest(input) {
14957
14844
  result: routerAbStepUpError(403, "wallet_session_scope_mismatch", "Wallet Session V2 scope does not match the active material")
14958
14845
  };
14959
14846
  const admissionDecision = await evaluateRouterAbNormalSigningAdmission({
14847
+ policyReadSource: {
14848
+ kind: "credential_snapshot",
14849
+ policyRead: input.policyRead
14850
+ },
14960
14851
  adapter: input.admissionAdapter,
14961
14852
  curve: "ecdsa",
14962
14853
  authorizationKind: "wallet_session_operation_credential_v1",
@@ -14991,29 +14882,21 @@ async function authorizeRouterAbEcdsaWalletSessionRequest(input) {
14991
14882
  };
14992
14883
  }
14993
14884
  async function resolveRouterAbEcdsaExhaustedCandidateAuthorization(input) {
14994
- const token = extractBearerCredential(input.headers);
14995
- if (!token) return null;
14996
- const exhausted = await readExhaustedWalletSessionCandidate({
14997
- authorizationSessions: input.authorizationSessions,
14998
- token,
14999
- operation: {
15000
- keyFamily: "ecdsa_secp256k1",
15001
- operationKind: "evm.sign_transaction"
15002
- }
14885
+ const candidate = input.candidate;
14886
+ const session = candidate.status.session;
14887
+ const admission = walletSessionCandidateAdmission(session, candidate, {
14888
+ keyFamily: "ecdsa_secp256k1",
14889
+ operationKind: "evm.sign_transaction"
15003
14890
  });
15004
- if (!exhausted) return null;
15005
- if (!exhausted.ok) return {
15006
- ok: false,
15007
- result: exhausted.error
15008
- };
15009
- const { candidate, session, admission } = exhausted;
15010
14891
  if (!admission.ok || admission.keyFamily !== "ecdsa_secp256k1") return {
15011
14892
  ok: false,
15012
14893
  result: routerAbWalletSessionError(WALLET_SESSION_FAILURE_CODES.scopeMismatch)
15013
14894
  };
15014
14895
  const authorized = await authorizeRouterAbEcdsaWalletSessionRequest({
14896
+ materialRead: input.materialRead,
14897
+ policyRead: input.policyRead,
15015
14898
  phase: input.phase,
15016
- body: input.body,
14899
+ request: input.request,
15017
14900
  session,
15018
14901
  admittedMaterialActivation: routerAbMpcMaterialActivationRefToWire(admission.materialActivation),
15019
14902
  admissionAdapter: input.admissionAdapter,
@@ -15066,6 +14949,7 @@ async function authenticateRouterAbEcdsaOperationStepUp(input) {
15066
14949
  let resolvedMaterial;
15067
14950
  try {
15068
14951
  resolvedMaterial = await input.resolveEcdsaMaterialActivation({
14952
+ source: { kind: "database" },
15069
14953
  walletId: scope.wallet_id,
15070
14954
  materialActivation: admittedMaterialActivation
15071
14955
  });
@@ -15173,6 +15057,7 @@ async function handleRouterAbEcdsaOperationStepUpRoute(input) {
15173
15057
  const materialActivationId = requireMpcMaterialActivationId(activeMaterial.materialActivation.activation_id);
15174
15058
  if (!input.admissionAdapter) return routerAbStepUpError(501, "not_configured", "Router A/B ECDSA operation step-up admission is not configured");
15175
15059
  const admission = await input.admissionAdapter.evaluatePolicy({
15060
+ policyReadSource: { kind: "database" },
15176
15061
  curve: "ecdsa",
15177
15062
  phase: input.phase,
15178
15063
  walletId: authenticated.session.walletId,
@@ -15222,19 +15107,19 @@ async function handleRouterAbEcdsaOperationStepUpRoute(input) {
15222
15107
  };
15223
15108
  }
15224
15109
  async function authorizeRouterAbEcdsaDerivationNormalSigningRoute(input) {
15225
- let requestedAuthorizationKind;
15110
+ let parsedRequest;
15226
15111
  try {
15227
- requestedAuthorizationKind = parseRouterAbEcdsaOperationStepUpRequest({
15112
+ parsedRequest = parseRouterAbEcdsaOperationStepUpRequest({
15228
15113
  phase: input.phase,
15229
15114
  body: input.body
15230
- }).authorization.kind;
15115
+ });
15231
15116
  } catch (error) {
15232
15117
  return {
15233
15118
  ok: false,
15234
15119
  result: routerAbStepUpError(400, "invalid_body", routerAbErrorMessage(error))
15235
15120
  };
15236
15121
  }
15237
- if (requestedAuthorizationKind === "operation_step_up") {
15122
+ if (parsedRequest.authorization.kind === "operation_step_up") {
15238
15123
  const stepUp = await handleRouterAbEcdsaOperationStepUpRoute({
15239
15124
  body: input.body,
15240
15125
  headers: input.headers,
@@ -15258,22 +15143,12 @@ async function authorizeRouterAbEcdsaDerivationNormalSigningRoute(input) {
15258
15143
  };
15259
15144
  }
15260
15145
  const validated = await validateRouterAbEcdsaDerivationWalletSessionInputs({
15146
+ materialActivation: parsedRequest.material_activation,
15261
15147
  headers: input.headers,
15262
15148
  authorizationSessions: input.authorizationSessions,
15263
15149
  operationKind: "evm.sign_transaction"
15264
15150
  });
15265
15151
  if (!validated.ok) {
15266
- if (validated.code === "wallet_session_unavailable" && input.authorizationSessions) {
15267
- const exhaustedCandidate = await resolveRouterAbEcdsaExhaustedCandidateAuthorization({
15268
- phase: input.phase,
15269
- body: input.body,
15270
- headers: input.headers,
15271
- authorizationSessions: input.authorizationSessions,
15272
- admissionAdapter: input.admissionAdapter,
15273
- resolveEcdsaMaterialActivation: input.resolveEcdsaMaterialActivation
15274
- });
15275
- if (exhaustedCandidate) return exhaustedCandidate;
15276
- }
15277
15152
  const stepUp = await resolveRouterAbEcdsaOwnerOperationStepUpPreparation({
15278
15153
  body: input.body,
15279
15154
  phase: input.phase,
@@ -15290,10 +15165,21 @@ async function authorizeRouterAbEcdsaDerivationNormalSigningRoute(input) {
15290
15165
  })
15291
15166
  };
15292
15167
  }
15168
+ if (validated.kind === "wallet_session_operation_credential_exhausted_candidate_v1") return await resolveRouterAbEcdsaExhaustedCandidateAuthorization({
15169
+ materialRead: validated.materialRead,
15170
+ policyRead: validated.policyRead,
15171
+ phase: input.phase,
15172
+ request: parsedRequest,
15173
+ candidate: validated.candidate,
15174
+ admissionAdapter: input.admissionAdapter,
15175
+ resolveEcdsaMaterialActivation: input.resolveEcdsaMaterialActivation
15176
+ });
15293
15177
  const session = validated.admission.context.authorization.session;
15294
15178
  const authorized = await authorizeRouterAbEcdsaWalletSessionRequest({
15179
+ materialRead: validated.materialRead,
15180
+ policyRead: validated.policyRead,
15295
15181
  phase: input.phase,
15296
- body: input.body,
15182
+ request: parsedRequest,
15297
15183
  session,
15298
15184
  admittedMaterialActivation: routerAbMpcMaterialActivationRefToWire(validated.admission.admission.materialActivation),
15299
15185
  admissionAdapter: input.admissionAdapter,
@@ -15445,6 +15331,164 @@ function parseRouterAbEcdsaDerivationPoolFillStepRouteRequest(raw) {
15445
15331
  };
15446
15332
  }
15447
15333
  //#endregion
15334
+ //#region src/router/transport/fetch/routes/ecdsaOperationStepUpFactor.ts
15335
+ async function verifyEcdsaOperationStepUpFactor(input) {
15336
+ const proof = input.proof;
15337
+ switch (proof.kind) {
15338
+ case "passkey": {
15339
+ if (input.authSource.kind !== "passkey" || proof.authority.factor.credentialIdB64u !== input.authSource.credentialIdB64u) return {
15340
+ ok: false,
15341
+ response: json$1({
15342
+ ok: false,
15343
+ code: "scope_mismatch",
15344
+ message: "Passkey authority changed"
15345
+ }, { status: 403 })
15346
+ };
15347
+ const credential = proof.webauthn_authentication;
15348
+ if (String(credential.rawId || credential.id).trim() !== input.authSource.credentialIdB64u) return {
15349
+ ok: false,
15350
+ response: json$1({
15351
+ ok: false,
15352
+ code: "unauthorized",
15353
+ message: "Passkey credential changed"
15354
+ }, { status: 401 })
15355
+ };
15356
+ const verified = await input.webAuthn.verifyWebAuthnAuthenticationLite({
15357
+ userId: input.walletId,
15358
+ rpId: proof.authority.verifier.rpId,
15359
+ expectedChallenge: input.expectedChallenge,
15360
+ expected_origin: input.requestOrigin,
15361
+ webauthn_authentication: credential
15362
+ });
15363
+ if (!verified.success || !verified.verified) return {
15364
+ ok: false,
15365
+ response: json$1({
15366
+ ok: false,
15367
+ code: verified.code || "not_verified",
15368
+ message: verified.message || "WebAuthn authentication verification failed"
15369
+ }, { status: 401 })
15370
+ };
15371
+ const assertionDigest = parseDigestB64u(base64UrlEncode(await sha256BytesUtf8(alphabetizeStringify(credential))));
15372
+ const verifiedAtMs = Date.now();
15373
+ if (input.expiresAtMs <= verifiedAtMs) return expiredStepUpFactor();
15374
+ const factorId = parseAuthFactorId(`passkey:${input.authSource.credentialIdB64u}`);
15375
+ if (!factorId.ok) throw new Error(factorId.error.message);
15376
+ return {
15377
+ ok: true,
15378
+ factor: buildVerifiedWalletOperationPasskeyFactorResult({
15379
+ tenantId: input.operation.tenantId,
15380
+ principalId: input.operation.principalId,
15381
+ walletId: input.walletId,
15382
+ requestOrigin: input.requestOrigin,
15383
+ audience: input.requestOrigin,
15384
+ factorId: factorId.value,
15385
+ authorityRef: input.authorityRef,
15386
+ operation: input.operation,
15387
+ credentialIdB64u: proof.authority.factor.credentialIdB64u,
15388
+ assertionDigest,
15389
+ verifiedAtMs,
15390
+ expiresAtMs: input.expiresAtMs
15391
+ }),
15392
+ unseal: { kind: "not_requested" }
15393
+ };
15394
+ }
15395
+ case "email_otp": {
15396
+ const isExport = input.operation.operation.operationKind === "evm.export_key";
15397
+ const emailOtpOperation = isExport ? WALLET_EMAIL_OTP_EXPORT_OPERATION : WALLET_EMAIL_OTP_TRANSACTION_SIGN_OPERATION;
15398
+ const operationBinding = await hashEmailOtpOperationBinding({
15399
+ walletId: input.walletId,
15400
+ providerUserId: proof.authority.factor.providerUserId,
15401
+ orgId: input.operation.tenantId,
15402
+ operation: emailOtpOperation,
15403
+ requestOrigin: input.requestOrigin,
15404
+ audience: input.requestOrigin,
15405
+ authorityRef: input.authorityRef,
15406
+ ...isExport ? {} : { operationFingerprintDigest: input.operation.digests.laneDigest }
15407
+ });
15408
+ const verified = await input.emailOtp.verifyEmailOtpChallenge({
15409
+ userId: proof.authority.factor.providerUserId,
15410
+ walletId: input.walletId,
15411
+ orgId: input.operation.tenantId,
15412
+ challengeId: proof.challenge_id,
15413
+ otpCode: proof.otp_code,
15414
+ otpChannel: EMAIL_OTP_CHANNEL,
15415
+ ownerProofBindingDigest: operationBinding,
15416
+ operation: emailOtpOperation
15417
+ });
15418
+ if (!verified.ok) return {
15419
+ ok: false,
15420
+ response: json$1(verified, { status: verified.code === "invalid_body" ? 400 : 401 })
15421
+ };
15422
+ let verifiedChallengeId = verified.challengeId;
15423
+ if (!isExport) {
15424
+ const orgId = parseOrgId(input.operation.tenantId);
15425
+ const providerSubject = parseProviderSubject(proof.authority.factor.providerUserId);
15426
+ if (!orgId.ok) throw new Error(orgId.error.message);
15427
+ if (!providerSubject.ok) throw new Error(providerSubject.error.message);
15428
+ const consumed = await input.emailOtp.consumeEmailOtpGrant({
15429
+ subject: {
15430
+ kind: "provider_identity",
15431
+ orgId: orgId.value,
15432
+ providerSubject: providerSubject.value,
15433
+ walletId: input.walletId
15434
+ },
15435
+ loginGrant: verified.loginGrant,
15436
+ otpChannel: EMAIL_OTP_CHANNEL
15437
+ });
15438
+ if (!consumed.ok) return {
15439
+ ok: false,
15440
+ response: json$1(consumed, { status: consumed.code === "invalid_body" ? 400 : 401 })
15441
+ };
15442
+ verifiedChallengeId = consumed.challengeId;
15443
+ }
15444
+ const verificationReceiptDigest = parseDigestB64u(base64UrlEncode(await sha256BytesUtf8(alphabetizeStringify({
15445
+ challengeId: verifiedChallengeId,
15446
+ operationFingerprint: input.expectedChallenge
15447
+ }))));
15448
+ const verifiedAtMs = Date.now();
15449
+ const expiresAtMs = Math.min(input.expiresAtMs, verified.grantExpiresAtMs);
15450
+ if (expiresAtMs <= verifiedAtMs) return expiredStepUpFactor();
15451
+ const factorId = parseAuthFactorId(`email_otp:${proof.authority.factor.provider}:${proof.authority.factor.providerUserId}`);
15452
+ const challengeId = parseEmailOtpChallengeId(verifiedChallengeId);
15453
+ if (!factorId.ok) throw new Error(factorId.error.message);
15454
+ if (!challengeId.ok) throw new Error(challengeId.error.message);
15455
+ return {
15456
+ ok: true,
15457
+ factor: buildVerifiedWalletOperationEmailOtpFactorResult({
15458
+ tenantId: input.operation.tenantId,
15459
+ principalId: input.operation.principalId,
15460
+ walletId: input.walletId,
15461
+ requestOrigin: input.requestOrigin,
15462
+ audience: input.requestOrigin,
15463
+ factorId: factorId.value,
15464
+ authorityRef: input.authorityRef,
15465
+ operation: input.operation,
15466
+ challengeId: challengeId.value,
15467
+ verificationReceiptDigest,
15468
+ verifiedAtMs,
15469
+ expiresAtMs
15470
+ }),
15471
+ unseal: isExport ? {
15472
+ kind: "email_otp_grant",
15473
+ grant: verified.loginGrant,
15474
+ challenge_id: verified.challengeId
15475
+ } : { kind: "not_requested" }
15476
+ };
15477
+ }
15478
+ default: throw new Error("Unsupported ECDSA operation step-up proof");
15479
+ }
15480
+ }
15481
+ function expiredStepUpFactor() {
15482
+ return {
15483
+ ok: false,
15484
+ response: json$1({
15485
+ ok: false,
15486
+ code: "verified_step_up_rejected",
15487
+ message: "Operation step-up authorization expired"
15488
+ }, { status: 403 })
15489
+ };
15490
+ }
15491
+ //#endregion
15448
15492
  //#region ../shared-ts/src/signing-lanes/recordParsers.ts
15449
15493
  const WALLET_KEY_COMMON_FIELDS = [
15450
15494
  "kind",
@@ -15860,18 +15904,13 @@ async function executeRouterAbEcdsaDerivationNormalSigningRoute(input, timing) {
15860
15904
  binding: await ecdsaOperationStepUpBinding(input.ctx, authorization.session, authorizedOperation)
15861
15905
  });
15862
15906
  } else {
15907
+ const request = input.phase === "prepare" ? parseRouterAbEcdsaDerivationEvmDigestSigningRequestV1(input.body) : parseRouterAbEcdsaDerivationEvmDigestSigningFinalizeRequestV1(input.body);
15863
15908
  const operation = await admitRouterAbEcdsaReusableWalletSessionOperation({
15864
- request: input.phase === "prepare" ? parseRouterAbEcdsaDerivationEvmDigestSigningRequestV1(input.body) : parseRouterAbEcdsaDerivationEvmDigestSigningFinalizeRequestV1(input.body),
15865
- materialActivation: authorization.admission.materialActivation,
15866
- binding: authorization.kind === "wallet_session_operation_credential_v1" ? {
15867
- kind: "wallet_session_operation_credential_v1",
15868
- context: authorization.validated.admission.context
15869
- } : {
15870
- kind: "wallet_session_operation_credential_exhausted_candidate_v1",
15871
- candidate: authorization.candidate
15872
- },
15873
- authorizedOperations: input.ctx.service.authorizedOperations,
15874
- resolveEcdsaMaterialActivation: input.ctx.service.walletRegistration.resolveEcdsaMaterialActivation.bind(input.ctx.service.walletRegistration)
15909
+ phase: input.phase,
15910
+ request,
15911
+ material: authorization.activeMaterial,
15912
+ binding: authorization,
15913
+ authorizedOperations: input.ctx.service.authorizedOperations
15875
15914
  });
15876
15915
  if (!operation.ok) {
15877
15916
  const failureBody = operation.error.body;
@@ -15897,11 +15936,6 @@ async function executeRouterAbEcdsaDerivationNormalSigningRoute(input, timing) {
15897
15936
  return json$1(failure.body, { status: failure.status });
15898
15937
  }
15899
15938
  if (operation.admission.kind === "replayed") return routerAbEcdsaReplayResponse(operation.admission.operation);
15900
- if (operation.admission.kind === "claimed" && input.phase === "finalize") return json$1({
15901
- ok: false,
15902
- code: "authorized_operation_missing",
15903
- message: "ECDSA finalize requires a claimed prepare operation"
15904
- }, { status: 409 });
15905
15939
  const ownerDecision = decideRouterAbEcdsaOwnerOperationAuthorization({ operation: operation.admission.operation });
15906
15940
  switch (ownerDecision.kind) {
15907
15941
  case "authorized": break;
@@ -16126,6 +16160,7 @@ async function issueEcdsaOperationStepUpAuthorization(input) {
16126
16160
  message: v2Resolution.message
16127
16161
  }, { status: 403 });
16128
16162
  const activeMaterial = v2Resolution.kind === "admitted" ? v2Resolution.activeMaterial : await input.ctx.service.walletRegistration.resolveEcdsaMaterialActivation({
16163
+ source: { kind: "database" },
16129
16164
  walletId: operation.wallet_id,
16130
16165
  materialActivation: operation.material_activation
16131
16166
  });
@@ -16215,7 +16250,6 @@ async function issueEcdsaOperationStepUpAuthorization(input) {
16215
16250
  }, { status: 400 });
16216
16251
  }
16217
16252
  const expectedChallenge = await computeRouterAbEcdsaOperationStepUpChallengeB64u(operation);
16218
- const nowMs = Date.now();
16219
16253
  const requestId = operation.operation_id;
16220
16254
  let freshMaterial;
16221
16255
  if (v2Resolution.kind === "admitted") {
@@ -16256,112 +16290,24 @@ async function issueEcdsaOperationStepUpAuthorization(input) {
16256
16290
  const evidenceSetId = requireAuthorizationValue$1(parseAuthorizationEvidenceSetId(`ecdsa-step-up-evidence-set:${requestId}`));
16257
16291
  const expiresAtMs = operation.expires_at_ms;
16258
16292
  const requestOrigin = authenticated.requestOrigin;
16259
- let emailOtpUnseal;
16260
- let factor;
16261
- switch (proof.kind) {
16262
- case "passkey": {
16263
- if (authenticated.session.laneAuthorization.authSource.kind !== "passkey" || proof.authority.factor.credentialIdB64u !== authenticated.session.laneAuthorization.authSource.credentialIdB64u) return json$1({
16264
- ok: false,
16265
- code: "scope_mismatch",
16266
- message: "Passkey authority changed"
16267
- }, { status: 403 });
16268
- const credential = proof.webauthn_authentication;
16269
- if (String(credential.rawId || credential.id).trim() !== authenticated.session.laneAuthorization.authSource.credentialIdB64u) return json$1({
16270
- ok: false,
16271
- code: "unauthorized",
16272
- message: "Passkey credential changed"
16273
- }, { status: 401 });
16274
- const verified = await input.ctx.service.webAuthn.verifyWebAuthnAuthenticationLite({
16275
- userId: authenticated.session.walletId,
16276
- rpId: proof.authority.verifier.rpId,
16277
- expectedChallenge,
16278
- expected_origin: requestOrigin,
16279
- webauthn_authentication: credential
16280
- });
16281
- if (!verified.success || !verified.verified) return json$1({
16282
- ok: false,
16283
- code: verified.code || "not_verified",
16284
- message: verified.message || "WebAuthn authentication verification failed"
16285
- }, { status: 401 });
16286
- factor = buildVerifiedWalletOperationPasskeyFactorResult({
16287
- tenantId: authenticated.session.tenantId,
16288
- principalId: authenticated.session.principalId,
16289
- walletId: walletIdFromString(authenticated.session.walletId),
16290
- requestOrigin,
16291
- audience: requestOrigin,
16292
- factorId: requireAuthorizationValue$1(parseAuthFactorId(`passkey:${authenticated.session.laneAuthorization.authSource.credentialIdB64u}`)),
16293
- authorityRef: authenticated.authorityRef,
16294
- operation: envelope,
16295
- credentialIdB64u: proof.authority.factor.credentialIdB64u,
16296
- assertionDigest: parseDigestB64u(base64UrlEncode(await sha256BytesUtf8(alphabetizeStringify(credential)))),
16297
- verifiedAtMs: nowMs,
16298
- expiresAtMs
16299
- });
16300
- break;
16301
- }
16302
- case "email_otp": {
16303
- const operationBinding = await hashEmailOtpOperationBinding({
16304
- walletId: authenticated.session.walletId,
16305
- providerUserId: proof.authority.factor.providerUserId,
16306
- orgId: authenticated.session.tenantId,
16307
- operation: operation.operation_kind === "evm.export_key" ? WALLET_EMAIL_OTP_EXPORT_OPERATION : WALLET_EMAIL_OTP_TRANSACTION_SIGN_OPERATION,
16308
- requestOrigin,
16309
- audience: requestOrigin,
16310
- authorityRef: authenticated.authorityRef,
16311
- ...operation.operation_kind === "evm.sign_transaction" ? { operationFingerprintDigest: envelope.digests.laneDigest } : {}
16312
- });
16313
- const verified = await input.ctx.service.emailOtp.verifyEmailOtpChallenge({
16314
- userId: proof.authority.factor.providerUserId,
16315
- walletId: authenticated.session.walletId,
16316
- orgId: authenticated.session.tenantId,
16317
- challengeId: proof.challenge_id,
16318
- otpCode: proof.otp_code,
16319
- otpChannel: EMAIL_OTP_CHANNEL,
16320
- ownerProofBindingDigest: operationBinding,
16321
- operation: operation.operation_kind === "evm.export_key" ? WALLET_EMAIL_OTP_EXPORT_OPERATION : WALLET_EMAIL_OTP_TRANSACTION_SIGN_OPERATION
16322
- });
16323
- if (!verified.ok) return json$1(verified, { status: verified.code === "invalid_body" ? 400 : 401 });
16324
- const consumed = operation.operation_kind === "evm.export_key" ? null : await input.ctx.service.emailOtp.consumeEmailOtpGrant({
16325
- subject: {
16326
- kind: "provider_identity",
16327
- orgId: requireAuthorizationValue$1(parseOrgId(authenticated.session.tenantId)),
16328
- providerSubject: requireAuthorizationValue$1(parseProviderSubject(proof.authority.factor.providerUserId)),
16329
- walletId: walletIdFromString(authenticated.session.walletId)
16330
- },
16331
- loginGrant: verified.loginGrant,
16332
- otpChannel: EMAIL_OTP_CHANNEL
16333
- });
16334
- if (consumed && !consumed.ok) return json$1(consumed, { status: consumed.code === "invalid_body" ? 400 : 401 });
16335
- if (operation.operation_kind === "evm.export_key") emailOtpUnseal = {
16336
- grant: verified.loginGrant,
16337
- challengeId: verified.challengeId
16338
- };
16339
- const verifiedChallengeId = consumed?.ok ? consumed.challengeId : verified.challengeId;
16340
- factor = buildVerifiedWalletOperationEmailOtpFactorResult({
16341
- tenantId: authenticated.session.tenantId,
16342
- principalId: authenticated.session.principalId,
16343
- walletId: walletIdFromString(authenticated.session.walletId),
16344
- requestOrigin,
16345
- audience: requestOrigin,
16346
- factorId: requireAuthorizationValue$1(parseAuthFactorId(`email_otp:${proof.authority.factor.provider}:${proof.authority.factor.providerUserId}`)),
16347
- authorityRef: authenticated.authorityRef,
16348
- operation: envelope,
16349
- challengeId: requireAuthorizationValue$1(parseEmailOtpChallengeId(verifiedChallengeId)),
16350
- verificationReceiptDigest: parseDigestB64u(base64UrlEncode(await sha256BytesUtf8(alphabetizeStringify({
16351
- challengeId: verifiedChallengeId,
16352
- operationFingerprint: expectedChallenge
16353
- })))),
16354
- verifiedAtMs: nowMs,
16355
- expiresAtMs: Math.min(expiresAtMs, verified.grantExpiresAtMs)
16356
- });
16357
- break;
16358
- }
16359
- }
16293
+ const verifiedFactor = await verifyEcdsaOperationStepUpFactor({
16294
+ proof,
16295
+ operation: envelope,
16296
+ walletId: walletIdFromString(authenticated.session.walletId),
16297
+ authorityRef: authenticated.authorityRef,
16298
+ authSource: authenticated.session.laneAuthorization.authSource,
16299
+ requestOrigin,
16300
+ expectedChallenge,
16301
+ expiresAtMs,
16302
+ webAuthn: input.ctx.service.webAuthn,
16303
+ emailOtp: input.ctx.service.emailOtp
16304
+ });
16305
+ if (!verifiedFactor.ok) return verifiedFactor.response;
16360
16306
  const evidenceSet = await input.ctx.service.authorizedOperations.recordVerifiedWalletOperationFactorEvidenceSet({
16361
16307
  operation: envelope,
16362
16308
  evidenceId,
16363
16309
  evidenceSetId,
16364
- factor
16310
+ factor: verifiedFactor.factor
16365
16311
  });
16366
16312
  const authorizedOperationId = requireAuthorizationValue$1(parseAuthorizedOperationId(`ecdsa-step-up-authorized-operation:${operation.operation_id}`));
16367
16313
  const atomicOperation = await input.ctx.service.authorizedOperations.admitAuthorizedOperation({
@@ -16375,7 +16321,7 @@ async function issueEcdsaOperationStepUpAuthorization(input) {
16375
16321
  evidenceSetDigest: evidenceSet.evidenceSetDigest
16376
16322
  },
16377
16323
  quota: { kind: "quota_neutral" },
16378
- claimedAtMs: nowMs
16324
+ claimedAtMs: Date.now()
16379
16325
  },
16380
16326
  material: {
16381
16327
  walletId: walletIdFromString(authenticated.session.walletId),
@@ -16408,11 +16354,7 @@ async function issueEcdsaOperationStepUpAuthorization(input) {
16408
16354
  const responseAuthorization = {
16409
16355
  kind: "operation_step_up",
16410
16356
  evidence_set_digest: evidenceSet.evidenceSetDigest,
16411
- unseal: emailOtpUnseal ? {
16412
- kind: "email_otp_grant",
16413
- grant: emailOtpUnseal.grant,
16414
- challenge_id: emailOtpUnseal.challengeId
16415
- } : { kind: "not_requested" }
16357
+ unseal: verifiedFactor.unseal
16416
16358
  };
16417
16359
  if (operation.operation_kind === "evm.export_key") {
16418
16360
  const exportTopology = v2Resolution.kind === "admitted" && v2Resolution.operationKind === "evm.export_key" ? v2Resolution.exportTopology : await resolveStrictEcdsaExportTopology({
@@ -16444,7 +16386,6 @@ async function issueEcdsaOperationStepUpAuthorization(input) {
16444
16386
  async function handleEcdsaPoolFillRoute(input) {
16445
16387
  const startedAt = performance.now();
16446
16388
  const timing = {
16447
- queue: null,
16448
16389
  authenticate: null,
16449
16390
  material: null,
16450
16391
  admit: null,
@@ -16479,31 +16420,24 @@ async function executeEcdsaPoolFillRoute(input, timing, workerTimings) {
16479
16420
  const parsed = input.phase === "init" ? parseRouterAbEcdsaDerivationPoolFillInitRouteRequest(input.body) : parseRouterAbEcdsaDerivationPoolFillStepRouteRequest(input.body);
16480
16421
  if (!parsed.ok) return json$1(parsed.body, { status: thresholdEcdsaStatusCode(parsed.body) });
16481
16422
  const request = parsed.request;
16482
- const queuedAt = performance.now();
16483
- const gateTicket = await presignPriorityGate.acquire(resolvePresignTrafficClass(request.requestTag));
16484
- timing.queue = performance.now() - queuedAt;
16485
- try {
16486
- const authorized = await authorizeEcdsaPoolFill({
16487
- ctx: input.ctx,
16488
- request,
16489
- timing
16490
- });
16491
- if (!authorized.ok) return json$1(authorized.error.body, { status: authorized.error.status });
16492
- const proxyStartedAt = performance.now();
16493
- const result = "poolFill" in request ? await runtime.initializePoolFill({
16494
- binding: authorized.binding,
16495
- request: ecdsaPoolFillInitRuntimeRequest(request),
16496
- onServerTiming: collectEcdsaPresignWorkerTiming.bind(void 0, workerTimings)
16497
- }) : await runtime.advancePoolFill({
16498
- binding: authorized.binding,
16499
- request: ecdsaPoolFillStepRuntimeRequest(request),
16500
- onServerTiming: collectEcdsaPresignWorkerTiming.bind(void 0, workerTimings)
16501
- });
16502
- timing.proxy = performance.now() - proxyStartedAt;
16503
- return json$1(result, { status: thresholdEcdsaStatusCode(result) });
16504
- } finally {
16505
- gateTicket.release();
16506
- }
16423
+ const authorized = await authorizeEcdsaPoolFill({
16424
+ ctx: input.ctx,
16425
+ request,
16426
+ timing
16427
+ });
16428
+ if (!authorized.ok) return json$1(authorized.error.body, { status: authorized.error.status });
16429
+ const proxyStartedAt = performance.now();
16430
+ const result = "poolFill" in request ? await runtime.initializePoolFill({
16431
+ binding: authorized.binding,
16432
+ request: ecdsaPoolFillInitRuntimeRequest(request),
16433
+ onServerTiming: collectEcdsaPresignWorkerTiming.bind(void 0, workerTimings)
16434
+ }) : await runtime.advancePoolFill({
16435
+ binding: authorized.binding,
16436
+ request: ecdsaPoolFillStepRuntimeRequest(request),
16437
+ onServerTiming: collectEcdsaPresignWorkerTiming.bind(void 0, workerTimings)
16438
+ });
16439
+ timing.proxy = performance.now() - proxyStartedAt;
16440
+ return json$1(result, { status: thresholdEcdsaStatusCode(result) });
16507
16441
  }
16508
16442
  function poolFillMaterialActivation(request) {
16509
16443
  return "poolFill" in request ? request.poolFill.scope.material_activation : null;
@@ -16642,6 +16576,7 @@ async function authorizeEcdsaPoolFill(input) {
16642
16576
  const admitted = validated;
16643
16577
  const materialStartedAt = performance.now();
16644
16578
  const activeMaterial = await input.ctx.service.walletRegistration.resolveEcdsaMaterialActivation({
16579
+ source: { kind: "database" },
16645
16580
  walletId: String(session.walletId),
16646
16581
  materialActivation: routerAbMpcMaterialActivationRefToWire(admitted.materialActivation)
16647
16582
  });
@@ -16730,43 +16665,6 @@ function ecdsaPoolFillStepRuntimeRequest(request) {
16730
16665
  ...request.requestTag === void 0 ? {} : { requestTag: request.requestTag }
16731
16666
  };
16732
16667
  }
16733
- function resolvePresignPriorityTurn(resolve) {
16734
- setTimeout(resolve, 5);
16735
- }
16736
- function waitForPresignPriorityTurn() {
16737
- return new Promise(resolvePresignPriorityTurn);
16738
- }
16739
- var PresignPriorityGate = class {
16740
- constructor() {
16741
- this.foregroundInFlight = 0;
16742
- this.backgroundInFlight = 0;
16743
- }
16744
- async acquire(trafficClass) {
16745
- if (trafficClass === "foreground") {
16746
- this.foregroundInFlight += 1;
16747
- return this.createTicket("foreground");
16748
- }
16749
- while (!this.canRunBackgroundNow()) await waitForPresignPriorityTurn();
16750
- this.backgroundInFlight += 1;
16751
- return this.createTicket("background");
16752
- }
16753
- createTicket(trafficClass) {
16754
- let released = false;
16755
- return { release: () => {
16756
- if (released) return;
16757
- released = true;
16758
- if (trafficClass === "foreground") this.foregroundInFlight = Math.max(0, this.foregroundInFlight - 1);
16759
- else this.backgroundInFlight = Math.max(0, this.backgroundInFlight - 1);
16760
- } };
16761
- }
16762
- canRunBackgroundNow() {
16763
- return this.foregroundInFlight === 0 && this.backgroundInFlight === 0;
16764
- }
16765
- };
16766
- function resolvePresignTrafficClass(requestTag) {
16767
- return requestTag === "background_presign_pool_refill" ? "background" : "foreground";
16768
- }
16769
- const presignPriorityGate = new PresignPriorityGate();
16770
16668
  function strictEcdsaAuthorizationFailureStatus(failure) {
16771
16669
  switch (failure.code) {
16772
16670
  case "unauthorized": return 401;
@@ -17149,6 +17047,7 @@ async function authorizeStrictEcdsaExport(input) {
17149
17047
  scope: operation.normal_signing_scope
17150
17048
  })) return strictEcdsaExportFailure(403, "scope_mismatch", "ECDSA export operation scope does not match the request");
17151
17049
  const activeMaterial = await input.ctx.service.walletRegistration.resolveEcdsaMaterialActivation({
17050
+ source: { kind: "database" },
17152
17051
  walletId: operation.wallet_id,
17153
17052
  materialActivation: input.request.material_activation
17154
17053
  });
@@ -17453,7 +17352,6 @@ async function handleThresholdEcdsa(ctx) {
17453
17352
  }
17454
17353
  //#endregion
17455
17354
  //#region src/router/domains/emailOtp/emailOtpRouteHandlers.ts
17456
- const EMAIL_OTP_FACTOR_RELEASE_AAD_DOMAIN = "seams/email-otp/factor-release/v1";
17457
17355
  function decodeEmailOtpFactorSecret32(value) {
17458
17356
  const magnitude = base64UrlDecode(value);
17459
17357
  if (magnitude.length === 0 || magnitude.length > 32) {
@@ -17467,7 +17365,7 @@ function decodeEmailOtpFactorSecret32(value) {
17467
17365
  }
17468
17366
  function emailOtpFactorReleaseAad(input) {
17469
17367
  return new TextEncoder().encode([
17470
- EMAIL_OTP_FACTOR_RELEASE_AAD_DOMAIN,
17368
+ EMAIL_OTP_FACTOR_RELEASE_AAD_DOMAIN_V1,
17471
17369
  input.walletId,
17472
17370
  input.enrollmentId,
17473
17371
  input.enrollmentSealKeyVersion,
@@ -17481,19 +17379,11 @@ async function sealEmailOtpFactorSecretForWorker(input) {
17481
17379
  factorSecret32 = decodeEmailOtpFactorSecret32(input.factorSecret32B64u);
17482
17380
  workerPublicKey65 = base64UrlDecode(input.workerEphemeralPublicKey65B64u);
17483
17381
  } catch {
17484
- return {
17485
- ok: false,
17486
- code: "invalid_body",
17487
- message: "Email OTP factor release key is invalid"
17488
- };
17382
+ return failure("invalid_body", "Email OTP factor release key is invalid");
17489
17383
  }
17490
17384
  if (workerPublicKey65.length !== 65 || workerPublicKey65[0] !== 4) {
17491
17385
  factorSecret32.fill(0);
17492
- return {
17493
- ok: false,
17494
- code: "invalid_body",
17495
- message: "Email OTP factor release key is invalid"
17496
- };
17386
+ return failure("invalid_body", "Email OTP factor release key is invalid");
17497
17387
  }
17498
17388
  try {
17499
17389
  const workerPublicKey = await crypto.subtle.importKey("raw", workerPublicKey65, {
@@ -17525,11 +17415,7 @@ async function sealEmailOtpFactorSecretForWorker(input) {
17525
17415
  ciphertextB64u: base64UrlEncode(ciphertext)
17526
17416
  };
17527
17417
  } catch {
17528
- return {
17529
- ok: false,
17530
- code: "factor_release_failed",
17531
- message: "Email OTP factor release encryption failed"
17532
- };
17418
+ return failure("factor_release_failed", "Email OTP factor release encryption failed");
17533
17419
  } finally {
17534
17420
  factorSecret32.fill(0);
17535
17421
  }
@@ -17541,11 +17427,7 @@ async function handleEmailOtpDevCleanupGoogleRegistrationRoute(input) {
17541
17427
  const code = verified.code || "not_verified";
17542
17428
  return {
17543
17429
  status: code === "internal" ? 500 : code === "not_configured" || code === "unsupported" ? 501 : code === "invalid_body" ? 400 : 401,
17544
- body: {
17545
- ok: false,
17546
- code,
17547
- message: verified.message || "Google login failed"
17548
- }
17430
+ body: failure(code, verified.message || "Google login failed")
17549
17431
  };
17550
17432
  }
17551
17433
  const runtimePolicyScope = isPlainObject(body.runtimePolicyScope) ? body.runtimePolicyScope : null;
@@ -17562,30 +17444,18 @@ async function handleEmailOtpDevCleanupGoogleRegistrationRoute(input) {
17562
17444
  async function handleEmailOtpRegistrationSealRoute(input) {
17563
17445
  if (!isPlainObject(input.body)) return {
17564
17446
  status: 400,
17565
- body: {
17566
- ok: false,
17567
- code: "invalid_body",
17568
- message: "Invalid body"
17569
- }
17447
+ body: failure("invalid_body", "Invalid body")
17570
17448
  };
17571
17449
  const allowedFields = new Set(["walletId", "wrappedCiphertext"]);
17572
17450
  for (const field of Object.keys(input.body)) if (!allowedFields.has(field)) return {
17573
17451
  status: 400,
17574
- body: {
17575
- ok: false,
17576
- code: "invalid_body",
17577
- message: `Unsupported field: ${field}`
17578
- }
17452
+ body: failure("invalid_body", `Unsupported field: ${field}`)
17579
17453
  };
17580
17454
  const walletId = normalizeOptionalTrimmedString(input.body.walletId);
17581
17455
  const wrappedCiphertext = normalizeOptionalTrimmedString(input.body.wrappedCiphertext);
17582
17456
  if (!walletId || !wrappedCiphertext) return {
17583
17457
  status: 400,
17584
- body: {
17585
- ok: false,
17586
- code: "invalid_body",
17587
- message: "Missing walletId or wrappedCiphertext"
17588
- }
17458
+ body: failure("invalid_body", "Missing walletId or wrappedCiphertext")
17589
17459
  };
17590
17460
  const result = await input.service.applyEmailOtpServerSeal({ wrappedCiphertext });
17591
17461
  return {
@@ -17599,11 +17469,7 @@ async function handleEmailOtpRegistrationSealRoute(input) {
17599
17469
  async function handleEmailOtpDevOutboxRoute(input) {
17600
17470
  if (!isPlainObject(input.body)) return {
17601
17471
  status: 400,
17602
- body: {
17603
- ok: false,
17604
- code: "invalid_body",
17605
- message: "Invalid body"
17606
- }
17472
+ body: failure("invalid_body", "Invalid body")
17607
17473
  };
17608
17474
  const allowedFields = new Set([
17609
17475
  "idToken",
@@ -17613,11 +17479,7 @@ async function handleEmailOtpDevOutboxRoute(input) {
17613
17479
  ]);
17614
17480
  for (const field of Object.keys(input.body)) if (!allowedFields.has(field)) return {
17615
17481
  status: 400,
17616
- body: {
17617
- ok: false,
17618
- code: "invalid_body",
17619
- message: `Unsupported field: ${field}`
17620
- }
17482
+ body: failure("invalid_body", `Unsupported field: ${field}`)
17621
17483
  };
17622
17484
  const idToken = normalizeOptionalTrimmedString(input.body.idToken);
17623
17485
  const walletId = normalizeOptionalTrimmedString(input.body.walletId);
@@ -17625,30 +17487,18 @@ async function handleEmailOtpDevOutboxRoute(input) {
17625
17487
  const challengeSubjectId = normalizeOptionalTrimmedString(input.body.challengeSubjectId);
17626
17488
  if (!idToken || !walletId) return {
17627
17489
  status: 400,
17628
- body: {
17629
- ok: false,
17630
- code: "invalid_body",
17631
- message: "Missing idToken or walletId"
17632
- }
17490
+ body: failure("invalid_body", "Missing idToken or walletId")
17633
17491
  };
17634
17492
  if (challengeSubjectId && !challengeId) return {
17635
17493
  status: 400,
17636
- body: {
17637
- ok: false,
17638
- code: "invalid_body",
17639
- message: "challengeSubjectId requires the exact challengeId it belongs to"
17640
- }
17494
+ body: failure("invalid_body", "challengeSubjectId requires the exact challengeId it belongs to")
17641
17495
  };
17642
17496
  const verified = await input.service.verifyGoogleLogin({ idToken });
17643
17497
  if (!verified.ok || !verified.verified || !verified.userId) {
17644
17498
  const code = verified.code || "not_verified";
17645
17499
  return {
17646
17500
  status: code === "internal" ? 500 : code === "not_configured" ? 501 : 401,
17647
- body: {
17648
- ok: false,
17649
- code,
17650
- message: verified.message || "Google login failed"
17651
- }
17501
+ body: failure(code, verified.message || "Google login failed")
17652
17502
  };
17653
17503
  }
17654
17504
  const result = await input.service.readEmailOtpOutboxEntry({
@@ -17894,6 +17744,7 @@ async function resolveWalletEmailOtpChallengeSignerSelection(args) {
17894
17744
  };
17895
17745
  }
17896
17746
  const resolved = await args.ctx.service.walletRegistration.resolveEcdsaMaterialActivation({
17747
+ source: { kind: "database" },
17897
17748
  walletId: String(args.authority.walletId),
17898
17749
  materialActivation: routerAbMpcMaterialActivationRefToWire(ecdsaActivation.materialActivation)
17899
17750
  });
@@ -19078,7 +18929,12 @@ function bootstrapError(code, message, status) {
19078
18929
  //#region src/router/transport/fetch/routes/syncAccount.ts
19079
18930
  function syncAccountResponseStatus(result) {
19080
18931
  if (result.ok && result.verified) return 200;
19081
- switch (result.code) {
18932
+ return syncAccountFailureStatus(result.code);
18933
+ }
18934
+ function syncAccountFailureStatus(code) {
18935
+ switch (code) {
18936
+ case "wallet_home_unavailable": return 503;
18937
+ case "wallet_home_conflict": return 409;
19082
18938
  case "internal": return 500;
19083
18939
  case "ed25519_not_provisioned": return 409;
19084
18940
  default: return 400;
@@ -19108,7 +18964,7 @@ async function handleSyncAccount(ctx) {
19108
18964
  const parsed = parseSyncAccountOptionsRequest(await readJson(ctx.request));
19109
18965
  if (!parsed.ok) return json$1(parsed.body, { status: parsed.status });
19110
18966
  const result = await ctx.service.webAuthn.createWebAuthnSyncAccountOptions(parsed.request);
19111
- return json$1(result, { status: result.ok ? 200 : result.code === "internal" ? 500 : 400 });
18967
+ return json$1(result, { status: result.ok ? 200 : syncAccountFailureStatus(result.code) });
19112
18968
  }
19113
18969
  if (ctx.pathname === "/sync-account/verify") {
19114
18970
  const parsed = parseSyncAccountVerifyRequest({
@@ -19120,11 +18976,7 @@ async function handleSyncAccount(ctx) {
19120
18976
  let responseBody = result;
19121
18977
  if (result.ok && result.verified && result.thresholdEd25519) {
19122
18978
  const custodyKeyManifestDigestB64u = result.custodyKeyManifestDigestB64u;
19123
- if (!custodyKeyManifestDigestB64u) return json$1({
19124
- ok: false,
19125
- code: "internal",
19126
- message: "Sync verification did not resolve the wallet key manifest"
19127
- }, { status: 500 });
18979
+ if (!custodyKeyManifestDigestB64u) return jsonFailure(500, "internal", "Sync verification did not resolve the wallet key manifest");
19128
18980
  const thresholdEd25519 = result.thresholdEd25519;
19129
18981
  const walletId = String(result.walletId || "").trim();
19130
18982
  const nearAccountId = String(result.nearAccountId || "").trim();
@@ -19132,11 +18984,7 @@ async function handleSyncAccount(ctx) {
19132
18984
  const signerSlot = Number(result.signerSlot);
19133
18985
  const walletBinding = result.walletBinding;
19134
18986
  const credentialIdB64u = String(result.credentialIdB64u || "").trim();
19135
- if (!thresholdEd25519 || !walletId || !nearAccountId || !nearEd25519SigningKeyId || !Number.isSafeInteger(signerSlot) || signerSlot < 1 || !walletBinding || !credentialIdB64u || !String(result.publicKey || "").trim() || !String(result.credentialPublicKeyB64u || "").trim() || String(walletBinding.walletId) !== walletId || String(walletBinding.nearAccountId) !== nearAccountId || String(walletBinding.nearEd25519SigningKeyId) !== nearEd25519SigningKeyId || walletBinding.signerSlot !== signerSlot) return json$1({
19136
- ok: false,
19137
- code: "internal",
19138
- message: "verified passkey wallet is missing its Ed25519 Yao identity"
19139
- }, { status: 500 });
18987
+ if (!thresholdEd25519 || !walletId || !nearAccountId || !nearEd25519SigningKeyId || !Number.isSafeInteger(signerSlot) || signerSlot < 1 || !walletBinding || !credentialIdB64u || !String(result.publicKey || "").trim() || !String(result.credentialPublicKeyB64u || "").trim() || String(walletBinding.walletId) !== walletId || String(walletBinding.nearAccountId) !== nearAccountId || String(walletBinding.nearEd25519SigningKeyId) !== nearEd25519SigningKeyId || walletBinding.signerSlot !== signerSlot) return jsonFailure(500, "internal", "verified passkey wallet is missing its Ed25519 Yao identity");
19140
18988
  const authority = passkeyWalletAuthAuthorityForMethod({
19141
18989
  walletId: walletBinding.walletId,
19142
18990
  rpId: walletBinding.rpId,
@@ -19148,29 +18996,17 @@ async function handleSyncAccount(ctx) {
19148
18996
  rpId: authority.verifier.rpId,
19149
18997
  credentialIdB64u: authority.factor.credentialIdB64u
19150
18998
  });
19151
- if (!activeAuthority.ok || activeAuthority.walletAuthority.authorityId !== result.walletAuthorityId || activeAuthority.authMethod.walletAuthMethodId !== result.walletAuthMethodId) return json$1({
19152
- ok: false,
19153
- code: "internal",
19154
- message: "Verified passkey wallet authority is unavailable"
19155
- }, { status: 500 });
18999
+ if (!activeAuthority.ok || activeAuthority.walletAuthority.authorityId !== result.walletAuthorityId || activeAuthority.authMethod.walletAuthMethodId !== result.walletAuthMethodId) return jsonFailure(500, "internal", "Verified passkey wallet authority is unavailable");
19156
19000
  const authorityRef = await walletAuthAuthorityRef({ authority });
19157
19001
  const principalId = parsePrincipalId(walletId);
19158
19002
  const mintId = parseWalletSessionMintId(parsed.request.challengeId);
19159
- if (!principalId.ok || !mintId.ok) return json$1({
19160
- ok: false,
19161
- code: "internal",
19162
- message: "Verified passkey Wallet Session identity is invalid"
19163
- }, { status: 500 });
19003
+ if (!principalId.ok || !mintId.ok) return jsonFailure(500, "internal", "Verified passkey Wallet Session identity is invalid");
19164
19004
  const issuedAtMs = Date.now();
19165
19005
  const expiresAtMs = issuedAtMs + DEFAULT_WALLET_SESSION_TTL_MS;
19166
19006
  const origin = parseSessionOrigin(parsed.request.expected_origin);
19167
19007
  const factorId = parseAuthFactorId(`passkey:${credentialIdB64u}`);
19168
19008
  const credentialId = parseWebAuthnCredentialIdB64u(credentialIdB64u);
19169
- if (!factorId.ok || !credentialId.ok) return json$1({
19170
- ok: false,
19171
- code: "internal",
19172
- message: "Verified passkey factor identity is invalid"
19173
- }, { status: 500 });
19009
+ if (!factorId.ok || !credentialId.ok) return jsonFailure(500, "internal", "Verified passkey factor identity is invalid");
19174
19010
  const proof = await ctx.service.authorizedOperations.buildVerifiedOwnerProof({
19175
19011
  purpose: "wallet_session",
19176
19012
  proofId: parseVerifiedOwnerProofId(`sync-account:${parsed.request.challengeId}`),
@@ -19188,11 +19024,7 @@ async function handleSyncAccount(ctx) {
19188
19024
  expiresAtMs
19189
19025
  })
19190
19026
  });
19191
- if (proof.purpose !== "wallet_session") return json$1({
19192
- ok: false,
19193
- code: "internal",
19194
- message: "Owner proof purpose is invalid"
19195
- }, { status: 500 });
19027
+ if (proof.purpose !== "wallet_session") return jsonFailure(500, "internal", "Owner proof purpose is invalid");
19196
19028
  const bootstrap = await issueSyncAccountBootstrapV1({
19197
19029
  ctx,
19198
19030
  result: {
@@ -19233,11 +19065,7 @@ async function handleSyncAccount(ctx) {
19233
19065
  message: "Wallet Session sync is already committed; retry the exact method",
19234
19066
  ...bootstrap.committed
19235
19067
  }, { status: 409 });
19236
- if (bootstrap.kind === "error") return json$1({
19237
- ok: false,
19238
- code: bootstrap.code,
19239
- message: bootstrap.message
19240
- }, { status: bootstrap.status });
19068
+ if (bootstrap.kind === "error") return jsonFailure(bootstrap.status, bootstrap.code, bootstrap.message);
19241
19069
  responseBody = bootstrap.body;
19242
19070
  }
19243
19071
  return json$1(responseBody, { status: syncAccountResponseStatus(result) });
@@ -21780,11 +21608,13 @@ async function handleOwnerWalletExecutionLanePreflight(ctx) {
21780
21608
  };
21781
21609
  } else {
21782
21610
  const validated = await validateRouterAbEcdsaDerivationWalletSessionInputs({
21611
+ materialActivation: routerAbMpcMaterialActivationRefToWire(request.expectedMaterialActivation),
21783
21612
  headers,
21784
21613
  authorizationSessions: ctx.service.authorizationSessions,
21785
21614
  operationKind: EVM_ECDSA_MPC_OPERATION_KINDS.signTransaction
21786
21615
  });
21787
21616
  if (!validated.ok) return validationFailure(validated);
21617
+ if (validated.kind === "wallet_session_operation_credential_exhausted_candidate_v1") return validationFailure(walletSessionFailure("wallet_session_unavailable"));
21788
21618
  walletIdRaw = String(validated.admission.context.authorization.session.walletId);
21789
21619
  authorization = {
21790
21620
  kind: "wallet_auth_method",
@@ -21832,22 +21662,14 @@ async function handleWebAuthnAuthenticators(ctx) {
21832
21662
  if (ctx.pathname !== "/webauthn/authenticators") return null;
21833
21663
  try {
21834
21664
  const token = extractBearerCredential(ctx.request.headers);
21835
- if (!token) return json$1({
21836
- ok: false,
21837
- code: "unauthorized",
21838
- message: "No valid Wallet Session"
21839
- }, { status: 401 });
21665
+ if (!token) return jsonFailure(401, "unauthorized", "No valid Wallet Session");
21840
21666
  const nowMs = Date.now();
21841
21667
  const exact = await ctx.service.authorizationSessions.readWalletSessionAuthorizationV2ByOperationCredential({
21842
21668
  tenantId: ctx.service.authorizationSessions.tenantId,
21843
21669
  token,
21844
21670
  nowMs
21845
21671
  });
21846
- if (!exact) return json$1({
21847
- ok: false,
21848
- code: "unauthorized",
21849
- message: "No valid Wallet Session"
21850
- }, { status: 401 });
21672
+ if (!exact) return jsonFailure(401, "unauthorized", "No valid Wallet Session");
21851
21673
  const rpIdFromQuery = String(ctx.url.searchParams.get("rpId") || ctx.url.searchParams.get("rp_id") || "").trim();
21852
21674
  const result = await ctx.service.webAuthn.listWebAuthnAuthenticatorsForUser({
21853
21675
  userId: String(exact.authorization.session.walletId),
@@ -21856,11 +21678,7 @@ async function handleWebAuthnAuthenticators(ctx) {
21856
21678
  if (!result.ok) return json$1(result, { status: result.code === "not_supported" ? 501 : result.code === "invalid_args" ? 400 : 500 });
21857
21679
  return json$1(result, { status: 200 });
21858
21680
  } catch (e) {
21859
- return json$1({
21860
- ok: false,
21861
- code: "internal",
21862
- message: e?.message || "Internal error"
21863
- }, { status: 500 });
21681
+ return jsonFailure(500, "internal", e?.message || "Internal error");
21864
21682
  }
21865
21683
  }
21866
21684
  //#endregion
@@ -21939,23 +21757,15 @@ function parseOptionalPositiveInteger(raw, fieldName) {
21939
21757
  value: Math.floor(value)
21940
21758
  };
21941
21759
  }
21942
- function parseAuthProviderAction(input) {
21943
- const provider = normalizeOptionalTrimmedString(input.provider);
21944
- const action = normalizeOptionalTrimmedString(input.action);
21945
- if (provider === "passkey" && action === "options") return { kind: "passkey_options" };
21946
- if (provider === "passkey" && action === "verify") return { kind: "passkey_verify" };
21947
- if (provider === "google" && action === "options") return { kind: "google_options" };
21948
- if (provider === "google" && action === "verify") return { kind: "google_verify" };
21949
- if (provider === "github" && action === "options") return { kind: "github_options" };
21950
- return null;
21951
- }
21952
21760
  function parseAuthProviderActionPath(pathname) {
21953
- const parts = String(pathname || "").split("/").filter(Boolean);
21954
- if (parts.length !== 3 || parts[0] !== "auth") return null;
21955
- return parseAuthProviderAction({
21956
- provider: parts[1],
21957
- action: parts[2]
21958
- });
21761
+ switch (pathname) {
21762
+ case "/auth/passkey/options": return { kind: "passkey_options" };
21763
+ case "/auth/passkey/verify": return { kind: "passkey_verify" };
21764
+ case "/auth/google/options": return { kind: "google_options" };
21765
+ case "/auth/google/verify": return { kind: "google_verify" };
21766
+ case "/auth/github/options": return { kind: "github_options" };
21767
+ default: return null;
21768
+ }
21959
21769
  }
21960
21770
  function parsePasskeyLoginOptionsRequest(raw) {
21961
21771
  const body = requireJsonObject(raw);
@@ -22133,11 +21943,7 @@ async function requireExactWalletSession(ctx) {
22133
21943
  const token = extractBearerCredential(ctx.request.headers);
22134
21944
  if (!token) return {
22135
21945
  ok: false,
22136
- response: json$1({
22137
- ok: false,
22138
- code: "unauthorized",
22139
- message: "No valid Wallet Session"
22140
- }, { status: 401 })
21946
+ response: jsonFailure(401, "unauthorized", "No valid Wallet Session")
22141
21947
  };
22142
21948
  try {
22143
21949
  const context = await ctx.service.authorizationSessions.readWalletSessionAuthorizationV2ByOperationCredential({
@@ -22147,11 +21953,7 @@ async function requireExactWalletSession(ctx) {
22147
21953
  });
22148
21954
  if (!context) return {
22149
21955
  ok: false,
22150
- response: json$1({
22151
- ok: false,
22152
- code: "unauthorized",
22153
- message: "No valid Wallet Session"
22154
- }, { status: 401 })
21956
+ response: jsonFailure(401, "unauthorized", "No valid Wallet Session")
22155
21957
  };
22156
21958
  return {
22157
21959
  ok: true,
@@ -22160,11 +21962,7 @@ async function requireExactWalletSession(ctx) {
22160
21962
  } catch {
22161
21963
  return {
22162
21964
  ok: false,
22163
- response: json$1({
22164
- ok: false,
22165
- code: "wallet_session_unavailable",
22166
- message: "Wallet Session is unavailable"
22167
- }, { status: 503 })
21965
+ response: jsonFailure(503, "wallet_session_unavailable", "Wallet Session is unavailable")
22168
21966
  };
22169
21967
  }
22170
21968
  }
@@ -22177,19 +21975,11 @@ async function requireExactPasskeyStepUp(input) {
22177
21975
  const walletId = String(input.context.authorization.session.walletId);
22178
21976
  if (String(result.userId).trim() !== walletId) return {
22179
21977
  ok: false,
22180
- response: json$1({
22181
- ok: false,
22182
- code: "forbidden",
22183
- message: "Step-up user mismatch"
22184
- }, { status: 403 })
21978
+ response: jsonFailure(403, "forbidden", "Step-up user mismatch")
22185
21979
  };
22186
21980
  if (result.walletAuthMethodId !== input.context.authMethod.walletAuthMethodId || result.walletAuthorityId !== input.context.authority.authorityId) return {
22187
21981
  ok: false,
22188
- response: json$1({
22189
- ok: false,
22190
- code: "forbidden",
22191
- message: "Step-up authority mismatch"
22192
- }, { status: 403 })
21982
+ response: jsonFailure(403, "forbidden", "Step-up authority mismatch")
22193
21983
  };
22194
21984
  return { ok: true };
22195
21985
  }
@@ -22247,11 +22037,7 @@ async function handleAuth(ctx) {
22247
22037
  default: assertNeverAuthIdentityMutation(command);
22248
22038
  }
22249
22039
  const subject = command.request.subject;
22250
- if (subject.startsWith("near:")) return json$1({
22251
- ok: false,
22252
- code: "not_supported",
22253
- message: "near: subjects cannot be unlinked"
22254
- }, { status: 400 });
22040
+ if (subject.startsWith("near:")) return jsonFailure(400, "not_supported", "near: subjects cannot be unlinked");
22255
22041
  const out = await ctx.service.identity.unlinkIdentity({
22256
22042
  userId: walletId,
22257
22043
  subject
@@ -22274,6 +22060,8 @@ async function handleAuth(ctx) {
22274
22060
  const parsed = parsePasskeyLoginOptionsRequest(await readJson(ctx.request));
22275
22061
  if (!parsed.ok) return json$1(parsed.body, { status: parsed.status });
22276
22062
  const result = await ctx.service.webAuthn.createWebAuthnLoginOptions(parsed.request);
22063
+ if (result.code === "wallet_home_unavailable") return json$1(result, { status: 503 });
22064
+ if (result.code === "wallet_home_conflict") return json$1(result, { status: 409 });
22277
22065
  return json$1(result, { status: result.ok ? 200 : result.code === "internal" ? 500 : 400 });
22278
22066
  }
22279
22067
  case "passkey_verify": {
@@ -22308,16 +22096,8 @@ async function handleAuth(ctx) {
22308
22096
  publishableKeyAuth: ctx.opts.publishableKeyAuth,
22309
22097
  orgProjectEnv: ctx.opts.orgProjectEnv
22310
22098
  });
22311
- if (!runtimePolicyScope.ok) return json$1({
22312
- ok: false,
22313
- code: runtimePolicyScope.code,
22314
- message: runtimePolicyScope.message
22315
- }, { status: runtimePolicyScope.status });
22316
- if (!runtimePolicyScope.scope) return json$1({
22317
- ok: false,
22318
- code: "runtime_policy_scope_unavailable",
22319
- message: "Google Email OTP requires an active managed runtime policy scope"
22320
- }, { status: 500 });
22099
+ if (!runtimePolicyScope.ok) return jsonFailure(runtimePolicyScope.status, runtimePolicyScope.code, runtimePolicyScope.message);
22100
+ if (!runtimePolicyScope.scope) return jsonFailure(500, "runtime_policy_scope_unavailable", "Google Email OTP requires an active managed runtime policy scope");
22321
22101
  const result = await ctx.service.identity.verifyGoogleLogin(parsed.request);
22322
22102
  if (!result.ok || !result.verified || !result.providerSubject) return json$1(result, { status: result.code === "internal" ? 500 : 400 });
22323
22103
  const resolution = await ctx.service.identity.resolveGoogleEmailOtpSession({
@@ -22334,40 +22114,6 @@ async function handleAuth(ctx) {
22334
22114
  }
22335
22115
  }
22336
22116
  //#endregion
22337
- //#region src/router/transport/fetch/routes/nearPublicKeys.ts
22338
- async function handleNearPublicKeys(ctx) {
22339
- if (ctx.method !== "GET") return null;
22340
- if (ctx.pathname !== "/near/public-keys") return null;
22341
- try {
22342
- const token = extractBearerCredential(ctx.request.headers);
22343
- if (!token) return json$1({
22344
- ok: false,
22345
- code: "unauthorized",
22346
- message: "No valid Wallet Session"
22347
- }, { status: 401 });
22348
- const nowMs = Date.now();
22349
- const exact = await ctx.service.authorizationSessions.readWalletSessionAuthorizationV2ByOperationCredential({
22350
- tenantId: ctx.service.authorizationSessions.tenantId,
22351
- token,
22352
- nowMs
22353
- });
22354
- if (!exact) return json$1({
22355
- ok: false,
22356
- code: "unauthorized",
22357
- message: "No valid Wallet Session"
22358
- }, { status: 401 });
22359
- const result = await ctx.service.nearFunding.listNearPublicKeysForUser({ userId: String(exact.authorization.session.walletId) });
22360
- if (!result.ok) return json$1(result, { status: result.code === "not_supported" ? 501 : result.code === "invalid_args" ? 400 : 500 });
22361
- return json$1(result, { status: 200 });
22362
- } catch (e) {
22363
- return json$1({
22364
- ok: false,
22365
- code: "internal",
22366
- message: e?.message || "Internal error"
22367
- }, { status: 500 });
22368
- }
22369
- }
22370
- //#endregion
22371
22117
  //#region src/router/framework/ror/normalize.ts
22372
22118
  function sanitizeRorOrigins(origins) {
22373
22119
  const list = Array.isArray(origins) ? origins : [];
@@ -22482,10 +22228,166 @@ async function handleWellKnown(ctx) {
22482
22228
  });
22483
22229
  }
22484
22230
  //#endregion
22231
+ //#region src/router/transport/fetch/routes/deviceLinkingResponses.ts
22232
+ function projectLinkSessionStateV1(state) {
22233
+ switch (state.state) {
22234
+ case "displaying_qr": return { state: "displaying_qr" };
22235
+ case "claimed":
22236
+ case "awaiting_target_factor":
22237
+ case "awaiting_source_contribution":
22238
+ case "provisioning": return {
22239
+ state: state.state,
22240
+ deviceId: state.deviceId
22241
+ };
22242
+ case "authority_pending_local_install": return {
22243
+ state: "authority_pending_local_install",
22244
+ deviceId: state.deviceId,
22245
+ authorityId: state.authorityId,
22246
+ packageSetDigestB64u: state.packageSetDigestB64u
22247
+ };
22248
+ case "active": return {
22249
+ state: "active",
22250
+ deviceId: state.deviceId,
22251
+ authorityId: state.authorityId,
22252
+ activatedAtMs: state.activatedAtMs
22253
+ };
22254
+ case "failed_before_commit": return {
22255
+ state: "failed_before_commit",
22256
+ error: state.error
22257
+ };
22258
+ case "cancelled": return {
22259
+ state: "cancelled",
22260
+ cancelledAtMs: state.cancelledAtMs
22261
+ };
22262
+ case "expired": return {
22263
+ state: "expired",
22264
+ expiredAtMs: state.expiredAtMs
22265
+ };
22266
+ default: return assertNeverLinkSessionStateV1(state);
22267
+ }
22268
+ }
22269
+ function projectSession(record) {
22270
+ return {
22271
+ kind: "linked_device_session_projection_v1",
22272
+ linkSessionId: record.linkSessionId,
22273
+ qrPayload: record.qrPayload,
22274
+ revision: record.revision,
22275
+ createdAtMs: record.createdAtMs,
22276
+ updatedAtMs: record.updatedAtMs,
22277
+ state: projectLinkSessionStateV1(record.state)
22278
+ };
22279
+ }
22280
+ function invalidStateResponse(record) {
22281
+ return json$1({
22282
+ ok: false,
22283
+ outcome: "invalid_state",
22284
+ state: record.state.state,
22285
+ session: projectSession(record)
22286
+ }, { status: 409 });
22287
+ }
22288
+ function sessionProjectionResponse(record, outcome) {
22289
+ return json$1({
22290
+ ok: true,
22291
+ outcome,
22292
+ session: projectSession(record)
22293
+ }, { status: 200 });
22294
+ }
22295
+ function targetCredentialResultResponse(record, outcome, targetCredential) {
22296
+ return json$1({
22297
+ ok: true,
22298
+ outcome,
22299
+ targetCredential,
22300
+ session: projectSession(record)
22301
+ }, { status: 200 });
22302
+ }
22303
+ function exportRootWriteResponse(result) {
22304
+ return result.outcome === "conflict" ? json$1({
22305
+ ok: false,
22306
+ code: result.reason ?? "conflict",
22307
+ message: "export-root relay conflict"
22308
+ }, { status: 409 }) : json$1({
22309
+ ok: true,
22310
+ outcome: result.outcome
22311
+ }, { status: 200 });
22312
+ }
22313
+ function invalidInputResponse(message) {
22314
+ return json$1({
22315
+ ok: false,
22316
+ outcome: "invalid_input",
22317
+ code: "invalid_input",
22318
+ message
22319
+ }, { status: 400 });
22320
+ }
22321
+ function notSupportedResponse(message = "Device linking is not configured") {
22322
+ return json$1({
22323
+ ok: false,
22324
+ code: "not_supported",
22325
+ message
22326
+ }, { status: 501 });
22327
+ }
22328
+ function notFoundResponse() {
22329
+ return json$1({
22330
+ ok: false,
22331
+ code: "not_found",
22332
+ message: "Linked-device session not found"
22333
+ }, { status: 404 });
22334
+ }
22335
+ function methodNotAllowedResponse$2() {
22336
+ return json$1({
22337
+ ok: false,
22338
+ code: "method_not_allowed",
22339
+ message: "Method is not allowed"
22340
+ }, { status: 405 });
22341
+ }
22342
+ function authDeniedResponse$2(result) {
22343
+ if (result.code === "unavailable") return json$1({
22344
+ ok: false,
22345
+ code: result.code,
22346
+ message: result.message
22347
+ }, { status: 503 });
22348
+ return json$1({
22349
+ ok: false,
22350
+ outcome: "unauthorized",
22351
+ code: result.code,
22352
+ message: result.message
22353
+ }, { status: result.code === "expired" ? 410 : 401 });
22354
+ }
22355
+ //#endregion
22356
+ //#region src/core/deviceLinking/linkedDeviceBootstrap.ts
22357
+ function linkedDeviceBootstrapFailure(error) {
22358
+ if (error && typeof error === "object" && "code" in error && (error.code === "home_conflict" || error.code === "home_unavailable")) return error.code;
22359
+ return null;
22360
+ }
22361
+ //#endregion
22362
+ //#region ../shared-ts/src/utils/exactKeys.ts
22363
+ /**
22364
+ * True when `value` is a non-array object whose own enumerable string keys are exactly `keys`.
22365
+ *
22366
+ * A key whose value is `undefined` still counts as present. Symbol, non-enumerable and inherited
22367
+ * keys are not counted, and the prototype is not checked. A list that repeats a key never matches.
22368
+ * Kept apart from validation.ts, which the wallet iframe's boot path loads.
22369
+ */
22370
+ function hasExactKeys$1(value, keys) {
22371
+ if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
22372
+ const actual = Object.keys(value);
22373
+ return actual.length === keys.length && actual.every((key) => keys.includes(key));
22374
+ }
22375
+ //#endregion
22485
22376
  //#region src/core/deviceLinking/requestProof.ts
22486
22377
  function parseLinkedDeviceRequestProofV1(raw) {
22487
22378
  if (raw === null || typeof raw !== "object" || Array.isArray(raw)) throw new Error("linked-device request proof must be an object");
22488
- if (!isLinkedDeviceRequestProofRecordV1(raw)) throw new Error("record contains invalid fields");
22379
+ if (!hasExactKeys$1(raw, [
22380
+ "kind",
22381
+ "linkSessionId",
22382
+ "devicePublicKeyDigestB64u",
22383
+ "requestNonceB64u",
22384
+ "method",
22385
+ "canonicalPath",
22386
+ "bodyDigestB64u",
22387
+ "issuedAtMs",
22388
+ "expiresAtMs",
22389
+ "signatureB64u"
22390
+ ])) throw new Error("record contains invalid fields");
22489
22391
  const record = raw;
22490
22392
  if (record.kind !== "linked_device_request_proof_v1") throw new Error("linked-device request proof kind is invalid");
22491
22393
  const linkSessionId = parseSessionId$1(record.linkSessionId);
@@ -22542,9 +22444,6 @@ function parseFixedB64u(raw, expectedBytes, field) {
22542
22444
  if (bytes.length !== expectedBytes || base64UrlEncode(bytes) !== raw) throw new Error(`${field} is invalid`);
22543
22445
  return raw;
22544
22446
  }
22545
- function isLinkedDeviceRequestProofRecordV1(value) {
22546
- return Object.keys(value).sort().join("|") === "bodyDigestB64u|canonicalPath|devicePublicKeyDigestB64u|expiresAtMs|issuedAtMs|kind|linkSessionId|method|requestNonceB64u|signatureB64u";
22547
- }
22548
22447
  //#endregion
22549
22448
  //#region src/router/transport/fetch/routes/deviceLinking.ts
22550
22449
  const DEVICE_LINKING_BASE = "/wallet/device-linking/v1/sessions";
@@ -22581,6 +22480,11 @@ async function handleDeviceLinking(ctx) {
22581
22480
  default: return assertNever$1(action);
22582
22481
  }
22583
22482
  } catch (error) {
22483
+ const bootstrapFailure = linkedDeviceBootstrapFailure(error);
22484
+ if (bootstrapFailure) return sessionResultResponse({
22485
+ outcome: bootstrapFailure,
22486
+ message: "Linked-device bootstrap authority failed"
22487
+ });
22584
22488
  if (error instanceof DeviceLinkingInputError) return invalidInputResponse(error.message);
22585
22489
  return json$1({
22586
22490
  ok: false,
@@ -22592,7 +22496,7 @@ async function handleDeviceLinking(ctx) {
22592
22496
  async function handleCreate(ctx, service, nowMs) {
22593
22497
  if (ctx.method !== "POST") return methodNotAllowedResponse$2();
22594
22498
  const bodyDigestB64u = await requestBodyDigest$1(ctx.request);
22595
- const rawBody = await readJsonBody(ctx.request);
22499
+ const rawBody = await readJson(ctx.request);
22596
22500
  const body = parseBoundary$1(() => parseCreateRequest(rawBody));
22597
22501
  const keyDigest = await computeDevicePublicKeyDigestB64u(body.payload.devicePublicKeyB64u);
22598
22502
  const proof = parseBoundary$1(() => parseRequestProofHeader(ctx.request));
@@ -22669,7 +22573,7 @@ async function handleApproval(ctx, service, rawLinkSessionId, nowMs) {
22669
22573
  });
22670
22574
  if (!session) return notFoundResponse();
22671
22575
  const ownerMismatch = requireOwnerMatchesClaimedWallet(authentication.owner, session);
22672
- if (ownerMismatch) return ownerMismatch;
22576
+ if (ownerMismatch) return authDeniedResponse$2(ownerMismatch);
22673
22577
  if (authentication.owner.walletId !== approval.walletId) return authDeniedResponse$2({
22674
22578
  kind: "denied",
22675
22579
  code: "unauthorized",
@@ -22753,6 +22657,7 @@ async function handleCredential(ctx, service, rawLinkSessionId, nowMs) {
22753
22657
  async function handleSourceContributionPreparation(ctx, service, rawLinkSessionId, nowMs) {
22754
22658
  const owner = await authenticateOwnerForSession(ctx, service, parseSessionId(rawLinkSessionId), nowMs);
22755
22659
  if (owner.kind !== "authorized") return ownerSessionResponse(owner);
22660
+ if (isLinkSessionTerminalFailureV1(owner.session.state)) return invalidStateResponse(owner.session);
22756
22661
  if (ctx.method !== "GET") return methodNotAllowedResponse$2();
22757
22662
  const preparation = owner.session.sourceContributionPreparation;
22758
22663
  if (!preparation) return new Response(null, { status: 204 });
@@ -22803,10 +22708,6 @@ async function handleSourceContribution(ctx, service, rawLinkSessionId, nowMs) {
22803
22708
  }));
22804
22709
  return sessionProjectionResponse(committed.session, committed.kind === "replayed" ? "replayed" : recorded.outcome);
22805
22710
  }
22806
- /**
22807
- * A precommit failure's reason is a single token. The installer's message
22808
- * keeps its words, joined, so the session still says what failed.
22809
- */
22810
22711
  function precommitFailureReasonV1(message) {
22811
22712
  const token = message.trim().replace(/\s+/g, "_").replace(/[\u0000-\u001f\u007f]/g, "");
22812
22713
  return token.length > 0 ? token : "authority_commit_failed";
@@ -22815,6 +22716,7 @@ async function handleSourceContributionExecute(ctx, service, rawLinkSessionId, n
22815
22716
  if (ctx.method !== "POST") return methodNotAllowedResponse$2();
22816
22717
  const owner = await authenticateOwnerForSession(ctx, service, parseSessionId(rawLinkSessionId), nowMs);
22817
22718
  if (owner.kind !== "authorized") return ownerSessionResponse(owner);
22719
+ if (isLinkSessionTerminalFailureV1(owner.session.state)) return invalidStateResponse(owner.session);
22818
22720
  const router = service.sourceContributionRouter;
22819
22721
  if (!router) return notSupportedResponse("Ed25519 source-preserving linking is not configured");
22820
22722
  const preparation = requireEd25519SourceContributionPreparation(owner.session);
@@ -22887,8 +22789,6 @@ async function handleEmailOtpBaseFactor(ctx, service, rawLinkSessionId, nowMs) {
22887
22789
  const authenticated = await authenticateOwnerForSession(ctx, service, parseSessionId(rawLinkSessionId), nowMs);
22888
22790
  if (authenticated.kind !== "authorized") return ownerSessionResponse(authenticated);
22889
22791
  const session = authenticated.session;
22890
- const ownerMismatch = requireOwnerMatchesClaimedWallet(authenticated.owner, session);
22891
- if (ownerMismatch) return ownerMismatch;
22892
22792
  if (session.state.state !== "claimed" || session.qrPayload.targetFactor.kind !== "email_otp" || !session.claimTranscript) return invalidStateResponse(session);
22893
22793
  const walletId = session.claimTranscript.value.walletId;
22894
22794
  const request = parseBoundary$1(() => parseLinkedDeviceEmailOtpBaseFactorRequestV1(authenticated.body));
@@ -22916,8 +22816,6 @@ async function handleOwnerCancel(ctx, service, rawLinkSessionId, nowMs) {
22916
22816
  if (authenticated.kind !== "authorized") return ownerSessionResponse(authenticated);
22917
22817
  parseBoundary$1(() => parseOwnerCancelRequest(authenticated.body));
22918
22818
  const session = authenticated.session;
22919
- const ownerMismatch = requireOwnerMatchesClaimedWallet(authenticated.owner, session);
22920
- if (ownerMismatch) return ownerMismatch;
22921
22819
  if (session.state.state === "cancelled") return sessionProjectionResponse(session, "replayed");
22922
22820
  return sessionResultResponse(await service.sessionService.cancelSessionV1({
22923
22821
  linkSessionId,
@@ -22965,6 +22863,7 @@ async function handleExportRootRecipient(ctx, service, rawLinkSessionId, nowMs)
22965
22863
  if (ctx.method === "GET") {
22966
22864
  const owner = await authenticateOwnerForSession(ctx, service, sessionId, nowMs);
22967
22865
  if (owner.kind !== "authorized") return ownerSessionResponse(owner);
22866
+ if (isLinkSessionTerminalFailureV1(owner.session.state)) return invalidStateResponse(owner.session);
22968
22867
  const transfer = await port.readTransferV1(sessionId);
22969
22868
  return transfer ? json$1(transfer.recipient, { status: 200 }) : new Response(null, { status: 204 });
22970
22869
  }
@@ -22972,8 +22871,14 @@ async function handleExportRootRecipient(ctx, service, rawLinkSessionId, nowMs)
22972
22871
  const authenticated = await authenticateDeviceForSession(ctx, service, rawLinkSessionId, nowMs);
22973
22872
  if (authenticated.kind === "denied") return authDeniedResponse$2(authenticated);
22974
22873
  if (authenticated.kind === "not_found") return notFoundResponse();
22874
+ if (isLinkSessionTerminalFailureV1(authenticated.session.state)) return invalidStateResponse(authenticated.session);
22975
22875
  const recipient = parseBoundary$1(() => parseLinkedDeviceEd25519ExportRootRecipientV1(authenticated.body));
22976
22876
  if (recipient.linkSessionId !== authenticated.linkSessionId) return invalidInputResponse("link session id does not match route");
22877
+ const session = authenticated.session;
22878
+ const preparation = await readTargetPreparation(service, session, requireApproval(session), { access: "replay_only" }, nowMs);
22879
+ if (preparation.kind === "conflict") return invalidStateResponse(session);
22880
+ const facts = preparation.ed25519ExportRoot;
22881
+ 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");
22977
22882
  return exportRootWriteResponse(await port.registerRecipientV1({ recipient }));
22978
22883
  }
22979
22884
  async function handleExportRootPackage(ctx, service, rawLinkSessionId, nowMs) {
@@ -22984,12 +22889,14 @@ async function handleExportRootPackage(ctx, service, rawLinkSessionId, nowMs) {
22984
22889
  const authenticated = await authenticateDeviceForSession(ctx, service, rawLinkSessionId, nowMs);
22985
22890
  if (authenticated.kind === "denied") return authDeniedResponse$2(authenticated);
22986
22891
  if (authenticated.kind === "not_found") return notFoundResponse();
22892
+ if (isLinkSessionTerminalFailureV1(authenticated.session.state)) return invalidStateResponse(authenticated.session);
22987
22893
  const transfer = await port.readTransferV1(sessionId);
22988
22894
  return transfer?.state === "sealed" ? json$1(transfer.package, { status: 200 }) : new Response(null, { status: 204 });
22989
22895
  }
22990
22896
  if (ctx.method !== "POST") return methodNotAllowedResponse$2();
22991
22897
  const owner = await authenticateOwnerForSession(ctx, service, sessionId, nowMs);
22992
22898
  if (owner.kind !== "authorized") return ownerSessionResponse(owner);
22899
+ if (isLinkSessionTerminalFailureV1(owner.session.state)) return invalidStateResponse(owner.session);
22993
22900
  const submission = parseBoundary$1(() => parseLinkedDeviceEd25519ExportRootSubmissionV1(owner.body));
22994
22901
  if (submission.linkSessionId !== sessionId) return invalidInputResponse("link session id does not match route");
22995
22902
  return exportRootWriteResponse(await port.submitPackageV1({
@@ -23001,7 +22908,7 @@ async function handleReceipt(ctx, service, rawLinkSessionId, nowMs) {
23001
22908
  if (!service.installationReceipt) return notSupportedResponse("Installation receipt is not configured");
23002
22909
  if (ctx.method !== "POST") return methodNotAllowedResponse$2();
23003
22910
  const linkSessionId = parseSessionId(rawLinkSessionId);
23004
- const rawBody = await readJsonBody(ctx.request.clone());
22911
+ const rawBody = await readJson(ctx.request.clone());
23005
22912
  if (isFinalActivationAcknowledgement(rawBody)) {
23006
22913
  const acknowledgement = parseBoundary$1(() => parseLocalAuthorityActivationFinalAckV1(rawBody));
23007
22914
  if (acknowledgement.linkSessionId !== linkSessionId) return invalidInputResponse("activation acknowledgement session does not match the route");
@@ -23187,6 +23094,8 @@ async function authenticateOwnerForSession(ctx, service, linkSessionId, nowMs) {
23187
23094
  });
23188
23095
  if (!session) return { kind: "not_found" };
23189
23096
  validateOwnerRequestBinding(authentication.binding, ctx, bodyDigestB64u, nowMs);
23097
+ const ownerMismatch = requireOwnerMatchesClaimedWallet(authentication.owner, session);
23098
+ if (ownerMismatch) return ownerMismatch;
23190
23099
  return {
23191
23100
  kind: "authorized",
23192
23101
  body: authentication.body,
@@ -23391,69 +23300,6 @@ async function authenticateTargetPasskeyOriginV1(ctx, routeId) {
23391
23300
  expectedOrigin
23392
23301
  };
23393
23302
  }
23394
- function projectLinkSessionStateV1(state) {
23395
- switch (state.state) {
23396
- case "displaying_qr": return { state: "displaying_qr" };
23397
- case "claimed":
23398
- case "awaiting_target_factor":
23399
- case "awaiting_source_contribution":
23400
- case "provisioning": return {
23401
- state: state.state,
23402
- deviceId: state.deviceId
23403
- };
23404
- case "authority_pending_local_install": return {
23405
- state: "authority_pending_local_install",
23406
- deviceId: state.deviceId,
23407
- authorityId: state.authorityId,
23408
- packageSetDigestB64u: state.packageSetDigestB64u
23409
- };
23410
- case "active": return {
23411
- state: "active",
23412
- deviceId: state.deviceId,
23413
- authorityId: state.authorityId,
23414
- activatedAtMs: state.activatedAtMs
23415
- };
23416
- case "failed_before_commit": return {
23417
- state: "failed_before_commit",
23418
- error: state.error
23419
- };
23420
- case "cancelled": return {
23421
- state: "cancelled",
23422
- cancelledAtMs: state.cancelledAtMs
23423
- };
23424
- case "expired": return {
23425
- state: "expired",
23426
- expiredAtMs: state.expiredAtMs
23427
- };
23428
- default: return assertNeverLinkSessionStateV1(state);
23429
- }
23430
- }
23431
- function projectSession(record) {
23432
- return {
23433
- kind: "linked_device_session_projection_v1",
23434
- linkSessionId: record.linkSessionId,
23435
- qrPayload: record.qrPayload,
23436
- revision: record.revision,
23437
- createdAtMs: record.createdAtMs,
23438
- updatedAtMs: record.updatedAtMs,
23439
- state: projectLinkSessionStateV1(record.state)
23440
- };
23441
- }
23442
- function sessionProjectionResponse(record, outcome) {
23443
- return json$1({
23444
- ok: true,
23445
- outcome,
23446
- session: projectSession(record)
23447
- }, { status: 200 });
23448
- }
23449
- function targetCredentialResultResponse(record, outcome, targetCredential) {
23450
- return json$1({
23451
- ok: true,
23452
- outcome,
23453
- targetCredential,
23454
- session: projectSession(record)
23455
- }, { status: 200 });
23456
- }
23457
23303
  function claimResultResponse(result) {
23458
23304
  if (result.outcome !== "applied" && result.outcome !== "replayed") return sessionResultResponse(result);
23459
23305
  const claim = result.record.claimTranscript?.value;
@@ -23482,6 +23328,16 @@ function approvalResultResponse(result) {
23482
23328
  }
23483
23329
  function sessionResultResponse(result) {
23484
23330
  switch (result.outcome) {
23331
+ case "home_conflict": return json$1({
23332
+ ok: false,
23333
+ code: "wallet_home_conflict",
23334
+ message: result.message
23335
+ }, { status: 409 });
23336
+ case "home_unavailable": return json$1({
23337
+ ok: false,
23338
+ code: "wallet_home_unavailable",
23339
+ message: result.message
23340
+ }, { status: 503 });
23485
23341
  case "applied":
23486
23342
  case "replayed": return sessionProjectionResponse(result.record, result.outcome);
23487
23343
  case "conflict": return json$1({
@@ -23522,49 +23378,19 @@ function sessionResultResponse(result) {
23522
23378
  default: return assertNever$1(result);
23523
23379
  }
23524
23380
  }
23525
- function invalidStateResponse(record) {
23526
- return json$1({
23527
- ok: false,
23528
- outcome: "invalid_state",
23529
- state: record.state.state,
23530
- session: projectSession(record)
23531
- }, { status: 409 });
23532
- }
23533
- function exportRootWriteResponse(result) {
23534
- return result.outcome === "conflict" ? json$1({
23535
- ok: false,
23536
- code: result.reason ?? "conflict",
23537
- message: "export-root relay conflict"
23538
- }, { status: 409 }) : json$1({
23539
- ok: true,
23540
- outcome: result.outcome
23541
- }, { status: 200 });
23542
- }
23543
23381
  function ownerSessionResponse(context) {
23544
23382
  return context.kind === "denied" ? authDeniedResponse$2(context) : notFoundResponse();
23545
23383
  }
23546
- /**
23547
- * The one owner-to-session binding, shared by every owner route on a claimed
23548
- * session. It runs before any state is disclosed: an authenticated owner of a
23549
- * DIFFERENT wallet must get the same denial for every state, not a projection
23550
- * or an invalid-state body. An unclaimed session has no wallet to bind to yet,
23551
- * so the caller's state checks answer instead.
23552
- */
23553
23384
  function requireOwnerMatchesClaimedWallet(owner, session) {
23554
23385
  const claimWalletId = session.claimTranscript?.value.walletId;
23555
23386
  if (claimWalletId === void 0) return null;
23556
23387
  if (owner.walletId === claimWalletId) return null;
23557
- return authDeniedResponse$2({
23388
+ return {
23558
23389
  kind: "denied",
23559
23390
  code: "unauthorized",
23560
23391
  message: "owner session does not match link wallet"
23561
- });
23392
+ };
23562
23393
  }
23563
- /**
23564
- * Approval-time revalidation of the selected Email OTP base method. The same
23565
- * eligibility question the dedicated base-factor route answers, asked once
23566
- * more with the id the approval names, so the two paths cannot drift.
23567
- */
23568
23394
  async function requireSelectedEmailOtpBaseFactorV1(service, session, input) {
23569
23395
  const provider = service.emailOtpTargetFactor;
23570
23396
  if (!provider) return notSupportedResponse("Email OTP linking is not configured");
@@ -23583,43 +23409,6 @@ async function requireSelectedEmailOtpBaseFactorV1(service, session, input) {
23583
23409
  });
23584
23410
  return null;
23585
23411
  }
23586
- function authDeniedResponse$2(result) {
23587
- return json$1({
23588
- ok: false,
23589
- outcome: "unauthorized",
23590
- code: result.code,
23591
- message: result.message
23592
- }, { status: result.code === "expired" ? 410 : 401 });
23593
- }
23594
- function invalidInputResponse(message) {
23595
- return json$1({
23596
- ok: false,
23597
- outcome: "invalid_input",
23598
- code: "invalid_input",
23599
- message
23600
- }, { status: 400 });
23601
- }
23602
- function notSupportedResponse(message = "Device linking is not configured") {
23603
- return json$1({
23604
- ok: false,
23605
- code: "not_supported",
23606
- message
23607
- }, { status: 501 });
23608
- }
23609
- function notFoundResponse() {
23610
- return json$1({
23611
- ok: false,
23612
- code: "not_found",
23613
- message: "Linked-device session not found"
23614
- }, { status: 404 });
23615
- }
23616
- function methodNotAllowedResponse$2() {
23617
- return json$1({
23618
- ok: false,
23619
- code: "method_not_allowed",
23620
- message: "Method is not allowed"
23621
- }, { status: 405 });
23622
- }
23623
23412
  function parseCreateRequest(raw) {
23624
23413
  const record = requireRecord(raw, "device-linking create request");
23625
23414
  requireExactKeys$1(record, ["kind", "payload"]);
@@ -23684,9 +23473,6 @@ function parseB64uBytes(raw, field) {
23684
23473
  if (bytes.length === 0 || base64UrlEncode(bytes) !== raw) throw new Error(`${field} is not canonical base64url`);
23685
23474
  return bytes;
23686
23475
  }
23687
- async function readJsonBody(request) {
23688
- return await readJson(request);
23689
- }
23690
23476
  function parseBoundary$1(parse) {
23691
23477
  try {
23692
23478
  return parse();
@@ -24039,11 +23825,7 @@ async function authenticateDeviceLinkingOwnerWalletSessionRequestV1(input) {
24039
23825
  async function handleDeviceLinkingOwnerAuthorization(ctx, service) {
24040
23826
  if (ctx.pathname !== "/wallet/device-linking/v1/owner-authorization") return null;
24041
23827
  if (ctx.method !== "POST") return methodNotAllowedResponse();
24042
- if (!service) return json$1({
24043
- ok: false,
24044
- code: "not_supported",
24045
- message: "Linked-device owner authorization is not configured"
24046
- }, { status: 501 });
23828
+ if (!service) return jsonFailure(501, "not_supported", "Linked-device owner authorization is not configured");
24047
23829
  const nowV1 = Date.now;
24048
23830
  let body;
24049
23831
  let rawBody;
@@ -24053,11 +23835,7 @@ async function handleDeviceLinkingOwnerAuthorization(ctx, service) {
24053
23835
  rawBody = await readJson(ctx.request.clone());
24054
23836
  body = parseLinkedDeviceOwnerAuthorizationRequestV1(rawBody);
24055
23837
  } catch (error) {
24056
- return json$1({
24057
- ok: false,
24058
- code: "invalid_body",
24059
- message: error instanceof Error ? error.message : "Owner authorization body is invalid"
24060
- }, { status: 400 });
23838
+ return jsonFailure(400, "invalid_body", error instanceof Error ? error.message : "Owner authorization body is invalid");
24061
23839
  }
24062
23840
  const validated = await authenticateDeviceLinkingOwnerWalletSessionRequestV1({
24063
23841
  request: ctx.request,
@@ -24077,11 +23855,7 @@ async function handleDeviceLinkingOwnerAuthorization(ctx, service) {
24077
23855
  owner: validated.owner
24078
23856
  }), { status: 200 });
24079
23857
  } catch (error) {
24080
- return json$1({
24081
- ok: false,
24082
- code: "internal",
24083
- message: error instanceof Error ? error.message : String(error)
24084
- }, { status: 500 });
23858
+ return jsonFailure(500, "internal", error instanceof Error ? error.message : String(error));
24085
23859
  }
24086
23860
  }
24087
23861
  async function validateOwnerWalletSessionV1(input) {
@@ -24245,12 +24019,8 @@ function methodNotAllowedResponse() {
24245
24019
  }, { status: 405 });
24246
24020
  }
24247
24021
  function authDeniedResponse(value) {
24248
- const status = value.code === "expired" ? 401 : value.code === "invalid" ? 403 : 401;
24249
- return json$1({
24250
- ok: false,
24251
- code: value.code,
24252
- message: value.message
24253
- }, { status });
24022
+ if (value.code === "unavailable") return jsonFailure(503, value.code, value.message);
24023
+ return jsonFailure(value.code === "invalid" ? 403 : 401, value.code, value.message);
24254
24024
  }
24255
24025
  //#endregion
24256
24026
  //#region src/threshold/session/signingSessionSeal/transport/fetch.ts
@@ -24260,20 +24030,6 @@ function json(body, status = 200) {
24260
24030
  headers: { "Content-Type": "application/json; charset=utf-8" }
24261
24031
  });
24262
24032
  }
24263
- async function readJsonSafe(request) {
24264
- try {
24265
- return await request.json();
24266
- } catch {
24267
- return null;
24268
- }
24269
- }
24270
- function headersToRecord(headers) {
24271
- const out = {};
24272
- headers.forEach((value, key) => {
24273
- out[key] = value;
24274
- });
24275
- return out;
24276
- }
24277
24033
  function errMessage(error) {
24278
24034
  return error instanceof Error ? error.message : String(error || "Internal error");
24279
24035
  }
@@ -24293,7 +24049,7 @@ async function handleSigningSessionSealRoutes(ctx) {
24293
24049
  route: isApply ? applyPath : removePath,
24294
24050
  operation
24295
24051
  });
24296
- const body = await readJsonSafe(ctx.request);
24052
+ const body = await readJson(ctx.request);
24297
24053
  const parsed = isApply ? parseSigningSessionSealApplyBody(body) : parseSigningSessionSealRemoveBody(body);
24298
24054
  if (!parsed.ok) {
24299
24055
  ctx.logger.warn("[threshold-signing-session-seal] invalid_body", {
@@ -24303,11 +24059,7 @@ async function handleSigningSessionSealRoutes(ctx) {
24303
24059
  message: parsed.message,
24304
24060
  durationMs: Math.max(0, Date.now() - startedAtMs)
24305
24061
  });
24306
- return json({
24307
- ok: false,
24308
- code: parsed.code,
24309
- message: parsed.message
24310
- }, 400);
24062
+ return json(failure(parsed.code, parsed.message), 400);
24311
24063
  }
24312
24064
  const authorized = await authorizeSigningSessionSealRequest({
24313
24065
  options,
@@ -24323,11 +24075,7 @@ async function handleSigningSessionSealRoutes(ctx) {
24323
24075
  message: authorized.message || "Unauthorized",
24324
24076
  durationMs: Math.max(0, Date.now() - startedAtMs)
24325
24077
  });
24326
- return json({
24327
- ok: false,
24328
- code: authorized.code || "unauthorized",
24329
- message: authorized.message || "Unauthorized"
24330
- }, signingSessionSealAuthorizeStatusCode(authorized));
24078
+ return json(failure(authorized.code || "unauthorized", authorized.message || "Unauthorized"), signingSessionSealAuthorizeStatusCode(authorized));
24331
24079
  }
24332
24080
  const result = isApply ? await options.service.applyServerSeal(parsed.value, authorized.auth) : await options.service.removeServerSeal(parsed.value, authorized.auth);
24333
24081
  const status = signingSessionSealStatusCode(result);
@@ -24347,11 +24095,7 @@ async function handleSigningSessionSealRoutes(ctx) {
24347
24095
  message,
24348
24096
  durationMs: Math.max(0, Date.now() - startedAtMs)
24349
24097
  });
24350
- return json({
24351
- ok: false,
24352
- code: "internal",
24353
- message
24354
- }, 500);
24098
+ return json(failure("internal", message), 500);
24355
24099
  }
24356
24100
  }
24357
24101
  //#endregion
@@ -24496,6 +24240,7 @@ async function signingSessionSealRecordFromExactAdmission(input) {
24496
24240
  switch (admission.curve) {
24497
24241
  case "ecdsa": {
24498
24242
  const active = await input.walletRegistration.resolveEcdsaMaterialActivation({
24243
+ source: { kind: "database" },
24499
24244
  walletId,
24500
24245
  materialActivation
24501
24246
  });
@@ -24656,11 +24401,7 @@ function createFetchRouter(service, opts, runtime) {
24656
24401
  async (context) => {
24657
24402
  if (!context.pathname.startsWith("/wallet/device-linking/v1/devices")) return null;
24658
24403
  const service = context.service.deviceManagement;
24659
- if (!service) return json$1({
24660
- ok: false,
24661
- code: "not_supported",
24662
- message: "Linked-device management is not configured"
24663
- }, { status: 501 });
24404
+ if (!service) return jsonFailure(501, "not_supported", "Linked-device management is not configured");
24664
24405
  return await handleDeviceManagement(context, service);
24665
24406
  },
24666
24407
  handlePasskeyCustody,
@@ -24685,7 +24426,6 @@ function createFetchRouter(service, opts, runtime) {
24685
24426
  handleThresholdEcdsa,
24686
24427
  handleExactWalletSigningSessionSeal,
24687
24428
  handleWebAuthnAuthenticators,
24688
- handleNearPublicKeys,
24689
24429
  handleExactWalletSessionStatus,
24690
24430
  handleHostedWalletSessionExchangeIssue,
24691
24431
  handleHostedWalletSessionExchangeRedeem,
@@ -24900,45 +24640,17 @@ function parseExpectation(raw) {
24900
24640
  }
24901
24641
  async function validateRuntimeSnapshotExpectation(input) {
24902
24642
  const expectationResult = parseExpectation(input.expectationRaw);
24903
- if (expectationResult.error) return {
24904
- ok: false,
24905
- code: "runtime_snapshot_invalid_expectation",
24906
- message: expectationResult.error
24907
- };
24643
+ if (expectationResult.error) return failure("runtime_snapshot_invalid_expectation", expectationResult.error);
24908
24644
  const expectation = expectationResult.parsed;
24909
24645
  if (!expectation) return { ok: true };
24910
24646
  const scope = input.scope;
24911
- if (!scope) return {
24912
- ok: false,
24913
- code: "runtime_snapshot_scope_missing",
24914
- message: "threshold session is missing runtimePolicyScope"
24915
- };
24916
- if (!input.runtimeSnapshots) return {
24917
- ok: false,
24918
- code: "runtime_snapshots_not_configured",
24919
- message: "Runtime snapshot consumer is not configured on this server"
24920
- };
24647
+ if (!scope) return failure("runtime_snapshot_scope_missing", "threshold session is missing runtimePolicyScope");
24648
+ if (!input.runtimeSnapshots) return failure("runtime_snapshots_not_configured", "Runtime snapshot consumer is not configured on this server");
24921
24649
  const latest = await input.runtimeSnapshots.getLatestSnapshot(scope);
24922
- if (!latest) return {
24923
- ok: false,
24924
- code: "runtime_snapshot_not_found",
24925
- message: `No runtime snapshot found for org=${scope.orgId} project=${scope.projectId} env=${scope.envId}`
24926
- };
24927
- if (expectation.snapshotId && latest.snapshotId !== expectation.snapshotId) return {
24928
- ok: false,
24929
- code: "runtime_snapshot_id_mismatch",
24930
- message: `Runtime snapshot id mismatch: expected ${expectation.snapshotId}, got ${latest.snapshotId}`
24931
- };
24932
- if (expectation.version !== void 0 && latest.version !== expectation.version) return {
24933
- ok: false,
24934
- code: "runtime_snapshot_version_mismatch",
24935
- message: `Runtime snapshot version mismatch: expected ${expectation.version}, got ${latest.version}`
24936
- };
24937
- if (expectation.checksum && latest.checksum !== expectation.checksum) return {
24938
- ok: false,
24939
- code: "runtime_snapshot_checksum_mismatch",
24940
- message: `Runtime snapshot checksum mismatch: expected ${expectation.checksum}, got ${latest.checksum}`
24941
- };
24650
+ if (!latest) return failure("runtime_snapshot_not_found", `No runtime snapshot found for org=${scope.orgId} project=${scope.projectId} env=${scope.envId}`);
24651
+ if (expectation.snapshotId && latest.snapshotId !== expectation.snapshotId) return failure("runtime_snapshot_id_mismatch", `Runtime snapshot id mismatch: expected ${expectation.snapshotId}, got ${latest.snapshotId}`);
24652
+ if (expectation.version !== void 0 && latest.version !== expectation.version) return failure("runtime_snapshot_version_mismatch", `Runtime snapshot version mismatch: expected ${expectation.version}, got ${latest.version}`);
24653
+ if (expectation.checksum && latest.checksum !== expectation.checksum) return failure("runtime_snapshot_checksum_mismatch", `Runtime snapshot checksum mismatch: expected ${expectation.checksum}, got ${latest.checksum}`);
24942
24654
  return { ok: true };
24943
24655
  }
24944
24656
  function makeScopeKey(scope) {
@@ -25002,9 +24714,17 @@ function createInMemoryRouterApiRuntimeSnapshotConsumer() {
25002
24714
  };
25003
24715
  }
25004
24716
  //#endregion
24717
+ //#region ../shared-ts/src/tenant-root/tenantRootIdentifier.ts
24718
+ function hasControlCharacters(value) {
24719
+ for (const character of value) {
24720
+ const codePoint = character.codePointAt(0) ?? 0;
24721
+ if (codePoint <= 31 || codePoint >= 127 && codePoint <= 159) return true;
24722
+ }
24723
+ return false;
24724
+ }
24725
+ //#endregion
25005
24726
  //#region ../shared-ts/src/tenant-root/tenantRootIdentity.ts
25006
24727
  const TENANT_ROOT_IDENTITY_DOMAIN_V1 = new TextEncoder().encode("seams/tenant-root-identity/v1");
25007
- const TENANT_ROOT_IDENTITY_MAX_IDENTIFIER_BYTES_V1 = 256;
25008
24728
  function concatenateBytes(parts) {
25009
24729
  let length = 0;
25010
24730
  for (const part of parts) length += part.length;
@@ -25023,13 +24743,6 @@ function hasLeadingOrTrailingRustWhitespace(value) {
25023
24743
  const codePoints = Array.from(value, (character) => character.codePointAt(0) ?? 0);
25024
24744
  return codePoints.length > 0 && (isRustWhitespace(codePoints[0]) || isRustWhitespace(codePoints[codePoints.length - 1]));
25025
24745
  }
25026
- function hasControlCharacters(value) {
25027
- for (const character of value) {
25028
- const codePoint = character.codePointAt(0) ?? 0;
25029
- if (codePoint <= 31 || codePoint >= 127 && codePoint <= 159) return true;
25030
- }
25031
- return false;
25032
- }
25033
24746
  function hasUnpairedSurrogate(value) {
25034
24747
  for (let index = 0; index < value.length; index += 1) {
25035
24748
  const codeUnit = value.charCodeAt(index);
@@ -25047,7 +24760,7 @@ function isCanonicalTenantRootIdentityField(value) {
25047
24760
  if (typeof value !== "string" || value.length === 0) return false;
25048
24761
  if (hasLeadingOrTrailingRustWhitespace(value) || hasControlCharacters(value)) return false;
25049
24762
  if (hasUnpairedSurrogate(value)) return false;
25050
- return new TextEncoder().encode(value).length <= TENANT_ROOT_IDENTITY_MAX_IDENTIFIER_BYTES_V1;
24763
+ return new TextEncoder().encode(value).length <= 256;
25051
24764
  }
25052
24765
  function lengthPrefixTenantRootIdentityField(value) {
25053
24766
  const output = new Uint8Array(4 + value.length);
@@ -26320,8 +26033,8 @@ function resolveTraceContext(request) {
26320
26033
  var InMemoryRouterAbEd25519YaoExportStateV1 = class {
26321
26034
  constructor() {
26322
26035
  this.exports = /* @__PURE__ */ new Map();
26323
- this.authorizationNonces = /* @__PURE__ */ new Set();
26324
- this.authorizationUncertain = /* @__PURE__ */ new Set();
26036
+ this.authorizationNonceOwners = /* @__PURE__ */ new Map();
26037
+ this.authorizationUncertainOwners = /* @__PURE__ */ new Map();
26325
26038
  }
26326
26039
  };
26327
26040
  const ROUTES = Object.freeze([defineRoute({