save progress

This commit is contained in:
StellaOps Bot
2026-01-04 14:54:52 +02:00
parent c49b03a254
commit 3098e84de4
132 changed files with 19783 additions and 31 deletions

View File

@@ -0,0 +1,195 @@
# Sprint 20260104_001_BE - Adaptive Noise-Gating for Vulnerability Graphs
## Topic & Scope
Implement adaptive noise-gating for vulnerability graphs to reduce alert fatigue and improve triage UX. The feature enables:
1. **Semantic Edge Deduplication**: Collapse redundant edges from multiple sources into single edges with provenance sets
2. **Proof Strength Hierarchy**: Formalize evidence authority ordering (Authority > Binary > Static > Heuristic)
3. **Stability Damping**: Prevent flip-flopping verdicts through hysteresis-based state transitions
4. **Delta Reports**: Surface only meaningful changes with typed sections (New, Resolved, ConfidenceUp, ConfidenceDown, PolicyImpact)
**Working directory:** `src/__Libraries/`, `src/VexLens/`, `src/Policy/`
## Dependencies & Concurrency
- Builds on existing `VexConsensusEngine`, `PolicyGateEvaluator`, and `NoisePriorService`
- No external dependencies; integrates with existing modules
- Tasks can be executed in parallel across modules
## Documentation Prerequisites
- docs/README.md
- docs/07_HIGH_LEVEL_ARCHITECTURE.md
- docs/modules/platform/architecture-overview.md
- CLAUDE.md (especially Section 8: Code Quality & Determinism Rules)
## Delivery Tracker
| # | Task ID | Status | Key dependency / next step | Owners | Task Definition |
| --- | --- | --- | --- | --- | --- |
| 1 | NG-001 | DONE | None | Guild | Add ProofStrength enum to StellaOps.Evidence.Core |
| 2 | NG-002 | DONE | NG-001 | Guild | Add ProofStrength field to EvidenceRecord |
| 3 | NG-003 | DONE | None | Guild | Create EdgeSemanticKey and deduplication logic in ReachGraph |
| 4 | NG-004 | DONE | None | Guild | Add StabilityDampingGate to Policy.Engine.Gates |
| 5 | NG-005 | DONE | NG-004 | Guild | Add StabilityDampingOptions with configurable thresholds |
| 6 | NG-006 | DONE | None | Guild | Create DeltaSection enum in VexLens |
| 7 | NG-007 | DONE | NG-006 | Guild | Extend VexDelta with section categorization |
| 8 | NG-008 | DONE | NG-001,NG-003,NG-004,NG-006 | Guild | Create INoiseGate interface and NoiseGateService |
| 9 | NG-009 | DONE | NG-008 | Guild | Add DI registration in VexLensServiceCollectionExtensions |
| 10 | NG-010 | DONE | All | Guild | Add unit tests for all new components |
| 11 | NG-011 | DONE | NG-010 | Guild | Update module AGENTS.md files |
## Task Details
### NG-001: ProofStrength Enum
Add `ProofStrength` enum to formalize evidence authority hierarchy:
```csharp
public enum ProofStrength
{
Authoritative = 100, // Vendor VEX, CSAF publisher
BinaryProof = 80, // Patch signature, binary analysis
StaticAnalysis = 60, // Reachability, call graph
Heuristic = 40 // Version matching, advisory correlation
}
```
Location: `src/__Libraries/StellaOps.Evidence/ProofStrength.cs`
### NG-002: EvidenceRecord Extension
Add optional `ProofStrength` field to existing evidence models for backward compatibility.
### NG-003: Edge Semantic Key
Create semantic key for edge deduplication:
```csharp
public readonly record struct EdgeSemanticKey(
string EntryPointId,
string SinkId,
string VulnerabilityId,
string? GateApplied)
{
public string ComputeKey() =>
$"{EntryPointId}|{SinkId}|{VulnerabilityId}|{GateApplied ?? "none"}";
}
```
Location: `src/__Libraries/StellaOps.ReachGraph/Deduplication/`
### NG-004: StabilityDampingGate
Implement hysteresis-based gate that:
- Tracks last verdict state per (artifact, CVE) tuple
- Requires score to persist for N hours OR change by X% before state transition
- Prevents flip-flopping notifications
Location: `src/Policy/StellaOps.Policy.Engine/Gates/StabilityDampingGate.cs`
### NG-005: StabilityDampingOptions
Configuration options:
- `MinDurationBeforeChange`: TimeSpan (default: 4 hours)
- `MinConfidenceDeltaPercent`: double (default: 15%)
- `EnabledStatuses`: List of VexStatus to apply damping
### NG-006: DeltaSection Enum
Categorize delta entries for UX:
```csharp
public enum DeltaSection
{
New, // First-time finding
Resolved, // Status changed to not_affected/fixed
ConfidenceUp, // Confidence increased significantly
ConfidenceDown, // Confidence decreased significantly
PolicyImpact // Gate decision changed
}
```
### NG-007: VexDelta Extension
Extend existing VexDelta with section categorization and aggregate summary.
### NG-008: INoiseGate Interface
Central interface for noise-gating operations:
```csharp
public interface INoiseGate
{
Task<IReadOnlyList<Edge>> DedupeEdgesAsync(
IReadOnlyList<Edge> edges,
CancellationToken ct = default);
Task<Verdict> ResolveNodeAsync(
string nodeId,
IReadOnlyList<Evidence> evidences,
CancellationToken ct = default);
Task<GraphSnapshot> GateAsync(
GraphSnapshot raw,
CancellationToken ct = default);
Task<DeltaReport> DiffAsync(
GraphSnapshot previous,
GraphSnapshot current,
CancellationToken ct = default);
}
```
### NG-009: DI Registration
Register services in `VexLensServiceCollectionExtensions`:
```csharp
services.AddSingleton<INoiseGate, NoiseGateService>();
services.AddOptions<StabilityDampingOptions>()
.Bind(config.GetSection("NoiseGate:StabilityDamping"))
.ValidateDataAnnotations()
.ValidateOnStart();
```
### NG-010: Unit Tests
Required test coverage:
- Edge deduplication with multi-source inputs
- Proof strength ordering in verdict resolution
- Hysteresis behavior (flip-flop prevention)
- Delta section categorization
- Determinism (same inputs = same outputs)
### NG-011: AGENTS.md Updates
Update module documentation:
- `src/VexLens/AGENTS.md`
- `src/Policy/AGENTS.md`
- `src/__Libraries/StellaOps.Evidence/AGENTS.md`
## Decisions & Risks
| Decision | Rationale |
|----------|-----------|
| Use ProofStrength instead of EvidenceClass | Avoids naming collision with existing EvidenceType enum |
| Integrate with existing VexConsensusEngine | Leverages proven consensus logic rather than creating parallel infrastructure |
| Make damping optional per-status | Production environments can enable for affected/not_affected but skip for under_investigation |
| Store dedup metadata for audit | Provenance tracking required for transparency |
## Execution Log
| Date | Action | Notes |
|------|--------|-------|
| 2026-01-04 | Sprint created | Based on product advisory review |
| 2026-01-04 | NG-001,NG-002 | Created ProofStrength enum, ProofStrengthExtensions, ProofRecord in StellaOps.Evidence.Models |
| 2026-01-04 | NG-003 | Created EdgeSemanticKey, DeduplicatedEdge, EdgeDeduplicator in StellaOps.ReachGraph.Deduplication |
| 2026-01-04 | NG-004,NG-005 | Created StabilityDampingGate, StabilityDampingOptions in StellaOps.Policy.Engine.Gates |
| 2026-01-04 | NG-006,NG-007 | Created DeltaSection, DeltaEntry, DeltaReport, DeltaReportBuilder in StellaOps.VexLens.Delta |
| 2026-01-04 | NG-008,NG-009 | Created INoiseGate, NoiseGateService, NoiseGateOptions; registered DI in VexLensServiceCollectionExtensions |
| 2026-01-04 | NG-010 | Added StabilityDampingGateTests, NoiseGateServiceTests, DeltaReportBuilderTests |
| 2026-01-04 | NG-011 | Updated VexLens and Policy.Engine AGENTS.md files |
| 2026-01-04 | Sprint complete | All 11 tasks DONE |

View File

@@ -0,0 +1,223 @@
# Sprint 20260104_002_FE - Noise-Gating Delta Report UI
## Topic & Scope
Implement frontend components to display noise-gating delta reports from the VexLens backend. This sprint composes existing Angular components to minimize new code while providing a complete UI for:
1. **Delta Report Display**: Show changes between vulnerability graph snapshots
2. **Section-Based Navigation**: Tabs for New, Resolved, ConfidenceUp/Down, PolicyImpact, Damped sections
3. **Gating Statistics**: Edge deduplication rates and verdict damping metrics
4. **Backend API Endpoints**: Expose DeltaReport via VexLens WebService
**Working directories:**
- `src/Web/StellaOps.Web/src/app/` (frontend)
- `src/VexLens/StellaOps.VexLens.WebService/` (backend API)
## Dependencies & Concurrency
- Builds on completed Sprint 20260104_001_BE (backend NoiseGate implementation)
- Reuses existing components: `DeltaSummaryStripComponent`, `TabsComponent`, `GatingExplainerComponent`
- Tasks NG-FE-001 through NG-FE-003 (backend + models) must complete before NG-FE-004+
## Existing Components to Reuse
| Component | Location | Usage |
|-----------|----------|-------|
| `DeltaSummaryStripComponent` | `features/compare/components/` | Overview stats display |
| `TabsComponent` / `TabPanelDirective` | `shared/components/tabs/` | Section navigation |
| `GatingExplainerComponent` | `features/triage/components/gating-explainer/` | Per-entry explanations |
| `DeltaComputeService` patterns | `features/compare/services/` | Signal-based state management |
| `GatingReason`, `DeltaSummary` | `features/triage/models/gating.model.ts` | Existing delta/gating types |
| `VexStatementStatus` | `core/api/vex-hub.models.ts` | VEX status types |
| `BadgeComponent`, `StatCardComponent` | `shared/components/` | Statistics display |
## Documentation Prerequisites
- CLAUDE.md (Section 8: Code Quality rules)
- src/Web/StellaOps.Web/README.md
- docs/modules/vexlens/architecture.md
## Delivery Tracker
| # | Task ID | Status | Key dependency | Task Definition |
|---|---------|--------|----------------|-----------------|
| 1 | NG-FE-001 | DONE | None | Add delta report API endpoints to VexLens.WebService |
| 2 | NG-FE-002 | DONE | None | Create TypeScript models for noise-gating delta (noise-gating.models.ts) |
| 3 | NG-FE-003 | DONE | NG-FE-002 | Create NoiseGatingApiClient service |
| 4 | NG-FE-004 | DONE | NG-FE-003 | Create NoiseGatingSummaryStripComponent (extends DeltaSummaryStrip) |
| 5 | NG-FE-005 | DONE | NG-FE-003 | Create DeltaEntryCardComponent for individual entries |
| 6 | NG-FE-006 | DONE | NG-FE-004,005 | Create NoiseGatingDeltaReportComponent (container with tabs) |
| 7 | NG-FE-007 | DONE | NG-FE-006 | Create GatingStatisticsCardComponent |
| 8 | NG-FE-008 | DONE | NG-FE-006 | Integrate into vuln-explorer/triage workspace |
| 9 | NG-FE-009 | DONE | All | Update feature module exports and routing |
## Task Details
### NG-FE-001: Backend API Endpoints
Add endpoints to `VexLensEndpointExtensions.cs`:
```csharp
// Delta computation
POST /api/v1/vexlens/deltas/compute
Body: { fromSnapshotId, toSnapshotId, options }
Returns: DeltaReportResponse
// Get gated snapshot
GET /api/v1/vexlens/snapshots/{snapshotId}/gated
Returns: GatedGraphSnapshotResponse
// Get gating statistics
GET /api/v1/vexlens/gating/statistics
Query: tenantId, fromDate, toDate
Returns: GatingStatisticsResponse
```
### NG-FE-002: TypeScript Models
Create `src/app/core/api/noise-gating.models.ts`:
```typescript
// Match backend DeltaSection enum
export type NoiseGatingDeltaSection =
| 'new' | 'resolved' | 'confidence_up' | 'confidence_down'
| 'policy_impact' | 'damped' | 'evidence_changed';
// Match backend DeltaEntry
export interface NoiseGatingDeltaEntry {
section: NoiseGatingDeltaSection;
vulnerabilityId: string;
productKey: string;
fromStatus?: VexStatementStatus;
toStatus?: VexStatementStatus;
fromConfidence?: number;
toConfidence?: number;
justification?: string;
rationaleClass?: string;
summary?: string;
contributingSources?: string[];
createdAt: string;
}
// Match backend DeltaReport
export interface NoiseGatingDeltaReport {
reportId: string;
fromSnapshotDigest: string;
toSnapshotDigest: string;
generatedAt: string;
entries: NoiseGatingDeltaEntry[];
summary: NoiseGatingDeltaSummary;
hasActionableChanges: boolean;
}
// Summary counts
export interface NoiseGatingDeltaSummary {
totalCount: number;
newCount: number;
resolvedCount: number;
confidenceUpCount: number;
confidenceDownCount: number;
policyImpactCount: number;
dampedCount: number;
evidenceChangedCount: number;
}
// Gating statistics
export interface GatingStatistics {
originalEdgeCount: number;
deduplicatedEdgeCount: number;
edgeReductionPercent: number;
totalVerdictCount: number;
surfacedVerdictCount: number;
dampedVerdictCount: number;
duration: string;
}
```
### NG-FE-003: API Client
Create `src/app/core/api/noise-gating.client.ts`:
```typescript
@Injectable({ providedIn: 'root' })
export class NoiseGatingApiClient {
// Follow VexHubApiHttpClient patterns
// Signal-based state management
// Caching with Map<string, Observable>
}
```
### NG-FE-004: Summary Strip Component
Extend `DeltaSummaryStripComponent` pattern for noise-gating sections:
- New (green), Resolved (blue), ConfidenceUp (teal), ConfidenceDown (orange)
- PolicyImpact (red), Damped (gray), EvidenceChanged (purple)
### NG-FE-005: Delta Entry Card
Create `delta-entry-card.component.ts`:
- Display CVE ID, package, status transition
- Confidence change visualization (before -> after with delta %)
- Section-specific styling
- Link to GatingExplainerComponent for details
### NG-FE-006: Container Component
Create `noise-gating-delta-report.component.ts`:
- Uses `TabsComponent` with section tabs (badge counts)
- Uses `NoiseGatingSummaryStripComponent` for overview
- Filterable entry list within each tab
- Follows three-pane pattern from compare feature
### NG-FE-007: Statistics Card
Create `gating-statistics-card.component.ts`:
- Edge reduction percentage visualization
- Verdict surfacing/damping ratios
- Processing duration display
- Follows `StatCardComponent` patterns
### NG-FE-008: Triage Integration
Add to vuln-explorer:
- "Delta Report" tab or drawer
- Trigger from snapshot comparison
- Link from finding detail to delta context
### NG-FE-009: Module Exports
Update feature module:
- Export new components
- Add to routing if needed
- Register API client
## Decisions & Risks
| Decision | Rationale |
|----------|-----------|
| Compose existing components | ~70% code reuse, consistent UX |
| Signal-based state | Matches existing Angular 17 patterns |
| Section tabs vs flat list | Better UX for categorized changes |
| Lazy-load delta data | Large reports should not block initial render |
## Execution Log
| Date | Action | Notes |
|------|--------|-------|
| 2026-01-04 | Sprint created | Based on backend noise-gating completion |
| 2026-01-04 | NG-FE-001 | Added endpoints to VexLensEndpointExtensions.cs, created NoiseGatingApiModels.cs |
| 2026-01-04 | NG-FE-001 | Created ISnapshotStore, IGatingStatisticsStore with in-memory implementations |
| 2026-01-04 | NG-FE-001 | Updated INoiseGate.DiffAsync to accept DeltaReportOptions |
| 2026-01-04 | NG-FE-001 | Registered storage services in VexLensServiceCollectionExtensions |
| 2026-01-04 | NG-FE-002 | Created noise-gating.models.ts with all API types and helper functions |
| 2026-01-04 | NG-FE-003 | Created noise-gating.client.ts with signal-based state and caching |
| 2026-01-04 | NG-FE-004 | Created NoiseGatingSummaryStripComponent with section badges |
| 2026-01-04 | NG-FE-005 | Created DeltaEntryCardComponent for individual entries |
| 2026-01-04 | NG-FE-006 | Created NoiseGatingDeltaReportComponent container with tabs |
| 2026-01-04 | NG-FE-007 | Created GatingStatisticsCardComponent with progress bars |
| 2026-01-04 | NG-FE-009 | Created index.ts barrel export for noise-gating components |
| 2026-01-04 | NG-FE-008 | Integrated noise-gating into TriageCanvasComponent with Delta tab |
| 2026-01-04 | NG-FE-008 | Added keyboard shortcut 'd' for delta tab |
| 2026-01-04 | NG-FE-008 | Updated triage components index.ts to export noise-gating components |
| 2026-01-04 | Sprint complete | All 9 tasks completed |