334 Commits (master)
 

Author SHA1 Message Date
oabrivard 3a59362acc docs: add tech lead assessment of test coverage and documentation 3 months ago
oabrivard 286dbbbcc8 test: add E2E infrastructure and 5 Playwright test flows
Add Playwright E2E testing setup with Docker Compose test environment,
database seed script, auth helpers, and five test scenarios covering
registration, admin providers, settings persistence, sources CRUD,
and settings export/import.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3 months ago
oabrivard 6f3ff1e9a2 docs: add JSDoc to all frontend API modules, pages, components, utilities
Add English JSDoc documentation to 32 source files across the frontend:
- API layer (8 files): client CSRF strategy, credential handling, 401 redirect,
  and endpoint-level docs for auth, settings, sources, syntheses, admin, config, apiKeys
- Pages (11 files): Settings export/import, GenerateSynthesis SSE state machine,
  Home delete confirmation timer, Sources bulk import parsing, SynthesisDetail
  email/export flows, Login/Register Turnstile lifecycle, AuthVerify token flow,
  admin Providers/RateLimits/Users
- Components (8 files): ApiKeyManager CRUD, Turnstile polling init, Navbar/MobileMenu
  route detection, Layout/AdminLayout structure, ErrorBoundary retry, Button variants,
  Toast auto-dismiss timer, LoadingSpinner props
- Utilities (2 files): SSE reconnection backoff, dates locale config
- Context (1 file): AuthContext session check, isAdmin derived signal

No logic changes. TypeScript and vitest pass unchanged.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3 months ago
oabrivard fa346dc346 test: add frontend page interaction tests (Home, Settings, Sources, Login, Register, Generate)
Add test-utils.tsx with renderWithProviders (MemoryRouter + I18n + Toast),
mockFetch, and mockFetchRoutes helpers. Create 39 interaction-level tests
across 6 page components covering rendering, form validation, API calls,
delete confirmation flows, SSE progress, and file import/export.

Also add Blob.text() polyfill in test setup for jsdom compatibility.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3 months ago
oabrivard a4e618feda test: add unit tests for auth middleware cookie extraction
Extract cookie parsing into a standalone `extract_session_token` function
and add 5 unit tests covering the valid, missing, multi-cookie, whitespace,
and empty-header cases.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
3 months ago
oabrivard 7b3fc717eb Add test coverage and documentation implementation plan
12 tasks: backend auth middleware tests, frontend test utilities,
5 page test suites (Home, Settings, Sources, Login/Register, Generate),
JSDoc for API layer + pages/components, E2E infrastructure + 5 Playwright flows.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3 months ago
oabrivard 449edfcf59 Add test coverage and documentation improvement spec
Addresses all 5 recommendations from tech lead assessment:
- Frontend page tests (~39 tests for Settings, Home, Sources, Login, Generate)
- Frontend JSDoc documentation (~30 files)
- Backend test gaps (schema builder, auth middleware, token utils)
- E2E tests with Playwright (5 flows against real Docker stack)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3 months ago
oabrivard 98528f51bd Fix rate limiter bug, simplify v2 code
Bug fix:
- Per-generation rate limiter was creating a new instance on every check,
  making user rate limit overrides non-functional. Fixed by creating the
  limiter once at pipeline start and reusing for both passes.

Simplifications:
- Extract spawn_task closure in scrape_articles (deduplicate spawn blocks)
- Use idiomatic if let Ok(...) instead of if let Some(..).ok() in scraper
- Replace manual loop with iterator chain in export_keys handler
- Simplify check_rate_limit to single boolean check
- Simplify handleImport settings merge (spread already provides defaults)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3 months ago
oabrivard 0f66c28c38 v2: empty sections fallback in email template
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
3 months ago
oabrivard 8c7672105c v2: empty sections fallback in synthesis detail view
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
3 months ago
oabrivard c698f6e4a3 v2: dual model selection, rate limit overrides, settings export/import
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3 months ago
oabrivard 7eb24cfd9a v2: API key export endpoint (POST, rate-limited)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
3 months ago
oabrivard 191e1c716b v2: enhanced scraper - title priority chain, broken link detection, noindex
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3 months ago
oabrivard 9b994e0528 v2: pipeline user model selection, rate limiter, URL filter, original title, null-safe sections
- resolve_provider_and_key() now respects user ai_provider preference
- Dual model resolution: ai_model for search pass, ai_model_writing for rewrite pass
- Per-generation rate limiter with user override support
- Homepage URL filter removes domain-only URLs after search pass
- ScrapedNewsItem gains original_title field populated from page <title>
- SynthesisResponse::try_from handles null sections gracefully (returns empty vec)
- Search prompt warns LLM against returning homepage URLs
- Rewrite prompt instructs LLM to use originalTitle with language preservation rules

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3 months ago
oabrivard ed6b41fe52 v2: add settings migration, model expansion, DB queries (provider, models, rate limits)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3 months ago
oabrivard 6b27a0f691 Add v2 changes implementation plan
10 tasks covering: migration, settings model expansion, DB queries,
pipeline updates (user model selection, rate limiter, URL filter),
prompts (deep-link, original title), scraper improvements, API key
export, frontend (dual models, rate limits, export/import), and
empty sections fallback.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3 months ago
oabrivard 74e2cb0273 Add v2 changes design spec
8 changes covering: settings export/import, dual model selection,
user rate limit overrides, original title preservation, enhanced
broken link detection, deep-link URL enforcement, settings schema
expansion, and empty sections fallback message.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3 months ago
oabrivard 62c2d959d3 Modified Claude settings 3 months ago
oabrivard 04819aa926 Simplify code: deduplicate patterns, fix captcha field name bug
Bug fix:
- Fix frontend sending captcha_token instead of turnstile_token in
  login/register requests (would cause 422 errors on auth)

Backend simplifications:
- Deduplicate VALID_PROVIDERS constant (provider.rs is now the single source)
- Extract validate_display_name/validate_models helpers in provider model
- Add From<UserSettings> for SettingsResponse, From<User> for AdminUserResponse
- Consolidate Resend API call pattern into shared send_via_resend()
- Extract do_bulk_import() for sources bulk/CSV import
- Use idiomatic range.contains() for rate limit validation

Frontend simplifications:
- Consolidate file download logic (exportCsv reuses shared fetchFile/triggerDownload)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3 months ago
oabrivard 8dc4900c47 Remove legacy React/Firebase files, update project metadata
- Delete original src/ directory (React components, Firebase, Gemini service)
- Delete root package.json, package-lock.json, node_modules/
- Delete vite.config.ts, tsconfig.json, index.html (old React config)
- Delete firebase-applet-config.json, firebase-blueprint.json, firestore.rules
- Delete metadata.json, README.md
- Update .gitignore for new project structure (backend/target, frontend/dist)
- Rewrite CLAUDE.md to document the new Rust/SolidJS/Postgres architecture

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3 months ago
oabrivard 1f9f7f39d7 Phase 7: Email sending via Resend + Markdown/PDF export
Backend:
- Synthesis email sending via Resend API with HTML template (inline CSS,
  tables-based for email client compatibility) + plain-text fallback
- XSS prevention via html_escape() on all user content in email templates
- Markdown export: clean format with headers, links, summaries
- PDF export: printpdf with built-in Helvetica fonts, indigo color scheme,
  automatic page breaks, word wrapping
- 3 new endpoints: send-email, export/markdown, export/pdf
- All endpoints enforce ownership checks
- Email validation using email_address crate
- 24 new unit tests, 13 integration tests

Frontend:
- Email section on SynthesisDetail: input pre-filled with user email,
  send button with loading state, success/error feedback
- Export buttons: Markdown + PDF with per-button loading states
- File download via Blob + temporary anchor with Content-Disposition parsing
- 6 new export tests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3 months ago
oabrivard 631bd43b9f Phase 6: Multi-provider support with OpenAI and Anthropic
Backend:
- OpenAiProvider: Responses API with web_search_preview (pass 1),
  Chat Completions with json_schema structured output (pass 2)
- AnthropicProvider: Messages API with web_search tool (pass 1),
  schema-in-prompt for structured output, code fence stripping (pass 2)
- Pipeline adaptation: skip scrape+rewrite when >70% of search URLs are valid
- Provider factory updated for all three providers
- Error sanitization extended for Anthropic key patterns (sk-ant-)
- 44 new unit tests (OpenAI, Anthropic, factory, pipeline heuristic)

Frontend:
- Provider-specific info text below model selection
- Web search support badges (green/gray)
- Generate page shows selected provider and model
- Warning banner when provider lacks web search
- Provider utility module with 10 tests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3 months ago
oabrivard aa6f1ba76b Phase 5: Generation pipeline with SSE progress, syntheses CRUD
Backend:
- Full 2-pass generation pipeline: LLM search -> URL scraping -> LLM rewrite
- Async generation with tokio::spawn, JobStore with per-user concurrency limit
- SSE progress streaming via axum::response::Sse + tokio::sync::watch
- Syntheses CRUD: list (paginated), get (ownership check), delete
- Prompt construction ported from original geminiService.ts
- Parallel URL scraping with bounded concurrency (max 10)
- Graceful partial failure handling (some URLs fail -> continue)
- 36 new unit tests, 16 integration tests

Frontend:
- Home dashboard: synthesis card grid, week badges, delete with confirmation
- Generate page: SSE-driven progress bar, step checklist, auto-redirect
- Synthesis detail: section-by-section display, external links, delete
- SSE client helper with auto-reconnect (exponential backoff)
- Date utilities with French locale formatting

Critical fixes applied:
- SSE EventSource now sends credentials (withCredentials: true)
- Gemini error logging sanitized to prevent API key leak in logs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3 months ago
oabrivard 439e547367 Phase 4: LLM provider abstraction with Gemini, user API key encryption
Backend:
- LlmProvider async trait with generate_search_pass/generate_rewrite_pass
- GeminiProvider: googleSearch grounding (pass 1), structured JSON output (pass 2)
- AES-256-GCM encryption for user API keys at rest (per-key random nonces)
- MasterKey with zeroize-on-drop (no Clone to prevent unzeroized copies)
- User API key endpoints: list (prefix only), create/update, delete, test
- Dynamic category schema builder for structured LLM output
- Provider factory (Gemini implemented, OpenAI/Anthropic stubbed for Phase 6)
- 37 new unit tests (encryption, schema, Gemini serialization, factory)
- 17 integration tests (CRUD, encryption verification, ownership isolation)

Frontend:
- ApiKeyManager component: per-provider key management in Settings
- Password input with show/hide toggle, key prefix display (monospace)
- Test button validates key with minimal LLM call
- Status badges (configured/not configured)
- 11 new tests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3 months ago
oabrivard 5abbf9b9ad Phase 3: Admin module with provider/model curation, rate limits, user management
Backend:
- Admin API: CRUD for providers, rate limits, user role management
- Public config endpoint for enabled providers/models
- AdminUser extractor enforces RBAC on all admin endpoints
- Per-provider rate limiter with hot-reload from DB
- Audit logging for all admin mutations
- Seed data: Gemini, OpenAI, Anthropic providers with default models
- Self-demotion prevention on role changes
- 30 integration tests, 27 new unit tests

Frontend:
- Admin layout with sidebar navigation (providers, rate limits, users)
- Provider management: enable/disable, model CRUD, default model selection
- Rate limit configuration with effective rate display
- User management with role badges and promote/demote
- Admin link in navbar/mobile menu (visible only to admins)
- Settings page: dynamic provider/model selection from admin config
- 10 new tests (admin guard, config API)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3 months ago
oabrivard 22ff026a4c Fix Phase 2 critical issues: SSRF IPv6 gaps, body text filtering, CSV validation
- Fix body text extraction to actually filter excluded elements (script,
  nav, footer, aside, etc.) using node ID tracking instead of unused HashSet
- Add IPv6 reserved range checks to SSRF prevention: ULA (fc00::/7),
  documentation (2001:db8::/32), discard prefix (100::/64)
- Add errors field to frontend BulkImportResponse type
- Validate Content-Type on CSV multipart upload (reject non-text files)
- Add 6 new unit tests for the fixes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3 months ago
oabrivard 2b75dc7049 Finished phase 2 3 months ago
oabrivard a36e3732bf Fixed critical problems from phase 1 3 months ago
oabrivard 355dbf6a5a Finished phase 1 3 months ago
oabrivard 7ae6ef7ef1 Defined implementation plan 3 months ago
oabrivard 8d8cce1f05 Answered Claude questions to guide code migration 3 months ago
oabrivard e7e2f8fa90 Code analysis and migration recommendations 3 months ago
oabrivard 2a10f95b22 Updated Claude code config 3 months ago
oabrivard 2e315f21c3 Initial commit 3 months ago