diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c0e2cf..bd63013 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,7 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `list_media_files()` and `get_media_file()` accept `source="dynamic"` or `source="url_analysis"`. The parameter is omitted from the request when unset. - `MediaFile.kind` reports `"video"`, `"screenshot"`, or `None`. -- `UrlAnalysisResponse` carries the scoring fields: `verdict_state`, `threat_score`, +- `UrlAnalysisResponse` carries the scoring fields: `threat_score`, `risk_level`, `privacy_score`, `privacy_risk_level`, `privacy_breakdown`, `verdict_provenance`, `impersonation_target`, `completeness`, `intel_detections`, `metafields`, and `scored_at`. Each is `None` or empty until scoring finishes. diff --git a/README.md b/README.md index 48858a3..b2d90a5 100644 --- a/README.md +++ b/README.md @@ -131,7 +131,7 @@ Session control: concurrent-submission quota. Scoring fields (`threat_score`, `risk_level`, `privacy_score`, `privacy_risk_level`, -`privacy_breakdown`, `verdict_state`, `verdict_provenance`, `impersonation_target`, +`privacy_breakdown`, `verdict_provenance`, `impersonation_target`, `completeness`, `intel_detections`, `metafields`, `scored_at`) are `None` or empty until scoring finishes. Read them after the report reaches `completed`. diff --git a/docs/TYPES.md b/docs/TYPES.md index 532e904..0be6b65 100644 --- a/docs/TYPES.md +++ b/docs/TYPES.md @@ -134,7 +134,7 @@ peer report type to dynamic/static/cdr — it is guarded separately by | Type | Purpose | |------|---------| -| `UrlAnalysisResponse` | Top-level report: `level`, `status`, `general_info`, `screenshot`, optional `ip_info`, `dns_records`, optional `whois`, optional `ssl_certificate`, optional `response_headers`, optional `extracted_file`, optional `threat_analysis`, `pages`, plus the scoring fields `verdict_state`, `threat_score`, `risk_level`, `privacy_score`, `privacy_risk_level`, `privacy_breakdown`, `verdict_provenance`, `impersonation_target`, `completeness`, `intel_detections`, `metafields`, `scored_at`. | +| `UrlAnalysisResponse` | Top-level report: `level`, `status`, `general_info`, `screenshot`, optional `ip_info`, `dns_records`, optional `whois`, optional `ssl_certificate`, optional `response_headers`, optional `extracted_file`, optional `threat_analysis`, `pages`, plus the scoring fields `threat_score`, `risk_level`, `privacy_score`, `privacy_risk_level`, `privacy_breakdown`, `verdict_provenance`, `impersonation_target`, `completeness`, `intel_detections`, `metafields`, `scored_at`. | | `UrlAnalysisGeneralInfo` | `{url, domain, website_title}`. | | `UrlAnalysisScreenshot` | `{available: bool}`. Fetch actual bytes with `client.get_screenshot(uuid)`. | | `UrlAnalysisIpInfo` | `{ip, asn, city, country, isp, organization, threat_status}`. | diff --git a/src/threatzone/testing/_responses.py b/src/threatzone/testing/_responses.py index 9b312fa..1819bf1 100644 --- a/src/threatzone/testing/_responses.py +++ b/src/threatzone/testing/_responses.py @@ -781,7 +781,6 @@ def build_url_analysis_response(state: SubmissionState) -> UrlAnalysisResponse: "threatDetails": [], }, "pages": [state.final_url] if state.final_url else [target_url], - "verdictState": "final" if state.current_status() == "completed" else "provisional", "threatScore": _THREAT_SCORE_BY_LEVEL[state.level], "riskLevel": _RISK_LEVEL_BY_LEVEL[state.level], "privacyScore": 35, diff --git a/src/threatzone/types/url_analysis.py b/src/threatzone/types/url_analysis.py index ab70193..b6ab0ae 100644 --- a/src/threatzone/types/url_analysis.py +++ b/src/threatzone/types/url_analysis.py @@ -243,7 +243,6 @@ class UrlAnalysisResponse(BaseModel): extracted_file: UrlAnalysisExtractedFile | None = Field(default=None, alias="extractedFile") threat_analysis: UrlAnalysisThreatAnalysis | None = Field(default=None, alias="threatAnalysis") pages: list[str] - verdict_state: str | None = Field(default=None, alias="verdictState") threat_score: int | None = Field(default=None, alias="threatScore") risk_level: str | None = Field(default=None, alias="riskLevel") privacy_score: int | None = Field(default=None, alias="privacyScore") diff --git a/tests/conftest.py b/tests/conftest.py index 437dfb1..d8fd656 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -874,7 +874,6 @@ def sample_url_analysis_response() -> dict[str, Any]: "threatDetails": [{"source": "intel-1", "details": {"family": "EvilKit"}}], }, "pages": ["https://evil.com/login"], - "verdictState": "final", "threatScore": 72, "riskLevel": "High", "privacyScore": 35, diff --git a/tests/test_types.py b/tests/test_types.py index 9a289a8..d4272eb 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -714,7 +714,6 @@ def test_url_analysis_response_keeps_the_scoring_fields( report = UrlAnalysisResponse.model_validate(sample_url_analysis_response) assert report.threat_score == 72 assert report.risk_level == "High" - assert report.verdict_state == "final" assert report.privacy_score == 35 assert report.privacy_risk_level == "Medium" assert report.privacy_breakdown is not None