feat(awooop): verify source correlation links in status chain
All checks were successful
Code Review / ai-code-review (push) Successful in 10s
CD Pipeline / tests (push) Successful in 6m9s
CD Pipeline / build-and-deploy (push) Successful in 4m39s
CD Pipeline / post-deploy-checks (push) Successful in 1m55s

This commit is contained in:
Your Name
2026-05-21 10:51:20 +08:00
parent ac7f642e41
commit efb38cf6af
7 changed files with 298 additions and 9 deletions

View File

@@ -1332,18 +1332,24 @@ def _source_correlation_empty(
"incident_ids": incident_ids,
"direct_ref_total": 0,
"candidate_total": 0,
"applied_link_total": 0,
"provider_event_total": 0,
"latest_applied_link_at": None,
"verification_status": status_value,
"providers": {
provider: {
"direct_ref_total": 0,
"candidate_total": 0,
"applied_link_total": 0,
"latest_event_at": None,
"latest_heartbeat_at": None,
"latest_applied_link_at": None,
}
for provider in _SOURCE_CORRELATION_PROVIDERS
},
"top_candidates": [],
"matching_criteria": [
"source_correlation_linked_stage",
"direct_source_ref",
"fingerprint_overlap",
"alertname_overlap",
@@ -1557,6 +1563,17 @@ def _score_source_correlation_event(
}
def _is_source_correlation_applied_link(
event_context: dict[str, Any],
scored: dict[str, Any],
) -> bool:
"""Applied source links must be append-only events that still match directly."""
return (
str(event_context.get("stage") or "").lower() == "source_correlation_linked"
and bool(scored.get("is_direct"))
)
async def _fetch_source_correlation_summary(
*,
project_id: str,
@@ -1689,6 +1706,19 @@ async def _fetch_source_correlation_summary(
summary["candidate_total"] += 1
provider_item["candidate_total"] += 1
is_applied_link = _is_source_correlation_applied_link(
event_context,
best_match,
)
if is_applied_link:
applied_at = _iso_or_none(row.get("received_at"))
summary["applied_link_total"] += 1
provider_item["applied_link_total"] += 1
if summary.get("latest_applied_link_at") is None:
summary["latest_applied_link_at"] = applied_at
if provider_item.get("latest_applied_link_at") is None:
provider_item["latest_applied_link_at"] = applied_at
top_candidates.append(
{
"provider": provider,
@@ -1696,19 +1726,40 @@ async def _fetch_source_correlation_summary(
"stage": str(event_context.get("stage") or ""),
"score": best_match["score"],
"match_type": "direct" if best_match["is_direct"] else "candidate",
"link_state": (
"applied"
if is_applied_link
else "direct_ref"
if best_match["is_direct"]
else "candidate"
),
"verification_status": (
"applied_link_verified"
if is_applied_link
else "direct_ref_verified"
if best_match["is_direct"]
else "candidate_only"
),
"reasons": best_match["reasons"],
"received_at": _iso_or_none(row.get("received_at")),
}
)
if summary["direct_ref_total"] > 0:
if summary["applied_link_total"] > 0:
summary["status"] = "linked"
summary["verification_status"] = "applied_link_verified"
summary["missing_reason"] = None
elif summary["direct_ref_total"] > 0:
summary["status"] = "linked"
summary["verification_status"] = "direct_ref_verified"
summary["missing_reason"] = None
elif summary["candidate_total"] > 0:
summary["status"] = "candidate_found"
summary["verification_status"] = "candidate_only"
summary["missing_reason"] = None
elif any(item.get("latest_heartbeat_at") for item in providers.values()):
summary["status"] = "provider_fresh_no_match"
summary["verification_status"] = "provider_fresh_no_match"
summary["missing_reason"] = "provider_heartbeat_present_but_no_incident_match"
summary["top_candidates"] = sorted(