@seams/wallet-server 0.7.1 → 0.8.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 +1 -113
- package/artifact-manifest.json +78 -33
- 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/scripts/prepare-local-runtime-config.mjs +0 -2
- package/cloudflare-router-ab/scripts/start-local-role-workers.mjs +77 -20
- package/dist/esm/authorization/lifecycleRouting.js +62 -0
- package/dist/esm/authorization/service.js +43 -12
- package/dist/esm/authorization/vaultProxyUse.js +2 -6
- package/dist/esm/cloud-host.js +23 -25
- package/dist/esm/core/EmailOtpRecords.js +1 -217
- package/dist/esm/core/EmailOtpStores.js +0 -859
- package/dist/esm/core/IdentityStore.js +2 -426
- package/dist/esm/core/SessionService.js +7 -30
- package/dist/esm/core/ThresholdService/config.js +1 -9
- package/dist/esm/core/ThresholdService/index.js +0 -4
- package/dist/esm/core/ThresholdService/kv.js +1 -66
- package/dist/esm/core/ThresholdService/routerAb/ecdsaDerivationPoolFillHandlers.js +1 -13
- package/dist/esm/core/ThresholdService/routerAbNormalSigningPolicy.js +4 -21
- package/dist/esm/core/ThresholdService/stores/WalletSessionStore.js +0 -617
- package/dist/esm/core/ThresholdService/validation.js +2 -346
- package/dist/esm/core/WalletAuthMethodStore.js +2 -123
- package/dist/esm/core/WalletStore.js +6 -214
- package/dist/esm/core/WebAuthnAuthenticatorStore.js +0 -202
- package/dist/esm/core/WebAuthnCredentialBindingStore.js +2 -182
- package/dist/esm/core/WebAuthnLoginChallengeStore.js +0 -52
- package/dist/esm/core/WebAuthnSyncChallengeStore.js +0 -54
- package/dist/esm/core/authService/emailOtpConfig.js +1 -195
- package/dist/esm/core/authService/emailOtpEnrollment.js +0 -141
- package/dist/esm/core/authService/emailOtpSeal.js +0 -78
- package/dist/esm/core/authService/nearTransactions.js +3 -98
- package/dist/esm/core/authService/rateLimits.js +0 -87
- package/dist/esm/core/authService/thresholdEcdsaKeyInventory.js +2 -1
- package/dist/esm/core/authService/webauthn.js +14 -464
- package/dist/esm/core/authService/webauthnOidcHelpers.js +1 -24
- package/dist/esm/core/authService/webauthnVerificationOutcomes.js +5 -24
- package/dist/esm/core/authService/webauthnWalletBinding.js +0 -37
- package/dist/esm/core/config.js +1 -95
- package/dist/esm/core/d1EcdsaSignerRead.js +76 -0
- package/dist/esm/core/d1IdentityStore.js +17 -77
- package/dist/esm/core/d1TenantStore.js +1 -24
- package/dist/esm/core/d1WalletAuthMethodStore.js +2 -5
- package/dist/esm/core/d1WalletStore.js +15 -25
- package/dist/esm/core/deviceLinking/linkedDeviceBootstrap.js +13 -0
- package/dist/esm/core/deviceLinking/linkedDeviceEmailOtpGrant.js +1 -5
- package/dist/esm/core/deviceLinking/linkedDeviceSession.js +20 -14
- 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 +22 -10
- package/dist/esm/core/ecdsaMaterialReadSnapshot.js +85 -0
- package/dist/esm/core/emailOtpD1Statements.js +107 -94
- package/dist/esm/core/keyMaterialBrands.js +2 -12
- package/dist/esm/core/nearKeys.js +0 -1
- package/dist/esm/core/nearRelayerAccountProvisioning.js +8 -14
- package/dist/esm/core/passkeyCredentialClaims.js +8 -0
- package/dist/esm/core/routerAbSigning/RouterAbEcdsaPresignRuntime.js +2 -6
- package/dist/esm/core/routerAbSigning/RouterAbNormalSigningRuntime.js +2 -30
- package/dist/esm/core/signingLanes/WalletExecutionLaneProjection.js +3 -6
- package/dist/esm/core/signingMaterial/ordinaryInactiveSignerMaterialReservation.js +2 -5
- package/dist/esm/core/thresholdEcdsaChainTarget.js +2 -7
- package/dist/esm/hosted-wallet-gateway.js +68 -45
- package/dist/esm/index.js +6 -19
- package/dist/esm/localHostedWalletGatewayHandler.js +25 -0
- package/dist/esm/localIntendedMaterialAdmissionFault.js +176 -0
- package/dist/esm/localIntendedPresignCancellation.js +44 -0
- package/dist/esm/localRegistrationSetupAuthority.js +89 -0
- package/dist/esm/router/auth/authRequestValidation.js +8 -16
- 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 -16
- package/dist/esm/router/cloudflare/d1/auth/d1AuthorizationAssembly.js +87 -0
- 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/d1RouterApiAuthConfig.js +12 -2
- package/dist/esm/router/cloudflare/d1/auth/d1RouterApiAuthService.js +37 -308
- package/dist/esm/router/cloudflare/d1/auth/walletSessionCredentialReaders.js +76 -0
- package/dist/esm/router/cloudflare/d1/authorization/authorizedOperationStatements.js +52 -43
- package/dist/esm/router/cloudflare/d1/authorization/d1AuthorizationStore.js +217 -50
- package/dist/esm/router/cloudflare/d1/authorization/d1VaultProxyStore.js +8 -12
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceAuthorityInstallService.js +62 -21
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceEd25519ExportRootStore.js +6 -1
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceEmailOtpGrantStore.js +12 -2
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceEmailOtpTargetFactor.js +4 -4
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceOwnerAuthorizationProvider.js +1 -1
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceRequestProofNonceStore.js +3 -9
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceRouteService.js +2 -1
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceSessionStore.js +89 -7
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceTargetCredentialProvider.js +24 -15
- package/dist/esm/router/cloudflare/d1/deviceLinking/index.js +3 -3
- package/dist/esm/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoCapabilityPersistence.js +9 -6
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeIssuer.js +12 -56
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeService.js +17 -81
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeStore.js +1 -1
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeVerifier.js +0 -1
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpDeliveryRuntime.js +6 -25
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpEnrollmentStore.js +1 -1
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpGrantStore.js +1 -7
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRateLimitStore.js +19 -13
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRecords.js +12 -48
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRecoveryService.js +24 -86
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRegistrationEnrollmentFinalizer.js +9 -32
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpServerSealRuntime.js +5 -21
- package/dist/esm/router/cloudflare/d1/emailOtp/d1GoogleEmailOtpRegistrationAttemptStore.js +44 -12
- package/dist/esm/router/cloudflare/d1/emailOtp/d1GoogleEmailOtpRegistrationRecords.js +1 -49
- package/dist/esm/router/cloudflare/d1/emailOtp/d1GoogleEmailOtpSessionResolver.js +37 -136
- package/dist/esm/router/cloudflare/d1/emailOtp/d1GoogleRegistrationCompletion.js +85 -0
- package/dist/esm/router/cloudflare/d1/identity/d1IdentityRecords.js +0 -1
- package/dist/esm/router/cloudflare/d1/identity/d1IdentityService.js +9 -88
- package/dist/esm/router/cloudflare/d1/near/d1SponsoredNearAccount.js +242 -0
- package/dist/esm/router/cloudflare/d1/oidc/d1OidcBoundary.js +18 -92
- package/dist/esm/router/cloudflare/d1/oidc/d1OidcVerificationService.js +4 -55
- package/dist/esm/router/cloudflare/d1/oidc/googleOidcToken.js +41 -0
- package/dist/esm/router/cloudflare/d1/passkeyCustody/d1PasskeyCustodyRouteService.js +9 -15
- package/dist/esm/router/cloudflare/d1/passkeyCustody/d1WalletCustodyCommitStore.js +36 -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 +13 -10
- package/dist/esm/router/cloudflare/d1/registration/d1RegistrationCeremonyRecords.js +9 -14
- package/dist/esm/router/cloudflare/d1/registration/d1RegistrationCeremonyStore.js +25 -13
- package/dist/esm/router/cloudflare/d1/registration/d1RegistrationIntentService.js +7 -31
- package/dist/esm/router/cloudflare/d1/registration/d1RegistrationSetupSupport.js +74 -0
- package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationCommitStore.js +7 -1
- package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationService.js +101 -260
- package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationSetup.js +12 -56
- package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationSetupExecution.js +155 -0
- package/dist/esm/router/cloudflare/d1/registration/walletRegistrationEstablishedSessionIssuer.js +1 -3
- package/dist/esm/router/cloudflare/d1/registration/walletRegistrationSessionCommitReceipt.js +1 -4
- package/dist/esm/router/cloudflare/d1/signingAdmission/d1RouterAbNormalSigningAdmissionStore.js +131 -31
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAddSignerFinalizeRecord.js +68 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAddSignerService.js +7 -54
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthMethodService.js +9 -8
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorityStore.js +2 -142
- package/dist/esm/router/cloudflare/d1/webauthn/d1WebAuthnAuthService.js +55 -171
- package/dist/esm/router/cloudflare/d1/webauthn/d1WebAuthnRecords.js +10 -79
- package/dist/esm/router/cloudflare/d1/webauthn/d1WebAuthnStore.js +23 -7
- package/dist/esm/router/cloudflare/runtime/routerAbPrewarm.js +2 -2
- package/dist/esm/router/cloudflare/runtime/staticWalletConsoleBinding.js +6 -20
- package/dist/esm/router/cloudflare/runtime/tenantRootCreationGrant.js +2 -9
- package/dist/esm/router/cloudflare/runtime/walletConsoleOps.js +1 -0
- package/dist/esm/router/cloudflare/runtime/walletConsoleOpsClient.js +5 -0
- package/dist/esm/router/cloudflare/runtime/walletControlOps.js +2 -1
- package/dist/esm/router/cloudflare/runtime/walletGateway.js +1 -1
- package/dist/esm/router/cloudflare/runtime/walletRuntimeOps.js +16 -4
- package/dist/esm/router/cloudflare-adaptor.js +1 -2
- package/dist/esm/router/cloudflare.js +3390 -3437
- package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistration.js +11 -8
- package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationPartitionedStateStore.js +3 -2
- package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationPartitioning.js +6 -6
- package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationPersistence.js +5 -8
- package/dist/esm/router/domains/ed25519Yao/export/routerAbEd25519YaoExport.js +6 -6
- package/dist/esm/router/domains/ed25519Yao/export/routerAbEd25519YaoExportRequestScopedCloudflare.js +3 -0
- package/dist/esm/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecoveryRequestScopedCloudflare.js +8 -0
- 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/emailOtpRequestValidation.js +0 -1
- package/dist/esm/router/domains/emailOtp/emailOtpRouteHandlers.js +15 -62
- package/dist/esm/router/domains/passkeyCustody/passkeyCustodyEnvelopeRetrieval.js +2 -8
- package/dist/esm/router/domains/passkeyCustody/walletCustodyRegistrationCommit.js +2 -8
- 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/routerAbPrivateSigningWorker.js +5 -19
- package/dist/esm/router/domains/signingOperations/walletExecutionAdmission.js +3 -7
- package/dist/esm/router/domains/tenantRoot/tenantRootIdentityResolution.js +7 -13
- package/dist/esm/router/domains/walletRegistration/walletRegistrationReservation.js +70 -0
- package/dist/esm/router/domains/walletRegistration/walletRegistrationRoutes.js +10 -11
- package/dist/esm/router/domains/walletRegistration/walletRegistrationSetupPayload.js +2 -3
- package/dist/esm/router/domains/walletUnlock/walletUnlockRouteHandlers.js +55 -200
- package/dist/esm/router/express.js +858 -1145
- package/dist/esm/router/framework/http.js +7 -1
- package/dist/esm/router/framework/registrationSetupDispatch.js +14 -0
- package/dist/esm/router/framework/ror/normalize.js +0 -1
- package/dist/esm/router/framework/ror/options.js +0 -1
- package/dist/esm/router/framework/ror/provider.js +0 -1
- package/dist/esm/router/framework/ror/staticProvider.js +0 -1
- package/dist/esm/router/framework/routeDefinitions.js +1 -2
- package/dist/esm/router/framework/routerApiWebhooks.js +0 -1
- package/dist/esm/router/framework/runtimeSnapshotConsumer.js +8 -35
- package/dist/esm/router/ror.js +0 -1
- package/dist/esm/router/transport/fetch/createFetchRouter.js +3 -8
- package/dist/esm/router/transport/fetch/routes/auth.js +11 -41
- package/dist/esm/router/transport/fetch/routes/deviceLinking.js +36 -147
- package/dist/esm/router/transport/fetch/routes/deviceLinkingOwnerAuthorization.js +7 -23
- package/dist/esm/router/transport/fetch/routes/deviceLinkingResponses.js +130 -0
- package/dist/esm/router/transport/fetch/routes/ecdsaOperationStepUpFactor.js +171 -0
- package/dist/esm/router/transport/fetch/routes/passkeyCustody.js +1 -0
- package/dist/esm/router/transport/fetch/routes/sessions.js +1 -0
- package/dist/esm/router/transport/fetch/routes/syncAccount.js +15 -38
- package/dist/esm/router/transport/fetch/routes/thresholdEcdsa.js +46 -194
- package/dist/esm/router/transport/fetch/routes/walletExecutionLanePreflight.js +4 -1
- package/dist/esm/router/transport/fetch/routes/walletRegistration.js +3 -1
- package/dist/esm/router/transport/fetch/routes/webauthnAuthenticators.js +4 -16
- package/dist/esm/shared-ts/src/authorization/walletSessionIssuance.js +0 -1
- package/dist/esm/shared-ts/src/authorization/walletSignerActivationEquality.js +12 -0
- package/dist/esm/shared-ts/src/device-linking/authorityActivation.js +0 -2
- package/dist/esm/shared-ts/src/device-linking/committedSignerPackages.js +2 -5
- package/dist/esm/shared-ts/src/device-linking/contracts.js +16 -1
- package/dist/esm/shared-ts/src/device-linking/delegatedActivationPlan.js +1 -5
- package/dist/esm/shared-ts/src/device-linking/digests.js +1 -8
- 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/near/actions.js +0 -1
- package/dist/esm/shared-ts/src/near/nearClient.js +0 -2
- package/dist/esm/shared-ts/src/passkey-custody/primitives.js +5 -1
- package/dist/esm/shared-ts/src/signing-lanes/evmFamilySigningKeySlotId.js +1 -1
- package/dist/esm/shared-ts/src/signing-lanes/index.js +1 -6
- package/dist/esm/shared-ts/src/signing-lanes/ownerContinuity.js +5 -9
- package/dist/esm/shared-ts/src/signing-lanes/participantDigest.js +2 -81
- package/dist/esm/shared-ts/src/signing-lanes/participants.js +1 -219
- package/dist/esm/shared-ts/src/signing-lanes/recordParsers.js +0 -3
- 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 +2 -6
- package/dist/esm/shared-ts/src/threshold/ecdsaDerivationRoleLocalBootstrap.js +0 -1
- package/dist/esm/shared-ts/src/threshold/keyMaterialBrands.js +1 -22
- package/dist/esm/shared-ts/src/threshold/participants.js +0 -1
- package/dist/esm/shared-ts/src/threshold/signingRootScope.js +0 -1
- package/dist/esm/shared-ts/src/utils/addWalletAuthMethod.js +4 -13
- package/dist/esm/shared-ts/src/utils/canonicalPrimitives.js +1 -7
- package/dist/esm/shared-ts/src/utils/domainIds.js +1 -16
- package/dist/esm/shared-ts/src/utils/ecdsaCapabilityActivation.js +1 -11
- package/dist/esm/shared-ts/src/utils/ecdsaKeyFactsInventory.js +2 -5
- 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/errors.js +1 -19
- 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/near.js +1 -1
- package/dist/esm/shared-ts/src/utils/registrationEstablishedSession.js +1 -1
- package/dist/esm/shared-ts/src/utils/registrationIds.js +1 -5
- package/dist/esm/shared-ts/src/utils/registrationIntent.js +3 -13
- package/dist/esm/shared-ts/src/utils/registrationSetupOperation.js +8 -0
- package/dist/esm/shared-ts/src/utils/registrationSignerPlan.js +3 -6
- package/dist/esm/shared-ts/src/utils/routerAbEcdsaDerivation.js +1 -2
- 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/utils/validation.js +1 -5
- package/dist/esm/shared-ts/src/utils/walletAuthAuthority.js +0 -1
- package/dist/esm/shared-ts/src/utils/walletManagementProtocol.js +6 -0
- package/dist/esm/shared-ts/src/utils/wireSchema.js +2 -13
- package/dist/esm/shared-ts/src/wallet-recovery/backupAcknowledgement.js +6 -24
- package/dist/esm/shared-ts/src/wallet-recovery/recoveryCodeLocator.js +0 -1
- package/dist/esm/shared-ts/src/wallet-recovery/recoveryKeyId.js +5 -6
- package/dist/esm/shared-ts/src/wallet-recovery/walletRecoveryCommittedProjection.js +1 -4
- package/dist/esm/storage/d1Sql.js +1 -7
- package/dist/esm/threshold/session/signingSessionSeal/crypto/cipher.js +10 -33
- package/dist/esm/threshold/session/signingSessionSeal/guards/backends.js +1 -2
- package/dist/esm/threshold/session/signingSessionSeal/idempotencyBackends.js +3 -4
- package/dist/esm/threshold/session/signingSessionSeal/idempotencyRecords.js +3 -10
- package/dist/esm/threshold/session/signingSessionSeal/options.js +0 -1
- 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.js +0 -611
- package/dist/esm/wasm/near_signer/pkg/wasm_signer_worker_bg.wasm +0 -0
- package/dist/esm/wasm/shamir3pass_runtime/pkg/shamir3pass_runtime_bg.wasm +0 -0
- package/dist/types/shared-ts/src/authorization/capabilityKinds.d.ts +0 -4
- 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 +6 -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/evmFamilySigningKeySlotId.d.ts +0 -2
- package/dist/types/shared-ts/src/signing-lanes/execution.d.ts +11 -12
- package/dist/types/shared-ts/src/signing-lanes/ids.d.ts +3 -17
- package/dist/types/shared-ts/src/signing-lanes/index.d.ts +0 -4
- package/dist/types/shared-ts/src/signing-lanes/ownerContinuity.d.ts +0 -1
- package/dist/types/shared-ts/src/signing-lanes/participantDigest.d.ts +0 -18
- package/dist/types/shared-ts/src/signing-lanes/participants.d.ts +6 -35
- package/dist/types/shared-ts/src/signing-lanes/rotation.d.ts +6 -845
- 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/keyMaterialBrands.d.ts +0 -10
- package/dist/types/shared-ts/src/threshold/participants.d.ts +1 -1
- package/dist/types/shared-ts/src/threshold/signingRootScope.d.ts +1 -0
- package/dist/types/shared-ts/src/utils/addWalletAuthMethod.d.ts +1 -133
- package/dist/types/shared-ts/src/utils/addWalletAuthMethod.typecheck.d.ts +4 -18
- package/dist/types/shared-ts/src/utils/domainIds.d.ts +0 -12
- 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/errors.d.ts +0 -4
- 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/near.d.ts +0 -20
- package/dist/types/shared-ts/src/utils/nearRpcResults.d.ts +1 -0
- package/dist/types/shared-ts/src/utils/normalize.d.ts +0 -2
- package/dist/types/shared-ts/src/utils/registrationAuthMethodInput.d.ts +3 -8
- package/dist/types/shared-ts/src/utils/registrationSetupOperation.d.ts +3 -0
- 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/validation.d.ts +1 -3
- 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/walletCapabilityBindings.d.ts +0 -1
- package/dist/types/shared-ts/src/utils/walletManagementProtocol.d.ts +3 -0
- package/dist/types/shared-ts/src/utils/webauthnDeviceInfo.d.ts +4 -2
- package/dist/types/shared-ts/src/utils/wireSchema.d.ts +0 -2
- package/dist/types/shared-ts/src/wallet-recovery/backupAcknowledgement.d.ts +0 -1
- package/dist/types/shared-ts/src/wallet-recovery/recoveryCodeReservation.d.ts +1 -10
- package/dist/types/shared-ts/src/wallet-recovery/recoveryCodes.d.ts +1 -3
- package/dist/types/shared-ts/src/wallet-recovery/recoveryEnvelopes.d.ts +3 -16
- package/dist/types/shared-ts/src/wallet-recovery/recoveryKeyId.d.ts +5 -21
- 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/lifecycleRouting.d.ts +32 -0
- package/dist/types/wallet-server/src/authorization/lifecycleRouting.typecheck.d.ts +2 -0
- package/dist/types/wallet-server/src/authorization/recoveryRouting.d.ts +22 -0
- package/dist/types/wallet-server/src/authorization/recoveryRouting.typecheck.d.ts +2 -0
- package/dist/types/wallet-server/src/authorization/service.d.ts +27 -1
- package/dist/types/wallet-server/src/authorization/sessionRouting.d.ts +20 -0
- package/dist/types/wallet-server/src/authorization/sessionRouting.typecheck.d.ts +2 -0
- package/dist/types/wallet-server/src/cloud-host.d.ts +31 -9
- package/dist/types/wallet-server/src/core/EmailOtpRecords.d.ts +1 -22
- package/dist/types/wallet-server/src/core/EmailOtpStores.d.ts +1 -79
- package/dist/types/wallet-server/src/core/IdentityStore.d.ts +0 -10
- package/dist/types/wallet-server/src/core/RegistrationCeremonyStore.d.ts +0 -1
- package/dist/types/wallet-server/src/core/ThresholdService/config.d.ts +0 -2
- package/dist/types/wallet-server/src/core/ThresholdService/index.d.ts +1 -3
- package/dist/types/wallet-server/src/core/ThresholdService/kv.d.ts +0 -7
- package/dist/types/wallet-server/src/core/ThresholdService/routerAb/ecdsaDerivationPoolFillHandlers.d.ts +0 -3
- package/dist/types/wallet-server/src/core/ThresholdService/routerAbNormalSigningPolicy.d.ts +0 -1
- package/dist/types/wallet-server/src/core/ThresholdService/stores/WalletSessionStore.d.ts +6 -18
- package/dist/types/wallet-server/src/core/ThresholdService/validation.d.ts +0 -127
- package/dist/types/wallet-server/src/core/WalletAuthMethodStore.d.ts +1 -5
- package/dist/types/wallet-server/src/core/WalletStore.d.ts +0 -3
- package/dist/types/wallet-server/src/core/WebAuthnAuthenticatorStore.d.ts +8 -20
- package/dist/types/wallet-server/src/core/WebAuthnCredentialBindingStore.d.ts +1 -27
- package/dist/types/wallet-server/src/core/WebAuthnLoginChallengeStore.d.ts +2 -16
- package/dist/types/wallet-server/src/core/WebAuthnSyncChallengeStore.d.ts +22 -14
- package/dist/types/wallet-server/src/core/authService/emailOtpConfig.d.ts +0 -24
- package/dist/types/wallet-server/src/core/authService/emailOtpEnrollment.d.ts +1 -70
- package/dist/types/wallet-server/src/core/authService/emailOtpSeal.d.ts +1 -14
- package/dist/types/wallet-server/src/core/authService/githubOAuth.d.ts +2 -1
- package/dist/types/wallet-server/src/core/authService/nearTransactions.d.ts +1 -39
- package/dist/types/wallet-server/src/core/authService/rateLimits.d.ts +0 -17
- package/dist/types/wallet-server/src/core/authService/webauthn.d.ts +0 -125
- package/dist/types/wallet-server/src/core/authService/webauthnOidcHelpers.d.ts +0 -3
- package/dist/types/wallet-server/src/core/authService/webauthnVerificationOutcomes.d.ts +1 -1
- package/dist/types/wallet-server/src/core/authService/webauthnWalletBinding.d.ts +0 -12
- package/dist/types/wallet-server/src/core/config.d.ts +0 -10
- package/dist/types/wallet-server/src/core/d1EcdsaSignerRead.d.ts +39 -0
- package/dist/types/wallet-server/src/core/d1IdentityStore.d.ts +0 -2
- package/dist/types/wallet-server/src/core/d1TenantStore.d.ts +0 -7
- package/dist/types/wallet-server/src/core/d1WalletAuthMethodStore.d.ts +0 -1
- package/dist/types/wallet-server/src/core/d1WalletStore.d.ts +10 -0
- package/dist/types/wallet-server/src/core/deviceLinking/linkedDeviceBootstrap.d.ts +19 -0
- package/dist/types/wallet-server/src/core/deviceLinking/linkedDeviceSession.d.ts +8 -6
- package/dist/types/wallet-server/src/core/deviceLinking/linkedDeviceSessionRecord.d.ts +3 -4
- package/dist/types/wallet-server/src/core/deviceLinking/requestProof.d.ts +2 -5
- package/dist/types/wallet-server/src/core/ecdsaMaterialReadSnapshot.d.ts +19 -0
- package/dist/types/wallet-server/src/core/emailOtpD1Statements.d.ts +10 -7
- package/dist/types/wallet-server/src/core/keyMaterialBrands.d.ts +1 -5
- package/dist/types/wallet-server/src/core/nearRelayerAccountProvisioning.d.ts +0 -1
- package/dist/types/wallet-server/src/core/passkeyCredentialClaims.d.ts +9 -0
- package/dist/types/wallet-server/src/core/routerAbSigning/RouterAbEcdsaPresignRuntime.d.ts +0 -2
- package/dist/types/wallet-server/src/core/routerAbSigning/RouterAbNormalSigningRuntime.d.ts +3 -7
- 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/threeRouteRegistrationContracts.d.ts +1 -92
- package/dist/types/wallet-server/src/core/threeRouteRegistrationContracts.typecheck.d.ts +4 -52
- package/dist/types/wallet-server/src/core/thresholdEcdsaChainTarget.d.ts +3 -12
- package/dist/types/wallet-server/src/core/types.d.ts +2 -305
- package/dist/types/wallet-server/src/hosted-wallet-gateway.d.ts +15 -3
- package/dist/types/wallet-server/src/index.d.ts +8 -13
- 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/localRegistrationSetupAuthority.d.ts +13 -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/d1AuthorizationAssembly.d.ts +23 -0
- 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/d1RouterApiAuthConfig.d.ts +25 -3
- 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 +11 -2
- package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceAuthorityInstallService.d.ts +22 -3
- package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceEmailOtpGrantStore.d.ts +7 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceRequestProofNonceStore.d.ts +1 -10
- package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceRouteService.d.ts +4 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceSessionStore.d.ts +8 -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/deviceLinking/d1LinkedDeviceTargetPlanner.d.ts +1 -13
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeService.d.ts +2 -2
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeStore.d.ts +1 -1
- 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/d1EmailOtpGrantStore.d.ts +0 -2
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpRateLimitStore.d.ts +20 -11
- 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/emailOtp/d1GoogleEmailOtpRegistrationAttemptStore.d.ts +29 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1GoogleEmailOtpRegistrationRecords.d.ts +3 -16
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1GoogleEmailOtpSessionResolver.d.ts +7 -2
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1GoogleRegistrationCompletion.d.ts +23 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/identity/d1IdentityService.d.ts +0 -12
- package/dist/types/wallet-server/src/router/cloudflare/d1/near/d1SponsoredNearAccount.d.ts +24 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/near/d1SponsoredNearAccount.typecheck.d.ts +2 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/oidc/d1OidcVerificationService.d.ts +0 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/oidc/googleOidcToken.d.ts +4 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/passkeyCustody/d1PasskeyCustodyRouteService.d.ts +5 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/passkeyCustody/d1WalletCustodyCommitStore.d.ts +9 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationCeremonyRecordStore.d.ts +3 -7
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationCeremonyRecords.d.ts +10 -11
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationCeremonyStore.d.ts +3 -2
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationSetupSupport.d.ts +51 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationCommitStore.d.ts +3 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationService.d.ts +35 -50
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationSetup.d.ts +3 -30
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationSetupExecution.d.ts +11 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/signingAdmission/d1RouterAbNormalSigningAdmissionStore.d.ts +14 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAddSignerFinalizeRecord.d.ts +27 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAddSignerService.d.ts +1 -10
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthMethodService.d.ts +2 -2
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorityStore.d.ts +0 -4
- package/dist/types/wallet-server/src/router/cloudflare/d1/webauthn/d1WebAuthnAuthService.d.ts +3 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/webauthn/d1WebAuthnRecords.d.ts +8 -50
- package/dist/types/wallet-server/src/router/cloudflare/d1/webauthn/d1WebAuthnStore.d.ts +23 -10
- package/dist/types/wallet-server/src/router/cloudflare/d1/webauthn/d1WebAuthnStore.typecheck.d.ts +2 -0
- package/dist/types/wallet-server/src/router/cloudflare/runtime/cloudflare.types.d.ts +0 -2
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletConsoleOps.d.ts +9 -34
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletConsoleOpsClient.d.ts +2 -0
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletGateway.d.ts +1 -1
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRuntimeOps.d.ts +3 -0
- package/dist/types/wallet-server/src/router/cloudflare-adaptor.d.ts +0 -1
- package/dist/types/wallet-server/src/router/domains/ecdsa/thresholdEcdsaRequestValidation.d.ts +3 -15
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistration.d.ts +1 -1
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationPartitioning.d.ts +2 -2
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/export/routerAbEd25519YaoExport.d.ts +2 -2
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/export/routerAbEd25519YaoExport.typecheck.d.ts +2 -0
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/export/routerAbEd25519YaoExportRequestScopedCloudflare.d.ts +2 -0
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecoveryRequestScopedCloudflare.d.ts +2 -0
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/session/routerAbEd25519YaoWalletSession.d.ts +9 -50
- package/dist/types/wallet-server/src/router/domains/passkeyCustody/passkeyCustodyEnvelopeRetrieval.d.ts +0 -2
- package/dist/types/wallet-server/src/router/domains/passkeyCustody/walletCustodyRegistrationCommit.d.ts +0 -3
- 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 -33
- package/dist/types/wallet-server/src/router/domains/signingOperations/walletExecutionAdmission.d.ts +1 -2
- package/dist/types/wallet-server/src/router/domains/syncAccount/syncAccountRequestValidation.d.ts +2 -7
- package/dist/types/wallet-server/src/router/domains/walletRegistration/walletRegistrationInputs.d.ts +1 -0
- package/dist/types/wallet-server/src/router/domains/walletRegistration/walletRegistrationReservation.d.ts +51 -0
- package/dist/types/wallet-server/src/router/domains/walletRegistration/walletRegistrationRoutes.d.ts +2 -10
- package/dist/types/wallet-server/src/router/domains/walletRegistration/walletRegistrationSetupPayload.d.ts +2 -2
- package/dist/types/wallet-server/src/router/framework/apiCredentialPorts.d.ts +3 -1
- package/dist/types/wallet-server/src/router/framework/authServicePort.d.ts +39 -38
- package/dist/types/wallet-server/src/router/framework/googleLoginResolution.typecheck.d.ts +2 -0
- package/dist/types/wallet-server/src/router/framework/http.d.ts +1 -0
- package/dist/types/wallet-server/src/router/framework/registrationSetupDispatch.d.ts +13 -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/deviceLinking.d.ts +1 -1
- 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/deviceLinkingResponses.d.ts +17 -0
- package/dist/types/wallet-server/src/router/transport/fetch/routes/ecdsaOperationStepUpFactor.d.ts +37 -0
- 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/storage/d1Sql.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/migrations/d1-signer/0040_namespace_home_challenges.sql +16 -0
- package/migrations/d1-signer/0041_step_up_admission_expiry.sql +28 -0
- package/migrations/d1-signer/0042_deployment_resource_challenges.sql +4 -0
- package/migrations/d1-signer/0043_google_registration_candidate_claim.sql +2 -0
- package/migrations/d1-signer/0044_linked_device_bootstrap_imports.sql +6 -0
- package/migrations/d1-signer/0045_wallet_owned_capability_receipts.sql +29 -0
- package/migrations/d1-signer/0046_wallet_owned_signing_abuse.sql +41 -0
- package/migrations/d1-signer/0047_remove_unused_near_public_keys.sql +2 -0
- package/migrations/d1-signer/0048_operation_owner_scope.sql +45 -0
- package/package.json +2 -3
- package/src/README.md +11 -3
- package/dist/esm/core/AuthService.js +0 -2
- package/dist/esm/core/NearPublicKeyStore.js +0 -200
- package/dist/esm/core/ThresholdService/stores/CloudflareDurableObjectStore.js +0 -397
- package/dist/esm/core/ThresholdService/stores/KeyStore.js +0 -140
- package/dist/esm/core/ThresholdService/stores/SessionStore.js +0 -361
- package/dist/esm/core/ThresholdService/stores/StoreConfig.js +0 -13
- package/dist/esm/core/authService/AuthService.js +0 -594
- package/dist/esm/core/authService/bytes.js +0 -22
- package/dist/esm/core/authService/configValues.js +0 -15
- package/dist/esm/core/authService/emailOtpChallengeOperations.js +0 -126
- package/dist/esm/core/authService/emailOtpChallengeProof.js +0 -214
- package/dist/esm/core/authService/emailOtpChallengeVerification.js +0 -335
- package/dist/esm/core/authService/emailOtpChallenges.js +0 -260
- package/dist/esm/core/authService/emailOtpDelivery.js +0 -169
- package/dist/esm/core/authService/emailOtpGrant.js +0 -74
- package/dist/esm/core/authService/emailOtpRegistrationEnrollment.js +0 -175
- package/dist/esm/core/authService/emailOtpUnlock.js +0 -264
- package/dist/esm/core/authService/googleEmailOtpOperations.js +0 -141
- package/dist/esm/core/authService/googleEmailOtpRegistration.js +0 -674
- package/dist/esm/core/authService/identity.js +0 -57
- package/dist/esm/core/authService/identityOperations.js +0 -32
- package/dist/esm/core/authService/nearAccountOperations.js +0 -229
- package/dist/esm/core/authService/nearPublicKeyMetadata.js +0 -127
- package/dist/esm/core/authService/oidcVerification.js +0 -261
- package/dist/esm/core/authService/registrationThresholdHelpers.js +0 -30
- package/dist/esm/core/authService/runtime.js +0 -45
- package/dist/esm/core/authService/storeRegistry.js +0 -102
- package/dist/esm/core/authService/thresholdStoreSummary.js +0 -32
- package/dist/esm/core/authService/webauthnAuthority.js +0 -17
- package/dist/esm/core/defaultConfigsServer.js +0 -9
- package/dist/esm/core/hostedAccountIds.js +0 -225
- package/dist/esm/core/routerAbSigning/createRouterAbSigningRuntimes.js +0 -84
- package/dist/esm/core/signingLanes/LaneAggregateRevocationApplicationService.js +0 -86
- package/dist/esm/core/signingLanes/LaneEnrollmentActivation.js +0 -324
- package/dist/esm/core/signingLanes/LaneEnrollmentRevocation.js +0 -173
- package/dist/esm/core/signingLanes/LaneLifecycleApplicationService.js +0 -198
- package/dist/esm/core/signingLanes/ecdsaServerRetirement.js +0 -73
- package/dist/esm/core/signingLanes/ed25519ServerRetirement.js +0 -68
- package/dist/esm/core/signingLanes/signingWorkerLaneMaterialIdentity.js +0 -0
- package/dist/esm/core/storeBackends.js +0 -208
- package/dist/esm/core/utils.js +0 -14
- package/dist/esm/core/webAuthnStoreBackends.js +0 -198
- package/dist/esm/router/cloudflare/d1/near/d1NearPublicKeyStore.js +0 -56
- package/dist/esm/router/cloudflare/d1/signingLanes/d1EcdsaLanePrivateBindingResolver.js +0 -10
- package/dist/esm/router/cloudflare/d1/signingLanes/d1LaneAggregateRevocationApplicationService.js +0 -22
- package/dist/esm/router/cloudflare/d1/signingLanes/d1LaneEffectJournalStore.js +0 -166
- package/dist/esm/router/cloudflare/d1/signingLanes/d1LaneEnrollmentGateway.js +0 -38
- package/dist/esm/router/cloudflare/d1/signingLanes/d1LaneLifecycleApplicationService.js +0 -20
- package/dist/esm/router/cloudflare/d1/signingLanes/d1LaneLifecycleStore.js +0 -1459
- package/dist/esm/router/cloudflare/d1/signingLanes/d1LaneLockStore.js +0 -114
- package/dist/esm/router/cloudflare/d1/signingLanes/d1LaneProtocolCommitter.js +0 -16
- package/dist/esm/router/cloudflare/d1/signingLanes/d1LaneRecords.js +0 -171
- package/dist/esm/router/cloudflare/d1/signingLanes/index.js +0 -10
- package/dist/esm/router/cloudflare/durableObjects/thresholdStore.js +0 -404
- package/dist/esm/router/cloudflare/signingLanes/cloudflareLaneCurveExecution.js +0 -596
- package/dist/esm/router/cloudflare/signingLanes/cloudflareLaneProtocolCommitter.js +0 -273
- package/dist/esm/router/cloudflare/signingLanes/index.js +0 -4
- package/dist/esm/router/cloudflare/signingLanes/linkedDeviceEd25519CeremonyBinding.js +0 -32
- package/dist/esm/router/transport/fetch/routes/nearPublicKeys.js +0 -39
- package/dist/esm/shared-ts/src/signing-lanes/rotation.js +0 -8
- package/dist/esm/shared-ts/src/signing-lanes/rotationDigests.js +0 -358
- package/dist/esm/shared-ts/src/signing-lanes/rotationLifecycle.js +0 -313
- package/dist/esm/shared-ts/src/signing-lanes/rotationParsers.js +0 -532
- package/dist/esm/shared-ts/src/signing-lanes/rotationProtocolParsers.js +0 -323
- package/dist/esm/shared-ts/src/signing-lanes/rotationWireFields.js +0 -59
- package/dist/esm/wasm/router_ab_ecdsa_signing_worker/pkg/router_ab_ecdsa_signing_worker_bg.wasm +0 -0
- package/dist/types/shared-ts/src/signing-lanes/participantDigest.typecheck.d.ts +0 -2
- package/dist/types/shared-ts/src/signing-lanes/rotation.typecheck.d.ts +0 -2
- package/dist/types/shared-ts/src/signing-lanes/rotationDigests.d.ts +0 -13
- package/dist/types/shared-ts/src/signing-lanes/rotationLifecycle.d.ts +0 -78
- package/dist/types/shared-ts/src/signing-lanes/rotationParsers.d.ts +0 -27
- package/dist/types/shared-ts/src/signing-lanes/rotationProtocolParsers.d.ts +0 -6
- package/dist/types/shared-ts/src/signing-lanes/rotationWireFields.d.ts +0 -20
- package/dist/types/shared-ts/src/wallet-recovery/recoveryCodeAttempt.d.ts +0 -59
- package/dist/types/wallet-server/src/core/AuthService.d.ts +0 -3
- package/dist/types/wallet-server/src/core/NearPublicKeyStore.d.ts +0 -48
- package/dist/types/wallet-server/src/core/ThresholdService/stores/CloudflareDurableObjectStore.d.ts +0 -21
- package/dist/types/wallet-server/src/core/ThresholdService/stores/KeyStore.d.ts +0 -40
- package/dist/types/wallet-server/src/core/ThresholdService/stores/SessionStore.d.ts +0 -98
- package/dist/types/wallet-server/src/core/ThresholdService/stores/StoreConfig.d.ts +0 -4
- package/dist/types/wallet-server/src/core/ThresholdService/stores/ThresholdStoreConfig.typecheck.d.ts +0 -2
- package/dist/types/wallet-server/src/core/authService/AuthService.d.ts +0 -490
- package/dist/types/wallet-server/src/core/authService/bytes.d.ts +0 -4
- package/dist/types/wallet-server/src/core/authService/configValues.d.ts +0 -7
- package/dist/types/wallet-server/src/core/authService/emailOtpChallengeOperations.d.ts +0 -109
- package/dist/types/wallet-server/src/core/authService/emailOtpChallengeProof.d.ts +0 -169
- package/dist/types/wallet-server/src/core/authService/emailOtpChallengeVerification.d.ts +0 -47
- package/dist/types/wallet-server/src/core/authService/emailOtpChallenges.d.ts +0 -94
- package/dist/types/wallet-server/src/core/authService/emailOtpDelivery.d.ts +0 -66
- package/dist/types/wallet-server/src/core/authService/emailOtpGrant.d.ts +0 -43
- package/dist/types/wallet-server/src/core/authService/emailOtpRegistrationEnrollment.d.ts +0 -49
- package/dist/types/wallet-server/src/core/authService/emailOtpUnlock.d.ts +0 -71
- package/dist/types/wallet-server/src/core/authService/googleEmailOtpOperations.d.ts +0 -126
- package/dist/types/wallet-server/src/core/authService/googleEmailOtpRegistration.d.ts +0 -169
- package/dist/types/wallet-server/src/core/authService/identity.d.ts +0 -25
- package/dist/types/wallet-server/src/core/authService/identityOperations.d.ts +0 -19
- package/dist/types/wallet-server/src/core/authService/nearAccountOperations.d.ts +0 -55
- package/dist/types/wallet-server/src/core/authService/nearPublicKeyMetadata.d.ts +0 -44
- package/dist/types/wallet-server/src/core/authService/oidcVerification.d.ts +0 -66
- package/dist/types/wallet-server/src/core/authService/registrationThresholdHelpers.d.ts +0 -11
- package/dist/types/wallet-server/src/core/authService/runtime.d.ts +0 -20
- package/dist/types/wallet-server/src/core/authService/storeRegistry.d.ts +0 -53
- package/dist/types/wallet-server/src/core/authService/thresholdStoreSummary.d.ts +0 -3
- package/dist/types/wallet-server/src/core/authService/webauthnAuthority.d.ts +0 -5
- package/dist/types/wallet-server/src/core/defaultConfigsServer.d.ts +0 -5
- package/dist/types/wallet-server/src/core/hostedAccountIds.d.ts +0 -16
- package/dist/types/wallet-server/src/core/routerAbSigning/createRouterAbSigningRuntimes.d.ts +0 -16
- package/dist/types/wallet-server/src/core/signingLanes/LaneAggregateRevocationApplicationService.d.ts +0 -36
- package/dist/types/wallet-server/src/core/signingLanes/LaneEffectJournalStore.d.ts +0 -62
- package/dist/types/wallet-server/src/core/signingLanes/LaneEnrollmentActivation.d.ts +0 -13
- package/dist/types/wallet-server/src/core/signingLanes/LaneEnrollmentRevocation.d.ts +0 -24
- package/dist/types/wallet-server/src/core/signingLanes/LaneLifecycleApplicationService.d.ts +0 -141
- package/dist/types/wallet-server/src/core/signingLanes/LaneLifecycleStore.d.ts +0 -228
- package/dist/types/wallet-server/src/core/signingLanes/ecdsaServerRetirement.d.ts +0 -58
- package/dist/types/wallet-server/src/core/signingLanes/ed25519ServerRetirement.d.ts +0 -30
- package/dist/types/wallet-server/src/core/signingLanes/signingWorkerLaneMaterialIdentity.d.ts +0 -21
- package/dist/types/wallet-server/src/core/storeBackends.d.ts +0 -83
- package/dist/types/wallet-server/src/core/utils.d.ts +0 -3
- package/dist/types/wallet-server/src/core/webAuthnStoreBackends.d.ts +0 -96
- package/dist/types/wallet-server/src/router/cloudflare/d1/near/d1NearPublicKeyStore.d.ts +0 -29
- package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/d1EcdsaLanePrivateBindingResolver.d.ts +0 -4
- package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/d1LaneAggregateRevocationApplicationService.d.ts +0 -4
- package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/d1LaneEffectJournalStore.d.ts +0 -24
- package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/d1LaneEnrollmentGateway.d.ts +0 -20
- package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/d1LaneLifecycleApplicationService.d.ts +0 -13
- package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/d1LaneLifecycleStore.d.ts +0 -51
- package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/d1LaneLockStore.d.ts +0 -28
- package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/d1LaneProtocolCommitter.d.ts +0 -5
- package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/d1LaneRecords.d.ts +0 -107
- package/dist/types/wallet-server/src/router/cloudflare/d1/signingLanes/index.d.ts +0 -10
- package/dist/types/wallet-server/src/router/cloudflare/durableObjects/thresholdStore.d.ts +0 -18
- package/dist/types/wallet-server/src/router/cloudflare/signingLanes/cloudflareLaneCurveExecution.d.ts +0 -217
- package/dist/types/wallet-server/src/router/cloudflare/signingLanes/cloudflareLaneProtocolCommitter.d.ts +0 -73
- package/dist/types/wallet-server/src/router/cloudflare/signingLanes/index.d.ts +0 -4
- package/dist/types/wallet-server/src/router/cloudflare/signingLanes/linkedDeviceEd25519CeremonyBinding.d.ts +0 -6
- package/dist/types/wallet-server/src/router/transport/fetch/routes/nearPublicKeys.d.ts +0 -3
- /package/dist/esm/{core/signingLanes/LaneEffectJournalStore.js → authorization/recoveryRouting.js} +0 -0
- /package/dist/esm/{core/signingLanes/LaneLifecycleStore.js → authorization/sessionRouting.js} +0 -0
|
@@ -38,6 +38,15 @@ function normalizeLogger(logger) {
|
|
|
38
38
|
//#region src/router/framework/logger.ts
|
|
39
39
|
const coerceRouterLogger = normalizeLogger;
|
|
40
40
|
//#endregion
|
|
41
|
+
//#region ../shared-ts/src/utils/failure.ts
|
|
42
|
+
function failure(code, message) {
|
|
43
|
+
return {
|
|
44
|
+
ok: false,
|
|
45
|
+
code,
|
|
46
|
+
message
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
//#endregion
|
|
41
50
|
//#region src/core/SessionService.ts
|
|
42
51
|
function normalizeParsedCorsOrigin(url) {
|
|
43
52
|
const host = url.hostname.toLowerCase();
|
|
@@ -81,6 +90,21 @@ function buildCorsOrigins(...inputs) {
|
|
|
81
90
|
}
|
|
82
91
|
//#endregion
|
|
83
92
|
//#region ../shared-ts/src/device-linking/contracts.ts
|
|
93
|
+
function isLinkSessionTerminalFailureV1(state) {
|
|
94
|
+
switch (state.state) {
|
|
95
|
+
case "failed_before_commit":
|
|
96
|
+
case "cancelled":
|
|
97
|
+
case "expired": return true;
|
|
98
|
+
case "displaying_qr":
|
|
99
|
+
case "claimed":
|
|
100
|
+
case "awaiting_target_factor":
|
|
101
|
+
case "awaiting_source_contribution":
|
|
102
|
+
case "provisioning":
|
|
103
|
+
case "authority_pending_local_install":
|
|
104
|
+
case "active": return false;
|
|
105
|
+
default: return assertNeverLinkSessionStateV1(state);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
84
108
|
function assertNeverLinkSessionStateV1(value) {
|
|
85
109
|
throw new Error(`[LinkSessionStateV1] unsupported state: ${String(value)}`);
|
|
86
110
|
}
|
|
@@ -389,112 +413,6 @@ function toRorOriginOrNull(value) {
|
|
|
389
413
|
}
|
|
390
414
|
}
|
|
391
415
|
//#endregion
|
|
392
|
-
//#region ../shared-ts/src/utils/base58.ts
|
|
393
|
-
/**
|
|
394
|
-
* Encodes binary data to base58 string using Bitcoin's base58 alphabet.
|
|
395
|
-
*
|
|
396
|
-
* @param data - Binary data to encode (Uint8Array, ArrayBuffer, or number[])
|
|
397
|
-
* @returns Base58-encoded string
|
|
398
|
-
*/
|
|
399
|
-
const base58Encode = (data) => {
|
|
400
|
-
if (data instanceof ArrayBuffer) return bs58.encode(new Uint8Array(data));
|
|
401
|
-
if (Array.isArray(data)) return bs58.encode(new Uint8Array(data));
|
|
402
|
-
return bs58.encode(data);
|
|
403
|
-
};
|
|
404
|
-
/**
|
|
405
|
-
* Decodes a base58 string to binary data using Bitcoin's base58 alphabet.
|
|
406
|
-
* Returns a Uint8Array containing the decoded bytes.
|
|
407
|
-
*
|
|
408
|
-
* @param base58String - Base58-encoded string to decode
|
|
409
|
-
* @returns Uint8Array containing the decoded bytes
|
|
410
|
-
* @throws Error if input contains invalid base58 characters
|
|
411
|
-
*/
|
|
412
|
-
const base58Decode = (base58String) => {
|
|
413
|
-
return bs58.decode(base58String);
|
|
414
|
-
};
|
|
415
|
-
//#endregion
|
|
416
|
-
//#region ../shared-ts/src/utils/near.ts
|
|
417
|
-
/**
|
|
418
|
-
* NEAR-specific utility helpers.
|
|
419
|
-
*
|
|
420
|
-
* Keep chain-specific parsing and validation logic here so generic utility
|
|
421
|
-
* modules (`validation`, `errors`, `encoders`, etc.) stay chain-agnostic.
|
|
422
|
-
*/
|
|
423
|
-
/**
|
|
424
|
-
* Ensure a key string has the NEAR Ed25519 prefix (`ed25519:`).
|
|
425
|
-
*
|
|
426
|
-
* - Accepts either `ed25519:<base58>` or a bare `<base58>` string.
|
|
427
|
-
* - Canonicalizes `ED25519:` -> `ed25519:`.
|
|
428
|
-
* - If a different prefix is present (e.g. `secp256k1:`), returns the input unchanged.
|
|
429
|
-
*/
|
|
430
|
-
function ensureEd25519Prefix(value) {
|
|
431
|
-
const raw = String(value ?? "").trim();
|
|
432
|
-
if (!raw) return "";
|
|
433
|
-
if (/^[a-z0-9_]+:/i.test(raw)) {
|
|
434
|
-
if (/^ed25519:/i.test(raw)) return `ed25519:${raw.replace(/^ed25519:/i, "")}`;
|
|
435
|
-
return raw;
|
|
436
|
-
}
|
|
437
|
-
return `ed25519:${raw}`;
|
|
438
|
-
}
|
|
439
|
-
/**
|
|
440
|
-
* Lightweight NEAR account ID validation used by server-side helpers.
|
|
441
|
-
* - length: 2..64
|
|
442
|
-
* - chars: lowercase letters, digits, `_`, `.`, `-`
|
|
443
|
-
*/
|
|
444
|
-
function isValidAccountId(accountId) {
|
|
445
|
-
if (typeof accountId !== "string") return false;
|
|
446
|
-
if (!accountId || accountId.length < 2 || accountId.length > 64) return false;
|
|
447
|
-
return /^[a-z0-9_.-]+$/.test(accountId);
|
|
448
|
-
}
|
|
449
|
-
function isImplicitNearAccountId(value) {
|
|
450
|
-
return typeof value === "string" && /^[0-9a-f]{64}$/.test(value);
|
|
451
|
-
}
|
|
452
|
-
function parseImplicitNearAccountId(raw) {
|
|
453
|
-
const value = typeof raw === "string" ? raw.trim() : "";
|
|
454
|
-
if (!value) return {
|
|
455
|
-
ok: false,
|
|
456
|
-
code: "missing",
|
|
457
|
-
message: "implicit NEAR account ID is required"
|
|
458
|
-
};
|
|
459
|
-
if (!isImplicitNearAccountId(value)) return {
|
|
460
|
-
ok: false,
|
|
461
|
-
code: "invalid",
|
|
462
|
-
message: "implicit NEAR account ID must be 64 lowercase hex characters"
|
|
463
|
-
};
|
|
464
|
-
return {
|
|
465
|
-
ok: true,
|
|
466
|
-
value
|
|
467
|
-
};
|
|
468
|
-
}
|
|
469
|
-
function parseNamedNearAccountId(raw) {
|
|
470
|
-
const value = typeof raw === "string" ? raw.trim() : "";
|
|
471
|
-
if (!value) return {
|
|
472
|
-
ok: false,
|
|
473
|
-
code: "missing",
|
|
474
|
-
message: "named NEAR account ID is required"
|
|
475
|
-
};
|
|
476
|
-
if (isImplicitNearAccountId(value) || !isValidAccountId(value) || !value.includes(".")) return {
|
|
477
|
-
ok: false,
|
|
478
|
-
code: "invalid",
|
|
479
|
-
message: "named NEAR account ID must be a valid named account containing a dot"
|
|
480
|
-
};
|
|
481
|
-
return {
|
|
482
|
-
ok: true,
|
|
483
|
-
value
|
|
484
|
-
};
|
|
485
|
-
}
|
|
486
|
-
function bytesToLowerHex(bytes) {
|
|
487
|
-
return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
488
|
-
}
|
|
489
|
-
function deriveImplicitNearAccountIdFromEd25519PublicKey(publicKey) {
|
|
490
|
-
const normalized = ensureEd25519Prefix(publicKey);
|
|
491
|
-
const encoded = normalized.startsWith("ed25519:") ? normalized.slice(8) : "";
|
|
492
|
-
if (!encoded) throw new Error("Ed25519 public key is required");
|
|
493
|
-
const decoded = base58Decode(encoded);
|
|
494
|
-
if (decoded.length !== 32) throw new Error("Ed25519 public key must decode to 32 bytes");
|
|
495
|
-
return bytesToLowerHex(decoded);
|
|
496
|
-
}
|
|
497
|
-
//#endregion
|
|
498
416
|
//#region ../shared-ts/src/utils/validation.ts
|
|
499
417
|
function requireTrimmedString(value, label, message = "is required") {
|
|
500
418
|
const parsed = normalizeOptionalTrimmedString(value);
|
|
@@ -984,6 +902,10 @@ function requireCanonicalBase64Url(value, label) {
|
|
|
984
902
|
if (base64UrlEncode(decoded) !== value) throw new Error(`${label} must be canonical base64url`);
|
|
985
903
|
return decoded;
|
|
986
904
|
}
|
|
905
|
+
function requireParsed$2(result, label) {
|
|
906
|
+
if (result.ok) return result.value;
|
|
907
|
+
throw new Error(`${label} ${result.error.message}`);
|
|
908
|
+
}
|
|
987
909
|
function parseDigestField$2(value, label) {
|
|
988
910
|
try {
|
|
989
911
|
return parseDigestB64u(value);
|
|
@@ -1204,11 +1126,11 @@ function parseLinkedDeviceEd25519ExportRootRecipientV1(raw) {
|
|
|
1204
1126
|
requireTransferAlg(record.transferAlg, "LinkedDeviceEd25519ExportRootRecipientV1.transferAlg");
|
|
1205
1127
|
return {
|
|
1206
1128
|
kind: "linked_device_ed25519_export_root_recipient_v1",
|
|
1207
|
-
linkSessionId:
|
|
1208
|
-
walletId:
|
|
1209
|
-
walletKeyId:
|
|
1210
|
-
enrollmentId:
|
|
1211
|
-
deviceId:
|
|
1129
|
+
linkSessionId: requireParsed$2(parseLinkDeviceSessionId(record.linkSessionId), "LinkedDeviceEd25519ExportRootRecipientV1.linkSessionId"),
|
|
1130
|
+
walletId: requireParsed$2(parseWalletId(record.walletId), "walletId"),
|
|
1131
|
+
walletKeyId: requireParsed$2(parseWalletKeyId(record.walletKeyId), "walletKeyId"),
|
|
1132
|
+
enrollmentId: requireParsed$2(parseLinkedDeviceEnrollmentId(record.enrollmentId), "enrollmentId"),
|
|
1133
|
+
deviceId: requireParsed$2(parseLinkedDeviceId(record.deviceId), "deviceId"),
|
|
1212
1134
|
transferAlg: LINKED_DEVICE_ED25519_EXPORT_ROOT_TRANSFER_ALG_V1,
|
|
1213
1135
|
applicationBindingDigestB64u: parseDigestField$2(record.applicationBindingDigestB64u, "applicationBindingDigestB64u"),
|
|
1214
1136
|
registeredPublicKeyB64u: parseEd25519PublicKeyB64u(record.registeredPublicKeyB64u, "registeredPublicKeyB64u"),
|
|
@@ -1227,11 +1149,11 @@ function parseLinkedDeviceEd25519ExportRootPackageV1(raw) {
|
|
|
1227
1149
|
if (recipientPublicKeyB64u === ephemeralPublicKeyB64u) throw new Error("ephemeralPublicKeyB64u repeats the recipient key");
|
|
1228
1150
|
return {
|
|
1229
1151
|
kind: "linked_device_ed25519_export_root_package_v1",
|
|
1230
|
-
linkSessionId:
|
|
1231
|
-
walletId:
|
|
1232
|
-
walletKeyId:
|
|
1233
|
-
enrollmentId:
|
|
1234
|
-
deviceId:
|
|
1152
|
+
linkSessionId: requireParsed$2(parseLinkDeviceSessionId(record.linkSessionId), "linkSessionId"),
|
|
1153
|
+
walletId: requireParsed$2(parseWalletId(record.walletId), "walletId"),
|
|
1154
|
+
walletKeyId: requireParsed$2(parseWalletKeyId(record.walletKeyId), "walletKeyId"),
|
|
1155
|
+
enrollmentId: requireParsed$2(parseLinkedDeviceEnrollmentId(record.enrollmentId), "enrollmentId"),
|
|
1156
|
+
deviceId: requireParsed$2(parseLinkedDeviceId(record.deviceId), "deviceId"),
|
|
1235
1157
|
transferAlg: LINKED_DEVICE_ED25519_EXPORT_ROOT_TRANSFER_ALG_V1,
|
|
1236
1158
|
applicationBindingDigestB64u: parseDigestField$2(record.applicationBindingDigestB64u, "applicationBindingDigestB64u"),
|
|
1237
1159
|
registeredPublicKeyB64u: parseEd25519PublicKeyB64u(record.registeredPublicKeyB64u, "registeredPublicKeyB64u"),
|
|
@@ -1251,7 +1173,7 @@ function parseLinkedDeviceEd25519ExportRootSubmissionV1(raw) {
|
|
|
1251
1173
|
if (record.kind !== "linked_device_ed25519_export_root_submission_v1") throw new Error("LinkedDeviceEd25519ExportRootSubmissionV1.kind is invalid");
|
|
1252
1174
|
return {
|
|
1253
1175
|
kind: "linked_device_ed25519_export_root_submission_v1",
|
|
1254
|
-
linkSessionId:
|
|
1176
|
+
linkSessionId: requireParsed$2(parseLinkDeviceSessionId(record.linkSessionId), "linkSessionId"),
|
|
1255
1177
|
package: parseLinkedDeviceEd25519ExportRootPackageV1(record.package)
|
|
1256
1178
|
};
|
|
1257
1179
|
}
|
|
@@ -1279,10 +1201,6 @@ function parseUnixMs(value, label) {
|
|
|
1279
1201
|
if (typeof value !== "number" || !Number.isSafeInteger(value) || value <= 0) throw new Error(`${label} must be a positive unix-millisecond timestamp`);
|
|
1280
1202
|
return value;
|
|
1281
1203
|
}
|
|
1282
|
-
function parseRequired(parsed, label) {
|
|
1283
|
-
if (!parsed.ok) throw new Error(`${label} ${parsed.error.message}`);
|
|
1284
|
-
return parsed.value;
|
|
1285
|
-
}
|
|
1286
1204
|
//#endregion
|
|
1287
1205
|
//#region ../shared-ts/src/device-linking/delegatedActivationPlan.ts
|
|
1288
1206
|
const MANIFEST_FIELDS = [
|
|
@@ -1406,10 +1324,6 @@ function exactRecord$2(raw, fields, label) {
|
|
|
1406
1324
|
for (const field of fields) if (!(field in record)) throw new Error(`${label}.${field} is required`);
|
|
1407
1325
|
return record;
|
|
1408
1326
|
}
|
|
1409
|
-
function requireParsed$2(parsed, label) {
|
|
1410
|
-
if (!parsed.ok) throw new Error(`${label} ${parsed.error.message}`);
|
|
1411
|
-
return parsed.value;
|
|
1412
|
-
}
|
|
1413
1327
|
//#endregion
|
|
1414
1328
|
//#region ../shared-ts/src/utils/addAuthMethodRegistration.ts
|
|
1415
1329
|
/**
|
|
@@ -3874,7 +3788,7 @@ function parseLinkedDeviceEd25519SourcePreservingReservationV1(raw) {
|
|
|
3874
3788
|
const participantIds = parseRouterAbEd25519YaoParticipantIdsV1(record.participant_ids);
|
|
3875
3789
|
const deriverA = parseEd25519ClientPackage(record.deriver_a_client_package, "deriver_a");
|
|
3876
3790
|
const deriverB = parseEd25519ClientPackage(record.deriver_b_client_package, "deriver_b");
|
|
3877
|
-
if (!
|
|
3791
|
+
if (!sameRouterAbEd25519YaoByteSequence(activationReceipt.transcript, deriverA.transcript) || !sameRouterAbEd25519YaoByteSequence(activationReceipt.transcript, deriverB.transcript)) throw new Error("linked-device Ed25519 reservation packages have mismatched transcripts");
|
|
3878
3792
|
return {
|
|
3879
3793
|
state: "inactive",
|
|
3880
3794
|
reservationId: requireText(record.reservation_id, "reservation_id"),
|
|
@@ -4033,10 +3947,10 @@ function parseEd25519Contribution(record) {
|
|
|
4033
3947
|
if (!sameEdStableIdentity(sourceBinding, targetBinding)) throw new Error("linked-device Ed25519 source contribution stable identity differs");
|
|
4034
3948
|
if (!mpcMaterialActivationRefsEqual(routerAbMpcMaterialActivationRefFromWire(activationReceipt.material_activation), targetMaterialActivation)) throw new Error("linked-device Ed25519 source contribution receipt activation differs");
|
|
4035
3949
|
const sourceRegisteredPublicKeyB64u = parseEd25519PublicKeyB64u(record.sourceRegisteredPublicKeyB64u, "sourceRegisteredPublicKeyB64u");
|
|
4036
|
-
if (!
|
|
3950
|
+
if (!sameRouterAbEd25519YaoByteSequence(activationReceipt.registered_public_key, Array.from(base64UrlDecode(sourceRegisteredPublicKeyB64u)))) throw new Error("linked-device Ed25519 source contribution receipt public key differs");
|
|
4037
3951
|
const deriverA = parseEd25519ClientPackage(record.deriver_a_client_package, "deriver_a");
|
|
4038
3952
|
const deriverB = parseEd25519ClientPackage(record.deriver_b_client_package, "deriver_b");
|
|
4039
|
-
if (!
|
|
3953
|
+
if (!sameRouterAbEd25519YaoByteSequence(activationReceipt.transcript, deriverA.transcript) || !sameRouterAbEd25519YaoByteSequence(activationReceipt.transcript, deriverB.transcript)) throw new Error("linked-device Ed25519 source contribution package transcript differs");
|
|
4040
3954
|
if (sourceBinding.material_activation.activation_id === targetMaterialActivation.activationId) throw new Error("linked-device Ed25519 source contribution reuses the source activation");
|
|
4041
3955
|
return {
|
|
4042
3956
|
kind: "linked_device_ed25519_source_contribution_v1",
|
|
@@ -4316,9 +4230,6 @@ function parseFixedBase64(raw, byteLength, label) {
|
|
|
4316
4230
|
if (decoded.length !== byteLength || base64UrlEncode(decoded) !== raw) throw new Error(`${label} must decode to ${byteLength} bytes`);
|
|
4317
4231
|
return raw;
|
|
4318
4232
|
}
|
|
4319
|
-
function sameBytes(left, right) {
|
|
4320
|
-
return left.length === right.length && left.every((value, index) => value === right[index]);
|
|
4321
|
-
}
|
|
4322
4233
|
function requireText(raw, label) {
|
|
4323
4234
|
if (typeof raw !== "string" || raw.length === 0 || raw.trim() !== raw || [...raw].some((character) => {
|
|
4324
4235
|
const code = character.charCodeAt(0);
|
|
@@ -5414,11 +5325,15 @@ function createRouterAbTraceContextV1() {
|
|
|
5414
5325
|
};
|
|
5415
5326
|
}
|
|
5416
5327
|
//#endregion
|
|
5328
|
+
//#region ../shared-ts/src/utils/walletManagementProtocol.ts
|
|
5329
|
+
const WALLET_MANAGEMENT_PROTOCOL_HEADER = "X-Seams-Wallet-Protocol";
|
|
5330
|
+
//#endregion
|
|
5417
5331
|
//#region src/router/framework/http.ts
|
|
5418
5332
|
const CORS_ALLOW_METHODS = "GET,POST,PUT,PATCH,DELETE,OPTIONS";
|
|
5419
5333
|
const CORS_PREFLIGHT_MAX_AGE_SECONDS = 600;
|
|
5420
5334
|
const CORS_ALLOW_HEADERS = [
|
|
5421
5335
|
"Content-Type",
|
|
5336
|
+
WALLET_MANAGEMENT_PROTOCOL_HEADER,
|
|
5422
5337
|
"Authorization",
|
|
5423
5338
|
"X-Seams-Benchmark-Diagnostics",
|
|
5424
5339
|
LINKED_DEVICE_REQUEST_PROOF_HEADER_V1,
|
|
@@ -5441,6 +5356,9 @@ function json$1(body, init, extraHeaders) {
|
|
|
5441
5356
|
headers
|
|
5442
5357
|
});
|
|
5443
5358
|
}
|
|
5359
|
+
function jsonFailure(status, code, message) {
|
|
5360
|
+
return json$1(failure(code, message), { status });
|
|
5361
|
+
}
|
|
5444
5362
|
function withCors(headers, opts, request) {
|
|
5445
5363
|
const pathname = request ? new URL(request.url).pathname : "";
|
|
5446
5364
|
if (pathname === "/healthz" || pathname === "/readyz") {
|
|
@@ -5479,6 +5397,13 @@ async function readJson(request) {
|
|
|
5479
5397
|
return null;
|
|
5480
5398
|
}
|
|
5481
5399
|
}
|
|
5400
|
+
function headersToRecord(headers) {
|
|
5401
|
+
const out = {};
|
|
5402
|
+
headers.forEach((v, k) => {
|
|
5403
|
+
out[k] = v;
|
|
5404
|
+
});
|
|
5405
|
+
return out;
|
|
5406
|
+
}
|
|
5482
5407
|
//#endregion
|
|
5483
5408
|
//#region src/router/transport/fetch/routes/health.ts
|
|
5484
5409
|
async function handleHealth(ctx) {
|
|
@@ -5517,6 +5442,11 @@ async function handleReady(ctx) {
|
|
|
5517
5442
|
}
|
|
5518
5443
|
}
|
|
5519
5444
|
//#endregion
|
|
5445
|
+
//#region ../shared-ts/src/utils/registrationSetupOperation.ts
|
|
5446
|
+
function parseRegistrationSetupOperationId(value) {
|
|
5447
|
+
return typeof value === "string" && /^wreg_[A-Za-z0-9_-]{43}$/u.test(value) ? value : null;
|
|
5448
|
+
}
|
|
5449
|
+
//#endregion
|
|
5520
5450
|
//#region src/router/auth/routerApiKeyAuth.ts
|
|
5521
5451
|
function readHeader(headers, name) {
|
|
5522
5452
|
if (headers instanceof Headers) return String(headers.get(name) || "").trim();
|
|
@@ -5611,6 +5541,12 @@ async function resolvePublishableKeyApiCredentialAuth(input) {
|
|
|
5611
5541
|
};
|
|
5612
5542
|
}
|
|
5613
5543
|
//#endregion
|
|
5544
|
+
//#region ../shared-ts/src/utils/thresholdEcdsaChainTarget.ts
|
|
5545
|
+
function thresholdEcdsaChainTargetKey(target) {
|
|
5546
|
+
if (target.kind === "evm") return `evm:eip155:${target.chainId}`;
|
|
5547
|
+
return `tempo:${target.chainId}`;
|
|
5548
|
+
}
|
|
5549
|
+
//#endregion
|
|
5614
5550
|
//#region src/core/thresholdEcdsaChainTarget.ts
|
|
5615
5551
|
function positiveSafeInteger(value) {
|
|
5616
5552
|
return typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? value : null;
|
|
@@ -5671,11 +5607,7 @@ function walletSessionFailureStatus(code) {
|
|
|
5671
5607
|
}
|
|
5672
5608
|
}
|
|
5673
5609
|
function walletSessionFailure(code) {
|
|
5674
|
-
return
|
|
5675
|
-
ok: false,
|
|
5676
|
-
code,
|
|
5677
|
-
message: walletSessionFailureMessage(code)
|
|
5678
|
-
};
|
|
5610
|
+
return failure(code, walletSessionFailureMessage(code));
|
|
5679
5611
|
}
|
|
5680
5612
|
//#endregion
|
|
5681
5613
|
//#region ../shared-ts/src/signing-lanes/participants.ts
|
|
@@ -5715,22 +5647,6 @@ function parseLaneParticipantBindingDigestB64u(raw) {
|
|
|
5715
5647
|
return parseDigest(raw, "participantBindingDigestB64u", brandParticipantDigest);
|
|
5716
5648
|
}
|
|
5717
5649
|
//#endregion
|
|
5718
|
-
//#region ../shared-ts/src/utils/registrationIds.ts
|
|
5719
|
-
function walletIdFromString(value) {
|
|
5720
|
-
const parsed = parseWalletId(value);
|
|
5721
|
-
if (!parsed.ok) throw new Error(parsed.error.message);
|
|
5722
|
-
return parsed.value;
|
|
5723
|
-
}
|
|
5724
|
-
function nearEd25519SigningKeyIdFromString(value) {
|
|
5725
|
-
const normalized = String(value || "").trim();
|
|
5726
|
-
if (!normalized) throw new Error("nearEd25519SigningKeyId is required");
|
|
5727
|
-
return normalized;
|
|
5728
|
-
}
|
|
5729
|
-
function parseNearEd25519SigningKeyId(value) {
|
|
5730
|
-
if (typeof value !== "string") throw new Error("nearEd25519SigningKeyId must be a string");
|
|
5731
|
-
return nearEd25519SigningKeyIdFromString(value);
|
|
5732
|
-
}
|
|
5733
|
-
//#endregion
|
|
5734
5650
|
//#region ../shared-ts/src/signing-lanes/participantDigest.ts
|
|
5735
5651
|
function u32(value) {
|
|
5736
5652
|
if (!Number.isInteger(value) || value < 0 || value > 4294967295) throw new Error("canonical u32 must be an integer between 0 and 4294967295");
|
|
@@ -5761,6 +5677,17 @@ function encodeLaneCanonicalU64V1(value) {
|
|
|
5761
5677
|
return output;
|
|
5762
5678
|
}
|
|
5763
5679
|
//#endregion
|
|
5680
|
+
//#region ../shared-ts/src/signing-lanes/execution.ts
|
|
5681
|
+
function buildPreparedOwnerWalletExecution(input) {
|
|
5682
|
+
return {
|
|
5683
|
+
kind: "prepared_owner_wallet_execution",
|
|
5684
|
+
laneKind: input.lane.laneKind,
|
|
5685
|
+
authorization: input.authorization,
|
|
5686
|
+
materialActivation: input.materialActivation,
|
|
5687
|
+
lane: input.lane
|
|
5688
|
+
};
|
|
5689
|
+
}
|
|
5690
|
+
//#endregion
|
|
5764
5691
|
//#region ../shared-ts/src/signing-lanes/ownerContinuity.ts
|
|
5765
5692
|
const OWNER_LANE_PARTICIPANT_BINDING_DOMAIN_V1 = "seams/rotatable-signing-lanes/owner-lane-participant-continuity/v1";
|
|
5766
5693
|
const OWNER_LANE_PARTICIPANT_CONTINUITY_FIELDS = [
|
|
@@ -5771,10 +5698,6 @@ const OWNER_LANE_PARTICIPANT_CONTINUITY_FIELDS = [
|
|
|
5771
5698
|
"custodyKeyManifestDigestB64u",
|
|
5772
5699
|
"sourceIdentityDigestB64u"
|
|
5773
5700
|
];
|
|
5774
|
-
function requireResult(result, label) {
|
|
5775
|
-
if (result.ok) return result.value;
|
|
5776
|
-
throw new Error(`${label} ${result.error.message}`);
|
|
5777
|
-
}
|
|
5778
5701
|
/** Parse the owner signer identity without widening it into a generic string. */
|
|
5779
5702
|
function parseWalletSignerId(raw, label = "walletSignerId") {
|
|
5780
5703
|
if (typeof raw !== "string") throw new Error(`${label} must be a string`);
|
|
@@ -5800,7 +5723,7 @@ function buildOwnerLaneParticipantContinuityV1(args) {
|
|
|
5800
5723
|
kind: "owner_lane_participant_continuity_v1",
|
|
5801
5724
|
signerId: parseWalletSignerId(args.signerId),
|
|
5802
5725
|
participantIds,
|
|
5803
|
-
signingWorkerId:
|
|
5726
|
+
signingWorkerId: requireParsed$2(parseMpcSigningWorkerRef(args.signingWorkerId), "signingWorkerId"),
|
|
5804
5727
|
custodyKeyManifestDigestB64u: parseDigestField$2(args.custodyKeyManifestDigestB64u, "custodyKeyManifestDigestB64u"),
|
|
5805
5728
|
sourceIdentityDigestB64u: parseDigestField$2(args.sourceIdentityDigestB64u, "sourceIdentityDigestB64u")
|
|
5806
5729
|
};
|
|
@@ -5812,7 +5735,7 @@ function parseOwnerLaneParticipantContinuityV1(raw, label = "ownerParticipantCon
|
|
|
5812
5735
|
return buildOwnerLaneParticipantContinuityV1({
|
|
5813
5736
|
signerId: parseWalletSignerId(record.signerId, `${label}.signerId`),
|
|
5814
5737
|
participantIds: parseParticipantIds$1(record.participantIds, `${label}.participantIds`),
|
|
5815
|
-
signingWorkerId:
|
|
5738
|
+
signingWorkerId: requireParsed$2(parseMpcSigningWorkerRef(record.signingWorkerId), `${label}.signingWorkerId`),
|
|
5816
5739
|
custodyKeyManifestDigestB64u: parseDigestField$2(record.custodyKeyManifestDigestB64u, `${label}.custodyKeyManifestDigestB64u`),
|
|
5817
5740
|
sourceIdentityDigestB64u: parseDigestField$2(record.sourceIdentityDigestB64u, `${label}.sourceIdentityDigestB64u`)
|
|
5818
5741
|
});
|
|
@@ -5830,19 +5753,7 @@ function ownerLaneParticipantContinuityCanonicalBytesV1(input) {
|
|
|
5830
5753
|
]);
|
|
5831
5754
|
}
|
|
5832
5755
|
async function computeOwnerLaneParticipantBindingDigestV1(input) {
|
|
5833
|
-
return
|
|
5834
|
-
}
|
|
5835
|
-
new TextEncoder();
|
|
5836
|
-
//#endregion
|
|
5837
|
-
//#region ../shared-ts/src/signing-lanes/execution.ts
|
|
5838
|
-
function buildPreparedOwnerWalletExecution(input) {
|
|
5839
|
-
return {
|
|
5840
|
-
kind: "prepared_owner_wallet_execution",
|
|
5841
|
-
laneKind: input.lane.laneKind,
|
|
5842
|
-
authorization: input.authorization,
|
|
5843
|
-
materialActivation: input.materialActivation,
|
|
5844
|
-
lane: input.lane
|
|
5845
|
-
};
|
|
5756
|
+
return requireParsed$2(parseLaneParticipantBindingDigestB64u(base64UrlEncode(await sha256Bytes(ownerLaneParticipantContinuityCanonicalBytesV1(input)))), "owner participant digest");
|
|
5846
5757
|
}
|
|
5847
5758
|
//#endregion
|
|
5848
5759
|
//#region ../shared-ts/src/authorization/operationFingerprint.ts
|
|
@@ -5896,6 +5807,30 @@ function parseSigningOperationFingerprintDigest(value) {
|
|
|
5896
5807
|
return parseDigestB64u(value.slice(7));
|
|
5897
5808
|
}
|
|
5898
5809
|
//#endregion
|
|
5810
|
+
//#region ../shared-ts/src/utils/base58.ts
|
|
5811
|
+
/**
|
|
5812
|
+
* Encodes binary data to base58 string using Bitcoin's base58 alphabet.
|
|
5813
|
+
*
|
|
5814
|
+
* @param data - Binary data to encode (Uint8Array, ArrayBuffer, or number[])
|
|
5815
|
+
* @returns Base58-encoded string
|
|
5816
|
+
*/
|
|
5817
|
+
const base58Encode = (data) => {
|
|
5818
|
+
if (data instanceof ArrayBuffer) return bs58.encode(new Uint8Array(data));
|
|
5819
|
+
if (Array.isArray(data)) return bs58.encode(new Uint8Array(data));
|
|
5820
|
+
return bs58.encode(data);
|
|
5821
|
+
};
|
|
5822
|
+
/**
|
|
5823
|
+
* Decodes a base58 string to binary data using Bitcoin's base58 alphabet.
|
|
5824
|
+
* Returns a Uint8Array containing the decoded bytes.
|
|
5825
|
+
*
|
|
5826
|
+
* @param base58String - Base58-encoded string to decode
|
|
5827
|
+
* @returns Uint8Array containing the decoded bytes
|
|
5828
|
+
* @throws Error if input contains invalid base58 characters
|
|
5829
|
+
*/
|
|
5830
|
+
const base58Decode = (base58String) => {
|
|
5831
|
+
return bs58.decode(base58String);
|
|
5832
|
+
};
|
|
5833
|
+
//#endregion
|
|
5899
5834
|
//#region src/authorization/domain.ts
|
|
5900
5835
|
/**
|
|
5901
5836
|
* The digest-free authorization projection published to the browser. It carries
|
|
@@ -6134,8 +6069,7 @@ function resolveWalletSessionAuthorizationV2AdministrationAdmission(input) {
|
|
|
6134
6069
|
if (!subject || subject.authorityId !== input.authority.authorityId) return admissionRefused("capability_subject_mismatch");
|
|
6135
6070
|
return {
|
|
6136
6071
|
ok: true,
|
|
6137
|
-
operationKind: "link_devices"
|
|
6138
|
-
authorityId: input.authority.authorityId
|
|
6072
|
+
operationKind: "link_devices"
|
|
6139
6073
|
};
|
|
6140
6074
|
}
|
|
6141
6075
|
default: return assertNeverWalletSessionAuthorizationV2AdministrationOperation(input.operation.kind);
|
|
@@ -6225,7 +6159,7 @@ async function prepareOwnerWalletExecution(input) {
|
|
|
6225
6159
|
if (lane.walletKeyId !== input.evidence.walletKey.walletKeyId) return refused("wallet_key_mismatch");
|
|
6226
6160
|
if (!operationMatchesWalletKey(input.authorizedOperation, input.evidence.walletKey)) return refused("curve_mismatch");
|
|
6227
6161
|
if (String(claimedOperation.operation.capabilityId) !== String(input.evidence.materialActivation.capability)) return refused("capability_mismatch");
|
|
6228
|
-
if (!
|
|
6162
|
+
if (!mpcMaterialActivationRefsEqual(input.evidence.materialActivation, input.evidence.expectedMaterialActivation)) return refused("material_activation_mismatch");
|
|
6229
6163
|
if (lane.participantBindingDigestB64u !== input.evidence.verifiedLaneParticipantBindingDigestB64u || String(lane.ownerParticipantContinuity.signingWorkerId) !== String(input.evidence.materialActivation.signingWorker)) return refused("participant_binding_mismatch");
|
|
6230
6164
|
if (await computeOwnerLaneParticipantBindingDigestV1(lane.ownerParticipantContinuity) !== lane.participantBindingDigestB64u) return refused("participant_binding_mismatch");
|
|
6231
6165
|
if (lane.lifecycle.activationReceiptDigestB64u !== input.evidence.verifiedActivationReceiptDigestB64u) return refused("activation_receipt_mismatch");
|
|
@@ -6273,9 +6207,6 @@ function operationMatchesWalletKey(operation, walletKey) {
|
|
|
6273
6207
|
case "ecdsa_secp256k1": return operation.operation.operation.capabilityKind === CAPABILITY_KINDS.evmEcdsaMpcSigning;
|
|
6274
6208
|
}
|
|
6275
6209
|
}
|
|
6276
|
-
function sameMaterialActivation(left, right) {
|
|
6277
|
-
return left.activationId === right.activationId && left.capability === right.capability && left.materialOwner === right.materialOwner && left.keyBinding === right.keyBinding && left.lifecycleBinding === right.lifecycleBinding && left.signingWorker === right.signingWorker;
|
|
6278
|
-
}
|
|
6279
6210
|
function refused(reason) {
|
|
6280
6211
|
return {
|
|
6281
6212
|
kind: "refused",
|
|
@@ -6472,32 +6403,46 @@ async function validateRouterAbEcdsaDerivationWalletSessionInputs(input) {
|
|
|
6472
6403
|
const token = extractBearerCredential(input.headers);
|
|
6473
6404
|
if (!token) return walletSessionFailure("wallet_session_missing");
|
|
6474
6405
|
const nowMs = input.nowMs || Date.now;
|
|
6475
|
-
let
|
|
6406
|
+
let candidate;
|
|
6476
6407
|
try {
|
|
6477
|
-
|
|
6478
|
-
authorizationSessions,
|
|
6408
|
+
candidate = await authorizationSessions.readWalletSessionSigningCandidateByOperationCredential({
|
|
6409
|
+
tenantId: authorizationSessions.tenantId,
|
|
6479
6410
|
token,
|
|
6480
6411
|
nowMs: nowMs(),
|
|
6481
|
-
|
|
6482
|
-
keyFamily: "ecdsa_secp256k1",
|
|
6483
|
-
operationKind: input.operationKind
|
|
6484
|
-
}
|
|
6412
|
+
materialActivation: input.materialActivation
|
|
6485
6413
|
});
|
|
6486
6414
|
} catch {
|
|
6487
6415
|
return walletSessionFailure("wallet_session_unavailable");
|
|
6488
6416
|
}
|
|
6489
|
-
if (
|
|
6490
|
-
if (resolution.kind === "not_found") return {
|
|
6417
|
+
if (!candidate) return {
|
|
6491
6418
|
ok: false,
|
|
6492
6419
|
code: "wallet_session_invalid",
|
|
6493
6420
|
message: walletSessionFailureMessage("wallet_session_invalid")
|
|
6494
6421
|
};
|
|
6422
|
+
if (candidate.kind === "exhausted") return {
|
|
6423
|
+
ok: true,
|
|
6424
|
+
kind: "wallet_session_operation_credential_exhausted_candidate_v1",
|
|
6425
|
+
candidate: candidate.candidate,
|
|
6426
|
+
materialRead: candidate.materialRead,
|
|
6427
|
+
policyRead: candidate.policyRead
|
|
6428
|
+
};
|
|
6429
|
+
const resolution = resolveWalletSessionOperationCredentialAdmissionFromContext({
|
|
6430
|
+
context: candidate.context,
|
|
6431
|
+
nowMs: nowMs(),
|
|
6432
|
+
operation: {
|
|
6433
|
+
keyFamily: "ecdsa_secp256k1",
|
|
6434
|
+
operationKind: input.operationKind
|
|
6435
|
+
}
|
|
6436
|
+
});
|
|
6437
|
+
if (resolution.kind === "rejected") return walletSessionFailure("wallet_session_scope_mismatch");
|
|
6495
6438
|
if (resolution.admission.curve !== "ecdsa") return walletSessionFailure("wallet_session_scope_mismatch");
|
|
6496
6439
|
return {
|
|
6497
6440
|
ok: true,
|
|
6498
6441
|
kind: "wallet_session_operation_credential_v1",
|
|
6499
6442
|
admission: resolution.admission,
|
|
6500
|
-
context: resolution.admission.context
|
|
6443
|
+
context: resolution.admission.context,
|
|
6444
|
+
materialRead: candidate.materialRead,
|
|
6445
|
+
policyRead: candidate.policyRead
|
|
6501
6446
|
};
|
|
6502
6447
|
}
|
|
6503
6448
|
async function resolveThresholdRuntimePolicyScope(input) {
|
|
@@ -6747,6 +6692,22 @@ function toFetchRouteResponse(response) {
|
|
|
6747
6692
|
});
|
|
6748
6693
|
}
|
|
6749
6694
|
//#endregion
|
|
6695
|
+
//#region ../shared-ts/src/utils/registrationIds.ts
|
|
6696
|
+
function walletIdFromString(value) {
|
|
6697
|
+
const parsed = parseWalletId(value);
|
|
6698
|
+
if (!parsed.ok) throw new Error(parsed.error.message);
|
|
6699
|
+
return parsed.value;
|
|
6700
|
+
}
|
|
6701
|
+
function nearEd25519SigningKeyIdFromString(value) {
|
|
6702
|
+
const normalized = String(value || "").trim();
|
|
6703
|
+
if (!normalized) throw new Error("nearEd25519SigningKeyId is required");
|
|
6704
|
+
return normalized;
|
|
6705
|
+
}
|
|
6706
|
+
function parseNearEd25519SigningKeyId(value) {
|
|
6707
|
+
if (typeof value !== "string") throw new Error("nearEd25519SigningKeyId must be a string");
|
|
6708
|
+
return nearEd25519SigningKeyIdFromString(value);
|
|
6709
|
+
}
|
|
6710
|
+
//#endregion
|
|
6750
6711
|
//#region ../shared-ts/src/passkey-custody/custodySecretBinding.ts
|
|
6751
6712
|
/** The only derivation scheme owner custody supports. */
|
|
6752
6713
|
const WALLET_SEED_DERIVATION_SCHEME_V1 = "wallet_seed_parallel_hkdf_sha256_v1";
|
|
@@ -7217,9 +7178,6 @@ function parseWalletRegistrationSetupPolicy(value) {
|
|
|
7217
7178
|
}
|
|
7218
7179
|
//#endregion
|
|
7219
7180
|
//#region ../shared-ts/src/utils/ecdsaKeyFactsInventory.ts
|
|
7220
|
-
function chainTargetKey(target) {
|
|
7221
|
-
return target.kind === "evm" ? `evm:eip155:${target.chainId}` : `tempo:${target.chainId}`;
|
|
7222
|
-
}
|
|
7223
7181
|
function normalizeChainTarget(target) {
|
|
7224
7182
|
if (target.kind === "evm") return {
|
|
7225
7183
|
kind: "evm",
|
|
@@ -7237,7 +7195,7 @@ function canonicalizeWalletEcdsaKeyFactsInventoryChallenge(input) {
|
|
|
7237
7195
|
const keyTargets = input.keyTargets.map((target) => ({
|
|
7238
7196
|
keyHandle: target.keyHandle,
|
|
7239
7197
|
chainTarget: normalizeChainTarget(target.chainTarget),
|
|
7240
|
-
targetKey:
|
|
7198
|
+
targetKey: thresholdEcdsaChainTargetKey(target.chainTarget)
|
|
7241
7199
|
})).sort((left, right) => {
|
|
7242
7200
|
const leftKey = `${left.keyHandle}:${left.targetKey}`;
|
|
7243
7201
|
const rightKey = `${right.keyHandle}:${right.targetKey}`;
|
|
@@ -7256,8 +7214,90 @@ async function computeWalletEcdsaKeyFactsInventoryChallengeDigestB64u(input) {
|
|
|
7256
7214
|
return base64UrlEncode(await sha256BytesUtf8(canonicalizeWalletEcdsaKeyFactsInventoryChallenge(input)));
|
|
7257
7215
|
}
|
|
7258
7216
|
//#endregion
|
|
7259
|
-
//#region ../shared-ts/src/utils/
|
|
7260
|
-
|
|
7217
|
+
//#region ../shared-ts/src/utils/near.ts
|
|
7218
|
+
/**
|
|
7219
|
+
* NEAR-specific utility helpers.
|
|
7220
|
+
*
|
|
7221
|
+
* Keep chain-specific parsing and validation logic here so generic utility
|
|
7222
|
+
* modules (`validation`, `errors`, `encoders`, etc.) stay chain-agnostic.
|
|
7223
|
+
*/
|
|
7224
|
+
/**
|
|
7225
|
+
* Ensure a key string has the NEAR Ed25519 prefix (`ed25519:`).
|
|
7226
|
+
*
|
|
7227
|
+
* - Accepts either `ed25519:<base58>` or a bare `<base58>` string.
|
|
7228
|
+
* - Canonicalizes `ED25519:` -> `ed25519:`.
|
|
7229
|
+
* - If a different prefix is present (e.g. `secp256k1:`), returns the input unchanged.
|
|
7230
|
+
*/
|
|
7231
|
+
function ensureEd25519Prefix(value) {
|
|
7232
|
+
const raw = String(value ?? "").trim();
|
|
7233
|
+
if (!raw) return "";
|
|
7234
|
+
if (/^[a-z0-9_]+:/i.test(raw)) {
|
|
7235
|
+
if (/^ed25519:/i.test(raw)) return `ed25519:${raw.replace(/^ed25519:/i, "")}`;
|
|
7236
|
+
return raw;
|
|
7237
|
+
}
|
|
7238
|
+
return `ed25519:${raw}`;
|
|
7239
|
+
}
|
|
7240
|
+
/**
|
|
7241
|
+
* Lightweight NEAR account ID validation used by server-side helpers.
|
|
7242
|
+
* - length: 2..64
|
|
7243
|
+
* - chars: lowercase letters, digits, `_`, `.`, `-`
|
|
7244
|
+
*/
|
|
7245
|
+
function isValidAccountId(accountId) {
|
|
7246
|
+
if (typeof accountId !== "string") return false;
|
|
7247
|
+
if (!accountId || accountId.length < 2 || accountId.length > 64) return false;
|
|
7248
|
+
return /^[a-z0-9_.-]+$/.test(accountId);
|
|
7249
|
+
}
|
|
7250
|
+
function isImplicitNearAccountId(value) {
|
|
7251
|
+
return typeof value === "string" && /^[0-9a-f]{64}$/.test(value);
|
|
7252
|
+
}
|
|
7253
|
+
function parseImplicitNearAccountId(raw) {
|
|
7254
|
+
const value = typeof raw === "string" ? raw.trim() : "";
|
|
7255
|
+
if (!value) return {
|
|
7256
|
+
ok: false,
|
|
7257
|
+
code: "missing",
|
|
7258
|
+
message: "implicit NEAR account ID is required"
|
|
7259
|
+
};
|
|
7260
|
+
if (!isImplicitNearAccountId(value)) return {
|
|
7261
|
+
ok: false,
|
|
7262
|
+
code: "invalid",
|
|
7263
|
+
message: "implicit NEAR account ID must be 64 lowercase hex characters"
|
|
7264
|
+
};
|
|
7265
|
+
return {
|
|
7266
|
+
ok: true,
|
|
7267
|
+
value
|
|
7268
|
+
};
|
|
7269
|
+
}
|
|
7270
|
+
function parseNamedNearAccountId(raw) {
|
|
7271
|
+
const value = typeof raw === "string" ? raw.trim() : "";
|
|
7272
|
+
if (!value) return {
|
|
7273
|
+
ok: false,
|
|
7274
|
+
code: "missing",
|
|
7275
|
+
message: "named NEAR account ID is required"
|
|
7276
|
+
};
|
|
7277
|
+
if (isImplicitNearAccountId(value) || !isValidAccountId(value) || !value.includes(".")) return {
|
|
7278
|
+
ok: false,
|
|
7279
|
+
code: "invalid",
|
|
7280
|
+
message: "named NEAR account ID must be a valid named account containing a dot"
|
|
7281
|
+
};
|
|
7282
|
+
return {
|
|
7283
|
+
ok: true,
|
|
7284
|
+
value
|
|
7285
|
+
};
|
|
7286
|
+
}
|
|
7287
|
+
function bytesToLowerHex(bytes) {
|
|
7288
|
+
return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
7289
|
+
}
|
|
7290
|
+
function deriveImplicitNearAccountIdFromEd25519PublicKey(publicKey) {
|
|
7291
|
+
const normalized = ensureEd25519Prefix(publicKey);
|
|
7292
|
+
const encoded = normalized.startsWith("ed25519:") ? normalized.slice(8) : "";
|
|
7293
|
+
if (!encoded) throw new Error("Ed25519 public key is required");
|
|
7294
|
+
const decoded = base58Decode(encoded);
|
|
7295
|
+
if (decoded.length !== 32) throw new Error("Ed25519 public key must decode to 32 bytes");
|
|
7296
|
+
return bytesToLowerHex(decoded);
|
|
7297
|
+
}
|
|
7298
|
+
//#endregion
|
|
7299
|
+
//#region ../shared-ts/src/utils/registrationSignerPlan.ts
|
|
7300
|
+
function normalizePositiveInteger(raw, fallback) {
|
|
7261
7301
|
const value = typeof raw === "number" ? raw : Number(raw);
|
|
7262
7302
|
return Number.isFinite(value) && value >= 1 ? Math.floor(value) : fallback;
|
|
7263
7303
|
}
|
|
@@ -7317,11 +7357,8 @@ function registrationSignerBranchKeyFromString(value) {
|
|
|
7317
7357
|
function registrationNearEd25519BranchKey(signerSlot) {
|
|
7318
7358
|
return registrationSignerBranchKeyFromString(`near_ed25519:slot:${signerSlot}`);
|
|
7319
7359
|
}
|
|
7320
|
-
function registrationEvmFamilyEcdsaTargetKey(target) {
|
|
7321
|
-
return alphabetizeStringify(target);
|
|
7322
|
-
}
|
|
7323
7360
|
function registrationEvmFamilyEcdsaBranchKey(chainTargets) {
|
|
7324
|
-
return registrationSignerBranchKeyFromString(`evm_family_ecdsa:${chainTargets.map(
|
|
7361
|
+
return registrationSignerBranchKeyFromString(`evm_family_ecdsa:${chainTargets.map(alphabetizeStringify).join("|")}`);
|
|
7325
7362
|
}
|
|
7326
7363
|
function registrationSignerPlanFromRequests(signers) {
|
|
7327
7364
|
return registrationSignerPlanFromBranches(signers.map(registrationSignerPlanBranchFromRequest));
|
|
@@ -7405,7 +7442,7 @@ function findDuplicateRegistrationSignerBranch(branch, branchKeys) {
|
|
|
7405
7442
|
}
|
|
7406
7443
|
function findDuplicateRegistrationEcdsaTarget(branch, ecdsaTargetKeys) {
|
|
7407
7444
|
for (const target of branch.chainTargets) {
|
|
7408
|
-
const targetKey =
|
|
7445
|
+
const targetKey = alphabetizeStringify(target);
|
|
7409
7446
|
if (ecdsaTargetKeys.has(targetKey)) return {
|
|
7410
7447
|
ok: false,
|
|
7411
7448
|
code: "invalid_body",
|
|
@@ -7591,17 +7628,11 @@ function addAuthMethodIntentGrantFromString(value) {
|
|
|
7591
7628
|
function addSignerIntentGrantFromString(value) {
|
|
7592
7629
|
return String(value || "").trim();
|
|
7593
7630
|
}
|
|
7594
|
-
function serializeAddSignerIntentV1(intent) {
|
|
7595
|
-
return alphabetizeStringify(intent);
|
|
7596
|
-
}
|
|
7597
|
-
function serializeAddAuthMethodIntentV1(intent) {
|
|
7598
|
-
return alphabetizeStringify(intent);
|
|
7599
|
-
}
|
|
7600
7631
|
async function computeAddSignerIntentDigestB64u(intent) {
|
|
7601
|
-
return base64UrlEncode(await sha256BytesUtf8(
|
|
7632
|
+
return base64UrlEncode(await sha256BytesUtf8(alphabetizeStringify(intent)));
|
|
7602
7633
|
}
|
|
7603
7634
|
async function computeAddAuthMethodIntentDigestB64u(intent) {
|
|
7604
|
-
return base64UrlEncode(await sha256BytesUtf8(
|
|
7635
|
+
return base64UrlEncode(await sha256BytesUtf8(alphabetizeStringify(intent)));
|
|
7605
7636
|
}
|
|
7606
7637
|
function normalizeAddAuthMethodIntentCaller(raw) {
|
|
7607
7638
|
const record = inspectRawObject(raw);
|
|
@@ -7932,6 +7963,12 @@ function parseWalletRegistrationSetupWallet(raw) {
|
|
|
7932
7963
|
};
|
|
7933
7964
|
}
|
|
7934
7965
|
function parseWalletRegistrationSetupRequest(body) {
|
|
7966
|
+
const registrationOperationId = parseRegistrationSetupOperationId(body.registrationOperationId);
|
|
7967
|
+
if (!registrationOperationId) return {
|
|
7968
|
+
ok: false,
|
|
7969
|
+
code: "invalid_body",
|
|
7970
|
+
message: "registrationOperationId is required"
|
|
7971
|
+
};
|
|
7935
7972
|
const signerSelection = parseRegistrationSignerSet(body.signerSelection);
|
|
7936
7973
|
if (!signerSelection.ok) return signerSelection;
|
|
7937
7974
|
const authMethod = normalizeRegistrationAuthMethodInput(body.authMethod);
|
|
@@ -7945,6 +7982,7 @@ function parseWalletRegistrationSetupRequest(body) {
|
|
|
7945
7982
|
return {
|
|
7946
7983
|
ok: true,
|
|
7947
7984
|
value: {
|
|
7985
|
+
registrationOperationId,
|
|
7948
7986
|
...wallet.value ? { wallet: wallet.value } : {},
|
|
7949
7987
|
signerSelection: signerSelection.value.selection,
|
|
7950
7988
|
authMethod
|
|
@@ -9162,14 +9200,6 @@ async function handleRouterApiWalletAddSignerIntent(input) {
|
|
|
9162
9200
|
});
|
|
9163
9201
|
return routeJson(result.ok ? 200 : 400, result);
|
|
9164
9202
|
}
|
|
9165
|
-
/**
|
|
9166
|
-
* `POST /wallets/register/setup` — the single admitted entry point that
|
|
9167
|
-
* replaces the bootstrap grant, the intent, and start.
|
|
9168
|
-
*
|
|
9169
|
-
* Authentication is the same API-credential plane the intent route used, so
|
|
9170
|
-
* origin and environment binding are unchanged; what is gone is the stored
|
|
9171
|
-
* grant that used to sit between the check and its only reader.
|
|
9172
|
-
*/
|
|
9173
9203
|
async function handleRouterApiWalletRegistrationSetup(input) {
|
|
9174
9204
|
if (!isPlainObject(input.body)) return routeError(400, "invalid_body", "JSON body required");
|
|
9175
9205
|
const origin = normalizeCorsOrigin(input.origin);
|
|
@@ -9212,7 +9242,7 @@ async function handleRouterApiWalletRegistrationSetup(input) {
|
|
|
9212
9242
|
if (!session) return routeError(500, "internal", "wallet registration setup requires session signing");
|
|
9213
9243
|
const request = parseWalletRegistrationSetupRequest(input.body);
|
|
9214
9244
|
if (!request.ok) return routeError(400, request.code, request.message);
|
|
9215
|
-
|
|
9245
|
+
return input.services.walletRegistration.setupWalletRegistration({
|
|
9216
9246
|
request: request.value,
|
|
9217
9247
|
orgId: principal.orgId,
|
|
9218
9248
|
expectedOrigin: origin,
|
|
@@ -9223,7 +9253,6 @@ async function handleRouterApiWalletRegistrationSetup(input) {
|
|
|
9223
9253
|
signingRootVersion: runtimePolicyScope.signingRootVersion
|
|
9224
9254
|
} : {}
|
|
9225
9255
|
});
|
|
9226
|
-
return routeJson(result.ok ? 200 : 400, result);
|
|
9227
9256
|
}
|
|
9228
9257
|
/**
|
|
9229
9258
|
* `POST /wallets/register/respond` — the authenticated leg.
|
|
@@ -10073,24 +10102,12 @@ function buildSigningSessionSealRemovePath(basePath) {
|
|
|
10073
10102
|
}
|
|
10074
10103
|
function parseSigningSessionSealApplyBody(body) {
|
|
10075
10104
|
const obj = asRecord(body);
|
|
10076
|
-
if (!obj) return
|
|
10077
|
-
ok: false,
|
|
10078
|
-
code: "invalid_body",
|
|
10079
|
-
message: "Request body must be a JSON object"
|
|
10080
|
-
};
|
|
10105
|
+
if (!obj) return failure("invalid_body", "Request body must be a JSON object");
|
|
10081
10106
|
const thresholdSessionId = readRequiredString(obj, "thresholdSessionId");
|
|
10082
10107
|
const ciphertext = readRequiredString(obj, "ciphertext");
|
|
10083
|
-
if (!thresholdSessionId || !ciphertext) return
|
|
10084
|
-
ok: false,
|
|
10085
|
-
code: "invalid_body",
|
|
10086
|
-
message: "thresholdSessionId and ciphertext are required"
|
|
10087
|
-
};
|
|
10108
|
+
if (!thresholdSessionId || !ciphertext) return failure("invalid_body", "thresholdSessionId and ciphertext are required");
|
|
10088
10109
|
const parsedThresholdSessionId = parseThresholdSessionId(thresholdSessionId);
|
|
10089
|
-
if (!parsedThresholdSessionId.ok) return
|
|
10090
|
-
ok: false,
|
|
10091
|
-
code: "invalid_body",
|
|
10092
|
-
message: "thresholdSessionId is invalid"
|
|
10093
|
-
};
|
|
10110
|
+
if (!parsedThresholdSessionId.ok) return failure("invalid_body", "thresholdSessionId is invalid");
|
|
10094
10111
|
return {
|
|
10095
10112
|
ok: true,
|
|
10096
10113
|
value: {
|
|
@@ -10113,11 +10130,7 @@ async function authorizeSigningSessionSealRequest(args) {
|
|
|
10113
10130
|
thresholdSessionId: args.thresholdSessionId
|
|
10114
10131
|
});
|
|
10115
10132
|
} catch (error) {
|
|
10116
|
-
return
|
|
10117
|
-
ok: false,
|
|
10118
|
-
code: "internal",
|
|
10119
|
-
message: error instanceof Error ? error.message : String(error || "Authorization failed")
|
|
10120
|
-
};
|
|
10133
|
+
return failure("internal", error instanceof Error ? error.message : String(error || "Authorization failed"));
|
|
10121
10134
|
}
|
|
10122
10135
|
return {
|
|
10123
10136
|
ok: false,
|
|
@@ -10240,7 +10253,6 @@ const ROUTER_API_ECDSA_STRICT_LIFECYCLE_SERVICES = [
|
|
|
10240
10253
|
"session"
|
|
10241
10254
|
];
|
|
10242
10255
|
const ROUTER_API_WEBAUTHN_AUTHENTICATOR_SERVICES = ["webAuthn", "session"];
|
|
10243
|
-
const ROUTER_API_NEAR_PUBLIC_KEY_SERVICES = ["nearFunding", "session"];
|
|
10244
10256
|
const ROUTER_API_PASSKEY_CUSTODY_SERVICES = [
|
|
10245
10257
|
"passkeyCustody",
|
|
10246
10258
|
"walletAuthMethods",
|
|
@@ -10607,7 +10619,7 @@ function createRouterApiRouteDefinitions(options = {}) {
|
|
|
10607
10619
|
}, ROUTER_API_ED25519_WALLET_SESSION_SERVICES), sessionPrincipalRoute("router_ab_ed25519_sign_prepare", "POST", ROUTER_AB_ED25519_NORMAL_SIGNING_PREPARE_PATH, "Prepare Router A/B Ed25519 normal signing", ROUTER_API_NORMAL_SIGNING_PROXY_SERVICES), sessionPrincipalRoute("router_ab_ed25519_sign_finalize", "POST", ROUTER_AB_ED25519_NORMAL_SIGNING_PATH, "Finalize Router A/B Ed25519 normal signing", ROUTER_API_NORMAL_SIGNING_PROXY_SERVICES), publicRoute("router_ab_ecdsa_derivation_healthz", "GET", ROUTER_AB_ECDSA_DERIVATION_HEALTH_PATH, "Router A/B ECDSA derivation health probe", {
|
|
10608
10620
|
plane: "public",
|
|
10609
10621
|
rationale: "Router A/B health probes are intentionally public diagnostics."
|
|
10610
|
-
}, ROUTER_API_THRESHOLD_RUNTIME_SERVICES), sessionPrincipalRoute("router_ab_ecdsa_derivation_export", "POST", ROUTER_AB_ECDSA_DERIVATION_EXPORT_PATH, "Export authorized Router A/B ECDSA derivation material", ROUTER_API_ECDSA_STRICT_LIFECYCLE_SERVICES), sessionPrincipalRoute("router_ab_ecdsa_derivation_refresh", "POST", ROUTER_AB_ECDSA_DERIVATION_REFRESH_PATH, "Refresh Router A/B ECDSA derivation activation", ROUTER_API_ECDSA_STRICT_LIFECYCLE_SERVICES), sessionPrincipalRoute("router_ab_ecdsa_derivation_session_activate", "POST", ROUTER_AB_ECDSA_DERIVATION_SESSION_ACTIVATION_PATH, "Activate Router A/B ECDSA normal-signing session", ROUTER_API_THRESHOLD_SESSION_SERVICES), sessionPrincipalRoute("router_ab_ecdsa_derivation_sign_prepare", "POST", ROUTER_AB_ECDSA_DERIVATION_NORMAL_SIGNING_PREPARE_PATH, "Prepare Router A/B ECDSA derivation normal signing", ROUTER_API_NORMAL_SIGNING_PROXY_SERVICES), sessionPrincipalRoute("router_ab_ecdsa_derivation_sign_finalize", "POST", ROUTER_AB_ECDSA_DERIVATION_NORMAL_SIGNING_PATH, "Finalize Router A/B ECDSA derivation normal signing", ROUTER_API_NORMAL_SIGNING_PROXY_SERVICES), sessionPrincipalRoute("router_ab_ecdsa_derivation_presignature_pool_fill_init", "POST", ROUTER_AB_ECDSA_DERIVATION_PRESIGNATURE_POOL_FILL_INIT_PATH, "Begin Router A/B ECDSA derivation presignature pool-fill session", ROUTER_API_THRESHOLD_SESSION_SERVICES), sessionPrincipalRoute("router_ab_ecdsa_derivation_presignature_pool_fill_step", "POST", ROUTER_AB_ECDSA_DERIVATION_PRESIGNATURE_POOL_FILL_STEP_PATH, "Continue Router A/B ECDSA derivation presignature pool-fill session", ROUTER_API_THRESHOLD_SESSION_SERVICES), sessionPrincipalRoute("webauthn_authenticators", "GET", "/webauthn/authenticators", "List registered WebAuthn authenticators", ROUTER_API_WEBAUTHN_AUTHENTICATOR_SERVICES),
|
|
10622
|
+
}, ROUTER_API_THRESHOLD_RUNTIME_SERVICES), sessionPrincipalRoute("router_ab_ecdsa_derivation_export", "POST", ROUTER_AB_ECDSA_DERIVATION_EXPORT_PATH, "Export authorized Router A/B ECDSA derivation material", ROUTER_API_ECDSA_STRICT_LIFECYCLE_SERVICES), sessionPrincipalRoute("router_ab_ecdsa_derivation_refresh", "POST", ROUTER_AB_ECDSA_DERIVATION_REFRESH_PATH, "Refresh Router A/B ECDSA derivation activation", ROUTER_API_ECDSA_STRICT_LIFECYCLE_SERVICES), sessionPrincipalRoute("router_ab_ecdsa_derivation_session_activate", "POST", ROUTER_AB_ECDSA_DERIVATION_SESSION_ACTIVATION_PATH, "Activate Router A/B ECDSA normal-signing session", ROUTER_API_THRESHOLD_SESSION_SERVICES), sessionPrincipalRoute("router_ab_ecdsa_derivation_sign_prepare", "POST", ROUTER_AB_ECDSA_DERIVATION_NORMAL_SIGNING_PREPARE_PATH, "Prepare Router A/B ECDSA derivation normal signing", ROUTER_API_NORMAL_SIGNING_PROXY_SERVICES), sessionPrincipalRoute("router_ab_ecdsa_derivation_sign_finalize", "POST", ROUTER_AB_ECDSA_DERIVATION_NORMAL_SIGNING_PATH, "Finalize Router A/B ECDSA derivation normal signing", ROUTER_API_NORMAL_SIGNING_PROXY_SERVICES), sessionPrincipalRoute("router_ab_ecdsa_derivation_presignature_pool_fill_init", "POST", ROUTER_AB_ECDSA_DERIVATION_PRESIGNATURE_POOL_FILL_INIT_PATH, "Begin Router A/B ECDSA derivation presignature pool-fill session", ROUTER_API_THRESHOLD_SESSION_SERVICES), sessionPrincipalRoute("router_ab_ecdsa_derivation_presignature_pool_fill_step", "POST", ROUTER_AB_ECDSA_DERIVATION_PRESIGNATURE_POOL_FILL_STEP_PATH, "Continue Router A/B ECDSA derivation presignature pool-fill session", ROUTER_API_THRESHOLD_SESSION_SERVICES), sessionPrincipalRoute("webauthn_authenticators", "GET", "/webauthn/authenticators", "List registered WebAuthn authenticators", ROUTER_API_WEBAUTHN_AUTHENTICATOR_SERVICES), publicRoute("wallet_unlock_challenge", "POST", "/wallet/unlock/challenge", "Create wallet unlock challenge", {
|
|
10611
10623
|
plane: "public",
|
|
10612
10624
|
proof: "challenge_exchange",
|
|
10613
10625
|
rationale: "Wallet unlock challenge issuance is intentionally public."
|
|
@@ -10687,6 +10699,7 @@ function resolveWalletRegistrationRoute(ctx) {
|
|
|
10687
10699
|
async function handleWalletRegistration(ctx) {
|
|
10688
10700
|
const route = resolveWalletRegistrationRoute(ctx);
|
|
10689
10701
|
if (!route) return null;
|
|
10702
|
+
if (ctx.request.headers.get("X-Seams-Wallet-Protocol") !== "2") return jsonFailure(409, "wallet_protocol_mismatch", "Your wallet application needs an update. Reload this page and try again. If the problem continues, ask the application developer to upgrade the Wallet SDK.");
|
|
10690
10703
|
const common = {
|
|
10691
10704
|
body: await readJson(ctx.request),
|
|
10692
10705
|
headers: Object.fromEntries(ctx.request.headers.entries()),
|
|
@@ -10982,6 +10995,8 @@ function requireVerificationWindow(verifiedAtMs, expiresAtMs) {
|
|
|
10982
10995
|
//#endregion
|
|
10983
10996
|
//#region ../shared-ts/src/utils/emailOtpDomain.ts
|
|
10984
10997
|
const EMAIL_OTP_CHANNEL = "email_otp";
|
|
10998
|
+
/** Domain label that opens the AAD binding a released Email OTP factor to its challenge. */
|
|
10999
|
+
const EMAIL_OTP_FACTOR_RELEASE_AAD_DOMAIN_V1 = "seams/email-otp/factor-release/v1";
|
|
10985
11000
|
const WALLET_UNLOCK_BACKENDS = ["passkey", EMAIL_OTP_CHANNEL];
|
|
10986
11001
|
const WALLET_EMAIL_OTP_LOGIN_OPERATIONS = [
|
|
10987
11002
|
"wallet_unlock",
|
|
@@ -11753,6 +11768,7 @@ async function handleWalletRecoveryPrepare(ctx) {
|
|
|
11753
11768
|
case "refused": return toFetchRouteResponse(refusedSpend());
|
|
11754
11769
|
case "reserved":
|
|
11755
11770
|
case "consumed": return routeErrorResponse(401, "recovery_code_used", "that recovery code has already been used");
|
|
11771
|
+
case "routing_unavailable": return routeErrorResponse(503, "wallet_home_unavailable", "Wallet recovery routing is temporarily unavailable");
|
|
11756
11772
|
case "manifest_unavailable":
|
|
11757
11773
|
case "registration_unavailable": return routeErrorResponse(409, "recovery_preparation_conflict", "wallet recovery could not be prepared");
|
|
11758
11774
|
}
|
|
@@ -12559,11 +12575,7 @@ async function refreshEmailOtpWalletUnlockSessionState(input) {
|
|
|
12559
12575
|
ok: false,
|
|
12560
12576
|
response: {
|
|
12561
12577
|
status: 500,
|
|
12562
|
-
body:
|
|
12563
|
-
ok: false,
|
|
12564
|
-
code: "internal",
|
|
12565
|
-
message: error instanceof Error ? error.message : "Email OTP authority refresh resolution failed"
|
|
12566
|
-
}
|
|
12578
|
+
body: failure("internal", error instanceof Error ? error.message : "Email OTP authority refresh resolution failed")
|
|
12567
12579
|
}
|
|
12568
12580
|
};
|
|
12569
12581
|
}
|
|
@@ -12571,11 +12583,7 @@ async function refreshEmailOtpWalletUnlockSessionState(input) {
|
|
|
12571
12583
|
ok: false,
|
|
12572
12584
|
response: {
|
|
12573
12585
|
status: authorityResolution.code === "internal" ? 500 : 403,
|
|
12574
|
-
body:
|
|
12575
|
-
ok: false,
|
|
12576
|
-
code: authorityResolution.code,
|
|
12577
|
-
message: authorityResolution.message
|
|
12578
|
-
}
|
|
12586
|
+
body: failure(authorityResolution.code, authorityResolution.message)
|
|
12579
12587
|
}
|
|
12580
12588
|
};
|
|
12581
12589
|
try {
|
|
@@ -12592,11 +12600,7 @@ async function refreshEmailOtpWalletUnlockSessionState(input) {
|
|
|
12592
12600
|
ok: false,
|
|
12593
12601
|
response: {
|
|
12594
12602
|
status: 500,
|
|
12595
|
-
body:
|
|
12596
|
-
ok: false,
|
|
12597
|
-
code: "internal",
|
|
12598
|
-
message: error instanceof Error ? error.message : "Email OTP Wallet Session authority projection refresh failed"
|
|
12599
|
-
}
|
|
12603
|
+
body: failure("internal", error instanceof Error ? error.message : "Email OTP Wallet Session authority projection refresh failed")
|
|
12600
12604
|
}
|
|
12601
12605
|
};
|
|
12602
12606
|
}
|
|
@@ -12607,11 +12611,7 @@ function walletUnlockCustodyUnavailableResponse(lookup, factor) {
|
|
|
12607
12611
|
ok: false,
|
|
12608
12612
|
response: {
|
|
12609
12613
|
status: lookup.kind === "manifest_unavailable" ? 503 : lookup.kind === "conflict" ? 409 : lookup.kind === "missing" ? 404 : 409,
|
|
12610
|
-
body: {
|
|
12611
|
-
ok: false,
|
|
12612
|
-
code: lookup.kind === "manifest_unavailable" ? "custody_manifest_unavailable" : "custody_envelope_unavailable",
|
|
12613
|
-
message: `${factor} wallet custody is unavailable`
|
|
12614
|
-
}
|
|
12614
|
+
body: failure(lookup.kind === "manifest_unavailable" ? "custody_manifest_unavailable" : "custody_envelope_unavailable", `${factor} wallet custody is unavailable`)
|
|
12615
12615
|
}
|
|
12616
12616
|
};
|
|
12617
12617
|
}
|
|
@@ -12626,11 +12626,7 @@ function projectEmailOtpCustody(verifiedUnlock, lookup) {
|
|
|
12626
12626
|
ok: false,
|
|
12627
12627
|
response: {
|
|
12628
12628
|
status: 500,
|
|
12629
|
-
body:
|
|
12630
|
-
ok: false,
|
|
12631
|
-
code: "custody_binding_mismatch",
|
|
12632
|
-
message: "Email OTP wallet custody binding is invalid"
|
|
12633
|
-
}
|
|
12629
|
+
body: failure("custody_binding_mismatch", "Email OTP wallet custody binding is invalid")
|
|
12634
12630
|
}
|
|
12635
12631
|
};
|
|
12636
12632
|
return {
|
|
@@ -12660,11 +12656,7 @@ function projectPasskeyCustody(verifiedUnlock, resolution) {
|
|
|
12660
12656
|
ok: false,
|
|
12661
12657
|
response: {
|
|
12662
12658
|
status: 500,
|
|
12663
|
-
body:
|
|
12664
|
-
ok: false,
|
|
12665
|
-
code: "custody_binding_mismatch",
|
|
12666
|
-
message: "Passkey wallet custody binding is invalid"
|
|
12667
|
-
}
|
|
12659
|
+
body: failure("custody_binding_mismatch", "Passkey wallet custody binding is invalid")
|
|
12668
12660
|
}
|
|
12669
12661
|
};
|
|
12670
12662
|
let ed25519 = { kind: "absent" };
|
|
@@ -12676,11 +12668,7 @@ function projectPasskeyCustody(verifiedUnlock, resolution) {
|
|
|
12676
12668
|
ok: false,
|
|
12677
12669
|
response: {
|
|
12678
12670
|
status: 500,
|
|
12679
|
-
body:
|
|
12680
|
-
ok: false,
|
|
12681
|
-
code: "custody_binding_mismatch",
|
|
12682
|
-
message: "Passkey Ed25519 custody binding is invalid"
|
|
12683
|
-
}
|
|
12671
|
+
body: failure("custody_binding_mismatch", "Passkey Ed25519 custody binding is invalid")
|
|
12684
12672
|
}
|
|
12685
12673
|
};
|
|
12686
12674
|
ed25519 = {
|
|
@@ -12711,11 +12699,7 @@ async function provisionFirstEcdsaWalletSession(input) {
|
|
|
12711
12699
|
ok: false,
|
|
12712
12700
|
response: {
|
|
12713
12701
|
status: 403,
|
|
12714
|
-
body:
|
|
12715
|
-
ok: false,
|
|
12716
|
-
code: "scope_mismatch",
|
|
12717
|
-
message: "Wallet unlock proof does not match the requested ECDSA wallet"
|
|
12718
|
-
}
|
|
12702
|
+
body: failure("scope_mismatch", "Wallet unlock proof does not match the requested ECDSA wallet")
|
|
12719
12703
|
}
|
|
12720
12704
|
};
|
|
12721
12705
|
const provisioned = await input.context.provisionWalletSession(input.authorization);
|
|
@@ -12723,11 +12707,7 @@ async function provisionFirstEcdsaWalletSession(input) {
|
|
|
12723
12707
|
ok: false,
|
|
12724
12708
|
response: {
|
|
12725
12709
|
status: provisioned.status,
|
|
12726
|
-
body:
|
|
12727
|
-
ok: false,
|
|
12728
|
-
code: provisioned.code,
|
|
12729
|
-
message: provisioned.message
|
|
12730
|
-
}
|
|
12710
|
+
body: failure(provisioned.code, provisioned.message)
|
|
12731
12711
|
}
|
|
12732
12712
|
};
|
|
12733
12713
|
return {
|
|
@@ -12755,11 +12735,7 @@ function walletUnlockScopeMismatchResponse() {
|
|
|
12755
12735
|
ok: false,
|
|
12756
12736
|
response: {
|
|
12757
12737
|
status: 403,
|
|
12758
|
-
body:
|
|
12759
|
-
ok: false,
|
|
12760
|
-
code: "scope_mismatch",
|
|
12761
|
-
message: "Email OTP unlock proof does not match the requested Ed25519 wallet"
|
|
12762
|
-
}
|
|
12738
|
+
body: failure("scope_mismatch", "Email OTP unlock proof does not match the requested Ed25519 wallet")
|
|
12763
12739
|
}
|
|
12764
12740
|
};
|
|
12765
12741
|
}
|
|
@@ -12823,11 +12799,7 @@ function planWalletUnlockAuthorityEcdsaSession(input) {
|
|
|
12823
12799
|
function walletUnlockDeviceLinkEcdsaSessionRejection() {
|
|
12824
12800
|
return {
|
|
12825
12801
|
status: 400,
|
|
12826
|
-
body:
|
|
12827
|
-
ok: false,
|
|
12828
|
-
code: "invalid_body",
|
|
12829
|
-
message: "ecdsaSessionPolicy is not supported for device-linked wallet unlock"
|
|
12830
|
-
}
|
|
12802
|
+
body: failure("invalid_body", "ecdsaSessionPolicy is not supported for device-linked wallet unlock")
|
|
12831
12803
|
};
|
|
12832
12804
|
}
|
|
12833
12805
|
function planWalletUnlockPasskeySession(input) {
|
|
@@ -12870,11 +12842,7 @@ async function provisionPasskeyEd25519YaoSession(input) {
|
|
|
12870
12842
|
ok: false,
|
|
12871
12843
|
response: {
|
|
12872
12844
|
status: 409,
|
|
12873
|
-
body:
|
|
12874
|
-
ok: false,
|
|
12875
|
-
code: "capability_unavailable",
|
|
12876
|
-
message: "Requested Ed25519 Wallet Session is unavailable"
|
|
12877
|
-
}
|
|
12845
|
+
body: failure("capability_unavailable", "Requested Ed25519 Wallet Session is unavailable")
|
|
12878
12846
|
}
|
|
12879
12847
|
};
|
|
12880
12848
|
const provisioned = await input.context.provisionWalletSession({
|
|
@@ -12928,11 +12896,7 @@ function walletUnlockEcdsaOperationCredential(input) {
|
|
|
12928
12896
|
function walletUnlockEcdsaCredentialUnavailableResponse() {
|
|
12929
12897
|
return {
|
|
12930
12898
|
status: 409,
|
|
12931
|
-
body:
|
|
12932
|
-
ok: false,
|
|
12933
|
-
code: "capability_unavailable",
|
|
12934
|
-
message: "ECDSA activation requires the exact Wallet Session operation credential"
|
|
12935
|
-
}
|
|
12899
|
+
body: failure("capability_unavailable", "ECDSA activation requires the exact Wallet Session operation credential")
|
|
12936
12900
|
};
|
|
12937
12901
|
}
|
|
12938
12902
|
/** The unlock response's Wallet Session, when the unlock holds one. */
|
|
@@ -12968,11 +12932,7 @@ function parseWalletUnlockRouteBody(body) {
|
|
|
12968
12932
|
ok: false,
|
|
12969
12933
|
response: {
|
|
12970
12934
|
status: 400,
|
|
12971
|
-
body:
|
|
12972
|
-
ok: false,
|
|
12973
|
-
code: "invalid_body",
|
|
12974
|
-
message: "Request body is required"
|
|
12975
|
-
}
|
|
12935
|
+
body: failure("invalid_body", "Request body is required")
|
|
12976
12936
|
}
|
|
12977
12937
|
};
|
|
12978
12938
|
const record = body;
|
|
@@ -12981,11 +12941,7 @@ function parseWalletUnlockRouteBody(body) {
|
|
|
12981
12941
|
ok: false,
|
|
12982
12942
|
response: {
|
|
12983
12943
|
status: 400,
|
|
12984
|
-
body:
|
|
12985
|
-
ok: false,
|
|
12986
|
-
code: "invalid_body",
|
|
12987
|
-
message: "unlockBackend is required"
|
|
12988
|
-
}
|
|
12944
|
+
body: failure("invalid_body", "unlockBackend is required")
|
|
12989
12945
|
}
|
|
12990
12946
|
};
|
|
12991
12947
|
return {
|
|
@@ -13002,11 +12958,7 @@ async function handleWalletUnlockChallengeRoute(input) {
|
|
|
13002
12958
|
const walletAuthMethodId = parseRequiredWalletAuthMethodId(body.walletAuthMethodId);
|
|
13003
12959
|
if (!walletAuthMethodId.ok) return {
|
|
13004
12960
|
status: 400,
|
|
13005
|
-
body:
|
|
13006
|
-
ok: false,
|
|
13007
|
-
code: "invalid_body",
|
|
13008
|
-
message: walletAuthMethodId.message
|
|
13009
|
-
}
|
|
12961
|
+
body: failure("invalid_body", walletAuthMethodId.message)
|
|
13010
12962
|
};
|
|
13011
12963
|
}
|
|
13012
12964
|
const result = unlockBackend === "passkey" ? await input.service.createWebAuthnLoginOptions({
|
|
@@ -13018,6 +12970,20 @@ async function handleWalletUnlockChallengeRoute(input) {
|
|
|
13018
12970
|
orgId: body.orgId,
|
|
13019
12971
|
ttlMs: body.ttlMs
|
|
13020
12972
|
});
|
|
12973
|
+
if (!result.ok && result.code === "wallet_home_unavailable") return {
|
|
12974
|
+
status: 503,
|
|
12975
|
+
body: {
|
|
12976
|
+
...result,
|
|
12977
|
+
unlockBackend
|
|
12978
|
+
}
|
|
12979
|
+
};
|
|
12980
|
+
if (!result.ok && result.code === "wallet_home_conflict") return {
|
|
12981
|
+
status: 409,
|
|
12982
|
+
body: {
|
|
12983
|
+
...result,
|
|
12984
|
+
unlockBackend
|
|
12985
|
+
}
|
|
12986
|
+
};
|
|
13021
12987
|
return {
|
|
13022
12988
|
status: result.ok ? 200 : result.code === "internal" ? 500 : 400,
|
|
13023
12989
|
body: {
|
|
@@ -13189,20 +13155,12 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13189
13155
|
const challengeId = String(body.challengeId || "").trim();
|
|
13190
13156
|
if (!challengeId) return {
|
|
13191
13157
|
status: 400,
|
|
13192
|
-
body:
|
|
13193
|
-
ok: false,
|
|
13194
|
-
code: "invalid_body",
|
|
13195
|
-
message: "challengeId is required"
|
|
13196
|
-
}
|
|
13158
|
+
body: failure("invalid_body", "challengeId is required")
|
|
13197
13159
|
};
|
|
13198
13160
|
if (unlockBackend === "passkey") {
|
|
13199
13161
|
if (input.capabilityContext.kind !== "passkey_unlock") return {
|
|
13200
13162
|
status: 400,
|
|
13201
|
-
body:
|
|
13202
|
-
ok: false,
|
|
13203
|
-
code: "invalid_body",
|
|
13204
|
-
message: "Passkey unlock context is invalid"
|
|
13205
|
-
}
|
|
13163
|
+
body: failure("invalid_body", "Passkey unlock context is invalid")
|
|
13206
13164
|
};
|
|
13207
13165
|
let ed25519SessionRequest;
|
|
13208
13166
|
try {
|
|
@@ -13210,11 +13168,7 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13210
13168
|
} catch (error) {
|
|
13211
13169
|
return {
|
|
13212
13170
|
status: 400,
|
|
13213
|
-
body:
|
|
13214
|
-
ok: false,
|
|
13215
|
-
code: "invalid_body",
|
|
13216
|
-
message: error instanceof Error ? error.message : "Ed25519 session request is invalid"
|
|
13217
|
-
}
|
|
13171
|
+
body: failure("invalid_body", error instanceof Error ? error.message : "Ed25519 session request is invalid")
|
|
13218
13172
|
};
|
|
13219
13173
|
}
|
|
13220
13174
|
const result = await verifyPasskeyWalletUnlock({
|
|
@@ -13233,11 +13187,7 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13233
13187
|
const userId = String(result.userId || "").trim();
|
|
13234
13188
|
if (!userId) return {
|
|
13235
13189
|
status: 500,
|
|
13236
|
-
body:
|
|
13237
|
-
ok: false,
|
|
13238
|
-
code: "internal",
|
|
13239
|
-
message: "Verified passkey user is missing"
|
|
13240
|
-
}
|
|
13190
|
+
body: failure("internal", "Verified passkey user is missing")
|
|
13241
13191
|
};
|
|
13242
13192
|
const walletId = parseWalletId(userId);
|
|
13243
13193
|
const walletAuthMethodId = parseWalletAuthMethodId(result.walletAuthMethodId);
|
|
@@ -13246,11 +13196,7 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13246
13196
|
const credentialIdB64u = parseWebAuthnCredentialIdB64u(result.credentialIdB64u);
|
|
13247
13197
|
if (!walletId.ok || !walletAuthMethodId.ok || !walletAuthorityId.ok || !rpId.ok || !credentialIdB64u.ok) return {
|
|
13248
13198
|
status: 500,
|
|
13249
|
-
body:
|
|
13250
|
-
ok: false,
|
|
13251
|
-
code: "internal",
|
|
13252
|
-
message: "Verified passkey identity is invalid"
|
|
13253
|
-
}
|
|
13199
|
+
body: failure("internal", "Verified passkey identity is invalid")
|
|
13254
13200
|
};
|
|
13255
13201
|
let authorization;
|
|
13256
13202
|
try {
|
|
@@ -13268,11 +13214,7 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13268
13214
|
} catch (error) {
|
|
13269
13215
|
return {
|
|
13270
13216
|
status: 403,
|
|
13271
|
-
body:
|
|
13272
|
-
ok: false,
|
|
13273
|
-
code: "owner_proof_rejected",
|
|
13274
|
-
message: error instanceof Error ? error.message : "Passkey owner proof is invalid"
|
|
13275
|
-
}
|
|
13217
|
+
body: failure("owner_proof_rejected", error instanceof Error ? error.message : "Passkey owner proof is invalid")
|
|
13276
13218
|
};
|
|
13277
13219
|
}
|
|
13278
13220
|
const resolvePasskeyAuthority = () => input.service.resolveActivePasskeyAuthorityForUnlock({
|
|
@@ -13290,11 +13232,7 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13290
13232
|
} catch (error) {
|
|
13291
13233
|
return {
|
|
13292
13234
|
status: 500,
|
|
13293
|
-
body:
|
|
13294
|
-
ok: false,
|
|
13295
|
-
code: "internal",
|
|
13296
|
-
message: error instanceof Error ? error.message : "Passkey authority resolution failed"
|
|
13297
|
-
}
|
|
13235
|
+
body: failure("internal", error instanceof Error ? error.message : "Passkey authority resolution failed")
|
|
13298
13236
|
};
|
|
13299
13237
|
}
|
|
13300
13238
|
if (authorityResolution.kind === "active_authority") {
|
|
@@ -13311,11 +13249,7 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13311
13249
|
switch (sessionPlan.kind) {
|
|
13312
13250
|
case "rejected": return {
|
|
13313
13251
|
status: walletUnlockIssuanceRejectionStatus(sessionPlan.authorityResolution),
|
|
13314
|
-
body:
|
|
13315
|
-
ok: false,
|
|
13316
|
-
code: sessionPlan.authorityResolution.code,
|
|
13317
|
-
message: sessionPlan.authorityResolution.message
|
|
13318
|
-
}
|
|
13252
|
+
body: failure(sessionPlan.authorityResolution.code, sessionPlan.authorityResolution.message)
|
|
13319
13253
|
};
|
|
13320
13254
|
case "wallet_registration":
|
|
13321
13255
|
passkeyCustodyRequired = true;
|
|
@@ -13337,11 +13271,7 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13337
13271
|
} catch (error) {
|
|
13338
13272
|
return {
|
|
13339
13273
|
status: 500,
|
|
13340
|
-
body:
|
|
13341
|
-
ok: false,
|
|
13342
|
-
code: "internal",
|
|
13343
|
-
message: error instanceof Error ? error.message : "Passkey Wallet Session issuance failed"
|
|
13344
|
-
}
|
|
13274
|
+
body: failure("internal", error instanceof Error ? error.message : "Passkey Wallet Session issuance failed")
|
|
13345
13275
|
};
|
|
13346
13276
|
}
|
|
13347
13277
|
switch (sessionResolution.kind) {
|
|
@@ -13362,11 +13292,7 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13362
13292
|
break;
|
|
13363
13293
|
case "rejected": return {
|
|
13364
13294
|
status: walletUnlockIssuanceRejectionStatus(sessionResolution),
|
|
13365
|
-
body:
|
|
13366
|
-
ok: false,
|
|
13367
|
-
code: sessionResolution.code,
|
|
13368
|
-
message: sessionResolution.message
|
|
13369
|
-
}
|
|
13295
|
+
body: failure(sessionResolution.code, sessionResolution.message)
|
|
13370
13296
|
};
|
|
13371
13297
|
}
|
|
13372
13298
|
break;
|
|
@@ -13385,11 +13311,7 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13385
13311
|
} catch (error) {
|
|
13386
13312
|
return {
|
|
13387
13313
|
status: 503,
|
|
13388
|
-
body:
|
|
13389
|
-
ok: false,
|
|
13390
|
-
code: "custody_unavailable",
|
|
13391
|
-
message: error instanceof Error ? error.message : "Passkey wallet custody is unavailable"
|
|
13392
|
-
}
|
|
13314
|
+
body: failure("custody_unavailable", error instanceof Error ? error.message : "Passkey wallet custody is unavailable")
|
|
13393
13315
|
};
|
|
13394
13316
|
}
|
|
13395
13317
|
const ed25519Session = await provisionPasskeyEd25519YaoSession({
|
|
@@ -13431,20 +13353,12 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13431
13353
|
} catch (error) {
|
|
13432
13354
|
return {
|
|
13433
13355
|
status: 500,
|
|
13434
|
-
body:
|
|
13435
|
-
ok: false,
|
|
13436
|
-
code: "internal",
|
|
13437
|
-
message: error instanceof Error ? error.message : "Passkey authority refresh resolution failed"
|
|
13438
|
-
}
|
|
13356
|
+
body: failure("internal", error instanceof Error ? error.message : "Passkey authority refresh resolution failed")
|
|
13439
13357
|
};
|
|
13440
13358
|
}
|
|
13441
13359
|
if (refreshedAuthority.kind === "rejected") return {
|
|
13442
13360
|
status: walletUnlockIssuanceRejectionStatus(refreshedAuthority),
|
|
13443
|
-
body:
|
|
13444
|
-
ok: false,
|
|
13445
|
-
code: refreshedAuthority.code,
|
|
13446
|
-
message: refreshedAuthority.message
|
|
13447
|
-
}
|
|
13361
|
+
body: failure(refreshedAuthority.code, refreshedAuthority.message)
|
|
13448
13362
|
};
|
|
13449
13363
|
try {
|
|
13450
13364
|
walletSessionState = await refreshWalletUnlockSessionState({
|
|
@@ -13455,11 +13369,7 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13455
13369
|
} catch (error) {
|
|
13456
13370
|
return {
|
|
13457
13371
|
status: 500,
|
|
13458
|
-
body:
|
|
13459
|
-
ok: false,
|
|
13460
|
-
code: "internal",
|
|
13461
|
-
message: error instanceof Error ? error.message : "Passkey Wallet Session authority projection refresh failed"
|
|
13462
|
-
}
|
|
13372
|
+
body: failure("internal", error instanceof Error ? error.message : "Passkey Wallet Session authority projection refresh failed")
|
|
13463
13373
|
};
|
|
13464
13374
|
}
|
|
13465
13375
|
}
|
|
@@ -13488,20 +13398,12 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13488
13398
|
}
|
|
13489
13399
|
if (input.capabilityContext.kind === "passkey_unlock") return {
|
|
13490
13400
|
status: 400,
|
|
13491
|
-
body:
|
|
13492
|
-
ok: false,
|
|
13493
|
-
code: "invalid_body",
|
|
13494
|
-
message: "Email OTP unlock context is invalid"
|
|
13495
|
-
}
|
|
13401
|
+
body: failure("invalid_body", "Email OTP unlock context is invalid")
|
|
13496
13402
|
};
|
|
13497
13403
|
const requestedWalletAuthMethodId = parseRequiredWalletAuthMethodId(body.walletAuthMethodId);
|
|
13498
13404
|
if (!requestedWalletAuthMethodId.ok) return {
|
|
13499
13405
|
status: 400,
|
|
13500
|
-
body:
|
|
13501
|
-
ok: false,
|
|
13502
|
-
code: "invalid_body",
|
|
13503
|
-
message: requestedWalletAuthMethodId.message
|
|
13504
|
-
}
|
|
13406
|
+
body: failure("invalid_body", requestedWalletAuthMethodId.message)
|
|
13505
13407
|
};
|
|
13506
13408
|
const result = await input.service.verifyEmailOtpUnlockProof({
|
|
13507
13409
|
walletId: body.walletId,
|
|
@@ -13528,11 +13430,7 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13528
13430
|
const walletId = parseWalletId(result.walletId);
|
|
13529
13431
|
if (!walletId.ok) return {
|
|
13530
13432
|
status: 500,
|
|
13531
|
-
body:
|
|
13532
|
-
ok: false,
|
|
13533
|
-
code: "internal",
|
|
13534
|
-
message: "Verified Email OTP wallet identity is invalid"
|
|
13535
|
-
}
|
|
13433
|
+
body: failure("internal", "Verified Email OTP wallet identity is invalid")
|
|
13536
13434
|
};
|
|
13537
13435
|
let authorityResolution;
|
|
13538
13436
|
try {
|
|
@@ -13545,20 +13443,12 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13545
13443
|
} catch (error) {
|
|
13546
13444
|
return {
|
|
13547
13445
|
status: 500,
|
|
13548
|
-
body:
|
|
13549
|
-
ok: false,
|
|
13550
|
-
code: "internal",
|
|
13551
|
-
message: error instanceof Error ? error.message : "Email OTP authority resolution failed"
|
|
13552
|
-
}
|
|
13446
|
+
body: failure("internal", error instanceof Error ? error.message : "Email OTP authority resolution failed")
|
|
13553
13447
|
};
|
|
13554
13448
|
}
|
|
13555
13449
|
if (authorityResolution.kind === "rejected") return {
|
|
13556
13450
|
status: authorityResolution.code === "internal" ? 500 : 403,
|
|
13557
|
-
body:
|
|
13558
|
-
ok: false,
|
|
13559
|
-
code: authorityResolution.code,
|
|
13560
|
-
message: authorityResolution.message
|
|
13561
|
-
}
|
|
13451
|
+
body: failure(authorityResolution.code, authorityResolution.message)
|
|
13562
13452
|
};
|
|
13563
13453
|
const exactEmailOtpAuthority = authorityResolution;
|
|
13564
13454
|
if (planWalletUnlockAuthorityEcdsaSession({
|
|
@@ -13592,11 +13482,7 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13592
13482
|
} catch (error) {
|
|
13593
13483
|
return {
|
|
13594
13484
|
status: 403,
|
|
13595
|
-
body:
|
|
13596
|
-
ok: false,
|
|
13597
|
-
code: "owner_proof_rejected",
|
|
13598
|
-
message: error instanceof Error ? error.message : "Email OTP owner proof is invalid"
|
|
13599
|
-
}
|
|
13485
|
+
body: failure("owner_proof_rejected", error instanceof Error ? error.message : "Email OTP owner proof is invalid")
|
|
13600
13486
|
};
|
|
13601
13487
|
}
|
|
13602
13488
|
let walletSessionState = { kind: "absent" };
|
|
@@ -13604,11 +13490,7 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13604
13490
|
const walletId = parseWalletId(result.walletId);
|
|
13605
13491
|
if (!walletId.ok) return {
|
|
13606
13492
|
status: 500,
|
|
13607
|
-
body:
|
|
13608
|
-
ok: false,
|
|
13609
|
-
code: "internal",
|
|
13610
|
-
message: "Verified Email OTP wallet identity is invalid"
|
|
13611
|
-
}
|
|
13493
|
+
body: failure("internal", "Verified Email OTP wallet identity is invalid")
|
|
13612
13494
|
};
|
|
13613
13495
|
let sessionResolution;
|
|
13614
13496
|
try {
|
|
@@ -13623,11 +13505,7 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13623
13505
|
} catch (error) {
|
|
13624
13506
|
return {
|
|
13625
13507
|
status: 500,
|
|
13626
|
-
body:
|
|
13627
|
-
ok: false,
|
|
13628
|
-
code: "internal",
|
|
13629
|
-
message: error instanceof Error ? error.message : "Email OTP Wallet Session issuance failed"
|
|
13630
|
-
}
|
|
13508
|
+
body: failure("internal", error instanceof Error ? error.message : "Email OTP Wallet Session issuance failed")
|
|
13631
13509
|
};
|
|
13632
13510
|
}
|
|
13633
13511
|
switch (sessionResolution.kind) {
|
|
@@ -13645,11 +13523,7 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13645
13523
|
case "wallet_registration": break;
|
|
13646
13524
|
case "rejected": return {
|
|
13647
13525
|
status: walletUnlockIssuanceRejectionStatus(sessionResolution),
|
|
13648
|
-
body:
|
|
13649
|
-
ok: false,
|
|
13650
|
-
code: sessionResolution.code,
|
|
13651
|
-
message: sessionResolution.message
|
|
13652
|
-
}
|
|
13526
|
+
body: failure(sessionResolution.code, sessionResolution.message)
|
|
13653
13527
|
};
|
|
13654
13528
|
}
|
|
13655
13529
|
}
|
|
@@ -13699,11 +13573,7 @@ async function handleWalletUnlockVerifyRoute(input) {
|
|
|
13699
13573
|
});
|
|
13700
13574
|
if (!isWalletUnlockEd25519YaoRequestedContext(input.capabilityContext)) return {
|
|
13701
13575
|
status: 400,
|
|
13702
|
-
body:
|
|
13703
|
-
ok: false,
|
|
13704
|
-
code: "invalid_body",
|
|
13705
|
-
message: "Email OTP capability context is invalid"
|
|
13706
|
-
}
|
|
13576
|
+
body: failure("invalid_body", "Email OTP capability context is invalid")
|
|
13707
13577
|
};
|
|
13708
13578
|
const capabilityResult = await provisionEmailOtpEd25519YaoCapability({
|
|
13709
13579
|
context: input.capabilityContext,
|
|
@@ -13742,7 +13612,6 @@ const ECDSA_TIMING_METRICS = new Set([
|
|
|
13742
13612
|
"ecdsa_sign_proxy",
|
|
13743
13613
|
"ecdsa_sign_complete",
|
|
13744
13614
|
"ecdsa_sign_total",
|
|
13745
|
-
"ecdsa_presign_queue",
|
|
13746
13615
|
"ecdsa_presign_authenticate",
|
|
13747
13616
|
"ecdsa_presign_material",
|
|
13748
13617
|
"ecdsa_presign_admit",
|
|
@@ -13831,6 +13700,7 @@ async function evaluateRouterAbNormalSigningAdmission(input) {
|
|
|
13831
13700
|
});
|
|
13832
13701
|
return await input.adapter.evaluatePolicy({
|
|
13833
13702
|
curve: "ecdsa",
|
|
13703
|
+
policyReadSource: input.policyReadSource,
|
|
13834
13704
|
phase: input.phase,
|
|
13835
13705
|
walletId: input.walletId,
|
|
13836
13706
|
materialActivationId: requireMpcMaterialActivationId(input.admission.materialActivation.activation_id),
|
|
@@ -14104,6 +13974,7 @@ async function authenticateRouterAbWalletOperationStepUpIdentity(input) {
|
|
|
14104
13974
|
if (admission.curve === "ecdsa" && input.keyFamily === "ecdsa_secp256k1") {
|
|
14105
13975
|
const active = ecdsaStepUpActiveMaterial({
|
|
14106
13976
|
activeMaterial: await input.resolveEcdsaMaterialActivation({
|
|
13977
|
+
source: { kind: "database" },
|
|
14107
13978
|
walletId: input.walletId,
|
|
14108
13979
|
materialActivation: admittedMaterialActivation
|
|
14109
13980
|
}),
|
|
@@ -14546,7 +14417,7 @@ async function buildRouterAbEd25519PrivateSigningWorkerBody(input) {
|
|
|
14546
14417
|
const scope = parseRouterAbEd25519NormalSigningScopeV2(input.body.scope);
|
|
14547
14418
|
const signingContext = privateSigningAuthorizationContext(scope, input.authorization);
|
|
14548
14419
|
const trustedSourceDigest = await privateSigningTrustedSourceDigest(input.headers);
|
|
14549
|
-
const materialSource =
|
|
14420
|
+
const materialSource = registrationMaterialSourceV1({
|
|
14550
14421
|
accountId: scope.account_id,
|
|
14551
14422
|
materialActivationId: scope.material_activation.activation_id,
|
|
14552
14423
|
signingWorkerId: scope.signing_worker_id
|
|
@@ -14663,6 +14534,7 @@ async function resolveRouterAbEcdsaOwnerOperationStepUpPreparation(input) {
|
|
|
14663
14534
|
const walletId = parseWalletId(request.scope.wallet_id);
|
|
14664
14535
|
if (!walletId.ok) return void 0;
|
|
14665
14536
|
const activeMaterial = await input.resolveEcdsaMaterialActivation({
|
|
14537
|
+
source: { kind: "database" },
|
|
14666
14538
|
walletId: walletId.value,
|
|
14667
14539
|
materialActivation: request.material_activation
|
|
14668
14540
|
});
|
|
@@ -14763,6 +14635,7 @@ function routerAbWalletSessionError(code) {
|
|
|
14763
14635
|
*/
|
|
14764
14636
|
async function resolveFreshRouterAbEcdsaMaterialActivation(input) {
|
|
14765
14637
|
const resolved = await input.resolveEcdsaMaterialActivation({
|
|
14638
|
+
source: { kind: "database" },
|
|
14766
14639
|
walletId: input.walletId,
|
|
14767
14640
|
materialActivation: input.expected
|
|
14768
14641
|
});
|
|
@@ -14782,15 +14655,7 @@ async function resolveFreshRouterAbEcdsaMaterialActivation(input) {
|
|
|
14782
14655
|
};
|
|
14783
14656
|
}
|
|
14784
14657
|
function validateRouterAbEcdsaV2NormalSigningRequestForSession(input) {
|
|
14785
|
-
|
|
14786
|
-
try {
|
|
14787
|
-
request = parseRouterAbEcdsaOperationStepUpRequest(input);
|
|
14788
|
-
} catch (error) {
|
|
14789
|
-
return {
|
|
14790
|
-
ok: false,
|
|
14791
|
-
error: routerAbStepUpError(400, "invalid_body", routerAbErrorMessage(error))
|
|
14792
|
-
};
|
|
14793
|
-
}
|
|
14658
|
+
const request = input.request;
|
|
14794
14659
|
if (request.authorization.kind !== "reusable_wallet_session" || request.authorization.wallet_session_id !== input.session.walletSessionId || request.scope.wallet_id !== String(input.session.walletId) || request.material_activation.material_owner !== String(input.session.walletId) || request.material_activation.signing_worker !== request.scope.signing_worker.server_id || !sameRouterAbMpcMaterialActivationRef(request.material_activation, request.scope.material_activation) || !sameRouterAbMpcMaterialActivationRef(request.material_activation, input.admittedMaterialActivation)) return {
|
|
14795
14660
|
ok: false,
|
|
14796
14661
|
error: routerAbWalletSessionError(WALLET_SESSION_FAILURE_CODES.scopeMismatch)
|
|
@@ -14819,7 +14684,7 @@ function validateRouterAbEcdsaV2NormalSigningRequestForSession(input) {
|
|
|
14819
14684
|
};
|
|
14820
14685
|
}
|
|
14821
14686
|
async function admitRouterAbEcdsaReusableWalletSessionOperation(input) {
|
|
14822
|
-
if (typeof input.authorizedOperations.admitEcdsaWalletSessionOperation !== "function") return {
|
|
14687
|
+
if (typeof input.authorizedOperations.admitEcdsaWalletSessionOperation !== "function" || typeof input.authorizedOperations.resolveEcdsaWalletSessionOperation !== "function") return {
|
|
14823
14688
|
ok: false,
|
|
14824
14689
|
error: routerAbStepUpError(501, "not_configured", "ECDSA atomic authorization is not configured")
|
|
14825
14690
|
};
|
|
@@ -14829,7 +14694,7 @@ async function admitRouterAbEcdsaReusableWalletSessionOperation(input) {
|
|
|
14829
14694
|
};
|
|
14830
14695
|
const nowMs = Date.now();
|
|
14831
14696
|
try {
|
|
14832
|
-
const session = input.binding.kind === "wallet_session_operation_credential_v1" ? input.binding.context.authorization.session : input.binding.candidate.status.session;
|
|
14697
|
+
const session = input.binding.kind === "wallet_session_operation_credential_v1" ? input.binding.validated.admission.context.authorization.session : input.binding.candidate.status.session;
|
|
14833
14698
|
const tenantId = session.tenantId;
|
|
14834
14699
|
const principalId = session.principalId;
|
|
14835
14700
|
const walletId = session.walletId;
|
|
@@ -14840,16 +14705,12 @@ async function admitRouterAbEcdsaReusableWalletSessionOperation(input) {
|
|
|
14840
14705
|
ok: false,
|
|
14841
14706
|
error: routerAbStepUpError(403, "wallet_session_mismatch", "Reusable Wallet Session identity does not match")
|
|
14842
14707
|
};
|
|
14843
|
-
const
|
|
14844
|
-
|
|
14845
|
-
walletId: String(walletId),
|
|
14846
|
-
expected: input.materialActivation
|
|
14847
|
-
});
|
|
14848
|
-
if (!freshMaterial.ok) return {
|
|
14708
|
+
const material = input.material;
|
|
14709
|
+
if (!sameRouterAbMpcMaterialActivationRef(material.materialActivation, input.request.material_activation)) return {
|
|
14849
14710
|
ok: false,
|
|
14850
|
-
error: routerAbStepUpError(
|
|
14711
|
+
error: routerAbStepUpError(403, "material_mismatch", "Signing material does not match the request")
|
|
14851
14712
|
};
|
|
14852
|
-
const capabilityId = requireAuthorizationValue$2(parseCapabilityId(
|
|
14713
|
+
const capabilityId = requireAuthorizationValue$2(parseCapabilityId(material.materialActivation.capability));
|
|
14853
14714
|
const operationId = requireAuthorizationValue$2(parseCapabilityOperationId(input.request.operation_id));
|
|
14854
14715
|
const envelope = buildCapabilityOperationEnvelope({
|
|
14855
14716
|
tenantId,
|
|
@@ -14863,13 +14724,11 @@ async function admitRouterAbEcdsaReusableWalletSessionOperation(input) {
|
|
|
14863
14724
|
displayDigest: parseDigestB64u(input.request.operation_digests.display_digest_b64u)
|
|
14864
14725
|
}
|
|
14865
14726
|
});
|
|
14866
|
-
const
|
|
14867
|
-
const auditEventId = requireAuthorizationValue$2(parseAuthorizationAuditEventId(`ecdsa-operation-audit:${operationId}`));
|
|
14868
|
-
const outcome = await input.authorizedOperations.admitEcdsaWalletSessionOperation({
|
|
14727
|
+
const admissionInput = {
|
|
14869
14728
|
operation: {
|
|
14870
14729
|
tenantId,
|
|
14871
|
-
authorizedOperationId,
|
|
14872
|
-
auditEventId,
|
|
14730
|
+
authorizedOperationId: requireAuthorizationValue$2(parseAuthorizedOperationId(`ecdsa-authorized-operation:${operationId}:${input.request.request_id}`)),
|
|
14731
|
+
auditEventId: requireAuthorizationValue$2(parseAuthorizationAuditEventId(`ecdsa-operation-audit:${operationId}`)),
|
|
14873
14732
|
operation: envelope,
|
|
14874
14733
|
authorization: {
|
|
14875
14734
|
kind: "authorization_grant",
|
|
@@ -14882,12 +14741,35 @@ async function admitRouterAbEcdsaReusableWalletSessionOperation(input) {
|
|
|
14882
14741
|
claimedAtMs: nowMs
|
|
14883
14742
|
},
|
|
14884
14743
|
material: {
|
|
14744
|
+
readSnapshot: material.readSnapshot,
|
|
14885
14745
|
walletId,
|
|
14886
|
-
keyHandle:
|
|
14887
|
-
runtimePolicyScope:
|
|
14888
|
-
materialActivation:
|
|
14746
|
+
keyHandle: material.keyHandle,
|
|
14747
|
+
runtimePolicyScope: material.runtimePolicyScope,
|
|
14748
|
+
materialActivation: material.materialActivation
|
|
14889
14749
|
}
|
|
14890
|
-
}
|
|
14750
|
+
};
|
|
14751
|
+
if (input.phase === "finalize") {
|
|
14752
|
+
const resolved = await input.authorizedOperations.resolveEcdsaWalletSessionOperation(admissionInput);
|
|
14753
|
+
if (resolved.kind === "authorized_operation_missing") return {
|
|
14754
|
+
ok: false,
|
|
14755
|
+
error: routerAbStepUpError(409, resolved.kind, "ECDSA finalize requires a claimed prepare operation")
|
|
14756
|
+
};
|
|
14757
|
+
const failure = routerAbReusableWalletSessionClaimFailure(resolved);
|
|
14758
|
+
if (failure) return {
|
|
14759
|
+
ok: false,
|
|
14760
|
+
error: failure
|
|
14761
|
+
};
|
|
14762
|
+
if (resolved.kind === "operation_in_progress" || resolved.kind === "replayed") return {
|
|
14763
|
+
ok: true,
|
|
14764
|
+
phase: "finalize",
|
|
14765
|
+
admission: resolved
|
|
14766
|
+
};
|
|
14767
|
+
return {
|
|
14768
|
+
ok: false,
|
|
14769
|
+
error: routerAbStepUpError(409, resolved.kind, "Authorized operation is unavailable")
|
|
14770
|
+
};
|
|
14771
|
+
}
|
|
14772
|
+
const outcome = await input.authorizedOperations.admitEcdsaWalletSessionOperation(admissionInput);
|
|
14891
14773
|
const claimFailure = routerAbReusableWalletSessionClaimFailure(outcome);
|
|
14892
14774
|
if (claimFailure) return {
|
|
14893
14775
|
ok: false,
|
|
@@ -14895,6 +14777,7 @@ async function admitRouterAbEcdsaReusableWalletSessionOperation(input) {
|
|
|
14895
14777
|
};
|
|
14896
14778
|
if (outcome.kind === "claimed" || outcome.kind === "operation_in_progress" || outcome.kind === "replayed") return {
|
|
14897
14779
|
ok: true,
|
|
14780
|
+
phase: "prepare",
|
|
14898
14781
|
admission: outcome
|
|
14899
14782
|
};
|
|
14900
14783
|
return {
|
|
@@ -14940,6 +14823,10 @@ async function authorizeRouterAbEcdsaWalletSessionRequest(input) {
|
|
|
14940
14823
|
result: validated.error
|
|
14941
14824
|
};
|
|
14942
14825
|
const activeMaterial = await input.resolveEcdsaMaterialActivation({
|
|
14826
|
+
source: {
|
|
14827
|
+
kind: "credential_snapshot",
|
|
14828
|
+
materialRead: input.materialRead
|
|
14829
|
+
},
|
|
14943
14830
|
walletId: String(input.session.walletId),
|
|
14944
14831
|
materialActivation: validated.admission.materialActivation
|
|
14945
14832
|
});
|
|
@@ -14957,6 +14844,10 @@ async function authorizeRouterAbEcdsaWalletSessionRequest(input) {
|
|
|
14957
14844
|
result: routerAbStepUpError(403, "wallet_session_scope_mismatch", "Wallet Session V2 scope does not match the active material")
|
|
14958
14845
|
};
|
|
14959
14846
|
const admissionDecision = await evaluateRouterAbNormalSigningAdmission({
|
|
14847
|
+
policyReadSource: {
|
|
14848
|
+
kind: "credential_snapshot",
|
|
14849
|
+
policyRead: input.policyRead
|
|
14850
|
+
},
|
|
14960
14851
|
adapter: input.admissionAdapter,
|
|
14961
14852
|
curve: "ecdsa",
|
|
14962
14853
|
authorizationKind: "wallet_session_operation_credential_v1",
|
|
@@ -14991,29 +14882,21 @@ async function authorizeRouterAbEcdsaWalletSessionRequest(input) {
|
|
|
14991
14882
|
};
|
|
14992
14883
|
}
|
|
14993
14884
|
async function resolveRouterAbEcdsaExhaustedCandidateAuthorization(input) {
|
|
14994
|
-
const
|
|
14995
|
-
|
|
14996
|
-
const
|
|
14997
|
-
|
|
14998
|
-
|
|
14999
|
-
operation: {
|
|
15000
|
-
keyFamily: "ecdsa_secp256k1",
|
|
15001
|
-
operationKind: "evm.sign_transaction"
|
|
15002
|
-
}
|
|
14885
|
+
const candidate = input.candidate;
|
|
14886
|
+
const session = candidate.status.session;
|
|
14887
|
+
const admission = walletSessionCandidateAdmission(session, candidate, {
|
|
14888
|
+
keyFamily: "ecdsa_secp256k1",
|
|
14889
|
+
operationKind: "evm.sign_transaction"
|
|
15003
14890
|
});
|
|
15004
|
-
if (!exhausted) return null;
|
|
15005
|
-
if (!exhausted.ok) return {
|
|
15006
|
-
ok: false,
|
|
15007
|
-
result: exhausted.error
|
|
15008
|
-
};
|
|
15009
|
-
const { candidate, session, admission } = exhausted;
|
|
15010
14891
|
if (!admission.ok || admission.keyFamily !== "ecdsa_secp256k1") return {
|
|
15011
14892
|
ok: false,
|
|
15012
14893
|
result: routerAbWalletSessionError(WALLET_SESSION_FAILURE_CODES.scopeMismatch)
|
|
15013
14894
|
};
|
|
15014
14895
|
const authorized = await authorizeRouterAbEcdsaWalletSessionRequest({
|
|
14896
|
+
materialRead: input.materialRead,
|
|
14897
|
+
policyRead: input.policyRead,
|
|
15015
14898
|
phase: input.phase,
|
|
15016
|
-
|
|
14899
|
+
request: input.request,
|
|
15017
14900
|
session,
|
|
15018
14901
|
admittedMaterialActivation: routerAbMpcMaterialActivationRefToWire(admission.materialActivation),
|
|
15019
14902
|
admissionAdapter: input.admissionAdapter,
|
|
@@ -15066,6 +14949,7 @@ async function authenticateRouterAbEcdsaOperationStepUp(input) {
|
|
|
15066
14949
|
let resolvedMaterial;
|
|
15067
14950
|
try {
|
|
15068
14951
|
resolvedMaterial = await input.resolveEcdsaMaterialActivation({
|
|
14952
|
+
source: { kind: "database" },
|
|
15069
14953
|
walletId: scope.wallet_id,
|
|
15070
14954
|
materialActivation: admittedMaterialActivation
|
|
15071
14955
|
});
|
|
@@ -15173,6 +15057,7 @@ async function handleRouterAbEcdsaOperationStepUpRoute(input) {
|
|
|
15173
15057
|
const materialActivationId = requireMpcMaterialActivationId(activeMaterial.materialActivation.activation_id);
|
|
15174
15058
|
if (!input.admissionAdapter) return routerAbStepUpError(501, "not_configured", "Router A/B ECDSA operation step-up admission is not configured");
|
|
15175
15059
|
const admission = await input.admissionAdapter.evaluatePolicy({
|
|
15060
|
+
policyReadSource: { kind: "database" },
|
|
15176
15061
|
curve: "ecdsa",
|
|
15177
15062
|
phase: input.phase,
|
|
15178
15063
|
walletId: authenticated.session.walletId,
|
|
@@ -15222,19 +15107,19 @@ async function handleRouterAbEcdsaOperationStepUpRoute(input) {
|
|
|
15222
15107
|
};
|
|
15223
15108
|
}
|
|
15224
15109
|
async function authorizeRouterAbEcdsaDerivationNormalSigningRoute(input) {
|
|
15225
|
-
let
|
|
15110
|
+
let parsedRequest;
|
|
15226
15111
|
try {
|
|
15227
|
-
|
|
15112
|
+
parsedRequest = parseRouterAbEcdsaOperationStepUpRequest({
|
|
15228
15113
|
phase: input.phase,
|
|
15229
15114
|
body: input.body
|
|
15230
|
-
})
|
|
15115
|
+
});
|
|
15231
15116
|
} catch (error) {
|
|
15232
15117
|
return {
|
|
15233
15118
|
ok: false,
|
|
15234
15119
|
result: routerAbStepUpError(400, "invalid_body", routerAbErrorMessage(error))
|
|
15235
15120
|
};
|
|
15236
15121
|
}
|
|
15237
|
-
if (
|
|
15122
|
+
if (parsedRequest.authorization.kind === "operation_step_up") {
|
|
15238
15123
|
const stepUp = await handleRouterAbEcdsaOperationStepUpRoute({
|
|
15239
15124
|
body: input.body,
|
|
15240
15125
|
headers: input.headers,
|
|
@@ -15258,22 +15143,12 @@ async function authorizeRouterAbEcdsaDerivationNormalSigningRoute(input) {
|
|
|
15258
15143
|
};
|
|
15259
15144
|
}
|
|
15260
15145
|
const validated = await validateRouterAbEcdsaDerivationWalletSessionInputs({
|
|
15146
|
+
materialActivation: parsedRequest.material_activation,
|
|
15261
15147
|
headers: input.headers,
|
|
15262
15148
|
authorizationSessions: input.authorizationSessions,
|
|
15263
15149
|
operationKind: "evm.sign_transaction"
|
|
15264
15150
|
});
|
|
15265
15151
|
if (!validated.ok) {
|
|
15266
|
-
if (validated.code === "wallet_session_unavailable" && input.authorizationSessions) {
|
|
15267
|
-
const exhaustedCandidate = await resolveRouterAbEcdsaExhaustedCandidateAuthorization({
|
|
15268
|
-
phase: input.phase,
|
|
15269
|
-
body: input.body,
|
|
15270
|
-
headers: input.headers,
|
|
15271
|
-
authorizationSessions: input.authorizationSessions,
|
|
15272
|
-
admissionAdapter: input.admissionAdapter,
|
|
15273
|
-
resolveEcdsaMaterialActivation: input.resolveEcdsaMaterialActivation
|
|
15274
|
-
});
|
|
15275
|
-
if (exhaustedCandidate) return exhaustedCandidate;
|
|
15276
|
-
}
|
|
15277
15152
|
const stepUp = await resolveRouterAbEcdsaOwnerOperationStepUpPreparation({
|
|
15278
15153
|
body: input.body,
|
|
15279
15154
|
phase: input.phase,
|
|
@@ -15290,10 +15165,21 @@ async function authorizeRouterAbEcdsaDerivationNormalSigningRoute(input) {
|
|
|
15290
15165
|
})
|
|
15291
15166
|
};
|
|
15292
15167
|
}
|
|
15168
|
+
if (validated.kind === "wallet_session_operation_credential_exhausted_candidate_v1") return await resolveRouterAbEcdsaExhaustedCandidateAuthorization({
|
|
15169
|
+
materialRead: validated.materialRead,
|
|
15170
|
+
policyRead: validated.policyRead,
|
|
15171
|
+
phase: input.phase,
|
|
15172
|
+
request: parsedRequest,
|
|
15173
|
+
candidate: validated.candidate,
|
|
15174
|
+
admissionAdapter: input.admissionAdapter,
|
|
15175
|
+
resolveEcdsaMaterialActivation: input.resolveEcdsaMaterialActivation
|
|
15176
|
+
});
|
|
15293
15177
|
const session = validated.admission.context.authorization.session;
|
|
15294
15178
|
const authorized = await authorizeRouterAbEcdsaWalletSessionRequest({
|
|
15179
|
+
materialRead: validated.materialRead,
|
|
15180
|
+
policyRead: validated.policyRead,
|
|
15295
15181
|
phase: input.phase,
|
|
15296
|
-
|
|
15182
|
+
request: parsedRequest,
|
|
15297
15183
|
session,
|
|
15298
15184
|
admittedMaterialActivation: routerAbMpcMaterialActivationRefToWire(validated.admission.admission.materialActivation),
|
|
15299
15185
|
admissionAdapter: input.admissionAdapter,
|
|
@@ -15445,6 +15331,164 @@ function parseRouterAbEcdsaDerivationPoolFillStepRouteRequest(raw) {
|
|
|
15445
15331
|
};
|
|
15446
15332
|
}
|
|
15447
15333
|
//#endregion
|
|
15334
|
+
//#region src/router/transport/fetch/routes/ecdsaOperationStepUpFactor.ts
|
|
15335
|
+
async function verifyEcdsaOperationStepUpFactor(input) {
|
|
15336
|
+
const proof = input.proof;
|
|
15337
|
+
switch (proof.kind) {
|
|
15338
|
+
case "passkey": {
|
|
15339
|
+
if (input.authSource.kind !== "passkey" || proof.authority.factor.credentialIdB64u !== input.authSource.credentialIdB64u) return {
|
|
15340
|
+
ok: false,
|
|
15341
|
+
response: json$1({
|
|
15342
|
+
ok: false,
|
|
15343
|
+
code: "scope_mismatch",
|
|
15344
|
+
message: "Passkey authority changed"
|
|
15345
|
+
}, { status: 403 })
|
|
15346
|
+
};
|
|
15347
|
+
const credential = proof.webauthn_authentication;
|
|
15348
|
+
if (String(credential.rawId || credential.id).trim() !== input.authSource.credentialIdB64u) return {
|
|
15349
|
+
ok: false,
|
|
15350
|
+
response: json$1({
|
|
15351
|
+
ok: false,
|
|
15352
|
+
code: "unauthorized",
|
|
15353
|
+
message: "Passkey credential changed"
|
|
15354
|
+
}, { status: 401 })
|
|
15355
|
+
};
|
|
15356
|
+
const verified = await input.webAuthn.verifyWebAuthnAuthenticationLite({
|
|
15357
|
+
userId: input.walletId,
|
|
15358
|
+
rpId: proof.authority.verifier.rpId,
|
|
15359
|
+
expectedChallenge: input.expectedChallenge,
|
|
15360
|
+
expected_origin: input.requestOrigin,
|
|
15361
|
+
webauthn_authentication: credential
|
|
15362
|
+
});
|
|
15363
|
+
if (!verified.success || !verified.verified) return {
|
|
15364
|
+
ok: false,
|
|
15365
|
+
response: json$1({
|
|
15366
|
+
ok: false,
|
|
15367
|
+
code: verified.code || "not_verified",
|
|
15368
|
+
message: verified.message || "WebAuthn authentication verification failed"
|
|
15369
|
+
}, { status: 401 })
|
|
15370
|
+
};
|
|
15371
|
+
const assertionDigest = parseDigestB64u(base64UrlEncode(await sha256BytesUtf8(alphabetizeStringify(credential))));
|
|
15372
|
+
const verifiedAtMs = Date.now();
|
|
15373
|
+
if (input.expiresAtMs <= verifiedAtMs) return expiredStepUpFactor();
|
|
15374
|
+
const factorId = parseAuthFactorId(`passkey:${input.authSource.credentialIdB64u}`);
|
|
15375
|
+
if (!factorId.ok) throw new Error(factorId.error.message);
|
|
15376
|
+
return {
|
|
15377
|
+
ok: true,
|
|
15378
|
+
factor: buildVerifiedWalletOperationPasskeyFactorResult({
|
|
15379
|
+
tenantId: input.operation.tenantId,
|
|
15380
|
+
principalId: input.operation.principalId,
|
|
15381
|
+
walletId: input.walletId,
|
|
15382
|
+
requestOrigin: input.requestOrigin,
|
|
15383
|
+
audience: input.requestOrigin,
|
|
15384
|
+
factorId: factorId.value,
|
|
15385
|
+
authorityRef: input.authorityRef,
|
|
15386
|
+
operation: input.operation,
|
|
15387
|
+
credentialIdB64u: proof.authority.factor.credentialIdB64u,
|
|
15388
|
+
assertionDigest,
|
|
15389
|
+
verifiedAtMs,
|
|
15390
|
+
expiresAtMs: input.expiresAtMs
|
|
15391
|
+
}),
|
|
15392
|
+
unseal: { kind: "not_requested" }
|
|
15393
|
+
};
|
|
15394
|
+
}
|
|
15395
|
+
case "email_otp": {
|
|
15396
|
+
const isExport = input.operation.operation.operationKind === "evm.export_key";
|
|
15397
|
+
const emailOtpOperation = isExport ? WALLET_EMAIL_OTP_EXPORT_OPERATION : WALLET_EMAIL_OTP_TRANSACTION_SIGN_OPERATION;
|
|
15398
|
+
const operationBinding = await hashEmailOtpOperationBinding({
|
|
15399
|
+
walletId: input.walletId,
|
|
15400
|
+
providerUserId: proof.authority.factor.providerUserId,
|
|
15401
|
+
orgId: input.operation.tenantId,
|
|
15402
|
+
operation: emailOtpOperation,
|
|
15403
|
+
requestOrigin: input.requestOrigin,
|
|
15404
|
+
audience: input.requestOrigin,
|
|
15405
|
+
authorityRef: input.authorityRef,
|
|
15406
|
+
...isExport ? {} : { operationFingerprintDigest: input.operation.digests.laneDigest }
|
|
15407
|
+
});
|
|
15408
|
+
const verified = await input.emailOtp.verifyEmailOtpChallenge({
|
|
15409
|
+
userId: proof.authority.factor.providerUserId,
|
|
15410
|
+
walletId: input.walletId,
|
|
15411
|
+
orgId: input.operation.tenantId,
|
|
15412
|
+
challengeId: proof.challenge_id,
|
|
15413
|
+
otpCode: proof.otp_code,
|
|
15414
|
+
otpChannel: EMAIL_OTP_CHANNEL,
|
|
15415
|
+
ownerProofBindingDigest: operationBinding,
|
|
15416
|
+
operation: emailOtpOperation
|
|
15417
|
+
});
|
|
15418
|
+
if (!verified.ok) return {
|
|
15419
|
+
ok: false,
|
|
15420
|
+
response: json$1(verified, { status: verified.code === "invalid_body" ? 400 : 401 })
|
|
15421
|
+
};
|
|
15422
|
+
let verifiedChallengeId = verified.challengeId;
|
|
15423
|
+
if (!isExport) {
|
|
15424
|
+
const orgId = parseOrgId(input.operation.tenantId);
|
|
15425
|
+
const providerSubject = parseProviderSubject(proof.authority.factor.providerUserId);
|
|
15426
|
+
if (!orgId.ok) throw new Error(orgId.error.message);
|
|
15427
|
+
if (!providerSubject.ok) throw new Error(providerSubject.error.message);
|
|
15428
|
+
const consumed = await input.emailOtp.consumeEmailOtpGrant({
|
|
15429
|
+
subject: {
|
|
15430
|
+
kind: "provider_identity",
|
|
15431
|
+
orgId: orgId.value,
|
|
15432
|
+
providerSubject: providerSubject.value,
|
|
15433
|
+
walletId: input.walletId
|
|
15434
|
+
},
|
|
15435
|
+
loginGrant: verified.loginGrant,
|
|
15436
|
+
otpChannel: EMAIL_OTP_CHANNEL
|
|
15437
|
+
});
|
|
15438
|
+
if (!consumed.ok) return {
|
|
15439
|
+
ok: false,
|
|
15440
|
+
response: json$1(consumed, { status: consumed.code === "invalid_body" ? 400 : 401 })
|
|
15441
|
+
};
|
|
15442
|
+
verifiedChallengeId = consumed.challengeId;
|
|
15443
|
+
}
|
|
15444
|
+
const verificationReceiptDigest = parseDigestB64u(base64UrlEncode(await sha256BytesUtf8(alphabetizeStringify({
|
|
15445
|
+
challengeId: verifiedChallengeId,
|
|
15446
|
+
operationFingerprint: input.expectedChallenge
|
|
15447
|
+
}))));
|
|
15448
|
+
const verifiedAtMs = Date.now();
|
|
15449
|
+
const expiresAtMs = Math.min(input.expiresAtMs, verified.grantExpiresAtMs);
|
|
15450
|
+
if (expiresAtMs <= verifiedAtMs) return expiredStepUpFactor();
|
|
15451
|
+
const factorId = parseAuthFactorId(`email_otp:${proof.authority.factor.provider}:${proof.authority.factor.providerUserId}`);
|
|
15452
|
+
const challengeId = parseEmailOtpChallengeId(verifiedChallengeId);
|
|
15453
|
+
if (!factorId.ok) throw new Error(factorId.error.message);
|
|
15454
|
+
if (!challengeId.ok) throw new Error(challengeId.error.message);
|
|
15455
|
+
return {
|
|
15456
|
+
ok: true,
|
|
15457
|
+
factor: buildVerifiedWalletOperationEmailOtpFactorResult({
|
|
15458
|
+
tenantId: input.operation.tenantId,
|
|
15459
|
+
principalId: input.operation.principalId,
|
|
15460
|
+
walletId: input.walletId,
|
|
15461
|
+
requestOrigin: input.requestOrigin,
|
|
15462
|
+
audience: input.requestOrigin,
|
|
15463
|
+
factorId: factorId.value,
|
|
15464
|
+
authorityRef: input.authorityRef,
|
|
15465
|
+
operation: input.operation,
|
|
15466
|
+
challengeId: challengeId.value,
|
|
15467
|
+
verificationReceiptDigest,
|
|
15468
|
+
verifiedAtMs,
|
|
15469
|
+
expiresAtMs
|
|
15470
|
+
}),
|
|
15471
|
+
unseal: isExport ? {
|
|
15472
|
+
kind: "email_otp_grant",
|
|
15473
|
+
grant: verified.loginGrant,
|
|
15474
|
+
challenge_id: verified.challengeId
|
|
15475
|
+
} : { kind: "not_requested" }
|
|
15476
|
+
};
|
|
15477
|
+
}
|
|
15478
|
+
default: throw new Error("Unsupported ECDSA operation step-up proof");
|
|
15479
|
+
}
|
|
15480
|
+
}
|
|
15481
|
+
function expiredStepUpFactor() {
|
|
15482
|
+
return {
|
|
15483
|
+
ok: false,
|
|
15484
|
+
response: json$1({
|
|
15485
|
+
ok: false,
|
|
15486
|
+
code: "verified_step_up_rejected",
|
|
15487
|
+
message: "Operation step-up authorization expired"
|
|
15488
|
+
}, { status: 403 })
|
|
15489
|
+
};
|
|
15490
|
+
}
|
|
15491
|
+
//#endregion
|
|
15448
15492
|
//#region ../shared-ts/src/signing-lanes/recordParsers.ts
|
|
15449
15493
|
const WALLET_KEY_COMMON_FIELDS = [
|
|
15450
15494
|
"kind",
|
|
@@ -15860,18 +15904,13 @@ async function executeRouterAbEcdsaDerivationNormalSigningRoute(input, timing) {
|
|
|
15860
15904
|
binding: await ecdsaOperationStepUpBinding(input.ctx, authorization.session, authorizedOperation)
|
|
15861
15905
|
});
|
|
15862
15906
|
} else {
|
|
15907
|
+
const request = input.phase === "prepare" ? parseRouterAbEcdsaDerivationEvmDigestSigningRequestV1(input.body) : parseRouterAbEcdsaDerivationEvmDigestSigningFinalizeRequestV1(input.body);
|
|
15863
15908
|
const operation = await admitRouterAbEcdsaReusableWalletSessionOperation({
|
|
15864
|
-
|
|
15865
|
-
|
|
15866
|
-
|
|
15867
|
-
|
|
15868
|
-
|
|
15869
|
-
} : {
|
|
15870
|
-
kind: "wallet_session_operation_credential_exhausted_candidate_v1",
|
|
15871
|
-
candidate: authorization.candidate
|
|
15872
|
-
},
|
|
15873
|
-
authorizedOperations: input.ctx.service.authorizedOperations,
|
|
15874
|
-
resolveEcdsaMaterialActivation: input.ctx.service.walletRegistration.resolveEcdsaMaterialActivation.bind(input.ctx.service.walletRegistration)
|
|
15909
|
+
phase: input.phase,
|
|
15910
|
+
request,
|
|
15911
|
+
material: authorization.activeMaterial,
|
|
15912
|
+
binding: authorization,
|
|
15913
|
+
authorizedOperations: input.ctx.service.authorizedOperations
|
|
15875
15914
|
});
|
|
15876
15915
|
if (!operation.ok) {
|
|
15877
15916
|
const failureBody = operation.error.body;
|
|
@@ -15897,11 +15936,6 @@ async function executeRouterAbEcdsaDerivationNormalSigningRoute(input, timing) {
|
|
|
15897
15936
|
return json$1(failure.body, { status: failure.status });
|
|
15898
15937
|
}
|
|
15899
15938
|
if (operation.admission.kind === "replayed") return routerAbEcdsaReplayResponse(operation.admission.operation);
|
|
15900
|
-
if (operation.admission.kind === "claimed" && input.phase === "finalize") return json$1({
|
|
15901
|
-
ok: false,
|
|
15902
|
-
code: "authorized_operation_missing",
|
|
15903
|
-
message: "ECDSA finalize requires a claimed prepare operation"
|
|
15904
|
-
}, { status: 409 });
|
|
15905
15939
|
const ownerDecision = decideRouterAbEcdsaOwnerOperationAuthorization({ operation: operation.admission.operation });
|
|
15906
15940
|
switch (ownerDecision.kind) {
|
|
15907
15941
|
case "authorized": break;
|
|
@@ -16126,6 +16160,7 @@ async function issueEcdsaOperationStepUpAuthorization(input) {
|
|
|
16126
16160
|
message: v2Resolution.message
|
|
16127
16161
|
}, { status: 403 });
|
|
16128
16162
|
const activeMaterial = v2Resolution.kind === "admitted" ? v2Resolution.activeMaterial : await input.ctx.service.walletRegistration.resolveEcdsaMaterialActivation({
|
|
16163
|
+
source: { kind: "database" },
|
|
16129
16164
|
walletId: operation.wallet_id,
|
|
16130
16165
|
materialActivation: operation.material_activation
|
|
16131
16166
|
});
|
|
@@ -16215,7 +16250,6 @@ async function issueEcdsaOperationStepUpAuthorization(input) {
|
|
|
16215
16250
|
}, { status: 400 });
|
|
16216
16251
|
}
|
|
16217
16252
|
const expectedChallenge = await computeRouterAbEcdsaOperationStepUpChallengeB64u(operation);
|
|
16218
|
-
const nowMs = Date.now();
|
|
16219
16253
|
const requestId = operation.operation_id;
|
|
16220
16254
|
let freshMaterial;
|
|
16221
16255
|
if (v2Resolution.kind === "admitted") {
|
|
@@ -16256,112 +16290,24 @@ async function issueEcdsaOperationStepUpAuthorization(input) {
|
|
|
16256
16290
|
const evidenceSetId = requireAuthorizationValue$1(parseAuthorizationEvidenceSetId(`ecdsa-step-up-evidence-set:${requestId}`));
|
|
16257
16291
|
const expiresAtMs = operation.expires_at_ms;
|
|
16258
16292
|
const requestOrigin = authenticated.requestOrigin;
|
|
16259
|
-
|
|
16260
|
-
|
|
16261
|
-
|
|
16262
|
-
|
|
16263
|
-
|
|
16264
|
-
|
|
16265
|
-
|
|
16266
|
-
|
|
16267
|
-
|
|
16268
|
-
|
|
16269
|
-
|
|
16270
|
-
|
|
16271
|
-
|
|
16272
|
-
message: "Passkey credential changed"
|
|
16273
|
-
}, { status: 401 });
|
|
16274
|
-
const verified = await input.ctx.service.webAuthn.verifyWebAuthnAuthenticationLite({
|
|
16275
|
-
userId: authenticated.session.walletId,
|
|
16276
|
-
rpId: proof.authority.verifier.rpId,
|
|
16277
|
-
expectedChallenge,
|
|
16278
|
-
expected_origin: requestOrigin,
|
|
16279
|
-
webauthn_authentication: credential
|
|
16280
|
-
});
|
|
16281
|
-
if (!verified.success || !verified.verified) return json$1({
|
|
16282
|
-
ok: false,
|
|
16283
|
-
code: verified.code || "not_verified",
|
|
16284
|
-
message: verified.message || "WebAuthn authentication verification failed"
|
|
16285
|
-
}, { status: 401 });
|
|
16286
|
-
factor = buildVerifiedWalletOperationPasskeyFactorResult({
|
|
16287
|
-
tenantId: authenticated.session.tenantId,
|
|
16288
|
-
principalId: authenticated.session.principalId,
|
|
16289
|
-
walletId: walletIdFromString(authenticated.session.walletId),
|
|
16290
|
-
requestOrigin,
|
|
16291
|
-
audience: requestOrigin,
|
|
16292
|
-
factorId: requireAuthorizationValue$1(parseAuthFactorId(`passkey:${authenticated.session.laneAuthorization.authSource.credentialIdB64u}`)),
|
|
16293
|
-
authorityRef: authenticated.authorityRef,
|
|
16294
|
-
operation: envelope,
|
|
16295
|
-
credentialIdB64u: proof.authority.factor.credentialIdB64u,
|
|
16296
|
-
assertionDigest: parseDigestB64u(base64UrlEncode(await sha256BytesUtf8(alphabetizeStringify(credential)))),
|
|
16297
|
-
verifiedAtMs: nowMs,
|
|
16298
|
-
expiresAtMs
|
|
16299
|
-
});
|
|
16300
|
-
break;
|
|
16301
|
-
}
|
|
16302
|
-
case "email_otp": {
|
|
16303
|
-
const operationBinding = await hashEmailOtpOperationBinding({
|
|
16304
|
-
walletId: authenticated.session.walletId,
|
|
16305
|
-
providerUserId: proof.authority.factor.providerUserId,
|
|
16306
|
-
orgId: authenticated.session.tenantId,
|
|
16307
|
-
operation: operation.operation_kind === "evm.export_key" ? WALLET_EMAIL_OTP_EXPORT_OPERATION : WALLET_EMAIL_OTP_TRANSACTION_SIGN_OPERATION,
|
|
16308
|
-
requestOrigin,
|
|
16309
|
-
audience: requestOrigin,
|
|
16310
|
-
authorityRef: authenticated.authorityRef,
|
|
16311
|
-
...operation.operation_kind === "evm.sign_transaction" ? { operationFingerprintDigest: envelope.digests.laneDigest } : {}
|
|
16312
|
-
});
|
|
16313
|
-
const verified = await input.ctx.service.emailOtp.verifyEmailOtpChallenge({
|
|
16314
|
-
userId: proof.authority.factor.providerUserId,
|
|
16315
|
-
walletId: authenticated.session.walletId,
|
|
16316
|
-
orgId: authenticated.session.tenantId,
|
|
16317
|
-
challengeId: proof.challenge_id,
|
|
16318
|
-
otpCode: proof.otp_code,
|
|
16319
|
-
otpChannel: EMAIL_OTP_CHANNEL,
|
|
16320
|
-
ownerProofBindingDigest: operationBinding,
|
|
16321
|
-
operation: operation.operation_kind === "evm.export_key" ? WALLET_EMAIL_OTP_EXPORT_OPERATION : WALLET_EMAIL_OTP_TRANSACTION_SIGN_OPERATION
|
|
16322
|
-
});
|
|
16323
|
-
if (!verified.ok) return json$1(verified, { status: verified.code === "invalid_body" ? 400 : 401 });
|
|
16324
|
-
const consumed = operation.operation_kind === "evm.export_key" ? null : await input.ctx.service.emailOtp.consumeEmailOtpGrant({
|
|
16325
|
-
subject: {
|
|
16326
|
-
kind: "provider_identity",
|
|
16327
|
-
orgId: requireAuthorizationValue$1(parseOrgId(authenticated.session.tenantId)),
|
|
16328
|
-
providerSubject: requireAuthorizationValue$1(parseProviderSubject(proof.authority.factor.providerUserId)),
|
|
16329
|
-
walletId: walletIdFromString(authenticated.session.walletId)
|
|
16330
|
-
},
|
|
16331
|
-
loginGrant: verified.loginGrant,
|
|
16332
|
-
otpChannel: EMAIL_OTP_CHANNEL
|
|
16333
|
-
});
|
|
16334
|
-
if (consumed && !consumed.ok) return json$1(consumed, { status: consumed.code === "invalid_body" ? 400 : 401 });
|
|
16335
|
-
if (operation.operation_kind === "evm.export_key") emailOtpUnseal = {
|
|
16336
|
-
grant: verified.loginGrant,
|
|
16337
|
-
challengeId: verified.challengeId
|
|
16338
|
-
};
|
|
16339
|
-
const verifiedChallengeId = consumed?.ok ? consumed.challengeId : verified.challengeId;
|
|
16340
|
-
factor = buildVerifiedWalletOperationEmailOtpFactorResult({
|
|
16341
|
-
tenantId: authenticated.session.tenantId,
|
|
16342
|
-
principalId: authenticated.session.principalId,
|
|
16343
|
-
walletId: walletIdFromString(authenticated.session.walletId),
|
|
16344
|
-
requestOrigin,
|
|
16345
|
-
audience: requestOrigin,
|
|
16346
|
-
factorId: requireAuthorizationValue$1(parseAuthFactorId(`email_otp:${proof.authority.factor.provider}:${proof.authority.factor.providerUserId}`)),
|
|
16347
|
-
authorityRef: authenticated.authorityRef,
|
|
16348
|
-
operation: envelope,
|
|
16349
|
-
challengeId: requireAuthorizationValue$1(parseEmailOtpChallengeId(verifiedChallengeId)),
|
|
16350
|
-
verificationReceiptDigest: parseDigestB64u(base64UrlEncode(await sha256BytesUtf8(alphabetizeStringify({
|
|
16351
|
-
challengeId: verifiedChallengeId,
|
|
16352
|
-
operationFingerprint: expectedChallenge
|
|
16353
|
-
})))),
|
|
16354
|
-
verifiedAtMs: nowMs,
|
|
16355
|
-
expiresAtMs: Math.min(expiresAtMs, verified.grantExpiresAtMs)
|
|
16356
|
-
});
|
|
16357
|
-
break;
|
|
16358
|
-
}
|
|
16359
|
-
}
|
|
16293
|
+
const verifiedFactor = await verifyEcdsaOperationStepUpFactor({
|
|
16294
|
+
proof,
|
|
16295
|
+
operation: envelope,
|
|
16296
|
+
walletId: walletIdFromString(authenticated.session.walletId),
|
|
16297
|
+
authorityRef: authenticated.authorityRef,
|
|
16298
|
+
authSource: authenticated.session.laneAuthorization.authSource,
|
|
16299
|
+
requestOrigin,
|
|
16300
|
+
expectedChallenge,
|
|
16301
|
+
expiresAtMs,
|
|
16302
|
+
webAuthn: input.ctx.service.webAuthn,
|
|
16303
|
+
emailOtp: input.ctx.service.emailOtp
|
|
16304
|
+
});
|
|
16305
|
+
if (!verifiedFactor.ok) return verifiedFactor.response;
|
|
16360
16306
|
const evidenceSet = await input.ctx.service.authorizedOperations.recordVerifiedWalletOperationFactorEvidenceSet({
|
|
16361
16307
|
operation: envelope,
|
|
16362
16308
|
evidenceId,
|
|
16363
16309
|
evidenceSetId,
|
|
16364
|
-
factor
|
|
16310
|
+
factor: verifiedFactor.factor
|
|
16365
16311
|
});
|
|
16366
16312
|
const authorizedOperationId = requireAuthorizationValue$1(parseAuthorizedOperationId(`ecdsa-step-up-authorized-operation:${operation.operation_id}`));
|
|
16367
16313
|
const atomicOperation = await input.ctx.service.authorizedOperations.admitAuthorizedOperation({
|
|
@@ -16375,7 +16321,7 @@ async function issueEcdsaOperationStepUpAuthorization(input) {
|
|
|
16375
16321
|
evidenceSetDigest: evidenceSet.evidenceSetDigest
|
|
16376
16322
|
},
|
|
16377
16323
|
quota: { kind: "quota_neutral" },
|
|
16378
|
-
claimedAtMs:
|
|
16324
|
+
claimedAtMs: Date.now()
|
|
16379
16325
|
},
|
|
16380
16326
|
material: {
|
|
16381
16327
|
walletId: walletIdFromString(authenticated.session.walletId),
|
|
@@ -16408,11 +16354,7 @@ async function issueEcdsaOperationStepUpAuthorization(input) {
|
|
|
16408
16354
|
const responseAuthorization = {
|
|
16409
16355
|
kind: "operation_step_up",
|
|
16410
16356
|
evidence_set_digest: evidenceSet.evidenceSetDigest,
|
|
16411
|
-
unseal:
|
|
16412
|
-
kind: "email_otp_grant",
|
|
16413
|
-
grant: emailOtpUnseal.grant,
|
|
16414
|
-
challenge_id: emailOtpUnseal.challengeId
|
|
16415
|
-
} : { kind: "not_requested" }
|
|
16357
|
+
unseal: verifiedFactor.unseal
|
|
16416
16358
|
};
|
|
16417
16359
|
if (operation.operation_kind === "evm.export_key") {
|
|
16418
16360
|
const exportTopology = v2Resolution.kind === "admitted" && v2Resolution.operationKind === "evm.export_key" ? v2Resolution.exportTopology : await resolveStrictEcdsaExportTopology({
|
|
@@ -16444,7 +16386,6 @@ async function issueEcdsaOperationStepUpAuthorization(input) {
|
|
|
16444
16386
|
async function handleEcdsaPoolFillRoute(input) {
|
|
16445
16387
|
const startedAt = performance.now();
|
|
16446
16388
|
const timing = {
|
|
16447
|
-
queue: null,
|
|
16448
16389
|
authenticate: null,
|
|
16449
16390
|
material: null,
|
|
16450
16391
|
admit: null,
|
|
@@ -16479,31 +16420,24 @@ async function executeEcdsaPoolFillRoute(input, timing, workerTimings) {
|
|
|
16479
16420
|
const parsed = input.phase === "init" ? parseRouterAbEcdsaDerivationPoolFillInitRouteRequest(input.body) : parseRouterAbEcdsaDerivationPoolFillStepRouteRequest(input.body);
|
|
16480
16421
|
if (!parsed.ok) return json$1(parsed.body, { status: thresholdEcdsaStatusCode(parsed.body) });
|
|
16481
16422
|
const request = parsed.request;
|
|
16482
|
-
const
|
|
16483
|
-
|
|
16484
|
-
|
|
16485
|
-
|
|
16486
|
-
|
|
16487
|
-
|
|
16488
|
-
|
|
16489
|
-
|
|
16490
|
-
|
|
16491
|
-
|
|
16492
|
-
|
|
16493
|
-
|
|
16494
|
-
|
|
16495
|
-
|
|
16496
|
-
|
|
16497
|
-
|
|
16498
|
-
|
|
16499
|
-
|
|
16500
|
-
onServerTiming: collectEcdsaPresignWorkerTiming.bind(void 0, workerTimings)
|
|
16501
|
-
});
|
|
16502
|
-
timing.proxy = performance.now() - proxyStartedAt;
|
|
16503
|
-
return json$1(result, { status: thresholdEcdsaStatusCode(result) });
|
|
16504
|
-
} finally {
|
|
16505
|
-
gateTicket.release();
|
|
16506
|
-
}
|
|
16423
|
+
const authorized = await authorizeEcdsaPoolFill({
|
|
16424
|
+
ctx: input.ctx,
|
|
16425
|
+
request,
|
|
16426
|
+
timing
|
|
16427
|
+
});
|
|
16428
|
+
if (!authorized.ok) return json$1(authorized.error.body, { status: authorized.error.status });
|
|
16429
|
+
const proxyStartedAt = performance.now();
|
|
16430
|
+
const result = "poolFill" in request ? await runtime.initializePoolFill({
|
|
16431
|
+
binding: authorized.binding,
|
|
16432
|
+
request: ecdsaPoolFillInitRuntimeRequest(request),
|
|
16433
|
+
onServerTiming: collectEcdsaPresignWorkerTiming.bind(void 0, workerTimings)
|
|
16434
|
+
}) : await runtime.advancePoolFill({
|
|
16435
|
+
binding: authorized.binding,
|
|
16436
|
+
request: ecdsaPoolFillStepRuntimeRequest(request),
|
|
16437
|
+
onServerTiming: collectEcdsaPresignWorkerTiming.bind(void 0, workerTimings)
|
|
16438
|
+
});
|
|
16439
|
+
timing.proxy = performance.now() - proxyStartedAt;
|
|
16440
|
+
return json$1(result, { status: thresholdEcdsaStatusCode(result) });
|
|
16507
16441
|
}
|
|
16508
16442
|
function poolFillMaterialActivation(request) {
|
|
16509
16443
|
return "poolFill" in request ? request.poolFill.scope.material_activation : null;
|
|
@@ -16642,6 +16576,7 @@ async function authorizeEcdsaPoolFill(input) {
|
|
|
16642
16576
|
const admitted = validated;
|
|
16643
16577
|
const materialStartedAt = performance.now();
|
|
16644
16578
|
const activeMaterial = await input.ctx.service.walletRegistration.resolveEcdsaMaterialActivation({
|
|
16579
|
+
source: { kind: "database" },
|
|
16645
16580
|
walletId: String(session.walletId),
|
|
16646
16581
|
materialActivation: routerAbMpcMaterialActivationRefToWire(admitted.materialActivation)
|
|
16647
16582
|
});
|
|
@@ -16730,43 +16665,6 @@ function ecdsaPoolFillStepRuntimeRequest(request) {
|
|
|
16730
16665
|
...request.requestTag === void 0 ? {} : { requestTag: request.requestTag }
|
|
16731
16666
|
};
|
|
16732
16667
|
}
|
|
16733
|
-
function resolvePresignPriorityTurn(resolve) {
|
|
16734
|
-
setTimeout(resolve, 5);
|
|
16735
|
-
}
|
|
16736
|
-
function waitForPresignPriorityTurn() {
|
|
16737
|
-
return new Promise(resolvePresignPriorityTurn);
|
|
16738
|
-
}
|
|
16739
|
-
var PresignPriorityGate = class {
|
|
16740
|
-
constructor() {
|
|
16741
|
-
this.foregroundInFlight = 0;
|
|
16742
|
-
this.backgroundInFlight = 0;
|
|
16743
|
-
}
|
|
16744
|
-
async acquire(trafficClass) {
|
|
16745
|
-
if (trafficClass === "foreground") {
|
|
16746
|
-
this.foregroundInFlight += 1;
|
|
16747
|
-
return this.createTicket("foreground");
|
|
16748
|
-
}
|
|
16749
|
-
while (!this.canRunBackgroundNow()) await waitForPresignPriorityTurn();
|
|
16750
|
-
this.backgroundInFlight += 1;
|
|
16751
|
-
return this.createTicket("background");
|
|
16752
|
-
}
|
|
16753
|
-
createTicket(trafficClass) {
|
|
16754
|
-
let released = false;
|
|
16755
|
-
return { release: () => {
|
|
16756
|
-
if (released) return;
|
|
16757
|
-
released = true;
|
|
16758
|
-
if (trafficClass === "foreground") this.foregroundInFlight = Math.max(0, this.foregroundInFlight - 1);
|
|
16759
|
-
else this.backgroundInFlight = Math.max(0, this.backgroundInFlight - 1);
|
|
16760
|
-
} };
|
|
16761
|
-
}
|
|
16762
|
-
canRunBackgroundNow() {
|
|
16763
|
-
return this.foregroundInFlight === 0 && this.backgroundInFlight === 0;
|
|
16764
|
-
}
|
|
16765
|
-
};
|
|
16766
|
-
function resolvePresignTrafficClass(requestTag) {
|
|
16767
|
-
return requestTag === "background_presign_pool_refill" ? "background" : "foreground";
|
|
16768
|
-
}
|
|
16769
|
-
const presignPriorityGate = new PresignPriorityGate();
|
|
16770
16668
|
function strictEcdsaAuthorizationFailureStatus(failure) {
|
|
16771
16669
|
switch (failure.code) {
|
|
16772
16670
|
case "unauthorized": return 401;
|
|
@@ -17149,6 +17047,7 @@ async function authorizeStrictEcdsaExport(input) {
|
|
|
17149
17047
|
scope: operation.normal_signing_scope
|
|
17150
17048
|
})) return strictEcdsaExportFailure(403, "scope_mismatch", "ECDSA export operation scope does not match the request");
|
|
17151
17049
|
const activeMaterial = await input.ctx.service.walletRegistration.resolveEcdsaMaterialActivation({
|
|
17050
|
+
source: { kind: "database" },
|
|
17152
17051
|
walletId: operation.wallet_id,
|
|
17153
17052
|
materialActivation: input.request.material_activation
|
|
17154
17053
|
});
|
|
@@ -17453,7 +17352,6 @@ async function handleThresholdEcdsa(ctx) {
|
|
|
17453
17352
|
}
|
|
17454
17353
|
//#endregion
|
|
17455
17354
|
//#region src/router/domains/emailOtp/emailOtpRouteHandlers.ts
|
|
17456
|
-
const EMAIL_OTP_FACTOR_RELEASE_AAD_DOMAIN = "seams/email-otp/factor-release/v1";
|
|
17457
17355
|
function decodeEmailOtpFactorSecret32(value) {
|
|
17458
17356
|
const magnitude = base64UrlDecode(value);
|
|
17459
17357
|
if (magnitude.length === 0 || magnitude.length > 32) {
|
|
@@ -17467,7 +17365,7 @@ function decodeEmailOtpFactorSecret32(value) {
|
|
|
17467
17365
|
}
|
|
17468
17366
|
function emailOtpFactorReleaseAad(input) {
|
|
17469
17367
|
return new TextEncoder().encode([
|
|
17470
|
-
|
|
17368
|
+
EMAIL_OTP_FACTOR_RELEASE_AAD_DOMAIN_V1,
|
|
17471
17369
|
input.walletId,
|
|
17472
17370
|
input.enrollmentId,
|
|
17473
17371
|
input.enrollmentSealKeyVersion,
|
|
@@ -17481,19 +17379,11 @@ async function sealEmailOtpFactorSecretForWorker(input) {
|
|
|
17481
17379
|
factorSecret32 = decodeEmailOtpFactorSecret32(input.factorSecret32B64u);
|
|
17482
17380
|
workerPublicKey65 = base64UrlDecode(input.workerEphemeralPublicKey65B64u);
|
|
17483
17381
|
} catch {
|
|
17484
|
-
return
|
|
17485
|
-
ok: false,
|
|
17486
|
-
code: "invalid_body",
|
|
17487
|
-
message: "Email OTP factor release key is invalid"
|
|
17488
|
-
};
|
|
17382
|
+
return failure("invalid_body", "Email OTP factor release key is invalid");
|
|
17489
17383
|
}
|
|
17490
17384
|
if (workerPublicKey65.length !== 65 || workerPublicKey65[0] !== 4) {
|
|
17491
17385
|
factorSecret32.fill(0);
|
|
17492
|
-
return
|
|
17493
|
-
ok: false,
|
|
17494
|
-
code: "invalid_body",
|
|
17495
|
-
message: "Email OTP factor release key is invalid"
|
|
17496
|
-
};
|
|
17386
|
+
return failure("invalid_body", "Email OTP factor release key is invalid");
|
|
17497
17387
|
}
|
|
17498
17388
|
try {
|
|
17499
17389
|
const workerPublicKey = await crypto.subtle.importKey("raw", workerPublicKey65, {
|
|
@@ -17525,11 +17415,7 @@ async function sealEmailOtpFactorSecretForWorker(input) {
|
|
|
17525
17415
|
ciphertextB64u: base64UrlEncode(ciphertext)
|
|
17526
17416
|
};
|
|
17527
17417
|
} catch {
|
|
17528
|
-
return
|
|
17529
|
-
ok: false,
|
|
17530
|
-
code: "factor_release_failed",
|
|
17531
|
-
message: "Email OTP factor release encryption failed"
|
|
17532
|
-
};
|
|
17418
|
+
return failure("factor_release_failed", "Email OTP factor release encryption failed");
|
|
17533
17419
|
} finally {
|
|
17534
17420
|
factorSecret32.fill(0);
|
|
17535
17421
|
}
|
|
@@ -17541,11 +17427,7 @@ async function handleEmailOtpDevCleanupGoogleRegistrationRoute(input) {
|
|
|
17541
17427
|
const code = verified.code || "not_verified";
|
|
17542
17428
|
return {
|
|
17543
17429
|
status: code === "internal" ? 500 : code === "not_configured" || code === "unsupported" ? 501 : code === "invalid_body" ? 400 : 401,
|
|
17544
|
-
body:
|
|
17545
|
-
ok: false,
|
|
17546
|
-
code,
|
|
17547
|
-
message: verified.message || "Google login failed"
|
|
17548
|
-
}
|
|
17430
|
+
body: failure(code, verified.message || "Google login failed")
|
|
17549
17431
|
};
|
|
17550
17432
|
}
|
|
17551
17433
|
const runtimePolicyScope = isPlainObject(body.runtimePolicyScope) ? body.runtimePolicyScope : null;
|
|
@@ -17562,30 +17444,18 @@ async function handleEmailOtpDevCleanupGoogleRegistrationRoute(input) {
|
|
|
17562
17444
|
async function handleEmailOtpRegistrationSealRoute(input) {
|
|
17563
17445
|
if (!isPlainObject(input.body)) return {
|
|
17564
17446
|
status: 400,
|
|
17565
|
-
body:
|
|
17566
|
-
ok: false,
|
|
17567
|
-
code: "invalid_body",
|
|
17568
|
-
message: "Invalid body"
|
|
17569
|
-
}
|
|
17447
|
+
body: failure("invalid_body", "Invalid body")
|
|
17570
17448
|
};
|
|
17571
17449
|
const allowedFields = new Set(["walletId", "wrappedCiphertext"]);
|
|
17572
17450
|
for (const field of Object.keys(input.body)) if (!allowedFields.has(field)) return {
|
|
17573
17451
|
status: 400,
|
|
17574
|
-
body: {
|
|
17575
|
-
ok: false,
|
|
17576
|
-
code: "invalid_body",
|
|
17577
|
-
message: `Unsupported field: ${field}`
|
|
17578
|
-
}
|
|
17452
|
+
body: failure("invalid_body", `Unsupported field: ${field}`)
|
|
17579
17453
|
};
|
|
17580
17454
|
const walletId = normalizeOptionalTrimmedString(input.body.walletId);
|
|
17581
17455
|
const wrappedCiphertext = normalizeOptionalTrimmedString(input.body.wrappedCiphertext);
|
|
17582
17456
|
if (!walletId || !wrappedCiphertext) return {
|
|
17583
17457
|
status: 400,
|
|
17584
|
-
body:
|
|
17585
|
-
ok: false,
|
|
17586
|
-
code: "invalid_body",
|
|
17587
|
-
message: "Missing walletId or wrappedCiphertext"
|
|
17588
|
-
}
|
|
17458
|
+
body: failure("invalid_body", "Missing walletId or wrappedCiphertext")
|
|
17589
17459
|
};
|
|
17590
17460
|
const result = await input.service.applyEmailOtpServerSeal({ wrappedCiphertext });
|
|
17591
17461
|
return {
|
|
@@ -17599,11 +17469,7 @@ async function handleEmailOtpRegistrationSealRoute(input) {
|
|
|
17599
17469
|
async function handleEmailOtpDevOutboxRoute(input) {
|
|
17600
17470
|
if (!isPlainObject(input.body)) return {
|
|
17601
17471
|
status: 400,
|
|
17602
|
-
body:
|
|
17603
|
-
ok: false,
|
|
17604
|
-
code: "invalid_body",
|
|
17605
|
-
message: "Invalid body"
|
|
17606
|
-
}
|
|
17472
|
+
body: failure("invalid_body", "Invalid body")
|
|
17607
17473
|
};
|
|
17608
17474
|
const allowedFields = new Set([
|
|
17609
17475
|
"idToken",
|
|
@@ -17613,11 +17479,7 @@ async function handleEmailOtpDevOutboxRoute(input) {
|
|
|
17613
17479
|
]);
|
|
17614
17480
|
for (const field of Object.keys(input.body)) if (!allowedFields.has(field)) return {
|
|
17615
17481
|
status: 400,
|
|
17616
|
-
body: {
|
|
17617
|
-
ok: false,
|
|
17618
|
-
code: "invalid_body",
|
|
17619
|
-
message: `Unsupported field: ${field}`
|
|
17620
|
-
}
|
|
17482
|
+
body: failure("invalid_body", `Unsupported field: ${field}`)
|
|
17621
17483
|
};
|
|
17622
17484
|
const idToken = normalizeOptionalTrimmedString(input.body.idToken);
|
|
17623
17485
|
const walletId = normalizeOptionalTrimmedString(input.body.walletId);
|
|
@@ -17625,30 +17487,18 @@ async function handleEmailOtpDevOutboxRoute(input) {
|
|
|
17625
17487
|
const challengeSubjectId = normalizeOptionalTrimmedString(input.body.challengeSubjectId);
|
|
17626
17488
|
if (!idToken || !walletId) return {
|
|
17627
17489
|
status: 400,
|
|
17628
|
-
body:
|
|
17629
|
-
ok: false,
|
|
17630
|
-
code: "invalid_body",
|
|
17631
|
-
message: "Missing idToken or walletId"
|
|
17632
|
-
}
|
|
17490
|
+
body: failure("invalid_body", "Missing idToken or walletId")
|
|
17633
17491
|
};
|
|
17634
17492
|
if (challengeSubjectId && !challengeId) return {
|
|
17635
17493
|
status: 400,
|
|
17636
|
-
body:
|
|
17637
|
-
ok: false,
|
|
17638
|
-
code: "invalid_body",
|
|
17639
|
-
message: "challengeSubjectId requires the exact challengeId it belongs to"
|
|
17640
|
-
}
|
|
17494
|
+
body: failure("invalid_body", "challengeSubjectId requires the exact challengeId it belongs to")
|
|
17641
17495
|
};
|
|
17642
17496
|
const verified = await input.service.verifyGoogleLogin({ idToken });
|
|
17643
17497
|
if (!verified.ok || !verified.verified || !verified.userId) {
|
|
17644
17498
|
const code = verified.code || "not_verified";
|
|
17645
17499
|
return {
|
|
17646
17500
|
status: code === "internal" ? 500 : code === "not_configured" ? 501 : 401,
|
|
17647
|
-
body:
|
|
17648
|
-
ok: false,
|
|
17649
|
-
code,
|
|
17650
|
-
message: verified.message || "Google login failed"
|
|
17651
|
-
}
|
|
17501
|
+
body: failure(code, verified.message || "Google login failed")
|
|
17652
17502
|
};
|
|
17653
17503
|
}
|
|
17654
17504
|
const result = await input.service.readEmailOtpOutboxEntry({
|
|
@@ -17894,6 +17744,7 @@ async function resolveWalletEmailOtpChallengeSignerSelection(args) {
|
|
|
17894
17744
|
};
|
|
17895
17745
|
}
|
|
17896
17746
|
const resolved = await args.ctx.service.walletRegistration.resolveEcdsaMaterialActivation({
|
|
17747
|
+
source: { kind: "database" },
|
|
17897
17748
|
walletId: String(args.authority.walletId),
|
|
17898
17749
|
materialActivation: routerAbMpcMaterialActivationRefToWire(ecdsaActivation.materialActivation)
|
|
17899
17750
|
});
|
|
@@ -19078,7 +18929,12 @@ function bootstrapError(code, message, status) {
|
|
|
19078
18929
|
//#region src/router/transport/fetch/routes/syncAccount.ts
|
|
19079
18930
|
function syncAccountResponseStatus(result) {
|
|
19080
18931
|
if (result.ok && result.verified) return 200;
|
|
19081
|
-
|
|
18932
|
+
return syncAccountFailureStatus(result.code);
|
|
18933
|
+
}
|
|
18934
|
+
function syncAccountFailureStatus(code) {
|
|
18935
|
+
switch (code) {
|
|
18936
|
+
case "wallet_home_unavailable": return 503;
|
|
18937
|
+
case "wallet_home_conflict": return 409;
|
|
19082
18938
|
case "internal": return 500;
|
|
19083
18939
|
case "ed25519_not_provisioned": return 409;
|
|
19084
18940
|
default: return 400;
|
|
@@ -19108,7 +18964,7 @@ async function handleSyncAccount(ctx) {
|
|
|
19108
18964
|
const parsed = parseSyncAccountOptionsRequest(await readJson(ctx.request));
|
|
19109
18965
|
if (!parsed.ok) return json$1(parsed.body, { status: parsed.status });
|
|
19110
18966
|
const result = await ctx.service.webAuthn.createWebAuthnSyncAccountOptions(parsed.request);
|
|
19111
|
-
return json$1(result, { status: result.ok ? 200 : result.code
|
|
18967
|
+
return json$1(result, { status: result.ok ? 200 : syncAccountFailureStatus(result.code) });
|
|
19112
18968
|
}
|
|
19113
18969
|
if (ctx.pathname === "/sync-account/verify") {
|
|
19114
18970
|
const parsed = parseSyncAccountVerifyRequest({
|
|
@@ -19120,11 +18976,7 @@ async function handleSyncAccount(ctx) {
|
|
|
19120
18976
|
let responseBody = result;
|
|
19121
18977
|
if (result.ok && result.verified && result.thresholdEd25519) {
|
|
19122
18978
|
const custodyKeyManifestDigestB64u = result.custodyKeyManifestDigestB64u;
|
|
19123
|
-
if (!custodyKeyManifestDigestB64u) return
|
|
19124
|
-
ok: false,
|
|
19125
|
-
code: "internal",
|
|
19126
|
-
message: "Sync verification did not resolve the wallet key manifest"
|
|
19127
|
-
}, { status: 500 });
|
|
18979
|
+
if (!custodyKeyManifestDigestB64u) return jsonFailure(500, "internal", "Sync verification did not resolve the wallet key manifest");
|
|
19128
18980
|
const thresholdEd25519 = result.thresholdEd25519;
|
|
19129
18981
|
const walletId = String(result.walletId || "").trim();
|
|
19130
18982
|
const nearAccountId = String(result.nearAccountId || "").trim();
|
|
@@ -19132,11 +18984,7 @@ async function handleSyncAccount(ctx) {
|
|
|
19132
18984
|
const signerSlot = Number(result.signerSlot);
|
|
19133
18985
|
const walletBinding = result.walletBinding;
|
|
19134
18986
|
const credentialIdB64u = String(result.credentialIdB64u || "").trim();
|
|
19135
|
-
if (!thresholdEd25519 || !walletId || !nearAccountId || !nearEd25519SigningKeyId || !Number.isSafeInteger(signerSlot) || signerSlot < 1 || !walletBinding || !credentialIdB64u || !String(result.publicKey || "").trim() || !String(result.credentialPublicKeyB64u || "").trim() || String(walletBinding.walletId) !== walletId || String(walletBinding.nearAccountId) !== nearAccountId || String(walletBinding.nearEd25519SigningKeyId) !== nearEd25519SigningKeyId || walletBinding.signerSlot !== signerSlot) return
|
|
19136
|
-
ok: false,
|
|
19137
|
-
code: "internal",
|
|
19138
|
-
message: "verified passkey wallet is missing its Ed25519 Yao identity"
|
|
19139
|
-
}, { status: 500 });
|
|
18987
|
+
if (!thresholdEd25519 || !walletId || !nearAccountId || !nearEd25519SigningKeyId || !Number.isSafeInteger(signerSlot) || signerSlot < 1 || !walletBinding || !credentialIdB64u || !String(result.publicKey || "").trim() || !String(result.credentialPublicKeyB64u || "").trim() || String(walletBinding.walletId) !== walletId || String(walletBinding.nearAccountId) !== nearAccountId || String(walletBinding.nearEd25519SigningKeyId) !== nearEd25519SigningKeyId || walletBinding.signerSlot !== signerSlot) return jsonFailure(500, "internal", "verified passkey wallet is missing its Ed25519 Yao identity");
|
|
19140
18988
|
const authority = passkeyWalletAuthAuthorityForMethod({
|
|
19141
18989
|
walletId: walletBinding.walletId,
|
|
19142
18990
|
rpId: walletBinding.rpId,
|
|
@@ -19148,29 +18996,17 @@ async function handleSyncAccount(ctx) {
|
|
|
19148
18996
|
rpId: authority.verifier.rpId,
|
|
19149
18997
|
credentialIdB64u: authority.factor.credentialIdB64u
|
|
19150
18998
|
});
|
|
19151
|
-
if (!activeAuthority.ok || activeAuthority.walletAuthority.authorityId !== result.walletAuthorityId || activeAuthority.authMethod.walletAuthMethodId !== result.walletAuthMethodId) return
|
|
19152
|
-
ok: false,
|
|
19153
|
-
code: "internal",
|
|
19154
|
-
message: "Verified passkey wallet authority is unavailable"
|
|
19155
|
-
}, { status: 500 });
|
|
18999
|
+
if (!activeAuthority.ok || activeAuthority.walletAuthority.authorityId !== result.walletAuthorityId || activeAuthority.authMethod.walletAuthMethodId !== result.walletAuthMethodId) return jsonFailure(500, "internal", "Verified passkey wallet authority is unavailable");
|
|
19156
19000
|
const authorityRef = await walletAuthAuthorityRef({ authority });
|
|
19157
19001
|
const principalId = parsePrincipalId(walletId);
|
|
19158
19002
|
const mintId = parseWalletSessionMintId(parsed.request.challengeId);
|
|
19159
|
-
if (!principalId.ok || !mintId.ok) return
|
|
19160
|
-
ok: false,
|
|
19161
|
-
code: "internal",
|
|
19162
|
-
message: "Verified passkey Wallet Session identity is invalid"
|
|
19163
|
-
}, { status: 500 });
|
|
19003
|
+
if (!principalId.ok || !mintId.ok) return jsonFailure(500, "internal", "Verified passkey Wallet Session identity is invalid");
|
|
19164
19004
|
const issuedAtMs = Date.now();
|
|
19165
19005
|
const expiresAtMs = issuedAtMs + DEFAULT_WALLET_SESSION_TTL_MS;
|
|
19166
19006
|
const origin = parseSessionOrigin(parsed.request.expected_origin);
|
|
19167
19007
|
const factorId = parseAuthFactorId(`passkey:${credentialIdB64u}`);
|
|
19168
19008
|
const credentialId = parseWebAuthnCredentialIdB64u(credentialIdB64u);
|
|
19169
|
-
if (!factorId.ok || !credentialId.ok) return
|
|
19170
|
-
ok: false,
|
|
19171
|
-
code: "internal",
|
|
19172
|
-
message: "Verified passkey factor identity is invalid"
|
|
19173
|
-
}, { status: 500 });
|
|
19009
|
+
if (!factorId.ok || !credentialId.ok) return jsonFailure(500, "internal", "Verified passkey factor identity is invalid");
|
|
19174
19010
|
const proof = await ctx.service.authorizedOperations.buildVerifiedOwnerProof({
|
|
19175
19011
|
purpose: "wallet_session",
|
|
19176
19012
|
proofId: parseVerifiedOwnerProofId(`sync-account:${parsed.request.challengeId}`),
|
|
@@ -19188,11 +19024,7 @@ async function handleSyncAccount(ctx) {
|
|
|
19188
19024
|
expiresAtMs
|
|
19189
19025
|
})
|
|
19190
19026
|
});
|
|
19191
|
-
if (proof.purpose !== "wallet_session") return
|
|
19192
|
-
ok: false,
|
|
19193
|
-
code: "internal",
|
|
19194
|
-
message: "Owner proof purpose is invalid"
|
|
19195
|
-
}, { status: 500 });
|
|
19027
|
+
if (proof.purpose !== "wallet_session") return jsonFailure(500, "internal", "Owner proof purpose is invalid");
|
|
19196
19028
|
const bootstrap = await issueSyncAccountBootstrapV1({
|
|
19197
19029
|
ctx,
|
|
19198
19030
|
result: {
|
|
@@ -19233,11 +19065,7 @@ async function handleSyncAccount(ctx) {
|
|
|
19233
19065
|
message: "Wallet Session sync is already committed; retry the exact method",
|
|
19234
19066
|
...bootstrap.committed
|
|
19235
19067
|
}, { status: 409 });
|
|
19236
|
-
if (bootstrap.kind === "error") return
|
|
19237
|
-
ok: false,
|
|
19238
|
-
code: bootstrap.code,
|
|
19239
|
-
message: bootstrap.message
|
|
19240
|
-
}, { status: bootstrap.status });
|
|
19068
|
+
if (bootstrap.kind === "error") return jsonFailure(bootstrap.status, bootstrap.code, bootstrap.message);
|
|
19241
19069
|
responseBody = bootstrap.body;
|
|
19242
19070
|
}
|
|
19243
19071
|
return json$1(responseBody, { status: syncAccountResponseStatus(result) });
|
|
@@ -21780,11 +21608,13 @@ async function handleOwnerWalletExecutionLanePreflight(ctx) {
|
|
|
21780
21608
|
};
|
|
21781
21609
|
} else {
|
|
21782
21610
|
const validated = await validateRouterAbEcdsaDerivationWalletSessionInputs({
|
|
21611
|
+
materialActivation: routerAbMpcMaterialActivationRefToWire(request.expectedMaterialActivation),
|
|
21783
21612
|
headers,
|
|
21784
21613
|
authorizationSessions: ctx.service.authorizationSessions,
|
|
21785
21614
|
operationKind: EVM_ECDSA_MPC_OPERATION_KINDS.signTransaction
|
|
21786
21615
|
});
|
|
21787
21616
|
if (!validated.ok) return validationFailure(validated);
|
|
21617
|
+
if (validated.kind === "wallet_session_operation_credential_exhausted_candidate_v1") return validationFailure(walletSessionFailure("wallet_session_unavailable"));
|
|
21788
21618
|
walletIdRaw = String(validated.admission.context.authorization.session.walletId);
|
|
21789
21619
|
authorization = {
|
|
21790
21620
|
kind: "wallet_auth_method",
|
|
@@ -21832,22 +21662,14 @@ async function handleWebAuthnAuthenticators(ctx) {
|
|
|
21832
21662
|
if (ctx.pathname !== "/webauthn/authenticators") return null;
|
|
21833
21663
|
try {
|
|
21834
21664
|
const token = extractBearerCredential(ctx.request.headers);
|
|
21835
|
-
if (!token) return
|
|
21836
|
-
ok: false,
|
|
21837
|
-
code: "unauthorized",
|
|
21838
|
-
message: "No valid Wallet Session"
|
|
21839
|
-
}, { status: 401 });
|
|
21665
|
+
if (!token) return jsonFailure(401, "unauthorized", "No valid Wallet Session");
|
|
21840
21666
|
const nowMs = Date.now();
|
|
21841
21667
|
const exact = await ctx.service.authorizationSessions.readWalletSessionAuthorizationV2ByOperationCredential({
|
|
21842
21668
|
tenantId: ctx.service.authorizationSessions.tenantId,
|
|
21843
21669
|
token,
|
|
21844
21670
|
nowMs
|
|
21845
21671
|
});
|
|
21846
|
-
if (!exact) return
|
|
21847
|
-
ok: false,
|
|
21848
|
-
code: "unauthorized",
|
|
21849
|
-
message: "No valid Wallet Session"
|
|
21850
|
-
}, { status: 401 });
|
|
21672
|
+
if (!exact) return jsonFailure(401, "unauthorized", "No valid Wallet Session");
|
|
21851
21673
|
const rpIdFromQuery = String(ctx.url.searchParams.get("rpId") || ctx.url.searchParams.get("rp_id") || "").trim();
|
|
21852
21674
|
const result = await ctx.service.webAuthn.listWebAuthnAuthenticatorsForUser({
|
|
21853
21675
|
userId: String(exact.authorization.session.walletId),
|
|
@@ -21856,11 +21678,7 @@ async function handleWebAuthnAuthenticators(ctx) {
|
|
|
21856
21678
|
if (!result.ok) return json$1(result, { status: result.code === "not_supported" ? 501 : result.code === "invalid_args" ? 400 : 500 });
|
|
21857
21679
|
return json$1(result, { status: 200 });
|
|
21858
21680
|
} catch (e) {
|
|
21859
|
-
return
|
|
21860
|
-
ok: false,
|
|
21861
|
-
code: "internal",
|
|
21862
|
-
message: e?.message || "Internal error"
|
|
21863
|
-
}, { status: 500 });
|
|
21681
|
+
return jsonFailure(500, "internal", e?.message || "Internal error");
|
|
21864
21682
|
}
|
|
21865
21683
|
}
|
|
21866
21684
|
//#endregion
|
|
@@ -21939,23 +21757,15 @@ function parseOptionalPositiveInteger(raw, fieldName) {
|
|
|
21939
21757
|
value: Math.floor(value)
|
|
21940
21758
|
};
|
|
21941
21759
|
}
|
|
21942
|
-
function parseAuthProviderAction(input) {
|
|
21943
|
-
const provider = normalizeOptionalTrimmedString(input.provider);
|
|
21944
|
-
const action = normalizeOptionalTrimmedString(input.action);
|
|
21945
|
-
if (provider === "passkey" && action === "options") return { kind: "passkey_options" };
|
|
21946
|
-
if (provider === "passkey" && action === "verify") return { kind: "passkey_verify" };
|
|
21947
|
-
if (provider === "google" && action === "options") return { kind: "google_options" };
|
|
21948
|
-
if (provider === "google" && action === "verify") return { kind: "google_verify" };
|
|
21949
|
-
if (provider === "github" && action === "options") return { kind: "github_options" };
|
|
21950
|
-
return null;
|
|
21951
|
-
}
|
|
21952
21760
|
function parseAuthProviderActionPath(pathname) {
|
|
21953
|
-
|
|
21954
|
-
|
|
21955
|
-
|
|
21956
|
-
|
|
21957
|
-
|
|
21958
|
-
|
|
21761
|
+
switch (pathname) {
|
|
21762
|
+
case "/auth/passkey/options": return { kind: "passkey_options" };
|
|
21763
|
+
case "/auth/passkey/verify": return { kind: "passkey_verify" };
|
|
21764
|
+
case "/auth/google/options": return { kind: "google_options" };
|
|
21765
|
+
case "/auth/google/verify": return { kind: "google_verify" };
|
|
21766
|
+
case "/auth/github/options": return { kind: "github_options" };
|
|
21767
|
+
default: return null;
|
|
21768
|
+
}
|
|
21959
21769
|
}
|
|
21960
21770
|
function parsePasskeyLoginOptionsRequest(raw) {
|
|
21961
21771
|
const body = requireJsonObject(raw);
|
|
@@ -22133,11 +21943,7 @@ async function requireExactWalletSession(ctx) {
|
|
|
22133
21943
|
const token = extractBearerCredential(ctx.request.headers);
|
|
22134
21944
|
if (!token) return {
|
|
22135
21945
|
ok: false,
|
|
22136
|
-
response:
|
|
22137
|
-
ok: false,
|
|
22138
|
-
code: "unauthorized",
|
|
22139
|
-
message: "No valid Wallet Session"
|
|
22140
|
-
}, { status: 401 })
|
|
21946
|
+
response: jsonFailure(401, "unauthorized", "No valid Wallet Session")
|
|
22141
21947
|
};
|
|
22142
21948
|
try {
|
|
22143
21949
|
const context = await ctx.service.authorizationSessions.readWalletSessionAuthorizationV2ByOperationCredential({
|
|
@@ -22147,11 +21953,7 @@ async function requireExactWalletSession(ctx) {
|
|
|
22147
21953
|
});
|
|
22148
21954
|
if (!context) return {
|
|
22149
21955
|
ok: false,
|
|
22150
|
-
response:
|
|
22151
|
-
ok: false,
|
|
22152
|
-
code: "unauthorized",
|
|
22153
|
-
message: "No valid Wallet Session"
|
|
22154
|
-
}, { status: 401 })
|
|
21956
|
+
response: jsonFailure(401, "unauthorized", "No valid Wallet Session")
|
|
22155
21957
|
};
|
|
22156
21958
|
return {
|
|
22157
21959
|
ok: true,
|
|
@@ -22160,11 +21962,7 @@ async function requireExactWalletSession(ctx) {
|
|
|
22160
21962
|
} catch {
|
|
22161
21963
|
return {
|
|
22162
21964
|
ok: false,
|
|
22163
|
-
response:
|
|
22164
|
-
ok: false,
|
|
22165
|
-
code: "wallet_session_unavailable",
|
|
22166
|
-
message: "Wallet Session is unavailable"
|
|
22167
|
-
}, { status: 503 })
|
|
21965
|
+
response: jsonFailure(503, "wallet_session_unavailable", "Wallet Session is unavailable")
|
|
22168
21966
|
};
|
|
22169
21967
|
}
|
|
22170
21968
|
}
|
|
@@ -22177,19 +21975,11 @@ async function requireExactPasskeyStepUp(input) {
|
|
|
22177
21975
|
const walletId = String(input.context.authorization.session.walletId);
|
|
22178
21976
|
if (String(result.userId).trim() !== walletId) return {
|
|
22179
21977
|
ok: false,
|
|
22180
|
-
response:
|
|
22181
|
-
ok: false,
|
|
22182
|
-
code: "forbidden",
|
|
22183
|
-
message: "Step-up user mismatch"
|
|
22184
|
-
}, { status: 403 })
|
|
21978
|
+
response: jsonFailure(403, "forbidden", "Step-up user mismatch")
|
|
22185
21979
|
};
|
|
22186
21980
|
if (result.walletAuthMethodId !== input.context.authMethod.walletAuthMethodId || result.walletAuthorityId !== input.context.authority.authorityId) return {
|
|
22187
21981
|
ok: false,
|
|
22188
|
-
response:
|
|
22189
|
-
ok: false,
|
|
22190
|
-
code: "forbidden",
|
|
22191
|
-
message: "Step-up authority mismatch"
|
|
22192
|
-
}, { status: 403 })
|
|
21982
|
+
response: jsonFailure(403, "forbidden", "Step-up authority mismatch")
|
|
22193
21983
|
};
|
|
22194
21984
|
return { ok: true };
|
|
22195
21985
|
}
|
|
@@ -22247,11 +22037,7 @@ async function handleAuth(ctx) {
|
|
|
22247
22037
|
default: assertNeverAuthIdentityMutation(command);
|
|
22248
22038
|
}
|
|
22249
22039
|
const subject = command.request.subject;
|
|
22250
|
-
if (subject.startsWith("near:")) return
|
|
22251
|
-
ok: false,
|
|
22252
|
-
code: "not_supported",
|
|
22253
|
-
message: "near: subjects cannot be unlinked"
|
|
22254
|
-
}, { status: 400 });
|
|
22040
|
+
if (subject.startsWith("near:")) return jsonFailure(400, "not_supported", "near: subjects cannot be unlinked");
|
|
22255
22041
|
const out = await ctx.service.identity.unlinkIdentity({
|
|
22256
22042
|
userId: walletId,
|
|
22257
22043
|
subject
|
|
@@ -22274,6 +22060,8 @@ async function handleAuth(ctx) {
|
|
|
22274
22060
|
const parsed = parsePasskeyLoginOptionsRequest(await readJson(ctx.request));
|
|
22275
22061
|
if (!parsed.ok) return json$1(parsed.body, { status: parsed.status });
|
|
22276
22062
|
const result = await ctx.service.webAuthn.createWebAuthnLoginOptions(parsed.request);
|
|
22063
|
+
if (result.code === "wallet_home_unavailable") return json$1(result, { status: 503 });
|
|
22064
|
+
if (result.code === "wallet_home_conflict") return json$1(result, { status: 409 });
|
|
22277
22065
|
return json$1(result, { status: result.ok ? 200 : result.code === "internal" ? 500 : 400 });
|
|
22278
22066
|
}
|
|
22279
22067
|
case "passkey_verify": {
|
|
@@ -22308,16 +22096,8 @@ async function handleAuth(ctx) {
|
|
|
22308
22096
|
publishableKeyAuth: ctx.opts.publishableKeyAuth,
|
|
22309
22097
|
orgProjectEnv: ctx.opts.orgProjectEnv
|
|
22310
22098
|
});
|
|
22311
|
-
if (!runtimePolicyScope.ok) return
|
|
22312
|
-
|
|
22313
|
-
code: runtimePolicyScope.code,
|
|
22314
|
-
message: runtimePolicyScope.message
|
|
22315
|
-
}, { status: runtimePolicyScope.status });
|
|
22316
|
-
if (!runtimePolicyScope.scope) return json$1({
|
|
22317
|
-
ok: false,
|
|
22318
|
-
code: "runtime_policy_scope_unavailable",
|
|
22319
|
-
message: "Google Email OTP requires an active managed runtime policy scope"
|
|
22320
|
-
}, { status: 500 });
|
|
22099
|
+
if (!runtimePolicyScope.ok) return jsonFailure(runtimePolicyScope.status, runtimePolicyScope.code, runtimePolicyScope.message);
|
|
22100
|
+
if (!runtimePolicyScope.scope) return jsonFailure(500, "runtime_policy_scope_unavailable", "Google Email OTP requires an active managed runtime policy scope");
|
|
22321
22101
|
const result = await ctx.service.identity.verifyGoogleLogin(parsed.request);
|
|
22322
22102
|
if (!result.ok || !result.verified || !result.providerSubject) return json$1(result, { status: result.code === "internal" ? 500 : 400 });
|
|
22323
22103
|
const resolution = await ctx.service.identity.resolveGoogleEmailOtpSession({
|
|
@@ -22334,40 +22114,6 @@ async function handleAuth(ctx) {
|
|
|
22334
22114
|
}
|
|
22335
22115
|
}
|
|
22336
22116
|
//#endregion
|
|
22337
|
-
//#region src/router/transport/fetch/routes/nearPublicKeys.ts
|
|
22338
|
-
async function handleNearPublicKeys(ctx) {
|
|
22339
|
-
if (ctx.method !== "GET") return null;
|
|
22340
|
-
if (ctx.pathname !== "/near/public-keys") return null;
|
|
22341
|
-
try {
|
|
22342
|
-
const token = extractBearerCredential(ctx.request.headers);
|
|
22343
|
-
if (!token) return json$1({
|
|
22344
|
-
ok: false,
|
|
22345
|
-
code: "unauthorized",
|
|
22346
|
-
message: "No valid Wallet Session"
|
|
22347
|
-
}, { status: 401 });
|
|
22348
|
-
const nowMs = Date.now();
|
|
22349
|
-
const exact = await ctx.service.authorizationSessions.readWalletSessionAuthorizationV2ByOperationCredential({
|
|
22350
|
-
tenantId: ctx.service.authorizationSessions.tenantId,
|
|
22351
|
-
token,
|
|
22352
|
-
nowMs
|
|
22353
|
-
});
|
|
22354
|
-
if (!exact) return json$1({
|
|
22355
|
-
ok: false,
|
|
22356
|
-
code: "unauthorized",
|
|
22357
|
-
message: "No valid Wallet Session"
|
|
22358
|
-
}, { status: 401 });
|
|
22359
|
-
const result = await ctx.service.nearFunding.listNearPublicKeysForUser({ userId: String(exact.authorization.session.walletId) });
|
|
22360
|
-
if (!result.ok) return json$1(result, { status: result.code === "not_supported" ? 501 : result.code === "invalid_args" ? 400 : 500 });
|
|
22361
|
-
return json$1(result, { status: 200 });
|
|
22362
|
-
} catch (e) {
|
|
22363
|
-
return json$1({
|
|
22364
|
-
ok: false,
|
|
22365
|
-
code: "internal",
|
|
22366
|
-
message: e?.message || "Internal error"
|
|
22367
|
-
}, { status: 500 });
|
|
22368
|
-
}
|
|
22369
|
-
}
|
|
22370
|
-
//#endregion
|
|
22371
22117
|
//#region src/router/framework/ror/normalize.ts
|
|
22372
22118
|
function sanitizeRorOrigins(origins) {
|
|
22373
22119
|
const list = Array.isArray(origins) ? origins : [];
|
|
@@ -22482,10 +22228,166 @@ async function handleWellKnown(ctx) {
|
|
|
22482
22228
|
});
|
|
22483
22229
|
}
|
|
22484
22230
|
//#endregion
|
|
22231
|
+
//#region src/router/transport/fetch/routes/deviceLinkingResponses.ts
|
|
22232
|
+
function projectLinkSessionStateV1(state) {
|
|
22233
|
+
switch (state.state) {
|
|
22234
|
+
case "displaying_qr": return { state: "displaying_qr" };
|
|
22235
|
+
case "claimed":
|
|
22236
|
+
case "awaiting_target_factor":
|
|
22237
|
+
case "awaiting_source_contribution":
|
|
22238
|
+
case "provisioning": return {
|
|
22239
|
+
state: state.state,
|
|
22240
|
+
deviceId: state.deviceId
|
|
22241
|
+
};
|
|
22242
|
+
case "authority_pending_local_install": return {
|
|
22243
|
+
state: "authority_pending_local_install",
|
|
22244
|
+
deviceId: state.deviceId,
|
|
22245
|
+
authorityId: state.authorityId,
|
|
22246
|
+
packageSetDigestB64u: state.packageSetDigestB64u
|
|
22247
|
+
};
|
|
22248
|
+
case "active": return {
|
|
22249
|
+
state: "active",
|
|
22250
|
+
deviceId: state.deviceId,
|
|
22251
|
+
authorityId: state.authorityId,
|
|
22252
|
+
activatedAtMs: state.activatedAtMs
|
|
22253
|
+
};
|
|
22254
|
+
case "failed_before_commit": return {
|
|
22255
|
+
state: "failed_before_commit",
|
|
22256
|
+
error: state.error
|
|
22257
|
+
};
|
|
22258
|
+
case "cancelled": return {
|
|
22259
|
+
state: "cancelled",
|
|
22260
|
+
cancelledAtMs: state.cancelledAtMs
|
|
22261
|
+
};
|
|
22262
|
+
case "expired": return {
|
|
22263
|
+
state: "expired",
|
|
22264
|
+
expiredAtMs: state.expiredAtMs
|
|
22265
|
+
};
|
|
22266
|
+
default: return assertNeverLinkSessionStateV1(state);
|
|
22267
|
+
}
|
|
22268
|
+
}
|
|
22269
|
+
function projectSession(record) {
|
|
22270
|
+
return {
|
|
22271
|
+
kind: "linked_device_session_projection_v1",
|
|
22272
|
+
linkSessionId: record.linkSessionId,
|
|
22273
|
+
qrPayload: record.qrPayload,
|
|
22274
|
+
revision: record.revision,
|
|
22275
|
+
createdAtMs: record.createdAtMs,
|
|
22276
|
+
updatedAtMs: record.updatedAtMs,
|
|
22277
|
+
state: projectLinkSessionStateV1(record.state)
|
|
22278
|
+
};
|
|
22279
|
+
}
|
|
22280
|
+
function invalidStateResponse(record) {
|
|
22281
|
+
return json$1({
|
|
22282
|
+
ok: false,
|
|
22283
|
+
outcome: "invalid_state",
|
|
22284
|
+
state: record.state.state,
|
|
22285
|
+
session: projectSession(record)
|
|
22286
|
+
}, { status: 409 });
|
|
22287
|
+
}
|
|
22288
|
+
function sessionProjectionResponse(record, outcome) {
|
|
22289
|
+
return json$1({
|
|
22290
|
+
ok: true,
|
|
22291
|
+
outcome,
|
|
22292
|
+
session: projectSession(record)
|
|
22293
|
+
}, { status: 200 });
|
|
22294
|
+
}
|
|
22295
|
+
function targetCredentialResultResponse(record, outcome, targetCredential) {
|
|
22296
|
+
return json$1({
|
|
22297
|
+
ok: true,
|
|
22298
|
+
outcome,
|
|
22299
|
+
targetCredential,
|
|
22300
|
+
session: projectSession(record)
|
|
22301
|
+
}, { status: 200 });
|
|
22302
|
+
}
|
|
22303
|
+
function exportRootWriteResponse(result) {
|
|
22304
|
+
return result.outcome === "conflict" ? json$1({
|
|
22305
|
+
ok: false,
|
|
22306
|
+
code: result.reason ?? "conflict",
|
|
22307
|
+
message: "export-root relay conflict"
|
|
22308
|
+
}, { status: 409 }) : json$1({
|
|
22309
|
+
ok: true,
|
|
22310
|
+
outcome: result.outcome
|
|
22311
|
+
}, { status: 200 });
|
|
22312
|
+
}
|
|
22313
|
+
function invalidInputResponse(message) {
|
|
22314
|
+
return json$1({
|
|
22315
|
+
ok: false,
|
|
22316
|
+
outcome: "invalid_input",
|
|
22317
|
+
code: "invalid_input",
|
|
22318
|
+
message
|
|
22319
|
+
}, { status: 400 });
|
|
22320
|
+
}
|
|
22321
|
+
function notSupportedResponse(message = "Device linking is not configured") {
|
|
22322
|
+
return json$1({
|
|
22323
|
+
ok: false,
|
|
22324
|
+
code: "not_supported",
|
|
22325
|
+
message
|
|
22326
|
+
}, { status: 501 });
|
|
22327
|
+
}
|
|
22328
|
+
function notFoundResponse() {
|
|
22329
|
+
return json$1({
|
|
22330
|
+
ok: false,
|
|
22331
|
+
code: "not_found",
|
|
22332
|
+
message: "Linked-device session not found"
|
|
22333
|
+
}, { status: 404 });
|
|
22334
|
+
}
|
|
22335
|
+
function methodNotAllowedResponse$2() {
|
|
22336
|
+
return json$1({
|
|
22337
|
+
ok: false,
|
|
22338
|
+
code: "method_not_allowed",
|
|
22339
|
+
message: "Method is not allowed"
|
|
22340
|
+
}, { status: 405 });
|
|
22341
|
+
}
|
|
22342
|
+
function authDeniedResponse$2(result) {
|
|
22343
|
+
if (result.code === "unavailable") return json$1({
|
|
22344
|
+
ok: false,
|
|
22345
|
+
code: result.code,
|
|
22346
|
+
message: result.message
|
|
22347
|
+
}, { status: 503 });
|
|
22348
|
+
return json$1({
|
|
22349
|
+
ok: false,
|
|
22350
|
+
outcome: "unauthorized",
|
|
22351
|
+
code: result.code,
|
|
22352
|
+
message: result.message
|
|
22353
|
+
}, { status: result.code === "expired" ? 410 : 401 });
|
|
22354
|
+
}
|
|
22355
|
+
//#endregion
|
|
22356
|
+
//#region src/core/deviceLinking/linkedDeviceBootstrap.ts
|
|
22357
|
+
function linkedDeviceBootstrapFailure(error) {
|
|
22358
|
+
if (error && typeof error === "object" && "code" in error && (error.code === "home_conflict" || error.code === "home_unavailable")) return error.code;
|
|
22359
|
+
return null;
|
|
22360
|
+
}
|
|
22361
|
+
//#endregion
|
|
22362
|
+
//#region ../shared-ts/src/utils/exactKeys.ts
|
|
22363
|
+
/**
|
|
22364
|
+
* True when `value` is a non-array object whose own enumerable string keys are exactly `keys`.
|
|
22365
|
+
*
|
|
22366
|
+
* A key whose value is `undefined` still counts as present. Symbol, non-enumerable and inherited
|
|
22367
|
+
* keys are not counted, and the prototype is not checked. A list that repeats a key never matches.
|
|
22368
|
+
* Kept apart from validation.ts, which the wallet iframe's boot path loads.
|
|
22369
|
+
*/
|
|
22370
|
+
function hasExactKeys$1(value, keys) {
|
|
22371
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
|
|
22372
|
+
const actual = Object.keys(value);
|
|
22373
|
+
return actual.length === keys.length && actual.every((key) => keys.includes(key));
|
|
22374
|
+
}
|
|
22375
|
+
//#endregion
|
|
22485
22376
|
//#region src/core/deviceLinking/requestProof.ts
|
|
22486
22377
|
function parseLinkedDeviceRequestProofV1(raw) {
|
|
22487
22378
|
if (raw === null || typeof raw !== "object" || Array.isArray(raw)) throw new Error("linked-device request proof must be an object");
|
|
22488
|
-
if (!
|
|
22379
|
+
if (!hasExactKeys$1(raw, [
|
|
22380
|
+
"kind",
|
|
22381
|
+
"linkSessionId",
|
|
22382
|
+
"devicePublicKeyDigestB64u",
|
|
22383
|
+
"requestNonceB64u",
|
|
22384
|
+
"method",
|
|
22385
|
+
"canonicalPath",
|
|
22386
|
+
"bodyDigestB64u",
|
|
22387
|
+
"issuedAtMs",
|
|
22388
|
+
"expiresAtMs",
|
|
22389
|
+
"signatureB64u"
|
|
22390
|
+
])) throw new Error("record contains invalid fields");
|
|
22489
22391
|
const record = raw;
|
|
22490
22392
|
if (record.kind !== "linked_device_request_proof_v1") throw new Error("linked-device request proof kind is invalid");
|
|
22491
22393
|
const linkSessionId = parseSessionId$1(record.linkSessionId);
|
|
@@ -22542,9 +22444,6 @@ function parseFixedB64u(raw, expectedBytes, field) {
|
|
|
22542
22444
|
if (bytes.length !== expectedBytes || base64UrlEncode(bytes) !== raw) throw new Error(`${field} is invalid`);
|
|
22543
22445
|
return raw;
|
|
22544
22446
|
}
|
|
22545
|
-
function isLinkedDeviceRequestProofRecordV1(value) {
|
|
22546
|
-
return Object.keys(value).sort().join("|") === "bodyDigestB64u|canonicalPath|devicePublicKeyDigestB64u|expiresAtMs|issuedAtMs|kind|linkSessionId|method|requestNonceB64u|signatureB64u";
|
|
22547
|
-
}
|
|
22548
22447
|
//#endregion
|
|
22549
22448
|
//#region src/router/transport/fetch/routes/deviceLinking.ts
|
|
22550
22449
|
const DEVICE_LINKING_BASE = "/wallet/device-linking/v1/sessions";
|
|
@@ -22581,6 +22480,11 @@ async function handleDeviceLinking(ctx) {
|
|
|
22581
22480
|
default: return assertNever$1(action);
|
|
22582
22481
|
}
|
|
22583
22482
|
} catch (error) {
|
|
22483
|
+
const bootstrapFailure = linkedDeviceBootstrapFailure(error);
|
|
22484
|
+
if (bootstrapFailure) return sessionResultResponse({
|
|
22485
|
+
outcome: bootstrapFailure,
|
|
22486
|
+
message: "Linked-device bootstrap authority failed"
|
|
22487
|
+
});
|
|
22584
22488
|
if (error instanceof DeviceLinkingInputError) return invalidInputResponse(error.message);
|
|
22585
22489
|
return json$1({
|
|
22586
22490
|
ok: false,
|
|
@@ -22592,7 +22496,7 @@ async function handleDeviceLinking(ctx) {
|
|
|
22592
22496
|
async function handleCreate(ctx, service, nowMs) {
|
|
22593
22497
|
if (ctx.method !== "POST") return methodNotAllowedResponse$2();
|
|
22594
22498
|
const bodyDigestB64u = await requestBodyDigest$1(ctx.request);
|
|
22595
|
-
const rawBody = await
|
|
22499
|
+
const rawBody = await readJson(ctx.request);
|
|
22596
22500
|
const body = parseBoundary$1(() => parseCreateRequest(rawBody));
|
|
22597
22501
|
const keyDigest = await computeDevicePublicKeyDigestB64u(body.payload.devicePublicKeyB64u);
|
|
22598
22502
|
const proof = parseBoundary$1(() => parseRequestProofHeader(ctx.request));
|
|
@@ -22669,7 +22573,7 @@ async function handleApproval(ctx, service, rawLinkSessionId, nowMs) {
|
|
|
22669
22573
|
});
|
|
22670
22574
|
if (!session) return notFoundResponse();
|
|
22671
22575
|
const ownerMismatch = requireOwnerMatchesClaimedWallet(authentication.owner, session);
|
|
22672
|
-
if (ownerMismatch) return ownerMismatch;
|
|
22576
|
+
if (ownerMismatch) return authDeniedResponse$2(ownerMismatch);
|
|
22673
22577
|
if (authentication.owner.walletId !== approval.walletId) return authDeniedResponse$2({
|
|
22674
22578
|
kind: "denied",
|
|
22675
22579
|
code: "unauthorized",
|
|
@@ -22753,6 +22657,7 @@ async function handleCredential(ctx, service, rawLinkSessionId, nowMs) {
|
|
|
22753
22657
|
async function handleSourceContributionPreparation(ctx, service, rawLinkSessionId, nowMs) {
|
|
22754
22658
|
const owner = await authenticateOwnerForSession(ctx, service, parseSessionId(rawLinkSessionId), nowMs);
|
|
22755
22659
|
if (owner.kind !== "authorized") return ownerSessionResponse(owner);
|
|
22660
|
+
if (isLinkSessionTerminalFailureV1(owner.session.state)) return invalidStateResponse(owner.session);
|
|
22756
22661
|
if (ctx.method !== "GET") return methodNotAllowedResponse$2();
|
|
22757
22662
|
const preparation = owner.session.sourceContributionPreparation;
|
|
22758
22663
|
if (!preparation) return new Response(null, { status: 204 });
|
|
@@ -22803,10 +22708,6 @@ async function handleSourceContribution(ctx, service, rawLinkSessionId, nowMs) {
|
|
|
22803
22708
|
}));
|
|
22804
22709
|
return sessionProjectionResponse(committed.session, committed.kind === "replayed" ? "replayed" : recorded.outcome);
|
|
22805
22710
|
}
|
|
22806
|
-
/**
|
|
22807
|
-
* A precommit failure's reason is a single token. The installer's message
|
|
22808
|
-
* keeps its words, joined, so the session still says what failed.
|
|
22809
|
-
*/
|
|
22810
22711
|
function precommitFailureReasonV1(message) {
|
|
22811
22712
|
const token = message.trim().replace(/\s+/g, "_").replace(/[\u0000-\u001f\u007f]/g, "");
|
|
22812
22713
|
return token.length > 0 ? token : "authority_commit_failed";
|
|
@@ -22815,6 +22716,7 @@ async function handleSourceContributionExecute(ctx, service, rawLinkSessionId, n
|
|
|
22815
22716
|
if (ctx.method !== "POST") return methodNotAllowedResponse$2();
|
|
22816
22717
|
const owner = await authenticateOwnerForSession(ctx, service, parseSessionId(rawLinkSessionId), nowMs);
|
|
22817
22718
|
if (owner.kind !== "authorized") return ownerSessionResponse(owner);
|
|
22719
|
+
if (isLinkSessionTerminalFailureV1(owner.session.state)) return invalidStateResponse(owner.session);
|
|
22818
22720
|
const router = service.sourceContributionRouter;
|
|
22819
22721
|
if (!router) return notSupportedResponse("Ed25519 source-preserving linking is not configured");
|
|
22820
22722
|
const preparation = requireEd25519SourceContributionPreparation(owner.session);
|
|
@@ -22887,8 +22789,6 @@ async function handleEmailOtpBaseFactor(ctx, service, rawLinkSessionId, nowMs) {
|
|
|
22887
22789
|
const authenticated = await authenticateOwnerForSession(ctx, service, parseSessionId(rawLinkSessionId), nowMs);
|
|
22888
22790
|
if (authenticated.kind !== "authorized") return ownerSessionResponse(authenticated);
|
|
22889
22791
|
const session = authenticated.session;
|
|
22890
|
-
const ownerMismatch = requireOwnerMatchesClaimedWallet(authenticated.owner, session);
|
|
22891
|
-
if (ownerMismatch) return ownerMismatch;
|
|
22892
22792
|
if (session.state.state !== "claimed" || session.qrPayload.targetFactor.kind !== "email_otp" || !session.claimTranscript) return invalidStateResponse(session);
|
|
22893
22793
|
const walletId = session.claimTranscript.value.walletId;
|
|
22894
22794
|
const request = parseBoundary$1(() => parseLinkedDeviceEmailOtpBaseFactorRequestV1(authenticated.body));
|
|
@@ -22916,8 +22816,6 @@ async function handleOwnerCancel(ctx, service, rawLinkSessionId, nowMs) {
|
|
|
22916
22816
|
if (authenticated.kind !== "authorized") return ownerSessionResponse(authenticated);
|
|
22917
22817
|
parseBoundary$1(() => parseOwnerCancelRequest(authenticated.body));
|
|
22918
22818
|
const session = authenticated.session;
|
|
22919
|
-
const ownerMismatch = requireOwnerMatchesClaimedWallet(authenticated.owner, session);
|
|
22920
|
-
if (ownerMismatch) return ownerMismatch;
|
|
22921
22819
|
if (session.state.state === "cancelled") return sessionProjectionResponse(session, "replayed");
|
|
22922
22820
|
return sessionResultResponse(await service.sessionService.cancelSessionV1({
|
|
22923
22821
|
linkSessionId,
|
|
@@ -22965,6 +22863,7 @@ async function handleExportRootRecipient(ctx, service, rawLinkSessionId, nowMs)
|
|
|
22965
22863
|
if (ctx.method === "GET") {
|
|
22966
22864
|
const owner = await authenticateOwnerForSession(ctx, service, sessionId, nowMs);
|
|
22967
22865
|
if (owner.kind !== "authorized") return ownerSessionResponse(owner);
|
|
22866
|
+
if (isLinkSessionTerminalFailureV1(owner.session.state)) return invalidStateResponse(owner.session);
|
|
22968
22867
|
const transfer = await port.readTransferV1(sessionId);
|
|
22969
22868
|
return transfer ? json$1(transfer.recipient, { status: 200 }) : new Response(null, { status: 204 });
|
|
22970
22869
|
}
|
|
@@ -22972,8 +22871,14 @@ async function handleExportRootRecipient(ctx, service, rawLinkSessionId, nowMs)
|
|
|
22972
22871
|
const authenticated = await authenticateDeviceForSession(ctx, service, rawLinkSessionId, nowMs);
|
|
22973
22872
|
if (authenticated.kind === "denied") return authDeniedResponse$2(authenticated);
|
|
22974
22873
|
if (authenticated.kind === "not_found") return notFoundResponse();
|
|
22874
|
+
if (isLinkSessionTerminalFailureV1(authenticated.session.state)) return invalidStateResponse(authenticated.session);
|
|
22975
22875
|
const recipient = parseBoundary$1(() => parseLinkedDeviceEd25519ExportRootRecipientV1(authenticated.body));
|
|
22976
22876
|
if (recipient.linkSessionId !== authenticated.linkSessionId) return invalidInputResponse("link session id does not match route");
|
|
22877
|
+
const session = authenticated.session;
|
|
22878
|
+
const preparation = await readTargetPreparation(service, session, requireApproval(session), { access: "replay_only" }, nowMs);
|
|
22879
|
+
if (preparation.kind === "conflict") return invalidStateResponse(session);
|
|
22880
|
+
const facts = preparation.ed25519ExportRoot;
|
|
22881
|
+
if (!facts || recipient.walletId !== preparation.walletId || recipient.enrollmentId !== preparation.enrollmentId || recipient.deviceId !== preparation.deviceId || recipient.targetFactor.kind !== preparation.targetFactor.kind || recipient.walletKeyId !== facts.walletKeyId || recipient.revocationEpoch !== facts.revocationEpoch || recipient.applicationBindingDigestB64u !== facts.applicationBindingDigestB64u || recipient.registeredPublicKeyB64u !== facts.registeredPublicKeyB64u) return invalidInputResponse("export-root recipient does not match target preparation");
|
|
22977
22882
|
return exportRootWriteResponse(await port.registerRecipientV1({ recipient }));
|
|
22978
22883
|
}
|
|
22979
22884
|
async function handleExportRootPackage(ctx, service, rawLinkSessionId, nowMs) {
|
|
@@ -22984,12 +22889,14 @@ async function handleExportRootPackage(ctx, service, rawLinkSessionId, nowMs) {
|
|
|
22984
22889
|
const authenticated = await authenticateDeviceForSession(ctx, service, rawLinkSessionId, nowMs);
|
|
22985
22890
|
if (authenticated.kind === "denied") return authDeniedResponse$2(authenticated);
|
|
22986
22891
|
if (authenticated.kind === "not_found") return notFoundResponse();
|
|
22892
|
+
if (isLinkSessionTerminalFailureV1(authenticated.session.state)) return invalidStateResponse(authenticated.session);
|
|
22987
22893
|
const transfer = await port.readTransferV1(sessionId);
|
|
22988
22894
|
return transfer?.state === "sealed" ? json$1(transfer.package, { status: 200 }) : new Response(null, { status: 204 });
|
|
22989
22895
|
}
|
|
22990
22896
|
if (ctx.method !== "POST") return methodNotAllowedResponse$2();
|
|
22991
22897
|
const owner = await authenticateOwnerForSession(ctx, service, sessionId, nowMs);
|
|
22992
22898
|
if (owner.kind !== "authorized") return ownerSessionResponse(owner);
|
|
22899
|
+
if (isLinkSessionTerminalFailureV1(owner.session.state)) return invalidStateResponse(owner.session);
|
|
22993
22900
|
const submission = parseBoundary$1(() => parseLinkedDeviceEd25519ExportRootSubmissionV1(owner.body));
|
|
22994
22901
|
if (submission.linkSessionId !== sessionId) return invalidInputResponse("link session id does not match route");
|
|
22995
22902
|
return exportRootWriteResponse(await port.submitPackageV1({
|
|
@@ -23001,7 +22908,7 @@ async function handleReceipt(ctx, service, rawLinkSessionId, nowMs) {
|
|
|
23001
22908
|
if (!service.installationReceipt) return notSupportedResponse("Installation receipt is not configured");
|
|
23002
22909
|
if (ctx.method !== "POST") return methodNotAllowedResponse$2();
|
|
23003
22910
|
const linkSessionId = parseSessionId(rawLinkSessionId);
|
|
23004
|
-
const rawBody = await
|
|
22911
|
+
const rawBody = await readJson(ctx.request.clone());
|
|
23005
22912
|
if (isFinalActivationAcknowledgement(rawBody)) {
|
|
23006
22913
|
const acknowledgement = parseBoundary$1(() => parseLocalAuthorityActivationFinalAckV1(rawBody));
|
|
23007
22914
|
if (acknowledgement.linkSessionId !== linkSessionId) return invalidInputResponse("activation acknowledgement session does not match the route");
|
|
@@ -23187,6 +23094,8 @@ async function authenticateOwnerForSession(ctx, service, linkSessionId, nowMs) {
|
|
|
23187
23094
|
});
|
|
23188
23095
|
if (!session) return { kind: "not_found" };
|
|
23189
23096
|
validateOwnerRequestBinding(authentication.binding, ctx, bodyDigestB64u, nowMs);
|
|
23097
|
+
const ownerMismatch = requireOwnerMatchesClaimedWallet(authentication.owner, session);
|
|
23098
|
+
if (ownerMismatch) return ownerMismatch;
|
|
23190
23099
|
return {
|
|
23191
23100
|
kind: "authorized",
|
|
23192
23101
|
body: authentication.body,
|
|
@@ -23391,69 +23300,6 @@ async function authenticateTargetPasskeyOriginV1(ctx, routeId) {
|
|
|
23391
23300
|
expectedOrigin
|
|
23392
23301
|
};
|
|
23393
23302
|
}
|
|
23394
|
-
function projectLinkSessionStateV1(state) {
|
|
23395
|
-
switch (state.state) {
|
|
23396
|
-
case "displaying_qr": return { state: "displaying_qr" };
|
|
23397
|
-
case "claimed":
|
|
23398
|
-
case "awaiting_target_factor":
|
|
23399
|
-
case "awaiting_source_contribution":
|
|
23400
|
-
case "provisioning": return {
|
|
23401
|
-
state: state.state,
|
|
23402
|
-
deviceId: state.deviceId
|
|
23403
|
-
};
|
|
23404
|
-
case "authority_pending_local_install": return {
|
|
23405
|
-
state: "authority_pending_local_install",
|
|
23406
|
-
deviceId: state.deviceId,
|
|
23407
|
-
authorityId: state.authorityId,
|
|
23408
|
-
packageSetDigestB64u: state.packageSetDigestB64u
|
|
23409
|
-
};
|
|
23410
|
-
case "active": return {
|
|
23411
|
-
state: "active",
|
|
23412
|
-
deviceId: state.deviceId,
|
|
23413
|
-
authorityId: state.authorityId,
|
|
23414
|
-
activatedAtMs: state.activatedAtMs
|
|
23415
|
-
};
|
|
23416
|
-
case "failed_before_commit": return {
|
|
23417
|
-
state: "failed_before_commit",
|
|
23418
|
-
error: state.error
|
|
23419
|
-
};
|
|
23420
|
-
case "cancelled": return {
|
|
23421
|
-
state: "cancelled",
|
|
23422
|
-
cancelledAtMs: state.cancelledAtMs
|
|
23423
|
-
};
|
|
23424
|
-
case "expired": return {
|
|
23425
|
-
state: "expired",
|
|
23426
|
-
expiredAtMs: state.expiredAtMs
|
|
23427
|
-
};
|
|
23428
|
-
default: return assertNeverLinkSessionStateV1(state);
|
|
23429
|
-
}
|
|
23430
|
-
}
|
|
23431
|
-
function projectSession(record) {
|
|
23432
|
-
return {
|
|
23433
|
-
kind: "linked_device_session_projection_v1",
|
|
23434
|
-
linkSessionId: record.linkSessionId,
|
|
23435
|
-
qrPayload: record.qrPayload,
|
|
23436
|
-
revision: record.revision,
|
|
23437
|
-
createdAtMs: record.createdAtMs,
|
|
23438
|
-
updatedAtMs: record.updatedAtMs,
|
|
23439
|
-
state: projectLinkSessionStateV1(record.state)
|
|
23440
|
-
};
|
|
23441
|
-
}
|
|
23442
|
-
function sessionProjectionResponse(record, outcome) {
|
|
23443
|
-
return json$1({
|
|
23444
|
-
ok: true,
|
|
23445
|
-
outcome,
|
|
23446
|
-
session: projectSession(record)
|
|
23447
|
-
}, { status: 200 });
|
|
23448
|
-
}
|
|
23449
|
-
function targetCredentialResultResponse(record, outcome, targetCredential) {
|
|
23450
|
-
return json$1({
|
|
23451
|
-
ok: true,
|
|
23452
|
-
outcome,
|
|
23453
|
-
targetCredential,
|
|
23454
|
-
session: projectSession(record)
|
|
23455
|
-
}, { status: 200 });
|
|
23456
|
-
}
|
|
23457
23303
|
function claimResultResponse(result) {
|
|
23458
23304
|
if (result.outcome !== "applied" && result.outcome !== "replayed") return sessionResultResponse(result);
|
|
23459
23305
|
const claim = result.record.claimTranscript?.value;
|
|
@@ -23482,6 +23328,16 @@ function approvalResultResponse(result) {
|
|
|
23482
23328
|
}
|
|
23483
23329
|
function sessionResultResponse(result) {
|
|
23484
23330
|
switch (result.outcome) {
|
|
23331
|
+
case "home_conflict": return json$1({
|
|
23332
|
+
ok: false,
|
|
23333
|
+
code: "wallet_home_conflict",
|
|
23334
|
+
message: result.message
|
|
23335
|
+
}, { status: 409 });
|
|
23336
|
+
case "home_unavailable": return json$1({
|
|
23337
|
+
ok: false,
|
|
23338
|
+
code: "wallet_home_unavailable",
|
|
23339
|
+
message: result.message
|
|
23340
|
+
}, { status: 503 });
|
|
23485
23341
|
case "applied":
|
|
23486
23342
|
case "replayed": return sessionProjectionResponse(result.record, result.outcome);
|
|
23487
23343
|
case "conflict": return json$1({
|
|
@@ -23522,49 +23378,19 @@ function sessionResultResponse(result) {
|
|
|
23522
23378
|
default: return assertNever$1(result);
|
|
23523
23379
|
}
|
|
23524
23380
|
}
|
|
23525
|
-
function invalidStateResponse(record) {
|
|
23526
|
-
return json$1({
|
|
23527
|
-
ok: false,
|
|
23528
|
-
outcome: "invalid_state",
|
|
23529
|
-
state: record.state.state,
|
|
23530
|
-
session: projectSession(record)
|
|
23531
|
-
}, { status: 409 });
|
|
23532
|
-
}
|
|
23533
|
-
function exportRootWriteResponse(result) {
|
|
23534
|
-
return result.outcome === "conflict" ? json$1({
|
|
23535
|
-
ok: false,
|
|
23536
|
-
code: result.reason ?? "conflict",
|
|
23537
|
-
message: "export-root relay conflict"
|
|
23538
|
-
}, { status: 409 }) : json$1({
|
|
23539
|
-
ok: true,
|
|
23540
|
-
outcome: result.outcome
|
|
23541
|
-
}, { status: 200 });
|
|
23542
|
-
}
|
|
23543
23381
|
function ownerSessionResponse(context) {
|
|
23544
23382
|
return context.kind === "denied" ? authDeniedResponse$2(context) : notFoundResponse();
|
|
23545
23383
|
}
|
|
23546
|
-
/**
|
|
23547
|
-
* The one owner-to-session binding, shared by every owner route on a claimed
|
|
23548
|
-
* session. It runs before any state is disclosed: an authenticated owner of a
|
|
23549
|
-
* DIFFERENT wallet must get the same denial for every state, not a projection
|
|
23550
|
-
* or an invalid-state body. An unclaimed session has no wallet to bind to yet,
|
|
23551
|
-
* so the caller's state checks answer instead.
|
|
23552
|
-
*/
|
|
23553
23384
|
function requireOwnerMatchesClaimedWallet(owner, session) {
|
|
23554
23385
|
const claimWalletId = session.claimTranscript?.value.walletId;
|
|
23555
23386
|
if (claimWalletId === void 0) return null;
|
|
23556
23387
|
if (owner.walletId === claimWalletId) return null;
|
|
23557
|
-
return
|
|
23388
|
+
return {
|
|
23558
23389
|
kind: "denied",
|
|
23559
23390
|
code: "unauthorized",
|
|
23560
23391
|
message: "owner session does not match link wallet"
|
|
23561
|
-
}
|
|
23392
|
+
};
|
|
23562
23393
|
}
|
|
23563
|
-
/**
|
|
23564
|
-
* Approval-time revalidation of the selected Email OTP base method. The same
|
|
23565
|
-
* eligibility question the dedicated base-factor route answers, asked once
|
|
23566
|
-
* more with the id the approval names, so the two paths cannot drift.
|
|
23567
|
-
*/
|
|
23568
23394
|
async function requireSelectedEmailOtpBaseFactorV1(service, session, input) {
|
|
23569
23395
|
const provider = service.emailOtpTargetFactor;
|
|
23570
23396
|
if (!provider) return notSupportedResponse("Email OTP linking is not configured");
|
|
@@ -23583,43 +23409,6 @@ async function requireSelectedEmailOtpBaseFactorV1(service, session, input) {
|
|
|
23583
23409
|
});
|
|
23584
23410
|
return null;
|
|
23585
23411
|
}
|
|
23586
|
-
function authDeniedResponse$2(result) {
|
|
23587
|
-
return json$1({
|
|
23588
|
-
ok: false,
|
|
23589
|
-
outcome: "unauthorized",
|
|
23590
|
-
code: result.code,
|
|
23591
|
-
message: result.message
|
|
23592
|
-
}, { status: result.code === "expired" ? 410 : 401 });
|
|
23593
|
-
}
|
|
23594
|
-
function invalidInputResponse(message) {
|
|
23595
|
-
return json$1({
|
|
23596
|
-
ok: false,
|
|
23597
|
-
outcome: "invalid_input",
|
|
23598
|
-
code: "invalid_input",
|
|
23599
|
-
message
|
|
23600
|
-
}, { status: 400 });
|
|
23601
|
-
}
|
|
23602
|
-
function notSupportedResponse(message = "Device linking is not configured") {
|
|
23603
|
-
return json$1({
|
|
23604
|
-
ok: false,
|
|
23605
|
-
code: "not_supported",
|
|
23606
|
-
message
|
|
23607
|
-
}, { status: 501 });
|
|
23608
|
-
}
|
|
23609
|
-
function notFoundResponse() {
|
|
23610
|
-
return json$1({
|
|
23611
|
-
ok: false,
|
|
23612
|
-
code: "not_found",
|
|
23613
|
-
message: "Linked-device session not found"
|
|
23614
|
-
}, { status: 404 });
|
|
23615
|
-
}
|
|
23616
|
-
function methodNotAllowedResponse$2() {
|
|
23617
|
-
return json$1({
|
|
23618
|
-
ok: false,
|
|
23619
|
-
code: "method_not_allowed",
|
|
23620
|
-
message: "Method is not allowed"
|
|
23621
|
-
}, { status: 405 });
|
|
23622
|
-
}
|
|
23623
23412
|
function parseCreateRequest(raw) {
|
|
23624
23413
|
const record = requireRecord(raw, "device-linking create request");
|
|
23625
23414
|
requireExactKeys$1(record, ["kind", "payload"]);
|
|
@@ -23684,9 +23473,6 @@ function parseB64uBytes(raw, field) {
|
|
|
23684
23473
|
if (bytes.length === 0 || base64UrlEncode(bytes) !== raw) throw new Error(`${field} is not canonical base64url`);
|
|
23685
23474
|
return bytes;
|
|
23686
23475
|
}
|
|
23687
|
-
async function readJsonBody(request) {
|
|
23688
|
-
return await readJson(request);
|
|
23689
|
-
}
|
|
23690
23476
|
function parseBoundary$1(parse) {
|
|
23691
23477
|
try {
|
|
23692
23478
|
return parse();
|
|
@@ -24039,11 +23825,7 @@ async function authenticateDeviceLinkingOwnerWalletSessionRequestV1(input) {
|
|
|
24039
23825
|
async function handleDeviceLinkingOwnerAuthorization(ctx, service) {
|
|
24040
23826
|
if (ctx.pathname !== "/wallet/device-linking/v1/owner-authorization") return null;
|
|
24041
23827
|
if (ctx.method !== "POST") return methodNotAllowedResponse();
|
|
24042
|
-
if (!service) return
|
|
24043
|
-
ok: false,
|
|
24044
|
-
code: "not_supported",
|
|
24045
|
-
message: "Linked-device owner authorization is not configured"
|
|
24046
|
-
}, { status: 501 });
|
|
23828
|
+
if (!service) return jsonFailure(501, "not_supported", "Linked-device owner authorization is not configured");
|
|
24047
23829
|
const nowV1 = Date.now;
|
|
24048
23830
|
let body;
|
|
24049
23831
|
let rawBody;
|
|
@@ -24053,11 +23835,7 @@ async function handleDeviceLinkingOwnerAuthorization(ctx, service) {
|
|
|
24053
23835
|
rawBody = await readJson(ctx.request.clone());
|
|
24054
23836
|
body = parseLinkedDeviceOwnerAuthorizationRequestV1(rawBody);
|
|
24055
23837
|
} catch (error) {
|
|
24056
|
-
return
|
|
24057
|
-
ok: false,
|
|
24058
|
-
code: "invalid_body",
|
|
24059
|
-
message: error instanceof Error ? error.message : "Owner authorization body is invalid"
|
|
24060
|
-
}, { status: 400 });
|
|
23838
|
+
return jsonFailure(400, "invalid_body", error instanceof Error ? error.message : "Owner authorization body is invalid");
|
|
24061
23839
|
}
|
|
24062
23840
|
const validated = await authenticateDeviceLinkingOwnerWalletSessionRequestV1({
|
|
24063
23841
|
request: ctx.request,
|
|
@@ -24077,11 +23855,7 @@ async function handleDeviceLinkingOwnerAuthorization(ctx, service) {
|
|
|
24077
23855
|
owner: validated.owner
|
|
24078
23856
|
}), { status: 200 });
|
|
24079
23857
|
} catch (error) {
|
|
24080
|
-
return
|
|
24081
|
-
ok: false,
|
|
24082
|
-
code: "internal",
|
|
24083
|
-
message: error instanceof Error ? error.message : String(error)
|
|
24084
|
-
}, { status: 500 });
|
|
23858
|
+
return jsonFailure(500, "internal", error instanceof Error ? error.message : String(error));
|
|
24085
23859
|
}
|
|
24086
23860
|
}
|
|
24087
23861
|
async function validateOwnerWalletSessionV1(input) {
|
|
@@ -24245,12 +24019,8 @@ function methodNotAllowedResponse() {
|
|
|
24245
24019
|
}, { status: 405 });
|
|
24246
24020
|
}
|
|
24247
24021
|
function authDeniedResponse(value) {
|
|
24248
|
-
|
|
24249
|
-
return
|
|
24250
|
-
ok: false,
|
|
24251
|
-
code: value.code,
|
|
24252
|
-
message: value.message
|
|
24253
|
-
}, { status });
|
|
24022
|
+
if (value.code === "unavailable") return jsonFailure(503, value.code, value.message);
|
|
24023
|
+
return jsonFailure(value.code === "invalid" ? 403 : 401, value.code, value.message);
|
|
24254
24024
|
}
|
|
24255
24025
|
//#endregion
|
|
24256
24026
|
//#region src/threshold/session/signingSessionSeal/transport/fetch.ts
|
|
@@ -24260,20 +24030,6 @@ function json(body, status = 200) {
|
|
|
24260
24030
|
headers: { "Content-Type": "application/json; charset=utf-8" }
|
|
24261
24031
|
});
|
|
24262
24032
|
}
|
|
24263
|
-
async function readJsonSafe(request) {
|
|
24264
|
-
try {
|
|
24265
|
-
return await request.json();
|
|
24266
|
-
} catch {
|
|
24267
|
-
return null;
|
|
24268
|
-
}
|
|
24269
|
-
}
|
|
24270
|
-
function headersToRecord(headers) {
|
|
24271
|
-
const out = {};
|
|
24272
|
-
headers.forEach((value, key) => {
|
|
24273
|
-
out[key] = value;
|
|
24274
|
-
});
|
|
24275
|
-
return out;
|
|
24276
|
-
}
|
|
24277
24033
|
function errMessage(error) {
|
|
24278
24034
|
return error instanceof Error ? error.message : String(error || "Internal error");
|
|
24279
24035
|
}
|
|
@@ -24293,7 +24049,7 @@ async function handleSigningSessionSealRoutes(ctx) {
|
|
|
24293
24049
|
route: isApply ? applyPath : removePath,
|
|
24294
24050
|
operation
|
|
24295
24051
|
});
|
|
24296
|
-
const body = await
|
|
24052
|
+
const body = await readJson(ctx.request);
|
|
24297
24053
|
const parsed = isApply ? parseSigningSessionSealApplyBody(body) : parseSigningSessionSealRemoveBody(body);
|
|
24298
24054
|
if (!parsed.ok) {
|
|
24299
24055
|
ctx.logger.warn("[threshold-signing-session-seal] invalid_body", {
|
|
@@ -24303,11 +24059,7 @@ async function handleSigningSessionSealRoutes(ctx) {
|
|
|
24303
24059
|
message: parsed.message,
|
|
24304
24060
|
durationMs: Math.max(0, Date.now() - startedAtMs)
|
|
24305
24061
|
});
|
|
24306
|
-
return json(
|
|
24307
|
-
ok: false,
|
|
24308
|
-
code: parsed.code,
|
|
24309
|
-
message: parsed.message
|
|
24310
|
-
}, 400);
|
|
24062
|
+
return json(failure(parsed.code, parsed.message), 400);
|
|
24311
24063
|
}
|
|
24312
24064
|
const authorized = await authorizeSigningSessionSealRequest({
|
|
24313
24065
|
options,
|
|
@@ -24323,11 +24075,7 @@ async function handleSigningSessionSealRoutes(ctx) {
|
|
|
24323
24075
|
message: authorized.message || "Unauthorized",
|
|
24324
24076
|
durationMs: Math.max(0, Date.now() - startedAtMs)
|
|
24325
24077
|
});
|
|
24326
|
-
return json(
|
|
24327
|
-
ok: false,
|
|
24328
|
-
code: authorized.code || "unauthorized",
|
|
24329
|
-
message: authorized.message || "Unauthorized"
|
|
24330
|
-
}, signingSessionSealAuthorizeStatusCode(authorized));
|
|
24078
|
+
return json(failure(authorized.code || "unauthorized", authorized.message || "Unauthorized"), signingSessionSealAuthorizeStatusCode(authorized));
|
|
24331
24079
|
}
|
|
24332
24080
|
const result = isApply ? await options.service.applyServerSeal(parsed.value, authorized.auth) : await options.service.removeServerSeal(parsed.value, authorized.auth);
|
|
24333
24081
|
const status = signingSessionSealStatusCode(result);
|
|
@@ -24347,11 +24095,7 @@ async function handleSigningSessionSealRoutes(ctx) {
|
|
|
24347
24095
|
message,
|
|
24348
24096
|
durationMs: Math.max(0, Date.now() - startedAtMs)
|
|
24349
24097
|
});
|
|
24350
|
-
return json(
|
|
24351
|
-
ok: false,
|
|
24352
|
-
code: "internal",
|
|
24353
|
-
message
|
|
24354
|
-
}, 500);
|
|
24098
|
+
return json(failure("internal", message), 500);
|
|
24355
24099
|
}
|
|
24356
24100
|
}
|
|
24357
24101
|
//#endregion
|
|
@@ -24496,6 +24240,7 @@ async function signingSessionSealRecordFromExactAdmission(input) {
|
|
|
24496
24240
|
switch (admission.curve) {
|
|
24497
24241
|
case "ecdsa": {
|
|
24498
24242
|
const active = await input.walletRegistration.resolveEcdsaMaterialActivation({
|
|
24243
|
+
source: { kind: "database" },
|
|
24499
24244
|
walletId,
|
|
24500
24245
|
materialActivation
|
|
24501
24246
|
});
|
|
@@ -24656,11 +24401,7 @@ function createFetchRouter(service, opts, runtime) {
|
|
|
24656
24401
|
async (context) => {
|
|
24657
24402
|
if (!context.pathname.startsWith("/wallet/device-linking/v1/devices")) return null;
|
|
24658
24403
|
const service = context.service.deviceManagement;
|
|
24659
|
-
if (!service) return
|
|
24660
|
-
ok: false,
|
|
24661
|
-
code: "not_supported",
|
|
24662
|
-
message: "Linked-device management is not configured"
|
|
24663
|
-
}, { status: 501 });
|
|
24404
|
+
if (!service) return jsonFailure(501, "not_supported", "Linked-device management is not configured");
|
|
24664
24405
|
return await handleDeviceManagement(context, service);
|
|
24665
24406
|
},
|
|
24666
24407
|
handlePasskeyCustody,
|
|
@@ -24685,7 +24426,6 @@ function createFetchRouter(service, opts, runtime) {
|
|
|
24685
24426
|
handleThresholdEcdsa,
|
|
24686
24427
|
handleExactWalletSigningSessionSeal,
|
|
24687
24428
|
handleWebAuthnAuthenticators,
|
|
24688
|
-
handleNearPublicKeys,
|
|
24689
24429
|
handleExactWalletSessionStatus,
|
|
24690
24430
|
handleHostedWalletSessionExchangeIssue,
|
|
24691
24431
|
handleHostedWalletSessionExchangeRedeem,
|
|
@@ -24900,45 +24640,17 @@ function parseExpectation(raw) {
|
|
|
24900
24640
|
}
|
|
24901
24641
|
async function validateRuntimeSnapshotExpectation(input) {
|
|
24902
24642
|
const expectationResult = parseExpectation(input.expectationRaw);
|
|
24903
|
-
if (expectationResult.error) return
|
|
24904
|
-
ok: false,
|
|
24905
|
-
code: "runtime_snapshot_invalid_expectation",
|
|
24906
|
-
message: expectationResult.error
|
|
24907
|
-
};
|
|
24643
|
+
if (expectationResult.error) return failure("runtime_snapshot_invalid_expectation", expectationResult.error);
|
|
24908
24644
|
const expectation = expectationResult.parsed;
|
|
24909
24645
|
if (!expectation) return { ok: true };
|
|
24910
24646
|
const scope = input.scope;
|
|
24911
|
-
if (!scope) return
|
|
24912
|
-
|
|
24913
|
-
code: "runtime_snapshot_scope_missing",
|
|
24914
|
-
message: "threshold session is missing runtimePolicyScope"
|
|
24915
|
-
};
|
|
24916
|
-
if (!input.runtimeSnapshots) return {
|
|
24917
|
-
ok: false,
|
|
24918
|
-
code: "runtime_snapshots_not_configured",
|
|
24919
|
-
message: "Runtime snapshot consumer is not configured on this server"
|
|
24920
|
-
};
|
|
24647
|
+
if (!scope) return failure("runtime_snapshot_scope_missing", "threshold session is missing runtimePolicyScope");
|
|
24648
|
+
if (!input.runtimeSnapshots) return failure("runtime_snapshots_not_configured", "Runtime snapshot consumer is not configured on this server");
|
|
24921
24649
|
const latest = await input.runtimeSnapshots.getLatestSnapshot(scope);
|
|
24922
|
-
if (!latest) return {
|
|
24923
|
-
|
|
24924
|
-
|
|
24925
|
-
|
|
24926
|
-
};
|
|
24927
|
-
if (expectation.snapshotId && latest.snapshotId !== expectation.snapshotId) return {
|
|
24928
|
-
ok: false,
|
|
24929
|
-
code: "runtime_snapshot_id_mismatch",
|
|
24930
|
-
message: `Runtime snapshot id mismatch: expected ${expectation.snapshotId}, got ${latest.snapshotId}`
|
|
24931
|
-
};
|
|
24932
|
-
if (expectation.version !== void 0 && latest.version !== expectation.version) return {
|
|
24933
|
-
ok: false,
|
|
24934
|
-
code: "runtime_snapshot_version_mismatch",
|
|
24935
|
-
message: `Runtime snapshot version mismatch: expected ${expectation.version}, got ${latest.version}`
|
|
24936
|
-
};
|
|
24937
|
-
if (expectation.checksum && latest.checksum !== expectation.checksum) return {
|
|
24938
|
-
ok: false,
|
|
24939
|
-
code: "runtime_snapshot_checksum_mismatch",
|
|
24940
|
-
message: `Runtime snapshot checksum mismatch: expected ${expectation.checksum}, got ${latest.checksum}`
|
|
24941
|
-
};
|
|
24650
|
+
if (!latest) return failure("runtime_snapshot_not_found", `No runtime snapshot found for org=${scope.orgId} project=${scope.projectId} env=${scope.envId}`);
|
|
24651
|
+
if (expectation.snapshotId && latest.snapshotId !== expectation.snapshotId) return failure("runtime_snapshot_id_mismatch", `Runtime snapshot id mismatch: expected ${expectation.snapshotId}, got ${latest.snapshotId}`);
|
|
24652
|
+
if (expectation.version !== void 0 && latest.version !== expectation.version) return failure("runtime_snapshot_version_mismatch", `Runtime snapshot version mismatch: expected ${expectation.version}, got ${latest.version}`);
|
|
24653
|
+
if (expectation.checksum && latest.checksum !== expectation.checksum) return failure("runtime_snapshot_checksum_mismatch", `Runtime snapshot checksum mismatch: expected ${expectation.checksum}, got ${latest.checksum}`);
|
|
24942
24654
|
return { ok: true };
|
|
24943
24655
|
}
|
|
24944
24656
|
function makeScopeKey(scope) {
|
|
@@ -25002,9 +24714,17 @@ function createInMemoryRouterApiRuntimeSnapshotConsumer() {
|
|
|
25002
24714
|
};
|
|
25003
24715
|
}
|
|
25004
24716
|
//#endregion
|
|
24717
|
+
//#region ../shared-ts/src/tenant-root/tenantRootIdentifier.ts
|
|
24718
|
+
function hasControlCharacters(value) {
|
|
24719
|
+
for (const character of value) {
|
|
24720
|
+
const codePoint = character.codePointAt(0) ?? 0;
|
|
24721
|
+
if (codePoint <= 31 || codePoint >= 127 && codePoint <= 159) return true;
|
|
24722
|
+
}
|
|
24723
|
+
return false;
|
|
24724
|
+
}
|
|
24725
|
+
//#endregion
|
|
25005
24726
|
//#region ../shared-ts/src/tenant-root/tenantRootIdentity.ts
|
|
25006
24727
|
const TENANT_ROOT_IDENTITY_DOMAIN_V1 = new TextEncoder().encode("seams/tenant-root-identity/v1");
|
|
25007
|
-
const TENANT_ROOT_IDENTITY_MAX_IDENTIFIER_BYTES_V1 = 256;
|
|
25008
24728
|
function concatenateBytes(parts) {
|
|
25009
24729
|
let length = 0;
|
|
25010
24730
|
for (const part of parts) length += part.length;
|
|
@@ -25023,13 +24743,6 @@ function hasLeadingOrTrailingRustWhitespace(value) {
|
|
|
25023
24743
|
const codePoints = Array.from(value, (character) => character.codePointAt(0) ?? 0);
|
|
25024
24744
|
return codePoints.length > 0 && (isRustWhitespace(codePoints[0]) || isRustWhitespace(codePoints[codePoints.length - 1]));
|
|
25025
24745
|
}
|
|
25026
|
-
function hasControlCharacters(value) {
|
|
25027
|
-
for (const character of value) {
|
|
25028
|
-
const codePoint = character.codePointAt(0) ?? 0;
|
|
25029
|
-
if (codePoint <= 31 || codePoint >= 127 && codePoint <= 159) return true;
|
|
25030
|
-
}
|
|
25031
|
-
return false;
|
|
25032
|
-
}
|
|
25033
24746
|
function hasUnpairedSurrogate(value) {
|
|
25034
24747
|
for (let index = 0; index < value.length; index += 1) {
|
|
25035
24748
|
const codeUnit = value.charCodeAt(index);
|
|
@@ -25047,7 +24760,7 @@ function isCanonicalTenantRootIdentityField(value) {
|
|
|
25047
24760
|
if (typeof value !== "string" || value.length === 0) return false;
|
|
25048
24761
|
if (hasLeadingOrTrailingRustWhitespace(value) || hasControlCharacters(value)) return false;
|
|
25049
24762
|
if (hasUnpairedSurrogate(value)) return false;
|
|
25050
|
-
return new TextEncoder().encode(value).length <=
|
|
24763
|
+
return new TextEncoder().encode(value).length <= 256;
|
|
25051
24764
|
}
|
|
25052
24765
|
function lengthPrefixTenantRootIdentityField(value) {
|
|
25053
24766
|
const output = new Uint8Array(4 + value.length);
|
|
@@ -26320,8 +26033,8 @@ function resolveTraceContext(request) {
|
|
|
26320
26033
|
var InMemoryRouterAbEd25519YaoExportStateV1 = class {
|
|
26321
26034
|
constructor() {
|
|
26322
26035
|
this.exports = /* @__PURE__ */ new Map();
|
|
26323
|
-
this.
|
|
26324
|
-
this.
|
|
26036
|
+
this.authorizationNonceOwners = /* @__PURE__ */ new Map();
|
|
26037
|
+
this.authorizationUncertainOwners = /* @__PURE__ */ new Map();
|
|
26325
26038
|
}
|
|
26326
26039
|
};
|
|
26327
26040
|
const ROUTES = Object.freeze([defineRoute({
|