From aefbf59275282b9f277832d9f98fd67f058fc238 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 17 Sep 2026 19:22:22 +0000 Subject: [PATCH] =?UTF-8?q?fix(changeset):=20the=20pending=20client=20entr?= =?UTF-8?q?y's=20closing=20register=20is=20dated,=20not=20present-tense=20?= =?UTF-8?q?=E2=80=94=20all=20three=20"not=20addressed=20here"=20clauses=20?= =?UTF-8?q?had=20been=20answered?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `.changeset/client-get-session-envelope-and-refresh-read.md` is release input: `changeset version` copies it verbatim into `packages/client/CHANGELOG.md` and it ships in the npm tarball. Its closing paragraph was an undated present-tense register of what the change left undone, and every one of its three clauses had since been falsified on `origin/main`: - the anonymous `/get-session` `null` "would need the published return annotation to widen" — `374d9d3afa` moved the PRODUCER instead: `refuseAnonymousSession` converts `200` + literal `null` into the ADR-0112 `401 UNAUTHENTICATED` refusal, so an anonymous `auth.me()` rejects and the annotation needs no widening at all; - `SessionUser.image` "declared `z.string().optional()`" — `0e51278f3` declares it `z.string().nullish()`; - `auth.login` / `auth.register` "normalize into `data` but set no `success`" — `01388fe81` put them on `normalizeSessionResponse`, which returns `{ success: true, ...body, data }`. Each clause is kept as what it recorded, anchored to when it was written, with the landing that answered it beside it. The dated better-auth 1.7.2 transcript above is history and is untouched. Co-Authored-By: Claude Claude-Session: https://claude.ai/code/session_01DvvamiacK328idtBYJBxV3 --- ...t-get-session-envelope-and-refresh-read.md | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/.changeset/client-get-session-envelope-and-refresh-read.md b/.changeset/client-get-session-envelope-and-refresh-read.md index ba6704d205f..96de2dfc172 100644 --- a/.changeset/client-get-session-envelope-and-refresh-read.md +++ b/.changeset/client-get-session-envelope-and-refresh-read.md @@ -57,8 +57,21 @@ inert as it was. `token.signature` form interchangeably, so a client that held the signed form stays signed in across the call. -Two answers stay outside the declared type and are **not** addressed here: the -anonymous `null`, which would need the published return annotation to widen, and -`SessionUser.image`, declared `z.string().optional()` against a route that -serves `null` (#17235). The sibling `auth.login` / `auth.register`, which -normalize into `data` but set no `success`, are #17234. +Three answers sat outside the declared type when this change was written and +are **not** addressed by it. Each has since been answered on its own card, so a +caller reading this entry does not have to code around any of them: + +- the **anonymous** `/get-session` answer, recorded above as `200 null`. It no + longer needs the published return annotation to widen, because the producer + moved instead: since #17881 `plugin-auth`'s `refuseAnonymousSession` converts + better-auth's `200` plus the literal JSON `null` into the declared ADR-0112 + refusal — HTTP `401` with `code: UNAUTHENTICATED` — before it leaves the + process. The SDK's shared `fetch` wrapper throws on any non-2xx, so an + anonymous `auth.me()` **rejects** rather than resolving outside its own type. + Ruled by #17238: the producer moved and `SessionResponseSchema` is untouched. +- `SessionUser.image`, then declared `z.string().optional()` against a route + that serves `null` (#17235). It is now declared `z.string().nullish()`, so + the `"image": null` every `/auth/*` session body carries parses. +- the sibling `auth.login` / `auth.register`, which then normalized into `data` + but set no `success` (#17234). They now run this entry's own lift, which + fills `success` as well as `data`.