Files
Inboxintel/docs/specs/feature-activity-log.md
cesnimda be6cbf90d7 docs: full specs for automation engine, sender policy, activity log, privacy monitor, UI overhaul
Clean.Email-parity feature build-out plus a Stripe/Notion-style UI rebuild on
Tailwind + shadcn-style primitives. Locks the hybrid-automation, Gmail-only,
light+dark, incremental-rollout decisions and lays out the backend/frontend
build sequence.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 23:04:52 +02:00

3.4 KiB

Spec: Activity Log, Undo & Activity Summaries

A unified, trustworthy record of everything automation did — and a way to take it back. Built entirely on the AutomationAction table from feature-rules-engine.md; no new storage.

1. Activity Log

  • Backed by AutomationAction rows with Status in (Applied, Rejected, Undone, Failed).
  • IAutomationActionService.GetActivityAsync(userId, take) returns ActivityLogEntryDto, newest first, grouped where it reads naturally (e.g. "Archived 38 emails from LinkedIn — Rule: Social noise").
  • Each entry exposes CanUndo:
    • Safe actions (Archive/SkipInbox/ApplyLabel/MarkRead/Star) — always undoable while we still hold UndoStateJson and the message exists.
    • Trash — undoable (Gmail untrash) within Gmail's 30-day window.
    • Hard delete — N/A (never automated).

UI (/app/activity)

  • Reverse-chronological feed with source chips (Rule / Policy / Screener / Age sweep), action icon, affected count, timestamp, and an Undo button where CanUndo.
  • Filter by source and action type. Date range. Search by sender.

2. Undo

UndoAsync(userId, actionIds):

  1. Load the Applied actions (verify UserId).
  2. For each, parse UndoStateJson (captured pre-apply: which labels were present, whether INBOX was set, whether it was in Trash).
  3. Issue the inverse BatchModifyAsync / BatchUntrash to restore prior state.
  4. Set Status = Undone, stamp AppliedUtc = now on the undo.
  5. Log is append-only in spirit: the original row flips to Undone rather than being deleted.

UndoStateJson shape (kept tiny):

{ "hadInbox": true, "labels": ["Label_12","Label_88"], "wasTrashed": false }

Captured by the engine/approval step immediately before mutating.

3. Activity Summaries (extends existing digest)

Clean.Email's "Activity Summaries" = periodic notification of what automation did. We already have the SMTP digest infra (IDigestService, DigestWorker, User.DigestEnabled). Extend rather than add:

  • DigestService.BuildHtml gains an "Automation activity since last digest" section: counts of archived/labeled/screened, pending-approval count (with a nudge to review), top rules by volume, new screener senders.
  • Pull from AutomationAction where AppliedUtc > user.LastDigestSentUtc.
  • No new toggle — folds into the existing digest opt-in. (Optional later: a separate User.ActivitySummaryEnabled if users want activity summaries without the analytics digest.)

4. Cleanup Reminders

A lightweight nudge when the inbox needs attention, reusing DigestWorker's tick:

  • If a user has pending destructive approvals older than ReminderAfterDays (default 3) and digests are on, the next digest leads with "You have N actions awaiting approval."
  • If automation is off but the dashboard health score is poor / unsubscribe backlog is large, include a "Time to clean up" prompt with a deep link.

No new infrastructure — just content rules inside DigestService.

5. API

Covered by feature-rules-engine.md §7: GET /automation/activity, POST /automation/activity/undo. Add query params for filtering: ?source=&action=&from=&to=&q=.

6. Security & safety

  • Activity + undo scoped to UserId; action ownership re-checked on undo.
  • Undo is best-effort and idempotent — undoing an already-undone/missing message logs and no-ops rather than erroring.
  • Log never exposes another user's senders/emails.