Commit 4d7c564
fix(plugin-auth): the better-auth-native /admin/ routes refuse an anonymous caller with the ADR-0112 envelope (#10800)
* fix(plugin-auth): envelope the better-auth-native /admin/ refusals (#10349)
The `/api/v1/auth/admin/` namespace answered the same question in two shapes.
ObjectStack's raw mounts refuse an anonymous caller with the ADR-0112 envelope
and `code: 'UNAUTHENTICATED'` (`platform-admin-gate.ts`); the routes better-auth
serves itself refuse through the vendor's `adminMiddleware`
(`APIError.fromStatus('UNAUTHORIZED')`, no body argument), which reaches the
client as a 401 announcing `application/json` and carrying the EMPTY STRING.
Measured on better-auth 1.7.1 through `AuthManager.handleRequest`, anonymous:
ten vendor-lane routes answered `401 ct=application/json len=0 body=""`.
`handleRequest` now gives those refusals the declared envelope at the one seam
every vendor route passes through, with the code DERIVED from the status by
ADR-0112's own `standardErrorCodeForHttpStatus` map — no new error code, no
literal to drift. Statuses and admission are unchanged.
Scope is the `/admin/` namespace (option C, not option B). The prefix test costs
no new concept: `handleRequest` already discriminates on `betterAuthEndpointPath`
twice, for `STOP_IMPERSONATING_PATH` and `SESSION_ERASURE_PATHS`.
Three narrowings, each pinned: a refusal that already carried a body keeps it
byte-for-byte; only 401/403 are named (a bodyless `/admin/oauth2/*` 404 and any
semantic 4xx the vendor owns stay as they are); nothing outside `/admin/` is
touched.
The dogfood sweep's `better-auth-gate` bucket tightens from
`[401, 403].includes(anon.status)` to the full ADR-0112 pin — status AND code —
which is the fix's own falsifiable assertion. That bucket documented this gap
instead of closing it, and nothing tracked closing it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PnJHU45vPJj5UQrxe946Bx
* test(dogfood): record the #10792 member-arm exception the tightened bucket exposed
The `better-auth-gate` bucket's member-arm vocabulary check was guarded by
`if (member.code !== undefined)`, and on every bodyless refusal the code WAS
undefined — so for those routes the check had never executed. Giving the vendor
lane an envelope made it executable, and it went red on the first run:
`/admin/remove-user` answers a SIGNED-IN member `401 UNAUTHENTICATED`, while
`set-role` and `update-user` answer the same bearer `403 YOU_ARE_NOT_ALLOWED_*`.
Measured on the booted showcase stack and controlled hermetically: the same
three fires against the in-memory engine give the member 403, both with no
`transaction` on the engine and with a pass-through one. So it is the real
erasure transaction (#7724, `SESSION_ERASURE_PATHS`) that the session re-read
inside `adminMiddleware` does not survive. Filed as #10792.
Recorded here as an ADDITIONAL accepted code for that one route, never as a
pin — the same reasoning the platform-admin arm below already carries. Pinning
today's 401 would turn the fix red, pinning the 403 is red today, and widening
the vocabulary for every route would let the next one drift in silence.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PnJHU45vPJj5UQrxe946Bx
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>1 parent c5d0c2f commit 4d7c564
7 files changed
Lines changed: 590 additions & 18 deletions
File tree
- .changeset
- packages
- plugins/plugin-auth/src
- qa/dogfood/test
| 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 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
Lines changed: 17 additions & 9 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
243 | 243 | | |
244 | 244 | | |
245 | 245 | | |
246 | | - | |
247 | | - | |
248 | | - | |
249 | | - | |
250 | | - | |
251 | | - | |
252 | | - | |
253 | | - | |
254 | | - | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
255 | 263 | | |
256 | 264 | | |
257 | 265 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
| 33 | + | |
33 | 34 | | |
34 | 35 | | |
35 | 36 | | |
| |||
3680 | 3681 | | |
3681 | 3682 | | |
3682 | 3683 | | |
3683 | | - | |
| 3684 | + | |
3684 | 3685 | | |
3685 | 3686 | | |
3686 | 3687 | | |
3687 | 3688 | | |
| 3689 | + | |
| 3690 | + | |
| 3691 | + | |
| 3692 | + | |
| 3693 | + | |
| 3694 | + | |
| 3695 | + | |
| 3696 | + | |
| 3697 | + | |
| 3698 | + | |
| 3699 | + | |
| 3700 | + | |
| 3701 | + | |
| 3702 | + | |
| 3703 | + | |
| 3704 | + | |
| 3705 | + | |
| 3706 | + | |
| 3707 | + | |
| 3708 | + | |
3688 | 3709 | | |
3689 | 3710 | | |
3690 | 3711 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
40 | 40 | | |
41 | 41 | | |
42 | 42 | | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
43 | 58 | | |
44 | 59 | | |
45 | 60 | | |
| |||
82 | 97 | | |
83 | 98 | | |
84 | 99 | | |
85 | | - | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
86 | 104 | | |
87 | 105 | | |
88 | 106 | | |
| |||
92 | 110 | | |
93 | 111 | | |
94 | 112 | | |
95 | | - | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
96 | 117 | | |
97 | 118 | | |
98 | 119 | | |
| |||
0 commit comments