@seams/wallet-server 0.7.1 → 0.7.3

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