@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
@@ -1,5 +1,6 @@
1
- import { requireNonEmptyString } from "../../../../shared-ts/src/utils/validation.js";
2
- import { isD1DatabaseLike } from "../../../../storage/d1Sql.js";
1
+ import { isPlainObject, requireNonEmptyString } from "../../../../shared-ts/src/utils/validation.js";
2
+ import { normalizeRuntimePolicyScope } from "../../../../shared-ts/src/threshold/signingRootScope.js";
3
+ import { isD1DatabaseLike, parseD1JsonColumn } from "../../../../storage/d1Sql.js";
3
4
  import { abusePrincipalKey, runtimePolicyScopeKey } from "../../../domains/signingOperations/routerAbNormalSigningAdmissionCore.js";
4
5
  //#region src/router/cloudflare/d1/signingAdmission/d1RouterAbNormalSigningAdmissionStore.ts
5
6
  const ROUTER_AB_NORMAL_SIGNING_ADMISSION_TABLE = "router_ab_normal_signing_admission_records";
@@ -11,8 +12,12 @@ var CloudflareD1RouterAbNormalSigningAdmissionStore = class {
11
12
  this.now = options.now || Date.now;
12
13
  }
13
14
  async evaluatePolicy(input) {
15
+ if (input.curve === "ecdsa" && input.policyReadSource.kind === "credential_snapshot") {
16
+ const decision = input.policyReadSource.policyRead.resolve(this.database, this.storageNamespace, input);
17
+ if (decision) return decision;
18
+ }
14
19
  const scope = input.runtimePolicyScope;
15
- const row = await this.database.prepare(`WITH scope(namespace, org_id, project_id, env_id, signing_root_version,
20
+ return parsePolicyRow(await this.database.prepare(`WITH scope(namespace, org_id, project_id, env_id, signing_root_version,
16
21
  project_key, abuse_key) AS (VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7))
17
22
  SELECT project.record_key AS project_key, project.decision AS project_decision,
18
23
  project.retry_after_ms AS project_retry_after_ms,
@@ -28,27 +33,7 @@ var CloudflareD1RouterAbNormalSigningAdmissionStore = class {
28
33
  ON abuse.namespace = scope.namespace AND abuse.org_id = scope.org_id
29
34
  AND abuse.project_id = scope.project_id AND abuse.env_id = scope.env_id
30
35
  AND abuse.signing_root_version = scope.signing_root_version
31
- AND abuse.record_kind = 'abuse' AND abuse.record_key = scope.abuse_key`).bind(this.storageNamespace, scope.orgId, scope.projectId, scope.envId, scope.signingRootVersion, runtimePolicyScopeKey(scope), abusePrincipalKey(input)).first();
32
- if (!row) throw new Error("Router A/B admission policy snapshot is missing");
33
- if (row.project_key !== null) {
34
- const project = parseProjectPolicyDecision({
35
- decision: row.project_decision,
36
- retry_after_ms: row.project_retry_after_ms
37
- });
38
- if (project.kind === "rejected") return {
39
- kind: "project_policy_rejected",
40
- retryAfterMs: project.retryAfterMs
41
- };
42
- }
43
- if (row.abuse_key === null) return { kind: "allowed" };
44
- const abuse = parseAbuseDecision({
45
- decision: row.abuse_decision,
46
- retry_after_ms: row.abuse_retry_after_ms
47
- });
48
- return abuse.kind === "rejected" ? {
49
- kind: "abuse_rejected",
50
- retryAfterMs: abuse.retryAfterMs
51
- } : abuse;
36
+ AND abuse.record_kind = 'abuse' AND abuse.record_key = scope.abuse_key`).bind(this.storageNamespace, scope.orgId, scope.projectId, scope.envId, scope.signingRootVersion, runtimePolicyScopeKey(scope), abusePrincipalKey(input)).first());
52
37
  }
53
38
  async setProjectPolicy(scope, decision) {
54
39
  const normalized = normalizeProjectPolicyDecision(decision);
@@ -158,7 +143,116 @@ function requirePositiveInteger(label, value) {
158
143
  function assertNever(value) {
159
144
  throw new Error(`Unexpected Router A/B normal-signing admission branch: ${String(value)}`);
160
145
  }
146
+ function parsePolicyRow(row) {
147
+ if (!row) throw new Error("Router A/B admission policy snapshot is missing");
148
+ if (row.project_key !== null) {
149
+ const project = parseProjectPolicyDecision({
150
+ decision: row.project_decision,
151
+ retry_after_ms: row.project_retry_after_ms
152
+ });
153
+ if (project.kind === "rejected") return {
154
+ kind: "project_policy_rejected",
155
+ retryAfterMs: project.retryAfterMs
156
+ };
157
+ }
158
+ if (row.abuse_key === null) return { kind: "allowed" };
159
+ const abuse = parseAbuseDecision({
160
+ decision: row.abuse_decision,
161
+ retry_after_ms: row.abuse_retry_after_ms
162
+ });
163
+ return abuse.kind === "rejected" ? {
164
+ kind: "abuse_rejected",
165
+ retryAfterMs: abuse.retryAfterMs
166
+ } : abuse;
167
+ }
168
+ var D1EcdsaAdmissionPolicyRead = class D1EcdsaAdmissionPolicyRead {
169
+ #decisions;
170
+ constructor(database, namespace, walletId, activationId, decisions) {
171
+ this.database = database;
172
+ this.namespace = namespace;
173
+ this.walletId = walletId;
174
+ this.activationId = activationId;
175
+ this.#decisions = decisions;
176
+ }
177
+ static fromRows(database, namespace, walletId, activationId, rows) {
178
+ if (!Array.isArray(rows)) throw new Error("ECDSA policy candidates are invalid");
179
+ const decisions = /* @__PURE__ */ new Map();
180
+ for (const row of rows) {
181
+ if (!isPlainObject(row)) throw new Error("ECDSA policy candidate is invalid");
182
+ const key = runtimePolicyScopeKey(normalizeRuntimePolicyScope(parseD1JsonColumn(row.scope_json)));
183
+ if (decisions.has(key)) throw new Error("ECDSA policy scope is ambiguous");
184
+ try {
185
+ const decision = parsePolicyRow({
186
+ project_key: row.project_key,
187
+ project_decision: row.project_decision,
188
+ project_retry_after_ms: row.project_retry_after_ms,
189
+ abuse_key: row.abuse_key,
190
+ abuse_decision: row.abuse_decision,
191
+ abuse_retry_after_ms: row.abuse_retry_after_ms
192
+ });
193
+ decisions.set(key, {
194
+ ok: true,
195
+ decision
196
+ });
197
+ } catch (error) {
198
+ decisions.set(key, {
199
+ ok: false,
200
+ message: error instanceof Error ? error.message : "ECDSA policy read failed"
201
+ });
202
+ }
203
+ }
204
+ return new D1EcdsaAdmissionPolicyRead(database, namespace, walletId, activationId, decisions);
205
+ }
206
+ resolve(database, namespace, input) {
207
+ if (database !== this.database || namespace !== this.namespace) return null;
208
+ if (input.walletId !== this.walletId || input.materialActivationId !== this.activationId) throw new Error("ECDSA policy credential scope does not match");
209
+ const result = this.#decisions.get(runtimePolicyScopeKey(input.runtimePolicyScope));
210
+ if (!result) throw new Error("Verified ECDSA material policy scope is missing");
211
+ if (!result.ok) throw new Error(result.message);
212
+ return result.decision;
213
+ }
214
+ };
215
+ const ECDSA_CREDENTIAL_POLICY_PROJECTION = `
216
+ (WITH candidates AS (
217
+ SELECT DISTINCT json_extract(signer.record_json, '$.runtimePolicyScope') AS scope_json
218
+ FROM wallet_signers AS signer
219
+ WHERE signer.namespace = session.namespace AND signer.org_id = session.org_id
220
+ AND signer.project_id = session.project_id AND signer.env_id = session.env_id
221
+ AND signer.wallet_id = session.wallet_id AND signer.signer_family = 'ecdsa'
222
+ AND json_valid(signer.record_json)
223
+ ), scopes AS (
224
+ SELECT scope_json,
225
+ json_extract(scope_json, '$.orgId') AS org_id,
226
+ json_extract(scope_json, '$.projectId') AS project_id,
227
+ json_extract(scope_json, '$.envId') AS env_id,
228
+ json_extract(scope_json, '$.signingRootVersion') AS signing_root_version,
229
+ json_extract(scope_json, '$.orgId') || char(31) ||
230
+ json_extract(scope_json, '$.projectId') || char(31) ||
231
+ json_extract(scope_json, '$.envId') || char(31) ||
232
+ json_extract(scope_json, '$.signingRootVersion') AS project_key
233
+ FROM candidates
234
+ )
235
+ SELECT json_group_array(json_object(
236
+ 'scope_json', scopes.scope_json,
237
+ 'project_key', project.record_key, 'project_decision', project.decision,
238
+ 'project_retry_after_ms', project.retry_after_ms,
239
+ 'abuse_key', abuse.record_key, 'abuse_decision', abuse.decision,
240
+ 'abuse_retry_after_ms', abuse.retry_after_ms))
241
+ FROM scopes
242
+ LEFT JOIN router_ab_normal_signing_admission_records AS project
243
+ ON project.namespace = session.namespace AND project.org_id = scopes.org_id
244
+ AND project.project_id = scopes.project_id AND project.env_id = scopes.env_id
245
+ AND project.signing_root_version = scopes.signing_root_version
246
+ AND project.record_kind = 'project_policy' AND project.record_key = scopes.project_key
247
+ LEFT JOIN router_ab_normal_signing_admission_records AS abuse
248
+ ON abuse.namespace = session.namespace AND abuse.org_id = scopes.org_id
249
+ AND abuse.project_id = scopes.project_id AND abuse.env_id = scopes.env_id
250
+ AND abuse.signing_root_version = scopes.signing_root_version
251
+ AND abuse.record_kind = 'abuse'
252
+ AND abuse.record_key = scopes.project_key || char(31) || session.wallet_id || char(31) ||
253
+ 'material_activation:' || ? || char(31) || 'ecdsa'
254
+ ) AS ecdsa_policy_records_json,`;
161
255
  //#endregion
162
- export { CloudflareD1RouterAbNormalSigningAdmissionStore, createCloudflareD1RouterAbNormalSigningAdmissionStore };
256
+ export { CloudflareD1RouterAbNormalSigningAdmissionStore, D1EcdsaAdmissionPolicyRead, ECDSA_CREDENTIAL_POLICY_PROJECTION, createCloudflareD1RouterAbNormalSigningAdmissionStore };
163
257
 
164
258
  //# sourceMappingURL=d1RouterAbNormalSigningAdmissionStore.js.map
@@ -3,6 +3,7 @@ import { parseDigestB64u } from "../../../../shared-ts/src/utils/canonicalPrimit
3
3
  import { normalizeOptionalTrimmedString } from "../../../../shared-ts/src/utils/normalize.js";
4
4
  import "../../../../shared-ts/src/utils/validation.js";
5
5
  import { secureRandomBase64Url } from "../../../../shared-ts/src/utils/secureRandomId.js";
6
+ import { failedVerification, failure } from "../../../../shared-ts/src/utils/failure.js";
6
7
  import { decodeWebAuthnBase64UrlOrBase64, parseWebAuthnAuthenticationCredential, parseWebAuthnClientDataJsonBase64url, webAuthnCredentialIdB64uFromCredential, webAuthnOriginHostnameOrEmpty } from "../../../auth/webAuthnCredentialCodecs.js";
7
8
  import { nonNegativeSafeInteger, optionalNonNegativeInteger, parseD1BoundaryWalletId, parseD1BoundaryWalletIdResult, parseJsonObject } from "../auth/d1RouterApiAuthBoundary.js";
8
9
  import { parseWebAuthnAuthenticatorRowDeviceInfo, webAuthnSyncWalletBindingFromCredentialBinding } from "./d1WebAuthnRecords.js";
@@ -21,11 +22,7 @@ var CloudflareD1WebAuthnAuthService = class {
21
22
  async listWebAuthnAuthenticatorsForUser(input) {
22
23
  try {
23
24
  const userId = parseD1BoundaryWalletIdResult(input.userId);
24
- if (!userId.ok) return {
25
- ok: false,
26
- code: "invalid_args",
27
- message: userId.code === "missing" ? "Missing userId" : "Invalid userId"
28
- };
25
+ if (!userId.ok) return failure("invalid_args", userId.code === "missing" ? "Missing userId" : "Invalid userId");
29
26
  const rpId = normalizeOptionalTrimmedString(input.rpId);
30
27
  const authRows = await this.webAuthnStore.readAuthenticatorRows(userId.value);
31
28
  const bindings = await this.webAuthnStore.readBindingRows({
@@ -55,27 +52,15 @@ var CloudflareD1WebAuthnAuthService = class {
55
52
  authenticators
56
53
  };
57
54
  } catch (error) {
58
- return {
59
- ok: false,
60
- code: "internal",
61
- message: errorMessage(error) || "Failed to list authenticators"
62
- };
55
+ return failure("internal", errorMessage(error) || "Failed to list authenticators");
63
56
  }
64
57
  }
65
58
  async createWebAuthnLoginOptions(input) {
66
59
  try {
67
60
  const userId = parseD1BoundaryWalletIdResult(input.userId ?? input.user_id);
68
61
  const rpId = normalizeOptionalTrimmedString(input.rpId ?? input.rp_id);
69
- if (!userId.ok) return {
70
- ok: false,
71
- code: "invalid_body",
72
- message: userId.code === "missing" ? "Missing userId" : "Invalid userId"
73
- };
74
- if (!rpId) return {
75
- ok: false,
76
- code: "invalid_body",
77
- message: "Missing rpId"
78
- };
62
+ if (!userId.ok) return failure("invalid_body", userId.code === "missing" ? "Missing userId" : "Invalid userId");
63
+ if (!rpId) return failure("invalid_body", "Missing rpId");
79
64
  const createdAtMs = Date.now();
80
65
  const expiresAtMs = createdAtMs + webAuthnLoginChallengeTtlMs(input.ttlMs ?? input.ttl_ms);
81
66
  const challengeId = secureRandomBase64Url(16, "WebAuthn login challenge id");
@@ -96,11 +81,7 @@ var CloudflareD1WebAuthnAuthService = class {
96
81
  seenCredentialIds.add(credentialId);
97
82
  credentialIds.push(credentialId);
98
83
  }
99
- if (credentialIds.length === 0) return {
100
- ok: false,
101
- code: "unknown_credential",
102
- message: "Wallet has no registered passkey credential"
103
- };
84
+ if (credentialIds.length === 0) return failure("unknown_credential", "Wallet has no registered passkey credential");
104
85
  const record = {
105
86
  version: "webauthn_login_challenge_v1",
106
87
  challengeId,
@@ -125,28 +106,16 @@ var CloudflareD1WebAuthnAuthService = class {
125
106
  expiresAtMs
126
107
  };
127
108
  } catch (error) {
128
- return {
129
- ok: false,
130
- code: "internal",
131
- message: errorMessage(error) || "Failed to create login options"
132
- };
109
+ return failure("internal", errorMessage(error) || "Failed to create login options");
133
110
  }
134
111
  }
135
112
  async createWebAuthnSyncAccountOptions(input) {
136
113
  try {
137
114
  const rpId = normalizeOptionalTrimmedString(input.rp_id);
138
- if (!rpId) return {
139
- ok: false,
140
- code: "invalid_body",
141
- message: "Missing rp_id"
142
- };
115
+ if (!rpId) return failure("invalid_body", "Missing rp_id");
143
116
  const expectedUserIdRaw = normalizeOptionalTrimmedString(input.account_id);
144
117
  const expectedUserId = expectedUserIdRaw ? parseD1BoundaryWalletId(expectedUserIdRaw) : null;
145
- if (expectedUserIdRaw && !expectedUserId) return {
146
- ok: false,
147
- code: "invalid_body",
148
- message: "Invalid wallet account_id"
149
- };
118
+ if (expectedUserIdRaw && !expectedUserId) return failure("invalid_body", "Invalid wallet account_id");
150
119
  const createdAtMs = Date.now();
151
120
  const expiresAtMs = createdAtMs + webAuthnLoginChallengeTtlMs(input.ttlMs ?? input.ttl_ms);
152
121
  const challengeId = secureRandomBase64Url(16, "WebAuthn sync challenge id");
@@ -172,11 +141,7 @@ var CloudflareD1WebAuthnAuthService = class {
172
141
  }
173
142
  if (credentialId && activeCredentialIds.has(credentialId) && !walletBinding) walletBinding = webAuthnSyncWalletBindingFromCredentialBinding(binding) || void 0;
174
143
  }
175
- if (credentialIds.length === 0) return {
176
- ok: false,
177
- code: "unknown_credential",
178
- message: "Wallet has no registered active passkey credential"
179
- };
144
+ if (credentialIds.length === 0) return failure("unknown_credential", "Wallet has no registered active passkey credential");
180
145
  }
181
146
  const record = {
182
147
  version: "webauthn_sync_challenge_v1",
@@ -203,11 +168,7 @@ var CloudflareD1WebAuthnAuthService = class {
203
168
  expiresAtMs
204
169
  };
205
170
  } catch (error) {
206
- return {
207
- ok: false,
208
- code: "internal",
209
- message: errorMessage(error) || "Failed to create sync account options"
210
- };
171
+ return failure("internal", errorMessage(error) || "Failed to create sync account options");
211
172
  }
212
173
  }
213
174
  async verifyWebAuthnAuthenticationLite(input) {
@@ -349,56 +310,22 @@ var CloudflareD1WebAuthnAuthService = class {
349
310
  async verifyWebAuthnLogin(input) {
350
311
  try {
351
312
  const challengeId = normalizeOptionalTrimmedString(input.challengeId ?? input.challenge_id);
352
- if (!challengeId) return {
353
- ok: false,
354
- code: "invalid_body",
355
- message: "Missing challengeId"
356
- };
313
+ if (!challengeId) return failure("invalid_body", "Missing challengeId");
357
314
  const challenge = await this.webAuthnStore.consumeLoginChallenge(challengeId);
358
- if (!challenge) return {
359
- ok: false,
360
- verified: false,
361
- code: "challenge_expired_or_invalid",
362
- message: "Login challenge expired or invalid"
363
- };
315
+ if (!challenge) return failedVerification("challenge_expired_or_invalid", "Login challenge expired or invalid");
364
316
  const expectedOrigin = normalizeOptionalTrimmedString(input.expected_origin);
365
- if (!expectedOrigin) return {
366
- ok: false,
367
- verified: false,
368
- code: "invalid_body",
369
- message: "expected_origin is required for WebAuthn authentication verification"
370
- };
317
+ if (!expectedOrigin) return failedVerification("invalid_body", "expected_origin is required for WebAuthn authentication verification");
371
318
  const rpId = parseWebAuthnRpId(challenge.rpId);
372
- if (!rpId.ok) return {
373
- ok: false,
374
- verified: false,
375
- code: "internal",
376
- message: `Stored login challenge rpId is invalid: ${rpId.error.message}`
377
- };
319
+ if (!rpId.ok) return failedVerification("internal", `Stored login challenge rpId is invalid: ${rpId.error.message}`);
378
320
  const credential = parseWebAuthnAuthenticationCredential(input.webauthn_authentication);
379
- if (!credential) return {
380
- ok: false,
381
- verified: false,
382
- code: "invalid_body",
383
- message: "Missing webauthn_authentication"
384
- };
321
+ if (!credential) return failedVerification("invalid_body", "Missing webauthn_authentication");
385
322
  const credentialId = webAuthnCredentialIdB64uFromCredential(credential);
386
- if (!credentialId.ok) return {
387
- ok: false,
388
- verified: false,
389
- code: credentialId.code,
390
- message: credentialId.message
391
- };
323
+ if (!credentialId.ok) return failedVerification(credentialId.code, credentialId.message);
392
324
  const activeMethod = await this.walletAuthMethodStore.getPasskeyV2({
393
325
  rpId: challenge.rpId,
394
326
  credentialIdB64u: credentialId.credentialIdB64u
395
327
  });
396
- if (!activeMethod || activeMethod.kind !== "passkey" || activeMethod.status !== "active" || String(activeMethod.walletId) !== String(challenge.userId) || String(activeMethod.rpId) !== String(challenge.rpId) || String(activeMethod.credentialIdB64u) !== String(credentialId.credentialIdB64u)) return {
397
- ok: false,
398
- verified: false,
399
- code: "unknown_credential",
400
- message: "Credential is not active for this wallet"
401
- };
328
+ if (!activeMethod || activeMethod.kind !== "passkey" || activeMethod.status !== "active" || String(activeMethod.walletId) !== String(challenge.userId) || String(activeMethod.rpId) !== String(challenge.rpId) || String(activeMethod.credentialIdB64u) !== String(credentialId.credentialIdB64u)) return failedVerification("unknown_credential", "Credential is not active for this wallet");
402
329
  const verificationFailure = webAuthnAuthenticationFailure(await this.verifyWebAuthnAuthenticationLite({
403
330
  userId: challenge.userId,
404
331
  rpId: rpId.value,
@@ -424,43 +351,19 @@ var CloudflareD1WebAuthnAuthService = class {
424
351
  ed25519: loginSigner.ed25519
425
352
  };
426
353
  } catch (error) {
427
- return {
428
- ok: false,
429
- verified: false,
430
- code: "internal",
431
- message: errorMessage(error) || "Login verification failed"
432
- };
354
+ return failedVerification("internal", errorMessage(error) || "Login verification failed");
433
355
  }
434
356
  }
435
357
  async verifyWebAuthnSyncAccount(input) {
436
358
  try {
437
359
  const challengeId = normalizeOptionalTrimmedString(input.challengeId ?? input.challenge_id);
438
- if (!challengeId) return {
439
- ok: false,
440
- code: "invalid_body",
441
- message: "Missing challengeId"
442
- };
360
+ if (!challengeId) return failure("invalid_body", "Missing challengeId");
443
361
  const challenge = await this.webAuthnStore.consumeSyncChallenge(challengeId);
444
- if (!challenge) return {
445
- ok: false,
446
- verified: false,
447
- code: "challenge_expired_or_invalid",
448
- message: "Sync challenge expired or invalid"
449
- };
362
+ if (!challenge) return failedVerification("challenge_expired_or_invalid", "Sync challenge expired or invalid");
450
363
  const credential = parseWebAuthnAuthenticationCredential(input.webauthn_authentication);
451
- if (!credential) return {
452
- ok: false,
453
- verified: false,
454
- code: "invalid_body",
455
- message: "Missing webauthn_authentication"
456
- };
364
+ if (!credential) return failedVerification("invalid_body", "Missing webauthn_authentication");
457
365
  const credentialId = webAuthnCredentialIdB64uFromCredential(credential);
458
- if (!credentialId.ok) return {
459
- ok: false,
460
- verified: false,
461
- code: credentialId.code,
462
- message: credentialId.message
463
- };
366
+ if (!credentialId.ok) return failedVerification(credentialId.code, credentialId.message);
464
367
  const syncBinding = webAuthnSyncCredentialBinding(await this.webAuthnStore.readBindingByCredential({
465
368
  rpId: challenge.rpId,
466
369
  credentialIdB64u: credentialId.credentialIdB64u
@@ -471,26 +374,11 @@ var CloudflareD1WebAuthnAuthService = class {
471
374
  rpId: challenge.rpId,
472
375
  credentialIdB64u: credentialId.credentialIdB64u
473
376
  });
474
- if (!activeMethod || activeMethod.kind !== "passkey" || activeMethod.status !== "active" || String(activeMethod.walletId) !== String(binding.userId) || String(activeMethod.rpId) !== String(challenge.rpId) || String(activeMethod.credentialIdB64u) !== String(credentialId.credentialIdB64u)) return {
475
- ok: false,
476
- verified: false,
477
- code: "unknown_credential",
478
- message: "Credential is not active for this wallet"
479
- };
377
+ if (!activeMethod || activeMethod.kind !== "passkey" || activeMethod.status !== "active" || String(activeMethod.walletId) !== String(binding.userId) || String(activeMethod.rpId) !== String(challenge.rpId) || String(activeMethod.credentialIdB64u) !== String(credentialId.credentialIdB64u)) return failedVerification("unknown_credential", "Credential is not active for this wallet");
480
378
  const expectedOrigin = normalizeOptionalTrimmedString(input.expected_origin);
481
- if (!expectedOrigin) return {
482
- ok: false,
483
- verified: false,
484
- code: "invalid_body",
485
- message: "expected_origin is required for WebAuthn authentication verification"
486
- };
379
+ if (!expectedOrigin) return failedVerification("invalid_body", "expected_origin is required for WebAuthn authentication verification");
487
380
  const rpId = parseWebAuthnRpId(binding.rpId);
488
- if (!rpId.ok) return {
489
- ok: false,
490
- verified: false,
491
- code: "internal",
492
- message: `Stored sync credential binding rpId is invalid: ${rpId.error.message}`
493
- };
381
+ if (!rpId.ok) return failedVerification("internal", `Stored sync credential binding rpId is invalid: ${rpId.error.message}`);
494
382
  const verificationFailure = webAuthnAuthenticationFailure(await this.verifyWebAuthnAuthenticationLite({
495
383
  userId: binding.userId,
496
384
  rpId: rpId.value,
@@ -503,36 +391,16 @@ var CloudflareD1WebAuthnAuthService = class {
503
391
  userId: binding.userId,
504
392
  credentialIdB64u: credentialId.credentialIdB64u
505
393
  });
506
- if (!authenticator) return {
507
- ok: false,
508
- verified: false,
509
- code: "unknown_credential",
510
- message: "Credential is not registered for user"
511
- };
394
+ if (!authenticator) return failedVerification("unknown_credential", "Credential is not registered for user");
512
395
  const walletBinding = webAuthnSyncWalletBindingFromCredentialBinding(binding);
513
- if (!walletBinding) return {
514
- ok: false,
515
- verified: false,
516
- code: "internal",
517
- message: "Credential binding is missing wallet identity fields"
518
- };
396
+ if (!walletBinding) return failedVerification("internal", "Credential binding is missing wallet identity fields");
519
397
  const walletId = parseD1BoundaryWalletId(walletBinding.walletId);
520
- if (!walletId) return {
521
- ok: false,
522
- verified: false,
523
- code: "internal",
524
- message: "Credential binding contains an invalid wallet ID"
525
- };
398
+ if (!walletId) return failedVerification("internal", "Credential binding contains an invalid wallet ID");
526
399
  const ed25519Manifest = await this.walletManifestSource.getEd25519KeyManifestBySlot({
527
400
  walletId,
528
401
  signerSlot: walletBinding.signerSlot
529
402
  });
530
- if (!ed25519Manifest) return {
531
- ok: false,
532
- verified: false,
533
- code: "ed25519_not_provisioned",
534
- message: "Wallet has no Ed25519 signer yet; NEAR provisioning has not completed"
535
- };
403
+ if (!ed25519Manifest) return failedVerification("ed25519_not_provisioned", "Wallet has no Ed25519 signer yet; NEAR provisioning has not completed");
536
404
  const thresholdEd25519 = binding.relayerKeyId && binding.publicKey ? {
537
405
  relayerKeyId: binding.relayerKeyId,
538
406
  authorityScope: {
@@ -566,12 +434,7 @@ var CloudflareD1WebAuthnAuthService = class {
566
434
  ...thresholdEd25519 ? { thresholdEd25519 } : {}
567
435
  };
568
436
  } catch (error) {
569
- return {
570
- ok: false,
571
- verified: false,
572
- code: "internal",
573
- message: errorMessage(error) || "Sync verification failed"
574
- };
437
+ return failedVerification("internal", errorMessage(error) || "Sync verification failed");
575
438
  }
576
439
  }
577
440
  };
@@ -7,6 +7,7 @@ import { normalizeRuntimePolicyScope } from "../../../../shared-ts/src/threshold
7
7
  import { parseWalletAuthMethodRecordV2 } from "../../../../shared-ts/src/utils/walletAuthMethodRecord.js";
8
8
  import { parseWalletAuthorityV1 } from "../../../../shared-ts/src/authorization/walletAuthority.js";
9
9
  import { parseWebAuthnAuthenticatorDeviceInfoJson } from "../../../../shared-ts/src/utils/webauthnDeviceInfo.js";
10
+ import { hasExactKeys } from "../../../../shared-ts/src/utils/exactKeys.js";
10
11
  import "../../../../shared-ts/src/passkey-custody/index.js";
11
12
  import { parseRecoveryCodeReservationId } from "../../../../shared-ts/src/wallet-recovery/recoveryCodeReservation.js";
12
13
  import { nonNegativeSafeInteger, optionalNonNegativeInteger, positiveInteger } from "../auth/d1RouterApiAuthBoundary.js";
@@ -25,7 +26,7 @@ function parseWebAuthnLoginChallengeRecord(input) {
25
26
  }
26
27
  if (prototype !== Object.prototype && prototype !== null) return null;
27
28
  const record = candidate;
28
- if (!hasExactFields(record, [
29
+ if (!hasExactKeys(record, [
29
30
  "version",
30
31
  "challengeId",
31
32
  "userId",
@@ -65,7 +66,7 @@ function parseWebAuthnSyncChallengeRecord(input) {
65
66
  }
66
67
  if (prototype !== Object.prototype && prototype !== null) return null;
67
68
  const record = candidate;
68
- if (!hasExactFields(record, Object.hasOwn(record, "expectedUserId") ? [
69
+ if (!hasExactKeys(record, Object.hasOwn(record, "expectedUserId") ? [
69
70
  "version",
70
71
  "challengeId",
71
72
  "rpId",
@@ -263,7 +264,7 @@ function parseWebAuthnRecoveryContinuityEnvelopeAnchor(input) {
263
264
  const updatedAtMs = positiveInteger(record.updatedAtMs);
264
265
  if (!kind || !envelopeId.ok || !walletId.ok || !envelopeRevision || updatedAtMs === null || record.bindingKind !== "wallet_custody_seed_v1") return null;
265
266
  if (kind === "passkey") {
266
- if (!hasExactFields(record, [
267
+ if (!hasExactKeys(record, [
267
268
  "kind",
268
269
  "envelopeId",
269
270
  "walletId",
@@ -288,7 +289,7 @@ function parseWebAuthnRecoveryContinuityEnvelopeAnchor(input) {
288
289
  };
289
290
  }
290
291
  if (kind === "email_otp") {
291
- if (!hasExactFields(record, [
292
+ if (!hasExactKeys(record, [
292
293
  "kind",
293
294
  "envelopeId",
294
295
  "walletId",
@@ -321,10 +322,6 @@ function parseRecoveryEnvelopeRevision(input) {
321
322
  return null;
322
323
  }
323
324
  }
324
- function hasExactFields(record, expectedFields) {
325
- const fields = Object.keys(record);
326
- return fields.length === expectedFields.length && expectedFields.every((field) => fields.includes(field));
327
- }
328
325
  function parseWebAuthnAuthenticator(row) {
329
326
  const credentialIdB64u = normalizeOptionalTrimmedString(row?.credential_id_b64u);
330
327
  const credentialPublicKeyB64u = normalizeOptionalTrimmedString(row?.credential_public_key_b64u);
@@ -478,7 +475,7 @@ function parseWebAuthnRuntimePolicyScope(raw) {
478
475
  }
479
476
  if (prototype !== Object.prototype && prototype !== null) return void 0;
480
477
  const record = raw;
481
- if (!hasExactFields(record, [
478
+ if (!hasExactKeys(record, [
482
479
  "orgId",
483
480
  "projectId",
484
481
  "envId",