From 8d8cce1f05beca2c1db970081a3f648ad4bfc670 Mon Sep 17 00:00:00 2001 From: oabrivard Date: Sat, 21 Mar 2026 15:46:17 +0100 Subject: [PATCH] Answered Claude questions to guide code migration --- .claude/settings.local.json | 5 +- docs/team-analysis/05-decisions.md | 95 ++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 docs/team-analysis/05-decisions.md diff --git a/.claude/settings.local.json b/.claude/settings.local.json index d64938b..c9b004f 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -5,7 +5,10 @@ "permissions": { "allow": [ "Skill(update-config)", - "Bash(jq:*)" + "Bash(jq:*)", + "WebSearch", + "WebFetch(domain:mcaptcha.org)", + "WebFetch(domain:github.com)" ] } } diff --git a/docs/team-analysis/05-decisions.md b/docs/team-analysis/05-decisions.md new file mode 100644 index 0000000..d950539 --- /dev/null +++ b/docs/team-analysis/05-decisions.md @@ -0,0 +1,95 @@ +# Project Decisions: AI Weekly Synth Rewrite + +**Date**: 2026-03-21 +**Decided by**: Project Owner +**Context**: Answers to the 30 consolidated open questions from the team analysis. + +--- + +## Scope + +| # | Decision | +|---|---| +| Q-SCOPE-1 | **Complete rewrite**, not a refactoring. Acknowledged that zero lines of current code survive. | +| Q-SCOPE-2 | **Phased approach** — each phase delivers a working app independently. | +| Q-SCOPE-3 | **All three LLM providers from day one** (Gemini, OpenAI, Anthropic). | +| Q-SCOPE-4 | **Testing is part of the plan** (unit, integration, API tests). | +| Q-ARCH-6 | **Open-ended timeline** — no hard deadline, "when it's done". | +| Q-ARCH-2 | **Rust is a learning goal** — must be idiomatic Rust. This is a deliberate choice, not driven purely by technical needs. The slower dev speed is an accepted trade-off. | + +## Architecture + +| # | Decision | +|---|---| +| Q-ARCH-1 | **Postgres from day one**. Many users expected. SQLite dropped entirely — no dual-target complexity. | +| Q-ARCH-3 | **Docker only**. Bare-metal deployment is not supported. | +| Q-ARCH-4 | **Fresh start** — no data migration from Firestore. No migration tooling needed. | +| Q-ARCH-5 | **No legacy data** — clean `sections[]` format only. No `majorAnnouncements`, `financialSector`, etc. | +| Q-ARCH-7 | **Asynchronous generation** with SSE progress streaming (per UX Specialist recommendations). User can navigate away and come back. | + +## Authentication + +| # | Decision | +|---|---| +| Q-AUTH-1 | **Google SSO dropped entirely**. Email + magic link only. | +| Q-AUTH-2 | N/A — fresh start, no existing users to migrate. | +| Q-AUTH-3 | **CLI command at deployment** to create the first admin account (`./ai-synth create-admin admin@example.com`). | +| Q-AUTH-4 | **Open registration** with captcha to prevent mass signups. | +| Q-AUTH-5 | **30-day session duration**. | + +## UX + +| # | Decision | +|---|---| +| Q-UX-1 | **SSE for real-time updates** (replacing Firestore `onSnapshot`). | +| Q-UX-2 | **Structure code for future i18n** but keep French-only for now. | +| Q-UX-3 | **Single-tenant self-hosted** — deployer is admin. One instance per deployment. | +| Q-UX-4 | **Users bring their own API keys** and select their provider/model from a list prepopulated by the admin. Admin curates available providers/models, users provide their own keys. | +| Q-UX-5 | **Backend SMTP via Resend** for email sending + **file export (PDF/Markdown)**. Both features. | + +## Security + +| # | Decision | +|---|---| +| Q-SEC-1 | **No shared syntheses** — strict per-user isolation. Future: users will be able to configure a list of email recipients to receive their syntheses. | +| Q-SEC-2 | **Environment variable** for the master encryption key (for encrypting user API keys at rest). No KMS. | +| Q-SEC-3 | **Admin sets global rate limits per provider as defaults**. Users can override (raise or lower) the limit for their own keys. | +| Q-SEC-4 | **Resend** (external transactional email service). No self-hosted SMTP. | +| Q-SEC-5 | **Minimize external dependencies** when possible and not too complex. Resend is the accepted external service. | +| Q-SEC-6 | **Owner operates in production**. Code will be open for others to self-host — good documentation and sensible defaults required. | +| Q-SEC-7 | Covered by Q-SEC-2 — environment variable for master encryption key. | + +## LLM Providers + +| # | Decision | +|---|---| +| Q-LLM-1 | **Hybrid approach** — use native web search grounding when available (Gemini googleSearch, OpenAI browsing, Anthropic web search), fall back to backend-side scraping when not. | +| Q-LLM-2 | **Pipeline adapts per provider** — the 2-pass pipeline can be simplified for providers where native grounding already produces high-quality results. Skip scrape/rewrite when unnecessary. | +| Q-LLM-3 | **One unified abstraction** (trait) over different capabilities, with per-provider behavior differences handled internally. | +| Q-LLM-4 | **Confirmed** — email sent by the system via Resend, not from user's Gmail. | + +## Key Tensions Resolved + +| Tension | Decision | +|---|---| +| CSRF strategy | **Architect's approach**: `X-Requested-With` custom header + `SameSite=Lax` cookies. Simpler, sufficient. | +| Captcha provider | **Cloudflare Turnstile** (external SaaS, good UX). | + +--- + +## Summary of Key Architectural Choices + +- **Backend**: Rust (Axum), idiomatic — learning goal +- **Database**: Postgres (via sqlx, no SQLite) +- **Frontend**: SolidJS with Tailwind CSS +- **Auth**: Email + magic link, session cookies (30 days), Cloudflare Turnstile captcha +- **LLM**: Unified trait, 3 providers (Gemini/OpenAI/Anthropic), user-provided API keys, admin-curated model list +- **Generation**: Async with SSE progress, adaptive pipeline per provider +- **Email**: Resend (transactional), system-sent +- **Export**: PDF + Markdown +- **Deployment**: Docker only, single-tenant, Postgres in compose +- **Admin**: CLI-created first admin, open registration with captcha +- **Real-time**: SSE +- **i18n**: Structured for future, French-only for now +- **Testing**: Part of the plan +- **Approach**: Phased delivery, each phase independently valuable