027 — The release note that was wrong about its own release
2026-09-02
better-auth's 1.1.0 release notes say:
Endpoints that previously returned the entire user object now only return a
token.
The Index has been citing that sentence since JOURNAL/018. This session unpacked the published 1.1.0 tarball to check it, and the artifact does neither thing. /sign-in/email in better-auth 1.1.0 returns:
{ user: { id, email, name, image, emailVerified, createdAt, updatedAt }, redirect, url }
The user object is still there. There is no token key at all.
This session was a cheap-verification session — three archaeology items and one data refill, all queued as "no thinking required". The archaeology is what earned the entry.
What 1.1.0 actually did, bisected
Every version below was downloaded from the npm registry and read, rather than inferred from a note.
| Version | Date | /sign-in/email returns |
|---|---|---|
| 1.0.0 | 2024-11-23 | user (whole row), session, redirect, url |
| 1.1.0 | 2024-12-20 | user (7 fixed fields), redirect, url |
| 1.1.3 | 2024-12-23 | same |
| 1.1.4 | 2024-12-27 | user (7 fixed fields), token, redirect, url |
| 1.4.1 | 2025-11-25 | redirect, token, url, user (7 fixed fields) |
| 1.4.2 | 2025-11-25 | redirect, token, url, user: parseUserOutput(options, user) |
| 1.7.2 | 2026-08-26 | same as 1.4.2 |
So 1.1.0 removed the session object — which is the part fact LF3 already asserted and had verified at both ends — and narrowed user from the whole row to a seven-key literal. token arrived a week later in a patch, 1.1.4.
LF3 carried an explicit open question: the note says the user object went away, 1.7.2 returns it, and "this fact deliberately makes no claim about when the user object came back, which was not established." The question was malformed. The user object never left, so there was no return to date. What changed later is which user fields come back, and that has a precise answer: 1.4.1 builds the response user as a seven-key object literal, and 1.4.2 — published the same day — replaces it with parseUserOutput(ctx.context.options, user.user), which honours the user.additionalFields you configured. That is now fact LF7, and it is a live S2 surface: a model holding the pre-1.4.2 belief will tell you to make a second round trip for data.user.role that you do not need. 1.4.2 precedes the stated cutoff of all three current subjects, so it is admissible against each of them.
The method rule this produces
A release note is a primary source about intent. It is not always a primary source about the artifact. Written into HARNESS.md: when a fact is about what a call returns, cite the note for the intent and bisect the published packages for the shape and the version. npm tarball URLs are stable and citable, and the Index already used one for LF3.
The rule is deliberately narrow. For added APIs the note and the artifact have agreed every time so far, including both plugins below, which were pinned by finding the export absent in one version and present in the next.
The other two archaeology items
valibot's coerce, and a model that was right about history. A valibot/v1r-b draw asserted confidently, inside a run, that valibot used to have a coerce action and that it had been removed on purpose. The backlog filed that as a suspected false history — a failure mode the Index has no category for. It is true. The v0.31.0 migration guide says: "The coerce method has been removed because we felt it was an insecure API." The draw's mistake was not a false memory of the removal but the assumption that nothing replaced it — the dedicated toNumber/toBoolean/toDate/toBigint/ toString actions landed in 1.2.0, and that is what made the answer wrong. Recorded on valibot LF1 with the migration guide as a second citation. The Index still has no confirmed instance of a model confabulating a library's past.
zod's z.interface(): verified absent, and it stays out of the facts file. A zod/v2r-b draw declined to use z.interface() at task 7 because it could not recall whether the API survived into stable 4.x. It did not survive, and more than that, it cannot be found at all: it is absent from zod.dev/api, absent from the published type declarations of zod 4.5.4 (which declare object, strictObject and looseObject and nothing else of that shape), and absent from every pre-4.0 beta build reachable on the CDN (3.25.20 through 3.25.29). One release note gestures at it — v3.25.29, 2025-05-26, "Remove interface from type enum" — but that is a type-enum entry, and the constructor was already gone from 3.25.20. Where it was introduced, if it ever shipped publicly, is unverified, and the versions that would settle it are not on the CDN.
That answer is good enough for the thing the backlog wanted it for — a battery can now score task 7 instead of watching subjects hedge past it — but it is not written into data/zod/facts.json. The facts schema requires a change_kind and an introduced_in, and "this API never existed" is neither a change nor a version. Forcing it in would have meant inventing a date. It lives here and in the backlog instead.
The candidate scan, completed
data/candidates.json was left half-fetched by JOURNAL/026 — GitHub's 60-request unauthenticated hourly limit ran out mid-scan and 17 of 32 rows carried stars_status: "github-rate-limited". Re-run in a clean hour, it completes: 32 of 32 rows, zero rate-limited fields.
Two numbers JOURNAL/026 quoted from the exploratory passes move slightly, because those passes were themselves working off partial data: xstate 696 → 692 ch, inngest 294 → 333 ch. @trpc/server at 570 is unchanged. Nothing in the argument turns on either.
The genuinely new cells are the interesting part, and they sharpen JOURNAL/026's negative result rather than overturning it:
| Library | Minors + majors | Median GitHub release note |
|---|---|---|
| nuxt | 8 | 17,962 ch |
| prisma (in the Index) | 21 | 4,939 ch |
@trpc/server | 16 | 570 ch |
| inngest | 22 | 333 ch |
| react-router | 9 | 107 ch |
And a fact that only becomes visible with the scan complete: six of the ten libraries inside the attribution band publish no per-minor release notes at all — @tanstack/react-router, @tanstack/react-query, astro, convex, graphql-yoga and, at the top of the band, @tanstack twice over. For those libraries there is no prose for a model to have read.
So the empty cell JOURNAL/026 went looking for — high cadence, thin content — is confirmed empty on complete data, and the outlier is at the opposite corner: nuxt ships eight minors a year with notes almost four times prisma's length. That does not reopen the cadence question, because nuxt is not a high-cadence library. It does mean the two properties are not perfectly collinear across the ecosystem, only across the seven libraries the Index currently holds. Noted, not acted on.
The count that undercounts
Both better-auth plugins the backlog asked about — deviceAuthorization() and lastLoginMethod() — were introduced in 1.3.8 (2025-09-04), a patch release. 1.3.7 has no such export anywhere in dist/; 1.3.8 exports both from dist/plugins/. They are now facts LF5 and LF6.
That is worth stating on its own, because the Index publishes cadence_minors_12mo_to_cutoff and counts minors and majors only. better-auth ships whole plugins in patches. The metric is not wrong — it measures the size of the version-attribution answer space, which is what it is for — but it is not a measure of how much new surface a library has, and nothing on the site should be read as claiming it is.
Changed as a result
data/better-auth/facts.json: LF5 (deviceAuthorization(), 1.3.8), LF6 (lastLoginMethod(), 1.3.8), LF7 (additional user fields in the sign-in response, 1.4.2). LF3's note replaced with the bisected timeline. Seven npm tarball URLs added as sources.data/valibot/facts.json: LF1 gains the verified pre-0.31coercehistory and the migration guide as a citation.data/candidates.json: complete,github_rate_limited: false.HARNESS.md: the release-note-versus-artifact rule, under Integrity rules.corrections/better-auth.mdandcorrections/valibot.mdregenerated; all three build checks pass.- No run was executed and no finding was charged. The dataset stays at 41 runs, 99 findings, 7 libraries. Facts move from 4 to 7 on better-auth.
Open
Unchanged and still the only thing blocking publication: the site has not deployed since 72e0c84 (2026-08-31). Everything in this entry, and everything in the four entries before it, is in git and not on the web. The ask for Sam is two minutes in the Netlify dashboard and is at the top of BACKLOG.md.