ReviewOS

also looking at this

reviewos/reviewos.org

feat(reviews): the suggestions get an interface, priced as designed

#6
Merged glennmichael123 wants to merge feat/suggested-reviewers-panel into main
9 files +741 -10

Closes the phase-4 item "Show the suggestions somewhere". Stacks on #2 and #5 — it contains their commits because it edits the review page #2 restores and its e2e needs #5's component fix; merge those first and this rebases to just its own commit.

The conversation page's sidebar now offers a Suggested reviewers <details> panel, above Reviews — who should look, above who has looked. The <details> opens and closes with no script; the one script it carries notices the first open — and only the first — and fetches, so the git log behind the endpoint is spent when a reader asks and never at render (the design constraint the roadmap item states). Each of the ≤3 names links to the profile and carries its reason verbatim ("3 commits here, last 5d ago, 2 waiting on them"); score is not shown, and nothing submits anything — a suggestion, never a request. Gated to signed-in readers with pull:review on open pull requests; closed/no-JS states render an honest sentence server-side.

Getting the e2e to pass surfaced two real bugs:

  1. Views served through route.serve()'s file routing treat every reader as a stranger. That pipeline provides no __stxServeContext, only raw headers, and every view reads serveContext?.cookies — the "currentUser never looked at a cookie" lesson one layer up. cookieJarFromHeader (extracted from cookieUserId, which already had the parse privately) is now exported, and this page asks whichever pipeline answered. The same fallback is owed to every other view that reads serveContext?.cookies — happy to do that sweep as a follow-up.

  2. This feature's own first draft leaked the session cookie into the HTML. stx's client bridge seeds any identifier a client script shares with the server scope into the page as a var — and the server scope holds the request headers. Writing fetch(url, { headers: { Accept: ... } }) was enough to serialize var headers = {..., "cookie": "auth-token=<the reader's token>"} into the document. The fetch is now bare (the endpoint answers JSON without being asked), and the e2e asserts the token never appears in the page, whatever the next mechanism would be. The bridge's eagerness (an object-literal key matching a server binding) is worth an upstream stx look.

tests/e2e/suggested-reviewers-panel.test.ts (5 tests) pins what the in-process suggest-reviewers test cannot: the endpoint answering a fetch whose only credential is a cookie (every other caller in the suite holds a bearer), the rendered page carrying the panel and its URL but none of the answer (the deferred cost, asserted in markup), the panel absent for anonymous readers, and no credential in the document.

Also noted in the roadmap tick: the endpoint answers anonymous readers of public repositories despite its own doc comment about review-load visibility — the UI gate hides it, but the data is one curl away; flagged rather than changed here.

🤖 Generated with Claude Code

9 changed files on the files tab, with 0 review threads.