Skip to content

[comp] Production Deploy#2460

Merged
Marfuen merged 5 commits intoreleasefrom
main
Apr 6, 2026
Merged

[comp] Production Deploy#2460
Marfuen merged 5 commits intoreleasefrom
main

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

@github-actions github-actions bot commented Apr 3, 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.

…m Yes to No and not the other way around

CS-208: [Bug] - Statement of Applicability only allows you to change answers from Yes to No and not the other way around
@cursor
Copy link
Copy Markdown

cursor bot commented Apr 3, 2026

PR Summary

Medium Risk
Moderate risk: refactors the vendor risk-assessment Trigger.dev task (parallel Firecrawl calls, metadata-driven UI refresh, DB updates) and replaces Trust Portal Vercel/DNS integration plumbing, which could impact long-running jobs and domain verification edge cases.

Overview
Vendor risk assessment now runs with parallel core+news research and realtime progress reporting. The Trigger.dev task splits Firecrawl work into firecrawlResearchCore and firecrawlResearchNews, streams progress via run metadata (phase/messages), writes core results first (risk level, links, certifications, badges, logo), then merges news into GlobalVendors when available, with improved error handling/reset behavior.

Risk assessment outputs are broadened and surfaced more consistently. Compliance badge extraction now passes through all verified certs (normalizing known types), frontend certification filtering no longer whitelists a few types, vendor list/detail pages show an explicit Researching state and a new VendorResearchFeed, and Trust Portal vendor enrichment can backfill badges from GlobalVendors data.

Audit + Trust Portal plumbing improvements. Audit logging gains action-specific descriptions for POST sub-endpoints like vendors/:id/trigger-assessment, and Trust Portal domain management replaces Axios + external DNS lookup with a fetch wrapper for Vercel API calls and Node dns-based verification.

Reviewed by Cursor Bugbot for commit 540b2fc. Bugbot is set up for automated code reviews on this repo. Configure here.

@vercel
Copy link
Copy Markdown

vercel bot commented Apr 3, 2026

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

Project Deployment Actions Updated (UTC)
comp-framework-editor Ready Ready Preview, Comment Apr 6, 2026 8:12pm
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
app (staging) Skipped Skipped Apr 6, 2026 8:12pm
portal (staging) Skipped Skipped Apr 6, 2026 8:12pm

Request Review

…in tables (#2461)

Removes hard-coded max-w-[300px] from framework description and requirement
name/description cells so text is no longer hidden beyond 60% of the column.

Co-authored-by: Mariano Fuentes <marfuen98@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: add @chenglou/pretext for vendor research feed animations

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor(vendor): extract shared firecrawl utilities

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(vendor): add research metadata types and data merge helper

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(vendor): add VendorNewsLoadingPlaceholder component

* feat(vendor): add news research firecrawl agent

* feat(vendor): add core research firecrawl agent (certs, links, assessment)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(vendor): parallel firecrawl calls with trigger.dev metadata progress

Replace the single firecrawl call with parallel core + news research
using Promise.allSettled. Progressive DB writes land core data first,
then merge news. Trigger.dev metadata tracks phase, messages, and
per-agent readiness for real-time frontend consumption.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(vendor): add VendorResearchFeed component with animated progress messages

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(vendor): add staggered entry animations to risk assessment cards

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(vendor): three-phase rendering with research feed, card reveal, and news arrival

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore(vendor): deprecate single firecrawl agent in favor of parallel core+news agents

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): show research feed during regeneration when assessment already exists

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore(vendor): add structured logging throughout risk assessment task

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(vendor): overhaul research feed UI with drip-feed animation and filler messages

- Messages now appear one-at-a-time with 600ms delay between each
- Simulated "scanning..." filler messages keep the feed alive during long Firecrawl pauses
- Gradient header bar, slide-in animations, colored backgrounds for found/error items
- Bouncing dots indicator at the bottom while active
- Bumped news maxCredits from 300 to 500 (was hitting limit)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): use design system color tokens, switch to risk-assessment tab on regenerate

- Replace all raw Tailwind colors (blue-400, emerald-500, etc.) with DS tokens
  (primary, success, destructive, muted-foreground, accent-foreground)
- Auto-switch to risk-assessment tab when user clicks Regenerate Assessment
- Make Tabs controlled so we can programmatically switch tabs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(vendor): integrate Pretext for jank-free feed height animation

Use Pretext prepare() + layout() to predict message list height without
DOM measurement. The container animates to the predicted height via CSS
transition, eliminating layout thrash as new messages drip in.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): remove Pretext height prediction causing bounce artifact

The predicted height didn't match actual DOM layout (font metrics mismatch),
causing the container to bounce up then scroll down. Reverted to natural
content flow — the drip-feed + slide-in animations are the real visual effect.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(vendor): redesign research feed with rolling window and findings counter

- Only show last 5 messages, older ones fade progressively (like Perplexity)
- 35 unique filler messages picked randomly without repeats
- Live findings counter at bottom ("2 certifications · 3 links · assessment")
- Filler interval reduced to 3.5s for more dynamic feel

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): hide stale certification badges and links during regeneration

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): replace misleading filler messages with honest crawling activity

Filler messages now describe what the agent is doing (reading pages, following
links, crawling subdomains) instead of implying specific findings that haven't
actually been discovered yet.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): show all verified certifications instead of hardcoded whitelist

The certification display was limited to a whitelist of 5 types (SOC 2,
ISO 27001, ISO 42001, HIPAA, ISO 9001), silently dropping valid certs
like FedRAMP, TISAX, C5, ISO 27017/27018/27701, CCPA, CSA, etc.

Now all verified certifications are shown. Known types get normalized to
canonical slugs, unknown types are passed through as-is.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(vendor): stagger real findings in feed, remove fake filler messages

Backend now reports each finding individually with real delays between
metadata pushes (700ms between certs, 500ms between links, etc.) so the
UI shows them appearing one by one. Every message is now a real finding
or honest status — no more simulated filler messages.

Frontend simplified to just render metadata messages directly with a
rolling window (last 6 visible, older fade out) and a findings counter.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): remove green background from found items in research feed

The bg-success/10 on every "found" message made the feed look like a
wall of green cards. Green text + checkmark icon is sufficient to
indicate findings without the heavy background highlight.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(vendor): replace text feed with radar visualization + finding badges

Animated security radar with sweep line and pulsing blips that appear
as findings are discovered. Certifications show as green badge chips,
links as blue badge chips, organized in labeled sections. Shimmer bar
at top, status text at bottom. Way more visually engaging than the
plain text feed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(vendor): add scanning checklist with pending/done states, remove bottom status text

Right side now shows 4 categories (Certifications, Links, Assessment, News)
each with a spinner → checkmark transition. Badge chips appear under each
category as findings arrive. Removed redundant status text at the bottom.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(vendor): visible radar sweep line, centered empty state, responsive layout

- Sonar sweep line now uses 0.8 opacity with gradient trail — visible on
  light theme, spins every 2.5s
- Empty state: large centered radar (200px) with horizontal checklist below
- With findings: compact side-by-side (160px radar + badges)
- Radar size prop for responsive sizing between states

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): use named CSS keyframes for radar sweep and blip animations

Tailwind arbitrary animation syntax (animate-[spin_2.5s...]) wasn't
rendering. Added proper @Keyframes radar-sweep in globals.css and
applied via inline style. Blips now use standard animate-pulse.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): fix invisible radar sweep, reduce finding delays

- Sweep line and shimmer bar now use Tailwind classes (from-primary/80)
  instead of hsl(var(--color-primary)) which didn't work with oklch colors
- Blip glow uses theme() shadow instead of hsl
- Reduced sleep delays between findings from 500-800ms to 150-400ms
  to eliminate the empty white space gap before badges render

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): use Tailwind animate-spin for radar sweep instead of custom keyframes

Custom @Keyframes wasn't being applied. Switched to Tailwind's built-in
animate-spin class with animationDuration override to 2.5s.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): replace div-based radar sweep with SVG for pixel-perfect alignment

The div-based sweep line and trail had mismatched transform origins causing
them to spin disconnected. Replaced with a single SVG element containing
both the gradient line and trail cone, sharing the same coordinate space.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): thinner sweep line (1px), darker gradient, narrower trail

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): use currentColor for radar sweep line — visible on all themes

theme(colors.primary) wasn't resolving in SVG stop-color. Switched to
currentColor with text-foreground class so the line inherits the dark
foreground color. Removed defs/linearGradient in favor of simple opacity.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): simplify radar sweep to single div line, remove trail cone

SVG trail was misaligned during rotation. Replaced with a simple div
line from center to edge using bg-foreground/40. Clean and guaranteed
to spin correctly since animate-spin rotates the parent container.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): use primary color for radar sweep line

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(vendor): replace radar with card-based research feed

4 category cards shown immediately as ghost/dashed placeholders with
shimmer skeletons. Each transforms into a filled card with badge chips
as findings arrive. Status pill shows current activity. Never empty,
never stuck — always something visible and animating.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(vendor): add animated AI research agent with rotating states

Replaces the static status text pill with an animated agent that cycles
through research actions every 2.5s: searching, reading, analyzing,
checking security, reviewing compliance, following links. Each state
has an emoji icon that rotates in/out with a scale+rotate animation
and a label that slides in from below. Pulsing ring behind the icon.
Always animating, never feels stuck.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(vendor): add scanning magnifying glass animation over card grid

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): use Motion animate for scanning glass instead of CSS keyframes

CSS @Keyframes in globals.css get purged by Tailwind v4. Switched to
Motion's animate prop with keyframe arrays for the 4-position scan
path (top-left → top-right → bottom-right → bottom-left). 6s loop.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): show research feed on page refresh when vendor is in_progress

The page now checks vendor.status from the DB, not just React state.
If vendor is in_progress (research running), the research feed shows
even without a realtime subscription (page was refreshed). The SWR
3-second polling will detect when status changes to assessed and
transition to showing the results.

Also hides stale certification badges and links when vendor is
in_progress (not just during the session that triggered it).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): center scanning glass on cards, seamless infinite loop

Glass lens now points at card centers using 25%/75% positions with
-15px translate offset. Last keyframe matches first for seamless
loop with linear easing — no pause between cycles.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): equal timing for all 4 scanning glass segments

Each move (right, down, left, up) now gets exactly 25% of the 6s
duration. Previously the last segment got 40% making it feel sluggish.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(vendor): highlight card being scanned by magnifying glass

Cards get a shadow + primary ring glow when the scanning glass
hovers over them. Uses a synchronized timer (1.5s per card) matching
the 6s glass animation. Highlight only applies to pending cards —
completed cards keep their solid appearance.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): derive active card from glass position instead of separate timer

Uses Motion's onUpdate callback to read the actual animated top/left
values and derive which quadrant (card) the glass is over. No more
timer synchronization — the highlight follows the glass exactly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): adjust scanning glass timing for consistent perceived speed

Horizontal moves (wider cards) now get 35% of the duration each,
vertical moves (shorter) get 15%. This compensates for the 2x2 grid
being wider than tall, making the glass appear to move at a constant
speed regardless of direction. Total duration bumped to 8s.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): center scanning glass lens on card centers visually

Increased translate offset to -18px to account for the SVG handle
pulling visual weight below the lens center. Adjusted vertical
positions from 25%/75% to 28%/72% to better match actual card
centers within the grid (accounting for gap and padding).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): nudge scanning glass higher on cards (22%/68%)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(vendor): scanning glass does small circle on each card before moving on

The glass now arrives at a card center, traces a small circle (4%
radius) clockwise around it like it's examining the card, then travels
to the next card. 25 keyframes total for 4 cards with seamless loop.
68% of time spent scanning (circles), 32% traveling between cards.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): use 8-point circle for smooth scanning motion instead of 4-point cross

Linear interpolation between 4 cardinal points (top/right/bottom/left)
creates a diamond shape. Using 8 points at 45° intervals approximates
a proper circle since Motion linearly interpolates between closer points.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): tighter scanning circle with oval shape matching card aspect ratio

Reduced horizontal radius from 4% to 2.5% and vertical from 4% to 3.5%.
The oval shape matches the card aspect ratio so the circle motion looks
proportional and stays well within the card boundaries.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): 16-point circle for smoother scanning motion

Doubled from 8 to 16 points (every 22.5°) for a nearly perfect
circle with linear interpolation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): compensate for container aspect ratio to make circle visually round

Grid container is ~2x wider than tall, so equal % radii look like a
wide oval. Reduced horizontal radius to 1.8% vs 3.5% vertical to
produce a visually circular scanning motion.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): use pixel radius for scanning circle — always perfectly round

Percentage-based radii produced ovals because the container is wider
than tall. Now uses a fixed 20px pixel radius with calc() offsets
from percentage card centers. Circle is always round regardless of
container dimensions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): smooth transition from circle to travel with easeInOut

Switched from linear to easeInOut easing so the glass gently decelerates
at the end of each circle, smoothly accelerates to travel, and gently
decelerates arriving at the next card. Also rebalanced timing: 12% travel
vs 13% circle (was 8% vs 17%) to reduce the speed contrast.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): smooth circle-to-travel transition, fix hover detection during circle

1. Circle now starts and ends at card center with settle keyframes,
   so there's no jump from center → top of circle or circle end → next card.
   Flow: arrive center → settle → circle → return to center → settle → travel.

2. Hover detection now parses percentage from calc() strings like
   "calc(22% + -20px)" using regex, instead of parseFloat which returned
   NaN for calc values and broke the card highlight during circle motion.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): smooth spiral loop — no jumps between center and circle

The scanning path now spirals out from center, loops around at full
radius, and spirals back to center using sin(progress * π) as a
radius ramp factor. This means the path starts and ends exactly at
the card center with zero discontinuity — the glass smoothly flows
from travel → spiral out → circle → spiral in → travel to next card.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(vendor): scanning glass only visits pending cards, disappears when all done

The glass now dynamically builds its path from only the cards that
haven't received findings yet. As cards complete, the glass skips them
and only travels between remaining pending cards. When one card is left
it just circles on that card. When all cards are done, the glass
disappears. Animation remounts (key change) when pending set changes
to restart cleanly with the new path.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): one continuous curve — no phase transitions, no jerks

Replaced the phase-based approach (spiral at card + travel to next)
with a single continuous parametric curve. The base position smoothly
eases between card centers using an S-curve, while a sinusoidal overlay
adds one circular loop per card. The glass is always moving AND looping
simultaneously — there are no separate phases, no stops, no velocity
discontinuities. Linear timing since easing is baked into the path.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): revert to 2-phase animation with 32-point circle, no spiral ramp

Reverted the continuous curve approach — it didn't feel smooth either.
Back to separate circle + travel phases but with improvements:
- 32 points for buttery smooth circle (was 16-20)
- Constant radius circle (no spiral ramp that caused stops)
- easeInOut smooths the transition between phases

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): restore spiral ramp (center→circle→center) with 32 points

Brought back the sin(progress * π) radius ramp so the glass smoothly
spirals out from center, reaches full radius at the midpoint, and
spirals back to center. Now with 32 points for a much smoother curve
than the original 16-20 point versions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): increase scanning circle radius from 18px to 30px

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): center scanning glass vertically on cards (27%/73%)

Moved from 22%/68% to 27%/73% so the circle is visually centered
within each card instead of sitting too high.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): adjust card centers (24%/70%) and reduce circle radius to 25px

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): shift scanning glass up 6px to center lens on cards

The SVG handle extends below the lens, pulling the visual center down.
Increased vertical offset from -18px to -24px so the lens circle
(not the bounding box) is centered on each card.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): reset card centers to true 25%/75% and translate to -20px

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): move circle centers up to 22%/72%

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): move circle centers down to 30%/77% so top of circle reaches card top

The circle radiates 25px above and below the center point. Moving
centers down means the top of the circle arc reaches the upper part
of the card instead of floating above it.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): move circle centers UP to 18%/68% so circle is visually centered on cards

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(vendor): show "AI research in progress" badge below vendor description

Pulsing primary dot + text badge appears below the vendor description
when research is active (either from this session or detected via
vendor.status === in_progress on page load).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): change badge text to "Researching vendor"

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): move "Researching vendor" badge above title, below breadcrumbs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): move "Researching vendor" badge above breadcrumbs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): minimal research indicator — small dot + muted text, no pill

Replaced the full-width pill badge with a minimal inline indicator:
tiny pulsing dot + "Researching vendor" in muted text. Subtle and
clean, doesn't dominate the page.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): move research indicator inline next to vendor name

Small "Researching" badge sits right next to the vendor title, where
the certification badges normally appear. Contextual, compact, no
extra line of space. Like GitHub's "Private" badge next to repo names.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): remove pulsating dot from research feed header

The inline badge next to the vendor name already indicates research
is active — the dot in the card header was redundant.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(vendor): add timing estimate and leave-page notice below research header

"This may take 1-3 minutes depending on the vendor. You can leave
this page — we'll notify you when it's done."

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): use Text secondary variant, add spacing between header and cards

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): tighten gap between research title and description

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): remove em dashes from research timing text

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): correct timing estimate to 1-10 minutes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): use variant="muted" for research description text

DS Text component uses "muted" not "secondary" for subdued text.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): measure card centers dynamically with refs instead of hardcoded %

The scanning glass now uses ResizeObserver + getBoundingClientRect to
measure actual card center positions relative to the grid container.
When cards expand with content, the glass path updates automatically.
No more hardcoded percentage positions that drift when cards resize.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): traverse cards in clockwise visual order (TL→TR→BR→BL)

Grid indices are 0=TL, 1=TR, 2=BL, 3=BR (row-major), but the scanning
glass should move clockwise: 0→1→3→2. Previously went 0→1→2→3 which
caused a diagonal jump from top-right to bottom-left.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(vendor): show "Researching" indicator in vendors table for in_progress vendors

Name column: small badge with pulsing dot + "Researching" next to vendor name
Status column: spinner + "Researching..." in primary color

Triggers when vendor.status === 'in_progress' in the DB, which covers
both onboarding assessments and manual regeneration.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): add research indicator to the actual VendorsTable component

The previous commit edited VendorColumns.tsx but the table uses its own
VendorNameCell and VendorStatusCell inside VendorsTable.tsx. Fixed the
correct file — name shows "Researching" badge, status shows spinner.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): remove redundant "Researching..." from status column

The badge on the name is enough. Status column shows the normal
VendorStatus component as before.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): skip audit log for trigger-assessment endpoint

The POST method caused the AuditLogInterceptor to log "Created vendor"
when triggering a risk assessment regeneration. Added @SkipAuditLog()
since triggering an assessment is not a vendor creation — the actual
assessment completion is already logged by the trigger.dev task itself.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): audit log says "Triggered vendor risk assessment" not "Created vendor"

Added extractActionDescription() to audit-log.utils.ts that detects
sub-action POST endpoints (like /trigger-assessment) and returns a
correct description. The interceptor now checks this before falling
back to the generic "Created <resource>" description.

Reverted @SkipAuditLog — the action IS logged, just with the right text.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): eliminate flash of old results when clicking regenerate

Two fixes:
1. isRegenerating alone now triggers the research feed immediately,
   without waiting for the realtime connection to establish. This
   closes the window where old data could flash.
2. setIsRegenerating + setActiveTab now fire BEFORE refreshVendor()
   so React batches the state updates and renders the feed before
   the SWR refresh brings back old riskAssessmentData.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): bump maxCredits to 2500 (default) for both core and news agents

News was hitting the 500 credit limit on larger vendors like GitHub.
Core was at 700. Both now use Firecrawl's default limit of 2500.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: remove PrismaInstrumentation from trigger.dev config

Prisma's OpenTelemetry instrumentation was flooding trigger.dev logs
with internal spans (prisma:client:operation, serialize, compile,
db_query) making actual task logs unreadable. Removed the
PrismaInstrumentation — Prisma queries still work, they just
don't emit trace spans to trigger.dev anymore.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(vendor): upgrade to spark-1-pro, add schema descriptions, improve prompts

Three improvements to Firecrawl research quality:

1. Upgraded both core and news agents from spark-1-mini to spark-1-pro
   (~50% recall vs ~40%, 25% better accuracy for security research)

2. Added description fields to all schema properties so the AI knows
   exactly what to extract (e.g. "Direct URL to the certification
   report or trust page on the vendor domain")

3. Improved news prompt with prioritized categories (security incidents
   first), cap of 10 items, and specific source suggestions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): rename "Links" to "Security Links" in research feed and assessment view

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): allow third-party trust portal URLs in vendor research

URLs like ghec.github.trust.page were filtered out because the domain
validation only allowed exact vendor domain matches. Now also accepts
URLs on well-known trust portal domains (SafeBase, Vanta, Drata, etc.)
when the vendor name appears in the hostname.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): stop filtering URLs by domain, trust the AI agent

Vendors host trust portals on arbitrary domains (SafeBase, Vanta,
custom domains) that no allowlist can fully cover. The Firecrawl
spark-1-pro agent already has a clear prompt and returns relevant
URLs intentionally. Now we just validate the URL is well-formed
HTTP(S) and let the agent's judgment stand.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): replace text-red-600 with text-destructive in certifications card

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): use primary color for Recent News card instead of success green

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): render news and links as text list instead of badge chips

Certifications and assessment keep the badge chip style (green bg).
News and security links now render as a simple text list in
muted-foreground — looks like actual content, not tags.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): style news/links items as link text (text-primary + hover:underline)

Matches the DS Button variant="link" style: text-primary with
underline-offset-4 and hover:underline.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vendor): rewrite prompt to prefer trust portals over docs pages

- Removed the "only return URLs from vendor domain" restriction since
  vendors use third-party trust portals (SafeBase, Vanta, etc.)
- Explicitly tells the agent to prefer the dedicated trust portal
  where customers request reports, NOT documentation pages
- Lists common trust portal platforms by name so the agent knows
  what to look for (trust.page, safebase.io, vanta.com)
- Expanded certification types in the prompt for better discovery
- Updated trust_center_url schema description to reinforce preference

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(vendor): make research feed findings clickable with real URLs

Backend now includes URLs in metadata messages for certs, links,
and news items. Frontend renders them as clickable: cert badges
open on click, links/news are anchor tags with hover:underline.

Also added search tip to the prompt: "Try searching '<vendor> trust
portal'" to help the agent find trust centers not directly linked
from the vendor site.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(vendor): show "+X more" for certifications without icons in title badges

Certs with icons (SOC 2, ISO 27001, ISO 42001, HIPAA) show as badge
icons. Remaining certs without icons (FedRAMP, TISAX, C5, etc.) are
counted and shown as "+X more" text at the end.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: address code review findings

Critical fixes:
- Fix failing test: validateVendorUrl no longer filters by domain
- Fix null core result silently marking vendor as "assessed" with no data
  — now throws so the catch handler resets status properly

Cleanup:
- Remove unused @chenglou/pretext dependency
- Remove dead CSS keyframes (shimmer-bar, scan-cards, radar-sweep)
- Add url field to frontend ResearchMessage type, remove unsafe cast
- Fix spark-1-pro model param type error (SDK types lag behind API)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Mariano Fuentes <marfuen98@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…-in resolver (#2463)

The DNS verification for custom trust portal domains was failing because
it relied on networkcalc.com, an unreliable external API. This caused
domainVerified to stay false, which made the trust portal middleware
redirect custom domains to trycomp.ai instead of serving the portal.

Replaced with Node's built-in dns.promises resolver (matching the
existing server action pattern). Also removed axios dependency from
the service, replacing it with native fetch for Vercel API calls.

Co-authored-by: Mariano Fuentes <marfuen98@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@vercel vercel bot temporarily deployed to staging – portal April 6, 2026 20:11 Inactive
@vercel vercel bot temporarily deployed to staging – app April 6, 2026 20:11 Inactive
@claudfuen
Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 3.16.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Copy link
Copy Markdown

@cursor cursor bot left a comment

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 and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 540b2fc. Configure here.

await db.vendor.update({
where: { id: vendor.id },
data: { status: VendorStatus.assessed },
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Failed assessment incorrectly marks vendor as "assessed"

High Severity

The catch block sets the vendor status to VendorStatus.assessed when the risk assessment fails. The VendorStatus enum has three values: not_assessed, in_progress, and assessed. On failure, the vendor appears successfully assessed in the UI despite having no (or incomplete) risk assessment data. The error message at the throw site even says "vendor will not be marked as assessed," directly contradicting what the catch block does. The status needs to be reset to not_assessed instead of assessed.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 540b2fc. Configure here.

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