diff --git a/apps/backend/package.json b/apps/backend/package.json index 0a9d57c2d..402395ab5 100644 --- a/apps/backend/package.json +++ b/apps/backend/package.json @@ -1,6 +1,6 @@ { "name": "@stackframe/backend", - "version": "2.8.105", + "version": "2.8.106", "repository": "https://github.com/hexclave/hexclave", "private": true, "type": "module", diff --git a/apps/backend/src/app/api/latest/auth/oauth/callback/[provider_id]/route.tsx b/apps/backend/src/app/api/latest/auth/oauth/callback/[provider_id]/route.tsx index d6195fada..3e7613c3b 100644 --- a/apps/backend/src/app/api/latest/auth/oauth/callback/[provider_id]/route.tsx +++ b/apps/backend/src/app/api/latest/auth/oauth/callback/[provider_id]/route.tsx @@ -13,7 +13,7 @@ import { InvalidClientError, InvalidScopeError, Request as OAuthRequest, Respons import { KnownError, KnownErrors } from "@stackframe/stack-shared"; import { yupMixed, yupNumber, yupObject, yupString } from "@stackframe/stack-shared/dist/schema-fields"; import { HexclaveAssertionError, StatusError, captureError } from "@stackframe/stack-shared/dist/utils/errors"; -import { deindent, extractScopes } from "@stackframe/stack-shared/dist/utils/strings"; +import { deindent, extractScopes, mergeScopeStrings } from "@stackframe/stack-shared/dist/utils/strings"; import { cookies } from "next/headers"; import { redirect } from "next/navigation"; import { oauthResponseToSmartResponse } from "../../oauth-helpers"; @@ -224,12 +224,13 @@ const handler = createSmartRouteHandler({ }); const storeTokens = async (oauthAccountId: string) => { + const tokenScopes = extractScopes(mergeScopeStrings(providerObj.scope, providerScope ?? "")); if (tokenSet.refreshToken) { await prisma.oAuthToken.create({ data: { tenancyId: outerInfo.tenancyId, refreshToken: tokenSet.refreshToken, - scopes: extractScopes(providerObj.scope + " " + providerScope), + scopes: tokenScopes, oauthAccountId, } }); @@ -239,7 +240,7 @@ const handler = createSmartRouteHandler({ data: { tenancyId: outerInfo.tenancyId, accessToken: tokenSet.accessToken, - scopes: extractScopes(providerObj.scope + " " + providerScope), + scopes: tokenScopes, expiresAt: tokenSet.accessTokenExpiredAt, oauthAccountId, } diff --git a/apps/backend/src/oauth/providers/base.test.ts b/apps/backend/src/oauth/providers/base.test.ts index e17514d01..f732f6d46 100644 --- a/apps/backend/src/oauth/providers/base.test.ts +++ b/apps/backend/src/oauth/providers/base.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from "vitest"; -import { getOAuthAccessTokenRefreshError, getOAuthAccessTokenRefreshErrorDisposition, isRetryableOAuthUserInfoError } from "./base"; +import { getOAuthAccessTokenRefreshError, getOAuthAccessTokenRefreshErrorDisposition, isRetryableOAuthUserInfoError, resolveOAuthAccessTokenExpiredAt } from "./base"; describe("isRetryableOAuthUserInfoError", () => { it("returns true for openid-client timeout errors", () => { @@ -101,3 +101,32 @@ describe("getOAuthAccessTokenRefreshError", () => { }); }); }); + +describe("resolveOAuthAccessTokenExpiredAt", () => { + it("uses finite provider expires_in values", () => { + expect(resolveOAuthAccessTokenExpiredAt({ + expiresInSeconds: 120, + expiresAtSeconds: undefined, + defaultExpiresInMillis: null, + nowMillis: 1000, + })?.toISOString()).toBe("1970-01-01T00:02:01.000Z"); + }); + + it("ignores non-finite provider expires_at values and uses explicit null defaults", () => { + expect(resolveOAuthAccessTokenExpiredAt({ + expiresInSeconds: undefined, + expiresAtSeconds: Number.NaN, + defaultExpiresInMillis: null, + nowMillis: 1000, + })).toBeNull(); + }); + + it("ignores non-finite provider expiry values and falls back to one hour", () => { + expect(resolveOAuthAccessTokenExpiredAt({ + expiresInSeconds: Number.NaN, + expiresAtSeconds: Number.NaN, + defaultExpiresInMillis: undefined, + nowMillis: 1000, + })?.toISOString()).toBe("1970-01-01T01:00:01.000Z"); + }); +}); diff --git a/apps/backend/src/oauth/providers/base.tsx b/apps/backend/src/oauth/providers/base.tsx index 346c3deb8..4d57f9917 100644 --- a/apps/backend/src/oauth/providers/base.tsx +++ b/apps/backend/src/oauth/providers/base.tsx @@ -219,6 +219,48 @@ export function getOAuthAccessTokenRefreshError(error: unknown, options: { type DefaultAccessTokenExpiresInMillis = number | null | ((tokenSet: OIDCTokenSet) => number | null | undefined); +function getFiniteNumber(value: unknown): number | undefined { + return typeof value === "number" && Number.isFinite(value) ? value : undefined; +} + +function dateFromMillis(millis: number, context: string): Date { + const date = new Date(millis); + if (!Number.isFinite(date.getTime())) { + throw new HexclaveAssertionError(`Invalid OAuth access token expiry computed from ${context}`, { millis }); + } + return date; +} + +export function resolveOAuthAccessTokenExpiredAt(options: { + expiresInSeconds: unknown, + expiresAtSeconds: unknown, + defaultExpiresInMillis: number | null | undefined, + nowMillis: number, +}): Date | null { + const expiresInSeconds = getFiniteNumber(options.expiresInSeconds); + if (expiresInSeconds !== undefined) { + return dateFromMillis(options.nowMillis + expiresInSeconds * 1000, "expires_in"); + } + + const expiresAtSeconds = getFiniteNumber(options.expiresAtSeconds); + if (expiresAtSeconds !== undefined) { + return dateFromMillis(expiresAtSeconds * 1000, "expires_at"); + } + + if (options.defaultExpiresInMillis === null) { + return null; + } + + if (options.defaultExpiresInMillis !== undefined) { + if (!Number.isFinite(options.defaultExpiresInMillis)) { + throw new HexclaveAssertionError("Invalid default OAuth access token expiry", { defaultExpiresInMillis: options.defaultExpiresInMillis }); + } + return dateFromMillis(options.nowMillis + options.defaultExpiresInMillis, "provider default"); + } + + return dateFromMillis(options.nowMillis + 3600 * 1000, "generic fallback"); +} + function processTokenSet(providerName: string, tokenSet: OIDCTokenSet, defaultAccessTokenExpiresInMillis?: DefaultAccessTokenExpiresInMillis): TokenSet { if (!tokenSet.access_token) { throw new HexclaveAssertionError(`No access token received from ${providerName}.`, { tokenSet, providerName }); @@ -230,7 +272,14 @@ function processTokenSet(providerName: string, tokenSet: OIDCTokenSet, defaultAc // one-hour fallback and capture telemetry. const defaultExpiresInMillis = typeof defaultAccessTokenExpiresInMillis === "function" ? defaultAccessTokenExpiresInMillis(tokenSet) : defaultAccessTokenExpiresInMillis; - if (tokenSet.expires_in == null && tokenSet.expires_at == null && defaultExpiresInMillis === undefined) { + const hasInvalidProviderExpiry = + (tokenSet.expires_in != null && getFiniteNumber(tokenSet.expires_in) === undefined) + || (tokenSet.expires_at != null && getFiniteNumber(tokenSet.expires_at) === undefined); + if (hasInvalidProviderExpiry) { + captureError("processTokenSet", new HexclaveAssertionError(`Invalid expires_in or expires_at received from OAuth provider ${providerName}. Falling back to provider/default expiry handling`, { tokenSetKeys: Object.keys(tokenSet) })); + } + + if (getFiniteNumber(tokenSet.expires_in) === undefined && getFiniteNumber(tokenSet.expires_at) === undefined && defaultExpiresInMillis === undefined) { captureError("processTokenSet", new HexclaveAssertionError(`No expires_in or expires_at received from OAuth provider ${providerName}. Falling back to 1h`, { tokenSetKeys: Object.keys(tokenSet) })); } @@ -238,13 +287,12 @@ function processTokenSet(providerName: string, tokenSet: OIDCTokenSet, defaultAc idToken: tokenSet.id_token, accessToken: tokenSet.access_token, refreshToken: tokenSet.refresh_token, - accessTokenExpiredAt: tokenSet.expires_in != null ? - new Date(Date.now() + tokenSet.expires_in * 1000) : - tokenSet.expires_at != null ? new Date(tokenSet.expires_at * 1000) : - defaultExpiresInMillis === null ? null : - defaultExpiresInMillis !== undefined ? - new Date(Date.now() + defaultExpiresInMillis) : - new Date(Date.now() + 3600 * 1000), + accessTokenExpiredAt: resolveOAuthAccessTokenExpiredAt({ + expiresInSeconds: tokenSet.expires_in, + expiresAtSeconds: tokenSet.expires_at, + defaultExpiresInMillis, + nowMillis: Date.now(), + }), }; } diff --git a/apps/dashboard/package.json b/apps/dashboard/package.json index f4b9f34a5..5cb4babe2 100644 --- a/apps/dashboard/package.json +++ b/apps/dashboard/package.json @@ -1,6 +1,6 @@ { "name": "@stackframe/dashboard", - "version": "2.8.105", + "version": "2.8.106", "repository": "https://github.com/hexclave/hexclave", "private": true, "scripts": { diff --git a/apps/dev-launchpad/package.json b/apps/dev-launchpad/package.json index cd6dc8406..5800f5953 100644 --- a/apps/dev-launchpad/package.json +++ b/apps/dev-launchpad/package.json @@ -1,6 +1,6 @@ { "name": "@stackframe/dev-launchpad", - "version": "2.8.105", + "version": "2.8.106", "repository": "https://github.com/hexclave/hexclave", "private": true, "scripts": { diff --git a/apps/e2e/package.json b/apps/e2e/package.json index bb50b32cf..a6aa16e47 100644 --- a/apps/e2e/package.json +++ b/apps/e2e/package.json @@ -1,6 +1,6 @@ { "name": "@stackframe/e2e-tests", - "version": "2.8.105", + "version": "2.8.106", "repository": "https://github.com/hexclave/hexclave", "private": true, "type": "module", diff --git a/apps/hosted-components/package.json b/apps/hosted-components/package.json index e5864a1cc..83cdede94 100644 --- a/apps/hosted-components/package.json +++ b/apps/hosted-components/package.json @@ -1,7 +1,7 @@ { "name": "@stackframe/hosted-components", "private": true, - "version": "2.8.105", + "version": "2.8.106", "type": "module", "scripts": { "dev": "vite dev --port ${NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX:-81}09", diff --git a/apps/internal-tool/package.json b/apps/internal-tool/package.json index cf8061b9a..1efea5501 100644 --- a/apps/internal-tool/package.json +++ b/apps/internal-tool/package.json @@ -1,7 +1,7 @@ { "name": "@stackframe/internal-tool", "private": true, - "version": "2.8.105", + "version": "2.8.106", "type": "module", "scripts": { "dev": "node scripts/pre-dev.mjs && next dev --turbopack --port ${NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX:-81}41", diff --git a/apps/mcp/package.json b/apps/mcp/package.json index 6dec6b9af..1fbc7bed0 100644 --- a/apps/mcp/package.json +++ b/apps/mcp/package.json @@ -1,6 +1,6 @@ { "name": "@stackframe/mcp", - "version": "2.8.105", + "version": "2.8.106", "repository": "https://github.com/hexclave/hexclave", "private": true, "type": "module", diff --git a/apps/mock-oauth-server/package.json b/apps/mock-oauth-server/package.json index 4c0183fbf..f8c2a82e1 100644 --- a/apps/mock-oauth-server/package.json +++ b/apps/mock-oauth-server/package.json @@ -1,6 +1,6 @@ { "name": "@stackframe/mock-oauth-server", - "version": "2.8.105", + "version": "2.8.106", "repository": "https://github.com/hexclave/hexclave", "private": true, "main": "index.js", diff --git a/apps/skills/package.json b/apps/skills/package.json index d6e9e18f3..d1f1e667c 100644 --- a/apps/skills/package.json +++ b/apps/skills/package.json @@ -1,6 +1,6 @@ { "name": "@stackframe/skills", - "version": "2.8.105", + "version": "2.8.106", "repository": "https://github.com/hexclave/hexclave", "private": true, "type": "module", diff --git a/docs-mintlify/package.json b/docs-mintlify/package.json index 4be51e30a..aa5d44a1c 100644 --- a/docs-mintlify/package.json +++ b/docs-mintlify/package.json @@ -1,6 +1,6 @@ { "name": "@stackframe/docs-mintlify", - "version": "2.8.105", + "version": "2.8.106", "private": true, "scripts": { "dev": "mint dev --port ${NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX:-81}04 --no-open", diff --git a/docs/package.json b/docs/package.json index 094a0f519..1defef05a 100644 --- a/docs/package.json +++ b/docs/package.json @@ -1,6 +1,6 @@ { "name": "@stackframe/stack-docs", - "version": "2.8.105", + "version": "2.8.106", "repository": "https://github.com/hexclave/stack-auth", "description": "", "main": "index.js", diff --git a/examples/cjs-test/package.json b/examples/cjs-test/package.json index 0756434b0..790a1e797 100644 --- a/examples/cjs-test/package.json +++ b/examples/cjs-test/package.json @@ -1,6 +1,6 @@ { "name": "@stackframe/example-cjs-test", - "version": "2.8.105", + "version": "2.8.106", "repository": "https://github.com/hexclave/hexclave", "private": true, "scripts": { diff --git a/examples/convex/package.json b/examples/convex/package.json index 288d6f812..4acbf30d0 100644 --- a/examples/convex/package.json +++ b/examples/convex/package.json @@ -1,6 +1,6 @@ { "name": "@stackframe/convex-example", - "version": "2.8.105", + "version": "2.8.106", "repository": "https://github.com/hexclave/hexclave", "private": true, "scripts": { diff --git a/examples/demo/package.json b/examples/demo/package.json index a23c7b231..b9fc41d3a 100644 --- a/examples/demo/package.json +++ b/examples/demo/package.json @@ -1,6 +1,6 @@ { "name": "@stackframe/example-demo-app", - "version": "2.8.105", + "version": "2.8.106", "repository": "https://github.com/hexclave/hexclave", "description": "", "private": true, diff --git a/examples/docs-examples/package.json b/examples/docs-examples/package.json index 042217751..dc223ee83 100644 --- a/examples/docs-examples/package.json +++ b/examples/docs-examples/package.json @@ -1,6 +1,6 @@ { "name": "@stackframe/docs-examples", - "version": "2.8.105", + "version": "2.8.106", "repository": "https://github.com/hexclave/hexclave", "description": "", "private": true, diff --git a/examples/e-commerce/package.json b/examples/e-commerce/package.json index 232068c90..cc2805f78 100644 --- a/examples/e-commerce/package.json +++ b/examples/e-commerce/package.json @@ -1,6 +1,6 @@ { "name": "@stackframe/e-commerce-demo", - "version": "2.8.105", + "version": "2.8.106", "repository": "https://github.com/hexclave/hexclave", "private": true, "scripts": { diff --git a/examples/js-example/package.json b/examples/js-example/package.json index 475f48861..cb3e22b48 100644 --- a/examples/js-example/package.json +++ b/examples/js-example/package.json @@ -1,6 +1,6 @@ { "name": "@stackframe/js-example", - "version": "2.8.105", + "version": "2.8.106", "repository": "https://github.com/hexclave/hexclave", "private": true, "description": "", diff --git a/examples/lovable-react-18-example/package.json b/examples/lovable-react-18-example/package.json index 34415872c..c84b80eb9 100644 --- a/examples/lovable-react-18-example/package.json +++ b/examples/lovable-react-18-example/package.json @@ -1,7 +1,7 @@ { "name": "@stackframe/lovable-react-18-example", "private": true, - "version": "2.8.105", + "version": "2.8.106", "repository": "https://github.com/hexclave/hexclave", "type": "module", "scripts": { diff --git a/examples/middleware/package.json b/examples/middleware/package.json index 64cf66e81..9cfd8089a 100644 --- a/examples/middleware/package.json +++ b/examples/middleware/package.json @@ -1,6 +1,6 @@ { "name": "@stackframe/example-middleware-demo", - "version": "2.8.105", + "version": "2.8.106", "repository": "https://github.com/hexclave/hexclave", "private": true, "scripts": { diff --git a/examples/react-example/package.json b/examples/react-example/package.json index 2b1d7f91c..9f38edc29 100644 --- a/examples/react-example/package.json +++ b/examples/react-example/package.json @@ -1,7 +1,7 @@ { "name": "react-example", "private": true, - "version": "2.8.105", + "version": "2.8.106", "repository": "https://github.com/hexclave/hexclave", "type": "module", "scripts": { diff --git a/examples/supabase/package.json b/examples/supabase/package.json index 2025def9a..6aeb8df6b 100644 --- a/examples/supabase/package.json +++ b/examples/supabase/package.json @@ -1,6 +1,6 @@ { "name": "@stackframe/example-supabase", - "version": "2.8.105", + "version": "2.8.106", "repository": "https://github.com/hexclave/hexclave", "private": true, "scripts": { diff --git a/examples/tanstack-start-demo/package.json b/examples/tanstack-start-demo/package.json index 380f3c3ff..62705473f 100644 --- a/examples/tanstack-start-demo/package.json +++ b/examples/tanstack-start-demo/package.json @@ -1,6 +1,6 @@ { "name": "@stackframe/example-tanstack-start-demo", - "version": "2.8.105", + "version": "2.8.106", "repository": "https://github.com/hexclave/hexclave", "description": "TanStack Start demo app for Hexclave", "private": true, diff --git a/packages/dashboard-ui-components/package.json b/packages/dashboard-ui-components/package.json index dbc666416..e8d52c810 100644 --- a/packages/dashboard-ui-components/package.json +++ b/packages/dashboard-ui-components/package.json @@ -1,6 +1,6 @@ { "name": "@stackframe/dashboard-ui-components", - "version": "2.8.105", + "version": "2.8.106", "repository": "https://github.com/hexclave/hexclave", "main": "./dist/index.js", "types": "./dist/index.d.ts", diff --git a/packages/init-stack/package.json b/packages/init-stack/package.json index 0f94a843f..563f88290 100644 --- a/packages/init-stack/package.json +++ b/packages/init-stack/package.json @@ -1,6 +1,6 @@ { "name": "@stackframe/init-stack", - "version": "2.8.105", + "version": "2.8.106", "repository": "https://github.com/hexclave/hexclave", "description": "The setup wizard for Hexclave. https://hexclave.com", "main": "dist/index.mjs", diff --git a/packages/js/package.json b/packages/js/package.json index c3845005f..882fb31cf 100644 --- a/packages/js/package.json +++ b/packages/js/package.json @@ -1,7 +1,7 @@ { "//": "THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template (FOR package.json FILES, PLEASE EDIT package-template.json)", "name": "@stackframe/js", - "version": "2.8.105", + "version": "2.8.106", "repository": "https://github.com/hexclave/hexclave", "sideEffects": false, "main": "./dist/index.js", diff --git a/packages/react/package.json b/packages/react/package.json index 6d6925762..2d9f9d0a1 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,7 +1,7 @@ { "//": "THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template (FOR package.json FILES, PLEASE EDIT package-template.json)", "name": "@stackframe/react", - "version": "2.8.105", + "version": "2.8.106", "repository": "https://github.com/hexclave/hexclave", "sideEffects": false, "main": "./dist/index.js", diff --git a/packages/stack-cli/package.json b/packages/stack-cli/package.json index b99b028da..f8e23dc81 100644 --- a/packages/stack-cli/package.json +++ b/packages/stack-cli/package.json @@ -1,6 +1,6 @@ { "name": "@stackframe/stack-cli", - "version": "2.8.105", + "version": "2.8.106", "repository": "https://github.com/hexclave/hexclave", "description": "The CLI for Hexclave. https://hexclave.com", "main": "dist/index.js", diff --git a/packages/stack-sc/package.json b/packages/stack-sc/package.json index 0cce9a4a7..69570eabd 100644 --- a/packages/stack-sc/package.json +++ b/packages/stack-sc/package.json @@ -1,6 +1,6 @@ { "name": "@stackframe/stack-sc", - "version": "2.8.105", + "version": "2.8.106", "repository": "https://github.com/hexclave/hexclave", "exports": { "./force-react-server": { diff --git a/packages/stack-shared/package.json b/packages/stack-shared/package.json index 65cda57b3..8075b3e0e 100644 --- a/packages/stack-shared/package.json +++ b/packages/stack-shared/package.json @@ -1,6 +1,6 @@ { "name": "@stackframe/stack-shared", - "version": "2.8.105", + "version": "2.8.106", "repository": "https://github.com/hexclave/hexclave", "scripts": { "build": "rimraf dist && tsdown", diff --git a/packages/stack-ui/package.json b/packages/stack-ui/package.json index b2b15f7a4..d729f24e0 100644 --- a/packages/stack-ui/package.json +++ b/packages/stack-ui/package.json @@ -1,6 +1,6 @@ { "name": "@stackframe/stack-ui", - "version": "2.8.105", + "version": "2.8.106", "repository": "https://github.com/hexclave/hexclave", "main": "./dist/index.js", "types": "./dist/index.d.ts", diff --git a/packages/stack/package.json b/packages/stack/package.json index c7934a800..3385bd5e9 100644 --- a/packages/stack/package.json +++ b/packages/stack/package.json @@ -1,7 +1,7 @@ { "//": "THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template (FOR package.json FILES, PLEASE EDIT package-template.json)", "name": "@stackframe/stack", - "version": "2.8.105", + "version": "2.8.106", "repository": "https://github.com/hexclave/hexclave", "sideEffects": false, "main": "./dist/index.js", diff --git a/packages/tanstack-start/package.json b/packages/tanstack-start/package.json index b61ccaf53..0569114f4 100644 --- a/packages/tanstack-start/package.json +++ b/packages/tanstack-start/package.json @@ -1,7 +1,7 @@ { "//": "THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template (FOR package.json FILES, PLEASE EDIT package-template.json)", "name": "@stackframe/tanstack-start", - "version": "2.8.105", + "version": "2.8.106", "repository": "https://github.com/hexclave/hexclave", "sideEffects": false, "main": "./dist/index.js", diff --git a/packages/template/package-template.json b/packages/template/package-template.json index 2b7ec0226..853c55556 100644 --- a/packages/template/package-template.json +++ b/packages/template/package-template.json @@ -13,7 +13,7 @@ "//": "NEXT_LINE_PLATFORM template", "private": true, - "version": "2.8.105", + "version": "2.8.106", "repository": "https://github.com/hexclave/hexclave", "sideEffects": false, "main": "./dist/index.js", diff --git a/packages/template/package.json b/packages/template/package.json index 6217d71f3..d8feacf67 100644 --- a/packages/template/package.json +++ b/packages/template/package.json @@ -2,7 +2,7 @@ "//": "THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template (FOR package.json FILES, PLEASE EDIT package-template.json)", "name": "@stackframe/template", "private": true, - "version": "2.8.105", + "version": "2.8.106", "repository": "https://github.com/hexclave/hexclave", "sideEffects": false, "main": "./dist/index.js", diff --git a/sdks/implementations/swift/package.json b/sdks/implementations/swift/package.json index 558163204..60bfe6ade 100644 --- a/sdks/implementations/swift/package.json +++ b/sdks/implementations/swift/package.json @@ -1,6 +1,6 @@ { "name": "@stackframe/swift-sdk", - "version": "2.8.105", + "version": "2.8.106", "private": true, "description": "Hexclave Swift SDK", "scripts": { diff --git a/sdks/spec/package.json b/sdks/spec/package.json index ccf2938c0..d285518a8 100644 --- a/sdks/spec/package.json +++ b/sdks/spec/package.json @@ -1,6 +1,6 @@ { "name": "@stackframe/sdk-spec", - "version": "2.8.105", + "version": "2.8.106", "private": true, "description": "Hexclave SDK specification files", "scripts": {}