From 91c65e75cde64b3202b7f19b9170a25b17f76dea Mon Sep 17 00:00:00 2001 From: os-zhuang Date: Fri, 26 Jun 2026 01:17:24 +0800 Subject: [PATCH] =?UTF-8?q?fix(identity):=20sys=5Fverification.value=20mus?= =?UTF-8?q?t=20not=20be=20UNIQUE=20=E2=80=94=20it=20breaks=20OIDC=20author?= =?UTF-8?q?ize?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit better-auth's oauth-provider stores OIDC authorization codes in the verification table with `value` = a JSON blob (keyed by user + client + state) that can legitimately repeat. The UNIQUE index on `value` makes `/api/v1/auth/oauth2/authorize` fail with `UNIQUE constraint failed: sys_verification.value` → HTTP 503, which breaks cloud-as-IdP SSO ("Continue with ObjectStack") entirely — the authorize loops forever. better-auth keys verification lookups on `identifier` (indexed), not `value`, so a non-unique index on `value` is sufficient. Found via a local browser E2E of the env→cloud OIDC SSO flow (ADR-0024 D3). NOTE: existing control-plane DBs already have `uniq_sys_verification_value`; they need a migration to drop it (schema-sync is additive). Co-Authored-By: Claude Opus 4.8 --- .../src/identity/sys-verification.object.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/platform-objects/src/identity/sys-verification.object.ts b/packages/platform-objects/src/identity/sys-verification.object.ts index 122afd8db0..07b6fe851d 100644 --- a/packages/platform-objects/src/identity/sys-verification.object.ts +++ b/packages/platform-objects/src/identity/sys-verification.object.ts @@ -67,7 +67,13 @@ export const SysVerification = ObjectSchema.create({ }, indexes: [ - { fields: ['value'], unique: true }, + // `value` must NOT be unique. better-auth's oauth-provider stores OIDC + // authorization codes in this table with `value` = a JSON blob keyed by + // user+client+state, which can legitimately repeat. A UNIQUE constraint + // makes `/api/v1/auth/oauth2/authorize` fail (`UNIQUE constraint failed: + // sys_verification.value`) → 503, breaking cloud-as-IdP SSO entirely. + // better-auth keys verification lookups on `identifier`, not `value`. + { fields: ['value'], unique: false }, { fields: ['identifier'], unique: false }, { fields: ['expires_at'], unique: false }, ],