@seams/wallet-server 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (369) hide show
  1. package/THIRD_PARTY_NOTICES.md +7 -1
  2. package/artifact-manifest.json +196 -41
  3. package/cloudflare-router-ab/build/deriver-a/build-stamp.json +1 -1
  4. package/cloudflare-router-ab/build/deriver-a/index.js +2 -2
  5. package/cloudflare-router-ab/build/deriver-a/index_bg.wasm +0 -0
  6. package/cloudflare-router-ab/build/deriver-b/build-stamp.json +1 -1
  7. package/cloudflare-router-ab/build/deriver-b/index.js +2 -2
  8. package/cloudflare-router-ab/build/deriver-b/index_bg.wasm +0 -0
  9. package/cloudflare-router-ab/build/local-tools/darwin-arm64/router_ab_local_init +0 -0
  10. package/cloudflare-router-ab/build/local-tools/darwin-x64/router_ab_local_init +0 -0
  11. package/cloudflare-router-ab/build/local-tools/linux-x64/router_ab_local_init +0 -0
  12. package/cloudflare-router-ab/build/router/build-stamp.json +1 -1
  13. package/cloudflare-router-ab/build/router/index.js +2 -2
  14. package/cloudflare-router-ab/build/router/index_bg.wasm +0 -0
  15. package/cloudflare-router-ab/build/signing-worker/build-stamp.json +1 -1
  16. package/cloudflare-router-ab/build/signing-worker/index.js +2 -2
  17. package/cloudflare-router-ab/build/signing-worker/index_bg.wasm +0 -0
  18. package/cloudflare-router-ab/build/tenant-root-control-plane/build-stamp.json +1 -1
  19. package/cloudflare-router-ab/build/tenant-root-control-plane/index.js +2 -2
  20. package/cloudflare-router-ab/build/tenant-root-control-plane/index_bg.wasm +0 -0
  21. package/cloudflare-router-ab/migrations/deriver-a/0019_wallet_object_addresses.sql +10 -0
  22. package/cloudflare-router-ab/migrations/deriver-b/0019_wallet_object_addresses.sql +10 -0
  23. package/cloudflare-router-ab/scripts/prepare-local-runtime-config.mjs +3 -117
  24. package/cloudflare-router-ab/wrangler.deriver-a.toml +0 -8
  25. package/cloudflare-router-ab/wrangler.deriver-b.toml +24 -8
  26. package/cloudflare-router-ab/wrangler.router.toml +0 -2
  27. package/cloudflare-router-ab/wrangler.signing-worker.toml +29 -0
  28. package/dist/esm/authorization/domain.js +3 -2
  29. package/dist/esm/authorization/ed25519WalletSessionAdmission.js +0 -0
  30. package/dist/esm/authorization/service.js +64 -36
  31. package/dist/esm/cloud-host.js +24 -19
  32. package/dist/esm/core/EmailOtpRecords.js +29 -6
  33. package/dist/esm/core/ThresholdService/routerAb/ecdsaDerivationPoolFillHandlers.js +2 -0
  34. package/dist/esm/core/ThresholdService/routerAb/ecdsaDerivationPresignBridge.js +10 -0
  35. package/dist/esm/core/ThresholdService/routerAb/internalServiceHttp.js +1 -0
  36. package/dist/esm/core/ThresholdService/validation.js +2 -2
  37. package/dist/esm/core/authService/nearPrivateKeySigning.js +1 -1
  38. package/dist/esm/core/authService/webauthn.js +1 -1
  39. package/dist/esm/core/d1Ed25519SignerRead.js +55 -0
  40. package/dist/esm/core/d1WalletStore.js +14 -11
  41. package/dist/esm/core/deviceLinking/linkedDeviceEmailOtpGrant.js +2 -2
  42. package/dist/esm/core/deviceLinking/linkedDeviceManagement.js +1 -1
  43. package/dist/esm/core/deviceLinking/linkedDeviceSessionRecord.js +2 -2
  44. package/dist/esm/core/emailOtpD1Statements.js +1 -0
  45. package/dist/esm/core/nearRelayerAccountProvisioning.js +1 -1
  46. package/dist/esm/core/routerAbSigning/RouterAbEcdsaPresignRuntime.js +4 -0
  47. package/dist/esm/core/signingLanes/WalletExecutionLaneProjection.js +1 -1
  48. package/dist/esm/core/signingMaterial/ordinaryInactiveSignerMaterialReservation.js +1 -0
  49. package/dist/esm/hosted-wallet-gateway.js +93 -10
  50. package/dist/esm/localHostedWalletGatewayHandler.js +12 -9
  51. package/dist/esm/localIntendedYaoSigningFault.js +2 -30
  52. package/dist/esm/localRegistrationSetupAuthority.js +8 -1
  53. package/dist/esm/router/auth/commonRouterUtils.js +17 -10
  54. package/dist/esm/router/auth/routerApiCredentialAuth.js +26 -7
  55. package/dist/esm/router/auth/walletRegistrationContext.js +49 -0
  56. package/dist/esm/router/auth/webAuthnCredentialCodecs.js +1 -1
  57. package/dist/esm/router/cloudflare/d1/auth/d1AuthorizationAssembly.js +4 -3
  58. package/dist/esm/router/cloudflare/d1/auth/d1AuthorizedOperationRouteService.js +2 -0
  59. package/dist/esm/router/cloudflare/d1/auth/d1EmailOtpRouteService.js +25 -0
  60. package/dist/esm/router/cloudflare/d1/auth/d1RouterApiAuthConfig.js +14 -6
  61. package/dist/esm/router/cloudflare/d1/auth/d1RouterApiAuthService.js +44 -40
  62. package/dist/esm/router/cloudflare/d1/auth/walletSessionCredentialReaders.js +17 -1
  63. package/dist/esm/router/cloudflare/d1/authorization/authorizedOperationStatements.js +35 -5
  64. package/dist/esm/router/cloudflare/d1/authorization/d1AuthorizationStore.js +258 -99
  65. package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceAuthorityInstallService.js +31 -4
  66. package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceOwnerAuthorizationProvider.js +1 -1
  67. package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceRequestProofNonceStore.js +1 -1
  68. package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceSessionRecords.js +1 -1
  69. package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceTargetCredentialProvider.js +1 -1
  70. package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceTargetPlanner.js +1 -1
  71. package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceVerifiedLinkBuilder.js +1 -1
  72. package/dist/esm/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoLifecycleDecisionStore.js +11 -2
  73. package/dist/esm/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoProductRegistrationPartitionedStateStore.js +100 -10
  74. package/dist/esm/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoStateWriteFence.js +92 -0
  75. package/dist/esm/router/cloudflare/d1/ed25519Yao/d1WalletCeremonyActivity.js +77 -0
  76. package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeIssuer.js +14 -8
  77. package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeStore.js +14 -8
  78. package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeVerifier.js +3 -1
  79. package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRateLimitStore.js +58 -38
  80. package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRecords.js +27 -20
  81. package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRecoveryService.js +1 -0
  82. package/dist/esm/router/cloudflare/d1/emailOtp/d1GoogleEmailOtpSessionResolver.js +1 -0
  83. package/dist/esm/router/cloudflare/d1/oidc/d1OidcBoundary.js +1 -1
  84. package/dist/esm/router/cloudflare/d1/passkeyCustody/d1WalletCustodyCommitStore.js +18 -7
  85. package/dist/esm/router/cloudflare/d1/registration/d1RegistrationCeremonyRecordStore.js +75 -14
  86. package/dist/esm/router/cloudflare/d1/registration/d1RegistrationCeremonyRecords.js +1 -1
  87. package/dist/esm/router/cloudflare/d1/registration/d1RegistrationCeremonyStore.js +49 -29
  88. package/dist/esm/router/cloudflare/d1/registration/d1RegistrationSessionTransaction.js +28 -0
  89. package/dist/esm/router/cloudflare/d1/registration/d1RegistrationSetupSupport.js +11 -1
  90. package/dist/esm/router/cloudflare/d1/registration/d1WalletExecutionAuthority.js +168 -0
  91. package/dist/esm/router/cloudflare/d1/registration/d1WalletOperationStore.js +53 -0
  92. package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationCommitStore.js +83 -42
  93. package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationInitialSession.js +33 -0
  94. package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationPreparation.js +16 -0
  95. package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationRead.js +58 -0
  96. package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationService.js +439 -500
  97. package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationSetup.js +1 -1
  98. package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationSetupExecution.js +104 -90
  99. package/dist/esm/router/cloudflare/d1/registration/walletRegistrationEstablishedSessionIssuer.js +78 -44
  100. package/dist/esm/router/cloudflare/d1/registration/walletRegistrationSessionCommitReceipt.js +11 -35
  101. package/dist/esm/router/cloudflare/d1/signingAdmission/d1RouterAbNormalSigningAdmissionStore.js +98 -39
  102. package/dist/esm/router/cloudflare/d1/versionedJson/d1VersionedJsonRecordStore.js +12 -9
  103. package/dist/esm/router/cloudflare/d1/wallet/authorizationSnapshotLayout.js +168 -0
  104. package/dist/esm/router/cloudflare/d1/wallet/d1WalletAddSignerFinalizeRecord.js +1 -1
  105. package/dist/esm/router/cloudflare/d1/wallet/d1WalletAddSignerService.js +15 -6
  106. package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthMethodService.js +3 -40
  107. package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorityStore.js +54 -1
  108. package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorizationCleanup.js +157 -0
  109. package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorizationFreeze.js +56 -0
  110. package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorizationHistory.js +238 -0
  111. package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorizationIntake.js +287 -0
  112. package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorizationSnapshot.js +295 -0
  113. package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationApprovals.js +140 -0
  114. package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationChallenges.js +170 -0
  115. package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationEmailOtp.js +60 -0
  116. package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationOwner.js +33 -0
  117. package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationOwnerRequest.js +74 -0
  118. package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationPasskey.js +77 -0
  119. package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationReadAccess.js +37 -0
  120. package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationSessions.js +97 -0
  121. package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationWriteBlock.js +133 -0
  122. package/dist/esm/router/cloudflare/d1/walletObjectAddresses.js +47 -0
  123. package/dist/esm/router/cloudflare/d1/webauthn/d1WebAuthnAuthService.js +1 -1
  124. package/dist/esm/router/cloudflare/runtime/routerAbServiceBindings.js +32 -1
  125. package/dist/esm/router/cloudflare/runtime/staticWalletConsoleBinding.js +20 -8
  126. package/dist/esm/router/cloudflare/runtime/walletAuthorizationRelocationRoutes.js +488 -0
  127. package/dist/esm/router/cloudflare/runtime/walletConsoleOps.js +1 -1
  128. package/dist/esm/router/cloudflare/runtime/walletConsoleOpsClient.js +26 -6
  129. package/dist/esm/router/cloudflare/runtime/walletControlOps.js +3 -0
  130. package/dist/esm/router/cloudflare/runtime/walletGateway.js +1 -1
  131. package/dist/esm/router/cloudflare/runtime/walletObjectAddresses.js +105 -0
  132. package/dist/esm/router/cloudflare/runtime/walletPlacementRoutes.js +339 -0
  133. package/dist/esm/router/cloudflare/runtime/walletRelocationDeriver.js +244 -0
  134. package/dist/esm/router/cloudflare/runtime/walletRelocationEcdsa.js +212 -0
  135. package/dist/esm/router/cloudflare/runtime/walletRelocationEd25519.js +172 -0
  136. package/dist/esm/router/cloudflare/runtime/walletRelocationOps.js +183 -0
  137. package/dist/esm/router/cloudflare/runtime/walletRelocationPresign.js +185 -0
  138. package/dist/esm/router/cloudflare/runtime/walletRelocationSource.js +221 -0
  139. package/dist/esm/router/cloudflare/signingLanes/cloudflareOrdinaryInactiveSignerMaterialReservation.js +30 -8
  140. package/dist/esm/router/cloudflare-adaptor.js +8 -8
  141. package/dist/esm/router/cloudflare.js +34115 -32240
  142. package/dist/esm/router/domains/ecdsa/routerAbEcdsaStrictRegistration.js +35 -9
  143. package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoCapabilityCommit.js +42 -0
  144. package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistration.js +32 -6
  145. package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationPartitionedStateStore.js +61 -1
  146. package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationPersistence.js +70 -3
  147. package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationRequestScopedRuntime.js +59 -87
  148. package/dist/esm/router/domains/ed25519Yao/export/routerAbEd25519YaoExport.js +52 -22
  149. package/dist/esm/router/domains/ed25519Yao/export/routerAbEd25519YaoExportRequestScopedCloudflare.js +10 -7
  150. package/dist/esm/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecovery.js +108 -78
  151. package/dist/esm/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecoveryRequestScopedCloudflare.js +19 -5
  152. package/dist/esm/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecoveryWalletSessionAuthorization.js +71 -22
  153. package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoHttpRegistrationBackend.js +37 -25
  154. package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistration.js +3 -3
  155. package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationExecutionRecord.js +2 -1
  156. package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationIntentAuthorization.js +24 -3
  157. package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationRequestScopedCloudflare.js +4 -3
  158. package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationSideEffectBoundary.js +20 -7
  159. package/dist/esm/router/domains/ed25519Yao/routerAbEd25519YaoGatewayEnvelope.js +7 -1
  160. package/dist/esm/router/domains/emailOtp/emailOtpRouteHandlers.js +2 -2
  161. package/dist/esm/router/domains/passkeyCustody/passkeyCustodyEnvelopeRetrieval.js +1 -1
  162. package/dist/esm/router/domains/passkeyCustody/registrationCustodyOutcome.js +34 -18
  163. package/dist/esm/router/domains/passkeyCustody/walletCustodyRegistrationAdmission.js +2 -2
  164. package/dist/esm/router/domains/passkeyCustody/walletCustodyRegistrationCommit.js +16 -6
  165. package/dist/esm/router/domains/signingOperations/authorizedOperationWire.js +73 -0
  166. package/dist/esm/router/domains/signingOperations/ecdsaSigningResponse.js +31 -0
  167. package/dist/esm/router/domains/signingOperations/ed25519AuthorizedOperationReceipt.js +1 -1
  168. package/dist/esm/router/domains/signingOperations/routerAbEcdsaDerivationNormalSigningRoute.js +2 -1
  169. package/dist/esm/router/domains/signingOperations/routerAbEd25519NormalSigningRoute.js +31 -121
  170. package/dist/esm/router/domains/signingOperations/routerAbNormalSigningAdmission.js +2 -93
  171. package/dist/esm/router/domains/signingOperations/routerAbPrivateSigningWorker.js +1 -1
  172. package/dist/esm/router/domains/signingOperations/signingPrepareSession.js +33 -0
  173. package/dist/esm/router/domains/walletRegistration/registrationSessionSeal.js +121 -0
  174. package/dist/esm/router/domains/walletRegistration/walletRegistrationReservation.js +4 -4
  175. package/dist/esm/router/domains/walletRegistration/walletRegistrationRoutes.js +46 -157
  176. package/dist/esm/router/domains/walletRegistration/walletRegistrationSetupPayload.js +1 -1
  177. package/dist/esm/router/express.js +764 -894
  178. package/dist/esm/router/framework/http.js +2 -1
  179. package/dist/esm/router/transport/fetch/createFetchRouter.js +2 -2
  180. package/dist/esm/router/transport/fetch/routes/auth.js +1 -1
  181. package/dist/esm/router/transport/fetch/routes/deviceLinking.js +3 -3
  182. package/dist/esm/router/transport/fetch/routes/deviceLinkingOwnerAuthorization.js +2 -2
  183. package/dist/esm/router/transport/fetch/routes/ed25519AuthorizedOperationRevalidation.js +65 -0
  184. package/dist/esm/router/transport/fetch/routes/normalSigningRouterProxy.js +13 -3
  185. package/dist/esm/router/transport/fetch/routes/passkeyCustody.js +3 -3
  186. package/dist/esm/router/transport/fetch/routes/sessions.js +3 -2
  187. package/dist/esm/router/transport/fetch/routes/thresholdEcdsa.js +67 -130
  188. package/dist/esm/router/transport/fetch/routes/thresholdEd25519.js +76 -212
  189. package/dist/esm/router/transport/fetch/routes/walletExecutionLanePreflight.js +18 -41
  190. package/dist/esm/router/transport/fetch/routes/walletRegistration.js +6 -5
  191. package/dist/esm/router/transport/fetch/routes/webauthnAuthenticators.js +1 -1
  192. package/dist/esm/shared-ts/src/authorization/index.js +1 -1
  193. package/dist/esm/shared-ts/src/authorization/walletAuthority.js +2 -2
  194. package/dist/esm/shared-ts/src/device-linking/activeWalletSession.js +12 -2
  195. package/dist/esm/shared-ts/src/device-linking/digests.js +1 -1
  196. package/dist/esm/shared-ts/src/device-linking/ed25519ExportRoot.js +1 -1
  197. package/dist/esm/shared-ts/src/device-linking/index.js +1 -1
  198. package/dist/esm/shared-ts/src/device-linking/parsers.js +1 -1
  199. package/dist/esm/shared-ts/src/device-linking/sourceContribution.js +1 -1
  200. package/dist/esm/shared-ts/src/device-linking/wireFields.js +1 -1
  201. package/dist/esm/shared-ts/src/near/nearClient.js +1 -1
  202. package/dist/esm/shared-ts/src/signing-lanes/ownerContinuity.js +2 -2
  203. package/dist/esm/shared-ts/src/utils/ecdsaServerTiming.js +6 -1
  204. package/dist/esm/shared-ts/src/utils/emailOtpDomain.js +4 -2
  205. package/dist/esm/shared-ts/src/utils/routerAbEcdsaDerivation.js +1 -1
  206. package/dist/esm/shared-ts/src/utils/routerAbPublicKeyset.js +0 -27
  207. package/dist/esm/shared-ts/src/wallet-recovery/walletRecoveryEcdsaPossession.js +1 -1
  208. package/dist/esm/threshold/session/signingSessionSeal/options.js +1 -1
  209. package/dist/esm/wasm/near_signer/pkg/wasm_signer_worker_bg.wasm +0 -0
  210. package/dist/types/shared-ts/src/device-linking/activeWalletSession.d.ts +2 -1
  211. package/dist/types/shared-ts/src/device-linking/contracts.d.ts +10 -0
  212. package/dist/types/shared-ts/src/threshold/ed25519OperationFingerprint.d.ts +2 -1
  213. package/dist/types/shared-ts/src/utils/emailOtpDomain.d.ts +3 -1
  214. package/dist/types/shared-ts/src/utils/routerAbPublicKeyset.d.ts +0 -9
  215. package/dist/types/shared-ts/src/utils/walletManagementProtocol.d.ts +1 -1
  216. package/dist/types/wallet-server/src/authorization/domain.d.ts +17 -1
  217. package/dist/types/wallet-server/src/authorization/ecdsaWalletSessionAdmission.d.ts +1 -0
  218. package/dist/types/wallet-server/src/authorization/ed25519WalletSessionAdmission.d.ts +35 -0
  219. package/dist/types/wallet-server/src/authorization/ed25519WalletSessionAdmission.typecheck.d.ts +2 -0
  220. package/dist/types/wallet-server/src/authorization/service.d.ts +43 -5
  221. package/dist/types/wallet-server/src/authorization/sessionRouting.d.ts +2 -0
  222. package/dist/types/wallet-server/src/cloud-host.d.ts +7 -3
  223. package/dist/types/wallet-server/src/core/EmailOtpRecords.d.ts +2 -1
  224. package/dist/types/wallet-server/src/core/EmailOtpStores.d.ts +19 -5
  225. package/dist/types/wallet-server/src/core/ThresholdService/routerAb/ecdsaDerivationPoolFillHandlers.d.ts +1 -0
  226. package/dist/types/wallet-server/src/core/ThresholdService/routerAb/ecdsaDerivationPresignBridge.d.ts +6 -0
  227. package/dist/types/wallet-server/src/core/ThresholdService/routerAb/internalServiceHttp.d.ts +1 -0
  228. package/dist/types/wallet-server/src/core/d1Ed25519SignerRead.d.ts +17 -0
  229. package/dist/types/wallet-server/src/core/d1WalletStore.d.ts +6 -0
  230. package/dist/types/wallet-server/src/core/emailOtpD1Statements.d.ts +1 -0
  231. package/dist/types/wallet-server/src/core/routerAbSigning/RouterAbEcdsaPresignRuntime.d.ts +5 -1
  232. package/dist/types/wallet-server/src/core/signingMaterial/ordinaryInactiveSignerMaterialReservation.d.ts +1 -0
  233. package/dist/types/wallet-server/src/core/threeRouteRegistrationContracts.d.ts +14 -48
  234. package/dist/types/wallet-server/src/hosted-wallet-gateway.d.ts +4 -3
  235. package/dist/types/wallet-server/src/localIntendedYaoSigningFault.d.ts +1 -16
  236. package/dist/types/wallet-server/src/localRegistrationSetupAuthority.d.ts +1 -1
  237. package/dist/types/wallet-server/src/router/auth/commonRouterUtils.d.ts +7 -1
  238. package/dist/types/wallet-server/src/router/auth/routerApiCredentialAuth.d.ts +11 -3
  239. package/dist/types/wallet-server/src/router/auth/walletRegistrationContext.d.ts +8 -0
  240. package/dist/types/wallet-server/src/router/cloudflare/d1/auth/d1AuthorizationAssembly.d.ts +1 -1
  241. package/dist/types/wallet-server/src/router/cloudflare/d1/auth/d1EmailOtpRouteService.d.ts +16 -0
  242. package/dist/types/wallet-server/src/router/cloudflare/d1/auth/d1RouterApiAuthConfig.d.ts +7 -4
  243. package/dist/types/wallet-server/src/router/cloudflare/d1/auth/d1RouterApiAuthService.d.ts +4 -1
  244. package/dist/types/wallet-server/src/router/cloudflare/d1/auth/walletSessionCredentialReaders.d.ts +7 -1
  245. package/dist/types/wallet-server/src/router/cloudflare/d1/authorization/d1AuthorizationStore.d.ts +32 -1
  246. package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceAuthorityInstallService.d.ts +2 -0
  247. package/dist/types/wallet-server/src/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoLifecycleDecisionStore.d.ts +3 -1
  248. package/dist/types/wallet-server/src/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoProductRegistrationPartitionedStateStore.d.ts +1 -0
  249. package/dist/types/wallet-server/src/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoStateWriteFence.d.ts +8 -0
  250. package/dist/types/wallet-server/src/router/cloudflare/d1/ed25519Yao/d1WalletCeremonyActivity.d.ts +15 -0
  251. package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeIssuer.d.ts +6 -1
  252. package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeStore.d.ts +1 -0
  253. package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeVerifier.d.ts +4 -1
  254. package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpCounters.typecheck.d.ts +2 -0
  255. package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpRateLimitStore.d.ts +6 -29
  256. package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpRecords.d.ts +21 -7
  257. package/dist/types/wallet-server/src/router/cloudflare/d1/passkeyCustody/d1WalletCustodyCommitStore.d.ts +17 -1
  258. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationCeremonyRecordStore.d.ts +32 -7
  259. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationCeremonyStore.d.ts +16 -7
  260. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationSessionTransaction.d.ts +13 -0
  261. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationSetupSupport.d.ts +7 -0
  262. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletExecutionAuthority.d.ts +41 -0
  263. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletOperationStore.d.ts +28 -0
  264. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationCommitStore.d.ts +6 -9
  265. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationInitialSession.d.ts +17 -0
  266. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationPreparation.d.ts +12 -0
  267. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationRead.d.ts +43 -0
  268. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationService.d.ts +24 -45
  269. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationSetupExecution.d.ts +9 -4
  270. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/walletRegistrationEstablishedSessionIssuer.d.ts +42 -14
  271. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/walletRegistrationSessionCommitReceipt.d.ts +5 -4
  272. package/dist/types/wallet-server/src/router/cloudflare/d1/signingAdmission/d1RouterAbNormalSigningAdmissionStore.d.ts +24 -1
  273. package/dist/types/wallet-server/src/router/cloudflare/d1/versionedJson/d1VersionedJsonRecordStore.d.ts +10 -4
  274. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/authorizationSnapshotLayout.d.ts +21 -0
  275. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAddSignerService.d.ts +3 -0
  276. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthMethodService.d.ts +3 -7
  277. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorityStore.d.ts +8 -0
  278. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorizationCleanup.d.ts +20 -0
  279. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorizationFreeze.d.ts +12 -0
  280. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorizationHistory.d.ts +20 -0
  281. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorizationIntake.d.ts +29 -0
  282. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorizationSnapshot.d.ts +31 -0
  283. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationApprovals.d.ts +49 -0
  284. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationChallenges.d.ts +47 -0
  285. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationEmailOtp.d.ts +25 -0
  286. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationOwner.d.ts +88 -0
  287. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationOwnerRequest.d.ts +37 -0
  288. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationPasskey.d.ts +12 -0
  289. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationReadAccess.d.ts +18 -0
  290. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationSessions.d.ts +23 -0
  291. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationWriteBlock.d.ts +16 -0
  292. package/dist/types/wallet-server/src/router/cloudflare/d1/walletObjectAddresses.d.ts +14 -0
  293. package/dist/types/wallet-server/src/router/cloudflare/runtime/routerAbServiceBindings.d.ts +13 -0
  294. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletAuthorizationRelocationRoutes.d.ts +21 -0
  295. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletConsoleOps.d.ts +1 -1
  296. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletConsoleOpsClient.d.ts +3 -3
  297. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletControlOps.d.ts +2 -1
  298. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletGateway.d.ts +3 -1
  299. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletObjectAddresses.d.ts +45 -0
  300. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletPlacementRoutes.d.ts +30 -0
  301. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRelocationDeriver.d.ts +11 -0
  302. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRelocationEcdsa.d.ts +7 -0
  303. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRelocationEd25519.d.ts +7 -0
  304. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRelocationOps.d.ts +11 -0
  305. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRelocationPresign.d.ts +7 -0
  306. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRelocationSource.d.ts +26 -0
  307. package/dist/types/wallet-server/src/router/cloudflare/signingLanes/cloudflareOrdinaryInactiveSignerMaterialReservation.d.ts +5 -0
  308. package/dist/types/wallet-server/src/router/domains/ecdsa/routerAbEcdsaStrictRegistration.d.ts +3 -0
  309. package/dist/types/wallet-server/src/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoCapabilityCommit.d.ts +7 -0
  310. package/dist/types/wallet-server/src/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistration.d.ts +41 -7
  311. package/dist/types/wallet-server/src/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationPartitionedStateStore.d.ts +33 -2
  312. package/dist/types/wallet-server/src/router/domains/ed25519Yao/export/routerAbEd25519YaoExport.d.ts +12 -6
  313. package/dist/types/wallet-server/src/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecovery.d.ts +17 -9
  314. package/dist/types/wallet-server/src/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecoveryWalletSessionAuthorization.d.ts +2 -0
  315. package/dist/types/wallet-server/src/router/domains/ed25519Yao/registration/routerAbEd25519YaoHttpRegistrationBackend.d.ts +13 -14
  316. package/dist/types/wallet-server/src/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistration.d.ts +7 -3
  317. package/dist/types/wallet-server/src/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationExecutionRecord.d.ts +1 -0
  318. package/dist/types/wallet-server/src/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationIntentAuthorization.d.ts +6 -1
  319. package/dist/types/wallet-server/src/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationSideEffectBoundary.d.ts +11 -0
  320. package/dist/types/wallet-server/src/router/domains/ed25519Yao/routerAbEd25519YaoGatewayEnvelope.d.ts +12 -3
  321. package/dist/types/wallet-server/src/router/domains/passkeyCustody/registrationCustodyOutcome.d.ts +10 -6
  322. package/dist/types/wallet-server/src/router/domains/passkeyCustody/walletCustodyRegistrationAdmission.d.ts +10 -3
  323. package/dist/types/wallet-server/src/router/domains/passkeyCustody/walletCustodyRegistrationCommit.d.ts +12 -5
  324. package/dist/types/wallet-server/src/router/domains/signingOperations/authorizedOperationWire.d.ts +97 -0
  325. package/dist/types/wallet-server/src/router/domains/signingOperations/ecdsaSigningResponse.d.ts +13 -0
  326. package/dist/types/wallet-server/src/router/domains/signingOperations/routerAbNormalSigningAdmission.d.ts +9 -206
  327. package/dist/types/wallet-server/src/router/domains/signingOperations/signingPrepareSession.d.ts +23 -0
  328. package/dist/types/wallet-server/src/router/domains/walletRegistration/registrationSessionSeal.d.ts +36 -0
  329. package/dist/types/wallet-server/src/router/domains/walletRegistration/walletRegistrationInputs.d.ts +7 -7
  330. package/dist/types/wallet-server/src/router/domains/walletRegistration/walletRegistrationReservation.d.ts +80 -6
  331. package/dist/types/wallet-server/src/router/domains/walletRegistration/walletRegistrationRoutes.d.ts +15 -5
  332. package/dist/types/wallet-server/src/router/framework/apiCredentialPorts.d.ts +24 -0
  333. package/dist/types/wallet-server/src/router/framework/authServicePort.d.ts +21 -7
  334. package/dist/types/wallet-server/src/router/framework/routerApi.d.ts +3 -12
  335. package/dist/types/wallet-server/src/router/transport/fetch/routes/ed25519AuthorizedOperationRevalidation.d.ts +37 -0
  336. package/dist/types/wallet-server/src/router/transport/fetch/routes/thresholdEcdsa.d.ts +1 -17
  337. package/dist/types/wallet-server/src/storage/tenantRoute.d.ts +1 -1
  338. package/migrations/d1-signer/0049_wallet_relocation_challenges.sql +16 -0
  339. package/migrations/d1-signer/0050_wallet_relocation_approvals.sql +14 -0
  340. package/migrations/d1-signer/0051_wallet_relocation_email_otp.sql +92 -0
  341. package/migrations/d1-signer/0052_wallet_relocation_session_fences.sql +91 -0
  342. package/migrations/d1-signer/0053_wallet_hosted_history_import.sql +164 -0
  343. package/migrations/d1-signer/0054_wallet_authorization_freeze.sql +318 -0
  344. package/migrations/d1-signer/0055_wallet_authorization_snapshot.sql +120 -0
  345. package/migrations/d1-signer/0056_wallet_authorization_history_import.sql +424 -0
  346. package/migrations/d1-signer/0057_wallet_authorization_intake.sql +44 -0
  347. package/migrations/d1-signer/0058_wallet_ceremony_activity.sql +59 -0
  348. package/migrations/d1-signer/0059_wallet_authorization_activation.sql +45 -0
  349. package/migrations/d1-signer/0060_wallet_authorization_cleanup.sql +153 -0
  350. package/migrations/d1-signer/0061_wallet_session_operation_settlement.sql +28 -0
  351. package/migrations/d1-signer/0062_wallet_step_up_operation_settlement.sql +204 -0
  352. package/migrations/d1-signer/0063_wallet_operation_history_transfer.sql +466 -0
  353. package/migrations/d1-signer/0064_wallet_execution_generations.sql +93 -0
  354. package/migrations/d1-signer/0065_wallet_operation_execution_generation.sql +37 -0
  355. package/migrations/d1-signer/0066_regional_deployment_admission.sql +59 -0
  356. package/migrations/d1-signer/0067_registration_completion_decision.sql +12 -0
  357. package/migrations/d1-signer/0068_registration_cancellation_write_fence.sql +24 -0
  358. package/migrations/d1-signer/0069_cancelled_registration_session_fence.sql +11 -0
  359. package/migrations/d1-signer/0070_wallet_passkey_relocation.sql +369 -0
  360. package/migrations/d1-signer/0071_regional_wallet_otp_counters.sql +98 -0
  361. package/migrations/d1-signer/0072_linked_device_relocation_history.sql +899 -0
  362. package/migrations/d1-signer/0073_wallet_recovery_relocation.sql +86 -0
  363. package/migrations/d1-signer/0074_email_otp_relocation.sql +158 -0
  364. package/migrations/d1-signer/0075_wallet_authorization_return.sql +107 -0
  365. package/migrations/d1-signer/0076_wallet_relocation_write_block.sql +406 -0
  366. package/migrations/d1-signer/0077_wallet_object_addresses.sql +24 -0
  367. package/package.json +1 -1
  368. package/src/README.md +23 -1
  369. package/cloudflare-router-ab/scripts/local-key-material.mjs +0 -29
@@ -1,7 +1,7 @@
1
+ import { normalizeOptionalTrimmedString } from "../../../../shared-ts/src/utils/normalize.js";
1
2
  import { base64UrlEncode } from "../../../../shared-ts/src/utils/base64.js";
2
3
  import { alphabetizeStringify, sha256BytesUtf8 } from "../../../../shared-ts/src/utils/digests.js";
3
4
  import "../../../../shared-ts/src/utils/encoders.js";
4
- import { normalizeOptionalTrimmedString } from "../../../../shared-ts/src/utils/normalize.js";
5
5
  import { EMAIL_OTP_CHANNEL, WALLET_EMAIL_OTP_ACTIONS, WALLET_EMAIL_OTP_REGISTRATION_OPERATION } from "../../../../shared-ts/src/utils/emailOtpDomain.js";
6
6
  import { emailOtpChallengeBindingMismatchCode, emailOtpChallengeInvalidOrExpired, emailOtpRegistrationChallengeBindingMismatchCode } from "./d1EmailOtpRecords.js";
7
7
  //#region src/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeVerifier.ts
@@ -121,6 +121,7 @@ var CloudflareD1EmailOtpChallengeVerifier = class {
121
121
  message: "Missing ownerProofBindingDigest"
122
122
  };
123
123
  const rateLimit = await this.emailOtpRateLimits.consume({
124
+ kind: "wallet",
124
125
  scope: "verify",
125
126
  action,
126
127
  userId,
@@ -305,6 +306,7 @@ var CloudflareD1EmailOtpChallengeVerifier = class {
305
306
  }
306
307
  }
307
308
  const rateLimit = await this.emailOtpRateLimits.consume({
309
+ kind: "wallet",
308
310
  scope: "verify",
309
311
  action: recoveryBootstrap ? WALLET_EMAIL_OTP_ACTIONS.recoveryBootstrap : WALLET_EMAIL_OTP_ACTIONS.registration,
310
312
  userId: providerSubject || walletId,
@@ -2,81 +2,101 @@ import { emailOtpRateLimitExceeded, emailOtpRateLimitKeys } from "./d1EmailOtpRe
2
2
  //#region src/router/cloudflare/d1/emailOtp/d1EmailOtpRateLimitStore.ts
3
3
  var CloudflareD1EmailOtpRateLimitStore = class {
4
4
  constructor(input) {
5
- this.rateLimits = input.rateLimits;
6
- this.counter = input.counter ?? new D1EmailOtpRateLimitCounter(input.prepare);
5
+ this.input = input;
7
6
  }
8
7
  async consume(input) {
9
- const policy = this.rateLimits[input.scope];
10
- const keys = emailOtpRateLimitKeys({
11
- ...input,
12
- policy
13
- });
14
- for (const key of keys) {
15
- const consumed = await this.counter.consume({
16
- key,
17
- limit: policy.limit,
18
- windowMs: policy.windowMs
19
- });
20
- if (!consumed.ok) return consumed;
8
+ const policy = this.input.rateLimits[input.scope];
9
+ const keys = emailOtpRateLimitKeys(input, policy);
10
+ if (keys.length === 0) return { ok: true };
11
+ const nowMs = Date.now();
12
+ const statements = [];
13
+ for (const [index, counter] of keys.entries()) statements.push(this.prepareConsume(counter, policy, nowMs, index === 0));
14
+ const results = await this.input.batch(statements);
15
+ if (results.length !== keys.length) throw new Error("OTP counter batch omitted results");
16
+ for (const [index, result] of results.entries()) {
17
+ if (!result.success) throw new Error("OTP counter batch failed");
18
+ if (result.results?.length) continue;
19
+ return emailOtpRateLimitExceeded(await this.readCounter(keys[index]));
21
20
  }
22
21
  return { ok: true };
23
22
  }
24
- };
25
- var D1EmailOtpRateLimitCounter = class {
26
- constructor(prepare) {
27
- this.prepare = prepare;
28
- }
29
- async consume(input) {
30
- const nowMs = Date.now();
31
- const resetAtMs = nowMs + input.windowMs;
32
- if (await this.prepare(`INSERT INTO email_otp_rate_limits (
23
+ prepareConsume(counter, policy, nowMs, first) {
24
+ const resetAtMs = nowMs + policy.windowMs;
25
+ let walletId;
26
+ switch (counter.kind) {
27
+ case "wallet":
28
+ walletId = counter.walletId;
29
+ break;
30
+ case "regional":
31
+ walletId = null;
32
+ break;
33
+ default: return assertNever(counter);
34
+ }
35
+ const table = walletId === null ? "email_otp_rate_limits" : "wallet_email_otp_rate_limits";
36
+ const ownerColumn = walletId === null ? "" : "wallet_id,";
37
+ const ownerPlaceholder = walletId === null ? "" : "?,";
38
+ const ownerValues = walletId === null ? [] : [walletId];
39
+ return this.input.prepare(`INSERT INTO ${table} (
33
40
  namespace,
34
41
  org_id,
35
42
  project_id,
36
43
  env_id,
44
+ ${ownerColumn}
37
45
  rate_key,
38
46
  consumed_count,
39
47
  reset_at_ms,
40
48
  updated_at_ms
41
49
  )
42
- VALUES (?, ?, ?, ?, ?, 1, ?, ?)
43
- ON CONFLICT (namespace, org_id, project_id, env_id, rate_key)
50
+ SELECT ?, ?, ?, ?, ${ownerPlaceholder} ?, 1, ?, ?
51
+ WHERE ? OR changes() > 0
52
+ ON CONFLICT (namespace, org_id, project_id, env_id, ${ownerColumn} rate_key)
44
53
  DO UPDATE SET
45
54
  consumed_count = CASE
46
- WHEN email_otp_rate_limits.reset_at_ms <= ?
55
+ WHEN ${table}.reset_at_ms <= ?
47
56
  THEN 1
48
- ELSE email_otp_rate_limits.consumed_count + 1
57
+ ELSE ${table}.consumed_count + 1
49
58
  END,
50
59
  reset_at_ms = CASE
51
- WHEN email_otp_rate_limits.reset_at_ms <= ?
60
+ WHEN ${table}.reset_at_ms <= ?
52
61
  THEN ?
53
- ELSE email_otp_rate_limits.reset_at_ms
62
+ ELSE ${table}.reset_at_ms
54
63
  END,
55
64
  updated_at_ms = ?
56
- WHERE email_otp_rate_limits.reset_at_ms <= ?
57
- OR email_otp_rate_limits.consumed_count < ?
65
+ WHERE ${table}.reset_at_ms <= ?
66
+ OR ${table}.consumed_count < ?
58
67
  RETURNING consumed_count, reset_at_ms`, [
59
- input.key,
68
+ ...ownerValues,
69
+ counter.key,
60
70
  resetAtMs,
61
71
  nowMs,
72
+ first ? 1 : 0,
62
73
  nowMs,
63
74
  nowMs,
64
75
  resetAtMs,
65
76
  nowMs,
66
77
  nowMs,
67
- input.limit
68
- ]).first()) return { ok: true };
69
- return emailOtpRateLimitExceeded(await this.prepare(`SELECT consumed_count, reset_at_ms
70
- FROM email_otp_rate_limits
78
+ policy.limit
79
+ ]);
80
+ }
81
+ async readCounter(counter) {
82
+ const walletId = counter.kind === "wallet" ? counter.walletId : null;
83
+ const table = walletId === null ? "email_otp_rate_limits" : "wallet_email_otp_rate_limits";
84
+ const ownerValues = walletId === null ? [] : [walletId];
85
+ return this.input.prepare(`SELECT consumed_count, reset_at_ms
86
+ FROM ${table}
71
87
  WHERE namespace = ?
72
88
  AND org_id = ?
73
89
  AND project_id = ?
74
90
  AND env_id = ?
91
+ ${walletId === null ? "" : "AND wallet_id = ?"}
75
92
  AND rate_key = ?
76
- LIMIT 1`, [input.key]).first());
93
+ LIMIT 1`, [...ownerValues, counter.key]).first();
77
94
  }
78
95
  };
96
+ function assertNever(value) {
97
+ throw new Error(`Unexpected OTP counter ownership: ${String(value)}`);
98
+ }
79
99
  //#endregion
80
- export { CloudflareD1EmailOtpRateLimitStore, D1EmailOtpRateLimitCounter };
100
+ export { CloudflareD1EmailOtpRateLimitStore };
81
101
 
82
102
  //# sourceMappingURL=d1EmailOtpRateLimitStore.js.map
@@ -1,11 +1,11 @@
1
+ import { normalizeOptionalTrimmedString } from "../../../../shared-ts/src/utils/normalize.js";
1
2
  import { base64UrlDecode } from "../../../../shared-ts/src/utils/base64.js";
2
3
  import "../../../../shared-ts/src/utils/encoders.js";
3
- import { normalizeOptionalTrimmedString } from "../../../../shared-ts/src/utils/normalize.js";
4
4
  import { hasExactKeys } from "../../../../shared-ts/src/utils/exactKeys.js";
5
5
  import { failure } from "../../../../shared-ts/src/utils/failure.js";
6
- import { EMAIL_OTP_CHANNEL, WALLET_EMAIL_OTP_ACTIONS, WALLET_EMAIL_OTP_DEVICE_LINK_OPERATION, WALLET_EMAIL_OTP_REGISTRATION_OPERATION, WALLET_EMAIL_OTP_UNLOCK_OPERATION, isWalletEmailOtpLoginOperation } from "../../../../shared-ts/src/utils/emailOtpDomain.js";
6
+ import { EMAIL_OTP_CHANNEL, WALLET_EMAIL_OTP_ACTIONS, WALLET_EMAIL_OTP_UNLOCK_OPERATION, isWalletEmailOtpLoginOperation } from "../../../../shared-ts/src/utils/emailOtpDomain.js";
7
7
  import { isB64uString, nonNegativeSafeInteger, parseJsonObject, positiveSafeInteger } from "../auth/d1RouterApiAuthBoundary.js";
8
- import { parseCurrentEmailOtpChallengeRow, parseCurrentEmailOtpGrantRow, parseCurrentEmailOtpUnlockChallengeRow } from "../../../../core/EmailOtpRecords.js";
8
+ import { parseCurrentEmailOtpChallengeRow, parseCurrentEmailOtpGrantRow, parseCurrentEmailOtpUnlockChallengeRow, parseEmailOtpChallengePurpose } from "../../../../core/EmailOtpRecords.js";
9
9
  //#region src/router/cloudflare/d1/emailOtp/d1EmailOtpRecords.ts
10
10
  function maskEmail(email) {
11
11
  const trimmed = email.trim().toLowerCase();
@@ -44,20 +44,30 @@ function bytesEqual(left, right) {
44
44
  for (let index = 0; index < left.length; index += 1) difference |= (left[index] || 0) ^ (right[index] || 0);
45
45
  return difference === 0;
46
46
  }
47
- function emailOtpRateLimitKeys(input) {
47
+ function emailOtpRateLimitKeys(input, policy) {
48
48
  const keySuffix = [
49
49
  `scope=${input.scope}`,
50
50
  `action=${input.action || "default"}`,
51
- `limit=${input.policy.limit}`,
52
- `windowMs=${input.policy.windowMs}`
51
+ `limit=${policy.limit}`,
52
+ `windowMs=${policy.windowMs}`
53
53
  ].join(":");
54
- return [
54
+ const counters = [];
55
+ if (input.kind === "wallet") counters.push({
56
+ kind: "wallet",
57
+ walletId: input.walletId,
58
+ key: keySuffix
59
+ });
60
+ const regionalKeys = [
55
61
  input.clientIp ? `${keySuffix}:ip:${input.clientIp}` : "",
56
62
  input.userId ? `${keySuffix}:user:${input.userId}` : "",
57
- input.walletId ? `${keySuffix}:wallet:${input.walletId}` : "",
58
63
  input.providerSubject ? `${keySuffix}:provider:${input.providerSubject}` : "",
59
64
  input.orgId ? `${keySuffix}:org:${input.orgId}` : ""
60
- ].filter(Boolean);
65
+ ];
66
+ for (const key of regionalKeys) if (key) counters.push({
67
+ kind: "regional",
68
+ key
69
+ });
70
+ return counters;
61
71
  }
62
72
  function emailOtpRateLimitExceeded(row) {
63
73
  const resetAtMs = positiveSafeInteger(row?.reset_at_ms);
@@ -158,7 +168,7 @@ function parseEmailOtpChallengeRow(row) {
158
168
  recordJson: row?.record_json,
159
169
  expiresAtMs: row?.expires_at_ms
160
170
  });
161
- if (!record || record.expiresAtMs <= record.createdAtMs || !emailOtpChallengePurposeIsValid(record)) return null;
171
+ if (!record || record.expiresAtMs <= record.createdAtMs) return null;
162
172
  return {
163
173
  ...record,
164
174
  email: record.email.toLowerCase()
@@ -226,6 +236,8 @@ function emailOtpChallengeContextValues(input) {
226
236
  ];
227
237
  }
228
238
  function emailOtpChallengeRecord(input) {
239
+ const purpose = parseEmailOtpChallengePurpose(input.action, input.operation);
240
+ if (!purpose) throw new Error("Invalid Email OTP challenge purpose");
229
241
  return {
230
242
  version: "email_otp_challenge_v1",
231
243
  challengeId: input.challengeId,
@@ -236,8 +248,7 @@ function emailOtpChallengeRecord(input) {
236
248
  email: input.email,
237
249
  otpCode: input.otpCode,
238
250
  ownerProofBindingDigest: input.ownerProofBindingDigest,
239
- action: input.action,
240
- operation: input.operation,
251
+ ...purpose,
241
252
  createdAtMs: input.createdAtMs,
242
253
  expiresAtMs: input.expiresAtMs,
243
254
  attemptCount: 0,
@@ -245,6 +256,8 @@ function emailOtpChallengeRecord(input) {
245
256
  };
246
257
  }
247
258
  function emailOtpChallengeWithAttemptCount(record, attemptCount) {
259
+ const purpose = parseEmailOtpChallengePurpose(record.action, record.operation);
260
+ if (!purpose) throw new Error("Invalid Email OTP challenge purpose");
248
261
  return {
249
262
  version: "email_otp_challenge_v1",
250
263
  challengeId: record.challengeId,
@@ -255,8 +268,7 @@ function emailOtpChallengeWithAttemptCount(record, attemptCount) {
255
268
  email: record.email,
256
269
  otpCode: record.otpCode,
257
270
  ownerProofBindingDigest: record.ownerProofBindingDigest,
258
- action: record.action,
259
- operation: record.operation,
271
+ ...purpose,
260
272
  createdAtMs: record.createdAtMs,
261
273
  expiresAtMs: record.expiresAtMs,
262
274
  attemptCount,
@@ -372,12 +384,7 @@ function emailOtpAuthStateRecord(input) {
372
384
  };
373
385
  }
374
386
  function emailOtpChallengePurposeIsValid(input) {
375
- switch (input.action) {
376
- case WALLET_EMAIL_OTP_ACTIONS.login: return isWalletEmailOtpLoginOperation(input.operation);
377
- case WALLET_EMAIL_OTP_ACTIONS.registration: return input.operation === WALLET_EMAIL_OTP_REGISTRATION_OPERATION;
378
- case WALLET_EMAIL_OTP_ACTIONS.recoveryBootstrap: return input.operation === WALLET_EMAIL_OTP_UNLOCK_OPERATION;
379
- case WALLET_EMAIL_OTP_ACTIONS.deviceLink: return input.operation === WALLET_EMAIL_OTP_DEVICE_LINK_OPERATION;
380
- }
387
+ return parseEmailOtpChallengePurpose(input.action, input.operation) !== null;
381
388
  }
382
389
  function optionalPositiveSafeIntegerField(record, field) {
383
390
  if (!hasRecordField(record, field) || record[field] == null) return void 0;
@@ -229,6 +229,7 @@ var CloudflareD1EmailOtpRecoveryService = class {
229
229
  const parsed = normalizeGrantConsumptionInput(input);
230
230
  if (!parsed.ok) return parsed.result;
231
231
  const rateLimit = await this.emailOtpRateLimits.consume({
232
+ kind: "wallet",
232
233
  scope: "grant",
233
234
  userId: parsed.value.userId,
234
235
  walletId: parsed.value.walletId,
@@ -121,6 +121,7 @@ var CloudflareD1GoogleEmailOtpSessionResolver = class {
121
121
  if (!orgId.ok) return failure("invalid_body", orgId.error.message);
122
122
  const restartOffer = isTrueFlag(input.restartRegistrationOffer);
123
123
  return await this.emailOtpRateLimits.consume({
124
+ kind: "regional",
124
125
  scope: "googleRegistrationAttempt",
125
126
  action: restartOffer ? "google_email_otp_registration_offer_restart" : "google_email_otp_registration_create",
126
127
  userId: normalizeOptionalTrimmedString(input.providerUserId),
@@ -1,6 +1,6 @@
1
+ import { normalizeOptionalTrimmedString } from "../../../../shared-ts/src/utils/normalize.js";
1
2
  import { base64UrlDecode } from "../../../../shared-ts/src/utils/base64.js";
2
3
  import "../../../../shared-ts/src/utils/encoders.js";
3
- import { normalizeOptionalTrimmedString } from "../../../../shared-ts/src/utils/normalize.js";
4
4
  import { failedVerification } from "../../../../shared-ts/src/utils/failure.js";
5
5
  import { toArrayBufferCopy } from "../../../../core/authService/portableCrypto.js";
6
6
  import { toRecordValue } from "../auth/d1RouterApiAuthBoundary.js";
@@ -1,6 +1,6 @@
1
1
  import { parseWalletId } from "../../../../shared-ts/src/utils/domainIds.js";
2
- import { sha256HexUtf8 } from "../../../../shared-ts/src/utils/digests.js";
3
2
  import { buildDelegatedWalletAuthorityV1, buildFullOwnerDelegatedWalletAuthorityV1, sameDelegatedWalletAuthorityV1 } from "../../../../shared-ts/src/authorization/delegatedAuthority.js";
3
+ import { sha256HexUtf8 } from "../../../../shared-ts/src/utils/digests.js";
4
4
  import { sameWalletAuthMethodRecordV2 } from "../../../../shared-ts/src/utils/walletAuthMethodRecord.js";
5
5
  import { sameVerifiedActiveWalletAuthorityV1, walletAuthorityDigestsMatchV1 } from "../../../../shared-ts/src/authorization/walletAuthority.js";
6
6
  import { D1_BATCH_CAS_GUARD_SQL } from "../../../../storage/d1Sql.js";
@@ -346,13 +346,11 @@ var CloudflareD1WalletCustodyCommitStore = class {
346
346
  LIMIT 1`).bind(this.scope.namespace, this.scope.orgId, this.scope.projectId, this.scope.envId, challengeId).first() !== null;
347
347
  }
348
348
  /**
349
- * Writes the envelope and the recovery set in one transaction.
350
- *
351
- * Both are inserts, never updates: `expectedVersion: null` fails if either
352
- * key already holds a row, so a repeated registration cannot silently replace
353
- * an established wallet's custody.
349
+ * Checks the commit and claims its recovery-code routes. The claim is an
350
+ * exact-retryable directory write that needs no local record, so a caller
351
+ * may run it beside its other remote effects and write afterwards.
354
352
  */
355
- async commitRegistration(commit) {
353
+ async reserveRegistration(commit) {
356
354
  const inconsistency = commitInconsistency(commit);
357
355
  if (inconsistency !== null) return {
358
356
  kind: "inconsistent",
@@ -362,6 +360,19 @@ var CloudflareD1WalletCustodyCommitStore = class {
362
360
  kind: "inconsistent",
363
361
  reason: "recovery code locator already exists"
364
362
  };
363
+ return {
364
+ kind: "reserved",
365
+ commit: () => this.commitReservedRegistration(commit)
366
+ };
367
+ }
368
+ /**
369
+ * Writes the envelope and the recovery set in one transaction.
370
+ *
371
+ * Both are inserts, never updates: `expectedVersion: null` fails if either
372
+ * key already holds a row, so a repeated registration cannot silently replace
373
+ * an established wallet's custody.
374
+ */
375
+ async commitReservedRegistration(commit) {
365
376
  const envelopeKey = passkeyCustodyEnvelopeRecordKey(passkeyCustodyEnvelopeLocatorOf(commit.envelope));
366
377
  const recoverySetKey = walletRecoveryEnvelopeSetRecordKey(commit.recoverySet.walletId);
367
378
  const recoveryBackupAcknowledgementKey = walletRecoveryBackupAcknowledgementRecordKey(commit.recoverySet.walletId);
@@ -1,6 +1,6 @@
1
- import { alphabetizeStringify } from "../../../../shared-ts/src/utils/digests.js";
2
1
  import { normalizeOptionalTrimmedString } from "../../../../shared-ts/src/utils/normalize.js";
3
2
  import { isPlainObject } from "../../../../shared-ts/src/utils/validation.js";
3
+ import { alphabetizeStringify } from "../../../../shared-ts/src/utils/digests.js";
4
4
  import { isD1DatabaseLike } from "../../../../storage/d1Sql.js";
5
5
  //#region src/router/cloudflare/d1/registration/d1RegistrationCeremonyRecordStore.ts
6
6
  const TABLE_NAME = "registration_ceremony_records";
@@ -34,19 +34,17 @@ var D1RegistrationCeremonyRecordStore = class {
34
34
  this.keyPrefix = normalizeKeyPart(options.keyPrefix, "keyPrefix", 128);
35
35
  }
36
36
  async get(scope, id) {
37
- const key = this.normalizeKey(scope, id);
38
- const row = await this.database.prepare(`SELECT version, record_json, expires_at_ms
39
- FROM ${TABLE_NAME}
40
- WHERE namespace = ?1
41
- AND org_id = ?2
42
- AND project_id = ?3
43
- AND env_id = ?4
44
- AND record_scope = ?5
45
- AND record_id = ?6`).bind(...this.bindKey(key)).first();
37
+ const row = await this.prepareGet(scope, id).first();
38
+ return this.parseGet(scope, id, row);
39
+ }
40
+ prepareGet(scope, id) {
41
+ return this.prepareRead(this.normalizeKey(scope, id));
42
+ }
43
+ async parseGet(scope, id, row) {
46
44
  if (!row) return null;
47
45
  const parsed = parseStoredRow(row);
48
46
  if (parsed.expiresAtMs > Date.now()) return parsed;
49
- await this.deleteVersion(key, parsed.version);
47
+ await this.deleteVersion(this.normalizeKey(scope, id), parsed.version);
50
48
  return null;
51
49
  }
52
50
  async putExact(mutation) {
@@ -64,11 +62,53 @@ var D1RegistrationCeremonyRecordStore = class {
64
62
  async insertOrRead(mutation) {
65
63
  const key = this.normalizeKey(mutation.scope, mutation.id);
66
64
  const prepared = prepareValue(mutation.value, mutation.expiresAtMs);
67
- await this.insert(key, prepared);
65
+ if (await this.insert(key, prepared) && prepared.expiresAtMs > Date.now()) return parseStoredRow({
66
+ version: 1,
67
+ record_json: prepared.recordJson,
68
+ expires_at_ms: prepared.expiresAtMs
69
+ });
68
70
  const stored = await this.get(mutation.scope, mutation.id);
69
71
  if (!stored) throw conflict("Registration setup expired during persistence");
70
72
  return stored;
71
73
  }
74
+ /**
75
+ * Stores `mutation` and opens `copyScope` with the value that `mutation`'s
76
+ * key then holds, in one batch. A competing insert leaves its winner in both
77
+ * records, as two `insertOrRead` calls in series would.
78
+ */
79
+ async insertOrReadWithCopy(mutation, copyScope, companion) {
80
+ const key = this.normalizeKey(mutation.scope, mutation.id);
81
+ const copyKey = this.normalizeKey(copyScope, mutation.id);
82
+ const nowMs = Date.now();
83
+ const results = await this.database.batch([
84
+ this.prepareInsert(key, prepareValue(mutation.value, mutation.expiresAtMs)),
85
+ this.database.prepare(`INSERT OR IGNORE INTO ${TABLE_NAME}
86
+ (namespace, org_id, project_id, env_id, record_scope, record_id,
87
+ version, record_json, expires_at_ms, updated_at_ms)
88
+ SELECT namespace, org_id, project_id, env_id, ?7, record_id,
89
+ 1, record_json, expires_at_ms, ?8
90
+ FROM ${TABLE_NAME}
91
+ WHERE namespace = ?1
92
+ AND org_id = ?2
93
+ AND project_id = ?3
94
+ AND env_id = ?4
95
+ AND record_scope = ?5
96
+ AND record_id = ?6
97
+ AND expires_at_ms > ?8`).bind(...this.bindKey(key), copyKey.scope, nowMs),
98
+ this.prepareRead(key),
99
+ this.prepareRead(copyKey),
100
+ ...companion
101
+ ]);
102
+ const record = results[2]?.results?.[0];
103
+ const copy = results[3]?.results?.[0];
104
+ if (!record || !copy) throw conflict("Registration setup expired during persistence");
105
+ const stored = {
106
+ record: parseStoredRow(record),
107
+ copy: parseStoredRow(copy)
108
+ };
109
+ if (stored.record.expiresAtMs <= nowMs || stored.copy.expiresAtMs <= nowMs) throw conflict("Registration setup expired during persistence");
110
+ return stored;
111
+ }
72
112
  async updateExpected(input) {
73
113
  const key = this.normalizeKey(input.scope, input.id);
74
114
  const current = await this.get(input.scope, input.id);
@@ -129,11 +169,22 @@ var D1RegistrationCeremonyRecordStore = class {
129
169
  };
130
170
  }
131
171
  async updateExpectedVersion(input) {
172
+ if (changes(await this.prepareVersionedUpdate(input).run()) !== 1) throw conflict("Registration ceremony record changed during versioned update");
173
+ return input.expectedVersion + 1;
174
+ }
175
+ /**
176
+ * The update of `updateExpectedVersion` with its guard, for a batch that
177
+ * another store owns on this database. The guard fails that batch when the
178
+ * record is no longer at the expected version.
179
+ */
180
+ prepareExpectedVersionUpdate(input) {
181
+ return [this.prepareVersionedUpdate(input), this.database.prepare(CAS_GUARD_SQL)];
182
+ }
183
+ prepareVersionedUpdate(input) {
132
184
  const key = this.normalizeKey(input.scope, input.id);
133
185
  if (!Number.isSafeInteger(input.expectedVersion) || input.expectedVersion < 1) throw new Error("Registration ceremony expected version is invalid");
134
186
  const next = prepareValue(input.next, input.expiresAtMs);
135
- if (changes(await this.database.prepare(UPDATE_EXPECTED_VERSION_SQL).bind(...this.bindKey(key), next.recordJson, next.expiresAtMs, Date.now(), input.expectedVersion).run()) !== 1) throw conflict("Registration ceremony record changed during versioned update");
136
- return input.expectedVersion + 1;
187
+ return this.database.prepare(UPDATE_EXPECTED_VERSION_SQL).bind(...this.bindKey(key), next.recordJson, next.expiresAtMs, Date.now(), input.expectedVersion);
137
188
  }
138
189
  async take(scope, id) {
139
190
  const key = this.normalizeKey(scope, id);
@@ -198,6 +249,16 @@ var D1RegistrationCeremonyRecordStore = class {
198
249
  }
199
250
  return true;
200
251
  }
252
+ prepareRead(key) {
253
+ return this.database.prepare(`SELECT version, record_json, expires_at_ms
254
+ FROM ${TABLE_NAME}
255
+ WHERE namespace = ?1
256
+ AND org_id = ?2
257
+ AND project_id = ?3
258
+ AND env_id = ?4
259
+ AND record_scope = ?5
260
+ AND record_id = ?6`).bind(...this.bindKey(key));
261
+ }
201
262
  async insert(key, value) {
202
263
  return changes(await this.prepareInsert(key, value).run()) === 1;
203
264
  }
@@ -1,7 +1,7 @@
1
1
  import { parseChallengeSubjectId, parseEmailOtpChallengeId, parseOrgId, parseProviderSubject, parseRootShareEpoch, parseWalletAuthMethodId, parseWalletAuthorityId, parseWebAuthnRpId } from "../../../../shared-ts/src/utils/domainIds.js";
2
2
  import { parseDeviceId } from "../../../../shared-ts/src/authorization/capabilityKinds.js";
3
- import { parseDigestB64u } from "../../../../shared-ts/src/utils/canonicalPrimitives.js";
4
3
  import { normalizeOptionalTrimmedString } from "../../../../shared-ts/src/utils/normalize.js";
4
+ import { parseDigestB64u } from "../../../../shared-ts/src/utils/canonicalPrimitives.js";
5
5
  import { parseWalletAddAuthMethodRegistrationOptions } from "../../../../shared-ts/src/utils/addAuthMethodRegistration.js";
6
6
  import { parseRouterAbEd25519YaoRegistrationActivationAdmissionReceiptV1, parseRouterAbEd25519YaoRegistrationActivationResultV1, parseRouterAbEd25519YaoRegistrationAdmissionRequestV1 } from "../../../../shared-ts/src/utils/routerAbEd25519Yao.js";
7
7
  import { deriveEvmFamilySigningKeySlotId } from "../../../../shared-ts/src/signing-lanes/evmFamilySigningKeySlotId.js";
@@ -1,10 +1,12 @@
1
1
  import { normalizeOptionalTrimmedString } from "../../../../shared-ts/src/utils/normalize.js";
2
2
  import { isPlainObject } from "../../../../shared-ts/src/utils/validation.js";
3
+ import { prepareD1RegistrationHomeReservation } from "./d1WalletExecutionAuthority.js";
3
4
  import { parseD1StoredAddAuthMethodIntent, parseD1StoredAddSignerIntent, parseD1StoredWalletAddAuthMethodCeremony, parseD1StoredWalletAddAuthMethodFinalizeReplay, parseD1StoredWalletAddSignerCeremony, parseD1StoredWalletAddSignerFinalizeReplay, parseD1StoredWalletRegistrationCeremony } from "./d1RegistrationCeremonyRecords.js";
4
5
  import { D1RegistrationCeremonyRecordStore } from "./d1RegistrationCeremonyRecordStore.js";
5
6
  //#region src/router/cloudflare/d1/registration/d1RegistrationCeremonyStore.ts
6
7
  var CloudflareD1RegistrationCeremonyIntentStore = class {
7
8
  constructor(input) {
9
+ this.input = input;
8
10
  this.storage = new D1RegistrationCeremonyRecordStore(input);
9
11
  }
10
12
  async getSetupCeremony(ceremonyId) {
@@ -14,40 +16,47 @@ var CloudflareD1RegistrationCeremonyIntentStore = class {
14
16
  if (!ceremony) throw new Error("Registration setup snapshot is invalid");
15
17
  return ceremony;
16
18
  }
17
- async reserveSetupCeremony(proposed) {
18
- const ceremony = parseD1StoredWalletRegistrationCeremony((await this.storage.insertOrRead({
19
+ /** One batch stores the setup snapshot, ceremony, and authenticated execution identity. */
20
+ async reserveSetupCeremony(proposed, ownershipGeneration) {
21
+ const stored = await this.storage.insertOrReadWithCopy({
19
22
  scope: "setup-ceremony",
20
23
  id: proposed.registrationCeremonyId,
21
24
  value: encodeRecord(proposed),
22
25
  expiresAtMs: proposed.expiresAtMs
23
- })).value);
24
- if (!ceremony || ceremony.registrationCeremonyId !== proposed.registrationCeremonyId || ceremony.expiresAtMs !== proposed.expiresAtMs || ceremony.orgId !== proposed.orgId || ceremony.digestB64u !== proposed.digestB64u || ceremony.foundingWalletAuthorityId !== proposed.foundingWalletAuthorityId || ceremony.foundingDeviceId !== proposed.foundingDeviceId || ceremony.foundingWalletAuthMethodId !== proposed.foundingWalletAuthMethodId || ceremony.expectedOrigin !== proposed.expectedOrigin) throw new Error("Registration setup snapshot conflicts with its reservation");
25
- await this.ensureSetupCeremony(ceremony);
26
+ }, "ceremony", prepareD1RegistrationHomeReservation(this.input.database, this.input.scope, {
27
+ walletId: proposed.intent.walletId,
28
+ ceremonyId: proposed.registrationCeremonyId,
29
+ ownershipGeneration
30
+ }));
31
+ const ceremony = parseD1StoredWalletRegistrationCeremony(stored.record.value);
32
+ if (!ceremony || !sameSetupReservation(ceremony, proposed)) throw new Error("Registration setup snapshot conflicts with its reservation");
33
+ const current = parseD1StoredWalletRegistrationCeremony(stored.copy.value);
34
+ if (!current || !sameSetupReservation(current, ceremony)) throw new Error("Registration ceremony conflicts with its setup snapshot");
26
35
  return ceremony;
27
36
  }
28
- async ensureSetupCeremony(setup) {
29
- const current = parseD1StoredWalletRegistrationCeremony((await this.storage.insertOrRead({
30
- scope: "ceremony",
31
- id: setup.registrationCeremonyId,
32
- value: encodeRecord(setup),
33
- expiresAtMs: setup.expiresAtMs
34
- })).value);
35
- if (!current || current.registrationCeremonyId !== setup.registrationCeremonyId || current.expiresAtMs !== setup.expiresAtMs || current.orgId !== setup.orgId || current.digestB64u !== setup.digestB64u || current.foundingWalletAuthorityId !== setup.foundingWalletAuthorityId || current.foundingDeviceId !== setup.foundingDeviceId || current.foundingWalletAuthMethodId !== setup.foundingWalletAuthMethodId || current.expectedOrigin !== setup.expectedOrigin) throw new Error("Registration ceremony conflicts with its setup snapshot");
36
- }
37
37
  async getCeremony(registrationCeremonyId) {
38
38
  return (await this.getCeremonySnapshot(registrationCeremonyId))?.ceremony ?? null;
39
39
  }
40
- async getCeremonySnapshot(registrationCeremonyId) {
41
- const id = normalizeOptionalTrimmedString(registrationCeremonyId);
42
- if (!id) return null;
43
- const stored = await this.storage.get("ceremony", id);
40
+ prepareCeremonyRead(registrationCeremonyId) {
41
+ return this.storage.prepareGet("ceremony", registrationCeremonyId);
42
+ }
43
+ async parseCeremonyRead(registrationCeremonyId, result) {
44
+ return (await this.parseCeremonySnapshotRead(registrationCeremonyId, result))?.ceremony ?? null;
45
+ }
46
+ async parseCeremonySnapshotRead(registrationCeremonyId, result) {
47
+ if (!result.success) throw new Error("Registration ceremony D1 read failed");
48
+ const stored = await this.storage.parseGet("ceremony", registrationCeremonyId, result.results?.[0] ?? null);
44
49
  if (!stored) return null;
45
50
  const ceremony = parseD1StoredWalletRegistrationCeremony(stored.value);
46
- if (!ceremony || ceremony.expiresAtMs <= Date.now()) return null;
47
- return {
51
+ return ceremony && ceremony.expiresAtMs > Date.now() ? {
48
52
  ceremony,
49
53
  version: stored.version
50
- };
54
+ } : null;
55
+ }
56
+ async getCeremonySnapshot(registrationCeremonyId) {
57
+ const id = normalizeOptionalTrimmedString(registrationCeremonyId);
58
+ if (!id) return null;
59
+ return this.parseCeremonySnapshotRead(id, await this.prepareCeremonyRead(id).all());
51
60
  }
52
61
  async updateCeremony(input) {
53
62
  if (input.expected.registrationCeremonyId !== input.next.registrationCeremonyId) throw new Error("Registration ceremony update cannot change its identity");
@@ -90,14 +99,11 @@ var CloudflareD1RegistrationCeremonyIntentStore = class {
90
99
  });
91
100
  }
92
101
  async commitEcdsaClaim(input) {
93
- if (input.expected.ceremony.registrationCeremonyId !== input.next.registrationCeremonyId) throw new Error("ECDSA registration claim commit cannot change its ceremony identity");
94
- await this.storage.updateExpectedVersion({
95
- scope: "ceremony",
96
- id: input.next.registrationCeremonyId,
97
- expectedVersion: input.expected.version,
98
- next: encodeRecord(input.next),
99
- expiresAtMs: input.next.expiresAtMs
100
- });
102
+ await this.storage.updateExpectedVersion(ceremonyCommitUpdate(input));
103
+ }
104
+ /** `commitEcdsaClaim` as statements for a batch that another store owns on this database. */
105
+ prepareEcdsaClaimCommit(input) {
106
+ return { statements: this.storage.prepareExpectedVersionUpdate(ceremonyCommitUpdate(input)) };
101
107
  }
102
108
  async deleteCeremony(registrationCeremonyId) {
103
109
  const id = normalizeOptionalTrimmedString(registrationCeremonyId);
@@ -318,6 +324,20 @@ function encodeRecord(value) {
318
324
  if (!isPlainObject(value)) throw new Error("Registration ceremony record must be an object");
319
325
  return value;
320
326
  }
327
+ function ceremonyCommitUpdate(input) {
328
+ if (input.expected.ceremony.registrationCeremonyId !== input.next.registrationCeremonyId) throw new Error("ECDSA registration claim commit cannot change its ceremony identity");
329
+ return {
330
+ scope: "ceremony",
331
+ id: input.next.registrationCeremonyId,
332
+ expectedVersion: input.expected.version,
333
+ next: encodeRecord(input.next),
334
+ expiresAtMs: input.next.expiresAtMs
335
+ };
336
+ }
337
+ /** The facts a reservation fixes for its setup snapshot and its ceremony. */
338
+ function sameSetupReservation(stored, expected) {
339
+ return stored.registrationCeremonyId === expected.registrationCeremonyId && stored.expiresAtMs === expected.expiresAtMs && stored.orgId === expected.orgId && stored.digestB64u === expected.digestB64u && stored.foundingWalletAuthorityId === expected.foundingWalletAuthorityId && stored.foundingDeviceId === expected.foundingDeviceId && stored.foundingWalletAuthMethodId === expected.foundingWalletAuthMethodId && stored.expectedOrigin === expected.expectedOrigin;
340
+ }
321
341
  //#endregion
322
342
  export { CloudflareD1RegistrationCeremonyIntentStore };
323
343
 
@@ -0,0 +1,28 @@
1
+ //#region src/router/cloudflare/d1/registration/d1RegistrationSessionTransaction.ts
2
+ /** The wallet's version checks and the session's winner read share one batch. */
3
+ var D1RegistrationSessionTransaction = class {
4
+ constructor(database, commitWallet) {
5
+ this.database = database;
6
+ this.commitWallet = commitWallet;
7
+ this.sessionResults = null;
8
+ }
9
+ async execute(sessionStatements) {
10
+ await this.commitWallet(this.commit.bind(this, sessionStatements));
11
+ if (this.sessionResults === null) throw new Error("Registration wallet commit did not execute its session transaction");
12
+ return this.sessionResults;
13
+ }
14
+ async commit(sessionStatements, walletStatements) {
15
+ this.sessionResults = null;
16
+ const results = await this.database.batch([...walletStatements, ...sessionStatements]);
17
+ if (results.length !== walletStatements.length + sessionStatements.length || results.some(batchStatementFailed)) throw new Error("Registration wallet/session transaction returned incomplete results");
18
+ this.sessionResults = results.slice(walletStatements.length);
19
+ return results.slice(0, walletStatements.length);
20
+ }
21
+ };
22
+ function batchStatementFailed(result) {
23
+ return !result.success;
24
+ }
25
+ //#endregion
26
+ export { D1RegistrationSessionTransaction };
27
+
28
+ //# sourceMappingURL=d1RegistrationSessionTransaction.js.map