# Advisory Ingestion with Canonical Deduplication ## Module Concelier ## Status VERIFIED ## Description Advisory ingestion pipeline with canonical deduplication, linkset observation factory, and raw advisory processing. ## Implementation Details - **Modules**: `src/Concelier/__Libraries/StellaOps.Concelier.Core/`, `src/Concelier/__Libraries/StellaOps.Concelier.Merge/`, `src/Concelier/__Libraries/StellaOps.Concelier.Persistence/` - **Key Classes**: - `CanonicalAdvisoryService` (`src/Concelier/__Libraries/StellaOps.Concelier.Core/Canonical/CanonicalAdvisoryService.cs`) - core canonical advisory management - `CachingCanonicalAdvisoryService` (`src/Concelier/__Libraries/StellaOps.Concelier.Core/Canonical/CachingCanonicalAdvisoryService.cs`) - caching decorator for canonical advisory lookups - `MergeHashCalculator` (`src/Concelier/__Libraries/StellaOps.Concelier.Merge/Identity/MergeHashCalculator.cs`) - deterministic semantic merge hash for deduplication - `ConnectorWorker` (`src/Concelier/__Libraries/StellaOps.Concelier.Core/Orchestration/ConnectorWorker.cs`) - orchestrates advisory ingestion cycles - `AdvisoryRepository` (`src/Concelier/__Libraries/StellaOps.Concelier.Persistence/Postgres/Repositories/AdvisoryRepository.cs`) - raw advisory persistence - `AdvisoryCanonicalRepository` (`src/Concelier/__Libraries/StellaOps.Concelier.Persistence/Postgres/Repositories/AdvisoryCanonicalRepository.cs`) - canonical advisory persistence - `AdvisorySourceEdgeEntity` (`src/Concelier/__Libraries/StellaOps.Concelier.Persistence/Postgres/Models/AdvisorySourceEdgeEntity.cs`) - source-to-canonical edge tracking - **Interfaces**: `ICanonicalAdvisoryService`, `IMergeHashCalculator`, `IAdvisoryRepository`, `IAdvisoryCanonicalRepository` - **Source**: Feature matrix scan ## E2E Test Plan - [ ] Ingest the same advisory from two different sources (e.g., NVD and GHSA) and verify they deduplicate to a single canonical advisory - [ ] Verify `MergeHashCalculator` produces identical hashes for semantically equivalent advisories from different sources - [ ] Verify `AdvisorySourceEdgeEntity` tracks both source edges pointing to the same canonical - [ ] Verify `CachingCanonicalAdvisoryService` returns cached results on repeated lookups - [ ] Verify new advisories with different CVE IDs produce distinct canonicals