@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.
- 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
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import { requireCanonicalString, requireRecord } from "../../../../shared-ts/src/utils/validation.js";
|
|
2
|
+
import { sha256HexUtf8 } from "../../../../shared-ts/src/utils/digests.js";
|
|
3
|
+
import { parseUnixMs } from "../../../../shared-ts/src/passkey-custody/primitives.js";
|
|
4
|
+
import { parseNonNegativeSafeInteger } from "../../../../shared-ts/src/device-linking/wireFields.js";
|
|
5
|
+
import { D1_BATCH_CAS_GUARD_SQL } from "../../../../storage/d1Sql.js";
|
|
6
|
+
import { prepareD1TenantStatement } from "../../../../core/d1TenantStore.js";
|
|
7
|
+
import { AuthorizationSnapshotLayout } from "./authorizationSnapshotLayout.js";
|
|
8
|
+
import { D1WalletAuthorizationHistory } from "./d1WalletAuthorizationHistory.js";
|
|
9
|
+
import "./d1WalletAuthorizationSnapshot.js";
|
|
10
|
+
//#region src/router/cloudflare/d1/wallet/d1WalletAuthorizationIntake.ts
|
|
11
|
+
const SCOPE = "namespace = ?1 AND org_id = ?2 AND project_id = ?3 AND env_id = ?4 AND wallet_id = ?5";
|
|
12
|
+
var D1WalletAuthorizationIntake = class {
|
|
13
|
+
constructor(database, scope) {
|
|
14
|
+
this.database = database;
|
|
15
|
+
this.scope = scope;
|
|
16
|
+
}
|
|
17
|
+
async prepare(source, rawManifest) {
|
|
18
|
+
const manifest = parseManifest(rawManifest);
|
|
19
|
+
if (manifest.schemaJson !== JSON.stringify(await AuthorizationSnapshotLayout.read(this.database))) throw new Error("Authorization intake schema conflicts");
|
|
20
|
+
const json = JSON.stringify(manifest);
|
|
21
|
+
const existing = await this.read(source);
|
|
22
|
+
if (existing) {
|
|
23
|
+
if (JSON.stringify(existing.manifest) !== json) throw new Error("Authorization intake manifest conflicts");
|
|
24
|
+
return intakeProgress(existing);
|
|
25
|
+
}
|
|
26
|
+
await new D1WalletAuthorizationHistory(this.database, this.scope).prepare(source);
|
|
27
|
+
const digest = await sha256HexUtf8(JSON.stringify([
|
|
28
|
+
"seams/wallet-authorization-snapshot/v1",
|
|
29
|
+
this.scope.namespace,
|
|
30
|
+
this.scope.orgId,
|
|
31
|
+
this.scope.projectId,
|
|
32
|
+
this.scope.envId,
|
|
33
|
+
source.walletId,
|
|
34
|
+
source.moveId,
|
|
35
|
+
source.requestDigestHex,
|
|
36
|
+
source.sourceGeneration,
|
|
37
|
+
manifest.schemaJson
|
|
38
|
+
]));
|
|
39
|
+
await prepareD1TenantStatement(this.database, this.scope, `
|
|
40
|
+
INSERT INTO wallet_relocation_authorization_intakes
|
|
41
|
+
(namespace, org_id, project_id, env_id, wallet_id, move_id, request_digest_hex,
|
|
42
|
+
source_generation, manifest_json, digest_hex)
|
|
43
|
+
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10)
|
|
44
|
+
ON CONFLICT DO NOTHING`, [
|
|
45
|
+
source.walletId,
|
|
46
|
+
source.moveId,
|
|
47
|
+
source.requestDigestHex,
|
|
48
|
+
source.sourceGeneration,
|
|
49
|
+
json,
|
|
50
|
+
digest
|
|
51
|
+
]).run();
|
|
52
|
+
const saved = await this.read(source);
|
|
53
|
+
if (!saved || JSON.stringify(saved.manifest) !== json) throw new Error("Authorization intake manifest conflicts");
|
|
54
|
+
return intakeProgress(saved);
|
|
55
|
+
}
|
|
56
|
+
async acceptSnapshot(source, raw) {
|
|
57
|
+
if (!Array.isArray(raw) || raw.length > 80 || new TextEncoder().encode(JSON.stringify(raw)).byteLength > 524288) throw new Error("Authorization snapshot exceeds supported capacity");
|
|
58
|
+
const state = await this.read(source);
|
|
59
|
+
if (!state) throw new Error("Authorization intake is absent");
|
|
60
|
+
const manifest = state.manifest;
|
|
61
|
+
if (raw.length !== manifest.chunkCount) throw new Error("Authorization snapshot count conflicts");
|
|
62
|
+
const layouts = AuthorizationSnapshotLayout.parse(JSON.parse(manifest.schemaJson));
|
|
63
|
+
let digest = await sha256HexUtf8(JSON.stringify([
|
|
64
|
+
"seams/wallet-authorization-snapshot/v1",
|
|
65
|
+
this.scope.namespace,
|
|
66
|
+
this.scope.orgId,
|
|
67
|
+
this.scope.projectId,
|
|
68
|
+
this.scope.envId,
|
|
69
|
+
source.walletId,
|
|
70
|
+
source.moveId,
|
|
71
|
+
source.requestDigestHex,
|
|
72
|
+
source.sourceGeneration,
|
|
73
|
+
manifest.schemaJson
|
|
74
|
+
]));
|
|
75
|
+
const records = [];
|
|
76
|
+
const completion = [];
|
|
77
|
+
let previous = null;
|
|
78
|
+
let recordHex = "";
|
|
79
|
+
for (const [index, value] of raw.entries()) {
|
|
80
|
+
const chunk = parseChunk(value, layouts);
|
|
81
|
+
const firstSegment = previous === null || previous.segmentIndex + 1 === previous.segmentCount;
|
|
82
|
+
if (chunk.index !== index || (firstSegment ? chunk.segmentIndex !== 0 : previous === null || chunk.segmentIndex !== previous.segmentIndex + 1 || chunk.segmentCount !== previous.segmentCount || chunk.recordKey !== previous.recordKey || chunk.table.table !== previous.table.table)) throw new Error("Authorization snapshot segments conflict");
|
|
83
|
+
digest = await sha256HexUtf8(JSON.stringify([
|
|
84
|
+
digest,
|
|
85
|
+
index,
|
|
86
|
+
chunk.chunkJson
|
|
87
|
+
]));
|
|
88
|
+
if (digest !== chunk.digestHex) throw new Error("Authorization snapshot digest conflicts");
|
|
89
|
+
recordHex += chunk.bytesHex;
|
|
90
|
+
const completed = chunk.segmentIndex + 1 === chunk.segmentCount;
|
|
91
|
+
if (completed) {
|
|
92
|
+
const bytes = new Uint8Array(recordHex.length / 2);
|
|
93
|
+
for (let offset = 0; offset < bytes.length; offset += 1) bytes[offset] = Number.parseInt(recordHex.slice(offset * 2, offset * 2 + 2), 16);
|
|
94
|
+
records.push({
|
|
95
|
+
table: chunk.table,
|
|
96
|
+
recordKey: chunk.recordKey,
|
|
97
|
+
recordJson: new TextDecoder("utf-8", { fatal: true }).decode(bytes)
|
|
98
|
+
});
|
|
99
|
+
recordHex = "";
|
|
100
|
+
}
|
|
101
|
+
completion.push(prepareD1TenantStatement(this.database, this.scope, `
|
|
102
|
+
INSERT INTO wallet_relocation_authorization_intake_chunks
|
|
103
|
+
(namespace, org_id, project_id, env_id, wallet_id, chunk_index, chunk_json, digest_hex)
|
|
104
|
+
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8)`, [
|
|
105
|
+
source.walletId,
|
|
106
|
+
index,
|
|
107
|
+
chunk.chunkJson,
|
|
108
|
+
chunk.digestHex
|
|
109
|
+
]), prepareD1TenantStatement(this.database, this.scope, `
|
|
110
|
+
UPDATE wallet_relocation_authorization_intakes SET next_index = next_index + 1,
|
|
111
|
+
record_count = record_count + ?8, digest_hex = ?7
|
|
112
|
+
WHERE ${SCOPE} AND next_index = ?6 AND state = 'receiving'`, [
|
|
113
|
+
source.walletId,
|
|
114
|
+
index,
|
|
115
|
+
chunk.digestHex,
|
|
116
|
+
completed ? 1 : 0
|
|
117
|
+
]), this.database.prepare(D1_BATCH_CAS_GUARD_SQL));
|
|
118
|
+
previous = chunk;
|
|
119
|
+
}
|
|
120
|
+
if (recordHex !== "" || records.length !== manifest.recordCount || digest !== manifest.digestHex) throw new Error("Authorization snapshot is incomplete");
|
|
121
|
+
if (state.state === "verified") return digest;
|
|
122
|
+
if (state.nextIndex !== 0) throw new Error("Authorization snapshot intake is not empty");
|
|
123
|
+
completion.push(prepareD1TenantStatement(this.database, this.scope, `
|
|
124
|
+
UPDATE wallet_relocation_authorization_intakes SET state = 'verified'
|
|
125
|
+
WHERE ${SCOPE} AND state = 'receiving' AND next_index = ?6 AND record_count = ?7 AND digest_hex = ?8`, [
|
|
126
|
+
source.walletId,
|
|
127
|
+
manifest.chunkCount,
|
|
128
|
+
manifest.recordCount,
|
|
129
|
+
digest
|
|
130
|
+
]), this.database.prepare(D1_BATCH_CAS_GUARD_SQL));
|
|
131
|
+
try {
|
|
132
|
+
await new D1WalletAuthorizationHistory(this.database, this.scope).restoreSnapshot(source, records, completion);
|
|
133
|
+
} catch (error) {
|
|
134
|
+
const concurrent = await this.read(source);
|
|
135
|
+
if (concurrent?.state === "verified" && concurrent.manifest.digestHex === digest) return digest;
|
|
136
|
+
throw error;
|
|
137
|
+
}
|
|
138
|
+
return digest;
|
|
139
|
+
}
|
|
140
|
+
async activate(source, rawManifest, commandDigest, nowMs) {
|
|
141
|
+
const manifest = parseManifest(rawManifest);
|
|
142
|
+
const manifestJson = JSON.stringify(manifest);
|
|
143
|
+
parseUnixMs(nowMs, "authorization activation time");
|
|
144
|
+
const existing = await this.readActivation(source, manifestJson, commandDigest);
|
|
145
|
+
if (existing !== null) return {
|
|
146
|
+
digestHex: manifest.digestHex,
|
|
147
|
+
activatedAtMs: existing
|
|
148
|
+
};
|
|
149
|
+
const identity = [
|
|
150
|
+
source.walletId,
|
|
151
|
+
source.moveId,
|
|
152
|
+
source.requestDigestHex,
|
|
153
|
+
source.sourceGeneration
|
|
154
|
+
];
|
|
155
|
+
await this.database.batch([
|
|
156
|
+
prepareD1TenantStatement(this.database, this.scope, `
|
|
157
|
+
INSERT INTO wallet_relocation_authorization_activations
|
|
158
|
+
(namespace, org_id, project_id, env_id, wallet_id, move_id, request_digest_hex,
|
|
159
|
+
source_generation, command_digest, manifest_json, activated_at_ms)
|
|
160
|
+
SELECT ?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11
|
|
161
|
+
WHERE NOT EXISTS (SELECT 1 FROM wallet_relocation_authorization_activations
|
|
162
|
+
WHERE ${SCOPE} AND move_id = ?6)
|
|
163
|
+
ON CONFLICT DO NOTHING`, [
|
|
164
|
+
...identity,
|
|
165
|
+
commandDigest,
|
|
166
|
+
manifestJson,
|
|
167
|
+
nowMs
|
|
168
|
+
]),
|
|
169
|
+
prepareD1TenantStatement(this.database, this.scope, `
|
|
170
|
+
UPDATE wallet_relocation_authorization_imports SET state = 'activated'
|
|
171
|
+
WHERE ${SCOPE} AND move_id = ?6 AND request_digest_hex = ?7 AND source_generation = ?8
|
|
172
|
+
AND state IN ('closed', 'activated')
|
|
173
|
+
AND EXISTS (SELECT 1 FROM wallet_relocation_authorization_activations AS receipt
|
|
174
|
+
WHERE receipt.namespace = ?1 AND receipt.org_id = ?2 AND receipt.project_id = ?3
|
|
175
|
+
AND receipt.env_id = ?4 AND receipt.wallet_id = ?5 AND receipt.move_id = ?6
|
|
176
|
+
AND receipt.command_digest = ?9 AND receipt.manifest_json = ?10)`, [
|
|
177
|
+
...identity,
|
|
178
|
+
commandDigest,
|
|
179
|
+
manifestJson
|
|
180
|
+
]),
|
|
181
|
+
this.database.prepare(D1_BATCH_CAS_GUARD_SQL)
|
|
182
|
+
]);
|
|
183
|
+
const activatedAtMs = await this.readActivation(source, manifestJson, commandDigest);
|
|
184
|
+
if (activatedAtMs === null) throw new Error("Authorization activation receipt disappeared");
|
|
185
|
+
return {
|
|
186
|
+
digestHex: manifest.digestHex,
|
|
187
|
+
activatedAtMs
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
async readActivation(source, manifestJson, commandDigest) {
|
|
191
|
+
const row = await prepareD1TenantStatement(this.database, this.scope, `
|
|
192
|
+
SELECT * FROM wallet_relocation_authorization_activations
|
|
193
|
+
WHERE ${SCOPE} AND move_id = ?6`, [source.walletId, source.moveId]).first();
|
|
194
|
+
if (!row) return null;
|
|
195
|
+
if (!source.matches(row) || row.command_digest !== commandDigest || row.manifest_json !== manifestJson) throw new Error("Authorization activation identity conflicts");
|
|
196
|
+
return parseUnixMs(row.activated_at_ms, "stored authorization activation time");
|
|
197
|
+
}
|
|
198
|
+
async read(source) {
|
|
199
|
+
const row = await prepareD1TenantStatement(this.database, this.scope, `
|
|
200
|
+
SELECT * FROM wallet_relocation_authorization_intakes WHERE ${SCOPE}`, [source.walletId]).first();
|
|
201
|
+
if (!row) return null;
|
|
202
|
+
if (!source.matches(row)) throw new Error("Authorization intake identity conflicts");
|
|
203
|
+
const manifest = parseManifest(JSON.parse(requireCanonicalString(row.manifest_json, "intake manifest")));
|
|
204
|
+
const nextIndex = parseNonNegativeSafeInteger(row.next_index, "intake next index");
|
|
205
|
+
const recordCount = parseNonNegativeSafeInteger(row.record_count, "intake record count");
|
|
206
|
+
const digest = digestHex(row.digest_hex);
|
|
207
|
+
switch (row.state) {
|
|
208
|
+
case "receiving": return {
|
|
209
|
+
state: "receiving",
|
|
210
|
+
manifest,
|
|
211
|
+
nextIndex,
|
|
212
|
+
recordCount,
|
|
213
|
+
digestHex: digest
|
|
214
|
+
};
|
|
215
|
+
case "verified":
|
|
216
|
+
if (nextIndex !== manifest.chunkCount || recordCount !== manifest.recordCount || digest !== manifest.digestHex) throw new Error("Authorization intake verified state conflicts");
|
|
217
|
+
return {
|
|
218
|
+
state: "verified",
|
|
219
|
+
manifest,
|
|
220
|
+
nextIndex,
|
|
221
|
+
recordCount,
|
|
222
|
+
digestHex: digest
|
|
223
|
+
};
|
|
224
|
+
default: throw new Error("Authorization intake state is invalid");
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
function parseManifest(raw) {
|
|
229
|
+
const value = requireRecord(raw, "authorization manifest");
|
|
230
|
+
if (Object.keys(value).length !== 4) throw new Error("Authorization manifest fields conflict");
|
|
231
|
+
const schemaJson = requireCanonicalString(value.schemaJson, "authorization schema");
|
|
232
|
+
AuthorizationSnapshotLayout.parse(JSON.parse(schemaJson));
|
|
233
|
+
return {
|
|
234
|
+
schemaJson,
|
|
235
|
+
chunkCount: parseNonNegativeSafeInteger(value.chunkCount, "manifest chunk count"),
|
|
236
|
+
recordCount: parseNonNegativeSafeInteger(value.recordCount, "manifest record count"),
|
|
237
|
+
digestHex: digestHex(value.digestHex)
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
function digestHex(raw) {
|
|
241
|
+
const value = requireCanonicalString(raw, "authorization digest");
|
|
242
|
+
if (!/^[a-f0-9]{64}$/u.test(value)) throw new Error("Authorization digest is invalid");
|
|
243
|
+
return value;
|
|
244
|
+
}
|
|
245
|
+
function parseChunk(raw, layouts) {
|
|
246
|
+
const value = requireRecord(raw, "authorization chunk");
|
|
247
|
+
if (Object.keys(value).length !== 3) throw new Error("Authorization chunk fields conflict");
|
|
248
|
+
const chunkJson = requireCanonicalString(value.chunkJson, "authorization chunk JSON");
|
|
249
|
+
if (new TextEncoder().encode(chunkJson).byteLength > 131072) throw new Error("Authorization chunk exceeds its bound");
|
|
250
|
+
const payload = requireRecord(JSON.parse(chunkJson), "authorization chunk payload");
|
|
251
|
+
if (Object.keys(payload).length !== 5) throw new Error("Authorization chunk payload fields conflict");
|
|
252
|
+
let table = null;
|
|
253
|
+
for (const layout of layouts) if (layout.table === payload.table) table = layout;
|
|
254
|
+
if (!table) throw new Error("Authorization chunk table conflicts");
|
|
255
|
+
const segmentIndex = parseNonNegativeSafeInteger(payload.segmentIndex, "segment index");
|
|
256
|
+
const segmentCount = parseNonNegativeSafeInteger(payload.segmentCount, "segment count");
|
|
257
|
+
if (segmentIndex >= segmentCount) throw new Error("Authorization segment index conflicts");
|
|
258
|
+
const hex = requireCanonicalString(payload.bytesHex, "segment bytes");
|
|
259
|
+
if (!/^(?:[A-F0-9]{2})+$/u.test(hex) || hex.length > 65536 || segmentIndex + 1 < segmentCount && hex.length !== 65536) throw new Error("Authorization segment size conflicts");
|
|
260
|
+
return {
|
|
261
|
+
index: parseNonNegativeSafeInteger(value.index, "chunk index"),
|
|
262
|
+
chunkJson,
|
|
263
|
+
digestHex: digestHex(value.digestHex),
|
|
264
|
+
table,
|
|
265
|
+
recordKey: requireCanonicalString(payload.recordKey, "record key"),
|
|
266
|
+
segmentIndex,
|
|
267
|
+
segmentCount,
|
|
268
|
+
bytesHex: hex
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
function intakeProgress(state) {
|
|
272
|
+
switch (state.state) {
|
|
273
|
+
case "receiving": return {
|
|
274
|
+
state: "receiving",
|
|
275
|
+
nextIndex: state.nextIndex,
|
|
276
|
+
chunkCount: state.manifest.chunkCount
|
|
277
|
+
};
|
|
278
|
+
case "verified": return {
|
|
279
|
+
state: "verified",
|
|
280
|
+
digestHex: state.digestHex
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
//#endregion
|
|
285
|
+
export { D1WalletAuthorizationIntake };
|
|
286
|
+
|
|
287
|
+
//# sourceMappingURL=d1WalletAuthorizationIntake.js.map
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
import { requireCanonicalString } from "../../../../shared-ts/src/utils/validation.js";
|
|
2
|
+
import { sha256HexUtf8 } from "../../../../shared-ts/src/utils/digests.js";
|
|
3
|
+
import { parseNonNegativeSafeInteger } from "../../../../shared-ts/src/device-linking/wireFields.js";
|
|
4
|
+
import { D1_BATCH_CAS_GUARD_SQL } from "../../../../storage/d1Sql.js";
|
|
5
|
+
import { prepareD1TenantStatement } from "../../../../core/d1TenantStore.js";
|
|
6
|
+
import { AuthorizationSnapshotLayout } from "./authorizationSnapshotLayout.js";
|
|
7
|
+
//#region src/router/cloudflare/d1/wallet/d1WalletAuthorizationSnapshot.ts
|
|
8
|
+
const CHUNK_BYTES = 32768;
|
|
9
|
+
const AUTHORIZATION_SNAPSHOT_MAX_BYTES = 524288;
|
|
10
|
+
const AUTHORIZATION_SNAPSHOT_MAX_CHUNKS = 80;
|
|
11
|
+
var D1WalletAuthorizationSnapshot = class {
|
|
12
|
+
constructor(database, scope) {
|
|
13
|
+
this.database = database;
|
|
14
|
+
this.scope = scope;
|
|
15
|
+
}
|
|
16
|
+
async seal(source) {
|
|
17
|
+
const state = await this.prepare(source);
|
|
18
|
+
if (state.state === "sealed") return state.manifest;
|
|
19
|
+
const layout = AuthorizationSnapshotLayout.parse(JSON.parse(state.schemaJson));
|
|
20
|
+
const progress = await this.readProgress(source, layout, state.schemaJson);
|
|
21
|
+
let digestHex = progress.digestHex;
|
|
22
|
+
let chunkCount = progress.chunkCount;
|
|
23
|
+
let recordCount = progress.recordCount;
|
|
24
|
+
for (let tableIndex = progress.tableIndex; tableIndex < layout.length; tableIndex += 1) {
|
|
25
|
+
const table = layout[tableIndex];
|
|
26
|
+
let cursor = tableIndex === progress.tableIndex ? progress.cursor : {
|
|
27
|
+
kind: "after",
|
|
28
|
+
key: ""
|
|
29
|
+
};
|
|
30
|
+
while (true) {
|
|
31
|
+
const record = await this.nextRecord(source, table, cursor);
|
|
32
|
+
if (record === null) {
|
|
33
|
+
if (cursor.kind === "resume") throw new Error("Authorization snapshot partial record disappeared");
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
const segmentCount = Math.ceil(record.byteLength / CHUNK_BYTES);
|
|
37
|
+
if (cursor.kind === "resume" && cursor.segmentCount !== segmentCount) throw new Error("Authorization snapshot partial record size changed");
|
|
38
|
+
const firstSegment = cursor.kind === "resume" ? cursor.nextSegment : 0;
|
|
39
|
+
for (let segmentIndex = firstSegment; segmentIndex < segmentCount; segmentIndex += 1) {
|
|
40
|
+
const bytesHex = await this.readSegment(source, table, record.key, segmentIndex);
|
|
41
|
+
const expectedBytes = Math.min(CHUNK_BYTES, record.byteLength - segmentIndex * CHUNK_BYTES);
|
|
42
|
+
if (!/^[A-F0-9]+$/u.test(bytesHex) || bytesHex.length !== expectedBytes * 2) throw new Error("Authorization snapshot record changed during capture");
|
|
43
|
+
const chunkJson = JSON.stringify({
|
|
44
|
+
table: table.table,
|
|
45
|
+
recordKey: record.key,
|
|
46
|
+
segmentIndex,
|
|
47
|
+
segmentCount,
|
|
48
|
+
bytesHex
|
|
49
|
+
});
|
|
50
|
+
digestHex = await sha256HexUtf8(JSON.stringify([
|
|
51
|
+
digestHex,
|
|
52
|
+
chunkCount,
|
|
53
|
+
chunkJson
|
|
54
|
+
]));
|
|
55
|
+
const completedRecords = recordCount + (segmentIndex + 1 === segmentCount ? 1 : 0);
|
|
56
|
+
await this.storeChunk(source, chunkCount, chunkJson, digestHex, completedRecords);
|
|
57
|
+
chunkCount += 1;
|
|
58
|
+
}
|
|
59
|
+
recordCount += 1;
|
|
60
|
+
cursor = {
|
|
61
|
+
kind: "after",
|
|
62
|
+
key: record.key
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
await this.database.batch([prepareD1TenantStatement(this.database, this.scope, `
|
|
67
|
+
UPDATE wallet_relocation_authorization_snapshots
|
|
68
|
+
SET state = 'sealed', chunk_count = ?9, record_count = ?10, digest_hex = ?11
|
|
69
|
+
WHERE namespace = ?1 AND org_id = ?2 AND project_id = ?3 AND env_id = ?4
|
|
70
|
+
AND wallet_id = ?5 AND move_id = ?6 AND request_digest_hex = ?7 AND source_generation = ?8`, [
|
|
71
|
+
source.walletId,
|
|
72
|
+
source.moveId,
|
|
73
|
+
source.requestDigestHex,
|
|
74
|
+
source.sourceGeneration,
|
|
75
|
+
chunkCount,
|
|
76
|
+
recordCount,
|
|
77
|
+
digestHex
|
|
78
|
+
]), this.database.prepare(D1_BATCH_CAS_GUARD_SQL)]);
|
|
79
|
+
const sealed = await this.read(source);
|
|
80
|
+
if (sealed?.state !== "sealed") throw new Error("Authorization snapshot seal disappeared");
|
|
81
|
+
return sealed.manifest;
|
|
82
|
+
}
|
|
83
|
+
async exportSnapshot(source) {
|
|
84
|
+
const state = await this.read(source);
|
|
85
|
+
if (state?.state !== "sealed") throw new Error("Authorization snapshot is not sealed");
|
|
86
|
+
const result = await prepareD1TenantStatement(this.database, this.scope, `
|
|
87
|
+
SELECT chunk_index, chunk_json, digest_hex FROM wallet_relocation_authorization_chunks
|
|
88
|
+
WHERE namespace = ?1 AND org_id = ?2 AND project_id = ?3 AND env_id = ?4
|
|
89
|
+
AND wallet_id = ?5 ORDER BY chunk_index`, [source.walletId]).all();
|
|
90
|
+
const chunks = [];
|
|
91
|
+
for (const row of result.results ?? []) chunks.push({
|
|
92
|
+
index: parseNonNegativeSafeInteger(row.chunk_index, "snapshot chunk index"),
|
|
93
|
+
chunkJson: requireCanonicalString(row.chunk_json, "snapshot chunk"),
|
|
94
|
+
digestHex: requireCanonicalString(row.digest_hex, "snapshot chunk digest")
|
|
95
|
+
});
|
|
96
|
+
if (chunks.length !== state.manifest.chunkCount || chunks.length > 80 || new TextEncoder().encode(JSON.stringify(chunks)).byteLength > 524288) throw new Error("Authorization snapshot exceeds supported capacity");
|
|
97
|
+
return chunks;
|
|
98
|
+
}
|
|
99
|
+
async assertCapacity(walletId) {
|
|
100
|
+
const statements = [];
|
|
101
|
+
for (const layout of await AuthorizationSnapshotLayout.read(this.database)) {
|
|
102
|
+
const expressions = layout.expressions();
|
|
103
|
+
statements.push(prepareD1TenantStatement(this.database, this.scope, `
|
|
104
|
+
SELECT COALESCE(SUM(length(CAST(${expressions.record} AS BLOB))), 0) AS bytes,
|
|
105
|
+
COALESCE(SUM((length(CAST(${expressions.record} AS BLOB)) + 512 + 32767) / 32768), 0) AS chunks
|
|
106
|
+
FROM ${layout.table} AS target WHERE ${expressions.ownership}`, [walletId]));
|
|
107
|
+
}
|
|
108
|
+
const results = await this.database.batch(statements);
|
|
109
|
+
let bytes = 0;
|
|
110
|
+
let chunks = 0;
|
|
111
|
+
for (const result of results) {
|
|
112
|
+
const row = result.results[0];
|
|
113
|
+
if (!row) throw new Error("Authorization capacity observation is absent");
|
|
114
|
+
bytes += parseNonNegativeSafeInteger(row.bytes, "authorization bytes");
|
|
115
|
+
chunks += parseNonNegativeSafeInteger(row.chunks, "authorization chunks");
|
|
116
|
+
}
|
|
117
|
+
if (chunks > 80 || bytes * 2 + chunks * 2048 > 524288) throw new Error("Authorization snapshot exceeds supported capacity");
|
|
118
|
+
}
|
|
119
|
+
async prepare(source) {
|
|
120
|
+
const existing = await this.read(source);
|
|
121
|
+
if (existing) return existing;
|
|
122
|
+
const schemaJson = JSON.stringify(await AuthorizationSnapshotLayout.read(this.database));
|
|
123
|
+
await this.database.batch([
|
|
124
|
+
prepareD1TenantStatement(this.database, this.scope, `
|
|
125
|
+
INSERT INTO wallet_relocation_authorization_snapshots
|
|
126
|
+
(namespace, org_id, project_id, env_id, wallet_id, move_id, request_digest_hex, source_generation, schema_json, state)
|
|
127
|
+
SELECT ?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, 'building'
|
|
128
|
+
WHERE NOT EXISTS (SELECT 1 FROM wallet_relocation_authorization_snapshots
|
|
129
|
+
WHERE namespace = ?1 AND org_id = ?2 AND project_id = ?3 AND env_id = ?4 AND wallet_id = ?5)`, [
|
|
130
|
+
source.walletId,
|
|
131
|
+
source.moveId,
|
|
132
|
+
source.requestDigestHex,
|
|
133
|
+
source.sourceGeneration,
|
|
134
|
+
schemaJson
|
|
135
|
+
]),
|
|
136
|
+
prepareD1TenantStatement(this.database, this.scope, `
|
|
137
|
+
UPDATE wallet_relocation_authorization_snapshots SET schema_json = schema_json
|
|
138
|
+
WHERE namespace = ?1 AND org_id = ?2 AND project_id = ?3 AND env_id = ?4
|
|
139
|
+
AND wallet_id = ?5 AND move_id = ?6 AND request_digest_hex = ?7 AND source_generation = ?8
|
|
140
|
+
AND schema_json = ?9`, [
|
|
141
|
+
source.walletId,
|
|
142
|
+
source.moveId,
|
|
143
|
+
source.requestDigestHex,
|
|
144
|
+
source.sourceGeneration,
|
|
145
|
+
schemaJson
|
|
146
|
+
]),
|
|
147
|
+
this.database.prepare(D1_BATCH_CAS_GUARD_SQL)
|
|
148
|
+
]);
|
|
149
|
+
const state = await this.read(source);
|
|
150
|
+
if (!state) throw new Error("Authorization snapshot preparation disappeared");
|
|
151
|
+
return state;
|
|
152
|
+
}
|
|
153
|
+
async read(source) {
|
|
154
|
+
const row = await prepareD1TenantStatement(this.database, this.scope, `
|
|
155
|
+
SELECT wallet_id, move_id, request_digest_hex, source_generation, schema_json,
|
|
156
|
+
state, chunk_count, record_count, digest_hex FROM wallet_relocation_authorization_snapshots
|
|
157
|
+
WHERE namespace = ?1 AND org_id = ?2 AND project_id = ?3 AND env_id = ?4 AND wallet_id = ?5`, [source.walletId]).first();
|
|
158
|
+
if (!row) return null;
|
|
159
|
+
if (!source.matches(row)) throw new Error("Authorization snapshot identity conflicts");
|
|
160
|
+
const schemaJson = requireCanonicalString(row.schema_json, "snapshot schema");
|
|
161
|
+
switch (row.state) {
|
|
162
|
+
case "building":
|
|
163
|
+
if (row.chunk_count !== null || row.record_count !== null || row.digest_hex !== null) throw new Error("Authorization snapshot building state conflicts");
|
|
164
|
+
return {
|
|
165
|
+
state: "building",
|
|
166
|
+
schemaJson
|
|
167
|
+
};
|
|
168
|
+
case "sealed": return {
|
|
169
|
+
state: "sealed",
|
|
170
|
+
schemaJson,
|
|
171
|
+
manifest: Object.freeze({
|
|
172
|
+
schemaJson,
|
|
173
|
+
chunkCount: parseNonNegativeSafeInteger(row.chunk_count, "snapshot chunk count"),
|
|
174
|
+
recordCount: parseNonNegativeSafeInteger(row.record_count, "snapshot record count"),
|
|
175
|
+
digestHex: requireCanonicalString(row.digest_hex, "snapshot digest")
|
|
176
|
+
})
|
|
177
|
+
};
|
|
178
|
+
default: throw new Error("Authorization snapshot state is invalid");
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
async readProgress(source, layout, schemaJson) {
|
|
182
|
+
const row = await prepareD1TenantStatement(this.database, this.scope, `
|
|
183
|
+
SELECT chunk_index, digest_hex,
|
|
184
|
+
json_extract(chunk_json, '$.table') AS table_name,
|
|
185
|
+
json_extract(chunk_json, '$.recordKey') AS record_key,
|
|
186
|
+
json_extract(chunk_json, '$.segmentIndex') AS segment_index,
|
|
187
|
+
json_extract(chunk_json, '$.segmentCount') AS segment_count, record_count
|
|
188
|
+
FROM wallet_relocation_authorization_chunks
|
|
189
|
+
WHERE namespace = ?1 AND org_id = ?2 AND project_id = ?3 AND env_id = ?4 AND wallet_id = ?5
|
|
190
|
+
ORDER BY chunk_index DESC LIMIT 1`, [source.walletId]).first();
|
|
191
|
+
if (!row) return {
|
|
192
|
+
tableIndex: 0,
|
|
193
|
+
cursor: {
|
|
194
|
+
kind: "after",
|
|
195
|
+
key: ""
|
|
196
|
+
},
|
|
197
|
+
chunkCount: 0,
|
|
198
|
+
recordCount: 0,
|
|
199
|
+
digestHex: await sha256HexUtf8(JSON.stringify([
|
|
200
|
+
"seams/wallet-authorization-snapshot/v1",
|
|
201
|
+
this.scope.namespace,
|
|
202
|
+
this.scope.orgId,
|
|
203
|
+
this.scope.projectId,
|
|
204
|
+
this.scope.envId,
|
|
205
|
+
source.walletId,
|
|
206
|
+
source.moveId,
|
|
207
|
+
source.requestDigestHex,
|
|
208
|
+
source.sourceGeneration,
|
|
209
|
+
schemaJson
|
|
210
|
+
]))
|
|
211
|
+
};
|
|
212
|
+
let tableIndex = -1;
|
|
213
|
+
for (const [index, table] of layout.entries()) if (table.table === row.table_name) tableIndex = index;
|
|
214
|
+
const segmentIndex = parseNonNegativeSafeInteger(row.segment_index, "snapshot last segment");
|
|
215
|
+
const segmentCount = parseNonNegativeSafeInteger(row.segment_count, "snapshot segment count");
|
|
216
|
+
if (tableIndex < 0 || segmentIndex >= segmentCount) throw new Error("Authorization snapshot checkpoint is invalid");
|
|
217
|
+
const key = requireCanonicalString(row.record_key, "snapshot checkpoint key");
|
|
218
|
+
const cursor = segmentIndex + 1 === segmentCount ? {
|
|
219
|
+
kind: "after",
|
|
220
|
+
key
|
|
221
|
+
} : {
|
|
222
|
+
kind: "resume",
|
|
223
|
+
key,
|
|
224
|
+
nextSegment: segmentIndex + 1,
|
|
225
|
+
segmentCount
|
|
226
|
+
};
|
|
227
|
+
return {
|
|
228
|
+
tableIndex,
|
|
229
|
+
cursor,
|
|
230
|
+
chunkCount: parseNonNegativeSafeInteger(row.chunk_index, "snapshot last chunk") + 1,
|
|
231
|
+
recordCount: parseNonNegativeSafeInteger(row.record_count, "snapshot completed records"),
|
|
232
|
+
digestHex: requireCanonicalString(row.digest_hex, "snapshot checkpoint digest")
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
async nextRecord(source, table, cursor) {
|
|
236
|
+
const sql = table.expressions();
|
|
237
|
+
const comparison = cursor.kind === "resume" ? "=" : ">";
|
|
238
|
+
const row = await prepareD1TenantStatement(this.database, this.scope, `
|
|
239
|
+
SELECT ${sql.key} AS record_key, length(CAST(${sql.record} AS BLOB)) AS byte_length
|
|
240
|
+
FROM ${table.table} AS target WHERE ${table.snapshotSelection()} AND ${sql.key} ${comparison} ?6
|
|
241
|
+
ORDER BY record_key COLLATE BINARY LIMIT 1`, [source.walletId, cursor.key]).first();
|
|
242
|
+
if (!row) return null;
|
|
243
|
+
const byteLength = parseNonNegativeSafeInteger(row.byte_length, "snapshot record length");
|
|
244
|
+
if (byteLength === 0) throw new Error("Authorization snapshot record is empty");
|
|
245
|
+
return {
|
|
246
|
+
key: requireCanonicalString(row.record_key, "snapshot record key"),
|
|
247
|
+
byteLength
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
async readSegment(source, table, key, segmentIndex) {
|
|
251
|
+
const sql = table.expressions();
|
|
252
|
+
const row = await prepareD1TenantStatement(this.database, this.scope, `
|
|
253
|
+
SELECT hex(substr(CAST(${sql.record} AS BLOB), ?7, ?8)) AS bytes_hex
|
|
254
|
+
FROM ${table.table} AS target WHERE ${table.snapshotSelection()} AND ${sql.key} = ?6`, [
|
|
255
|
+
source.walletId,
|
|
256
|
+
key,
|
|
257
|
+
segmentIndex * CHUNK_BYTES + 1,
|
|
258
|
+
CHUNK_BYTES
|
|
259
|
+
]).first();
|
|
260
|
+
if (!row) throw new Error("Authorization snapshot record disappeared");
|
|
261
|
+
return requireCanonicalString(row.bytes_hex, "snapshot bytes");
|
|
262
|
+
}
|
|
263
|
+
async storeChunk(source, index, chunkJson, digestHex, recordCount) {
|
|
264
|
+
await this.database.batch([
|
|
265
|
+
prepareD1TenantStatement(this.database, this.scope, `
|
|
266
|
+
INSERT INTO wallet_relocation_authorization_chunks
|
|
267
|
+
(namespace, org_id, project_id, env_id, wallet_id, chunk_index, chunk_json, digest_hex, record_count)
|
|
268
|
+
SELECT ?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9
|
|
269
|
+
WHERE NOT EXISTS (SELECT 1 FROM wallet_relocation_authorization_chunks
|
|
270
|
+
WHERE namespace = ?1 AND org_id = ?2 AND project_id = ?3 AND env_id = ?4
|
|
271
|
+
AND wallet_id = ?5 AND chunk_index = ?6)`, [
|
|
272
|
+
source.walletId,
|
|
273
|
+
index,
|
|
274
|
+
chunkJson,
|
|
275
|
+
digestHex,
|
|
276
|
+
recordCount
|
|
277
|
+
]),
|
|
278
|
+
prepareD1TenantStatement(this.database, this.scope, `
|
|
279
|
+
UPDATE wallet_relocation_authorization_chunks SET digest_hex = digest_hex
|
|
280
|
+
WHERE namespace = ?1 AND org_id = ?2 AND project_id = ?3 AND env_id = ?4
|
|
281
|
+
AND wallet_id = ?5 AND chunk_index = ?6 AND chunk_json = ?7 AND digest_hex = ?8 AND record_count = ?9`, [
|
|
282
|
+
source.walletId,
|
|
283
|
+
index,
|
|
284
|
+
chunkJson,
|
|
285
|
+
digestHex,
|
|
286
|
+
recordCount
|
|
287
|
+
]),
|
|
288
|
+
this.database.prepare(D1_BATCH_CAS_GUARD_SQL)
|
|
289
|
+
]);
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
//#endregion
|
|
293
|
+
export { AUTHORIZATION_SNAPSHOT_MAX_BYTES, AUTHORIZATION_SNAPSHOT_MAX_CHUNKS, D1WalletAuthorizationSnapshot };
|
|
294
|
+
|
|
295
|
+
//# sourceMappingURL=d1WalletAuthorizationSnapshot.js.map
|