8.4 KiB
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
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:
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 detailPOST /templates- Create template (requiresremediation.submit)
Submissions
GET /submissions- List PR submissionsGET /submissions/{id}- Get submission with attestation chainPOST /submissions- Submit PR for verificationGET /submissions/{id}/status- Pipeline status
Matching
GET /match?cve=...&purl=...&version=...- Find applicable fix templates
Contributors
GET /contributors- List contributorsGET /contributors/{username}- Profile with trust score
Sources
GET /sources- List marketplace sourcesGET /sources/{key}- Source detailPOST /sources- Create/update source (requiresremediation.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/httpsURL when provided
- key pattern:
- Tenant isolation:
- all source endpoints require tenant context (
RequireTenant) - repository operations are tenant-scoped for list/get/upsert behavior
- all source endpoints require tenant context (
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:DefaultorRemediation:Storage:Postgres:ConnectionString. - Optional schema override:
Remediation:Storage:Postgres:SchemaName(defaults toremediation). - Behavior: repositories are wired with
RemediationDataSourceand Postgres-backed constructors. - Startup: fails fast when required connection configuration is missing.
- Required settings:
-
inmemory:- Allowed only in
Test/Testingenvironment profiles. - Intended for deterministic automated tests only.
- Startup: fails fast outside test profiles.
- Allowed only in
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
inmemoryinTest/Testingprofiles). - Integration tests should pin
REMEDIATION__STORAGE__DRIVER=inmemoryunder 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
- PR submitted (status:
opened) - Pre-merge scan captures baseline SBOM digest
- PR merged (status:
merged) - Post-merge scan captures updated SBOM digest
- Reachability delta computed between pre and post digests
- Fix-chain DSSE envelope signed
- Verdict determined:
fixed,partial,not_fixed, orinconclusive
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
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-001is closed for marketplace sources.
Closed behaviors:
GET /api/v1/remediation/sourcesreturns persisted tenant-scoped sources with deterministic ordering.GET /api/v1/remediation/sources/{key}resolves persisted records (no unconditional stubsource_not_foundpath).POST /api/v1/remediation/sourcesperforms validated upsert and no longer returns501.- Marketplace source repository abstraction and implementation are wired through DI:
IMarketplaceSourceRepositoryPostgresMarketplaceSourceRepository
Verification evidence:
dotnet test src/Remediation/__Tests/StellaOps.Remediation.Tests/StellaOps.Remediation.Tests.csproj -m:1 -v minimal-28passed.dotnet test src/Remediation/__Tests/StellaOps.Remediation.WebService.Tests/StellaOps.Remediation.WebService.Tests.csproj -m:1 -v minimal-4passed.
Tracking sprint:
docs/implplan/SPRINT_20260304_308_Remediation_marketplace_sources_api_completion.md