- Created expected JSON files for Go modules and workspaces. - Added go.mod and go.sum files for example projects. - Implemented private module structure with expected JSON output. - Introduced vendored dependencies with corresponding expected JSON. - Developed PostgresGraphJobStore for managing graph jobs. - Established SQL migration scripts for graph jobs schema. - Implemented GraphJobRepository for CRUD operations on graph jobs. - Created IGraphJobRepository interface for repository abstraction. - Added unit tests for GraphJobRepository to ensure functionality.
365 lines
9.9 KiB
JSON
365 lines
9.9 KiB
JSON
{
|
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
"$id": "https://stellaops.io/schemas/risk-scoring.v1.json",
|
|
"title": "RiskScoring",
|
|
"description": "Risk scoring contract for vulnerability prioritization - job requests, results, and profiles",
|
|
"type": "object",
|
|
"$defs": {
|
|
"RiskScoringJobRequest": {
|
|
"type": "object",
|
|
"description": "Request to create a risk scoring job",
|
|
"required": ["tenantId", "contextId", "profileId", "findings"],
|
|
"properties": {
|
|
"tenantId": {
|
|
"type": "string",
|
|
"description": "Tenant identifier"
|
|
},
|
|
"contextId": {
|
|
"type": "string",
|
|
"description": "Context/snapshot identifier"
|
|
},
|
|
"profileId": {
|
|
"type": "string",
|
|
"description": "Risk profile to use for scoring"
|
|
},
|
|
"findings": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/$defs/FindingInput"
|
|
},
|
|
"minItems": 1
|
|
},
|
|
"priority": {
|
|
"$ref": "#/$defs/JobPriority"
|
|
},
|
|
"correlationId": {
|
|
"type": "string",
|
|
"description": "Optional correlation ID for tracing"
|
|
},
|
|
"requestedAt": {
|
|
"type": "string",
|
|
"format": "date-time",
|
|
"description": "Request timestamp (defaults to now)"
|
|
}
|
|
}
|
|
},
|
|
"FindingInput": {
|
|
"type": "object",
|
|
"required": ["findingId", "componentPurl", "advisoryId", "trigger"],
|
|
"properties": {
|
|
"findingId": {
|
|
"type": "string",
|
|
"description": "Finding identifier"
|
|
},
|
|
"componentPurl": {
|
|
"type": "string",
|
|
"description": "Package URL of affected component",
|
|
"examples": ["pkg:npm/lodash@4.17.20", "pkg:maven/org.apache.log4j/log4j-core@2.14.1"]
|
|
},
|
|
"advisoryId": {
|
|
"type": "string",
|
|
"description": "Advisory/CVE identifier",
|
|
"examples": ["CVE-2024-1234"]
|
|
},
|
|
"trigger": {
|
|
"$ref": "#/$defs/ScoringTrigger"
|
|
}
|
|
}
|
|
},
|
|
"ScoringTrigger": {
|
|
"type": "string",
|
|
"description": "Event that triggered rescoring",
|
|
"enum": ["created", "updated", "enriched", "vex_applied"]
|
|
},
|
|
"JobPriority": {
|
|
"type": "string",
|
|
"description": "Job priority level",
|
|
"enum": ["low", "normal", "high", "emergency"],
|
|
"default": "normal"
|
|
},
|
|
"RiskScoringJob": {
|
|
"type": "object",
|
|
"description": "A queued or completed risk scoring job",
|
|
"required": ["jobId", "tenantId", "contextId", "profileId", "status"],
|
|
"properties": {
|
|
"jobId": {
|
|
"type": "string",
|
|
"description": "Unique job identifier"
|
|
},
|
|
"tenantId": {
|
|
"type": "string"
|
|
},
|
|
"contextId": {
|
|
"type": "string"
|
|
},
|
|
"profileId": {
|
|
"type": "string"
|
|
},
|
|
"profileHash": {
|
|
"type": "string",
|
|
"pattern": "^sha256:[a-f0-9]{64}$",
|
|
"description": "SHA-256 hash of profile for reproducibility"
|
|
},
|
|
"findings": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/$defs/FindingInput"
|
|
}
|
|
},
|
|
"priority": {
|
|
"$ref": "#/$defs/JobPriority"
|
|
},
|
|
"status": {
|
|
"$ref": "#/$defs/JobStatus"
|
|
},
|
|
"requestedAt": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"startedAt": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"completedAt": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"correlationId": {
|
|
"type": "string"
|
|
},
|
|
"errorMessage": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"JobStatus": {
|
|
"type": "string",
|
|
"description": "Job execution status",
|
|
"enum": ["queued", "running", "completed", "failed", "cancelled"]
|
|
},
|
|
"RiskScoringResult": {
|
|
"type": "object",
|
|
"description": "Result of scoring a single finding",
|
|
"required": ["findingId", "profileId", "profileVersion", "rawScore", "normalizedScore", "severity", "scoredAt"],
|
|
"properties": {
|
|
"findingId": {
|
|
"type": "string"
|
|
},
|
|
"profileId": {
|
|
"type": "string"
|
|
},
|
|
"profileVersion": {
|
|
"type": "string",
|
|
"pattern": "^\\d+\\.\\d+\\.\\d+$"
|
|
},
|
|
"rawScore": {
|
|
"type": "number",
|
|
"minimum": 0,
|
|
"maximum": 1,
|
|
"description": "Unweighted sum of signal values"
|
|
},
|
|
"normalizedScore": {
|
|
"type": "number",
|
|
"minimum": 0,
|
|
"maximum": 1,
|
|
"description": "Weighted and clamped final score"
|
|
},
|
|
"severity": {
|
|
"$ref": "#/$defs/Severity"
|
|
},
|
|
"signalValues": {
|
|
"type": "object",
|
|
"description": "Individual signal values",
|
|
"additionalProperties": {
|
|
"oneOf": [
|
|
{"type": "number"},
|
|
{"type": "boolean"}
|
|
]
|
|
},
|
|
"examples": [{"cvss": 7.5, "kev": true, "reachability": 0.9}]
|
|
},
|
|
"signalContributions": {
|
|
"type": "object",
|
|
"description": "Weighted contribution of each signal",
|
|
"additionalProperties": {
|
|
"type": "number",
|
|
"minimum": 0,
|
|
"maximum": 1
|
|
}
|
|
},
|
|
"overrideApplied": {
|
|
"type": "string",
|
|
"description": "Name of override rule if applied"
|
|
},
|
|
"overrideReason": {
|
|
"type": "string",
|
|
"description": "Human-readable reason for override"
|
|
},
|
|
"scoredAt": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
}
|
|
}
|
|
},
|
|
"Severity": {
|
|
"type": "string",
|
|
"description": "Risk severity level",
|
|
"enum": ["critical", "high", "medium", "low", "informational"]
|
|
},
|
|
"RiskProfileModel": {
|
|
"type": "object",
|
|
"description": "Risk profile defining scoring rules",
|
|
"required": ["id", "version", "signals", "weights"],
|
|
"properties": {
|
|
"id": {
|
|
"type": "string",
|
|
"description": "Profile identifier",
|
|
"examples": ["default-profile", "critical-only"]
|
|
},
|
|
"version": {
|
|
"type": "string",
|
|
"pattern": "^\\d+\\.\\d+\\.\\d+$"
|
|
},
|
|
"description": {
|
|
"type": "string"
|
|
},
|
|
"extends": {
|
|
"type": "string",
|
|
"description": "Parent profile to inherit from"
|
|
},
|
|
"signals": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/$defs/RiskSignal"
|
|
},
|
|
"minItems": 1
|
|
},
|
|
"weights": {
|
|
"type": "object",
|
|
"description": "Signal name to weight mapping (must sum to 1.0)",
|
|
"additionalProperties": {
|
|
"type": "number",
|
|
"minimum": 0,
|
|
"maximum": 1
|
|
}
|
|
},
|
|
"overrides": {
|
|
"$ref": "#/$defs/RiskOverrides"
|
|
},
|
|
"metadata": {
|
|
"type": "object",
|
|
"additionalProperties": true
|
|
}
|
|
}
|
|
},
|
|
"RiskSignal": {
|
|
"type": "object",
|
|
"description": "Definition of a scoring signal",
|
|
"required": ["name", "source", "type"],
|
|
"properties": {
|
|
"name": {
|
|
"type": "string",
|
|
"examples": ["cvss", "kev", "reachability", "fix_available"]
|
|
},
|
|
"source": {
|
|
"type": "string",
|
|
"examples": ["nvd", "cisa", "scanner", "vex"]
|
|
},
|
|
"type": {
|
|
"$ref": "#/$defs/SignalType"
|
|
},
|
|
"path": {
|
|
"type": "string",
|
|
"description": "JSON Pointer to evidence value",
|
|
"examples": ["/cvss/base_score", "/kev/in_catalog"]
|
|
},
|
|
"transform": {
|
|
"type": "string",
|
|
"description": "Normalization transform to apply",
|
|
"examples": ["normalize_10", "invert", "threshold_0.5"]
|
|
},
|
|
"unit": {
|
|
"type": "string",
|
|
"examples": ["score", "percent", "days"]
|
|
}
|
|
}
|
|
},
|
|
"SignalType": {
|
|
"type": "string",
|
|
"description": "Signal data type",
|
|
"enum": ["boolean", "numeric", "categorical"]
|
|
},
|
|
"RiskOverrides": {
|
|
"type": "object",
|
|
"description": "Override rules for severity and decisions",
|
|
"properties": {
|
|
"severity": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/$defs/SeverityOverride"
|
|
}
|
|
},
|
|
"decisions": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/$defs/DecisionOverride"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"SeverityOverride": {
|
|
"type": "object",
|
|
"required": ["when", "set"],
|
|
"properties": {
|
|
"when": {
|
|
"type": "object",
|
|
"description": "Condition to match (signal name to value/expression)",
|
|
"additionalProperties": true
|
|
},
|
|
"set": {
|
|
"$ref": "#/$defs/Severity"
|
|
}
|
|
}
|
|
},
|
|
"DecisionOverride": {
|
|
"type": "object",
|
|
"required": ["when", "action"],
|
|
"properties": {
|
|
"when": {
|
|
"type": "object",
|
|
"additionalProperties": true
|
|
},
|
|
"action": {
|
|
"$ref": "#/$defs/DecisionAction"
|
|
},
|
|
"reason": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"DecisionAction": {
|
|
"type": "string",
|
|
"description": "Policy decision action",
|
|
"enum": ["allow", "review", "deny"]
|
|
}
|
|
},
|
|
"examples": [
|
|
{
|
|
"jobId": "job-12345",
|
|
"tenantId": "default",
|
|
"contextId": "ctx-abcde",
|
|
"profileId": "default-profile",
|
|
"profileHash": "sha256:abc123def456...",
|
|
"status": "completed",
|
|
"findings": [
|
|
{
|
|
"findingId": "finding-001",
|
|
"componentPurl": "pkg:npm/lodash@4.17.20",
|
|
"advisoryId": "CVE-2024-1234",
|
|
"trigger": "created"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|