Skip to content

feat(card): add third-party flagging system#122

Merged
MatteoGabriele merged 5 commits into
mainfrom
feat/third-party-warning-integrations
May 15, 2026
Merged

feat(card): add third-party flagging system#122
MatteoGabriele merged 5 commits into
mainfrom
feat/third-party-warning-integrations

Conversation

@MatteoGabriele
Copy link
Copy Markdown
Owner

@MatteoGabriele MatteoGabriele commented May 15, 2026

Add support for a third-party flagging system.
For now, it's just one, not 100% ready for multiple, but it's a start.
Will refactor some stuff later on.

Summary by CodeRabbit

  • New Features
    • Added a "Suspicious Activity Reported" disclosure to analysis cards with expandable details.
    • Analysis now shows an "Activity Signals" section when flagged or when an external activity report exists.
    • Matched external integration reports are displayed with labels, reasons, counts and links.
    • Score color logic updated to reflect automation/mixed/activity signals for clearer visual emphasis.

Review Change Stack

@netlify
Copy link
Copy Markdown

netlify Bot commented May 15, 2026

Deploy Preview for agentscan ready!

Name Link
🔨 Latest commit 475ef4e
🔍 Latest deploy log https://app.netlify.com/projects/agentscan/deploys/6a0759ef55e3760008b90b53
😎 Deploy Preview https://deploy-preview-122--agentscan.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 15, 2026

Warning

Rate limit exceeded

@MatteoGabriele has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 44 minutes and 59 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0303f217-2c56-417c-b708-4ee9069c0890

📥 Commits

Reviewing files that changed from the base of the PR and between 1bb0cb3 and 475ef4e.

📒 Files selected for processing (2)
  • app/components/ExternalAnlysis/Card.vue
  • server/api/integration/unsafe-labs.get.ts
📝 Walkthrough

Walkthrough

Adds a shared IntegrationItem type, a server endpoint that fetches and transforms UnsafeLabs' clankers.json, a client composable useIntegrations(), an ExternalAnlysis card component, and Analysis card UI changes to match integrations by username and display activity reports.

Changes

Integration-based suspicious activity disclosure

Layer / File(s) Summary
Integration types contract
shared/types/integrations.ts
Defines IntegrationItem with username, optional createdAt, reason, label, and link fields, establishing the shared type contract for integration data.
Server-side integration fetching
server/api/integration/unsafe-labs.get.ts
Implements the GET endpoint that authenticates with GitHub via Octokit, fetches clankers.json from UnsafeLabs/Bounty-Hunters, decodes and parses it, and maps records into IntegrationItem objects with formatted reasons and author PR search links.
Client-side integration composable
app/composables/useIntegrations.ts
Adds useIntegrations() which uses useLazyAsyncData and $fetch to load the IntegrationItem[] from the unsafe-labs endpoint for client components.
External analysis disclosure component
app/components/ExternalAnlysis/Card.vue
New reusable component rendering a collapsible "Suspicious Activity Reported" button and an amber-styled list of IntegrationItem entries with reasons and external links.
Analysis card suspicious activity integration
app/components/Analysis/Card.vue
Types verifiedAutomation as `VerifiedAutomation

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • MatteoGabriele/agentscan#17: Both PRs modify app/components/Analysis/Card.vue, with this PR extending the card's suspicious activity disclosure logic by introducing the new integrations composable and data pipeline.
  • MatteoGabriele/agentscan#18: Related adjustments to classification-driven UI styling in app/components/Analysis/Card.vue.

Suggested labels

agentscan:automation-signals, agentscan:community-flagged

Poem

🐰 In burrows of code I sniff and peep,

I match the names where secrets sleep,
A tiny card that gently warns,
Of automated, nightly scorns,
I hop, I flag—together keep. 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(card): add third-party flagging system' accurately summarizes the main change: introducing a third-party flagging system with integrations support across multiple files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/third-party-warning-integrations

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
server/api/integration/unsafe-labs.get.ts (2)

25-25: ⚡ Quick win

Consider validating the parsed JSON structure.

The type assertion assumes the JSON matches IntegrationUsafeLab[] without runtime validation. If the upstream schema changes, property access in the map function (lines 26-31) could fail unexpectedly.

🛡️ Suggested validation approach
       const content = Buffer.from(data.content, "base64").toString("utf-8");
-      const integrationData = JSON.parse(content) as IntegrationUsafeLab[];
+      const parsed = JSON.parse(content);
+      if (!Array.isArray(parsed)) {
+        throw new Error("Expected clankers.json to contain an array");
+      }
+      const integrationData = parsed as IntegrationUsafeLab[];
       return integrationData.map((d) => ({

For more robust validation, consider using a schema validation library like Zod or Yup.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@server/api/integration/unsafe-labs.get.ts` at line 25, The code currently
does JSON.parse(content) and casts to IntegrationUsafeLab[] without runtime
checks; update the parsing to validate the structure at runtime (e.g., use a
schema validator like Zod or manual checks) before assigning to integrationData
so the later mapping over integrationData (the map that accesses properties of
IntegrationUsafeLab) cannot throw; specifically, validate that parsed value is
an array and each item contains the required fields of IntegrationUsafeLab, and
return or throw a clear error/HTTP 400 if validation fails so downstream code
using integrationData is safe.

14-14: ⚡ Quick win

Validate that githubToken is configured.

If githubToken is missing from runtime config, the API call will fail with an authentication error that's obscured by the generic error message. Validating the config upfront provides clearer feedback.

⚙️ Proposed config validation
   const config = useRuntimeConfig();
+  if (!config.githubToken) {
+    throw createError({
+      statusCode: 500,
+      message: "GitHub token not configured",
+    });
+  }
   const octokit = new Octokit({ auth: config.githubToken });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@server/api/integration/unsafe-labs.get.ts` at line 14, Check that
config.githubToken is present before instantiating Octokit: if missing,
return/throw a clear 400/500 error (or short-circuit the request) with a message
indicating the GitHub token is not configured. Update the code around the
Octokit creation (the Octokit constructor call and uses of config.githubToken)
to validate config.githubToken first, and avoid calling new Octokit({ auth:
config.githubToken }) when it's falsy so you surface a clear configuration error
instead of the generic authentication failure.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/components/Analysis/Card.vue`:
- Line 143: The Tailwind class 'border-b-none' used in the class binding for the
activity disclosure is invalid; update the conditional class entry that
references 'border-b-none' (the object where 'isActivityDisclosureOpen' is the
key condition) to use the valid utility 'border-b-0' so the bottom border is
removed when isActivityDisclosureOpen is true (keep the existing
'rounded-b-none' logic intact).

In `@server/api/integration/unsafe-labs.get.ts`:
- Around line 35-40: The catch block currently swallows the original exception;
change it to catch the error (e.g., catch (err)), log the error and its stack
(using your existing logger or console.error) to preserve diagnostic context,
and then rethrow/createError with the same 500 response but include the original
error message or attach the error as context (referencing the createError call
in server/api/integration/unsafe-labs.get.ts) so logs and the thrown error both
contain the underlying failure details.

---

Nitpick comments:
In `@server/api/integration/unsafe-labs.get.ts`:
- Line 25: The code currently does JSON.parse(content) and casts to
IntegrationUsafeLab[] without runtime checks; update the parsing to validate the
structure at runtime (e.g., use a schema validator like Zod or manual checks)
before assigning to integrationData so the later mapping over integrationData
(the map that accesses properties of IntegrationUsafeLab) cannot throw;
specifically, validate that parsed value is an array and each item contains the
required fields of IntegrationUsafeLab, and return or throw a clear error/HTTP
400 if validation fails so downstream code using integrationData is safe.
- Line 14: Check that config.githubToken is present before instantiating
Octokit: if missing, return/throw a clear 400/500 error (or short-circuit the
request) with a message indicating the GitHub token is not configured. Update
the code around the Octokit creation (the Octokit constructor call and uses of
config.githubToken) to validate config.githubToken first, and avoid calling new
Octokit({ auth: config.githubToken }) when it's falsy so you surface a clear
configuration error instead of the generic authentication failure.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bc3c29cf-069c-4a7c-8492-0e1bae424080

📥 Commits

Reviewing files that changed from the base of the PR and between ad8dee9 and 9c834fa.

📒 Files selected for processing (4)
  • app/components/Analysis/Card.vue
  • app/composables/useIntegrations.ts
  • server/api/integration/unsafe-labs.get.ts
  • shared/types/integrations.ts

Comment thread app/components/Analysis/Card.vue Outdated
Comment thread server/api/integration/unsafe-labs.get.ts Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
app/components/ExternalAnlysis/Card.vue (1)

7-9: 💤 Low value

Simplify the counter computed property.

The computed property can be simplified by removing the explicit return statement and redundant type annotation, as TypeScript can infer the type.

♻️ Proposed simplification
-const counter = computed<number>(() => {
-  return props.items.length;
-});
+const counter = computed(() => props.items.length);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/components/ExternalAnlysis/Card.vue` around lines 7 - 9, The computed
property counter currently uses an explicit return and an unnecessary type
annotation; simplify it by replacing the function body with a concise arrow
expression so that counter is defined as computed(() => props.items.length),
letting TypeScript infer the number type—update the declaration for counter (the
computed import usage) accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/components/ExternalAnlysis/Card.vue`:
- Line 47: The v-for in Card.vue uses the array index as the key (li
v-for="(item, index) in items" :key="index"), which can break identity when
items are reordered; update the :key to use a stable unique identifier from the
item (e.g., item.link or a composite like `${item.username}-${item.link}`) so
Vue can track IntegrationItem components correctly—replace :key="index" with a
key expression based on item.link or the composite key.
- Around line 14-21: The disclosure button currently toggles isDisclosureOpen
but lacks ARIA attributes; update the button (where `@click` toggles
isDisclosureOpen) to include :aria-expanded="isDisclosureOpen" and
aria-controls="<unique-id>" (or bind to a generated id), and add the matching
id="<unique-id>" to the disclosure content element (the element that shows/hides
based on isDisclosureOpen) so screen readers can detect the expanded state and
relationship between the button and the controlled panel.
- Around line 1-4: The props declaration in Card.vue uses the IntegrationItem
type but it isn't imported; add an import for the IntegrationItem type at the
top of the script setup (e.g., import type { IntegrationItem } from '...' ), so
the defineProps<{ items: IntegrationItem[] }>() declaration compiles; ensure the
import path matches where IntegrationItem is exported in the codebase.

---

Nitpick comments:
In `@app/components/ExternalAnlysis/Card.vue`:
- Around line 7-9: The computed property counter currently uses an explicit
return and an unnecessary type annotation; simplify it by replacing the function
body with a concise arrow expression so that counter is defined as computed(()
=> props.items.length), letting TypeScript infer the number type—update the
declaration for counter (the computed import usage) accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 95a91e04-4578-410d-a602-a3e7180a7f5d

📥 Commits

Reviewing files that changed from the base of the PR and between 9c834fa and 1bb0cb3.

📒 Files selected for processing (4)
  • app/components/Analysis/Card.vue
  • app/components/ExternalAnlysis/Card.vue
  • server/api/integration/unsafe-labs.get.ts
  • shared/types/integrations.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • server/api/integration/unsafe-labs.get.ts

Comment thread app/components/ExternalAnlysis/Card.vue
Comment thread app/components/ExternalAnlysis/Card.vue
Comment thread app/components/ExternalAnlysis/Card.vue Outdated
@MatteoGabriele MatteoGabriele merged commit 53b7dba into main May 15, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant