fix(sre): verify DR scorecard RAG writeback
This commit is contained in:
@@ -31,6 +31,8 @@ from src.services.agent99_controlled_dispatch_ledger import (
|
||||
validate_agent99_outcome_identity,
|
||||
)
|
||||
from src.services.agent99_public_receipts import (
|
||||
AGENT99_BACKUP_REQUIRED_VERIFIER_EVIDENCE_REFS,
|
||||
AGENT99_REQUIRED_VERIFIER_EVIDENCE_REFS,
|
||||
extract_agent99_outcome_evidence_refs,
|
||||
sanitize_agent99_public_receipt_refs,
|
||||
)
|
||||
@@ -749,8 +751,19 @@ async def _ensure_dr_scorecard(
|
||||
) -> str | None:
|
||||
if "backup_health" not in identity.route_id:
|
||||
return "not_required"
|
||||
required_refs = (
|
||||
AGENT99_REQUIRED_VERIFIER_EVIDENCE_REFS
|
||||
| AGENT99_BACKUP_REQUIRED_VERIFIER_EVIDENCE_REFS
|
||||
)
|
||||
safe_refs = sanitize_agent99_public_receipt_refs(
|
||||
evidence_refs,
|
||||
allowed_keys=required_refs,
|
||||
)
|
||||
if not required_refs.issubset(safe_refs):
|
||||
return None
|
||||
try:
|
||||
entry = await get_knowledge_service().create_entry(
|
||||
knowledge = get_knowledge_service()
|
||||
entry = await knowledge.create_entry(
|
||||
KnowledgeEntryCreate(
|
||||
title=f"DR scorecard {identity.incident_id}",
|
||||
content=(
|
||||
@@ -758,7 +771,7 @@ async def _ensure_dr_scorecard(
|
||||
"restore-drill, and source-resolution receipts. "
|
||||
+ "; ".join(
|
||||
f"{key}={value}"
|
||||
for key, value in sorted(evidence_refs.items())
|
||||
for key, value in sorted(safe_refs.items())
|
||||
)
|
||||
),
|
||||
entry_type=EntryType.BEST_PRACTICE,
|
||||
@@ -777,8 +790,17 @@ async def _ensure_dr_scorecard(
|
||||
created_by="agent99_controlled_dispatch_reconciler",
|
||||
),
|
||||
project_id=identity.project_id,
|
||||
schedule_embedding=False,
|
||||
)
|
||||
return f"knowledge_entries:{entry.id}:dr_scorecard"
|
||||
embedded = await knowledge.ensure_entry_embedding(
|
||||
entry.id,
|
||||
entry.title,
|
||||
entry.content,
|
||||
project_id=identity.project_id,
|
||||
)
|
||||
if not embedded:
|
||||
return None
|
||||
return f"knowledge_entries:{entry.id}:dr_scorecard_embedding_verified"
|
||||
except Exception as exc:
|
||||
logger.warning(
|
||||
"agent99_dr_scorecard_writeback_failed",
|
||||
|
||||
@@ -189,6 +189,66 @@ async def test_backup_mcp_ack_requires_dr_scorecard_binding() -> None:
|
||||
assert receipt is None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_dr_scorecard_ack_requires_complete_safe_refs_and_rag_embedding(
|
||||
monkeypatch,
|
||||
) -> None:
|
||||
identity = build_agent99_dispatch_identity(
|
||||
project_id="awoooi",
|
||||
incident_id="INC-20260719-DR-RAG",
|
||||
source_fingerprint="backup-dr-rag-fingerprint",
|
||||
route_id="agent99:backup_health:BackupCheck",
|
||||
)
|
||||
created = []
|
||||
|
||||
class Knowledge:
|
||||
async def create_entry(self, request, **kwargs): # type: ignore[no-untyped-def]
|
||||
created.append((request, kwargs))
|
||||
return SimpleNamespace(
|
||||
id="00000000-0000-0000-0000-0000000000dr",
|
||||
title=request.title,
|
||||
content=request.content,
|
||||
)
|
||||
|
||||
async def ensure_entry_embedding(
|
||||
self, *_args, **_kwargs
|
||||
): # type: ignore[no-untyped-def]
|
||||
return True
|
||||
|
||||
monkeypatch.setattr(job, "get_knowledge_service", lambda: Knowledge())
|
||||
complete_refs = {
|
||||
"agent99_outcome_receipt_id": "agent99:outcome:1",
|
||||
"post_verifier_evidence_ref": "verifier:1",
|
||||
"source_event_evidence_ref": "source:1",
|
||||
"backup_status_evidence_ref": "backup:1",
|
||||
"freshness_evidence_ref": "freshness:1",
|
||||
"offsite_verify_evidence_ref": "offsite:1",
|
||||
"escrow_evidence_ref": "escrow:1",
|
||||
"restore_drill_evidence_ref": "restore:1",
|
||||
"source_resolution_receipt_ref": "resolution:1",
|
||||
}
|
||||
|
||||
missing = await job._ensure_dr_scorecard(
|
||||
identity,
|
||||
evidence_refs={"backup_status_evidence_ref": "backup:1"},
|
||||
)
|
||||
receipt = await job._ensure_dr_scorecard(
|
||||
identity,
|
||||
evidence_refs={**complete_refs, "unsafe": "secret=value"},
|
||||
)
|
||||
|
||||
assert missing is None
|
||||
assert receipt == (
|
||||
"knowledge_entries:00000000-0000-0000-0000-0000000000dr:"
|
||||
"dr_scorecard_embedding_verified"
|
||||
)
|
||||
assert len(created) == 1
|
||||
request, kwargs = created[0]
|
||||
assert kwargs["schedule_embedding"] is False
|
||||
assert "unsafe" not in request.content
|
||||
assert all(value in request.content for value in complete_refs.values())
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_backup_telegram_ack_is_no_write_lifecycle_not_apply(
|
||||
monkeypatch,
|
||||
|
||||
Reference in New Issue
Block a user