.NET 8 security support ends 2026-11-10; .NET 10 is LTS to Nov 2028.
- TargetFramework net8.0 -> net10.0 (Directory.Build.props)
- EF Core 8.0.4 -> 10.0.9; Npgsql provider 8.0.4 -> 10.0.2; Pgvector.EFCore
0.2.0 -> 0.3.0; ASP.NET/Extensions packages -> 10.0.9
- Dockerfile sdk/aspnet 8.0 -> 10.0; CI setup-dotnet -> 10.0.x
- Modernised deprecated APIs: X509CertificateLoader (SYSLIB0057),
KnownIPNetworks + System.Net.IPNetwork.Parse (ASPDEPR005)
- Adapted tests to Npgsql 10's eager connection-string validation (dummy conn
string in test factories; behaviour change from lazy 8.x)
Verified: 0 errors/0 warnings; all 54 tests green on net10; the 3 LiveDb tests
green against a real pgvector container on the new EF10/Npgsql10/Pgvector 0.3
stack; dotnet format clean; vulnerable-package scan clean; the .NET 10 API
Docker image builds successfully.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Heuristic classifier falls back to AI only when it can't determine a category;
unsubscribe confidence blends method reliability with an AI safety opinion and
surfaces it in the Unsubscribe Manager; emails get an on-demand AI one-line
summary in the detail pane. All AI calls degrade gracefully when AI is disabled
or the provider errors.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a periodic inbox-summary email per opted-in user. SMTP is
configured via appsettings (Smtp section); the digest is built from
existing analytics (health score, top senders, recommendations) and
sent by a new hourly DigestWorker, mirroring the GmailSyncWorker
pattern. Frequency and send hour are configurable (Digest section).
Backend: IEmailSender (SmtpEmailSender, MailKit), IDigestService,
DigestWorker, new User.DigestEnabled/LastDigestSentUtc fields +
migration, SettingsController for the per-user toggle and a
send-now test endpoint, all scoped to the authenticated UserId.
Frontend: SettingsApi + a bell/no-bell toggle button in the topbar.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
SyncStatus widget polls /sync/status and shows a live progress bar in
the topbar while syncing, or last-synced time / error otherwise.
Unsubscribe page reworked into a proper queue: status filter tabs
(All/Pending/Succeeded/Failed), select-all, sorted by volume, status
badges, and a result toast after processing.
GET /email/{id} returns full BodyText; Senders detail view fetches
and renders it instead of just the snippet.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- ✉✕ button appears on rows where the email has a List-Unsubscribe header
- One-click POST / HTTP GET executed automatically; shows ✓ on success
- mailto: targets open the user mail client (we never auto-send email)
- POST /email/{id}/unsubscribe: detects sender, then processes — UserId scoped
- EmailSummaryDto gains IsStarred, HasListUnsubscribe, SupportsOneClick fields
- Both SearchService and CleanupService updated to populate new DTO fields
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New FolderView page at /app/folder/:slug renders a paginated email table
- Sidebar links now route to their respective folder views
- Extended SearchRequestDto with IsInInbox, IsStarred, IsTrashed, GmailLabel, Category, MinSizeBytes
- SearchService applies the new filters; GmailLabel does a label-id lookup (SENT/DRAFT/SPAM)
- Frontend folderToRequest() maps every slug to the correct search payload
- Email rows show sender, subject+snippet, attachment icon, size, date; bold for unread
- Pagination controls for large folders
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>