Commit 7baf04a
Fixes #17210
Implements the director seat's ruling on this card
(`#issuecomment-5634036848`), option **B**: **the SDK gains no method;
the ledger row is untouched.** The one measured trap is made visible in
prose where its reader meets it. No SDK method is added, no request or
response type moves, no accept set moves, and
`packages/plugins/plugin-auth/src/auth-route-ledger.ts` is not in this
diff.
## Premises — falsified first, on `origin/main` at `396eae33`
All four rows of the dispatch's premise table hold, plus the
falsification trigger it named.
| # | premise | reading |
|:--|:--|:--|
| 1 | `oauth.applications.register` still exists | `applications: {` at
`:3997`; `register: async (req: {` at `:4043`; pin named at `:4041` |
| 2 | the request type is the vendor shape | `client_name?: string` at
`:4044` and `redirect_uris: string[]` at `:4045` in the request type;
the same two members at `:947` / `:960` in `OAuthApplication` |
| 3 | the ledger row is unchanged and still `server-only` |
`auth-route-ledger.ts:241`, `disposition: 'server-only'`, note verbatim
as quoted on the card |
| 4 | control | `disposition` returns **70** in that ledger — the probe
is live |
| 5 | PR #17209's removal held: no bare `name` in the typed request |
**zero** hits for `^\s*name\??:` in lines `4043-4055`. Positive control,
**same file, same regex**: 14 bare `name` members elsewhere (`:1062`,
`:1218`, `:1267`, `:1305`, `:1741`, …) |
Every `client_name` hit in `packages/client/src/index.ts` was read in
context, not counted: `:947` (an `OAuthApplication` member), `:1008`
(inside the `OAuthApplicationPublic` `Pick`), `:4025` / `:4027` (the
existing #15447 docblock), `:4044` (the request type). Premise not
falsified — `premise_still_valid: true`.
## 1. The JSDoc — landed bytes
Added to the `oauth.applications.register` docblock, after the
`metadata` paragraph and before the `Pinned by` line:
```
* ## ⚠️ 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.
```
Both halves the ruling asked for are stated: `name` is honoured only by
the Console's server-only mount, and this route requires `redirect_uris`
pre-split.
## 2. `content/docs/protocol/objectui/actions.mdx` — the same fact, that
page's own idiom
Not a copy-paste of the JSDoc. The page is an action-authoring
reference, so the note is written to an action author, about the
`target` of the `create_oauth_application` example, and it is addressed
at the `:424` neighbourhood — a new `#### ⚠️ That target is not
interchangeable with the SDK's registration door` immediately after that
example's `resultDialog` explanation, inside the same **Result Dialog**
section. It says why the YAML above is that short (the mount does the
plain-`name` mapping and the textarea split on the action's behalf),
that the ledger carries it `server-only` for exactly that reason, and
what an author would have to change — rename the name param to
`client_name`, pre-split the redirect URLs — if they re-pointed `target`
at the provider route.
The docs-drift tool cannot surface this page for this diff (it states
the rule by its YAML inputs, so it shares no identifier with the SDK
file), which is why it was edited by hand.
## 3. The measured evidence, restated and not overstated
From the #15447 round, on a real socket, driven through the real client:
- `POST /api/v1/auth/sys-oauth-application/register` with a body spelled
`name` answered **200**, the value came back as `client_name`, and the
`sys_oauth_application` row's `name` column was set.
- The same spelling posted to `/oauth2/create-client` answered **201**
with the value **stripped**: absent from the response, absent from
`oauth.applications.get`, absent from `oauth.applications.list`, `null`
in the DB column.
Nothing in this PR claims more than those two readings. In particular it
does not claim the mount is reachable from the SDK, nor that any
behaviour changed.
## 4. Changeset — `patch`, measured, not assumed
`skip-changeset` was tested and refused. `@objectstack/client`'s
`files[]` is `["dist","README.md","CHANGELOG.md"]`; after `pnpm --filter
@objectstack/client build`, the new docblock prose is present in
**both** `dist/index.d.ts` and `dist/index.d.mts` — it ships as editor
hover to every consumer.
- measurement: `grep -c "A plain \`name\` IS honoured somewhere"` → `1`
in each of the two files
- positive control, same files, same grep shape: `grep -c "the vendor's
RECORD vocabulary"` (pre-existing docblock prose) → `1` in each
- negative control: an absent marker string → `0`
Published bytes move ⇒ `patch`.
`.changeset/17210-oauth-register-name-trap-prose.md`.
## Gates
Derived mechanically with `node scripts/pm/dispatch-gates.mjs --commands
--repo objectstack-ai/objectstack` (no hand-written path list), then
reconciled with `--ran` carrying each command's own exit code, captured
before any pipe.
- **82 derived families — 81 run green, 0 UNRUN, 1 NOT MEASURED.**
- `pnpm lint` (whole repo, `eslint . --no-inline-config`) — **exit 0**.
- `pnpm --filter @objectstack/client test` — **42 files / 506 tests
passed**, including the
`oauth-applications-register-request-members.test.ts` pin.
- `pnpm --filter @objectstack/client typecheck` — **exit 0**, test layer
included (`check:test-typecheck`: 0 files / 0 errors).
- Dependency closure built first: `pnpm --filter
'@objectstack/client^...' build` — exit 0. Heavy runs went through
`scripts/pm/os-verify-lock.sh`; verdicts read from its `VERDICT
command-exit` lines.
- Control characters: `grep -naP` over both edited files, zero hits, on
top of `check:nul-bytes` green.
**NOT MEASURED: `pnpm check:dual-build-cjs-loads`, reason:** it exited
**3** with `PREREQUISITE NOT MET — this gate reads built output, and
some package has no dist/ … ⛔ This is NOT a pass: nothing was measured`.
It wants a whole-repo `pnpm build` (34 packages listed, none of them
`@objectstack/client`, which is built). That is CI's `Build Core` run,
and the gate reads emitted runtime JS where comments are stripped, so a
docblock-only diff has no way to move it. Declared rather than run.
`Clause-②: no`, re-derived from the delivered diff: three files, 33
inserted lines plus a changeset, zero deletions; no declaration, export,
accept set or published symbol moves.
## Acceptance notes
**`docs/qa/platform-checklist/areas/identity-auth.json` (`:1008`,
`:1017`, `:1078`) — read, judged out of scope, not edited.** The
dispatch left this call to me, so here is the reasoning rather than the
verdict alone.
All three lines were read in context. They belong to
`identity-auth.oauth-app-consent-loop`, and **none of them states
anything false.** `:1008` enumerates the three registration doors and
already records this mount's distinguishing behaviour (*"the
session-required wrapper that splits the redirect-URL textarea into
redirect_uris"*); `:1017` offers two of those doors as alternatives for
a step whose object is the **`client_secret`**, not the client's name;
`:1078` is a `source` row naming the ledger. Nothing there claims the
provider route honours a plain `name`. The item never names an
application, at any step, in any acceptance clause or negative — so the
trap is not reachable from it, and there is no assertion to correct.
Against that, editing it has a real cost in the checklist's own
machinery: a semantic edit owes a `revision` bump
(`scripts/check-platform-checklist.mjs` holds `revision` equal to the
last `history` entry precisely so that a changed item cannot silently
re-validate old run results), which would invalidate the item's recorded
runs for a clarification its steps never exercise.
So: read, found accurate, left alone. It is not orphaned — the carriers
that will next open it are the `checklist-author` coverage sweep and any
`checklist-test` run selecting `identity-auth.oauth-app-consent-loop`.
**Red lines held.** No `packages/spec` path in the diff.
`auth-route-ledger.ts` untouched. No `content/docs/releases/` path. No
file held by #17725, #17718 or #17093 is reached — the diff is
`packages/client/src/index.ts`,
`content/docs/protocol/objectui/actions.mdx` and one new changeset.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01TSf4DV7ziu4V5j73e46b7c)_
---------
Co-authored-by: Claude <noreply@anthropic.com>
1 parent 813f8e9 commit 7baf04a
3 files changed
Lines changed: 61 additions & 0 deletions
File tree
- .changeset
- content/docs/protocol/objectui
- packages/client/src
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
435 | 435 | | |
436 | 436 | | |
437 | 437 | | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
438 | 444 | | |
439 | 445 | | |
440 | 446 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4038 | 4038 | | |
4039 | 4039 | | |
4040 | 4040 | | |
| 4041 | + | |
| 4042 | + | |
| 4043 | + | |
| 4044 | + | |
| 4045 | + | |
| 4046 | + | |
| 4047 | + | |
| 4048 | + | |
| 4049 | + | |
| 4050 | + | |
| 4051 | + | |
| 4052 | + | |
| 4053 | + | |
| 4054 | + | |
| 4055 | + | |
| 4056 | + | |
| 4057 | + | |
| 4058 | + | |
| 4059 | + | |
| 4060 | + | |
| 4061 | + | |
| 4062 | + | |
| 4063 | + | |
| 4064 | + | |
| 4065 | + | |
| 4066 | + | |
| 4067 | + | |
4041 | 4068 | | |
4042 | 4069 | | |
4043 | 4070 | | |
| |||
0 commit comments