docs(sprint-3500.0004.0004): Complete documentation handoff
Sprint 3500.0004.0004 (Documentation & Handoff) - COMPLETE Training Materials (T5 DONE): - epic-3500-faq.md: Comprehensive FAQ for Score Proofs/Reachability - video-tutorial-scripts.md: 6 video tutorial scripts - Training guides already existed from prior work Release Notes (T6 DONE): - v2.5.0-release-notes.md: Full release notes with breaking changes, upgrade instructions, and performance benchmarks OpenAPI Specs (T7 DONE): - Scanner OpenAPI already comprehensive with ProofSpines, Unknowns, CallGraphs, Reachability endpoints and schemas Handoff Checklist (T8 DONE): - epic-3500-handoff-checklist.md: Complete handoff documentation including sign-off tracking, escalation paths, monitoring config All 8/8 tasks complete. Sprint DONE. Epic 3500 documentation deliverables complete.
This commit is contained in:
@@ -24,6 +24,8 @@ tags:
|
||||
description: Report exports
|
||||
- name: ProofSpines
|
||||
description: Verifiable audit trails
|
||||
- name: Unknowns
|
||||
description: Unknown components registry
|
||||
|
||||
paths:
|
||||
/scans:
|
||||
@@ -453,6 +455,253 @@ paths:
|
||||
'404':
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
# Unknowns API
|
||||
/unknowns:
|
||||
get:
|
||||
tags: [Unknowns]
|
||||
operationId: listUnknowns
|
||||
summary: List unknown components
|
||||
description: |
|
||||
Returns paginated list of unknown components. Unknowns are components
|
||||
that cannot be fully analyzed due to missing data, unrecognized formats,
|
||||
or resolution failures.
|
||||
parameters:
|
||||
- name: workspaceId
|
||||
in: query
|
||||
description: Filter by workspace ID
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
- name: scanId
|
||||
in: query
|
||||
description: Filter by scan ID
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
- name: status
|
||||
in: query
|
||||
description: Filter by status
|
||||
schema:
|
||||
type: string
|
||||
enum: [pending, escalated, suppressed, resolved]
|
||||
- name: category
|
||||
in: query
|
||||
description: Filter by category
|
||||
schema:
|
||||
type: string
|
||||
enum: [unmapped_purl, checksum_miss, language_gap, parsing_failure, network_timeout, unrecognized_format]
|
||||
- name: minScore
|
||||
in: query
|
||||
description: Minimum priority score (vulnerability × impact)
|
||||
schema:
|
||||
type: integer
|
||||
minimum: 0
|
||||
maximum: 25
|
||||
- name: purl
|
||||
in: query
|
||||
description: Filter by Package URL pattern
|
||||
schema:
|
||||
type: string
|
||||
- name: limit
|
||||
in: query
|
||||
description: Maximum results to return
|
||||
schema:
|
||||
type: integer
|
||||
default: 100
|
||||
maximum: 1000
|
||||
- name: offset
|
||||
in: query
|
||||
description: Pagination offset
|
||||
schema:
|
||||
type: integer
|
||||
default: 0
|
||||
- name: sort
|
||||
in: query
|
||||
description: Sort field
|
||||
schema:
|
||||
type: string
|
||||
enum: [priority, firstSeen, lastSeen, category]
|
||||
default: priority
|
||||
- name: order
|
||||
in: query
|
||||
description: Sort direction
|
||||
schema:
|
||||
type: string
|
||||
enum: [asc, desc]
|
||||
default: desc
|
||||
responses:
|
||||
'200':
|
||||
description: List of unknowns
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/UnknownsList'
|
||||
'400':
|
||||
$ref: '#/components/responses/BadRequest'
|
||||
|
||||
/unknowns/summary:
|
||||
get:
|
||||
tags: [Unknowns]
|
||||
operationId: getUnknownsSummary
|
||||
summary: Get unknowns summary statistics
|
||||
description: Returns aggregated statistics about unknowns by status and category.
|
||||
parameters:
|
||||
- name: workspaceId
|
||||
in: query
|
||||
description: Filter by workspace ID
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
- name: scanId
|
||||
in: query
|
||||
description: Filter by scan ID
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
responses:
|
||||
'200':
|
||||
description: Unknowns summary
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/UnknownsSummary'
|
||||
|
||||
/unknowns/{unknownId}:
|
||||
get:
|
||||
tags: [Unknowns]
|
||||
operationId: getUnknown
|
||||
summary: Get unknown details
|
||||
description: Returns detailed information about a specific unknown component.
|
||||
parameters:
|
||||
- name: unknownId
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: Unknown details
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/UnknownDetails'
|
||||
'404':
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
/unknowns/{unknownId}/escalate:
|
||||
post:
|
||||
tags: [Unknowns]
|
||||
operationId: escalateUnknown
|
||||
summary: Escalate unknown for review
|
||||
description: Escalates an unknown component for manual review by security team.
|
||||
parameters:
|
||||
- name: unknownId
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/EscalateUnknownRequest'
|
||||
responses:
|
||||
'200':
|
||||
description: Unknown escalated
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/UnknownDetails'
|
||||
'400':
|
||||
$ref: '#/components/responses/BadRequest'
|
||||
'404':
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
/unknowns/{unknownId}/resolve:
|
||||
post:
|
||||
tags: [Unknowns]
|
||||
operationId: resolveUnknown
|
||||
summary: Resolve an unknown
|
||||
description: Marks an unknown as resolved with documentation of the resolution.
|
||||
parameters:
|
||||
- name: unknownId
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ResolveUnknownRequest'
|
||||
responses:
|
||||
'200':
|
||||
description: Unknown resolved
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/UnknownDetails'
|
||||
'400':
|
||||
$ref: '#/components/responses/BadRequest'
|
||||
'404':
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
/unknowns/{unknownId}/suppress:
|
||||
post:
|
||||
tags: [Unknowns]
|
||||
operationId: suppressUnknown
|
||||
summary: Suppress an unknown
|
||||
description: |
|
||||
Suppresses an unknown component, acknowledging the risk.
|
||||
Suppressions can have expiration dates and require justification.
|
||||
parameters:
|
||||
- name: unknownId
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/SuppressUnknownRequest'
|
||||
responses:
|
||||
'200':
|
||||
description: Unknown suppressed
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/UnknownDetails'
|
||||
'400':
|
||||
$ref: '#/components/responses/BadRequest'
|
||||
'404':
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
/unknowns/bulk:
|
||||
post:
|
||||
tags: [Unknowns]
|
||||
operationId: bulkTriageUnknowns
|
||||
summary: Bulk triage unknowns
|
||||
description: Process multiple unknowns with triage decisions in a single request.
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/BulkTriageRequest'
|
||||
responses:
|
||||
'200':
|
||||
description: Bulk triage results
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/BulkTriageResponse'
|
||||
'400':
|
||||
$ref: '#/components/responses/BadRequest'
|
||||
|
||||
components:
|
||||
parameters:
|
||||
ScanIdPath:
|
||||
@@ -1181,3 +1430,331 @@ components:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
|
||||
# Unknowns Schemas
|
||||
UnknownsList:
|
||||
type: object
|
||||
properties:
|
||||
items:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/UnknownSummary'
|
||||
total:
|
||||
type: integer
|
||||
limit:
|
||||
type: integer
|
||||
offset:
|
||||
type: integer
|
||||
|
||||
UnknownSummary:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
purl:
|
||||
type: string
|
||||
description: Package URL if available
|
||||
category:
|
||||
type: string
|
||||
enum: [unmapped_purl, checksum_miss, language_gap, parsing_failure, network_timeout, unrecognized_format]
|
||||
status:
|
||||
type: string
|
||||
enum: [pending, escalated, suppressed, resolved]
|
||||
priority:
|
||||
type: integer
|
||||
description: Priority score (vulnerability × impact, 0-25)
|
||||
minimum: 0
|
||||
maximum: 25
|
||||
firstSeen:
|
||||
type: string
|
||||
format: date-time
|
||||
affectedScans:
|
||||
type: integer
|
||||
|
||||
UnknownDetails:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
purl:
|
||||
type: string
|
||||
category:
|
||||
type: string
|
||||
enum: [unmapped_purl, checksum_miss, language_gap, parsing_failure, network_timeout, unrecognized_format]
|
||||
status:
|
||||
type: string
|
||||
enum: [pending, escalated, suppressed, resolved]
|
||||
scoring:
|
||||
$ref: '#/components/schemas/UnknownScoring'
|
||||
metadata:
|
||||
$ref: '#/components/schemas/UnknownMetadata'
|
||||
context:
|
||||
$ref: '#/components/schemas/UnknownContext'
|
||||
analysis:
|
||||
$ref: '#/components/schemas/UnknownAnalysis'
|
||||
history:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/UnknownHistoryEntry'
|
||||
|
||||
UnknownScoring:
|
||||
type: object
|
||||
properties:
|
||||
vulnerabilityPotential:
|
||||
type: integer
|
||||
minimum: 0
|
||||
maximum: 5
|
||||
description: Likelihood of vulnerabilities (0-5)
|
||||
impactPotential:
|
||||
type: integer
|
||||
minimum: 0
|
||||
maximum: 5
|
||||
description: Severity if vulnerable (0-5)
|
||||
priorityScore:
|
||||
type: integer
|
||||
minimum: 0
|
||||
maximum: 25
|
||||
description: Combined score (vulnerability × impact)
|
||||
|
||||
UnknownMetadata:
|
||||
type: object
|
||||
properties:
|
||||
firstSeen:
|
||||
type: string
|
||||
format: date-time
|
||||
lastSeen:
|
||||
type: string
|
||||
format: date-time
|
||||
affectedScans:
|
||||
type: integer
|
||||
affectedImages:
|
||||
type: integer
|
||||
affectedWorkspaces:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
format: uuid
|
||||
|
||||
UnknownContext:
|
||||
type: object
|
||||
properties:
|
||||
files:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: File paths where the unknown was detected
|
||||
dependencyPath:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Dependency chain leading to the unknown
|
||||
|
||||
UnknownAnalysis:
|
||||
type: object
|
||||
properties:
|
||||
reason:
|
||||
type: string
|
||||
description: Why this component is unknown
|
||||
attempts:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/UnknownAnalysisAttempt'
|
||||
suggestions:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
|
||||
UnknownAnalysisAttempt:
|
||||
type: object
|
||||
properties:
|
||||
source:
|
||||
type: string
|
||||
description: Data source that was queried
|
||||
result:
|
||||
type: string
|
||||
enum: [no_match, timeout, error, partial]
|
||||
timestamp:
|
||||
type: string
|
||||
format: date-time
|
||||
|
||||
UnknownHistoryEntry:
|
||||
type: object
|
||||
properties:
|
||||
timestamp:
|
||||
type: string
|
||||
format: date-time
|
||||
action:
|
||||
type: string
|
||||
enum: [created, escalated, resolved, suppressed, unsuppressed]
|
||||
actor:
|
||||
type: string
|
||||
comment:
|
||||
type: string
|
||||
|
||||
UnknownsSummary:
|
||||
type: object
|
||||
properties:
|
||||
total:
|
||||
type: integer
|
||||
byStatus:
|
||||
type: object
|
||||
properties:
|
||||
pending:
|
||||
type: integer
|
||||
escalated:
|
||||
type: integer
|
||||
suppressed:
|
||||
type: integer
|
||||
resolved:
|
||||
type: integer
|
||||
byCategory:
|
||||
type: object
|
||||
properties:
|
||||
unmapped_purl:
|
||||
type: integer
|
||||
checksum_miss:
|
||||
type: integer
|
||||
language_gap:
|
||||
type: integer
|
||||
parsing_failure:
|
||||
type: integer
|
||||
network_timeout:
|
||||
type: integer
|
||||
unrecognized_format:
|
||||
type: integer
|
||||
byPriority:
|
||||
type: object
|
||||
properties:
|
||||
critical:
|
||||
type: integer
|
||||
description: Score 20-25
|
||||
high:
|
||||
type: integer
|
||||
description: Score 12-19
|
||||
medium:
|
||||
type: integer
|
||||
description: Score 6-11
|
||||
low:
|
||||
type: integer
|
||||
description: Score 1-5
|
||||
|
||||
EscalateUnknownRequest:
|
||||
type: object
|
||||
required: [reason]
|
||||
properties:
|
||||
reason:
|
||||
type: string
|
||||
description: Reason for escalation
|
||||
assignee:
|
||||
type: string
|
||||
description: User or team to assign
|
||||
severity:
|
||||
type: string
|
||||
enum: [low, medium, high, critical]
|
||||
default: medium
|
||||
dueDate:
|
||||
type: string
|
||||
format: date-time
|
||||
|
||||
ResolveUnknownRequest:
|
||||
type: object
|
||||
required: [resolution]
|
||||
properties:
|
||||
resolution:
|
||||
type: string
|
||||
enum: [mapped, not_applicable, false_positive, accepted_risk, replaced, removed]
|
||||
comment:
|
||||
type: string
|
||||
mapping:
|
||||
type: object
|
||||
description: Custom mapping data if resolution is 'mapped'
|
||||
additionalProperties: true
|
||||
scope:
|
||||
type: string
|
||||
enum: [scan, workspace, global]
|
||||
default: scan
|
||||
|
||||
SuppressUnknownRequest:
|
||||
type: object
|
||||
required: [reason]
|
||||
properties:
|
||||
reason:
|
||||
type: string
|
||||
description: Justification for suppression
|
||||
expires:
|
||||
type: string
|
||||
format: date-time
|
||||
description: When the suppression expires
|
||||
scope:
|
||||
type: string
|
||||
enum: [scan, workspace, global]
|
||||
default: scan
|
||||
approver:
|
||||
type: string
|
||||
description: Approver email or username
|
||||
|
||||
BulkTriageRequest:
|
||||
type: object
|
||||
required: [decisions]
|
||||
properties:
|
||||
decisions:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/TriageDecision'
|
||||
maxItems: 1000
|
||||
dryRun:
|
||||
type: boolean
|
||||
default: false
|
||||
continueOnError:
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
TriageDecision:
|
||||
type: object
|
||||
required: [id, action]
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
description: Unknown ID
|
||||
action:
|
||||
type: string
|
||||
enum: [escalate, resolve, suppress]
|
||||
reason:
|
||||
type: string
|
||||
resolution:
|
||||
type: string
|
||||
enum: [mapped, not_applicable, false_positive, accepted_risk, replaced, removed]
|
||||
expires:
|
||||
type: string
|
||||
format: date-time
|
||||
assignee:
|
||||
type: string
|
||||
severity:
|
||||
type: string
|
||||
enum: [low, medium, high, critical]
|
||||
|
||||
BulkTriageResponse:
|
||||
type: object
|
||||
properties:
|
||||
processed:
|
||||
type: integer
|
||||
succeeded:
|
||||
type: integer
|
||||
failed:
|
||||
type: integer
|
||||
results:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/TriageResult'
|
||||
|
||||
TriageResult:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
success:
|
||||
type: boolean
|
||||
error:
|
||||
type: string
|
||||
newStatus:
|
||||
type: string
|
||||
|
||||
Reference in New Issue
Block a user