Advisory affected symbols

GET /api/vulnerabilities/v1/advisories/{vulnerabilityId}/symbols provides the upstream symbol coordinates used by Scanner reachability. It requires advisory:read. The hub is tenant-free; Scanner does not forward a tenant selector for this lookup.

The owner reads OSV documents referenced by live, non-tombstoned facts for the requested vulnerability. Each row includes the upstream advisory identifier, source, document digest, fetch time and decoded symbol coordinates. The shared OSV wire decoder supports flat and structured symbol arrays, Go imports and Rust affected functions in both ecosystem_specific and database_specific. It is also used by compact vulnerability database export.

This point lookup is bounded to 8,192 distinct symbols and a 16 MiB source document. Exceeding either bound returns 503; it does not return a truncated successful result. Bulk consumers continue to use retained corpus publications. An advisory with no current upstream symbols returns an empty list. Replacing a normalized document removes symbols no longer present in that document, even when the vulnerability fact’s value is unchanged.

Scanner’s HubHttpAffectedSymbolProvider uses the same authenticated hub client and Scanner:Worker:Reachability:HubAdvisoryBaseUrl as product-issue lookup. The old AdvisoryBaseUrl setting and /v1/signals/symbols/* requests are removed. Scanner merges these upstream symbols with its explicit sink mappings through AffectedSymbolCveSymbolMappingService. An unavailable owner leaves source symbols unavailable and preserves the existing unknown reachability behavior.

Source verification: AdvisorySymbolEndpointTests drives ordinary ingestion and normalization against PostgreSQL, checks authorization, then replaces a document’s symbol list. HubHttpAffectedSymbolProviderTests verifies the typed HTTP contract and omission of tenant headers. Deployment acceptance is recorded separately in the owning sprint.