"""Generate response and signed webhook examples from provider serializers.""" import argparse import asyncio import json from datetime import UTC, datetime from pathlib import Path import httpx from ai_platform.infrastructure.webhook import OmniWebhook from ai_platform.lead_scoring.application.notifications import Notification from ai_platform.lead_scoring.application.repository import ScoringRunRecord from ai_platform.lead_scoring.application.run_use_cases import to_run_detail from ai_platform.lead_scoring.application.scoring import calculate_run from ai_platform.presentation.http.routes import to_detail_json, to_json from ai_platform.presentation.http.run_responses import RunDetail, RunSummary from ai_platform.presentation.http.schemas import RunRequest FIXTURES = Path(__file__).resolve().parents[1] / "contracts/lead-scoring/v2/fixtures" NOW = datetime(2026, 9, 28, tzinfo=UTC) SECRET = "test-only-webhook-secret-32-characters-long" RUN_ID = "22222222-2222-4222-8222-222222222222" EVENT_ID = "11111111-1111-4111-8111-111111111111" def write_json(name: str, value: dict, *, check: bool) -> None: path = FIXTURES / name expected = json.dumps(value, ensure_ascii=False, indent=2) + "\n" if check: if not path.exists() or path.read_text() != expected: raise SystemExit(f"Contract fixture drift: {name}; regenerate provider examples") else: path.write_text(expected) async def main(*, check: bool = False) -> None: request = RunRequest.model_validate_json( (FIXTURES / "run-request.json").read_text() ).model_dump(mode="json") rule_score, breakdown = calculate_run(request) row = ScoringRunRecord( id=RUN_ID, request_id=request["request_id"], app_id="omni-local", account_id=request["account_id"], status="completed", fingerprint="0" * 64, profile_version="profile-example", request=request, rule_score=rule_score, ai_score=None, final_score=rule_score, degraded=False, result_mode="rules_only", error_code=None, breakdown=breakdown, created_at=NOW, completed_at=NOW, ai_confidence=None, ai_reasoning=None, ai_evidence=None, ) write_json( "run-summary.json", RunSummary.model_validate(to_json(row)).model_dump(mode="json"), check=check, ) write_json( "run-detail.json", RunDetail.model_validate(to_detail_json(to_run_detail(row))).model_dump(mode="json"), check=check, ) event = Notification( EVENT_ID, RUN_ID, row.app_id, row.account_id, row.request_id, "completed", NOW, 0 ) def capture(request: httpx.Request) -> httpx.Response: write_json( "webhook-delivery.json", { "method": request.method, "content_type": request.headers["Content-Type"], "timestamp": request.headers["X-Webhook-Timestamp"], "body": request.content.decode(), "signature": request.headers["X-Webhook-Signature"], }, check=check, ) return httpx.Response(202) async with httpx.AsyncClient(transport=httpx.MockTransport(capture)) as client: assert await OmniWebhook( client, "https://omni.example.invalid/events", SECRET, lambda: NOW ).send(event) if __name__ == "__main__": parser = argparse.ArgumentParser(description=__doc__) parser.add_argument( "--check", action="store_true", help="Reject drift without writing artifacts" ) asyncio.run(main(check=parser.parse_args().check))