@seams/wallet-server 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/THIRD_PARTY_NOTICES.md +7 -1
- package/artifact-manifest.json +196 -41
- package/cloudflare-router-ab/build/deriver-a/build-stamp.json +1 -1
- package/cloudflare-router-ab/build/deriver-a/index.js +2 -2
- package/cloudflare-router-ab/build/deriver-a/index_bg.wasm +0 -0
- package/cloudflare-router-ab/build/deriver-b/build-stamp.json +1 -1
- package/cloudflare-router-ab/build/deriver-b/index.js +2 -2
- package/cloudflare-router-ab/build/deriver-b/index_bg.wasm +0 -0
- package/cloudflare-router-ab/build/local-tools/darwin-arm64/router_ab_local_init +0 -0
- package/cloudflare-router-ab/build/local-tools/darwin-x64/router_ab_local_init +0 -0
- package/cloudflare-router-ab/build/local-tools/linux-x64/router_ab_local_init +0 -0
- package/cloudflare-router-ab/build/router/build-stamp.json +1 -1
- package/cloudflare-router-ab/build/router/index.js +2 -2
- package/cloudflare-router-ab/build/router/index_bg.wasm +0 -0
- package/cloudflare-router-ab/build/signing-worker/build-stamp.json +1 -1
- package/cloudflare-router-ab/build/signing-worker/index.js +2 -2
- package/cloudflare-router-ab/build/signing-worker/index_bg.wasm +0 -0
- package/cloudflare-router-ab/build/tenant-root-control-plane/build-stamp.json +1 -1
- package/cloudflare-router-ab/build/tenant-root-control-plane/index.js +2 -2
- package/cloudflare-router-ab/build/tenant-root-control-plane/index_bg.wasm +0 -0
- package/cloudflare-router-ab/migrations/deriver-a/0019_wallet_object_addresses.sql +10 -0
- package/cloudflare-router-ab/migrations/deriver-b/0019_wallet_object_addresses.sql +10 -0
- package/cloudflare-router-ab/scripts/prepare-local-runtime-config.mjs +3 -117
- package/cloudflare-router-ab/wrangler.deriver-a.toml +0 -8
- package/cloudflare-router-ab/wrangler.deriver-b.toml +24 -8
- package/cloudflare-router-ab/wrangler.router.toml +0 -2
- package/cloudflare-router-ab/wrangler.signing-worker.toml +29 -0
- package/dist/esm/authorization/domain.js +3 -2
- package/dist/esm/authorization/ed25519WalletSessionAdmission.js +0 -0
- package/dist/esm/authorization/service.js +64 -36
- package/dist/esm/cloud-host.js +24 -19
- package/dist/esm/core/EmailOtpRecords.js +29 -6
- package/dist/esm/core/ThresholdService/routerAb/ecdsaDerivationPoolFillHandlers.js +2 -0
- package/dist/esm/core/ThresholdService/routerAb/ecdsaDerivationPresignBridge.js +10 -0
- package/dist/esm/core/ThresholdService/routerAb/internalServiceHttp.js +1 -0
- package/dist/esm/core/ThresholdService/validation.js +2 -2
- package/dist/esm/core/authService/nearPrivateKeySigning.js +1 -1
- package/dist/esm/core/authService/webauthn.js +1 -1
- package/dist/esm/core/d1Ed25519SignerRead.js +55 -0
- package/dist/esm/core/d1WalletStore.js +14 -11
- package/dist/esm/core/deviceLinking/linkedDeviceEmailOtpGrant.js +2 -2
- package/dist/esm/core/deviceLinking/linkedDeviceManagement.js +1 -1
- package/dist/esm/core/deviceLinking/linkedDeviceSessionRecord.js +2 -2
- package/dist/esm/core/emailOtpD1Statements.js +1 -0
- package/dist/esm/core/nearRelayerAccountProvisioning.js +1 -1
- package/dist/esm/core/routerAbSigning/RouterAbEcdsaPresignRuntime.js +4 -0
- package/dist/esm/core/signingLanes/WalletExecutionLaneProjection.js +1 -1
- package/dist/esm/core/signingMaterial/ordinaryInactiveSignerMaterialReservation.js +1 -0
- package/dist/esm/hosted-wallet-gateway.js +93 -10
- package/dist/esm/localHostedWalletGatewayHandler.js +12 -9
- package/dist/esm/localIntendedYaoSigningFault.js +2 -30
- package/dist/esm/localRegistrationSetupAuthority.js +8 -1
- package/dist/esm/router/auth/commonRouterUtils.js +17 -10
- package/dist/esm/router/auth/routerApiCredentialAuth.js +26 -7
- package/dist/esm/router/auth/walletRegistrationContext.js +49 -0
- package/dist/esm/router/auth/webAuthnCredentialCodecs.js +1 -1
- package/dist/esm/router/cloudflare/d1/auth/d1AuthorizationAssembly.js +4 -3
- package/dist/esm/router/cloudflare/d1/auth/d1AuthorizedOperationRouteService.js +2 -0
- package/dist/esm/router/cloudflare/d1/auth/d1EmailOtpRouteService.js +25 -0
- package/dist/esm/router/cloudflare/d1/auth/d1RouterApiAuthConfig.js +14 -6
- package/dist/esm/router/cloudflare/d1/auth/d1RouterApiAuthService.js +44 -40
- package/dist/esm/router/cloudflare/d1/auth/walletSessionCredentialReaders.js +17 -1
- package/dist/esm/router/cloudflare/d1/authorization/authorizedOperationStatements.js +35 -5
- package/dist/esm/router/cloudflare/d1/authorization/d1AuthorizationStore.js +258 -99
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceAuthorityInstallService.js +31 -4
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceOwnerAuthorizationProvider.js +1 -1
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceRequestProofNonceStore.js +1 -1
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceSessionRecords.js +1 -1
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceTargetCredentialProvider.js +1 -1
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceTargetPlanner.js +1 -1
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceVerifiedLinkBuilder.js +1 -1
- package/dist/esm/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoLifecycleDecisionStore.js +11 -2
- package/dist/esm/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoProductRegistrationPartitionedStateStore.js +100 -10
- package/dist/esm/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoStateWriteFence.js +92 -0
- package/dist/esm/router/cloudflare/d1/ed25519Yao/d1WalletCeremonyActivity.js +77 -0
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeIssuer.js +14 -8
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeStore.js +14 -8
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeVerifier.js +3 -1
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRateLimitStore.js +58 -38
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRecords.js +27 -20
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRecoveryService.js +1 -0
- package/dist/esm/router/cloudflare/d1/emailOtp/d1GoogleEmailOtpSessionResolver.js +1 -0
- package/dist/esm/router/cloudflare/d1/oidc/d1OidcBoundary.js +1 -1
- package/dist/esm/router/cloudflare/d1/passkeyCustody/d1WalletCustodyCommitStore.js +18 -7
- package/dist/esm/router/cloudflare/d1/registration/d1RegistrationCeremonyRecordStore.js +75 -14
- package/dist/esm/router/cloudflare/d1/registration/d1RegistrationCeremonyRecords.js +1 -1
- package/dist/esm/router/cloudflare/d1/registration/d1RegistrationCeremonyStore.js +49 -29
- package/dist/esm/router/cloudflare/d1/registration/d1RegistrationSessionTransaction.js +28 -0
- package/dist/esm/router/cloudflare/d1/registration/d1RegistrationSetupSupport.js +11 -1
- package/dist/esm/router/cloudflare/d1/registration/d1WalletExecutionAuthority.js +168 -0
- package/dist/esm/router/cloudflare/d1/registration/d1WalletOperationStore.js +53 -0
- package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationCommitStore.js +83 -42
- package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationInitialSession.js +33 -0
- package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationPreparation.js +16 -0
- package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationRead.js +58 -0
- package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationService.js +439 -500
- package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationSetup.js +1 -1
- package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationSetupExecution.js +104 -90
- package/dist/esm/router/cloudflare/d1/registration/walletRegistrationEstablishedSessionIssuer.js +78 -44
- package/dist/esm/router/cloudflare/d1/registration/walletRegistrationSessionCommitReceipt.js +11 -35
- package/dist/esm/router/cloudflare/d1/signingAdmission/d1RouterAbNormalSigningAdmissionStore.js +98 -39
- package/dist/esm/router/cloudflare/d1/versionedJson/d1VersionedJsonRecordStore.js +12 -9
- package/dist/esm/router/cloudflare/d1/wallet/authorizationSnapshotLayout.js +168 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAddSignerFinalizeRecord.js +1 -1
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAddSignerService.js +15 -6
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthMethodService.js +3 -40
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorityStore.js +54 -1
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorizationCleanup.js +157 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorizationFreeze.js +56 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorizationHistory.js +238 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorizationIntake.js +287 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorizationSnapshot.js +295 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationApprovals.js +140 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationChallenges.js +170 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationEmailOtp.js +60 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationOwner.js +33 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationOwnerRequest.js +74 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationPasskey.js +77 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationReadAccess.js +37 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationSessions.js +97 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationWriteBlock.js +133 -0
- package/dist/esm/router/cloudflare/d1/walletObjectAddresses.js +47 -0
- package/dist/esm/router/cloudflare/d1/webauthn/d1WebAuthnAuthService.js +1 -1
- package/dist/esm/router/cloudflare/runtime/routerAbServiceBindings.js +32 -1
- package/dist/esm/router/cloudflare/runtime/staticWalletConsoleBinding.js +20 -8
- package/dist/esm/router/cloudflare/runtime/walletAuthorizationRelocationRoutes.js +488 -0
- package/dist/esm/router/cloudflare/runtime/walletConsoleOps.js +1 -1
- package/dist/esm/router/cloudflare/runtime/walletConsoleOpsClient.js +26 -6
- package/dist/esm/router/cloudflare/runtime/walletControlOps.js +3 -0
- package/dist/esm/router/cloudflare/runtime/walletGateway.js +1 -1
- package/dist/esm/router/cloudflare/runtime/walletObjectAddresses.js +105 -0
- package/dist/esm/router/cloudflare/runtime/walletPlacementRoutes.js +339 -0
- package/dist/esm/router/cloudflare/runtime/walletRelocationDeriver.js +244 -0
- package/dist/esm/router/cloudflare/runtime/walletRelocationEcdsa.js +212 -0
- package/dist/esm/router/cloudflare/runtime/walletRelocationEd25519.js +172 -0
- package/dist/esm/router/cloudflare/runtime/walletRelocationOps.js +183 -0
- package/dist/esm/router/cloudflare/runtime/walletRelocationPresign.js +185 -0
- package/dist/esm/router/cloudflare/runtime/walletRelocationSource.js +221 -0
- package/dist/esm/router/cloudflare/signingLanes/cloudflareOrdinaryInactiveSignerMaterialReservation.js +30 -8
- package/dist/esm/router/cloudflare-adaptor.js +8 -8
- package/dist/esm/router/cloudflare.js +34115 -32240
- package/dist/esm/router/domains/ecdsa/routerAbEcdsaStrictRegistration.js +35 -9
- package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoCapabilityCommit.js +42 -0
- package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistration.js +32 -6
- package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationPartitionedStateStore.js +61 -1
- package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationPersistence.js +70 -3
- package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationRequestScopedRuntime.js +59 -87
- package/dist/esm/router/domains/ed25519Yao/export/routerAbEd25519YaoExport.js +52 -22
- package/dist/esm/router/domains/ed25519Yao/export/routerAbEd25519YaoExportRequestScopedCloudflare.js +10 -7
- package/dist/esm/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecovery.js +108 -78
- package/dist/esm/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecoveryRequestScopedCloudflare.js +19 -5
- package/dist/esm/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecoveryWalletSessionAuthorization.js +71 -22
- package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoHttpRegistrationBackend.js +37 -25
- package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistration.js +3 -3
- package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationExecutionRecord.js +2 -1
- package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationIntentAuthorization.js +24 -3
- package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationRequestScopedCloudflare.js +4 -3
- package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationSideEffectBoundary.js +20 -7
- package/dist/esm/router/domains/ed25519Yao/routerAbEd25519YaoGatewayEnvelope.js +7 -1
- package/dist/esm/router/domains/emailOtp/emailOtpRouteHandlers.js +2 -2
- package/dist/esm/router/domains/passkeyCustody/passkeyCustodyEnvelopeRetrieval.js +1 -1
- package/dist/esm/router/domains/passkeyCustody/registrationCustodyOutcome.js +34 -18
- package/dist/esm/router/domains/passkeyCustody/walletCustodyRegistrationAdmission.js +2 -2
- package/dist/esm/router/domains/passkeyCustody/walletCustodyRegistrationCommit.js +16 -6
- package/dist/esm/router/domains/signingOperations/authorizedOperationWire.js +73 -0
- package/dist/esm/router/domains/signingOperations/ecdsaSigningResponse.js +31 -0
- package/dist/esm/router/domains/signingOperations/ed25519AuthorizedOperationReceipt.js +1 -1
- package/dist/esm/router/domains/signingOperations/routerAbEcdsaDerivationNormalSigningRoute.js +2 -1
- package/dist/esm/router/domains/signingOperations/routerAbEd25519NormalSigningRoute.js +31 -121
- package/dist/esm/router/domains/signingOperations/routerAbNormalSigningAdmission.js +2 -93
- package/dist/esm/router/domains/signingOperations/routerAbPrivateSigningWorker.js +1 -1
- package/dist/esm/router/domains/signingOperations/signingPrepareSession.js +33 -0
- package/dist/esm/router/domains/walletRegistration/registrationSessionSeal.js +121 -0
- package/dist/esm/router/domains/walletRegistration/walletRegistrationReservation.js +4 -4
- package/dist/esm/router/domains/walletRegistration/walletRegistrationRoutes.js +46 -157
- package/dist/esm/router/domains/walletRegistration/walletRegistrationSetupPayload.js +1 -1
- package/dist/esm/router/express.js +764 -894
- package/dist/esm/router/framework/http.js +2 -1
- package/dist/esm/router/transport/fetch/createFetchRouter.js +2 -2
- package/dist/esm/router/transport/fetch/routes/auth.js +1 -1
- package/dist/esm/router/transport/fetch/routes/deviceLinking.js +3 -3
- package/dist/esm/router/transport/fetch/routes/deviceLinkingOwnerAuthorization.js +2 -2
- package/dist/esm/router/transport/fetch/routes/ed25519AuthorizedOperationRevalidation.js +65 -0
- package/dist/esm/router/transport/fetch/routes/normalSigningRouterProxy.js +13 -3
- package/dist/esm/router/transport/fetch/routes/passkeyCustody.js +3 -3
- package/dist/esm/router/transport/fetch/routes/sessions.js +3 -2
- package/dist/esm/router/transport/fetch/routes/thresholdEcdsa.js +67 -130
- package/dist/esm/router/transport/fetch/routes/thresholdEd25519.js +76 -212
- package/dist/esm/router/transport/fetch/routes/walletExecutionLanePreflight.js +18 -41
- package/dist/esm/router/transport/fetch/routes/walletRegistration.js +6 -5
- package/dist/esm/router/transport/fetch/routes/webauthnAuthenticators.js +1 -1
- package/dist/esm/shared-ts/src/authorization/index.js +1 -1
- package/dist/esm/shared-ts/src/authorization/walletAuthority.js +2 -2
- package/dist/esm/shared-ts/src/device-linking/activeWalletSession.js +12 -2
- package/dist/esm/shared-ts/src/device-linking/digests.js +1 -1
- package/dist/esm/shared-ts/src/device-linking/ed25519ExportRoot.js +1 -1
- package/dist/esm/shared-ts/src/device-linking/index.js +1 -1
- package/dist/esm/shared-ts/src/device-linking/parsers.js +1 -1
- package/dist/esm/shared-ts/src/device-linking/sourceContribution.js +1 -1
- package/dist/esm/shared-ts/src/device-linking/wireFields.js +1 -1
- package/dist/esm/shared-ts/src/near/nearClient.js +1 -1
- package/dist/esm/shared-ts/src/signing-lanes/ownerContinuity.js +2 -2
- package/dist/esm/shared-ts/src/utils/ecdsaServerTiming.js +6 -1
- package/dist/esm/shared-ts/src/utils/emailOtpDomain.js +4 -2
- package/dist/esm/shared-ts/src/utils/routerAbEcdsaDerivation.js +1 -1
- package/dist/esm/shared-ts/src/utils/routerAbPublicKeyset.js +0 -27
- package/dist/esm/shared-ts/src/wallet-recovery/walletRecoveryEcdsaPossession.js +1 -1
- package/dist/esm/threshold/session/signingSessionSeal/options.js +1 -1
- package/dist/esm/wasm/near_signer/pkg/wasm_signer_worker_bg.wasm +0 -0
- package/dist/types/shared-ts/src/device-linking/activeWalletSession.d.ts +2 -1
- package/dist/types/shared-ts/src/device-linking/contracts.d.ts +10 -0
- package/dist/types/shared-ts/src/threshold/ed25519OperationFingerprint.d.ts +2 -1
- package/dist/types/shared-ts/src/utils/emailOtpDomain.d.ts +3 -1
- package/dist/types/shared-ts/src/utils/routerAbPublicKeyset.d.ts +0 -9
- package/dist/types/shared-ts/src/utils/walletManagementProtocol.d.ts +1 -1
- package/dist/types/wallet-server/src/authorization/domain.d.ts +17 -1
- package/dist/types/wallet-server/src/authorization/ecdsaWalletSessionAdmission.d.ts +1 -0
- package/dist/types/wallet-server/src/authorization/ed25519WalletSessionAdmission.d.ts +35 -0
- package/dist/types/wallet-server/src/authorization/ed25519WalletSessionAdmission.typecheck.d.ts +2 -0
- package/dist/types/wallet-server/src/authorization/service.d.ts +43 -5
- package/dist/types/wallet-server/src/authorization/sessionRouting.d.ts +2 -0
- package/dist/types/wallet-server/src/cloud-host.d.ts +7 -3
- package/dist/types/wallet-server/src/core/EmailOtpRecords.d.ts +2 -1
- package/dist/types/wallet-server/src/core/EmailOtpStores.d.ts +19 -5
- package/dist/types/wallet-server/src/core/ThresholdService/routerAb/ecdsaDerivationPoolFillHandlers.d.ts +1 -0
- package/dist/types/wallet-server/src/core/ThresholdService/routerAb/ecdsaDerivationPresignBridge.d.ts +6 -0
- package/dist/types/wallet-server/src/core/ThresholdService/routerAb/internalServiceHttp.d.ts +1 -0
- package/dist/types/wallet-server/src/core/d1Ed25519SignerRead.d.ts +17 -0
- package/dist/types/wallet-server/src/core/d1WalletStore.d.ts +6 -0
- package/dist/types/wallet-server/src/core/emailOtpD1Statements.d.ts +1 -0
- package/dist/types/wallet-server/src/core/routerAbSigning/RouterAbEcdsaPresignRuntime.d.ts +5 -1
- package/dist/types/wallet-server/src/core/signingMaterial/ordinaryInactiveSignerMaterialReservation.d.ts +1 -0
- package/dist/types/wallet-server/src/core/threeRouteRegistrationContracts.d.ts +14 -48
- package/dist/types/wallet-server/src/hosted-wallet-gateway.d.ts +4 -3
- package/dist/types/wallet-server/src/localIntendedYaoSigningFault.d.ts +1 -16
- package/dist/types/wallet-server/src/localRegistrationSetupAuthority.d.ts +1 -1
- package/dist/types/wallet-server/src/router/auth/commonRouterUtils.d.ts +7 -1
- package/dist/types/wallet-server/src/router/auth/routerApiCredentialAuth.d.ts +11 -3
- package/dist/types/wallet-server/src/router/auth/walletRegistrationContext.d.ts +8 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/auth/d1AuthorizationAssembly.d.ts +1 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/auth/d1EmailOtpRouteService.d.ts +16 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/auth/d1RouterApiAuthConfig.d.ts +7 -4
- package/dist/types/wallet-server/src/router/cloudflare/d1/auth/d1RouterApiAuthService.d.ts +4 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/auth/walletSessionCredentialReaders.d.ts +7 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/authorization/d1AuthorizationStore.d.ts +32 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceAuthorityInstallService.d.ts +2 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoLifecycleDecisionStore.d.ts +3 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoProductRegistrationPartitionedStateStore.d.ts +1 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoStateWriteFence.d.ts +8 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/ed25519Yao/d1WalletCeremonyActivity.d.ts +15 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeIssuer.d.ts +6 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeStore.d.ts +1 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeVerifier.d.ts +4 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpCounters.typecheck.d.ts +2 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpRateLimitStore.d.ts +6 -29
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpRecords.d.ts +21 -7
- package/dist/types/wallet-server/src/router/cloudflare/d1/passkeyCustody/d1WalletCustodyCommitStore.d.ts +17 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationCeremonyRecordStore.d.ts +32 -7
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationCeremonyStore.d.ts +16 -7
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationSessionTransaction.d.ts +13 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationSetupSupport.d.ts +7 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletExecutionAuthority.d.ts +41 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletOperationStore.d.ts +28 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationCommitStore.d.ts +6 -9
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationInitialSession.d.ts +17 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationPreparation.d.ts +12 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationRead.d.ts +43 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationService.d.ts +24 -45
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationSetupExecution.d.ts +9 -4
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/walletRegistrationEstablishedSessionIssuer.d.ts +42 -14
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/walletRegistrationSessionCommitReceipt.d.ts +5 -4
- package/dist/types/wallet-server/src/router/cloudflare/d1/signingAdmission/d1RouterAbNormalSigningAdmissionStore.d.ts +24 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/versionedJson/d1VersionedJsonRecordStore.d.ts +10 -4
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/authorizationSnapshotLayout.d.ts +21 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAddSignerService.d.ts +3 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthMethodService.d.ts +3 -7
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorityStore.d.ts +8 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorizationCleanup.d.ts +20 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorizationFreeze.d.ts +12 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorizationHistory.d.ts +20 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorizationIntake.d.ts +29 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorizationSnapshot.d.ts +31 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationApprovals.d.ts +49 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationChallenges.d.ts +47 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationEmailOtp.d.ts +25 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationOwner.d.ts +88 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationOwnerRequest.d.ts +37 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationPasskey.d.ts +12 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationReadAccess.d.ts +18 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationSessions.d.ts +23 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationWriteBlock.d.ts +16 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/walletObjectAddresses.d.ts +14 -0
- package/dist/types/wallet-server/src/router/cloudflare/runtime/routerAbServiceBindings.d.ts +13 -0
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletAuthorizationRelocationRoutes.d.ts +21 -0
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletConsoleOps.d.ts +1 -1
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletConsoleOpsClient.d.ts +3 -3
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletControlOps.d.ts +2 -1
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletGateway.d.ts +3 -1
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletObjectAddresses.d.ts +45 -0
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletPlacementRoutes.d.ts +30 -0
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRelocationDeriver.d.ts +11 -0
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRelocationEcdsa.d.ts +7 -0
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRelocationEd25519.d.ts +7 -0
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRelocationOps.d.ts +11 -0
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRelocationPresign.d.ts +7 -0
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRelocationSource.d.ts +26 -0
- package/dist/types/wallet-server/src/router/cloudflare/signingLanes/cloudflareOrdinaryInactiveSignerMaterialReservation.d.ts +5 -0
- package/dist/types/wallet-server/src/router/domains/ecdsa/routerAbEcdsaStrictRegistration.d.ts +3 -0
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoCapabilityCommit.d.ts +7 -0
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistration.d.ts +41 -7
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationPartitionedStateStore.d.ts +33 -2
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/export/routerAbEd25519YaoExport.d.ts +12 -6
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecovery.d.ts +17 -9
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecoveryWalletSessionAuthorization.d.ts +2 -0
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/registration/routerAbEd25519YaoHttpRegistrationBackend.d.ts +13 -14
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistration.d.ts +7 -3
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationExecutionRecord.d.ts +1 -0
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationIntentAuthorization.d.ts +6 -1
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationSideEffectBoundary.d.ts +11 -0
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/routerAbEd25519YaoGatewayEnvelope.d.ts +12 -3
- package/dist/types/wallet-server/src/router/domains/passkeyCustody/registrationCustodyOutcome.d.ts +10 -6
- package/dist/types/wallet-server/src/router/domains/passkeyCustody/walletCustodyRegistrationAdmission.d.ts +10 -3
- package/dist/types/wallet-server/src/router/domains/passkeyCustody/walletCustodyRegistrationCommit.d.ts +12 -5
- package/dist/types/wallet-server/src/router/domains/signingOperations/authorizedOperationWire.d.ts +97 -0
- package/dist/types/wallet-server/src/router/domains/signingOperations/ecdsaSigningResponse.d.ts +13 -0
- package/dist/types/wallet-server/src/router/domains/signingOperations/routerAbNormalSigningAdmission.d.ts +9 -206
- package/dist/types/wallet-server/src/router/domains/signingOperations/signingPrepareSession.d.ts +23 -0
- package/dist/types/wallet-server/src/router/domains/walletRegistration/registrationSessionSeal.d.ts +36 -0
- package/dist/types/wallet-server/src/router/domains/walletRegistration/walletRegistrationInputs.d.ts +7 -7
- package/dist/types/wallet-server/src/router/domains/walletRegistration/walletRegistrationReservation.d.ts +80 -6
- package/dist/types/wallet-server/src/router/domains/walletRegistration/walletRegistrationRoutes.d.ts +15 -5
- package/dist/types/wallet-server/src/router/framework/apiCredentialPorts.d.ts +24 -0
- package/dist/types/wallet-server/src/router/framework/authServicePort.d.ts +21 -7
- package/dist/types/wallet-server/src/router/framework/routerApi.d.ts +3 -12
- package/dist/types/wallet-server/src/router/transport/fetch/routes/ed25519AuthorizedOperationRevalidation.d.ts +37 -0
- package/dist/types/wallet-server/src/router/transport/fetch/routes/thresholdEcdsa.d.ts +1 -17
- package/dist/types/wallet-server/src/storage/tenantRoute.d.ts +1 -1
- package/migrations/d1-signer/0049_wallet_relocation_challenges.sql +16 -0
- package/migrations/d1-signer/0050_wallet_relocation_approvals.sql +14 -0
- package/migrations/d1-signer/0051_wallet_relocation_email_otp.sql +92 -0
- package/migrations/d1-signer/0052_wallet_relocation_session_fences.sql +91 -0
- package/migrations/d1-signer/0053_wallet_hosted_history_import.sql +164 -0
- package/migrations/d1-signer/0054_wallet_authorization_freeze.sql +318 -0
- package/migrations/d1-signer/0055_wallet_authorization_snapshot.sql +120 -0
- package/migrations/d1-signer/0056_wallet_authorization_history_import.sql +424 -0
- package/migrations/d1-signer/0057_wallet_authorization_intake.sql +44 -0
- package/migrations/d1-signer/0058_wallet_ceremony_activity.sql +59 -0
- package/migrations/d1-signer/0059_wallet_authorization_activation.sql +45 -0
- package/migrations/d1-signer/0060_wallet_authorization_cleanup.sql +153 -0
- package/migrations/d1-signer/0061_wallet_session_operation_settlement.sql +28 -0
- package/migrations/d1-signer/0062_wallet_step_up_operation_settlement.sql +204 -0
- package/migrations/d1-signer/0063_wallet_operation_history_transfer.sql +466 -0
- package/migrations/d1-signer/0064_wallet_execution_generations.sql +93 -0
- package/migrations/d1-signer/0065_wallet_operation_execution_generation.sql +37 -0
- package/migrations/d1-signer/0066_regional_deployment_admission.sql +59 -0
- package/migrations/d1-signer/0067_registration_completion_decision.sql +12 -0
- package/migrations/d1-signer/0068_registration_cancellation_write_fence.sql +24 -0
- package/migrations/d1-signer/0069_cancelled_registration_session_fence.sql +11 -0
- package/migrations/d1-signer/0070_wallet_passkey_relocation.sql +369 -0
- package/migrations/d1-signer/0071_regional_wallet_otp_counters.sql +98 -0
- package/migrations/d1-signer/0072_linked_device_relocation_history.sql +899 -0
- package/migrations/d1-signer/0073_wallet_recovery_relocation.sql +86 -0
- package/migrations/d1-signer/0074_email_otp_relocation.sql +158 -0
- package/migrations/d1-signer/0075_wallet_authorization_return.sql +107 -0
- package/migrations/d1-signer/0076_wallet_relocation_write_block.sql +406 -0
- package/migrations/d1-signer/0077_wallet_object_addresses.sql +24 -0
- package/package.json +1 -1
- package/src/README.md +23 -1
- package/cloudflare-router-ab/scripts/local-key-material.mjs +0 -29
|
@@ -992,15 +992,25 @@ function parseTargetEmail(raw, label) {
|
|
|
992
992
|
}
|
|
993
993
|
//#endregion
|
|
994
994
|
//#region ../shared-ts/src/device-linking/activeWalletSession.ts
|
|
995
|
+
const walletSessionHome = wireUnion("kind", [wireObject({ kind: wireLiteral("direct") }), wireObject({
|
|
996
|
+
kind: wireLiteral("regional"),
|
|
997
|
+
region: wireLiteral("US", "WEUR", "APAC", "OC")
|
|
998
|
+
})]);
|
|
999
|
+
function parseWalletSessionHome(raw) {
|
|
1000
|
+
return walletSessionHome(raw, "Wallet Session home");
|
|
1001
|
+
}
|
|
995
1002
|
function walletSessionOperationCredentialV1() {
|
|
996
1003
|
return wireObject({
|
|
997
1004
|
kind: wireLiteral("opaque_wallet_session_operation_credential_v1"),
|
|
1005
|
+
ownershipGeneration: parseNonNegativeSafeInteger,
|
|
1006
|
+
home: parseWalletSessionHome,
|
|
998
1007
|
token: (raw, label) => {
|
|
999
1008
|
if (typeof raw !== "string" || raw.length > 8192) throw new Error(`${label} is invalid`);
|
|
1000
1009
|
return raw;
|
|
1001
1010
|
},
|
|
1002
1011
|
walletSessionId: keyLabeled(walletSessionId)
|
|
1003
1012
|
}, (credential, label) => {
|
|
1013
|
+
if (credential.ownershipGeneration === 0) throw new Error(`${label} ownership generation must be positive`);
|
|
1004
1014
|
if (!/^wst_[A-Za-z0-9_-]{43}$/.test(credential.token)) throw new Error(`${label} opaque token is invalid`);
|
|
1005
1015
|
});
|
|
1006
1016
|
}
|
|
@@ -1445,11 +1455,6 @@ function requireSignerRole(value, label) {
|
|
|
1445
1455
|
default: throw new Error(`${label} must be signer_a or signer_b`);
|
|
1446
1456
|
}
|
|
1447
1457
|
}
|
|
1448
|
-
function requireLowerHex(value, label, byteLength) {
|
|
1449
|
-
const hex = coerceNonEmptyString(value, label);
|
|
1450
|
-
if (!new RegExp(`^[0-9a-f]{${byteLength * 2}}$`).test(hex)) throw new Error(`${label} must be ${byteLength} lowercase-hex bytes`);
|
|
1451
|
-
return hex;
|
|
1452
|
-
}
|
|
1453
1458
|
function requireRouterAbX25519PublicKey(value, label) {
|
|
1454
1459
|
const publicKey = coerceNonEmptyString(value, label);
|
|
1455
1460
|
if (!/^x25519:[0-9a-f]{64}$/.test(publicKey)) throw new Error(`${label} must use x25519:<64 lowercase hex chars> encoding`);
|
|
@@ -1504,26 +1509,6 @@ function parseSignerEnvelopeHpkeRotationPublicKeySet(value, label) {
|
|
|
1504
1509
|
previous_retire_at_ms: requirePositiveInteger(record.previous_retire_at_ms, `${label}.previous_retire_at_ms`)
|
|
1505
1510
|
};
|
|
1506
1511
|
}
|
|
1507
|
-
function parseSignerPeerVerifyingKey(value, label) {
|
|
1508
|
-
const record = requireRecord(value, label);
|
|
1509
|
-
requireExactKeys$5(record, ["role", "verifying_key_hex"], label);
|
|
1510
|
-
return {
|
|
1511
|
-
role: requireSignerRole(record.role, `${label}.role`),
|
|
1512
|
-
verifying_key_hex: requireLowerHex(record.verifying_key_hex, `${label}.verifying_key_hex`, 32)
|
|
1513
|
-
};
|
|
1514
|
-
}
|
|
1515
|
-
function parseSignerPeerVerifyingKeySet(value, label) {
|
|
1516
|
-
const record = requireRecord(value, label);
|
|
1517
|
-
requireExactKeys$5(record, ["deriver_a", "deriver_b"], label);
|
|
1518
|
-
const deriverA = parseSignerPeerVerifyingKey(record.deriver_a, `${label}.deriver_a`);
|
|
1519
|
-
const deriverB = parseSignerPeerVerifyingKey(record.deriver_b, `${label}.deriver_b`);
|
|
1520
|
-
if (deriverA.role !== "signer_a") throw new Error(`${label}.deriver_a.role must be signer_a`);
|
|
1521
|
-
if (deriverB.role !== "signer_b") throw new Error(`${label}.deriver_b.role must be signer_b`);
|
|
1522
|
-
return {
|
|
1523
|
-
deriver_a: deriverA,
|
|
1524
|
-
deriver_b: deriverB
|
|
1525
|
-
};
|
|
1526
|
-
}
|
|
1527
1512
|
function parsePublicHpkeKeyDescriptor(value, label) {
|
|
1528
1513
|
const record = requireRecord(value, label);
|
|
1529
1514
|
requireExactKeys$5(record, ["key_epoch", "public_key"], label);
|
|
@@ -1537,7 +1522,6 @@ function parseRouterAbPublicKeysetV2(value) {
|
|
|
1537
1522
|
requireExactKeys$5(record, [
|
|
1538
1523
|
"keyset_version",
|
|
1539
1524
|
"signer_envelope_hpke",
|
|
1540
|
-
"signer_peer_verifying_keys",
|
|
1541
1525
|
"signing_worker_server_output_hpke"
|
|
1542
1526
|
], "Router A/B public keyset");
|
|
1543
1527
|
const keysetVersion = coerceNonEmptyString(record.keyset_version, "keyset_version");
|
|
@@ -1545,7 +1529,6 @@ function parseRouterAbPublicKeysetV2(value) {
|
|
|
1545
1529
|
return {
|
|
1546
1530
|
keyset_version: ROUTER_AB_PUBLIC_KEYSET_VERSION_V2,
|
|
1547
1531
|
signer_envelope_hpke: parseSignerEnvelopeHpkeRotationPublicKeySet(record.signer_envelope_hpke, "signer_envelope_hpke"),
|
|
1548
|
-
signer_peer_verifying_keys: parseSignerPeerVerifyingKeySet(record.signer_peer_verifying_keys, "signer_peer_verifying_keys"),
|
|
1549
1532
|
signing_worker_server_output_hpke: parsePublicHpkeKeyDescriptor(record.signing_worker_server_output_hpke, "signing_worker_server_output_hpke")
|
|
1550
1533
|
};
|
|
1551
1534
|
}
|
|
@@ -5335,6 +5318,7 @@ const CORS_ALLOW_HEADERS = [
|
|
|
5335
5318
|
"Content-Type",
|
|
5336
5319
|
WALLET_MANAGEMENT_PROTOCOL_HEADER,
|
|
5337
5320
|
"Authorization",
|
|
5321
|
+
"X-Seams-Wallet-Region",
|
|
5338
5322
|
"X-Seams-Benchmark-Diagnostics",
|
|
5339
5323
|
LINKED_DEVICE_REQUEST_PROOF_HEADER_V1,
|
|
5340
5324
|
ROUTER_AB_ED25519_YAO_RECOVERY_CHALLENGE_ID_HEADER_V1,
|
|
@@ -5387,7 +5371,7 @@ function withCors(headers, opts, request) {
|
|
|
5387
5371
|
headers.set("Access-Control-Allow-Methods", CORS_ALLOW_METHODS);
|
|
5388
5372
|
headers.set("Access-Control-Allow-Headers", CORS_ALLOW_HEADERS);
|
|
5389
5373
|
if (allowedOrigin && request?.method === "OPTIONS") headers.set("Access-Control-Max-Age", String(CORS_PREFLIGHT_MAX_AGE_SECONDS));
|
|
5390
|
-
|
|
5374
|
+
headers.set("Access-Control-Expose-Headers", "Server-Timing, X-Seams-Wallet-Region");
|
|
5391
5375
|
if (allowedOrigin && allowedOrigin !== "*") headers.set("Access-Control-Allow-Credentials", "true");
|
|
5392
5376
|
}
|
|
5393
5377
|
async function readJson(request) {
|
|
@@ -5497,7 +5481,7 @@ function routeAuthNotConfigured(message) {
|
|
|
5497
5481
|
message
|
|
5498
5482
|
};
|
|
5499
5483
|
}
|
|
5500
|
-
|
|
5484
|
+
function parsePublishableKeyRequest(input) {
|
|
5501
5485
|
if (input.route.auth.plane !== "api_credentials") return routeAuthNotConfigured(input.routeAuthNotConfiguredMessage);
|
|
5502
5486
|
const publishableKey = extractBearerCredential(input.headers);
|
|
5503
5487
|
if (!publishableKey) return {
|
|
@@ -5520,23 +5504,42 @@ async function resolvePublishableKeyApiCredentialAuth(input) {
|
|
|
5520
5504
|
code: "forbidden",
|
|
5521
5505
|
message: `publishable_key_environment_mismatch: ${input.missingEnvironmentMessage}`
|
|
5522
5506
|
};
|
|
5523
|
-
|
|
5524
|
-
|
|
5525
|
-
|
|
5526
|
-
|
|
5507
|
+
return {
|
|
5508
|
+
ok: true,
|
|
5509
|
+
request: {
|
|
5510
|
+
secret: publishableKey,
|
|
5511
|
+
origin,
|
|
5512
|
+
environmentId
|
|
5513
|
+
}
|
|
5514
|
+
};
|
|
5515
|
+
}
|
|
5516
|
+
async function resolveWalletRegistrationContext(input) {
|
|
5517
|
+
const parsed = parsePublishableKeyRequest(input);
|
|
5518
|
+
if (!parsed.ok) return parsed;
|
|
5519
|
+
return input.registrationContext.resolve({
|
|
5520
|
+
...parsed.request,
|
|
5521
|
+
registration: input.registration
|
|
5527
5522
|
});
|
|
5523
|
+
}
|
|
5524
|
+
async function resolvePublishableKeyApiCredentialAuth(input) {
|
|
5525
|
+
const parsed = parsePublishableKeyRequest(input);
|
|
5526
|
+
if (!parsed.ok) return parsed;
|
|
5527
|
+
const authResult = await input.publishableKeyAuth.authenticate(parsed.request);
|
|
5528
5528
|
if (!authResult.ok) return {
|
|
5529
5529
|
ok: false,
|
|
5530
5530
|
status: authResult.status,
|
|
5531
5531
|
code: authResult.status === 403 ? "forbidden" : "unauthorized",
|
|
5532
5532
|
message: `${authResult.code}: ${authResult.message}`
|
|
5533
5533
|
};
|
|
5534
|
+
return publishableKeyRoutePrincipal(authResult.principal);
|
|
5535
|
+
}
|
|
5536
|
+
async function publishableKeyRoutePrincipal(principal) {
|
|
5534
5537
|
return {
|
|
5535
5538
|
ok: true,
|
|
5536
5539
|
principal: {
|
|
5537
5540
|
kind: "api_credentials",
|
|
5538
5541
|
credentialType: "publishable_key",
|
|
5539
|
-
principal
|
|
5542
|
+
principal
|
|
5540
5543
|
}
|
|
5541
5544
|
};
|
|
5542
5545
|
}
|
|
@@ -5937,6 +5940,9 @@ function walletSessionCapabilitySubjectsV1Equal(left, right) {
|
|
|
5937
5940
|
}
|
|
5938
5941
|
return true;
|
|
5939
5942
|
}
|
|
5943
|
+
function walletSessionAuthorizationV2RecordsEqual(left, right) {
|
|
5944
|
+
return left.kind === right.kind && left.tenantId === right.tenantId && left.principalId === right.principalId && left.walletId === right.walletId && left.authorityId === right.authorityId && left.walletAuthMethodId === right.walletAuthMethodId && left.authorityDigestB64u === right.authorityDigestB64u && left.authorityRevocationEpoch === right.authorityRevocationEpoch && left.mintId === right.mintId && left.authorizationId === right.authorizationId && left.walletSessionId === right.walletSessionId && left.quotaId === right.quotaId && walletSessionCapabilitySubjectsV1Equal(left.capabilitySubjects, right.capabilitySubjects) && left.createdAtMs === right.createdAtMs && left.expiresAtMs === right.expiresAtMs;
|
|
5945
|
+
}
|
|
5940
5946
|
function parseAuthorizedOperationReplayResponse(value) {
|
|
5941
5947
|
if (!isAuthorizedOperationReplayResponseRecordV1(value)) throw new Error("authorized operation replay response must be an object");
|
|
5942
5948
|
const keys = Object.keys(value).sort();
|
|
@@ -6321,12 +6327,23 @@ async function validateRouterAbEd25519WalletSessionInputs(input) {
|
|
|
6321
6327
|
const token = extractBearerCredential(input.headers);
|
|
6322
6328
|
if (!token) return walletSessionFailure("wallet_session_missing");
|
|
6323
6329
|
const nowMs = input.nowMs || Date.now;
|
|
6330
|
+
let read;
|
|
6324
6331
|
let resolution;
|
|
6325
6332
|
try {
|
|
6326
|
-
|
|
6327
|
-
authorizationSessions,
|
|
6333
|
+
read = await authorizationSessions.readEd25519WalletSessionSigningReadByOperationCredential({
|
|
6334
|
+
tenantId: authorizationSessions.tenantId,
|
|
6328
6335
|
token,
|
|
6329
6336
|
nowMs: nowMs(),
|
|
6337
|
+
materialActivation: input.materialActivation
|
|
6338
|
+
});
|
|
6339
|
+
if (!read) return {
|
|
6340
|
+
ok: false,
|
|
6341
|
+
code: "wallet_session_invalid",
|
|
6342
|
+
message: walletSessionFailureMessage("wallet_session_invalid")
|
|
6343
|
+
};
|
|
6344
|
+
resolution = resolveWalletSessionOperationCredentialAdmissionFromContext({
|
|
6345
|
+
context: read.context,
|
|
6346
|
+
nowMs: nowMs(),
|
|
6330
6347
|
operation: {
|
|
6331
6348
|
keyFamily: "ed25519",
|
|
6332
6349
|
operationKind: input.operationKind
|
|
@@ -6335,18 +6352,14 @@ async function validateRouterAbEd25519WalletSessionInputs(input) {
|
|
|
6335
6352
|
} catch {
|
|
6336
6353
|
return walletSessionFailure("wallet_session_unavailable");
|
|
6337
6354
|
}
|
|
6338
|
-
if (resolution.kind === "rejected") return walletSessionFailure("wallet_session_scope_mismatch");
|
|
6339
|
-
if (resolution.kind === "not_found") return {
|
|
6340
|
-
ok: false,
|
|
6341
|
-
code: "wallet_session_invalid",
|
|
6342
|
-
message: walletSessionFailureMessage("wallet_session_invalid")
|
|
6343
|
-
};
|
|
6344
|
-
if (resolution.admission.curve !== "ed25519") return walletSessionFailure("wallet_session_scope_mismatch");
|
|
6355
|
+
if (resolution.kind === "rejected" || resolution.admission.curve !== "ed25519") return walletSessionFailure("wallet_session_scope_mismatch");
|
|
6345
6356
|
return {
|
|
6346
6357
|
ok: true,
|
|
6347
6358
|
kind: "wallet_session_operation_credential_v1",
|
|
6348
6359
|
admission: resolution.admission,
|
|
6349
|
-
context: resolution.admission.context
|
|
6360
|
+
context: resolution.admission.context,
|
|
6361
|
+
signerRead: read.signerRead,
|
|
6362
|
+
policyRead: read.policyRead
|
|
6350
6363
|
};
|
|
6351
6364
|
}
|
|
6352
6365
|
async function validateEcdsaPreprocessingSession(input) {
|
|
@@ -6666,6 +6679,123 @@ async function enforceRoutePolicy(input) {
|
|
|
6666
6679
|
};
|
|
6667
6680
|
}
|
|
6668
6681
|
//#endregion
|
|
6682
|
+
//#region src/router/domains/walletRegistration/registrationSessionSeal.ts
|
|
6683
|
+
/** Holds one request's computation until registration can publish its response. */
|
|
6684
|
+
var RegistrationPreparedSessionSeal = class {
|
|
6685
|
+
constructor(request, service) {
|
|
6686
|
+
this.request = request;
|
|
6687
|
+
this.service = service;
|
|
6688
|
+
this.prepared = null;
|
|
6689
|
+
}
|
|
6690
|
+
async prepare(session) {
|
|
6691
|
+
await this.finish(session);
|
|
6692
|
+
}
|
|
6693
|
+
async finish(session) {
|
|
6694
|
+
const tokens = session.tokens;
|
|
6695
|
+
const ed25519 = tokens.kind === "near_ed25519" || tokens.kind === "near_ed25519_and_evm_family_ecdsa" ? tokens.ed25519 : null;
|
|
6696
|
+
if (!ed25519 || String(ed25519.thresholdSessionId) !== this.request.thresholdSessionId) return {
|
|
6697
|
+
ok: false,
|
|
6698
|
+
code: "invalid_session_seal",
|
|
6699
|
+
message: "Prepared seal does not match the established Ed25519 session"
|
|
6700
|
+
};
|
|
6701
|
+
if (this.prepared === null) this.prepared = {
|
|
6702
|
+
walletId: String(session.walletId),
|
|
6703
|
+
walletSessionId: String(session.walletSessionId),
|
|
6704
|
+
expiresAtMs: session.expiresAtMs,
|
|
6705
|
+
result: applyRegistrationSessionSeal(this.service, this.request, session)
|
|
6706
|
+
};
|
|
6707
|
+
if (this.prepared.walletId !== String(session.walletId) || this.prepared.walletSessionId !== String(session.walletSessionId) || this.prepared.expiresAtMs !== session.expiresAtMs) return {
|
|
6708
|
+
ok: false,
|
|
6709
|
+
code: "invalid_session_seal",
|
|
6710
|
+
message: "Prepared seal does not match the committed Wallet Session"
|
|
6711
|
+
};
|
|
6712
|
+
const sealed = await this.prepared.result;
|
|
6713
|
+
if (!sealed.ok) return sealed;
|
|
6714
|
+
const keyVersion = String(sealed.keyVersion || "").trim();
|
|
6715
|
+
if (!keyVersion) return {
|
|
6716
|
+
ok: false,
|
|
6717
|
+
code: "invalid_session_seal",
|
|
6718
|
+
message: "Signing-session seal response is missing its key version"
|
|
6719
|
+
};
|
|
6720
|
+
const expiresAtMs = Math.min(sealed.expiresAtMs ?? session.expiresAtMs, session.expiresAtMs);
|
|
6721
|
+
if (expiresAtMs <= Date.now()) return {
|
|
6722
|
+
ok: false,
|
|
6723
|
+
code: "expired",
|
|
6724
|
+
message: "threshold session expired"
|
|
6725
|
+
};
|
|
6726
|
+
return {
|
|
6727
|
+
ok: true,
|
|
6728
|
+
value: {
|
|
6729
|
+
ciphertext: sealed.ciphertext,
|
|
6730
|
+
keyVersion,
|
|
6731
|
+
expiresAtMs,
|
|
6732
|
+
remainingUses: session.remainingUses
|
|
6733
|
+
}
|
|
6734
|
+
};
|
|
6735
|
+
}
|
|
6736
|
+
};
|
|
6737
|
+
async function applyRegistrationSessionSeal(service, request, session) {
|
|
6738
|
+
if (!service) return {
|
|
6739
|
+
ok: false,
|
|
6740
|
+
code: "signing_session_seal_unavailable",
|
|
6741
|
+
message: "Signing-session sealing is unavailable"
|
|
6742
|
+
};
|
|
6743
|
+
try {
|
|
6744
|
+
return await service.applyServerSeal(request, {
|
|
6745
|
+
userId: String(session.walletId),
|
|
6746
|
+
session: {
|
|
6747
|
+
kind: "exact_wallet_session_operation_credential",
|
|
6748
|
+
curve: "ed25519",
|
|
6749
|
+
thresholdSessionId: request.thresholdSessionId,
|
|
6750
|
+
userId: String(session.walletId),
|
|
6751
|
+
expiresAtMs: session.expiresAtMs
|
|
6752
|
+
}
|
|
6753
|
+
});
|
|
6754
|
+
} catch {
|
|
6755
|
+
return {
|
|
6756
|
+
ok: false,
|
|
6757
|
+
code: "signing_session_seal_unavailable",
|
|
6758
|
+
message: "Signing-session sealing failed"
|
|
6759
|
+
};
|
|
6760
|
+
}
|
|
6761
|
+
}
|
|
6762
|
+
function parseRegistrationPreparedSessionSeal(raw, service) {
|
|
6763
|
+
if (raw === void 0) return {
|
|
6764
|
+
ok: true,
|
|
6765
|
+
value: null
|
|
6766
|
+
};
|
|
6767
|
+
if (!isPlainObject(raw)) return {
|
|
6768
|
+
ok: false,
|
|
6769
|
+
code: "invalid_body",
|
|
6770
|
+
message: "sessionSeal must be an object"
|
|
6771
|
+
};
|
|
6772
|
+
for (const field of Object.keys(raw)) if (![
|
|
6773
|
+
"thresholdSessionId",
|
|
6774
|
+
"ciphertext",
|
|
6775
|
+
"keyVersion"
|
|
6776
|
+
].includes(field)) return {
|
|
6777
|
+
ok: false,
|
|
6778
|
+
code: "invalid_body",
|
|
6779
|
+
message: "sessionSeal has unknown fields"
|
|
6780
|
+
};
|
|
6781
|
+
const thresholdSessionId = String(raw.thresholdSessionId || "").trim();
|
|
6782
|
+
const ciphertext = String(raw.ciphertext || "").trim();
|
|
6783
|
+
const keyVersion = String(raw.keyVersion || "").trim();
|
|
6784
|
+
if (!thresholdSessionId || !ciphertext) return {
|
|
6785
|
+
ok: false,
|
|
6786
|
+
code: "invalid_body",
|
|
6787
|
+
message: "sessionSeal thresholdSessionId and ciphertext are required"
|
|
6788
|
+
};
|
|
6789
|
+
return {
|
|
6790
|
+
ok: true,
|
|
6791
|
+
value: new RegistrationPreparedSessionSeal({
|
|
6792
|
+
thresholdSessionId,
|
|
6793
|
+
ciphertext,
|
|
6794
|
+
...keyVersion ? { keyVersion } : {}
|
|
6795
|
+
}, service)
|
|
6796
|
+
};
|
|
6797
|
+
}
|
|
6798
|
+
//#endregion
|
|
6669
6799
|
//#region src/router/framework/routeResponses.ts
|
|
6670
6800
|
function routeJson(status, body, options) {
|
|
6671
6801
|
return {
|
|
@@ -7084,99 +7214,6 @@ function parsePasskeyCustodyEnvelopeRecord(raw, label = "walletCustodyEnvelope")
|
|
|
7084
7214
|
});
|
|
7085
7215
|
}
|
|
7086
7216
|
//#endregion
|
|
7087
|
-
//#region src/router/domains/walletRegistration/walletRegistrationSetupPayload.ts
|
|
7088
|
-
const WALLET_REGISTRATION_SETUP_CLAIM_KIND = "wallet_registration_setup_v1";
|
|
7089
|
-
/**
|
|
7090
|
-
* Verifies the payload and binds it to the ceremony the caller is driving.
|
|
7091
|
-
* A payload that verifies cryptographically but names a different ceremony,
|
|
7092
|
-
* wallet, or setup digest is rejected — signature validity alone is not
|
|
7093
|
-
* authorization for this request.
|
|
7094
|
-
*/
|
|
7095
|
-
/**
|
|
7096
|
-
* Verifies the payload's signature, ceremony binding, and expiry, and returns
|
|
7097
|
-
* its claims — without needing the ceremony row.
|
|
7098
|
-
*
|
|
7099
|
-
* Activate depends on this: a successful activation deletes the ceremony, so
|
|
7100
|
-
* an exact replay must be answerable from the operation row alone. The claims
|
|
7101
|
-
* are Gateway-signed, so the `setupDigestB64u` they carry is trustworthy
|
|
7102
|
-
* without recomputing it from storage.
|
|
7103
|
-
*/
|
|
7104
|
-
async function verifyWalletRegistrationSetupClaims(signer, token, expected) {
|
|
7105
|
-
const value = normalizeOptionalTrimmedString(token);
|
|
7106
|
-
if (!value) return {
|
|
7107
|
-
ok: false,
|
|
7108
|
-
code: "invalid_body",
|
|
7109
|
-
message: "signedSetup is required"
|
|
7110
|
-
};
|
|
7111
|
-
const verified = await signer.verifyJwt(value);
|
|
7112
|
-
if (!verified.valid) return {
|
|
7113
|
-
ok: false,
|
|
7114
|
-
code: "invalid_grant",
|
|
7115
|
-
message: "signedSetup is not valid"
|
|
7116
|
-
};
|
|
7117
|
-
const claims = parseWalletRegistrationSetupClaims(verified.payload);
|
|
7118
|
-
if (!claims) return {
|
|
7119
|
-
ok: false,
|
|
7120
|
-
code: "invalid_grant",
|
|
7121
|
-
message: "signedSetup claims are not valid"
|
|
7122
|
-
};
|
|
7123
|
-
if (claims.registrationCeremonyId !== expected.registrationCeremonyId) return {
|
|
7124
|
-
ok: false,
|
|
7125
|
-
code: "invalid_grant",
|
|
7126
|
-
message: "signedSetup belongs to a different registration ceremony"
|
|
7127
|
-
};
|
|
7128
|
-
if (claims.expiresAtMs <= expected.nowMs) return {
|
|
7129
|
-
ok: false,
|
|
7130
|
-
code: "invalid_grant",
|
|
7131
|
-
message: "signedSetup has expired"
|
|
7132
|
-
};
|
|
7133
|
-
return {
|
|
7134
|
-
ok: true,
|
|
7135
|
-
claims
|
|
7136
|
-
};
|
|
7137
|
-
}
|
|
7138
|
-
function parseWalletRegistrationSetupClaims(value) {
|
|
7139
|
-
if (typeof value !== "object" || value === null) return null;
|
|
7140
|
-
const record = value;
|
|
7141
|
-
if (record.kind !== WALLET_REGISTRATION_SETUP_CLAIM_KIND) return null;
|
|
7142
|
-
const registrationCeremonyId = normalizeOptionalTrimmedString(record.registrationCeremonyId);
|
|
7143
|
-
const walletId = normalizeOptionalTrimmedString(record.walletId);
|
|
7144
|
-
const orgId = normalizeOptionalTrimmedString(record.orgId);
|
|
7145
|
-
const signingRootId = normalizeOptionalTrimmedString(record.signingRootId);
|
|
7146
|
-
const signingRootVersion = normalizeOptionalTrimmedString(record.signingRootVersion);
|
|
7147
|
-
const setupDigestB64u = normalizeOptionalTrimmedString(record.setupDigestB64u);
|
|
7148
|
-
const expiresAtMs = Number(record.expiresAtMs);
|
|
7149
|
-
const policy = parseWalletRegistrationSetupPolicy(record.policy);
|
|
7150
|
-
if (!registrationCeremonyId || !walletId || !orgId || !signingRootId || !signingRootVersion || !setupDigestB64u || !policy || !Number.isSafeInteger(expiresAtMs)) return null;
|
|
7151
|
-
return {
|
|
7152
|
-
kind: WALLET_REGISTRATION_SETUP_CLAIM_KIND,
|
|
7153
|
-
registrationCeremonyId,
|
|
7154
|
-
walletId,
|
|
7155
|
-
orgId,
|
|
7156
|
-
signingRootId,
|
|
7157
|
-
signingRootVersion,
|
|
7158
|
-
policy,
|
|
7159
|
-
setupDigestB64u,
|
|
7160
|
-
expiresAtMs
|
|
7161
|
-
};
|
|
7162
|
-
}
|
|
7163
|
-
function parseWalletRegistrationSetupPolicy(value) {
|
|
7164
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) return null;
|
|
7165
|
-
const record = value;
|
|
7166
|
-
switch (record.kind) {
|
|
7167
|
-
case "runtime_policy_scope": try {
|
|
7168
|
-
return {
|
|
7169
|
-
kind: "runtime_policy_scope",
|
|
7170
|
-
scope: normalizeRuntimePolicyScope(record.scope)
|
|
7171
|
-
};
|
|
7172
|
-
} catch {
|
|
7173
|
-
return null;
|
|
7174
|
-
}
|
|
7175
|
-
case "signing_root_only": return record.scope === void 0 ? { kind: "signing_root_only" } : null;
|
|
7176
|
-
default: return null;
|
|
7177
|
-
}
|
|
7178
|
-
}
|
|
7179
|
-
//#endregion
|
|
7180
7217
|
//#region ../shared-ts/src/utils/ecdsaKeyFactsInventory.ts
|
|
7181
7218
|
function normalizeChainTarget(target) {
|
|
7182
7219
|
if (target.kind === "evm") return {
|
|
@@ -9204,8 +9241,27 @@ async function handleRouterApiWalletRegistrationSetup(input) {
|
|
|
9204
9241
|
if (!isPlainObject(input.body)) return routeError(400, "invalid_body", "JSON body required");
|
|
9205
9242
|
const origin = normalizeCorsOrigin(input.origin);
|
|
9206
9243
|
if (!origin) return routeError(403, "forbidden", "Origin header is required and must be a valid exact origin");
|
|
9207
|
-
const
|
|
9208
|
-
if (!
|
|
9244
|
+
const registrationContext = input.services.registrationContext;
|
|
9245
|
+
if (!registrationContext) return routeError(500, "route_auth_not_configured", "Wallet registration context is not configured");
|
|
9246
|
+
const request = parseWalletRegistrationSetupRequest(input.body);
|
|
9247
|
+
if (!request.ok) return routeError(400, request.code, request.message);
|
|
9248
|
+
const context = await resolveWalletRegistrationContext({
|
|
9249
|
+
registration: request.value,
|
|
9250
|
+
environmentId: extractRouterApiEnvironmentId(input.headers) || void 0,
|
|
9251
|
+
headers: input.headers,
|
|
9252
|
+
missingEnvironmentMessage: "Environment header is required for wallet registration setup",
|
|
9253
|
+
missingOriginMessage: "Origin header is required and must be a valid exact origin",
|
|
9254
|
+
missingPublishableKeyMessage: "Missing publishable key",
|
|
9255
|
+
origin,
|
|
9256
|
+
registrationContext,
|
|
9257
|
+
route: input.route,
|
|
9258
|
+
routeAuthNotConfiguredMessage: "Wallet registration setup requires API credential auth policy"
|
|
9259
|
+
});
|
|
9260
|
+
if (!context.ok) {
|
|
9261
|
+
if (context.status === 401) return routeError(401, "unauthorized", `${context.code}: ${context.message}`);
|
|
9262
|
+
if (context.status === 403) return routeError(403, "forbidden", `${context.code}: ${context.message}`);
|
|
9263
|
+
return routeError(context.status, "internal", `${context.code}: ${context.message}`);
|
|
9264
|
+
}
|
|
9209
9265
|
const resolved = await enforceRoutePolicy({
|
|
9210
9266
|
headers: input.headers,
|
|
9211
9267
|
logger: input.logger,
|
|
@@ -9216,42 +9272,26 @@ async function handleRouterApiWalletRegistrationSetup(input) {
|
|
|
9216
9272
|
route: input.route,
|
|
9217
9273
|
services: walletRegistrationRoutePolicyServices(input),
|
|
9218
9274
|
sourceIp: input.sourceIp,
|
|
9219
|
-
resolvers: { apiCredentials:
|
|
9220
|
-
environmentId: extractRouterApiEnvironmentId(input.headers) || void 0,
|
|
9221
|
-
headers: input.headers,
|
|
9222
|
-
missingEnvironmentMessage: "Environment header is required for wallet registration setup",
|
|
9223
|
-
missingOriginMessage: "Origin header is required and must be a valid exact origin",
|
|
9224
|
-
missingPublishableKeyMessage: "Missing publishable key",
|
|
9225
|
-
origin,
|
|
9226
|
-
publishableKeyAuth,
|
|
9227
|
-
route: input.route,
|
|
9228
|
-
routeAuthNotConfiguredMessage: "Wallet registration setup requires API credential auth policy"
|
|
9229
|
-
}) }
|
|
9275
|
+
resolvers: { apiCredentials: publishableKeyRoutePrincipal.bind(void 0, context.principal) }
|
|
9230
9276
|
});
|
|
9231
9277
|
if (!resolved.ok) return routeJson(resolved.status, resolved.body);
|
|
9232
|
-
|
|
9233
|
-
const
|
|
9234
|
-
const runtimePolicyScope = await resolveActiveRuntimePolicyScopeForEnvironment({
|
|
9235
|
-
orgProjectEnv: input.services.orgProjectEnv || null,
|
|
9278
|
+
const principal = context.principal;
|
|
9279
|
+
const runtimePolicyScope = {
|
|
9236
9280
|
orgId: principal.orgId,
|
|
9237
|
-
|
|
9238
|
-
|
|
9239
|
-
|
|
9240
|
-
}
|
|
9281
|
+
projectId: context.environment.projectId,
|
|
9282
|
+
envId: context.environment.key,
|
|
9283
|
+
signingRootVersion: context.environment.signingRootVersion
|
|
9284
|
+
};
|
|
9241
9285
|
const session = input.services.session;
|
|
9242
9286
|
if (!session) return routeError(500, "internal", "wallet registration setup requires session signing");
|
|
9243
|
-
const request = parseWalletRegistrationSetupRequest(input.body);
|
|
9244
|
-
if (!request.ok) return routeError(400, request.code, request.message);
|
|
9245
9287
|
return input.services.walletRegistration.setupWalletRegistration({
|
|
9246
9288
|
request: request.value,
|
|
9247
9289
|
orgId: principal.orgId,
|
|
9248
9290
|
expectedOrigin: origin,
|
|
9249
9291
|
signer: session,
|
|
9250
|
-
|
|
9251
|
-
|
|
9252
|
-
|
|
9253
|
-
signingRootVersion: runtimePolicyScope.signingRootVersion
|
|
9254
|
-
} : {}
|
|
9292
|
+
runtimePolicyScope,
|
|
9293
|
+
signingRootId: `${runtimePolicyScope.projectId}:${runtimePolicyScope.envId}`,
|
|
9294
|
+
signingRootVersion: runtimePolicyScope.signingRootVersion
|
|
9255
9295
|
});
|
|
9256
9296
|
}
|
|
9257
9297
|
/**
|
|
@@ -9417,30 +9457,6 @@ function parseRegistrationRequestDigestB64u(raw) {
|
|
|
9417
9457
|
return null;
|
|
9418
9458
|
}
|
|
9419
9459
|
}
|
|
9420
|
-
async function projectActivatedWallet(input) {
|
|
9421
|
-
const walletProjection = input.services.walletProjection || null;
|
|
9422
|
-
if (!walletProjection) return null;
|
|
9423
|
-
const verifier = input.services.session;
|
|
9424
|
-
if (!verifier) return "wallet projection requires setup verification";
|
|
9425
|
-
const verified = await verifyWalletRegistrationSetupClaims(verifier, input.signedSetup, {
|
|
9426
|
-
registrationCeremonyId: input.registrationCeremonyId,
|
|
9427
|
-
nowMs: Date.now()
|
|
9428
|
-
});
|
|
9429
|
-
if (!verified.ok) return verified.message;
|
|
9430
|
-
if (verified.claims.policy.kind !== "runtime_policy_scope") return "wallet projection requires an exact runtime policy scope";
|
|
9431
|
-
if (verified.claims.policy.scope.orgId !== verified.claims.orgId) return "wallet projection scope does not match its organization";
|
|
9432
|
-
try {
|
|
9433
|
-
await walletProjection.recordCreatedWallet({
|
|
9434
|
-
orgId: verified.claims.orgId,
|
|
9435
|
-
runtimePolicyScope: verified.claims.policy.scope,
|
|
9436
|
-
walletId: verified.claims.walletId,
|
|
9437
|
-
occurredAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
9438
|
-
});
|
|
9439
|
-
return null;
|
|
9440
|
-
} catch (error) {
|
|
9441
|
-
return error instanceof Error ? error.message : String(error);
|
|
9442
|
-
}
|
|
9443
|
-
}
|
|
9444
9460
|
/**
|
|
9445
9461
|
* `POST /wallets/register/activate` — activation and finalization behind
|
|
9446
9462
|
* one Gateway operation row.
|
|
@@ -9459,9 +9475,7 @@ async function handleRouterApiWalletRegistrationActivate(input) {
|
|
|
9459
9475
|
const idempotencyKey = String(body.idempotencyKey || "").trim();
|
|
9460
9476
|
if (!idempotencyKey) return routeError(400, "invalid_body", "idempotencyKey is required");
|
|
9461
9477
|
const planKind = String(body.kind || "").trim();
|
|
9462
|
-
if (planKind !== "evm_family_ecdsa" && planKind !== "near_ed25519_and_evm_family_ecdsa"
|
|
9463
|
-
const ed25519Only = planKind === "near_ed25519";
|
|
9464
|
-
if (ed25519Only && body.ecdsa !== void 0) return routeError(400, "invalid_body", "an Ed25519-only activate carries no ECDSA activation");
|
|
9478
|
+
if (planKind !== "evm_family_ecdsa" && planKind !== "near_ed25519_and_evm_family_ecdsa") return routeError(400, "invalid_body", "activation requires an ECDSA signer plan");
|
|
9465
9479
|
const ecdsa = isPlainObject(body.ecdsa) ? body.ecdsa : null;
|
|
9466
9480
|
const unknownEcdsaField = ecdsa ? findUnknownField(ecdsa, [
|
|
9467
9481
|
"activationCorrelationId",
|
|
@@ -9469,9 +9483,9 @@ async function handleRouterApiWalletRegistrationActivate(input) {
|
|
|
9469
9483
|
"clientActivation"
|
|
9470
9484
|
]) : null;
|
|
9471
9485
|
if (unknownEcdsaField) return routeError(400, "invalid_body", `wallet registration ECDSA activation field ${unknownEcdsaField} is unsupported`);
|
|
9472
|
-
if (!
|
|
9486
|
+
if (!ecdsa || typeof ecdsa.activationCorrelationId !== "string" || typeof ecdsa.activationRequestDigestB64u !== "string" || !isPlainObject(ecdsa.clientActivation)) return routeError(400, "invalid_body", "browser-verified clientActivation is required");
|
|
9473
9487
|
let parsedActivation;
|
|
9474
|
-
|
|
9488
|
+
try {
|
|
9475
9489
|
const parsed = parseRouterAbEcdsaRegistrationActivationRequestV1({
|
|
9476
9490
|
registrationCeremonyId,
|
|
9477
9491
|
ecdsa: {
|
|
@@ -9494,25 +9508,17 @@ async function handleRouterApiWalletRegistrationActivate(input) {
|
|
|
9494
9508
|
signedSetup,
|
|
9495
9509
|
idempotencyKey,
|
|
9496
9510
|
planKind,
|
|
9497
|
-
|
|
9511
|
+
ecdsa: parsedActivation,
|
|
9498
9512
|
...body.emailOtpEnrollment ? { emailOtpEnrollment: body.emailOtpEnrollment } : {},
|
|
9499
9513
|
...body.walletCustodyCommit !== void 0 ? { walletCustodyCommit: body.walletCustodyCommit } : {},
|
|
9500
9514
|
verifier: session
|
|
9501
9515
|
}, traceContext.value ?? void 0, serverTiming);
|
|
9502
9516
|
if (!result.ok) return routeJson(400, result);
|
|
9503
9517
|
if (!isEmailOtpWalletRegistrationActivateSuccessV2(result) && !isPasskeyWalletRegistrationActivateSuccessV2(result)) return routeError(500, "internal", "Wallet registration activation returned an invalid authority");
|
|
9504
|
-
const projectionError = await projectActivatedWallet({
|
|
9505
|
-
registrationCeremonyId,
|
|
9506
|
-
services: input.services,
|
|
9507
|
-
signedSetup
|
|
9508
|
-
});
|
|
9509
|
-
if (projectionError) return routeError(500, "internal", `Wallet was created but its Console projection failed: ${projectionError}`);
|
|
9510
9518
|
return routeJson(200, result, { headers: ecdsaGatewayServerTimingHeaders(serverTiming) });
|
|
9511
9519
|
}
|
|
9512
9520
|
/**
|
|
9513
|
-
*
|
|
9514
|
-
* the client calls after activate, once its already-running Yao computation
|
|
9515
|
-
* produces an activation.
|
|
9521
|
+
* Commits a NEAR-only wallet or completes a mixed wallet's deferred signer.
|
|
9516
9522
|
*/
|
|
9517
9523
|
async function handleRouterApiWalletRegistrationNearProvisioning(input) {
|
|
9518
9524
|
if (!isPlainObject(input.body)) return routeError(400, "invalid_body", "JSON body required");
|
|
@@ -9525,7 +9531,7 @@ async function handleRouterApiWalletRegistrationNearProvisioning(input) {
|
|
|
9525
9531
|
if (!registrationCeremonyId || !signedSetup || !idempotencyKey) return routeError(400, "invalid_body", "registrationCeremonyId, signedSetup and idempotencyKey are required");
|
|
9526
9532
|
const ed25519 = parseWalletRegistrationEd25519Finalize(body.ed25519);
|
|
9527
9533
|
if (!ed25519.ok) return routeError(400, ed25519.code, ed25519.message);
|
|
9528
|
-
const sessionSeal = parseRegistrationPreparedSessionSeal(body.sessionSeal);
|
|
9534
|
+
const sessionSeal = parseRegistrationPreparedSessionSeal(body.sessionSeal, input.signingSessionSeal?.service ?? null);
|
|
9529
9535
|
if (!sessionSeal.ok) return routeError(400, sessionSeal.code, sessionSeal.message);
|
|
9530
9536
|
const serverTiming = [];
|
|
9531
9537
|
const result = await input.services.walletRegistration.completeWalletRegistrationNearProvisioning({
|
|
@@ -9536,17 +9542,14 @@ async function handleRouterApiWalletRegistrationNearProvisioning(input) {
|
|
|
9536
9542
|
ed25519: ed25519.value,
|
|
9537
9543
|
emailOtpEnrollment: body.emailOtpEnrollment,
|
|
9538
9544
|
...body.walletCustodyCommit !== void 0 ? { walletCustodyCommit: body.walletCustodyCommit } : {},
|
|
9539
|
-
verifier: session
|
|
9540
|
-
|
|
9545
|
+
verifier: session,
|
|
9546
|
+
onSessionCommitted: sessionSeal.value?.prepare.bind(sessionSeal.value)
|
|
9547
|
+
}, serverTiming, input.waitUntil);
|
|
9541
9548
|
if (!result.ok) return routeJson(400, result);
|
|
9542
9549
|
if (sessionSeal.value) {
|
|
9543
9550
|
if (!isPasskeyWalletRegistrationNearProvisioningSuccessV2(result)) return routeError(400, "invalid_body", "Registration session sealing requires a passkey authority");
|
|
9544
9551
|
const sealStartedAt = Date.now();
|
|
9545
|
-
const sealed = await
|
|
9546
|
-
options: input.signingSessionSeal,
|
|
9547
|
-
request: sessionSeal.value,
|
|
9548
|
-
response: result
|
|
9549
|
-
});
|
|
9552
|
+
const sealed = await sessionSeal.value.finish(result.registrationEstablishedSession.session);
|
|
9550
9553
|
serverTiming.push(["near_finalize_session_seal", Math.max(0, Date.now() - sealStartedAt)]);
|
|
9551
9554
|
if (!sealed.ok) return routeJson(503, {
|
|
9552
9555
|
ok: false,
|
|
@@ -9560,87 +9563,10 @@ async function handleRouterApiWalletRegistrationNearProvisioning(input) {
|
|
|
9560
9563
|
}
|
|
9561
9564
|
return routeJson(200, result, { headers: ecdsaGatewayServerTimingHeaders(serverTiming) });
|
|
9562
9565
|
}
|
|
9563
|
-
function
|
|
9564
|
-
if (
|
|
9565
|
-
|
|
9566
|
-
|
|
9567
|
-
};
|
|
9568
|
-
if (!isPlainObject(raw)) return {
|
|
9569
|
-
ok: false,
|
|
9570
|
-
code: "invalid_body",
|
|
9571
|
-
message: "sessionSeal must be an object"
|
|
9572
|
-
};
|
|
9573
|
-
if (Object.keys(raw).some((field) => ![
|
|
9574
|
-
"thresholdSessionId",
|
|
9575
|
-
"ciphertext",
|
|
9576
|
-
"keyVersion"
|
|
9577
|
-
].includes(field))) return {
|
|
9578
|
-
ok: false,
|
|
9579
|
-
code: "invalid_body",
|
|
9580
|
-
message: "sessionSeal has unknown fields"
|
|
9581
|
-
};
|
|
9582
|
-
const thresholdSessionId = String(raw.thresholdSessionId || "").trim();
|
|
9583
|
-
const ciphertext = String(raw.ciphertext || "").trim();
|
|
9584
|
-
const keyVersion = String(raw.keyVersion || "").trim();
|
|
9585
|
-
if (!thresholdSessionId || !ciphertext) return {
|
|
9586
|
-
ok: false,
|
|
9587
|
-
code: "invalid_body",
|
|
9588
|
-
message: "sessionSeal thresholdSessionId and ciphertext are required"
|
|
9589
|
-
};
|
|
9590
|
-
return {
|
|
9591
|
-
ok: true,
|
|
9592
|
-
value: {
|
|
9593
|
-
thresholdSessionId,
|
|
9594
|
-
ciphertext,
|
|
9595
|
-
...keyVersion ? { keyVersion } : {}
|
|
9596
|
-
}
|
|
9597
|
-
};
|
|
9598
|
-
}
|
|
9599
|
-
async function applyRegistrationPreparedSessionSeal(args) {
|
|
9600
|
-
if (!args.options) return {
|
|
9601
|
-
ok: false,
|
|
9602
|
-
code: "signing_session_seal_unavailable",
|
|
9603
|
-
message: "Signing-session sealing is unavailable"
|
|
9604
|
-
};
|
|
9605
|
-
const session = args.response.registrationEstablishedSession.session;
|
|
9606
|
-
const tokens = session.tokens;
|
|
9607
|
-
const ed25519 = tokens.kind === "near_ed25519" || tokens.kind === "near_ed25519_and_evm_family_ecdsa" ? tokens.ed25519 : null;
|
|
9608
|
-
if (!ed25519 || String(ed25519.thresholdSessionId) !== args.request.thresholdSessionId) return {
|
|
9609
|
-
ok: false,
|
|
9610
|
-
code: "invalid_session_seal",
|
|
9611
|
-
message: "Prepared seal does not match the established Ed25519 session"
|
|
9612
|
-
};
|
|
9613
|
-
const sealed = await args.options.service.applyServerSeal(args.request, {
|
|
9614
|
-
userId: String(session.walletId),
|
|
9615
|
-
session: {
|
|
9616
|
-
kind: "exact_wallet_session_operation_credential",
|
|
9617
|
-
curve: "ed25519",
|
|
9618
|
-
thresholdSessionId: args.request.thresholdSessionId,
|
|
9619
|
-
userId: String(session.walletId),
|
|
9620
|
-
expiresAtMs: session.expiresAtMs
|
|
9621
|
-
}
|
|
9622
|
-
});
|
|
9623
|
-
if (!sealed.ok) return sealed;
|
|
9624
|
-
const keyVersion = String(sealed.keyVersion || "").trim();
|
|
9625
|
-
if (!keyVersion) return {
|
|
9626
|
-
ok: false,
|
|
9627
|
-
code: "invalid_session_seal",
|
|
9628
|
-
message: "Signing-session seal response is missing its key version"
|
|
9629
|
-
};
|
|
9630
|
-
return {
|
|
9631
|
-
ok: true,
|
|
9632
|
-
value: {
|
|
9633
|
-
ciphertext: sealed.ciphertext,
|
|
9634
|
-
keyVersion,
|
|
9635
|
-
expiresAtMs: Math.min(sealed.expiresAtMs ?? session.expiresAtMs, session.expiresAtMs),
|
|
9636
|
-
remainingUses: session.remainingUses
|
|
9637
|
-
}
|
|
9638
|
-
};
|
|
9639
|
-
}
|
|
9640
|
-
function ecdsaGatewayServerTimingHeaders(serverTiming) {
|
|
9641
|
-
if (serverTiming.length === 0) return void 0;
|
|
9642
|
-
const header = serverTiming.map(([name, durationMs]) => `${name};dur=${Math.max(0, durationMs).toFixed(1)}`).join(", ");
|
|
9643
|
-
return { "Server-Timing": header };
|
|
9566
|
+
function ecdsaGatewayServerTimingHeaders(serverTiming) {
|
|
9567
|
+
if (serverTiming.length === 0) return void 0;
|
|
9568
|
+
const header = serverTiming.map(([name, durationMs]) => `${name};dur=${Math.max(0, durationMs).toFixed(1)}`).join(", ");
|
|
9569
|
+
return { "Server-Timing": header };
|
|
9644
9570
|
}
|
|
9645
9571
|
async function handleRouterApiWalletAddSignerStart(input) {
|
|
9646
9572
|
if (!isPlainObject(input.body)) return routeError(400, "invalid_body", "JSON body required");
|
|
@@ -10699,7 +10625,7 @@ function resolveWalletRegistrationRoute(ctx) {
|
|
|
10699
10625
|
async function handleWalletRegistration(ctx) {
|
|
10700
10626
|
const route = resolveWalletRegistrationRoute(ctx);
|
|
10701
10627
|
if (!route) return null;
|
|
10702
|
-
if (ctx.request.headers.get("X-Seams-Wallet-Protocol") !== "
|
|
10628
|
+
if (ctx.request.headers.get("X-Seams-Wallet-Protocol") !== "3") 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.");
|
|
10703
10629
|
const common = {
|
|
10704
10630
|
body: await readJson(ctx.request),
|
|
10705
10631
|
headers: Object.fromEntries(ctx.request.headers.entries()),
|
|
@@ -10719,10 +10645,11 @@ async function handleWalletRegistration(ctx) {
|
|
|
10719
10645
|
routerAbPublicKeyset: ctx.opts.routerAbPublicKeyset,
|
|
10720
10646
|
session: ctx.opts.session,
|
|
10721
10647
|
publishableKeyAuth: ctx.opts.publishableKeyAuth,
|
|
10722
|
-
|
|
10648
|
+
registrationContext: ctx.opts.registrationContext
|
|
10723
10649
|
},
|
|
10724
10650
|
sourceIp: resolveSourceIpFromFetchHeaders(ctx.request.headers) || void 0,
|
|
10725
|
-
signingSessionSeal: ctx.opts.signingSessionSeal
|
|
10651
|
+
signingSessionSeal: ctx.opts.signingSessionSeal,
|
|
10652
|
+
waitUntil: ctx.runtime.kind === "background" ? ctx.runtime.waitUntil : void 0
|
|
10726
10653
|
};
|
|
10727
10654
|
let response;
|
|
10728
10655
|
switch (route.id) {
|
|
@@ -13605,41 +13532,47 @@ function walletUnlockIssuanceRejectionStatus(rejection) {
|
|
|
13605
13532
|
}
|
|
13606
13533
|
}
|
|
13607
13534
|
//#endregion
|
|
13608
|
-
//#region
|
|
13609
|
-
|
|
13610
|
-
|
|
13611
|
-
|
|
13612
|
-
|
|
13613
|
-
|
|
13614
|
-
|
|
13615
|
-
|
|
13616
|
-
|
|
13617
|
-
|
|
13618
|
-
|
|
13619
|
-
|
|
13620
|
-
|
|
13621
|
-
|
|
13622
|
-
|
|
13623
|
-
|
|
13624
|
-
|
|
13625
|
-
|
|
13626
|
-
|
|
13627
|
-
|
|
13628
|
-
|
|
13629
|
-
|
|
13630
|
-
|
|
13631
|
-
|
|
13632
|
-
for (const parameter of parameters) {
|
|
13633
|
-
const [key, rawValue] = parameter.trim().split("=");
|
|
13634
|
-
if (key !== "dur" || !rawValue?.trim()) continue;
|
|
13635
|
-
const duration = Number(rawValue);
|
|
13636
|
-
if (Number.isFinite(duration) && duration >= 0) durations.set(name, duration);
|
|
13637
|
-
break;
|
|
13535
|
+
//#region src/router/domains/signingOperations/signingPrepareSession.ts
|
|
13536
|
+
/** The session snapshot validated for this admission, before its quota claim. */
|
|
13537
|
+
function signingPrepareSessionResponse(signing, authorization) {
|
|
13538
|
+
switch (authorization.kind) {
|
|
13539
|
+
case "operation_step_up": return {
|
|
13540
|
+
kind: "operation_step_up",
|
|
13541
|
+
signing
|
|
13542
|
+
};
|
|
13543
|
+
case "wallet_session_operation_credential_v1": {
|
|
13544
|
+
const { session, quota } = authorization.validated.admission.context.authorization;
|
|
13545
|
+
return {
|
|
13546
|
+
kind: "reusable_wallet_session",
|
|
13547
|
+
signing,
|
|
13548
|
+
session_status: {
|
|
13549
|
+
ok: true,
|
|
13550
|
+
status: "active",
|
|
13551
|
+
walletSessionId: session.walletSessionId,
|
|
13552
|
+
quotaId: session.quotaId,
|
|
13553
|
+
remainingUses: quota.remainingUses,
|
|
13554
|
+
expiresAtMs: quota.expiresAtMs,
|
|
13555
|
+
quotaLifecycle: "active",
|
|
13556
|
+
authorization: projectExactWalletSessionAuthorizationV1(session)
|
|
13557
|
+
}
|
|
13558
|
+
};
|
|
13638
13559
|
}
|
|
13560
|
+
case "wallet_session_operation_credential_exhausted_candidate_v1": throw new Error("An exhausted Wallet Session cannot publish a fresh prepare response");
|
|
13639
13561
|
}
|
|
13640
|
-
return durations;
|
|
13641
13562
|
}
|
|
13642
13563
|
//#endregion
|
|
13564
|
+
//#region ../shared-ts/src/utils/walletSessionFailure.ts
|
|
13565
|
+
const WALLET_SESSION_FAILURE_CODES = {
|
|
13566
|
+
missing: "wallet_session_missing",
|
|
13567
|
+
signatureInvalid: "wallet_session_signature_invalid",
|
|
13568
|
+
claimsInvalid: "wallet_session_claims_invalid",
|
|
13569
|
+
invalid: "wallet_session_invalid",
|
|
13570
|
+
expired: "wallet_session_expired",
|
|
13571
|
+
scopeMismatch: "wallet_session_scope_mismatch",
|
|
13572
|
+
unavailable: "wallet_session_unavailable",
|
|
13573
|
+
budgetExhausted: "wallet_budget_exhausted"
|
|
13574
|
+
};
|
|
13575
|
+
//#endregion
|
|
13643
13576
|
//#region src/router/domains/signingOperations/routerAbNormalSigningAdmission.ts
|
|
13644
13577
|
function routerAbOwnerOperationStepUpDecision(input) {
|
|
13645
13578
|
const reason = (() => {
|
|
@@ -13686,6 +13619,7 @@ async function evaluateRouterAbNormalSigningAdmission(input) {
|
|
|
13686
13619
|
};
|
|
13687
13620
|
if (input.curve === "ed25519") return await input.adapter.evaluatePolicy({
|
|
13688
13621
|
curve: "ed25519",
|
|
13622
|
+
policyReadSource: input.policyReadSource,
|
|
13689
13623
|
authorityKind: "wallet_authority_v1",
|
|
13690
13624
|
authorityId: input.authorityId,
|
|
13691
13625
|
phase: input.phase,
|
|
@@ -14053,18 +13987,6 @@ function routerAbOperationStepUpClaimFailure(result) {
|
|
|
14053
13987
|
}
|
|
14054
13988
|
}
|
|
14055
13989
|
//#endregion
|
|
14056
|
-
//#region ../shared-ts/src/utils/walletSessionFailure.ts
|
|
14057
|
-
const WALLET_SESSION_FAILURE_CODES = {
|
|
14058
|
-
missing: "wallet_session_missing",
|
|
14059
|
-
signatureInvalid: "wallet_session_signature_invalid",
|
|
14060
|
-
claimsInvalid: "wallet_session_claims_invalid",
|
|
14061
|
-
invalid: "wallet_session_invalid",
|
|
14062
|
-
expired: "wallet_session_expired",
|
|
14063
|
-
scopeMismatch: "wallet_session_scope_mismatch",
|
|
14064
|
-
unavailable: "wallet_session_unavailable",
|
|
14065
|
-
budgetExhausted: "wallet_budget_exhausted"
|
|
14066
|
-
};
|
|
14067
|
-
//#endregion
|
|
14068
13990
|
//#region src/core/ThresholdService/routerAb/internalServiceHttp.ts
|
|
14069
13991
|
const ROUTER_AB_INTERNAL_SERVICE_AUTH_HEADER_V1 = "x-router-ab-internal-service-auth";
|
|
14070
13992
|
function normalizeRouterAbInternalServiceAuthSecret(input) {
|
|
@@ -15195,6 +15117,143 @@ async function authorizeRouterAbEcdsaDerivationNormalSigningRoute(input) {
|
|
|
15195
15117
|
};
|
|
15196
15118
|
}
|
|
15197
15119
|
//#endregion
|
|
15120
|
+
//#region src/router/domains/signingOperations/ecdsaSigningResponse.ts
|
|
15121
|
+
async function finishRouterAbEcdsaSigningResponse(input) {
|
|
15122
|
+
const upstream = input.upstream;
|
|
15123
|
+
const upstreamBodyText = await upstream.clone().text().catch(() => "");
|
|
15124
|
+
input.timing.proxy = performance.now() - input.proxyStartedAt;
|
|
15125
|
+
if (isRouterAbEcdsaOperationInProgressResponse({
|
|
15126
|
+
status: upstream.status,
|
|
15127
|
+
bodyText: upstreamBodyText
|
|
15128
|
+
})) return upstream;
|
|
15129
|
+
const completionStartedAt = performance.now();
|
|
15130
|
+
await completeRouterAbEcdsaOperation({
|
|
15131
|
+
authorizedOperations: input.authorizedOperations,
|
|
15132
|
+
operation: input.operation,
|
|
15133
|
+
result: upstream.ok ? "succeeded" : upstream.status < 500 ? "failed_before_side_effect" : "failed_after_side_effect",
|
|
15134
|
+
response: {
|
|
15135
|
+
status: upstream.status,
|
|
15136
|
+
contentType: upstream.headers.get("content-type") || "application/json",
|
|
15137
|
+
bodyText: upstreamBodyText
|
|
15138
|
+
}
|
|
15139
|
+
});
|
|
15140
|
+
input.timing.complete = performance.now() - completionStartedAt;
|
|
15141
|
+
return upstream;
|
|
15142
|
+
}
|
|
15143
|
+
function isRouterAbEcdsaOperationInProgressResponse(input) {
|
|
15144
|
+
return input.status === 409 && input.bodyText.includes("ReplayedLocalRequest:") && input.bodyText.includes("SigningWorker ECDSA effect is already in progress");
|
|
15145
|
+
}
|
|
15146
|
+
//#endregion
|
|
15147
|
+
//#region src/router/domains/signingOperations/authorizedOperationWire.ts
|
|
15148
|
+
function buildAuthorizedOperationWire(input, commonAuthorizedOperation) {
|
|
15149
|
+
const operation = input.operation;
|
|
15150
|
+
switch (input.binding.kind) {
|
|
15151
|
+
case "reusable_wallet_session":
|
|
15152
|
+
if (operation.authorization.kind !== "authorization_grant" || operation.quota.kind !== "consume_reusable_wallet_session") throw new Error("Reusable Wallet Session authorized operation is invalid");
|
|
15153
|
+
return {
|
|
15154
|
+
binding: {
|
|
15155
|
+
kind: "reusable_wallet_session",
|
|
15156
|
+
authorization_id: operation.authorization.authorizationGrantRef.authorizationId,
|
|
15157
|
+
wallet_session_id: input.binding.walletSessionId,
|
|
15158
|
+
quota_id: input.binding.quotaId
|
|
15159
|
+
},
|
|
15160
|
+
authorized_operation: {
|
|
15161
|
+
kind: "reusable_wallet_session_authorized_operation_v1",
|
|
15162
|
+
...commonAuthorizedOperation
|
|
15163
|
+
}
|
|
15164
|
+
};
|
|
15165
|
+
case "gateway_owner_wallet_session":
|
|
15166
|
+
if (operation.authorization.kind !== "authorization_grant" || operation.quota.kind !== "consume_reusable_wallet_session") throw new Error("Gateway owner Wallet Session authorized operation is invalid");
|
|
15167
|
+
return {
|
|
15168
|
+
binding: {
|
|
15169
|
+
kind: "gateway_owner_wallet_session",
|
|
15170
|
+
ownership_generation: input.binding.ownershipGeneration,
|
|
15171
|
+
subject_id: input.binding.subjectId,
|
|
15172
|
+
account_id: input.binding.accountId,
|
|
15173
|
+
authorization_id: input.binding.authorizationId,
|
|
15174
|
+
wallet_session_id: input.binding.walletSessionId,
|
|
15175
|
+
quota_id: input.binding.quotaId,
|
|
15176
|
+
threshold_session_id: input.binding.thresholdSessionId,
|
|
15177
|
+
org_id: input.binding.orgId,
|
|
15178
|
+
project_id: input.binding.projectId,
|
|
15179
|
+
environment: input.binding.environment,
|
|
15180
|
+
project_environment_id: input.binding.projectEnvironmentId,
|
|
15181
|
+
signing_worker_id: input.binding.signingWorkerId,
|
|
15182
|
+
expires_at_ms: input.binding.expiresAtMs
|
|
15183
|
+
},
|
|
15184
|
+
authorized_operation: {
|
|
15185
|
+
kind: "reusable_wallet_session_authorized_operation_v1",
|
|
15186
|
+
...commonAuthorizedOperation
|
|
15187
|
+
}
|
|
15188
|
+
};
|
|
15189
|
+
case "operation_step_up":
|
|
15190
|
+
if (operation.authorization.kind !== "verified_step_up" || operation.quota.kind !== "quota_neutral") throw new Error("Verified step-up authorized operation is invalid");
|
|
15191
|
+
return {
|
|
15192
|
+
binding: {
|
|
15193
|
+
kind: "operation_step_up",
|
|
15194
|
+
ownership_generation: input.binding.ownershipGeneration,
|
|
15195
|
+
authorization_session_id: input.binding.authorizationSessionId,
|
|
15196
|
+
org_id: input.binding.orgId,
|
|
15197
|
+
project_id: input.binding.projectId,
|
|
15198
|
+
environment: input.binding.environment,
|
|
15199
|
+
project_environment_id: input.binding.projectEnvironmentId,
|
|
15200
|
+
subject_id: input.binding.subjectId,
|
|
15201
|
+
account_id: input.binding.accountId
|
|
15202
|
+
},
|
|
15203
|
+
authorized_operation: {
|
|
15204
|
+
kind: "verified_step_up_authorized_operation_v1",
|
|
15205
|
+
authorization_session_id: input.binding.authorizationSessionId,
|
|
15206
|
+
evidence_set_digest: operation.authorization.evidenceSetDigest,
|
|
15207
|
+
...commonAuthorizedOperation
|
|
15208
|
+
}
|
|
15209
|
+
};
|
|
15210
|
+
default: return assertNeverOperationBinding(input.binding);
|
|
15211
|
+
}
|
|
15212
|
+
}
|
|
15213
|
+
function assertNeverOperationBinding(_binding) {
|
|
15214
|
+
throw new Error("Unsupported authorized-operation binding");
|
|
15215
|
+
}
|
|
15216
|
+
//#endregion
|
|
15217
|
+
//#region ../shared-ts/src/utils/ecdsaServerTiming.ts
|
|
15218
|
+
const ECDSA_TIMING_METRICS = new Set([
|
|
15219
|
+
"wallet_gateway_binding",
|
|
15220
|
+
"wallet_gateway_total",
|
|
15221
|
+
"wallet_console_binding_d1",
|
|
15222
|
+
"wallet_console_binding_sql",
|
|
15223
|
+
"ecdsa_sign_authorize",
|
|
15224
|
+
"ecdsa_sign_admit",
|
|
15225
|
+
"ecdsa_sign_proxy",
|
|
15226
|
+
"ecdsa_sign_complete",
|
|
15227
|
+
"ecdsa_sign_total",
|
|
15228
|
+
"ecdsa_presign_authenticate",
|
|
15229
|
+
"ecdsa_presign_material",
|
|
15230
|
+
"ecdsa_presign_admit",
|
|
15231
|
+
"ecdsa_presign_proxy",
|
|
15232
|
+
"ecdsa_presign_total",
|
|
15233
|
+
"ecdsa_presign_sw_material",
|
|
15234
|
+
"ecdsa_presign_sw_session",
|
|
15235
|
+
"ecdsa_presign_sw_do_response_headers",
|
|
15236
|
+
"ecdsa_presign_sw_do_response_body",
|
|
15237
|
+
"ecdsa_presign_sw_admit",
|
|
15238
|
+
"ecdsa_presign_sw_total"
|
|
15239
|
+
]);
|
|
15240
|
+
function parseEcdsaServerTiming(header) {
|
|
15241
|
+
const durations = /* @__PURE__ */ new Map();
|
|
15242
|
+
if (!header) return durations;
|
|
15243
|
+
for (const metric of header.split(",")) {
|
|
15244
|
+
const [name, ...parameters] = metric.trim().split(";");
|
|
15245
|
+
if (!ECDSA_TIMING_METRICS.has(name) || durations.has(name)) continue;
|
|
15246
|
+
for (const parameter of parameters) {
|
|
15247
|
+
const [key, rawValue] = parameter.trim().split("=");
|
|
15248
|
+
if (key !== "dur" || !rawValue?.trim()) continue;
|
|
15249
|
+
const duration = Number(rawValue);
|
|
15250
|
+
if (Number.isFinite(duration) && duration >= 0) durations.set(name, duration);
|
|
15251
|
+
break;
|
|
15252
|
+
}
|
|
15253
|
+
}
|
|
15254
|
+
return durations;
|
|
15255
|
+
}
|
|
15256
|
+
//#endregion
|
|
15198
15257
|
//#region src/router/domains/ecdsa/thresholdEcdsaRequestValidation.ts
|
|
15199
15258
|
const POOL_FILL_INIT_KEYS = [
|
|
15200
15259
|
"presignSessionId",
|
|
@@ -15595,6 +15654,27 @@ function walletAuthorityForAuthMethod(authMethod, authSource) {
|
|
|
15595
15654
|
};
|
|
15596
15655
|
}
|
|
15597
15656
|
//#endregion
|
|
15657
|
+
//#region src/router/cloudflare/runtime/walletObjectAddresses.ts
|
|
15658
|
+
const WALLET_OBJECT_IDENTITY_HEADER = "x-seams-wallet-object-identity";
|
|
15659
|
+
function walletObjectIdentity(wallet, generation, tenant) {
|
|
15660
|
+
const parsed = parseWalletId(wallet);
|
|
15661
|
+
if (!parsed.ok || typeof generation !== "number" || !Number.isSafeInteger(generation) || generation < 1) throw new Error("Wallet object identity requires a wallet and ownership generation");
|
|
15662
|
+
return {
|
|
15663
|
+
walletId: parsed.value,
|
|
15664
|
+
ownershipGeneration: generation,
|
|
15665
|
+
orgId: tenantPart(tenant.orgId),
|
|
15666
|
+
projectId: tenantPart(tenant.projectId),
|
|
15667
|
+
envId: tenantPart(tenant.envId)
|
|
15668
|
+
};
|
|
15669
|
+
}
|
|
15670
|
+
function walletObjectIdentityHeaders(identity) {
|
|
15671
|
+
return { [WALLET_OBJECT_IDENTITY_HEADER]: JSON.stringify(identity) };
|
|
15672
|
+
}
|
|
15673
|
+
function tenantPart(value) {
|
|
15674
|
+
if (typeof value !== "string" || !value || value.trim() !== value) throw new Error("Wallet object tenant is invalid");
|
|
15675
|
+
return value;
|
|
15676
|
+
}
|
|
15677
|
+
//#endregion
|
|
15598
15678
|
//#region src/router/transport/fetch/routes/normalSigningRouterProxy.ts
|
|
15599
15679
|
async function proxyNormalSigningRequestToMpcRouter(input) {
|
|
15600
15680
|
const proxy = input.proxy;
|
|
@@ -15605,6 +15685,14 @@ async function proxyNormalSigningRequestToMpcRouter(input) {
|
|
|
15605
15685
|
}, { status: 501 });
|
|
15606
15686
|
try {
|
|
15607
15687
|
const headers = new Headers(input.request.headers);
|
|
15688
|
+
const envelope = input.body?.authorized_operation;
|
|
15689
|
+
if (!isPlainObject(envelope) || !isPlainObject(envelope.binding)) throw new Error("Signing requires an admitted wallet binding");
|
|
15690
|
+
const identity = walletObjectIdentity(envelope.binding.account_id, envelope.binding.ownership_generation, {
|
|
15691
|
+
orgId: envelope.binding.org_id,
|
|
15692
|
+
projectId: envelope.binding.project_id,
|
|
15693
|
+
envId: envelope.binding.project_environment_id
|
|
15694
|
+
});
|
|
15695
|
+
for (const [name, value] of Object.entries(walletObjectIdentityHeaders(identity))) headers.set(name, value);
|
|
15608
15696
|
if (input.body && parseNormalSigningSessionAdmission(input.body)) headers.delete("authorization");
|
|
15609
15697
|
headers.set(ROUTER_AB_INTERNAL_SERVICE_AUTH_HEADER_V1, normalizeRouterAbInternalServiceAuthSecret(proxy.internalServiceAuthSecret));
|
|
15610
15698
|
const request = input.targetPath ? new Request(new URL(input.targetPath, input.request.url), input.request) : input.request;
|
|
@@ -15646,7 +15734,7 @@ function isNormalSigningReusableBindingRecord(value) {
|
|
|
15646
15734
|
}
|
|
15647
15735
|
function isNormalSigningGatewayOwnerBindingRecord(value) {
|
|
15648
15736
|
if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
|
|
15649
|
-
return Object.keys(value).sort().join("|") === "account_id|authorization_id|environment|expires_at_ms|kind|org_id|project_environment_id|project_id|quota_id|signing_worker_id|subject_id|threshold_session_id|wallet_session_id";
|
|
15737
|
+
return Object.keys(value).sort().join("|") === "account_id|authorization_id|environment|expires_at_ms|kind|org_id|ownership_generation|project_environment_id|project_id|quota_id|signing_worker_id|subject_id|threshold_session_id|wallet_session_id";
|
|
15650
15738
|
}
|
|
15651
15739
|
function isNormalSigningReusableReceiptRecord(value) {
|
|
15652
15740
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
@@ -15655,7 +15743,7 @@ function isNormalSigningReusableBindingValues(record) {
|
|
|
15655
15743
|
return typeof record.authorization_id === "string" && record.authorization_id.trim().length > 0 && typeof record.wallet_session_id === "string" && record.wallet_session_id.trim().length > 0 && typeof record.quota_id === "string" && record.quota_id.trim().length > 0;
|
|
15656
15744
|
}
|
|
15657
15745
|
function isNormalSigningGatewayOwnerBindingValues(record) {
|
|
15658
|
-
return typeof record.subject_id === "string" && record.subject_id.trim().length > 0 && typeof record.account_id === "string" && record.account_id.trim().length > 0 && typeof record.authorization_id === "string" && record.authorization_id.trim().length > 0 && typeof record.wallet_session_id === "string" && record.wallet_session_id.trim().length > 0 && typeof record.quota_id === "string" && record.quota_id.trim().length > 0 && typeof record.threshold_session_id === "string" && record.threshold_session_id.trim().length > 0 && typeof record.org_id === "string" && record.org_id.trim().length > 0 && typeof record.project_id === "string" && record.project_id.trim().length > 0 && typeof record.environment === "string" && record.environment.trim().length > 0 && typeof record.project_environment_id === "string" && record.project_environment_id.trim().length > 0 && typeof record.signing_worker_id === "string" && record.signing_worker_id.trim().length > 0 && typeof record.expires_at_ms === "number" && Number.isSafeInteger(record.expires_at_ms) && record.expires_at_ms > 0;
|
|
15746
|
+
return record.kind === "gateway_owner_wallet_session" && typeof record.ownership_generation === "number" && Number.isSafeInteger(record.ownership_generation) && record.ownership_generation > 0 && typeof record.subject_id === "string" && record.subject_id.trim().length > 0 && typeof record.account_id === "string" && record.account_id.trim().length > 0 && typeof record.authorization_id === "string" && record.authorization_id.trim().length > 0 && typeof record.wallet_session_id === "string" && record.wallet_session_id.trim().length > 0 && typeof record.quota_id === "string" && record.quota_id.trim().length > 0 && typeof record.threshold_session_id === "string" && record.threshold_session_id.trim().length > 0 && typeof record.org_id === "string" && record.org_id.trim().length > 0 && typeof record.project_id === "string" && record.project_id.trim().length > 0 && typeof record.environment === "string" && record.environment.trim().length > 0 && typeof record.project_environment_id === "string" && record.project_environment_id.trim().length > 0 && typeof record.signing_worker_id === "string" && record.signing_worker_id.trim().length > 0 && typeof record.expires_at_ms === "number" && Number.isSafeInteger(record.expires_at_ms) && record.expires_at_ms > 0;
|
|
15659
15747
|
}
|
|
15660
15748
|
async function proxyOwnerLaneAdmittedNormalSigningRequest(input) {
|
|
15661
15749
|
const expectedMaterialActivation = routerAbMpcMaterialActivationRefFromWire(input.expectedMaterialActivation);
|
|
@@ -15720,6 +15808,7 @@ async function ecdsaOperationStepUpBinding(ctx, session, operation) {
|
|
|
15720
15808
|
const pinned = await readPinnedEcdsaStepUpWalletScope(ctx, session, operation);
|
|
15721
15809
|
return {
|
|
15722
15810
|
kind: "operation_step_up",
|
|
15811
|
+
ownershipGeneration: pinned.ownershipGeneration,
|
|
15723
15812
|
authorizationSessionId: session.sessionId,
|
|
15724
15813
|
orgId: scope.orgId,
|
|
15725
15814
|
projectId: scope.projectId,
|
|
@@ -15739,7 +15828,10 @@ async function readPinnedEcdsaStepUpWalletScope(ctx, session, operation) {
|
|
|
15739
15828
|
const scope = session.runtimePolicyScope;
|
|
15740
15829
|
if (pinned.orgId !== scope.orgId || pinned.projectId !== scope.projectId) throw new Error("Step-up wallet scope differs from the Wallet Session scope");
|
|
15741
15830
|
return {
|
|
15742
|
-
|
|
15831
|
+
orgId: pinned.orgId,
|
|
15832
|
+
projectId: pinned.projectId,
|
|
15833
|
+
projectEnvironmentId: pinned.projectEnvironmentId,
|
|
15834
|
+
ownershipGeneration: pinned.ownershipGeneration,
|
|
15743
15835
|
walletId: session.walletId
|
|
15744
15836
|
};
|
|
15745
15837
|
}
|
|
@@ -15747,7 +15839,7 @@ function buildRouterAbEcdsaAuthorizedOperationWire(input) {
|
|
|
15747
15839
|
const operation = input.operation;
|
|
15748
15840
|
const operationRef = operation.operation.operation;
|
|
15749
15841
|
if (operationRef.capabilityKind !== "evm_ecdsa_mpc_signing" || operationRef.operationKind !== "evm.sign_transaction") throw new Error("ECDSA authorized operation capability or operation kind is invalid");
|
|
15750
|
-
|
|
15842
|
+
return buildAuthorizedOperationWire(input, {
|
|
15751
15843
|
authorized_operation_id: operation.authorizedOperationId,
|
|
15752
15844
|
operation_id: operation.operation.operationId,
|
|
15753
15845
|
capability_kind: "evm_ecdsa_mpc_signing",
|
|
@@ -15756,66 +15848,7 @@ function buildRouterAbEcdsaAuthorizedOperationWire(input) {
|
|
|
15756
15848
|
intent_digest_b64u: operation.operation.digests.intentDigest,
|
|
15757
15849
|
display_digest_b64u: operation.operation.digests.displayDigest,
|
|
15758
15850
|
operation_fingerprint_digest: operation.operationFingerprintDigest
|
|
15759
|
-
};
|
|
15760
|
-
switch (input.binding.kind) {
|
|
15761
|
-
case "reusable_wallet_session":
|
|
15762
|
-
if (operation.authorization.kind !== "authorization_grant" || operation.quota.kind !== "consume_reusable_wallet_session") throw new Error("Reusable Wallet Session authorized operation is invalid");
|
|
15763
|
-
return {
|
|
15764
|
-
binding: {
|
|
15765
|
-
kind: "reusable_wallet_session",
|
|
15766
|
-
authorization_id: operation.authorization.authorizationGrantRef.authorizationId,
|
|
15767
|
-
wallet_session_id: input.binding.walletSessionId,
|
|
15768
|
-
quota_id: input.binding.quotaId
|
|
15769
|
-
},
|
|
15770
|
-
authorized_operation: {
|
|
15771
|
-
kind: "reusable_wallet_session_authorized_operation_v1",
|
|
15772
|
-
...commonAuthorizedOperation
|
|
15773
|
-
}
|
|
15774
|
-
};
|
|
15775
|
-
case "gateway_owner_wallet_session":
|
|
15776
|
-
if (operation.authorization.kind !== "authorization_grant" || operation.quota.kind !== "consume_reusable_wallet_session") throw new Error("Gateway owner Wallet Session authorized operation is invalid");
|
|
15777
|
-
return {
|
|
15778
|
-
binding: {
|
|
15779
|
-
kind: "gateway_owner_wallet_session",
|
|
15780
|
-
subject_id: input.binding.subjectId,
|
|
15781
|
-
account_id: input.binding.accountId,
|
|
15782
|
-
authorization_id: input.binding.authorizationId,
|
|
15783
|
-
wallet_session_id: input.binding.walletSessionId,
|
|
15784
|
-
quota_id: input.binding.quotaId,
|
|
15785
|
-
threshold_session_id: input.binding.thresholdSessionId,
|
|
15786
|
-
org_id: input.binding.orgId,
|
|
15787
|
-
project_id: input.binding.projectId,
|
|
15788
|
-
environment: input.binding.environment,
|
|
15789
|
-
project_environment_id: input.binding.projectEnvironmentId,
|
|
15790
|
-
signing_worker_id: input.binding.signingWorkerId,
|
|
15791
|
-
expires_at_ms: input.binding.expiresAtMs
|
|
15792
|
-
},
|
|
15793
|
-
authorized_operation: {
|
|
15794
|
-
kind: "reusable_wallet_session_authorized_operation_v1",
|
|
15795
|
-
...commonAuthorizedOperation
|
|
15796
|
-
}
|
|
15797
|
-
};
|
|
15798
|
-
case "operation_step_up":
|
|
15799
|
-
if (operation.authorization.kind !== "verified_step_up" || operation.quota.kind !== "quota_neutral") throw new Error("Verified step-up authorized operation is invalid");
|
|
15800
|
-
return {
|
|
15801
|
-
binding: {
|
|
15802
|
-
kind: "operation_step_up",
|
|
15803
|
-
authorization_session_id: input.binding.authorizationSessionId,
|
|
15804
|
-
org_id: input.binding.orgId,
|
|
15805
|
-
project_id: input.binding.projectId,
|
|
15806
|
-
environment: input.binding.environment,
|
|
15807
|
-
project_environment_id: input.binding.projectEnvironmentId,
|
|
15808
|
-
subject_id: input.binding.subjectId,
|
|
15809
|
-
account_id: input.binding.accountId
|
|
15810
|
-
},
|
|
15811
|
-
authorized_operation: {
|
|
15812
|
-
kind: "verified_step_up_authorized_operation_v1",
|
|
15813
|
-
authorization_session_id: input.binding.authorizationSessionId,
|
|
15814
|
-
evidence_set_digest: operation.authorization.evidenceSetDigest,
|
|
15815
|
-
...commonAuthorizedOperation
|
|
15816
|
-
}
|
|
15817
|
-
};
|
|
15818
|
-
}
|
|
15851
|
+
});
|
|
15819
15852
|
}
|
|
15820
15853
|
function decideRouterAbEcdsaOperationStepUpExecution(input) {
|
|
15821
15854
|
if (input.admissionKind === "replayed") return {
|
|
@@ -15970,6 +16003,7 @@ async function executeRouterAbEcdsaDerivationNormalSigningRoute(input, timing) {
|
|
|
15970
16003
|
operation: authorizedOperation,
|
|
15971
16004
|
binding: {
|
|
15972
16005
|
kind: "gateway_owner_wallet_session",
|
|
16006
|
+
ownershipGeneration: pinnedOwnerScope.ownershipGeneration,
|
|
15973
16007
|
subjectId: String(session.principalId),
|
|
15974
16008
|
accountId: String(session.walletId),
|
|
15975
16009
|
authorizationId: String(session.authorizationId),
|
|
@@ -16016,8 +16050,18 @@ async function executeRouterAbEcdsaDerivationNormalSigningRoute(input, timing) {
|
|
|
16016
16050
|
walletRegistration: input.ctx.service.walletRegistration,
|
|
16017
16051
|
body: admittedBody
|
|
16018
16052
|
});
|
|
16053
|
+
if (input.phase === "prepare" && upstream.ok) {
|
|
16054
|
+
const body = signingPrepareSessionResponse(await upstream.json(), authorization);
|
|
16055
|
+
timing.proxy = performance.now() - proxyStartedAt;
|
|
16056
|
+
const headers = new Headers(upstream.headers);
|
|
16057
|
+
headers.delete("content-length");
|
|
16058
|
+
headers.delete("content-encoding");
|
|
16059
|
+
return new Response(JSON.stringify(body), {
|
|
16060
|
+
status: upstream.status,
|
|
16061
|
+
headers
|
|
16062
|
+
});
|
|
16063
|
+
}
|
|
16019
16064
|
return finishRouterAbEcdsaSigningResponse({
|
|
16020
|
-
phase: input.phase,
|
|
16021
16065
|
upstream,
|
|
16022
16066
|
operation: authorizedOperation,
|
|
16023
16067
|
authorizedOperations: input.ctx.service.authorizedOperations,
|
|
@@ -16025,35 +16069,6 @@ async function executeRouterAbEcdsaDerivationNormalSigningRoute(input, timing) {
|
|
|
16025
16069
|
proxyStartedAt
|
|
16026
16070
|
});
|
|
16027
16071
|
}
|
|
16028
|
-
async function finishRouterAbEcdsaSigningResponse(input) {
|
|
16029
|
-
const upstream = input.upstream;
|
|
16030
|
-
if (input.phase === "prepare" && upstream.ok) {
|
|
16031
|
-
input.timing.proxy = performance.now() - input.proxyStartedAt;
|
|
16032
|
-
return upstream;
|
|
16033
|
-
}
|
|
16034
|
-
const upstreamBodyText = await upstream.clone().text().catch(() => "");
|
|
16035
|
-
input.timing.proxy = performance.now() - input.proxyStartedAt;
|
|
16036
|
-
if (isRouterAbEcdsaOperationInProgressResponse({
|
|
16037
|
-
status: upstream.status,
|
|
16038
|
-
bodyText: upstreamBodyText
|
|
16039
|
-
})) return upstream;
|
|
16040
|
-
const completionStartedAt = performance.now();
|
|
16041
|
-
await completeRouterAbEcdsaOperation({
|
|
16042
|
-
authorizedOperations: input.authorizedOperations,
|
|
16043
|
-
operation: input.operation,
|
|
16044
|
-
result: upstream.ok ? "succeeded" : upstream.status < 500 ? "failed_before_side_effect" : "failed_after_side_effect",
|
|
16045
|
-
response: {
|
|
16046
|
-
status: upstream.status,
|
|
16047
|
-
contentType: upstream.headers.get("content-type") || "application/json",
|
|
16048
|
-
bodyText: upstreamBodyText
|
|
16049
|
-
}
|
|
16050
|
-
});
|
|
16051
|
-
input.timing.complete = performance.now() - completionStartedAt;
|
|
16052
|
-
return upstream;
|
|
16053
|
-
}
|
|
16054
|
-
function isRouterAbEcdsaOperationInProgressResponse(input) {
|
|
16055
|
-
return input.status === 409 && input.bodyText.includes("ReplayedLocalRequest:") && input.bodyText.includes("SigningWorker ECDSA effect is already in progress");
|
|
16056
|
-
}
|
|
16057
16072
|
function routerAbEcdsaReplayResponse(operation) {
|
|
16058
16073
|
const response = routerAbEcdsaReplayHttpResponse(operation);
|
|
16059
16074
|
if (response) return response;
|
|
@@ -16063,31 +16078,40 @@ function routerAbEcdsaReplayResponse(operation) {
|
|
|
16063
16078
|
async function resolveV2EcdsaOperationStepUpAdmission(input) {
|
|
16064
16079
|
const token = extractBearerCredential(input.ctx.request.headers);
|
|
16065
16080
|
if (!token) return { kind: "not_found" };
|
|
16066
|
-
let
|
|
16081
|
+
let context;
|
|
16067
16082
|
try {
|
|
16068
|
-
|
|
16069
|
-
|
|
16083
|
+
context = await input.ctx.service.authorizationSessions.readWalletSessionExactOperationContextByCredential({
|
|
16084
|
+
tenantId: input.ctx.service.authorizationSessions.tenantId,
|
|
16070
16085
|
token,
|
|
16071
|
-
nowMs: Date.now()
|
|
16072
|
-
operation: {
|
|
16073
|
-
keyFamily: "ecdsa_secp256k1",
|
|
16074
|
-
operationKind: input.operation.operation_kind
|
|
16075
|
-
}
|
|
16086
|
+
nowMs: Date.now()
|
|
16076
16087
|
});
|
|
16077
16088
|
} catch {
|
|
16078
16089
|
return { kind: "unavailable" };
|
|
16079
16090
|
}
|
|
16080
|
-
if (
|
|
16081
|
-
if (resolution.kind === "rejected") return {
|
|
16091
|
+
if (!context) return {
|
|
16082
16092
|
kind: "rejected",
|
|
16083
|
-
message: "ECDSA operation step-up Wallet Session
|
|
16093
|
+
message: "ECDSA operation step-up Wallet Session is unavailable"
|
|
16084
16094
|
};
|
|
16085
|
-
|
|
16095
|
+
const session = context.session;
|
|
16096
|
+
const admission = resolveWalletSessionAuthorizationV2Admission({
|
|
16097
|
+
authorization: session,
|
|
16098
|
+
authority: context.authority,
|
|
16099
|
+
authMethod: context.authMethod,
|
|
16100
|
+
retiredAtMs: context.retiredAtMs,
|
|
16101
|
+
nowMs: Date.now(),
|
|
16102
|
+
operation: {
|
|
16103
|
+
tenantId: session.tenantId,
|
|
16104
|
+
principalId: session.principalId,
|
|
16105
|
+
walletId: session.walletId,
|
|
16106
|
+
keyFamily: "ecdsa_secp256k1",
|
|
16107
|
+
operationKind: input.operation.operation_kind
|
|
16108
|
+
}
|
|
16109
|
+
});
|
|
16110
|
+
if (!admission.ok || admission.keyFamily !== "ecdsa_secp256k1") return {
|
|
16086
16111
|
kind: "rejected",
|
|
16087
|
-
message: "ECDSA operation step-up Wallet Session
|
|
16112
|
+
message: "ECDSA operation step-up Wallet Session authorization is invalid"
|
|
16088
16113
|
};
|
|
16089
|
-
const
|
|
16090
|
-
const admittedSigner = resolution.admission.admission.signer;
|
|
16114
|
+
const admittedSigner = admission.signer;
|
|
16091
16115
|
if (input.operation.wallet_id !== String(session.walletId) || input.operation.material_activation.material_owner !== String(session.walletId) || input.operation.expires_at_ms > session.expiresAtMs || input.operation.expires_at_ms <= Date.now()) return {
|
|
16092
16116
|
kind: "rejected",
|
|
16093
16117
|
message: "ECDSA operation step-up Wallet Session scope is invalid"
|
|
@@ -16103,13 +16127,13 @@ async function resolveV2EcdsaOperationStepUpAdmission(input) {
|
|
|
16103
16127
|
kind: "rejected",
|
|
16104
16128
|
message: "ECDSA operation step-up material is not uniquely active"
|
|
16105
16129
|
};
|
|
16106
|
-
if (input.operation.signing_worker_id !== input.operation.normal_signing_scope.signing_worker.server_id || !sameRouterAbMpcMaterialActivationRef(input.operation.material_activation, input.operation.normal_signing_scope.material_activation) || !sameRouterAbMpcMaterialActivationRef(input.operation.material_activation, routerAbMpcMaterialActivationRefToWire(
|
|
16130
|
+
if (input.operation.signing_worker_id !== input.operation.normal_signing_scope.signing_worker.server_id || !sameRouterAbMpcMaterialActivationRef(input.operation.material_activation, input.operation.normal_signing_scope.material_activation) || !sameRouterAbMpcMaterialActivationRef(input.operation.material_activation, routerAbMpcMaterialActivationRefToWire(admission.materialActivation))) return {
|
|
16107
16131
|
kind: "rejected",
|
|
16108
16132
|
message: "ECDSA operation step-up material activation is invalid"
|
|
16109
16133
|
};
|
|
16110
16134
|
const activeMaterial = {
|
|
16111
16135
|
ok: true,
|
|
16112
|
-
materialActivation: routerAbMpcMaterialActivationRefToWire(
|
|
16136
|
+
materialActivation: routerAbMpcMaterialActivationRefToWire(admission.materialActivation),
|
|
16113
16137
|
keyHandle: signer.walletKey.keyHandle,
|
|
16114
16138
|
relayerKeyId: signer.walletKey.relayerKeyId,
|
|
16115
16139
|
participantIds: signer.walletKey.participantIds,
|
|
@@ -16118,13 +16142,13 @@ async function resolveV2EcdsaOperationStepUpAdmission(input) {
|
|
|
16118
16142
|
if (input.operation.operation_kind === "evm.sign_transaction") return {
|
|
16119
16143
|
kind: "admitted",
|
|
16120
16144
|
operationKind: "evm.sign_transaction",
|
|
16121
|
-
|
|
16145
|
+
context,
|
|
16122
16146
|
activeMaterial
|
|
16123
16147
|
};
|
|
16124
16148
|
return {
|
|
16125
16149
|
kind: "admitted",
|
|
16126
16150
|
operationKind: "evm.export_key",
|
|
16127
|
-
|
|
16151
|
+
context,
|
|
16128
16152
|
activeMaterial,
|
|
16129
16153
|
exportTopology: {
|
|
16130
16154
|
signer_set: signer.walletKey.publicCapability.signer_set,
|
|
@@ -16184,8 +16208,8 @@ async function issueEcdsaOperationStepUpAuthorization(input) {
|
|
|
16184
16208
|
let v2AuthorityRef;
|
|
16185
16209
|
if (v2Resolution.kind === "admitted") {
|
|
16186
16210
|
v2AuthorityRef = await walletAuthAuthorityRef({ authority });
|
|
16187
|
-
const session = v2Resolution.
|
|
16188
|
-
const context = v2Resolution.
|
|
16211
|
+
const session = v2Resolution.context.session;
|
|
16212
|
+
const context = v2Resolution.context;
|
|
16189
16213
|
if (authority.walletId !== String(session.walletId) || authority.bindingId !== context.authMethod.walletAuthMethodId || context.authMethod.walletAuthorityId !== context.authority.authorityId) return json$1({
|
|
16190
16214
|
ok: false,
|
|
16191
16215
|
code: "scope_mismatch",
|
|
@@ -16213,10 +16237,10 @@ async function issueEcdsaOperationStepUpAuthorization(input) {
|
|
|
16213
16237
|
ok: true,
|
|
16214
16238
|
authorizedOperations: proofAuthenticated.authorizedOperations,
|
|
16215
16239
|
session: {
|
|
16216
|
-
tenantId: v2Resolution.
|
|
16217
|
-
principalId: v2Resolution.
|
|
16218
|
-
sessionId: String(v2Resolution.
|
|
16219
|
-
walletId: String(v2Resolution.
|
|
16240
|
+
tenantId: v2Resolution.context.session.tenantId,
|
|
16241
|
+
principalId: v2Resolution.context.session.principalId,
|
|
16242
|
+
sessionId: String(v2Resolution.context.session.authorizationId),
|
|
16243
|
+
walletId: String(v2Resolution.context.session.walletId),
|
|
16220
16244
|
runtimePolicyScope: activeMaterial.runtimePolicyScope,
|
|
16221
16245
|
laneAuthorization: {
|
|
16222
16246
|
kind: "authority_ref",
|
|
@@ -16262,7 +16286,7 @@ async function issueEcdsaOperationStepUpAuthorization(input) {
|
|
|
16262
16286
|
code: "wallet_session_unavailable",
|
|
16263
16287
|
message: "Wallet Session authorization is unavailable"
|
|
16264
16288
|
}, { status: 503 });
|
|
16265
|
-
if (refreshedV2Resolution.kind !== "admitted" || !
|
|
16289
|
+
if (refreshedV2Resolution.kind !== "admitted" || !walletSessionAuthorizationV2RecordsEqual(v2Resolution.context.session, refreshedV2Resolution.context.session)) return json$1({
|
|
16266
16290
|
ok: false,
|
|
16267
16291
|
code: "scope_mismatch",
|
|
16268
16292
|
message: "ECDSA operation step-up Wallet Session authorization changed"
|
|
@@ -16538,6 +16562,7 @@ async function authorizeEcdsaPoolFillOperationStepUp(input) {
|
|
|
16538
16562
|
materialExpiresAtMs: input.operation.expires_at_ms
|
|
16539
16563
|
},
|
|
16540
16564
|
ownerWalletScope,
|
|
16565
|
+
ownershipGeneration: ownerWalletScope.ownershipGeneration,
|
|
16541
16566
|
routerAbEcdsaDerivationNormalSigning: {
|
|
16542
16567
|
kind: ROUTER_AB_ECDSA_DERIVATION_NORMAL_SIGNING_STATE_KIND_V1,
|
|
16543
16568
|
scope: input.operation.normal_signing_scope
|
|
@@ -16617,6 +16642,7 @@ async function authorizeEcdsaPoolFill(input) {
|
|
|
16617
16642
|
thresholdExpiresAtMs: session.expiresAtMs,
|
|
16618
16643
|
authorization: { kind: "wallet_session" },
|
|
16619
16644
|
ownerWalletScope: validated.ownerWalletScope,
|
|
16645
|
+
ownershipGeneration: validated.ownerWalletScope.ownershipGeneration,
|
|
16620
16646
|
routerAbEcdsaDerivationNormalSigning: normalSigning
|
|
16621
16647
|
}
|
|
16622
16648
|
};
|
|
@@ -16985,11 +17011,6 @@ async function admitStrictEcdsaExportOperationStepUp(input) {
|
|
|
16985
17011
|
case "wallet_session_quota_exhausted": return strictEcdsaExportFailure(409, result.kind, "Operation step-up authorization is invalid");
|
|
16986
17012
|
}
|
|
16987
17013
|
}
|
|
16988
|
-
function sameWalletSessionOperationCredentialAdmission(left, right) {
|
|
16989
|
-
const leftSession = left.context.authorization.session;
|
|
16990
|
-
const rightSession = right.context.authorization.session;
|
|
16991
|
-
return leftSession.tenantId === rightSession.tenantId && leftSession.principalId === rightSession.principalId && leftSession.walletId === rightSession.walletId && leftSession.authorityId === rightSession.authorityId && leftSession.walletAuthMethodId === rightSession.walletAuthMethodId && leftSession.authorityDigestB64u === rightSession.authorityDigestB64u && leftSession.authorityRevocationEpoch === rightSession.authorityRevocationEpoch && leftSession.authorizationId === rightSession.authorizationId && leftSession.walletSessionId === rightSession.walletSessionId && leftSession.quotaId === rightSession.quotaId && leftSession.expiresAtMs === rightSession.expiresAtMs && left.context.authority.authorityId === right.context.authority.authorityId && left.context.authority.authorityDigestB64u === right.context.authority.authorityDigestB64u && left.context.authMethod.walletAuthMethodId === right.context.authMethod.walletAuthMethodId && left.context.authMethod.walletAuthorityId === right.context.authMethod.walletAuthorityId && left.context.retiredAtMs === right.context.retiredAtMs && sameRouterAbMpcMaterialActivationRef(routerAbMpcMaterialActivationRefToWire(left.admission.materialActivation), routerAbMpcMaterialActivationRefToWire(right.admission.materialActivation));
|
|
16992
|
-
}
|
|
16993
17014
|
async function authorizeStrictEcdsaV2ExportOperationStepUp(input) {
|
|
16994
17015
|
const operation = input.request.operation;
|
|
16995
17016
|
if (!operation) return strictEcdsaExportFailure(400, "invalid_body", "Operation step-up export requires operation preparation");
|
|
@@ -16999,8 +17020,8 @@ async function authorizeStrictEcdsaV2ExportOperationStepUp(input) {
|
|
|
16999
17020
|
});
|
|
17000
17021
|
if (resolution.kind === "unavailable") return strictEcdsaExportFailure(503, "wallet_session_unavailable", "Wallet Session authorization is unavailable");
|
|
17001
17022
|
if (resolution.kind !== "admitted") return strictEcdsaExportFailure(403, "scope_mismatch", "ECDSA export operation step-up Wallet Session authorization is invalid");
|
|
17002
|
-
if (!
|
|
17003
|
-
const session = resolution.
|
|
17023
|
+
if (!walletSessionAuthorizationV2RecordsEqual(input.authorization.v2Admission.context.authorization.session, resolution.context.session)) return strictEcdsaExportFailure(403, "scope_mismatch", "ECDSA export operation step-up Wallet Session changed");
|
|
17024
|
+
const session = resolution.context.session;
|
|
17004
17025
|
const activeMaterial = resolution.activeMaterial;
|
|
17005
17026
|
if (input.request.authorization.kind !== "operation_step_up" || operation.operation_kind !== "evm.export_key" || operation.wallet_id !== String(session.walletId) || operation.wallet_id !== input.request.lifecycle.account_id || operation.material_activation.material_owner !== String(session.walletId) || operation.material_activation.signing_worker !== input.request.lifecycle.selected_server_id || operation.signing_worker_id !== input.request.lifecycle.selected_server_id || !sameRouterAbMpcMaterialActivationRef(operation.material_activation, input.request.material_activation) || operation.expires_at_ms < input.request.expires_at_ms || !strictEcdsaExportScopeMatchesRequest({
|
|
17006
17027
|
request: input.request,
|
|
@@ -17887,6 +17908,7 @@ async function handleHostedWalletSessionExchangeIssue(ctx) {
|
|
|
17887
17908
|
ok: true,
|
|
17888
17909
|
delivery: {
|
|
17889
17910
|
exchangeCode: delivery.exchangeCode,
|
|
17911
|
+
home: delivery.home,
|
|
17890
17912
|
nonce: delivery.nonce,
|
|
17891
17913
|
appOrigin: delivery.appOrigin,
|
|
17892
17914
|
walletOrigin: delivery.walletOrigin,
|
|
@@ -19073,6 +19095,67 @@ async function handleSyncAccount(ctx) {
|
|
|
19073
19095
|
return null;
|
|
19074
19096
|
}
|
|
19075
19097
|
//#endregion
|
|
19098
|
+
//#region src/router/transport/fetch/routes/ed25519AuthorizedOperationRevalidation.ts
|
|
19099
|
+
function rejected(code, message, status) {
|
|
19100
|
+
return {
|
|
19101
|
+
ok: false,
|
|
19102
|
+
response: json$1({
|
|
19103
|
+
ok: false,
|
|
19104
|
+
code,
|
|
19105
|
+
message
|
|
19106
|
+
}, { status })
|
|
19107
|
+
};
|
|
19108
|
+
}
|
|
19109
|
+
function rejectedAdmission(kind) {
|
|
19110
|
+
return kind === "authorization_grant_rejected" || kind === "verified_step_up_rejected" ? rejected(kind, "Ed25519 operation authorization is no longer active", 403) : rejected(kind, "Ed25519 operation admission failed", 409);
|
|
19111
|
+
}
|
|
19112
|
+
async function revalidateEd25519StepUpOperation(input) {
|
|
19113
|
+
const stored = input.operation;
|
|
19114
|
+
if (stored.authorization.kind !== "verified_step_up" || stored.quota.kind !== "quota_neutral") return rejected("verified_step_up_rejected", "Ed25519 operation step-up authorization has an invalid quota", 403);
|
|
19115
|
+
const result = await input.ctx.service.authorizedOperations.admitAuthorizedOperation({ operation: {
|
|
19116
|
+
tenantId: stored.tenantId,
|
|
19117
|
+
authorizedOperationId: stored.authorizedOperationId,
|
|
19118
|
+
auditEventId: stored.auditEventId,
|
|
19119
|
+
operation: stored.operation,
|
|
19120
|
+
authorization: stored.authorization,
|
|
19121
|
+
quota: stored.quota,
|
|
19122
|
+
claimedAtMs: Date.now()
|
|
19123
|
+
} });
|
|
19124
|
+
if (!("operation" in result)) return rejectedAdmission(result.kind);
|
|
19125
|
+
if (result.operation.authorizedOperationId !== stored.authorizedOperationId) throw new Error("Ed25519 authorized operation changed during revalidation");
|
|
19126
|
+
return {
|
|
19127
|
+
ok: true,
|
|
19128
|
+
operation: result.operation
|
|
19129
|
+
};
|
|
19130
|
+
}
|
|
19131
|
+
/**
|
|
19132
|
+
* Finds the operation a reusable Wallet Session prepared and checks that its
|
|
19133
|
+
* grant is still active. A live operation returns the owner scope its
|
|
19134
|
+
* admission row pinned. A completed operation returns none: it replays its
|
|
19135
|
+
* stored response. The operation is read by its fingerprint, so a receipt
|
|
19136
|
+
* that names another operation ID has no stored operation.
|
|
19137
|
+
*/
|
|
19138
|
+
async function resolveEd25519WalletSessionOperation(input) {
|
|
19139
|
+
const result = await input.ctx.service.authorizedOperations.resolveEd25519WalletSessionOperation({
|
|
19140
|
+
tenantId: input.tenantId,
|
|
19141
|
+
operationFingerprintDigest: input.operationFingerprintDigest,
|
|
19142
|
+
walletId: input.walletId,
|
|
19143
|
+
nowMs: Date.now()
|
|
19144
|
+
});
|
|
19145
|
+
if (result.kind === "authorized_operation_missing") return rejected("authorized_operation_missing", "Authorized operation is unavailable", 409);
|
|
19146
|
+
if (!result.operation) return rejectedAdmission(result.kind);
|
|
19147
|
+
const stored = result.operation;
|
|
19148
|
+
if (stored.authorizedOperationId !== input.authorizedOperationId) return rejected("authorized_operation_missing", "Authorized operation is unavailable", 409);
|
|
19149
|
+
if (stored.quota.kind !== "consume_reusable_wallet_session") return rejected("authorization_grant_rejected", "Ed25519 reusable operation authorization has an invalid quota", 403);
|
|
19150
|
+
const operation = stored.operation.operation;
|
|
19151
|
+
if (operation.capabilityKind !== "near_ed25519_mpc_signing" || operation.operationKind === "near.export_key") return rejected("authorization_grant_rejected", "Ed25519 reusable operation kind is invalid", 403);
|
|
19152
|
+
return {
|
|
19153
|
+
ok: true,
|
|
19154
|
+
operation: stored,
|
|
19155
|
+
ownerScope: result.ownerScope ?? null
|
|
19156
|
+
};
|
|
19157
|
+
}
|
|
19158
|
+
//#endregion
|
|
19076
19159
|
//#region src/router/domains/signingOperations/ed25519AuthorizedOperationReceipt.ts
|
|
19077
19160
|
function requireEd25519OperationKind(value) {
|
|
19078
19161
|
if (value !== "near.sign_transaction" && value !== "near.sign_delegate_action" && value !== "near.sign_nep413_message") throw new Error("authorized_operation.operation_kind is invalid");
|
|
@@ -19446,151 +19529,56 @@ function parseRouterAbOperationStepUpOperation(value) {
|
|
|
19446
19529
|
message: "Router A/B step-up intent kind is invalid"
|
|
19447
19530
|
};
|
|
19448
19531
|
}
|
|
19449
|
-
const operationId = parseCapabilityOperationId(intent.operation_id);
|
|
19450
|
-
if (!operationId.ok) return {
|
|
19451
|
-
ok: false,
|
|
19452
|
-
message: operationId.error.message
|
|
19453
|
-
};
|
|
19454
|
-
return {
|
|
19455
|
-
ok: true,
|
|
19456
|
-
operationId: operationId.value,
|
|
19457
|
-
operation: buildNearEd25519MpcOperationRef(operationKind)
|
|
19458
|
-
};
|
|
19459
|
-
}
|
|
19460
|
-
function parseRouterAbEd25519NormalSigningOperationForAdmission(input) {
|
|
19461
|
-
if (input.phase === "prepare") {
|
|
19462
|
-
const requestedOperation = parseRouterAbOperationStepUpOperation(input.body.intent);
|
|
19463
|
-
if (!requestedOperation.ok) return requestedOperation;
|
|
19464
|
-
return {
|
|
19465
|
-
ok: true,
|
|
19466
|
-
operation: {
|
|
19467
|
-
phase: "prepare",
|
|
19468
|
-
operationKind: requestedOperation.operation.operationKind
|
|
19469
|
-
}
|
|
19470
|
-
};
|
|
19471
|
-
}
|
|
19472
|
-
try {
|
|
19473
|
-
switch (input.authorizationKind) {
|
|
19474
|
-
case "reusable_wallet_session": {
|
|
19475
|
-
const receipt = parseEd25519ReusableAuthorizedOperationReceipt(input.body.authorized_operation);
|
|
19476
|
-
return {
|
|
19477
|
-
ok: true,
|
|
19478
|
-
operation: {
|
|
19479
|
-
phase: "finalize",
|
|
19480
|
-
operationKind: receipt.operation_kind,
|
|
19481
|
-
authorizationKind: "reusable_wallet_session",
|
|
19482
|
-
receipt
|
|
19483
|
-
}
|
|
19484
|
-
};
|
|
19485
|
-
}
|
|
19486
|
-
case "operation_step_up": {
|
|
19487
|
-
const receipt = parseEd25519VerifiedStepUpAuthorizedOperationReceipt(input.body.authorized_operation);
|
|
19488
|
-
return {
|
|
19489
|
-
ok: true,
|
|
19490
|
-
operation: {
|
|
19491
|
-
phase: "finalize",
|
|
19492
|
-
operationKind: receipt.operation_kind,
|
|
19493
|
-
authorizationKind: "operation_step_up",
|
|
19494
|
-
receipt
|
|
19495
|
-
}
|
|
19496
|
-
};
|
|
19497
|
-
}
|
|
19498
|
-
}
|
|
19499
|
-
} catch (error) {
|
|
19500
|
-
return {
|
|
19501
|
-
ok: false,
|
|
19502
|
-
message: routerAbErrorMessage(error)
|
|
19503
|
-
};
|
|
19504
|
-
}
|
|
19505
|
-
}
|
|
19506
|
-
async function validateRouterAbEd25519V2FinalizeAuthorizedOperation(input) {
|
|
19507
|
-
if (!input.authorizedOperations) return {
|
|
19508
|
-
ok: false,
|
|
19509
|
-
result: routerAbEd25519OwnerOperationFailureResult({
|
|
19510
|
-
status: 501,
|
|
19511
|
-
code: "not_configured",
|
|
19512
|
-
message: "Reusable Wallet Session authorization is not configured",
|
|
19513
|
-
phase: input.phase
|
|
19514
|
-
})
|
|
19515
|
-
};
|
|
19516
|
-
let authorizedOperationId;
|
|
19517
|
-
try {
|
|
19518
|
-
authorizedOperationId = requireAuthorizationValue$2(parseAuthorizedOperationId(input.receipt.authorized_operation_id));
|
|
19519
|
-
requireAuthorizationValue$2(parseCapabilityOperationId(input.receipt.operation_id));
|
|
19520
|
-
} catch (error) {
|
|
19521
|
-
return {
|
|
19522
|
-
ok: false,
|
|
19523
|
-
result: routerAbEd25519OwnerOperationFailureResult({
|
|
19524
|
-
status: 400,
|
|
19525
|
-
code: "invalid_authorized_operation",
|
|
19526
|
-
message: routerAbErrorMessage(error),
|
|
19527
|
-
phase: input.phase
|
|
19528
|
-
})
|
|
19529
|
-
};
|
|
19530
|
-
}
|
|
19531
|
-
let operation;
|
|
19532
|
-
try {
|
|
19533
|
-
operation = await input.authorizedOperations.readAuthorizedOperationById({
|
|
19534
|
-
tenantId: input.authorizedOperations.tenantId,
|
|
19535
|
-
authorizedOperationId
|
|
19536
|
-
});
|
|
19537
|
-
} catch (error) {
|
|
19538
|
-
return {
|
|
19539
|
-
ok: false,
|
|
19540
|
-
result: routerAbEd25519OwnerOperationFailureResult({
|
|
19541
|
-
status: 500,
|
|
19542
|
-
code: "internal",
|
|
19543
|
-
message: routerAbErrorMessage(error),
|
|
19544
|
-
phase: input.phase
|
|
19545
|
-
})
|
|
19546
|
-
};
|
|
19547
|
-
}
|
|
19548
|
-
if (!operation) return {
|
|
19549
|
-
ok: false,
|
|
19550
|
-
result: routerAbEd25519OwnerOperationFailureResult({
|
|
19551
|
-
status: 409,
|
|
19552
|
-
code: "authorized_operation_missing",
|
|
19553
|
-
message: "Authorized operation is unavailable",
|
|
19554
|
-
phase: input.phase
|
|
19555
|
-
})
|
|
19556
|
-
};
|
|
19557
|
-
const operationRef = operation.operation.operation;
|
|
19558
|
-
if (operation.tenantId !== input.authorizedOperations.tenantId || operation.authorizedOperationId !== authorizedOperationId || operation.operation.operationId !== input.receipt.operation_id || operation.operationFingerprintDigest !== input.receipt.operation_fingerprint_digest || operation.operation.digests.laneDigest !== input.receipt.lane_digest_b64u || operation.operation.digests.intentDigest !== input.receipt.intent_digest_b64u || operation.operation.digests.displayDigest !== input.receipt.display_digest_b64u || operationRef.capabilityKind !== "near_ed25519_mpc_signing" || operationRef.operationKind !== input.receipt.operation_kind) return {
|
|
19559
|
-
ok: false,
|
|
19560
|
-
result: routerAbEd25519OwnerOperationFailureResult({
|
|
19561
|
-
status: 400,
|
|
19562
|
-
code: "invalid_authorized_operation",
|
|
19563
|
-
message: "Ed25519 authorized operation does not match its receipt",
|
|
19564
|
-
phase: input.phase
|
|
19565
|
-
})
|
|
19532
|
+
const operationId = parseCapabilityOperationId(intent.operation_id);
|
|
19533
|
+
if (!operationId.ok) return {
|
|
19534
|
+
ok: false,
|
|
19535
|
+
message: operationId.error.message
|
|
19536
|
+
};
|
|
19537
|
+
return {
|
|
19538
|
+
ok: true,
|
|
19539
|
+
operationId: operationId.value,
|
|
19540
|
+
operation: buildNearEd25519MpcOperationRef(operationKind)
|
|
19566
19541
|
};
|
|
19567
|
-
|
|
19568
|
-
|
|
19569
|
-
|
|
19570
|
-
|
|
19542
|
+
}
|
|
19543
|
+
function parseRouterAbEd25519NormalSigningOperationForAdmission(input) {
|
|
19544
|
+
if (input.phase === "prepare") {
|
|
19545
|
+
const requestedOperation = parseRouterAbOperationStepUpOperation(input.body.intent);
|
|
19546
|
+
if (!requestedOperation.ok) return requestedOperation;
|
|
19547
|
+
return {
|
|
19571
19548
|
ok: true,
|
|
19572
|
-
|
|
19549
|
+
operation: {
|
|
19550
|
+
phase: "prepare",
|
|
19551
|
+
operationKind: requestedOperation.operation.operationKind
|
|
19552
|
+
}
|
|
19573
19553
|
};
|
|
19574
19554
|
}
|
|
19575
|
-
|
|
19576
|
-
|
|
19577
|
-
|
|
19578
|
-
|
|
19579
|
-
|
|
19580
|
-
|
|
19581
|
-
|
|
19582
|
-
|
|
19583
|
-
|
|
19584
|
-
|
|
19555
|
+
try {
|
|
19556
|
+
switch (input.authorizationKind) {
|
|
19557
|
+
case "reusable_wallet_session": return {
|
|
19558
|
+
ok: true,
|
|
19559
|
+
operation: {
|
|
19560
|
+
phase: "finalize",
|
|
19561
|
+
operationKind: parseEd25519ReusableAuthorizedOperationReceipt(input.body.authorized_operation).operation_kind,
|
|
19562
|
+
authorizationKind: "reusable_wallet_session"
|
|
19563
|
+
}
|
|
19564
|
+
};
|
|
19565
|
+
case "operation_step_up": return {
|
|
19566
|
+
ok: true,
|
|
19567
|
+
operation: {
|
|
19568
|
+
phase: "finalize",
|
|
19569
|
+
operationKind: parseEd25519VerifiedStepUpAuthorizedOperationReceipt(input.body.authorized_operation).operation_kind,
|
|
19570
|
+
authorizationKind: "operation_step_up"
|
|
19571
|
+
}
|
|
19572
|
+
};
|
|
19573
|
+
}
|
|
19574
|
+
} catch (error) {
|
|
19575
|
+
return {
|
|
19585
19576
|
ok: false,
|
|
19586
|
-
|
|
19587
|
-
status: 403,
|
|
19588
|
-
code: "wallet_session_scope_mismatch",
|
|
19589
|
-
message: "Exact Wallet Session operation does not match the authorized operation",
|
|
19590
|
-
phase: input.phase
|
|
19591
|
-
})
|
|
19577
|
+
message: routerAbErrorMessage(error)
|
|
19592
19578
|
};
|
|
19593
19579
|
}
|
|
19580
|
+
}
|
|
19581
|
+
async function authorizeRouterAbEd25519WalletSessionRequest(input) {
|
|
19594
19582
|
const expectedMaterialActivation = routerAbMpcMaterialActivationRefFromWire(input.scope.material_activation);
|
|
19595
19583
|
const admittedMaterialActivation = routerAbMpcMaterialActivationRefToWire(input.admission.materialActivation);
|
|
19596
19584
|
const expiresAtMs = Number(input.body.expires_at_ms);
|
|
@@ -19623,7 +19611,8 @@ async function authorizeRouterAbEd25519WalletSessionRequest(input) {
|
|
|
19623
19611
|
};
|
|
19624
19612
|
const activeMaterial = await input.resolveEd25519MaterialActivation({
|
|
19625
19613
|
walletId: String(input.session.walletId),
|
|
19626
|
-
materialActivation: admittedMaterialActivation
|
|
19614
|
+
materialActivation: admittedMaterialActivation,
|
|
19615
|
+
...input.signerRead ? { signerRead: input.signerRead } : {}
|
|
19627
19616
|
});
|
|
19628
19617
|
if (!activeMaterial.ok || !sameRouterAbMpcMaterialActivationRef(activeMaterial.materialActivation, admittedMaterialActivation) || activeMaterial.signingWorkerId !== input.scope.signing_worker_id || base64UrlEncode(Uint8Array.from(activeMaterial.exportIdentity.registered_public_key)) !== input.admission.signer.registeredPublicKeyB64u) return {
|
|
19629
19618
|
ok: false,
|
|
@@ -19644,6 +19633,7 @@ async function authorizeRouterAbEd25519WalletSessionRequest(input) {
|
|
|
19644
19633
|
const admissionDecision = await evaluateRouterAbNormalSigningAdmission({
|
|
19645
19634
|
adapter: input.admissionAdapter,
|
|
19646
19635
|
curve: "ed25519",
|
|
19636
|
+
policyReadSource: input.policyReadSource,
|
|
19647
19637
|
authorizationKind: "wallet_session_operation_credential_v1",
|
|
19648
19638
|
phase: input.phase,
|
|
19649
19639
|
walletId: String(input.session.walletId),
|
|
@@ -19701,13 +19691,13 @@ async function resolveRouterAbEd25519ExhaustedCandidateAuthorization(input) {
|
|
|
19701
19691
|
phase: input.phase,
|
|
19702
19692
|
body: input.body,
|
|
19703
19693
|
scope: input.scope,
|
|
19704
|
-
operation: input.operation,
|
|
19705
19694
|
session,
|
|
19706
19695
|
authorityId: String(candidate.authority.authorityId),
|
|
19707
19696
|
admission,
|
|
19708
|
-
authorizedOperations: input.authorizedOperations,
|
|
19709
19697
|
admissionAdapter: input.admissionAdapter,
|
|
19710
|
-
resolveEd25519MaterialActivation: input.resolveEd25519MaterialActivation
|
|
19698
|
+
resolveEd25519MaterialActivation: input.resolveEd25519MaterialActivation,
|
|
19699
|
+
signerRead: null,
|
|
19700
|
+
policyReadSource: { kind: "database" }
|
|
19711
19701
|
});
|
|
19712
19702
|
if (!authorized.ok) return authorized;
|
|
19713
19703
|
return {
|
|
@@ -19770,7 +19760,8 @@ async function authorizeRouterAbEd25519NormalSigningRoute(input) {
|
|
|
19770
19760
|
const validated = await validateRouterAbEd25519WalletSessionInputs({
|
|
19771
19761
|
headers: input.headers,
|
|
19772
19762
|
authorizationSessions: input.authorizationSessions,
|
|
19773
|
-
operationKind: operationForAdmission.operation.operationKind
|
|
19763
|
+
operationKind: operationForAdmission.operation.operationKind,
|
|
19764
|
+
materialActivation: scope.material_activation
|
|
19774
19765
|
});
|
|
19775
19766
|
if (!validated.ok) {
|
|
19776
19767
|
const operation = operationForAdmission.operation;
|
|
@@ -19781,7 +19772,6 @@ async function authorizeRouterAbEd25519NormalSigningRoute(input) {
|
|
|
19781
19772
|
scope,
|
|
19782
19773
|
phase: input.phase,
|
|
19783
19774
|
operation,
|
|
19784
|
-
authorizedOperations: input.authorizedOperations,
|
|
19785
19775
|
authorizationSessions: input.authorizationSessions,
|
|
19786
19776
|
admissionAdapter: input.admissionAdapter,
|
|
19787
19777
|
resolveEd25519MaterialActivation: input.resolveEd25519MaterialActivation
|
|
@@ -19819,13 +19809,16 @@ async function authorizeRouterAbEd25519NormalSigningRoute(input) {
|
|
|
19819
19809
|
phase: input.phase,
|
|
19820
19810
|
body: input.body,
|
|
19821
19811
|
scope,
|
|
19822
|
-
operation,
|
|
19823
19812
|
session: validated.admission.context.authorization.session,
|
|
19824
19813
|
authorityId: String(validated.admission.context.authority.authorityId),
|
|
19825
19814
|
admission: validated.admission.admission,
|
|
19826
|
-
authorizedOperations: input.authorizedOperations,
|
|
19827
19815
|
admissionAdapter: input.admissionAdapter,
|
|
19828
|
-
resolveEd25519MaterialActivation: input.resolveEd25519MaterialActivation
|
|
19816
|
+
resolveEd25519MaterialActivation: input.resolveEd25519MaterialActivation,
|
|
19817
|
+
signerRead: validated.signerRead,
|
|
19818
|
+
policyReadSource: {
|
|
19819
|
+
kind: "credential_snapshot",
|
|
19820
|
+
policyRead: validated.policyRead
|
|
19821
|
+
}
|
|
19829
19822
|
});
|
|
19830
19823
|
if (!authorized.ok) return authorized;
|
|
19831
19824
|
return {
|
|
@@ -20154,11 +20147,12 @@ function ed25519ReusableWalletSessionIdentity(authorization) {
|
|
|
20154
20147
|
quotaId: session.quotaId
|
|
20155
20148
|
};
|
|
20156
20149
|
}
|
|
20157
|
-
function buildEd25519GatewayOwnerWalletSessionBinding(authorization,
|
|
20150
|
+
function buildEd25519GatewayOwnerWalletSessionBinding(authorization, pinned) {
|
|
20158
20151
|
const session = ed25519ReusableWalletSession(authorization);
|
|
20159
20152
|
const runtimePolicyScope = authorization.activeMaterial.runtimePolicyScope;
|
|
20160
20153
|
return {
|
|
20161
20154
|
kind: "gateway_owner_wallet_session",
|
|
20155
|
+
ownershipGeneration: pinned.ownershipGeneration,
|
|
20162
20156
|
subjectId: String(session.principalId),
|
|
20163
20157
|
accountId: String(session.walletId),
|
|
20164
20158
|
authorizationId: String(session.authorizationId),
|
|
@@ -20168,20 +20162,16 @@ function buildEd25519GatewayOwnerWalletSessionBinding(authorization, projectEnvi
|
|
|
20168
20162
|
orgId: runtimePolicyScope.orgId,
|
|
20169
20163
|
projectId: runtimePolicyScope.projectId,
|
|
20170
20164
|
environment: runtimePolicyScope.envId,
|
|
20171
|
-
projectEnvironmentId,
|
|
20165
|
+
projectEnvironmentId: pinned.projectEnvironmentId,
|
|
20172
20166
|
signingWorkerId: authorization.activeMaterial.signingWorkerId,
|
|
20173
20167
|
expiresAtMs: session.expiresAtMs
|
|
20174
20168
|
};
|
|
20175
20169
|
}
|
|
20176
|
-
|
|
20177
|
-
|
|
20170
|
+
/** The scope the operation's own admission pinned, checked against the active material. */
|
|
20171
|
+
function pinnedEd25519WalletScope(authorization, pinned) {
|
|
20178
20172
|
const scope = authorization.activeMaterial.runtimePolicyScope;
|
|
20179
|
-
const pinned = await ctx.service.authorizedOperations.readPinnedOwnerWalletScope({
|
|
20180
|
-
operation,
|
|
20181
|
-
walletId: session.walletId
|
|
20182
|
-
});
|
|
20183
20173
|
if (pinned.orgId !== scope.orgId || pinned.projectId !== scope.projectId) throw new Error("Pinned owner Wallet Session scope differs from active material");
|
|
20184
|
-
return pinned
|
|
20174
|
+
return pinned;
|
|
20185
20175
|
}
|
|
20186
20176
|
/**
|
|
20187
20177
|
* The Router binding for a verified step-up: the wallet it signs for and the
|
|
@@ -20197,6 +20187,7 @@ async function ed25519OperationStepUpBinding(ctx, session, operation) {
|
|
|
20197
20187
|
if (pinned.orgId !== scope.orgId || pinned.projectId !== scope.projectId) throw new Error("Step-up wallet scope differs from the Wallet Session scope");
|
|
20198
20188
|
return {
|
|
20199
20189
|
kind: "operation_step_up",
|
|
20190
|
+
ownershipGeneration: pinned.ownershipGeneration,
|
|
20200
20191
|
authorizationSessionId: session.sessionId,
|
|
20201
20192
|
orgId: scope.orgId,
|
|
20202
20193
|
projectId: scope.projectId,
|
|
@@ -20211,7 +20202,7 @@ function buildRouterAbEd25519AuthorizedOperationWire(input) {
|
|
|
20211
20202
|
const operationRef = operation.operation.operation;
|
|
20212
20203
|
if (operationRef.capabilityKind !== "near_ed25519_mpc_signing") throw new Error("Ed25519 authorized operation capability is invalid");
|
|
20213
20204
|
const operationKind = requireEd25519OperationKind(operationRef.operationKind);
|
|
20214
|
-
|
|
20205
|
+
return buildAuthorizedOperationWire(input, {
|
|
20215
20206
|
authorized_operation_id: operation.authorizedOperationId,
|
|
20216
20207
|
operation_id: operation.operation.operationId,
|
|
20217
20208
|
capability_kind: "near_ed25519_mpc_signing",
|
|
@@ -20220,66 +20211,7 @@ function buildRouterAbEd25519AuthorizedOperationWire(input) {
|
|
|
20220
20211
|
intent_digest_b64u: operation.operation.digests.intentDigest,
|
|
20221
20212
|
display_digest_b64u: operation.operation.digests.displayDigest,
|
|
20222
20213
|
operation_fingerprint_digest: operation.operationFingerprintDigest
|
|
20223
|
-
};
|
|
20224
|
-
switch (input.binding.kind) {
|
|
20225
|
-
case "reusable_wallet_session":
|
|
20226
|
-
if (operation.authorization.kind !== "authorization_grant" || operation.quota.kind !== "consume_reusable_wallet_session") throw new Error("Reusable Wallet Session authorized operation is invalid");
|
|
20227
|
-
return {
|
|
20228
|
-
binding: {
|
|
20229
|
-
kind: "reusable_wallet_session",
|
|
20230
|
-
authorization_id: operation.authorization.authorizationGrantRef.authorizationId,
|
|
20231
|
-
wallet_session_id: input.binding.walletSessionId,
|
|
20232
|
-
quota_id: input.binding.quotaId
|
|
20233
|
-
},
|
|
20234
|
-
authorized_operation: {
|
|
20235
|
-
kind: "reusable_wallet_session_authorized_operation_v1",
|
|
20236
|
-
...commonAuthorizedOperation
|
|
20237
|
-
}
|
|
20238
|
-
};
|
|
20239
|
-
case "gateway_owner_wallet_session":
|
|
20240
|
-
if (operation.authorization.kind !== "authorization_grant" || operation.quota.kind !== "consume_reusable_wallet_session") throw new Error("Gateway owner Wallet Session authorized operation is invalid");
|
|
20241
|
-
return {
|
|
20242
|
-
binding: {
|
|
20243
|
-
kind: "gateway_owner_wallet_session",
|
|
20244
|
-
subject_id: input.binding.subjectId,
|
|
20245
|
-
account_id: input.binding.accountId,
|
|
20246
|
-
authorization_id: input.binding.authorizationId,
|
|
20247
|
-
wallet_session_id: input.binding.walletSessionId,
|
|
20248
|
-
quota_id: input.binding.quotaId,
|
|
20249
|
-
threshold_session_id: input.binding.thresholdSessionId,
|
|
20250
|
-
org_id: input.binding.orgId,
|
|
20251
|
-
project_id: input.binding.projectId,
|
|
20252
|
-
environment: input.binding.environment,
|
|
20253
|
-
project_environment_id: input.binding.projectEnvironmentId,
|
|
20254
|
-
signing_worker_id: input.binding.signingWorkerId,
|
|
20255
|
-
expires_at_ms: input.binding.expiresAtMs
|
|
20256
|
-
},
|
|
20257
|
-
authorized_operation: {
|
|
20258
|
-
kind: "reusable_wallet_session_authorized_operation_v1",
|
|
20259
|
-
...commonAuthorizedOperation
|
|
20260
|
-
}
|
|
20261
|
-
};
|
|
20262
|
-
case "operation_step_up":
|
|
20263
|
-
if (operation.authorization.kind !== "verified_step_up" || operation.quota.kind !== "quota_neutral") throw new Error("Verified step-up authorized operation is invalid");
|
|
20264
|
-
return {
|
|
20265
|
-
binding: {
|
|
20266
|
-
kind: "operation_step_up",
|
|
20267
|
-
authorization_session_id: input.binding.authorizationSessionId,
|
|
20268
|
-
org_id: input.binding.orgId,
|
|
20269
|
-
project_id: input.binding.projectId,
|
|
20270
|
-
environment: input.binding.environment,
|
|
20271
|
-
project_environment_id: input.binding.projectEnvironmentId,
|
|
20272
|
-
subject_id: input.binding.subjectId,
|
|
20273
|
-
account_id: input.binding.accountId
|
|
20274
|
-
},
|
|
20275
|
-
authorized_operation: {
|
|
20276
|
-
kind: "verified_step_up_authorized_operation_v1",
|
|
20277
|
-
authorization_session_id: input.binding.authorizationSessionId,
|
|
20278
|
-
evidence_set_digest: operation.authorization.evidenceSetDigest,
|
|
20279
|
-
...commonAuthorizedOperation
|
|
20280
|
-
}
|
|
20281
|
-
};
|
|
20282
|
-
}
|
|
20214
|
+
});
|
|
20283
20215
|
}
|
|
20284
20216
|
async function releaseEmailOtpFactorForWorker(input) {
|
|
20285
20217
|
const unsealed = await input.emailOtp.removeEmailOtpServerSeal({ wrappedCiphertext: input.request.enrollment.serverSealedFactorCiphertextB64u });
|
|
@@ -20438,21 +20370,24 @@ async function authorizeEd25519ReusableWalletSessionOperation(input) {
|
|
|
20438
20370
|
}
|
|
20439
20371
|
});
|
|
20440
20372
|
const authorizedOperationId = requireAuthorizationValue(parseAuthorizedOperationId(`ed25519-operation:${operation.operationId}:${scope.request_id}`));
|
|
20441
|
-
const outcome = await input.ctx.service.authorizedOperations.
|
|
20442
|
-
|
|
20443
|
-
|
|
20444
|
-
|
|
20445
|
-
|
|
20446
|
-
|
|
20447
|
-
|
|
20448
|
-
|
|
20449
|
-
|
|
20450
|
-
|
|
20451
|
-
|
|
20452
|
-
|
|
20373
|
+
const outcome = await input.ctx.service.authorizedOperations.admitEd25519WalletSessionOperation({
|
|
20374
|
+
operation: {
|
|
20375
|
+
tenantId: identity.tenantId,
|
|
20376
|
+
authorizedOperationId,
|
|
20377
|
+
auditEventId: requireAuthorizationValue(parseAuthorizationAuditEventId(`ed25519-operation-audit:${operation.operationId}`)),
|
|
20378
|
+
operation: envelope,
|
|
20379
|
+
authorization: {
|
|
20380
|
+
kind: "authorization_grant",
|
|
20381
|
+
authorizationGrantRef: buildAuthorizationGrantRef(identity.authorizationId)
|
|
20382
|
+
},
|
|
20383
|
+
quota: {
|
|
20384
|
+
kind: "consume_reusable_wallet_session",
|
|
20385
|
+
quotaId: identity.quotaId
|
|
20386
|
+
},
|
|
20387
|
+
claimedAtMs: nowMs
|
|
20453
20388
|
},
|
|
20454
|
-
|
|
20455
|
-
}
|
|
20389
|
+
walletId: session.walletId
|
|
20390
|
+
});
|
|
20456
20391
|
if (outcome.kind !== "claimed" && outcome.kind !== "operation_in_progress" && outcome.kind !== "replayed") {
|
|
20457
20392
|
const stepUpMaterial = await input.ctx.service.walletRegistration.resolveEd25519MaterialActivation({
|
|
20458
20393
|
walletId: scope.account_id,
|
|
@@ -20487,6 +20422,7 @@ async function authorizeEd25519ReusableWalletSessionOperation(input) {
|
|
|
20487
20422
|
admission: {
|
|
20488
20423
|
kind: "claimed",
|
|
20489
20424
|
operation: outcome.operation,
|
|
20425
|
+
ownerScope: outcome.ownerScope,
|
|
20490
20426
|
receipt: {
|
|
20491
20427
|
kind: "reusable_wallet_session_authorized_operation_v1",
|
|
20492
20428
|
authorized_operation_id: outcome.operation.authorizedOperationId,
|
|
@@ -20511,101 +20447,6 @@ async function authorizeEd25519ReusableWalletSessionOperation(input) {
|
|
|
20511
20447
|
};
|
|
20512
20448
|
}
|
|
20513
20449
|
}
|
|
20514
|
-
async function revalidateEd25519AuthorizedOperation(input) {
|
|
20515
|
-
let admission;
|
|
20516
|
-
if (input.operation.authorization.kind === "verified_step_up") {
|
|
20517
|
-
if (input.operation.quota.kind !== "quota_neutral") return {
|
|
20518
|
-
ok: false,
|
|
20519
|
-
response: json$1({
|
|
20520
|
-
ok: false,
|
|
20521
|
-
code: "verified_step_up_rejected",
|
|
20522
|
-
message: "Ed25519 operation step-up authorization has an invalid quota"
|
|
20523
|
-
}, { status: 403 })
|
|
20524
|
-
};
|
|
20525
|
-
admission = {
|
|
20526
|
-
tenantId: input.operation.tenantId,
|
|
20527
|
-
authorizedOperationId: input.operation.authorizedOperationId,
|
|
20528
|
-
auditEventId: input.operation.auditEventId,
|
|
20529
|
-
operation: input.operation.operation,
|
|
20530
|
-
authorization: input.operation.authorization,
|
|
20531
|
-
quota: input.operation.quota,
|
|
20532
|
-
claimedAtMs: Date.now()
|
|
20533
|
-
};
|
|
20534
|
-
} else {
|
|
20535
|
-
if (input.operation.quota.kind !== "consume_reusable_wallet_session") return {
|
|
20536
|
-
ok: false,
|
|
20537
|
-
response: json$1({
|
|
20538
|
-
ok: false,
|
|
20539
|
-
code: "authorization_grant_rejected",
|
|
20540
|
-
message: "Ed25519 reusable operation authorization has an invalid quota"
|
|
20541
|
-
}, { status: 403 })
|
|
20542
|
-
};
|
|
20543
|
-
const operation = buildEd25519ReusableOperationEnvelope(input.operation);
|
|
20544
|
-
if (!operation) return {
|
|
20545
|
-
ok: false,
|
|
20546
|
-
response: json$1({
|
|
20547
|
-
ok: false,
|
|
20548
|
-
code: "authorization_grant_rejected",
|
|
20549
|
-
message: "Ed25519 reusable operation kind is invalid"
|
|
20550
|
-
}, { status: 403 })
|
|
20551
|
-
};
|
|
20552
|
-
admission = {
|
|
20553
|
-
tenantId: input.operation.tenantId,
|
|
20554
|
-
authorizedOperationId: input.operation.authorizedOperationId,
|
|
20555
|
-
auditEventId: input.operation.auditEventId,
|
|
20556
|
-
operation,
|
|
20557
|
-
authorization: input.operation.authorization,
|
|
20558
|
-
quota: input.operation.quota,
|
|
20559
|
-
claimedAtMs: Date.now()
|
|
20560
|
-
};
|
|
20561
|
-
}
|
|
20562
|
-
const result = await input.ctx.service.authorizedOperations.admitAuthorizedOperation({ operation: admission });
|
|
20563
|
-
switch (result.kind) {
|
|
20564
|
-
case "claimed":
|
|
20565
|
-
case "operation_in_progress":
|
|
20566
|
-
case "replayed":
|
|
20567
|
-
if (result.operation.authorizedOperationId !== input.operation.authorizedOperationId) throw new Error("Ed25519 authorized operation changed during revalidation");
|
|
20568
|
-
return {
|
|
20569
|
-
ok: true,
|
|
20570
|
-
operation: result.operation
|
|
20571
|
-
};
|
|
20572
|
-
case "authorization_grant_rejected":
|
|
20573
|
-
case "verified_step_up_rejected": return {
|
|
20574
|
-
ok: false,
|
|
20575
|
-
response: json$1({
|
|
20576
|
-
ok: false,
|
|
20577
|
-
code: result.kind,
|
|
20578
|
-
message: "Ed25519 operation authorization is no longer active"
|
|
20579
|
-
}, { status: 403 })
|
|
20580
|
-
};
|
|
20581
|
-
case "wallet_session_quota_exhausted":
|
|
20582
|
-
case "material_mismatch": return {
|
|
20583
|
-
ok: false,
|
|
20584
|
-
response: json$1({
|
|
20585
|
-
ok: false,
|
|
20586
|
-
code: result.kind,
|
|
20587
|
-
message: "Ed25519 operation admission failed"
|
|
20588
|
-
}, { status: 409 })
|
|
20589
|
-
};
|
|
20590
|
-
}
|
|
20591
|
-
}
|
|
20592
|
-
function buildEd25519ReusableOperationEnvelope(operation) {
|
|
20593
|
-
const operationRef = operation.operation.operation;
|
|
20594
|
-
if (operationRef.capabilityKind !== "near_ed25519_mpc_signing") return null;
|
|
20595
|
-
switch (operationRef.operationKind) {
|
|
20596
|
-
case "near.sign_transaction":
|
|
20597
|
-
case "near.sign_delegate_action":
|
|
20598
|
-
case "near.sign_nep413_message": return buildCapabilityOperationEnvelope({
|
|
20599
|
-
tenantId: operation.operation.tenantId,
|
|
20600
|
-
principalId: operation.operation.principalId,
|
|
20601
|
-
capabilityId: operation.operation.capabilityId,
|
|
20602
|
-
operationId: operation.operation.operationId,
|
|
20603
|
-
operation: buildNearEd25519MpcOperationRef(operationRef.operationKind),
|
|
20604
|
-
digests: operation.operation.digests
|
|
20605
|
-
});
|
|
20606
|
-
case "near.export_key": return null;
|
|
20607
|
-
}
|
|
20608
|
-
}
|
|
20609
20450
|
async function validateEd25519ReusableAuthorizedOperation(input) {
|
|
20610
20451
|
try {
|
|
20611
20452
|
const receipt = parseEd25519ReusableAuthorizedOperationReceipt(input.body.authorized_operation);
|
|
@@ -20614,7 +20455,7 @@ async function validateEd25519ReusableAuthorizedOperation(input) {
|
|
|
20614
20455
|
const identity = ed25519ReusableWalletSessionIdentity(input.authorization);
|
|
20615
20456
|
const capabilityId = requireAuthorizationValue(parseCapabilityId(scope.material_activation.capability));
|
|
20616
20457
|
const operationId = requireAuthorizationValue(parseCapabilityOperationId(receipt.operation_id));
|
|
20617
|
-
const
|
|
20458
|
+
const envelope = buildCapabilityOperationEnvelope({
|
|
20618
20459
|
tenantId: identity.tenantId,
|
|
20619
20460
|
principalId: identity.principalId,
|
|
20620
20461
|
capabilityId,
|
|
@@ -20628,31 +20469,39 @@ async function validateEd25519ReusableAuthorizedOperation(input) {
|
|
|
20628
20469
|
intentDigest: parseDigestB64u(receipt.intent_digest_b64u),
|
|
20629
20470
|
displayDigest: parseDigestB64u(receipt.display_digest_b64u)
|
|
20630
20471
|
}
|
|
20631
|
-
})
|
|
20472
|
+
});
|
|
20473
|
+
const fingerprint = await computeCapabilityOperationFingerprintDigest(envelope);
|
|
20632
20474
|
if (fingerprint !== parseCapabilityOperationFingerprintDigest(receipt.operation_fingerprint_digest)) throw new Error("Ed25519 authorized operation fingerprint changed");
|
|
20633
20475
|
if (digestWireB64u((isPlainObject(input.body.prepare_binding) ? input.body.prepare_binding : null)?.intent_digest, "prepare_binding.intent_digest") !== receipt.intent_digest_b64u) throw new Error("Ed25519 authorized operation intent changed after prepare");
|
|
20634
|
-
const
|
|
20635
|
-
|
|
20636
|
-
|
|
20637
|
-
|
|
20638
|
-
|
|
20639
|
-
|
|
20640
|
-
|
|
20476
|
+
const authorizedOperationId = requireAuthorizationValue(parseAuthorizedOperationId(receipt.authorized_operation_id));
|
|
20477
|
+
let resolved;
|
|
20478
|
+
try {
|
|
20479
|
+
resolved = await resolveEd25519WalletSessionOperation({
|
|
20480
|
+
ctx: input.ctx,
|
|
20481
|
+
tenantId: identity.tenantId,
|
|
20482
|
+
authorizedOperationId,
|
|
20483
|
+
operationFingerprintDigest: fingerprint,
|
|
20484
|
+
walletId: ed25519ReusableWalletSession(input.authorization).walletId
|
|
20485
|
+
});
|
|
20486
|
+
} catch {
|
|
20487
|
+
return {
|
|
20641
20488
|
ok: false,
|
|
20642
|
-
|
|
20643
|
-
|
|
20644
|
-
|
|
20645
|
-
|
|
20646
|
-
|
|
20647
|
-
|
|
20648
|
-
|
|
20649
|
-
|
|
20650
|
-
|
|
20651
|
-
|
|
20489
|
+
response: json$1({
|
|
20490
|
+
ok: false,
|
|
20491
|
+
code: "internal",
|
|
20492
|
+
message: "Authorized operation lookup failed"
|
|
20493
|
+
}, { status: 500 })
|
|
20494
|
+
};
|
|
20495
|
+
}
|
|
20496
|
+
if (!resolved.ok) return resolved;
|
|
20497
|
+
const operationResult = resolved.operation;
|
|
20498
|
+
if (operationResult.tenantId !== identity.tenantId || operationResult.tenantId !== input.ctx.service.authorizedOperations.tenantId || operationResult.operationFingerprintDigest !== fingerprint || operationResult.operation.operationId !== operationId || operationResult.operation.digests.laneDigest !== envelope.digests.laneDigest || operationResult.operation.digests.intentDigest !== envelope.digests.intentDigest || operationResult.operation.digests.displayDigest !== envelope.digests.displayDigest || operationResult.operation.operation.capabilityKind !== "near_ed25519_mpc_signing" || operationResult.operation.operation.operationKind !== receipt.operation_kind) throw new Error("Ed25519 authorized operation identity changed after prepare");
|
|
20499
|
+
return {
|
|
20652
20500
|
ok: true,
|
|
20653
20501
|
receipt,
|
|
20654
|
-
operation:
|
|
20655
|
-
|
|
20502
|
+
operation: operationResult,
|
|
20503
|
+
ownerScope: resolved.ownerScope
|
|
20504
|
+
};
|
|
20656
20505
|
} catch (error) {
|
|
20657
20506
|
return {
|
|
20658
20507
|
ok: false,
|
|
@@ -20718,7 +20567,7 @@ async function validateEd25519VerifiedStepUpAuthorizedOperation(input) {
|
|
|
20718
20567
|
};
|
|
20719
20568
|
if (operationResult.authorizedOperationId !== requireAuthorizationValue(parseAuthorizedOperationId(receipt.authorized_operation_id)) || operationResult.operationFingerprintDigest !== fingerprint) throw new Error("Operation step-up authorized operation identity changed after prepare");
|
|
20720
20569
|
if (operationResult.authorization.kind !== "verified_step_up" || operationResult.authorization.evidenceSetDigest !== parseDigestB64u(receipt.evidence_set_digest)) throw new Error("Operation step-up evidence changed after prepare");
|
|
20721
|
-
const revalidated = await
|
|
20570
|
+
const revalidated = await revalidateEd25519StepUpOperation({
|
|
20722
20571
|
ctx: input.ctx,
|
|
20723
20572
|
operation: operationResult
|
|
20724
20573
|
});
|
|
@@ -21181,13 +21030,15 @@ async function handleRouterAbEd25519NormalSigningRoute(input) {
|
|
|
21181
21030
|
bodyText: upstreamBodyText
|
|
21182
21031
|
})
|
|
21183
21032
|
}));
|
|
21184
|
-
|
|
21033
|
+
const headers = new Headers(upstream.headers);
|
|
21034
|
+
headers.delete("content-length");
|
|
21035
|
+
return new Response(JSON.stringify(signingPrepareSessionResponse({
|
|
21185
21036
|
...upstreamBody,
|
|
21186
21037
|
authorized_operation: buildEd25519VerifiedStepUpAuthorizedOperationReceipt({ authorization })
|
|
21187
|
-
}), {
|
|
21038
|
+
}, authorization)), {
|
|
21188
21039
|
status: upstream.status,
|
|
21189
21040
|
statusText: upstream.statusText,
|
|
21190
|
-
headers
|
|
21041
|
+
headers
|
|
21191
21042
|
});
|
|
21192
21043
|
}
|
|
21193
21044
|
if (authorization.phase !== "finalize") throw new Error("Operation step-up finalize authorization phase changed");
|
|
@@ -21261,7 +21112,7 @@ async function handleRouterAbEd25519NormalSigningRoute(input) {
|
|
|
21261
21112
|
...input.body,
|
|
21262
21113
|
authorized_operation: buildRouterAbEd25519AuthorizedOperationWire({
|
|
21263
21114
|
operation: execution.operation,
|
|
21264
|
-
binding:
|
|
21115
|
+
binding: buildEd25519GatewayOwnerWalletSessionBinding(authorization, pinnedEd25519WalletScope(authorization, authorized.admission.ownerScope))
|
|
21265
21116
|
})
|
|
21266
21117
|
}
|
|
21267
21118
|
});
|
|
@@ -21285,13 +21136,15 @@ async function handleRouterAbEd25519NormalSigningRoute(input) {
|
|
|
21285
21136
|
bodyText: upstreamBodyText
|
|
21286
21137
|
})
|
|
21287
21138
|
}));
|
|
21288
|
-
|
|
21139
|
+
const headers = new Headers(upstream.headers);
|
|
21140
|
+
headers.delete("content-length");
|
|
21141
|
+
return new Response(JSON.stringify(signingPrepareSessionResponse({
|
|
21289
21142
|
...upstreamBody,
|
|
21290
21143
|
authorized_operation: authorized.admission.receipt
|
|
21291
|
-
}), {
|
|
21144
|
+
}, authorization)), {
|
|
21292
21145
|
status: upstream.status,
|
|
21293
21146
|
statusText: upstream.statusText,
|
|
21294
|
-
headers
|
|
21147
|
+
headers
|
|
21295
21148
|
});
|
|
21296
21149
|
}
|
|
21297
21150
|
const validatedAuthorization = await validateEd25519ReusableAuthorizedOperation({
|
|
@@ -21302,6 +21155,7 @@ async function handleRouterAbEd25519NormalSigningRoute(input) {
|
|
|
21302
21155
|
if (!validatedAuthorization.ok) return validatedAuthorization.response;
|
|
21303
21156
|
const replay = replayCompletedEd25519Operation(validatedAuthorization.operation);
|
|
21304
21157
|
if (replay) return replay;
|
|
21158
|
+
if (!validatedAuthorization.ownerScope) throw new Error("Pinned owner Wallet Session scope is unavailable");
|
|
21305
21159
|
const upstream = await proxyEd25519OwnerLaneExecution({
|
|
21306
21160
|
ctx: input.ctx,
|
|
21307
21161
|
authorization,
|
|
@@ -21310,7 +21164,7 @@ async function handleRouterAbEd25519NormalSigningRoute(input) {
|
|
|
21310
21164
|
...input.body,
|
|
21311
21165
|
authorized_operation: buildRouterAbEd25519AuthorizedOperationWire({
|
|
21312
21166
|
operation: validatedAuthorization.operation,
|
|
21313
|
-
binding:
|
|
21167
|
+
binding: buildEd25519GatewayOwnerWalletSessionBinding(authorization, pinnedEd25519WalletScope(authorization, validatedAuthorization.ownerScope))
|
|
21314
21168
|
})
|
|
21315
21169
|
}
|
|
21316
21170
|
});
|
|
@@ -21442,7 +21296,7 @@ function parsePreflightRequest(raw) {
|
|
|
21442
21296
|
if (!isPlainObject(raw)) throw new Error("owner execution-lane preflight body is required");
|
|
21443
21297
|
const fields = Object.keys(raw).sort();
|
|
21444
21298
|
if (fields.length !== 2 || fields[0] !== "curve" || fields[1] !== "expectedMaterialActivation") throw new Error("owner execution-lane preflight body fields are invalid");
|
|
21445
|
-
if (raw.curve !== "
|
|
21299
|
+
if (raw.curve !== "ecdsa_secp256k1") throw new Error("owner execution-lane preflight curve is invalid");
|
|
21446
21300
|
const materialActivation = parseMpcMaterialActivationRef(raw.expectedMaterialActivation);
|
|
21447
21301
|
if (!materialActivation.ok) throw new Error(materialActivation.error.message);
|
|
21448
21302
|
return {
|
|
@@ -21592,46 +21446,24 @@ async function handleOwnerWalletExecutionLanePreflight(ctx) {
|
|
|
21592
21446
|
}, { status: 400 });
|
|
21593
21447
|
}
|
|
21594
21448
|
const headers = Object.fromEntries(ctx.request.headers.entries());
|
|
21595
|
-
|
|
21596
|
-
|
|
21597
|
-
|
|
21598
|
-
|
|
21599
|
-
|
|
21600
|
-
authorizationSessions: ctx.service.authorizationSessions,
|
|
21601
|
-
operationKind: NEAR_ED25519_MPC_OPERATION_KINDS.signTransaction
|
|
21602
|
-
});
|
|
21603
|
-
if (!validated.ok) return validationFailure(validated);
|
|
21604
|
-
walletIdRaw = String(validated.admission.context.authorization.session.walletId);
|
|
21605
|
-
authorization = {
|
|
21606
|
-
kind: "wallet_auth_method",
|
|
21607
|
-
walletAuthMethodId: validated.admission.context.authorization.session.walletAuthMethodId
|
|
21608
|
-
};
|
|
21609
|
-
} else {
|
|
21610
|
-
const validated = await validateRouterAbEcdsaDerivationWalletSessionInputs({
|
|
21611
|
-
materialActivation: routerAbMpcMaterialActivationRefToWire(request.expectedMaterialActivation),
|
|
21612
|
-
headers,
|
|
21613
|
-
authorizationSessions: ctx.service.authorizationSessions,
|
|
21614
|
-
operationKind: EVM_ECDSA_MPC_OPERATION_KINDS.signTransaction
|
|
21615
|
-
});
|
|
21616
|
-
if (!validated.ok) return validationFailure(validated);
|
|
21617
|
-
if (validated.kind === "wallet_session_operation_credential_exhausted_candidate_v1") return validationFailure(walletSessionFailure("wallet_session_unavailable"));
|
|
21618
|
-
walletIdRaw = String(validated.admission.context.authorization.session.walletId);
|
|
21619
|
-
authorization = {
|
|
21620
|
-
kind: "wallet_auth_method",
|
|
21621
|
-
walletAuthMethodId: validated.admission.context.authorization.session.walletAuthMethodId
|
|
21622
|
-
};
|
|
21623
|
-
}
|
|
21624
|
-
const walletId = parseWalletId(walletIdRaw);
|
|
21625
|
-
if (!walletId.ok) return validationFailure({
|
|
21626
|
-
code: WALLET_SESSION_FAILURE_CODES.invalid,
|
|
21627
|
-
message: "Wallet Session wallet identity is invalid"
|
|
21449
|
+
const validated = await validateRouterAbEcdsaDerivationWalletSessionInputs({
|
|
21450
|
+
materialActivation: routerAbMpcMaterialActivationRefToWire(request.expectedMaterialActivation),
|
|
21451
|
+
headers,
|
|
21452
|
+
authorizationSessions: ctx.service.authorizationSessions,
|
|
21453
|
+
operationKind: EVM_ECDSA_MPC_OPERATION_KINDS.signTransaction
|
|
21628
21454
|
});
|
|
21455
|
+
if (!validated.ok) return validationFailure(validated);
|
|
21456
|
+
if (validated.kind === "wallet_session_operation_credential_exhausted_candidate_v1") return validationFailure(walletSessionFailure("wallet_session_unavailable"));
|
|
21457
|
+
const session = validated.admission.context.authorization.session;
|
|
21629
21458
|
let resolved;
|
|
21630
21459
|
try {
|
|
21631
21460
|
resolved = await ctx.service.walletRegistration.resolveActiveOwnerWalletExecutionLane({
|
|
21632
|
-
walletId: walletId
|
|
21461
|
+
walletId: session.walletId,
|
|
21633
21462
|
expectedMaterialActivation: request.expectedMaterialActivation,
|
|
21634
|
-
authorization
|
|
21463
|
+
authorization: {
|
|
21464
|
+
kind: "wallet_auth_method",
|
|
21465
|
+
walletAuthMethodId: session.walletAuthMethodId
|
|
21466
|
+
}
|
|
21635
21467
|
});
|
|
21636
21468
|
} catch {
|
|
21637
21469
|
return json$1({
|
|
@@ -24834,6 +24666,12 @@ async function routerAbEd25519YaoTenantRootWireV1(root) {
|
|
|
24834
24666
|
custody_lineage_b64u: root.custodyLineageB64u
|
|
24835
24667
|
};
|
|
24836
24668
|
}
|
|
24669
|
+
function routerAbEd25519YaoRegistrationSigningRootIdV1(admissionRequest) {
|
|
24670
|
+
return {
|
|
24671
|
+
signing_root_id: admissionRequest.application_binding.signing_root_id,
|
|
24672
|
+
root_share_epoch: admissionRequest.scope.root_share_epoch
|
|
24673
|
+
};
|
|
24674
|
+
}
|
|
24837
24675
|
//#endregion
|
|
24838
24676
|
//#region src/router/domains/ed25519Yao/registration/routerAbEd25519YaoHttpRegistrationBackend.ts
|
|
24839
24677
|
const INTERNAL_AUTH_HEADER = "x-router-ab-internal-service-auth";
|
|
@@ -25041,6 +24879,7 @@ function registrationRouterExecuteRequest(input, tenantRoot) {
|
|
|
25041
24879
|
participant_ids: input.admissionRequest.participant_ids,
|
|
25042
24880
|
target: {
|
|
25043
24881
|
operation: "registration",
|
|
24882
|
+
ownership_generation: input.ownershipGeneration,
|
|
25044
24883
|
binding: input.request.binding,
|
|
25045
24884
|
deriver_a_input: input.request.deriver_a_input,
|
|
25046
24885
|
deriver_b_input: input.request.deriver_b_input
|
|
@@ -25054,6 +24893,7 @@ function recoveryRouterExecuteRequest(input, tenantRoot, attempt) {
|
|
|
25054
24893
|
participant_ids: input.admissionRequest.participant_ids,
|
|
25055
24894
|
target: {
|
|
25056
24895
|
operation: "recovery",
|
|
24896
|
+
ownership_generation: input.ownershipGeneration,
|
|
25057
24897
|
binding: input.request.binding,
|
|
25058
24898
|
attempt,
|
|
25059
24899
|
deriver_a_input: input.request.deriver_a_input,
|
|
@@ -25066,7 +24906,7 @@ async function routerExecuteRequest(input, resolveTenantRoot) {
|
|
|
25066
24906
|
switch (input.operation) {
|
|
25067
24907
|
case "registration": return registrationRouterExecuteRequest(input, await routerAbEd25519YaoTenantRootWireV1(await resolveTenantRoot({
|
|
25068
24908
|
operation: "registration",
|
|
25069
|
-
|
|
24909
|
+
...routerAbEd25519YaoRegistrationSigningRootIdV1(input.admissionRequest)
|
|
25070
24910
|
})));
|
|
25071
24911
|
case "export": return {
|
|
25072
24912
|
tenant_root: await routerAbEd25519YaoTenantRootWireV1(await resolveTenantRoot({
|
|
@@ -25077,6 +24917,7 @@ async function routerExecuteRequest(input, resolveTenantRoot) {
|
|
|
25077
24917
|
participant_ids: input.admissionRequest.participant_ids,
|
|
25078
24918
|
target: {
|
|
25079
24919
|
operation: "export",
|
|
24920
|
+
ownership_generation: input.ownershipGeneration,
|
|
25080
24921
|
binding: input.request.binding,
|
|
25081
24922
|
deriver_a_input: input.request.deriver_a_input,
|
|
25082
24923
|
deriver_b_input: input.request.deriver_b_input
|
|
@@ -25273,11 +25114,12 @@ var RouterAbEd25519YaoHttpRegistrationBackend = class {
|
|
|
25273
25114
|
}
|
|
25274
25115
|
};
|
|
25275
25116
|
}
|
|
25276
|
-
async executeExport(request,
|
|
25117
|
+
async executeExport(request, claim, traceContext) {
|
|
25277
25118
|
return await this.executeRouterRequest({
|
|
25278
25119
|
operation: "export",
|
|
25279
25120
|
request,
|
|
25280
|
-
admissionRequest
|
|
25121
|
+
admissionRequest: claim.admissionRequest,
|
|
25122
|
+
ownershipGeneration: claim.ownershipGeneration
|
|
25281
25123
|
}, false, traceContext);
|
|
25282
25124
|
}
|
|
25283
25125
|
keyset() {
|
|
@@ -25344,34 +25186,37 @@ var RouterAbEd25519YaoHttpRegistrationBackend = class {
|
|
|
25344
25186
|
};
|
|
25345
25187
|
}
|
|
25346
25188
|
}
|
|
25347
|
-
async execute(request, admissionRequest, traceContext) {
|
|
25189
|
+
async execute(request, admissionRequest, ownershipGeneration, traceContext) {
|
|
25348
25190
|
return await this.executeRouterRequest({
|
|
25349
25191
|
operation: "registration",
|
|
25350
25192
|
request,
|
|
25351
|
-
admissionRequest
|
|
25193
|
+
admissionRequest,
|
|
25194
|
+
ownershipGeneration
|
|
25352
25195
|
}, false, traceContext);
|
|
25353
25196
|
}
|
|
25354
|
-
async resolveRegistrationDispatchRoot(
|
|
25197
|
+
async resolveRegistrationDispatchRoot(signingRootId) {
|
|
25355
25198
|
return await routerAbEd25519YaoTenantRootWireV1(await this.config.resolveTenantRoot({
|
|
25356
25199
|
operation: "registration",
|
|
25357
|
-
|
|
25200
|
+
...signingRootId
|
|
25358
25201
|
}));
|
|
25359
25202
|
}
|
|
25360
|
-
async executePinnedRegistration(request,
|
|
25203
|
+
async executePinnedRegistration(request, authority, traceContext) {
|
|
25361
25204
|
const routerInput = {
|
|
25362
25205
|
operation: "registration",
|
|
25363
25206
|
request,
|
|
25364
|
-
admissionRequest
|
|
25207
|
+
admissionRequest: authority.admissionRequest,
|
|
25208
|
+
ownershipGeneration: authority.ownershipGeneration
|
|
25365
25209
|
};
|
|
25366
|
-
return await this.sendRouterRequest(routerInput, registrationRouterExecuteRequest(routerInput, dispatchRoot), traceContext.value, "exact", false);
|
|
25210
|
+
return await this.sendRouterRequest(routerInput, registrationRouterExecuteRequest(routerInput, authority.dispatchRoot), traceContext.value, "exact", false);
|
|
25367
25211
|
}
|
|
25368
25212
|
async consumeRegistration(input) {
|
|
25369
25213
|
let response;
|
|
25370
25214
|
try {
|
|
25371
|
-
response = await this.post(ROUTER_REGISTRATION_CONSUME_PATH, {
|
|
25372
|
-
tenant_root: input.
|
|
25373
|
-
|
|
25374
|
-
|
|
25215
|
+
response = await this.post(ROUTER_REGISTRATION_CONSUME_PATH, walletObjectIdentity(input.authority.admissionReceipt.binding.lifecycle.account_id, input.authority.ownershipGeneration, input.authority.dispatchRoot.identity), {
|
|
25216
|
+
tenant_root: input.authority.dispatchRoot,
|
|
25217
|
+
ownership_generation: input.authority.ownershipGeneration,
|
|
25218
|
+
wallet_id: input.authority.admissionReceipt.binding.lifecycle.account_id,
|
|
25219
|
+
lifecycle_id: input.authority.lifecycleId,
|
|
25375
25220
|
session_id: Array.from(input.sessionId),
|
|
25376
25221
|
consumer_binding: input.consumerBinding
|
|
25377
25222
|
}, createRouterAbTraceContextV1().value, "exact");
|
|
@@ -25393,13 +25238,14 @@ var RouterAbEd25519YaoHttpRegistrationBackend = class {
|
|
|
25393
25238
|
admissionRequest
|
|
25394
25239
|
}));
|
|
25395
25240
|
}
|
|
25396
|
-
async executeRecovery(request,
|
|
25241
|
+
async executeRecovery(request, claim, traceContext) {
|
|
25397
25242
|
const routerInput = {
|
|
25398
25243
|
operation: "recovery",
|
|
25399
25244
|
request,
|
|
25400
|
-
admissionRequest
|
|
25245
|
+
admissionRequest: claim.admissionRequest,
|
|
25246
|
+
ownershipGeneration: claim.ownershipGeneration
|
|
25401
25247
|
};
|
|
25402
|
-
return await this.sendRouterRequest(routerInput, recoveryRouterExecuteRequest(routerInput, dispatchRoot, attempt), (traceContext ?? createRouterAbTraceContextV1()).value, "replay", replay);
|
|
25248
|
+
return await this.sendRouterRequest(routerInput, recoveryRouterExecuteRequest(routerInput, claim.dispatchRoot, claim.attempt), (traceContext ?? createRouterAbTraceContextV1()).value, "replay", claim.replay);
|
|
25403
25249
|
}
|
|
25404
25250
|
async executeRouterRequest(request, replay, traceContext) {
|
|
25405
25251
|
const traceId = (traceContext ?? createRouterAbTraceContextV1()).value;
|
|
@@ -25419,7 +25265,7 @@ var RouterAbEd25519YaoHttpRegistrationBackend = class {
|
|
|
25419
25265
|
const operation = request.operation;
|
|
25420
25266
|
const executeStartedAt = performance.now();
|
|
25421
25267
|
try {
|
|
25422
|
-
const response = await this.post(ROUTER_EXECUTE_PATH, routerRequest, traceId, retryAfterTransportFailure, replay);
|
|
25268
|
+
const response = await this.post(ROUTER_EXECUTE_PATH, walletObjectIdentity(request.admissionRequest.application_binding.wallet_id, request.ownershipGeneration, routerRequest.tenant_root.identity), routerRequest, traceId, retryAfterTransportFailure, replay);
|
|
25423
25269
|
this.lastRouterServerTiming = response.ok ? response.serverTiming : null;
|
|
25424
25270
|
const result = response.ok ? parseRouterExecuteResult(response.body, request.request) : response;
|
|
25425
25271
|
emitGatewaySpan(this.config.onSpan, "gateway.yao_execute", operation, traceId, executeStartedAt, result.ok ? "success" : "failure");
|
|
@@ -25429,10 +25275,11 @@ var RouterAbEd25519YaoHttpRegistrationBackend = class {
|
|
|
25429
25275
|
return unavailableFailure(error);
|
|
25430
25276
|
}
|
|
25431
25277
|
}
|
|
25432
|
-
async activateRecovery(request, dispatchRoot, traceContext) {
|
|
25433
|
-
const promoted = await this.post(ROUTER_RECOVERY_PROMOTE_PATH, {
|
|
25278
|
+
async activateRecovery(request, dispatchRoot, ownershipGeneration, traceContext) {
|
|
25279
|
+
const promoted = await this.post(ROUTER_RECOVERY_PROMOTE_PATH, walletObjectIdentity(request.binding.lifecycle.account_id, ownershipGeneration, dispatchRoot.identity), {
|
|
25434
25280
|
...request,
|
|
25435
|
-
tenant_root: dispatchRoot
|
|
25281
|
+
tenant_root: dispatchRoot,
|
|
25282
|
+
ownership_generation: ownershipGeneration
|
|
25436
25283
|
}, (traceContext ?? createRouterAbTraceContextV1()).value);
|
|
25437
25284
|
if (!promoted.ok) return promoted;
|
|
25438
25285
|
if (!activeReceiptMatchesRecoveryActivation(parseActiveSigningWorkerReceipt(promoted.body, request.binding.session_id, request.public_receipt.transcript), request)) return internalFailure("recovery_promotion_mismatch", "Router promotion receipt does not match the verified recovery result");
|
|
@@ -25441,10 +25288,13 @@ var RouterAbEd25519YaoHttpRegistrationBackend = class {
|
|
|
25441
25288
|
body: request
|
|
25442
25289
|
};
|
|
25443
25290
|
}
|
|
25444
|
-
async post(path, body, traceId, retryAfterTransportFailure = "none", replay = false) {
|
|
25291
|
+
async post(path, identity, body, traceId, retryAfterTransportFailure = "none", replay = false) {
|
|
25445
25292
|
const init = {
|
|
25446
25293
|
method: "POST",
|
|
25447
|
-
headers:
|
|
25294
|
+
headers: {
|
|
25295
|
+
...this.headers(traceId),
|
|
25296
|
+
...walletObjectIdentityHeaders(identity)
|
|
25297
|
+
},
|
|
25448
25298
|
body: JSON.stringify(body)
|
|
25449
25299
|
};
|
|
25450
25300
|
return await this.request(this.config.routerUrl, path, replay ? requestInitWithReplayHeader(init) : init, retryAfterTransportFailure);
|
|
@@ -25484,7 +25334,6 @@ function parseRouterServerTiming(value) {
|
|
|
25484
25334
|
const metrics = value.split(",").map((metric) => metric.trim());
|
|
25485
25335
|
const allowedNames = new Set([
|
|
25486
25336
|
"yao_router_prepare_pair",
|
|
25487
|
-
"yao_router_verify_readiness",
|
|
25488
25337
|
"yao_router_role_execution",
|
|
25489
25338
|
"yao_router_signing_worker_delivery"
|
|
25490
25339
|
]);
|
|
@@ -25631,7 +25480,7 @@ var RouterAbEd25519YaoRegistrationRouteExtension = class {
|
|
|
25631
25480
|
body: parsed.value
|
|
25632
25481
|
});
|
|
25633
25482
|
if (!authorization.ok) return routeFailureResponse$1(authorization);
|
|
25634
|
-
const result = await this.service.execute(parsed.value, traceContext.value);
|
|
25483
|
+
const result = await this.service.execute(parsed.value, authorization.ownershipGeneration, traceContext.value);
|
|
25635
25484
|
if (!result.ok) return routeFailureResponse$1(result);
|
|
25636
25485
|
return json$1(result.value, { status: result.status });
|
|
25637
25486
|
}
|
|
@@ -25662,11 +25511,17 @@ function resolveTraceContext$1(request) {
|
|
|
25662
25511
|
message: parsed.message
|
|
25663
25512
|
};
|
|
25664
25513
|
}
|
|
25665
|
-
function recoveryAuthorizationBinding(
|
|
25666
|
-
|
|
25514
|
+
function recoveryAuthorizationBinding(admitted) {
|
|
25515
|
+
const authorization = admitted.authorization;
|
|
25516
|
+
if (authorization.kind === "wallet_recovery") return {
|
|
25517
|
+
kind: "wallet_recovery",
|
|
25518
|
+
walletId: authorization.walletId,
|
|
25519
|
+
ownershipGeneration: admitted.ownershipGeneration
|
|
25520
|
+
};
|
|
25667
25521
|
const session = authorization.kind === "wallet_session_v2" ? authorization.context.authorization.session : authorization.context.status.session;
|
|
25668
25522
|
return {
|
|
25669
25523
|
kind: "wallet_session_v2",
|
|
25524
|
+
ownershipGeneration: admitted.ownershipGeneration,
|
|
25670
25525
|
tenantId: session.tenantId,
|
|
25671
25526
|
principalId: session.principalId,
|
|
25672
25527
|
walletId: session.walletId,
|
|
@@ -25959,7 +25814,7 @@ var RouterAbEd25519YaoRecoveryRouteExtension = class {
|
|
|
25959
25814
|
body: parsed.value
|
|
25960
25815
|
});
|
|
25961
25816
|
if (!authorization.ok) return routeFailureResponse(authorization);
|
|
25962
|
-
const result = await this.service.admitRecovery(parsed.value, recoveryAuthorizationBinding(authorization
|
|
25817
|
+
const result = await this.service.admitRecovery(parsed.value, recoveryAuthorizationBinding(authorization), traceContext.value);
|
|
25963
25818
|
if (!result.ok) return routeFailureResponse(result);
|
|
25964
25819
|
return json$1(result.value, { status: result.status });
|
|
25965
25820
|
}
|
|
@@ -25976,13 +25831,16 @@ var RouterAbEd25519YaoRecoveryRouteExtension = class {
|
|
|
25976
25831
|
code: parsed.code,
|
|
25977
25832
|
message: parsed.message
|
|
25978
25833
|
}, { status: 400 });
|
|
25834
|
+
const ownership = this.service.recoveryOwnershipGeneration(parsed.value.binding);
|
|
25835
|
+
if (!ownership.ok) return routeFailureResponse(ownership);
|
|
25979
25836
|
const authorization = await this.authorization.authorize({
|
|
25980
25837
|
kind: "execute",
|
|
25838
|
+
ownershipGeneration: ownership.value,
|
|
25981
25839
|
request,
|
|
25982
25840
|
body: parsed.value
|
|
25983
25841
|
});
|
|
25984
25842
|
if (!authorization.ok) return routeFailureResponse(authorization);
|
|
25985
|
-
const result = await this.service.executeRecovery(parsed.value, recoveryAuthorizationBinding(authorization
|
|
25843
|
+
const result = await this.service.executeRecovery(parsed.value, recoveryAuthorizationBinding(authorization), traceContext.value);
|
|
25986
25844
|
if (!result.ok) return routeFailureResponse(result);
|
|
25987
25845
|
return json$1(result.value, { status: result.status });
|
|
25988
25846
|
}
|
|
@@ -25999,13 +25857,16 @@ var RouterAbEd25519YaoRecoveryRouteExtension = class {
|
|
|
25999
25857
|
code: parsed.code,
|
|
26000
25858
|
message: parsed.message
|
|
26001
25859
|
}, { status: 400 });
|
|
25860
|
+
const ownership = this.service.recoveryOwnershipGeneration(parsed.value.binding);
|
|
25861
|
+
if (!ownership.ok) return routeFailureResponse(ownership);
|
|
26002
25862
|
const authorization = await this.authorization.authorize({
|
|
26003
25863
|
kind: "activate",
|
|
25864
|
+
ownershipGeneration: ownership.value,
|
|
26004
25865
|
request,
|
|
26005
25866
|
body: parsed.value
|
|
26006
25867
|
});
|
|
26007
25868
|
if (!authorization.ok) return routeFailureResponse(authorization);
|
|
26008
|
-
const result = await this.service.activateRecovery(parsed.value, recoveryAuthorizationBinding(authorization
|
|
25869
|
+
const result = await this.service.activateRecovery(parsed.value, recoveryAuthorizationBinding(authorization), traceContext.value);
|
|
26009
25870
|
if (!result.ok) return routeFailureResponse(result);
|
|
26010
25871
|
return json$1(result.value, { status: result.status });
|
|
26011
25872
|
}
|
|
@@ -26226,7 +26087,7 @@ var RouterAbEd25519YaoExportRouteExtension = class {
|
|
|
26226
26087
|
code: authorized.code,
|
|
26227
26088
|
message: authorized.message
|
|
26228
26089
|
}, { status: authorized.status });
|
|
26229
|
-
const result = await this.service.admitExport(parsed.protocol, authorized.authorizationIdentity, authorized.admission, authorized.factorRelease ?? null, traceContext.value);
|
|
26090
|
+
const result = await this.service.admitExport(parsed.protocol, authorized.authorizationIdentity, authorized.ownershipGeneration, authorized.admission, authorized.factorRelease ?? null, traceContext.value);
|
|
26230
26091
|
return result.ok ? json$1({
|
|
26231
26092
|
protocol: result.value,
|
|
26232
26093
|
...authorized.factorRelease ? { factorRelease: authorized.factorRelease } : {}
|
|
@@ -26341,17 +26202,26 @@ var RouterAbEd25519YaoProductRegistrationRuntime = class {
|
|
|
26341
26202
|
async bindVerifiedIntent(input) {
|
|
26342
26203
|
return await this.input.authorization.bindVerifiedIntent(input);
|
|
26343
26204
|
}
|
|
26205
|
+
/** The registration service of this runtime resolves the tenant root when it executes. */
|
|
26206
|
+
startRegistrationDispatchRoot() {
|
|
26207
|
+
return null;
|
|
26208
|
+
}
|
|
26344
26209
|
async bindAndAdmitVerifiedRegistration(input) {
|
|
26345
|
-
const bound = await this.input.authorization.
|
|
26210
|
+
const bound = await this.input.authorization.bindAndAuthorizeAdmission(input);
|
|
26346
26211
|
if (!bound.ok) return bound;
|
|
26347
|
-
|
|
26212
|
+
const admitted = await this.input.registrationService.admit(bound.admissionRequest);
|
|
26213
|
+
if (!admitted.ok) return admitted;
|
|
26214
|
+
return {
|
|
26215
|
+
ok: true,
|
|
26216
|
+
status: 200,
|
|
26217
|
+
admissionRequest: bound.admissionRequest,
|
|
26218
|
+
value: admitted.value,
|
|
26219
|
+
companionWrite: "not_committed"
|
|
26220
|
+
};
|
|
26348
26221
|
}
|
|
26349
26222
|
async consumeActivated(request) {
|
|
26350
26223
|
return await this.input.registrationService.consumeActivated(request);
|
|
26351
26224
|
}
|
|
26352
|
-
async installRegistrationFinalizeCapability(input) {
|
|
26353
|
-
return await this.input.capabilityInstaller.installRegistrationFinalizeCapability(input);
|
|
26354
|
-
}
|
|
26355
26225
|
async installPersistedActiveCapability(input) {
|
|
26356
26226
|
return await this.input.capabilityInstaller.installPersistedActiveCapability(input);
|
|
26357
26227
|
}
|