@seams/wallet-server 0.10.2 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/THIRD_PARTY_NOTICES.md +33 -1812
- package/artifact-manifest.json +28 -28
- package/cloudflare-router-ab/build/deriver-a/build-stamp.json +1 -1
- package/cloudflare-router-ab/build/deriver-a/index.js +2 -2
- package/cloudflare-router-ab/build/deriver-a/index_bg.wasm +0 -0
- package/cloudflare-router-ab/build/deriver-b/build-stamp.json +1 -1
- package/cloudflare-router-ab/build/deriver-b/index.js +2 -2
- package/cloudflare-router-ab/build/deriver-b/index_bg.wasm +0 -0
- package/cloudflare-router-ab/build/local-tools/darwin-arm64/router_ab_local_init +0 -0
- package/cloudflare-router-ab/build/local-tools/darwin-x64/router_ab_local_init +0 -0
- package/cloudflare-router-ab/build/local-tools/linux-x64/router_ab_local_init +0 -0
- package/cloudflare-router-ab/build/router/build-stamp.json +1 -1
- package/cloudflare-router-ab/build/router/index.js +2 -2
- package/cloudflare-router-ab/build/router/index_bg.wasm +0 -0
- package/cloudflare-router-ab/build/signing-worker/build-stamp.json +1 -1
- package/cloudflare-router-ab/build/signing-worker/index.js +2 -2
- package/cloudflare-router-ab/build/signing-worker/index_bg.wasm +0 -0
- package/cloudflare-router-ab/build/tenant-root-control-plane/build-stamp.json +1 -1
- package/cloudflare-router-ab/build/tenant-root-control-plane/index.js +2 -2
- package/cloudflare-router-ab/build/tenant-root-control-plane/index_bg.wasm +0 -0
- package/cloudflare-router-ab/scripts/start-local-role-workers.mjs +3 -0
- package/cloudflare-router-ab/scripts/start-local-wallet-system.mjs +3 -0
- package/dist/esm/cloud-host.js +7 -7
- package/dist/esm/core/ThresholdService/kv.js +1 -218
- package/dist/esm/hosted-wallet-gateway.js +1 -1
- package/dist/esm/index.js +3 -4
- package/dist/esm/localHostedWalletGatewayHandler.js +17 -11
- package/dist/esm/localIntendedYaoFault.js +34 -3
- package/dist/esm/localIntendedYaoRecoveryFault.js +19 -16
- package/dist/esm/localIntendedYaoSigningFault.js +31 -16
- package/dist/esm/router/auth/routerApiKeyAuth.js +1 -13
- package/dist/esm/router/cloudflare/d1/auth/d1RouterApiAuthService.js +3 -3
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceOwnerAuthorizationProvider.js +1 -1
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRecords.js +1 -1
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRecoveryService.js +1 -1
- package/dist/esm/router/cloudflare/d1/emailOtp/d1GoogleEmailOtpSessionResolver.js +1 -1
- package/dist/esm/router/cloudflare/d1/registration/d1RegistrationCeremonyRecordStore.js +19 -0
- package/dist/esm/router/cloudflare/d1/registration/d1RegistrationCeremonyRecords.js +5 -5
- package/dist/esm/router/cloudflare/d1/registration/d1RegistrationCeremonyStore.js +5 -2
- package/dist/esm/router/cloudflare/d1/registration/d1RegistrationSetupSupport.js +7 -1
- package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationCommitStore.js +29 -4
- package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationRead.js +6 -3
- package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationService.js +51 -29
- package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationSetupExecution.js +23 -7
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAddSignerFinalizeRecord.js +1 -1
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAddSignerService.js +2 -2
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthMethodService.js +3 -3
- package/dist/esm/router/cloudflare/d1/webauthn/d1WebAuthnAuthService.js +1 -1
- package/dist/esm/router/cloudflare/d1/webauthn/d1WebAuthnRecords.js +1 -1
- package/dist/esm/router/cloudflare-adaptor.js +2 -3
- package/dist/esm/router/cloudflare.js +2470 -2515
- package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistration.js +1 -1
- package/dist/esm/router/domains/walletRegistration/walletRegistrationRoutes.js +39 -32
- package/dist/esm/router/framework/registrationSetupDispatch.js +11 -3
- package/dist/esm/router/framework/routeResponses.js +1 -5
- package/dist/esm/router/transport/fetch/routes/deviceLinkingOwnerAuthorization.js +1 -1
- package/dist/esm/router/transport/fetch/routes/passkeyCustody.js +2 -2
- package/dist/esm/router/transport/fetch/routes/thresholdEd25519.js +51 -24
- package/dist/esm/shared-ts/src/utils/validation.js +5 -1
- package/dist/esm/threshold/session/signingSessionSeal/guards/backends.js +2 -98
- package/dist/esm/threshold/session/signingSessionSeal/idempotencyBackends.js +2 -69
- package/dist/esm/threshold/session/signingSessionSeal/index.js +3 -4
- package/dist/esm/wasm/evm_crypto/pkg/evm_crypto_bg.wasm +0 -0
- package/dist/esm/wasm/near_signer/pkg/wasm_signer_worker_bg.wasm +0 -0
- package/dist/esm/wasm/shamir3pass_runtime/pkg/shamir3pass_runtime_bg.wasm +0 -0
- package/dist/types/wallet-server/src/cloud-host.d.ts +1 -0
- package/dist/types/wallet-server/src/core/ThresholdService/kv.d.ts +0 -29
- package/dist/types/wallet-server/src/localHostedWalletGatewayHandler.d.ts +1 -1
- package/dist/types/wallet-server/src/localIntendedYaoFault.d.ts +13 -3
- package/dist/types/wallet-server/src/localIntendedYaoRecoveryFault.d.ts +4 -2
- package/dist/types/wallet-server/src/localIntendedYaoSigningFault.d.ts +4 -2
- package/dist/types/wallet-server/src/router/auth/routerApiKeyAuth.d.ts +0 -8
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationCeremonyRecordStore.d.ts +2 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationCeremonyStore.d.ts +1 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationSetupSupport.d.ts +2 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationCommitStore.d.ts +25 -5
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationRead.d.ts +15 -0
- package/dist/types/wallet-server/src/router/cloudflare-adaptor.d.ts +1 -3
- package/dist/types/wallet-server/src/router/domains/walletRegistration/walletRegistrationInputs.d.ts +2 -0
- package/dist/types/wallet-server/src/router/framework/routeResponses.d.ts +0 -2
- package/dist/types/wallet-server/src/threshold/session/signingSessionSeal/guards/backends.d.ts +1 -16
- package/dist/types/wallet-server/src/threshold/session/signingSessionSeal/idempotencyBackends.d.ts +1 -16
- package/dist/types/wallet-server/src/threshold/session/signingSessionSeal/index.d.ts +5 -6
- package/package.json +2 -9
- package/src/README.md +5 -3
- package/dist/esm/router/cloudflare/runtime/createSelfHostedCloudflareSigningWorker.js +0 -93
- package/dist/esm/router/express-adaptor.js +0 -84
- package/dist/esm/router/express.js +0 -26400
- package/dist/esm/router/node/nodeHostedWalletGateway.js +0 -64
- package/dist/esm/router/node/nodeHostedWalletGatewayCheck.js +0 -163
- package/dist/esm/router/node/nodeHostedWalletGatewayMain.js +0 -120
- package/dist/esm/router/node/nodeHttp.js +0 -79
- package/dist/esm/router/node/nodeSqlite.js +0 -43
- package/dist/esm/router/node/signerSqlMigrations.js +0 -48
- package/dist/esm/storage/syncSqlite.js +0 -79
- package/dist/esm/threshold/session/signingSessionSeal/transport/express.js +0 -75
- package/dist/types/wallet-server/src/router/cloudflare/runtime/createSelfHostedCloudflareSigningWorker.d.ts +0 -23
- package/dist/types/wallet-server/src/router/express-adaptor.d.ts +0 -22
- package/dist/types/wallet-server/src/router/node/nodeHostedWalletGateway.d.ts +0 -34
- package/dist/types/wallet-server/src/router/node/nodeHostedWalletGatewayCheck.d.ts +0 -21
- package/dist/types/wallet-server/src/router/node/nodeHostedWalletGatewayMain.d.ts +0 -2
- package/dist/types/wallet-server/src/router/node/nodeHttp.d.ts +0 -13
- package/dist/types/wallet-server/src/router/node/nodeSqlite.d.ts +0 -22
- package/dist/types/wallet-server/src/router/node/signerSqlMigrations.d.ts +0 -20
- package/dist/types/wallet-server/src/storage/syncSqlite.d.ts +0 -28
- package/dist/types/wallet-server/src/threshold/session/signingSessionSeal/transport/express.d.ts +0 -12
|
@@ -7,8 +7,8 @@ import { secureRandomBase64Url } from "../../../../shared-ts/src/utils/secureRan
|
|
|
7
7
|
import { ROUTER_AB_ED25519_NORMAL_SIGNING_STATE_KIND } from "../../../../shared-ts/src/utils/signingSessionSeal.js";
|
|
8
8
|
import { computeAddSignerNearEd25519SigningKeyId, computeRegistrationNearEd25519SigningKeyId } from "../../../../shared-ts/src/utils/registrationIds.js";
|
|
9
9
|
import { registrationNearEd25519BranchKey } from "../../../../shared-ts/src/utils/registrationSignerPlan.js";
|
|
10
|
-
import "../../../../shared-ts/src/threshold/sessionPolicy.js";
|
|
11
10
|
import { thresholdEd25519AuthorityScopeFromWalletAuthAuthority } from "../../../../core/ThresholdService/validation.js";
|
|
11
|
+
import "../../../../shared-ts/src/threshold/sessionPolicy.js";
|
|
12
12
|
import { createRouterApiModule } from "../../../framework/modules.js";
|
|
13
13
|
import { InMemoryRouterAbEd25519YaoRegistrationStateV1, createRouterAbEd25519YaoRegistrationModule } from "../registration/routerAbEd25519YaoRegistration.js";
|
|
14
14
|
import { InMemoryRouterAbEd25519YaoRegistrationIntentAuthorizationStateV1 } from "../registration/routerAbEd25519YaoRegistrationIntentAuthorization.js";
|
|
@@ -14,6 +14,13 @@ import { parseHostedWalletSessionOperationCredentialToken, parsePrimaryWalletSes
|
|
|
14
14
|
import { normalizeCorsOrigin } from "../../../core/SessionService.js";
|
|
15
15
|
import { thresholdEcdsaChainTargetFromValue } from "../../../core/thresholdEcdsaChainTarget.js";
|
|
16
16
|
import { walletIdFromString } from "../../../shared-ts/src/utils/registrationIds.js";
|
|
17
|
+
import { deriveImplicitNearAccountIdFromEd25519PublicKey, parseImplicitNearAccountId } from "../../../shared-ts/src/utils/near.js";
|
|
18
|
+
import { normalizeRegistrationSignerPlan, registrationSignerSetSelectionFromPlan } from "../../../shared-ts/src/utils/registrationSignerPlan.js";
|
|
19
|
+
import { addAuthMethodIntentGrantFromString, addSignerIntentGrantFromString, computeAddAuthMethodIntentDigestB64u, computeAddSignerIntentDigestB64u, normalizeAddAuthMethodIntentCaller } from "../../../shared-ts/src/utils/registrationIntent.js";
|
|
20
|
+
import { parsePasskeyCustodyEnvelopeRecord } from "../../../shared-ts/src/passkey-custody/custodyEnvelope.js";
|
|
21
|
+
import "../../../shared-ts/src/passkey-custody/index.js";
|
|
22
|
+
import { parseRouterAbTraceContextV1 } from "../../../shared-ts/src/utils/routerAbTraceContext.js";
|
|
23
|
+
import { recordRegistrationServerTiming, registrationServerTimingHeaders } from "../../cloudflare/d1/registration/d1RegistrationSetupSupport.js";
|
|
17
24
|
import { parseRegistrationSetupOperationId } from "../../../shared-ts/src/utils/registrationSetupOperation.js";
|
|
18
25
|
import { extractBearerCredential, extractRouterApiEnvironmentId } from "../../auth/routerApiKeyAuth.js";
|
|
19
26
|
import { publishableKeyRoutePrincipal, resolvePublishableKeyApiCredentialAuth, resolveWalletRegistrationContext } from "../../auth/routerApiCredentialAuth.js";
|
|
@@ -21,13 +28,7 @@ import { resolveActiveRuntimePolicyScopeForEnvironment, resolveWalletSessionAdmi
|
|
|
21
28
|
import { enforceRoutePolicy } from "../../framework/enforceRoutePolicy.js";
|
|
22
29
|
import { parseRegistrationPreparedSessionSeal } from "./registrationSessionSeal.js";
|
|
23
30
|
import { routeError, routeJson } from "../../framework/routeResponses.js";
|
|
24
|
-
import { parsePasskeyCustodyEnvelopeRecord } from "../../../shared-ts/src/passkey-custody/custodyEnvelope.js";
|
|
25
|
-
import "../../../shared-ts/src/passkey-custody/index.js";
|
|
26
31
|
import { computeWalletEcdsaKeyFactsInventoryChallengeDigestB64u } from "../../../shared-ts/src/utils/ecdsaKeyFactsInventory.js";
|
|
27
|
-
import { deriveImplicitNearAccountIdFromEd25519PublicKey, parseImplicitNearAccountId } from "../../../shared-ts/src/utils/near.js";
|
|
28
|
-
import { normalizeRegistrationSignerPlan, registrationSignerSetSelectionFromPlan } from "../../../shared-ts/src/utils/registrationSignerPlan.js";
|
|
29
|
-
import { addAuthMethodIntentGrantFromString, addSignerIntentGrantFromString, computeAddAuthMethodIntentDigestB64u, computeAddSignerIntentDigestB64u, normalizeAddAuthMethodIntentCaller } from "../../../shared-ts/src/utils/registrationIntent.js";
|
|
30
|
-
import { parseRouterAbTraceContextV1 } from "../../../shared-ts/src/utils/routerAbTraceContext.js";
|
|
31
32
|
//#region src/router/domains/walletRegistration/walletRegistrationRoutes.ts
|
|
32
33
|
function parseRegistrationTraceContext(headers) {
|
|
33
34
|
const parsed = parseRouterAbTraceContextV1(headers["x-seams-trace-id"] ?? headers["X-Seams-Trace-Id"]);
|
|
@@ -1573,6 +1574,8 @@ async function handleRouterApiWalletRegistrationSetup(input) {
|
|
|
1573
1574
|
if (!registrationContext) return routeError(500, "route_auth_not_configured", "Wallet registration context is not configured");
|
|
1574
1575
|
const request = parseWalletRegistrationSetupRequest(input.body);
|
|
1575
1576
|
if (!request.ok) return routeError(400, request.code, request.message);
|
|
1577
|
+
const serverTiming = [];
|
|
1578
|
+
const contextStartedAtMs = Date.now();
|
|
1576
1579
|
const context = await resolveWalletRegistrationContext({
|
|
1577
1580
|
registration: request.value,
|
|
1578
1581
|
environmentId: extractRouterApiEnvironmentId(input.headers) || void 0,
|
|
@@ -1585,11 +1588,13 @@ async function handleRouterApiWalletRegistrationSetup(input) {
|
|
|
1585
1588
|
route: input.route,
|
|
1586
1589
|
routeAuthNotConfiguredMessage: "Wallet registration setup requires API credential auth policy"
|
|
1587
1590
|
});
|
|
1591
|
+
recordRegistrationServerTiming(serverTiming, "setup_context", contextStartedAtMs);
|
|
1588
1592
|
if (!context.ok) {
|
|
1589
1593
|
if (context.status === 401) return routeError(401, "unauthorized", `${context.code}: ${context.message}`);
|
|
1590
1594
|
if (context.status === 403) return routeError(403, "forbidden", `${context.code}: ${context.message}`);
|
|
1591
1595
|
return routeError(context.status, "internal", `${context.code}: ${context.message}`);
|
|
1592
1596
|
}
|
|
1597
|
+
const policyStartedAtMs = Date.now();
|
|
1593
1598
|
const resolved = await enforceRoutePolicy({
|
|
1594
1599
|
headers: input.headers,
|
|
1595
1600
|
logger: input.logger,
|
|
@@ -1602,23 +1607,29 @@ async function handleRouterApiWalletRegistrationSetup(input) {
|
|
|
1602
1607
|
sourceIp: input.sourceIp,
|
|
1603
1608
|
resolvers: { apiCredentials: publishableKeyRoutePrincipal.bind(void 0, context.principal) }
|
|
1604
1609
|
});
|
|
1610
|
+
recordRegistrationServerTiming(serverTiming, "setup_route_policy", policyStartedAtMs);
|
|
1605
1611
|
if (!resolved.ok) return routeJson(resolved.status, resolved.body);
|
|
1606
1612
|
const principal = context.principal;
|
|
1607
|
-
if (input.services.registrationSetupRateLimit)
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1613
|
+
if (input.services.registrationSetupRateLimit) {
|
|
1614
|
+
const limitStartedAtMs = Date.now();
|
|
1615
|
+
try {
|
|
1616
|
+
const limit = await input.services.registrationSetupRateLimit({
|
|
1617
|
+
apiKeyId: principal.apiKeyId,
|
|
1618
|
+
orgId: principal.orgId,
|
|
1619
|
+
projectId: context.environment.projectId,
|
|
1620
|
+
envId: context.environment.key,
|
|
1621
|
+
sourceIp: input.sourceIp || "unknown"
|
|
1622
|
+
});
|
|
1623
|
+
recordRegistrationServerTiming(serverTiming, "setup_rate_limit", limitStartedAtMs);
|
|
1624
|
+
if (!limit.allowed) return routeJson(429, {
|
|
1625
|
+
ok: false,
|
|
1626
|
+
code: "rate_limited",
|
|
1627
|
+
message: "Too many registration attempts. Wait one minute and try again.",
|
|
1628
|
+
retryAfterMs: 6e4
|
|
1629
|
+
});
|
|
1630
|
+
} catch {
|
|
1631
|
+
return routeError(503, "internal", "Registration setup rate limit is unavailable");
|
|
1632
|
+
}
|
|
1622
1633
|
}
|
|
1623
1634
|
const runtimePolicyScope = {
|
|
1624
1635
|
orgId: principal.orgId,
|
|
@@ -1635,7 +1646,8 @@ async function handleRouterApiWalletRegistrationSetup(input) {
|
|
|
1635
1646
|
signer: session,
|
|
1636
1647
|
runtimePolicyScope,
|
|
1637
1648
|
signingRootId: `${runtimePolicyScope.projectId}:${runtimePolicyScope.envId}`,
|
|
1638
|
-
signingRootVersion: runtimePolicyScope.signingRootVersion
|
|
1649
|
+
signingRootVersion: runtimePolicyScope.signingRootVersion,
|
|
1650
|
+
serverTiming
|
|
1639
1651
|
});
|
|
1640
1652
|
}
|
|
1641
1653
|
/**
|
|
@@ -1659,7 +1671,7 @@ async function handleRouterApiWalletRegistrationRespond(input) {
|
|
|
1659
1671
|
verifier: session,
|
|
1660
1672
|
...registrationUserAgentFromHeaders(input.headers) ? { userAgent: registrationUserAgentFromHeaders(input.headers) } : {}
|
|
1661
1673
|
}, traceContext.value ?? void 0, serverTiming, input.waitUntil);
|
|
1662
|
-
return routeJson(result.ok ? 200 : result.code === "storage_unavailable" ? 503 : 400, result, { headers:
|
|
1674
|
+
return routeJson(result.ok ? 200 : result.code === "storage_unavailable" ? 503 : 400, result, { headers: registrationServerTimingHeaders(serverTiming) });
|
|
1663
1675
|
}
|
|
1664
1676
|
async function handleRouterApiWalletRegistrationNearAdmission(input) {
|
|
1665
1677
|
const traceContext = parseRegistrationTraceContext(input.headers);
|
|
@@ -1882,7 +1894,7 @@ async function handleRouterApiWalletRegistrationActivate(input) {
|
|
|
1882
1894
|
}, traceContext.value ?? void 0, serverTiming);
|
|
1883
1895
|
if (!result.ok) return routeJson(400, result);
|
|
1884
1896
|
if (!isEmailOtpWalletRegistrationActivateSuccessV2(result) && !isPasskeyWalletRegistrationActivateSuccessV2(result)) return routeError(500, "internal", "Wallet registration activation returned an invalid authority");
|
|
1885
|
-
return routeJson(200, result, { headers:
|
|
1897
|
+
return routeJson(200, result, { headers: registrationServerTimingHeaders(serverTiming) });
|
|
1886
1898
|
}
|
|
1887
1899
|
/**
|
|
1888
1900
|
* Commits a NEAR-only wallet or completes a mixed wallet's deferred signer.
|
|
@@ -1922,18 +1934,13 @@ async function handleRouterApiWalletRegistrationNearProvisioning(input) {
|
|
|
1922
1934
|
ok: false,
|
|
1923
1935
|
code: sealed.code,
|
|
1924
1936
|
message: sealed.message
|
|
1925
|
-
}, { headers:
|
|
1937
|
+
}, { headers: registrationServerTimingHeaders(serverTiming) });
|
|
1926
1938
|
return routeJson(200, {
|
|
1927
1939
|
...result,
|
|
1928
1940
|
sessionSeal: sealed.value
|
|
1929
|
-
}, { headers:
|
|
1941
|
+
}, { headers: registrationServerTimingHeaders(serverTiming) });
|
|
1930
1942
|
}
|
|
1931
|
-
return routeJson(200, result, { headers:
|
|
1932
|
-
}
|
|
1933
|
-
function ecdsaGatewayServerTimingHeaders(serverTiming) {
|
|
1934
|
-
if (serverTiming.length === 0) return void 0;
|
|
1935
|
-
const header = serverTiming.map(([name, durationMs]) => `${name};dur=${Math.max(0, durationMs).toFixed(1)}`).join(", ");
|
|
1936
|
-
return { "Server-Timing": header };
|
|
1943
|
+
return routeJson(200, result, { headers: registrationServerTimingHeaders(serverTiming) });
|
|
1937
1944
|
}
|
|
1938
1945
|
async function handleRouterApiWalletAddSignerStart(input) {
|
|
1939
1946
|
if (!isPlainObject(input.body)) return routeError(400, "invalid_body", "JSON body required");
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { recordRegistrationServerTiming, registrationServerTimingHeaders } from "../cloudflare/d1/registration/d1RegistrationSetupSupport.js";
|
|
1
2
|
//#region src/router/framework/registrationSetupDispatch.ts
|
|
2
3
|
/** A transient storage fault outlived its retries. The same request can succeed later. */
|
|
3
4
|
const SETUP_STORAGE_UNAVAILABLE = {
|
|
@@ -9,17 +10,23 @@ const SETUP_INTERNAL_FAILURE = {
|
|
|
9
10
|
message: "Wallet registration setup failed"
|
|
10
11
|
};
|
|
11
12
|
async function dispatchWalletRegistrationSetup(context, input) {
|
|
13
|
+
const serverTiming = input.serverTiming ?? [];
|
|
14
|
+
const dispatchStartedAtMs = Date.now();
|
|
12
15
|
const forwarded = await context.dispatcher?.dispatch(input);
|
|
13
16
|
if (forwarded) return forwarded;
|
|
17
|
+
recordRegistrationServerTiming(serverTiming, "setup_dispatch", dispatchStartedAtMs);
|
|
14
18
|
const result = await context.local.setupWalletRegistration(input);
|
|
19
|
+
const headers = registrationServerTimingHeaders(serverTiming);
|
|
15
20
|
if (result.ok) return {
|
|
16
21
|
status: 200,
|
|
17
|
-
body: result
|
|
22
|
+
body: result,
|
|
23
|
+
...headers ? { headers } : {}
|
|
18
24
|
};
|
|
19
25
|
const serverFailure = result.code === "storage_unavailable" ? SETUP_STORAGE_UNAVAILABLE : result.code === "internal" ? SETUP_INTERNAL_FAILURE : null;
|
|
20
26
|
if (!serverFailure) return {
|
|
21
27
|
status: 400,
|
|
22
|
-
body: result
|
|
28
|
+
body: result,
|
|
29
|
+
...headers ? { headers } : {}
|
|
23
30
|
};
|
|
24
31
|
console.error("[wallet-registration] setup failed", {
|
|
25
32
|
code: result.code,
|
|
@@ -31,7 +38,8 @@ async function dispatchWalletRegistrationSetup(context, input) {
|
|
|
31
38
|
ok: false,
|
|
32
39
|
code: result.code,
|
|
33
40
|
message: serverFailure.message
|
|
34
|
-
}
|
|
41
|
+
},
|
|
42
|
+
...headers ? { headers } : {}
|
|
35
43
|
};
|
|
36
44
|
}
|
|
37
45
|
//#endregion
|
|
@@ -14,10 +14,6 @@ function routeError(status, code, message) {
|
|
|
14
14
|
message
|
|
15
15
|
});
|
|
16
16
|
}
|
|
17
|
-
function sendExpressRouteResponse(res, response) {
|
|
18
|
-
for (const [name, value] of Object.entries(response.headers || {})) res.set(name, value);
|
|
19
|
-
res.status(response.status).json(response.body);
|
|
20
|
-
}
|
|
21
17
|
function toFetchRouteResponse(response) {
|
|
22
18
|
return new Response(JSON.stringify(response.body), {
|
|
23
19
|
status: response.status,
|
|
@@ -28,6 +24,6 @@ function toFetchRouteResponse(response) {
|
|
|
28
24
|
});
|
|
29
25
|
}
|
|
30
26
|
//#endregion
|
|
31
|
-
export { routeError, routeJson,
|
|
27
|
+
export { routeError, routeJson, toFetchRouteResponse };
|
|
32
28
|
|
|
33
29
|
//# sourceMappingURL=routeResponses.js.map
|
|
@@ -4,9 +4,9 @@ import { sha256DigestB64u } from "../../../../shared-ts/src/utils/canonicalPrimi
|
|
|
4
4
|
import { buildEmailOtpWalletAuthAuthority, buildPasskeyWalletAuthAuthority, walletAuthAuthorityRef } from "../../../../shared-ts/src/utils/walletAuthAuthority.js";
|
|
5
5
|
import { parseLinkedDeviceOwnerAuthorizationRequestV1 } from "../../../../shared-ts/src/device-linking/parsers.js";
|
|
6
6
|
import { buildWalletSessionCapabilitySubjectsV1, walletSessionCapabilitySubjectsV1Equal } from "../../../../authorization/domain.js";
|
|
7
|
+
import { thresholdEd25519AuthorityScopeFromWalletAuthAuthority } from "../../../../core/ThresholdService/validation.js";
|
|
7
8
|
import { extractBearerCredential } from "../../../auth/routerApiKeyAuth.js";
|
|
8
9
|
import { json, jsonFailure, readJson } from "../../../framework/http.js";
|
|
9
|
-
import { thresholdEd25519AuthorityScopeFromWalletAuthAuthority } from "../../../../core/ThresholdService/validation.js";
|
|
10
10
|
//#region src/router/transport/fetch/routes/deviceLinkingOwnerAuthorization.ts
|
|
11
11
|
const LINKED_DEVICE_OWNER_AUTHORIZATION_PATH_V1 = "/wallet/device-linking/v1/owner-authorization";
|
|
12
12
|
/**
|
|
@@ -10,10 +10,10 @@ import { buildPasskeyWalletAuthAuthority, walletAuthAuthorityRef } from "../../.
|
|
|
10
10
|
import { parseSessionOrigin, parseVerifiedOwnerProofId } from "../../../../authorization/domain.js";
|
|
11
11
|
import { buildVerifiedWalletOperationEmailOtpFactorResult, buildVerifiedWalletOperationPasskeyFactorResult } from "../../../../authorization/factorEvidence.js";
|
|
12
12
|
import { findRouteDefinitionById, matchesRouteDefinitionRequest } from "../../../framework/routeDefinitions.js";
|
|
13
|
-
import { extractBearerCredential, resolveSourceIpFromFetchHeaders } from "../../../auth/routerApiKeyAuth.js";
|
|
14
|
-
import { toFetchRouteResponse } from "../../../framework/routeResponses.js";
|
|
15
13
|
import { parsePasskeyCustodyEnvelopeRecord } from "../../../../shared-ts/src/passkey-custody/custodyEnvelope.js";
|
|
16
14
|
import "../../../../shared-ts/src/passkey-custody/index.js";
|
|
15
|
+
import { extractBearerCredential, resolveSourceIpFromFetchHeaders } from "../../../auth/routerApiKeyAuth.js";
|
|
16
|
+
import { toFetchRouteResponse } from "../../../framework/routeResponses.js";
|
|
17
17
|
import { readJson } from "../../../framework/http.js";
|
|
18
18
|
import { isHostWithinRpId, originHostnameOrEmpty } from "../../../../core/authService/webauthnOidcHelpers.js";
|
|
19
19
|
import { parseRecoveryCodeReservationId } from "../../../../shared-ts/src/wallet-recovery/recoveryCodeReservation.js";
|
|
@@ -890,7 +890,34 @@ async function proxyEd25519OwnerLaneExecution(input) {
|
|
|
890
890
|
});
|
|
891
891
|
}
|
|
892
892
|
async function handleRouterAbEd25519NormalSigningRoute(input) {
|
|
893
|
-
const
|
|
893
|
+
const startedAt = performance.now();
|
|
894
|
+
const timing = {
|
|
895
|
+
authorize: null,
|
|
896
|
+
admit: null,
|
|
897
|
+
proxy: null,
|
|
898
|
+
complete: null,
|
|
899
|
+
total: null
|
|
900
|
+
};
|
|
901
|
+
const response = await executeRouterAbEd25519NormalSigningRoute(input, timing);
|
|
902
|
+
timing.total = performance.now() - startedAt;
|
|
903
|
+
const headers = new Headers(response.headers);
|
|
904
|
+
for (const [stage, duration] of Object.entries(timing)) if (duration !== null) headers.append("Server-Timing", `ed25519_sign_${stage};dur=${Math.max(0, duration).toFixed(1)}`);
|
|
905
|
+
return new Response(response.body, {
|
|
906
|
+
status: response.status,
|
|
907
|
+
statusText: response.statusText,
|
|
908
|
+
headers
|
|
909
|
+
});
|
|
910
|
+
}
|
|
911
|
+
async function timeEd25519SigningStage(timing, stage, pending) {
|
|
912
|
+
const startedAt = performance.now();
|
|
913
|
+
try {
|
|
914
|
+
return await pending;
|
|
915
|
+
} finally {
|
|
916
|
+
timing[stage] = performance.now() - startedAt;
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
async function executeRouterAbEd25519NormalSigningRoute(input, timing) {
|
|
920
|
+
const authorization = await timeEd25519SigningStage(timing, "authorize", authorizeRouterAbEd25519NormalSigningRoute({
|
|
894
921
|
body: input.body,
|
|
895
922
|
rawBody: input.body,
|
|
896
923
|
headers: Object.fromEntries(input.ctx.request.headers.entries()),
|
|
@@ -900,7 +927,7 @@ async function handleRouterAbEd25519NormalSigningRoute(input) {
|
|
|
900
927
|
admissionAdapter: input.ctx.opts.routerAbNormalSigningAdmission,
|
|
901
928
|
resolveEd25519MaterialActivation: input.ctx.service.walletRegistration.resolveEd25519MaterialActivation.bind(input.ctx.service.walletRegistration),
|
|
902
929
|
phase: input.phase
|
|
903
|
-
});
|
|
930
|
+
}));
|
|
904
931
|
if (!authorization.ok) return json(authorization.result.body, { status: authorization.result.status });
|
|
905
932
|
if (authorization.kind === "operation_step_up") {
|
|
906
933
|
if (input.phase === "prepare") {
|
|
@@ -910,7 +937,7 @@ async function handleRouterAbEd25519NormalSigningRoute(input) {
|
|
|
910
937
|
operation: authorization.operation
|
|
911
938
|
});
|
|
912
939
|
if (execution.kind !== "execute") return execution.response;
|
|
913
|
-
const upstream = await proxyEd25519OwnerLaneExecution({
|
|
940
|
+
const upstream = await timeEd25519SigningStage(timing, "proxy", proxyEd25519OwnerLaneExecution({
|
|
914
941
|
ctx: input.ctx,
|
|
915
942
|
authorization,
|
|
916
943
|
authorizedOperation: execution.operation,
|
|
@@ -921,7 +948,7 @@ async function handleRouterAbEd25519NormalSigningRoute(input) {
|
|
|
921
948
|
binding: await ed25519OperationStepUpBinding(input.ctx, authorization.session, execution.operation)
|
|
922
949
|
})
|
|
923
950
|
}
|
|
924
|
-
});
|
|
951
|
+
}));
|
|
925
952
|
const upstreamBodyText = await upstream.clone().text().catch(() => "");
|
|
926
953
|
let upstreamBody = null;
|
|
927
954
|
try {
|
|
@@ -933,7 +960,7 @@ async function handleRouterAbEd25519NormalSigningRoute(input) {
|
|
|
933
960
|
status: upstream.status,
|
|
934
961
|
bodyText: upstreamBodyText
|
|
935
962
|
})) return upstream;
|
|
936
|
-
if (!upstream.ok || !isPlainObject(upstreamBody)) return requireCompletedEd25519OperationResponse(await completeEd25519Operation({
|
|
963
|
+
if (!upstream.ok || !isPlainObject(upstreamBody)) return requireCompletedEd25519OperationResponse(await timeEd25519SigningStage(timing, "complete", completeEd25519Operation({
|
|
937
964
|
ctx: input.ctx,
|
|
938
965
|
operation: execution.operation,
|
|
939
966
|
result: upstream.status < 500 ? "failed_before_side_effect" : "failed_after_side_effect",
|
|
@@ -941,7 +968,7 @@ async function handleRouterAbEd25519NormalSigningRoute(input) {
|
|
|
941
968
|
response: upstream,
|
|
942
969
|
bodyText: upstreamBodyText
|
|
943
970
|
})
|
|
944
|
-
}));
|
|
971
|
+
})));
|
|
945
972
|
const headers = new Headers(upstream.headers);
|
|
946
973
|
headers.delete("content-length");
|
|
947
974
|
return new Response(JSON.stringify(signingPrepareSessionResponse({
|
|
@@ -954,15 +981,15 @@ async function handleRouterAbEd25519NormalSigningRoute(input) {
|
|
|
954
981
|
});
|
|
955
982
|
}
|
|
956
983
|
if (authorization.phase !== "finalize") throw new Error("Operation step-up finalize authorization phase changed");
|
|
957
|
-
const validatedAuthorization = await validateEd25519VerifiedStepUpAuthorizedOperation({
|
|
984
|
+
const validatedAuthorization = await timeEd25519SigningStage(timing, "admit", validateEd25519VerifiedStepUpAuthorizedOperation({
|
|
958
985
|
ctx: input.ctx,
|
|
959
986
|
body: input.body,
|
|
960
987
|
authorization
|
|
961
|
-
});
|
|
988
|
+
}));
|
|
962
989
|
if (!validatedAuthorization.ok) return validatedAuthorization.response;
|
|
963
990
|
const replay = replayCompletedEd25519Operation(validatedAuthorization.operation);
|
|
964
991
|
if (replay) return replay;
|
|
965
|
-
const upstream = await proxyEd25519OwnerLaneExecution({
|
|
992
|
+
const upstream = await timeEd25519SigningStage(timing, "proxy", proxyEd25519OwnerLaneExecution({
|
|
966
993
|
ctx: input.ctx,
|
|
967
994
|
authorization,
|
|
968
995
|
authorizedOperation: validatedAuthorization.operation,
|
|
@@ -973,13 +1000,13 @@ async function handleRouterAbEd25519NormalSigningRoute(input) {
|
|
|
973
1000
|
binding: await ed25519OperationStepUpBinding(input.ctx, authorization.session, validatedAuthorization.operation)
|
|
974
1001
|
})
|
|
975
1002
|
}
|
|
976
|
-
});
|
|
1003
|
+
}));
|
|
977
1004
|
const upstreamBodyText = await upstream.clone().text().catch(() => "");
|
|
978
1005
|
if (isRouterAbEd25519OperationInProgressResponse({
|
|
979
1006
|
status: upstream.status,
|
|
980
1007
|
bodyText: upstreamBodyText
|
|
981
1008
|
})) return upstream;
|
|
982
|
-
return requireCompletedEd25519OperationResponse(await completeEd25519Operation({
|
|
1009
|
+
return requireCompletedEd25519OperationResponse(await timeEd25519SigningStage(timing, "complete", completeEd25519Operation({
|
|
983
1010
|
ctx: input.ctx,
|
|
984
1011
|
operation: validatedAuthorization.operation,
|
|
985
1012
|
result: upstream.ok ? "succeeded" : upstream.status < 500 ? "failed_before_side_effect" : "failed_after_side_effect",
|
|
@@ -987,14 +1014,14 @@ async function handleRouterAbEd25519NormalSigningRoute(input) {
|
|
|
987
1014
|
response: upstream,
|
|
988
1015
|
bodyText: upstreamBodyText
|
|
989
1016
|
})
|
|
990
|
-
}));
|
|
1017
|
+
})));
|
|
991
1018
|
}
|
|
992
1019
|
if (input.phase === "prepare") {
|
|
993
|
-
const authorized = await authorizeEd25519ReusableWalletSessionOperation({
|
|
1020
|
+
const authorized = await timeEd25519SigningStage(timing, "admit", authorizeEd25519ReusableWalletSessionOperation({
|
|
994
1021
|
ctx: input.ctx,
|
|
995
1022
|
body: input.body,
|
|
996
1023
|
authorization
|
|
997
|
-
});
|
|
1024
|
+
}));
|
|
998
1025
|
if (!authorized.ok) return authorized.response;
|
|
999
1026
|
const execution = decideEd25519NormalSigningExecution({
|
|
1000
1027
|
phase: "prepare",
|
|
@@ -1016,7 +1043,7 @@ async function handleRouterAbEd25519NormalSigningRoute(input) {
|
|
|
1016
1043
|
}
|
|
1017
1044
|
}
|
|
1018
1045
|
}, { status: 403 });
|
|
1019
|
-
const upstream = await proxyEd25519OwnerLaneExecution({
|
|
1046
|
+
const upstream = await timeEd25519SigningStage(timing, "proxy", proxyEd25519OwnerLaneExecution({
|
|
1020
1047
|
ctx: input.ctx,
|
|
1021
1048
|
authorization,
|
|
1022
1049
|
authorizedOperation: execution.operation,
|
|
@@ -1027,7 +1054,7 @@ async function handleRouterAbEd25519NormalSigningRoute(input) {
|
|
|
1027
1054
|
binding: buildEd25519GatewayOwnerWalletSessionBinding(authorization, pinnedEd25519WalletScope(authorization, authorized.admission.ownerScope))
|
|
1028
1055
|
})
|
|
1029
1056
|
}
|
|
1030
|
-
});
|
|
1057
|
+
}));
|
|
1031
1058
|
const upstreamBodyText = await upstream.clone().text().catch(() => "");
|
|
1032
1059
|
let upstreamBody = null;
|
|
1033
1060
|
try {
|
|
@@ -1039,7 +1066,7 @@ async function handleRouterAbEd25519NormalSigningRoute(input) {
|
|
|
1039
1066
|
status: upstream.status,
|
|
1040
1067
|
bodyText: upstreamBodyText
|
|
1041
1068
|
})) return upstream;
|
|
1042
|
-
if (!upstream.ok || !isPlainObject(upstreamBody)) return requireCompletedEd25519OperationResponse(await completeEd25519Operation({
|
|
1069
|
+
if (!upstream.ok || !isPlainObject(upstreamBody)) return requireCompletedEd25519OperationResponse(await timeEd25519SigningStage(timing, "complete", completeEd25519Operation({
|
|
1043
1070
|
ctx: input.ctx,
|
|
1044
1071
|
operation: execution.operation,
|
|
1045
1072
|
result: upstream.status < 500 ? "failed_before_side_effect" : "failed_after_side_effect",
|
|
@@ -1047,7 +1074,7 @@ async function handleRouterAbEd25519NormalSigningRoute(input) {
|
|
|
1047
1074
|
response: upstream,
|
|
1048
1075
|
bodyText: upstreamBodyText
|
|
1049
1076
|
})
|
|
1050
|
-
}));
|
|
1077
|
+
})));
|
|
1051
1078
|
const headers = new Headers(upstream.headers);
|
|
1052
1079
|
headers.delete("content-length");
|
|
1053
1080
|
return new Response(JSON.stringify(signingPrepareSessionResponse({
|
|
@@ -1059,16 +1086,16 @@ async function handleRouterAbEd25519NormalSigningRoute(input) {
|
|
|
1059
1086
|
headers
|
|
1060
1087
|
});
|
|
1061
1088
|
}
|
|
1062
|
-
const validatedAuthorization = await validateEd25519ReusableAuthorizedOperation({
|
|
1089
|
+
const validatedAuthorization = await timeEd25519SigningStage(timing, "admit", validateEd25519ReusableAuthorizedOperation({
|
|
1063
1090
|
ctx: input.ctx,
|
|
1064
1091
|
body: input.body,
|
|
1065
1092
|
authorization
|
|
1066
|
-
});
|
|
1093
|
+
}));
|
|
1067
1094
|
if (!validatedAuthorization.ok) return validatedAuthorization.response;
|
|
1068
1095
|
const replay = replayCompletedEd25519Operation(validatedAuthorization.operation);
|
|
1069
1096
|
if (replay) return replay;
|
|
1070
1097
|
if (!validatedAuthorization.ownerScope) throw new Error("Pinned owner Wallet Session scope is unavailable");
|
|
1071
|
-
const upstream = await proxyEd25519OwnerLaneExecution({
|
|
1098
|
+
const upstream = await timeEd25519SigningStage(timing, "proxy", proxyEd25519OwnerLaneExecution({
|
|
1072
1099
|
ctx: input.ctx,
|
|
1073
1100
|
authorization,
|
|
1074
1101
|
authorizedOperation: validatedAuthorization.operation,
|
|
@@ -1079,13 +1106,13 @@ async function handleRouterAbEd25519NormalSigningRoute(input) {
|
|
|
1079
1106
|
binding: buildEd25519GatewayOwnerWalletSessionBinding(authorization, pinnedEd25519WalletScope(authorization, validatedAuthorization.ownerScope))
|
|
1080
1107
|
})
|
|
1081
1108
|
}
|
|
1082
|
-
});
|
|
1109
|
+
}));
|
|
1083
1110
|
const upstreamBodyText = await upstream.clone().text().catch(() => "");
|
|
1084
1111
|
if (isRouterAbEd25519OperationInProgressResponse({
|
|
1085
1112
|
status: upstream.status,
|
|
1086
1113
|
bodyText: upstreamBodyText
|
|
1087
1114
|
})) return upstream;
|
|
1088
|
-
return requireCompletedEd25519OperationResponse(await completeEd25519Operation({
|
|
1115
|
+
return requireCompletedEd25519OperationResponse(await timeEd25519SigningStage(timing, "complete", completeEd25519Operation({
|
|
1089
1116
|
ctx: input.ctx,
|
|
1090
1117
|
operation: validatedAuthorization.operation,
|
|
1091
1118
|
result: upstream.ok ? "succeeded" : upstream.status < 500 ? "failed_before_side_effect" : "failed_after_side_effect",
|
|
@@ -1093,7 +1120,7 @@ async function handleRouterAbEd25519NormalSigningRoute(input) {
|
|
|
1093
1120
|
response: upstream,
|
|
1094
1121
|
bodyText: upstreamBodyText
|
|
1095
1122
|
})
|
|
1096
|
-
}));
|
|
1123
|
+
})));
|
|
1097
1124
|
}
|
|
1098
1125
|
async function handleThresholdEd25519(ctx) {
|
|
1099
1126
|
if (ctx.method === "GET" && ctx.pathname === "/router-ab/ed25519/healthz") {
|
|
@@ -44,7 +44,11 @@ function requireArray(value, label) {
|
|
|
44
44
|
if (!Array.isArray(value)) throw new Error(`${label} must be an array`);
|
|
45
45
|
return value;
|
|
46
46
|
}
|
|
47
|
+
function assertString(val, name = "value") {
|
|
48
|
+
if (typeof val !== "string") throw new Error(`Invalid ${name}: expected string`);
|
|
49
|
+
return val;
|
|
50
|
+
}
|
|
47
51
|
//#endregion
|
|
48
|
-
export { asRecord, coerceNonEmptyString, isFunction, isObject, isPlainObject, requireArray, requireCanonicalString, requireNonEmptyString, requireRecord, requireRecordCopy, requireRecordOrArray, requireTrimmedString };
|
|
52
|
+
export { asRecord, assertString, coerceNonEmptyString, isFunction, isObject, isPlainObject, requireArray, requireCanonicalString, requireNonEmptyString, requireRecord, requireRecordCopy, requireRecordOrArray, requireTrimmedString };
|
|
49
53
|
|
|
50
54
|
//# sourceMappingURL=validation.js.map
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { normalizeOptionalTrimmedString } from "../../../../shared-ts/src/utils/normalize.js";
|
|
2
|
-
import {
|
|
3
|
-
import { RedisTcpClient, UpstashRedisRestClient } from "../../../../core/ThresholdService/kv.js";
|
|
2
|
+
import { UpstashRedisRestClient } from "../../../../core/ThresholdService/kv.js";
|
|
4
3
|
//#region src/threshold/session/signingSessionSeal/guards/backends.ts
|
|
5
4
|
const WINDOW_COUNTER_LUA = `
|
|
6
5
|
local key = KEYS[1]
|
|
@@ -87,105 +86,10 @@ var UpstashSigningSessionSealRateLimiter = class {
|
|
|
87
86
|
}
|
|
88
87
|
}
|
|
89
88
|
};
|
|
90
|
-
function redisRespToString(resp) {
|
|
91
|
-
if (resp.type === "error") return null;
|
|
92
|
-
if (resp.type === "bulk") return typeof resp.value === "string" ? resp.value : null;
|
|
93
|
-
if (resp.type === "integer") return String(resp.value);
|
|
94
|
-
if (resp.type === "simple") return resp.value;
|
|
95
|
-
return null;
|
|
96
|
-
}
|
|
97
|
-
var RedisTcpSigningSessionSealRateLimiter = class {
|
|
98
|
-
constructor(input) {
|
|
99
|
-
this.client = new RedisTcpClient(input.redisUrl);
|
|
100
|
-
this.keyPrefix = normalizeOptionalTrimmedString(input.keyPrefix);
|
|
101
|
-
}
|
|
102
|
-
withPrefix(key) {
|
|
103
|
-
return this.keyPrefix ? `${this.keyPrefix}${key}` : key;
|
|
104
|
-
}
|
|
105
|
-
async consume(input) {
|
|
106
|
-
const key = this.withPrefix(normalizeOptionalTrimmedString(input.key));
|
|
107
|
-
if (!key) return {
|
|
108
|
-
ok: false,
|
|
109
|
-
code: "invalid_rate_limit_key",
|
|
110
|
-
message: "Rate-limit key is required"
|
|
111
|
-
};
|
|
112
|
-
try {
|
|
113
|
-
const resp = await this.client.send([
|
|
114
|
-
"EVAL",
|
|
115
|
-
WINDOW_COUNTER_LUA,
|
|
116
|
-
"1",
|
|
117
|
-
key,
|
|
118
|
-
String(Math.max(1, Math.floor(Number(input.windowMs) || 0)))
|
|
119
|
-
]);
|
|
120
|
-
if (resp.type === "error") return {
|
|
121
|
-
ok: false,
|
|
122
|
-
code: "internal",
|
|
123
|
-
message: `Redis EVAL error: ${resp.value}`
|
|
124
|
-
};
|
|
125
|
-
const parsed = parseCounterWindow(redisRespToString(resp));
|
|
126
|
-
if (!parsed) return {
|
|
127
|
-
ok: false,
|
|
128
|
-
code: "internal",
|
|
129
|
-
message: "Invalid Redis rate-limit response"
|
|
130
|
-
};
|
|
131
|
-
return finalizeConsume({
|
|
132
|
-
count: parsed.count,
|
|
133
|
-
ttlMs: parsed.ttlMs,
|
|
134
|
-
limit: Math.max(1, Math.floor(Number(input.limit) || 0)),
|
|
135
|
-
nowMs: Math.floor(Number(input.nowMs) || 0)
|
|
136
|
-
});
|
|
137
|
-
} catch (error) {
|
|
138
|
-
return {
|
|
139
|
-
ok: false,
|
|
140
|
-
code: "internal",
|
|
141
|
-
message: error instanceof Error ? error.message : String(error || "Redis rate-limit failed")
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
};
|
|
146
89
|
function createUpstashSigningSessionSealRateLimiter(options) {
|
|
147
90
|
return new UpstashSigningSessionSealRateLimiter(options);
|
|
148
91
|
}
|
|
149
|
-
function createRedisTcpSigningSessionSealRateLimiter(options) {
|
|
150
|
-
return new RedisTcpSigningSessionSealRateLimiter(options);
|
|
151
|
-
}
|
|
152
|
-
function resolveSigningSessionSealRateLimitFromEnv(input) {
|
|
153
|
-
const limiterKind = normalizeOptionalTrimmedString(input.limiterKind || "").toLowerCase();
|
|
154
|
-
const upstashUrl = normalizeOptionalTrimmedString(input.upstashUrl || "");
|
|
155
|
-
const upstashToken = normalizeOptionalTrimmedString(input.upstashToken || "");
|
|
156
|
-
const redisUrl = normalizeOptionalTrimmedString(input.redisUrl || "");
|
|
157
|
-
const keyPrefix = normalizeOptionalTrimmedString(input.keyPrefix || "") || void 0;
|
|
158
|
-
const selectedKind = limiterKind || (upstashUrl || upstashToken ? "upstash-redis-rest" : redisUrl ? "redis-tcp" : "in-memory");
|
|
159
|
-
if (selectedKind === "upstash-redis-rest") {
|
|
160
|
-
if (!upstashUrl || !upstashToken) throw new Error("Upstash Signing-session seal rate limiter requires both upstashUrl and upstashToken");
|
|
161
|
-
return {
|
|
162
|
-
limiter: createUpstashSigningSessionSealRateLimiter({
|
|
163
|
-
url: upstashUrl,
|
|
164
|
-
token: upstashToken,
|
|
165
|
-
keyPrefix
|
|
166
|
-
}),
|
|
167
|
-
limit: input.limit,
|
|
168
|
-
windowMs: input.windowMs
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
if (selectedKind === "redis-tcp") {
|
|
172
|
-
if (!redisUrl) throw new Error("Redis TCP Signing-session seal rate limiter requires redisUrl");
|
|
173
|
-
return {
|
|
174
|
-
limiter: createRedisTcpSigningSessionSealRateLimiter({
|
|
175
|
-
redisUrl,
|
|
176
|
-
keyPrefix
|
|
177
|
-
}),
|
|
178
|
-
limit: input.limit,
|
|
179
|
-
windowMs: input.windowMs
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
return {
|
|
183
|
-
limiter: createInMemorySigningSessionSealRateLimiter(),
|
|
184
|
-
limit: input.limit,
|
|
185
|
-
windowMs: input.windowMs
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
92
|
//#endregion
|
|
189
|
-
export {
|
|
93
|
+
export { createUpstashSigningSessionSealRateLimiter };
|
|
190
94
|
|
|
191
95
|
//# sourceMappingURL=backends.js.map
|