Skip to content

feat: thread authenticated user id through chat, feedback, and ADK#51

Draft
nonumpa wants to merge 3 commits intofeature/bff-authfrom
feature/issue-47-user-id
Draft

feat: thread authenticated user id through chat, feedback, and ADK#51
nonumpa wants to merge 3 commits intofeature/bff-authfrom
feature/issue-47-user-id

Conversation

@nonumpa
Copy link
Copy Markdown
Member

@nonumpa nonumpa commented May 9, 2026

Implements #47 on top of #25.

Summary

  • ADK endpoints now receive the real Cofacts user id instead of 'anonymous', so per-user side panels and session lists work.
  • Langfuse feedback scores are tagged with the user id (via metadata.userId, since ScoreBody has no first-class userId field).
  • The chat input is replaced with a login CTA when no user is signed in, on both the landing page and inside an existing session.

Changes

  • src/server/adkUser.ts: new resolveAdkUserIdOrThrow() reads the cofacts_session cookie via cofactsExec, returns user.id, throws UnauthorizedError when unauthenticated.
  • src/lib/chatSessions.functions.ts, src/routes/api/run-sse.ts: drop the hardcoded ADK_USER_ID, resolve per-request. The SSE proxy returns 401 JSON on unauthenticated callers.
  • src/components/FeedbackButtons.tsx: pass metadata: { userId } to all three langfuse.score() calls.
  • src/components/LoginPrompt.tsx (new): shared login CTA shown in place of ChatInput.
  • src/components/ChatArea.tsx, src/routes/_app/index.tsx: gate chat input behind useAuth().user.

Verification

  • tsc --noEmit: clean
  • eslint on changed files: clean (one pre-existing warning in chatSessions.functions.ts:26 left untouched)
  • vitest run: 47/47 pass
  • vite build: success

Notes

nonumpa added 3 commits May 9, 2026 03:46
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.
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread src/server/adkUser.ts
Comment on lines +3 to +5
// 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.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant