Gadoes makes legal sources a thing you can actually pick

The fork turns a backend catalogue of legal data sources into a real product surface - users connect them, pick them, and scope them per question.

searchchat-ui

Gadoes has built out the user-facing layer around connecting to outside legal data sources. There's a settings page where people browse sources by region, toggle them on, and paste in their own API keys for services like CourtListener and GovInfo. Those keys are encrypted at rest, with a fallback path so self-hosters can supply a shared key via environment instead of forcing every user to bring their own.

The more interesting move is in the chat itself. A sources pill sits next to the input, opening a picker where users can narrow a single question to a specific set of sources - and choose whether that scope sticks for the conversation or resets after one message. It's a small UI decision that maps neatly to how lawyers actually research: sometimes you want everything, sometimes you want only the Ninth Circuit.

So what Worth a look for anyone building legal-AI products who's wrestled with how to expose a growing catalogue of sources without burying users in toggles.

View this fork on GitHub →

Spotted something wrong? Or know the PR text has fresher detail than the writeup above?

Commits in this thread

6 commits from Gadoes/dispumike, oldest first. Source extracted verbatim from the harvested git log.

SHA Subject Author Date
da870cef Chunk 6: Source Connections DB + User Settings UX + Key Encryption Gadoes 2026-05-02 ↗ GitHub
commit body
- Add migrations: mcp_servers (seed data for 12 sources), mcp_connections,
  user_profiles column additions (courtlistener_api_key, govinfo_api_key, is_admin)
- Implement AES-256-GCM encryption in backend/src/lib/mcp/encryption.ts
  (encryptApiKey / decryptApiKey, key from MCP_KEY_ENCRYPTION_KEY env var)
- Add REST API: GET/POST/DELETE /user/mcp-connections with key encryption on write
- Extend getUserApiKeys() and add getMcpApiKey() with env fallback pattern
- Add UserApiKeys.courtlistener and .govinfo fields to llm types
- Create LegalSourcesPage frontend settings page (grouped by region, toggle +
  API key input per server, tier-based 'coming soon' badge)
- Add 'Legal Sources' tab to account settings layout
- 13 backend unit tests (encryption round-trip, format, edge cases)
- 13 frontend component tests all passing; tsc --noEmit clean

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
bb72208c Merge chunk-6-source-connections into main Gadoes 2026-05-02 ↗ GitHub
488ea9b4 Chunk 7: Source Picker Popover UI Gadoes 2026-05-02 ↗ GitHub
commit body
- Create SourcePickerPopover component with search, region grouping, state
  badges (Always on / Connected / Connect / Permission required), region_glyph
  display, and checkbox hooks for Chunk 8 scope toggling
- Create SourcesPill component showing 'Sources · N active' in chat toolbar
- Integrate SourcesPill + SourcePickerPopover into ChatInput.tsx
- Closes on outside click and Escape key
- Footer 'Add custom MCP server' placeholder (disabled for v1)
- 16 component tests covering popover open/close, region order, search
  filtering, state badges, region_glyph, and checkbox callbacks
- tsc --noEmit passes; all 51 frontend tests pass

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
c8e13dac Merge chunk-7-source-picker into main Gadoes 2026-05-02 ↗ GitHub
64ec30ab Chunk 8: Per-Query Scope Toggling Gadoes 2026-05-02 ↗ GitHub
commit body
Backend:
- Add mcpScope?: string[] | null to POST /chat and POST /projects/:projectId/chat
- Pass mcpScope to runLLMStream(); filter MCP server tools when scope is set
  (scopeSet filter applied after open-circuit filter, empty array = no filter)

Frontend:
- Create useScopeState hook: activeSources, scopeMode (per-message/sticky),
  toggleSource, clearScope, afterSend, mcpScopePayload
- Add mcpScope? field to streamChat() and streamProjectChat()
- Create ScopeIndicator component: 'Scope: N sources for this thread' + Clear

Tests:
- 7 backend unit tests: mcpScope filtering, open-circuit interaction
- 12 frontend unit tests: useScopeState hook (toggle, sticky/per-message modes,
  clearScope, afterSend, mcpScopePayload computation)
- All 57 backend tests and 63 frontend tests passing
- tsc --noEmit clean

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
e1df3784 Merge chunk-8-scope-toggling into main Gadoes 2026-05-02 ↗ GitHub

Capture this thread into my fork

Download a single Markdown prompt that tells Claude how to port every commit above into your working tree — adapting paths and structure to match your repo. Run it via claude -p < capture-thread-30.md from inside the repo you want the changes in.

⬇ Download capture-thread-30.md