| @objectstack/client | minor |
|---|
fix(client): oauth.applications.register declares only the members /oauth2/create-client accepts — name, scopes and metadata are removed (#15447)
BREAKING — three members leave a published request type. A caller who sets one compiles today and gets a type error after this release. That is the point: the route never honoured any of them, so what the compiler now refuses is code that was already having its value thrown away.
| you were passing | pass instead | why |
|---|---|---|
name: 'My App' |
client_name: 'My App' |
same string, and client_name is the member the route reads |
scopes: ['openid', 'profile'] |
scope: ['openid', 'profile'].join(' ') |
scope is one space-delimited string; posting an array is refused with 400 [body.scope] Invalid input: expected string, received array |
metadata: { tenant: 'acme' } |
nothing — delete the member | no door this SDK can reach accepts it (see below) |
client_name writes the DB column literally named name; scope writes the DB column literally named scopes, as a JSON array. The removed members were the column names offered next to the wire names in the same declared type — an author picking the adjacent one of two got a success receipt and no value. Treating them as misspellings would be the wrong reading of what they were; the prescription above is still the wire member either way.
POST /api/v1/auth/oauth2/create-client is mounted verbatim from @better-auth/oauth-provider@1.7.2. Its body schema declares 21 members and sets no catchall, so it is zod's default strip: an unknown key is dropped, not refused, and the caller gets HTTP 201 and a client that quietly does not have the value. Driven end to end against a real betterAuth + oauthProvider over a real ObjectQL engine on a real socket, through this client: each of the three came back absent from the response, absent from oauth.applications.get, absent from oauth.applications.list, and null in the sys_oauth_application row.
A second, independent barrier stands behind that strip — the handler funnels the parsed remainder into the opaque-metadata envelope, and all three names sit in OPAQUE_METADATA_RESERVED_FIELDS — so no amount of loosening on the SDK side could ever have made them arrive. metadata in particular is honoured only by PATCH /admin/oauth2/update-client, which is SERVER_ONLY and therefore not an HTTP route at all: over the wire it answers 404 with a zero-byte body.
Nothing else on the method moves. The two members the route does honour, client_name and scope, are declared exactly as before and still reach the server byte for byte; the method's return type, its URL and its request-building step are unchanged.
Graded minor rather than patch because a published package's public surface moves, per the maintainer's ruling of 2026-09-04 (decision batch #35) that such a change takes at least minor; the banner above carries the breaking-ness the level cannot.