Files
git.stella-ops.org/docs/modules/excititor/operations/graph-linkouts-implementation.md
StellaOps Bot 9f6e6f7fb3
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Policy Simulation / policy-simulate (push) Has been cancelled
SDK Publish & Sign / sdk-publish (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
devportal-offline / build-offline (push) Has been cancelled
up
2025-11-25 22:09:44 +02:00

3.2 KiB

Excititor · Graph Linkouts & Overlays — Implementation Notes (Graph 21-001/002/005/24-101/24-102)

  • Date: 2025-11-21
  • Scope: EXCITITOR-GRAPH-21-001, EXCITITOR-GRAPH-21-002, EXCITITOR-GRAPH-21-005
  • Status: Implementation guidance (storage wiring pending).

Endpoints

  1. Linkouts (21-001)

    • POST /internal/graph/linkouts
    • Body: tenant, purls[] (max 500), includeJustifications?, includeProvenance?
    • Response: ordered by input purls; each item includes advisories[] (advisoryId, source, status, justification?, modifiedAt, evidenceHash, connectorId, dsseEnvelopeHash?) plus conflicts[]; notFound[].
  2. Overlays (21-002)

    • GET /v1/graph/overlays?purl=<purl>&purl=<purl>&includeJustifications=true|false
    • Response per PURL: summary counts (open, not_affected, under_investigation, no_statement), latestModifiedAt, justifications[] (unique, sorted), provenance (sources[], lastEvidenceHash), cached, cacheAgeMs.
  3. Status summaries (24-101)

    • GET /v1/graph/status?purl=<purl>&purl=<purl>
    • Response mirrors overlay summaries but omits justification payloads; includes sources[], lastEvidenceHash, cached, cacheAgeMs. Intended for Vuln Explorer status colouring.
  4. Batch observations for tooltips (24-102)

    • GET /v1/graph/observations?purl=<purl>[&purl=...]&includeJustifications=true|false[&limitPerPurl=50][&cursor=<base64>]
    • Response per PURL: ordered observations[] (observationId, advisoryId, status, justification?, providerId, modifiedAt, evidenceHash, dsseEnvelopeHash?) plus truncated; top-level nextCursor, hasMore enable paging. Limits enforced per PURL and globally.

Storage & Indexes (21-005)

  • vex_observations indexes:
    • { tenant: 1, component.purl: 1, advisoryId: 1, source: 1, modifiedAt: -1 }
    • Sparse { tenant: 1, component.purl: 1, status: 1 }
  • Optional materialized vex_overlays cache: unique { tenant: 1, purl: 1 }, TTL on cachedAt driven by excititor:graph:overlayTtlSeconds (default 300s).

Determinism

  • Ordering: input PURL order → advisoryIdsource for linkouts; overlays follow input order.
  • Truncation: max 200 advisories per PURL; when truncated, include truncated: true and nextCursor (advisoryId, source).

Config knobs

  • excititor:graph:overlayTtlSeconds (default 300)
  • excititor:graph:maxPurls (default 500)
  • excititor:graph:maxAdvisoriesPerPurl (default 200)
  • excititor:graph:maxTooltipItemsPerPurl (default 50)
  • excititor:graph:maxTooltipTotal (default 1000)

Telemetry

  • Counter excititor.graph.linkouts.requests tags: tenant, includeJustifications, includeProvenance.
  • Counter excititor.graph.overlays.cache tags: tenant, hit (true|false).
  • Histogram excititor.graph.linkouts.latency.ms tags: tenant.

Steps to implement

  • Bind GraphOptions to Excititor:Graph.
  • Add endpoints to WebService with tenant guard; enforce limits.
  • Implement overlay cache with deterministic sort; respect TTL; surface cached + cacheAgeMs.
  • Backfill Mongo indexes above.
  • Integration tests (WebApplicationFactory + Mongo2Go) for ordering, truncation, cache metadata, tenant isolation.