You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Filed unassigned by the #11701 dev while discharging that card's narrowing condition. Not fixed there: narrowing this column is a contract change on a different published object and would move it off #12198's hash shadow, so it needs its own ruling.
The observation
sys_oauth_resource.identifier (packages/platform-objects/src/identity/sys-oauth-resource.object.ts) declares maxLength: 1024. Two things are true of that number:
Measured, the producing contract cannot fill it. better-auth 1.7.1 is the sole writer (managedBy: 'better-auth', protection.lock: 'full'). Its own MySQL migration generator (better-auth/dist/db/get-migration.mjs, getType) emits this column as varchar(255) (the field.unique branch — oauthResource.identifier is { type: "string", required: true, unique: true }), and the referring oauthClientResource.resourceId as varchar(36) (the field.references branch). On an upstream MySQL deployment a resource identifier longer than 255 characters cannot be registered at all.
Why it matters now rather than before
#11701 narrowed sys_oauth_client_resource.resource_id from 1024 to 768 so its declared non-unique index could exist on MySQL at all. That leaves the pair asymmetric in the declaration, not just in practice:
column
declared
physical (MySQL, measured 8.0.46)
sys_oauth_resource.identifier (referent)
1024
text + UNIQUE on a varbinary(32) hash shadow (#12198)
sys_oauth_client_resource.resource_id (referrer)
768
varchar(768), index with SUB_PART = NULL
So on PostgreSQL or SQLite an operator can register a resource whose identifier is 900 characters — the referent's declared contract admits it — and then no client can ever be granted that resource, because the referring column refuses it. Nothing upstream can produce such a value, which is exactly why #11701's narrowing was ruled safe; but the two declarations still disagree about what a legitimate resource identifier is, and only one of them is sourced.
Dispositions worth weighing (not ruled)
A — narrow identifier to 768 to match its referrer. Cheapest; keeps the pair consistent; but ⚠️ it also takes sys_oauth_resourceofffix(driver-sql): carry an over-long UNIQUE index on a hash-shadow column (MySQL utf8mb4) #12198's hash shadow (768 × 4 = 3072 bytes is exactly the last direct width), changing physical schema on an object that just landed on that route, and reducing the population that route demonstrates.
B — narrow both to a sourced 255, matching what upstream can actually store. Most honest against the producer; largest declared-domain reduction, and it rejects values in (255, 768] that the current referrer would accept.
C — leave 1024 and document why, i.e. accept the asymmetry and add the citation this column is missing. Cheapest by far, and defensible if the band is agreed unreachable — but it keeps a number nothing derives.
No recommendation carried here — #11701's ruling deliberately scoped itself to the referring column, and picking among these is a fresh decision.
Evidence trail
Upstream field declarations: @better-auth/oauth-provider@1.7.1/dist/authorize-*.mjs (resourceId.references = { model: "oauthResource", field: "identifier" }) and dist/oauth-*.d.mts.
Upstream width emission: better-auth@1.7.1/dist/db/get-migration.mjs, getType's mysql string branch.
Physical readings above are from information_schema.COLUMNS / .STATISTICS on live MySQL 8.0.46 (utf8mb4/InnoDB, STRICT_TRANS_TABLES), read as a separate query rather than from emitted DDL.
Related to #11701 (which narrowed the referrer) and #12198 (which put the referent on a hash shadow).
Filed unassigned by the #11701 dev while discharging that card's narrowing condition. Not fixed there: narrowing this column is a contract change on a different published object and would move it off #12198's hash shadow, so it needs its own ruling.
The observation
sys_oauth_resource.identifier(packages/platform-objects/src/identity/sys-oauth-resource.object.ts) declaresmaxLength: 1024. Two things are true of that number:It cites no producer. Every bound driver-sql: the platform-objects schema does not sync onto MySQL — unbounded string fields become TEXT, which MySQL refuses to index #11374 declared carries a
[#11374]comment naming where it came from (sys_session.token→ "better-auth 1.7.1's own MySQL schema … varchar(255)";sys_oauth_consent.client_id→ "a referencing column takes the referenced column's bound";sys_account.issuer→ "transitively from sys_sso_provider.issuer"). This one has no comment at all.git log -Sputs it in 4109153 (fix(plugin-auth,platform-objects): close @better-auth/oauth-provider 1.7 schema drift — restore platform SSO #3080), the@better-auth/oauth-provider1.7 schema-drift close — a parity fix that added the object wholesale, not a sourced-bound pass. It reads as generous slack chosen for "a URI", never derived.Measured, the producing contract cannot fill it. better-auth 1.7.1 is the sole writer (
managedBy: 'better-auth',protection.lock: 'full'). Its own MySQL migration generator (better-auth/dist/db/get-migration.mjs,getType) emits this column asvarchar(255)(thefield.uniquebranch —oauthResource.identifieris{ type: "string", required: true, unique: true }), and the referringoauthClientResource.resourceIdasvarchar(36)(thefield.referencesbranch). On an upstream MySQL deployment a resource identifier longer than 255 characters cannot be registered at all.Why it matters now rather than before
#11701 narrowed
sys_oauth_client_resource.resource_idfrom 1024 to 768 so its declared non-unique index could exist on MySQL at all. That leaves the pair asymmetric in the declaration, not just in practice:sys_oauth_resource.identifier(referent)text+ UNIQUE on avarbinary(32)hash shadow (#12198)sys_oauth_client_resource.resource_id(referrer)varchar(768), index withSUB_PART = NULLSo on PostgreSQL or SQLite an operator can register a resource whose
identifieris 900 characters — the referent's declared contract admits it — and then no client can ever be granted that resource, because the referring column refuses it. Nothing upstream can produce such a value, which is exactly why #11701's narrowing was ruled safe; but the two declarations still disagree about what a legitimate resource identifier is, and only one of them is sourced.Dispositions worth weighing (not ruled)
identifierto 768 to match its referrer. Cheapest; keeps the pair consistent; butsys_oauth_resourceoff fix(driver-sql): carry an over-long UNIQUE index on a hash-shadow column (MySQL utf8mb4) #12198's hash shadow (768 × 4 = 3072 bytes is exactly the last direct width), changing physical schema on an object that just landed on that route, and reducing the population that route demonstrates.No recommendation carried here — #11701's ruling deliberately scoped itself to the referring column, and picking among these is a fresh decision.
Evidence trail
@better-auth/oauth-provider@1.7.1/dist/authorize-*.mjs(resourceId.references = { model: "oauthResource", field: "identifier" }) anddist/oauth-*.d.mts.better-auth@1.7.1/dist/db/get-migration.mjs,getType'smysqlstring branch.information_schema.COLUMNS/.STATISTICSon live MySQL 8.0.46 (utf8mb4/InnoDB,STRICT_TRANS_TABLES), read as a separate query rather than from emitted DDL.Related to #11701 (which narrowed the referrer) and #12198 (which put the referent on a hash shadow).
Generated by Claude Code