Add OpenAPI specification for Link-Not-Merge Policy APIs
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled

- Introduced a new OpenAPI YAML file for the StellaOps Concelier service.
- Defined endpoints for listing linksets, retrieving linksets by advisory ID, and searching linksets.
- Included detailed parameter specifications and response schemas for each endpoint.
- Established components for reusable parameters and schemas, enhancing API documentation clarity.
This commit is contained in:
StellaOps Bot
2025-11-22 23:39:01 +02:00
parent 48702191be
commit 2e89a92d92
13 changed files with 938 additions and 49 deletions

View File

@@ -0,0 +1,276 @@
openapi: 3.1.0
info:
title: StellaOps Concelier Link-Not-Merge Policy APIs
version: "0.1.0"
description: Fact-only advisory/linkset retrieval for Policy Engine consumers.
servers:
- url: /
description: Relative base path (API Gateway rewrites in production).
tags:
- name: Linksets
description: Link-Not-Merge linkset retrieval
paths:
/v1/lnm/linksets:
get:
summary: List linksets
tags: [Linksets]
parameters:
- $ref: '#/components/parameters/Tenant'
- name: includeConflicts
in: query
required: false
schema: { type: boolean, default: true }
- name: includeObservations
in: query
required: false
schema: { type: boolean, default: false }
- $ref: '#/components/parameters/purl'
- $ref: '#/components/parameters/cpe'
- $ref: '#/components/parameters/ghsa'
- $ref: '#/components/parameters/cve'
- $ref: '#/components/parameters/advisoryId'
- $ref: '#/components/parameters/source'
- $ref: '#/components/parameters/severityMin'
- $ref: '#/components/parameters/severityMax'
- $ref: '#/components/parameters/publishedSince'
- $ref: '#/components/parameters/modifiedSince'
- $ref: '#/components/parameters/page'
- $ref: '#/components/parameters/pageSize'
- $ref: '#/components/parameters/sort'
responses:
"200":
description: Deterministically ordered list of linksets
content:
application/json:
schema:
$ref: '#/components/schemas/PagedLinksets'
/v1/lnm/linksets/{advisoryId}:
get:
summary: Get linkset by advisory ID
tags: [Linksets]
parameters:
- $ref: '#/components/parameters/Tenant'
- name: advisoryId
in: path
required: true
schema:
type: string
- name: source
in: query
required: false
schema: { type: string }
- name: includeConflicts
in: query
required: false
schema: { type: boolean, default: true }
- name: includeObservations
in: query
required: false
schema: { type: boolean, default: false }
responses:
"200":
description: Linkset with provenance and conflicts
content:
application/json:
schema:
$ref: '#/components/schemas/Linkset'
"404":
description: Not found
/v1/lnm/linksets/search:
post:
summary: Search linksets (body filters)
tags: [Linksets]
parameters:
- $ref: '#/components/parameters/Tenant'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/LinksetSearchRequest'
responses:
"200":
description: Deterministically ordered search results
content:
application/json:
schema:
$ref: '#/components/schemas/PagedLinksets'
components:
parameters:
Tenant:
name: Tenant
in: header
required: true
schema:
type: string
description: Tenant identifier (required).
purl:
name: purl
in: query
schema:
type: array
items: { type: string }
style: form
explode: true
cpe:
name: cpe
in: query
schema: { type: string }
ghsa:
name: ghsa
in: query
schema: { type: string }
cve:
name: cve
in: query
schema: { type: string }
advisoryId:
name: advisoryId
in: query
schema: { type: string }
source:
name: source
in: query
schema:
type: string
severityMin:
name: severityMin
in: query
schema:
type: number
format: float
severityMax:
name: severityMax
in: query
schema:
type: number
format: float
publishedSince:
name: publishedSince
in: query
schema:
type: string
format: date-time
modifiedSince:
name: modifiedSince
in: query
schema:
type: string
format: date-time
page:
name: page
in: query
schema:
type: integer
minimum: 1
default: 1
pageSize:
name: pageSize
in: query
schema:
type: integer
minimum: 1
maximum: 200
default: 50
sort:
name: sort
in: query
schema:
type: string
enum:
- modifiedAt desc
- modifiedAt asc
- publishedAt desc
- publishedAt asc
- severity desc
- severity asc
- source
- advisoryId
description: Default modifiedAt desc; ties advisoryId asc, source asc.
schemas:
LinksetSearchRequest:
type: object
properties:
purl: { type: array, items: { type: string } }
cpe: { type: array, items: { type: string } }
ghsa: { type: string }
cve: { type: string }
advisoryId: { type: string }
source: { type: string }
severityMin: { type: number }
severityMax: { type: number }
publishedSince: { type: string, format: date-time }
modifiedSince: { type: string, format: date-time }
includeTimeline: { type: boolean, default: false }
includeObservations: { type: boolean, default: false }
includeConflicts: { type: boolean, default: true }
page: { type: integer, minimum: 1, default: 1 }
pageSize: { type: integer, minimum: 1, maximum: 200, default: 50 }
sort: { type: string, enum: [modifiedAt desc, modifiedAt asc, publishedAt desc, publishedAt asc, severity desc, severity asc, source, advisoryId] }
PagedLinksets:
type: object
properties:
items:
type: array
items: { $ref: '#/components/schemas/Linkset' }
page: { type: integer }
pageSize: { type: integer }
total: { type: integer }
Linkset:
type: object
required: [advisoryId, source, purl, cpe, provenance]
properties:
advisoryId: { type: string }
source: { type: string }
purl: { type: array, items: { type: string } }
cpe: { type: array, items: { type: string } }
summary: { type: string }
publishedAt: { type: string, format: date-time }
modifiedAt: { type: string, format: date-time }
severity: { type: string, description: Source-native severity label }
status: { type: string }
provenance: { $ref: '#/components/schemas/LinksetProvenance' }
conflicts:
type: array
items: { $ref: '#/components/schemas/LinksetConflict' }
timeline:
type: array
items: { $ref: '#/components/schemas/LinksetTimeline' }
normalized:
type: object
properties:
aliases: { type: array, items: { type: string } }
purl: { type: array, items: { type: string } }
versions: { type: array, items: { type: string } }
ranges: { type: array, items: { type: object } }
severities: { type: array, items: { type: object } }
cached:
type: boolean
description: True if served from cache; provenance.evidenceHash present for integrity.
remarks:
type: array
items: { type: string }
observations:
type: array
items: { type: string }
LinksetProvenance:
type: object
properties:
ingestedAt: { type: string, format: date-time }
connectorId: { type: string }
evidenceHash: { type: string }
dsseEnvelopeHash: { type: string }
LinksetConflict:
type: object
properties:
field: { type: string }
reason: { type: string }
observedValue: { type: string }
observedAt: { type: string, format: date-time }
evidenceHash: { type: string }
LinksetTimeline:
type: object
properties:
event: { type: string }
at: { type: string, format: date-time }
evidenceHash: { type: string }