Files
Inboxintel/RECOMMENDATIONS.md
T
cesnimda 59522a6e96
CI / backend (push) Successful in 50s
CI / frontend (push) Successful in 11s
CI / format (push) Successful in 46s
CI / db-tests (push) Successful in 50s
Deploy Staging / deploy (push) Successful in 16s
CI / backend (pull_request) Successful in 48s
CI / frontend (pull_request) Successful in 12s
CI / format (pull_request) Successful in 45s
CI / db-tests (pull_request) Successful in 53s
Security / secrets (push) Successful in 3s
Security / dependencies (push) Successful in 52s
Security / secrets (pull_request) Successful in 3s
Security / dependencies (pull_request) Successful in 54s
docs: Phase 3 recommendations (#25)
2026-07-02 16:10:12 +02:00

122 lines
7.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# InboxIntel — Phase 3 Recommendations
**Date:** 2026-07-02 · Follows the completed audit remediation ([AUDIT_REPORT.md](AUDIT_REPORT.md)).
Each item: what · concrete benefit · effort (S/M/L) · risk · sources. **Ranked by value-to-effort.**
> Research notes: grounded in official primary sources (fetched 2026-07-02) plus the
> competitor/feature research already performed in `docs/discovery/02-competitor-analysis.md`.
> (Live web *search* was quota-limited this session; the load-bearing facts below — support
> dates, EF 10 features, Npgsql 10, Renovate/Gitea — were verified against primary docs.)
---
## 1. Migrate .NET 8 → .NET 10 LTS ⚠️ deadline-driven
- **What:** move the solution to .NET 10 / EF Core 10 / Npgsql provider 10; bump
`Pgvector.EntityFrameworkCore` off the 0.2.0 EF8-pin at the same time.
- **Why (hard fact):** **.NET 8 support ends 2026-11-10 — ~4 months away.** After that: no
security patches. .NET 10 is LTS until Nov 2028. This is not optional, only *when*.
- **Bonus value:** EF 10 brings **named query filters** (exactly our multi-filter tenant
scenario — e.g. tenant + soft-delete filters, selectively ignorable), **redacted inlined
constants in SQL logs** (privacy win for an email app), first-class `LeftJoin`, and
better parameterized-collection SQL (plan-cache friendly).
- **Watch-outs:** Npgsql 10 changes `array.Contains(x)` translation to `= ANY(...)` (check
our GIN-indexed paths); the migration touches every csproj + CI images + Dockerfiles.
The live-DB CI job we just added is the safety net for the search paths.
- **Effort: M** (mechanical + verify) · **Risk: M** · Blast radius: whole repo, but staged
behind the pipeline.
- Sources: [.NET support policy](https://dotnet.microsoft.com/en-us/platform/support/policy/dotnet-core),
[EF Core 10 what's-new](https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-10.0/whatsnew),
[Npgsql EF 10 release notes](https://www.npgsql.org/efcore/release-notes/10.0.html).
## 2. Automated dependency updates via Renovate (self-hosted Gitea)
- **What:** run Renovate against the Gitea instance (PAT with repo/user/issue scopes,
`platform=gitea`); it opens update PRs that ride the existing required CI gates
(build, tests, gitleaks, vuln scan, live-DB).
- **Benefit:** closes the audit's supply-chain gap permanently — the MailKit/System.Text.Json
CVE round we did by hand becomes an automated PR you just merge. NuGet + npm + Dockerfile
+ Actions all covered.
- **Effort: S** (a config + a scheduled runner job) · **Risk: L** (PRs are gated by CI).
- Source: [Renovate Gitea platform docs](https://docs.renovatebot.com/modules/platform/gitea/).
## 3. Database backups (currently none!)
- **What:** nightly `pg_dump` sidecar/cron in compose, rotating N days, written to a
host path covered by your disk-encryption/backup regime (per SECURITY.md).
- **Benefit:** today a bad migration or volume loss = total data loss; the audit fixed
security but the **availability** story is a single Docker volume. Highest
value-per-line-of-config item on this list.
- **Effort: S** · **Risk: L**. Pair with a documented restore drill.
## 4. Activate semantic search (Ollama + embedding backfill + hybrid ranking)
- **What:** the pgvector column, HNSW index, `IEmbeddingProvider`, and live-DB tests are
already shipped. Remaining: an optional `ollama` compose profile, the embedding
backfill worker (batched, VRAM-aware), and RRF hybrid merge in `SearchService`
(design: `docs/discovery/05/06`).
- **Benefit:** the flagship differentiator from the discovery blueprint — *"gym receipt
march"* finds the email; nobody mainstream offers this locally/privately.
- **Effort: ML** · **Risk: M** (quality tuning) · Needs the RTX-3080 box to pull
`nomic-embed-text` (~0.5 GB, always-on per the AI strategy).
## 5. Observability: OpenTelemetry + a dashboard
- **What:** wire .NET's built-in OTel (traces/metrics for ASP.NET, EF, HttpClient) exported
to a compose-profile Prometheus+Grafana (or an OTLP endpoint later). Keep Serilog for logs.
- **Benefit:** today diagnosis = `docker logs`. This gives request latency, sync-job
timings, rate-limit hits, and search-performance baselines — the "what will break first
as usage grows" early-warning system.
- **Effort: M** · **Risk: L** (additive).
## 6. Named query filters for tenancy (after #1)
- **What:** convert the hand-rolled `CurrentUserId == Guid.Empty || …` filters to EF 10
named filters (`"Tenant"`, future `"SoftDelete"`), selectively ignorable per-query.
- **Benefit:** cleaner + safer than the worker-bypass convention; directly feeds the
multi-provider platform's isolation model.
- **Effort: S** (post-migration) · **Risk: L** (isolation tests already exist).
## 7. Frontend bundle code-splitting
- **What:** vite `manualChunks`/dynamic imports to split the 678 KB bundle (charts,
grid-layout, per-route chunks); drop `react-grid-layout` when the Analytics redesign
lands (it's the sole consumer).
- **Benefit:** faster cold loads; audit L-5 closed. Gzip is already on (batch B), so this
is the remaining lever.
- **Effort: SM** · **Risk: L**.
## 8. Keyset (cursor) pagination for search
- **What:** replace offset `Skip/Take` with keyset pagination for browse/date-ordered
paths; ranked paths already effectively top-N (design in `docs/discovery/05`).
- **Benefit:** deep-page latency stops degrading linearly at 100k+ mailboxes.
- **Effort: M** (API shape + frontend infinite-scroll cursor) · **Risk: M** (API change).
## 9. SAST in CI (Semgrep)
- **What:** a `semgrep` job (OSS rules for C#/JS + secrets/OWASP packs) in `ci.yml`
CodeQL is GitHub-centric; Semgrep runs anywhere Docker does.
- **Benefit:** closes audit L-6; catches injection/crypto misuse patterns the current
gates (gitleaks + dep-audit + tests) don't look for.
- **Effort: SM** (tuning noise) · **Risk: L** (advisory job first, required later).
## 10. Settings + feature-flag platform (multi-provider Phase 4)
- **What:** implement `docs/discovery/multi-provider/04``feature_flags`/`user_settings`
tables, `IFeatureFlags`/`IAiGate`, admin toggles later.
- **Benefit:** unblocks shipping AI features dark (`ai.enabled` master switch), the
Settings UI, and everything in the multi-provider plan; prerequisite for #4 to be
properly gated per the approved design.
- **Effort: L** · **Risk: M** — the biggest item, but the one the roadmap already commits to.
---
## Value-to-effort ranking (summary)
| # | Item | Effort | Why this rank |
|---|------|--------|---------------|
| 1 | .NET 10 migration | M | **EOL deadline Nov 2026**; unlocks #6 |
| 2 | Renovate | S | Permanent supply-chain automation for one config file |
| 3 | Backups | S | Only protection against total data loss |
| 4 | Semantic search activation | ML | Flagship product differentiator; infra already live |
| 5 | OpenTelemetry | M | Can't manage what you can't see |
| 6 | Named query filters | S | Cheap once #1 lands |
| 7 | Bundle splitting | SM | Perceived speed; last audit-perf leftover |
| 8 | Keyset pagination | M | Scales search; roadmap item |
| 9 | Semgrep SAST | SM | Last unautomated security layer |
| 10 | Settings/flags platform | L | Roadmap-committed foundation |
**Suggested sequencing:** 2+3 immediately (tiny, standalone) → 1 (deadline) → 6 → 4 (+10 gating if you want flags first) → 5 → 7/8/9 opportunistically.
**STOP — awaiting your selections before implementing anything (Phase 4).**