feat: thread authenticated user id through chat, feedback, and ADK#51
feat: thread authenticated user id through chat, feedback, and ADK#51nonumpa wants to merge 3 commits intofeature/bff-authfrom
Conversation
Replace the hardcoded 'anonymous' ADK user id with a server-side resolver that reads the cofacts session cookie and dispatches GetCurrentUser. Server functions and the run-sse proxy now reject unauthenticated callers with 401 and forward the real user id to ADK so per-user session lists work correctly.
Attach the current user's Cofacts id to every thumbs-up/down score through ScoreBody.metadata so we can attribute or filter feedback by the user who gave it. Falls back to null for anonymous viewers since the score API has no first-class userId field.
Replace the chat input with a login CTA when no user is signed in, both on the landing page and inside an existing session. Pairs with the server-side 401 enforcement so the UI no longer offers an interaction the backend would reject.
There was a problem hiding this comment.
Code Review
This pull request implements user authentication by replacing the hardcoded anonymous user ID with dynamic session-based resolution. It introduces a new LoginPrompt component and updates the ChatArea and landing page to conditionally render inputs based on the user's login status. Additionally, server-side functions and feedback metadata now include the authenticated user's ID. A review comment identifies a discrepancy in src/server/adkUser.ts where the code throws a custom error instead of a Response object, which may prevent TanStack Start from correctly propagating a 401 status code to the client.
| // cookie (via cofactsExec) and dispatches GetCurrentUser. Throws a 401-shaped | ||
| // Response when no authenticated user is present so callers can let the | ||
| // framework propagate it back to the browser. |
There was a problem hiding this comment.
The comment states that this helper throws a "401-shaped Response", but the implementation on lines 19-21 throws a custom UnauthorizedError object.
In TanStack Start, throwing a standard Error in a createServerFn (like those in chatSessions.functions.ts) typically results in a 500 Internal Server Error on the client side. To allow the framework to propagate a specific HTTP status code (like 401) automatically to the browser, you should throw a Response object instead.
If you prefer using the custom error class for manual handling (as seen in run-sse.ts), please update the comment to reflect that an Error is thrown rather than a Response.
Implements #47 on top of #25.
Summary
'anonymous', so per-user side panels and session lists work.metadata.userId, sinceScoreBodyhas no first-classuserIdfield).Changes
src/server/adkUser.ts: newresolveAdkUserIdOrThrow()reads thecofacts_sessioncookie viacofactsExec, returnsuser.id, throwsUnauthorizedErrorwhen unauthenticated.src/lib/chatSessions.functions.ts,src/routes/api/run-sse.ts: drop the hardcodedADK_USER_ID, resolve per-request. The SSE proxy returns 401 JSON on unauthenticated callers.src/components/FeedbackButtons.tsx: passmetadata: { userId }to all threelangfuse.score()calls.src/components/LoginPrompt.tsx(new): shared login CTA shown in place ofChatInput.src/components/ChatArea.tsx,src/routes/_app/index.tsx: gate chat input behinduseAuth().user.Verification
tsc --noEmit: cleaneslinton changed files: clean (one pre-existing warning inchatSessions.functions.ts:26left untouched)vitest run: 47/47 passvite build: successNotes
feature/bff-auth). Will rebase ontomasteronce feat(auth): BFF auth with HttpOnly cookie + SSR #25 lands.