{ "dashboard_title": "Source Coverage & Gaps", "description": "Operational dashboard for identifying source coverage gaps, stale sources, and symbols missing expected data feeds.", "slug": "source-coverage-gaps", "position_json": { "HEADER_ID": {"id": "HEADER_ID", "type": "HEADER", "meta": {"text": "Source Coverage & Gaps"}}, "ROW-1": { "type": "ROW", "children": ["CHART-coverage-matrix", "CHART-missing-types-table"] }, "ROW-2": { "type": "ROW", "children": ["CHART-stale-sources-table", "CHART-failure-heatmap"] } }, "metadata": { "refresh_frequency": 600, "default_filters": "{}", "color_scheme": "supersetColors" }, "charts": [ { "slice_name": "Source Coverage Matrix", "viz_type": "table", "description": "Per-symbol source type coverage showing active source counts", "datasource_type": "query", "query": "SELECT c.ticker, c.legal_name, c.sector, COUNT(s.id) FILTER (WHERE s.active) AS active_sources, COUNT(s.id) FILTER (WHERE s.source_type = 'market_api' AND s.active) AS market_sources, COUNT(s.id) FILTER (WHERE s.source_type = 'news_api' AND s.active) AS news_sources, COUNT(s.id) FILTER (WHERE s.source_type = 'filings_api' AND s.active) AS filings_sources, COUNT(s.id) FILTER (WHERE s.source_type = 'web_scrape' AND s.active) AS web_scrape_sources, COUNT(s.id) FILTER (WHERE s.source_type = 'broker' AND s.active) AS broker_sources FROM companies c LEFT JOIN sources s ON s.company_id = c.id WHERE c.active = TRUE GROUP BY c.ticker, c.legal_name, c.sector ORDER BY c.ticker" }, { "slice_name": "Symbols Missing Source Types", "viz_type": "table", "description": "Companies that lack one or more expected source types (market_api, news_api, filings_api)", "datasource_type": "query", "query": "SELECT c.ticker, c.legal_name, c.sector, ARRAY_AGG(DISTINCT s.source_type) FILTER (WHERE s.active) AS active_types FROM companies c LEFT JOIN sources s ON s.company_id = c.id AND s.active = TRUE WHERE c.active = TRUE GROUP BY c.ticker, c.legal_name, c.sector HAVING NOT ARRAY['market_api', 'news_api', 'filings_api'] <@ ARRAY_AGG(DISTINCT s.source_type) FILTER (WHERE s.active) OR ARRAY_AGG(DISTINCT s.source_type) FILTER (WHERE s.active) IS NULL ORDER BY c.ticker" }, { "slice_name": "Stale Sources (No Success in 24h)", "viz_type": "table", "description": "Active sources that have not completed a successful ingestion run in the last 24 hours", "datasource_type": "query", "query": "SELECT c.ticker, s.source_type, s.source_name, MAX(ir.started_at) FILTER (WHERE ir.status = 'completed') AS last_success, MAX(ir.started_at) AS last_attempt, COUNT(*) FILTER (WHERE ir.status = 'failed' AND ir.started_at >= NOW() - INTERVAL '24 hours') AS recent_failures FROM sources s JOIN companies c ON c.id = s.company_id LEFT JOIN ingestion_runs ir ON ir.source_id = s.id WHERE s.active = TRUE AND c.active = TRUE GROUP BY c.ticker, s.source_type, s.source_name HAVING MAX(ir.started_at) FILTER (WHERE ir.status = 'completed') < NOW() - INTERVAL '24 hours' OR MAX(ir.started_at) FILTER (WHERE ir.status = 'completed') IS NULL ORDER BY c.ticker, s.source_type" }, { "slice_name": "Source Failure Heatmap", "viz_type": "heatmap", "description": "Failure counts by source type and ticker in the last 24h", "datasource_type": "query", "query": "SELECT c.ticker, ir.source_type, COUNT(*) FILTER (WHERE ir.status = 'failed') AS failures FROM ingestion_runs ir JOIN companies c ON c.id = ir.company_id WHERE ir.started_at >= NOW() - INTERVAL '24 hours' GROUP BY c.ticker, ir.source_type HAVING COUNT(*) FILTER (WHERE ir.status = 'failed') > 0 ORDER BY failures DESC" } ] }