feat(cloud): add dedicated Cloud page and Breach Monitor#78
Conversation
Extract cloud settings from SettingsPage into a standalone CloudPage with a feature showcase for unlinked users (local features first, then cloud dashboard features, plan comparison, and connect flow) and full settings management for linked users. Implement full-stack breach monitoring: cloud agent methods with deleteApi, IPC handlers with email validation, Zustand store with optimistic removal, and a complete UI page with add/remove emails, expandable breach cards with data class pills, and proper error handling (403 upgrade prompt, inline error banners, toast notifications). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Redesign breach monitor page from expandable cards to an email list + sortable table layout. Users select an email from the sidebar list to view its breaches in a table that can be sorted by date, accounts, or status. Add breach acknowledgment: users can mark individual breaches or all breaches for an email as "reviewed" via PATCH /breach-monitor/acknowledge. Unacknowledged breaches show a "New" badge; acknowledged ones show "Reviewed". Sidebar badge now only counts unacknowledged breaches. Backend: add patchApi method, acknowledgeBreaches cloud agent method, IPC handler with validation, preload bridge. Add acknowledgedAt field to BreachEntry type. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The POST response only returns newly added emails, not the full list. Re-fetch via GET after adding so existing emails are preserved. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… filters Replace the two-column email sidebar + detail panel layout with a flat table showing all breaches sorted by date. Emails appear as filter chips and an optional dropdown when multiple are monitored. Remove unused selectedEmail state from the store. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Show the real API error in the toast instead of a generic message, and log breach IDs to the console for debugging. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 572f40cbbb
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
- Chunk acknowledge-all into batches of 100 to stay within IPC limit - Separate delete/add success from refresh failure so a successful mutation isn't reverted or reported as failed due to a transient fetch error Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b16ff075ef
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
- Eagerly fetch breach data on module load when cloud-connected so the sidebar badge is accurate without visiting the page first - Also fetch when a device is newly linked - Optimistically decrement usage on email removal so the add button isn't blocked if the follow-up refresh fails Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Hovering the card shows per-plan email limits and an upgrade nudge. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 701620cd1c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Replace the native title attribute with a HelpCircle icon and the project's SafetyTooltip-style popover with arrow, matching the tooltip pattern used in StartupPage and UninstallerPage. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 08883f65d9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const raw = (await this.patchApi(path, { breach_ids: breachIds })) as Record<string, unknown> | ||
| return { | ||
| status: typeof raw.status === 'string' ? raw.status : 'ok', | ||
| acknowledged: typeof raw.acknowledged === 'number' ? raw.acknowledged : 0, |
There was a problem hiding this comment.
Guard acknowledge parsing when PATCH returns no JSON
patchApi can return null for successful non-JSON responses (for example a 204 No Content acknowledge endpoint), but this code immediately dereferences raw.status/raw.acknowledged. In that case, a successful acknowledge request throws a runtime TypeError and is surfaced as a failure to the UI. Please validate that raw is an object before property access and fall back to defaults when it is not.
Useful? React with 👍 / 👎.
| {emails.length === 0 && status === 'done' && ( | ||
| <EmptyState icon={Mail} title={t('emptyState.noEmails')} description={t('emptyState.noEmailsDesc')} /> |
There was a problem hiding this comment.
Avoid showing empty state when initial fetch failed
This renders the “no emails” empty state whenever loading is done and the list is empty, even if the fetch failed. Because error toast/banner paths are also gated on emails.length > 0, first-load API failures (network/5xx) are presented as a successful zero-results state, which is misleading for users who already have monitored emails and can trigger duplicate add/remove attempts. Gate this empty state on !error or show an explicit error state.
Useful? React with 👍 / 👎.
The eager hydration can fire before the cloud agent finishes its handshake. Now the store silently retries up to 3 times (3s apart) on "not connected" errors instead of surfacing the error to the UI. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c851b45b62
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| for (let i = 0; i < breachIds.length; i += 100) { | ||
| await window.kudu.breachMonitorAcknowledge(breachIds.slice(i, i + 100)) | ||
| } |
There was a problem hiding this comment.
Preserve successful chunks when acknowledge-all partially fails
When acknowledgeBreaches processes more than 100 IDs, each chunk is sent sequentially, but any failure in a later chunk throws before local state is updated. In that case, earlier chunks may already be acknowledged server-side while the UI still shows everything as unreviewed, which leads to stale badge/count state and misleading retry behavior for large breach sets. Record per-chunk successes and apply them (or force a refetch) even if a later chunk fails.
Useful? React with 👍 / 👎.
Summary
/cloudroute. Unlinked users see a feature showcase (local features first — threat monitor, CVE, AI safety scores — then cloud dashboard features, plan comparison with tier badges, and connect flow). Linked users see all cloud settings organized into sections (connection, monitoring, remote control, advanced).deleteApi, IPC handlers with email validation, Zustand store with optimistic removal and auto-reset on cloud unlink, and a complete UI page with add/remove emails, expandable email cards with breach details (data class pills, pwn count, verified badges), 403 upgrade prompt, and proper error handling (inline banners only when relevant, toast notifications for add/remove failures)./cloud. Removed ~300 lines of cloud state management from SettingsPage.cloud.jsonandbreachMonitor.jsontranslation namespaces; updated settings translations across all 27 locales.New files
src/main/ipc/breach-monitor.ipc.ts— IPC handlersrc/renderer/src/stores/breach-store.ts— Zustand storesrc/renderer/src/pages/CloudPage.tsx— Cloud settings/showcase pagesrc/renderer/src/pages/BreachMonitorPage.tsx— Breach monitor pagesrc/renderer/src/locales/en/cloud.json— Cloud page translationssrc/renderer/src/locales/en/breachMonitor.json— Breach monitor translationsTest plan
/cloudwhen not linked — feature showcase renders with all sections/cloudwhen linked — all settings sections render and toggles work/breach-monitorwhen not linked — redirects to/🤖 Generated with Claude Code