Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .changeset/17210-oauth-register-name-trap-prose.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
'@objectstack/client': patch
---

`oauth.applications.register`'s docblock says where a plain `name` IS honoured, and that it is not this route

A caller who wants to name an OAuth client reaches for `name`. On the route this
method posts — the provider's `/oauth2/create-client` — that member is not in
the body schema and is stripped: driven on a real socket, the call answered
**201** and the value was absent from the response, from `applications.get`,
from `applications.list`, and `null` in the `sys_oauth_application` row's `name`
column. Nothing in the answer says so.

The spelling is not wrong everywhere, which is what made it worth writing down:
`POST /api/v1/auth/sys-oauth-application/register` — the session-required
ObjectStack mount behind the Console's *Setup → OAuth Applications* form —
answered **200** to the same body, mapped `name` onto `client_name`, and set
that column. That mount is `disposition: 'server-only'` in the auth route ledger
and objectstack#17210 ruled it stays that way, so no SDK method builds its URL.

The docblock now states both halves where the caller reads them: post
`client_name` to name a client from here, and `redirect_uris` must arrive
pre-split — the newline-separated-textarea split is the Console wrapper's, not
this route's.

Docblock only. No method is added, no request or response type changes, and the
ledger row is untouched — but the text ships inside `dist/*.d.ts` as editor
hover, so it is a `patch` rather than a no-publish change.
6 changes: 6 additions & 0 deletions content/docs/protocol/objectui/actions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,12 @@ resultDialog:

Each `fields[].path` is a dot path into `result.data`. The per-field `format` (`qrcode`, `code-list`, `secret`, `text`, `json`) controls rendering.

#### ⚠️ That `target` is not interchangeable with the SDK's registration door

`POST /api/v1/auth/sys-oauth-application/register` is an **ObjectStack mount written for this form**, and it is what keeps the YAML above this short. It accepts the application's display name as a plain `name` body key — the spelling an author writes as a param — and it splits a newline-separated redirect-URL **textarea** into the `redirect_uris` array the underlying provider schema requires. Both are form-shaped conveniences the mount performs on the action's behalf; the route ledger carries it as `disposition: server-only` (`packages/plugins/plugin-auth/src/auth-route-ledger.ts`) for exactly that reason, and [#17210](https://github.com/objectstack-ai/objectstack/issues/17210) ruled that it stays that way — no SDK method builds this URL.

So do **not** re-point this `target` at the provider's own registration route, `/api/v1/auth/oauth2/create-client` (what `@objectstack/client`'s `oauth.applications.register` posts). Driven on a real socket, the two doors answer the same body differently: the mount above returned **200**, mapped `name` onto `client_name`, and set the `sys_oauth_application` row's `name`; the provider route returned **201** with the value **stripped** — absent from the response, from `oauth.applications.get`, from `oauth.applications.list`, and `null` in that column. An action retargeted there needs its name param renamed to `client_name`, and its redirect URLs split into an array before the post — the textarea param would arrive as one unsplit string.

## Action Parameters

`params` declares inputs collected from the user before execution. Each entry is an `ActionParam` with two modes:
Expand Down
27 changes: 27 additions & 0 deletions packages/client/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4038,6 +4038,33 @@ export class ObjectStackClient {
* router skips SERVER_ONLY endpoints, so over HTTP it answers 404 with a
* zero-byte body.
*
* ## ⚠️ A plain `name` IS honoured somewhere — not here (#17210)
*
* There is exactly one door that reads a body member spelled `name`, and
* this method does not build it:
* `POST /api/v1/auth/sys-oauth-application/register`, the ObjectStack
* mount behind the Console's *Setup → OAuth Applications* create form.
* The same #15447 round drove both doors on one real socket: that mount
* answered **200** to a body spelled `name`, mapped it onto
* `client_name`, and the `sys_oauth_application` row's `name` column was
* set; this method's route, `/oauth2/create-client`, answered **201**
* with the value **stripped** — absent from the response, absent from
* `applications.get`, absent from `applications.list`, and `null` in
* that same column.
*
* ⛔ That mount is **not** an SDK door, and it is not withheld by
* oversight: it is `disposition: 'server-only'` in the auth route ledger
* (`packages/plugins/plugin-auth/src/auth-route-ledger.ts`), a
* session-required self-service wrapper written to serve the Console's
* form — and #17210 ruled that it **stays** `server-only`, so no SDK
* method builds its URL. To name a client from here, post `client_name`.
*
* The wrapper's other Console-shaped convenience is the same asymmetry's
* second half: it splits that form's newline-separated redirect-URL
* **textarea** into the array the vendor schema requires. ⛔ This route
* performs no such split — `redirect_uris` must arrive **pre-split**,
* one entry per URL, which is what an SDK caller holds anyway.
*
* Pinned by `oauth-applications-register-request-members.test.ts`.
*/
register: async (req: {
Expand Down
Loading