diff --git a/source/components/editor-shell/editor-shell.css b/source/components/editor-shell/editor-shell.css index 52e8cf6..cedba32 100644 --- a/source/components/editor-shell/editor-shell.css +++ b/source/components/editor-shell/editor-shell.css @@ -5,7 +5,7 @@ editor-shell { overflow: hidden; background: #0f1117; color: #e2e4ed; - font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif; + font-family: Barlow, ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif; } .es-header { @@ -26,11 +26,15 @@ editor-shell { } .es-back:hover { color: #e2e4ed; } -.es-title { +.es-title +{ flex: 1; font-size: 0.9rem; - font-weight: 600; - color: #c8cbde; + font-weight: 900; + color: #fff; + font-style: italic; + letter-spacing: 0.05em; + text-transform: uppercase; } .es-portrait-btns { diff --git a/source/components/tab-container/tab-container.css b/source/components/tab-container/tab-container.css index 7269bf4..288b4e2 100644 --- a/source/components/tab-container/tab-container.css +++ b/source/components/tab-container/tab-container.css @@ -40,8 +40,8 @@ tab-container.tc-drop-target { color: #7b7f96; cursor: pointer; white-space: nowrap; - border-right: 1px solid #2a2d3a; user-select: none; + font-weight: 700; } .tc-tab:hover { color: #c8cbde; background: #1a1d27; } diff --git a/source/server/middleware/auth.ts b/source/server/middleware/auth.ts index 26f2698..989ae09 100644 --- a/source/server/middleware/auth.ts +++ b/source/server/middleware/auth.ts @@ -51,17 +51,29 @@ interface RefreshResult { } async function tryRefresh( refreshToken: string ): Promise { + const url = `${AUTH_INTERNAL_HOST}/api/auth/refresh`; + console.log( '[auth] tryRefresh →', url ); try { - const r = await fetch( `${AUTH_INTERNAL_HOST}/api/auth/refresh`, { + const r = await fetch( url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify( { refreshToken } ) } ); - if ( !r.ok ) return null; + console.log( '[auth] tryRefresh status:', r.status ); + if ( !r.ok ) { + const body = await r.text(); + console.log( '[auth] tryRefresh error body:', body ); + return null; + } const data = await r.json() as Partial; - if ( !data.accessToken || !data.refreshToken ) return null; + if ( !data.accessToken || !data.refreshToken ) { + console.log( '[auth] tryRefresh missing tokens in response:', Object.keys( data ) ); + return null; + } + console.log( '[auth] tryRefresh succeeded' ); return { accessToken: data.accessToken, refreshToken: data.refreshToken }; - } catch { + } catch ( err ) { + console.log( '[auth] tryRefresh fetch error:', err ); return null; } } @@ -84,11 +96,18 @@ export function jwtMiddleware( req: Request, res: Response, next: NextFunction ) } // API request with expired token — try transparent refresh via refreshToken cookie + console.log( '[auth] expired token on API route:', req.path ); const refreshToken = req.cookies?.refreshToken as string | undefined; - if ( !refreshToken ) { next(); return; } + if ( !refreshToken ) { + console.log( '[auth] no refreshToken cookie — cannot refresh' ); + next(); return; + } tryRefresh( refreshToken ).then( result => { - if ( !result ) { next(); return; } + if ( !result ) { + console.log( '[auth] refresh failed, returning 401 for:', req.path ); + next(); return; + } res.cookie( 'accessToken', result.accessToken, cookieOpts( 60 * 60 * 1000 ) ); res.cookie( 'refreshToken', result.refreshToken, cookieOpts( 30 * 24 * 60 * 60 * 1000 ) ); try {