Skip to content

Data inconsistency reports#2083

Open
pikonha wants to merge 3 commits into
devfrom
chore/clickup-user-reports-list
Open

Data inconsistency reports#2083
pikonha wants to merge 3 commits into
devfrom
chore/clickup-user-reports-list

Conversation

@pikonha

@pikonha pikonha commented Jul 22, 2026

Copy link
Copy Markdown
Member

Note

Medium Risk
Introduces a new public API that forwards user content (and optional email) to ClickUp using server secrets; in-memory IP rate limits may be weaker under multi-instance deploys.

Overview
Adds a public “report incorrect data” path so visitors can flag dashboard data issues from DAO pages, with submissions turned into ClickUp tasks for triage.

A new POST /api/report route validates the payload (DAO, section, allowed panel, description, optional email, page URL), enforces 3 reports per IP per hour (via x-real-ip), and creates a task named like [Report] ENS — Token distribution when CLICKUP_API_TOKEN and CLICKUP_REPORT_LIST_ID are set. Misconfiguration and upstream failures return 503/502 with user-facing messages.

The UI is a shared modal form (useReportForm + zod) that derives section and panel options from the current pathname (report-panels maps routes including whitelabel aliases). Entry points: Help popover on standard DAO routes and a fixed floating button on whitelabel (WhitelabelShell). Unit tests cover the API and panel routing; Playwright covers submit, rate-limit messaging, and correct context after navigation.

Reviewed by Cursor Bugbot for commit 96c17b7. Configure here.

@vercel

vercel Bot commented Jul 22, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
anticapture-storybook Ready Ready Preview, Comment Jul 24, 2026 1:30pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
anticapture Ignored Ignored Jul 24, 2026 1:30pm

Request Review

@pikonha pikonha changed the title Add data inconsistency reports Data inconsistency reports Jul 22, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7d4c104bfc

ℹ️ 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".

Comment thread apps/dashboard/shared/components/ReportDataButton.tsx Outdated
Comment thread apps/dashboard/shared/constants/report-panels.ts Outdated

Copy link
Copy Markdown
Collaborator

🎨 UI Review

Automated review · Figma: not found (linked ClickUp task has no Figma URL on record) · Spec: ⚠️ Inconsistency Report
ℹ️ Reviewed without a Figma reference — grounded in code/diff review + UX-expert evaluation.
⚠️ This review ran with restricted network egress: the PR's Vercel preview (only anticapture-storybook deployed; the anticapture dashboard deployment itself was Ignored) and both ClickUp attachments on the linked task (a DefiLlama reference screenshot + a mockup) could not be fetched. Findings below are code-level only — worth a quick manual glance at the live preview before merge.


Floating "Report incorrect data" button (global — renders on every DAO page, dashboard + whitelabel)

Must-fix — overlaps the cookie-consent banner

  • ReportDataButton renders fixed bottom-4 right-4 z-30 (apps/dashboard/shared/components/ReportDataButton.tsx:101). CookieConsent renders fixed bottom-7 left-1/2 z-50 and is w-full on mobile (apps/dashboard/features/cookie/components/CookieConsent.tsx:88) — centered, near-full-width, sitting on top (z-50 vs z-30). CookieConsent mounts in the root layout, so on any first visit (before accept/decline) the two fixed elements occupy the same bottom-of-viewport region and the report button ends up covered by/crowded against the cookie banner, on both mobile and most desktop widths. Give the report button a taller offset (e.g. bottom-24) or coordinate visibility with the cookie-consent state. [Code-only]

Panel selector — wrong options on proposal detail routes

Must-fix — getReportSection misresolves dynamic-ID routes

  • getReportSection takes the last non-empty path segment (apps/dashboard/shared/constants/report-panels.ts:25). That breaks for /[daoId]/proposals/[proposalId], /[daoId]/proposals/new, and /[daoId]/governance/offchain-proposal/[proposalId] — none of those segments (a proposal ID, or new) match a key in REPORT_PANELS_BY_SECTION or SECTION_ALIASES, so all three silently fall back to overview. A user reporting bad data from a proposal page sees "Overview metrics / Resilience stages / Attack exposure" as their panel choices instead of anything proposal-related, and the ClickUp task created from that report will misrepresent where the report came from. Match on any path segment (or an explicit route→section map) rather than .at(-1). [Code-only]

Mobile

Nice-to-have — touch target below 44×44px

  • The floating button uses size="sm" (py-1 px-2, apps/dashboard/shared/components/design-system/buttons/button/Button.tsx:15) with text-sm/tight — well under the 44px minimum touch target, and it's the only affordance for this feature on mobile. Bump to size="md"/lg, or pad the hit area via className. (apps/dashboard/shared/components/ReportDataButton.tsx:98-99) [UX-heuristic]

Design-system adherence

No issues — the form composes DS Form/FormField/FormLabel/Select/Textarea/Input/Modal throughout, no hand-rolled primitives. FormLabel isOptional on the Email field matches the existing optional-label convention (no forced asterisk). The DS Modal already handles the mobile bottom-sheet conversion, so no separate check needed there. [Code-only]

Scope note

This is a UI-only review (visual fidelity, DS adherence, UX, copy, responsive behavior) — architecture, hook structure, and other code-quality concerns are left to the code reviewer.


Generated by Claude Code

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4e01543e3f

ℹ️ 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".

variant="outline"
size="sm"
onClick={() => setIsOpen(true)}
className="fixed bottom-4 right-4 z-30 shadow-lg"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep the report CTA from covering Help

On normal DAO pages the root layout still renders HelpPopover, which is fixed at right-4 bottom-4 with a lower z-index. This new CTA uses the same fixed coordinates with z-30, so on routes like /ens it sits directly on top of the existing Help button and makes that support entry point unreachable; offset one of the buttons or compose them together.

Useful? React with 👍 / 👎.

Comment thread apps/dashboard/shared/components/ReportDataButton.tsx Outdated
@railway-app

railway-app Bot commented Jul 22, 2026

Copy link
Copy Markdown

🚅 Deployed to the anticapture-pr-2083 environment in anticapture-infra

Service Status Web Updated (UTC)
grafana ✅ Success (View Logs) Web Jul 24, 2026 at 1:29 pm
otelcol ✅ Success (View Logs) Jul 24, 2026 at 1:29 pm
prometheus ✅ Success (View Logs) Jul 24, 2026 at 1:29 pm
loki ✅ Success (View Logs) Jul 24, 2026 at 1:29 pm
authful ✅ Success (View Logs) Web Jul 24, 2026 at 1:29 pm
gateful ✅ Success (View Logs) Web Jul 24, 2026 at 1:29 pm
alertmanager ✅ Success (View Logs) Jul 24, 2026 at 1:29 pm
tempo ✅ Success (View Logs) Jul 24, 2026 at 1:28 pm
compound-indexer-offchain ✅ Success (View Logs) Jul 23, 2026 at 8:58 pm
uniswap-indexer-offchain ✅ Success (View Logs) Jul 23, 2026 at 8:58 pm
gitcoin-indexer-offchain ✅ Success (View Logs) Jul 23, 2026 at 8:58 pm
shutter-indexer-offchain ✅ Success (View Logs) Jul 23, 2026 at 8:53 pm
ens-indexer-offchain ✅ Success (View Logs) Jul 23, 2026 at 8:53 pm
ens-relayer ✅ Success (View Logs) Jul 23, 2026 at 12:22 pm
mcp ✅ Success (View Logs) Web Jul 22, 2026 at 11:00 pm
docs ✅ Success (View Logs) Web Jul 22, 2026 at 11:00 pm
aave-api ✅ Success (View Logs) Jul 22, 2026 at 10:56 pm
tornado-api ✅ Success (View Logs) Jul 22, 2026 at 10:56 pm
fluid-indexer ✅ Success (View Logs) Jul 22, 2026 at 10:56 pm
compound-api ✅ Success (View Logs) Jul 22, 2026 at 10:56 pm
gitcoin-indexer ✅ Success (View Logs) Jul 22, 2026 at 10:56 pm
address-enrichment ✅ Success (View Logs) Web Jul 22, 2026 at 10:56 pm
obol-api ✅ Success (View Logs) Jul 22, 2026 at 10:56 pm
shutter-indexer ✅ Success (View Logs) Jul 22, 2026 at 10:55 pm
lil-nouns-indexer ✅ Success (View Logs) Jul 22, 2026 at 10:55 pm
ens-api ✅ Success (View Logs) Jul 22, 2026 at 10:55 pm
uniswap-indexer ✅ Success (View Logs) Jul 22, 2026 at 10:55 pm
ens-indexer ✅ Success (View Logs) Jul 22, 2026 at 10:55 pm
obol-indexer ✅ Success (View Logs) Jul 22, 2026 at 10:55 pm
gitcoin-api ✅ Success (View Logs) Jul 22, 2026 at 10:55 pm
aave-indexer ✅ Success (View Logs) Jul 22, 2026 at 10:55 pm
shutter-api ✅ Success (View Logs) Jul 22, 2026 at 10:55 pm
nouns-indexer ✅ Success (View Logs) Jul 22, 2026 at 10:55 pm
uniswap-api ✅ Success (View Logs) Jul 22, 2026 at 10:55 pm
nouns-api ✅ Success (View Logs) Jul 22, 2026 at 10:55 pm
fluid-api ✅ Success (View Logs) Jul 22, 2026 at 10:55 pm
scroll-indexer ✅ Success (View Logs) Jul 22, 2026 at 10:55 pm
compound-indexer ✅ Success (View Logs) Jul 22, 2026 at 10:55 pm
lil-nouns-api ✅ Success (View Logs) Jul 22, 2026 at 10:55 pm
tornado-indexer ✅ Success (View Logs) Jul 22, 2026 at 10:55 pm
erpc ✅ Success (View Logs) Web Jul 22, 2026 at 10:55 pm
nodeful ✅ Success (View Logs) Jul 22, 2026 at 10:47 pm
user-api ✅ Success (View Logs) Web Jul 22, 2026 at 10:46 pm
scroll-api ✅ Success (View Logs) Jul 22, 2026 at 10:45 pm

@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

🔍 Vercel preview: https://anticapture-3uugi7enx-ful.vercel.app

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.

Fix All in Cursor

Bugbot Autofix prepared fixes for both issues found in the latest run.

  • ✅ Fixed: Rate limit before success
    • Rate-limit timestamps are now recorded only after ClickUp successfully creates a task, so failed submissions no longer consume hourly quota.
  • ✅ Fixed: Stale submit error persists
    • resetReportForm now calls the TanStack Query mutation reset() so closing or reopening the modal clears stale submission errors.

Create PR

Or push these changes by commenting:

@cursor push 6efd3f9d8e
Preview (6efd3f9d8e)
diff --git a/apps/dashboard/app/api/report/route.ts b/apps/dashboard/app/api/report/route.ts
--- a/apps/dashboard/app/api/report/route.ts
+++ b/apps/dashboard/app/api/report/route.ts
@@ -29,13 +29,13 @@
     (timestamp) => now - timestamp < REPORT_WINDOW_MS,
   );
 
-  if (attempts.length >= REPORT_LIMIT) {
-    reportAttempts.set(ip, attempts);
-    return true;
-  }
+  reportAttempts.set(ip, attempts);
+  return attempts.length >= REPORT_LIMIT;
+};
 
+const recordReportAttempt = (ip: string, now = Date.now()) => {
+  const attempts = reportAttempts.get(ip) ?? [];
   reportAttempts.set(ip, [...attempts, now]);
-  return false;
 };
 
 const formatDescription = ({
@@ -111,6 +111,7 @@
       );
     }
 
+    recordReportAttempt(clientIP);
     return NextResponse.json({ message: "Report submitted successfully" });
   } catch (error) {
     if (error instanceof z.ZodError) {

diff --git a/apps/dashboard/shared/components/ReportDataButton.tsx b/apps/dashboard/shared/components/ReportDataButton.tsx
--- a/apps/dashboard/shared/components/ReportDataButton.tsx
+++ b/apps/dashboard/shared/components/ReportDataButton.tsx
@@ -64,7 +64,7 @@
       ? "https://anticapture.com"
       : window.location.href;
   const [isSubmitted, setIsSubmitted] = useState(false);
-  const { form, mutate, isPending, error } = useReportForm({
+  const { form, mutate, isPending, error, reset } = useReportForm({
     daoId,
     section,
     url,
@@ -77,6 +77,7 @@
   const defaultPanel = isOverview ? panels[0].value : "";
 
   const resetReportForm = useCallback(() => {
+    reset();
     form.reset({
       daoId,
       section,
@@ -85,7 +86,7 @@
       email: "",
       url,
     });
-  }, [daoId, defaultPanel, form, section, url]);
+  }, [daoId, defaultPanel, form, reset, section, url]);
 
   useEffect(() => {
     setIsSubmitted(false);

You can send follow-ups to the cloud agent here.

Reviewed by Cursor Bugbot for commit 96c17b7. Configure here.

return NextResponse.json(
{ error: "We couldn't submit your report. Please try again shortly." },
{ status: 502 },
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rate limit before success

Medium Severity

Each POST calls isRateLimited before ClickUp runs, so failed submissions (502/503 or upstream errors) still consume one of the three hourly slots. During outages or misconfiguration, users can hit 429 without any report ever being created.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 96c17b7. Configure here.

onOpenChange(nextOpen);
setIsSubmitted(false);
resetReportForm();
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale submit error persists

Medium Severity

Closing or resetting the report modal clears react-hook-form via resetReportForm, but the TanStack Query mutation error from useReportForm is never reset. Reopening the modal can show the previous submission failure even with a fresh form.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 96c17b7. Configure here.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 96c17b73b3

ℹ️ 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".

<main className="min-h-0 min-w-0 flex-1 overflow-y-auto">
{children}
</main>
<ReportDataButton daoId={daoId} />

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep the whitelabel report CTA off the publish bar

On whitelabel proposal creation routes such as /whitelabel/ens/proposals/new and custom-domain /proposals/new, this unconditional mount renders ReportDataButton, whose trigger is fixed at bottom-4 right-4 z-30; that same flow renders ProposalFormNavBar as a sticky bottom bar with Save Draft/Publish controls on the right. In that context the report CTA can sit on top of those controls and make publishing or saving unreachable, especially on narrow screens, so skip or offset it for create-proposal routes as the regular Help button already does.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants