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 }