4ce2df0a2b
CI / backend (push) Successful in 52s
CI / frontend (push) Successful in 14s
Deploy Staging / deploy (push) Successful in 18s
CI / backend (pull_request) Successful in 52s
CI / frontend (pull_request) Successful in 15s
Security / secrets (push) Successful in 4s
Security / dependencies (push) Successful in 55s
Security / secrets (pull_request) Successful in 4s
Security / dependencies (pull_request) Successful in 54s
89 lines
5.3 KiB
Markdown
89 lines
5.3 KiB
Markdown
# 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.
|