@seams/wallet-server 0.6.0 → 0.6.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.
@@ -7904,6 +7904,9 @@ function isEmailOtpWalletRegistrationActivateSuccessV2(result) {
7904
7904
  function isPasskeyWalletRegistrationActivateSuccessV2(result) {
7905
7905
  return result.authMethod.kind === "passkey";
7906
7906
  }
7907
+ function isPasskeyWalletRegistrationNearProvisioningSuccessV2(result) {
7908
+ return result.authMethod.kind === "passkey";
7909
+ }
7907
7910
  function walletRegistrationRoutePolicyServices(input) {
7908
7911
  const service = input.services.walletRegistration;
7909
7912
  return {
@@ -9477,13 +9480,62 @@ async function handleRouterApiWalletRegistrationRespond(input) {
9477
9480
  if (!session) return routeError(500, "internal", "wallet registration respond requires session signing");
9478
9481
  const parsed = parseWalletRegistrationRespondRequest(input.body);
9479
9482
  if (!parsed.ok) return routeError(400, parsed.code, parsed.message);
9483
+ const serverTiming = [];
9480
9484
  const result = await input.services.walletRegistration.respondWalletRegistration({
9481
9485
  ...parsed.value,
9482
9486
  verifier: session,
9483
9487
  ...registrationUserAgentFromHeaders(input.headers) ? { userAgent: registrationUserAgentFromHeaders(input.headers) } : {}
9484
- }, traceContext.value ?? void 0);
9488
+ }, traceContext.value ?? void 0, serverTiming);
9489
+ return routeJson(result.ok ? 200 : 400, result, { headers: ecdsaGatewayServerTimingHeaders(serverTiming) });
9490
+ }
9491
+ async function handleRouterApiWalletRegistrationNearAdmission(input) {
9492
+ const traceContext = parseRegistrationTraceContext(input.headers);
9493
+ if (!traceContext.ok) return routeError(400, "invalid_trace_id", traceContext.message);
9494
+ if (!isPlainObject$1(input.body)) return routeError(400, "invalid_body", "JSON body required");
9495
+ const session = input.services.session;
9496
+ if (!session) return routeError(500, "internal", "NEAR admission requires setup verification");
9497
+ const body = input.body;
9498
+ const registrationCeremonyId = String(body.registrationCeremonyId || "").trim();
9499
+ const signedSetup = String(body.signedSetup || "").trim();
9500
+ if (!registrationCeremonyId || !signedSetup) return routeError(400, "invalid_body", "registrationCeremonyId and signedSetup are required");
9501
+ const authority = parseWalletRegistrationAuthorityProof(body);
9502
+ if (!authority.ok) return routeError(400, authority.code, authority.message);
9503
+ const result = await input.services.walletRegistration.authorizeWalletRegistrationNearAdmission({
9504
+ registrationCeremonyId,
9505
+ signedSetup,
9506
+ authority: authority.value,
9507
+ verifier: session,
9508
+ ...registrationUserAgentFromHeaders(input.headers) ? { userAgent: registrationUserAgentFromHeaders(input.headers) } : {}
9509
+ });
9485
9510
  return routeJson(result.ok ? 200 : 400, result);
9486
9511
  }
9512
+ function parseWalletRegistrationAuthorityProof(body) {
9513
+ const hasWebAuthn = Object.prototype.hasOwnProperty.call(body, "webauthn_registration");
9514
+ if (hasWebAuthn === Object.prototype.hasOwnProperty.call(body, "emailOtpRegistrationProof")) return {
9515
+ ok: false,
9516
+ code: "invalid_body",
9517
+ message: "exactly one registration authority proof is required"
9518
+ };
9519
+ if (hasWebAuthn) return {
9520
+ ok: true,
9521
+ value: {
9522
+ kind: "passkey",
9523
+ webauthnRegistration: body.webauthn_registration
9524
+ }
9525
+ };
9526
+ const proof = normalizeEmailOtpRegistrationProof(body.emailOtpRegistrationProof);
9527
+ return proof ? {
9528
+ ok: true,
9529
+ value: {
9530
+ kind: "email_otp",
9531
+ emailOtpRegistrationProof: proof
9532
+ }
9533
+ } : {
9534
+ ok: false,
9535
+ code: "invalid_body",
9536
+ message: "emailOtpRegistrationProof is invalid"
9537
+ };
9538
+ }
9487
9539
  /**
9488
9540
  * Parses respond's public body. `signedSetup` stays an opaque string here —
9489
9541
  * the service verifies it; parsing its contents at the boundary would invite
@@ -9518,29 +9570,9 @@ function parseWalletRegistrationRespondRequest(body) {
9518
9570
  code: "invalid_body",
9519
9571
  message: "an Ed25519-only respond carries no ECDSA registration"
9520
9572
  };
9521
- const hasWebAuthn = Object.prototype.hasOwnProperty.call(body, "webauthn_registration");
9522
- if (hasWebAuthn === Object.prototype.hasOwnProperty.call(body, "emailOtpRegistrationProof")) return {
9523
- ok: false,
9524
- code: "invalid_body",
9525
- message: "exactly one registration authority proof is required"
9526
- };
9527
- let authority;
9528
- if (hasWebAuthn) authority = {
9529
- kind: "passkey",
9530
- webauthnRegistration: body.webauthn_registration
9531
- };
9532
- else {
9533
- const proof = normalizeEmailOtpRegistrationProof(body.emailOtpRegistrationProof);
9534
- if (!proof) return {
9535
- ok: false,
9536
- code: "invalid_body",
9537
- message: "emailOtpRegistrationProof is invalid"
9538
- };
9539
- authority = {
9540
- kind: "email_otp",
9541
- emailOtpRegistrationProof: proof
9542
- };
9543
- }
9573
+ const parsedAuthority = parseWalletRegistrationAuthorityProof(body);
9574
+ if (!parsedAuthority.ok) return parsedAuthority;
9575
+ const authority = parsedAuthority.value;
9544
9576
  if (planKind === "near_ed25519") return {
9545
9577
  ok: true,
9546
9578
  value: {
@@ -9667,6 +9699,7 @@ async function handleRouterApiWalletRegistrationActivate(input) {
9667
9699
  } catch {
9668
9700
  return routeError(400, "invalid_body", "ECDSA activation facts are invalid");
9669
9701
  }
9702
+ const serverTiming = [];
9670
9703
  const result = await input.services.walletRegistration.activateWalletRegistration({
9671
9704
  registrationCeremonyId,
9672
9705
  signedSetup,
@@ -9676,7 +9709,7 @@ async function handleRouterApiWalletRegistrationActivate(input) {
9676
9709
  ...body.emailOtpEnrollment ? { emailOtpEnrollment: body.emailOtpEnrollment } : {},
9677
9710
  ...body.walletCustodyCommit !== void 0 ? { walletCustodyCommit: body.walletCustodyCommit } : {},
9678
9711
  verifier: session
9679
- }, traceContext.value ?? void 0);
9712
+ }, traceContext.value ?? void 0, serverTiming);
9680
9713
  if (!result.ok) return routeJson(400, result);
9681
9714
  if (!isEmailOtpWalletRegistrationActivateSuccessV2(result) && !isPasskeyWalletRegistrationActivateSuccessV2(result)) return routeError(500, "internal", "Wallet registration activation returned an invalid authority");
9682
9715
  const projectionError = await projectActivatedWallet({
@@ -9685,7 +9718,7 @@ async function handleRouterApiWalletRegistrationActivate(input) {
9685
9718
  signedSetup
9686
9719
  });
9687
9720
  if (projectionError) return routeError(500, "internal", `Wallet was created but its Console projection failed: ${projectionError}`);
9688
- return routeJson(200, result);
9721
+ return routeJson(200, result, { headers: ecdsaGatewayServerTimingHeaders(serverTiming) });
9689
9722
  }
9690
9723
  /**
9691
9724
  * Refactor 94C. `POST /wallets/register/near-provisioning` — the non-blocking
@@ -9703,6 +9736,9 @@ async function handleRouterApiWalletRegistrationNearProvisioning(input) {
9703
9736
  if (!registrationCeremonyId || !signedSetup || !idempotencyKey) return routeError(400, "invalid_body", "registrationCeremonyId, signedSetup and idempotencyKey are required");
9704
9737
  const ed25519 = parseWalletRegistrationEd25519Finalize(body.ed25519);
9705
9738
  if (!ed25519.ok) return routeError(400, ed25519.code, ed25519.message);
9739
+ const sessionSeal = parseRegistrationPreparedSessionSeal(body.sessionSeal);
9740
+ if (!sessionSeal.ok) return routeError(400, sessionSeal.code, sessionSeal.message);
9741
+ const serverTiming = [];
9706
9742
  const result = await input.services.walletRegistration.completeWalletRegistrationNearProvisioning({
9707
9743
  authorization: registrationContinuationAuthorization(input.headers),
9708
9744
  registrationCeremonyId,
@@ -9712,9 +9748,110 @@ async function handleRouterApiWalletRegistrationNearProvisioning(input) {
9712
9748
  emailOtpEnrollment: body.emailOtpEnrollment,
9713
9749
  ...body.walletCustodyCommit !== void 0 ? { walletCustodyCommit: body.walletCustodyCommit } : {},
9714
9750
  verifier: session
9715
- });
9751
+ }, serverTiming);
9716
9752
  if (!result.ok) return routeJson(400, result);
9717
- return routeJson(200, result);
9753
+ if (sessionSeal.value) {
9754
+ if (!isPasskeyWalletRegistrationNearProvisioningSuccessV2(result)) return routeError(400, "invalid_body", "Registration session sealing requires a passkey authority");
9755
+ const sealStartedAt = Date.now();
9756
+ const sealed = await applyRegistrationPreparedSessionSeal({
9757
+ options: input.signingSessionSeal,
9758
+ request: sessionSeal.value,
9759
+ response: result
9760
+ });
9761
+ serverTiming.push(["near_finalize_session_seal", Math.max(0, Date.now() - sealStartedAt)]);
9762
+ if (!sealed.ok) return routeJson(503, {
9763
+ ok: false,
9764
+ code: sealed.code,
9765
+ message: sealed.message
9766
+ }, { headers: ecdsaGatewayServerTimingHeaders(serverTiming) });
9767
+ return routeJson(200, {
9768
+ ...result,
9769
+ sessionSeal: sealed.value
9770
+ }, { headers: ecdsaGatewayServerTimingHeaders(serverTiming) });
9771
+ }
9772
+ return routeJson(200, result, { headers: ecdsaGatewayServerTimingHeaders(serverTiming) });
9773
+ }
9774
+ function parseRegistrationPreparedSessionSeal(raw) {
9775
+ if (raw === void 0) return {
9776
+ ok: true,
9777
+ value: void 0
9778
+ };
9779
+ if (!isPlainObject$1(raw)) return {
9780
+ ok: false,
9781
+ code: "invalid_body",
9782
+ message: "sessionSeal must be an object"
9783
+ };
9784
+ if (Object.keys(raw).some((field) => ![
9785
+ "thresholdSessionId",
9786
+ "ciphertext",
9787
+ "keyVersion"
9788
+ ].includes(field))) return {
9789
+ ok: false,
9790
+ code: "invalid_body",
9791
+ message: "sessionSeal has unknown fields"
9792
+ };
9793
+ const thresholdSessionId = String(raw.thresholdSessionId || "").trim();
9794
+ const ciphertext = String(raw.ciphertext || "").trim();
9795
+ const keyVersion = String(raw.keyVersion || "").trim();
9796
+ if (!thresholdSessionId || !ciphertext) return {
9797
+ ok: false,
9798
+ code: "invalid_body",
9799
+ message: "sessionSeal thresholdSessionId and ciphertext are required"
9800
+ };
9801
+ return {
9802
+ ok: true,
9803
+ value: {
9804
+ thresholdSessionId,
9805
+ ciphertext,
9806
+ ...keyVersion ? { keyVersion } : {}
9807
+ }
9808
+ };
9809
+ }
9810
+ async function applyRegistrationPreparedSessionSeal(args) {
9811
+ if (!args.options) return {
9812
+ ok: false,
9813
+ code: "signing_session_seal_unavailable",
9814
+ message: "Signing-session sealing is unavailable"
9815
+ };
9816
+ const session = args.response.registrationEstablishedSession.session;
9817
+ const tokens = session.tokens;
9818
+ const ed25519 = tokens.kind === "near_ed25519" || tokens.kind === "near_ed25519_and_evm_family_ecdsa" ? tokens.ed25519 : null;
9819
+ if (!ed25519 || String(ed25519.thresholdSessionId) !== args.request.thresholdSessionId) return {
9820
+ ok: false,
9821
+ code: "invalid_session_seal",
9822
+ message: "Prepared seal does not match the established Ed25519 session"
9823
+ };
9824
+ const sealed = await args.options.service.applyServerSeal(args.request, {
9825
+ userId: String(session.walletId),
9826
+ session: {
9827
+ kind: "exact_wallet_session_operation_credential",
9828
+ curve: "ed25519",
9829
+ thresholdSessionId: args.request.thresholdSessionId,
9830
+ userId: String(session.walletId),
9831
+ expiresAtMs: session.expiresAtMs
9832
+ }
9833
+ });
9834
+ if (!sealed.ok) return sealed;
9835
+ const keyVersion = String(sealed.keyVersion || "").trim();
9836
+ if (!keyVersion) return {
9837
+ ok: false,
9838
+ code: "invalid_session_seal",
9839
+ message: "Signing-session seal response is missing its key version"
9840
+ };
9841
+ return {
9842
+ ok: true,
9843
+ value: {
9844
+ ciphertext: sealed.ciphertext,
9845
+ keyVersion,
9846
+ expiresAtMs: Math.min(sealed.expiresAtMs ?? session.expiresAtMs, session.expiresAtMs),
9847
+ remainingUses: session.remainingUses
9848
+ }
9849
+ };
9850
+ }
9851
+ function ecdsaGatewayServerTimingHeaders(serverTiming) {
9852
+ if (serverTiming.length === 0) return void 0;
9853
+ const header = serverTiming.map(([name, durationMs]) => `${name};dur=${Math.max(0, durationMs).toFixed(1)}`).join(", ");
9854
+ return { "Server-Timing": header };
9718
9855
  }
9719
9856
  async function handleRouterApiWalletAddSignerStart(input) {
9720
9857
  if (!isPlainObject$1(input.body)) return routeError(400, "invalid_body", "JSON body required");
@@ -10622,6 +10759,10 @@ function createRouterApiRouteDefinitions(options = {}) {
10622
10759
  plane: "public",
10623
10760
  proof: "webauthn",
10624
10761
  rationale: "Registration respond is authorized by the signed setup payload and the registration authority proof."
10762
+ }, ROUTER_API_WALLET_REGISTRATION_SESSION_SERVICES), publicRoute("wallet_registration_near_admission", "POST", "/wallets/register/near-admission", "Authorize deferred NEAR registration while ECDSA respond runs", {
10763
+ plane: "public",
10764
+ proof: "webauthn",
10765
+ rationale: "NEAR admission is authorized by the signed setup payload and the registration authority proof."
10625
10766
  }, ROUTER_API_WALLET_REGISTRATION_SESSION_SERVICES), publicRoute("wallet_registration_activate", "POST", "/wallets/register/activate", "Activate and finalize one wallet ECDSA registration", {
10626
10767
  plane: "public",
10627
10768
  proof: "threshold_protocol_state",
@@ -10795,6 +10936,7 @@ function createRouterApiRouteDefinitions(options = {}) {
10795
10936
  const ROUTE_IDS = [
10796
10937
  "wallet_registration_setup",
10797
10938
  "wallet_registration_respond",
10939
+ "wallet_registration_near_admission",
10798
10940
  "wallet_registration_activate",
10799
10941
  "wallet_registration_near_provisioning",
10800
10942
  "wallet_add_signer_intent",
@@ -10850,9 +10992,64 @@ async function handleWalletRegistration(ctx) {
10850
10992
  publishableKeyAuth: ctx.opts.publishableKeyAuth,
10851
10993
  walletProjection: ctx.opts.walletProjection
10852
10994
  },
10853
- sourceIp: resolveSourceIpFromFetchHeaders(ctx.request.headers) || void 0
10995
+ sourceIp: resolveSourceIpFromFetchHeaders(ctx.request.headers) || void 0,
10996
+ signingSessionSeal: ctx.opts.signingSessionSeal
10854
10997
  };
10855
- return toFetchRouteResponse(route.id === "wallet_registration_setup" ? await handleRouterApiWalletRegistrationSetup(common) : route.id === "wallet_registration_respond" ? await handleRouterApiWalletRegistrationRespond(common) : route.id === "wallet_registration_activate" ? await handleRouterApiWalletRegistrationActivate(common) : route.id === "wallet_registration_near_provisioning" ? await handleRouterApiWalletRegistrationNearProvisioning(common) : route.id === "wallet_add_signer_intent" ? await handleRouterApiWalletAddSignerIntent(common) : route.id === "wallet_add_signer_start" ? await handleRouterApiWalletAddSignerStart(common) : route.id === "wallet_add_signer_ecdsa_derivation_respond" ? await handleRouterApiWalletAddSignerEcdsaDerivationRespond(common) : route.id === "wallet_add_signer_ecdsa_activation" ? await handleRouterApiWalletAddSignerEcdsaActivation(common) : route.id === "wallet_add_signer_finalize" ? await handleRouterApiWalletAddSignerFinalize(common) : route.id === "wallet_add_auth_method_intent" ? await handleRouterApiWalletAddAuthMethodIntent(common) : route.id === "wallet_add_auth_method_email_otp_challenge" ? await handleRouterApiWalletAddAuthMethodEmailOtpChallenge(common) : route.id === "wallet_add_auth_method_start" ? await handleRouterApiWalletAddAuthMethodStart(common) : route.id === "wallet_add_auth_method_finalize" ? await handleRouterApiWalletAddAuthMethodFinalize(common) : route.id === "wallet_revoke_auth_method" ? await handleRouterApiWalletRevokeAuthMethod(common) : route.id === "wallet_ecdsa_key_facts_inventory" ? await handleRouterApiWalletEcdsaKeyFactsInventory(common) : await handleRouterApiWalletNearImplicitAccountFund(common));
10998
+ let response;
10999
+ switch (route.id) {
11000
+ case "wallet_registration_setup":
11001
+ response = await handleRouterApiWalletRegistrationSetup(common);
11002
+ break;
11003
+ case "wallet_registration_respond":
11004
+ response = await handleRouterApiWalletRegistrationRespond(common);
11005
+ break;
11006
+ case "wallet_registration_near_admission":
11007
+ response = await handleRouterApiWalletRegistrationNearAdmission(common);
11008
+ break;
11009
+ case "wallet_registration_activate":
11010
+ response = await handleRouterApiWalletRegistrationActivate(common);
11011
+ break;
11012
+ case "wallet_registration_near_provisioning":
11013
+ response = await handleRouterApiWalletRegistrationNearProvisioning(common);
11014
+ break;
11015
+ case "wallet_add_signer_intent":
11016
+ response = await handleRouterApiWalletAddSignerIntent(common);
11017
+ break;
11018
+ case "wallet_add_signer_start":
11019
+ response = await handleRouterApiWalletAddSignerStart(common);
11020
+ break;
11021
+ case "wallet_add_signer_ecdsa_derivation_respond":
11022
+ response = await handleRouterApiWalletAddSignerEcdsaDerivationRespond(common);
11023
+ break;
11024
+ case "wallet_add_signer_ecdsa_activation":
11025
+ response = await handleRouterApiWalletAddSignerEcdsaActivation(common);
11026
+ break;
11027
+ case "wallet_add_signer_finalize":
11028
+ response = await handleRouterApiWalletAddSignerFinalize(common);
11029
+ break;
11030
+ case "wallet_add_auth_method_intent":
11031
+ response = await handleRouterApiWalletAddAuthMethodIntent(common);
11032
+ break;
11033
+ case "wallet_add_auth_method_email_otp_challenge":
11034
+ response = await handleRouterApiWalletAddAuthMethodEmailOtpChallenge(common);
11035
+ break;
11036
+ case "wallet_add_auth_method_start":
11037
+ response = await handleRouterApiWalletAddAuthMethodStart(common);
11038
+ break;
11039
+ case "wallet_add_auth_method_finalize":
11040
+ response = await handleRouterApiWalletAddAuthMethodFinalize(common);
11041
+ break;
11042
+ case "wallet_revoke_auth_method":
11043
+ response = await handleRouterApiWalletRevokeAuthMethod(common);
11044
+ break;
11045
+ case "wallet_ecdsa_key_facts_inventory":
11046
+ response = await handleRouterApiWalletEcdsaKeyFactsInventory(common);
11047
+ break;
11048
+ default:
11049
+ response = await handleRouterApiWalletNearImplicitAccountFund(common);
11050
+ break;
11051
+ }
11052
+ return toFetchRouteResponse(response);
10856
11053
  }
10857
11054
  //#endregion
10858
11055
  //#region ../shared-ts/src/utils/errors.ts
@@ -272,6 +272,10 @@ function createRouterApiRouteDefinitions(options = {}) {
272
272
  plane: "public",
273
273
  proof: "webauthn",
274
274
  rationale: "Registration respond is authorized by the signed setup payload and the registration authority proof."
275
+ }, ROUTER_API_WALLET_REGISTRATION_SESSION_SERVICES), publicRoute("wallet_registration_near_admission", "POST", "/wallets/register/near-admission", "Authorize deferred NEAR registration while ECDSA respond runs", {
276
+ plane: "public",
277
+ proof: "webauthn",
278
+ rationale: "NEAR admission is authorized by the signed setup payload and the registration authority proof."
275
279
  }, ROUTER_API_WALLET_REGISTRATION_SESSION_SERVICES), publicRoute("wallet_registration_activate", "POST", "/wallets/register/activate", "Activate and finalize one wallet ECDSA registration", {
276
280
  plane: "public",
277
281
  proof: "threshold_protocol_state",
@@ -2,12 +2,13 @@ import { findRouteDefinitionById, matchesRouteDefinitionRequest } from "../../..
2
2
  import { readJson } from "../../../framework/http.js";
3
3
  import { resolveSourceIpFromFetchHeaders } from "../../../auth/routerApiKeyAuth.js";
4
4
  import { toFetchRouteResponse } from "../../../framework/routeResponses.js";
5
- import { handleRouterApiWalletAddAuthMethodEmailOtpChallenge, handleRouterApiWalletAddAuthMethodFinalize, handleRouterApiWalletAddAuthMethodIntent, handleRouterApiWalletAddAuthMethodStart, handleRouterApiWalletAddSignerEcdsaActivation, handleRouterApiWalletAddSignerEcdsaDerivationRespond, handleRouterApiWalletAddSignerFinalize, handleRouterApiWalletAddSignerIntent, handleRouterApiWalletAddSignerStart, handleRouterApiWalletEcdsaKeyFactsInventory, handleRouterApiWalletNearImplicitAccountFund, handleRouterApiWalletRegistrationActivate, handleRouterApiWalletRegistrationNearProvisioning, handleRouterApiWalletRegistrationRespond, handleRouterApiWalletRegistrationSetup, handleRouterApiWalletRevokeAuthMethod } from "../../../domains/walletRegistration/walletRegistrationRoutes.js";
5
+ import { handleRouterApiWalletAddAuthMethodEmailOtpChallenge, handleRouterApiWalletAddAuthMethodFinalize, handleRouterApiWalletAddAuthMethodIntent, handleRouterApiWalletAddAuthMethodStart, handleRouterApiWalletAddSignerEcdsaActivation, handleRouterApiWalletAddSignerEcdsaDerivationRespond, handleRouterApiWalletAddSignerFinalize, handleRouterApiWalletAddSignerIntent, handleRouterApiWalletAddSignerStart, handleRouterApiWalletEcdsaKeyFactsInventory, handleRouterApiWalletNearImplicitAccountFund, handleRouterApiWalletRegistrationActivate, handleRouterApiWalletRegistrationNearAdmission, handleRouterApiWalletRegistrationNearProvisioning, handleRouterApiWalletRegistrationRespond, handleRouterApiWalletRegistrationSetup, handleRouterApiWalletRevokeAuthMethod } from "../../../domains/walletRegistration/walletRegistrationRoutes.js";
6
6
  import { routerApiWalletRegistrationRouteService } from "../../../framework/authServicePort.js";
7
7
  //#region src/router/transport/fetch/routes/walletRegistration.ts
8
8
  const ROUTE_IDS = [
9
9
  "wallet_registration_setup",
10
10
  "wallet_registration_respond",
11
+ "wallet_registration_near_admission",
11
12
  "wallet_registration_activate",
12
13
  "wallet_registration_near_provisioning",
13
14
  "wallet_add_signer_intent",
@@ -63,9 +64,64 @@ async function handleWalletRegistration(ctx) {
63
64
  publishableKeyAuth: ctx.opts.publishableKeyAuth,
64
65
  walletProjection: ctx.opts.walletProjection
65
66
  },
66
- sourceIp: resolveSourceIpFromFetchHeaders(ctx.request.headers) || void 0
67
+ sourceIp: resolveSourceIpFromFetchHeaders(ctx.request.headers) || void 0,
68
+ signingSessionSeal: ctx.opts.signingSessionSeal
67
69
  };
68
- return toFetchRouteResponse(route.id === "wallet_registration_setup" ? await handleRouterApiWalletRegistrationSetup(common) : route.id === "wallet_registration_respond" ? await handleRouterApiWalletRegistrationRespond(common) : route.id === "wallet_registration_activate" ? await handleRouterApiWalletRegistrationActivate(common) : route.id === "wallet_registration_near_provisioning" ? await handleRouterApiWalletRegistrationNearProvisioning(common) : route.id === "wallet_add_signer_intent" ? await handleRouterApiWalletAddSignerIntent(common) : route.id === "wallet_add_signer_start" ? await handleRouterApiWalletAddSignerStart(common) : route.id === "wallet_add_signer_ecdsa_derivation_respond" ? await handleRouterApiWalletAddSignerEcdsaDerivationRespond(common) : route.id === "wallet_add_signer_ecdsa_activation" ? await handleRouterApiWalletAddSignerEcdsaActivation(common) : route.id === "wallet_add_signer_finalize" ? await handleRouterApiWalletAddSignerFinalize(common) : route.id === "wallet_add_auth_method_intent" ? await handleRouterApiWalletAddAuthMethodIntent(common) : route.id === "wallet_add_auth_method_email_otp_challenge" ? await handleRouterApiWalletAddAuthMethodEmailOtpChallenge(common) : route.id === "wallet_add_auth_method_start" ? await handleRouterApiWalletAddAuthMethodStart(common) : route.id === "wallet_add_auth_method_finalize" ? await handleRouterApiWalletAddAuthMethodFinalize(common) : route.id === "wallet_revoke_auth_method" ? await handleRouterApiWalletRevokeAuthMethod(common) : route.id === "wallet_ecdsa_key_facts_inventory" ? await handleRouterApiWalletEcdsaKeyFactsInventory(common) : await handleRouterApiWalletNearImplicitAccountFund(common));
70
+ let response;
71
+ switch (route.id) {
72
+ case "wallet_registration_setup":
73
+ response = await handleRouterApiWalletRegistrationSetup(common);
74
+ break;
75
+ case "wallet_registration_respond":
76
+ response = await handleRouterApiWalletRegistrationRespond(common);
77
+ break;
78
+ case "wallet_registration_near_admission":
79
+ response = await handleRouterApiWalletRegistrationNearAdmission(common);
80
+ break;
81
+ case "wallet_registration_activate":
82
+ response = await handleRouterApiWalletRegistrationActivate(common);
83
+ break;
84
+ case "wallet_registration_near_provisioning":
85
+ response = await handleRouterApiWalletRegistrationNearProvisioning(common);
86
+ break;
87
+ case "wallet_add_signer_intent":
88
+ response = await handleRouterApiWalletAddSignerIntent(common);
89
+ break;
90
+ case "wallet_add_signer_start":
91
+ response = await handleRouterApiWalletAddSignerStart(common);
92
+ break;
93
+ case "wallet_add_signer_ecdsa_derivation_respond":
94
+ response = await handleRouterApiWalletAddSignerEcdsaDerivationRespond(common);
95
+ break;
96
+ case "wallet_add_signer_ecdsa_activation":
97
+ response = await handleRouterApiWalletAddSignerEcdsaActivation(common);
98
+ break;
99
+ case "wallet_add_signer_finalize":
100
+ response = await handleRouterApiWalletAddSignerFinalize(common);
101
+ break;
102
+ case "wallet_add_auth_method_intent":
103
+ response = await handleRouterApiWalletAddAuthMethodIntent(common);
104
+ break;
105
+ case "wallet_add_auth_method_email_otp_challenge":
106
+ response = await handleRouterApiWalletAddAuthMethodEmailOtpChallenge(common);
107
+ break;
108
+ case "wallet_add_auth_method_start":
109
+ response = await handleRouterApiWalletAddAuthMethodStart(common);
110
+ break;
111
+ case "wallet_add_auth_method_finalize":
112
+ response = await handleRouterApiWalletAddAuthMethodFinalize(common);
113
+ break;
114
+ case "wallet_revoke_auth_method":
115
+ response = await handleRouterApiWalletRevokeAuthMethod(common);
116
+ break;
117
+ case "wallet_ecdsa_key_facts_inventory":
118
+ response = await handleRouterApiWalletEcdsaKeyFactsInventory(common);
119
+ break;
120
+ default:
121
+ response = await handleRouterApiWalletNearImplicitAccountFund(common);
122
+ break;
123
+ }
124
+ return toFetchRouteResponse(response);
69
125
  }
70
126
  //#endregion
71
127
  export { handleWalletRegistration };
@@ -294,6 +294,11 @@ export type WalletRegistrationRespondResponseV2 = ({
294
294
  ok: true;
295
295
  registrationCeremonyId: string;
296
296
  } & WalletRegistrationRespondSignerPlanV2) | WalletRegistrationRouteErrorV2;
297
+ export type WalletRegistrationNearAdmissionResponseV2 = {
298
+ readonly ok: true;
299
+ readonly registrationCeremonyId: string;
300
+ readonly ed25519: RespondEd25519DeferredWorkV2;
301
+ } | WalletRegistrationRouteErrorV2;
297
302
  /**
298
303
  * Route 3 — activate-and-finalize; the operation row is the replay record.
299
304
  *
@@ -414,16 +419,40 @@ export type WalletRegistrationNearProvisioningRequestV2 = {
414
419
  kind: 'near_ed25519';
415
420
  }>['ed25519'];
416
421
  emailOtpEnrollment?: NonNullable<WalletRegistrationFinalizeRequest['emailOtpEnrollment']>;
422
+ sessionSeal?: {
423
+ readonly thresholdSessionId: string;
424
+ readonly ciphertext: string;
425
+ readonly keyVersion?: string;
426
+ };
417
427
  };
418
- type WalletRegistrationNearProvisioningSuccessV2 = Extract<WalletRegistrationFinalizeResponse, {
428
+ type WalletRegistrationNearProvisioningFinalizeSuccessV2 = Extract<WalletRegistrationFinalizeResponse, {
419
429
  ok: true;
420
430
  kind: 'near_ed25519';
421
- }> & {
431
+ }>;
432
+ type WalletRegistrationNearProvisioningSuccessBaseV2 = {
422
433
  registrationEstablishedSession: RegistrationEstablishedSessionResultV2;
423
434
  nearProvisioning: {
424
435
  status: 'near_ready';
425
436
  };
426
437
  };
438
+ type WalletRegistrationNearProvisioningSuccessV2 = (Extract<WalletRegistrationNearProvisioningFinalizeSuccessV2, {
439
+ authMethod: {
440
+ kind: 'passkey';
441
+ };
442
+ }> & WalletRegistrationNearProvisioningSuccessBaseV2 & {
443
+ sessionSeal?: {
444
+ readonly ciphertext: string;
445
+ readonly keyVersion: string;
446
+ readonly expiresAtMs: number;
447
+ readonly remainingUses: number;
448
+ };
449
+ }) | (Extract<WalletRegistrationNearProvisioningFinalizeSuccessV2, {
450
+ authMethod: {
451
+ kind: 'email_otp';
452
+ };
453
+ }> & WalletRegistrationNearProvisioningSuccessBaseV2 & {
454
+ sessionSeal?: never;
455
+ });
427
456
  export type WalletRegistrationNearProvisioningResponseV2 = WalletRegistrationNearProvisioningSuccessV2 | (WalletRegistrationRouteErrorV2 & {
428
457
  /**
429
458
  * A retryable failure leaves the pending wallet intact and the call
@@ -17,8 +17,8 @@ import { CloudflareD1RegistrationCeremonyIntentStore } from './d1RegistrationCer
17
17
  import type { InstalledLinkedDeviceEcdsaAuthorityProjectionV1, InstalledLinkedDeviceEd25519AuthorityProjectionV1 } from '../deviceLinking/d1LinkedDeviceAuthorityInstallService';
18
18
  import { type ThresholdEcdsaKeyInventoryDiagnostics, type ThresholdEcdsaKeyInventoryRecord } from '../../../../core/authService/thresholdEcdsaKeyInventory';
19
19
  import { type StoredWalletRegistrationEvmFamilyEcdsaPendingActivationBranch } from '../../../../core/RegistrationCeremonyStore';
20
- import type { WalletRegistrationNearProvisioningResponseV2, WalletRegistrationActivateResponseV2, WalletRegistrationRespondResponseV2, WalletRegistrationSetupResponseV2, WalletRegistrationSessionCommitReceiptV2 } from '../../../../core/threeRouteRegistrationContracts';
21
- import type { WalletRegistrationSetupInput, WalletRegistrationRespondInput, WalletRegistrationActivateInput, WalletRegistrationNearProvisioningInput } from '../../../domains/walletRegistration/walletRegistrationInputs';
20
+ import type { WalletRegistrationNearProvisioningResponseV2, WalletRegistrationNearAdmissionResponseV2, WalletRegistrationActivateResponseV2, WalletRegistrationRespondResponseV2, WalletRegistrationSetupResponseV2, WalletRegistrationSessionCommitReceiptV2 } from '../../../../core/threeRouteRegistrationContracts';
21
+ import type { WalletRegistrationSetupInput, WalletRegistrationRespondInput, WalletRegistrationActivateInput, WalletRegistrationNearProvisioningInput, WalletRegistrationNearAdmissionInput } from '../../../domains/walletRegistration/walletRegistrationInputs';
22
22
  import type { CloudflareD1WalletCustodyCommitStore } from '../passkeyCustody/d1WalletCustodyCommitStore';
23
23
  import { CloudflareD1EmailOtpRegistrationEnrollmentFinalizer } from '../emailOtp/d1EmailOtpRegistrationEnrollmentFinalizer';
24
24
  import { CloudflareD1WalletAuthMethodService } from '../wallet/d1WalletAuthMethodService';
@@ -272,7 +272,8 @@ export declare class CloudflareD1WalletRegistrationService {
272
272
  * can invalidate the other.
273
273
  */
274
274
  setupWalletRegistration(input: WalletRegistrationSetupInput): Promise<WalletRegistrationSetupResponseV2>;
275
- respondWalletRegistration(input: WalletRegistrationRespondInput, traceContext?: RouterAbTraceContextV1): Promise<WalletRegistrationRespondResponseV2>;
275
+ authorizeWalletRegistrationNearAdmission(input: WalletRegistrationNearAdmissionInput): Promise<WalletRegistrationNearAdmissionResponseV2>;
276
+ respondWalletRegistration(input: WalletRegistrationRespondInput, traceContext?: RouterAbTraceContextV1, timingSink?: Array<readonly [string, number]>): Promise<WalletRegistrationRespondResponseV2>;
276
277
  /**
277
278
  * The Ed25519 commit core, extracted so deferred provisioning reaches it
278
279
  * without going through the standalone finalize wrapper. The operation row
@@ -286,6 +287,7 @@ export declare class CloudflareD1WalletRegistrationService {
286
287
  readonly lifecycleId: string;
287
288
  readonly credential: string;
288
289
  }): Promise<VerifiedNearRegistrationContinuationV1 | null>;
290
+ private readNearRegistrationContinuationContext;
289
291
  private readCommittedRegistrationInstallation;
290
292
  private prepareNearProvisioningOperation;
291
293
  private commitDeferredEd25519Signer;
@@ -301,7 +303,7 @@ export declare class CloudflareD1WalletRegistrationService {
301
303
  * be destroyed because its signer ceremony needs another attempt.
302
304
  */
303
305
  private verifyNearProvisioningAuthority;
304
- completeWalletRegistrationNearProvisioning(input: WalletRegistrationNearProvisioningInput): Promise<WalletRegistrationNearProvisioningResponseV2>;
306
+ completeWalletRegistrationNearProvisioning(input: WalletRegistrationNearProvisioningInput, timingSink?: Array<readonly [string, number]>): Promise<WalletRegistrationNearProvisioningResponseV2>;
305
307
  /**
306
308
  * Persists the Ed25519-only wallet in `near_pending`: wallet, profile, and
307
309
  * authentication state, and no signer record — the signer does not exist
@@ -355,7 +357,7 @@ export declare class CloudflareD1WalletRegistrationService {
355
357
  * before execution; an ambiguous outcome after the custody call stays
356
358
  * `uncertain` rather than being guessed either way.
357
359
  */
358
- activateWalletRegistration(input: WalletRegistrationActivateInput, traceContext?: RouterAbTraceContextV1): Promise<WalletRegistrationActivateResponseV2>;
360
+ activateWalletRegistration(input: WalletRegistrationActivateInput, traceContext?: RouterAbTraceContextV1, serverTiming?: Array<readonly [string, number]>): Promise<WalletRegistrationActivateResponseV2>;
359
361
  /**
360
362
  * Router/SigningWorker activation followed by the blocking finalize
361
363
  * persistence, as one unit inside the operation row. The commit is told the
@@ -34,6 +34,13 @@ export type WalletRegistrationRespondInput = {
34
34
  readonly verifier: WalletRegistrationSetupVerifier;
35
35
  readonly userAgent?: string;
36
36
  };
37
+ export type WalletRegistrationNearAdmissionInput = {
38
+ readonly registrationCeremonyId: string;
39
+ readonly signedSetup: unknown;
40
+ readonly authority: WalletRegistrationAuthorityInput;
41
+ readonly verifier: WalletRegistrationSetupVerifier;
42
+ readonly userAgent?: string;
43
+ };
37
44
  export type WalletRegistrationActivateInput = {
38
45
  readonly registrationCeremonyId: string;
39
46
  readonly signedSetup: unknown;
@@ -1,4 +1,4 @@
1
- import type { WalletRegistrationNearProvisioningResponseV2, WalletRegistrationActivateRouteResponseV2, WalletRegistrationRespondResponseV2, WalletRegistrationSetupResponseV2 } from '../../../core/threeRouteRegistrationContracts';
1
+ import type { WalletRegistrationNearProvisioningResponseV2, WalletRegistrationNearAdmissionResponseV2, WalletRegistrationActivateRouteResponseV2, WalletRegistrationRespondResponseV2, WalletRegistrationSetupResponseV2 } from '../../../core/threeRouteRegistrationContracts';
2
2
  import type { RouterApiPublishableKeyAuthAdapter } from '../../framework/routerApi';
3
3
  import type { RouterApiAuthorizationSessionService, RouterApiWalletRegistrationRouteService } from '../../framework/authServicePort';
4
4
  import type { FundImplicitNearAccountResult } from '../../../core/types';
@@ -7,6 +7,7 @@ import type { NormalizedRouterLogger } from '../../framework/logger';
7
7
  import type { RouterApiKeyAuthAdapter, RouterApiProjectEnvironmentResolver, SessionAdapter, RouterApiWalletProjectionAdapter } from '../../framework/routerApi';
8
8
  import type { HeaderRecord, RouteResponse } from '../../framework/routeExecutionContext';
9
9
  import type { RouteDefinition } from '../../framework/routeDefinitions';
10
+ import type { SigningSessionSealRoutesOptions } from '../../../threshold/session/signingSessionSeal/signingSessionSeal.types';
10
11
  import type { RouteErrorBody } from '../../framework/routeResponses';
11
12
  import type { RouterAbPublicKeysetV2 } from '../../../../../shared-ts/src/utils/routerAbPublicKeyset';
12
13
  type RouterApiWalletRegistrationServices = {
@@ -29,6 +30,7 @@ type RouterApiWalletRegistrationInput = {
29
30
  route: RouteDefinition;
30
31
  services: RouterApiWalletRegistrationServices;
31
32
  sourceIp?: string;
33
+ signingSessionSeal?: SigningSessionSealRoutesOptions | null;
32
34
  };
33
35
  export declare function handleRouterApiWalletAddSignerIntent(input: RouterApiWalletRegistrationInput): Promise<RouteResponse<CreateAddSignerIntentResponse | RouteErrorBody>>;
34
36
  /**
@@ -48,6 +50,7 @@ export declare function handleRouterApiWalletRegistrationSetup(input: RouterApiW
48
50
  * derivation respond leg it replaces was.
49
51
  */
50
52
  export declare function handleRouterApiWalletRegistrationRespond(input: RouterApiWalletRegistrationInput): Promise<RouteResponse<WalletRegistrationRespondResponseV2 | RouteErrorBody>>;
53
+ export declare function handleRouterApiWalletRegistrationNearAdmission(input: RouterApiWalletRegistrationInput): Promise<RouteResponse<WalletRegistrationNearAdmissionResponseV2 | RouteErrorBody>>;
51
54
  /**
52
55
  * Refactor 94C. `POST /wallets/register/activate` — activation and
53
56
  * finalization behind one Gateway operation row.
@@ -1,7 +1,7 @@
1
1
  import type { DigestB64u } from '../../../../shared-ts/src/utils/canonicalPrimitives';
2
2
  import type { AddAuthMethodIntentCallerV1, AddAuthMethodIntentGrant } from '../../../../shared-ts/src/utils/registrationIntent';
3
- import type { WalletRegistrationNearProvisioningResponseV2, WalletRegistrationActivateResponseV2, WalletRegistrationRespondResponseV2, WalletRegistrationSetupResponseV2 } from '../../core/threeRouteRegistrationContracts';
4
- import type { WalletRegistrationNearProvisioningInput, WalletRegistrationActivateInput, WalletRegistrationRespondInput, WalletRegistrationSetupInput } from '../domains/walletRegistration/walletRegistrationInputs';
3
+ import type { WalletRegistrationNearProvisioningResponseV2, WalletRegistrationNearAdmissionResponseV2, WalletRegistrationActivateResponseV2, WalletRegistrationRespondResponseV2, WalletRegistrationSetupResponseV2 } from '../../core/threeRouteRegistrationContracts';
4
+ import type { WalletRegistrationNearProvisioningInput, WalletRegistrationNearAdmissionInput, WalletRegistrationActivateInput, WalletRegistrationRespondInput, WalletRegistrationSetupInput } from '../domains/walletRegistration/walletRegistrationInputs';
5
5
  import type { WalletEmailOtpAction } from '../../../../shared-ts/src/utils/emailOtpDomain';
6
6
  import type { MpcMaterialActivationRef, OrgId, ProviderSubject, WalletAuthMethodId, WalletAuthorityId, WalletId, WebAuthnCredentialIdB64u, WebAuthnRpId } from '../../../../shared-ts/src/utils/domainIds';
7
7
  import type { ActiveWalletAuthorityV1, WalletAuthorityProvenanceV1 } from '../../../../shared-ts/src/authorization/walletAuthority';
@@ -1031,9 +1031,10 @@ export interface RouterApiWalletRegistrationService {
1031
1031
  listWalletEcdsaKeyFactsInventory(input: RouterApiMethodTypes['listWalletEcdsaKeyFactsInventory']['input']): Promise<RouterApiMethodTypes['listWalletEcdsaKeyFactsInventory']['result']>;
1032
1032
  readActiveEmailOtpEnrollment(input: RouterApiMethodTypes['readActiveEmailOtpEnrollment']['input']): Promise<RouterApiMethodTypes['readActiveEmailOtpEnrollment']['result']>;
1033
1033
  setupWalletRegistration(input: WalletRegistrationSetupInput): Promise<WalletRegistrationSetupResponseV2>;
1034
- respondWalletRegistration(input: WalletRegistrationRespondInput, traceContext?: RouterAbTraceContextV1): Promise<WalletRegistrationRespondResponseV2>;
1035
- activateWalletRegistration(input: WalletRegistrationActivateInput, traceContext?: RouterAbTraceContextV1): Promise<WalletRegistrationActivateResponseV2>;
1036
- completeWalletRegistrationNearProvisioning(input: WalletRegistrationNearProvisioningInput): Promise<WalletRegistrationNearProvisioningResponseV2>;
1034
+ respondWalletRegistration(input: WalletRegistrationRespondInput, traceContext?: RouterAbTraceContextV1, serverTiming?: Array<readonly [string, number]>): Promise<WalletRegistrationRespondResponseV2>;
1035
+ authorizeWalletRegistrationNearAdmission(input: WalletRegistrationNearAdmissionInput): Promise<WalletRegistrationNearAdmissionResponseV2>;
1036
+ activateWalletRegistration(input: WalletRegistrationActivateInput, traceContext?: RouterAbTraceContextV1, serverTiming?: Array<readonly [string, number]>): Promise<WalletRegistrationActivateResponseV2>;
1037
+ completeWalletRegistrationNearProvisioning(input: WalletRegistrationNearProvisioningInput, serverTiming?: Array<readonly [string, number]>): Promise<WalletRegistrationNearProvisioningResponseV2>;
1037
1038
  refreshEd25519YaoWalletSession(input: RouterAbEd25519YaoBudgetRefreshRequestV1): Promise<RouterAbEd25519YaoBudgetRefreshResponseV1>;
1038
1039
  provisionEd25519YaoWalletSession(input: RouterAbEd25519YaoVerifiedWalletUnlockRequestV1): Promise<RouterAbEd25519YaoVerifiedWalletUnlockResponseV1>;
1039
1040
  recordEcdsaPostRegistrationProof(input: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seams/wallet-server",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "type": "module",
5
5
  "description": "Seams server TypeScript SDK for NEAR and EVM-family wallets",
6
6
  "main": "./dist/esm/index.js",