Skip to content

feat(security): implement end-to-end security pillar#34

Merged
Arzu-N merged 50 commits into
mainfrom
feature/security-pillar
Jun 30, 2026
Merged

feat(security): implement end-to-end security pillar#34
Arzu-N merged 50 commits into
mainfrom
feature/security-pillar

Conversation

@Arzu-N

@Arzu-N Arzu-N commented Jun 28, 2026

Copy link
Copy Markdown
Member

What does this change?

  • add entities and repositories for secrets, vulnerabilities, and code alerts
  • implement scan workers for github findings ingestion
  • add endpoints for security findings with contract shapes
  • implement vulnerability priority calculation and storage
  • add unit tests for scanners and controllers

Related issue

Closes #8

Area

  • Frontend (apps/web)
  • Backend
  • Docs
  • Other

Screenshots

If this touches the UI, drop before and after screenshots here.

Checklist

  • I ran bun run typecheck && bun run build in apps/web (for frontend changes)
  • I bumped the version if this is a meaningful change
  • Commits are small and focused, with no AI attribution lines
  • I updated docs or AGENTS.md if behavior or structure changed

Summary by CodeRabbit

  • New Features
    • Added API endpoints to create code scan alerts, secret findings, and vulnerabilities, including vulnerability lookup by ID.
    • Extended the dashboard dataset to include code scan alerts.
    • Added vulnerability priority calculation and included priority in vulnerability responses.
  • Bug Fixes
    • Improved API error handling with consistent JSON responses for not found and unexpected server errors.
  • Tests
    • Added web-layer and scanner workflow tests for the new endpoints and processing.
  • Refactor
    • Updated internal processing and mapping to support code scan alerts end-to-end.

@coderabbitai

coderabbitai Bot commented Jun 28, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Implements the security pillar end to end: adds alert and vulnerability contracts, persistence schema, dedicated mappers, scanning services, REST endpoints, exception handling, a scheduled worker, and related tests.

Changes

Security Pillar: Code Scan Alerts and Vulnerability Priority

Layer / File(s) Summary
Contracts and domain types
backend/libs/common/src/main/java/dev/cleat/common/enums/Priority.java, ...enums/Status.java, ...dto/request/CodeScanAlertRequestDto.java, ...dto/response/CodeScanAlertResponseDto.java, ...dto/response/VulnerabilityResponseDto.java, ...dto/response/DatasetDto.java, backend/libs/domain/...
Adds Priority and Status enums, code scan alert request/response DTOs, priority on VulnerabilityResponseDto, codeAlerts on DatasetDto, the domain Vulnerability record, and PriorityCalculator.
Persistence entities and migrations
backend/libs/persistence/src/main/java/dev/cleat/persistence/entity/CodeScanAlertEntity.java, ...entity/VulnerabilityEntity.java, ...repository/CodeScanAlertRepository.java, ...resources/db/migration/V2__...sql, V3__...sql, V4__...sql, V5__...sql
Adds the code scan alert entity and repository, extends vulnerability persistence with priority, and adds the alert table migration, vulnerability column migration, timestamp default change, and index statements.
Dedicated persistence mappers and DashboardService wiring
backend/libs/persistence/src/main/java/dev/cleat/persistence/mapper/*, ...persistence/DashboardService.java
Removes CleatMapper, adds focused mappers for accounts, activity events, members, repos, scorecards, secrets, usage, vulnerabilities, and code scan alerts, and rewires dataset assembly to include code alerts.
Scanners and scanning services
backend/libs/scanning/src/main/java/dev/cleat/scanning/CodeScanAlertScanner.java, ...SecretFindingScanner.java, ...VulnerabilityScanner.java, ...service/CodeScanAlertService.java, ...service/SecretFindingService.java, ...service/VulnerabilityService.java, backend/libs/scanning/src/test/..., backend/libs/scanning/build.gradle.kts
Adds scanners and service wrappers for alerts, secrets, and vulnerabilities, including priority calculation and module test setup with unit coverage.
REST controllers and exception handling
backend/apps/api/src/main/java/dev/cleat/api/controller/*, ...exception/GlobalExceptionHandler.java, ...CleatApiApplication.java, backend/apps/api/src/test/java/dev/cleat/api/*
Adds three REST controllers, a global exception handler, API scan package expansion, and controller/integration test updates.
Worker scheduling and build wiring
backend/apps/worker/src/main/java/dev/cleat/worker/VulnerabilityWorker.java, ...CleatWorkerApplication.java, backend/apps/worker/build.gradle.kts, backend/apps/worker/src/test/...
Adds the scheduled vulnerability worker, explicit worker application scanning/JPA configuration, worker test dependencies, and worker test context updates.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant VulnerabilityController
  participant VulnerabilityService
  participant VulnerabilityScanner
  participant PriorityCalculator
  participant VulnerabilityRepository

  Client->>VulnerabilityController: POST /api/v1/vulnerabilities
  VulnerabilityController->>VulnerabilityService: create(requestDto)
  VulnerabilityService->>VulnerabilityScanner: processAndSave(entity)
  VulnerabilityScanner->>PriorityCalculator: calculate(Vulnerability)
  PriorityCalculator-->>VulnerabilityScanner: Priority
  VulnerabilityScanner->>VulnerabilityRepository: save(entity with priority)
  VulnerabilityScanner-->>VulnerabilityService: updated entity
  VulnerabilityService-->>VulnerabilityController: VulnerabilityResponseDto
  VulnerabilityController-->>Client: 201 Created
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • Devlaner/cleat#32: Touches CleatApiApplication, DatasetDto, and dashboard wiring that this PR extends.

Suggested reviewers

  • martian56

Poem

🐇 A rabbit hops through code so bright,
Alerts now scan by day and night.
Priority rises, status shows,
And workers run where security flows.

🚥 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 is concise and accurately summarizes the PR’s main security-pillar implementation.
Linked Issues check ✅ Passed The PR appears to satisfy #8 by adding the required entities, endpoints, scan workers, and vulnerability priority storage.
Out of Scope Changes check ✅ Passed No clear unrelated changes stand out; the build and test updates support the security feature work.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/security-pillar

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

@coderabbitai coderabbitai 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.

Actionable comments posted: 19

🧹 Nitpick comments (4)
backend/apps/api/src/test/java/dev/cleat/api/CodeScanAlertControllerTest.java (1)

33-43: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Assert the response contract, not only the status.

This test currently passes even if CodeScanAlertController.create(...) returns the wrong body, because the mock is unstubbed and only 201 is asserted. Given the PR objective is to return the expected contract shapes, stub codeScanAlertService.create(...), verify delegation, and assert the JSON fields you expect back.

🤖 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
`@backend/apps/api/src/test/java/dev/cleat/api/CodeScanAlertControllerTest.java`
around lines 33 - 43, The test for CodeScanAlertController.create is only
checking the HTTP status, so it can pass even if the response body is wrong. In
CodeScanAlertControllerTest, stub codeScanAlertService.create(...) with the
expected DTO, verify the controller delegates to that service method, and add
JSON assertions on the returned payload to validate the response contract
instead of only asserting 201.
backend/apps/api/src/test/java/dev/cleat/api/SecretFindingControllerTest.java (1)

33-43: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Cover the returned DTO shape as well.

SecretFindingController.createSecret(...) returns a created body, but this test only checks the status code. Stub secretFindingService.create(...), verify it was called, and assert the response JSON so this actually guards the contract introduced in this PR.

🤖 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
`@backend/apps/api/src/test/java/dev/cleat/api/SecretFindingControllerTest.java`
around lines 33 - 43, The SecretFindingControllerTest currently only verifies
the 201 status and does not validate the returned DTO contract. Update
whenCreateSecret_thenShouldReturn201() to stub secretFindingService.create(...),
verify that create(...) is invoked, and assert the response JSON/body shape from
SecretFindingController.createSecret(...) so the test covers the created
response payload as well as the status.
backend/apps/api/src/test/java/dev/cleat/api/VulnerabilityControllerTest.java (1)

33-43: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Assert the vulnerability payload, not just 201 Created.

This endpoint’s response now includes security-specific fields such as priority, but the test never checks them. Stub vulnerabilityService.create(...), verify the call, and assert the returned JSON so the contract change is actually protected.

🤖 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
`@backend/apps/api/src/test/java/dev/cleat/api/VulnerabilityControllerTest.java`
around lines 33 - 43, The create-vulnerability test currently only checks for
201 Created and does not verify the response contract. Update
whenCreateVulnerability_thenShouldReturn201 in VulnerabilityControllerTest to
stub vulnerabilityService.create(...), verify that the controller invokes it,
and assert the returned JSON payload includes the security-specific fields such
as priority. Use the existing MockMvc setup and ObjectMapper to validate the
response body instead of only the status.
backend/libs/scanning/src/main/java/dev/cleat/scanning/CodeScanAlertScanner.java (1)

22-27: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove the dead severity branch or implement the missing mapping.

Lines 22-27 set Status.OPEN in both paths, so severity currently has no effect. If all new alerts should start open, collapse this to one assignment; otherwise the low/medium rule is missing here.

🤖 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
`@backend/libs/scanning/src/main/java/dev/cleat/scanning/CodeScanAlertScanner.java`
around lines 22 - 27, The severity check in CodeScanAlertScanner is dead code
because both branches set the same Status.OPEN value. Update the scan alert
mapping logic in the method that processes CodeScanAlertEntity so either all
severities are assigned OPEN with a single assignment, or add the missing
low/medium severity-specific status mapping if that was intended. Use the
Severity, Status, and CodeScanAlertEntity symbols to locate and simplify the
conditional.

Source: Linters/SAST tools

🤖 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
`@backend/apps/api/src/main/java/dev/cleat/api/exception/GlobalExceptionHandler.java`:
- Around line 18-21: The RuntimeException handler in GlobalExceptionHandler is
exposing raw exception text in the 500 response; change handleRuntimeException
to return a generic client-facing message instead of ex.getMessage(), and add
server-side logging of the exception details for debugging. Keep the response
body consistent and update the ResponseEntity/Map.of usage so only a safe
generic error string is returned.

In
`@backend/apps/api/src/test/java/dev/cleat/api/CodeScanAlertControllerTest.java`:
- Line 34: Rename the test method in CodeScanAlertControllerTest to satisfy the
MethodName Checkstyle rule by removing underscores from
whenCreateCodeScanAlert_thenShouldBeReturn201; keep the same test behavior, but
use a camelCase method name so the class continues to compile and CI passes.

In
`@backend/apps/api/src/test/java/dev/cleat/api/SecretFindingControllerTest.java`:
- Line 34: The test method name in SecretFindingControllerTest does not match
the configured MethodName pattern, causing Checkstyle failure. Rename
whenCreateSecret_thenShouldReturn201 to a valid lowerCamelCase test name that
fits the project’s naming rules, and keep the behavior and assertions unchanged.

In
`@backend/apps/api/src/test/java/dev/cleat/api/VulnerabilityControllerTest.java`:
- Line 34: Rename the test method whenCreateVulnerability_thenShouldReturn201 to
match the configured camelCase test naming rule used by Checkstyle, keeping it
in VulnerabilityControllerTest and preserving the same test behavior. Update
only the method identifier so the name uses standard lowerCamelCase while still
clearly describing the create vulnerability success case.

In
`@backend/apps/worker/src/main/java/dev/cleat/worker/CleatWorkerApplication.java`:
- Line 7: `CleatWorkerApplication` is not scanning the worker package, so
`VulnerabilityWorker` is never discovered and its scheduled job won’t run.
Update the `@SpringBootApplication` component scan on `CleatWorkerApplication`
to include `dev.cleat.worker` (or broaden it to `dev.cleat`) alongside the
existing `dev.cleat.persistence` and `dev.cleat.scanning` packages so the worker
bean is registered.

In `@backend/apps/worker/src/main/java/dev/cleat/worker/VulnerabilityWorker.java`:
- Around line 10-15: The VulnerabilityWorker constructor is incorrectly
injecting VulnerabilityEntity, which is a JPA entity and not a Spring-managed
bean. Update VulnerabilityWorker so it only injects the service/dependency that
provides scan input, and create or fetch the VulnerabilityEntity inside
runSecurityScan() or via a proper repository/service instead of constructor
injection. Keep the constructor signature aligned with the actual Spring bean
dependencies and ensure the worker no longer depends on a directly injected
entity instance.

In
`@backend/libs/common/src/main/java/dev/cleat/common/dto/request/VulnerabilityRequestDto.java`:
- Line 3: Remove client-write access to priority from the vulnerability
create/update flow: VulnerabilityRequestDto should no longer expose or carry a
writable priority field, since it must be derived server-side. Update
VulnerabilityMapper.toVulnerabilityEntity(...) so it stops copying getPriority()
from the request DTO into VulnerabilityEntity, and compute/set priority in the
server-side mapping/service path based on CVSS/KEV/severity. Also remove any
unused Priority import and related DTO accessors/constructors tied to
request-supplied priority.

In `@backend/libs/domain/src/main/java/dev/cleat/domain/model/Vulnerability.java`:
- Line 5: The Vulnerability record currently allows nullable cvss and severity
values, but PriorityCalculator and VulnerabilityScanner assume both are present
for comparisons and switching. Update Vulnerability to enforce its invariants in
the canonical constructor, or adjust PriorityCalculator to handle missing
cvss/severity explicitly before doing numeric checks or the severity switch,
using the Vulnerability record, VulnerabilityScanner, and PriorityCalculator
symbols to locate the flow.

In `@backend/libs/domain/src/main/java/dev/cleat/domain/PriorityCalculator.java`:
- Around line 9-21: PriorityCalculator.calculate currently dereferences nullable
Vulnerability fields before the priority decision, causing failures instead of a
safe priority result. Update calculate(Vulnerability) to guard cvss() and
severity() up front: avoid auto-unboxing cvss() in the range check and handle
null severity before the switch, returning a sensible default priority when
either field is missing. Keep the existing URGENT/HIGH/MEDIUM/LOW mapping in
PriorityCalculator, but make the logic null-safe before evaluating the CVSS
threshold or switching on severity.

In
`@backend/libs/persistence/src/main/java/dev/cleat/persistence/entity/CodeScanAlertEntity.java`:
- Around line 56-57: The `detectedAt` field on `CodeScanAlertEntity` is
currently left unset before persistence, so `CodeScanAlertScanner` can save a
null value instead of relying on the timestamp default. Populate this field
either in `CodeScanAlertMapper` when building the entity or in a `@PrePersist`
hook on `CodeScanAlertEntity`, and ensure the `detectedAt` column is marked
non-null if the timestamp is required. Keep the fix centered on the entity
mapping/save flow so every alert has a timestamp before insert.

In
`@backend/libs/persistence/src/main/java/dev/cleat/persistence/mapper/ActivityEventMapper.java`:
- Around line 15-24: ActivityEventMapper is not null-safe when mapping the repo
field, so activityEventEntity.getRepo().getName() can throw if repo is absent.
Update the mapping logic in the mapper’s ActivityEventResponseDto conversion to
handle a null repo gracefully, either by guarding the getRepo() access before
calling getName() or by applying a required-field change consistently across the
entity/schema and mapper.

In
`@backend/libs/persistence/src/main/java/dev/cleat/persistence/mapper/SecretFindingMapper.java`:
- Around line 28-42: The SecretFindingMapper.toSecretFindingEntity create-flow
mapping is missing the account/repo data that SecretFindingService later needs
for the POST response. Update toSecretFindingEntity to also copy the account
identifier and repo association from SecretFindingRequestDto into
SecretFindingEntity so toSecretFindingDto can safely read getAccountId() and
getRepo().getName() without relying on scanner-side hydration.

In
`@backend/libs/persistence/src/main/java/dev/cleat/persistence/mapper/UsageMapper.java`:
- Around line 20-30: The UsageMapper.toUsageResponseDto mapping dereferences
usageEntity.getSeries() directly, which can fail when
DashboardService.getDataset(...) supplies a fallback new UsageEntity() with a
null series. Update the mapper to safely handle a null series by defaulting to
an empty list before streaming, or initialize the series field in the
UsageEntity fallback path, so the UsageResponseDto mapping remains valid for
empty-usage accounts.

In
`@backend/libs/persistence/src/main/resources/db/migration/V3_alter_vulnerability_table.sql`:
- Line 1: The V3_alter_vulnerability_table migration only adds the priority
column and leaves existing vulnerability rows with NULL values. Update the
rollout so the vulnerability table change is paired with a backfill or explicit
post-migration rescan, using the migration script or the related vulnerability
persistence/rescan flow, so existing records get populated with priority instead
of remaining incomplete.
- Line 1: Rename the Flyway migration file to use the default versioned format
with a double underscore so it is picked up automatically. Update the migration
named V3_alter_vulnerability_table.sql to V3__alter_vulnerability_table.sql,
keeping the ALTER TABLE vulnerability statement unchanged.

In
`@backend/libs/persistence/src/main/resources/db/migration/V4__create_code_scan_alerts_table.sql`:
- Line 7: The schema for code scan alerts is hardcoding branch to "main" in the
migration, which can store the wrong value when ingest data omits branch. Remove
the default from the branch column in V4__create_code_scan_alerts_table.sql so
it stays nullable, and ensure the real branch is set earlier in the ingest flow
instead of being synthesized in the database schema.

In
`@backend/libs/scanning/src/main/java/dev/cleat/scanning/VulnerabilityScanner.java`:
- Around line 23-37: Move the null/input validation in
VulnerabilityScanner.processAndSave out of the try block so invalid inputs are
rejected before any persistence or priority calculation work starts. Keep the
null guard for VulnerabilityEntity at the top of the method, then run the
Vulnerability/priorityCalculator flow inside the try, and ensure the catch only
handles downstream failures. Also avoid calling vulnerabilityEntity.getId() in
the error path unless the entity is known non-null, so a null payload doesn’t
trigger a second exception and hide the original failure.

In
`@backend/libs/scanning/src/test/java/dev/cleat/scanning/VulnerabilityScannerTest.java`:
- Around line 39-53: The test in VulnerabilityScannerTest is asserting against a
stubbed repository lookup instead of the actual save behavior. Update the
verification around VulnerabilityScanner.processAndSave(...) to assert directly
on vulnerabilityEntity after the call and verify that
vulnerabilityRepository.save(vulnerabilityEntity) was invoked. Keep the existing
priority expectations tied to the saved entity so the test validates persistence
rather than a mocked findById(...) path.
- Around line 60-67: The current test in VulnerabilityScannerTest only verifies
exception wrapping because priorityCalculator.calculate(...) is mocked to throw,
so it does not actually cover invalid CVSS handling. Update the test to either
use the real PriorityCalculator path with an out-of-range CVSS value in
VulnerabilityScanner.processAndSave, or rename the test/method to reflect that
it is testing downstream exception propagation rather than CVSS validation.

---

Nitpick comments:
In
`@backend/apps/api/src/test/java/dev/cleat/api/CodeScanAlertControllerTest.java`:
- Around line 33-43: The test for CodeScanAlertController.create is only
checking the HTTP status, so it can pass even if the response body is wrong. In
CodeScanAlertControllerTest, stub codeScanAlertService.create(...) with the
expected DTO, verify the controller delegates to that service method, and add
JSON assertions on the returned payload to validate the response contract
instead of only asserting 201.

In
`@backend/apps/api/src/test/java/dev/cleat/api/SecretFindingControllerTest.java`:
- Around line 33-43: The SecretFindingControllerTest currently only verifies the
201 status and does not validate the returned DTO contract. Update
whenCreateSecret_thenShouldReturn201() to stub secretFindingService.create(...),
verify that create(...) is invoked, and assert the response JSON/body shape from
SecretFindingController.createSecret(...) so the test covers the created
response payload as well as the status.

In
`@backend/apps/api/src/test/java/dev/cleat/api/VulnerabilityControllerTest.java`:
- Around line 33-43: The create-vulnerability test currently only checks for 201
Created and does not verify the response contract. Update
whenCreateVulnerability_thenShouldReturn201 in VulnerabilityControllerTest to
stub vulnerabilityService.create(...), verify that the controller invokes it,
and assert the returned JSON payload includes the security-specific fields such
as priority. Use the existing MockMvc setup and ObjectMapper to validate the
response body instead of only the status.

In
`@backend/libs/scanning/src/main/java/dev/cleat/scanning/CodeScanAlertScanner.java`:
- Around line 22-27: The severity check in CodeScanAlertScanner is dead code
because both branches set the same Status.OPEN value. Update the scan alert
mapping logic in the method that processes CodeScanAlertEntity so either all
severities are assigned OPEN with a single assignment, or add the missing
low/medium severity-specific status mapping if that was intended. Use the
Severity, Status, and CodeScanAlertEntity symbols to locate and simplify the
conditional.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8972a510-5ec3-459d-a880-7f6bdf28e730

📥 Commits

Reviewing files that changed from the base of the PR and between 066f931 and 2e3d219.

📒 Files selected for processing (50)
  • backend/apps/api/src/main/java/dev/cleat/api/CleatApiApplication.java
  • backend/apps/api/src/main/java/dev/cleat/api/controller/CodeScanAlertController.java
  • backend/apps/api/src/main/java/dev/cleat/api/controller/SecretFindingController.java
  • backend/apps/api/src/main/java/dev/cleat/api/controller/VulnerabilityController.java
  • backend/apps/api/src/main/java/dev/cleat/api/exception/GlobalExceptionHandler.java
  • backend/apps/api/src/test/java/dev/cleat/api/CodeScanAlertControllerTest.java
  • backend/apps/api/src/test/java/dev/cleat/api/SecretFindingControllerTest.java
  • backend/apps/api/src/test/java/dev/cleat/api/VulnerabilityControllerTest.java
  • backend/apps/worker/build.gradle.kts
  • backend/apps/worker/src/main/java/dev/cleat/worker/CleatWorkerApplication.java
  • backend/apps/worker/src/main/java/dev/cleat/worker/VulnerabilityWorker.java
  • backend/libs/common/src/main/java/dev/cleat/common/dto/request/CodeScanAlertRequestDto.java
  • backend/libs/common/src/main/java/dev/cleat/common/dto/request/VulnerabilityRequestDto.java
  • backend/libs/common/src/main/java/dev/cleat/common/dto/response/CodeScanAlertResponseDto.java
  • backend/libs/common/src/main/java/dev/cleat/common/dto/response/DatasetDto.java
  • backend/libs/common/src/main/java/dev/cleat/common/dto/response/VulnerabilityResponseDto.java
  • backend/libs/common/src/main/java/dev/cleat/common/enums/Priority.java
  • backend/libs/common/src/main/java/dev/cleat/common/enums/Status.java
  • backend/libs/domain/build.gradle.kts
  • backend/libs/domain/src/main/java/dev/cleat/domain/PriorityCalculator.java
  • backend/libs/domain/src/main/java/dev/cleat/domain/model/Vulnerability.java
  • backend/libs/persistence/src/main/java/dev/cleat/persistence/DashboardService.java
  • backend/libs/persistence/src/main/java/dev/cleat/persistence/entity/CodeScanAlertEntity.java
  • backend/libs/persistence/src/main/java/dev/cleat/persistence/entity/VulnerabilityEntity.java
  • backend/libs/persistence/src/main/java/dev/cleat/persistence/mapper/AccountMapper.java
  • backend/libs/persistence/src/main/java/dev/cleat/persistence/mapper/ActivityEventMapper.java
  • backend/libs/persistence/src/main/java/dev/cleat/persistence/mapper/CleatMapper.java
  • backend/libs/persistence/src/main/java/dev/cleat/persistence/mapper/CodeScanAlertMapper.java
  • backend/libs/persistence/src/main/java/dev/cleat/persistence/mapper/MemberMapper.java
  • backend/libs/persistence/src/main/java/dev/cleat/persistence/mapper/RepoMapper.java
  • backend/libs/persistence/src/main/java/dev/cleat/persistence/mapper/ScorecardCheckMapper.java
  • backend/libs/persistence/src/main/java/dev/cleat/persistence/mapper/SecretFindingMapper.java
  • backend/libs/persistence/src/main/java/dev/cleat/persistence/mapper/UsageMapper.java
  • backend/libs/persistence/src/main/java/dev/cleat/persistence/mapper/UsagePointMapper.java
  • backend/libs/persistence/src/main/java/dev/cleat/persistence/mapper/VulnerabilityMapper.java
  • backend/libs/persistence/src/main/java/dev/cleat/persistence/repository/CodeScanAlertRepository.java
  • backend/libs/persistence/src/main/resources/db/migration/V2__update_repo_and_add_tables.sql
  • backend/libs/persistence/src/main/resources/db/migration/V3_alter_vulnerability_table.sql
  • backend/libs/persistence/src/main/resources/db/migration/V4__create_code_scan_alerts_table.sql
  • backend/libs/persistence/src/main/resources/db/migration/V5__alter_secret_finding_table.sql
  • backend/libs/scanning/build.gradle.kts
  • backend/libs/scanning/src/main/java/dev/cleat/scanning/CodeScanAlertScanner.java
  • backend/libs/scanning/src/main/java/dev/cleat/scanning/SecretFindingScanner.java
  • backend/libs/scanning/src/main/java/dev/cleat/scanning/VulnerabilityScanner.java
  • backend/libs/scanning/src/main/java/dev/cleat/scanning/service/CodeScanAlertService.java
  • backend/libs/scanning/src/main/java/dev/cleat/scanning/service/SecretFindingService.java
  • backend/libs/scanning/src/main/java/dev/cleat/scanning/service/VulnerabilityService.java
  • backend/libs/scanning/src/test/java/dev/cleat/scanning/CodeScanAlertScannerTest.java
  • backend/libs/scanning/src/test/java/dev/cleat/scanning/SecretFindingScannerTest.java
  • backend/libs/scanning/src/test/java/dev/cleat/scanning/VulnerabilityScannerTest.java
💤 Files with no reviewable changes (1)
  • backend/libs/persistence/src/main/java/dev/cleat/persistence/mapper/CleatMapper.java

Comment thread backend/apps/api/src/test/java/dev/cleat/api/CodeScanAlertControllerTest.java Outdated
Comment thread backend/apps/api/src/test/java/dev/cleat/api/SecretFindingControllerTest.java Outdated
Comment thread backend/apps/api/src/test/java/dev/cleat/api/VulnerabilityControllerTest.java Outdated
Comment thread backend/apps/worker/src/main/java/dev/cleat/worker/CleatWorkerApplication.java Outdated

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🧹 Nitpick comments (2)
backend/apps/worker/src/main/java/dev/cleat/worker/VulnerabilityWorker.java (1)

19-21: 🚀 Performance & Scalability | 🔵 Trivial | 🏗️ Heavy lift

Avoid rescanning the entire table on every tick.

findAll() loads every vulnerability, and processAndSave(...) writes each entity back after recalculating priority. Once priorities are populated, this job turns into a full-table read/write every 10 minutes. Prefer paging plus a narrower query (for example, only rows with missing/stale priority) so the worker cost does not grow with table size.

🤖 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 `@backend/apps/worker/src/main/java/dev/cleat/worker/VulnerabilityWorker.java`
around lines 19 - 21, The scheduled scan in VulnerabilityWorker.runSecurityScan
is doing a full-table read with vulnerabilityRepository.findAll() and then
rewriting every row via vulnerabilityScanner.processAndSave, so it will keep
rescanning everything on each tick. Update this job to use a narrower repository
query and paging/batching, targeting only vulnerabilities with missing or stale
priority instead of all rows, and keep the work bounded as the table grows.
backend/libs/scanning/src/main/java/dev/cleat/scanning/CodeScanAlertScanner.java (1)

22-27: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Collapse or complete the severity branch.

Lines 22-27 ignore severity and always set Status.OPEN, so the conditional currently adds no behavior and can hide a missed mapping. Either remove the branch or implement the intended non-OPEN path.

🤖 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
`@backend/libs/scanning/src/main/java/dev/cleat/scanning/CodeScanAlertScanner.java`
around lines 22 - 27, The severity check in CodeScanAlertScanner is redundant
because both branches in the status assignment set Status.OPEN. Update the logic
in the scanner method that handles CodeScanAlertEntity so the
Severity.CRITICAL/Severity.HIGH branch has distinct behavior, or collapse the
conditional entirely if all severities should map to OPEN. Use the existing
Severity and Status handling in CodeScanAlertScanner to keep the mapping
explicit and avoid a no-op branch.

Source: Linters/SAST tools

🤖 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 `@backend/apps/worker/src/main/java/dev/cleat/worker/VulnerabilityWorker.java`:
- Around line 19-21: The batch scan in VulnerabilityWorker.runSecurityScan
currently stops on the first exception because
vulnerabilityScanner.processAndSave is called directly inside the forEach. Wrap
each per-row call in its own try/catch inside runSecurityScan so a failure for
one Vulnerability does not abort the scheduled run, and continue processing the
remaining entities while preserving the existing scheduler behavior.

---

Nitpick comments:
In `@backend/apps/worker/src/main/java/dev/cleat/worker/VulnerabilityWorker.java`:
- Around line 19-21: The scheduled scan in VulnerabilityWorker.runSecurityScan
is doing a full-table read with vulnerabilityRepository.findAll() and then
rewriting every row via vulnerabilityScanner.processAndSave, so it will keep
rescanning everything on each tick. Update this job to use a narrower repository
query and paging/batching, targeting only vulnerabilities with missing or stale
priority instead of all rows, and keep the work bounded as the table grows.

In
`@backend/libs/scanning/src/main/java/dev/cleat/scanning/CodeScanAlertScanner.java`:
- Around line 22-27: The severity check in CodeScanAlertScanner is redundant
because both branches in the status assignment set Status.OPEN. Update the logic
in the scanner method that handles CodeScanAlertEntity so the
Severity.CRITICAL/Severity.HIGH branch has distinct behavior, or collapse the
conditional entirely if all severities should map to OPEN. Use the existing
Severity and Status handling in CodeScanAlertScanner to keep the mapping
explicit and avoid a no-op branch.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a27bb90a-2681-473c-9e0c-18c0cdc9fe76

📥 Commits

Reviewing files that changed from the base of the PR and between 0b84f18 and 2b59ea8.

📒 Files selected for processing (5)
  • backend/apps/api/src/test/java/dev/cleat/api/CleatApiTests.java
  • backend/apps/worker/src/main/java/dev/cleat/worker/VulnerabilityWorker.java
  • backend/libs/scanning/src/main/java/dev/cleat/scanning/CodeScanAlertScanner.java
  • backend/libs/scanning/src/main/java/dev/cleat/scanning/SecretFindingScanner.java
  • backend/libs/scanning/src/main/java/dev/cleat/scanning/VulnerabilityScanner.java
🚧 Files skipped from review as they are similar to previous changes (2)
  • backend/libs/scanning/src/main/java/dev/cleat/scanning/VulnerabilityScanner.java
  • backend/libs/scanning/src/main/java/dev/cleat/scanning/SecretFindingScanner.java

Comment thread backend/apps/worker/src/main/java/dev/cleat/worker/VulnerabilityWorker.java Outdated

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 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
`@backend/apps/worker/src/test/java/dev/cleat/worker/CleatWorkerApplicationTests.java`:
- Around line 8-12: Disable background scheduling in CleatWorkerApplicationTests
so the smoke test does not trigger VulnerabilityWorker.runSecurityScan() or
other scheduled work; `@MockitoBean` on VulnerabilityScanner is not enough because
the scheduled path can still reach VulnerabilityRepository.findAll(). Update the
test setup around `@SpringBootTest/CleatWorkerApplicationTests` to either exclude
scheduling or load a narrower configuration so only the intended smoke-test
context starts.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6088706b-686e-431c-8819-2282234b23ed

📥 Commits

Reviewing files that changed from the base of the PR and between 0ef3c0e and 796d6b5.

📒 Files selected for processing (1)
  • backend/apps/worker/src/test/java/dev/cleat/worker/CleatWorkerApplicationTests.java

@Arzu-N Arzu-N self-assigned this Jun 29, 2026
@Arzu-N Arzu-N added the area: backend Backend service or library label Jun 29, 2026

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 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
`@backend/apps/api/src/main/java/dev/cleat/api/exception/GlobalExceptionHandler.java`:
- Around line 22-26: The broad RuntimeException handler in
GlobalExceptionHandler is swallowing framework/client errors that should
preserve their 4xx responses. Narrow handleRuntimeException to only unexpected
server-side failures, and add explicit exception handlers for Spring MVC
exceptions you want to keep unchanged, such as ResponseStatusException and
request conversion/binding failures, so those paths don’t get converted into a
generic 500.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b2eeb002-a8eb-4545-b2e2-bb020ba6893f

📥 Commits

Reviewing files that changed from the base of the PR and between dfa2451 and 09815e4.

📒 Files selected for processing (1)
  • backend/apps/api/src/main/java/dev/cleat/api/exception/GlobalExceptionHandler.java

Arzu-N added 4 commits June 29, 2026 21:56

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 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
`@backend/libs/scanning/src/test/java/dev/cleat/scanning/VulnerabilityScannerTest.java`:
- Around line 61-62: The test setup in VulnerabilityScannerTest has broken
entity construction because the VulnerabilityEntity initialization is malformed
and leaves an invalid statement in the same block. Fix the setup around
VulnerabilityEntity and the subsequent Severity assignment so the entity is
built with valid Java syntax and the severity is applied to the intended
variable, keeping the test compileable.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b22fc870-c2ca-46b0-8d5f-e43307901d5c

📥 Commits

Reviewing files that changed from the base of the PR and between 5e05290 and a2cd900.

📒 Files selected for processing (1)
  • backend/libs/scanning/src/test/java/dev/cleat/scanning/VulnerabilityScannerTest.java

@Arzu-N

Arzu-N commented Jun 30, 2026

Copy link
Copy Markdown
Member Author

Hi, @martian56
I have finished the task. All tests have passed successfully, and the implementation is working as expected.

Could you please review the PR when you have a moment? #34

Thanks!

@martian56 martian56 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks Arzu, and yes, I went through it. This is a big PR and it holds together well. Approving.

First, on the CodeRabbit feedback, since you said you cleared all of it: I checked, all 22 threads are resolved, and I spot-checked the ones that actually mattered rather than trusting the green checkmarks. The fixes are real, not just closed:

  • GlobalExceptionHandler no longer echoes the raw exception in the 500 body. It returns a generic message and logs the real one server side, and it rethrows ResponseStatusException so those still surface properly. That was the security one and it is handled correctly.
  • PriorityCalculator validates the CVSS range and the non-null invariants now live in the Vulnerability record's canonical constructor, so the nullable-input concern is closed at construction time, which is the right place for it.
  • The client-supplied priority is gone from VulnerabilityRequestDto, the migration no longer hardcodes 'main' as a column default, and the per-row failure isolation in the worker is in place.

A few things I checked on my own that look good:

  • SecurityScanWorker wraps each record in its own try/catch, so one bad row logs and the batch keeps going. It also reads scalar fields and saves rather than walking lazy associations, so it sidesteps the detached-entity LazyInitializationException trap that came up on the workflow-audit PR. Nice.
  • DatasetDto picked up codeAlerts, so the contract is growing pillar by pillar as each one lands. That is the right way to close the gap toward the frontend's full Dataset shape.

None of the following block the merge, but worth a look:

  1. Migration numbering is going to collide with the other open backend PRs. This branch has V3__alter_vulnerability_table, while the workflow-audit PR has a V3__update_repo_and_add_tables, and the API-contract PR also touches V2__update_repo_and_add_tables. Flyway versions have to be unique and ordered, so whichever of these merges second will fail on a duplicate version or apply things out of order. Please sort the sequencing with Nurlan before the second one lands, this is the one I would not want to discover at deploy time.

  2. SecurityScanWorker re-reads and reprocesses every finding in the tables every ten minutes. Fine for now, but it will not scale, so at some point this wants to be incremental (only new or changed rows) or at least paged.

  3. Tiny one: GlobalExceptionHandler has 'occured' twice, should be 'occurred'. And the fixedDelay of 600000 could move into config like the other scan intervals, just for consistency.

Good work getting the whole security pillar in and grinding through that long tail of test-context wiring. Approving, just please lock down the migration ordering.

@Arzu-N Arzu-N merged commit 517832e into main Jun 30, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: backend Backend service or library

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Security: secrets, vulnerabilities, code scanning

2 participants