Skip to content

Conversation

@github-actions
Copy link
Contributor

@github-actions github-actions bot commented Jan 2, 2026

This is an automated pull request to release the candidate branch into production, which will trigger a deployment.
It was created by the [Production PR] action.

github-actions bot and others added 2 commits January 1, 2026 22:10
@cursor
Copy link

cursor bot commented Jan 2, 2026

PR Summary

Modernizes vendor risk assessments and related UX/backends.

  • Risk assessment migration + versioning: Store assessments on GlobalVendors with riskAssessmentData/version/updatedAt; add Postgres advisory locking and version auto-increment; normalize domain/website lookups; DB migrations move fields off Vendor.
  • Task pipeline overhaul: vendor-risk-assessment-task now updates GlobalVendors, marks vendor status, and manages a blocking then todo "Verify risk assessment" task; removes legacy backfill task; adds monthly schedule to refresh all vendors.
  • Cheaper, deduped triggering: Internal batch trigger defaults to ensure-mode (withResearch=false) and only researches when data missing; also ensures/updates Verify tasks without running jobs; onboarding uses ensure-mode.
  • App UI: New vendor header/tabs and dedicated Review page rendering RA (timeline, security assessment); task list shows a skeleton for in-progress Verify tasks and polls until ready; removes old generated-task views; safer description parsing for plain text.
  • PDF/text robustness: Strip invisible Unicode, preserve unknown glyphs (avoid "?" corruption) in policy PDF renderer and shared PDF utility; editor file-upload change defers state updates to avoid flushSync errors.
  • Audit/logging: Await audit logs on task create/assign to preserve order; minor badge style tweak.

Written by Cursor Bugbot for commit 26f86ee. This will update automatically on new commits. Configure here.

@vercel
Copy link

vercel bot commented Jan 2, 2026

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

Project Deployment Review Updated (UTC)
app (staging) Ready Ready Preview, Comment Jan 2, 2026 3:17pm
portal (staging) Ready Ready Preview, Comment Jan 2, 2026 3:17pm

@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@graphite-app
Copy link

graphite-app bot commented Jan 2, 2026

Graphite Automations

"Auto-assign PRs to Author" took an action on this PR • (01/02/26)

1 reviewer was added to this PR based on Mariano Fuentes's automation.

* feat(vendor): implement vendor risk assessment features and UI components

* feat(vendor): enhance vendor risk assessment logic and domain extraction

* refactor(vendor): remove distinct constraint for website in risk assessment

* refactor(vendor): replace ShieldCheck icon with Shield icon in assessment view

* refactor(vendor): remove backfill vendor risk assessment tasks and enhance task handling

---------

Co-authored-by: Tofik Hasanov <annexcies@gmail.com>
taskItemId: params.taskItemId,
});
return await run();
}
Copy link

Choose a reason for hiding this comment

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

Advisory lock catches all errors causing double execution

The withAdvisoryLock function's error handling structure is flawed. The outer catch block catches errors from both lock acquisition AND the run() callback. If a database operation inside run() throws (e.g., constraint violation), the error is caught, the misleading message "Advisory lock unavailable" is logged, and run() executes a second time without lock protection. Since run() performs database updates and version increments, this causes double writes and incorrect version numbers (e.g., v1v3 instead of v1v2). The catch should only handle lock acquisition failures, not errors from the critical section.

Fix in Cursor Fix in Web

website: {
contains: domain,
},
},
Copy link

Choose a reason for hiding this comment

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

Domain substring matching causes wrong vendor data association

The GlobalVendors lookup uses website: { contains: domain } which performs substring matching and can match unrelated vendors. For example, searching for domain "a.com" would incorrectly match "nota.com", "data.com", or "mega.company". Similarly, "stripe.com" would match any website containing that substring. This causes risk assessment data to be incorrectly read from or written to the wrong vendor records. The pattern is used consistently across multiple files for both reads and writes.

Additional Locations (2)

Fix in Cursor Fix in Web

// Mark as ready for normal UX: clickable + full renderer
await db.taskItem.update({
where: { id: taskItemId },
const data = parseRiskAssessmentJson(description);
Copy link

Choose a reason for hiding this comment

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

Research with null website saves empty data to GlobalVendors

The batch trigger includes vendors without valid websites (line 207: if (!domain) return true), passing vendorWebsite: null in the payload with withResearch: true. If the vendor's website is later updated before the task runs, the task passes the early-return checks (using current DB website) but research evaluates to null because payload.vendorWebsite is still null. The code then calls buildRiskAssessmentDescription with null research, creating empty data that gets saved to GlobalVendors, overwriting any existing risk assessment data for that website.

Additional Locations (1)

Fix in Cursor Fix in Web

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