@seams/wallet-server 0.7.1 → 0.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/THIRD_PARTY_NOTICES.md +1 -105
- package/artifact-manifest.json +21 -21
- package/cloudflare-router-ab/build/deriver-a/build-stamp.json +1 -1
- 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_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_bg.wasm +0 -0
- package/cloudflare-router-ab/build/signing-worker/build-stamp.json +1 -1
- 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_bg.wasm +0 -0
- package/dist/esm/authorization/service.js +8 -0
- package/dist/esm/authorization/vaultProxyUse.js +2 -6
- package/dist/esm/cloud-host.js +4 -4
- package/dist/esm/core/IdentityStore.js +23 -110
- package/dist/esm/core/SessionService.js +7 -30
- package/dist/esm/core/ThresholdService/routerAbNormalSigningPolicy.js +3 -10
- package/dist/esm/core/ThresholdService/stores/WalletSessionStore.js +21 -97
- package/dist/esm/core/ThresholdService/stores/exportReplayGuard.js +7 -0
- package/dist/esm/core/WalletStore.js +4 -6
- package/dist/esm/core/authService/bytes.js +1 -4
- package/dist/esm/core/authService/emailOtpChallengeOperations.js +2 -5
- package/dist/esm/core/authService/emailOtpChallengeProof.js +9 -40
- package/dist/esm/core/authService/emailOtpChallengeVerification.js +19 -90
- package/dist/esm/core/authService/emailOtpChallenges.js +10 -45
- package/dist/esm/core/authService/emailOtpDelivery.js +10 -45
- package/dist/esm/core/authService/emailOtpEnrollment.js +9 -40
- package/dist/esm/core/authService/emailOtpGrant.js +9 -40
- package/dist/esm/core/authService/emailOtpRegistrationEnrollment.js +9 -40
- package/dist/esm/core/authService/emailOtpSeal.js +5 -20
- package/dist/esm/core/authService/emailOtpUnlock.js +20 -110
- package/dist/esm/core/authService/googleEmailOtpRegistration.js +28 -115
- package/dist/esm/core/authService/identity.js +5 -20
- package/dist/esm/core/authService/nearPublicKeyMetadata.js +6 -25
- package/dist/esm/core/authService/oidcVerification.js +22 -34
- package/dist/esm/core/authService/rateLimits.js +2 -5
- package/dist/esm/core/authService/thresholdEcdsaKeyInventory.js +2 -1
- package/dist/esm/core/authService/webauthn.js +37 -191
- package/dist/esm/core/authService/webauthnVerificationOutcomes.js +5 -24
- package/dist/esm/core/d1EcdsaSignerRead.js +76 -0
- package/dist/esm/core/d1IdentityStore.js +16 -75
- package/dist/esm/core/d1TenantStore.js +1 -1
- package/dist/esm/core/d1WalletStore.js +15 -25
- package/dist/esm/core/deviceLinking/linkedDeviceEmailOtpGrant.js +1 -5
- package/dist/esm/core/deviceLinking/linkedDeviceSessionApproval.js +1 -3
- package/dist/esm/core/deviceLinking/linkedDeviceSessionRecord.js +2 -8
- package/dist/esm/core/deviceLinking/requestProof.js +13 -4
- package/dist/esm/core/ecdsaMaterialReadSnapshot.js +85 -0
- package/dist/esm/core/nearRelayerAccountProvisioning.js +2 -5
- package/dist/esm/core/signingLanes/WalletExecutionLaneProjection.js +3 -6
- package/dist/esm/core/signingMaterial/ordinaryInactiveSignerMaterialReservation.js +2 -5
- package/dist/esm/core/storeBackends.js +1 -1
- package/dist/esm/core/thresholdEcdsaChainTarget.js +1 -3
- package/dist/esm/hosted-wallet-gateway.js +2 -2
- package/dist/esm/localHostedWalletGatewayHandler.js +13 -0
- package/dist/esm/localIntendedMaterialAdmissionFault.js +176 -0
- package/dist/esm/localIntendedPresignCancellation.js +44 -0
- package/dist/esm/router/auth/commonRouterUtils.js +24 -10
- package/dist/esm/router/auth/walletSessionFailure.js +2 -5
- package/dist/esm/router/auth/webAuthnCredentialCodecs.js +4 -15
- package/dist/esm/router/cloudflare/d1/auth/d1AuthorizedOperationRouteService.js +1 -0
- package/dist/esm/router/cloudflare/d1/auth/d1RouterApiAuthBoundary.js +2 -6
- package/dist/esm/router/cloudflare/d1/auth/d1RouterApiAuthService.js +5 -27
- package/dist/esm/router/cloudflare/d1/auth/walletSessionCredentialReaders.js +76 -0
- package/dist/esm/router/cloudflare/d1/authorization/authorizedOperationStatements.js +28 -21
- package/dist/esm/router/cloudflare/d1/authorization/d1AuthorizationStore.js +209 -44
- package/dist/esm/router/cloudflare/d1/authorization/d1VaultProxyStore.js +8 -12
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceAuthorityInstallService.js +50 -8
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceTargetCredentialProvider.js +1 -1
- package/dist/esm/router/cloudflare/d1/deviceLinking/index.js +3 -3
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeIssuer.js +12 -55
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeService.js +17 -80
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpDeliveryRuntime.js +6 -25
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRecords.js +12 -47
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRecoveryService.js +24 -85
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRegistrationEnrollmentFinalizer.js +7 -30
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpServerSealRuntime.js +5 -20
- package/dist/esm/router/cloudflare/d1/emailOtp/d1GoogleEmailOtpSessionResolver.js +23 -110
- package/dist/esm/router/cloudflare/d1/identity/d1IdentityService.js +9 -40
- package/dist/esm/router/cloudflare/d1/near/d1NearPublicKeyStore.js +3 -10
- package/dist/esm/router/cloudflare/d1/oidc/d1OidcBoundary.js +18 -91
- package/dist/esm/router/cloudflare/d1/oidc/d1OidcVerificationService.js +6 -30
- package/dist/esm/router/cloudflare/d1/passkeyCustody/d1PasskeyCustodyRouteService.js +4 -15
- package/dist/esm/router/cloudflare/d1/passkeyCustody/d1WalletCustodyCommitStore.js +2 -7
- package/dist/esm/router/cloudflare/d1/passkeyCustody/d1WalletRecoveryGoogleEmailOtpRecords.js +9 -13
- package/dist/esm/router/cloudflare/d1/passkeyCustody/d1WalletRecoveryGoogleEmailOtpService.js +11 -50
- package/dist/esm/router/cloudflare/d1/registration/d1EvmFamilyEcdsaRegistrationBranch.js +5 -20
- package/dist/esm/router/cloudflare/d1/registration/d1RegistrationCeremonyRecordStore.js +4 -7
- package/dist/esm/router/cloudflare/d1/registration/d1RegistrationCeremonyRecords.js +2 -1
- package/dist/esm/router/cloudflare/d1/registration/d1RegistrationIntentService.js +7 -30
- package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationService.js +32 -22
- package/dist/esm/router/cloudflare/d1/registration/walletRegistrationSessionCommitReceipt.js +1 -4
- package/dist/esm/router/cloudflare/d1/signingAdmission/d1RouterAbNormalSigningAdmissionStore.js +119 -25
- package/dist/esm/router/cloudflare/d1/webauthn/d1WebAuthnAuthService.js +31 -168
- package/dist/esm/router/cloudflare/d1/webauthn/d1WebAuthnRecords.js +6 -9
- package/dist/esm/router/cloudflare/durableObjects/thresholdStore.js +59 -66
- package/dist/esm/router/cloudflare/runtime/routerAbPrewarm.js +2 -2
- package/dist/esm/router/cloudflare/runtime/staticWalletConsoleBinding.js +5 -20
- package/dist/esm/router/cloudflare/runtime/tenantRootCreationGrant.js +2 -9
- package/dist/esm/router/cloudflare/runtime/walletControlOps.js +2 -1
- package/dist/esm/router/cloudflare/signingLanes/cloudflareLaneCurveExecution.js +2 -1
- package/dist/esm/router/cloudflare/signingLanes/cloudflareLaneProtocolCommitter.js +2 -2
- package/dist/esm/router/cloudflare.js +2146 -1802
- package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationPersistence.js +5 -8
- package/dist/esm/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecoveryWalletSessionAuthorization.js +3 -6
- package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationIntentAuthorization.js +6 -25
- package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationSideEffectBoundary.js +39 -55
- package/dist/esm/router/domains/emailOtp/emailOtpRouteHandlers.js +15 -62
- package/dist/esm/router/domains/signingOperations/routerAbEcdsaDerivationNormalSigningRoute.js +83 -74
- package/dist/esm/router/domains/signingOperations/routerAbNormalSigningAdmission.js +1 -0
- package/dist/esm/router/domains/signingOperations/routerAbOperationStepUp.js +1 -0
- package/dist/esm/router/domains/signingOperations/walletExecutionAdmission.js +1 -4
- package/dist/esm/router/domains/tenantRoot/tenantRootIdentityResolution.js +7 -13
- package/dist/esm/router/domains/walletUnlock/walletUnlockRouteHandlers.js +41 -200
- package/dist/esm/router/express.js +317 -699
- package/dist/esm/router/framework/http.js +5 -1
- package/dist/esm/router/framework/runtimeSnapshotConsumer.js +8 -35
- package/dist/esm/router/transport/fetch/createFetchRouter.js +3 -6
- package/dist/esm/router/transport/fetch/routes/auth.js +9 -41
- package/dist/esm/router/transport/fetch/routes/deviceLinkingOwnerAuthorization.js +5 -22
- package/dist/esm/router/transport/fetch/routes/nearPublicKeys.js +4 -16
- package/dist/esm/router/transport/fetch/routes/sessions.js +1 -0
- package/dist/esm/router/transport/fetch/routes/syncAccount.js +8 -36
- package/dist/esm/router/transport/fetch/routes/thresholdEcdsa.js +27 -79
- package/dist/esm/router/transport/fetch/routes/walletExecutionLanePreflight.js +4 -1
- package/dist/esm/router/transport/fetch/routes/webauthnAuthenticators.js +4 -16
- package/dist/esm/shared-ts/src/authorization/walletSignerActivationEquality.js +12 -0
- package/dist/esm/shared-ts/src/device-linking/committedSignerPackages.js +2 -5
- package/dist/esm/shared-ts/src/device-linking/delegatedActivationPlan.js +1 -5
- package/dist/esm/shared-ts/src/device-linking/ed25519ExportRoot.js +12 -16
- package/dist/esm/shared-ts/src/device-linking/sourceContribution.js +5 -8
- package/dist/esm/shared-ts/src/passkey-custody/primitives.js +5 -1
- package/dist/esm/shared-ts/src/signing-lanes/ownerContinuity.js +4 -8
- package/dist/esm/shared-ts/src/tenant-root/tenantRootIdentifier.js +12 -0
- package/dist/esm/shared-ts/src/tenant-root/tenantRootIdentity.js +2 -9
- package/dist/esm/shared-ts/src/tenant-root/tenantRootOperationRecord.js +1 -4
- package/dist/esm/shared-ts/src/utils/ecdsaKeyFactsInventory.js +2 -4
- package/dist/esm/shared-ts/src/utils/ecdsaServerTiming.js +0 -1
- package/dist/esm/shared-ts/src/utils/emailOtpDomain.js +3 -1
- package/dist/esm/shared-ts/src/utils/exactKeys.js +17 -0
- package/dist/esm/shared-ts/src/utils/failure.js +20 -0
- package/dist/esm/shared-ts/src/utils/registrationIntent.js +3 -12
- package/dist/esm/shared-ts/src/utils/registrationSignerPlan.js +2 -5
- package/dist/esm/shared-ts/src/utils/routerAbEcdsaDerivation.js +1 -1
- package/dist/esm/shared-ts/src/utils/routerAbEd25519Yao.js +1 -1
- package/dist/esm/shared-ts/src/utils/thresholdEcdsaChainTarget.js +9 -0
- package/dist/esm/shared-ts/src/wallet-recovery/walletRecoveryCommittedProjection.js +1 -4
- package/dist/esm/threshold/session/signingSessionSeal/crypto/cipher.js +10 -32
- package/dist/esm/threshold/session/signingSessionSeal/idempotencyBackends.js +3 -3
- package/dist/esm/threshold/session/signingSessionSeal/idempotencyRecords.js +3 -9
- package/dist/esm/threshold/session/signingSessionSeal/service.js +8 -35
- package/dist/esm/threshold/session/signingSessionSeal/transport/express.js +18 -94
- package/dist/esm/threshold/session/signingSessionSeal/transport/fetch.js +6 -30
- package/dist/esm/threshold/session/signingSessionSeal/transport/shared.js +5 -20
- package/dist/esm/wasm/evm_crypto/pkg/evm_crypto_bg.wasm +0 -0
- package/dist/esm/wasm/near_signer/pkg/wasm_signer_worker_bg.wasm +0 -0
- package/dist/types/shared-ts/src/authorization/delegatedAuthority.d.ts +2 -1
- package/dist/types/shared-ts/src/authorization/walletSessionIssuance.d.ts +9 -2
- package/dist/types/shared-ts/src/authorization/walletSignerActivationEquality.d.ts +4 -0
- package/dist/types/shared-ts/src/device-linking/committedSignerPackages.d.ts +3 -4
- package/dist/types/shared-ts/src/device-linking/contracts.d.ts +5 -63
- package/dist/types/shared-ts/src/device-linking/sourceContribution.d.ts +2 -0
- package/dist/types/shared-ts/src/passkey-custody/custodyEnvelope.d.ts +5 -12
- package/dist/types/shared-ts/src/passkey-custody/primitives.d.ts +9 -0
- package/dist/types/shared-ts/src/signing-lanes/execution.d.ts +11 -1
- package/dist/types/shared-ts/src/signing-lanes/ids.d.ts +1 -10
- package/dist/types/shared-ts/src/signing-lanes/rotation.d.ts +3 -5
- package/dist/types/shared-ts/src/tenant-root/tenantRootIdentifier.d.ts +3 -0
- package/dist/types/shared-ts/src/tenant-root/tenantRootOperationRecord.d.ts +2 -1
- package/dist/types/shared-ts/src/threshold/ecdsaDerivationRoleLocalBootstrap.d.ts +6 -0
- package/dist/types/shared-ts/src/threshold/signingRootScope.d.ts +1 -0
- package/dist/types/shared-ts/src/utils/ecdsaKeyFactsInventory.d.ts +2 -11
- package/dist/types/shared-ts/src/utils/eip1559TxWasmJson.d.ts +16 -0
- package/dist/types/shared-ts/src/utils/emailOtpDomain.d.ts +2 -0
- package/dist/types/shared-ts/src/utils/exactKeys.d.ts +11 -0
- package/dist/types/shared-ts/src/utils/failure.d.ts +12 -0
- package/dist/types/shared-ts/src/utils/jsonRpc.d.ts +3 -4
- package/dist/types/shared-ts/src/utils/nearRpcResults.d.ts +1 -0
- package/dist/types/shared-ts/src/utils/registrationAuthMethodInput.d.ts +3 -8
- package/dist/types/shared-ts/src/utils/registrationSignerPlan.d.ts +7 -19
- package/dist/types/shared-ts/src/utils/routerAbEcdsaDerivation.d.ts +3 -1
- package/dist/types/shared-ts/src/utils/routerAbEd25519Yao.d.ts +1 -0
- package/dist/types/shared-ts/src/utils/routerAbEd25519YaoDigests.d.ts +3 -4
- package/dist/types/shared-ts/src/utils/routerAbNormalSigningIdentity.d.ts +30 -8
- package/dist/types/shared-ts/src/utils/routerApiKeyAuth.d.ts +2 -0
- package/dist/types/shared-ts/src/utils/signingSessionSeal.d.ts +10 -11
- package/dist/types/shared-ts/src/utils/thresholdEcdsaChainTarget.d.ts +25 -0
- package/dist/types/shared-ts/src/utils/variant.d.ts +18 -0
- package/dist/types/shared-ts/src/utils/walletAuthMethodRecord.d.ts +3 -6
- package/dist/types/shared-ts/src/utils/webauthnDeviceInfo.d.ts +4 -2
- package/dist/types/shared-ts/src/wallet-recovery/recoveryEnvelopes.d.ts +3 -16
- package/dist/types/shared-ts/src/wallet-recovery/walletRecoveryPreparation.d.ts +15 -0
- package/dist/types/shared-ts/src/wallet-recovery/walletRecoveryTarget.d.ts +3 -4
- package/dist/types/wallet-server/src/authorization/domain.d.ts +13 -2
- package/dist/types/wallet-server/src/authorization/ecdsaWalletSessionAdmission.d.ts +27 -3
- package/dist/types/wallet-server/src/authorization/service.d.ts +19 -0
- package/dist/types/wallet-server/src/core/ThresholdService/stores/SessionStore.d.ts +2 -2
- package/dist/types/wallet-server/src/core/ThresholdService/stores/WalletSessionStore.d.ts +1 -1
- package/dist/types/wallet-server/src/core/ThresholdService/stores/exportReplayGuard.d.ts +3 -0
- package/dist/types/wallet-server/src/core/ThresholdService/validation.d.ts +8 -101
- package/dist/types/wallet-server/src/core/WebAuthnAuthenticatorStore.d.ts +8 -0
- package/dist/types/wallet-server/src/core/authService/bytes.d.ts +0 -1
- package/dist/types/wallet-server/src/core/authService/emailOtpChallenges.d.ts +2 -10
- package/dist/types/wallet-server/src/core/authService/emailOtpSeal.d.ts +1 -1
- package/dist/types/wallet-server/src/core/authService/emailOtpUnlock.d.ts +3 -10
- package/dist/types/wallet-server/src/core/d1EcdsaSignerRead.d.ts +39 -0
- package/dist/types/wallet-server/src/core/d1WalletStore.d.ts +10 -0
- package/dist/types/wallet-server/src/core/deviceLinking/linkedDeviceSessionRecord.d.ts +3 -4
- package/dist/types/wallet-server/src/core/ecdsaMaterialReadSnapshot.d.ts +19 -0
- package/dist/types/wallet-server/src/core/routerAbSigning/RouterAbNormalSigningRuntime.d.ts +3 -5
- package/dist/types/wallet-server/src/core/rpcClients/near/NearClient.d.ts +1 -2
- package/dist/types/wallet-server/src/core/signingLanes/WalletExecutionLaneProjection.d.ts +2 -11
- package/dist/types/wallet-server/src/core/signingLanes/signingWorkerLaneMaterialIdentity.d.ts +2 -19
- package/dist/types/wallet-server/src/core/thresholdEcdsaChainTarget.d.ts +3 -11
- package/dist/types/wallet-server/src/core/types.d.ts +2 -6
- package/dist/types/wallet-server/src/localIntendedMaterialAdmissionFault.d.ts +38 -0
- package/dist/types/wallet-server/src/localIntendedPresignCancellation.d.ts +4 -0
- package/dist/types/wallet-server/src/router/auth/authRequestValidation.d.ts +4 -9
- package/dist/types/wallet-server/src/router/auth/commonRouterUtils.d.ts +15 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/auth/d1RouterApiAuthBoundary.d.ts +0 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/auth/d1RouterApiAuthService.d.ts +1 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/auth/walletSessionCredentialReaders.d.ts +9 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/authorization/authorizedOperationStatements.d.ts +4 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/authorization/d1AuthorizationStore.d.ts +10 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceAuthorityInstallService.d.ts +19 -2
- package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceSessionStore.d.ts +2 -6
- package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceTargetCredentialProvider.d.ts +5 -8
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpEnrollmentStore.d.ts +2 -8
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpRateLimitStore.d.ts +2 -9
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpRecords.d.ts +5 -5
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpServerSealRuntime.d.ts +4 -14
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationCeremonyRecordStore.d.ts +2 -6
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationService.d.ts +8 -6
- package/dist/types/wallet-server/src/router/cloudflare/d1/signingAdmission/d1RouterAbNormalSigningAdmissionStore.d.ts +14 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/webauthn/d1WebAuthnRecords.d.ts +10 -39
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletConsoleOps.d.ts +8 -34
- package/dist/types/wallet-server/src/router/domains/ecdsa/thresholdEcdsaRequestValidation.d.ts +3 -15
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/session/routerAbEd25519YaoWalletSession.d.ts +9 -50
- package/dist/types/wallet-server/src/router/domains/passkeyCustody/walletRecoveryKeyManifest.d.ts +1 -13
- package/dist/types/wallet-server/src/router/domains/signingOperations/routerAbEcdsaDerivationNormalSigningRoute.d.ts +8 -9
- package/dist/types/wallet-server/src/router/domains/signingOperations/routerAbNormalSigningAdmission.d.ts +13 -0
- package/dist/types/wallet-server/src/router/domains/signingOperations/routerAbOperationStepUp.d.ts +3 -4
- package/dist/types/wallet-server/src/router/domains/signingOperations/routerAbPrivateSigningWorker.d.ts +7 -16
- package/dist/types/wallet-server/src/router/domains/syncAccount/syncAccountRequestValidation.d.ts +2 -7
- package/dist/types/wallet-server/src/router/framework/apiCredentialPorts.d.ts +3 -1
- package/dist/types/wallet-server/src/router/framework/authServicePort.d.ts +25 -4
- package/dist/types/wallet-server/src/router/framework/http.d.ts +1 -0
- package/dist/types/wallet-server/src/router/framework/ror/normalize.d.ts +1 -9
- package/dist/types/wallet-server/src/router/transport/fetch/routes/deviceLinkingOwnerAuthorization.d.ts +3 -6
- package/dist/types/wallet-server/src/router/transport/fetch/routes/syncAccountBootstrap.d.ts +3 -5
- package/dist/types/wallet-server/src/router/transport/fetch/routes/thresholdEcdsa.d.ts +0 -1
- package/dist/types/wallet-server/src/threshold/session/signingSessionSeal/idempotencyRecords.d.ts +1 -2
- package/dist/types/wallet-server/src/threshold/session/signingSessionSeal/signingSessionSeal.types.d.ts +6 -8
- package/package.json +1 -1
- package/dist/esm/wasm/router_ab_ecdsa_signing_worker/pkg/router_ab_ecdsa_signing_worker_bg.wasm +0 -0
package/dist/esm/router/cloudflare/d1/signingAdmission/d1RouterAbNormalSigningAdmissionStore.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { requireNonEmptyString } from "../../../../shared-ts/src/utils/validation.js";
|
|
2
|
-
import {
|
|
1
|
+
import { isPlainObject, requireNonEmptyString } from "../../../../shared-ts/src/utils/validation.js";
|
|
2
|
+
import { normalizeRuntimePolicyScope } from "../../../../shared-ts/src/threshold/signingRootScope.js";
|
|
3
|
+
import { isD1DatabaseLike, parseD1JsonColumn } from "../../../../storage/d1Sql.js";
|
|
3
4
|
import { abusePrincipalKey, runtimePolicyScopeKey } from "../../../domains/signingOperations/routerAbNormalSigningAdmissionCore.js";
|
|
4
5
|
//#region src/router/cloudflare/d1/signingAdmission/d1RouterAbNormalSigningAdmissionStore.ts
|
|
5
6
|
const ROUTER_AB_NORMAL_SIGNING_ADMISSION_TABLE = "router_ab_normal_signing_admission_records";
|
|
@@ -11,8 +12,12 @@ var CloudflareD1RouterAbNormalSigningAdmissionStore = class {
|
|
|
11
12
|
this.now = options.now || Date.now;
|
|
12
13
|
}
|
|
13
14
|
async evaluatePolicy(input) {
|
|
15
|
+
if (input.curve === "ecdsa" && input.policyReadSource.kind === "credential_snapshot") {
|
|
16
|
+
const decision = input.policyReadSource.policyRead.resolve(this.database, this.storageNamespace, input);
|
|
17
|
+
if (decision) return decision;
|
|
18
|
+
}
|
|
14
19
|
const scope = input.runtimePolicyScope;
|
|
15
|
-
|
|
20
|
+
return parsePolicyRow(await this.database.prepare(`WITH scope(namespace, org_id, project_id, env_id, signing_root_version,
|
|
16
21
|
project_key, abuse_key) AS (VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7))
|
|
17
22
|
SELECT project.record_key AS project_key, project.decision AS project_decision,
|
|
18
23
|
project.retry_after_ms AS project_retry_after_ms,
|
|
@@ -28,27 +33,7 @@ var CloudflareD1RouterAbNormalSigningAdmissionStore = class {
|
|
|
28
33
|
ON abuse.namespace = scope.namespace AND abuse.org_id = scope.org_id
|
|
29
34
|
AND abuse.project_id = scope.project_id AND abuse.env_id = scope.env_id
|
|
30
35
|
AND abuse.signing_root_version = scope.signing_root_version
|
|
31
|
-
AND abuse.record_kind = 'abuse' AND abuse.record_key = scope.abuse_key`).bind(this.storageNamespace, scope.orgId, scope.projectId, scope.envId, scope.signingRootVersion, runtimePolicyScopeKey(scope), abusePrincipalKey(input)).first();
|
|
32
|
-
if (!row) throw new Error("Router A/B admission policy snapshot is missing");
|
|
33
|
-
if (row.project_key !== null) {
|
|
34
|
-
const project = parseProjectPolicyDecision({
|
|
35
|
-
decision: row.project_decision,
|
|
36
|
-
retry_after_ms: row.project_retry_after_ms
|
|
37
|
-
});
|
|
38
|
-
if (project.kind === "rejected") return {
|
|
39
|
-
kind: "project_policy_rejected",
|
|
40
|
-
retryAfterMs: project.retryAfterMs
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
if (row.abuse_key === null) return { kind: "allowed" };
|
|
44
|
-
const abuse = parseAbuseDecision({
|
|
45
|
-
decision: row.abuse_decision,
|
|
46
|
-
retry_after_ms: row.abuse_retry_after_ms
|
|
47
|
-
});
|
|
48
|
-
return abuse.kind === "rejected" ? {
|
|
49
|
-
kind: "abuse_rejected",
|
|
50
|
-
retryAfterMs: abuse.retryAfterMs
|
|
51
|
-
} : abuse;
|
|
36
|
+
AND abuse.record_kind = 'abuse' AND abuse.record_key = scope.abuse_key`).bind(this.storageNamespace, scope.orgId, scope.projectId, scope.envId, scope.signingRootVersion, runtimePolicyScopeKey(scope), abusePrincipalKey(input)).first());
|
|
52
37
|
}
|
|
53
38
|
async setProjectPolicy(scope, decision) {
|
|
54
39
|
const normalized = normalizeProjectPolicyDecision(decision);
|
|
@@ -158,7 +143,116 @@ function requirePositiveInteger(label, value) {
|
|
|
158
143
|
function assertNever(value) {
|
|
159
144
|
throw new Error(`Unexpected Router A/B normal-signing admission branch: ${String(value)}`);
|
|
160
145
|
}
|
|
146
|
+
function parsePolicyRow(row) {
|
|
147
|
+
if (!row) throw new Error("Router A/B admission policy snapshot is missing");
|
|
148
|
+
if (row.project_key !== null) {
|
|
149
|
+
const project = parseProjectPolicyDecision({
|
|
150
|
+
decision: row.project_decision,
|
|
151
|
+
retry_after_ms: row.project_retry_after_ms
|
|
152
|
+
});
|
|
153
|
+
if (project.kind === "rejected") return {
|
|
154
|
+
kind: "project_policy_rejected",
|
|
155
|
+
retryAfterMs: project.retryAfterMs
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
if (row.abuse_key === null) return { kind: "allowed" };
|
|
159
|
+
const abuse = parseAbuseDecision({
|
|
160
|
+
decision: row.abuse_decision,
|
|
161
|
+
retry_after_ms: row.abuse_retry_after_ms
|
|
162
|
+
});
|
|
163
|
+
return abuse.kind === "rejected" ? {
|
|
164
|
+
kind: "abuse_rejected",
|
|
165
|
+
retryAfterMs: abuse.retryAfterMs
|
|
166
|
+
} : abuse;
|
|
167
|
+
}
|
|
168
|
+
var D1EcdsaAdmissionPolicyRead = class D1EcdsaAdmissionPolicyRead {
|
|
169
|
+
#decisions;
|
|
170
|
+
constructor(database, namespace, walletId, activationId, decisions) {
|
|
171
|
+
this.database = database;
|
|
172
|
+
this.namespace = namespace;
|
|
173
|
+
this.walletId = walletId;
|
|
174
|
+
this.activationId = activationId;
|
|
175
|
+
this.#decisions = decisions;
|
|
176
|
+
}
|
|
177
|
+
static fromRows(database, namespace, walletId, activationId, rows) {
|
|
178
|
+
if (!Array.isArray(rows)) throw new Error("ECDSA policy candidates are invalid");
|
|
179
|
+
const decisions = /* @__PURE__ */ new Map();
|
|
180
|
+
for (const row of rows) {
|
|
181
|
+
if (!isPlainObject(row)) throw new Error("ECDSA policy candidate is invalid");
|
|
182
|
+
const key = runtimePolicyScopeKey(normalizeRuntimePolicyScope(parseD1JsonColumn(row.scope_json)));
|
|
183
|
+
if (decisions.has(key)) throw new Error("ECDSA policy scope is ambiguous");
|
|
184
|
+
try {
|
|
185
|
+
const decision = parsePolicyRow({
|
|
186
|
+
project_key: row.project_key,
|
|
187
|
+
project_decision: row.project_decision,
|
|
188
|
+
project_retry_after_ms: row.project_retry_after_ms,
|
|
189
|
+
abuse_key: row.abuse_key,
|
|
190
|
+
abuse_decision: row.abuse_decision,
|
|
191
|
+
abuse_retry_after_ms: row.abuse_retry_after_ms
|
|
192
|
+
});
|
|
193
|
+
decisions.set(key, {
|
|
194
|
+
ok: true,
|
|
195
|
+
decision
|
|
196
|
+
});
|
|
197
|
+
} catch (error) {
|
|
198
|
+
decisions.set(key, {
|
|
199
|
+
ok: false,
|
|
200
|
+
message: error instanceof Error ? error.message : "ECDSA policy read failed"
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return new D1EcdsaAdmissionPolicyRead(database, namespace, walletId, activationId, decisions);
|
|
205
|
+
}
|
|
206
|
+
resolve(database, namespace, input) {
|
|
207
|
+
if (database !== this.database || namespace !== this.namespace) return null;
|
|
208
|
+
if (input.walletId !== this.walletId || input.materialActivationId !== this.activationId) throw new Error("ECDSA policy credential scope does not match");
|
|
209
|
+
const result = this.#decisions.get(runtimePolicyScopeKey(input.runtimePolicyScope));
|
|
210
|
+
if (!result) throw new Error("Verified ECDSA material policy scope is missing");
|
|
211
|
+
if (!result.ok) throw new Error(result.message);
|
|
212
|
+
return result.decision;
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
const ECDSA_CREDENTIAL_POLICY_PROJECTION = `
|
|
216
|
+
(WITH candidates AS (
|
|
217
|
+
SELECT DISTINCT json_extract(signer.record_json, '$.runtimePolicyScope') AS scope_json
|
|
218
|
+
FROM wallet_signers AS signer
|
|
219
|
+
WHERE signer.namespace = session.namespace AND signer.org_id = session.org_id
|
|
220
|
+
AND signer.project_id = session.project_id AND signer.env_id = session.env_id
|
|
221
|
+
AND signer.wallet_id = session.wallet_id AND signer.signer_family = 'ecdsa'
|
|
222
|
+
AND json_valid(signer.record_json)
|
|
223
|
+
), scopes AS (
|
|
224
|
+
SELECT scope_json,
|
|
225
|
+
json_extract(scope_json, '$.orgId') AS org_id,
|
|
226
|
+
json_extract(scope_json, '$.projectId') AS project_id,
|
|
227
|
+
json_extract(scope_json, '$.envId') AS env_id,
|
|
228
|
+
json_extract(scope_json, '$.signingRootVersion') AS signing_root_version,
|
|
229
|
+
json_extract(scope_json, '$.orgId') || char(31) ||
|
|
230
|
+
json_extract(scope_json, '$.projectId') || char(31) ||
|
|
231
|
+
json_extract(scope_json, '$.envId') || char(31) ||
|
|
232
|
+
json_extract(scope_json, '$.signingRootVersion') AS project_key
|
|
233
|
+
FROM candidates
|
|
234
|
+
)
|
|
235
|
+
SELECT json_group_array(json_object(
|
|
236
|
+
'scope_json', scopes.scope_json,
|
|
237
|
+
'project_key', project.record_key, 'project_decision', project.decision,
|
|
238
|
+
'project_retry_after_ms', project.retry_after_ms,
|
|
239
|
+
'abuse_key', abuse.record_key, 'abuse_decision', abuse.decision,
|
|
240
|
+
'abuse_retry_after_ms', abuse.retry_after_ms))
|
|
241
|
+
FROM scopes
|
|
242
|
+
LEFT JOIN router_ab_normal_signing_admission_records AS project
|
|
243
|
+
ON project.namespace = session.namespace AND project.org_id = scopes.org_id
|
|
244
|
+
AND project.project_id = scopes.project_id AND project.env_id = scopes.env_id
|
|
245
|
+
AND project.signing_root_version = scopes.signing_root_version
|
|
246
|
+
AND project.record_kind = 'project_policy' AND project.record_key = scopes.project_key
|
|
247
|
+
LEFT JOIN router_ab_normal_signing_admission_records AS abuse
|
|
248
|
+
ON abuse.namespace = session.namespace AND abuse.org_id = scopes.org_id
|
|
249
|
+
AND abuse.project_id = scopes.project_id AND abuse.env_id = scopes.env_id
|
|
250
|
+
AND abuse.signing_root_version = scopes.signing_root_version
|
|
251
|
+
AND abuse.record_kind = 'abuse'
|
|
252
|
+
AND abuse.record_key = scopes.project_key || char(31) || session.wallet_id || char(31) ||
|
|
253
|
+
'material_activation:' || ? || char(31) || 'ecdsa'
|
|
254
|
+
) AS ecdsa_policy_records_json,`;
|
|
161
255
|
//#endregion
|
|
162
|
-
export { CloudflareD1RouterAbNormalSigningAdmissionStore, createCloudflareD1RouterAbNormalSigningAdmissionStore };
|
|
256
|
+
export { CloudflareD1RouterAbNormalSigningAdmissionStore, D1EcdsaAdmissionPolicyRead, ECDSA_CREDENTIAL_POLICY_PROJECTION, createCloudflareD1RouterAbNormalSigningAdmissionStore };
|
|
163
257
|
|
|
164
258
|
//# sourceMappingURL=d1RouterAbNormalSigningAdmissionStore.js.map
|
|
@@ -3,6 +3,7 @@ import { parseDigestB64u } from "../../../../shared-ts/src/utils/canonicalPrimit
|
|
|
3
3
|
import { normalizeOptionalTrimmedString } from "../../../../shared-ts/src/utils/normalize.js";
|
|
4
4
|
import "../../../../shared-ts/src/utils/validation.js";
|
|
5
5
|
import { secureRandomBase64Url } from "../../../../shared-ts/src/utils/secureRandomId.js";
|
|
6
|
+
import { failedVerification, failure } from "../../../../shared-ts/src/utils/failure.js";
|
|
6
7
|
import { decodeWebAuthnBase64UrlOrBase64, parseWebAuthnAuthenticationCredential, parseWebAuthnClientDataJsonBase64url, webAuthnCredentialIdB64uFromCredential, webAuthnOriginHostnameOrEmpty } from "../../../auth/webAuthnCredentialCodecs.js";
|
|
7
8
|
import { nonNegativeSafeInteger, optionalNonNegativeInteger, parseD1BoundaryWalletId, parseD1BoundaryWalletIdResult, parseJsonObject } from "../auth/d1RouterApiAuthBoundary.js";
|
|
8
9
|
import { parseWebAuthnAuthenticatorRowDeviceInfo, webAuthnSyncWalletBindingFromCredentialBinding } from "./d1WebAuthnRecords.js";
|
|
@@ -21,11 +22,7 @@ var CloudflareD1WebAuthnAuthService = class {
|
|
|
21
22
|
async listWebAuthnAuthenticatorsForUser(input) {
|
|
22
23
|
try {
|
|
23
24
|
const userId = parseD1BoundaryWalletIdResult(input.userId);
|
|
24
|
-
if (!userId.ok) return
|
|
25
|
-
ok: false,
|
|
26
|
-
code: "invalid_args",
|
|
27
|
-
message: userId.code === "missing" ? "Missing userId" : "Invalid userId"
|
|
28
|
-
};
|
|
25
|
+
if (!userId.ok) return failure("invalid_args", userId.code === "missing" ? "Missing userId" : "Invalid userId");
|
|
29
26
|
const rpId = normalizeOptionalTrimmedString(input.rpId);
|
|
30
27
|
const authRows = await this.webAuthnStore.readAuthenticatorRows(userId.value);
|
|
31
28
|
const bindings = await this.webAuthnStore.readBindingRows({
|
|
@@ -55,27 +52,15 @@ var CloudflareD1WebAuthnAuthService = class {
|
|
|
55
52
|
authenticators
|
|
56
53
|
};
|
|
57
54
|
} catch (error) {
|
|
58
|
-
return
|
|
59
|
-
ok: false,
|
|
60
|
-
code: "internal",
|
|
61
|
-
message: errorMessage(error) || "Failed to list authenticators"
|
|
62
|
-
};
|
|
55
|
+
return failure("internal", errorMessage(error) || "Failed to list authenticators");
|
|
63
56
|
}
|
|
64
57
|
}
|
|
65
58
|
async createWebAuthnLoginOptions(input) {
|
|
66
59
|
try {
|
|
67
60
|
const userId = parseD1BoundaryWalletIdResult(input.userId ?? input.user_id);
|
|
68
61
|
const rpId = normalizeOptionalTrimmedString(input.rpId ?? input.rp_id);
|
|
69
|
-
if (!userId.ok) return
|
|
70
|
-
|
|
71
|
-
code: "invalid_body",
|
|
72
|
-
message: userId.code === "missing" ? "Missing userId" : "Invalid userId"
|
|
73
|
-
};
|
|
74
|
-
if (!rpId) return {
|
|
75
|
-
ok: false,
|
|
76
|
-
code: "invalid_body",
|
|
77
|
-
message: "Missing rpId"
|
|
78
|
-
};
|
|
62
|
+
if (!userId.ok) return failure("invalid_body", userId.code === "missing" ? "Missing userId" : "Invalid userId");
|
|
63
|
+
if (!rpId) return failure("invalid_body", "Missing rpId");
|
|
79
64
|
const createdAtMs = Date.now();
|
|
80
65
|
const expiresAtMs = createdAtMs + webAuthnLoginChallengeTtlMs(input.ttlMs ?? input.ttl_ms);
|
|
81
66
|
const challengeId = secureRandomBase64Url(16, "WebAuthn login challenge id");
|
|
@@ -96,11 +81,7 @@ var CloudflareD1WebAuthnAuthService = class {
|
|
|
96
81
|
seenCredentialIds.add(credentialId);
|
|
97
82
|
credentialIds.push(credentialId);
|
|
98
83
|
}
|
|
99
|
-
if (credentialIds.length === 0) return
|
|
100
|
-
ok: false,
|
|
101
|
-
code: "unknown_credential",
|
|
102
|
-
message: "Wallet has no registered passkey credential"
|
|
103
|
-
};
|
|
84
|
+
if (credentialIds.length === 0) return failure("unknown_credential", "Wallet has no registered passkey credential");
|
|
104
85
|
const record = {
|
|
105
86
|
version: "webauthn_login_challenge_v1",
|
|
106
87
|
challengeId,
|
|
@@ -125,28 +106,16 @@ var CloudflareD1WebAuthnAuthService = class {
|
|
|
125
106
|
expiresAtMs
|
|
126
107
|
};
|
|
127
108
|
} catch (error) {
|
|
128
|
-
return
|
|
129
|
-
ok: false,
|
|
130
|
-
code: "internal",
|
|
131
|
-
message: errorMessage(error) || "Failed to create login options"
|
|
132
|
-
};
|
|
109
|
+
return failure("internal", errorMessage(error) || "Failed to create login options");
|
|
133
110
|
}
|
|
134
111
|
}
|
|
135
112
|
async createWebAuthnSyncAccountOptions(input) {
|
|
136
113
|
try {
|
|
137
114
|
const rpId = normalizeOptionalTrimmedString(input.rp_id);
|
|
138
|
-
if (!rpId) return
|
|
139
|
-
ok: false,
|
|
140
|
-
code: "invalid_body",
|
|
141
|
-
message: "Missing rp_id"
|
|
142
|
-
};
|
|
115
|
+
if (!rpId) return failure("invalid_body", "Missing rp_id");
|
|
143
116
|
const expectedUserIdRaw = normalizeOptionalTrimmedString(input.account_id);
|
|
144
117
|
const expectedUserId = expectedUserIdRaw ? parseD1BoundaryWalletId(expectedUserIdRaw) : null;
|
|
145
|
-
if (expectedUserIdRaw && !expectedUserId) return
|
|
146
|
-
ok: false,
|
|
147
|
-
code: "invalid_body",
|
|
148
|
-
message: "Invalid wallet account_id"
|
|
149
|
-
};
|
|
118
|
+
if (expectedUserIdRaw && !expectedUserId) return failure("invalid_body", "Invalid wallet account_id");
|
|
150
119
|
const createdAtMs = Date.now();
|
|
151
120
|
const expiresAtMs = createdAtMs + webAuthnLoginChallengeTtlMs(input.ttlMs ?? input.ttl_ms);
|
|
152
121
|
const challengeId = secureRandomBase64Url(16, "WebAuthn sync challenge id");
|
|
@@ -172,11 +141,7 @@ var CloudflareD1WebAuthnAuthService = class {
|
|
|
172
141
|
}
|
|
173
142
|
if (credentialId && activeCredentialIds.has(credentialId) && !walletBinding) walletBinding = webAuthnSyncWalletBindingFromCredentialBinding(binding) || void 0;
|
|
174
143
|
}
|
|
175
|
-
if (credentialIds.length === 0) return
|
|
176
|
-
ok: false,
|
|
177
|
-
code: "unknown_credential",
|
|
178
|
-
message: "Wallet has no registered active passkey credential"
|
|
179
|
-
};
|
|
144
|
+
if (credentialIds.length === 0) return failure("unknown_credential", "Wallet has no registered active passkey credential");
|
|
180
145
|
}
|
|
181
146
|
const record = {
|
|
182
147
|
version: "webauthn_sync_challenge_v1",
|
|
@@ -203,11 +168,7 @@ var CloudflareD1WebAuthnAuthService = class {
|
|
|
203
168
|
expiresAtMs
|
|
204
169
|
};
|
|
205
170
|
} catch (error) {
|
|
206
|
-
return
|
|
207
|
-
ok: false,
|
|
208
|
-
code: "internal",
|
|
209
|
-
message: errorMessage(error) || "Failed to create sync account options"
|
|
210
|
-
};
|
|
171
|
+
return failure("internal", errorMessage(error) || "Failed to create sync account options");
|
|
211
172
|
}
|
|
212
173
|
}
|
|
213
174
|
async verifyWebAuthnAuthenticationLite(input) {
|
|
@@ -349,56 +310,22 @@ var CloudflareD1WebAuthnAuthService = class {
|
|
|
349
310
|
async verifyWebAuthnLogin(input) {
|
|
350
311
|
try {
|
|
351
312
|
const challengeId = normalizeOptionalTrimmedString(input.challengeId ?? input.challenge_id);
|
|
352
|
-
if (!challengeId) return
|
|
353
|
-
ok: false,
|
|
354
|
-
code: "invalid_body",
|
|
355
|
-
message: "Missing challengeId"
|
|
356
|
-
};
|
|
313
|
+
if (!challengeId) return failure("invalid_body", "Missing challengeId");
|
|
357
314
|
const challenge = await this.webAuthnStore.consumeLoginChallenge(challengeId);
|
|
358
|
-
if (!challenge) return
|
|
359
|
-
ok: false,
|
|
360
|
-
verified: false,
|
|
361
|
-
code: "challenge_expired_or_invalid",
|
|
362
|
-
message: "Login challenge expired or invalid"
|
|
363
|
-
};
|
|
315
|
+
if (!challenge) return failedVerification("challenge_expired_or_invalid", "Login challenge expired or invalid");
|
|
364
316
|
const expectedOrigin = normalizeOptionalTrimmedString(input.expected_origin);
|
|
365
|
-
if (!expectedOrigin) return
|
|
366
|
-
ok: false,
|
|
367
|
-
verified: false,
|
|
368
|
-
code: "invalid_body",
|
|
369
|
-
message: "expected_origin is required for WebAuthn authentication verification"
|
|
370
|
-
};
|
|
317
|
+
if (!expectedOrigin) return failedVerification("invalid_body", "expected_origin is required for WebAuthn authentication verification");
|
|
371
318
|
const rpId = parseWebAuthnRpId(challenge.rpId);
|
|
372
|
-
if (!rpId.ok) return {
|
|
373
|
-
ok: false,
|
|
374
|
-
verified: false,
|
|
375
|
-
code: "internal",
|
|
376
|
-
message: `Stored login challenge rpId is invalid: ${rpId.error.message}`
|
|
377
|
-
};
|
|
319
|
+
if (!rpId.ok) return failedVerification("internal", `Stored login challenge rpId is invalid: ${rpId.error.message}`);
|
|
378
320
|
const credential = parseWebAuthnAuthenticationCredential(input.webauthn_authentication);
|
|
379
|
-
if (!credential) return
|
|
380
|
-
ok: false,
|
|
381
|
-
verified: false,
|
|
382
|
-
code: "invalid_body",
|
|
383
|
-
message: "Missing webauthn_authentication"
|
|
384
|
-
};
|
|
321
|
+
if (!credential) return failedVerification("invalid_body", "Missing webauthn_authentication");
|
|
385
322
|
const credentialId = webAuthnCredentialIdB64uFromCredential(credential);
|
|
386
|
-
if (!credentialId.ok) return
|
|
387
|
-
ok: false,
|
|
388
|
-
verified: false,
|
|
389
|
-
code: credentialId.code,
|
|
390
|
-
message: credentialId.message
|
|
391
|
-
};
|
|
323
|
+
if (!credentialId.ok) return failedVerification(credentialId.code, credentialId.message);
|
|
392
324
|
const activeMethod = await this.walletAuthMethodStore.getPasskeyV2({
|
|
393
325
|
rpId: challenge.rpId,
|
|
394
326
|
credentialIdB64u: credentialId.credentialIdB64u
|
|
395
327
|
});
|
|
396
|
-
if (!activeMethod || activeMethod.kind !== "passkey" || activeMethod.status !== "active" || String(activeMethod.walletId) !== String(challenge.userId) || String(activeMethod.rpId) !== String(challenge.rpId) || String(activeMethod.credentialIdB64u) !== String(credentialId.credentialIdB64u)) return
|
|
397
|
-
ok: false,
|
|
398
|
-
verified: false,
|
|
399
|
-
code: "unknown_credential",
|
|
400
|
-
message: "Credential is not active for this wallet"
|
|
401
|
-
};
|
|
328
|
+
if (!activeMethod || activeMethod.kind !== "passkey" || activeMethod.status !== "active" || String(activeMethod.walletId) !== String(challenge.userId) || String(activeMethod.rpId) !== String(challenge.rpId) || String(activeMethod.credentialIdB64u) !== String(credentialId.credentialIdB64u)) return failedVerification("unknown_credential", "Credential is not active for this wallet");
|
|
402
329
|
const verificationFailure = webAuthnAuthenticationFailure(await this.verifyWebAuthnAuthenticationLite({
|
|
403
330
|
userId: challenge.userId,
|
|
404
331
|
rpId: rpId.value,
|
|
@@ -424,43 +351,19 @@ var CloudflareD1WebAuthnAuthService = class {
|
|
|
424
351
|
ed25519: loginSigner.ed25519
|
|
425
352
|
};
|
|
426
353
|
} catch (error) {
|
|
427
|
-
return
|
|
428
|
-
ok: false,
|
|
429
|
-
verified: false,
|
|
430
|
-
code: "internal",
|
|
431
|
-
message: errorMessage(error) || "Login verification failed"
|
|
432
|
-
};
|
|
354
|
+
return failedVerification("internal", errorMessage(error) || "Login verification failed");
|
|
433
355
|
}
|
|
434
356
|
}
|
|
435
357
|
async verifyWebAuthnSyncAccount(input) {
|
|
436
358
|
try {
|
|
437
359
|
const challengeId = normalizeOptionalTrimmedString(input.challengeId ?? input.challenge_id);
|
|
438
|
-
if (!challengeId) return
|
|
439
|
-
ok: false,
|
|
440
|
-
code: "invalid_body",
|
|
441
|
-
message: "Missing challengeId"
|
|
442
|
-
};
|
|
360
|
+
if (!challengeId) return failure("invalid_body", "Missing challengeId");
|
|
443
361
|
const challenge = await this.webAuthnStore.consumeSyncChallenge(challengeId);
|
|
444
|
-
if (!challenge) return
|
|
445
|
-
ok: false,
|
|
446
|
-
verified: false,
|
|
447
|
-
code: "challenge_expired_or_invalid",
|
|
448
|
-
message: "Sync challenge expired or invalid"
|
|
449
|
-
};
|
|
362
|
+
if (!challenge) return failedVerification("challenge_expired_or_invalid", "Sync challenge expired or invalid");
|
|
450
363
|
const credential = parseWebAuthnAuthenticationCredential(input.webauthn_authentication);
|
|
451
|
-
if (!credential) return
|
|
452
|
-
ok: false,
|
|
453
|
-
verified: false,
|
|
454
|
-
code: "invalid_body",
|
|
455
|
-
message: "Missing webauthn_authentication"
|
|
456
|
-
};
|
|
364
|
+
if (!credential) return failedVerification("invalid_body", "Missing webauthn_authentication");
|
|
457
365
|
const credentialId = webAuthnCredentialIdB64uFromCredential(credential);
|
|
458
|
-
if (!credentialId.ok) return
|
|
459
|
-
ok: false,
|
|
460
|
-
verified: false,
|
|
461
|
-
code: credentialId.code,
|
|
462
|
-
message: credentialId.message
|
|
463
|
-
};
|
|
366
|
+
if (!credentialId.ok) return failedVerification(credentialId.code, credentialId.message);
|
|
464
367
|
const syncBinding = webAuthnSyncCredentialBinding(await this.webAuthnStore.readBindingByCredential({
|
|
465
368
|
rpId: challenge.rpId,
|
|
466
369
|
credentialIdB64u: credentialId.credentialIdB64u
|
|
@@ -471,26 +374,11 @@ var CloudflareD1WebAuthnAuthService = class {
|
|
|
471
374
|
rpId: challenge.rpId,
|
|
472
375
|
credentialIdB64u: credentialId.credentialIdB64u
|
|
473
376
|
});
|
|
474
|
-
if (!activeMethod || activeMethod.kind !== "passkey" || activeMethod.status !== "active" || String(activeMethod.walletId) !== String(binding.userId) || String(activeMethod.rpId) !== String(challenge.rpId) || String(activeMethod.credentialIdB64u) !== String(credentialId.credentialIdB64u)) return
|
|
475
|
-
ok: false,
|
|
476
|
-
verified: false,
|
|
477
|
-
code: "unknown_credential",
|
|
478
|
-
message: "Credential is not active for this wallet"
|
|
479
|
-
};
|
|
377
|
+
if (!activeMethod || activeMethod.kind !== "passkey" || activeMethod.status !== "active" || String(activeMethod.walletId) !== String(binding.userId) || String(activeMethod.rpId) !== String(challenge.rpId) || String(activeMethod.credentialIdB64u) !== String(credentialId.credentialIdB64u)) return failedVerification("unknown_credential", "Credential is not active for this wallet");
|
|
480
378
|
const expectedOrigin = normalizeOptionalTrimmedString(input.expected_origin);
|
|
481
|
-
if (!expectedOrigin) return
|
|
482
|
-
ok: false,
|
|
483
|
-
verified: false,
|
|
484
|
-
code: "invalid_body",
|
|
485
|
-
message: "expected_origin is required for WebAuthn authentication verification"
|
|
486
|
-
};
|
|
379
|
+
if (!expectedOrigin) return failedVerification("invalid_body", "expected_origin is required for WebAuthn authentication verification");
|
|
487
380
|
const rpId = parseWebAuthnRpId(binding.rpId);
|
|
488
|
-
if (!rpId.ok) return {
|
|
489
|
-
ok: false,
|
|
490
|
-
verified: false,
|
|
491
|
-
code: "internal",
|
|
492
|
-
message: `Stored sync credential binding rpId is invalid: ${rpId.error.message}`
|
|
493
|
-
};
|
|
381
|
+
if (!rpId.ok) return failedVerification("internal", `Stored sync credential binding rpId is invalid: ${rpId.error.message}`);
|
|
494
382
|
const verificationFailure = webAuthnAuthenticationFailure(await this.verifyWebAuthnAuthenticationLite({
|
|
495
383
|
userId: binding.userId,
|
|
496
384
|
rpId: rpId.value,
|
|
@@ -503,36 +391,16 @@ var CloudflareD1WebAuthnAuthService = class {
|
|
|
503
391
|
userId: binding.userId,
|
|
504
392
|
credentialIdB64u: credentialId.credentialIdB64u
|
|
505
393
|
});
|
|
506
|
-
if (!authenticator) return
|
|
507
|
-
ok: false,
|
|
508
|
-
verified: false,
|
|
509
|
-
code: "unknown_credential",
|
|
510
|
-
message: "Credential is not registered for user"
|
|
511
|
-
};
|
|
394
|
+
if (!authenticator) return failedVerification("unknown_credential", "Credential is not registered for user");
|
|
512
395
|
const walletBinding = webAuthnSyncWalletBindingFromCredentialBinding(binding);
|
|
513
|
-
if (!walletBinding) return
|
|
514
|
-
ok: false,
|
|
515
|
-
verified: false,
|
|
516
|
-
code: "internal",
|
|
517
|
-
message: "Credential binding is missing wallet identity fields"
|
|
518
|
-
};
|
|
396
|
+
if (!walletBinding) return failedVerification("internal", "Credential binding is missing wallet identity fields");
|
|
519
397
|
const walletId = parseD1BoundaryWalletId(walletBinding.walletId);
|
|
520
|
-
if (!walletId) return
|
|
521
|
-
ok: false,
|
|
522
|
-
verified: false,
|
|
523
|
-
code: "internal",
|
|
524
|
-
message: "Credential binding contains an invalid wallet ID"
|
|
525
|
-
};
|
|
398
|
+
if (!walletId) return failedVerification("internal", "Credential binding contains an invalid wallet ID");
|
|
526
399
|
const ed25519Manifest = await this.walletManifestSource.getEd25519KeyManifestBySlot({
|
|
527
400
|
walletId,
|
|
528
401
|
signerSlot: walletBinding.signerSlot
|
|
529
402
|
});
|
|
530
|
-
if (!ed25519Manifest) return
|
|
531
|
-
ok: false,
|
|
532
|
-
verified: false,
|
|
533
|
-
code: "ed25519_not_provisioned",
|
|
534
|
-
message: "Wallet has no Ed25519 signer yet; NEAR provisioning has not completed"
|
|
535
|
-
};
|
|
403
|
+
if (!ed25519Manifest) return failedVerification("ed25519_not_provisioned", "Wallet has no Ed25519 signer yet; NEAR provisioning has not completed");
|
|
536
404
|
const thresholdEd25519 = binding.relayerKeyId && binding.publicKey ? {
|
|
537
405
|
relayerKeyId: binding.relayerKeyId,
|
|
538
406
|
authorityScope: {
|
|
@@ -566,12 +434,7 @@ var CloudflareD1WebAuthnAuthService = class {
|
|
|
566
434
|
...thresholdEd25519 ? { thresholdEd25519 } : {}
|
|
567
435
|
};
|
|
568
436
|
} catch (error) {
|
|
569
|
-
return
|
|
570
|
-
ok: false,
|
|
571
|
-
verified: false,
|
|
572
|
-
code: "internal",
|
|
573
|
-
message: errorMessage(error) || "Sync verification failed"
|
|
574
|
-
};
|
|
437
|
+
return failedVerification("internal", errorMessage(error) || "Sync verification failed");
|
|
575
438
|
}
|
|
576
439
|
}
|
|
577
440
|
};
|
|
@@ -7,6 +7,7 @@ import { normalizeRuntimePolicyScope } from "../../../../shared-ts/src/threshold
|
|
|
7
7
|
import { parseWalletAuthMethodRecordV2 } from "../../../../shared-ts/src/utils/walletAuthMethodRecord.js";
|
|
8
8
|
import { parseWalletAuthorityV1 } from "../../../../shared-ts/src/authorization/walletAuthority.js";
|
|
9
9
|
import { parseWebAuthnAuthenticatorDeviceInfoJson } from "../../../../shared-ts/src/utils/webauthnDeviceInfo.js";
|
|
10
|
+
import { hasExactKeys } from "../../../../shared-ts/src/utils/exactKeys.js";
|
|
10
11
|
import "../../../../shared-ts/src/passkey-custody/index.js";
|
|
11
12
|
import { parseRecoveryCodeReservationId } from "../../../../shared-ts/src/wallet-recovery/recoveryCodeReservation.js";
|
|
12
13
|
import { nonNegativeSafeInteger, optionalNonNegativeInteger, positiveInteger } from "../auth/d1RouterApiAuthBoundary.js";
|
|
@@ -25,7 +26,7 @@ function parseWebAuthnLoginChallengeRecord(input) {
|
|
|
25
26
|
}
|
|
26
27
|
if (prototype !== Object.prototype && prototype !== null) return null;
|
|
27
28
|
const record = candidate;
|
|
28
|
-
if (!
|
|
29
|
+
if (!hasExactKeys(record, [
|
|
29
30
|
"version",
|
|
30
31
|
"challengeId",
|
|
31
32
|
"userId",
|
|
@@ -65,7 +66,7 @@ function parseWebAuthnSyncChallengeRecord(input) {
|
|
|
65
66
|
}
|
|
66
67
|
if (prototype !== Object.prototype && prototype !== null) return null;
|
|
67
68
|
const record = candidate;
|
|
68
|
-
if (!
|
|
69
|
+
if (!hasExactKeys(record, Object.hasOwn(record, "expectedUserId") ? [
|
|
69
70
|
"version",
|
|
70
71
|
"challengeId",
|
|
71
72
|
"rpId",
|
|
@@ -263,7 +264,7 @@ function parseWebAuthnRecoveryContinuityEnvelopeAnchor(input) {
|
|
|
263
264
|
const updatedAtMs = positiveInteger(record.updatedAtMs);
|
|
264
265
|
if (!kind || !envelopeId.ok || !walletId.ok || !envelopeRevision || updatedAtMs === null || record.bindingKind !== "wallet_custody_seed_v1") return null;
|
|
265
266
|
if (kind === "passkey") {
|
|
266
|
-
if (!
|
|
267
|
+
if (!hasExactKeys(record, [
|
|
267
268
|
"kind",
|
|
268
269
|
"envelopeId",
|
|
269
270
|
"walletId",
|
|
@@ -288,7 +289,7 @@ function parseWebAuthnRecoveryContinuityEnvelopeAnchor(input) {
|
|
|
288
289
|
};
|
|
289
290
|
}
|
|
290
291
|
if (kind === "email_otp") {
|
|
291
|
-
if (!
|
|
292
|
+
if (!hasExactKeys(record, [
|
|
292
293
|
"kind",
|
|
293
294
|
"envelopeId",
|
|
294
295
|
"walletId",
|
|
@@ -321,10 +322,6 @@ function parseRecoveryEnvelopeRevision(input) {
|
|
|
321
322
|
return null;
|
|
322
323
|
}
|
|
323
324
|
}
|
|
324
|
-
function hasExactFields(record, expectedFields) {
|
|
325
|
-
const fields = Object.keys(record);
|
|
326
|
-
return fields.length === expectedFields.length && expectedFields.every((field) => fields.includes(field));
|
|
327
|
-
}
|
|
328
325
|
function parseWebAuthnAuthenticator(row) {
|
|
329
326
|
const credentialIdB64u = normalizeOptionalTrimmedString(row?.credential_id_b64u);
|
|
330
327
|
const credentialPublicKeyB64u = normalizeOptionalTrimmedString(row?.credential_public_key_b64u);
|
|
@@ -478,7 +475,7 @@ function parseWebAuthnRuntimePolicyScope(raw) {
|
|
|
478
475
|
}
|
|
479
476
|
if (prototype !== Object.prototype && prototype !== null) return void 0;
|
|
480
477
|
const record = raw;
|
|
481
|
-
if (!
|
|
478
|
+
if (!hasExactKeys(record, [
|
|
482
479
|
"orgId",
|
|
483
480
|
"projectId",
|
|
484
481
|
"envId",
|