docs consolidation work
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
# MongoDB to PostgreSQL Conversion Plan
|
||||
|
||||
**Version:** 2.0.0
|
||||
**Status:** APPROVED
|
||||
**Status:** ✅ **CONVERSION COMPLETED** — Sprint 4400 (November 2024)
|
||||
**Created:** 2025-11-28
|
||||
**Last Updated:** 2025-11-28
|
||||
**Last Updated:** 2025-12-25
|
||||
|
||||
> **COMPLETION NOTICE:** MongoDB to PostgreSQL conversion **completed in Sprint 4400 (November 2024)**. All control-plane services now use PostgreSQL 16+. MongoDB dependencies removed from all modules. This document is preserved for historical reference and lessons learned.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1491,7 +1491,7 @@ CREATE INDEX idx_format ON sbom_docs ((doc->>'bomFormat'));
|
||||
-- Query planner can't estimate cardinality, may choose suboptimal plans
|
||||
```
|
||||
|
||||
**Solution: Generated columns (PostgreSQL 12+):**
|
||||
**Solution: Generated columns (PostgreSQL 16+):**
|
||||
```sql
|
||||
-- Add generated column that extracts JSONB field
|
||||
ALTER TABLE scanner.sbom_documents
|
||||
|
||||
@@ -181,3 +181,69 @@ CREATE INDEX IF NOT EXISTS idx_merge_events_advisory ON vuln.merge_events(adviso
|
||||
CREATE INDEX IF NOT EXISTS idx_advisories_fts ON vuln.advisories USING GIN (
|
||||
to_tsvector('english', COALESCE(title, '') || ' ' || COALESCE(summary, '') || ' ' || COALESCE(description, ''))
|
||||
);
|
||||
|
||||
-- ===========================================================================
|
||||
-- Canonical Advisory Deduplication (Sprint 8200.0012.0002)
|
||||
-- ===========================================================================
|
||||
|
||||
-- Deduplicated canonical advisory records
|
||||
-- Identified by semantic merge_hash computed from (cve, affects_key, version_range, weakness, patch_lineage)
|
||||
CREATE TABLE IF NOT EXISTS vuln.advisory_canonical (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
cve TEXT NOT NULL, -- CVE identifier (e.g., CVE-2024-1234)
|
||||
affects_key TEXT NOT NULL, -- Normalized PURL or CPE
|
||||
version_range JSONB, -- Structured: { introduced, fixed, last_affected }
|
||||
weakness TEXT[] NOT NULL DEFAULT '{}', -- Sorted CWE array
|
||||
merge_hash TEXT NOT NULL UNIQUE, -- SHA256 of normalized identity components
|
||||
status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'stub', 'withdrawn')),
|
||||
severity TEXT CHECK (severity IN ('critical', 'high', 'medium', 'low', 'none', 'unknown')),
|
||||
epss_score NUMERIC(5,4), -- EPSS probability (0.0000-1.0000)
|
||||
exploit_known BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
title TEXT,
|
||||
summary TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Canonical indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_advisory_canonical_cve ON vuln.advisory_canonical(cve);
|
||||
CREATE INDEX IF NOT EXISTS idx_advisory_canonical_affects ON vuln.advisory_canonical(affects_key);
|
||||
CREATE INDEX IF NOT EXISTS idx_advisory_canonical_merge_hash ON vuln.advisory_canonical(merge_hash);
|
||||
CREATE INDEX IF NOT EXISTS idx_advisory_canonical_status ON vuln.advisory_canonical(status) WHERE status = 'active';
|
||||
CREATE INDEX IF NOT EXISTS idx_advisory_canonical_severity ON vuln.advisory_canonical(severity) WHERE severity IS NOT NULL;
|
||||
CREATE INDEX IF NOT EXISTS idx_advisory_canonical_exploit ON vuln.advisory_canonical(exploit_known) WHERE exploit_known = TRUE;
|
||||
CREATE INDEX IF NOT EXISTS idx_advisory_canonical_updated ON vuln.advisory_canonical(updated_at DESC);
|
||||
|
||||
-- Source edge linking canonical advisories to source documents
|
||||
-- Stores DSSE signature envelopes and raw payloads for provenance
|
||||
CREATE TABLE IF NOT EXISTS vuln.advisory_source_edge (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
canonical_id UUID NOT NULL REFERENCES vuln.advisory_canonical(id) ON DELETE CASCADE,
|
||||
source_id UUID NOT NULL REFERENCES vuln.sources(id) ON DELETE RESTRICT,
|
||||
source_advisory_id TEXT NOT NULL, -- Vendor advisory ID (DSA-5678, RHSA-2024:1234)
|
||||
source_doc_hash TEXT NOT NULL, -- SHA256 of raw source document
|
||||
vendor_status TEXT CHECK (vendor_status IN ('affected', 'not_affected', 'fixed', 'under_investigation')),
|
||||
precedence_rank INT NOT NULL DEFAULT 100, -- Lower = higher priority (vendor=10, distro=20, osv=30, nvd=40)
|
||||
dsse_envelope JSONB, -- { payloadType, payload, signatures[] }
|
||||
raw_payload JSONB, -- Original advisory document
|
||||
fetched_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
UNIQUE (canonical_id, source_id, source_doc_hash)
|
||||
);
|
||||
|
||||
-- Source edge indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_source_edge_canonical ON vuln.advisory_source_edge(canonical_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_source_edge_source ON vuln.advisory_source_edge(source_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_source_edge_advisory_id ON vuln.advisory_source_edge(source_advisory_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_source_edge_canonical_source ON vuln.advisory_source_edge(canonical_id, source_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_source_edge_fetched ON vuln.advisory_source_edge(fetched_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_source_edge_dsse_gin ON vuln.advisory_source_edge USING GIN (dsse_envelope jsonb_path_ops);
|
||||
|
||||
-- Comments for canonical deduplication tables
|
||||
COMMENT ON TABLE vuln.advisory_canonical IS 'Deduplicated canonical advisories with semantic merge_hash';
|
||||
COMMENT ON COLUMN vuln.advisory_canonical.merge_hash IS 'Deterministic SHA256 hash of (cve, affects_key, version_range, weakness, patch_lineage)';
|
||||
COMMENT ON COLUMN vuln.advisory_canonical.affects_key IS 'Normalized PURL or CPE identifying the affected package';
|
||||
COMMENT ON COLUMN vuln.advisory_canonical.status IS 'active=full record, stub=minimal for low interest, withdrawn=no longer valid';
|
||||
COMMENT ON TABLE vuln.advisory_source_edge IS 'Links canonical advisories to source documents with DSSE signatures';
|
||||
COMMENT ON COLUMN vuln.advisory_source_edge.precedence_rank IS 'Source priority: vendor=10, distro=20, osv=30, nvd=40, default=100';
|
||||
COMMENT ON COLUMN vuln.advisory_source_edge.dsse_envelope IS 'DSSE envelope with signature over raw_payload';
|
||||
|
||||
Reference in New Issue
Block a user