@byline/host-tanstack-start 2.3.1 → 2.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -20,7 +20,7 @@ async function getAdminRequestContext() {
|
|
|
20
20
|
} catch {}
|
|
21
21
|
const refreshToken = readRefreshTokenCookie();
|
|
22
22
|
if (!refreshToken) {
|
|
23
|
-
clearSessionCookies();
|
|
23
|
+
if (accessToken) clearSessionCookies();
|
|
24
24
|
throw ERR_UNAUTHENTICATED({
|
|
25
25
|
message: 'no admin session'
|
|
26
26
|
});
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"private": false,
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MPL-2.0",
|
|
6
|
-
"version": "2.3.
|
|
6
|
+
"version": "2.3.2",
|
|
7
7
|
"engines": {
|
|
8
8
|
"node": ">=20.9.0"
|
|
9
9
|
},
|
|
@@ -107,12 +107,12 @@
|
|
|
107
107
|
"react-swipeable": "^7.0.2",
|
|
108
108
|
"uuid": "^14.0.0",
|
|
109
109
|
"zod": "^4.4.3",
|
|
110
|
-
"@byline/
|
|
111
|
-
"@byline/
|
|
112
|
-
"@byline/core": "2.3.
|
|
113
|
-
"@byline/
|
|
114
|
-
"@byline/
|
|
115
|
-
"@byline/ui": "2.3.
|
|
110
|
+
"@byline/auth": "2.3.2",
|
|
111
|
+
"@byline/admin": "2.3.2",
|
|
112
|
+
"@byline/core": "2.3.2",
|
|
113
|
+
"@byline/client": "2.3.2",
|
|
114
|
+
"@byline/ai": "2.3.2",
|
|
115
|
+
"@byline/ui": "2.3.2"
|
|
116
116
|
},
|
|
117
117
|
"peerDependencies": {
|
|
118
118
|
"@tanstack/react-router": "^1.167.0",
|
|
@@ -137,7 +137,7 @@ describe('getAdminRequestContext', () => {
|
|
|
137
137
|
expect(verifyAccessToken).toHaveBeenCalledWith('fresh-access')
|
|
138
138
|
})
|
|
139
139
|
|
|
140
|
-
it('throws ERR_UNAUTHENTICATED
|
|
140
|
+
it('throws ERR_UNAUTHENTICATED without emitting Set-Cookie when no cookies are sent', async () => {
|
|
141
141
|
cookiesReturn({})
|
|
142
142
|
|
|
143
143
|
try {
|
|
@@ -147,7 +147,22 @@ describe('getAdminRequestContext', () => {
|
|
|
147
147
|
expect(err).toBeInstanceOf(AuthError)
|
|
148
148
|
expect((err as AuthError).code).toBe(AuthErrorCodes.UNAUTHENTICATED)
|
|
149
149
|
}
|
|
150
|
-
//
|
|
150
|
+
// Anonymous visitors must produce zero Set-Cookie headers so shared
|
|
151
|
+
// caches (Cloudflare) can cache public pages — a Set-Cookie on the
|
|
152
|
+
// response is a hard bypass signal for CDNs.
|
|
153
|
+
expect(setCookie).not.toHaveBeenCalled()
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
it('clears the stale access cookie when only an access token was sent', async () => {
|
|
157
|
+
cookiesReturn({ byline_access_token: 'stale' })
|
|
158
|
+
verifyAccessToken.mockRejectedValueOnce(new Error('expired'))
|
|
159
|
+
|
|
160
|
+
try {
|
|
161
|
+
await getAdminRequestContext()
|
|
162
|
+
expect.fail('expected ERR_UNAUTHENTICATED')
|
|
163
|
+
} catch (err) {
|
|
164
|
+
expect((err as AuthError).code).toBe(AuthErrorCodes.UNAUTHENTICATED)
|
|
165
|
+
}
|
|
151
166
|
const clears = setCookie.mock.calls.filter((c) => c[2]?.maxAge === 0)
|
|
152
167
|
const clearedNames = new Set(clears.map((c) => c[0]))
|
|
153
168
|
expect(clearedNames.has('byline_access_token')).toBe(true)
|
package/src/auth/auth-context.ts
CHANGED
|
@@ -80,8 +80,13 @@ export async function getAdminRequestContext(): Promise<RequestContext> {
|
|
|
80
80
|
// Refresh path: swap the refresh cookie for a fresh token pair.
|
|
81
81
|
const refreshToken = readRefreshTokenCookie()
|
|
82
82
|
if (!refreshToken) {
|
|
83
|
-
//
|
|
84
|
-
|
|
83
|
+
// Only emit cookie clears when the browser actually sent a stale access
|
|
84
|
+
// cookie — otherwise the response carries no Set-Cookie at all, which
|
|
85
|
+
// lets shared caches (Cloudflare) cache public pages for anonymous
|
|
86
|
+
// visitors. Set-Cookie on the response is a hard bypass signal for CDNs.
|
|
87
|
+
if (accessToken) {
|
|
88
|
+
clearSessionCookies()
|
|
89
|
+
}
|
|
85
90
|
throw ERR_UNAUTHENTICATED({ message: 'no admin session' })
|
|
86
91
|
}
|
|
87
92
|
|