save development progress

This commit is contained in:
StellaOps Bot
2025-12-25 23:09:58 +02:00
parent d71853ad7e
commit aa70af062e
351 changed files with 37683 additions and 150156 deletions

View File

@@ -344,6 +344,375 @@ paths:
application/yaml:
schema:
type: string
# Evidence-Weighted Score (EWS) Endpoints - Sprint 8200.0012.0004
/api/v1/findings/{findingId}/score:
post:
summary: Calculate evidence-weighted score for a finding
description: >-
Calculates the Evidence-Weighted Score (EWS) for a finding by aggregating
reachability, runtime signals, exploit likelihood, source trust, and mitigation
effectiveness. Returns a 0-100 score and action bucket (ActNow, ScheduleNext,
Investigate, Watchlist).
operationId: calculateFindingScore
tags: [scoring]
security:
- bearerAuth: [write:scores]
parameters:
- name: findingId
in: path
required: true
description: Finding identifier in format CVE-ID@pkg:PURL
schema:
type: string
pattern: "^[A-Z]+-\\d+@pkg:.+$"
example: "CVE-2024-1234@pkg:deb/debian/curl@7.64.0-4"
requestBody:
required: false
content:
application/json:
schema:
$ref: '#/components/schemas/CalculateScoreRequest'
example:
forceRecalculate: false
includeBreakdown: true
policyVersion: null
responses:
'200':
description: Score calculated successfully
content:
application/json:
schema:
$ref: '#/components/schemas/EvidenceWeightedScoreResponse'
example:
findingId: "CVE-2024-1234@pkg:deb/debian/curl@7.64.0-4"
score: 78
bucket: "ScheduleNext"
inputs:
rch: 0.85
rts: 0.40
bkp: 0.00
xpl: 0.70
src: 0.80
mit: 0.10
weights:
rch: 0.30
rts: 0.25
bkp: 0.15
xpl: 0.15
src: 0.10
mit: 0.10
flags: ["live-signal", "proven-path"]
explanations:
- "Static reachability: path to vulnerable sink (confidence: 85%)"
- "Runtime: 3 observations in last 24 hours"
policyDigest: "sha256:abc123..."
calculatedAt: "2026-01-15T14:30:00Z"
cachedUntil: "2026-01-15T15:30:00Z"
'400':
description: Invalid request
content:
application/json:
schema:
$ref: '#/components/schemas/ScoringErrorResponse'
'404':
description: Finding not found or no evidence available
content:
application/json:
schema:
$ref: '#/components/schemas/ScoringErrorResponse'
'429':
description: Rate limit exceeded (100/min)
get:
summary: Get cached evidence-weighted score for a finding
description: Returns the most recently calculated score from cache. Returns 404 if no score has been calculated.
operationId: getFindingScore
tags: [scoring]
security:
- bearerAuth: [read:scores]
parameters:
- name: findingId
in: path
required: true
schema:
type: string
responses:
'200':
description: Cached score retrieved
content:
application/json:
schema:
$ref: '#/components/schemas/EvidenceWeightedScoreResponse'
'404':
description: No cached score found
/api/v1/findings/scores:
post:
summary: Calculate evidence-weighted scores for multiple findings
description: Batch calculation of scores for up to 100 findings. Returns summary statistics and individual results.
operationId: calculateFindingScoresBatch
tags: [scoring]
security:
- bearerAuth: [write:scores]
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CalculateScoresBatchRequest'
example:
findingIds:
- "CVE-2024-1234@pkg:deb/debian/curl@7.64.0-4"
- "CVE-2024-5678@pkg:npm/lodash@4.17.20"
forceRecalculate: false
includeBreakdown: true
responses:
'200':
description: Batch scores calculated
content:
application/json:
schema:
$ref: '#/components/schemas/CalculateScoresBatchResponse'
'400':
description: Invalid request or batch too large (max 100)
content:
application/json:
schema:
$ref: '#/components/schemas/ScoringErrorResponse'
'429':
description: Rate limit exceeded (10/min)
/api/v1/findings/{findingId}/score-history:
get:
summary: Get score history for a finding
description: Returns historical score calculations with pagination. Tracks score changes, triggers, and which factors changed.
operationId: getFindingScoreHistory
tags: [scoring]
security:
- bearerAuth: [read:scores]
parameters:
- name: findingId
in: path
required: true
schema:
type: string
- name: from
in: query
description: Start of date range (inclusive)
schema:
type: string
format: date-time
- name: to
in: query
description: End of date range (inclusive)
schema:
type: string
format: date-time
- name: limit
in: query
description: Maximum entries to return (1-100, default 50)
schema:
type: integer
default: 50
minimum: 1
maximum: 100
- name: cursor
in: query
description: Pagination cursor from previous response
schema:
type: string
responses:
'200':
description: Score history retrieved
content:
application/json:
schema:
$ref: '#/components/schemas/ScoreHistoryResponse'
'404':
description: Finding not found
/api/v1/scoring/policy:
get:
summary: Get active scoring policy configuration
description: Returns the currently active evidence weight policy including weights, guardrails, and bucket thresholds.
operationId: getActiveScoringPolicy
tags: [scoring]
security:
- bearerAuth: [read:scores]
responses:
'200':
description: Active policy retrieved
content:
application/json:
schema:
$ref: '#/components/schemas/ScoringPolicyResponse'
example:
version: "ews.v1.2"
digest: "sha256:abc123..."
activeSince: "2026-01-01T00:00:00Z"
environment: "production"
weights:
rch: 0.30
rts: 0.25
bkp: 0.15
xpl: 0.15
src: 0.10
mit: 0.10
guardrails:
notAffectedCap: { enabled: true, maxScore: 15 }
runtimeFloor: { enabled: true, minScore: 60 }
speculativeCap: { enabled: true, maxScore: 45 }
buckets:
actNowMin: 90
scheduleNextMin: 70
investigateMin: 40
/api/v1/scoring/policy/{version}:
get:
summary: Get specific scoring policy version
description: Returns a specific version of the scoring policy for historical comparison or audit.
operationId: getScoringPolicyVersion
tags: [scoring]
security:
- bearerAuth: [read:scores]
parameters:
- name: version
in: path
required: true
schema:
type: string
example: "ews.v1.2"
responses:
'200':
description: Policy version retrieved
content:
application/json:
schema:
$ref: '#/components/schemas/ScoringPolicyResponse'
'404':
description: Policy version not found
/api/v1/scoring/webhooks:
post:
summary: Register a webhook for score change notifications
description: >-
Registers a webhook to receive notifications when finding scores change.
Supports filtering by finding patterns, minimum score change threshold,
and bucket changes. Webhook payloads are signed with HMAC-SHA256 if a
secret is provided.
operationId: registerScoringWebhook
tags: [scoring, webhooks]
security:
- bearerAuth: [admin:scoring]
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/RegisterWebhookRequest'
example:
url: "https://example.com/webhook/scores"
secret: "webhook-secret-key"
findingPatterns: ["CVE-*"]
minScoreChange: 10
triggerOnBucketChange: true
responses:
'201':
description: Webhook registered
content:
application/json:
schema:
$ref: '#/components/schemas/WebhookResponse'
'400':
description: Invalid webhook URL or configuration
'429':
description: Rate limit exceeded (10/min)
get:
summary: List all registered webhooks
operationId: listScoringWebhooks
tags: [scoring, webhooks]
security:
- bearerAuth: [admin:scoring]
responses:
'200':
description: List of webhooks
content:
application/json:
schema:
$ref: '#/components/schemas/WebhookListResponse'
/api/v1/scoring/webhooks/{id}:
get:
summary: Get a specific webhook by ID
operationId: getScoringWebhook
tags: [scoring, webhooks]
security:
- bearerAuth: [admin:scoring]
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
responses:
'200':
description: Webhook details
content:
application/json:
schema:
$ref: '#/components/schemas/WebhookResponse'
'404':
description: Webhook not found
put:
summary: Update a webhook configuration
operationId: updateScoringWebhook
tags: [scoring, webhooks]
security:
- bearerAuth: [admin:scoring]
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/RegisterWebhookRequest'
responses:
'200':
description: Webhook updated
content:
application/json:
schema:
$ref: '#/components/schemas/WebhookResponse'
'404':
description: Webhook not found
'400':
description: Invalid configuration
delete:
summary: Delete a webhook
operationId: deleteScoringWebhook
tags: [scoring, webhooks]
security:
- bearerAuth: [admin:scoring]
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
responses:
'204':
description: Webhook deleted
'404':
description: Webhook not found
components:
securitySchemes:
bearerAuth:
@@ -410,6 +779,464 @@ components:
default: 200
maximum: 1000
schemas:
# Evidence-Weighted Score (EWS) Schemas - Sprint 8200.0012.0004
CalculateScoreRequest:
type: object
description: Request to calculate score for a finding
properties:
forceRecalculate:
type: boolean
default: false
description: Force recalculation even if cached score exists
includeBreakdown:
type: boolean
default: true
description: Include detailed breakdown in response
policyVersion:
type: string
nullable: true
description: Specific policy version to use. Null = use latest
CalculateScoresBatchRequest:
type: object
required: [findingIds]
description: Request to calculate scores for multiple findings
properties:
findingIds:
type: array
maxItems: 100
items:
type: string
description: Finding IDs to calculate scores for. Max 100.
forceRecalculate:
type: boolean
default: false
includeBreakdown:
type: boolean
default: true
policyVersion:
type: string
nullable: true
EvidenceWeightedScoreResponse:
type: object
required: [findingId, score, bucket, policyDigest, calculatedAt]
description: Evidence-weighted score calculation result
properties:
findingId:
type: string
description: Finding identifier
score:
type: integer
minimum: 0
maximum: 100
description: Calculated score (0-100). Higher = more urgent.
bucket:
type: string
enum: [ActNow, ScheduleNext, Investigate, Watchlist]
description: Action bucket classification
inputs:
$ref: '#/components/schemas/EvidenceInputs'
weights:
$ref: '#/components/schemas/EvidenceWeights'
flags:
type: array
items:
type: string
enum: [live-signal, proven-path, vendor-na, speculative]
description: Active flags affecting the score
explanations:
type: array
items:
type: string
description: Human-readable explanations for each factor
caps:
$ref: '#/components/schemas/AppliedCaps'
policyDigest:
type: string
pattern: "^sha256:[a-f0-9]{64}$"
description: Policy digest used for calculation
calculatedAt:
type: string
format: date-time
description: When the score was calculated
cachedUntil:
type: string
format: date-time
description: When the cached score expires
fromCache:
type: boolean
description: Whether this result came from cache
EvidenceInputs:
type: object
description: Normalized evidence input values (0-1 scale)
properties:
rch:
type: number
format: double
minimum: 0
maximum: 1
description: Reachability
rts:
type: number
format: double
minimum: 0
maximum: 1
description: Runtime signal
bkp:
type: number
format: double
minimum: 0
maximum: 1
description: Backport availability
xpl:
type: number
format: double
minimum: 0
maximum: 1
description: Exploit likelihood
src:
type: number
format: double
minimum: 0
maximum: 1
description: Source trust
mit:
type: number
format: double
minimum: 0
maximum: 1
description: Mitigation effectiveness
EvidenceWeights:
type: object
description: Evidence weight configuration (weights must sum to 1.0)
properties:
rch:
type: number
format: double
description: Reachability weight
rts:
type: number
format: double
description: Runtime signal weight
bkp:
type: number
format: double
description: Backport weight
xpl:
type: number
format: double
description: Exploit weight
src:
type: number
format: double
description: Source trust weight
mit:
type: number
format: double
description: Mitigation weight
AppliedCaps:
type: object
description: Applied guardrail caps and floors
properties:
speculativeCap:
type: boolean
description: Speculative cap applied (no runtime evidence)
notAffectedCap:
type: boolean
description: Not-affected cap applied (VEX status)
runtimeFloor:
type: boolean
description: Runtime floor applied (observed in production)
CalculateScoresBatchResponse:
type: object
required: [results, summary, policyDigest, calculatedAt]
description: Batch score calculation result
properties:
results:
type: array
items:
$ref: '#/components/schemas/EvidenceWeightedScoreResponse'
description: Individual score results
summary:
$ref: '#/components/schemas/BatchSummary'
errors:
type: array
items:
$ref: '#/components/schemas/ScoringError'
description: Errors for failed calculations
policyDigest:
type: string
description: Policy digest used for all calculations
calculatedAt:
type: string
format: date-time
BatchSummary:
type: object
required: [total, succeeded, failed, byBucket, averageScore, calculationTimeMs]
properties:
total:
type: integer
description: Total findings processed
succeeded:
type: integer
description: Successful calculations
failed:
type: integer
description: Failed calculations
byBucket:
$ref: '#/components/schemas/BucketDistribution'
averageScore:
type: number
format: double
description: Average score across all findings
calculationTimeMs:
type: number
format: double
description: Total calculation time in milliseconds
BucketDistribution:
type: object
description: Score distribution by bucket
properties:
actNow:
type: integer
scheduleNext:
type: integer
investigate:
type: integer
watchlist:
type: integer
ScoreHistoryResponse:
type: object
required: [findingId, history, pagination]
description: Score history response
properties:
findingId:
type: string
description: Finding ID
history:
type: array
items:
$ref: '#/components/schemas/ScoreHistoryEntry'
description: History entries
pagination:
$ref: '#/components/schemas/Pagination'
ScoreHistoryEntry:
type: object
required: [score, bucket, policyDigest, calculatedAt, trigger]
description: Score history entry
properties:
score:
type: integer
minimum: 0
maximum: 100
description: Score value at this point in time
bucket:
type: string
description: Bucket at this point in time
policyDigest:
type: string
description: Policy digest used
calculatedAt:
type: string
format: date-time
description: When calculated
trigger:
type: string
enum: [evidence_update, policy_change, scheduled, manual]
description: What triggered recalculation
changedFactors:
type: array
items:
type: string
description: Which factors changed since previous calculation
Pagination:
type: object
required: [hasMore]
description: Pagination metadata
properties:
hasMore:
type: boolean
description: Whether more results are available
nextCursor:
type: string
description: Cursor for next page. Null if no more pages.
ScoringPolicyResponse:
type: object
required: [version, digest, activeSince, environment, weights, guardrails, buckets]
description: Scoring policy response
properties:
version:
type: string
description: Policy version identifier
digest:
type: string
description: Policy content digest
activeSince:
type: string
format: date-time
description: When this policy became active
environment:
type: string
description: Environment (production, staging, etc.)
weights:
$ref: '#/components/schemas/EvidenceWeights'
guardrails:
$ref: '#/components/schemas/GuardrailsConfig'
buckets:
$ref: '#/components/schemas/BucketThresholds'
GuardrailsConfig:
type: object
description: Guardrail configuration
properties:
notAffectedCap:
$ref: '#/components/schemas/Guardrail'
runtimeFloor:
$ref: '#/components/schemas/Guardrail'
speculativeCap:
$ref: '#/components/schemas/Guardrail'
Guardrail:
type: object
required: [enabled]
description: Individual guardrail settings
properties:
enabled:
type: boolean
maxScore:
type: integer
minScore:
type: integer
BucketThresholds:
type: object
required: [actNowMin, scheduleNextMin, investigateMin]
description: Bucket threshold configuration
properties:
actNowMin:
type: integer
description: Minimum score for ActNow bucket
scheduleNextMin:
type: integer
description: Minimum score for ScheduleNext bucket
investigateMin:
type: integer
description: Minimum score for Investigate bucket
RegisterWebhookRequest:
type: object
required: [url]
description: Request to register a webhook for score changes
properties:
url:
type: string
format: uri
description: Webhook URL to call on score changes
secret:
type: string
description: Optional secret for HMAC-SHA256 signature
findingPatterns:
type: array
items:
type: string
description: Finding ID patterns to watch. Empty = all findings.
minScoreChange:
type: integer
default: 5
description: Minimum score change to trigger webhook
triggerOnBucketChange:
type: boolean
default: true
description: Whether to trigger on bucket changes
WebhookResponse:
type: object
required: [id, url, hasSecret, minScoreChange, triggerOnBucketChange, createdAt]
description: Webhook registration response
properties:
id:
type: string
format: uuid
description: Webhook ID
url:
type: string
description: Webhook URL
hasSecret:
type: boolean
description: Whether secret is configured
findingPatterns:
type: array
items:
type: string
description: Finding patterns being watched
minScoreChange:
type: integer
description: Minimum score change threshold
triggerOnBucketChange:
type: boolean
description: Whether to trigger on bucket changes
createdAt:
type: string
format: date-time
description: When webhook was created
WebhookListResponse:
type: object
required: [webhooks, totalCount]
properties:
webhooks:
type: array
items:
$ref: '#/components/schemas/WebhookResponse'
totalCount:
type: integer
ScoringError:
type: object
required: [findingId, code, message]
description: Scoring error information
properties:
findingId:
type: string
description: Finding ID that failed
code:
type: string
description: Error code
message:
type: string
description: Error message
ScoringErrorResponse:
type: object
required: [code, message]
description: Scoring error response
properties:
code:
type: string
description: Error code
message:
type: string
description: Error message
details:
type: object
additionalProperties: true
description: Additional details
traceId:
type: string
description: Trace ID for debugging
# Existing Ledger Schemas
LedgerEvent:
type: object
required: [event]