# 01 — Architecture Review (current state) Phase 1 deliverable: a grounded assessment of InboxIntel as it exists today, from the source. This is the baseline the redesign builds on. ## Architecture **Clean Architecture, .NET 8** — strict dependency rule `Api → Infrastructure → Application → Domain`. | Layer | Responsibility | Key contents | |-------|----------------|--------------| | **Domain** | Entities + enums, no external deps | `Email`, `Sender`, `Domain`, `MailThread`, `Label`/`EmailLabel`, `Attachment`; `EmailCategory` | | **Application** | Interfaces, DTOs, validation, parsing | `ISearchService` et al., `GmailQueryParser`, FluentValidation | | **Infrastructure** | EF Core/Npgsql, integrations, workers | `SearchService`, `CleanupService`, `AnalyticsService`, `HeuristicClassifier`, **AI providers**, exports, `GmailSyncWorker`, `DigestWorker` | | **Api** | ASP.NET Core Web API | Thin controllers, DI, Serilog, OAuth | | **Frontend** | React 18 + Vite SPA | Chart.js, react-grid-layout (draggable dashboard), Tailwind | - **Data:** PostgreSQL (EF Core + Npgsql). `Email` designed for 100k+ rows/user; a **generated `tsvector`** column backs full-text search. - **Background:** hosted workers — `GmailSyncWorker` (scheduled sync), `DigestWorker` (digest). - **AI seam (already present):** `IAiProvider` with `NullAiProvider` (disabled), `OllamaProvider` (local `/api/chat`), `OpenAiProvider` (cloud). Contract today is a single `CompleteAsync(systemPrompt, userPrompt)`. - **Security:** Google OAuth2 (read-only Gmail), cookie session + JWT, refresh tokens encrypted via Data Protection API, **IDOR-safe global query filters**, SSRF egress guard, non-root containers, destructive actions require `Confirmed` + server preview. - **Delivery:** Docker Compose (Postgres/API/frontend/optional nginx) + Gitea CI/CD. ## Feature set Gmail connect + sync → Postgres · analytics dashboard (draggable widgets) · advanced search (Gmail operators + FTS) · safe bulk cleanup · unsubscribe management (List-Unsubscribe / one-click) · heuristic categorisation (smart folders) · exports (PDF/CSV/JSON) · optional **advisory** AI · sender/domain aggregation. ## Existing search implementation (flagship) 1. **`GmailQueryParser`** (Application) parses `from: to: domain: after: before: is:unread|read has:attachment`; remaining text → free-text. 2. **`SearchService`** (Infrastructure) composes structured filters as EF `WHERE` clauses, and free text via Postgres FTS: `SearchVector.Matches(PlainToTsQuery('english', term))`, where `SearchVector = to_tsvector('english', coalesce(Subject,'') || ' ' || coalesce(BodyText,''))`. 3. Results are per-user filtered (IDOR-safe), **ordered by `SentAtUtc DESC`**, offset-paginated, projected to `EmailSummaryDto`. ## Strengths - Clean, testable layering; DI throughout; 39 tests + CI/CD gate. - **Real Postgres FTS** (generated tsvector), not naïve `LIKE`. - Security-forward (IDOR filters, encrypted tokens, SSRF guard, confirmed destructive ops). - **AI already decoupled behind `IAiProvider`** — the "no-AI / Ollama / future" requirement is architecturally seeded. - Read-only scope + advisory AI = privacy-respecting. ## Weaknesses - **Search is single-mode**: ordered by **date, not relevance** (no `ts_rank`); no fuzzy/typo tolerance, no semantic/vector search, no grouping, no "why matched," no saved/recent/suggested searches. - FTS is **English-only** and covers **only Subject + Body** (not sender, attachment names, labels). - Sender/domain filters use `.Contains()` → **non-sargable ILIKE scans** (no `pg_trgm`). - Category is a **single heuristic enum** — no multi-label, confidence, or learning. - **`IAiProvider` is chat-only** — no embeddings/classification/extraction contract, so semantic search & structured extraction can't yet be expressed. - Threading (`ThreadId`) exists but isn't surfaced as conversation intelligence. ## Technical debt - EF global-query-filter vs required `Email↔EmailLabel` relationship warning (in logs). - Hardcoded English FTS config. - **678 KB single JS chunk** (no code-splitting) — cold-load cost. - Relevance-blind ordering. - AI interface too narrow for the roadmap. ## Performance bottlenecks - `.Contains()` sender/domain → sequential scans (need `pg_trgm` GIN indexes). - **Offset pagination** (`Skip/Take` + `Count`) degrades on deep pages → keyset/cursor. - No score-based top-N (no ranking) → sorts full match set by date. - Single JS chunk (~219 KB gzip) slows cold loads. - Full-mailbox sync latency at 100k+ (batching/Polly present, but per-message fetch). ## Documentation quality Strong for a scaffold: `README`, `docs/ARCHITECTURE.md`, OAuth setup, `docs/specs/*`, `AGENTS.md`, plus `WORKFLOW.md`/`CHANGELOG`; meaningful XML-doc comments. **Gaps:** no API reference, no ERD/data-model doc, no ADRs, no search/AI design docs — which this discovery produces. ## Verdict A clean, secure, well-tested foundation with a **genuine FTS base** and an **AI seam already in place**. The biggest opportunities are exactly where the product wants to win: **relevance-ranked, multi-mode, assisted search**; a **richer AI contract** (embeddings/classification/extraction); **conversation intelligence**; and a **modern, approachable UX**. None of these require a rewrite — they extend the existing seams.