# Excititor ยท Graph Linkouts & Overlays โ€” Implementation Notes (Graph 21-001/002/005) - **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=&includeJustifications=true|false` - Response per PURL: `summary` counts (`open`, `not_affected`, `under_investigation`, `no_statement`), `latestModifiedAt`, `justifications[]` (unique, sorted), `provenance` (`sources[]`, `lastEvidenceHash`), `cached`, `cacheAgeMs`. ## 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 โ†’ `advisoryId` โ†’ `source` 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) ## 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.