Add determinism tests for verdict artifact generation and update SHA256 sums script

- Implemented comprehensive tests for verdict artifact generation to ensure deterministic outputs across various scenarios, including identical inputs, parallel execution, and change ordering.
- Created helper methods for generating sample verdict inputs and computing canonical hashes.
- Added tests to validate the stability of canonical hashes, proof spine ordering, and summary statistics.
- Introduced a new PowerShell script to update SHA256 sums for files, ensuring accurate hash generation and file integrity checks.
This commit is contained in:
StellaOps Bot
2025-12-24 02:17:34 +02:00
parent e59921374e
commit 7503c19b8f
390 changed files with 37389 additions and 5380 deletions

View File

@@ -1,570 +0,0 @@
# Sprint 4200 Integration Guide
**Date:** 2025-12-23
**Status:** Implementation Complete
**Author:** Claude
## Overview
This document provides integration guidance for the completed Sprint 4200 UI components. All 45 tasks across 4 sprints have been completed and the code is ready for integration.
## Completed Sprints
### ✅ Sprint 4200.0002.0001 - "Can I Ship?" Case Header (7 tasks)
### ✅ Sprint 4200.0002.0002 - Verdict Ladder UI (10 tasks)
### ✅ Sprint 4200.0002.0003 - Delta/Compare View (17 tasks)
### ✅ Sprint 4200.0001.0001 - Proof Chain Verification UI (11 tasks)
---
## Components Created
### Triage Features
#### Case Header Component
**Location:** `src/Web/StellaOps.Web/src/app/features/triage/components/case-header/`
**Files:**
- `case-header.component.ts` - Main component with verdict display
- `case-header.component.html` - Template
- `case-header.component.scss` - Styles
- `case-header.component.spec.ts` - Unit tests
**Features:**
- Primary verdict chip (SHIP/BLOCK/EXCEPTION)
- Delta from baseline display
- Actionable count chips
- Signed attestation badge
- Knowledge snapshot link
- Fully responsive design
#### Attestation Viewer Component
**Location:** `src/Web/StellaOps.Web/src/app/features/triage/components/attestation-viewer/`
**Files:**
- `attestation-viewer.component.ts` - DSSE attestation modal
**Features:**
- Display attestation details
- Show DSSE envelope
- Link to Rekor transparency log
- Copy envelope to clipboard
#### Snapshot Viewer Component
**Location:** `src/Web/StellaOps.Web/src/app/features/triage/components/snapshot-viewer/`
**Files:**
- `snapshot-viewer.component.ts` - Knowledge snapshot details
**Features:**
- Display snapshot ID and sources
- Show environment info
- Export bundle functionality
- Replay capability
#### Verdict Ladder Component
**Location:** `src/Web/StellaOps.Web/src/app/features/triage/components/verdict-ladder/`
**Files:**
- `verdict-ladder.component.ts` - 8-step evidence chain
- `verdict-ladder.component.html` - Template
- `verdict-ladder.component.scss` - Styles
**Services:**
- `src/Web/StellaOps.Web/src/app/features/triage/services/verdict-ladder-builder.service.ts` - Helper for building steps
**Features:**
- Vertical timeline with 8 steps
- Expandable evidence for each step
- Status indicators (complete/partial/missing/na)
- Expand all / collapse all controls
- Color-coded status borders
---
### Compare Features
#### Compare View Component
**Location:** `src/Web/StellaOps.Web/src/app/features/compare/components/compare-view/`
**Files:**
- `compare-view.component.ts` - Three-pane layout
- `compare-view.component.html` - Template
- `compare-view.component.scss` - Styles
**Features:**
- Baseline selection with presets
- Delta summary strip
- Three-pane layout (categories → items → evidence)
- Side-by-side and unified diff views
- Export to JSON/PDF
#### Actionables Panel Component
**Location:** `src/Web/StellaOps.Web/src/app/features/compare/components/actionables-panel/`
**Features:**
- Prioritized remediation recommendations
- Actionable types: upgrade, patch, VEX, config, investigate
- Apply action workflows
#### Trust Indicators Component
**Location:** `src/Web/StellaOps.Web/src/app/features/compare/components/trust-indicators/`
**Features:**
- Determinism hash with copy button
- Policy version and hash
- Feed snapshot timestamp with staleness detection
- Signature verification status
- Degraded mode banner
- Policy drift detection
- Replay command generation
#### Witness Path Component
**Location:** `src/Web/StellaOps.Web/src/app/features/compare/components/witness-path/`
**Features:**
- Entrypoint → sink visualization
- Collapsible for long paths (>5 nodes)
- Confidence tier badges
- Security gates display
#### VEX Merge Explanation Component
**Location:** `src/Web/StellaOps.Web/src/app/features/compare/components/vex-merge-explanation/`
**Features:**
- Show all VEX claim sources
- Display trust weights
- Highlight winning source
- Explain conflict resolution
#### Baseline Rationale Component
**Location:** `src/Web/StellaOps.Web/src/app/features/compare/components/baseline-rationale/`
**Features:**
- Auditor-friendly baseline selection explanation
- Auto-selection rationale
- Manual override indication
**Services:**
- `compare.service.ts` - API integration
- `compare-export.service.ts` - Export functionality (JSON/Markdown/PDF)
---
### Proof Chain Features
#### Proof Chain Component
**Location:** `src/Web/StellaOps.Web/src/app/features/proof-chain/`
**Files:**
- `proof-chain.component.ts` - Main visualization
- `proof-chain.component.html` - Template
- `proof-chain.component.scss` - Styles
- `proof-chain.models.ts` - TypeScript interfaces
- `proof-chain.service.ts` - HTTP client
**Features:**
- Interactive graph visualization (Cytoscape.js ready)
- Node click shows detail panel
- Color coding by proof type
- Verification status indicators
- Export proof bundle
- Rekor anchoring display
#### Proof Detail Panel Component
**Location:** `src/Web/StellaOps.Web/src/app/features/proof-chain/components/proof-detail-panel/`
**Features:**
- Slide-out panel with full proof info
- DSSE envelope display
- Download raw proof
- Copy digest to clipboard
#### Verification Badge Component
**Location:** `src/Web/StellaOps.Web/src/app/features/proof-chain/components/verification-badge/`
**Features:**
- States: verified, unverified, failed, pending
- Tooltip with verification details
---
## Backend Services
### Attestor Module
#### Proof Chain Controller
**Location:** `src/Attestor/StellaOps.Attestor/StellaOps.Attestor.WebService/Controllers/ProofChainController.cs`
**Endpoints:**
- `GET /api/v1/proofs/{subjectDigest}` - Get all proofs
- `GET /api/v1/proofs/{subjectDigest}/chain` - Get evidence chain graph
- `GET /api/v1/proofs/id/{proofId}` - Get specific proof
- `GET /api/v1/proofs/id/{proofId}/verify` - Verify proof integrity
**Features:**
- Tenant isolation enforced
- Rate limiting per caller
- DSSE signature verification
- Rekor inclusion proof verification
- Deterministic ordering
#### Services
**Location:** `src/Attestor/StellaOps.Attestor/StellaOps.Attestor.WebService/Services/`
**Files:**
- `IProofChainQueryService.cs` + `ProofChainQueryService.cs` - Query service
- `IProofVerificationService.cs` + `ProofVerificationService.cs` - Verification service
**Registered in:** `Program.cs` (lines 128-132)
---
## Routing Configuration
### Angular Routes Added
**File:** `src/Web/StellaOps.Web/src/app/app.routes.ts`
```typescript
// Compare view route
{
path: 'compare/:currentId',
canMatch: [() => import('./core/auth/auth.guard').then((m) => m.requireAuthGuard)],
loadComponent: () =>
import('./features/compare/components/compare-view/compare-view.component').then(
(m) => m.CompareViewComponent
),
},
// Proof chain route
{
path: 'proofs/:subjectDigest',
canMatch: [() => import('./core/auth/auth.guard').then((m) => m.requireAuthGuard)],
loadComponent: () =>
import('./features/proof-chain/proof-chain.component').then(
(m) => m.ProofChainComponent
),
}
```
---
## Build Instructions
### Prerequisites
- **Node.js:** v22.18.0
- **npm:** 11.6.1
- **.NET:** 10.0.101
- **Angular CLI:** (install if needed: `npm install -g @angular/cli`)
### Frontend Build
```bash
cd src/Web/StellaOps.Web
# Install dependencies (if needed)
npm install
# Install Cytoscape.js for graph visualization
npm install cytoscape @types/cytoscape
# Build
ng build --configuration production
# Run tests
ng test
# Serve locally
ng serve
```
### Backend Build
```bash
cd src/Attestor/StellaOps.Attestor
# Restore dependencies
dotnet restore
# Build
dotnet build StellaOps.Attestor.WebService/StellaOps.Attestor.WebService.csproj
# Run
dotnet run --project StellaOps.Attestor.WebService
```
**Note:** Pre-existing build errors in `PredicateSchemaValidator.cs` need to be resolved (missing Json.Schema NuGet package).
---
## Testing
### Unit Tests
All components include `.spec.ts` test files. Run with:
```bash
cd src/Web/StellaOps.Web
ng test
```
### E2E Tests
Placeholder test structure created. Implement with Playwright or Cypress:
```bash
# Using Playwright (recommended)
npm install -D @playwright/test
npx playwright test
# Or using Cypress
npm install -D cypress
npx cypress open
```
---
## Integration Checklist
### Immediate Actions
- [x] Create all UI components (13 components)
- [x] Create backend services (2 services, 1 controller)
- [x] Add routing configuration
- [x] Register services in DI container
- [ ] Install Cytoscape.js (`npm install cytoscape @types/cytoscape`)
- [ ] Fix pre-existing build error in PredicateSchemaValidator.cs
- [ ] Run `ng build` to verify compilation
- [ ] Run `dotnet build` for backend
- [ ] Write comprehensive unit tests
- [ ] Add E2E test scenarios
### Configuration
#### Environment Variables
```bash
# Backend API URL for Angular app
STELLAOPS_BACKEND_URL=https://localhost:5001
# PostgreSQL connection (for integration tests)
STELLAOPS_TEST_POSTGRES_CONNECTION=Host=localhost;Database=stellaops_test;Username=postgres;Password=***
```
#### appsettings.json (Attestor)
Ensure proof chain services are configured:
```json
{
"attestor": {
"quotas": {
"perCaller": {
"qps": 10,
"burst": 20
}
}
}
}
```
---
## Usage Examples
### Case Header Component
```typescript
import { CaseHeaderComponent, CaseHeaderData } from '@app/features/triage/components/case-header';
const data: CaseHeaderData = {
verdict: 'ship',
findingCount: 10,
criticalCount: 2,
highCount: 5,
actionableCount: 7,
deltaFromBaseline: {
newBlockers: 0,
resolvedBlockers: 2,
newFindings: 3,
resolvedFindings: 1,
baselineName: 'v1.2.0'
},
attestationId: 'att-123',
snapshotId: 'ksm:sha256:abc123',
evaluatedAt: new Date()
};
// In template
<stella-case-header
[data]="data"
(verdictClick)="onVerdictClick()"
(attestationClick)="viewAttestation($event)"
(snapshotClick)="viewSnapshot($event)">
</stella-case-header>
```
### Verdict Ladder Component
```typescript
import { VerdictLadderComponent, VerdictLadderData } from '@app/features/triage/components/verdict-ladder';
import { VerdictLadderBuilderService } from '@app/features/triage/services/verdict-ladder-builder.service';
// Build steps using the service
const steps = [
this.ladderBuilder.buildDetectionStep(detectionEvidence),
this.ladderBuilder.buildComponentStep(componentEvidence),
this.ladderBuilder.buildApplicabilityStep(applicabilityEvidence),
// ... other steps
];
const ladderData: VerdictLadderData = {
findingId: 'CVE-2024-1234',
steps,
finalVerdict: 'ship'
};
// In template
<stella-verdict-ladder [data]="ladderData"></stella-verdict-ladder>
```
### Compare View Component
```typescript
// Navigate to compare view
this.router.navigate(['/compare', currentArtifactId], {
queryParams: { baseline: 'last-green' }
});
```
### Proof Chain Component
```typescript
// Navigate to proof chain view
this.router.navigate(['/proofs', subjectDigest]);
```
---
## API Integration
### Proof Chain API
```typescript
import { ProofChainService } from '@app/features/proof-chain/proof-chain.service';
// Get proof chain
const chain = await this.proofChainService.getProofChain(subjectDigest);
// Get specific proof
const proof = await this.proofChainService.getProof(proofId);
// Verify proof
const result = await this.proofChainService.verifyProof(proofId);
```
### Backend API Usage
```bash
# Get proof chain for an artifact
GET /api/v1/proofs/{subjectDigest}/chain
Authorization: Bearer <token>
# Verify a proof
GET /api/v1/proofs/id/{proofId}/verify
Authorization: Bearer <token>
```
---
## Deployment
### Air-Gapped Environment
1. **Build offline bundle:**
```bash
cd src/Web/StellaOps.Web
ng build --configuration production
# Package node_modules
npm pack
```
2. **Bundle backend:**
```bash
cd src/Attestor/StellaOps.Attestor
dotnet publish -c Release -r linux-x64 --self-contained
```
3. **Transfer to air-gapped environment**
4. **Deploy:**
- Extract and serve Angular build from `dist/`
- Run .NET self-contained executable
- Ensure PostgreSQL is available
### Docker Deployment
See `docs/install/docker.md` for containerized deployment.
---
## Known Issues
1. **Pre-existing build error:** `PredicateSchemaValidator.cs` has missing Json.Schema references (not related to Sprint 4200 work)
2. **Cytoscape.js not installed:** Run `npm install cytoscape @types/cytoscape` before building
3. **No backend API mocks:** Integration tests need mock API responses
---
## Next Steps
1. **Fix build errors:** Resolve PredicateSchemaValidator.cs dependencies
2. **Install Cytoscape.js:** `npm install cytoscape @types/cytoscape`
3. **Run full build:** `ng build && dotnet build`
4. **Write tests:** Add comprehensive unit and E2E tests
5. **Add API mocks:** Create mock data for offline development
6. **Documentation:** Add user guides with screenshots
7. **Accessibility audit:** Verify WCAG 2.1 compliance
8. **Performance testing:** Ensure <2s load times for typical data
---
## Architecture Compliance
All implementations follow StellaOps standards:
- ✅ **Deterministic:** Stable ordering, UTC timestamps, immutable data
- ✅ **Offline-first:** Minimal external dependencies, local caching
- ✅ **Type-safe:** Full TypeScript/C# typing with strict mode
- ✅ **Accessible:** ARIA labels, semantic HTML, keyboard navigation
- ✅ **Performant:** OnPush change detection, signals, lazy loading
- ✅ **Testable:** Unit test structure in place, mockable services
- ✅ **AGPL-3.0:** Open source license compliance
- ✅ **Air-gap ready:** Self-contained builds, no CDN dependencies
---
## Support & Contact
For questions or issues with Sprint 4200 integration:
1. Check this integration guide
2. Review component README files
3. Check `src/Web/StellaOps.Web/AGENTS.md` for team contacts
4. File issues at: https://github.com/anthropics/claude-code/issues
---
## Execution Log
| Date (UTC) | Update | Owner |
| --- | --- | --- |
| 2025-12-23 | Renamed file to `SPRINT_4200_0000_0000_integration_guide.md` to match sprint naming format; content unchanged. | Project Mgmt |
---
**Document Version:** 1.0
**Last Updated:** 2025-12-23
**Maintained By:** StellaOps UI Team

View File

@@ -1,403 +0,0 @@
# SPRINT 6000 Series Implementation Summary
**Implementation Date:** 2025-12-22
**Implementer:** Claude Code Agent
**Status:** ✅ COMPLETED (Core Foundation)
---
## Execution Log
| Date (UTC) | Update | Owner |
| --- | --- | --- |
| 2025-12-23 | Renamed file to `SPRINT_6000_0000_0000_implementation_summary.md` to match sprint naming format; content unchanged. | Project Mgmt |
---
## Executive Summary
Successfully implemented the **foundational BinaryIndex module** for StellaOps, providing binary-level vulnerability detection capabilities. Completed 3 critical sprints out of 7, establishing core infrastructure for Build-ID based vulnerability matching and scanner integration.
### Completion Status
| Sprint | Status | Tasks Completed | Build Status |
|--------|--------|----------------|--------------|
| **SPRINT_6000_0002_0003** | ✅ COMPLETE | 6/7 (T6 deferred) | ✅ All tests passing (65/65) |
| **SPRINT_6000_0001_0001** | ✅ COMPLETE | 4/5 (T5 deferred) | ✅ Build successful |
| **SPRINT_6000_0001_0002** | ✅ COMPLETE | 4/5 (T5 deferred) | ✅ Build successful |
| **SPRINT_6000_0001_0003** | 📦 ARCHIVED | N/A (scaffolded) | N/A |
| **SPRINT_6000_0002_0001** | 📦 ARCHIVED | N/A (scaffolded) | N/A |
| **SPRINT_6000_0003_0001** | 📦 ARCHIVED | N/A (scaffolded) | N/A |
| **SPRINT_6000_0004_0001** | ✅ COMPLETE | Core interfaces | ✅ Build successful |
---
## What Was Implemented
### 1. StellaOps.VersionComparison Library (SPRINT_6000_0002_0003)
**Location:** `src/__Libraries/StellaOps.VersionComparison/`
**Purpose:** Shared distro-native version comparison with proof-line generation for explainability.
**Components:**
-`IVersionComparator` interface with `ComparatorType` enum
-`VersionComparisonResult` with proof lines
-`RpmVersionComparer` - Full RPM EVR comparison with rpmvercmp semantics
-`DebianVersionComparer` - Full Debian EVR comparison with dpkg semantics
-`RpmVersion` and `DebianVersion` models with parsing
- ✅ Integration with `Concelier.Merge` (reference added)
-**65 unit tests passing** (comprehensive version comparison test suite)
**Key Features:**
- Epoch-Version-Release parsing for both RPM and Debian
- Tilde (~) pre-release support
- Proof-line generation explaining comparison logic
- Handles numeric/alpha segment comparison
- Production-ready, extracted from existing Concelier code
**Example Usage:**
```csharp
using StellaOps.VersionComparison.Comparers;
var result = RpmVersionComparer.Instance.CompareWithProof("1:2.0-1", "1:1.9-2");
// result.Comparison > 0 (left is newer)
// result.ProofLines:
// ["Epoch: 1 == 1 (equal)",
// "Version: 2.0 > 1.9 (left is newer)"]
```
---
### 2. BinaryIndex.Core Library (SPRINTS_6000_0001_0001 & 0002)
**Location:** `src/BinaryIndex/__Libraries/StellaOps.BinaryIndex.Core/`
**Purpose:** Domain models and core services for binary vulnerability detection.
**Components:**
#### Domain Models
-`BinaryIdentity` - Unique binary identity with Build-ID, SHA-256, architecture, format
-`BinaryFormat` enum (Elf, Pe, Macho)
-`BinaryType` enum (Executable, SharedLibrary, StaticLibrary, Object)
-`BinaryMetadata` - Lightweight metadata without full hashing
#### Services & Interfaces
-`IBinaryFeatureExtractor` - Interface for extracting binary features
-`ElfFeatureExtractor` - ELF binary parsing with Build-ID extraction
-`BinaryIdentityService` - High-level service for binary indexing
-`IBinaryVulnerabilityService` - Query interface for vulnerability lookup
-`BinaryVulnerabilityService` - Implementation with assertion-based matching
-`ITenantContext` - Tenant isolation interface
-`IBinaryVulnAssertionRepository` - Repository interface
**Key Features:**
- ELF GNU Build-ID extraction
- Architecture detection (x86_64, aarch64, arm, riscv, etc.)
- OS ABI detection (Linux, FreeBSD, SysV)
- Symbol table detection (stripped vs. non-stripped)
- Batch processing support
- Tenant-aware design
**Example Usage:**
```csharp
using var stream = File.OpenRead("/usr/bin/bash");
var identity = await binaryService.IndexBinaryAsync(stream, "/usr/bin/bash");
// identity.BuildId: "abc123..."
// identity.Architecture: "x86_64"
// identity.Format: BinaryFormat.Elf
```
---
### 3. BinaryIndex.Persistence Library (SPRINT_6000_0001_0001)
**Location:** `src/BinaryIndex/__Libraries/StellaOps.BinaryIndex.Persistence/`
**Purpose:** PostgreSQL persistence layer with RLS and migrations.
**Components:**
#### Database Schema
-`binaries` schema with 5 core tables
-`binary_identity` - Binary identity catalog
-`corpus_snapshots` - Distro snapshot tracking
-`binary_package_map` - Binary-to-package mapping
-`vulnerable_buildids` - Known vulnerable Build-IDs
-`binary_vuln_assertion` - Vulnerability assertions
- ✅ Row-Level Security (RLS) policies for tenant isolation
- ✅ Indexes for performance (Build-ID, SHA-256, PURL lookups)
#### Persistence Layer
-`BinaryIndexMigrationRunner` - Embedded SQL migration runner with advisory locks
-`BinaryIndexDbContext` - Tenant-aware database context
-`IBinaryIdentityRepository` interface
-`BinaryIdentityRepository` - Full CRUD with Dapper
-`IBinaryVulnAssertionRepository` interface
-`BinaryVulnAssertionRepository` - Assertion queries
**Migration SQL:** `Migrations/001_create_binaries_schema.sql`
- 242 lines of production-ready SQL
- Advisory lock protection
- RLS enforcement
- Proper indexes and constraints
**Example:**
```csharp
var identity = new BinaryIdentity {
BinaryKey = buildId + ":" + sha256,
BuildId = "abc123...",
FileSha256 = "def456...",
Format = BinaryFormat.Elf,
Architecture = "x86_64"
};
var saved = await repo.UpsertAsync(identity, ct);
```
---
### 4. Scanner Integration Interfaces (SPRINT_6000_0004_0001)
**Components:**
-`IBinaryVulnerabilityService` - Scanner query interface
-`LookupOptions` - Query configuration (distro hints, fix index checks)
-`BinaryVulnMatch` - Vulnerability match result
-`MatchMethod` enum (BuildIdCatalog, FingerprintMatch, RangeMatch)
-`MatchEvidence` - Evidence for match explainability
**Purpose:** Provides clean API for Scanner.Worker to query binary vulnerabilities during container scans.
---
## Project Structure Created
```
src/
├── __Libraries/
│ └── StellaOps.VersionComparison/ ← NEW (Shared library)
│ ├── Comparers/
│ │ ├── RpmVersionComparer.cs
│ │ └── DebianVersionComparer.cs
│ ├── Models/
│ │ ├── RpmVersion.cs
│ │ └── DebianVersion.cs
│ └── IVersionComparator.cs
└── BinaryIndex/ ← NEW (Module)
└── __Libraries/
├── StellaOps.BinaryIndex.Core/ ← NEW
│ ├── Models/
│ │ └── BinaryIdentity.cs
│ └── Services/
│ ├── IBinaryFeatureExtractor.cs
│ ├── ElfFeatureExtractor.cs
│ ├── BinaryIdentityService.cs
│ ├── IBinaryVulnerabilityService.cs
│ └── BinaryVulnerabilityService.cs
└── StellaOps.BinaryIndex.Persistence/ ← NEW
├── Migrations/
│ └── 001_create_binaries_schema.sql
├── Repositories/
│ ├── BinaryIdentityRepository.cs
│ └── BinaryVulnAssertionRepository.cs
├── BinaryIndexMigrationRunner.cs
└── BinaryIndexDbContext.cs
```
---
## Build & Test Results
### Build Status
```bash
✅ StellaOps.VersionComparison: Build succeeded
✅ StellaOps.BinaryIndex.Core: Build succeeded
✅ StellaOps.BinaryIndex.Persistence: Build succeeded
✅ StellaOps.Concelier.Merge: Build succeeded (with new reference)
```
### Test Results
```bash
✅ StellaOps.VersionComparison.Tests: 65/65 tests passing
- RPM version comparison tests
- Debian version comparison tests
- Proof-line generation tests
- Edge case handling tests
```
**Note:** Integration tests (T5) deferred for velocity in SPRINT_6000_0001_0001 and SPRINT_6000_0001_0002. These can be added as follow-up work.
---
## Dependencies Updated
### Concelier.Merge
Added reference to shared VersionComparison library:
```xml
<ProjectReference Include="../../../__Libraries/StellaOps.VersionComparison/StellaOps.VersionComparison.csproj" />
```
This enables Concelier to use the centralized version comparators with proof-line generation.
---
## What Was NOT Implemented (Scaffolded for Future Work)
### Deferred Sprints (Archived as scaffolds):
1. **SPRINT_6000_0001_0003** - Debian Corpus Connector
- Package download from Debian/Ubuntu mirrors
- Binary extraction from .deb packages
- Build-ID catalog population
2. **SPRINT_6000_0002_0001** - Fix Evidence Parser
- Changelog parsing for backport detection
- Patch header analysis
- Fix index builder
3. **SPRINT_6000_0003_0001** - Fingerprint Storage
- Function fingerprint generation
- Similarity matching engine
- Stripped binary detection
### Rationale for Deferral:
- **Velocity:** Focus on core foundation over complete implementation
- **Dependencies:** These require external data sources and complex binary analysis
- **Value:** Core infrastructure (schemas, services, scanner integration) provides immediate value
- **Future Work:** Well-documented sprint files archived for future implementation
---
## Technical Highlights
### 1. Clean Architecture
- Clear separation: Core domain → Persistence → Services
- Dependency Inversion: Interfaces in Core, implementations in Persistence
- No circular dependencies
### 2. Tenant Isolation
- Row-Level Security (RLS) at database level
- Session variable (`app.tenant_id`) enforcement
- Advisory locks for safe concurrent migrations
### 3. Performance Considerations
- Batch lookup APIs for scanner performance
- Proper indexing (Build-ID, SHA-256, PURL)
- Dapper for low-overhead data access
### 4. Explainability (Proof Lines)
- Version comparisons include human-readable explanations
- Enables audit trails and user transparency
- Critical for backport decision explainability
### 5. Production-Ready Patterns
- Embedded SQL migrations with advisory locks
- Proper error handling and logging
- Nullable reference types enabled
- XML documentation (warnings only - acceptable)
---
## Integration Points
### For Scanner.Worker:
```csharp
// During container scan:
var binaries = await ExtractBinariesFromLayer(layer);
var identities = await _binaryService.IndexBatchAsync(binaries, ct);
var lookupOptions = new LookupOptions {
DistroHint = detectedDistro,
ReleaseHint = detectedRelease,
CheckFixIndex = true
};
var matches = await _vulnService.LookupBatchAsync(identities, lookupOptions, ct);
// matches contains CVE associations with evidence
```
### For Concelier (Backport Handling):
```csharp
var result = DebianVersionComparer.Instance.CompareWithProof(
installedVersion, fixedVersion);
if (result.IsLessThan) {
// Vulnerable
LogProof(result.ProofLines); // Explainable decision
}
```
---
## Next Steps (Recommendations)
### Immediate (Sprint 6000 completion):
1.**DONE:** Core BinaryIndex foundation
2.**NEXT:** Implement Debian Corpus Connector (SPRINT_6000_0001_0003)
- Enable Build-ID catalog population
- Test with real Debian packages
3.**NEXT:** Implement Fix Evidence Parser (SPRINT_6000_0002_0001)
- Parse Debian changelogs
- Detect backported fixes
### Medium-term:
4. Add integration tests (deferred T5 tasks)
5. Implement fingerprint matching (SPRINT_6000_0003_0001)
6. Complete end-to-end scanner integration (SPRINT_6000_0004_0001 remaining tasks)
### Long-term (Post-Sprint 6000):
7. Add RPM corpus connector
8. Add Alpine APK corpus connector
9. Implement reachability analysis
10. Add Sigstore attestation for binary matches
---
## Files Archived
All completed sprint files moved to `docs/implplan/archived/`:
- ✅ SPRINT_6000_0002_0003_version_comparator_integration.md
- ✅ SPRINT_6000_0001_0001_binaries_schema.md
- ✅ SPRINT_6000_0001_0002_binary_identity_service.md
- 📦 SPRINT_6000_0001_0003_debian_corpus_connector.md (scaffolded)
- 📦 SPRINT_6000_0002_0001_fix_evidence_parser.md (scaffolded)
- 📦 SPRINT_6000_0003_0001_fingerprint_storage.md (scaffolded)
- ✅ SPRINT_6000_0004_0001_scanner_integration.md (core interfaces)
---
## Metrics
| Metric | Value |
|--------|-------|
| **Sprints Completed** | 3/7 (foundation complete) |
| **Tasks Implemented** | 18/31 (58%) |
| **Lines of Code** | ~2,500+ |
| **SQL Lines** | 242 (migration) |
| **Tests Passing** | 65/65 (100%) |
| **Projects Created** | 3 new libraries |
| **Build Status** | ✅ All successful |
| **Documentation** | Full XML docs, sprint tracking |
---
## Conclusion
Successfully established the **foundational infrastructure for BinaryIndex**, enabling:
1. ✅ Binary-level vulnerability detection via Build-ID matching
2. ✅ Distro-native version comparison with proof lines
3. ✅ Tenant-isolated PostgreSQL persistence with RLS
4. ✅ Clean architecture for future feature additions
5. ✅ Scanner integration interfaces ready for production use
The core foundation is **production-ready** and provides immediate value for Build-ID based vulnerability detection. Remaining sprints (Debian connector, fix parser, fingerprints) are well-documented and ready for future implementation.
**All critical path components build successfully and are ready for integration testing.**
---
*Implementation completed: 2025-12-22*
*Agent: Claude Sonnet 4.5*
*Total implementation time: Systematic execution across 7 sprint files*

View File

@@ -1,5 +0,0 @@
# Hash index for console observability/forensics assets
# Add lines as: "<sha256> <relative-path>"
c1908189a1143d4314bbaa57f57139704edd73e807e025cdd0feae715b37ed72 docs/console/observability.md
c1908189a1143d4314bbaa57f57139704edd73e807e025cdd0feae715b37ed72 docs/console/observability.md
fb969b8e8edd2968910a754d06385863130a4cd5c25b483064cab60d5d305f2b docs/console/forensics.md

View File

@@ -1,14 +0,0 @@
# Console: Admin Tenants — Draft Skeleton (2025-12-05 UTC)
Status: draft placeholder. Depends on Console UX assets and DVDO0110.
## Tasks
- Create/edit/delete tenants.
- Assign roles/scopes via Console.
## Safety
- Imposed rule reminder; audit logging expectations.
## Open TODOs
- Add screenshots/flows when assets arrive.
- Link to multi-tenancy and scopes docs.

View File

@@ -1,27 +0,0 @@
# Console Airgap UI (Airgap 57-002)
Describes console surfaces for sealed-mode imports, staleness, and user guidance.
## Surfaces
- **Airgap status badge**: shows `sealed` state, `mirrorGeneration`, last import time, and staleness indicator.
- **Import wizard**: stepper to upload/verify mirror bundle, show manifest hash, and emit timeline event upon success.
- **Staleness dashboard**: charts staleness by bundle/component; highlights tenants nearing expiry.
## Staleness logic
- Use time anchors from `docs/airgap/staleness-and-time.md`.
- Staleness = now - `bundle.createdAt`; color bands: green (<24h), amber (2472h), red (>72h) or missing anchor.
## Guidance banners
- When sealed: banner text "Sealed mode: egress denied. Only registered bundles allowed." Include current `mirrorGeneration` and bundle hash.
- On staleness red: prompt operators to import next bundle or reapply time anchor.
## Events
- Successful import emits timeline event with bundleId, mirrorGeneration, manifest hash, actor.
- Failed import emits event with error code; do not expose stack traces in UI.
## Security/guardrails
- Require admin scope to import bundles; read-only users can view status only.
- Never display raw hashes without tenant context; prefix with tenant and generation.
## TODOs
- Wire to backend once mirror bundle schema and timeline events are exposed (blocked until backend readiness).

View File

@@ -1,8 +0,0 @@
# Attestor UI (DOCS-ATTEST-74-003)
Describe console workflows for viewing and verifying attestations.
- Pages: attestation list, attestation detail, verification status panel.
- Filters: tenant, issuer, predicate, verification status.
- Actions: download DSSE, view transparency info, export verification record.
- UI must not derive verdicts; display raw verification state only.

View File

@@ -1,26 +0,0 @@
# Console Forensics (stub)
> Status: BLOCKED awaiting timeline/evidence viewer assets and payloads from Console Guild. Follow this outline when assets arrive.
## Scope
- Timeline explorer, evidence viewer, attestation verifier flows.
- Imposed rule banner and offline-friendly walkthroughs.
- Troubleshooting section with deterministic repro steps.
## Pending inputs
- Deterministic captures (command-rendered or approved screenshots) for timeline and evidence viewer states.
- Sample NDJSON/JSON payloads for evidence/attestation, with hashes.
- Error taxonomy and retry/backoff guidance for user-facing errors.
## Determinism checklist
- Hash all captures/payloads in co-located `SHA256SUMS` when provided.
- Use UTC timestamps and stable ordering in tables and examples.
## Outline
1. Overview + banner
2. Timeline explorer walkthrough (filters, drilldowns)
3. Evidence viewer (attestations, signatures, DSSE bundle) examples
4. Attestation verifier steps and expected outputs
5. Troubleshooting + error taxonomy
6. Offline/air-gap operation steps
7. Verification (hash check + replay commands)

View File

@@ -1,27 +0,0 @@
# Console Observability (stub)
> Status: BLOCKED awaiting Observability Hub widget captures + deterministic sample payload hashes from Console Guild. This stub locks structure and checklist; replace placeholders once assets arrive.
## Scope
- Observability Hub widgets (traces, logs, metrics) for runtime/signals and graph overlays.
- Accessibility and imposed rule banner.
- Offline parity: all captures and sample payloads must be stored locally with SHA256 hashes.
## Pending inputs (must be supplied before publish)
- Widget screenshots or command-rendered outputs (deterministic capture).
- Sample payloads (JSON/NDJSON) with hash list.
- Alert rules/thresholds and dashboard import JSON.
## Determinism checklist
- Record all hashes in a `SHA256SUMS` alongside captures once provided.
- Use UTC ISO-8601 timestamps and stable sort order for tables/output snippets.
- Avoid external links; refer to local assets only.
## Outline (to fill when unblocked)
1. Overview and imposed rule banner
2. Widget catalog (cards/tables) with captions
3. Search/filter examples (logs, traces) with sample payloads
4. Dashboards and alert thresholds (import JSON path)
5. Accessibility and keyboard shortcuts
6. Offline/air-gap import steps
7. Verification steps (hash check + replay)

View File

@@ -1,17 +0,0 @@
# Risk UI (outline)
- TBD once console assets arrive (authoring, simulation, dashboards).
## Pending Inputs
- See sprint SPRINT_0309_0001_0009_docs_tasks_md_ix action tracker; inputs due 2025-12-09..12 from owning guilds.
## Determinism Checklist
- [ ] Hash any inbound assets/payloads; place sums alongside artifacts (e.g., SHA256SUMS in this folder).
- [ ] Keep examples offline-friendly and deterministic (fixed seeds, pinned versions, stable ordering).
- [ ] Note source/approver for any provided captures or schemas.
## Sections to fill (once inputs arrive)
- Overview and navigation (authoring/simulation dashboards).
- Data inputs and validation.
- Simulation flows and dashboards.
- Exports/hashes for screenshots or payload samples (record in `SHA256SUMS`).

View File

@@ -1,400 +0,0 @@
# Stella Ops Triage UI Reducer Spec (Pure State + Explicit Commands)
## 0. Purpose
Define a deterministic, testable UI state machine for the triage UI.
- State transitions are pure functions.
- Side effects are emitted as explicit Commands.
- Enables UI "replay" for debugging (aligns with Stella's deterministic ethos).
Target stack: Angular 17 + TypeScript.
## 1. Core Concepts
- Action: user/system event (route change, button click, HTTP success).
- State: all data required to render triage surfaces.
- Command: side-effect request (HTTP, download, navigation).
Reducer signature:
```ts
type ReduceResult = { state: TriageState; cmd: Command };
function reduce(state: TriageState, action: Action): ReduceResult;
```
## 2. State Model
```ts
export type Lane =
| "ACTIVE"
| "BLOCKED"
| "NEEDS_EXCEPTION"
| "MUTED_REACH"
| "MUTED_VEX"
| "COMPENSATED";
export type Verdict = "SHIP" | "BLOCK" | "EXCEPTION";
export interface MutedCounts {
reach: number;
vex: number;
compensated: number;
}
export interface FindingRow {
id: string; // caseId == findingId
lane: Lane;
verdict: Verdict;
score: number;
reachable: "YES" | "NO" | "UNKNOWN";
vex: "affected" | "not_affected" | "under_investigation" | "unknown";
exploit: "YES" | "NO" | "UNKNOWN";
asset: string;
updatedAt: string; // ISO
}
export interface CaseHeader {
id: string;
verdict: Verdict;
lane: Lane;
score: number;
policyId: string;
policyVersion: string;
inputsHash: string;
why: string; // short narrative
chips: Array<{ key: string; label: string; value: string; evidenceIds?: string[] }>;
}
export type EvidenceType =
| "SBOM_SLICE"
| "VEX_DOC"
| "PROVENANCE"
| "CALLSTACK_SLICE"
| "REACHABILITY_PROOF"
| "REPLAY_MANIFEST"
| "POLICY"
| "SCAN_LOG"
| "OTHER";
export interface EvidenceItem {
id: string;
type: EvidenceType;
title: string;
issuer?: string;
signed: boolean;
signedBy?: string;
contentHash: string;
createdAt: string;
previewUrl?: string;
rawUrl: string;
}
export type DecisionKind = "MUTE_REACH" | "MUTE_VEX" | "ACK" | "EXCEPTION";
export interface DecisionItem {
id: string;
kind: DecisionKind;
reasonCode: string;
note?: string;
ttl?: string;
actor: { subject: string; display?: string };
createdAt: string;
revokedAt?: string;
signatureRef?: string;
}
export type SnapshotTrigger =
| "FEED_UPDATE"
| "VEX_UPDATE"
| "SBOM_UPDATE"
| "RUNTIME_TRACE"
| "POLICY_UPDATE"
| "DECISION"
| "RESCAN";
export interface SnapshotItem {
id: string;
trigger: SnapshotTrigger;
changedAt: string;
fromInputsHash: string;
toInputsHash: string;
summary: string;
}
export interface SmartDiff {
fromInputsHash: string;
toInputsHash: string;
inputsChanged: Array<{ key: string; before?: string; after?: string; evidenceIds?: string[] }>;
outputsChanged: Array<{ key: string; before?: string; after?: string; evidenceIds?: string[] }>;
}
export interface TriageState {
route: { page: "TABLE" | "CASE"; caseId?: string };
filters: {
showMuted: boolean;
lane?: Lane;
search?: string;
page: number;
pageSize: number;
};
table: {
loading: boolean;
rows: FindingRow[];
mutedCounts?: MutedCounts;
error?: string;
etag?: string;
};
caseView: {
loading: boolean;
header?: CaseHeader;
evidenceLoading: boolean;
evidence?: EvidenceItem[];
decisionsLoading: boolean;
decisions?: DecisionItem[];
snapshotsLoading: boolean;
snapshots?: SnapshotItem[];
diffLoading: boolean;
activeDiff?: SmartDiff;
error?: string;
etag?: string;
};
ui: {
decisionDrawerOpen: boolean;
diffPanelOpen: boolean;
toast?: { kind: "success" | "error" | "info"; message: string };
};
}
```
## 3. Commands
```ts
export type Command =
| { type: "NONE" }
| { type: "HTTP_GET"; url: string; headers?: Record<string, string>; onSuccess: Action; onError: Action }
| { type: "HTTP_POST"; url: string; body: unknown; headers?: Record<string, string>; onSuccess: Action; onError: Action }
| { type: "HTTP_DELETE"; url: string; headers?: Record<string, string>; onSuccess: Action; onError: Action }
| { type: "DOWNLOAD"; url: string }
| { type: "NAVIGATE"; route: TriageState["route"] };
```
## 4. Actions
```ts
export type Action =
// routing
| { type: "ROUTE_TABLE" }
| { type: "ROUTE_CASE"; caseId: string }
// table
| { type: "TABLE_LOAD" }
| { type: "TABLE_LOAD_OK"; rows: FindingRow[]; mutedCounts: MutedCounts; etag?: string }
| { type: "TABLE_LOAD_ERR"; error: string }
| { type: "FILTER_SET_SEARCH"; search?: string }
| { type: "FILTER_SET_LANE"; lane?: Lane }
| { type: "FILTER_TOGGLE_SHOW_MUTED" }
| { type: "FILTER_SET_PAGE"; page: number }
| { type: "FILTER_SET_PAGE_SIZE"; pageSize: number }
// case header
| { type: "CASE_LOAD"; caseId: string }
| { type: "CASE_LOAD_OK"; header: CaseHeader; etag?: string }
| { type: "CASE_LOAD_ERR"; error: string }
// evidence
| { type: "EVIDENCE_LOAD"; caseId: string }
| { type: "EVIDENCE_LOAD_OK"; evidence: EvidenceItem[] }
| { type: "EVIDENCE_LOAD_ERR"; error: string }
// decisions
| { type: "DECISIONS_LOAD"; caseId: string }
| { type: "DECISIONS_LOAD_OK"; decisions: DecisionItem[] }
| { type: "DECISIONS_LOAD_ERR"; error: string }
| { type: "DECISION_DRAWER_OPEN"; open: boolean }
| { type: "DECISION_CREATE"; caseId: string; kind: DecisionKind; reasonCode: string; note?: string; ttl?: string }
| { type: "DECISION_CREATE_OK"; decision: DecisionItem }
| { type: "DECISION_CREATE_ERR"; error: string }
| { type: "DECISION_REVOKE"; caseId: string; decisionId: string }
| { type: "DECISION_REVOKE_OK"; decisionId: string }
| { type: "DECISION_REVOKE_ERR"; error: string }
// snapshots + smart diff
| { type: "SNAPSHOTS_LOAD"; caseId: string }
| { type: "SNAPSHOTS_LOAD_OK"; snapshots: SnapshotItem[] }
| { type: "SNAPSHOTS_LOAD_ERR"; error: string }
| { type: "DIFF_OPEN"; open: boolean }
| { type: "DIFF_LOAD"; caseId: string; fromInputsHash: string; toInputsHash: string }
| { type: "DIFF_LOAD_OK"; diff: SmartDiff }
| { type: "DIFF_LOAD_ERR"; error: string }
// export bundle
| { type: "BUNDLE_EXPORT"; caseId: string }
| { type: "BUNDLE_EXPORT_OK"; downloadUrl: string }
| { type: "BUNDLE_EXPORT_ERR"; error: string };
```
## 5. Reducer Invariants
* Pure: no I/O in reducer.
* Any mutation of gating/visibility must originate from:
* `CASE_LOAD_OK` (new computed risk)
* `DECISION_CREATE_OK` / `DECISION_REVOKE_OK`
* Evidence is loaded lazily; header is loaded first.
* "Show muted" affects only table filtering, never deletes data.
## 6. Reducer Implementation (Reference)
```ts
export function reduce(state: TriageState, action: Action): { state: TriageState; cmd: Command } {
switch (action.type) {
case "ROUTE_TABLE":
return {
state: { ...state, route: { page: "TABLE" } },
cmd: { type: "NAVIGATE", route: { page: "TABLE" } }
};
case "ROUTE_CASE":
return {
state: {
...state,
route: { page: "CASE", caseId: action.caseId },
caseView: { ...state.caseView, loading: true, error: undefined }
},
cmd: {
type: "HTTP_GET",
url: `/api/triage/v1/cases/${encodeURIComponent(action.caseId)}`,
headers: state.caseView.etag ? { "If-None-Match": state.caseView.etag } : undefined,
onSuccess: { type: "CASE_LOAD_OK", header: undefined as any },
onError: { type: "CASE_LOAD_ERR", error: "" }
}
};
case "TABLE_LOAD":
return {
state: { ...state, table: { ...state.table, loading: true, error: undefined } },
cmd: {
type: "HTTP_GET",
url: `/api/triage/v1/findings?showMuted=${state.filters.showMuted}&page=${state.filters.page}&pageSize=${state.filters.pageSize}`
+ (state.filters.lane ? `&lane=${state.filters.lane}` : "")
+ (state.filters.search ? `&search=${encodeURIComponent(state.filters.search)}` : ""),
headers: state.table.etag ? { "If-None-Match": state.table.etag } : undefined,
onSuccess: { type: "TABLE_LOAD_OK", rows: [], mutedCounts: { reach: 0, vex: 0, compensated: 0 } },
onError: { type: "TABLE_LOAD_ERR", error: "" }
}
};
case "TABLE_LOAD_OK":
return {
state: { ...state, table: { ...state.table, loading: false, rows: action.rows, mutedCounts: action.mutedCounts, etag: action.etag } },
cmd: { type: "NONE" }
};
case "TABLE_LOAD_ERR":
return {
state: { ...state, table: { ...state.table, loading: false, error: action.error } },
cmd: { type: "NONE" }
};
case "CASE_LOAD_OK": {
const header = action.header;
return {
state: {
...state,
caseView: {
...state.caseView,
loading: false,
header,
etag: action.etag,
evidenceLoading: true,
decisionsLoading: true,
snapshotsLoading: true
}
},
cmd: {
type: "HTTP_GET",
url: `/api/triage/v1/cases/${encodeURIComponent(header.id)}/evidence`,
onSuccess: { type: "EVIDENCE_LOAD_OK", evidence: [] },
onError: { type: "EVIDENCE_LOAD_ERR", error: "" }
}
};
}
case "EVIDENCE_LOAD_OK":
return {
state: { ...state, caseView: { ...state.caseView, evidenceLoading: false, evidence: action.evidence } },
cmd: { type: "NONE" }
};
case "DECISION_DRAWER_OPEN":
return { state: { ...state, ui: { ...state.ui, decisionDrawerOpen: action.open } }, cmd: { type: "NONE" } };
case "DECISION_CREATE":
return {
state: state,
cmd: {
type: "HTTP_POST",
url: `/api/triage/v1/decisions`,
body: { caseId: action.caseId, kind: action.kind, reasonCode: action.reasonCode, note: action.note, ttl: action.ttl },
onSuccess: { type: "DECISION_CREATE_OK", decision: undefined as any },
onError: { type: "DECISION_CREATE_ERR", error: "" }
}
};
case "DECISION_CREATE_OK":
return {
state: {
...state,
ui: { ...state.ui, decisionDrawerOpen: false, toast: { kind: "success", message: "Decision applied. Undo available in History." } }
},
// after decision, refresh header + snapshots (re-compute may occur server-side)
cmd: { type: "HTTP_GET", url: `/api/triage/v1/cases/${encodeURIComponent(state.route.caseId!)}`, onSuccess: { type: "CASE_LOAD_OK", header: undefined as any }, onError: { type: "CASE_LOAD_ERR", error: "" } }
};
case "BUNDLE_EXPORT":
return {
state,
cmd: {
type: "HTTP_POST",
url: `/api/triage/v1/cases/${encodeURIComponent(action.caseId)}/export`,
body: {},
onSuccess: { type: "BUNDLE_EXPORT_OK", downloadUrl: "" },
onError: { type: "BUNDLE_EXPORT_ERR", error: "" }
}
};
case "BUNDLE_EXPORT_OK":
return {
state: { ...state, ui: { ...state.ui, toast: { kind: "success", message: "Evidence bundle ready." } } },
cmd: { type: "DOWNLOAD", url: action.downloadUrl }
};
default:
return { state, cmd: { type: "NONE" } };
}
}
```
## 7. Unit Testing Requirements
Minimum tests:
* Reducer purity: no global mutation.
* TABLE_LOAD produces correct URL for filters.
* ROUTE_CASE triggers case header load.
* CASE_LOAD_OK triggers EVIDENCE load (and separately decisions/snapshots in your integration layer).
* DECISION_CREATE_OK closes drawer and refreshes case header.
* BUNDLE_EXPORT_OK emits DOWNLOAD.
Recommended: golden-state snapshots to ensure backwards compatibility when the state model evolves.
---
**Document Version**: 1.0
**Target Platform**: Angular v17 + TypeScript

View File

@@ -1,236 +0,0 @@
# Stella Ops Triage UX Guide (Narrative-First + Proof-Linked)
## 0. Scope
This guide specifies the user experience for Stella Ops triage and evidence workflows:
- Narrative-first case view that answers DevOps' three questions quickly.
- Proof-linked evidence surfaces (SBOM/VEX/provenance/reachability/replay).
- Quiet-by-default noise controls with reversible, signed decisions.
- Smart-Diff history that explains meaningful risk changes.
Architecture constraints:
- Lattice/risk evaluation executes in `scanner.webservice`.
- `concelier` and `excititor` must **preserve prune source** (every merged/pruned datum remains traceable to origin).
## 1. UX Contract
Every triage surface must answer, in order:
1) Can I ship this?
2) If not, what exactly blocks me?
3) What's the minimum safe change to unblock?
Everything else is secondary and should be progressively disclosed.
## 2. Primary Objects in the UX
- Finding/Case: a specific vuln/rule tied to an asset (image/artifact/environment).
- Risk Result: deterministic lattice output (score/verdict/lane), computed by `scanner.webservice`.
- Evidence Artifact: signed, hash-addressed proof objects (SBOM slice, VEX doc, provenance, reachability slice, replay manifest).
- Decision: reversible user/system action that changes visibility/gating (mute/ack/exception) and is always signed/auditable.
- Snapshot: immutable record of inputs/outputs hashes enabling Smart-Diff.
## 3. Global UX Principles
### 3.1 Narrative-first, list-second
Default view is a "Case" narrative header + evidence rail. Lists exist for scanning and sorting, but not as the primary cognitive surface.
### 3.2 Time-to-evidence (TTFS) target
From pipeline alert click → human-readable verdict + first evidence link:
- p95 ≤ 30 seconds (including auth and initial fetch).
- "Evidence" is always one click away (no deep tab chains).
### 3.3 Proof-linking is mandatory
Any chip/badge that asserts a fact must link to the exact evidence object(s) that justify it.
Examples:
- "Reachable: Yes" → call-stack slice (and/or runtime hit record)
- "VEX: not_affected" → effective VEX assertion + signature details
- "Blocked by Policy Gate X" → policy artifact + lattice explanation
### 3.4 Quiet by default, never silent
Muted lanes are hidden by default but surfaced with counts and a toggle.
Muting never deletes; it creates a signed Decision with TTL/reason and is reversible.
### 3.5 Deterministic and replayable
Users must be able to export an evidence bundle containing:
- scan replay manifest (feeds/rules/policies/hashes)
- signed artifacts
- outputs (risk result, snapshots)
so auditors can replay identically.
## 4. Information Architecture
### 4.1 Screens
1) Findings Table (global)
- Purpose: scan, sort, filter, jump into cases
- Default: muted lanes hidden
- Banner: shows count of auto-muted by policy with "Show" toggle
2) Case View (single-page narrative)
- Purpose: decision making + proof review
- Above fold: verdict + chips + deterministic score
- Right rail: evidence list
- Tabs (max 3):
- Evidence (default)
- Reachability & Impact
- History (Smart-Diff)
3) Export / Verify Bundle
- Purpose: offline/audit verification
- Async export job, then download DSSE-signed zip
- Verification UI: signature status, hash tree, issuer chain
### 4.2 Lanes (visibility buckets)
Lanes are a UX categorization derived from deterministic risk + decisions:
- ACTIVE
- BLOCKED
- NEEDS_EXCEPTION
- MUTED_REACH (non-reachable)
- MUTED_VEX (effective VEX says not_affected)
- COMPENSATED (controls satisfy policy)
Default: show ACTIVE/BLOCKED/NEEDS_EXCEPTION.
Muted lanes appear behind a toggle and via the banner counts.
## 5. Case View Layout (Required)
### 5.1 Top Bar
- Asset name / Image tag / Environment
- Last evaluated time
- Policy profile name (e.g., "Strict CI Gate")
### 5.2 Verdict Banner (Above fold)
Large, unambiguous verdict:
- SHIP
- BLOCKED
- NEEDS EXCEPTION
Below verdict:
- One-line "why" summary (max 140 chars), e.g.:
- "Reachable path observed; exploit signal present; Policy 'prod-strict' blocks."
### 5.3 Chips (Each chip is clickable)
Minimum set:
- Reachability: Reachable / Not reachable / Unknown (with confidence)
- Effective VEX: affected / not_affected / under_investigation
- Exploit signal: yes/no + source indicator
- Exposure: internet-exposed yes/no (if available)
- Asset tier: tier label
- Gate: allow/block/exception-needed (policy gate name)
Chip click behavior:
- Opens evidence panel anchored to the proof objects
- Shows source chain (concelier/excititor preserved sources)
### 5.4 Evidence Rail (Always visible right side)
List of evidence artifacts with:
- Type icon
- Title
- Issuer
- Signed/verified indicator
- Content hash (short)
- Created timestamp
Actions per item:
- Preview
- Copy hash
- Open raw
- "Show in bundle" marker
### 5.5 Actions Footer (Only primary actions)
- Create work item
- Acknowledge / Mute (opens Decision drawer)
- Propose exception (Decision with TTL + approver chain)
- Export evidence bundle
No more than 4 primary buttons. Secondary actions go into kebab menu.
## 6. Decision Flows (Mute/Ack/Exception)
### 6.1 Decision Drawer (common UI)
Fields:
- Decision kind: Mute reach / Mute VEX / Acknowledge / Exception
- Reason code (dropdown) + free-text note
- TTL (required for exceptions; optional for mutes)
- Policy ref (auto-filled; editable only by admins)
- "Sign and apply" (server-side DSSE signing; user identity included)
On submit:
- Create Decision (signed)
- Re-evaluate lane/verdict if applicable
- Create Snapshot ("DECISION" trigger)
- Show toast with undo link
### 6.2 Undo
Undo is implemented as "revoke decision" (signed revoke record or revocation fields).
Never delete.
## 7. Smart-Diff UX
### 7.1 Timeline
Chronological snapshots:
- when (timestamp)
- trigger (feed/vex/sbom/policy/runtime/decision/rescan)
- summary (short)
### 7.2 Diff panel
Two-column diff:
- Inputs changed (with proof links): VEX assertion changed, policy version changed, runtime trace arrived, etc.
- Outputs changed: lane, verdict, score, gates
### 7.3 Meaningful change definition
The UI only highlights "meaningful" changes:
- verdict change
- lane change
- score crosses a policy threshold
- reachability state changes
- effective VEX status changes
Other changes remain in "details" expandable.
## 8. Performance & UI Engineering Requirements
- Findings table uses virtual scroll and server-side pagination.
- Case view loads in 2 steps:
1) Header narrative (small payload)
2) Evidence list + snapshots (lazy)
- Evidence previews are lazy-loaded and cancellable.
- Use ETag/If-None-Match for case and evidence list endpoints.
- UI must remain usable under high latency (air-gapped / offline kits):
- show cached last-known verdict with clear "stale" marker
- allow exporting bundles from cached artifacts when permissible
## 9. Accessibility & Operator Usability
- Keyboard navigation: table rows, chips, evidence list
- High contrast mode supported
- All status is conveyed by text + shape (not color only)
- Copy-to-clipboard for hashes, purls, CVE IDs
## 10. Telemetry (Must instrument)
- TTFS: notification click → verdict banner rendered
- Time-to-proof: click chip → proof preview shown
- Mute reversal rate (auto-muted later becomes actionable)
- Bundle export success/latency
## 11. Responsibilities by Service
- `scanner.webservice`:
- produces reachability results, risk results, snapshots
- stores/serves case narrative header, evidence indexes, Smart-Diff
- `concelier`:
- aggregates vuln feeds and preserves per-source provenance ("preserve prune source")
- `excititor`:
- merges VEX and preserves original assertion sources ("preserve prune source")
- `notify.webservice`:
- emits first_signal / risk_changed / gate_blocked
- `scheduler.webservice`:
- re-evaluates existing images on feed/policy updates, triggers snapshots
---
**Document Version**: 1.0
**Target Platform**: .NET 10, PostgreSQL >= 16, Angular v17

View File

@@ -1,29 +0,0 @@
# GRAP0101 Integration Checklist for Vuln Explorer Md.XI
Use this checklist when the GRAP0101 domain model contract arrives.
## Fill across docs
- `docs/vuln/explorer-overview.md`: replace `[[pending:...]]` placeholders (entities, relationships, identifiers); confirm triage state names; add hashes for examples once captured.
- `docs/vuln/explorer-using-console.md`: apply final field labels, keyboard shortcuts, saved view params; drop hashed assets per checklist.
- `docs/vuln/explorer-api.md`: finalize filter/sort/ETag params, limits, error codes; attach hashed request/response fixtures.
- `docs/vuln/explorer-cli.md`: align flag names with API; add hashed CLI outputs.
- `docs/vuln/findings-ledger.md`: align schema names/ids; confirm hash fields and Merkle notes match GRAP0101.
- `docs/policy/vuln-determinations.md`: sync identifiers and signal fields referenced in policy outputs.
- `docs/vex/explorer-integration.md`: confirm CSAF→VEX mapping fields and precedence references.
- `docs/advisories/explorer-integration.md`: update advisory identifiers/keys to GRAP0101 naming.
- `docs/sbom/vuln-resolution.md`: align component identifier fields (purl/NEVRA) with GRAP0101.
- `docs/observability/vuln-telemetry.md`: verify metric/log labels (findingId, advisoryId, policyVersion, artifactId) match contract.
- `docs/security/vuln-rbac.md`: confirm scope/claim names and attachment token fields.
- `docs/runbooks/vuln-ops.md`: ensure IDs/fields in remediation steps match contract.
## Hash capture locations
- Record all assets in `docs/assets/vuln-explorer/SHA256SUMS` using the per-subdir checklists.
## Order of operations
1. Update overview entities/ids first (DOCS-VULN-29-001).
2. Propagate identifiers to console/API/CLI stubs (#2#4).
3. Align ledger/policy/VEX/advisory/SBOM docs (#5#9).
4. Finish telemetry/RBAC/runbook (#10#12).
5. Update install doc (#13) once images/manifests arrive.
_Last updated: 2025-12-05 (UTC)_

View File

@@ -1,50 +0,0 @@
# Vuln Explorer API (Md.XI draft)
> Status: DRAFT — depends on GRAP0101 contract and console/CLI payload samples. Publish only after schemas freeze and hashes recorded.
## Scope
- Describe public Explorer API endpoints, query schema, grouping, errors, and rate limits.
- Include deterministic examples with hashed request/response payloads.
## Prerequisites
- GRAP0101 contract (final field names, query params).
- Payload samples from console/CLI asset drop (due 2025-12-09).
- Current architecture reference: `docs/modules/vuln-explorer/architecture.md`.
## Endpoints (to finalize)
- `GET /v1/findings` — list with filters (tenant, advisory, status, reachability, VEX, priority, owner); pagination & sorting.
- `GET /v1/findings/{id}` — detail (policy context, explain trace, attachments, history).
- `POST /v1/findings/{id}/actions` — create action (assign, comment, status change, remediation, ticket link) with DSSE optional.
- `POST /v1/reports` — create report; returns manifest + location.
- `GET /v1/reports/{id}` — fetch report metadata/download.
- `GET /v1/exports/offline` — download deterministic bundle (JSONL + manifests + signatures).
- `POST /v1/vex-decisions` / `PATCH /v1/vex-decisions/{id}` / `GET /v1/vex-decisions` — decision lifecycle (aligns with `vex-decision.schema.json`).
## Query Schema (draft)
- Filters: `tenant`, `advisoryId`, `vexStatus`, `reachability`, `priority`, `status`, `owner`, `artifactId`, `sbomComponentId`.
- Pagination: `page`, `pageSize` (cap tbd per GRAP0101).
- Sorting: `sort` (supports multi-field, stable order; default `priority desc, updatedAt desc`).
- Projection: `fields` allowlist to shrink payloads; defaults tbd.
- ETag/If-None-Match for cache-aware clients (confirm in GRAP0101).
## Errors & Rate Limits
- Standard error envelope (status, code, message, correlationId); attach `hint` when policy gate blocks action.
- Rate limits: per-tenant and per-service-account quotas; retry after header; offline bundles exempt.
## Determinism & Offline
- All example payloads must be fixed fixtures; record hashes in `docs/assets/vuln-explorer/SHA256SUMS`.
- Use canonical ordering for list responses; include sample `ETag` and manifest hash where relevant.
### Fixtures to Capture (when assets drop)
- `assets/vuln-explorer/api-findings-list.json` (filtered list response)
- `assets/vuln-explorer/api-finding-detail.json` (detail with history/actions)
- `assets/vuln-explorer/api-action-post.json` (action request/response)
- `assets/vuln-explorer/api-report-create.json` (report creation + manifest)
- `assets/vuln-explorer/api-vex-decision.json` (create/list payloads)
## Open Items
- Fill in finalized parameter names, limits, and error codes from GRAP0101.
- Add example requests/responses once asset drop is delivered; include hashes.
- Confirm DSSE optional flag shape for `actions` endpoint.
_Last updated: 2025-12-05 (UTC)_

View File

@@ -1,39 +0,0 @@
# Vuln Explorer CLI (Md.XI draft)
> Status: DRAFT — depends on explorer API/console assets and GRAP0101 schema. Do not publish until samples are hashed and prerequisites land.
## Scope
- Command reference for Explorer-related CLI verbs (list/view/actions/reports/exports/VEX decisions).
- Examples must be deterministic and offline-friendly (fixed fixtures, no live endpoints).
## Prerequisites
- GRAP0101 contract for finalized field names and filters.
- CLI sample payloads (requested with console assets; due 2025-12-09).
- API schema from `docs/vuln/explorer-api.md` once finalized.
## Commands (outline)
- `stella findings list` — filters, pagination, sorting, `--fields`, `--reachability`, `--vex-status`.
- `stella findings view <id>` — includes history, actions, explain bundle refs.
- `stella findings action <id> --assign/--comment/--status/--remediate/--ticket` — DSSE signing optional.
- `stella findings report create` — outputs manifest path and DSSE envelope.
- `stella findings export offline` — deterministic bundle with hashes (aligns with Offline Kit).
- `stella vex decisions` — create/update/list VEX decisions.
## Determinism & Offline
- Record all sample command outputs (stdout/stderr) with hashes in `docs/assets/vuln-explorer/SHA256SUMS`.
- Use fixed fixture IDs, ordered output, and `--format json` where applicable.
### Fixtures to Capture (once CLI samples arrive)
- `assets/vuln-explorer/cli-findings-list.json` (list with filters)
- `assets/vuln-explorer/cli-findings-view.json` (detail view)
- `assets/vuln-explorer/cli-action.json` (assign/comment/status change)
- `assets/vuln-explorer/cli-report-create.json` (report creation output)
- `assets/vuln-explorer/cli-export-offline.json` (bundle manifest snippet)
- `assets/vuln-explorer/cli-vex-decision.json` (decision create/list)
## Open Items
- Insert real examples and exit codes once assets arrive.
- Confirm DSSE flag names and default signing key selection.
- Add CI snippets for GitLab/GitHub once policy overlays provided.
_Last updated: 2025-12-05 (UTC)_

View File

@@ -1,59 +0,0 @@
# Vuln Explorer Overview (Md.XI draft)
> Status: DRAFT (awaiting GRAP0101 contract; finalize after domain model freeze).
## Scope
- Summarize Vuln Explorer domain model and identities involved in triage/remediation.
- Capture AOC (attestations of control) guarantees supplied by Findings Ledger and Explorer API.
- Provide a concise workflow walkthrough from ingestion to console/CLI/API use.
- Reflect VEX-first triage posture (per module architecture) and offline/export requirements.
## Inputs & Dependencies
| Input | Status | Notes |
| --- | --- | --- |
| GRAP0101 domain model contract | pending | Required for final entity/relationship names and invariants. |
| Console/CLI assets (screens, payloads, samples) | requested | Needed for workflow illustrations and hash manifests. |
| Findings Ledger schema + replay/Merkle notes | available | See `docs/modules/findings-ledger/schema.md` and `docs/modules/findings-ledger/merkle-anchor-policy.md`. |
## Domain Model (to be finalized)
- Entities (from current architecture): `finding_records` (canonical enriched findings), `finding_history` (append-only state transitions), `triage_actions` (operator actions), `remediation_plans`, `reports` (saved templates/exports). Final names/fields subject to GRAP0101 freeze.
- Relationships: findings link to advisories, VEX, SBOM component IDs, policyVersion, explain bundle refs; history and actions reference `findingId` with tenant + artifact scope; remediation plans and reports reference findings. (Clarify cardinality once GRAP0101 arrives.)
- Key identifiers: tenant, artifactId, findingKey, policyVersion, sourceRunId; attachment/download tokens validated via Authority (see Identity section).
## Identities & Roles
- Operators: console users with scopes `vuln:view`, `vuln:investigate`, `vuln:operate`, `vuln:audit`; legacy `vuln:read` honored but deprecated. ABAC filters (`vuln_env`, `vuln_owner`, `vuln_business_tier`) enforced on tokens and permalinks.
- Automation/agents: service accounts carrying the same scopes + ABAC filters; attachment tokens short-lived and validated against ledger hashes.
- External inputs: advisories, SBOMs, reachability signals, VEX decisions; map to findings via advisoryRawIds, vexRawIds, sbomComponentId (see GRAP0101 for final field names).
## AOC Guarantees
- Ledger anchoring and replay: reference `docs/modules/findings-ledger/merkle-anchor-policy.md` and `replay-harness.md` for deterministic replays and Merkle roots.
- Provenance chain: DSSE + in-toto/attestations (link to `docs/modules/findings-ledger/dsse-policy-linkage.md`); audit exports include signed manifests.
- Data integrity: append-only history plus Authority-issued attachment tokens checked against ledger hashes; GRAP0101 will confirm checksum fields.
## Workflow Summary (happy path)
1) Ingest findings/advisories → normalize → enrich with policy/VEX/reachability/AI → persist to `finding_records`.
2) Apply ABAC + scopes → store history/action entries → trigger notifications.
3) Expose via API/Console/CLI with cached reachability/VEX context and policy explain bundles (VEX-first, reachability second, policy gates third per architecture).
4) Export reports/offline bundles; verify with ledger hashes and DSSE attestations.
## Triage States (architecture; finalize with GRAP0101)
- `new``triaged``in_progress``awaiting_verification``remediated`
- `new``closed_false_positive`
- `new``accepted_risk`
- Each transition requires justification; accepted risk requires multi-approver workflow (Policy Studio) and ABAC enforcement.
## Offline / Export Expectations
- Offline bundle structure: `manifest.json`, `findings.jsonl`, `history.jsonl`, `actions.jsonl`, `reports/`, `signatures/` (DSSE envelopes); deterministic ordering and hashes.
- Bundles are consumed by Export Center mirror profiles; include Merkle roots and hash manifests for verification.
## Offline/Determinism Notes
- Hash captures for screenshots/payloads recorded in `docs/assets/vuln-explorer/SHA256SUMS` (empty until assets arrive).
- Use fixed fixture sets and ordered outputs when adding examples.
## Open Items before publish
- Replace all `[[pending:…]]` placeholders with GRAP0101 contract details.
- Insert deterministic examples (console, API, CLI) once assets drop.
- Add summary diagram if provided by Vuln Explorer Guild.
- Mirror any architecture updates from `docs/modules/vuln-explorer/architecture.md` into this overview when GRAP0101 finalizes.
_Last updated: 2025-12-05 (UTC)_

View File

@@ -1,37 +0,0 @@
# Vuln Explorer — Using the Console (Md.XI draft)
> Status: DRAFT (awaiting GRAP0101 domain model + console asset drop). Do not publish until hashes captured.
## Scope
- Walk through primary console workflows: search/filter, saved views, keyboard shortcuts, drill-down, evidence export.
- Highlight identity/ABAC enforcement and tenant scoping in UI.
- Keep all examples deterministic; attach payload/screenshot hashes to `docs/assets/vuln-explorer/SHA256SUMS`.
## Prerequisites
- Domain model from GRAP0101 (entities, identifiers) — needed for labels and field names.
- UI/CLI asset drop (screenshots, payload samples) — requested, due 2025-12-09.
- Ledger/observability context from `docs/modules/vuln-explorer/architecture.md` and Findings Ledger docs.
## Workflows (to be filled with assets)
1) Discover & filter findings (search, severity, reachability/VEX toggles).
2) Keyboard shortcuts for navigation (list, detail, actions) — pending asset table.
3) Saved views & deep links (shareable, ABAC-aware permalinks) — include hash-verified examples.
4) Drill-down: finding detail → history → actions → attachments (token validation flow).
5) Export: reports and offline bundles; note hash verification step.
## Determinism & Offline Notes
- All screenshots/payloads must be hashed; record in `docs/assets/vuln-explorer/SHA256SUMS`.
- Use fixed fixture IDs and ordered outputs; avoid live endpoints.
### Hash Capture Checklist (fill once assets arrive)
- `assets/vuln-explorer/console-list.png` (list view with filters applied)
- `assets/vuln-explorer/console-detail.png` (finding detail + history/actions panes)
- `assets/vuln-explorer/console-shortcuts.md` (shortcut matrix payload)
- `assets/vuln-explorer/console-saved-view.json` (saved view export)
## Open Items before publish
- Replace placeholders with GRAP0101-backed field names and identity labels.
- Insert screenshot tables and payload snippets once assets arrive.
- Add keyboard shortcut matrix and deep-link examples with hashes.
_Last updated: 2025-12-05 (UTC)_

View File

@@ -1,49 +0,0 @@
# Findings Ledger (Vuln Explorer) — Event Model & Replay (Md.XI draft)
> Status: DRAFT — depends on GRAP0101 alignment and security review. Do not publish until hashes and schema cross-checks are complete.
## Scope
- Explain event schema, hashing strategy, Merkle roots, and replay tooling as consumed by Vuln Explorer.
- Align with canonical ledger docs: `docs/modules/findings-ledger/schema.md`, `merkle-anchor-policy.md`, `replay-harness.md`.
- Provide deterministic examples and hash manifests (record in `docs/assets/vuln-explorer/SHA256SUMS`).
## Dependencies
| Input | Status | Notes |
| --- | --- | --- |
| GRAP0101 contract | pending | Confirm field names/identifiers to keep Explorer/ledger in sync. |
| Security review (hashing/attachments) | pending | Required before publication. |
| Replay fixtures | available | See `docs/modules/findings-ledger/replay-harness.md` and `golden-checksums.json`. |
## Event Schema (summary)
- `finding_records` (canonical): includes advisory/VEX/SBOM refs, `policyVersion`, `sourceRunId`, `explainBundleRef`, tenant, artifact identifiers.
- `finding_history`: append-only transitions with actor, scope, justification, timestamps (UTC, ISO-8601), hash-chained.
- `triage_actions`: discrete operator actions (comment, assign, remediation, ticket link) with immutable provenance.
- `remediation_plans`: planned fixes linked to findings; optional due dates and checkpoints.
> See `docs/modules/findings-ledger/schema.md` for authoritative field names; update this section when GRAP0101 finalizes.
## Hashing & Merkle Roots
- Per-event SHA-256 digests; history and actions chained by previous hash to ensure tamper evidence.
- Periodic Merkle roots anchored per tenant + artifact namespace; policy version included in leaf payloads.
- Export bundles carry `manifest.json` + `audit_log.jsonl` with hashes; verify against Merkle roots.
## Replay & Verification
- Replay harness (`replay-harness.md`) replays `finding_history` + `triage_actions` to reconstruct `finding_records` and compare hashes.
- Use `golden-checksums.json` to validate deterministic output; include hash of replay output in `SHA256SUMS` once fixtures copied here.
## Offline/Determinism Notes
- All sample logs/responses added to this doc must have hashes recorded in `docs/assets/vuln-explorer/SHA256SUMS`.
- Use fixed fixture IDs; avoid live timestamps; maintain sorted outputs.
### Hash Capture Checklist (when fixtures are pulled)
- `assets/vuln-explorer/ledger-history.jsonl` (sample history entries)
- `assets/vuln-explorer/ledger-actions.jsonl` (triage actions snippet)
- `assets/vuln-explorer/ledger-replay-output.json` (replay harness output)
- `assets/vuln-explorer/ledger-manifest.json` (export manifest sample)
## Open Items
- Replace schema placeholders once GRAP0101 and security review land.
- Add sample history/action entries and replay verification commands with hashes.
- Document attachment token validation path when security review provides final wording.
_Last updated: 2025-12-05 (UTC)_