Skip to content

fix(plugin-auth,platform-objects): close @better-auth/oauth-provider 1.7 schema drift — restore platform SSO - #3080

Merged
os-zhuang merged 2 commits into
mainfrom
fix/oauth-provider-17-schema-drift
Jul 16, 2026
Merged

fix(plugin-auth,platform-objects): close @better-auth/oauth-provider 1.7 schema drift — restore platform SSO#3080
os-zhuang merged 2 commits into
mainfrom
fix/oauth-provider-17-schema-drift

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

问题

better-auth 1.7.0-rc.1 升级(4ab16f8 “pnpm upgrade”)改变了 @better-auth/oauth-provider 的模型 schema,但 sys_oauth_* 平台对象和 auth-schema-config.ts 里的 camelCase→snake_case 映射没有跟上。实测(cloud 本地 rig,三仓 main)平台 SSO token 交换 500:

table sys_oauth_access_token has no column named authorizationCodeId

新字段没有 fieldName 映射时 camelCase 直通(其它列都是 snake_case),列也不存在 —— SQLite 与 prod PG 同炸。这是「Continue with ObjectStack」全环境登录链路的断点之一(另两个在 cloud / objectui,见下)。

修复

补列(1.7 完整对齐):

  • sys_oauth_access_token / sys_oauth_refresh_token:authorization_code_id(带索引)、resourcesrequested_user_info_claimsconfirmation;access 另加 revoked;refresh 另加 rotated_atrotation_replay_responserotation_replay_expires_at
  • sys_oauth_consent:resourcesrequested_user_info_claims
  • sys_oauth_application:jwksjwks_uribackchannel_logout_uribackchannel_logout_session_requireddpop_bound_access_tokens(1.7 的 DCR 会写带默认值的 dpopBoundAccessTokens,同类炸点)

新表(1.7 新增的三个模型):

  • sys_oauth_resource / sys_oauth_client_resource — RFC 8707 resource indicators(MCP OAuth track 的 audience 绑定用)
  • sys_oauth_client_assertion — RFC 7523 client-assertion jti 防重放

已注册进 auth manifest、SystemObjectName、i18n extract config 与 buildOauthProviderPluginSchema();翻译 bundle 重新生成(纯新增,708 insertions / 0 deletions)。

防漂移门(新测试):oauth-provider-schema-parity.test.ts 遍历 已安装 插件声明的 schema(fieldName ?? key 与 better-auth adapter 同逻辑解析),任何对象缺列直接红 —— 下次 better-auth bump 新增字段会在测试期失败而不是 prod 500。这个测试就是本 PR 发现三张新表的来源。

测试

  • plugin-auth:19 files / 452 tests 全过(含新 parity 8/8)
  • platform-objects:5 files / 197 tests 全过(含 bundle-ownership 门)
  • spec:6883 tests 全过
  • turbo build --filter=@objectstack/plugin-auth:11/11 成功

三仓协调

  1. framework(本 PR) — schema 修复,先合
  2. cloudplatform-sso.ts 注册双格式 redirect_uri(新 /api/v1/auth/callback/<provider> + 旧 /oauth2/callback/ 过渡)
  3. objectui — OIDC 登录从 POST /sign-in/oauth2(1.7 已移除)迁到 POST /sign-in/social,带旧路由 fallback

⚠️ cloud 当前 .framework-sha(929efdf)已包含 better-auth 升级点 —— 如果 staging/prod 已滚过含该 pin 的镜像,平台 SSO 现在就是断的;三仓合并后需尽快一起 bump pin 部署。

🤖 Generated with Claude Code

…1.7 schema drift — restore platform SSO
The better-auth 1.7.0-rc.1 bump (4ab16f8 "pnpm upgrade") changed the
oauth-provider model schemas, but the sys_oauth_* platform objects and the
camelCase→snake_case fieldName mappings in auth-schema-config.ts were never
updated. Token exchange then 500s with `table sys_oauth_access_token has no
column named authorizationCodeId`, breaking platform SSO ("Continue with
ObjectStack") end-to-end for every environment login — on SQLite AND
Postgres control planes alike.
- sys_oauth_access_token / sys_oauth_refresh_token: add
authorization_code_id (indexed), resources, requested_user_info_claims,
confirmation; access adds revoked; refresh adds rotated_at,
rotation_replay_response, rotation_replay_expires_at.
- sys_oauth_consent: add resources, requested_user_info_claims.
- sys_oauth_application: add jwks, jwks_uri, backchannel_logout_uri,
backchannel_logout_session_required, dpop_bound_access_tokens (1.7 DCR
writes dpopBoundAccessTokens with a default — same crash class).
- New objects for the three models 1.7 introduced: sys_oauth_resource,
sys_oauth_client_resource (RFC 8707 resource indicators, used by the MCP
OAuth track), sys_oauth_client_assertion (RFC 7523 jti replay
prevention); registered in the auth manifest, SystemObjectName, i18n
extract config, and buildOauthProviderPluginSchema().
- Mappings extended for every camelCase field; regenerated the
platform-objects translation bundles (additive only).
- NEW oauth-provider-schema-parity.test.ts: iterates the INSTALLED
plugin's declared schema and fails when any writable column is missing
from the platform objects — the next better-auth bump that adds fields
breaks at test time, not in production. (This test is what surfaced the
three brand-new 1.7 models above.)
Companion changes: cloud registers the ≥1.7 social-flow callback format
(/api/v1/auth/callback/<provider>) alongside the legacy one, and
@object-ui/auth signs OIDC providers in via POST /sign-in/social.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercelBot commented Jul 16, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
specReadyReadyPreview, CommentJul 16, 2026 5:06pm

Request Review

@github-actions

github-actionsBot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 4 package(s): @objectstack/platform-objects, @objectstack/plugin-auth, packages/qa, @objectstack/spec.

102 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/agents.mdx(via @objectstack/spec)
  • content/docs/ai/skills-reference.mdx(via @objectstack/spec)
  • content/docs/ai/skills.mdx(via @objectstack/spec)
  • content/docs/api/client-sdk.mdx(via @objectstack/spec)
  • content/docs/api/environment-routing.mdx(via @objectstack/spec)
  • content/docs/api/error-catalog.mdx(via @objectstack/spec)
  • content/docs/api/error-handling-client.mdx(via @objectstack/spec)
  • content/docs/api/error-handling-server.mdx(via @objectstack/spec)
  • content/docs/api/index.mdx(via @objectstack/spec)
  • content/docs/automation/approvals.mdx(via packages/spec)
  • content/docs/automation/flows.mdx(via @objectstack/spec)
  • content/docs/automation/hook-bodies.mdx(via packages/spec)
  • content/docs/automation/hooks.mdx(via @objectstack/spec)
  • content/docs/automation/index.mdx(via @objectstack/spec)
  • content/docs/automation/webhooks.mdx(via @objectstack/spec)
  • content/docs/automation/workflows.mdx(via @objectstack/spec)
  • content/docs/concepts/architecture.mdx(via @objectstack/spec)
  • content/docs/concepts/design-principles.mdx(via packages/spec)
  • content/docs/concepts/index.mdx(via @objectstack/spec)
  • content/docs/concepts/metadata-driven.mdx(via @objectstack/spec)
  • content/docs/concepts/metadata-lifecycle.mdx(via packages/spec)
  • content/docs/concepts/north-star.mdx(via packages/spec)
  • content/docs/data-modeling/analytics.mdx(via @objectstack/spec)
  • content/docs/data-modeling/drivers.mdx(via @objectstack/spec)
  • content/docs/data-modeling/external-datasources.mdx(via @objectstack/spec)
  • content/docs/data-modeling/field-types.mdx(via @objectstack/spec)
  • content/docs/data-modeling/fields.mdx(via @objectstack/spec)
  • content/docs/data-modeling/formulas.mdx(via @objectstack/spec)
  • content/docs/data-modeling/index.mdx(via @objectstack/spec)
  • content/docs/data-modeling/objects.mdx(via @objectstack/spec)
  • content/docs/data-modeling/queries.mdx(via @objectstack/spec)
  • content/docs/data-modeling/schema-design.mdx(via @objectstack/spec)
  • content/docs/data-modeling/seed-data.mdx(via @objectstack/spec)
  • content/docs/data-modeling/validation-rules.mdx(via @objectstack/spec)
  • content/docs/data-modeling/validation.mdx(via @objectstack/spec)
  • content/docs/deployment/production-readiness.mdx(via @objectstack/plugin-auth)
  • content/docs/deployment/troubleshooting.mdx(via @objectstack/spec)
  • content/docs/getting-started/build-with-claude-code.mdx(via @objectstack/spec)
  • content/docs/getting-started/cli.mdx(via @objectstack/plugin-auth, @objectstack/spec)
  • content/docs/getting-started/common-patterns.mdx(via @objectstack/spec)
  • content/docs/getting-started/examples.mdx(via @objectstack/spec)
  • content/docs/getting-started/quick-reference.mdx(via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx(via @objectstack/spec)
  • content/docs/getting-started/validating-metadata.mdx(via @objectstack/spec)
  • content/docs/getting-started/your-first-project.mdx(via @objectstack/spec)
  • content/docs/kernel/cluster.mdx(via @objectstack/spec)
  • content/docs/kernel/contracts/auth-service.mdx(via packages/spec)
  • content/docs/kernel/contracts/cache-service.mdx(via packages/spec)
  • content/docs/kernel/contracts/data-engine.mdx(via @objectstack/spec)
  • content/docs/kernel/contracts/index.mdx(via @objectstack/spec)
  • content/docs/kernel/contracts/metadata-service.mdx(via packages/spec)
  • content/docs/kernel/contracts/storage-service.mdx(via packages/spec)
  • content/docs/kernel/index.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/email-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/index.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/queue-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/sharing-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/sms-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx(via packages/spec)
  • content/docs/kernel/services-checklist.mdx(via @objectstack/plugin-auth, @objectstack/spec)
  • content/docs/permissions/authentication.mdx(via @objectstack/plugin-auth)
  • content/docs/permissions/authorization.mdx(via packages/qa, @objectstack/spec)
  • content/docs/permissions/delegated-administration.mdx(via packages/qa)
  • content/docs/permissions/permission-sets.mdx(via @objectstack/spec)
  • content/docs/permissions/permissions-matrix.mdx(via @objectstack/spec)
  • content/docs/permissions/positions.mdx(via @objectstack/spec)
  • content/docs/permissions/sharing-rules.mdx(via @objectstack/spec)
  • content/docs/permissions/sso.mdx(via @objectstack/plugin-auth)
  • content/docs/plugins/adding-a-metadata-type.mdx(via @objectstack/spec)
  • content/docs/plugins/development.mdx(via @objectstack/spec)
  • content/docs/plugins/index.mdx(via @objectstack/plugin-auth, @objectstack/spec)
  • content/docs/plugins/packages.mdx(via @objectstack/platform-objects, @objectstack/plugin-auth, @objectstack/spec)
  • content/docs/protocol/backward-compatibility.mdx(via @objectstack/spec)
  • content/docs/protocol/diagram.mdx(via packages/spec)
  • content/docs/protocol/kernel/config-resolution.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/i18n-standard.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/lifecycle.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/plugin-spec.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/runtime-capabilities.mdx(via @objectstack/spec)
  • content/docs/protocol/knowledge.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx(via packages/spec)
  • content/docs/protocol/objectql/query-syntax.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/schema.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/security.mdx(via packages/spec)
  • content/docs/protocol/objectql/state-machine.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/actions.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/concept.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/index.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/layout-dsl.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/record-alert.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx(via @objectstack/spec)
  • content/docs/releases/implementation-status.mdx(via @objectstack/plugin-auth, @objectstack/spec)
  • content/docs/releases/index.mdx(via @objectstack/spec)
  • content/docs/releases/v12.mdx(via @objectstack/spec)
  • content/docs/releases/v13.mdx(via @objectstack/spec)
  • content/docs/releases/v9.mdx(via @objectstack/plugin-auth, @objectstack/spec)
  • content/docs/ui/create-vs-edit-form.mdx(via @objectstack/spec)
  • content/docs/ui/dashboards.mdx(via @objectstack/spec)
  • content/docs/ui/forms.mdx(via @objectstack/spec)
  • content/docs/ui/index.mdx(via @objectstack/spec)
  • content/docs/ui/public-data-collection.mdx(via @objectstack/spec)
  • content/docs/ui/setup-app.mdx(via @objectstack/platform-objects, @objectstack/spec)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

…oken exchange
Drives authorize → code → token → userinfo against a bootStack kernel with
OS_OIDC_PROVIDER_ENABLED, seeding the client row exactly the way cloud's
seedPlatformSsoClient does (hashed secret, skip_consent, client_secret_basic,
≥1.7 /api/v1/auth/callback/<provider> redirect_uri). The token-exchange step
is the hop that 500'd in production on the 1.7 schema drift; verified the
test fails (2/3) when the authorization_code_id column is removed and passes
(3/3) with the fix. Complements the static parity gate in plugin-auth.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
os-zhuang added a commit to objectstack-ai/objectui that referenced this pull request Jul 16, 2026
…h ≥ 1.7) (#2621)
better-auth 1.7 restructured the genericOAuth plugin: generic OAuth/OIDC
providers are injected into the core social sign-in flow and the dedicated
POST /sign-in/oauth2 endpoint no longer exists. `signInWithProvider` with
`type: 'oidc'` therefore 404'd on every click — "Continue with ObjectStack"
(platform SSO) was dead against a current framework server.
Sign in through `signIn.social` first; when the social route rejects the
provider AND the legacy `signIn.oauth2` client method succeeds (an older
< 1.7 server), fall back to it — the coordinated framework/cloud rollout
can't atomically flip every deployment. When both routes fail, surface the
social-route error: on a ≥ 1.7 server it is the real failure, the legacy
route only 404s.
Companion changes: framework adds the better-auth 1.7 sys_oauth_* columns
(objectstack-ai/objectstack#3080); cloud registers the new
/api/v1/auth/callback/<provider> redirect_uri format alongside the legacy
one.
Co-authored-by: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
@os-zhuangos-zhuang reopened this Jul 16, 2026
@os-zhuang
os-zhuang merged commit 4109153 into mainJul 16, 2026
29 of 31 checks passed
@os-zhuang
os-zhuang deleted the fix/oauth-provider-17-schema-drift branch July 16, 2026 17:05
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/xlteststooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@os-zhuang