@seams/wallet-server 0.8.0 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (369) hide show
  1. package/THIRD_PARTY_NOTICES.md +7 -1
  2. package/artifact-manifest.json +196 -41
  3. package/cloudflare-router-ab/build/deriver-a/build-stamp.json +1 -1
  4. package/cloudflare-router-ab/build/deriver-a/index.js +2 -2
  5. package/cloudflare-router-ab/build/deriver-a/index_bg.wasm +0 -0
  6. package/cloudflare-router-ab/build/deriver-b/build-stamp.json +1 -1
  7. package/cloudflare-router-ab/build/deriver-b/index.js +2 -2
  8. package/cloudflare-router-ab/build/deriver-b/index_bg.wasm +0 -0
  9. package/cloudflare-router-ab/build/local-tools/darwin-arm64/router_ab_local_init +0 -0
  10. package/cloudflare-router-ab/build/local-tools/darwin-x64/router_ab_local_init +0 -0
  11. package/cloudflare-router-ab/build/local-tools/linux-x64/router_ab_local_init +0 -0
  12. package/cloudflare-router-ab/build/router/build-stamp.json +1 -1
  13. package/cloudflare-router-ab/build/router/index.js +2 -2
  14. package/cloudflare-router-ab/build/router/index_bg.wasm +0 -0
  15. package/cloudflare-router-ab/build/signing-worker/build-stamp.json +1 -1
  16. package/cloudflare-router-ab/build/signing-worker/index.js +2 -2
  17. package/cloudflare-router-ab/build/signing-worker/index_bg.wasm +0 -0
  18. package/cloudflare-router-ab/build/tenant-root-control-plane/build-stamp.json +1 -1
  19. package/cloudflare-router-ab/build/tenant-root-control-plane/index.js +2 -2
  20. package/cloudflare-router-ab/build/tenant-root-control-plane/index_bg.wasm +0 -0
  21. package/cloudflare-router-ab/migrations/deriver-a/0019_wallet_object_addresses.sql +10 -0
  22. package/cloudflare-router-ab/migrations/deriver-b/0019_wallet_object_addresses.sql +10 -0
  23. package/cloudflare-router-ab/scripts/prepare-local-runtime-config.mjs +3 -117
  24. package/cloudflare-router-ab/wrangler.deriver-a.toml +0 -8
  25. package/cloudflare-router-ab/wrangler.deriver-b.toml +24 -8
  26. package/cloudflare-router-ab/wrangler.router.toml +0 -2
  27. package/cloudflare-router-ab/wrangler.signing-worker.toml +29 -0
  28. package/dist/esm/authorization/domain.js +3 -2
  29. package/dist/esm/authorization/ed25519WalletSessionAdmission.js +0 -0
  30. package/dist/esm/authorization/service.js +64 -36
  31. package/dist/esm/cloud-host.js +24 -19
  32. package/dist/esm/core/EmailOtpRecords.js +29 -6
  33. package/dist/esm/core/ThresholdService/routerAb/ecdsaDerivationPoolFillHandlers.js +2 -0
  34. package/dist/esm/core/ThresholdService/routerAb/ecdsaDerivationPresignBridge.js +10 -0
  35. package/dist/esm/core/ThresholdService/routerAb/internalServiceHttp.js +1 -0
  36. package/dist/esm/core/ThresholdService/validation.js +2 -2
  37. package/dist/esm/core/authService/nearPrivateKeySigning.js +1 -1
  38. package/dist/esm/core/authService/webauthn.js +1 -1
  39. package/dist/esm/core/d1Ed25519SignerRead.js +55 -0
  40. package/dist/esm/core/d1WalletStore.js +14 -11
  41. package/dist/esm/core/deviceLinking/linkedDeviceEmailOtpGrant.js +2 -2
  42. package/dist/esm/core/deviceLinking/linkedDeviceManagement.js +1 -1
  43. package/dist/esm/core/deviceLinking/linkedDeviceSessionRecord.js +2 -2
  44. package/dist/esm/core/emailOtpD1Statements.js +1 -0
  45. package/dist/esm/core/nearRelayerAccountProvisioning.js +1 -1
  46. package/dist/esm/core/routerAbSigning/RouterAbEcdsaPresignRuntime.js +4 -0
  47. package/dist/esm/core/signingLanes/WalletExecutionLaneProjection.js +1 -1
  48. package/dist/esm/core/signingMaterial/ordinaryInactiveSignerMaterialReservation.js +1 -0
  49. package/dist/esm/hosted-wallet-gateway.js +93 -10
  50. package/dist/esm/localHostedWalletGatewayHandler.js +12 -9
  51. package/dist/esm/localIntendedYaoSigningFault.js +2 -30
  52. package/dist/esm/localRegistrationSetupAuthority.js +8 -1
  53. package/dist/esm/router/auth/commonRouterUtils.js +17 -10
  54. package/dist/esm/router/auth/routerApiCredentialAuth.js +26 -7
  55. package/dist/esm/router/auth/walletRegistrationContext.js +49 -0
  56. package/dist/esm/router/auth/webAuthnCredentialCodecs.js +1 -1
  57. package/dist/esm/router/cloudflare/d1/auth/d1AuthorizationAssembly.js +4 -3
  58. package/dist/esm/router/cloudflare/d1/auth/d1AuthorizedOperationRouteService.js +2 -0
  59. package/dist/esm/router/cloudflare/d1/auth/d1EmailOtpRouteService.js +25 -0
  60. package/dist/esm/router/cloudflare/d1/auth/d1RouterApiAuthConfig.js +14 -6
  61. package/dist/esm/router/cloudflare/d1/auth/d1RouterApiAuthService.js +44 -40
  62. package/dist/esm/router/cloudflare/d1/auth/walletSessionCredentialReaders.js +17 -1
  63. package/dist/esm/router/cloudflare/d1/authorization/authorizedOperationStatements.js +35 -5
  64. package/dist/esm/router/cloudflare/d1/authorization/d1AuthorizationStore.js +258 -99
  65. package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceAuthorityInstallService.js +31 -4
  66. package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceOwnerAuthorizationProvider.js +1 -1
  67. package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceRequestProofNonceStore.js +1 -1
  68. package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceSessionRecords.js +1 -1
  69. package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceTargetCredentialProvider.js +1 -1
  70. package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceTargetPlanner.js +1 -1
  71. package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceVerifiedLinkBuilder.js +1 -1
  72. package/dist/esm/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoLifecycleDecisionStore.js +11 -2
  73. package/dist/esm/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoProductRegistrationPartitionedStateStore.js +100 -10
  74. package/dist/esm/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoStateWriteFence.js +92 -0
  75. package/dist/esm/router/cloudflare/d1/ed25519Yao/d1WalletCeremonyActivity.js +77 -0
  76. package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeIssuer.js +14 -8
  77. package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeStore.js +14 -8
  78. package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeVerifier.js +3 -1
  79. package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRateLimitStore.js +58 -38
  80. package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRecords.js +27 -20
  81. package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRecoveryService.js +1 -0
  82. package/dist/esm/router/cloudflare/d1/emailOtp/d1GoogleEmailOtpSessionResolver.js +1 -0
  83. package/dist/esm/router/cloudflare/d1/oidc/d1OidcBoundary.js +1 -1
  84. package/dist/esm/router/cloudflare/d1/passkeyCustody/d1WalletCustodyCommitStore.js +18 -7
  85. package/dist/esm/router/cloudflare/d1/registration/d1RegistrationCeremonyRecordStore.js +75 -14
  86. package/dist/esm/router/cloudflare/d1/registration/d1RegistrationCeremonyRecords.js +1 -1
  87. package/dist/esm/router/cloudflare/d1/registration/d1RegistrationCeremonyStore.js +49 -29
  88. package/dist/esm/router/cloudflare/d1/registration/d1RegistrationSessionTransaction.js +28 -0
  89. package/dist/esm/router/cloudflare/d1/registration/d1RegistrationSetupSupport.js +11 -1
  90. package/dist/esm/router/cloudflare/d1/registration/d1WalletExecutionAuthority.js +168 -0
  91. package/dist/esm/router/cloudflare/d1/registration/d1WalletOperationStore.js +53 -0
  92. package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationCommitStore.js +83 -42
  93. package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationInitialSession.js +33 -0
  94. package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationPreparation.js +16 -0
  95. package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationRead.js +58 -0
  96. package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationService.js +439 -500
  97. package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationSetup.js +1 -1
  98. package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationSetupExecution.js +104 -90
  99. package/dist/esm/router/cloudflare/d1/registration/walletRegistrationEstablishedSessionIssuer.js +78 -44
  100. package/dist/esm/router/cloudflare/d1/registration/walletRegistrationSessionCommitReceipt.js +11 -35
  101. package/dist/esm/router/cloudflare/d1/signingAdmission/d1RouterAbNormalSigningAdmissionStore.js +98 -39
  102. package/dist/esm/router/cloudflare/d1/versionedJson/d1VersionedJsonRecordStore.js +12 -9
  103. package/dist/esm/router/cloudflare/d1/wallet/authorizationSnapshotLayout.js +168 -0
  104. package/dist/esm/router/cloudflare/d1/wallet/d1WalletAddSignerFinalizeRecord.js +1 -1
  105. package/dist/esm/router/cloudflare/d1/wallet/d1WalletAddSignerService.js +15 -6
  106. package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthMethodService.js +3 -40
  107. package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorityStore.js +54 -1
  108. package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorizationCleanup.js +157 -0
  109. package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorizationFreeze.js +56 -0
  110. package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorizationHistory.js +238 -0
  111. package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorizationIntake.js +287 -0
  112. package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorizationSnapshot.js +295 -0
  113. package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationApprovals.js +140 -0
  114. package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationChallenges.js +170 -0
  115. package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationEmailOtp.js +60 -0
  116. package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationOwner.js +33 -0
  117. package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationOwnerRequest.js +74 -0
  118. package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationPasskey.js +77 -0
  119. package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationReadAccess.js +37 -0
  120. package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationSessions.js +97 -0
  121. package/dist/esm/router/cloudflare/d1/wallet/d1WalletRelocationWriteBlock.js +133 -0
  122. package/dist/esm/router/cloudflare/d1/walletObjectAddresses.js +47 -0
  123. package/dist/esm/router/cloudflare/d1/webauthn/d1WebAuthnAuthService.js +1 -1
  124. package/dist/esm/router/cloudflare/runtime/routerAbServiceBindings.js +32 -1
  125. package/dist/esm/router/cloudflare/runtime/staticWalletConsoleBinding.js +20 -8
  126. package/dist/esm/router/cloudflare/runtime/walletAuthorizationRelocationRoutes.js +488 -0
  127. package/dist/esm/router/cloudflare/runtime/walletConsoleOps.js +1 -1
  128. package/dist/esm/router/cloudflare/runtime/walletConsoleOpsClient.js +26 -6
  129. package/dist/esm/router/cloudflare/runtime/walletControlOps.js +3 -0
  130. package/dist/esm/router/cloudflare/runtime/walletGateway.js +1 -1
  131. package/dist/esm/router/cloudflare/runtime/walletObjectAddresses.js +105 -0
  132. package/dist/esm/router/cloudflare/runtime/walletPlacementRoutes.js +339 -0
  133. package/dist/esm/router/cloudflare/runtime/walletRelocationDeriver.js +244 -0
  134. package/dist/esm/router/cloudflare/runtime/walletRelocationEcdsa.js +212 -0
  135. package/dist/esm/router/cloudflare/runtime/walletRelocationEd25519.js +172 -0
  136. package/dist/esm/router/cloudflare/runtime/walletRelocationOps.js +183 -0
  137. package/dist/esm/router/cloudflare/runtime/walletRelocationPresign.js +185 -0
  138. package/dist/esm/router/cloudflare/runtime/walletRelocationSource.js +221 -0
  139. package/dist/esm/router/cloudflare/signingLanes/cloudflareOrdinaryInactiveSignerMaterialReservation.js +30 -8
  140. package/dist/esm/router/cloudflare-adaptor.js +8 -8
  141. package/dist/esm/router/cloudflare.js +34115 -32240
  142. package/dist/esm/router/domains/ecdsa/routerAbEcdsaStrictRegistration.js +35 -9
  143. package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoCapabilityCommit.js +42 -0
  144. package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistration.js +32 -6
  145. package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationPartitionedStateStore.js +61 -1
  146. package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationPersistence.js +70 -3
  147. package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationRequestScopedRuntime.js +59 -87
  148. package/dist/esm/router/domains/ed25519Yao/export/routerAbEd25519YaoExport.js +52 -22
  149. package/dist/esm/router/domains/ed25519Yao/export/routerAbEd25519YaoExportRequestScopedCloudflare.js +10 -7
  150. package/dist/esm/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecovery.js +108 -78
  151. package/dist/esm/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecoveryRequestScopedCloudflare.js +19 -5
  152. package/dist/esm/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecoveryWalletSessionAuthorization.js +71 -22
  153. package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoHttpRegistrationBackend.js +37 -25
  154. package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistration.js +3 -3
  155. package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationExecutionRecord.js +2 -1
  156. package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationIntentAuthorization.js +24 -3
  157. package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationRequestScopedCloudflare.js +4 -3
  158. package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationSideEffectBoundary.js +20 -7
  159. package/dist/esm/router/domains/ed25519Yao/routerAbEd25519YaoGatewayEnvelope.js +7 -1
  160. package/dist/esm/router/domains/emailOtp/emailOtpRouteHandlers.js +2 -2
  161. package/dist/esm/router/domains/passkeyCustody/passkeyCustodyEnvelopeRetrieval.js +1 -1
  162. package/dist/esm/router/domains/passkeyCustody/registrationCustodyOutcome.js +34 -18
  163. package/dist/esm/router/domains/passkeyCustody/walletCustodyRegistrationAdmission.js +2 -2
  164. package/dist/esm/router/domains/passkeyCustody/walletCustodyRegistrationCommit.js +16 -6
  165. package/dist/esm/router/domains/signingOperations/authorizedOperationWire.js +73 -0
  166. package/dist/esm/router/domains/signingOperations/ecdsaSigningResponse.js +31 -0
  167. package/dist/esm/router/domains/signingOperations/ed25519AuthorizedOperationReceipt.js +1 -1
  168. package/dist/esm/router/domains/signingOperations/routerAbEcdsaDerivationNormalSigningRoute.js +2 -1
  169. package/dist/esm/router/domains/signingOperations/routerAbEd25519NormalSigningRoute.js +31 -121
  170. package/dist/esm/router/domains/signingOperations/routerAbNormalSigningAdmission.js +2 -93
  171. package/dist/esm/router/domains/signingOperations/routerAbPrivateSigningWorker.js +1 -1
  172. package/dist/esm/router/domains/signingOperations/signingPrepareSession.js +33 -0
  173. package/dist/esm/router/domains/walletRegistration/registrationSessionSeal.js +121 -0
  174. package/dist/esm/router/domains/walletRegistration/walletRegistrationReservation.js +4 -4
  175. package/dist/esm/router/domains/walletRegistration/walletRegistrationRoutes.js +46 -157
  176. package/dist/esm/router/domains/walletRegistration/walletRegistrationSetupPayload.js +1 -1
  177. package/dist/esm/router/express.js +764 -894
  178. package/dist/esm/router/framework/http.js +2 -1
  179. package/dist/esm/router/transport/fetch/createFetchRouter.js +2 -2
  180. package/dist/esm/router/transport/fetch/routes/auth.js +1 -1
  181. package/dist/esm/router/transport/fetch/routes/deviceLinking.js +3 -3
  182. package/dist/esm/router/transport/fetch/routes/deviceLinkingOwnerAuthorization.js +2 -2
  183. package/dist/esm/router/transport/fetch/routes/ed25519AuthorizedOperationRevalidation.js +65 -0
  184. package/dist/esm/router/transport/fetch/routes/normalSigningRouterProxy.js +13 -3
  185. package/dist/esm/router/transport/fetch/routes/passkeyCustody.js +3 -3
  186. package/dist/esm/router/transport/fetch/routes/sessions.js +3 -2
  187. package/dist/esm/router/transport/fetch/routes/thresholdEcdsa.js +67 -130
  188. package/dist/esm/router/transport/fetch/routes/thresholdEd25519.js +76 -212
  189. package/dist/esm/router/transport/fetch/routes/walletExecutionLanePreflight.js +18 -41
  190. package/dist/esm/router/transport/fetch/routes/walletRegistration.js +6 -5
  191. package/dist/esm/router/transport/fetch/routes/webauthnAuthenticators.js +1 -1
  192. package/dist/esm/shared-ts/src/authorization/index.js +1 -1
  193. package/dist/esm/shared-ts/src/authorization/walletAuthority.js +2 -2
  194. package/dist/esm/shared-ts/src/device-linking/activeWalletSession.js +12 -2
  195. package/dist/esm/shared-ts/src/device-linking/digests.js +1 -1
  196. package/dist/esm/shared-ts/src/device-linking/ed25519ExportRoot.js +1 -1
  197. package/dist/esm/shared-ts/src/device-linking/index.js +1 -1
  198. package/dist/esm/shared-ts/src/device-linking/parsers.js +1 -1
  199. package/dist/esm/shared-ts/src/device-linking/sourceContribution.js +1 -1
  200. package/dist/esm/shared-ts/src/device-linking/wireFields.js +1 -1
  201. package/dist/esm/shared-ts/src/near/nearClient.js +1 -1
  202. package/dist/esm/shared-ts/src/signing-lanes/ownerContinuity.js +2 -2
  203. package/dist/esm/shared-ts/src/utils/ecdsaServerTiming.js +6 -1
  204. package/dist/esm/shared-ts/src/utils/emailOtpDomain.js +4 -2
  205. package/dist/esm/shared-ts/src/utils/routerAbEcdsaDerivation.js +1 -1
  206. package/dist/esm/shared-ts/src/utils/routerAbPublicKeyset.js +0 -27
  207. package/dist/esm/shared-ts/src/wallet-recovery/walletRecoveryEcdsaPossession.js +1 -1
  208. package/dist/esm/threshold/session/signingSessionSeal/options.js +1 -1
  209. package/dist/esm/wasm/near_signer/pkg/wasm_signer_worker_bg.wasm +0 -0
  210. package/dist/types/shared-ts/src/device-linking/activeWalletSession.d.ts +2 -1
  211. package/dist/types/shared-ts/src/device-linking/contracts.d.ts +10 -0
  212. package/dist/types/shared-ts/src/threshold/ed25519OperationFingerprint.d.ts +2 -1
  213. package/dist/types/shared-ts/src/utils/emailOtpDomain.d.ts +3 -1
  214. package/dist/types/shared-ts/src/utils/routerAbPublicKeyset.d.ts +0 -9
  215. package/dist/types/shared-ts/src/utils/walletManagementProtocol.d.ts +1 -1
  216. package/dist/types/wallet-server/src/authorization/domain.d.ts +17 -1
  217. package/dist/types/wallet-server/src/authorization/ecdsaWalletSessionAdmission.d.ts +1 -0
  218. package/dist/types/wallet-server/src/authorization/ed25519WalletSessionAdmission.d.ts +35 -0
  219. package/dist/types/wallet-server/src/authorization/ed25519WalletSessionAdmission.typecheck.d.ts +2 -0
  220. package/dist/types/wallet-server/src/authorization/service.d.ts +43 -5
  221. package/dist/types/wallet-server/src/authorization/sessionRouting.d.ts +2 -0
  222. package/dist/types/wallet-server/src/cloud-host.d.ts +7 -3
  223. package/dist/types/wallet-server/src/core/EmailOtpRecords.d.ts +2 -1
  224. package/dist/types/wallet-server/src/core/EmailOtpStores.d.ts +19 -5
  225. package/dist/types/wallet-server/src/core/ThresholdService/routerAb/ecdsaDerivationPoolFillHandlers.d.ts +1 -0
  226. package/dist/types/wallet-server/src/core/ThresholdService/routerAb/ecdsaDerivationPresignBridge.d.ts +6 -0
  227. package/dist/types/wallet-server/src/core/ThresholdService/routerAb/internalServiceHttp.d.ts +1 -0
  228. package/dist/types/wallet-server/src/core/d1Ed25519SignerRead.d.ts +17 -0
  229. package/dist/types/wallet-server/src/core/d1WalletStore.d.ts +6 -0
  230. package/dist/types/wallet-server/src/core/emailOtpD1Statements.d.ts +1 -0
  231. package/dist/types/wallet-server/src/core/routerAbSigning/RouterAbEcdsaPresignRuntime.d.ts +5 -1
  232. package/dist/types/wallet-server/src/core/signingMaterial/ordinaryInactiveSignerMaterialReservation.d.ts +1 -0
  233. package/dist/types/wallet-server/src/core/threeRouteRegistrationContracts.d.ts +14 -48
  234. package/dist/types/wallet-server/src/hosted-wallet-gateway.d.ts +4 -3
  235. package/dist/types/wallet-server/src/localIntendedYaoSigningFault.d.ts +1 -16
  236. package/dist/types/wallet-server/src/localRegistrationSetupAuthority.d.ts +1 -1
  237. package/dist/types/wallet-server/src/router/auth/commonRouterUtils.d.ts +7 -1
  238. package/dist/types/wallet-server/src/router/auth/routerApiCredentialAuth.d.ts +11 -3
  239. package/dist/types/wallet-server/src/router/auth/walletRegistrationContext.d.ts +8 -0
  240. package/dist/types/wallet-server/src/router/cloudflare/d1/auth/d1AuthorizationAssembly.d.ts +1 -1
  241. package/dist/types/wallet-server/src/router/cloudflare/d1/auth/d1EmailOtpRouteService.d.ts +16 -0
  242. package/dist/types/wallet-server/src/router/cloudflare/d1/auth/d1RouterApiAuthConfig.d.ts +7 -4
  243. package/dist/types/wallet-server/src/router/cloudflare/d1/auth/d1RouterApiAuthService.d.ts +4 -1
  244. package/dist/types/wallet-server/src/router/cloudflare/d1/auth/walletSessionCredentialReaders.d.ts +7 -1
  245. package/dist/types/wallet-server/src/router/cloudflare/d1/authorization/d1AuthorizationStore.d.ts +32 -1
  246. package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceAuthorityInstallService.d.ts +2 -0
  247. package/dist/types/wallet-server/src/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoLifecycleDecisionStore.d.ts +3 -1
  248. package/dist/types/wallet-server/src/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoProductRegistrationPartitionedStateStore.d.ts +1 -0
  249. package/dist/types/wallet-server/src/router/cloudflare/d1/ed25519Yao/d1Ed25519YaoStateWriteFence.d.ts +8 -0
  250. package/dist/types/wallet-server/src/router/cloudflare/d1/ed25519Yao/d1WalletCeremonyActivity.d.ts +15 -0
  251. package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeIssuer.d.ts +6 -1
  252. package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeStore.d.ts +1 -0
  253. package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeVerifier.d.ts +4 -1
  254. package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpCounters.typecheck.d.ts +2 -0
  255. package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpRateLimitStore.d.ts +6 -29
  256. package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpRecords.d.ts +21 -7
  257. package/dist/types/wallet-server/src/router/cloudflare/d1/passkeyCustody/d1WalletCustodyCommitStore.d.ts +17 -1
  258. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationCeremonyRecordStore.d.ts +32 -7
  259. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationCeremonyStore.d.ts +16 -7
  260. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationSessionTransaction.d.ts +13 -0
  261. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationSetupSupport.d.ts +7 -0
  262. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletExecutionAuthority.d.ts +41 -0
  263. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletOperationStore.d.ts +28 -0
  264. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationCommitStore.d.ts +6 -9
  265. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationInitialSession.d.ts +17 -0
  266. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationPreparation.d.ts +12 -0
  267. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationRead.d.ts +43 -0
  268. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationService.d.ts +24 -45
  269. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationSetupExecution.d.ts +9 -4
  270. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/walletRegistrationEstablishedSessionIssuer.d.ts +42 -14
  271. package/dist/types/wallet-server/src/router/cloudflare/d1/registration/walletRegistrationSessionCommitReceipt.d.ts +5 -4
  272. package/dist/types/wallet-server/src/router/cloudflare/d1/signingAdmission/d1RouterAbNormalSigningAdmissionStore.d.ts +24 -1
  273. package/dist/types/wallet-server/src/router/cloudflare/d1/versionedJson/d1VersionedJsonRecordStore.d.ts +10 -4
  274. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/authorizationSnapshotLayout.d.ts +21 -0
  275. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAddSignerService.d.ts +3 -0
  276. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthMethodService.d.ts +3 -7
  277. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorityStore.d.ts +8 -0
  278. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorizationCleanup.d.ts +20 -0
  279. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorizationFreeze.d.ts +12 -0
  280. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorizationHistory.d.ts +20 -0
  281. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorizationIntake.d.ts +29 -0
  282. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthorizationSnapshot.d.ts +31 -0
  283. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationApprovals.d.ts +49 -0
  284. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationChallenges.d.ts +47 -0
  285. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationEmailOtp.d.ts +25 -0
  286. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationOwner.d.ts +88 -0
  287. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationOwnerRequest.d.ts +37 -0
  288. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationPasskey.d.ts +12 -0
  289. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationReadAccess.d.ts +18 -0
  290. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationSessions.d.ts +23 -0
  291. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationWriteBlock.d.ts +16 -0
  292. package/dist/types/wallet-server/src/router/cloudflare/d1/walletObjectAddresses.d.ts +14 -0
  293. package/dist/types/wallet-server/src/router/cloudflare/runtime/routerAbServiceBindings.d.ts +13 -0
  294. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletAuthorizationRelocationRoutes.d.ts +21 -0
  295. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletConsoleOps.d.ts +1 -1
  296. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletConsoleOpsClient.d.ts +3 -3
  297. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletControlOps.d.ts +2 -1
  298. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletGateway.d.ts +3 -1
  299. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletObjectAddresses.d.ts +45 -0
  300. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletPlacementRoutes.d.ts +30 -0
  301. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRelocationDeriver.d.ts +11 -0
  302. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRelocationEcdsa.d.ts +7 -0
  303. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRelocationEd25519.d.ts +7 -0
  304. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRelocationOps.d.ts +11 -0
  305. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRelocationPresign.d.ts +7 -0
  306. package/dist/types/wallet-server/src/router/cloudflare/runtime/walletRelocationSource.d.ts +26 -0
  307. package/dist/types/wallet-server/src/router/cloudflare/signingLanes/cloudflareOrdinaryInactiveSignerMaterialReservation.d.ts +5 -0
  308. package/dist/types/wallet-server/src/router/domains/ecdsa/routerAbEcdsaStrictRegistration.d.ts +3 -0
  309. package/dist/types/wallet-server/src/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoCapabilityCommit.d.ts +7 -0
  310. package/dist/types/wallet-server/src/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistration.d.ts +41 -7
  311. package/dist/types/wallet-server/src/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationPartitionedStateStore.d.ts +33 -2
  312. package/dist/types/wallet-server/src/router/domains/ed25519Yao/export/routerAbEd25519YaoExport.d.ts +12 -6
  313. package/dist/types/wallet-server/src/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecovery.d.ts +17 -9
  314. package/dist/types/wallet-server/src/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecoveryWalletSessionAuthorization.d.ts +2 -0
  315. package/dist/types/wallet-server/src/router/domains/ed25519Yao/registration/routerAbEd25519YaoHttpRegistrationBackend.d.ts +13 -14
  316. package/dist/types/wallet-server/src/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistration.d.ts +7 -3
  317. package/dist/types/wallet-server/src/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationExecutionRecord.d.ts +1 -0
  318. package/dist/types/wallet-server/src/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationIntentAuthorization.d.ts +6 -1
  319. package/dist/types/wallet-server/src/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationSideEffectBoundary.d.ts +11 -0
  320. package/dist/types/wallet-server/src/router/domains/ed25519Yao/routerAbEd25519YaoGatewayEnvelope.d.ts +12 -3
  321. package/dist/types/wallet-server/src/router/domains/passkeyCustody/registrationCustodyOutcome.d.ts +10 -6
  322. package/dist/types/wallet-server/src/router/domains/passkeyCustody/walletCustodyRegistrationAdmission.d.ts +10 -3
  323. package/dist/types/wallet-server/src/router/domains/passkeyCustody/walletCustodyRegistrationCommit.d.ts +12 -5
  324. package/dist/types/wallet-server/src/router/domains/signingOperations/authorizedOperationWire.d.ts +97 -0
  325. package/dist/types/wallet-server/src/router/domains/signingOperations/ecdsaSigningResponse.d.ts +13 -0
  326. package/dist/types/wallet-server/src/router/domains/signingOperations/routerAbNormalSigningAdmission.d.ts +9 -206
  327. package/dist/types/wallet-server/src/router/domains/signingOperations/signingPrepareSession.d.ts +23 -0
  328. package/dist/types/wallet-server/src/router/domains/walletRegistration/registrationSessionSeal.d.ts +36 -0
  329. package/dist/types/wallet-server/src/router/domains/walletRegistration/walletRegistrationInputs.d.ts +7 -7
  330. package/dist/types/wallet-server/src/router/domains/walletRegistration/walletRegistrationReservation.d.ts +80 -6
  331. package/dist/types/wallet-server/src/router/domains/walletRegistration/walletRegistrationRoutes.d.ts +15 -5
  332. package/dist/types/wallet-server/src/router/framework/apiCredentialPorts.d.ts +24 -0
  333. package/dist/types/wallet-server/src/router/framework/authServicePort.d.ts +21 -7
  334. package/dist/types/wallet-server/src/router/framework/routerApi.d.ts +3 -12
  335. package/dist/types/wallet-server/src/router/transport/fetch/routes/ed25519AuthorizedOperationRevalidation.d.ts +37 -0
  336. package/dist/types/wallet-server/src/router/transport/fetch/routes/thresholdEcdsa.d.ts +1 -17
  337. package/dist/types/wallet-server/src/storage/tenantRoute.d.ts +1 -1
  338. package/migrations/d1-signer/0049_wallet_relocation_challenges.sql +16 -0
  339. package/migrations/d1-signer/0050_wallet_relocation_approvals.sql +14 -0
  340. package/migrations/d1-signer/0051_wallet_relocation_email_otp.sql +92 -0
  341. package/migrations/d1-signer/0052_wallet_relocation_session_fences.sql +91 -0
  342. package/migrations/d1-signer/0053_wallet_hosted_history_import.sql +164 -0
  343. package/migrations/d1-signer/0054_wallet_authorization_freeze.sql +318 -0
  344. package/migrations/d1-signer/0055_wallet_authorization_snapshot.sql +120 -0
  345. package/migrations/d1-signer/0056_wallet_authorization_history_import.sql +424 -0
  346. package/migrations/d1-signer/0057_wallet_authorization_intake.sql +44 -0
  347. package/migrations/d1-signer/0058_wallet_ceremony_activity.sql +59 -0
  348. package/migrations/d1-signer/0059_wallet_authorization_activation.sql +45 -0
  349. package/migrations/d1-signer/0060_wallet_authorization_cleanup.sql +153 -0
  350. package/migrations/d1-signer/0061_wallet_session_operation_settlement.sql +28 -0
  351. package/migrations/d1-signer/0062_wallet_step_up_operation_settlement.sql +204 -0
  352. package/migrations/d1-signer/0063_wallet_operation_history_transfer.sql +466 -0
  353. package/migrations/d1-signer/0064_wallet_execution_generations.sql +93 -0
  354. package/migrations/d1-signer/0065_wallet_operation_execution_generation.sql +37 -0
  355. package/migrations/d1-signer/0066_regional_deployment_admission.sql +59 -0
  356. package/migrations/d1-signer/0067_registration_completion_decision.sql +12 -0
  357. package/migrations/d1-signer/0068_registration_cancellation_write_fence.sql +24 -0
  358. package/migrations/d1-signer/0069_cancelled_registration_session_fence.sql +11 -0
  359. package/migrations/d1-signer/0070_wallet_passkey_relocation.sql +369 -0
  360. package/migrations/d1-signer/0071_regional_wallet_otp_counters.sql +98 -0
  361. package/migrations/d1-signer/0072_linked_device_relocation_history.sql +899 -0
  362. package/migrations/d1-signer/0073_wallet_recovery_relocation.sql +86 -0
  363. package/migrations/d1-signer/0074_email_otp_relocation.sql +158 -0
  364. package/migrations/d1-signer/0075_wallet_authorization_return.sql +107 -0
  365. package/migrations/d1-signer/0076_wallet_relocation_write_block.sql +406 -0
  366. package/migrations/d1-signer/0077_wallet_object_addresses.sql +24 -0
  367. package/package.json +1 -1
  368. package/src/README.md +23 -1
  369. 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
- if (headers.has("Server-Timing")) headers.set("Access-Control-Expose-Headers", "Server-Timing");
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
- async function resolvePublishableKeyApiCredentialAuth(input) {
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
- const authResult = await input.publishableKeyAuth.authenticate({
5524
- secret: publishableKey,
5525
- origin,
5526
- environmentId
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: authResult.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
- resolution = await resolveWalletSessionOperationCredentialAdmission({
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 publishableKeyAuth = input.services.publishableKeyAuth;
9208
- if (!publishableKeyAuth) return routeError(500, "route_auth_not_configured", "wallet registration setup requires publishable key auth on this server");
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: async () => await resolvePublishableKeyApiCredentialAuth({
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
- if (resolved.context.principal.kind !== "api_credentials") return routeError(500, "internal", "wallet registration setup requires API credentials");
9233
- const principal = resolved.context.principal.principal;
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
- environmentId: principal.environmentId,
9238
- projectId: principal.projectId,
9239
- envId: principal.envId
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
- ...runtimePolicyScope ? { runtimePolicyScope } : {},
9251
- ...runtimePolicyScope ? {
9252
- signingRootId: `${runtimePolicyScope.projectId}:${runtimePolicyScope.envId}`,
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" && planKind !== "near_ed25519") return routeError(400, "invalid_body", "kind must name the signer plan");
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 (!ed25519Only && (!ecdsa || typeof ecdsa.activationCorrelationId !== "string" || typeof ecdsa.activationRequestDigestB64u !== "string" || !isPlainObject(ecdsa.clientActivation))) return routeError(400, "invalid_body", "browser-verified clientActivation is required");
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
- if (ecdsa) try {
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
- ...parsedActivation ? { ecdsa: parsedActivation } : {},
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
- * `POST /wallets/register/near-provisioning` — the non-blocking completion
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
- }, serverTiming);
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 applyRegistrationPreparedSessionSeal({
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 parseRegistrationPreparedSessionSeal(raw) {
9564
- if (raw === void 0) return {
9565
- ok: true,
9566
- value: void 0
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") !== "2") return jsonFailure(409, "wallet_protocol_mismatch", "Your wallet application needs an update. Reload this page and try again. If the problem continues, ask the application developer to upgrade the Wallet SDK.");
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
- walletProjection: ctx.opts.walletProjection
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 ../shared-ts/src/utils/ecdsaServerTiming.ts
13609
- const ECDSA_TIMING_METRICS = new Set([
13610
- "ecdsa_sign_authorize",
13611
- "ecdsa_sign_admit",
13612
- "ecdsa_sign_proxy",
13613
- "ecdsa_sign_complete",
13614
- "ecdsa_sign_total",
13615
- "ecdsa_presign_authenticate",
13616
- "ecdsa_presign_material",
13617
- "ecdsa_presign_admit",
13618
- "ecdsa_presign_proxy",
13619
- "ecdsa_presign_total",
13620
- "ecdsa_presign_sw_material",
13621
- "ecdsa_presign_sw_session",
13622
- "ecdsa_presign_sw_do_total",
13623
- "ecdsa_presign_sw_admit",
13624
- "ecdsa_presign_sw_total"
13625
- ]);
13626
- function parseEcdsaServerTiming(header) {
13627
- const durations = /* @__PURE__ */ new Map();
13628
- if (!header) return durations;
13629
- for (const metric of header.split(",")) {
13630
- const [name, ...parameters] = metric.trim().split(";");
13631
- if (!ECDSA_TIMING_METRICS.has(name) || durations.has(name)) continue;
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
- ...pinned,
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
- const commonAuthorizedOperation = {
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 resolution;
16081
+ let context;
16067
16082
  try {
16068
- resolution = await resolveWalletSessionOperationCredentialAdmission({
16069
- authorizationSessions: input.ctx.service.authorizationSessions,
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 (resolution.kind === "not_found") return { kind: "not_found" };
16081
- if (resolution.kind === "rejected") return {
16091
+ if (!context) return {
16082
16092
  kind: "rejected",
16083
- message: "ECDSA operation step-up Wallet Session authorization is invalid"
16093
+ message: "ECDSA operation step-up Wallet Session is unavailable"
16084
16094
  };
16085
- if (resolution.admission.curve !== "ecdsa") return {
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 family is invalid"
16112
+ message: "ECDSA operation step-up Wallet Session authorization is invalid"
16088
16113
  };
16089
- const session = resolution.admission.context.authorization.session;
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(resolution.admission.admission.materialActivation))) return {
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(resolution.admission.admission.materialActivation),
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
- admission: resolution.admission,
16145
+ context,
16122
16146
  activeMaterial
16123
16147
  };
16124
16148
  return {
16125
16149
  kind: "admitted",
16126
16150
  operationKind: "evm.export_key",
16127
- admission: resolution.admission,
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.admission.context.authorization.session;
16188
- const context = v2Resolution.admission.context;
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.admission.context.authorization.session.tenantId,
16217
- principalId: v2Resolution.admission.context.authorization.session.principalId,
16218
- sessionId: String(v2Resolution.admission.context.authorization.session.authorizationId),
16219
- walletId: String(v2Resolution.admission.context.authorization.session.walletId),
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" || !sameWalletSessionOperationCredentialAdmission(v2Resolution.admission, refreshedV2Resolution.admission)) return json$1({
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 (!sameWalletSessionOperationCredentialAdmission(input.authorization.v2Admission, resolution.admission)) return strictEcdsaExportFailure(403, "scope_mismatch", "ECDSA export operation step-up Wallet Session changed");
17003
- const session = resolution.admission.context.authorization.session;
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
- switch (operationRef.operationKind) {
19568
- case "near.sign_transaction":
19569
- case "near.sign_delegate_action":
19570
- case "near.sign_nep413_message": return {
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
- operationKind: operationRef.operationKind
19549
+ operation: {
19550
+ phase: "prepare",
19551
+ operationKind: requestedOperation.operation.operationKind
19552
+ }
19573
19553
  };
19574
19554
  }
19575
- }
19576
- async function authorizeRouterAbEd25519WalletSessionRequest(input) {
19577
- if (input.operation.phase === "finalize") {
19578
- const exactOperation = await validateRouterAbEd25519V2FinalizeAuthorizedOperation({
19579
- receipt: input.operation.receipt,
19580
- authorizedOperations: input.authorizedOperations,
19581
- phase: input.phase
19582
- });
19583
- if (!exactOperation.ok) return exactOperation;
19584
- if (exactOperation.operationKind !== input.admission.operationKind) return {
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
- result: routerAbEd25519OwnerOperationFailureResult({
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, projectEnvironmentId) {
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
- async function readPinnedEd25519WalletProjectEnvironmentId(ctx, authorization, operation) {
20177
- const session = ed25519ReusableWalletSession(authorization);
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.projectEnvironmentId;
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
- const commonAuthorizedOperation = {
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.admitAuthorizedOperation({ operation: {
20442
- tenantId: identity.tenantId,
20443
- authorizedOperationId,
20444
- auditEventId: requireAuthorizationValue(parseAuthorizationAuditEventId(`ed25519-operation-audit:${operation.operationId}`)),
20445
- operation: envelope,
20446
- authorization: {
20447
- kind: "authorization_grant",
20448
- authorizationGrantRef: buildAuthorizationGrantRef(identity.authorizationId)
20449
- },
20450
- quota: {
20451
- kind: "consume_reusable_wallet_session",
20452
- quotaId: identity.quotaId
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
- claimedAtMs: nowMs
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 fingerprint = await computeCapabilityOperationFingerprintDigest(buildCapabilityOperationEnvelope({
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 operationResult = await input.ctx.service.authorizedOperations.readAuthorizedOperation({
20635
- tenantId: identity.tenantId,
20636
- operationFingerprintDigest: fingerprint
20637
- });
20638
- if (!operationResult) return {
20639
- ok: false,
20640
- response: json$1({
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
- code: "authorized_operation_missing",
20643
- message: "Authorized operation is unavailable"
20644
- }, { status: 409 })
20645
- };
20646
- if (operationResult.authorizedOperationId !== requireAuthorizationValue(parseAuthorizedOperationId(receipt.authorized_operation_id)) || operationResult.operationFingerprintDigest !== fingerprint) throw new Error("Ed25519 authorized operation identity changed after prepare");
20647
- const revalidated = await revalidateEd25519AuthorizedOperation({
20648
- ctx: input.ctx,
20649
- operation: operationResult
20650
- });
20651
- return revalidated.ok ? {
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: revalidated.operation
20655
- } : revalidated;
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 revalidateEd25519AuthorizedOperation({
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
- return new Response(JSON.stringify({
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: new Headers(upstream.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: { ...buildEd25519GatewayOwnerWalletSessionBinding(authorization, await readPinnedEd25519WalletProjectEnvironmentId(input.ctx, authorization, execution.operation)) }
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
- return new Response(JSON.stringify({
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: new Headers(upstream.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: { ...buildEd25519GatewayOwnerWalletSessionBinding(authorization, await readPinnedEd25519WalletProjectEnvironmentId(input.ctx, authorization, validatedAuthorization.operation)) }
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 !== "ed25519" && raw.curve !== "ecdsa_secp256k1") throw new Error("owner execution-lane preflight curve is invalid");
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
- let walletIdRaw;
21596
- let authorization;
21597
- if (request.curve === "ed25519") {
21598
- const validated = await validateRouterAbEd25519WalletSessionInputs({
21599
- headers,
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.value,
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
- admissionRequest: input.admissionRequest
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, admissionRequest, traceContext) {
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(admissionRequest) {
25197
+ async resolveRegistrationDispatchRoot(signingRootId) {
25355
25198
  return await routerAbEd25519YaoTenantRootWireV1(await this.config.resolveTenantRoot({
25356
25199
  operation: "registration",
25357
- admissionRequest
25200
+ ...signingRootId
25358
25201
  }));
25359
25202
  }
25360
- async executePinnedRegistration(request, admissionRequest, dispatchRoot, traceContext) {
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.tenantRoot,
25373
- wallet_id: input.walletId,
25374
- lifecycle_id: input.lifecycleId,
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, admissionRequest, dispatchRoot, attempt, replay, traceContext) {
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: this.headers(traceId),
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(authorization) {
25666
- if (authorization.kind === "wallet_recovery") return authorization;
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.authorization), traceContext.value);
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.authorization), traceContext.value);
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.authorization), traceContext.value);
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.bindVerifiedIntent(input);
26210
+ const bound = await this.input.authorization.bindAndAuthorizeAdmission(input);
26346
26211
  if (!bound.ok) return bound;
26347
- return await this.input.registrationService.admit(bound.admissionRequest);
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
  }