@seams/wallet-server 0.8.0 → 0.9.1
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.
- package/THIRD_PARTY_NOTICES.md +7 -1
- package/artifact-manifest.json +196 -41
- package/cloudflare-router-ab/build/deriver-a/build-stamp.json +1 -1
- package/cloudflare-router-ab/build/deriver-a/index.js +2 -2
- package/cloudflare-router-ab/build/deriver-a/index_bg.wasm +0 -0
- package/cloudflare-router-ab/build/deriver-b/build-stamp.json +1 -1
- package/cloudflare-router-ab/build/deriver-b/index.js +2 -2
- package/cloudflare-router-ab/build/deriver-b/index_bg.wasm +0 -0
- package/cloudflare-router-ab/build/local-tools/darwin-arm64/router_ab_local_init +0 -0
- package/cloudflare-router-ab/build/local-tools/darwin-x64/router_ab_local_init +0 -0
- package/cloudflare-router-ab/build/local-tools/linux-x64/router_ab_local_init +0 -0
- package/cloudflare-router-ab/build/router/build-stamp.json +1 -1
- package/cloudflare-router-ab/build/router/index.js +2 -2
- package/cloudflare-router-ab/build/router/index_bg.wasm +0 -0
- package/cloudflare-router-ab/build/signing-worker/build-stamp.json +1 -1
- package/cloudflare-router-ab/build/signing-worker/index.js +2 -2
- package/cloudflare-router-ab/build/signing-worker/index_bg.wasm +0 -0
- package/cloudflare-router-ab/build/tenant-root-control-plane/build-stamp.json +1 -1
- package/cloudflare-router-ab/build/tenant-root-control-plane/index.js +2 -2
- package/cloudflare-router-ab/build/tenant-root-control-plane/index_bg.wasm +0 -0
- package/cloudflare-router-ab/migrations/deriver-a/0019_wallet_object_addresses.sql +10 -0
- package/cloudflare-router-ab/migrations/deriver-b/0019_wallet_object_addresses.sql +10 -0
- package/cloudflare-router-ab/scripts/prepare-local-runtime-config.mjs +3 -117
- package/cloudflare-router-ab/wrangler.deriver-a.toml +0 -8
- package/cloudflare-router-ab/wrangler.deriver-b.toml +24 -8
- package/cloudflare-router-ab/wrangler.router.toml +0 -2
- package/cloudflare-router-ab/wrangler.signing-worker.toml +29 -0
- package/dist/esm/authorization/domain.js +3 -2
- package/dist/esm/authorization/ed25519WalletSessionAdmission.js +0 -0
- package/dist/esm/authorization/service.js +64 -36
- package/dist/esm/cloud-host.js +24 -19
- package/dist/esm/core/EmailOtpRecords.js +29 -6
- package/dist/esm/core/ThresholdService/routerAb/ecdsaDerivationPoolFillHandlers.js +2 -0
- package/dist/esm/core/ThresholdService/routerAb/ecdsaDerivationPresignBridge.js +10 -0
- package/dist/esm/core/ThresholdService/routerAb/internalServiceHttp.js +1 -0
- package/dist/esm/core/ThresholdService/validation.js +2 -2
- package/dist/esm/core/authService/nearPrivateKeySigning.js +1 -1
- package/dist/esm/core/authService/webauthn.js +1 -1
- package/dist/esm/core/d1Ed25519SignerRead.js +55 -0
- package/dist/esm/core/d1WalletStore.js +14 -11
- package/dist/esm/core/deviceLinking/linkedDeviceEmailOtpGrant.js +2 -2
- package/dist/esm/core/deviceLinking/linkedDeviceManagement.js +1 -1
- package/dist/esm/core/deviceLinking/linkedDeviceSessionRecord.js +2 -2
- package/dist/esm/core/emailOtpD1Statements.js +1 -0
- package/dist/esm/core/nearRelayerAccountProvisioning.js +1 -1
- package/dist/esm/core/routerAbSigning/RouterAbEcdsaPresignRuntime.js +4 -0
- package/dist/esm/core/signingLanes/WalletExecutionLaneProjection.js +1 -1
- package/dist/esm/core/signingMaterial/ordinaryInactiveSignerMaterialReservation.js +1 -0
- package/dist/esm/hosted-wallet-gateway.js +93 -10
- package/dist/esm/localHostedWalletGatewayHandler.js +12 -9
- package/dist/esm/localIntendedYaoSigningFault.js +2 -30
- package/dist/esm/localRegistrationSetupAuthority.js +8 -1
- package/dist/esm/router/auth/commonRouterUtils.js +17 -10
- package/dist/esm/router/auth/routerApiCredentialAuth.js +26 -7
- package/dist/esm/router/auth/walletRegistrationContext.js +49 -0
- package/dist/esm/router/auth/webAuthnCredentialCodecs.js +1 -1
- package/dist/esm/router/cloudflare/d1/auth/d1AuthorizationAssembly.js +4 -3
- package/dist/esm/router/cloudflare/d1/auth/d1AuthorizedOperationRouteService.js +2 -0
- package/dist/esm/router/cloudflare/d1/auth/d1EmailOtpRouteService.js +25 -0
- package/dist/esm/router/cloudflare/d1/auth/d1RouterApiAuthConfig.js +14 -6
- package/dist/esm/router/cloudflare/d1/auth/d1RouterApiAuthService.js +44 -40
- package/dist/esm/router/cloudflare/d1/auth/walletSessionCredentialReaders.js +17 -1
- package/dist/esm/router/cloudflare/d1/authorization/authorizedOperationStatements.js +35 -5
- package/dist/esm/router/cloudflare/d1/authorization/d1AuthorizationStore.js +258 -99
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceAuthorityInstallService.js +31 -4
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceOwnerAuthorizationProvider.js +1 -1
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceRequestProofNonceStore.js +1 -1
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceSessionRecords.js +1 -1
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceTargetCredentialProvider.js +1 -1
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceTargetPlanner.js +1 -1
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceVerifiedLinkBuilder.js +1 -1
- package/dist/esm/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoLifecycleDecisionStore.js +11 -2
- package/dist/esm/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoProductRegistrationPartitionedStateStore.js +100 -10
- package/dist/esm/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoStateWriteFence.js +92 -0
- package/dist/esm/router/cloudflare/d1/ed25519Yao/d1WalletCeremonyActivity.js +77 -0
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeIssuer.js +14 -8
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeStore.js +14 -8
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeVerifier.js +3 -1
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRateLimitStore.js +58 -38
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRecords.js +27 -20
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRecoveryService.js +1 -0
- package/dist/esm/router/cloudflare/d1/emailOtp/d1GoogleEmailOtpSessionResolver.js +1 -0
- package/dist/esm/router/cloudflare/d1/oidc/d1OidcBoundary.js +1 -1
- package/dist/esm/router/cloudflare/d1/passkeyCustody/d1WalletCustodyCommitStore.js +18 -7
- package/dist/esm/router/cloudflare/d1/registration/d1RegistrationCeremonyRecordStore.js +75 -14
- package/dist/esm/router/cloudflare/d1/registration/d1RegistrationCeremonyRecords.js +1 -1
- package/dist/esm/router/cloudflare/d1/registration/d1RegistrationCeremonyStore.js +49 -29
- package/dist/esm/router/cloudflare/d1/registration/d1RegistrationSessionTransaction.js +28 -0
- package/dist/esm/router/cloudflare/d1/registration/d1RegistrationSetupSupport.js +11 -1
- package/dist/esm/router/cloudflare/d1/registration/d1WalletExecutionAuthority.js +168 -0
- package/dist/esm/router/cloudflare/d1/registration/d1WalletOperationStore.js +53 -0
- package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationCommitStore.js +83 -42
- package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationInitialSession.js +33 -0
- package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationPreparation.js +16 -0
- package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationRead.js +58 -0
- package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationService.js +439 -500
- package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationSetup.js +1 -1
- package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationSetupExecution.js +104 -90
- package/dist/esm/router/cloudflare/d1/registration/walletRegistrationEstablishedSessionIssuer.js +78 -44
- package/dist/esm/router/cloudflare/d1/registration/walletRegistrationSessionCommitReceipt.js +11 -35
- package/dist/esm/router/cloudflare/d1/signingAdmission/d1RouterAbNormalSigningAdmissionStore.js +98 -39
- package/dist/esm/router/cloudflare/d1/versionedJson/d1VersionedJsonRecordStore.js +12 -9
- package/dist/esm/router/cloudflare/d1/wallet/authorizationSnapshotLayout.js +168 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAddSignerFinalizeRecord.js +1 -1
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAddSignerService.js +15 -6
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthMethodService.js +3 -40
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorityStore.js +54 -1
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorizationCleanup.js +157 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorizationFreeze.js +56 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorizationHistory.js +238 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorizationIntake.js +287 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorizationSnapshot.js +295 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationApprovals.js +140 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationChallenges.js +170 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationEmailOtp.js +60 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationOwner.js +33 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationOwnerRequest.js +74 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationPasskey.js +77 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationReadAccess.js +37 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationSessions.js +97 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationWriteBlock.js +133 -0
- package/dist/esm/router/cloudflare/d1/walletObjectAddresses.js +47 -0
- package/dist/esm/router/cloudflare/d1/webauthn/d1WebAuthnAuthService.js +1 -1
- package/dist/esm/router/cloudflare/runtime/routerAbServiceBindings.js +32 -1
- package/dist/esm/router/cloudflare/runtime/staticWalletConsoleBinding.js +20 -8
- package/dist/esm/router/cloudflare/runtime/walletAuthorizationRelocationRoutes.js +488 -0
- package/dist/esm/router/cloudflare/runtime/walletConsoleOps.js +1 -1
- package/dist/esm/router/cloudflare/runtime/walletConsoleOpsClient.js +26 -6
- package/dist/esm/router/cloudflare/runtime/walletControlOps.js +3 -0
- package/dist/esm/router/cloudflare/runtime/walletGateway.js +1 -1
- package/dist/esm/router/cloudflare/runtime/walletObjectAddresses.js +105 -0
- package/dist/esm/router/cloudflare/runtime/walletPlacementRoutes.js +339 -0
- package/dist/esm/router/cloudflare/runtime/walletRelocationDeriver.js +244 -0
- package/dist/esm/router/cloudflare/runtime/walletRelocationEcdsa.js +212 -0
- package/dist/esm/router/cloudflare/runtime/walletRelocationEd25519.js +172 -0
- package/dist/esm/router/cloudflare/runtime/walletRelocationOps.js +183 -0
- package/dist/esm/router/cloudflare/runtime/walletRelocationPresign.js +185 -0
- package/dist/esm/router/cloudflare/runtime/walletRelocationSource.js +221 -0
- package/dist/esm/router/cloudflare/signingLanes/cloudflareOrdinaryInactiveSignerMaterialReservation.js +30 -8
- package/dist/esm/router/cloudflare-adaptor.js +8 -8
- package/dist/esm/router/cloudflare.js +34115 -32240
- package/dist/esm/router/domains/ecdsa/routerAbEcdsaStrictRegistration.js +35 -9
- package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoCapabilityCommit.js +42 -0
- package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistration.js +32 -6
- package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationPartitionedStateStore.js +61 -1
- package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationPersistence.js +70 -3
- package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationRequestScopedRuntime.js +59 -87
- package/dist/esm/router/domains/ed25519Yao/export/routerAbEd25519YaoExport.js +52 -22
- package/dist/esm/router/domains/ed25519Yao/export/routerAbEd25519YaoExportRequestScopedCloudflare.js +10 -7
- package/dist/esm/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecovery.js +108 -78
- package/dist/esm/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecoveryRequestScopedCloudflare.js +19 -5
- package/dist/esm/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecoveryWalletSessionAuthorization.js +71 -22
- package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoHttpRegistrationBackend.js +37 -25
- package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistration.js +3 -3
- package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationExecutionRecord.js +2 -1
- package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationIntentAuthorization.js +24 -3
- package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationRequestScopedCloudflare.js +4 -3
- package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationSideEffectBoundary.js +20 -7
- package/dist/esm/router/domains/ed25519Yao/routerAbEd25519YaoGatewayEnvelope.js +7 -1
- package/dist/esm/router/domains/emailOtp/emailOtpRouteHandlers.js +2 -2
- package/dist/esm/router/domains/passkeyCustody/passkeyCustodyEnvelopeRetrieval.js +1 -1
- package/dist/esm/router/domains/passkeyCustody/registrationCustodyOutcome.js +34 -18
- package/dist/esm/router/domains/passkeyCustody/walletCustodyRegistrationAdmission.js +2 -2
- package/dist/esm/router/domains/passkeyCustody/walletCustodyRegistrationCommit.js +16 -6
- package/dist/esm/router/domains/signingOperations/authorizedOperationWire.js +73 -0
- package/dist/esm/router/domains/signingOperations/ecdsaSigningResponse.js +31 -0
- package/dist/esm/router/domains/signingOperations/ed25519AuthorizedOperationReceipt.js +1 -1
- package/dist/esm/router/domains/signingOperations/routerAbEcdsaDerivationNormalSigningRoute.js +2 -1
- package/dist/esm/router/domains/signingOperations/routerAbEd25519NormalSigningRoute.js +31 -121
- package/dist/esm/router/domains/signingOperations/routerAbNormalSigningAdmission.js +2 -93
- package/dist/esm/router/domains/signingOperations/routerAbPrivateSigningWorker.js +1 -1
- package/dist/esm/router/domains/signingOperations/signingPrepareSession.js +33 -0
- package/dist/esm/router/domains/walletRegistration/registrationSessionSeal.js +121 -0
- package/dist/esm/router/domains/walletRegistration/walletRegistrationReservation.js +4 -4
- package/dist/esm/router/domains/walletRegistration/walletRegistrationRoutes.js +46 -157
- package/dist/esm/router/domains/walletRegistration/walletRegistrationSetupPayload.js +1 -1
- package/dist/esm/router/express.js +764 -894
- package/dist/esm/router/framework/http.js +2 -1
- package/dist/esm/router/transport/fetch/createFetchRouter.js +2 -2
- package/dist/esm/router/transport/fetch/routes/auth.js +1 -1
- package/dist/esm/router/transport/fetch/routes/deviceLinking.js +3 -3
- package/dist/esm/router/transport/fetch/routes/deviceLinkingOwnerAuthorization.js +2 -2
- package/dist/esm/router/transport/fetch/routes/ed25519AuthorizedOperationRevalidation.js +65 -0
- package/dist/esm/router/transport/fetch/routes/normalSigningRouterProxy.js +13 -3
- package/dist/esm/router/transport/fetch/routes/passkeyCustody.js +3 -3
- package/dist/esm/router/transport/fetch/routes/sessions.js +3 -2
- package/dist/esm/router/transport/fetch/routes/thresholdEcdsa.js +67 -130
- package/dist/esm/router/transport/fetch/routes/thresholdEd25519.js +76 -212
- package/dist/esm/router/transport/fetch/routes/walletExecutionLanePreflight.js +18 -41
- package/dist/esm/router/transport/fetch/routes/walletRegistration.js +6 -5
- package/dist/esm/router/transport/fetch/routes/webauthnAuthenticators.js +1 -1
- package/dist/esm/shared-ts/src/authorization/index.js +1 -1
- package/dist/esm/shared-ts/src/authorization/walletAuthority.js +2 -2
- package/dist/esm/shared-ts/src/device-linking/activeWalletSession.js +12 -2
- package/dist/esm/shared-ts/src/device-linking/digests.js +1 -1
- package/dist/esm/shared-ts/src/device-linking/ed25519ExportRoot.js +1 -1
- package/dist/esm/shared-ts/src/device-linking/index.js +1 -1
- package/dist/esm/shared-ts/src/device-linking/parsers.js +1 -1
- package/dist/esm/shared-ts/src/device-linking/sourceContribution.js +1 -1
- package/dist/esm/shared-ts/src/device-linking/wireFields.js +1 -1
- package/dist/esm/shared-ts/src/near/nearClient.js +1 -1
- package/dist/esm/shared-ts/src/signing-lanes/ownerContinuity.js +2 -2
- package/dist/esm/shared-ts/src/utils/ecdsaServerTiming.js +6 -1
- package/dist/esm/shared-ts/src/utils/emailOtpDomain.js +4 -2
- package/dist/esm/shared-ts/src/utils/routerAbEcdsaDerivation.js +1 -1
- package/dist/esm/shared-ts/src/utils/routerAbPublicKeyset.js +0 -27
- package/dist/esm/shared-ts/src/wallet-recovery/walletRecoveryEcdsaPossession.js +1 -1
- package/dist/esm/threshold/session/signingSessionSeal/options.js +1 -1
- package/dist/esm/wasm/near_signer/pkg/wasm_signer_worker_bg.wasm +0 -0
- package/dist/types/shared-ts/src/device-linking/activeWalletSession.d.ts +2 -1
- package/dist/types/shared-ts/src/device-linking/contracts.d.ts +10 -0
- package/dist/types/shared-ts/src/threshold/ed25519OperationFingerprint.d.ts +2 -1
- package/dist/types/shared-ts/src/utils/emailOtpDomain.d.ts +3 -1
- package/dist/types/shared-ts/src/utils/routerAbPublicKeyset.d.ts +0 -9
- package/dist/types/shared-ts/src/utils/walletManagementProtocol.d.ts +1 -1
- package/dist/types/wallet-server/src/authorization/domain.d.ts +17 -1
- package/dist/types/wallet-server/src/authorization/ecdsaWalletSessionAdmission.d.ts +1 -0
- package/dist/types/wallet-server/src/authorization/ed25519WalletSessionAdmission.d.ts +35 -0
- package/dist/types/wallet-server/src/authorization/ed25519WalletSessionAdmission.typecheck.d.ts +2 -0
- package/dist/types/wallet-server/src/authorization/service.d.ts +43 -5
- package/dist/types/wallet-server/src/authorization/sessionRouting.d.ts +2 -0
- package/dist/types/wallet-server/src/cloud-host.d.ts +7 -3
- package/dist/types/wallet-server/src/core/EmailOtpRecords.d.ts +2 -1
- package/dist/types/wallet-server/src/core/EmailOtpStores.d.ts +19 -5
- package/dist/types/wallet-server/src/core/ThresholdService/routerAb/ecdsaDerivationPoolFillHandlers.d.ts +1 -0
- package/dist/types/wallet-server/src/core/ThresholdService/routerAb/ecdsaDerivationPresignBridge.d.ts +6 -0
- package/dist/types/wallet-server/src/core/ThresholdService/routerAb/internalServiceHttp.d.ts +1 -0
- package/dist/types/wallet-server/src/core/d1Ed25519SignerRead.d.ts +17 -0
- package/dist/types/wallet-server/src/core/d1WalletStore.d.ts +6 -0
- package/dist/types/wallet-server/src/core/emailOtpD1Statements.d.ts +1 -0
- package/dist/types/wallet-server/src/core/routerAbSigning/RouterAbEcdsaPresignRuntime.d.ts +5 -1
- package/dist/types/wallet-server/src/core/signingMaterial/ordinaryInactiveSignerMaterialReservation.d.ts +1 -0
- package/dist/types/wallet-server/src/core/threeRouteRegistrationContracts.d.ts +14 -48
- package/dist/types/wallet-server/src/hosted-wallet-gateway.d.ts +4 -3
- package/dist/types/wallet-server/src/localIntendedYaoSigningFault.d.ts +1 -16
- package/dist/types/wallet-server/src/localRegistrationSetupAuthority.d.ts +1 -1
- package/dist/types/wallet-server/src/router/auth/commonRouterUtils.d.ts +7 -1
- package/dist/types/wallet-server/src/router/auth/routerApiCredentialAuth.d.ts +11 -3
- package/dist/types/wallet-server/src/router/auth/walletRegistrationContext.d.ts +8 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/auth/d1AuthorizationAssembly.d.ts +1 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/auth/d1EmailOtpRouteService.d.ts +16 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/auth/d1RouterApiAuthConfig.d.ts +7 -4
- package/dist/types/wallet-server/src/router/cloudflare/d1/auth/d1RouterApiAuthService.d.ts +4 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/auth/walletSessionCredentialReaders.d.ts +7 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/authorization/d1AuthorizationStore.d.ts +32 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceAuthorityInstallService.d.ts +2 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoLifecycleDecisionStore.d.ts +3 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoProductRegistrationPartitionedStateStore.d.ts +1 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoStateWriteFence.d.ts +8 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/ed25519Yao/d1WalletCeremonyActivity.d.ts +15 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeIssuer.d.ts +6 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeStore.d.ts +1 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeVerifier.d.ts +4 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpCounters.typecheck.d.ts +2 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpRateLimitStore.d.ts +6 -29
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpRecords.d.ts +21 -7
- package/dist/types/wallet-server/src/router/cloudflare/d1/passkeyCustody/d1WalletCustodyCommitStore.d.ts +17 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationCeremonyRecordStore.d.ts +32 -7
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationCeremonyStore.d.ts +16 -7
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationSessionTransaction.d.ts +13 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationSetupSupport.d.ts +7 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletExecutionAuthority.d.ts +41 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletOperationStore.d.ts +28 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationCommitStore.d.ts +6 -9
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationInitialSession.d.ts +17 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationPreparation.d.ts +12 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationRead.d.ts +43 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationService.d.ts +24 -45
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationSetupExecution.d.ts +9 -4
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/walletRegistrationEstablishedSessionIssuer.d.ts +42 -14
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/walletRegistrationSessionCommitReceipt.d.ts +5 -4
- package/dist/types/wallet-server/src/router/cloudflare/d1/signingAdmission/d1RouterAbNormalSigningAdmissionStore.d.ts +24 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/versionedJson/d1VersionedJsonRecordStore.d.ts +10 -4
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/authorizationSnapshotLayout.d.ts +21 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAddSignerService.d.ts +3 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthMethodService.d.ts +3 -7
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorityStore.d.ts +8 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorizationCleanup.d.ts +20 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorizationFreeze.d.ts +12 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorizationHistory.d.ts +20 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorizationIntake.d.ts +29 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorizationSnapshot.d.ts +31 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationApprovals.d.ts +49 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationChallenges.d.ts +47 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationEmailOtp.d.ts +25 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationOwner.d.ts +88 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationOwnerRequest.d.ts +37 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationPasskey.d.ts +12 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationReadAccess.d.ts +18 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationSessions.d.ts +23 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationWriteBlock.d.ts +16 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/walletObjectAddresses.d.ts +14 -0
- package/dist/types/wallet-server/src/router/cloudflare/runtime/routerAbServiceBindings.d.ts +13 -0
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletAuthorizationRelocationRoutes.d.ts +21 -0
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletConsoleOps.d.ts +1 -1
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletConsoleOpsClient.d.ts +3 -3
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletControlOps.d.ts +2 -1
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletGateway.d.ts +3 -1
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletObjectAddresses.d.ts +45 -0
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletPlacementRoutes.d.ts +30 -0
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRelocationDeriver.d.ts +11 -0
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRelocationEcdsa.d.ts +7 -0
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRelocationEd25519.d.ts +7 -0
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRelocationOps.d.ts +11 -0
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRelocationPresign.d.ts +7 -0
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRelocationSource.d.ts +26 -0
- package/dist/types/wallet-server/src/router/cloudflare/signingLanes/cloudflareOrdinaryInactiveSignerMaterialReservation.d.ts +5 -0
- package/dist/types/wallet-server/src/router/domains/ecdsa/routerAbEcdsaStrictRegistration.d.ts +3 -0
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoCapabilityCommit.d.ts +7 -0
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistration.d.ts +41 -7
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationPartitionedStateStore.d.ts +33 -2
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/export/routerAbEd25519YaoExport.d.ts +12 -6
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecovery.d.ts +17 -9
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecoveryWalletSessionAuthorization.d.ts +2 -0
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/registration/routerAbEd25519YaoHttpRegistrationBackend.d.ts +13 -14
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistration.d.ts +7 -3
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationExecutionRecord.d.ts +1 -0
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationIntentAuthorization.d.ts +6 -1
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationSideEffectBoundary.d.ts +11 -0
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/routerAbEd25519YaoGatewayEnvelope.d.ts +12 -3
- package/dist/types/wallet-server/src/router/domains/passkeyCustody/registrationCustodyOutcome.d.ts +10 -6
- package/dist/types/wallet-server/src/router/domains/passkeyCustody/walletCustodyRegistrationAdmission.d.ts +10 -3
- package/dist/types/wallet-server/src/router/domains/passkeyCustody/walletCustodyRegistrationCommit.d.ts +12 -5
- package/dist/types/wallet-server/src/router/domains/signingOperations/authorizedOperationWire.d.ts +97 -0
- package/dist/types/wallet-server/src/router/domains/signingOperations/ecdsaSigningResponse.d.ts +13 -0
- package/dist/types/wallet-server/src/router/domains/signingOperations/routerAbNormalSigningAdmission.d.ts +9 -206
- package/dist/types/wallet-server/src/router/domains/signingOperations/signingPrepareSession.d.ts +23 -0
- package/dist/types/wallet-server/src/router/domains/walletRegistration/registrationSessionSeal.d.ts +36 -0
- package/dist/types/wallet-server/src/router/domains/walletRegistration/walletRegistrationInputs.d.ts +7 -7
- package/dist/types/wallet-server/src/router/domains/walletRegistration/walletRegistrationReservation.d.ts +80 -6
- package/dist/types/wallet-server/src/router/domains/walletRegistration/walletRegistrationRoutes.d.ts +15 -5
- package/dist/types/wallet-server/src/router/framework/apiCredentialPorts.d.ts +24 -0
- package/dist/types/wallet-server/src/router/framework/authServicePort.d.ts +21 -7
- package/dist/types/wallet-server/src/router/framework/routerApi.d.ts +3 -12
- package/dist/types/wallet-server/src/router/transport/fetch/routes/ed25519AuthorizedOperationRevalidation.d.ts +37 -0
- package/dist/types/wallet-server/src/router/transport/fetch/routes/thresholdEcdsa.d.ts +1 -17
- package/dist/types/wallet-server/src/storage/tenantRoute.d.ts +1 -1
- package/migrations/d1-signer/0049_wallet_relocation_challenges.sql +16 -0
- package/migrations/d1-signer/0050_wallet_relocation_approvals.sql +14 -0
- package/migrations/d1-signer/0051_wallet_relocation_email_otp.sql +92 -0
- package/migrations/d1-signer/0052_wallet_relocation_session_fences.sql +91 -0
- package/migrations/d1-signer/0053_wallet_hosted_history_import.sql +164 -0
- package/migrations/d1-signer/0054_wallet_authorization_freeze.sql +318 -0
- package/migrations/d1-signer/0055_wallet_authorization_snapshot.sql +120 -0
- package/migrations/d1-signer/0056_wallet_authorization_history_import.sql +424 -0
- package/migrations/d1-signer/0057_wallet_authorization_intake.sql +44 -0
- package/migrations/d1-signer/0058_wallet_ceremony_activity.sql +59 -0
- package/migrations/d1-signer/0059_wallet_authorization_activation.sql +45 -0
- package/migrations/d1-signer/0060_wallet_authorization_cleanup.sql +153 -0
- package/migrations/d1-signer/0061_wallet_session_operation_settlement.sql +28 -0
- package/migrations/d1-signer/0062_wallet_step_up_operation_settlement.sql +204 -0
- package/migrations/d1-signer/0063_wallet_operation_history_transfer.sql +466 -0
- package/migrations/d1-signer/0064_wallet_execution_generations.sql +93 -0
- package/migrations/d1-signer/0065_wallet_operation_execution_generation.sql +37 -0
- package/migrations/d1-signer/0066_regional_deployment_admission.sql +59 -0
- package/migrations/d1-signer/0067_registration_completion_decision.sql +12 -0
- package/migrations/d1-signer/0068_registration_cancellation_write_fence.sql +24 -0
- package/migrations/d1-signer/0069_cancelled_registration_session_fence.sql +11 -0
- package/migrations/d1-signer/0070_wallet_passkey_relocation.sql +369 -0
- package/migrations/d1-signer/0071_regional_wallet_otp_counters.sql +98 -0
- package/migrations/d1-signer/0072_linked_device_relocation_history.sql +899 -0
- package/migrations/d1-signer/0073_wallet_recovery_relocation.sql +86 -0
- package/migrations/d1-signer/0074_email_otp_relocation.sql +158 -0
- package/migrations/d1-signer/0075_wallet_authorization_return.sql +107 -0
- package/migrations/d1-signer/0076_wallet_relocation_write_block.sql +406 -0
- package/migrations/d1-signer/0077_wallet_object_addresses.sql +24 -0
- package/package.json +1 -1
- package/src/README.md +23 -1
- 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.
|
|
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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
for (const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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
|
-
|
|
43
|
-
|
|
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
|
|
55
|
+
WHEN ${table}.reset_at_ms <= ?
|
|
47
56
|
THEN 1
|
|
48
|
-
ELSE
|
|
57
|
+
ELSE ${table}.consumed_count + 1
|
|
49
58
|
END,
|
|
50
59
|
reset_at_ms = CASE
|
|
51
|
-
WHEN
|
|
60
|
+
WHEN ${table}.reset_at_ms <= ?
|
|
52
61
|
THEN ?
|
|
53
|
-
ELSE
|
|
62
|
+
ELSE ${table}.reset_at_ms
|
|
54
63
|
END,
|
|
55
64
|
updated_at_ms = ?
|
|
56
|
-
WHERE
|
|
57
|
-
OR
|
|
65
|
+
WHERE ${table}.reset_at_ms <= ?
|
|
66
|
+
OR ${table}.consumed_count < ?
|
|
58
67
|
RETURNING consumed_count, reset_at_ms`, [
|
|
59
|
-
|
|
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
|
-
|
|
68
|
-
])
|
|
69
|
-
|
|
70
|
-
|
|
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`, [
|
|
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
|
|
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,
|
|
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=${
|
|
52
|
-
`windowMs=${
|
|
51
|
+
`limit=${policy.limit}`,
|
|
52
|
+
`windowMs=${policy.windowMs}`
|
|
53
53
|
].join(":");
|
|
54
|
-
|
|
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
|
-
]
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
*
|
|
350
|
-
*
|
|
351
|
-
*
|
|
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
|
|
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
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
18
|
-
|
|
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
|
-
}
|
|
24
|
-
|
|
25
|
-
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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
|
-
|
|
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
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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
|