fix(plugin-auth): pin better-auth family to 1.7.0-rc.1 — fresh 15.1.0 projects 500 on every auth endpoint#3085
Merged
Merged
Conversation
…ed manifest Every fresh `npx create-objectstack` (15.1.0) project shipped with auth returning 500 on sign-up / sign-in / get-session: "Cannot set properties of undefined (setting 'modelName')", thrown from @better-auth/oauth-provider@1.6.23 during better-auth init. The workspace forces the whole better-auth family to 1.7.0-rc.1 via pnpm-workspace.yaml overrides (GHSA-j8v8-g9cx-5qf4 is only fixed in the 1.7.0 pre-release line, see 602053c), so every CI job and showcase here ran a graph downstream installs can never reproduce: overrides do not ship with published packages, and plugin-auth still declared ^1.6.23 for better-auth / @better-auth/core / @better-auth/oauth-provider / @better-auth/sso. Downstream resolved those to 1.6.23 (still the npm `latest`), and the 1.7 scim + 1.6.23 rest mix crashes at startup. - Pin all four to the exact 1.7.0-rc.1 (same as @better-auth/scim) — the only combination this repo actually builds and tests. No `^` on the rc: npm's default resolution never selects a prerelease from a caret range, which is precisely how this drift shipped. Relax to ^1.7.0 once a stable better-auth 1.7.0 exists. - Workspace lockfile is unchanged by the pin (pnpm already resolved these to 1.7.0-rc.1 via the overrides); the overrides stay as belt-and-braces. - Add scripts/check-override-consistency.mjs + a validate-deps step: for every pnpm-workspace override whose package appears in a publishable package's dependencies/optionalDependencies/peerDependencies, the declared range must resolve to the override target under npm's default (no-prerelease) semantics, so tested-vs-published drift fails CI with a "overrides do not ship with published packages" hint instead of shipping silently. Needs semver, added as a root devDependency. Verified against the packed artifact: `pnpm pack` of this plugin-auth, installed into a fresh create-objectstack@15.1.0 project via a pnpm override — lockfile resolves the whole family (adapters + telemetry included) to 1.7.0-rc.1, startup log has zero "Failed to register OIDC discovery routes", and sign-up / sign-in / get-session all return 200. A control project without the override reproduces the three 500s. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
📓 Docs Drift CheckThis PR changes 1 package(s): 9 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
os-zhuang
added a commit
that referenced
this pull request
Jul 17, 2026
…rom core auth (#3087) Follow-up to #3085. In the 15.1.0 incident, @better-auth/oauth-provider threw "Cannot set properties of undefined (setting 'modelName')" during plugin construction, and because the better-auth instance is built lazily per request, that single optional federation feature turned EVERY auth endpoint (sign-up / sign-in / get-session) into a 500 — a blast radius wildly out of proportion to the feature. AuthManager.buildPluginList now constructs plugins in two explicit tiers: - OPTIONAL (organization, admin, phoneNumber, magicLink, genericOAuth, jwt+oauthProvider as one atomic unit, sso, scim, deviceAuthorization): built through addOptionalPlugin(), which on failure skips the feature with one loud actionable console.error, records it in getDegradedAuthFeatures(), and leaves core email/password + session auth up. The feature's endpoints 404 until the operator fixes the underlying error and restarts. - CORE (bearer, twoFactor, haveIBeenPwned, customSession): still fail hard. Skipping these would silently weaken auth — 2FA-enrolled accounts signing in on password alone, opted-in breached-password rejection vanishing, the ADR-0069 authGate (password expiry, enforced MFA) and positions[] disappearing from sessions. Better a hard 500 than fail-open security. The OIDC discovery mount in auth-plugin.ts consults the degraded set and skips advertising /.well-known documents for an IdP whose endpoints did not come up (previously the "Failed to register OIDC discovery routes" path), logging why instead of sending external clients into 404s. Regression tests run the REAL better-auth pipeline (no betterAuth mock, a minimal in-memory IDataEngine behind the genuine ObjectQL adapter) with the exact incident TypeError injected into oauthProvider: sign-up and get-session return 200, the degraded feature is reported, the console.error fires; a throwing CORE plugin (bearer) still rejects; the degraded set resets on a healthy rebuild. Full plugin-auth suite: 457 tests pass. Co-authored-by: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
os-zhuang
added a commit
that referenced
this pull request
Jul 17, 2026
…r would (#3100) The 15.1.0 incident (#3091): workspace pnpm overrides kept every in-repo CI job on better-auth 1.7.0-rc.1, but overrides do not ship with published packages, so every fresh `npx create-objectstack` project resolved an untested dependency mix that 500'd all auth endpoints. #3085 added the static gate (override ↔ declaration consistency); this adds the dynamic gate — install the exact bits a user would get and drive the first-run flow. scripts/publish-smoke.sh, two modes sharing one probe set: - pack (default): pnpm-pack all 67 publishable packages (pack applies the same manifest rewrites as publish), scaffold a fresh project outside the workspace with the repo-built create-objectstack, pin @objectstack/* to the tarballs via the project's OWN pnpm-workspace.yaml overrides (nothing inherited from the repo), install, and smoke. A lockfile assertion proves no @objectstack/* leaked to the registry. - registry: npx create-objectstack@latest + npm install against the real registry — catches ^-range ecosystem drift breaking published versions. Probes: anonymous get-session 200 → sign-up 200 → sign-in 200 → session carries the user → REST CRUD round (201/200/200/200) on the scaffolded object as the seeded dev admin → zero error/fatal log lines (ANSI-stripped; catches the #3091 'Failed to register OIDC discovery routes' signature). .github/workflows/publish-smoke.yml: - workflow_run after each Release run — the changesets release PR is pushed with GITHUB_TOKEN, whose events never trigger on:push/pull_request (the release PR has no Actions checks today), so the smoke runs after Release completes, checks out the release-branch head SHA iff an open release PR exists, and reports the verdict back as a commit status on that SHA so it is visible on the release PR. Deliberately not in normal PR CI (too slow). - weekly registry canary (Mon 04:47 UTC) that opens/refreshes an issue on failure. Verified locally: pack mode green on the current tree; a negative run with plugin-auth's declarations reverted to the 15.1.0 mix (^1.6.23 + scim rc.1) goes red via the log scan — core sign-in stays up thanks to the #3087 isolation, and the smoke still catches the broken optional-plugin init. Registry mode green against published 15.1.1. better-sqlite3 stays an optionalDependency, so a failed native build falls back to WASM sqlite (#2229) instead of blocking the smoke. Co-authored-by: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
P0:
npx create-objectstack(15.1.0) ships with broken authEvery fresh project returns 500 on sign-up / sign-in / get-session with
Cannot set properties of undefined (setting 'modelName'), thrown from@better-auth/oauth-provider@1.6.23during better-auth initialization (Failed to register OIDC discovery routesat startup).Root cause: overrides don't ship with published packages
602053c pinned the better-auth family to 1.7.0-rc.1 via
pnpm-workspace.yamloverrides, because GHSA-j8v8-g9cx-5qf4 (high, account/provider takeover in@better-auth/scim) is fixed only in the 1.7.0 pre-release line — npmlatestis still 1.6.23 and no stable 1.7.0 exists, so waiting for stable is not an option.That makes the whole framework CI/showcase surface green against 1.7.0-rc.1 — but pnpm overrides apply only inside this workspace. The published
@objectstack/plugin-authstill declared^1.6.23forbetter-auth/@better-auth/core/@better-auth/oauth-provider/@better-auth/sso(only@better-auth/scimwas pinned). npm's default resolution never selects a prerelease from a caret range, so downstream installs get scim@1.7.0-rc.1 + everything else @1.6.23 — a combination never tested here, and one that crashes at init: the 1.7 code paths import symbols that only exist in@better-auth/core1.7.x, so the family must move together.Fix
1.7.0-rc.1(matching@better-auth/scim) inpackages/plugins/plugin-auth/package.json. No^on the rc — a caret range on a prerelease is exactly how this drift shipped. Relax to^1.7.0the moment a stable better-auth 1.7.0 ships (tracked in the pnpm-workspace.yaml comment block).@objectstack/plugin-auth(fixed group).Prevention: override-consistency CI gate
New
scripts/check-override-consistency.mjs, wired into the validate-deps workflow: for everypnpm-workspace.yamloverride whose package name appears in a publishable package'sdependencies/optionalDependencies/peerDependencies, the declared range must resolve to the override target under npm's default (no-prerelease) semantics — i.e. what a downstream install actually gets. Violations fail CI with:Declarations the override can never rewrite (range doesn't intersect the override's
pkg@selectorscope, e.g.create-objectstack'star ^7.5.20vstar@>=2.0.0 <7.5.11) are skipped — workspace and downstream already agree there. Negative-tested: reverting one pin to^1.6.23fails the check; current tree passes. Needssemver(root devDependency; the step runs afterpnpm install).Verification (packed artifact, not workspace)
Two fresh
create-objectstack@15.1.0projects, side by side; the fixed one resolves@objectstack/plugin-authto thepnpm packtarball of this branch:Failed to register OIDC discovery routes(modelName TypeError)/api/v1/auth/sign-up/email/api/v1/auth/sign-in/email/api/v1/auth/get-sessionRefs: GHSA-j8v8-g9cx-5qf4 · 602053c · aead168 (validate-deps pipeline)
🤖 Generated with Claude Code