From 75aaf74a1d583f920a38282f4600cf2f444c5ba4 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 21 Oct 2026 10:20:54 +0000 Subject: [PATCH 1/9] chore(deps): lift the better-auth family from 1.7.3 to 1.7.12 All sixteen pins move together, exact: the eleven family overrides in pnpm-workspace.yaml and the five exact ranges plugin-auth declares. The lockfile is regenerated by pnpm install. Claude-Session: https://claude.ai/code/session_011TdZ8GjixNZFLz1xJD9zzK Co-authored-by: Claude --- packages/plugins/plugin-auth/package.json | 10 +- pnpm-lock.yaml | 500 ++++++---------------- pnpm-workspace.yaml | 22 +- 3 files changed, 153 insertions(+), 379 deletions(-) diff --git a/packages/plugins/plugin-auth/package.json b/packages/plugins/plugin-auth/package.json index 3be56d7784e..f44652d3895 100644 --- a/packages/plugins/plugin-auth/package.json +++ b/packages/plugins/plugin-auth/package.json @@ -31,10 +31,10 @@ "gen:test-typecheck-debt": "tsx ../../../scripts/check-test-typecheck.mts --update --package packages/plugins/plugin-auth --project tsconfig.test.json" }, "dependencies": { - "@better-auth/core": "1.7.3", - "@better-auth/oauth-provider": "1.7.3", - "@better-auth/scim": "1.7.3", - "@better-auth/sso": "1.7.3", + "@better-auth/core": "1.7.12", + "@better-auth/oauth-provider": "1.7.12", + "@better-auth/scim": "1.7.12", + "@better-auth/sso": "1.7.12", "@noble/hashes": "^2.4.0", "@objectstack/core": "workspace:*", "@objectstack/platform-objects": "workspace:*", @@ -42,7 +42,7 @@ "@objectstack/service-messaging": "workspace:*", "@objectstack/spec": "workspace:*", "@objectstack/types": "workspace:*", - "better-auth": "1.7.3", + "better-auth": "1.7.12", "jose": "^6.2.12" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index eb8b5fcda52..9edeba45548 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,17 +11,17 @@ overrides: form-data@<5.0.0: '>=4.0.6' undici@>=7.23.0 <8.0.0: ^7.29.1 undici@>=8.1.0 <9.0.0: ^8.10.2 - better-auth@<2.0.0: 1.7.3 - '@better-auth/core@<2.0.0': 1.7.3 - '@better-auth/scim@<2.0.0': 1.7.3 - '@better-auth/oauth-provider@<2.0.0': 1.7.3 - '@better-auth/sso@<2.0.0': 1.7.3 - '@better-auth/drizzle-adapter@<2.0.0': 1.7.3 - '@better-auth/kysely-adapter@<2.0.0': 1.7.3 - '@better-auth/memory-adapter@<2.0.0': 1.7.3 - '@better-auth/mongo-adapter@<2.0.0': 1.7.3 - '@better-auth/prisma-adapter@<2.0.0': 1.7.3 - '@better-auth/telemetry@<2.0.0': 1.7.3 + better-auth@<2.0.0: 1.7.12 + '@better-auth/core@<2.0.0': 1.7.12 + '@better-auth/scim@<2.0.0': 1.7.12 + '@better-auth/oauth-provider@<2.0.0': 1.7.12 + '@better-auth/sso@<2.0.0': 1.7.12 + '@better-auth/drizzle-adapter@<2.0.0': 1.7.12 + '@better-auth/kysely-adapter@<2.0.0': 1.7.12 + '@better-auth/memory-adapter@<2.0.0': 1.7.12 + '@better-auth/mongo-adapter@<2.0.0': 1.7.12 + '@better-auth/prisma-adapter@<2.0.0': 1.7.12 + '@better-auth/telemetry@<2.0.0': 1.7.12 uuid@<12.0.0: ^11.1.1 postcss@<9.0.0: ^8.5.10 cookie@<0.8.0: ^0.7.0 @@ -405,7 +405,7 @@ importers: version: 6.0.3 vitest: specifier: ^4.1.11 - version: 4.1.11(@opentelemetry/api@1.9.1)(@types/node@26.6.3)(@vitest/coverage-v8@4.1.11)(happy-dom@20.10.2)(jsdom@30.1.1(@noble/hashes@2.4.0))(msw@2.14.6(@types/node@26.6.3)(typescript@6.0.3))(vite@8.3.4(@types/node@26.6.3)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15(patch_hash=4d1d35da1809be2a945519cb26890e48107810b9b66c6913a6a89abb5ad6a1e6))(yaml@2.9.1)) + version: 4.1.11(@opentelemetry/api@1.9.1)(@types/node@26.6.3)(@vitest/coverage-v8@4.1.11)(happy-dom@20.10.2)(jsdom@30.1.1(@noble/hashes@2.4.0))(msw@2.14.6(@types/node@26.6.3)(typescript@6.0.3))(vite@8.3.4(@types/node@26.6.3)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.15(patch_hash=4d1d35da1809be2a945519cb26890e48107810b9b66c6913a6a89abb5ad6a1e6))(yaml@2.9.1)) packages/apps/setup: dependencies: @@ -427,7 +427,7 @@ importers: version: 6.0.3 vitest: specifier: ^4.1.11 - version: 4.1.11(@opentelemetry/api@1.9.1)(@types/node@26.6.3)(@vitest/coverage-v8@4.1.11)(happy-dom@20.10.2)(jsdom@30.1.1(@noble/hashes@2.4.0))(msw@2.14.6(@types/node@26.6.3)(typescript@6.0.3))(vite@8.3.4(@types/node@26.6.3)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.15(patch_hash=4d1d35da1809be2a945519cb26890e48107810b9b66c6913a6a89abb5ad6a1e6))(yaml@2.9.1)) + version: 4.1.11(@opentelemetry/api@1.9.1)(@types/node@26.6.3)(@vitest/coverage-v8@4.1.11)(happy-dom@20.10.2)(jsdom@30.1.1(@noble/hashes@2.4.0))(msw@2.14.6(@types/node@26.6.3)(typescript@6.0.3))(vite@8.3.4(@types/node@26.6.3)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15(patch_hash=4d1d35da1809be2a945519cb26890e48107810b9b66c6913a6a89abb5ad6a1e6))(yaml@2.9.1)) packages/apps/studio: dependencies: @@ -1692,17 +1692,17 @@ importers: packages/plugins/plugin-auth: dependencies: '@better-auth/core': - specifier: 1.7.3 - version: 1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0) + specifier: 1.7.12 + version: 1.7.12(@better-auth/utils@0.5.0)(@better-fetch/fetch@1.3.2)(@opentelemetry/api@1.9.1)(better-call@1.4.4(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0) '@better-auth/oauth-provider': - specifier: 1.7.3 - version: 1.7.3(@better-auth/core@1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0))(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-auth@1.7.3(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-sqlite3@12.11.1)(mongodb@7.7.0(socks@2.8.9))(mysql2@3.24.4(@types/node@26.6.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.63.0)(@types/node@26.6.3)(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(pg@8.23.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(svelte@5.57.1(@typescript-eslint/types@8.70.1))(vitest@4.1.11))(better-call@1.4.0(zod@4.6.5)) + specifier: 1.7.12 + version: 1.7.12(@better-auth/core@1.7.12(@better-auth/utils@0.5.0)(@better-fetch/fetch@1.3.2)(@opentelemetry/api@1.9.1)(better-call@1.4.4(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0))(@better-auth/utils@0.5.0)(@better-fetch/fetch@1.3.2)(better-auth@1.7.12(@opentelemetry/api@1.9.1)(mongodb@7.7.0(socks@2.8.9))(mysql2@3.24.4(@types/node@26.6.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.63.0)(@types/node@26.6.3)(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(pg@8.23.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(svelte@5.57.1(@typescript-eslint/types@8.70.1))(vitest@4.1.11))(better-call@1.4.4(zod@4.6.5)) '@better-auth/scim': - specifier: 1.7.3 - version: 1.7.3(@better-auth/core@1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0))(@better-auth/utils@0.4.2)(better-auth@1.7.3(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-sqlite3@12.11.1)(mongodb@7.7.0(socks@2.8.9))(mysql2@3.24.4(@types/node@26.6.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.63.0)(@types/node@26.6.3)(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(pg@8.23.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(svelte@5.57.1(@typescript-eslint/types@8.70.1))(vitest@4.1.11))(better-call@1.4.0(zod@4.6.5)) + specifier: 1.7.12 + version: 1.7.12(@better-auth/core@1.7.12(@better-auth/utils@0.5.0)(@better-fetch/fetch@1.3.2)(@opentelemetry/api@1.9.1)(better-call@1.4.4(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0))(@better-auth/utils@0.5.0)(better-auth@1.7.12(@opentelemetry/api@1.9.1)(mongodb@7.7.0(socks@2.8.9))(mysql2@3.24.4(@types/node@26.6.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.63.0)(@types/node@26.6.3)(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(pg@8.23.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(svelte@5.57.1(@typescript-eslint/types@8.70.1))(vitest@4.1.11))(better-call@1.4.4(zod@4.6.5)) '@better-auth/sso': - specifier: 1.7.3 - version: 1.7.3(@better-auth/core@1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0))(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-auth@1.7.3(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-sqlite3@12.11.1)(mongodb@7.7.0(socks@2.8.9))(mysql2@3.24.4(@types/node@26.6.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.63.0)(@types/node@26.6.3)(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(pg@8.23.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(svelte@5.57.1(@typescript-eslint/types@8.70.1))(vitest@4.1.11))(better-call@1.4.0(zod@4.6.5)) + specifier: 1.7.12 + version: 1.7.12(@better-auth/core@1.7.12(@better-auth/utils@0.5.0)(@better-fetch/fetch@1.3.2)(@opentelemetry/api@1.9.1)(better-call@1.4.4(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0))(@better-auth/utils@0.5.0)(@better-fetch/fetch@1.3.2)(better-auth@1.7.12(@opentelemetry/api@1.9.1)(mongodb@7.7.0(socks@2.8.9))(mysql2@3.24.4(@types/node@26.6.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.63.0)(@types/node@26.6.3)(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(pg@8.23.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(svelte@5.57.1(@typescript-eslint/types@8.70.1))(vitest@4.1.11))(better-call@1.4.4(zod@4.6.5)) '@noble/hashes': specifier: ^2.4.0 version: 2.4.0 @@ -1725,8 +1725,8 @@ importers: specifier: workspace:* version: link:../../types better-auth: - specifier: 1.7.3 - version: 1.7.3(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-sqlite3@12.11.1)(mongodb@7.7.0(socks@2.8.9))(mysql2@3.24.4(@types/node@26.6.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.63.0)(@types/node@26.6.3)(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(pg@8.23.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(svelte@5.57.1(@typescript-eslint/types@8.70.1))(vitest@4.1.11) + specifier: 1.7.12 + version: 1.7.12(@opentelemetry/api@1.9.1)(mongodb@7.7.0(socks@2.8.9))(mysql2@3.24.4(@types/node@26.6.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.63.0)(@types/node@26.6.3)(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(pg@8.23.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(svelte@5.57.1(@typescript-eslint/types@8.70.1))(vitest@4.1.11) jose: specifier: ^6.2.12 version: 6.2.12 @@ -3510,73 +3510,70 @@ packages: resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} engines: {node: '>=18'} - '@better-auth/core@1.7.3': - resolution: {integrity: sha512-JdP7lOkyE83jgjn7RilJj1XvZ7n2JjRsErKJuaXchjyuNo6cf1iVd3GtbhAtiUyJJkWdk8yL+LaUBKT80H0zLA==} + '@better-auth/core@1.7.12': + resolution: {integrity: sha512-SUStBGHJ13KnSO6+7U/1DSlfuOtln4jtOrFZqzQtxZVHZIrAoMjwHNGitlF+s7hvKbuC3Z14xjnqfLLqIqGfxw==} peerDependencies: - '@better-auth/utils': 0.4.2 - '@better-fetch/fetch': 1.3.1 - '@cloudflare/workers-types': '>=4' + '@better-auth/utils': ^0.4.2 || ^0.5.0 + '@better-fetch/fetch': 1.3.2 '@opentelemetry/api': ^1.9.0 - better-call: 1.4.0 + better-call: 1.4.4 jose: ^6.1.0 kysely: ^0.28.5 || ^0.29.0 nanostores: ^1.0.1 peerDependenciesMeta: - '@cloudflare/workers-types': - optional: true '@opentelemetry/api': optional: true - '@better-auth/drizzle-adapter@1.7.3': - resolution: {integrity: sha512-S+nQRlxbUhkR43LrSv8c98ZvOvmv3nrtOnHkiZXkdDkr60PWp7maC2cqgzZ2C9exCC1a+4TugJlx2jRL+r+/9A==} + '@better-auth/drizzle-adapter@1.7.12': + resolution: {integrity: sha512-Qzoyuf05aK01Pc0k3EXv8Xj3XCT2m2dCWc5HoB7x+xX6N3Pm2eQsca+UIArsJcbuNEWWP3L51oIebnBoHJ5DTw==} peerDependencies: - '@better-auth/core': 1.7.3 - '@better-auth/utils': 0.4.2 + '@better-auth/core': 1.7.12 + '@better-auth/utils': ^0.4.2 || ^0.5.0 drizzle-orm: ^0.45.2 || >=1.0.0-rc.1 <2.0.0 peerDependenciesMeta: drizzle-orm: optional: true - '@better-auth/kysely-adapter@1.7.3': - resolution: {integrity: sha512-UIsyJMIrjUnT+yTaS6dkCxYYmtPwxFHxwSJ8+CLty2II5w9BewlDxDA0/QzhoL/InYCPxQ5Y6xIgLHZG1dhwRA==} + '@better-auth/kysely-adapter@1.7.12': + resolution: {integrity: sha512-1PaFXktLv4n3DmrGbPaCj5SsvcT40NnWw7NLua5/J1+8/A051N5ZzqOwJifXEIQX5k6NdwvmymwDQxKytduEAQ==} peerDependencies: - '@better-auth/core': 1.7.3 - '@better-auth/utils': 0.4.2 + '@better-auth/core': 1.7.12 + '@better-auth/utils': ^0.4.2 || ^0.5.0 kysely: ^0.28.17 || ^0.29.0 peerDependenciesMeta: kysely: optional: true - '@better-auth/memory-adapter@1.7.3': - resolution: {integrity: sha512-WdLANFY/QWC3G351RCzxU+Y9YlW+BQ1oG9NwBTSOUWQw5rZ87ws+weU8tvAMO7sQ4C9gKIlkOKBKUKXrSt91Tw==} + '@better-auth/memory-adapter@1.7.12': + resolution: {integrity: sha512-glaDwXzDptnddHqRuu7fj47FAssUcOzLNgdlTGJoEPrspkX69x2vnXwgAzNuApjZI21WLtPH/rQ6CN+DQGybPA==} peerDependencies: - '@better-auth/core': 1.7.3 - '@better-auth/utils': 0.4.2 + '@better-auth/core': 1.7.12 + '@better-auth/utils': ^0.4.2 || ^0.5.0 - '@better-auth/mongo-adapter@1.7.3': - resolution: {integrity: sha512-YL9m01tNogmFmRvOWJ46M9WwE6HirCXHDell29mtsQB/Qs1TPNLrgj7ybGMMGhQuyj6S218+8Wbls8m9s+i8RQ==} + '@better-auth/mongo-adapter@1.7.12': + resolution: {integrity: sha512-HKV4sgYSw/Gdt9AuHlESMkiKL72SWdGweDy1Wsyxoh06BpG7aNu4aSJ7marNpMdKZteyRbxWWqQkA9ediA8qFw==} peerDependencies: - '@better-auth/core': 1.7.3 - '@better-auth/utils': 0.4.2 + '@better-auth/core': 1.7.12 + '@better-auth/utils': ^0.4.2 || ^0.5.0 mongodb: ^6.0.0 || ^7.0.0 peerDependenciesMeta: mongodb: optional: true - '@better-auth/oauth-provider@1.7.3': - resolution: {integrity: sha512-Eoajj68F1ETmp4NBM98tgj1Uiip4cZiFqFsijAWIvOEQTejr/67PWK1/92N8PiNdLf03ezUWU538W93rd9fyIw==} + '@better-auth/oauth-provider@1.7.12': + resolution: {integrity: sha512-XzjlApbWtuuoEK63CUNHbgs8zpr3AjlQeGbT1vWEPqvOvI2z4lOaIvIsogomfqFAgj/jgB0zMGYjt0MRyW0T7w==} peerDependencies: - '@better-auth/core': 1.7.3 - '@better-auth/utils': 0.4.2 - '@better-fetch/fetch': 1.3.1 - better-auth: 1.7.3 - better-call: 1.4.0 + '@better-auth/core': 1.7.12 + '@better-auth/utils': ^0.4.2 || ^0.5.0 + '@better-fetch/fetch': 1.3.2 + better-auth: 1.7.12 + better-call: 1.4.4 - '@better-auth/prisma-adapter@1.7.3': - resolution: {integrity: sha512-TJ/DhlU7oLzrC626/1wfYA1Pl+lVsXa/zXBZ8d7Rlc2YO5fGd5fsAYJdRrYMyA51iZEo+rWLXMhZ0cez1BamsQ==} + '@better-auth/prisma-adapter@1.7.12': + resolution: {integrity: sha512-FZRX6ORbwhDmeYE1Tl0IPtUn8v3BlVFgbJxDnm/DCNHxuFRf+0t4HfddUgYeYehHFR8aSDsdYX44fEFWM9877w==} peerDependencies: - '@better-auth/core': 1.7.3 - '@better-auth/utils': 0.4.2 + '@better-auth/core': 1.7.12 + '@better-auth/utils': ^0.4.2 || ^0.5.0 '@prisma/client': ^5.0.0 || ^6.0.0 || ^7.0.0 prisma: ^5.0.0 || ^6.0.0 || ^7.0.0 peerDependenciesMeta: @@ -3585,38 +3582,35 @@ packages: prisma: optional: true - '@better-auth/scim@1.7.3': - resolution: {integrity: sha512-1/L7zIEUAb1jxlzWKkqbDAD4Jz7u83yZg15TSaIaKcFe1dpCdNxkzQRrjbPLUfnVtBh/vnk10uLxVFCtbMdrdg==} + '@better-auth/scim@1.7.12': + resolution: {integrity: sha512-mmDGQr9tu6z0mUhuQ5zGlutU0wmg3zujuP2uz02FqVil7RdEsHuYI6THeahF2EQEmCQ4E241SI8Lp94OruQw3A==} peerDependencies: - '@better-auth/core': 1.7.3 - '@better-auth/utils': 0.4.2 - better-auth: 1.7.3 - better-call: 1.4.0 + '@better-auth/core': 1.7.12 + '@better-auth/utils': ^0.4.2 || ^0.5.0 + better-auth: 1.7.12 + better-call: 1.4.4 - '@better-auth/sso@1.7.3': - resolution: {integrity: sha512-inxETRuOfyy8m0uEJSfi9uhScp4RkQ7ZYI+GRj+Jtz6ml/p5wTzNOjYZsG43TroUTDfrElF6CYQON5/Xk1XdmA==} + '@better-auth/sso@1.7.12': + resolution: {integrity: sha512-fxUD9+MjNRhuT+nVtFgqPvWAvwWJVacuIijdf4x2nCHqR44xfFgYYWK2iB6vOiin9Qxof9kTPKvRl7ZCJHdwFQ==} peerDependencies: - '@better-auth/core': 1.7.3 - '@better-auth/utils': 0.4.2 - '@better-fetch/fetch': 1.3.1 - better-auth: 1.7.3 - better-call: 1.4.0 + '@better-auth/core': 1.7.12 + '@better-auth/utils': ^0.4.2 || ^0.5.0 + '@better-fetch/fetch': 1.3.2 + better-auth: 1.7.12 + better-call: 1.4.4 - '@better-auth/telemetry@1.7.3': - resolution: {integrity: sha512-aixgHbJhGvS8PRczX/LR3murYyBnIvOGmJw37ZZBMg6ZtLR/UBJAkufbDi1HYn5THSuTJ3D5DtY85Ahh/ABQtw==} + '@better-auth/telemetry@1.7.12': + resolution: {integrity: sha512-DaDkKNnI99vKGGbWq9KJg2uYeaOjsK9nIBw9T2m2KG/RkxpvQRjYkZ00++up2bZQkR5pB1nukGbplza3UJG/Xg==} peerDependencies: - '@better-auth/core': 1.7.3 - '@better-auth/utils': 0.4.2 - '@better-fetch/fetch': 1.3.1 - - '@better-auth/utils@0.4.2': - resolution: {integrity: sha512-AUxrvu+HaaODsUyzDxFgwd/8RZ1yZaYo42LXKSrU2oGgR38pS1ij8nqQKNgtTWoYGpNevNXtCfgTy6loHveW9A==} + '@better-auth/core': 1.7.12 + '@better-auth/utils': ^0.4.2 || ^0.5.0 + '@better-fetch/fetch': 1.3.2 '@better-auth/utils@0.5.0': resolution: {integrity: sha512-BL8W4EfIZFwlu0r54m3v1ztjDhu6dDe/amLTm0xybmbZaNgYUqhD3SjpAsnq0q8YD6/ki4iwIgxJNLP/N3TxiA==} - '@better-fetch/fetch@1.3.1': - resolution: {integrity: sha512-ABkD1WhyfPZprKRQI3bhATjeiFuNWC9PXhfGWqL+sg/gKrM977oFrYkdb4msM3hgUGonr7KlOsOFT5TU2rht9g==} + '@better-fetch/fetch@1.3.2': + resolution: {integrity: sha512-Gs7n99b5tqUC6cQAPbV0uED3IraHB6xQbHLQ/C3l7ZFafHScOx9pQ+DYmP5blbLFShVWLqxNUlI9wi4xU/X+ow==} '@braintree/sanitize-url@7.1.2': resolution: {integrity: sha512-jigsZK+sMF/cuiB7sERuo9V7N9jx+dhmHHnQyDSVdpZwVutaBu7WvNYqMDLSgFgfB30n452TP3vjDAvFC973mA==} @@ -3703,9 +3697,6 @@ packages: resolution: {integrity: sha512-dlT1m5e/0yUL0kRNcQn7yGLVThkgbB0Ga/1AmfDDC/8ik6AIiSf2QLQO2zPYvefsHP0aFgxO93cVLCCfDp7kzQ==} engines: {node: '>= 20.12.0'} - '@cloudflare/workers-types@4.20260520.1': - resolution: {integrity: sha512-wdmf9Fwabp06OgK9ZyCl8Q77GZ94k9J7OA9qA65FbgxZ/hd3hYRkVNiY7Bvsx4tKim+sWmKqGOblecZInAvoRg==} - '@csstools/color-helpers@6.1.2': resolution: {integrity: sha512-grhRy3OKmniaAEKXMjua5z/EODX0MSqBGjunw8+j/3HQjOnahs2AGhvEOIYVUWcU6ScApbhLhVrQTX8XqrMrow==} engines: {node: '>=20.19.0'} @@ -4577,10 +4568,6 @@ packages: cpu: [x64] os: [win32] - '@noble/ciphers@2.3.0': - resolution: {integrity: sha512-Clu/xdfgVTf9o7ngLOURaxePwR0j8sjclKEtVij10/jGulwFsPWCvvRgG/XjUVf8Nei+jLG6uwyXzUTGY1DQrw==} - engines: {node: '>= 20.19.0'} - '@noble/ciphers@2.4.0': resolution: {integrity: sha512-AnjFn0Jv92laAkvMrghlFZq4qQCIN/4DxFV/eooqtC2YTjB7kBeLMS2T9KJX4Dn+ZVXLOwK0lSgqDtx9gvxtiw==} engines: {node: '>= 20.19.0'} @@ -4612,10 +4599,6 @@ packages: resolution: {integrity: sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==} engines: {node: '>=8.0.0'} - '@opentelemetry/semantic-conventions@1.43.0': - resolution: {integrity: sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==} - engines: {node: '>=14'} - '@oxc-project/types@0.154.0': resolution: {integrity: sha512-KYOUGQFlLWR+s4QMV2Q9ko38TZm7EdO87Qm7rvZLqk/webse/cDjtyxKhg/47l0byCbs/k46LT8qc4PKjAikzA==} @@ -6029,15 +6012,14 @@ packages: engines: {node: '>=6.0.0'} hasBin: true - better-auth@1.7.3: - resolution: {integrity: sha512-8xGp68JQ+l36kniDEgP8bP99TLi1GdEv0NTEUBkyqnYnus/cgFUZseUfqUHKzr2BAsg2O6aD88I9f0U68shanQ==} + better-auth@1.7.12: + resolution: {integrity: sha512-f1fEG0QdTslzbmFA+vOGFFW/XXCWkG4kBxLeH9n1vp1otTH9+ZzV6EJ6797GStWeiYYgS5Vnt9xqE12KwSyAAw==} peerDependencies: '@lynx-js/react': '*' '@prisma/client': ^5.0.0 || ^6.0.0 || ^7.0.0 '@sveltejs/kit': ^2.69.1 '@tanstack/react-start': ^1.0.0 '@tanstack/solid-start': ^1.0.0 - better-sqlite3: ^12.0.0 drizzle-kit: '>=0.31.4 || >=1.0.0-beta.1' drizzle-orm: ^0.45.2 || >=1.0.0-rc.1 <2.0.0 mongodb: ^6.0.0 || ^7.0.0 @@ -6049,7 +6031,7 @@ packages: react-dom: ^18.0.0 || ^19.0.0 solid-js: ^1.0.0 svelte: ^5.55.7 - vitest: ^2.0.0 || ^3.0.0 || ^4.0.0 + vitest: ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 vue: ^3.0.0 peerDependenciesMeta: '@lynx-js/react': @@ -6062,8 +6044,6 @@ packages: optional: true '@tanstack/solid-start': optional: true - better-sqlite3: - optional: true drizzle-kit: optional: true drizzle-orm: @@ -6091,18 +6071,14 @@ packages: vue: optional: true - better-call@1.4.0: - resolution: {integrity: sha512-bBKOT4vv1kZLDgxVePdilk/Jwkn+dtRRsmi3DzHcDP+WnswyVl6dR59l2HEeP/0cB+bDoopASAesWDPIdd/zZA==} + better-call@1.4.4: + resolution: {integrity: sha512-Gq4XdGFy4dmUxFEAX2nj0ycFcFbD9ZWh8YROouZoyXeF1M11TpYbplk0pDByTFF8Wz+MYa6W9052c9m7dD+mfw==} peerDependencies: zod: ^4.0.0 peerDependenciesMeta: zod: optional: true - better-sqlite3@12.11.1: - resolution: {integrity: sha512-dq9AtApgg5PGFtBzPFSBl3HZQjHok5gaQCM6zh2Yk0aSmDCs1CbnVI8/HgASQkNKsWFpseIO9beg5xxpYhbIfA==} - engines: {node: 20.x || 22.x || 23.x || 24.x || 25.x || 26.x} - better-sqlite3@13.0.3: resolution: {integrity: sha512-RbOBxmLBG8uvFUc15X9+9SFemKcQ0WBuISBVkpuiaUB2qblC8UWlHEjdWVoZ8AdhSwmoEgsiXKfopX0CQxaACQ==} engines: {node: '>=22'} @@ -6117,9 +6093,6 @@ packages: binary@0.3.0: resolution: {integrity: sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==} - bindings@1.5.0: - resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} - bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} @@ -6246,9 +6219,6 @@ packages: resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==} engines: {node: '>= 20.19.0'} - chownr@1.1.4: - resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} - class-variance-authority@0.7.1: resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} @@ -6589,14 +6559,6 @@ packages: decode-named-character-reference@1.3.0: resolution: {integrity: sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==} - decompress-response@6.0.0: - resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} - engines: {node: '>=10'} - - deep-extend@0.6.0: - resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} - engines: {node: '>=4.0.0'} - deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} @@ -6862,10 +6824,6 @@ packages: resolution: {integrity: sha512-XctvKaEMaj1Ii9oDOqbW/6e1gXknSY4g/aLCDicOXqBE4M0nRWkUu0PTp++UPNzoFY12BNHMfs/VadKIS6llvg==} engines: {node: '>=8.3.0'} - expand-template@2.0.3: - resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} - engines: {node: '>=6'} - expect-type@1.4.0: resolution: {integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==} engines: {node: '>=12.0.0'} @@ -6942,9 +6900,6 @@ packages: file-entry-cache@11.1.5: resolution: {integrity: sha512-+PFTHITI08JIGhnNpGNI8T8inUpgZfk3GNEqfT9R2zZV2iFXg3CvqzSl/uEhs7TSGujYRELEANyDvS8Fj7+S7Q==} - file-uri-to-path@1.0.0: - resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} - finalhandler@2.1.1: resolution: {integrity: sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==} engines: {node: '>= 18.0.0'} @@ -7159,9 +7114,6 @@ packages: getopts@2.3.0: resolution: {integrity: sha512-5eDf9fuSXwxBL6q5HX+dhDj+dslFGWzU5thZ9kNKUkcPtaPdatmUFKwHFrLb/uf/WpA4BHET+AX3Scl56cAjpA==} - github-from-package@0.0.0: - resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} - github-slugger@2.0.0: resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==} @@ -7313,9 +7265,6 @@ packages: inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - ini@1.3.8: - resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - inline-style-parser@0.2.7: resolution: {integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==} @@ -8050,10 +7999,6 @@ packages: resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==} engines: {node: '>=18'} - mimic-response@3.1.0: - resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} - engines: {node: '>=10'} - mingo@7.2.4: resolution: {integrity: sha512-KrxHKzMMguL+G1lBC6YbU5UTXdw2viwVHNTPzNYVfEQfSAoetC3M1a7rlveOksn/96oNy+QwBlIXvx/q6rWyxQ==} @@ -8072,9 +8017,6 @@ packages: resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} engines: {node: '>=16 || 14 >=14.17'} - mkdirp-classic@0.5.3: - resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} - mkdirp@0.5.6: resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} hasBin: true @@ -8218,9 +8160,6 @@ packages: resolution: {integrity: sha512-i0tloweeudshAEuddpDxcg9Ik6pkPfVsHIgKyf143JrgG7/MOh0+q7BypdLXZPoOP7fOYt1eTcwGkyiVmhJFkA==} engines: {node: ^20.0.0 || >=22.0.0} - napi-build-utils@2.0.0: - resolution: {integrity: sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==} - native-duplexpair@1.0.0: resolution: {integrity: sha512-E7QQoM+3jvNtlmyfqRZ0/U75VFgCls+fSkbml2MpgWkWyz3ox8Y58gNhfuziuQYGNNQAbFZJQck55LHCnCK6CA==} @@ -8262,10 +8201,6 @@ packages: sass: optional: true - node-abi@3.96.0: - resolution: {integrity: sha512-rebQ/lz7i0EkoLzUVSrKRzA69zMkwLp95kKMWoMDkkM00Suxz0D7zEQPwRml5fQum24mj7bPvmlgLAmu2JCiYg==} - engines: {node: '>=10'} - node-addon-api@8.9.2: resolution: {integrity: sha512-VijLXbi3UACN69I0JVXJsX4tjACjNoQDgv2gTF6sx2wWEi8tkSg2eX8p5gSIFi8z2+DL3oHmY6OyKce38SDolg==} engines: {node: ^18 || ^20 || >= 21} @@ -8538,12 +8473,6 @@ packages: resolution: {integrity: sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==} engines: {node: '>=20'} - prebuild-install@7.1.3: - resolution: {integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==} - engines: {node: '>=10'} - deprecated: No longer maintained. Please contact the author of the relevant native addon; alternatives are available. - hasBin: true - prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -8569,9 +8498,6 @@ packages: resolution: {integrity: sha512-5nnx0yGyVUcY6t9RnWcARWtwT9F1D8O9rt08htPvnd49W1IgZtmLkhu9WfMzQj1cFxjHIO6connUNVW5k7AVyQ==} engines: {node: '>= 0.10'} - pump@3.0.4: - resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==} - punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -8602,10 +8528,6 @@ packages: resolution: {integrity: sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==} engines: {node: '>= 0.10'} - rc@1.2.8: - resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} - hasBin: true - react-dom@19.2.8: resolution: {integrity: sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==} peerDependencies: @@ -8906,12 +8828,6 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} - simple-concat@1.0.1: - resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} - - simple-get@4.0.1: - resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} - sisteransi@1.0.5: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} @@ -8991,10 +8907,6 @@ packages: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} - strip-json-comments@2.0.1: - resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} - engines: {node: '>=0.10.0'} - strnum@2.4.1: resolution: {integrity: sha512-M9eUSMT2dCB2cTNPG7UYj6KuK7RJR2SN2+yCV/fTW3xzTCS6EaGZ5pSMgDIjB7r8zSfTGk+dvvn9rTjpVS9Mwg==} @@ -9055,9 +8967,6 @@ packages: resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} engines: {node: '>=6'} - tar-fs@2.1.5: - resolution: {integrity: sha512-OboTd8mmMhZDNPV+UjQcK9yKAatXu2aJ+r1w4im1Otd4M4fl2hwvdoXUxIYHFTHWK/3y3FarBP70v3vwmGlOxw==} - tar-stream@2.2.0: resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} engines: {node: '>=6'} @@ -9115,17 +9024,10 @@ packages: tldts-core@7.4.16: resolution: {integrity: sha512-MDolfaSJtlSK5Y0A1xl3277ekubZwobpBjugknDizI9O5Rm60a1m8k4ICK+MRsCDzPygT81mp3BBf5RKDlFRfA==} - tldts-core@7.4.9: - resolution: {integrity: sha512-DxKfPBI52p2msTEu7MPhdpdDTBhhVQg1a/8PjQckeyAvO13eMYElX545grIp6nnTGIMZlRvFZPvFhvI/WIz2Vg==} - tldts@7.4.16: resolution: {integrity: sha512-QwBER5KMR86IIjpIiO7H/Z3IMJPsZ1A6RKPAqzTTgOyUQUSt9FdnKcqhTaJmkY6HVrgouZHZR0ncK5QxvmnQeg==} hasBin: true - tldts@7.4.9: - resolution: {integrity: sha512-3kZ8wQQ/k5DrChD4X4FVvr2D7E5uoRgAqkPyLpSCGUvqOvqu+JEdr3mwMUaVWb+vMHZaKhF5fp2PBigKsui7hA==} - hasBin: true - tmp@0.2.7: resolution: {integrity: sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==} engines: {node: '>=14.14'} @@ -9202,9 +9104,6 @@ packages: engines: {node: '>=18.0.0'} hasBin: true - tunnel-agent@0.6.0: - resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} - turbo@2.11.5: resolution: {integrity: sha512-qLXheqz3TUvJpHIV6MUBwkNkvwKxMVG/QsimyiKT9DfNWPHJ294G/i5nDaH+fbHJt3UH7orubNNxAqYkbUNGAQ==} hasBin: true @@ -9973,98 +9872,92 @@ snapshots: '@bcoe/v8-coverage@1.0.2': {} - '@better-auth/core@1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0)': + '@better-auth/core@1.7.12(@better-auth/utils@0.5.0)(@better-fetch/fetch@1.3.2)(@opentelemetry/api@1.9.1)(better-call@1.4.4(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0)': dependencies: - '@better-auth/utils': 0.4.2 - '@better-fetch/fetch': 1.3.1 - '@opentelemetry/semantic-conventions': 1.43.0 + '@better-auth/utils': 0.5.0 + '@better-fetch/fetch': 1.3.2 '@standard-schema/spec': 1.1.0 - better-call: 1.4.0(zod@4.6.5) + better-call: 1.4.4(zod@4.6.5) jose: 6.2.12 kysely: 0.29.4 nanostores: 1.4.0 zod: 4.6.5 optionalDependencies: - '@cloudflare/workers-types': 4.20260520.1 '@opentelemetry/api': 1.9.1 - '@better-auth/drizzle-adapter@1.7.3(@better-auth/core@1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0))(@better-auth/utils@0.4.2)': + '@better-auth/drizzle-adapter@1.7.12(@better-auth/core@1.7.12(@better-auth/utils@0.5.0)(@better-fetch/fetch@1.3.2)(@opentelemetry/api@1.9.1)(better-call@1.4.4(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0))(@better-auth/utils@0.5.0)': dependencies: - '@better-auth/core': 1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0) - '@better-auth/utils': 0.4.2 + '@better-auth/core': 1.7.12(@better-auth/utils@0.5.0)(@better-fetch/fetch@1.3.2)(@opentelemetry/api@1.9.1)(better-call@1.4.4(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0) + '@better-auth/utils': 0.5.0 - '@better-auth/kysely-adapter@1.7.3(@better-auth/core@1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0))(@better-auth/utils@0.4.2)(kysely@0.29.4)': + '@better-auth/kysely-adapter@1.7.12(@better-auth/core@1.7.12(@better-auth/utils@0.5.0)(@better-fetch/fetch@1.3.2)(@opentelemetry/api@1.9.1)(better-call@1.4.4(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0))(@better-auth/utils@0.5.0)(kysely@0.29.4)': dependencies: - '@better-auth/core': 1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0) - '@better-auth/utils': 0.4.2 + '@better-auth/core': 1.7.12(@better-auth/utils@0.5.0)(@better-fetch/fetch@1.3.2)(@opentelemetry/api@1.9.1)(better-call@1.4.4(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0) + '@better-auth/utils': 0.5.0 optionalDependencies: kysely: 0.29.4 - '@better-auth/memory-adapter@1.7.3(@better-auth/core@1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0))(@better-auth/utils@0.4.2)': + '@better-auth/memory-adapter@1.7.12(@better-auth/core@1.7.12(@better-auth/utils@0.5.0)(@better-fetch/fetch@1.3.2)(@opentelemetry/api@1.9.1)(better-call@1.4.4(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0))(@better-auth/utils@0.5.0)': dependencies: - '@better-auth/core': 1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0) - '@better-auth/utils': 0.4.2 + '@better-auth/core': 1.7.12(@better-auth/utils@0.5.0)(@better-fetch/fetch@1.3.2)(@opentelemetry/api@1.9.1)(better-call@1.4.4(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0) + '@better-auth/utils': 0.5.0 - '@better-auth/mongo-adapter@1.7.3(@better-auth/core@1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0))(@better-auth/utils@0.4.2)(mongodb@7.7.0(socks@2.8.9))': + '@better-auth/mongo-adapter@1.7.12(@better-auth/core@1.7.12(@better-auth/utils@0.5.0)(@better-fetch/fetch@1.3.2)(@opentelemetry/api@1.9.1)(better-call@1.4.4(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0))(@better-auth/utils@0.5.0)(mongodb@7.7.0(socks@2.8.9))': dependencies: - '@better-auth/core': 1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0) - '@better-auth/utils': 0.4.2 + '@better-auth/core': 1.7.12(@better-auth/utils@0.5.0)(@better-fetch/fetch@1.3.2)(@opentelemetry/api@1.9.1)(better-call@1.4.4(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0) + '@better-auth/utils': 0.5.0 optionalDependencies: mongodb: 7.7.0(socks@2.8.9) - '@better-auth/oauth-provider@1.7.3(@better-auth/core@1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0))(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-auth@1.7.3(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-sqlite3@12.11.1)(mongodb@7.7.0(socks@2.8.9))(mysql2@3.24.4(@types/node@26.6.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.63.0)(@types/node@26.6.3)(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(pg@8.23.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(svelte@5.57.1(@typescript-eslint/types@8.70.1))(vitest@4.1.11))(better-call@1.4.0(zod@4.6.5))': + '@better-auth/oauth-provider@1.7.12(@better-auth/core@1.7.12(@better-auth/utils@0.5.0)(@better-fetch/fetch@1.3.2)(@opentelemetry/api@1.9.1)(better-call@1.4.4(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0))(@better-auth/utils@0.5.0)(@better-fetch/fetch@1.3.2)(better-auth@1.7.12(@opentelemetry/api@1.9.1)(mongodb@7.7.0(socks@2.8.9))(mysql2@3.24.4(@types/node@26.6.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.63.0)(@types/node@26.6.3)(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(pg@8.23.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(svelte@5.57.1(@typescript-eslint/types@8.70.1))(vitest@4.1.11))(better-call@1.4.4(zod@4.6.5))': dependencies: - '@better-auth/core': 1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0) - '@better-auth/utils': 0.4.2 - '@better-fetch/fetch': 1.3.1 - better-auth: 1.7.3(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-sqlite3@12.11.1)(mongodb@7.7.0(socks@2.8.9))(mysql2@3.24.4(@types/node@26.6.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.63.0)(@types/node@26.6.3)(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(pg@8.23.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(svelte@5.57.1(@typescript-eslint/types@8.70.1))(vitest@4.1.11) - better-call: 1.4.0(zod@4.6.5) + '@better-auth/core': 1.7.12(@better-auth/utils@0.5.0)(@better-fetch/fetch@1.3.2)(@opentelemetry/api@1.9.1)(better-call@1.4.4(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0) + '@better-auth/utils': 0.5.0 + '@better-fetch/fetch': 1.3.2 + better-auth: 1.7.12(@opentelemetry/api@1.9.1)(mongodb@7.7.0(socks@2.8.9))(mysql2@3.24.4(@types/node@26.6.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.63.0)(@types/node@26.6.3)(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(pg@8.23.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(svelte@5.57.1(@typescript-eslint/types@8.70.1))(vitest@4.1.11) + better-call: 1.4.4(zod@4.6.5) jose: 6.2.12 zod: 4.6.5 - '@better-auth/prisma-adapter@1.7.3(@better-auth/core@1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0))(@better-auth/utils@0.4.2)': + '@better-auth/prisma-adapter@1.7.12(@better-auth/core@1.7.12(@better-auth/utils@0.5.0)(@better-fetch/fetch@1.3.2)(@opentelemetry/api@1.9.1)(better-call@1.4.4(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0))(@better-auth/utils@0.5.0)': dependencies: - '@better-auth/core': 1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0) - '@better-auth/utils': 0.4.2 + '@better-auth/core': 1.7.12(@better-auth/utils@0.5.0)(@better-fetch/fetch@1.3.2)(@opentelemetry/api@1.9.1)(better-call@1.4.4(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0) + '@better-auth/utils': 0.5.0 - '@better-auth/scim@1.7.3(@better-auth/core@1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0))(@better-auth/utils@0.4.2)(better-auth@1.7.3(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-sqlite3@12.11.1)(mongodb@7.7.0(socks@2.8.9))(mysql2@3.24.4(@types/node@26.6.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.63.0)(@types/node@26.6.3)(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(pg@8.23.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(svelte@5.57.1(@typescript-eslint/types@8.70.1))(vitest@4.1.11))(better-call@1.4.0(zod@4.6.5))': + '@better-auth/scim@1.7.12(@better-auth/core@1.7.12(@better-auth/utils@0.5.0)(@better-fetch/fetch@1.3.2)(@opentelemetry/api@1.9.1)(better-call@1.4.4(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0))(@better-auth/utils@0.5.0)(better-auth@1.7.12(@opentelemetry/api@1.9.1)(mongodb@7.7.0(socks@2.8.9))(mysql2@3.24.4(@types/node@26.6.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.63.0)(@types/node@26.6.3)(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(pg@8.23.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(svelte@5.57.1(@typescript-eslint/types@8.70.1))(vitest@4.1.11))(better-call@1.4.4(zod@4.6.5))': dependencies: - '@better-auth/core': 1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0) - '@better-auth/utils': 0.4.2 + '@better-auth/core': 1.7.12(@better-auth/utils@0.5.0)(@better-fetch/fetch@1.3.2)(@opentelemetry/api@1.9.1)(better-call@1.4.4(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0) + '@better-auth/utils': 0.5.0 '@noble/hashes': 2.4.0 - better-auth: 1.7.3(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-sqlite3@12.11.1)(mongodb@7.7.0(socks@2.8.9))(mysql2@3.24.4(@types/node@26.6.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.63.0)(@types/node@26.6.3)(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(pg@8.23.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(svelte@5.57.1(@typescript-eslint/types@8.70.1))(vitest@4.1.11) - better-call: 1.4.0(zod@4.6.5) + better-auth: 1.7.12(@opentelemetry/api@1.9.1)(mongodb@7.7.0(socks@2.8.9))(mysql2@3.24.4(@types/node@26.6.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.63.0)(@types/node@26.6.3)(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(pg@8.23.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(svelte@5.57.1(@typescript-eslint/types@8.70.1))(vitest@4.1.11) + better-call: 1.4.4(zod@4.6.5) zod: 4.6.5 - '@better-auth/sso@1.7.3(@better-auth/core@1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0))(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-auth@1.7.3(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-sqlite3@12.11.1)(mongodb@7.7.0(socks@2.8.9))(mysql2@3.24.4(@types/node@26.6.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.63.0)(@types/node@26.6.3)(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(pg@8.23.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(svelte@5.57.1(@typescript-eslint/types@8.70.1))(vitest@4.1.11))(better-call@1.4.0(zod@4.6.5))': + '@better-auth/sso@1.7.12(@better-auth/core@1.7.12(@better-auth/utils@0.5.0)(@better-fetch/fetch@1.3.2)(@opentelemetry/api@1.9.1)(better-call@1.4.4(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0))(@better-auth/utils@0.5.0)(@better-fetch/fetch@1.3.2)(better-auth@1.7.12(@opentelemetry/api@1.9.1)(mongodb@7.7.0(socks@2.8.9))(mysql2@3.24.4(@types/node@26.6.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.63.0)(@types/node@26.6.3)(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(pg@8.23.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(svelte@5.57.1(@typescript-eslint/types@8.70.1))(vitest@4.1.11))(better-call@1.4.4(zod@4.6.5))': dependencies: - '@better-auth/core': 1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0) - '@better-auth/utils': 0.4.2 - '@better-fetch/fetch': 1.3.1 + '@better-auth/core': 1.7.12(@better-auth/utils@0.5.0)(@better-fetch/fetch@1.3.2)(@opentelemetry/api@1.9.1)(better-call@1.4.4(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0) + '@better-auth/utils': 0.5.0 + '@better-fetch/fetch': 1.3.2 '@xmldom/xmldom': 0.9.12 - better-auth: 1.7.3(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-sqlite3@12.11.1)(mongodb@7.7.0(socks@2.8.9))(mysql2@3.24.4(@types/node@26.6.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.63.0)(@types/node@26.6.3)(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(pg@8.23.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(svelte@5.57.1(@typescript-eslint/types@8.70.1))(vitest@4.1.11) - better-call: 1.4.0(zod@4.6.5) + better-auth: 1.7.12(@opentelemetry/api@1.9.1)(mongodb@7.7.0(socks@2.8.9))(mysql2@3.24.4(@types/node@26.6.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.63.0)(@types/node@26.6.3)(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(pg@8.23.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(svelte@5.57.1(@typescript-eslint/types@8.70.1))(vitest@4.1.11) + better-call: 1.4.4(zod@4.6.5) fast-xml-parser: 5.10.1 jose: 6.2.12 samlify: 2.13.1 - tldts: 7.4.9 + tldts: 7.4.16 zod: 4.6.5 - '@better-auth/telemetry@1.7.3(@better-auth/core@1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0))(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)': - dependencies: - '@better-auth/core': 1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0) - '@better-auth/utils': 0.4.2 - '@better-fetch/fetch': 1.3.1 - - '@better-auth/utils@0.4.2': + '@better-auth/telemetry@1.7.12(@better-auth/core@1.7.12(@better-auth/utils@0.5.0)(@better-fetch/fetch@1.3.2)(@opentelemetry/api@1.9.1)(better-call@1.4.4(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0))(@better-auth/utils@0.5.0)(@better-fetch/fetch@1.3.2)': dependencies: - '@noble/hashes': 2.4.0 + '@better-auth/core': 1.7.12(@better-auth/utils@0.5.0)(@better-fetch/fetch@1.3.2)(@opentelemetry/api@1.9.1)(better-call@1.4.4(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0) + '@better-auth/utils': 0.5.0 + '@better-fetch/fetch': 1.3.2 '@better-auth/utils@0.5.0': dependencies: '@noble/hashes': 2.4.0 - '@better-fetch/fetch@1.3.1': {} + '@better-fetch/fetch@1.3.2': {} '@braintree/sanitize-url@7.1.2': {} @@ -10202,9 +10095,6 @@ snapshots: fast-wrap-ansi: 0.2.2 sisteransi: 1.0.5 - '@cloudflare/workers-types@4.20260520.1': - optional: true - '@csstools/color-helpers@6.1.2': {} '@csstools/css-calc@3.4.1(@csstools/css-parser-algorithms@4.0.1(@csstools/css-tokenizer@4.0.2))(@csstools/css-tokenizer@4.0.2)': @@ -10870,8 +10760,6 @@ snapshots: '@next/swc-win32-x64-msvc@16.3.8': optional: true - '@noble/ciphers@2.3.0': {} - '@noble/ciphers@2.4.0': {} '@noble/hashes@2.4.0': {} @@ -10917,8 +10805,6 @@ snapshots: '@opentelemetry/api@1.9.1': optional: true - '@opentelemetry/semantic-conventions@1.43.0': {} - '@oxc-project/types@0.154.0': {} '@playwright/test@1.63.0': @@ -12213,27 +12099,26 @@ snapshots: baseline-browser-mapping@2.11.14: {} - better-auth@1.7.3(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-sqlite3@12.11.1)(mongodb@7.7.0(socks@2.8.9))(mysql2@3.24.4(@types/node@26.6.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.63.0)(@types/node@26.6.3)(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(pg@8.23.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(svelte@5.57.1(@typescript-eslint/types@8.70.1))(vitest@4.1.11): - dependencies: - '@better-auth/core': 1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0) - '@better-auth/drizzle-adapter': 1.7.3(@better-auth/core@1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0))(@better-auth/utils@0.4.2) - '@better-auth/kysely-adapter': 1.7.3(@better-auth/core@1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0))(@better-auth/utils@0.4.2)(kysely@0.29.4) - '@better-auth/memory-adapter': 1.7.3(@better-auth/core@1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0))(@better-auth/utils@0.4.2) - '@better-auth/mongo-adapter': 1.7.3(@better-auth/core@1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0))(@better-auth/utils@0.4.2)(mongodb@7.7.0(socks@2.8.9)) - '@better-auth/prisma-adapter': 1.7.3(@better-auth/core@1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0))(@better-auth/utils@0.4.2) - '@better-auth/telemetry': 1.7.3(@better-auth/core@1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@4.20260520.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0))(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1) - '@better-auth/utils': 0.4.2 - '@better-fetch/fetch': 1.3.1 - '@noble/ciphers': 2.3.0 + better-auth@1.7.12(@opentelemetry/api@1.9.1)(mongodb@7.7.0(socks@2.8.9))(mysql2@3.24.4(@types/node@26.6.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.63.0)(@types/node@26.6.3)(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(pg@8.23.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(svelte@5.57.1(@typescript-eslint/types@8.70.1))(vitest@4.1.11): + dependencies: + '@better-auth/core': 1.7.12(@better-auth/utils@0.5.0)(@better-fetch/fetch@1.3.2)(@opentelemetry/api@1.9.1)(better-call@1.4.4(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0) + '@better-auth/drizzle-adapter': 1.7.12(@better-auth/core@1.7.12(@better-auth/utils@0.5.0)(@better-fetch/fetch@1.3.2)(@opentelemetry/api@1.9.1)(better-call@1.4.4(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0))(@better-auth/utils@0.5.0) + '@better-auth/kysely-adapter': 1.7.12(@better-auth/core@1.7.12(@better-auth/utils@0.5.0)(@better-fetch/fetch@1.3.2)(@opentelemetry/api@1.9.1)(better-call@1.4.4(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0))(@better-auth/utils@0.5.0)(kysely@0.29.4) + '@better-auth/memory-adapter': 1.7.12(@better-auth/core@1.7.12(@better-auth/utils@0.5.0)(@better-fetch/fetch@1.3.2)(@opentelemetry/api@1.9.1)(better-call@1.4.4(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0))(@better-auth/utils@0.5.0) + '@better-auth/mongo-adapter': 1.7.12(@better-auth/core@1.7.12(@better-auth/utils@0.5.0)(@better-fetch/fetch@1.3.2)(@opentelemetry/api@1.9.1)(better-call@1.4.4(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0))(@better-auth/utils@0.5.0)(mongodb@7.7.0(socks@2.8.9)) + '@better-auth/prisma-adapter': 1.7.12(@better-auth/core@1.7.12(@better-auth/utils@0.5.0)(@better-fetch/fetch@1.3.2)(@opentelemetry/api@1.9.1)(better-call@1.4.4(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0))(@better-auth/utils@0.5.0) + '@better-auth/telemetry': 1.7.12(@better-auth/core@1.7.12(@better-auth/utils@0.5.0)(@better-fetch/fetch@1.3.2)(@opentelemetry/api@1.9.1)(better-call@1.4.4(zod@4.6.5))(jose@6.2.12)(kysely@0.29.4)(nanostores@1.4.0))(@better-auth/utils@0.5.0)(@better-fetch/fetch@1.3.2) + '@better-auth/utils': 0.5.0 + '@better-fetch/fetch': 1.3.2 + '@noble/ciphers': 2.4.0 '@noble/hashes': 2.4.0 - better-call: 1.4.0(zod@4.6.5) + better-call: 1.4.4(zod@4.6.5) defu: 6.1.7 jose: 6.2.12 kysely: 0.29.4 nanostores: 1.4.0 zod: 4.6.5 optionalDependencies: - better-sqlite3: 12.11.1 mongodb: 7.7.0(socks@2.8.9) mysql2: 3.24.4(@types/node@26.6.3) next: 16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.63.0)(@types/node@26.6.3)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) @@ -12243,24 +12128,17 @@ snapshots: svelte: 5.57.1(@typescript-eslint/types@8.70.1) vitest: 4.1.11(@opentelemetry/api@1.9.1)(@types/node@26.6.3)(@vitest/coverage-v8@4.1.11)(happy-dom@20.10.2)(jsdom@30.1.1(@noble/hashes@2.4.0))(msw@2.14.6(@types/node@26.6.3)(typescript@6.0.3))(vite@8.3.4(@types/node@26.6.3)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15(patch_hash=4d1d35da1809be2a945519cb26890e48107810b9b66c6913a6a89abb5ad6a1e6))(yaml@2.9.1)) transitivePeerDependencies: - - '@cloudflare/workers-types' - '@opentelemetry/api' - better-call@1.4.0(zod@4.6.5): + better-call@1.4.4(zod@4.6.5): dependencies: '@better-auth/utils': 0.5.0 - '@better-fetch/fetch': 1.3.1 + '@better-fetch/fetch': 1.3.2 rou3: 0.9.2 set-cookie-parser: 3.1.2 optionalDependencies: zod: 4.6.5 - better-sqlite3@12.11.1: - dependencies: - bindings: 1.5.0 - prebuild-install: 7.1.3 - optional: true - better-sqlite3@13.0.3: dependencies: node-addon-api: 8.9.2 @@ -12276,11 +12154,6 @@ snapshots: buffers: 0.1.1 chainsaw: 0.1.0 - bindings@1.5.0: - dependencies: - file-uri-to-path: 1.0.0 - optional: true - bl@4.1.0: dependencies: buffer: 5.7.1 @@ -12411,9 +12284,6 @@ snapshots: dependencies: readdirp: 5.0.0 - chownr@1.1.4: - optional: true - class-variance-authority@0.7.1: dependencies: clsx: 2.1.1 @@ -12743,14 +12613,6 @@ snapshots: dependencies: character-entities: 2.0.2 - decompress-response@6.0.0: - dependencies: - mimic-response: 3.1.0 - optional: true - - deep-extend@0.6.0: - optional: true - deep-is@0.1.4: {} default-browser-id@5.0.1: {} @@ -13071,9 +12933,6 @@ snapshots: unzipper: 0.10.14 uuid: 11.1.1 - expand-template@2.0.3: - optional: true - expect-type@1.4.0: {} express-rate-limit@8.6.1(express@5.2.1): @@ -13180,9 +13039,6 @@ snapshots: dependencies: flat-cache: 6.1.23 - file-uri-to-path@1.0.0: - optional: true - finalhandler@2.1.1: dependencies: debug: 4.4.3(supports-color@8.1.1) @@ -13392,9 +13248,6 @@ snapshots: getopts@2.3.0: {} - github-from-package@0.0.0: - optional: true - github-slugger@2.0.0: {} glob-parent@6.0.2: @@ -13632,9 +13485,6 @@ snapshots: inherits@2.0.4: {} - ini@1.3.8: - optional: true - inline-style-parser@0.2.7: {} internmap@1.0.1: {} @@ -14566,9 +14416,6 @@ snapshots: dependencies: mime-db: 1.54.0 - mimic-response@3.1.0: - optional: true - mingo@7.2.4: {} minimatch@10.2.3: @@ -14583,9 +14430,6 @@ snapshots: minipass@7.1.3: {} - mkdirp-classic@0.5.3: - optional: true - mkdirp@0.5.6: dependencies: minimist: 1.2.8 @@ -14748,9 +14592,6 @@ snapshots: nanostores@1.4.0: {} - napi-build-utils@2.0.0: - optional: true - native-duplexpair@1.0.0: {} natural-compare@1.4.0: {} @@ -14825,11 +14666,6 @@ snapshots: - babel-plugin-macros optional: true - node-abi@3.96.0: - dependencies: - semver: 7.8.5 - optional: true - node-addon-api@8.9.2: {} node-rsa@1.1.1: @@ -15068,22 +14904,6 @@ snapshots: powershell-utils@0.1.0: {} - prebuild-install@7.1.3: - dependencies: - detect-libc: 2.1.2 - expand-template: 2.0.3 - github-from-package: 0.0.0 - minimist: 1.2.8 - mkdirp-classic: 0.5.3 - napi-build-utils: 2.0.0 - node-abi: 3.96.0 - pump: 3.0.4 - rc: 1.2.8 - simple-get: 4.0.1 - tar-fs: 2.1.5 - tunnel-agent: 0.6.0 - optional: true - prelude-ls@1.2.1: {} pretty-format@27.5.1: @@ -15105,12 +14925,6 @@ snapshots: forwarded: 0.2.0 ipaddr.js: 1.9.1 - pump@3.0.4: - dependencies: - end-of-stream: 1.4.5 - once: 1.4.0 - optional: true - punycode@2.3.1: {} pure-rand@8.4.2: {} @@ -15145,14 +14959,6 @@ snapshots: iconv-lite: 0.7.3 unpipe: 1.0.0 - rc@1.2.8: - dependencies: - deep-extend: 0.6.0 - ini: 1.3.8 - minimist: 1.2.8 - strip-json-comments: 2.0.1 - optional: true - react-dom@19.2.8(react@19.2.8): dependencies: react: 19.2.8 @@ -15598,16 +15404,6 @@ snapshots: signal-exit@4.1.0: optional: true - simple-concat@1.0.1: - optional: true - - simple-get@4.0.1: - dependencies: - decompress-response: 6.0.0 - once: 1.4.0 - simple-concat: 1.0.1 - optional: true - sisteransi@1.0.5: {} smart-buffer@4.2.0: @@ -15682,9 +15478,6 @@ snapshots: dependencies: ansi-regex: 5.0.1 - strip-json-comments@2.0.1: - optional: true - strnum@2.4.1: dependencies: anynum: 1.0.1 @@ -15759,14 +15552,6 @@ snapshots: tapable@2.3.3: {} - tar-fs@2.1.5: - dependencies: - chownr: 1.1.4 - mkdirp-classic: 0.5.3 - pump: 3.0.4 - tar-stream: 2.2.0 - optional: true - tar-stream@2.2.0: dependencies: bl: 4.1.0 @@ -15843,16 +15628,10 @@ snapshots: tldts-core@7.4.16: {} - tldts-core@7.4.9: {} - tldts@7.4.16: dependencies: tldts-core: 7.4.16 - tldts@7.4.9: - dependencies: - tldts-core: 7.4.9 - tmp@0.2.7: {} toidentifier@1.0.1: {} @@ -15926,11 +15705,6 @@ snapshots: optionalDependencies: fsevents: 2.3.3 - tunnel-agent@0.6.0: - dependencies: - safe-buffer: 5.2.1 - optional: true - turbo@2.11.5: optionalDependencies: '@turbo/darwin-64': 2.11.5 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index ecbd0f4bfde..c7522b82a3b 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -251,8 +251,8 @@ overrides: # requires the declared range to be exact and to export what we import). # Move all eleven together, in one commit, or better-auth init throws and # every auth endpoint 500s. - 'better-auth@<2.0.0': '1.7.3' - '@better-auth/core@<2.0.0': '1.7.3' + 'better-auth@<2.0.0': '1.7.12' + '@better-auth/core@<2.0.0': '1.7.12' # scim carries the family's target — see the @better-auth/scim note # above. It was held at 1.7.1 EXACT, one deliberate step behind `^1.7.1`, # because `^1.7.1` then resolved scim to 1.7.2 while the installed family @@ -283,15 +283,15 @@ overrides: # a lift whose new version drops a symbol `plugin-auth` imports. # What stays true: the whole family still moves as ONE line, and a bump that # moves scim alone is still the mistake the #3653 ruling named. - '@better-auth/scim@<2.0.0': '1.7.3' - '@better-auth/oauth-provider@<2.0.0': '1.7.3' - '@better-auth/sso@<2.0.0': '1.7.3' - '@better-auth/drizzle-adapter@<2.0.0': '1.7.3' - '@better-auth/kysely-adapter@<2.0.0': '1.7.3' - '@better-auth/memory-adapter@<2.0.0': '1.7.3' - '@better-auth/mongo-adapter@<2.0.0': '1.7.3' - '@better-auth/prisma-adapter@<2.0.0': '1.7.3' - '@better-auth/telemetry@<2.0.0': '1.7.3' + '@better-auth/scim@<2.0.0': '1.7.12' + '@better-auth/oauth-provider@<2.0.0': '1.7.12' + '@better-auth/sso@<2.0.0': '1.7.12' + '@better-auth/drizzle-adapter@<2.0.0': '1.7.12' + '@better-auth/kysely-adapter@<2.0.0': '1.7.12' + '@better-auth/memory-adapter@<2.0.0': '1.7.12' + '@better-auth/mongo-adapter@<2.0.0': '1.7.12' + '@better-auth/prisma-adapter@<2.0.0': '1.7.12' + '@better-auth/telemetry@<2.0.0': '1.7.12' 'uuid@<12.0.0': '^11.1.1' 'postcss@<9.0.0': '^8.5.10' 'cookie@<0.8.0': '^0.7.0' From 9ffd7eb619263bb1998b2c9eea3abf4d9123e967 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 21 Oct 2026 10:30:14 +0000 Subject: [PATCH 2/9] test(plugin-auth): ledger the oauth-provider rotate-keys route 1.7.12 publishes @better-auth/oauth-provider 1.7.12 registers POST /oauth2/client/rotate-keys, so the catch-all now publishes it. The handler refuses unless the plugin is given allowClientKeyRotation, which auth-manager does not set. Claude-Session: https://claude.ai/code/session_011TdZ8GjixNZFLz1xJD9zzK Co-authored-by: Claude --- packages/plugins/plugin-auth/src/auth-route-ledger.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/plugins/plugin-auth/src/auth-route-ledger.ts b/packages/plugins/plugin-auth/src/auth-route-ledger.ts index 75e17329bd3..20984305737 100644 --- a/packages/plugins/plugin-auth/src/auth-route-ledger.ts +++ b/packages/plugins/plugin-auth/src/auth-route-ledger.ts @@ -382,6 +382,13 @@ export const BETTER_AUTH_MOUNTED_SURFACE: readonly string[] = [ 'POST /api/v1/auth/get-session', 'POST /api/v1/auth/link-social', 'POST /api/v1/auth/oauth2/authorize', + // `private_key_jwt` client key rotation. Added to `@better-auth/oauth-provider` + // after 1.7.3 and published here since the 1.7.12 lift (#25096). The handler + // refuses before it reads anything unless the plugin is given + // `allowClientKeyRotation`, and `auth-manager.ts` does not set it, so every + // call answers 403 `access_denied` ("Client key rotation is disabled"), + // measured on this stack for #25096. Turning it on is its own decision. + 'POST /api/v1/auth/oauth2/client/rotate-keys', 'POST /api/v1/auth/oauth2/client/rotate-secret', 'POST /api/v1/auth/oauth2/consent', 'POST /api/v1/auth/oauth2/continue', From aa3112430a4d8259fe2ea34848dd93235b1eae08 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 21 Oct 2026 10:32:17 +0000 Subject: [PATCH 3/9] test(plugin-auth): pin the session-read failure answer and single-use reservations on 1.7.12 Two vendor changes the lift brings, measured on a real ObjectQL + SQL stack: customSession lets a failed session lookup through as 500 FAILED_TO_GET_SESSION instead of a signed-out null, and the adapter keeps the forced reservation id so a replayed reservation is refused. Claude-Session: https://claude.ai/code/session_011TdZ8GjixNZFLz1xJD9zzK Co-authored-by: Claude --- .../src/session-read-failure-answer.test.ts | 157 ++++++++++++++++++ ...erification-reservation-single-use.test.ts | 109 ++++++++++++ 2 files changed, 266 insertions(+) create mode 100644 packages/plugins/plugin-auth/src/session-read-failure-answer.test.ts create mode 100644 packages/plugins/plugin-auth/src/verification-reservation-single-use.test.ts diff --git a/packages/plugins/plugin-auth/src/session-read-failure-answer.test.ts b/packages/plugins/plugin-auth/src/session-read-failure-answer.test.ts new file mode 100644 index 00000000000..79f68d2d3ce --- /dev/null +++ b/packages/plugins/plugin-auth/src/session-read-failure-answer.test.ts @@ -0,0 +1,157 @@ +// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. + +/** + * [#25096] A session lookup the store cannot answer is a FAILURE, never a + * signed-out caller. + * + * plugin-auth mounts better-auth's `customSession` whenever a data engine is + * configured, so `GET /get-session` and every in-process `api.getSession` run + * its override. Up to 1.7.7 that override caught whatever the inner session + * read threw and answered `null`, so a store outage read exactly like "nobody + * is signed in": over HTTP `anonymous-session-refusal.ts` then turned that + * `null` into its 401 `UNAUTHENTICATED`, telling a signed-in browser to sign in + * again. From 1.7.8 (better-auth/better-auth#11391) the override lets the + * read's error through, so the store failure reaches the caller as + * better-auth's own 500 `FAILED_TO_GET_SESSION`, which that seam passes + * through untouched (it converts a `200` + `null` only). + * + * That is the right answer for this platform (AGENTS.md, "Absence must be + * loud" and the degradation-log-level rule): a failure the caller is told + * about is not a silent degradation, and the browser can tell "retry later" + * from "sign in again". The in-process callers that want the old reading keep + * it on purpose: `resolveSessionData` (runtime) and `resolveRequestExecutionContext` + * (core) catch the throw themselves and treat the request as anonymous. + * + * Real stack: `ObjectQL` over `@objectstack/driver-sql` + better-sqlite3, the + * objects from this plugin's manifest and a real `AuthManager`. The fault is + * injected at the engine, on the `sys_session` reads alone, after the sign-up + * wrote the session, so every other read the request makes is the real one. + * + * Pinned: + * - the store failure answers 500 `FAILED_TO_GET_SESSION` over HTTP and + * rejects the in-process read, and it does not clear the session cookie; + * - the two controls the failure must stay distinguishable from: the healthy + * store answers the session, and a token the store does not hold is signed + * out (401 `UNAUTHENTICATED` over HTTP, `null` in process). + */ + +import { describe, it, expect, afterEach, vi } from 'vitest'; +import { ObjectQL } from '@objectstack/objectql'; +import { SqlDriver } from '@objectstack/driver-sql'; +import { AuthManager } from './auth-manager.js'; +import { authIdentityObjects } from './manifest.js'; + +const BASE = 'http://localhost:3000'; +const AUTH = `${BASE}/api/v1/auth`; +const SECRET = 'test-secret-at-least-32-chars-long-25096'; +const PASSWORD = 'S3cure!Passw0rd-25096'; +const SESSION_OBJECT = 'sys_session'; + +const engines: ObjectQL[] = []; +afterEach(async () => { + vi.restoreAllMocks(); + while (engines.length) { + try { await engines.pop()!.destroy(); } catch { /* noop */ } + } +}); + +async function bootEngine(): Promise { + const engine = new ObjectQL(); + engines.push(engine); + engine.registerDriver(new SqlDriver({ client: 'better-sqlite3', connection: { filename: ':memory:' }, useNullAsDefault: true }), true); + await engine.init(); + for (const object of authIdentityObjects) engine.registry.registerObject(object as never, '@objectstack/plugin-auth'); + await engine.syncSchemas(); + return engine; +} + +const cookieFrom = (response: Response): string => + (response.headers.getSetCookie?.() ?? [response.headers.get('set-cookie') ?? '']) + .map((c) => c.split(';')[0]) + .filter(Boolean) + .join('; '); + +const getSession = (manager: AuthManager, cookie: string) => + manager.handleRequest(new Request(`${AUTH}/get-session`, { headers: { cookie } })); + +/** A signed-up user's session cookie, on a manager over a real engine. */ +async function signedIn(): Promise<{ engine: ObjectQL; manager: AuthManager; cookie: string }> { + const engine = await bootEngine(); + const manager = new AuthManager({ secret: SECRET, baseUrl: BASE, dataEngine: engine as never } as never); + const signedUp = await manager.handleRequest(new Request(`${AUTH}/sign-up/email`, { + method: 'POST', + headers: { 'Content-Type': 'application/json', origin: BASE }, + body: JSON.stringify({ email: 'reader@example.com', password: PASSWORD, name: 'Reader' }), + })); + expect(signedUp.status, await signedUp.clone().text()).toBe(200); + const cookie = cookieFrom(signedUp); + expect(cookie, 'the sign-up set a session cookie').toMatch(/session_token=/); + return { engine, manager, cookie }; +} + +/** Every engine read of `sys_session` throws from here on; every other read is the real one. */ +function failSessionStore(engine: ObjectQL): { attempts: () => number } { + let attempts = 0; + const target = engine as unknown as Record<'find' | 'findOne', (object: string, ...rest: unknown[]) => Promise>; + for (const method of ['find', 'findOne'] as const) { + const real = target[method].bind(engine); + vi.spyOn(target, method).mockImplementation(async (object: string, ...rest: unknown[]) => { + if (object === SESSION_OBJECT) { + attempts += 1; + throw new Error('session store unavailable (injected)'); + } + return real(object, ...rest); + }); + } + return { attempts: () => attempts }; +} + +describe('[#25096] a session lookup the store cannot answer is a failure, never a signed-out caller', () => { + it('CONTROL: the healthy store answers the signed-in session', async () => { + const { manager, cookie } = await signedIn(); + const res = await getSession(manager, cookie); + expect(res.status).toBe(200); + const body = (await res.json()) as { user?: { email?: string } } | null; + expect(body?.user?.email).toBe('reader@example.com'); + }); + + it('CONTROL: a token the store does not hold is signed out, 401 UNAUTHENTICATED over HTTP and null in process', async () => { + const { manager } = await signedIn(); + const stranger = 'better-auth.session_token=not-a-session-the-store-holds.sig'; + const res = await getSession(manager, stranger); + const text = await res.clone().text(); + expect(res.status, text).toBe(401); + expect(JSON.stringify(JSON.parse(text))).toContain('UNAUTHENTICATED'); + const api = await manager.getApi(); + expect(await api.getSession({ headers: new Headers({ cookie: stranger }) } as never)).toBeNull(); + }); + + it('over HTTP: the store failure answers 500 FAILED_TO_GET_SESSION and keeps the session cookie', async () => { + vi.spyOn(console, 'error').mockImplementation(() => {}); + const { engine, manager, cookie } = await signedIn(); + const fault = failSessionStore(engine); + + const res = await getSession(manager, cookie); + + expect(fault.attempts(), 'the request really reached the session store').toBeGreaterThan(0); + const text = await res.clone().text(); + expect(res.status, text).toBe(500); + expect((JSON.parse(text) as { code?: string }).code).toBe('FAILED_TO_GET_SESSION'); + // Nothing tells the browser to drop its credential: the session still + // exists, the store just could not read it. + const cleared = (res.headers.getSetCookie?.() ?? []).filter((c) => /session_token=;|session_token=\s*;|Max-Age=0/i.test(c)); + expect(cleared).toEqual([]); + }); + + it('in process: the store failure rejects `api.getSession` instead of resolving null', async () => { + vi.spyOn(console, 'error').mockImplementation(() => {}); + const { engine, manager, cookie } = await signedIn(); + const api = await manager.getApi(); + const fault = failSessionStore(engine); + + const read = api.getSession({ headers: new Headers({ cookie }) } as never); + + await expect(read).rejects.toMatchObject({ statusCode: 500, body: { code: 'FAILED_TO_GET_SESSION' } }); + expect(fault.attempts()).toBeGreaterThan(0); + }); +}); diff --git a/packages/plugins/plugin-auth/src/verification-reservation-single-use.test.ts b/packages/plugins/plugin-auth/src/verification-reservation-single-use.test.ts new file mode 100644 index 00000000000..ee125330d0b --- /dev/null +++ b/packages/plugins/plugin-auth/src/verification-reservation-single-use.test.ts @@ -0,0 +1,109 @@ +// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. + +/** + * [#25096] The ObjectQL adapter keeps the primary key better-auth forces on a + * single-use reservation, so a replayed reservation is refused. + * + * better-auth's replay checks (DPoP proof `jti`s, `private_key_jwt` client + * assertions, SAML assertion ids, SIWE nonces) all go through + * `internalAdapter.reserveVerificationValue`. It inserts a `verification` row + * whose `id` is derived from the guarded value (SHA-256 of + * `reserve:IDENTIFIER`), with `forceAllowId: true`, and reads a failed insert + * as "already taken" only when a row with THAT id exists. So the whole check + * rests on one property of the adapter underneath: the forced id must land as + * the row's primary key. An adapter or engine that swaps in an id of its own + * lets every insert succeed, and every replay with it. + * + * 1.7.8 (better-auth/better-auth#11625) fixed that for `generateId: "uuid"`, + * where the id field used to replace the non-UUID digest. plugin-auth sets no + * `generateId`, so better-auth's own generator runs and the forced digest is + * passed through as base64url (`encodeDeterministicId`). What this file pins is + * the half better-auth cannot see: that the ObjectQL adapter, the engine and + * the SQL driver keep it. + * + * Real stack: `ObjectQL` over `@objectstack/driver-sql` + better-sqlite3, the + * objects from this plugin's manifest and a real `AuthManager`; the + * reservation is better-auth's own, read off the instance's `$context`. + */ + +import { describe, it, expect, afterEach } from 'vitest'; +import { createHash } from 'node:crypto'; +import { ObjectQL } from '@objectstack/objectql'; +import { SqlDriver } from '@objectstack/driver-sql'; +import { AuthManager } from './auth-manager.js'; +import { authIdentityObjects } from './manifest.js'; + +const BASE = 'http://localhost:3000'; +const SECRET = 'test-secret-at-least-32-chars-long-25096'; +const VERIFICATION_OBJECT = 'sys_verification'; + +type Row = Record; + +interface ReservingContext { + internalAdapter: { + reserveVerificationValue(data: { identifier: string; value: string; expiresAt: Date }): Promise; + }; +} + +const engines: ObjectQL[] = []; +afterEach(async () => { + while (engines.length) { + try { await engines.pop()!.destroy(); } catch { /* noop */ } + } +}); + +async function boot(): Promise<{ engine: ObjectQL; context: ReservingContext }> { + const engine = new ObjectQL(); + engines.push(engine); + engine.registerDriver(new SqlDriver({ client: 'better-sqlite3', connection: { filename: ':memory:' }, useNullAsDefault: true }), true); + await engine.init(); + for (const object of authIdentityObjects) engine.registry.registerObject(object as never, '@objectstack/plugin-auth'); + await engine.syncSchemas(); + const manager = new AuthManager({ secret: SECRET, baseUrl: BASE, dataEngine: engine as never } as never); + const auth = (await manager.getAuthInstance()) as unknown as { $context: Promise }; + return { engine, context: await auth.$context }; +} + +/** Rows at DRIVER level, below the engine, with the identifier the reservation stored. */ +async function reservationRows(engine: ObjectQL, identifier: string): Promise { + const driver = (engine as unknown as { getDriver(o: string): { find(o: string, q: unknown): Promise } }) + .getDriver(VERIFICATION_OBJECT); + const found = await driver.find(VERIFICATION_OBJECT, { where: { identifier } }); + return (Array.isArray(found) ? found : [found]).filter(Boolean) as Row[]; +} + +/** better-auth's deterministic reservation id without a `generateId` strategy: base64url SHA-256, unpadded. */ +const reservationId = (identifier: string): string => + createHash('sha256').update(`reserve:${identifier}`).digest('base64url'); + +const expiresAt = () => new Date(Date.now() + 5 * 60_000); + +describe('[#25096] a single-use reservation refuses its replay through the ObjectQL adapter', () => { + it('the first reservation wins and is stored under the id better-auth forced', async () => { + const { engine, context } = await boot(); + const identifier = 'replay-probe:first'; + + expect(await context.internalAdapter.reserveVerificationValue({ identifier, value: 'v', expiresAt: expiresAt() })).toBe(true); + + const rows = await reservationRows(engine, identifier); + expect(rows).toHaveLength(1); + expect(rows[0]!.id, 'the engine kept the forced primary key').toBe(reservationId(identifier)); + }); + + it('the replay of the same value is refused, and leaves one row', async () => { + const { engine, context } = await boot(); + const identifier = 'replay-probe:replayed'; + + expect(await context.internalAdapter.reserveVerificationValue({ identifier, value: 'v', expiresAt: expiresAt() })).toBe(true); + expect(await context.internalAdapter.reserveVerificationValue({ identifier, value: 'v', expiresAt: expiresAt() })).toBe(false); + + expect(await reservationRows(engine, identifier)).toHaveLength(1); + }); + + it('CONTROL: a different value is its own reservation and wins', async () => { + const { context } = await boot(); + + expect(await context.internalAdapter.reserveVerificationValue({ identifier: 'replay-probe:a', value: 'v', expiresAt: expiresAt() })).toBe(true); + expect(await context.internalAdapter.reserveVerificationValue({ identifier: 'replay-probe:b', value: 'v', expiresAt: expiresAt() })).toBe(true); + }); +}); From 347772618d56f4af65a1877dbfdbf42367fbdc2b Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 21 Oct 2026 10:46:25 +0000 Subject: [PATCH 4/9] docs(plugin-auth): re-measure the better-auth version attestations on 1.7.12 Every live reading that named 1.7.3 was re-measured against the installed 1.7.12 dist or by the test that pins it, and restamped with the date and the card. Facts about the 1.7.3 release itself stay as written. The internal-field-readback census is scoped to its 1.7.3 trace and flagged instead of restamped: sso's verify-domain reads the verification identifier back off the row, which the census says no flow does. The pnpm-workspace.yaml family note states the new target and what the lift moved. Claude-Session: https://claude.ai/code/session_011TdZ8GjixNZFLz1xJD9zzK Co-authored-by: Claude --- .../src/account-invitation-marker.ts | 7 ++++--- ...port-users-invite-delivery-failure.test.ts | 3 ++- .../plugin-auth/src/auth-email-locale.test.ts | 8 ++++---- .../plugins/plugin-auth/src/auth-manager.ts | 19 ++++++++++-------- .../plugin-auth/src/auth-schema-config.ts | 6 +++--- .../src/implicit-account-linking.ts | 5 +++-- .../plugin-auth/src/in-process-redispatch.ts | 3 ++- .../src/internal-field-readback.ts | 8 +++++++- .../src/invite-role-not-found-code.ts | 4 ++-- .../src/list-user-invitations-verification.ts | 6 +++--- .../plugin-auth/src/organization-delete.ts | 2 +- .../src/session-envelope-completion.ts | 6 +++--- .../src/two-factor-totp-issuer.test.ts | 5 +++-- pnpm-workspace.yaml | 20 +++++++++++++++---- 14 files changed, 64 insertions(+), 38 deletions(-) diff --git a/packages/plugins/plugin-auth/src/account-invitation-marker.ts b/packages/plugins/plugin-auth/src/account-invitation-marker.ts index de941fab232..06fb0a518a2 100644 --- a/packages/plugins/plugin-auth/src/account-invitation-marker.ts +++ b/packages/plugins/plugin-auth/src/account-invitation-marker.ts @@ -11,7 +11,8 @@ * is what creates the row's credential on first set. But better-auth hands the * resulting link only to `sendResetPassword({ user, url, token }, ctx.request)`; * `requestPasswordReset` itself answers `{ status, message }` and nothing else - * (installed better-auth 1.7.3, `dist/api/routes/password.mjs`). So the import + * (better-auth 1.7.12, `dist/api/routes/password.mjs`, re-measured 2026-10-21 + * for #25096). So the import * never holds the link, and the template choice can only be made inside * `sendResetPassword` (`auth-manager.ts`). Without a marker that callback * cannot tell an administrator's invitation from a user who forgot their @@ -65,8 +66,8 @@ * * better-auth runs `sendResetPassword` through `runInBackgroundOrAwait`, which * CATCHES and logs whatever the send throws, and `requestPasswordReset` still - * answers `{ status: true }` (installed 1.7.3, `dist/context/create-context.mjs` - * and `dist/api/routes/password.mjs`). That is right for the public door — the + * answers `{ status: true }` (better-auth 1.7.12, `dist/context/create-context.mjs` + * and `dist/api/routes/password.mjs`, re-measured 2026-10-21 for #25096). That is right for the public door — the * answer must not say whether an address exists or whether its mail went out — * and it means a throw inside the send can never reach the import. No * better-auth option makes the call rethrow: `advanced.backgroundTasks.handler` diff --git a/packages/plugins/plugin-auth/src/admin-import-users-invite-delivery-failure.test.ts b/packages/plugins/plugin-auth/src/admin-import-users-invite-delivery-failure.test.ts index 8873a99d148..984a26f89e9 100644 --- a/packages/plugins/plugin-auth/src/admin-import-users-invite-delivery-failure.test.ts +++ b/packages/plugins/plugin-auth/src/admin-import-users-invite-delivery-failure.test.ts @@ -6,7 +6,8 @@ * The import invites an email row by asking better-auth for a password reset, * and better-auth runs `sendResetPassword` through `runInBackgroundOrAwait`, * which catches and logs whatever the send throws and still answers - * `{ status: true }` (installed 1.7.3, `dist/context/create-context.mjs`). So a + * `{ status: true }` (better-auth 1.7.12, `dist/context/create-context.mjs`, + * re-measured 2026-10-21 for #25096). So a * throw inside the send can never reach the import. `sendResetPassword` now * settles a delivery receipt the import's own request carries * (`account-invitation-marker.ts`), and the import reads it after the request diff --git a/packages/plugins/plugin-auth/src/auth-email-locale.test.ts b/packages/plugins/plugin-auth/src/auth-email-locale.test.ts index 338f8623ab6..b5666cf7427 100644 --- a/packages/plugins/plugin-auth/src/auth-email-locale.test.ts +++ b/packages/plugins/plugin-auth/src/auth-email-locale.test.ts @@ -867,8 +867,8 @@ describe("#14641 — an invitation reads the INVITEE's own sys_user.locale", () * recipient-keyed engine, not by asserting it about this send alone. * * Two branches, because a magic link is BOTH a sign-in for an existing account - * and a sign-up for a new address (re-measured 2026-09-11 in the installed - * better-auth 1.7.3, unchanged from 1.7.2: the `/sign-in/magic-link` handler + * and a sign-up for a new address (re-measured 2026-10-21 for #25096 on + * better-auth 1.7.12, unchanged since 1.7.2: the `/sign-in/magic-link` handler * takes `email` straight off the body, stores a verification value and calls * `sendMagicLink` — no user lookup on that path at all — while * `/magic-link/verify` reads `findUserByEmail` and, finding nobody, calls @@ -1003,8 +1003,8 @@ describe("#15106 — the magic link reads the recipient's own sys_user.locale", }); it('matches the address better-auth itself will resolve the link with — lowercased', async () => { - // ⚠️ Measured against the installed better-auth 1.7.3 (2026-09-11), not - // assumed, and unchanged from the 1.7.2 reading this replaces: + // ⚠️ Measured against better-auth 1.7.12 (2026-10-21, #25096), not + // assumed, and unchanged since the 1.7.2 reading: // `signInMagicLinkBodySchema` declares `email: z.email()` with no case // transform, so a typed `Ada@Example.com` arrives here verbatim, while // `internalAdapter.findUserByEmail` — what `/magic-link/verify` resolves diff --git a/packages/plugins/plugin-auth/src/auth-manager.ts b/packages/plugins/plugin-auth/src/auth-manager.ts index 9bf5c29d981..32d727067e6 100644 --- a/packages/plugins/plugin-auth/src/auth-manager.ts +++ b/packages/plugins/plugin-auth/src/auth-manager.ts @@ -1799,8 +1799,9 @@ export class AuthManager { // The deployment's product name, from the one authority every auth // email already reads (`getAppName()`: the `branding.workspace_name` // override, else the configured `appName`, else 'ObjectStack'). - // better-auth 1.7.3 reads this key once, into its context's `appName` - // (unset ⇒ "Better Auth"), and reads that in exactly two places: the + // better-auth 1.7.12 (re-read 2026-10-21 for #25096) reads this key once, + // into its context's `appName` (unset ⇒ "Better Auth"), and reads that + // in exactly two places: the // issuer and label prefix of the otpauth URI that `/two-factor/enable` // and `/two-factor/get-totp-uri` answer. No cookie name derives from it // (the prefix is the literal "better-auth") and nothing stores it, so an @@ -2058,8 +2059,8 @@ export class AuthManager { ); } // The lifetime the token in `url` really has: better-auth mints it - // with `resetPasswordTokenExpiresIn || 3600` seconds (installed - // 1.7.3 `routes/password.mjs`) — `||`, so a configured `0` is its + // with `resetPasswordTokenExpiresIn || 3600` seconds (better-auth + // 1.7.12 `routes/password.mjs`, re-measured 2026-10-21 for #25096) — `||`, so a configured `0` is its // default too, and the mail must not say "0 minutes" for it. const ttlSec = this.config.emailAndPassword?.resetPasswordTokenExpiresIn || 60 * 60; // [#23343] An account an administrator created (the identity @@ -2081,7 +2082,8 @@ export class AuthManager { // commit 35e94c96b — the ladder's stored rung. It matters most HERE: an // admin-initiated send (`admin-import-users.ts` calls // `requestPasswordReset` server-side) reaches this callback with NO - // request at all (measured on 1.7.3, #23343), so without this rung + // request at all (measured on 1.7.3, #23343; unchanged on 1.7.12, + // re-read for #25096), so without this rung // the user's mail carries only the deployment default. Best-effort; // `undefined` leaves the #14319 ladder exactly as it was. const storedLocale = await this.storedRecipientLocale({ id: user.id }); @@ -4723,8 +4725,8 @@ export class AuthManager { // // Handing better-auth no `database` makes it build its own in-memory store // in `getBaseAdapter`, and that store is keyed by the schema KEY while - // every read resolves by `modelName`. Re-measured 2026-09-11 on the - // installed better-auth 1.7.3, unchanged from the 1.7.2 reading it replaces + // every read resolves by `modelName`. Re-measured 2026-10-21 for #25096 on + // better-auth 1.7.12, unchanged since the 1.7.2 reading // (`db/adapter-base.mjs` builds the store by schema KEY; // `@better-auth/memory-adapter` throws on the lookup, naming the model): // @@ -9698,7 +9700,8 @@ export class AuthManager { * (plus `id`), or `undefined` when the identifier names no account. * * It asks exactly what better-auth's `/sign-in/email` credential check asks - * (1.7.3: `internalAdapter.findUserByEmail(email.toLowerCase())`, an + * (1.7.12, re-read 2026-10-21 for #25096: + * `internalAdapter.findUserByEmail(email.toLowerCase())`, an * equality match of the `email` column against the lower-cased address, * which is also the spelling `internalAdapter.createUser` stores), so the * gate, the counter, the ledger and the credential check name one account diff --git a/packages/plugins/plugin-auth/src/auth-schema-config.ts b/packages/plugins/plugin-auth/src/auth-schema-config.ts index d66b4690e9b..bc38c1dde37 100644 --- a/packages/plugins/plugin-auth/src/auth-schema-config.ts +++ b/packages/plugins/plugin-auth/src/auth-schema-config.ts @@ -953,12 +953,12 @@ export const buildOidcProviderPluginSchema = buildOauthProviderPluginSchema; // NOTE: there is intentionally no scim mapping constant here, and no // `buildScimPluginSchema()`. `@better-auth/scim` hardcodes its models and exposes -// NO `schema` option — still true of the installed stable `@better-auth/scim@1.7.3` -// (re-read 2026-09-11: `SCIMOptions` declares no `schema` / `modelName` / `fields` +// NO `schema` option — still true of the installed stable `@better-auth/scim@1.7.12` +// (re-read 2026-10-21 for #25096: `SCIMOptions` declares no `schema` / `modelName` / `fields` // member at all — its six members are still connections, authentication, // managedConnections, identity, projection, compatibility; measured 2026-08-19 on // the rc, re-measured 2026-08-27 on stable 1.7.1, again 2026-08-31 on 1.7.2 for -// #13940, and again on 1.7.3 with the family lift), so +// #13940, again on 1.7.3 with the family lift, and on 1.7.12 with #25096), so // there is nowhere to hand one. This is no longer true // of `@better-auth/sso@1.7.1`, which now accepts one (#8224) — for scim, and for // scim alone, the ADAPTER layer is the only available route. diff --git a/packages/plugins/plugin-auth/src/implicit-account-linking.ts b/packages/plugins/plugin-auth/src/implicit-account-linking.ts index be82116f00f..7d3994eae4a 100644 --- a/packages/plugins/plugin-auth/src/implicit-account-linking.ts +++ b/packages/plugins/plugin-auth/src/implicit-account-linking.ts @@ -42,7 +42,7 @@ * * ## Why the enforcement point is `user.validateUserInfo` * - * Measured against the installed better-auth `1.7.3` + * Measured against better-auth `1.7.12` (re-measured 2026-10-21 for #25096) * (`dist/oauth2/link-account.mjs`, `handleOAuthUserInfo`): * * - The library's own gate refuses an implicit link when @@ -63,7 +63,8 @@ * implicitly (`/callback/:id`, `/sign-in/social` with an id token, * one-tap, oauth-proxy, and the SSO plugin, which share the function). * - The EXPLICIT link (`/link-social` → `/callback/:id` with `link` in the - * OAuth state) passes the same `action: 'link-account'`. It is told apart + * OAuth state) passes the same `action: 'link-account'` (1.7.12 routes it + * through `linkOAuthAccount`, in the same file). It is told apart * by the OAuth state the callback parsed (`getOAuthState().link`), which * the server writes from the session at `/link-social`; `generateState` * places `link` AFTER the client-supplied `additionalData`, so a client diff --git a/packages/plugins/plugin-auth/src/in-process-redispatch.ts b/packages/plugins/plugin-auth/src/in-process-redispatch.ts index 2630df2167e..d823066cffc 100644 --- a/packages/plugins/plugin-auth/src/in-process-redispatch.ts +++ b/packages/plugins/plugin-auth/src/in-process-redispatch.ts @@ -27,7 +27,8 @@ * renewing — there is no cookie to fall behind. * * better-auth reads the flag from the query on both kinds of re-dispatch - * (1.7.3, measured by `in-process-session-renewal.pin.test.ts`): the + * (1.7.12, re-measured 2026-10-21 for #25096 by + * `in-process-session-renewal.pin.test.ts`): the * `/get-session` route declares it (`getSessionQuerySchema`, coerced), and * `getSessionFromCtx` — which `sessionMiddleware` and this plugin's own * before-hooks call — spreads the route's `ctx.query` into the read it makes, diff --git a/packages/plugins/plugin-auth/src/internal-field-readback.ts b/packages/plugins/plugin-auth/src/internal-field-readback.ts index 50dec6899e7..65aab815166 100644 --- a/packages/plugins/plugin-auth/src/internal-field-readback.ts +++ b/packages/plugins/plugin-auth/src/internal-field-readback.ts @@ -194,7 +194,8 @@ const READBACK_FIELDS: Readonly> = { // that no generic exit — the data path, and the compliance ledger's CRUD // mirror that honours the same flag — carries it, and each is here because a // better-auth route reads it back OFF a row its storage adapter returned - // (traced in the installed better-auth / @better-auth/* dist, 1.7.3): + // (traced in the then-installed better-auth / @better-auth/* dist, 1.7.3; + // ⚠️ [#25096] NOT re-stamped for 1.7.12 — see the `identifier` note below): // // - `sys_jwks.private_key` — the jwt plugin's key read (`findMany`, no // projection) feeds signing. MEASURED before this row existed: the flag @@ -206,6 +207,11 @@ const READBACK_FIELDS: Readonly> = { // adapter's `consumeOne` re-attaches through this table too). // `required: true`. `identifier` is deliberately absent: no flow reads it // back off a row — it is only ever the lookup key. + // ⚠️ [#25096] That census is wrong, on 1.7.3 and on 1.7.12 alike: + // `@better-auth/sso`'s `/sso/verify-domain` builds the TXT record it + // expects from `identifier` read back off the row, so on this store it + // expects `undefined=TOKEN`. Measured and reported on #25096; nothing + // here is changed by that card. // - `sys_two_factor.secret` (`required: true`) and `.backup_codes` (empty // until generated) — TOTP and backup-code verification read both off the // enrolment row. diff --git a/packages/plugins/plugin-auth/src/invite-role-not-found-code.ts b/packages/plugins/plugin-auth/src/invite-role-not-found-code.ts index cb8a65dc5ed..71be2e6f557 100644 --- a/packages/plugins/plugin-auth/src/invite-role-not-found-code.ts +++ b/packages/plugins/plugin-auth/src/invite-role-not-found-code.ts @@ -12,8 +12,8 @@ * * new APIError("BAD_REQUEST", { message: `${ROLE_NOT_FOUND}: ${unknownRoles}` }) * - * (`dist/plugins/organization/routes/crud-invites.mjs`, measured against the - * installed better-auth `1.7.3`). Its sibling `update-member-role` + * (`dist/plugins/organization/routes/crud-invites.mjs`, measured against + * better-auth `1.7.12`, re-measured 2026-10-21 for #25096). Its sibling `update-member-role` * (`routes/crud-members.mjs`) throws the SAME refusal with * `code: ROLE_NOT_FOUND` beside the identical message — so one vendor * condition reached the wire coded on one door and uncoded on the other. The diff --git a/packages/plugins/plugin-auth/src/list-user-invitations-verification.ts b/packages/plugins/plugin-auth/src/list-user-invitations-verification.ts index a761e4ed63d..a8d7c389296 100644 --- a/packages/plugins/plugin-auth/src/list-user-invitations-verification.ts +++ b/packages/plugins/plugin-auth/src/list-user-invitations-verification.ts @@ -7,9 +7,9 @@ * * ## The defect, and where it is minted * - * Not here: it comes out of the pinned vendor. Re-measured 2026-09-11 against - * the installed better-auth `1.7.3` (unchanged from the `1.7.2` reading this - * replaces), `dist/plugins/organization/routes/crud-invites.mjs`: + * Not here: it comes out of the pinned vendor. Re-measured 2026-10-21 for + * #25096 against better-auth `1.7.12` (unchanged since the `1.7.2` reading), + * `dist/plugins/organization/routes/crud-invites.mjs`: * the three id-addressed routes ask * `shouldRequireVerifiedEmailForInvitationIdAction({ organizationOptions, … })`, * whose first line is diff --git a/packages/plugins/plugin-auth/src/organization-delete.ts b/packages/plugins/plugin-auth/src/organization-delete.ts index 8aff7beba35..5dd4c47fad9 100644 --- a/packages/plugins/plugin-auth/src/organization-delete.ts +++ b/packages/plugins/plugin-auth/src/organization-delete.ts @@ -7,7 +7,7 @@ * * ## What better-auth does, and what it leaves * - * `POST /organization/delete` (better-auth 1.7.3, + * `POST /organization/delete` (better-auth 1.7.12, re-read 2026-10-21 for #25096, * `plugins/organization/routes/crud-org.mjs`) authorizes the caller, clears the * caller's active organization, calls `organizationHooks.beforeDeleteOrganization`, * and then `adapter.deleteOrganization`, which deletes `member`, then diff --git a/packages/plugins/plugin-auth/src/session-envelope-completion.ts b/packages/plugins/plugin-auth/src/session-envelope-completion.ts index e701c4763ee..dd8651ded2e 100644 --- a/packages/plugins/plugin-auth/src/session-envelope-completion.ts +++ b/packages/plugins/plugin-auth/src/session-envelope-completion.ts @@ -18,12 +18,12 @@ * `secondaryStorage` — see `auth-manager.ts`'s `deleteUser` note), and * `internalAdapter.createSession` is `await`-ed to completion — including the * database write — before the sign-in/sign-up ENDPOINT returns - * `{ token, user }` at all (`better-auth@1.7.3` - * `dist/db/internal-adapter.mjs:247-319`). So by the time this repo's global + * `{ token, user }` at all (`better-auth@1.7.12`, re-read 2026-10-21 for #25096, + * `dist/db/internal-adapter.mjs:259-332`). So by the time this repo's global * `after` hook runs (`ctx.context.returned` already holds the endpoint's * answer), the row the token names is not merely creatABLE — it is already * committed. Reading it back is exactly what `/get-session` already does - * (`internalAdapter.findSession`, `dist/db/internal-adapter.mjs:321-358`), so + * (`internalAdapter.findSession`, `dist/db/internal-adapter.mjs:333-370`), so * this produces the SAME shape `data.session` already carries on that route * (`auth-get-session-envelope.test.ts`), not a second declaration of it. * diff --git a/packages/plugins/plugin-auth/src/two-factor-totp-issuer.test.ts b/packages/plugins/plugin-auth/src/two-factor-totp-issuer.test.ts index 0dbb461b5a7..49bfa8c2522 100644 --- a/packages/plugins/plugin-auth/src/two-factor-totp-issuer.test.ts +++ b/packages/plugins/plugin-auth/src/two-factor-totp-issuer.test.ts @@ -8,8 +8,9 @@ // `appName`, so better-auth fell back to its own name, and every user's // authenticator app listed the account under "Better Auth". // -// What better-auth 1.7.3 does with the name, read off its dist rather than its -// docs, decides what these pins have to cover: +// What better-auth 1.7.12 does with the name (re-read 2026-10-21 for #25096, +// unchanged since 1.7.3), read off its dist rather than its docs, decides +// what these pins have to cover: // - the config's `appName` is read ONCE, into the context's `appName` // (`context/create-context.mjs`, unset ⇒ "Better Auth"); // - that context value is read in exactly TWO places, both otpauth URIs: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index c7522b82a3b..d9b99fcddf1 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -187,7 +187,7 @@ patchedDependencies: # undici above). # IMPORTANT: these overrides do NOT ship with published packages — a # downstream `npx create-objectstack` install resolves plugin-auth's own -# declared ranges. plugin-auth therefore declares the same exact `1.7.2` +# declared ranges. plugin-auth therefore declares the same exact target # in its dependencies (a `^1.6.23` range there resolved to the broken # 1.6.23 mix and 500'd every fresh 15.1.0 project; a `^1.7.2` range there # resolved to 1.7.3 and made every fresh 17.1.0–17.3.0 project unloadable, @@ -238,12 +238,24 @@ overrides: # all. The selectors keep their `<2.0.0` major boundary, so lifting the # family later is still a target-only edit. # - # The target IS 1.7.3 since #17440: the platform adopted the vendor's + # The target was 1.7.3 from #17440: the platform adopted the vendor's # rollback rather than owning a fork of a model its author abandoned, so # nothing here imports the two deleted names any more and `sys_account` # no longer carries the column they served. What did NOT change is the rule - # above — the exact target stays exact for the reason 1.7.3 demonstrated, - # and 1.7.4 (published) is the next reviewed one-line lift, not a float. + # above — the exact target stays exact for the reason 1.7.3 demonstrated. + # + # The target IS 1.7.12 since #25096, a reviewed lift of the whole family at + # once, made for the security fixes published after 1.7.3 in packages + # plugin-auth mounts (GHSA-965c-763c-88jm and GHSA-r4xp-prcw-77qf in 1.7.7, + # and fixes in oauth-provider, sso, scim and core up to 1.7.12). Measured on + # the lift, not assumed: every symbol plugin-auth imports is still exported + # (`pnpm check:vendor-export-contract`), and only what the family pulls in + # moved with it: better-call 1.4.0 -> 1.4.4, @better-auth/utils 0.4.2 -> + # 0.5.0 (one copy left), @better-fetch/fetch 1.3.1 -> 1.3.2, and the copies + # 1.7.12 no longer asks for (the better-sqlite3 12 peer, + # @cloudflare/workers-types, core's @opentelemetry/semantic-conventions) + # left the lockfile. The 1.8 line is a separate decision; the next lift is + # again a reviewed edit, never a float. # # These targets are held EQUAL to the ranges `@objectstack/plugin-auth` # declares (`scripts/check-override-consistency.mjs` cross-checks that the From becfb99a890231793bb6f1a03f78b0fe981f93da Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 21 Oct 2026 10:48:33 +0000 Subject: [PATCH 5/9] chore(changeset): plugin-auth minor for the better-auth 1.7.12 lift MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Breaking narrowing: Clause-② no (narrowing), ADR-0087 disposition not-required (no-migration-prescription), with FROM / TO for each measured vendor change and the operator notes. Claude-Session: https://claude.ai/code/session_011TdZ8GjixNZFLz1xJD9zzK Co-authored-by: Claude --- .changeset/25096-better-auth-1-7-12.md | 31 ++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 .changeset/25096-better-auth-1-7-12.md diff --git a/.changeset/25096-better-auth-1-7-12.md b/.changeset/25096-better-auth-1-7-12.md new file mode 100644 index 00000000000..5986b0a1fdb --- /dev/null +++ b/.changeset/25096-better-auth-1-7-12.md @@ -0,0 +1,31 @@ +--- +'@objectstack/plugin-auth': minor +--- + +fix(plugin-auth)!: lift the better-auth family from 1.7.3 to 1.7.12 for the security fixes published since + +`@objectstack/plugin-auth` declares the better-auth family exactly, so a fresh install resolves what this package tested. All five declared ranges (`better-auth`, `@better-auth/core`, `@better-auth/oauth-provider`, `@better-auth/scim`, `@better-auth/sso`) move from `1.7.3` to `1.7.12`, still exact. The lift takes the fixes published in 1.7.4 to 1.7.12 for packages this plugin mounts: GHSA-965c-763c-88jm and GHSA-r4xp-prcw-77qf (1.7.7), and the oauth-provider, SSO, SCIM, JWT and password-reset fixes up to 1.7.12. Every symbol this package imports from the family is still exported. It also pulls in `better-call` 1.4.4, `@better-auth/utils` 0.5.0 and `@better-fetch/fetch` 1.3.2, the versions 1.7.12 declares. + +Clause-②: no (narrowing) + + + +**BREAKING** (the auth endpoints refuse some requests 1.7.3 accepted, and some refusals change status), shipped as `minor` under the launch-window convention for breaking changes. + +- **FROM:** a Magic Link, OAuth or social sign-in, SAML or account-linking flow started before the upgrade could complete after it. + **TO:** it fails, and the user starts it again. 1.7.7 stores Magic Link and OAuth-state verification rows under new identifier prefixes and keys the OAuth state cookie per purpose, so a link or a pending identity-provider round-trip minted by 1.7.3 is not found: a Magic Link answers `?error=INVALID_TOKEN`, an OAuth callback answers a state mismatch. +- **FROM:** an OIDC SSO provider whose configured issuer differed from its discovery document's `issuer`, for example only by a trailing slash, signed users in. + **TO:** the provider is refused with `issuer_mismatch`. 1.7.12 also refuses an OIDC ID token that carries no `exp` or `iat`. +- **FROM:** `POST /api/v1/auth/oauth2/token` with a PKCE `code_verifier` that does not match the challenge answered `401`. + **TO:** it answers `400` with `error: 'invalid_grant'`. +- **FROM:** `GET /api/v1/auth/get-session` answered `401 UNAUTHENTICATED` ("Sign in first") when the session store could not be read, the same answer a signed-out browser gets, and an in-process `api.getSession` resolved `null`. + **TO:** it answers `500` with `code: 'FAILED_TO_GET_SESSION'` and keeps the session cookie, and the in-process read rejects. Callers that treat a failed read as anonymous on purpose (the request-context resolution in `@objectstack/core` and `@objectstack/runtime`) still do. +- **FROM:** `POST /api/v1/auth/sign-in/email` with a password longer than the configured maximum answered as an ordinary failed sign-in. + **TO:** it answers `400` with `code: 'PASSWORD_TOO_LONG'` before any account is looked up. It still counts as a failed attempt for the account lockout. +- **FROM:** a DPoP proof sent to the token endpoint was checked against the URL of the request as it reached the server. + **TO:** it is checked against the configured public base URL plus the request path. Behind a proxy that rewrites the host, a proof bound to the public URL is now accepted and a proof bound to the internal URL is refused with `invalid_dpop_proof`. +- **FROM:** `GET /api/v1/auth/get-session` with a cookie for a session that no longer exists answered `401` and left the cookie in place. + **TO:** the same `401` also clears the stale session cookies. +- **New route:** `POST /api/v1/auth/oauth2/client/rotate-keys` (`private_key_jwt` key rotation) is now published, and refused with `403 access_denied` because this package does not enable client key rotation. +- **Unchanged:** the package's exports and configuration; sign-up, sign-in and session cookies (`HttpOnly; SameSite=Lax; Path=/`, no `Secure` on plain HTTP); the active organization stamped on a new session; implicit account linking and its unlink records; single-use reservations (a replayed DPoP proof or client assertion is still refused); and where sessions and verification values are stored with or without a host `secondaryStorage`. +- **What to do as an operator:** tell users that a Magic Link, social, SSO or account-linking sign-in begun before the upgrade must be started again after it. Check each OIDC SSO provider's configured issuer against its discovery document and set it to the exact `issuer` string the document publishes. An OAuth client that branched on `401` for a PKCE failure should branch on `400 invalid_grant`. A browser client that read every non-`200` `/get-session` answer as "signed out" should treat a `500` as "try again". From 8c4bf6489b471513e5cf17759c3257bbfbde377e Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 21 Oct 2026 11:56:33 +0000 Subject: [PATCH 6/9] docs(spec,cli): re-measure the two better-auth stamps the 1.7.12 lift falsified The organization schema's updatedAt TSDoc keeps its 1.7.3 reading and appends the 1.7.12 re-measurement (the organization plugin schema is byte-identical; transformOutput still projects declared fields only). The os migrate account-issuer description names the restored key and no version, so no later lift can falsify it. spec and cli ride the existing changeset as patch, text only. Claude-Session: https://claude.ai/code/session_011TdZ8GjixNZFLz1xJD9zzK Co-authored-by: Claude --- .changeset/25096-better-auth-1-7-12.md | 3 +++ packages/cli/src/commands/migrate/account-issuer.ts | 2 +- packages/spec/src/identity/organization.zod.ts | 4 +++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.changeset/25096-better-auth-1-7-12.md b/.changeset/25096-better-auth-1-7-12.md index 5986b0a1fdb..6aa7d288c90 100644 --- a/.changeset/25096-better-auth-1-7-12.md +++ b/.changeset/25096-better-auth-1-7-12.md @@ -1,5 +1,7 @@ --- '@objectstack/plugin-auth': minor +'@objectstack/spec': patch +'@objectstack/cli': patch --- fix(plugin-auth)!: lift the better-auth family from 1.7.3 to 1.7.12 for the security fixes published since @@ -28,4 +30,5 @@ Clause-②: no (narrowing) **TO:** the same `401` also clears the stale session cookies. - **New route:** `POST /api/v1/auth/oauth2/client/rotate-keys` (`private_key_jwt` key rotation) is now published, and refused with `403 access_denied` because this package does not enable client key rotation. - **Unchanged:** the package's exports and configuration; sign-up, sign-in and session cookies (`HttpOnly; SameSite=Lax; Path=/`, no `Secure` on plain HTTP); the active organization stamped on a new session; implicit account linking and its unlink records; single-use reservations (a replayed DPoP proof or client assertion is still refused); and where sessions and verification values are stored with or without a host `secondaryStorage`. +- **`@objectstack/spec` and `@objectstack/cli` (patch, text only, not breaking):** the TSDoc on the organization schema's optional `updatedAt` now records that its better-auth measurement still holds on 1.7.12, and the `os migrate account-issuer` description no longer names a better-auth version. No schema, type, flag or behaviour changes in either package. - **What to do as an operator:** tell users that a Magic Link, social, SSO or account-linking sign-in begun before the upgrade must be started again after it. Check each OIDC SSO provider's configured issuer against its discovery document and set it to the exact `issuer` string the document publishes. An OAuth client that branched on `401` for a PKCE failure should branch on `400 invalid_grant`. A browser client that read every non-`200` `/get-session` answer as "signed out" should treat a `500` as "try again". diff --git a/packages/cli/src/commands/migrate/account-issuer.ts b/packages/cli/src/commands/migrate/account-issuer.ts index 261c386e66d..7153993f79a 100644 --- a/packages/cli/src/commands/migrate/account-issuer.ts +++ b/packages/cli/src/commands/migrate/account-issuer.ts @@ -68,7 +68,7 @@ export default class MigrateAccountIssuer extends Command { static override description = 'Pre-flight the retirement of sys_account.issuer: report every (provider_id, account_id) ' + 'key held by more than one row — the class that is legal under the retired (issuer, account_id) key ' + - 'and is ONE account under the key better-auth 1.7.3 restored. Read-only; exits non-zero when the ' + + 'and is ONE account under the (provider_id, account_id) key better-auth restored. Read-only; exits non-zero when the ' + 'drop must not proceed.'; static override examples = [ diff --git a/packages/spec/src/identity/organization.zod.ts b/packages/spec/src/identity/organization.zod.ts index da528144b87..8e602b1d261 100644 --- a/packages/spec/src/identity/organization.zod.ts +++ b/packages/spec/src/identity/organization.zod.ts @@ -92,7 +92,9 @@ export const OrganizationSchema = lazySchema(() => z.object({ * produced by better-auth's own serializer and its documented shape carries * no `updatedAt`, then for those routes the spec aligns to the documented * wire (`updatedAt` optional there)」. Both halves measured against the - * installed better-auth 1.7.3, so fallback A applies: + * installed better-auth 1.7.3 (re-measured on 1.7.12 for #25096: the + * organization plugin schema is byte-identical and `transformOutput` still + * projects declared fields only), so fallback A applies: * * - **The serializer is the vendor's.** The `organization/*` routes are * better-auth's own endpoints, mounted through plugin-auth's single From c4281378084fc183669ab6fef0aa82200e382f17 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 21 Oct 2026 13:10:59 +0000 Subject: [PATCH 7/9] test(service-datasource): model better-sqlite3 13's own never-built error, not a phantom bindings The never-built fixture required the bindings package relative to better-sqlite3 13, which does not depend on it; it resolved only through pnpm's hidden hoist of the copy better-sqlite3 12 brought in as better-auth 1.7.3's optional peer, and the 1.7.12 lift removed that copy. better-sqlite3 13 loads its addon with a plain require of build/Release/better_sqlite3.node, so the fixture now makes that require from the installed package against a module root that was never built, and the case asserts MODULE_NOT_FOUND. The two docblock sentences that named bindings' message now describe the 13.x error. No code moves. Claude-Session: https://claude.ai/code/session_011TdZ8GjixNZFLz1xJD9zzK Co-authored-by: Claude --- ...-driver-fallback-file-open-failure.test.ts | 24 +++++++++++-------- .../src/sqlite-driver-fallback.ts | 12 ++++++---- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/packages/services/service-datasource/src/__tests__/sqlite-driver-fallback-file-open-failure.test.ts b/packages/services/service-datasource/src/__tests__/sqlite-driver-fallback-file-open-failure.test.ts index 84ce07ca50c..44afd66b44c 100644 --- a/packages/services/service-datasource/src/__tests__/sqlite-driver-fallback-file-open-failure.test.ts +++ b/packages/services/service-datasource/src/__tests__/sqlite-driver-fallback-file-open-failure.test.ts @@ -18,14 +18,15 @@ * It is faked at the seam where `better-sqlite3` loads its addon: the knex * better-sqlite3 client's `acquireRawConnection` (`new Database(file)`). * The fake throws a REAL load error: Node's own `ERR_DLOPEN_FAILED`, or the - * `bindings` package's own "not built" error. + * `MODULE_NOT_FOUND` better-sqlite3's own loader meets when its addon was + * never built. */ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'; import { createRequire } from 'node:module'; import { tmpdir } from 'node:os'; -import { dirname, join } from 'node:path'; +import { join } from 'node:path'; import { SqlDriver } from '@objectstack/driver-sql'; import { NATIVE_SQLITE_WASM_FALLBACK_WARNING, @@ -87,21 +88,24 @@ function realDlopenFailure(): Error { } /** - * The real error `better-sqlite3` throws when its addon was never built: the - * `bindings` package it loads the addon through, asked for an addon that is - * not there. It carries no code. + * The real error `better-sqlite3` throws when its addon was never built. Its + * 13.x loader (`lib/binding.js`) takes no helper package: with no prebuilt + * binary for the platform it `require()`s `build/Release/better_sqlite3.node` + * under its own module root, and Node answers `MODULE_NOT_FOUND`. Produced + * here by that same require, made from the installed package, against a + * module root that was never built. */ function realNotBuiltFailure(): Error { const fromHere = createRequire(import.meta.url); const fromDriver = createRequire(fromHere.resolve('@objectstack/driver-sql')); const betterSqlite3 = fromDriver.resolve('better-sqlite3/package.json'); - const bindings = createRequire(betterSqlite3)('bindings'); + const neverBuilt = join(dir, 'never-built', 'build', 'Release', 'better_sqlite3.node'); try { - bindings({ bindings: 'os_24950_never_built.node', module_root: dirname(betterSqlite3) }); + createRequire(betterSqlite3)(neverBuilt); } catch (error) { return error as Error; } - throw new Error('bindings located an addon that was never built'); + throw new Error('required an addon that was never built'); } /** @@ -170,9 +174,9 @@ describe('resolveSqliteDriver in development: a native addon that cannot load st expect(await resolved.driver.execute('SELECT 1 AS one')).toEqual([{ one: 1 }]); }); - it('an addon that was never built (no code) steps down to wasm SQLite', async () => { + it('an addon that was never built (MODULE_NOT_FOUND) steps down to wasm SQLite', async () => { const loadError = realNotBuiltFailure(); - expect((loadError as any).code).toBeUndefined(); + expect((loadError as any).code).toBe('MODULE_NOT_FOUND'); await failNativeAddonLoad(loadError); const resolved = await resolveDev(join(dir, 'dev.db')); diff --git a/packages/services/service-datasource/src/sqlite-driver-fallback.ts b/packages/services/service-datasource/src/sqlite-driver-fallback.ts index 6e42085d451..cd3fd64524f 100644 --- a/packages/services/service-datasource/src/sqlite-driver-fallback.ts +++ b/packages/services/service-datasource/src/sqlite-driver-fallback.ts @@ -39,9 +39,10 @@ * * - **The addon cannot load — steps down.** An ABI mismatch (Node's * `ERR_DLOPEN_FAILED`, a `NODE_MODULE_VERSION` message), an addon that was - * never built (`bindings`' "Could not locate the bindings file", which has - * no code), or a missing `better-sqlite3` package. Today's path, - * unchanged. + * never built (better-sqlite3 13's loader `require()`s the absent + * `build/Release/better_sqlite3.node`, and Node answers + * `MODULE_NOT_FOUND`), or a missing `better-sqlite3` package. Today's + * path, unchanged. * - **The database FILE cannot be opened or created, or is not a database — * re-thrown, as in production.** A path under a regular file, a parent * directory the driver cannot make, a permission refusal, a directory where @@ -164,8 +165,9 @@ function isEphemeralFilename(filename: string): boolean { * An addon that cannot load never carries any of these. It surfaces at the * probe's `SELECT 1`, whose failure `SqlDriver.execute()` hands back as * `DATABASE_ERROR`, with the load error as its `cause`: Node's - * `ERR_DLOPEN_FAILED`, `MODULE_NOT_FOUND`, or no code at all (`bindings`' - * "Could not locate the bindings file"). A missing `better-sqlite3` package + * `ERR_DLOPEN_FAILED`, or `MODULE_NOT_FOUND` (an addon that was never built: + * better-sqlite3 13's loader `require()`s the absent + * `build/Release/better_sqlite3.node`). A missing `better-sqlite3` package * fails at construction with knex's install hint, which has no code. None of * these matches. * From 1a28ccb4384cb103a9dbe0b585a241e1e2f6929e Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 21 Oct 2026 13:14:30 +0000 Subject: [PATCH 8/9] chore(changeset): name service-datasource as a text-only patch Its resolveSqliteDriver docblock ships in dist/index.d.ts, so the corrected never-built sentence publishes. Claude-Session: https://claude.ai/code/session_011TdZ8GjixNZFLz1xJD9zzK Co-authored-by: Claude --- .changeset/25096-better-auth-1-7-12.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.changeset/25096-better-auth-1-7-12.md b/.changeset/25096-better-auth-1-7-12.md index 6aa7d288c90..52c29f52e04 100644 --- a/.changeset/25096-better-auth-1-7-12.md +++ b/.changeset/25096-better-auth-1-7-12.md @@ -2,6 +2,7 @@ '@objectstack/plugin-auth': minor '@objectstack/spec': patch '@objectstack/cli': patch +'@objectstack/service-datasource': patch --- fix(plugin-auth)!: lift the better-auth family from 1.7.3 to 1.7.12 for the security fixes published since @@ -31,4 +32,5 @@ Clause-②: no (narrowing) - **New route:** `POST /api/v1/auth/oauth2/client/rotate-keys` (`private_key_jwt` key rotation) is now published, and refused with `403 access_denied` because this package does not enable client key rotation. - **Unchanged:** the package's exports and configuration; sign-up, sign-in and session cookies (`HttpOnly; SameSite=Lax; Path=/`, no `Secure` on plain HTTP); the active organization stamped on a new session; implicit account linking and its unlink records; single-use reservations (a replayed DPoP proof or client assertion is still refused); and where sessions and verification values are stored with or without a host `secondaryStorage`. - **`@objectstack/spec` and `@objectstack/cli` (patch, text only, not breaking):** the TSDoc on the organization schema's optional `updatedAt` now records that its better-auth measurement still holds on 1.7.12, and the `os migrate account-issuer` description no longer names a better-auth version. No schema, type, flag or behaviour changes in either package. +- **`@objectstack/service-datasource` (patch, text only, not breaking):** the `resolveSqliteDriver` docs now describe the error better-sqlite3 13 actually throws for an addon that was never built: its loader's `require()` of the absent `build/Release/better_sqlite3.node`, which Node answers with `MODULE_NOT_FOUND`. The docs used to name a helper package's message that 13.x no longer produces. Development still steps down to wasm SQLite on that error, as before. No code changes. - **What to do as an operator:** tell users that a Magic Link, social, SSO or account-linking sign-in begun before the upgrade must be started again after it. Check each OIDC SSO provider's configured issuer against its discovery document and set it to the exact `issuer` string the document publishes. An OAuth client that branched on `401` for a PKCE failure should branch on `400 invalid_grant`. A browser client that read every non-`200` `/get-session` answer as "signed out" should treat a `500` as "try again". From ea86e485634d247bbd29f39c0984ba11a0abfa66 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 21 Oct 2026 14:03:24 +0000 Subject: [PATCH 9/9] chore(changeset): plugin-auth ships patch under ruling A, Metadata-protocol none The lift changes nothing a metadata author can write. Under the maintainer's ruling A a non-protocol breaking change ships patch and keeps its BREAKING banner and ADR-0087 disposition, so plugin-auth moves from minor to patch and the changeset declares Metadata-protocol: none. Claude-Session: https://claude.ai/code/session_011TdZ8GjixNZFLz1xJD9zzK Co-authored-by: Claude --- .changeset/25096-better-auth-1-7-12.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.changeset/25096-better-auth-1-7-12.md b/.changeset/25096-better-auth-1-7-12.md index 52c29f52e04..2e716be2a18 100644 --- a/.changeset/25096-better-auth-1-7-12.md +++ b/.changeset/25096-better-auth-1-7-12.md @@ -1,5 +1,5 @@ --- -'@objectstack/plugin-auth': minor +'@objectstack/plugin-auth': patch '@objectstack/spec': patch '@objectstack/cli': patch '@objectstack/service-datasource': patch @@ -10,10 +10,11 @@ fix(plugin-auth)!: lift the better-auth family from 1.7.3 to 1.7.12 for the secu `@objectstack/plugin-auth` declares the better-auth family exactly, so a fresh install resolves what this package tested. All five declared ranges (`better-auth`, `@better-auth/core`, `@better-auth/oauth-provider`, `@better-auth/scim`, `@better-auth/sso`) move from `1.7.3` to `1.7.12`, still exact. The lift takes the fixes published in 1.7.4 to 1.7.12 for packages this plugin mounts: GHSA-965c-763c-88jm and GHSA-r4xp-prcw-77qf (1.7.7), and the oauth-provider, SSO, SCIM, JWT and password-reset fixes up to 1.7.12. Every symbol this package imports from the family is still exported. It also pulls in `better-call` 1.4.4, `@better-auth/utils` 0.5.0 and `@better-fetch/fetch` 1.3.2, the versions 1.7.12 declares. Clause-②: no (narrowing) +Metadata-protocol: none -**BREAKING** (the auth endpoints refuse some requests 1.7.3 accepted, and some refusals change status), shipped as `minor` under the launch-window convention for breaking changes. +**BREAKING** (the auth endpoints refuse some requests 1.7.3 accepted, and some refusals change status), shipped as `patch` under ruling A: it changes nothing a metadata author can write, and a non-protocol breaking change ships `patch` while keeping this BREAKING banner and its ADR-0087 disposition. - **FROM:** a Magic Link, OAuth or social sign-in, SAML or account-linking flow started before the upgrade could complete after it. **TO:** it fails, and the user starts it again. 1.7.7 stores Magic Link and OAuth-state verification rows under new identifier prefixes and keys the OAuth state cookie per purpose, so a link or a pending identity-provider round-trip minted by 1.7.3 is not found: a Magic Link answers `?error=INVALID_TOKEN`, an OAuth callback answers a state mismatch.