feat(entity): add exploit intelligence job tracking entities and migration#2435
feat(entity): add exploit intelligence job tracking entities and migration#2435Strum355 wants to merge 5 commits into
Conversation
Reviewer's GuideAdds new SeaORM entities and a database migration to track Exploit Intelligence analysis jobs and per-component results, wiring them into the existing entity and migration registries. Entity relationship diagram for Exploit Intelligence job trackingerDiagram
exploit_intelligence_job {
uuid id
string scan_id
uuid sbom_id
string vulnerability_id
int status
int finding
string product_id
int total_components
uuid advisory_id
}
exploit_intelligence_job_component {
uuid id
uuid job_id
string component_ref
string component_name
string scan_id
int status
int finding
uuid advisory_id
}
sbom {
uuid sbom_id
}
advisory {
uuid id
}
sbom ||--o{ exploit_intelligence_job : sbom_id
advisory ||--o{ exploit_intelligence_job : advisory_id
exploit_intelligence_job ||--o{ exploit_intelligence_job_component : job_id
advisory ||--o{ exploit_intelligence_job_component : advisory_id
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 1 issue, and left some high level feedback:
- If
exploit_intelligence_jobrecords will frequently be queried byvulnerability_id(e.g., listing jobs for a CVE), consider adding an index onVulnerabilityIdto avoid full table scans as the table grows. - Similarly, if per-component lookups are commonly done by
component_refinexploit_intelligence_job_component, adding an index onComponentRefwould improve query performance for larger datasets.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- If `exploit_intelligence_job` records will frequently be queried by `vulnerability_id` (e.g., listing jobs for a CVE), consider adding an index on `VulnerabilityId` to avoid full table scans as the table grows.
- Similarly, if per-component lookups are commonly done by `component_ref` in `exploit_intelligence_job_component`, adding an index on `ComponentRef` would improve query performance for larger datasets.
## Individual Comments
### Comment 1
<location path="migration/src/m0002200_create_exploit_intelligence_job.rs" line_range="42-51" />
<code_context>
+ .col(ColumnDef::new(ExploitIntelligenceJob::SourceUrl).string())
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Explicitly size URL/text columns to avoid silent truncation or inefficient storage.
These URL fields (e.g., SourceUrl, ReportUrl) use `.string()` with the default length (typically 255), which may be too small for real EI/report/repo URLs and can cause silent truncation or require later schema changes. Please use an explicit length (e.g., `.string_len(1024)`) or `.text()` to better match expected URL sizes and avoid data loss and future migrations.
Suggested implementation:
```rust
.col(
ColumnDef::new(ExploitIntelligenceJob::SourceUrl)
.string_len(1024),
)
.col(
ColumnDef::new(ExploitIntelligenceJob::ReportUrl)
.string_len(1024),
)
```
Depending on the rest of the schema, you may also want to:
1. Apply explicit lengths or switch to `.text()` for other potentially long text fields (e.g., `ErrorMessage`, any other URL or description fields).
2. Ensure corresponding entity definitions (e.g., in your SeaORM models) use compatible types so ORM-level validations align with the new column lengths.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| .col(ColumnDef::new(ExploitIntelligenceJob::SourceUrl).string()) | ||
| .col(ColumnDef::new(ExploitIntelligenceJob::ReportUrl).string()) | ||
| .col(ColumnDef::new(ExploitIntelligenceJob::AdvisoryId).uuid()) | ||
| .col(ColumnDef::new(ExploitIntelligenceJob::Finding).integer()) | ||
| .col(ColumnDef::new(ExploitIntelligenceJob::ErrorMessage).string()) | ||
| .col(ColumnDef::new(ExploitIntelligenceJob::ProductId).string()) | ||
| .col( | ||
| ColumnDef::new(ExploitIntelligenceJob::TotalComponents).integer(), | ||
| ) | ||
| .col( |
There was a problem hiding this comment.
suggestion (bug_risk): Explicitly size URL/text columns to avoid silent truncation or inefficient storage.
These URL fields (e.g., SourceUrl, ReportUrl) use .string() with the default length (typically 255), which may be too small for real EI/report/repo URLs and can cause silent truncation or require later schema changes. Please use an explicit length (e.g., .string_len(1024)) or .text() to better match expected URL sizes and avoid data loss and future migrations.
Suggested implementation:
.col(
ColumnDef::new(ExploitIntelligenceJob::SourceUrl)
.string_len(1024),
)
.col(
ColumnDef::new(ExploitIntelligenceJob::ReportUrl)
.string_len(1024),
)Depending on the rest of the schema, you may also want to:
- Apply explicit lengths or switch to
.text()for other potentially long text fields (e.g.,ErrorMessage, any other URL or description fields). - Ensure corresponding entity definitions (e.g., in your SeaORM models) use compatible types so ORM-level validations align with the new column lengths.
Merge m0002200 and m0002210 into a single migration that creates both the exploit_intelligence_job and exploit_intelligence_job_component tables together, including product_id/total_components columns upfront. Add the missing advisory_id FK index on the component table per CONVENTIONS.md migration patterns. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The column stores both purls (successful components) and container image references (failed/excluded components), so component_ref is more accurate. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…nt docs sbom_id is always provided when creating a job, so make it NOT NULL in both the entity and migration. Change the FK on-delete action from SetNull to Cascade accordingly. Add doc comments to scan_id, report_url, advisory_id, finding, and product_id clarifying which fields stay None in the multi-component SPDX product flow vs the single-component CycloneDX flow. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| .uuid() | ||
| .not_null() | ||
| .primary_key() | ||
| .default(Func::cust(UuidV4)), |
There was a problem hiding this comment.
Please use V7 UUIDs. They perform better in PSQL.
| /// Lifecycle status of an Exploit Intelligence analysis job. | ||
| #[derive(Copy, Clone, Debug, Eq, PartialEq, EnumIter, DeriveActiveEnum)] | ||
| #[sea_orm(rs_type = "i32", db_type = "Integer")] | ||
| pub enum ExploitIntelligenceJobStatus { |
There was a problem hiding this comment.
Please use actual enum types:
trustify/entity/src/advisory_vulnerability_score.rs
Lines 65 to 76 in db01ffe
trustify/migration/src/m0002010_add_advisory_scores.rs
Lines 20 to 25 in db01ffe
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## feature/exploit-intelligence-integration #2435 +/- ##
============================================================================
- Coverage 71.39% 71.38% -0.02%
============================================================================
Files 452 455 +3
Lines 27249 27269 +20
Branches 27249 27269 +20
============================================================================
+ Hits 19454 19465 +11
- Misses 6666 6669 +3
- Partials 1129 1135 +6 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Address PR review feedback: remove gen_random_uuid() defaults so application code generates V7 UUIDs, and convert Status/Finding from integer-backed columns to proper PostgreSQL enum types matching the existing Severity/ScoreType pattern. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
Add database entities and migrations for tracking Exploit Intelligence analysis jobs in trustify. This is the data-layer foundation for integrating the Exploit Intelligence (EI) service, which performs automated vulnerability reachability analysis and produces VEX advisories.
Jira
Implements TC-4675
What changed
New entities:
exploit_intelligence_job— tracks the lifecycle of each EI analysis request (submission → completion), including scan ID, status, associated SBOM/vulnerability, and the result (VEX advisory link or error). Supports both single-component (CycloneDX) and multi-component (SPDX product) flows viaproduct_id/total_components.exploit_intelligence_job_component— tracks per-component analysis results within a multi-component SPDX product job. Each row represents one container image component independently analysed by the EI service.New enums:
ExploitIntelligenceJobStatus—Pending,Running,Completed,FailedFinding—Vulnerable,NotVulnerable,UncertainMigration (
m0002200):sbomandadvisorytables (both nullable)scan_id(both tables)Summary by Sourcery
Introduce database support for tracking Exploit Intelligence analysis jobs and their per-component results.
New Features:
Enhancements: