Files
git.stella-ops.org/docs/modules/excititor/operations/evidence-api.md
2025-11-18 23:45:25 +02:00

6.4 KiB
Raw Blame History

Excititor Advisory-AI evidence APIs (projection + chunks)

Covers the read-only evidence surfaces shipped in Sprints 119120: /v1/vex/observations/{vulnerabilityId}/{productKey} and /v1/vex/evidence/chunks.

Scope and determinism

  • Aggregation-only: no consensus, severity merging, or reachability. Responses carry raw statements plus provenance/signature metadata.
  • Stable ordering: both endpoints sort by lastSeen DESC; pagination uses a deterministic limit.
  • Limits: observation projection default limit=200, max 500; chunk stream default limit=500, max 2000.
  • Tenancy: reads respect X-Stella-Tenant when provided; otherwise fall back to DefaultTenant configuration.
  • Auth: bearer token with vex.read scope required.

/v1/vex/observations/{vulnerabilityId}/{productKey}

  • Response: JSON object with vulnerabilityId, productKey, generatedAt, totalCount, truncated, statements[].
  • Statement fields: observationId, providerId, status, justification, detail, firstSeen, lastSeen, scope{key,name,version,purl,cpe,componentIdentifiers[]}, anchors[], document{digest,format,revision,sourceUri}, signature{type,keyId,issuer,verifiedAt}.
  • Filters:
    • providerId (multi-valued, comma-separated)
    • status (values in VexClaimStatus)
    • since (ISO-8601, UTC)
    • limit (ints within bounds)
  • Mapping back to storage:
    • observationId = {providerId}:{document.digest}
    • document.digest locates the raw record in vex_raw.
    • anchors contain JSON pointers/paragraph locators from source metadata.

Headers:

  • Excititor-Results-Truncated: true|false
  • Excititor-Results-Total: <int>

/v1/vex/evidence/chunks

  • Query params: vulnerabilityId (required), productKey (required), optional providerId, status, since, limit.
  • Limits: default limit=500, max 2000.
  • Response: NDJSON stream; each line is a VexEvidenceChunkResponse.
  • Chunk fields: observationId, linksetId, vulnerabilityId, productKey, providerId, status, justification, detail, scopeScore (from confidence or signals), firstSeen, lastSeen, scope{...}, document{digest,format,sourceUri,revision}, signature{type,subject,issuer,keyId,verifiedAt,transparencyRef}, metadata (flattened additionalMetadata).
  • Headers: Excititor-Results-Total, Excititor-Results-Truncated (mirrors projection API naming).
  • Streaming guidance (SDK/clients):
    • Use HTTP client that supports response streaming; read line-by-line and JSON-deserialize per line.
    • Treat stream as an NDJSON list up to limit; no outer array.
    • Back-off or paginate by adjusting since or narrowing providers/statuses.

OpenAPI (excerpt):

paths:
  /v1/vex/evidence/chunks:
    get:
      summary: Stream evidence chunks for a vulnerability/product
      parameters:
        - in: query
          name: vulnerabilityId
          schema: { type: string }
          required: true
        - in: query
          name: productKey
          schema: { type: string }
          required: true
        - in: query
          name: providerId
          schema: { type: string }
          description: Comma-separated provider ids
        - in: query
          name: status
          schema: { type: string }
          description: Comma-separated VEX statuses
        - in: query
          name: since
          schema: { type: string, format: date-time }
        - in: query
          name: limit
          schema: { type: integer, minimum: 1, maximum: 2000, default: 500 }
      responses:
        "200":
          description: NDJSON stream of VexEvidenceChunkResponse
          headers:
            Excititor-Results-Total: { schema: { type: integer } }
            Excititor-Results-Truncated: { schema: { type: boolean } }
          content:
            application/x-ndjson:
              schema:
                type: string
                description: One JSON object per line (VexEvidenceChunkResponse)

Example (curl):

curl -s -H "Authorization: Bearer <token>" \
     -H "X-Stella-Tenant: acme" \
     "https://exc.example.test/v1/vex/evidence/chunks?vulnerabilityId=CVE-2025-0001&productKey=pkg:docker/demo&limit=2" |
  head -n 2

Sample NDJSON line:

{"observationId":"provider-a:4d2f...","linksetId":"CVE-2025-0001:pkg:docker/demo","vulnerabilityId":"CVE-2025-0001","productKey":"pkg:docker/demo","providerId":"provider-a","status":"Affected","justification":"ComponentNotPresent","detail":"demo detail","scopeScore":0.9,"firstSeen":"2025-11-10T12:00:00Z","lastSeen":"2025-11-12T12:00:00Z","scope":{"key":"pkg:docker/demo","name":"demo","version":"1.0.0","purl":"pkg:docker/demo","cpe":null,"componentIdentifiers":["component-a"]},"document":{"digest":"sha256:e7...","format":"sbomcyclonedx","sourceUri":"https://example.test/vex.json","revision":"r1"},"signature":{"type":"cosign","subject":"demo","issuer":"issuer","keyId":"kid","verifiedAt":"2025-11-12T12:00:00Z","transparencyRef":null},"metadata":{}}

/v1/vex/attestations/{attestationId}

  • Purpose: Lookup attestation provenance (supplier ↔ observation/linkset ↔ product/vulnerability) without touching consensus.
  • Response: VexAttestationPayload with fields:
    • attestationId, supplierId, observationId, linksetId, vulnerabilityId, productKey, justificationSummary, issuedAt, metadata{}.
  • Semantics:
    • attestationId matches the export/attestation ID used when signing (Resolve/Worker flows).
    • observationId/linksetId map back to evidence identifiers; clients can stitch provenance for citations.
  • Auth: vex.read scope; tenant header optional (payloads are tenant-agnostic).

Error model

  • Standard API envelope with ValidationProblem for missing required params.
  • scope failures return 403 with problem details.
  • Tenancy parse failures return 400.

Backwards compatibility

  • No legacy routes are deprecated by these endpoints; they are additive and remain aggregation-only.

References

  • Implementation: src/Excititor/StellaOps.Excititor.WebService/Program.cs (/v1/vex/observations/**, /v1/vex/evidence/chunks).
  • Telemetry: src/Excititor/StellaOps.Excititor.WebService/Telemetry/EvidenceTelemetry.cs (excititor.vex.observation.*, excititor.vex.chunks.*).
  • Data model: src/Excititor/StellaOps.Excititor.WebService/Contracts/VexObservationContracts.cs, Contracts/VexEvidenceChunkContracts.cs.