Add unit tests for RabbitMq and Udp transport servers and clients
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled

- Implemented comprehensive unit tests for RabbitMqTransportServer, covering constructor, disposal, connection management, event handlers, and exception handling.
- Added configuration tests for RabbitMqTransportServer to validate SSL, durable queues, auto-recovery, and custom virtual host options.
- Created unit tests for UdpFrameProtocol, including frame parsing and serialization, header size validation, and round-trip data preservation.
- Developed tests for UdpTransportClient, focusing on connection handling, event subscriptions, and exception scenarios.
- Established tests for UdpTransportServer, ensuring proper start/stop behavior, connection state management, and event handling.
- Included tests for UdpTransportOptions to verify default values and modification capabilities.
- Enhanced service registration tests for Udp transport services in the dependency injection container.
This commit is contained in:
master
2025-12-05 19:01:12 +02:00
parent 53508ceccb
commit cc69d332e3
245 changed files with 22440 additions and 27719 deletions

View File

@@ -0,0 +1,286 @@
# Risk Scoring Contract (66-002)
**Contract ID:** `CONTRACT-RISK-SCORING-002`
**Version:** 1.0
**Status:** Published
**Last Updated:** 2025-12-05
## Overview
This contract defines the risk scoring interface used by the Policy Engine to calculate and prioritize vulnerability findings. It covers job requests, results, risk profiles, and signal definitions.
## Implementation References
- **Scoring Models:** `src/Policy/StellaOps.Policy.Engine/Scoring/RiskScoringModels.cs`
- **Risk Profile:** `src/Policy/StellaOps.Policy.RiskProfile/Models/RiskProfileModel.cs`
- **Attestation Schema:** `src/Attestor/StellaOps.Attestor.Types/schemas/stellaops-risk-profile.v1.schema.json`
## Data Models
### RiskScoringJobRequest
Request to create a risk scoring job.
```json
{
"tenant_id": "string",
"context_id": "string",
"profile_id": "string",
"findings": [
{
"finding_id": "string",
"component_purl": "pkg:npm/lodash@4.17.20",
"advisory_id": "CVE-2024-1234",
"trigger": "created|updated|enriched|vex_applied"
}
],
"priority": "low|normal|high|emergency",
"correlation_id": "string (optional)",
"requested_at": "2025-12-05T00:00:00Z (optional)"
}
```
### RiskScoringJob
A queued or completed risk scoring job.
```json
{
"job_id": "string",
"tenant_id": "string",
"context_id": "string",
"profile_id": "string",
"profile_hash": "sha256:...",
"findings": [...],
"priority": "normal",
"status": "queued|running|completed|failed|cancelled",
"requested_at": "2025-12-05T00:00:00Z",
"started_at": "2025-12-05T00:00:01Z (optional)",
"completed_at": "2025-12-05T00:00:02Z (optional)",
"correlation_id": "string (optional)",
"error_message": "string (optional)"
}
```
### RiskScoringResult
Result of scoring a single finding.
```json
{
"finding_id": "string",
"profile_id": "string",
"profile_version": "1.0.0",
"raw_score": 0.75,
"normalized_score": 0.85,
"severity": "high",
"signal_values": {
"cvss": 7.5,
"kev": true,
"reachability": 0.9
},
"signal_contributions": {
"cvss": 0.4,
"kev": 0.3,
"reachability": 0.3
},
"override_applied": "kev-boost (optional)",
"override_reason": "Known Exploited Vulnerability (optional)",
"scored_at": "2025-12-05T00:00:02Z"
}
```
## Risk Profile Model
### RiskProfileModel
Defines how findings are scored and prioritized.
```json
{
"id": "default-profile",
"version": "1.0.0",
"description": "Default risk profile for vulnerability prioritization",
"extends": "base-profile (optional)",
"signals": [
{
"name": "cvss",
"source": "nvd",
"type": "numeric",
"path": "/cvss/base_score",
"transform": "normalize_10",
"unit": "score"
},
{
"name": "kev",
"source": "cisa",
"type": "boolean",
"path": "/kev/in_catalog"
},
{
"name": "reachability",
"source": "scanner",
"type": "numeric",
"path": "/reachability/score"
}
],
"weights": {
"cvss": 0.4,
"kev": 0.3,
"reachability": 0.3
},
"overrides": {
"severity": [
{
"when": { "kev": true },
"set": "critical"
}
],
"decisions": [
{
"when": { "kev": true, "reachability": { "$gt": 0.8 } },
"action": "deny",
"reason": "KEV with high reachability"
}
]
},
"metadata": {}
}
```
### Signal Types
| Type | Description | Value Range |
|------|-------------|-------------|
| `boolean` | True/false signal | `true` / `false` |
| `numeric` | Numeric signal | `0.0` to `1.0` (normalized) |
| `categorical` | Categorical signal | String values |
### Severity Levels
| Level | JSON Value | Priority |
|-------|------------|----------|
| Critical | `"critical"` | 1 (highest) |
| High | `"high"` | 2 |
| Medium | `"medium"` | 3 |
| Low | `"low"` | 4 |
| Informational | `"informational"` | 5 (lowest) |
### Decision Actions
| Action | Description |
|--------|-------------|
| `allow` | Finding is acceptable, no action required |
| `review` | Finding requires manual review |
| `deny` | Finding is not acceptable, blocks promotion |
## Scoring Algorithm
### Score Calculation
```
raw_score = Σ(signal_value × weight) for all signals
normalized_score = clamp(raw_score, 0.0, 1.0)
```
### VEX Gate Provider
The VEX gate provider short-circuits scoring when a VEX denial is present:
```csharp
if (signals.HasVexDenial)
return 0.0; // Fully mitigated
return Math.Max(signals.Values); // Otherwise, max signal
```
### CVSS + KEV Provider
```csharp
score = clamp01((cvss / 10.0) + kevBonus)
where kevBonus = kev ? 0.2 : 0.0
```
## API Endpoints
### Submit Scoring Job
```
POST /api/v1/risk/jobs
Content-Type: application/json
{
"tenant_id": "...",
"context_id": "...",
"profile_id": "...",
"findings": [...]
}
Response: 202 Accepted
{
"job_id": "...",
"status": "queued"
}
```
### Get Job Status
```
GET /api/v1/risk/jobs/{job_id}
Response: 200 OK
{
"job_id": "...",
"status": "completed",
"results": [...]
}
```
### Get Finding Score
```
GET /api/v1/risk/findings/{finding_id}/score
Response: 200 OK
{
"finding_id": "...",
"normalized_score": 0.85,
"severity": "high",
...
}
```
## Finding Change Events
Events that trigger rescoring:
| Event | JSON Value | Description |
|-------|------------|-------------|
| Created | `"created"` | New finding discovered |
| Updated | `"updated"` | Finding metadata changed |
| Enriched | `"enriched"` | New signals available |
| VEX Applied | `"vex_applied"` | VEX status changed |
## Determinism Guarantees
1. **Reproducible scores:** Same inputs always produce same outputs
2. **Profile versioning:** Profile hash included in results for traceability
3. **Signal ordering:** Signals processed in deterministic order
4. **Timestamp precision:** UTC ISO-8601 with millisecond precision
## Unblocks
This contract unblocks the following tasks:
- LEDGER-RISK-67-001
- LEDGER-RISK-68-001
- LEDGER-RISK-69-001
- POLICY-RISK-67-003
- POLICY-RISK-68-001
- POLICY-RISK-68-002
## Related Contracts
- [Advisory Key Contract](./advisory-key.md) - Advisory ID canonicalization
- [VEX Lens Contract](./vex-lens.md) - VEX evidence for scoring
- [Export Bundle Contract](./export-bundle.md) - Score digest in exports