Skip to content

fix(auth): upgrade better-auth to 1.7.1, verify account.issuer derives automatically - #1015

Merged
borisno2 merged 4 commits into
mainfrom
claude/focused-rubin-pi2ve0
Aug 22, 2026
Merged

fix(auth): upgrade better-auth to 1.7.1, verify account.issuer derives automatically#1015
borisno2 merged 4 commits into
mainfrom
claude/focused-rubin-pi2ve0

Conversation

@borisno2

Copy link
Copy Markdown
Member

Summary

Collateral of the version bump (needed to make 1.7.1 actually build/test)

better-auth 1.7 split the mcp plugin out of better-auth/plugins into a separate @better-auth/mcp package, rebuilt on the OAuth Provider RFC 8707/9728 resource model:

  • @opensaas/stack-auth/plugins now re-exports mcp from @better-auth/mcp (added as an optional peer dependency — only needed by apps using MCP).
  • mcp() now requires a resource option (the canonical protected-resource URL). Updated the MCP how-to guide, the auth reference doc, root CLAUDE.md, and examples/mcp-demo's config to pass it.
  • The plugin's own OAuth table set expanded/renamed (oauthApplication/oauthAccessToken/oauthConsentoauthClient/oauthAccessToken/oauthConsent/oauthRefreshToken/oauthResource/oauthClientResource/oauthClientAssertion). Since the derivation is schema-driven this needed no production code changes beyond the above, but the MCP-plugin-specific tests (plugin-table-derivation.test.ts, generated-fk-shape.test.ts, auth-lists-drift.test.ts) were updated to match the new table/field shapes.
  • Fixed a small, genuinely-unrelated gap surfaced by the new schema (which now includes number-typed fields with static defaults): deriveAuthLists's scalar-field builder wasn't threading defaultValue through for number fields (integer()/bigInt()), unlike string/boolean. One-line fix, matching existing behavior.

Examples

Test plan

  • pnpm test in packages/auth — 16 files, 271 passed, 3 skipped
  • pnpm test in packages/core and packages/cli — unaffected, all green
  • pnpm build (full monorepo) — clean
  • pnpm lint — no new warnings/errors
  • pnpm manypkg fix / pnpm format — applied
  • Verified generated schema directly: account.issuer String (required, non-nullable), positioned after providerId; composite unique intentionally not emitted (confirmed and asserted in the new test)
  • Regenerated examples/starter-auth and examples/auth-demo schemas end-to-end; examples/mcp-demo generate succeeds with the new mcp({ resource }) config
  • Changeset added (@opensaas/stack-auth: minor)

Closes #986


Generated by Claude Code

…s automatically

Bumps the better-auth dev dependency to 1.7.1 and moves the stale ^1.3.29
peer floor to ^1.4.0 (the release line where the index:true flags #937
depends on first shipped).

Since deriveAuthLists reads better-auth's own getAuthTables() (#987/#997),
the new required account.issuer column reaches the generated schema
automatically — verified with a new regression test rather than assuming
it. The table-level @@unique([issuer, accountId]) constraint better-auth
1.7 also declares is not emitted yet: that needs table-level db.indexes
derivation (#985), which hasn't landed, so per #986's own triage note this
stops short of duplicating that work.

Collateral of the bump: better-auth 1.7 split the MCP plugin into a
separate @better-auth/mcp package (added as an optional peer) with a new
required `resource` option and a substantially redesigned OAuth table set,
which needed the mcp-plugin tests and example config updated to match. Also
fixes a pre-existing gap where deriveAuthLists didn't thread a static
defaultValue through for number-typed fields, surfaced by the MCP plugin's
expanded schema.

Closes #986

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QtaxBvCjLsZcm7YiSmpteJ
@changeset-bot

changeset-bot Bot commented Aug 22, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: a5234d9

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 9 packages
Name Type
@opensaas/stack-auth Minor
@opensaas/stack-cli Minor
@opensaas/stack-core Minor
@opensaas/stack-rag Minor
@opensaas/stack-storage-s3 Minor
@opensaas/stack-storage-vercel Minor
@opensaas/stack-storage Minor
@opensaas/stack-tiptap Minor
@opensaas/stack-ui Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Aug 22, 2026

Copy link
Copy Markdown

Deployment failed for project stack-docs with the following error:

Resource is limited - try again in 24 hours (more than 100, code: "api-deployments-free-per-day").

Learn More: https://vercel.com/open-saas?upgradeToPro=build-rate-limit

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 12a6c74dcc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .changeset/eleven-mice-jog.md
Comment thread .changeset/eleven-mice-jog.md
Comment thread docs/content/reference/auth.md Outdated
…longside mcp()

CI caught two real bugs in the earlier commit that only surface with a live
better-auth 1.7 instance:

1. deriveAuthLists silently dropped createdAt/updatedAt for any plugin table
   that doesn't declare both symmetrically (several of the MCP plugin's new
   OAuth tables declare only createdAt). The column vanished entirely rather
   than falling back to an ordinary field, so the first real write supplying
   it crashed with a Prisma "Unknown argument" error — which is exactly what
   happened when better-auth's own OAuth Provider seeds an oauthResource row
   during betterAuth() init. Fixed by only relying on the list-level
   db.timestamps auto-columns when a model declares both fields; otherwise
   the field derives normally like any other column.

2. better-auth 1.7's mcp() is built on the OAuth Provider, which issues
   JWT-based access tokens and now hard-requires better-auth's own jwt()
   plugin registered alongside it (throws BetterAuthError: jwt_config
   otherwise). Added it to the e2e test fixture, examples/mcp-demo, and the
   three places docs showed betterAuthPlugins: [mcp(...)].

Also rewrote the e2e test's OAuth row assertions for the new table/field
shapes (oauthApplication -> oauthClient, no more combined access+refresh
token row) and made its baseURL explicit, which the OAuth Provider now
needs to resolve at init and which this test's in-process createAuth()
doesn't get from the CLI subprocess's BETTER_AUTH_URL.

Verified locally: full auth unit suite plus both e2e suites
(RUN_MCP_OAUTH_CASCADE_E2E=1, RUN_RATE_LIMIT_E2E=1) green, full monorepo
build/lint/format clean.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QtaxBvCjLsZcm7YiSmpteJ
@vercel

vercel Bot commented Aug 22, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
stack-docs Ready Ready Preview Aug 22, 2026 8:07am

claude added 2 commits August 22, 2026 08:08
Addresses automated review feedback on PR #1015:
- docs/content/reference/auth.md's MCP snippets used an undocumented
  APP_URL env var (would resolve to undefined/api/mcp); switched to
  NEXT_PUBLIC_APP_URL with the localhost fallback, matching this file's
  own existing baseURL convention.
- The changeset's account.issuer backfill SQL used || for concatenation,
  which is logical OR on MySQL by default and would silently write 0/1
  instead of the intended string. Added a MySQL-safe CONCAT variant
  alongside the PostgreSQL/SQLite one, and a note to substitute the
  project's actual (possibly renamed/schema-qualified) account table name.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QtaxBvCjLsZcm7YiSmpteJ
…-auth/core, missing consentPage

The full turbo test run (which builds every example, unlike the fast local
`pnpm build`/`pnpm test` I'd been checking) surfaced three more real
problems in examples/mcp-demo, all collateral of the better-auth 1.7 MCP
redesign:

1. mcp-demo's opensaas.config.ts imports `jwt` from 'better-auth/plugins'
   directly, but the package never declared `better-auth` as its own
   dependency (relying on incidental hoisting, which Next.js/Turbopack's
   strict per-package module resolution doesn't honor). Added it.

2. better-auth 1.7.1's own published packages disagree on their
   `@better-auth/utils` dependency (better-auth pins exactly 0.4.2,
   better-call - shared by @better-auth/core/oauth-provider/mcp - wants
   ^0.5.0), so pnpm resolved two physical @better-auth/core instances.
   jwt() and mcp() ended up typed against different instances, so
   betterAuthPlugins: [jwt(), mcp(...)] failed to type-check with a
   structural BetterAuthPlugin mismatch even though both were configured
   correctly. Added a root pnpm.overrides pin forcing one instance.

3. better-auth 1.7's mcp() also requires a `consentPage` option (the page
   where a user approves/denies an MCP client's requested scopes),
   alongside the resource option already added. Missing it is a type
   error, not a runtime throw like the missing jwt()/resource cases, so it
   only surfaced once (1) and (2) were fixed and the build actually
   reached type-checking. Added it everywhere resource was added.

Verified with the actual commands CI runs rather than the narrower ones
I'd been using locally: `pnpm turbo run build` and `pnpm turbo run test`
across all 24 workspace packages/examples, both green (32/32 tasks).
Also re-ran the full auth unit suite and both e2e suites.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QtaxBvCjLsZcm7YiSmpteJ
@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report for Core Package Coverage (./packages/core)

Status Category Percentage Covered / Total
🟢 Lines 94.04% (🎯 65%) 1626 / 1729
🟢 Statements 92.29% (🎯 65%) 1762 / 1909
🟢 Functions 97.38% (🎯 62%) 261 / 268
🟢 Branches 86.05% (🎯 50%) 1277 / 1484
File CoverageNo changed files found.
Generated in workflow #1781 for commit a5234d9 by the Vitest Coverage Report Action

@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report for UI Package Coverage (./packages/ui)

Status Category Percentage Covered / Total
🔵 Lines 76.72% 244 / 318
🔵 Statements 76.29% 251 / 329
🔵 Functions 69.15% 74 / 107
🔵 Branches 64.25% 160 / 249
File CoverageNo changed files found.
Generated in workflow #1781 for commit a5234d9 by the Vitest Coverage Report Action

@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report for CLI Package Coverage (./packages/cli)

Status Category Percentage Covered / Total
🔵 Lines 78.98% 1545 / 1956
🔵 Statements 78.79% 1613 / 2047
🔵 Functions 86.11% 217 / 252
🔵 Branches 69.5% 752 / 1082
File CoverageNo changed files found.
Generated in workflow #1781 for commit a5234d9 by the Vitest Coverage Report Action

@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report for Auth Package Coverage (./packages/auth)

Status Category Percentage Covered / Total
🔵 Lines 99.38% 162 / 163
🔵 Statements 97.72% 172 / 176
🔵 Functions 100% 41 / 41
🔵 Branches 89.71% 157 / 175
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
packages/auth/src/config/derive-auth-lists.ts 96.52% 87.14% 100% 99.04% 132, 133, 296-298, 593
packages/auth/src/config/types.ts 0% 0% 0% 0%
Generated in workflow #1781 for commit a5234d9 by the Vitest Coverage Report Action

@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report for Storage Package Coverage (./packages/storage)

Status Category Percentage Covered / Total
🔵 Lines 78.57% 220 / 280
🔵 Statements 80.06% 245 / 306
🔵 Functions 86.07% 68 / 79
🔵 Branches 75.88% 214 / 282
File CoverageNo changed files found.
Generated in workflow #1781 for commit a5234d9 by the Vitest Coverage Report Action

@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report for RAG Package Coverage (./packages/rag)

Status Category Percentage Covered / Total
🔵 Lines 47.97% 355 / 740
🔵 Statements 48.14% 377 / 783
🔵 Functions 54.26% 70 / 129
🔵 Branches 42.55% 180 / 423
File CoverageNo changed files found.
Generated in workflow #1781 for commit a5234d9 by the Vitest Coverage Report Action

@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report for Storage S3 Package Coverage (./packages/storage-s3)

Status Category Percentage Covered / Total
🔵 Lines 100% 40 / 40
🔵 Statements 100% 40 / 40
🔵 Functions 100% 9 / 9
🔵 Branches 100% 19 / 19
File CoverageNo changed files found.
Generated in workflow #1781 for commit a5234d9 by the Vitest Coverage Report Action

@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report for Storage Vercel Package Coverage (./packages/storage-vercel)

Status Category Percentage Covered / Total
🔵 Lines 100% 68 / 68
🔵 Statements 100% 71 / 71
🔵 Functions 100% 15 / 15
🔵 Branches 97.87% 46 / 47
File CoverageNo changed files found.
Generated in workflow #1781 for commit a5234d9 by the Vitest Coverage Report Action

@borisno2
borisno2 merged commit 72c4ba3 into main Aug 22, 2026
4 checks passed
@borisno2
borisno2 deleted the claude/focused-rubin-pi2ve0 branch August 22, 2026 09:21
@github-actions github-actions Bot mentioned this pull request Aug 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

auth: upgrade better-auth to 1.7.1 — new required account.issuer column, new @@unique([issuer, accountId]), and a stale ^1.3.29 peer floor

2 participants