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

76 lines
3.4 KiB
Markdown

# 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):
```json
{ "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.