Findings.VulnCorrelation — retained analytics ingestion and correlation libraries

Ownership and schema verified at c0a5692e8a022952d7a3c814919c8c485d173ca4 on 2026-10-04 (PCD-267). The standalone VulnCorrelation host and its compose overlay were deleted at FND-10 (2026-08-27). The application and legacy persistence libraries remain, but no serving host calls AddAnalyticsIngestion or AddVulnCorrelationMigrations. Both current Findings roles select the consolidated persistence lineage described in section 6. This is source verification; the database contents of an installation were not inspected.

1. Overview

This page separates retained library behavior from the schema selected by the consolidated Findings hosts. See the Findings architecture for the serving module.

PAC-5 originally moved analytics ingestion out of Platform into a dedicated worker. That host is deleted. Its retained consumers still reference the old streams and database contracts; their presence in source does not establish a scheduled ingestion path.

findings-worker registers the advisory-corpus, advisory/SBOM and Scanner projections through the consolidated persistence library. Those registrations do not call the legacy ingestion extension. Their configuration and contracts are described in the Findings architecture.

2. Ownership and implementation limits

  1. The consolidated Findings family owns stellaops_findings, including its analytics schema.
  2. Both findings-web and findings-worker apply the family’s embedded migration chain at startup.
  3. The retained VulnCorrelation migration chain is not selected by either host.
  4. The retained application library still contains same-database reads of vuln.* and writes to analytics.vex_overrides, which the consolidated baseline does not provide.
  5. Platform’s analytics read API and maintenance lane were withdrawn by PCD-127 on 2026-09-30.

3. Components

Paths below are relative to src/Findings/.

SourceRole
StellaOps.Findings.WebService/Program.csServing HTTP host; calls AddConsolidatedFindingsPersistence.
StellaOps.Findings.Worker/Program.csServing worker; calls the same persistence registration and the current projection registrations.
__Libraries/StellaOps.Findings.Persistence/Selected migration lineage, including 001_findings_consolidated_baseline.sql.
__Libraries/StellaOps.Findings.VulnCorrelation.Application/ServiceCollectionExtensions.csRetained AddAnalyticsIngestion registration, with no serving caller.
__Libraries/StellaOps.Findings.VulnCorrelation.Application/Services/Retained scanner/SBOM, attestation and correlation consumers, CAS reader and disposition cache.
__Libraries/StellaOps.Findings.VulnCorrelation.Application/Options/ and Utilities/Library configuration, PURL/version rules, tenant normalization and hashing.
__Libraries/StellaOps.Findings.VulnCorrelation.Persistence/Retained AddVulnCorrelationMigrations extension and embedded legacy analytics DDL.

Tests that instantiate the retained library live under src/Findings/__Tests/StellaOps.Findings.VulnCorrelation.Tests/.

4. Data flow in the retained library

The following describes the unscheduled library implementation. It is not a serving data flow. File names in this section resolve under the application library’s Services/ or Models/ directories.

orchestrator:events ────────► AnalyticsIngestionService ──► CAS (SBOM) ──► analytics.artifacts
  (scanner.event.report.ready │                                              analytics.raw_sboms
   scanner.scan.completed)    │                                              analytics.components
                              │                                              analytics.artifact_components
                              └─ finding.disposition.changed ──► in-memory FindingDispositionCache
                                                                 (not persisted)

attestor:events ────────────► AttestationIngestionService ─► CAS (DSSE bundle) ─► analytics.attestations
  (rekor.entry.logged                                                             analytics.raw_attestations
   rekor.inclusion.verified)                                                      analytics.vex_overrides
                                                                                  analytics.artifacts (provenance/SLSA)

concelier:advisory.observation.updated:v1 ┐
concelier:advisory.linkset.updated:v1     ┴► VulnerabilityCorrelationService ─► analytics.component_vulns
                                             (reads Concelier vuln.* in the same DB)  analytics.artifacts (counts)

4.1 Scanner / SBOM lane (AnalyticsIngestionService)

4.2 Attestor lane (AttestationIngestionService)

4.3 Concelier / correlation lane (VulnerabilityCorrelationService)

Unresolved legacy dependencies. The retained correlation SQL joins vuln.* in the same database (Services/VulnerabilityCorrelationService.cs). The attestation consumer writes analytics.vex_overrides (Services/AttestationIngestionService.cs). Neither dependency is supplied by the consolidated Findings migrations. These are not supported cross-service read contracts.

5. Current ownership boundary

ConcernCurrent stateSource
Serving analytics DDLFindings consolidated persistenceBoth serving Program.cs files call AddConsolidatedFindingsPersistence; see section 6.
Legacy analytics DDLEmbedded in the retained VulnCorrelation persistence library; no serving callerExtensions/VulnCorrelationMigrationExtensions.cs and its project resource items.
Legacy SBOM/attestation ingestion and correlationRetained application code, unscheduledServiceCollectionExtensions.AddAnalyticsIngestion; neither serving host calls it.
GET /api/analytics/*Withdrawn by PCD-127Former Platform sources are frozen under src/__Obsoleted/Platform/StellaOps.Platform.WebService/PCD-127/.
Daily rollups and materialized-view refreshFormer Platform maintenance lane withdrawn by PCD-127The consolidated Findings migration chain creates neither these rollups nor these views.

The Platform dossier records the withdrawal. Retained legacy DDL is not evidence that the former analytics API or maintenance process is available.

6. Serving schema and retained legacy DDL

6.1 Selected Findings migration lineage

src/Findings/StellaOps.Findings.WebService/Program.cs and src/Findings/StellaOps.Findings.Worker/Program.cs call AddConsolidatedFindingsPersistence. Its implementation is src/Findings/__Libraries/StellaOps.Findings.Persistence/Extensions/ConsolidatedFindingsPersistenceExtensions.cs. It registers AddStartupMigrations with its own assembly, module Findings.Consolidated, and migration ledger findings.schema_migrations.

The service resolves STELLAOPS_POSTGRES_FINDINGS_CONNECTION, with the service-specific Postgres:Findings:ConnectionString configuration override, and fails closed without a value. It does not select the former shared-database connection fallbacks.

src/Findings/__Libraries/StellaOps.Findings.Persistence/Migrations/001_findings_consolidated_baseline.sql creates the following analytics tables. The numbered migrations beside it are the authority for later changes; migration 016 adds retention comments to these tables.

TablePurpose
analytics.componentsComponent registry keyed by (purl, hash_sha256), with supplier/license data and inventory counts.
analytics.artifactsArtifact inventory keyed by digest, with SBOM pointers, severity counts and provenance fields.
analytics.artifact_componentsArtifact/component edges and dependency depth.
analytics.component_vulnsCorrelation results keyed by (component_id, vuln_id).
analytics.attestationsParsed attestation metadata and DSSE payload hashes.
analytics.raw_sbomsSBOM pointers and deduplication by content_hash.
analytics.raw_attestationsAttestation pointers and deduplication by content_hash.

The baseline also creates the helpers analytics.normalize_supplier, analytics.categorize_license and analytics.parse_purl. Creating these objects does not schedule the retained ingestion services.

6.2 Legacy objects excluded from the serving chain

The retained StellaOps.Findings.VulnCorrelation.Persistence project embeds Migrations/001_v1_analytics_baseline.sql and excludes Migrations/_archived/ resources. AddVulnCorrelationMigrations would register that assembly under module Findings.VulnCorrelation and schema analytics, but a source-wide caller search finds only its declaration outside frozen code and tests.

These legacy objects are absent from the consolidated migration chain:

Legacy objectsConsolidated disposition
analytics.schema_versionLegacy version marker omitted; the family uses findings.schema_migrations.
analytics.vex_overridesOmitted under DC-32. The retained attestation consumer still references it.
analytics.daily_vulnerability_counts, analytics.daily_component_countsRollup tables omitted under ruling A4.
mv_supplier_concentration, mv_license_distribution, mv_vuln_exposure, mv_attestation_coverageMaterialized views omitted under ruling A4.
sp_top_suppliers, sp_license_heatmap, sp_vuln_exposure, sp_fixable_backlog, sp_attestation_gaps, sp_mttr_by_severityLegacy query functions omitted.
compute_daily_rollups, refresh_all_views, update_updated_at_columnLegacy rollup, refresh and unused trigger functions omitted.

The omitted view/function names above are in the analytics schema. The consolidation design preserves the dated disposition decisions. The analytics SQL reference documents the legacy design; it is not the serving startup migration source.

The legacy baseline concatenates historical migrations. Later definitions supersede earlier definitions within that file. Reading or retaining that DDL does not apply it to Findings, and this document does not establish whether an older installation retains predecessor objects.

6.3 Re-verify from the repository root

rg -n 'AddVulnCorrelationMigrations|AddAnalyticsIngestion' src -g '*.cs' -g '!__Obsoleted/**' -g '!**/__Tests/**'
rg -n 'AddConsolidatedFindingsPersistence|AddAdvisoryCorpusProjection|AddAdvisorySbomProjection|AddScannerSecurityProjection' src/Findings/StellaOps.Findings.WebService/Program.cs src/Findings/StellaOps.Findings.Worker/Program.cs
rg -n 'AddStartupMigrations|ModuleName|SchemaName|migrationsAssembly|ConnectionEnvironmentVariable|ConnectionConfigurationKey' src/Findings/__Libraries/StellaOps.Findings.Persistence/Extensions/ConsolidatedFindingsPersistenceExtensions.cs
rg -n 'CREATE.*(TABLE|VIEW|FUNCTION|PROCEDURE).*analytics|analytics[.](mv_|sp_|daily_|schema_version|vex_overrides|compute_daily_rollups|refresh_all_views)' src/Findings/__Libraries/StellaOps.Findings.Persistence/Migrations

Expected: the first search returns only the two retained declarations. The serving hosts select consolidated persistence. The migration search shows the ingestion tables and three helpers; excluded objects appear only in historical exclusion comments, not executable create statements. These checks establish source wiring and DDL, not deployed schema contents or ingestion acceptance.

7. Retained library configuration

The retained options use Platform:AnalyticsIngestion(AnalyticsIngestionOptions.SectionName). No serving host calls this registration, so these keys do not enable ingestion in current Findings.

KeyDefaultNotes
Platform:AnalyticsIngestion:Enabledtruefalse ⇒ the SBOM lane logs “disabled by configuration” and exits.
…:PostgresConnectionString—Library data-source connection; AddAnalyticsIngestion can fill a missing value from its defaultConnectionString argument. This is not the consolidated migration connection selector.
…:AllowedTenants(empty)Ingestion tenant allowlist. Empty ⇒ every tenant is accepted (see §8).
…:Streams:ScannerStreamorchestrator:events
…:Streams:ConcelierObservationStreamconcelier:advisory.observation.updated:v1
…:Streams:ConcelierLinksetStreamconcelier:advisory.linkset.updated:v1
…:Streams:AttestorStreamattestor:events
…:Streams:StartFromBeginningfalse
…:Streams:ResumeFromCheckpointtrue
…:Streams:ScannerCheckpointFilePath(derived)Defaults to <Cas:RootPath>/.state/platform-scanner-stream.checkpoint.
…:Cas:RootPath—Must be the same CAS volume the scanner writes SBOMs to.
…:Attestations:BundleUriTemplatebundle:{digest}

8. Retained analytics tenancy limits

  1. The retained analytics tables have no tenant column. Both the legacy baseline and the consolidated analytics table definitions key this inventory without a tenant dimension. This observation does not describe the tenant-bound findings or findings_security schemas.
  2. Tenancy is enforced only at the ingestion boundary, from the event envelope’s tenant (envelope.Tenant / payload TenantId) — never from a caller-supplied header — against the AllowedTenants allowlist (TenantNormalizer.IsAllowed, which strips a urn:tenant: prefix and compares case-insensitively).
  3. An empty AllowedTenants list allows every tenant (Utilities/TenantNormalizer.cs, IsAllowed: if (allowedTenants is null || allowedTenants.Count == 0) return true;). The old overlay is deleted; no current deployment setting activates this library registration.
  4. The retained validator rejects multiple explicit tenants when ingestion is enabled (AnalyticsIngestionOptions.Validate, CLO-4). Normalize() strips urn:tenant: and de-duplicates case-insensitively before that check. AddAnalyticsIngestion registers the validator through ValidateOnStart(). The empty allowlist still admits every tenant; the validator therefore does not establish tenant isolation for that default.
  5. Consequently analytics.* is a single-tenant read model per deployment. Platform’s former /api/analytics/* endpoints required the analytics.read scope and RequireTenant(), but the tenant only participated in the cache key (PlatformAnalyticsService.cs:55-168) — the SQL cannot filter by tenant because the column does not exist. True per-tenant isolation would require a real tenant dimension end-to-end (schema column + ingestion write + read-path filter); that is a follow-up, not a current guarantee. Recorded in SPRINT_20260712_006 and SPRINT_20260712_009 (CLO-4) Decisions & Risks.
  6. The VulnCorrelation library has no serving host or gateway route. The consolidated Findings security read model serves /api/findings/v1/security/* through findings-web (StellaOps.Findings.Security.Application/Endpoints/SecurityReadModelEndpoints.cs). Platform’s former analytics read surface is withdrawn.

9. Deployment and operations

The former stellaops/findings-vulncorrelation image, host project and devops/compose/docker-compose.findings-vulncorrelation.override.yml overlay are retired. Their health, transport and shared-CAS instructions are historical and cannot deploy a current host.

Use the Findings architecture for the current findings-web and findings-worker roles. Their startup migrations create the consolidated schema described above. Neither host schedules the retained analytics consumers, and adding legacy configuration keys does not create that wiring.

10. Determinism & replay

The retained library implements at-least-once ingestion with upserts and dedupe-guarded inserts. The scanner checkpoint is advanced after the event is handled, so a crash between handling and checkpointing replays the last event (idempotently).

11. References