209 lines
8.4 KiB
Markdown
209 lines
8.4 KiB
Markdown
# Remediation Module Architecture
|
|
|
|
> **Status: Partially implemented.** Core remediation APIs exist, and marketplace source endpoints now run with persistence-backed list/get/upsert behavior. Remaining areas are still incremental (template lifecycle depth, contributor workflow hardening, and broader policy integration).
|
|
|
|
## Overview
|
|
|
|
The Remediation module provides a developer-facing signed-PR remediation marketplace for the Stella Ops platform. It enables developers to discover, apply, and verify community-contributed or vendor-supplied fix templates for known vulnerabilities (CVEs).
|
|
|
|
## Key Concepts
|
|
|
|
### Fix Templates
|
|
Structured remediation patches tied to specific CVE + PURL combinations. Templates include unified diff content, version range applicability, and trust scores from contributor history.
|
|
|
|
### PR Submissions
|
|
Tracks the lifecycle of a remediation pull request from submission through scanning, merging, and post-merge verification. Each submission produces attestation evidence including reachability deltas and fix-chain DSSE envelopes.
|
|
|
|
### Contributors
|
|
Community members or vendors who submit fix templates. Each contributor has a trust score computed from their verification history (verified fixes, rejections).
|
|
|
|
### Marketplace Sources
|
|
Curated collections of fix templates from community, partner, or vendor origins. Sources are rated independently and can be enabled or disabled per tenant.
|
|
|
|
## Domain Model
|
|
|
|
```text
|
|
FixTemplate (remediation.fix_templates)
|
|
|- CveId (text, indexed)
|
|
|- Purl (text, indexed - pkg:type/name)
|
|
|- VersionRange (semver range)
|
|
|- PatchContent (unified diff)
|
|
|- Status (pending/verified/rejected)
|
|
|- TrustScore (0.0-1.0)
|
|
|- DsseDigest (nullable - signed envelope hash)
|
|
`- ContributorId / SourceId (foreign keys)
|
|
|
|
PrSubmission (remediation.pr_submissions)
|
|
|- FixTemplateId (nullable FK)
|
|
|- PrUrl, RepositoryUrl, SourceBranch, TargetBranch
|
|
|- CveId (text, indexed)
|
|
|- Status (opened/scanning/merged/verified/failed/inconclusive)
|
|
|- PreScanDigest, PostScanDigest
|
|
|- ReachabilityDeltaDigest, FixChainDsseDigest
|
|
|- Verdict (fixed/partial/not_fixed/inconclusive)
|
|
`- ContributorId
|
|
|
|
Contributor (remediation.contributors)
|
|
|- Username (unique)
|
|
|- VerifiedFixes, TotalSubmissions, RejectedSubmissions
|
|
`- TrustScore (computed)
|
|
|
|
MarketplaceSource (remediation.marketplace_sources)
|
|
|- Key (tenant-scoped unique key)
|
|
|- SourceType (community/partner/vendor)
|
|
|- Enabled, TrustScore
|
|
`- LastSyncAt
|
|
```
|
|
|
|
## Trust Scoring
|
|
|
|
Contributor trust score formula:
|
|
|
|
```text
|
|
score = clamp((verified * 1.0 - rejected * 0.5) / max(total, 1), 0, 1)
|
|
```
|
|
|
|
Trust tiers:
|
|
- **trusted** (> 0.8): Verified track record
|
|
- **established** (> 0.5): Growing history
|
|
- **new** (> 0.2): Recently joined
|
|
- **untrusted** (<= 0.2): Insufficient or negative history
|
|
|
|
## API Surface
|
|
|
|
All endpoints are under `/api/v1/remediation/`.
|
|
|
|
### Templates
|
|
- `GET /templates` - List fix templates (filter by CVE, PURL)
|
|
- `GET /templates/{id}` - Get template detail
|
|
- `POST /templates` - Create template (requires `remediation.submit`)
|
|
|
|
### Submissions
|
|
- `GET /submissions` - List PR submissions
|
|
- `GET /submissions/{id}` - Get submission with attestation chain
|
|
- `POST /submissions` - Submit PR for verification
|
|
- `GET /submissions/{id}/status` - Pipeline status
|
|
|
|
### Matching
|
|
- `GET /match?cve=...&purl=...&version=...` - Find applicable fix templates
|
|
|
|
### Contributors
|
|
- `GET /contributors` - List contributors
|
|
- `GET /contributors/{username}` - Profile with trust score
|
|
|
|
### Sources
|
|
- `GET /sources` - List marketplace sources
|
|
- `GET /sources/{key}` - Source detail
|
|
- `POST /sources` - Create/update source (requires `remediation.manage`)
|
|
|
|
Implemented source API contract (2026-03-04):
|
|
- Request model for upsert (`POST /sources`): `key`, `name`, `url`, `sourceType`, `enabled`, `trustScore`, `lastSyncAt`.
|
|
- Deterministic behavior:
|
|
- key normalization uses lowercase invariant
|
|
- list ordering is key-based ordinal ordering
|
|
- upsert is idempotent by tenant + source key
|
|
- Validation:
|
|
- key pattern: `^[a-z0-9][a-z0-9._-]{0,63}$`
|
|
- sourceType allowed values: `community`, `partner`, `vendor`
|
|
- trustScore range: `0..1`
|
|
- url must be an absolute `http`/`https` URL when provided
|
|
- Tenant isolation:
|
|
- all source endpoints require tenant context (`RequireTenant`)
|
|
- repository operations are tenant-scoped for list/get/upsert behavior
|
|
|
|
## Authorization Policies
|
|
|
|
| Policy | Description |
|
|
|--------|-------------|
|
|
| `remediation.read` | Read templates, submissions, contributors, sources |
|
|
| `remediation.submit` | Create templates and submit PRs |
|
|
| `remediation.manage` | Manage marketplace sources, verify/reject templates |
|
|
|
|
## Runtime Storage Contract (2026-03-05)
|
|
|
|
Remediation runtime storage is now selected through `Remediation:Storage:Driver` (or `Storage:Driver`) with explicit startup validation:
|
|
|
|
- `postgres` (default):
|
|
- Required settings: `ConnectionStrings:Default` or `Remediation:Storage:Postgres:ConnectionString`.
|
|
- Optional schema override: `Remediation:Storage:Postgres:SchemaName` (defaults to `remediation`).
|
|
- Behavior: repositories are wired with `RemediationDataSource` and Postgres-backed constructors.
|
|
- Startup: fails fast when required connection configuration is missing.
|
|
|
|
- `inmemory`:
|
|
- Allowed only in `Test`/`Testing` environment profiles.
|
|
- Intended for deterministic automated tests only.
|
|
- Startup: fails fast outside test profiles.
|
|
|
|
This removes implicit production-like in-memory behavior and makes storage mode explicit and auditable.
|
|
|
|
Migration notes:
|
|
- Legacy webservice wiring that instantiated parameterless repository constructors has been removed.
|
|
- Existing deployments must provide a Postgres connection string (or explicitly run with `inmemory` in `Test`/`Testing` profiles).
|
|
- Integration tests should pin `REMEDIATION__STORAGE__DRIVER=inmemory` under a testing environment profile for deterministic non-network execution.
|
|
|
|
## Service Integration Baseline (2026-03-05)
|
|
|
|
- Router integration enabled (`serviceName: remediation`) with endpoint refresh on startup.
|
|
- Local alias binding/logging enabled via `remediation.stella-ops.local`.
|
|
- CORS and tenant middleware are part of the default request pipeline before endpoint execution.
|
|
|
|
## Verification Pipeline
|
|
|
|
1. PR submitted (status: `opened`)
|
|
2. Pre-merge scan captures baseline SBOM digest
|
|
3. PR merged (status: `merged`)
|
|
4. Post-merge scan captures updated SBOM digest
|
|
5. Reachability delta computed between pre and post digests
|
|
6. Fix-chain DSSE envelope signed
|
|
7. Verdict determined: `fixed`, `partial`, `not_fixed`, or `inconclusive`
|
|
|
|
## Webhook Integration
|
|
|
|
The `RemediationPrWebhookHandler` in the Signals module detects remediation PRs by:
|
|
- Title convention: `fix(CVE-XXXX-NNNNN): description`
|
|
- Label: `stella-ops/remediation`
|
|
|
|
## Module Location
|
|
|
|
```text
|
|
src/Remediation/
|
|
|- StellaOps.Remediation.Core/ - Domain models, interfaces, services
|
|
|- StellaOps.Remediation.WebService/ - API endpoints, Program.cs
|
|
|- StellaOps.Remediation.Persistence/ - SQL migrations, repositories
|
|
|- __Tests/StellaOps.Remediation.Tests/ - Repository/domain unit tests
|
|
`- __Tests/StellaOps.Remediation.WebService.Tests/ - Source endpoint integration tests
|
|
```
|
|
|
|
## Related Sprints
|
|
|
|
- SPRINT_20260220_010: Registry and persistence
|
|
- SPRINT_20260220_011: Signals webhook handler
|
|
- SPRINT_20260220_012: Verification pipeline
|
|
- SPRINT_20260220_013: Matching, sources, policy
|
|
- SPRINT_20260220_014: UI components
|
|
- SPRINT_20260220_015: Documentation
|
|
|
|
## Related Contracts
|
|
|
|
- `docs/contracts/remediation-pr-v1.md`
|
|
|
|
## Advisory Gap Status (2026-03-04 Batch)
|
|
|
|
Status:
|
|
- Advisory gap `REM-001` is closed for marketplace sources.
|
|
|
|
Closed behaviors:
|
|
- `GET /api/v1/remediation/sources` returns persisted tenant-scoped sources with deterministic ordering.
|
|
- `GET /api/v1/remediation/sources/{key}` resolves persisted records (no unconditional stub `source_not_found` path).
|
|
- `POST /api/v1/remediation/sources` performs validated upsert and no longer returns `501`.
|
|
- Marketplace source repository abstraction and implementation are wired through DI:
|
|
- `IMarketplaceSourceRepository`
|
|
- `PostgresMarketplaceSourceRepository`
|
|
|
|
Verification evidence:
|
|
- `dotnet test src/Remediation/__Tests/StellaOps.Remediation.Tests/StellaOps.Remediation.Tests.csproj -m:1 -v minimal` - `28` passed.
|
|
- `dotnet test src/Remediation/__Tests/StellaOps.Remediation.WebService.Tests/StellaOps.Remediation.WebService.Tests.csproj -m:1 -v minimal` - `4` passed.
|
|
|
|
Tracking sprint:
|
|
- `docs/implplan/SPRINT_20260304_308_Remediation_marketplace_sources_api_completion.md`
|