{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/ismalicious-com/json-schema/ismalicious-com-check-response-schema.json",
  "title": "CheckResponse",
  "description": "Main threat analysis response (`domain/check_pipeline.rs::assemble_check_json`;\nfor hashes `api/check_core.rs::check_hash_json`; for email addresses and\nphone numbers `domain/contact_indicators`).\n\nOnly `malicious`, `apiVersion`, `enrichmentLevel`, `dataTrust`,\n`evidence` and the three document stamps (`firstSeen`, `lastSeen`,\n`lastUpdated` — nullable) are present on every entity response.\nEverything else depends on the\nquery (with no target at all, a minimal body is returned), the entity type\n(hash responses carry `hashInfo`/`knownGood`, never `geo`/`whois`), the\nenrichment level (`riskScore`, `confidence`, `classification` and the\ncross-correlation block need `standard`+; `timeline` and\n`relatedInfrastructure` need `full`) and on what the dataset holds for the\nentity.\n\n`geo`, `whois`, `certificates`, `vulnerabilities` and `dns` are **raw\nupstream payloads** cached as-is — their shape follows the source\n(ip-api, WHOIS, crt.sh, Shodan InternetDB, DoH), not a schema this API\ncontrols. `certificates` keeps crt.sh's row shape but is normalised (see\nthe field). Feed-ingested hash documents additionally pass their raw\nfields through at the top level (e.g. `malwareFamily`, `firstSeen`,\n`categories`).\n\nThis endpoint never contacts the target: it reads the dataset and the\ncaches the report stream filled. Only `/check/stream` and\n`/check/certificates` open a connection to the target (a TLS handshake on\nport 443, no HTTP request).\n\nAn **email address** or a **phone number** answers from the dataset only\n— no live lookup at any enrichment level — with `type`, `entity`,\n`lookupStatus` (`found` | `unknown`), `verdict`, `recommendedAction`,\n`reasons`, `categories`, `riskScore` and an `email` or `phone` block next\nto the common fields. Its `verdict` is `malicious`, `suspicious` or\n`unknown` and never `clean`: absence from the dataset is not evidence of\nsafety.",
  "x-generated": "2026-11-12",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/ismalicious-com-openapi.json#/components/schemas/CheckResponse",
  "type": "object",
  "required": [
    "malicious",
    "apiVersion",
    "enrichmentLevel",
    "dataTrust",
    "evidence"
  ],
  "properties": {
    "apiVersion": {
      "type": "string",
      "description": "API version"
    },
    "asnReputation": {
      "type": [
        "object",
        "null"
      ],
      "description": "ASN-level reputation (`standard`/`full`, when resolvable)"
    },
    "azureTenant": {
      "type": [
        "object",
        "null"
      ],
      "description": "Azure tenant details (cached enrichment)"
    },
    "blocklistHits": {
      "type": [
        "integer",
        "null"
      ],
      "format": "int64",
      "description": "Number of blocklist sources listing the entity",
      "minimum": 0
    },
    "blocklistListed": {
      "type": [
        "boolean",
        "null"
      ],
      "description": "Whether the entity appears on at least one enabled blocklist"
    },
    "categories": {
      "type": [
        "array",
        "null"
      ],
      "items": {
        "type": "string"
      },
      "description": "Categories claimed by the threat listings (email and phone queries);\nhash documents pass their stored `categories` through"
    },
    "certificateFacts": {
      "type": [
        "object",
        "null"
      ],
      "description": "The certificate section, each part naming its source and time:\n`status` (`found` | `none` | `unknown` | `pending` |\n`not_applicable`), `live` (what our own TLS handshake on port 443\nobserved — read from the cache here, never probed by this endpoint)\nand `ctHistory` (crt.sh: `status`, `via` http|postgres|stored,\n`fetchedAt`, `stale`, counts, `rows`, `error`). `none` is only ever\nsaid for a registrable domain with no current certificate logged and\nnothing observed live; a source that did not answer reads `unknown`."
    },
    "certificates": {
      "type": [
        "array",
        "null"
      ],
      "items": {
        "type": "object"
      },
      "description": "Certificate Transparency entries from crt.sh, in crt.sh's row shape\n(`not_before` / `not_after` without a timezone, UTC). Normalised: at\nmost 10 current certificates, newest first, or the 10 most recent\nexpired ones when none is current, with the precertificate/final\nduplicates removed — the full counts are in\n`certificateFacts.ctHistory` (`currentCount`, `totalSeen`). Never the\nlive certificate, never set for an IP. Omitted while crt.sh is\nswitched off."
    },
    "classification": {
      "oneOf": [
        {
          "type": "null"
        },
        {
          "$ref": "#/$defs/Classification",
          "description": "Threat classification (`standard`/`full` enrichment)"
        }
      ]
    },
    "confidence": {
      "oneOf": [
        {
          "type": "null"
        },
        {
          "$ref": "#/$defs/Confidence",
          "description": "Confidence score (`standard`/`full` enrichment)"
        }
      ]
    },
    "confidenceScore": {
      "type": [
        "number",
        "null"
      ],
      "format": "double",
      "description": "Hash queries only: ingestion confidence from the feed document (0-100)"
    },
    "crossCorrelation": {
      "type": [
        "object",
        "null"
      ],
      "description": "Cross-correlation signals across data facets (`standard`/`full`)"
    },
    "dataTrust": {
      "$ref": "#/$defs/DataTrustProfile",
      "description": "Data quality, freshness, source reliability, and provider agreement profile"
    },
    "delisted": {
      "type": [
        "boolean",
        "null"
      ],
      "description": "Present and `true` when the entity was delisted after review"
    },
    "dns": {
      "type": [
        "object",
        "null"
      ],
      "description": "Raw DNS snapshot (records, SPF/DMARC flags)"
    },
    "email": {
      "oneOf": [
        {
          "type": "null"
        },
        {
          "$ref": "#/$defs/EmailIndicator",
          "description": "Email queries only: the address, its domain and what the dataset holds\nabout that domain"
        }
      ]
    },
    "enrichmentLevel": {
      "type": "string",
      "description": "Enrichment level applied: `basic` | `standard` | `full` | `fast`"
    },
    "entity": {
      "type": [
        "string",
        "null"
      ],
      "description": "Email and phone queries only: what was looked up — the lowercased\naddress, or the E.164 number (its digits when no country could be told)"
    },
    "evidence": {
      "$ref": "#/$defs/SocEvidence",
      "description": "SOC verdict evidence, reasons, contradictions, and recommended action"
    },
    "firstSeen": {
      "type": [
        "string",
        "null"
      ],
      "description": "When the entity entered the dataset, or the feed's earliest\nobservation of it — RFC 3339 UTC (`2026-08-25T14:17:40Z`). Present at\nevery enrichment level; `null` when the stored document carries no\nstamp (an entity no feed has ever listed)"
    },
    "geo": {
      "type": [
        "object",
        "null"
      ],
      "description": "Raw geolocation payload (shape follows ip-api)"
    },
    "greynoise": {
      "type": [
        "object",
        "null"
      ],
      "description": "GreyNoise Community context for an IPv4 (`standard`/`full`), present\nonly when a report lookup has fetched it in the last three days —\nthis endpoint reads that answer and never calls GreyNoise itself.\n`{ source, fetchedAt, classification: benign|malicious|unknown,\nnoise, riot, name, link, lastSeen, tags }`. `riot: true` (a known\nbusiness service) and `benign` are context and never raise\n`riskScore`; `malicious` feeds its Context factor. Absent is \"no\nanswer\", never a clean verdict"
    },
    "hashInfo": {
      "oneOf": [
        {
          "type": "null"
        },
        {
          "$ref": "#/$defs/HashInfo",
          "description": "Hash queries only: what was looked up"
        }
      ]
    },
    "infrastructure": {
      "oneOf": [
        {
          "type": "null"
        },
        {
          "$ref": "#/$defs/InfrastructureAttribution",
          "description": "What the entity IS according to its non-threat listings — a cloud or\nCDN range, a Tor exit, a VPN egress, a DoH resolver, a crawler, an\nuptime monitor, a sinkhole, a known-good list. Present only when at\nleast one listing in `sources` is `infrastructure` / `policy` /\n`allowlist` class; such listings carry no verdict weight and are not\ncounted in `blocklistHits`"
        }
      ]
    },
    "intelOwl": {
      "type": [
        "object",
        "null"
      ],
      "description": "IntelOwl analyzer output (cached enrichment)"
    },
    "knownGood": {
      "type": [
        "boolean",
        "null"
      ],
      "description": "Hash queries only: present and `true` when the hash is NSRL-listed\nknown software"
    },
    "lastSeen": {
      "type": [
        "string",
        "null"
      ],
      "description": "Latest re-observation of the entity by a feed — RFC 3339 UTC. Present\nat every enrichment level; `null` when unknown"
    },
    "lastUpdated": {
      "type": [
        "string",
        "null"
      ],
      "description": "Last full refresh of the stored document at ingest — RFC 3339 UTC.\nPresent at every enrichment level; `null` when unknown"
    },
    "lookupQueued": {
      "type": [
        "boolean",
        "null"
      ],
      "description": "Hash queries only, next to `pending: [\"circl\"]`: `false` when nothing\nis running or queued for the hash — every background lookup slot was\ntaken — so nothing completes it in the background: the next check\nstarts the lookup. Absent otherwise (additive: a lookup is running,\nor queued to start once a slot frees)"
    },
    "lookupStatus": {
      "type": [
        "string",
        "null"
      ],
      "description": "Hash queries: `known` when a reputation source or NSRL match is\navailable, otherwise `unknown`. Email and phone queries: `found` when\nthe dataset holds a document for the address or number, otherwise\n`unknown`. Unknown is never positive evidence of safety."
    },
    "malicious": {
      "type": "boolean",
      "description": "Explicit or scanner-derived malicious detection for IPs/domains;\nhashes also include malware-feed matches. `false` is not a safety\nverdict. Consult `riskScore`, `evidence` and blocklist fields for the\noverall assessment, and `lookupStatus` for unknown hashes."
    },
    "microsoftTenant": {
      "type": [
        "boolean",
        "null"
      ],
      "description": "Whether the domain maps to a Microsoft/Azure tenant"
    },
    "mitre": {
      "type": [
        "object",
        "null"
      ],
      "description": "MITRE ATT&CK mapping for the classified categories (`standard`/`full`)"
    },
    "otx": {
      "type": [
        "object",
        "null"
      ],
      "description": "AlienVault OTX pulse context (`standard`/`full`)"
    },
    "pending": {
      "type": [
        "array",
        "null"
      ],
      "items": {
        "type": "string"
      },
      "description": "`fast` only: the facets the cache did not hold for this answer and\nthat are being fetched in the background — `dns`, `whois`, `geo`,\n`certificates` (the CT history of a public domain name), `otx` for an\nIP, a domain or a URL; `circl` for a hash\nwhose lookup outlived the request deadline, or found every lookup slot\nbusy until it and starts once one frees (`lookupStatus` then reads\n`unknown` for now, not a CIRCL miss) — unless `lookupQueued` is\n`false`. A re-check a few seconds later answers them from the cache.\nA facet no fetch can fill is not listed: one whose last fetch failed\nwithin the past five minutes, the geo and WHOIS of a private or\nreserved address. Absent when nothing is pending"
    },
    "phone": {
      "oneOf": [
        {
          "type": "null"
        },
        {
          "$ref": "#/$defs/PhoneIndicator",
          "description": "Phone queries only: the number as received and how it was resolved\nto E.164"
        }
      ]
    },
    "processingTime": {
      "type": [
        "integer",
        "null"
      ],
      "format": "int64",
      "description": "Server-side processing time in milliseconds (absent on the minimal\nno-target response)",
      "minimum": 0
    },
    "pwnedPassword": {
      "oneOf": [
        {
          "type": "null"
        },
        {
          "$ref": "#/$defs/PwnedPassword",
          "description": "Hash queries only: present when the digest is the SHA-1 (40 hex) or\nNTLM (32 hex) hash of a password seen in breaches"
        }
      ]
    },
    "ransomware": {
      "type": [
        "object",
        "null"
      ],
      "description": "Ransomware-group context, when the entity appears in ransomware feeds"
    },
    "reasons": {
      "type": [
        "array",
        "null"
      ],
      "items": {
        "type": "string"
      },
      "description": "Email and phone queries only: at most five short sentences stating the\nevidence behind `verdict`"
    },
    "recommendedAction": {
      "type": [
        "string",
        "null"
      ],
      "description": "Email and phone queries only: `block` (malicious) | `review`\n(suspicious) | `unverified` (unknown — nothing is known either way)"
    },
    "relatedInfrastructure": {
      "type": [
        "object",
        "null"
      ],
      "description": "Related infrastructure (`full` enrichment only)"
    },
    "reputation": {
      "type": [
        "object",
        "null"
      ],
      "description": "Aggregated detection counters (typically `malicious` / `suspicious` /\n`harmless` / `undetected`, sometimes `timeout`). May be `null` for\nunknown entities."
    },
    "riskScore": {
      "oneOf": [
        {
          "type": "null"
        },
        {
          "$ref": "#/$defs/RiskScore",
          "description": "Risk score (`standard`/`full` enrichment, and hash queries)"
        }
      ]
    },
    "similar_domains": {
      "type": [
        "object",
        "null"
      ],
      "description": "Lookalikes of the domain that the corpus lists — typosquats,\nhomoglyphs, the name on other TLDs or wrapped in phishing words — best\nfirst: `{ keywords, hits, total_hits, truncated, matches: [{ domain,\nfuzzer, threatLevel }] }`. `hits` holds the same names as `matches`."
    },
    "sources": {
      "type": [
        "array",
        "null"
      ],
      "items": {
        "type": "object"
      },
      "description": "Raw source rows from the feed corpus (name, url, category, … as\ningested). Each row may carry `threatClass` (`threat` when absent,\n`infrastructure`, `policy`, `allowlist`) and `fpRisk` (`low` when\nabsent, `medium`, `high`) copied from the feed registry"
    },
    "techStack": {
      "type": [
        "object",
        "null"
      ],
      "description": "Detected technology stack (cached enrichment)"
    },
    "timeline": {
      "type": [
        "object",
        "null"
      ],
      "description": "Detection timeline (`full` enrichment only)"
    },
    "type": {
      "type": [
        "string",
        "null"
      ],
      "description": "Email and phone queries only: `email` | `phone`"
    },
    "verdict": {
      "type": [
        "string",
        "null"
      ],
      "description": "Email and phone queries only: `malicious` | `suspicious` | `unknown`,\nnever `clean`"
    },
    "vulnerabilities": {
      "type": [
        "object",
        "null"
      ],
      "description": "Raw open-port / CVE payload (shape follows Shodan InternetDB:\n`cpes` / `hostnames` / `ip` / `ports` / `tags` / `vulns`)"
    },
    "whois": {
      "type": [
        "object",
        "null"
      ],
      "description": "Raw WHOIS payload (shape follows the WHOIS provider)"
    }
  },
  "$defs": {
    "Classification": {
      "type": "object",
      "description": "Classification of the entity\n(`enrichment/threat_classifier.rs::ThreatClassification`).",
      "required": [
        "primary",
        "secondary",
        "confidence",
        "indicators"
      ],
      "properties": {
        "confidence": {
          "type": "integer",
          "format": "int32",
          "description": "Classification confidence (0-100)",
          "minimum": 0
        },
        "indicators": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/ThreatIndicator"
          },
          "description": "Indicators behind the classification"
        },
        "primary": {
          "type": "string",
          "description": "Primary classification"
        },
        "secondary": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Secondary classifications"
        }
      }
    },
    "Confidence": {
      "type": "object",
      "description": "Confidence score with level and factors\n(`enrichment/confidence.rs::ConfidenceScore`).",
      "required": [
        "score",
        "level",
        "factors",
        "explanation"
      ],
      "properties": {
        "explanation": {
          "type": "string",
          "description": "One-line explanation of the confidence"
        },
        "factors": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/ConfidenceFactor"
          },
          "description": "Factors contributing to the confidence score"
        },
        "level": {
          "type": "string",
          "description": "Confidence level: `low` | `medium` | `high`"
        },
        "score": {
          "type": "integer",
          "format": "int32",
          "description": "Confidence score from 0-100",
          "maximum": 100,
          "minimum": 0
        }
      }
    },
    "ConfidenceFactor": {
      "type": "object",
      "description": "One weighted factor of the confidence score\n(`enrichment/confidence.rs::ConfidenceFactor`).",
      "required": [
        "name",
        "score",
        "weight",
        "contribution",
        "description"
      ],
      "properties": {
        "contribution": {
          "type": "number",
          "format": "double",
          "description": "Weighted contribution to the final score"
        },
        "description": {
          "type": "string",
          "description": "Human-readable explanation"
        },
        "name": {
          "type": "string",
          "description": "Factor name"
        },
        "score": {
          "type": "number",
          "format": "double",
          "description": "Raw factor score"
        },
        "weight": {
          "type": "number",
          "format": "double",
          "description": "Weight of this factor in the composite score"
        }
      }
    },
    "DataCompleteness": {
      "type": "object",
      "description": "Data completeness across expected enrichment facets",
      "required": [
        "score",
        "present",
        "missing"
      ],
      "properties": {
        "facetFreshness": {
          "type": "object",
          "description": "Age of each cached enrichment facet that carries a `fetchedAt`\n(`techStack`, `relatedInfrastructure`, `azureTenant`, `ransomware`,\n`intelOwl`, `timeline`), keyed by facet: `{ fetchedAt, freshness,\ndataAgeHours }`. An empty object when none is cached"
        },
        "missing": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "present": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "score": {
          "type": "integer",
          "format": "int32"
        }
      }
    },
    "DataTrustCertificates": {
      "type": "object",
      "description": "The certificate facet of a domain's Data Trust profile: the summary of\n`certificateFacts`, and which source said so.",
      "required": [
        "state"
      ],
      "properties": {
        "source": {
          "type": [
            "string",
            "null"
          ],
          "description": "`tls` (our own handshake on port 443), `crt.sh` (Certificate\nTransparency), `stored` (the CT rows a previous lookup stored), or\n`null` when no source answered"
        },
        "state": {
          "type": "string",
          "description": "`found`, `none` (CT logs no current certificate for this registrable\ndomain and nothing was observed live), `unknown` (no source answered:\nnever read it as `none`), `pending` (report stream only, before the\nCT lookup lands) or `not_applicable` (an IP, an invalid name)"
        }
      }
    },
    "DataTrustProfile": {
      "type": "object",
      "description": "Data Trust profile attached to check responses",
      "required": [
        "observedAt",
        "freshness",
        "sourceAgreement",
        "sources",
        "completeness",
        "providerAgreement"
      ],
      "properties": {
        "certificates": {
          "oneOf": [
            {
              "type": "null"
            },
            {
              "$ref": "#/$defs/DataTrustCertificates",
              "description": "Domains only: the certificate facet's state and source"
            }
          ]
        },
        "completeness": {
          "$ref": "#/$defs/DataCompleteness"
        },
        "dataAgeHours": {
          "type": [
            "number",
            "null"
          ],
          "format": "double"
        },
        "firstSeen": {
          "type": [
            "string",
            "null"
          ]
        },
        "freshness": {
          "type": "string"
        },
        "lastSeen": {
          "type": [
            "string",
            "null"
          ]
        },
        "lastUpdated": {
          "type": [
            "string",
            "null"
          ]
        },
        "observedAt": {
          "type": "string"
        },
        "providerAgreement": {
          "$ref": "#/$defs/ProviderAgreement"
        },
        "sourceAgreement": {
          "$ref": "#/$defs/SourceAgreement"
        },
        "sources": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/DataTrustSource"
          }
        }
      }
    },
    "DataTrustSource": {
      "type": "object",
      "description": "Source entry with reliability metadata",
      "required": [
        "name",
        "type",
        "reliability",
        "reliabilityLevel",
        "noiseProfile"
      ],
      "properties": {
        "category": {
          "type": [
            "string",
            "null"
          ]
        },
        "name": {
          "type": "string"
        },
        "noiseProfile": {
          "$ref": "#/$defs/NoiseProfile"
        },
        "reliability": {
          "type": "number",
          "format": "double"
        },
        "reliabilityLevel": {
          "$ref": "#/$defs/ReliabilityLevel"
        },
        "type": {
          "type": "string"
        },
        "url": {
          "type": [
            "string",
            "null"
          ]
        }
      }
    },
    "EmailDomainReputation": {
      "type": "object",
      "description": "What the dataset holds about the sender domain.",
      "required": [
        "lookupStatus",
        "malicious",
        "blocklistHits",
        "sources",
        "infrastructure"
      ],
      "properties": {
        "blocklistHits": {
          "type": "integer",
          "description": "Threat-class listings on the domain",
          "minimum": 0
        },
        "delisted": {
          "type": [
            "boolean",
            "null"
          ],
          "description": "Present and `true` when a delisting cleared the domain's listings"
        },
        "infrastructure": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Attributes of the domain's non-threat listings (`disposable-email`, …)"
        },
        "lookupStatus": {
          "type": "string",
          "description": "`found` when a document exists for the domain, else `unknown`"
        },
        "malicious": {
          "type": "boolean",
          "description": "The domain is malicious by the same evidence `/check` reads for it"
        },
        "sources": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Names of those listings, at most 10"
        }
      }
    },
    "EmailIndicator": {
      "type": "object",
      "description": "The `email` block of a contact body.",
      "required": [
        "address",
        "localPart",
        "domain",
        "disposable",
        "freeProvider",
        "domainReputation"
      ],
      "properties": {
        "address": {
          "type": "string",
          "description": "The address as looked up: trimmed, lowercased"
        },
        "disposable": {
          "type": "boolean",
          "description": "The domain is a disposable-mail provider: a disposable-email listing\nfrom a list that is not an aggregate of other lists. Never `true` for\na shared mail provider"
        },
        "domain": {
          "type": "string"
        },
        "domainReputation": {
          "$ref": "#/$defs/EmailDomainReputation"
        },
        "freeProvider": {
          "type": "boolean",
          "description": "The domain is a consumer or shared mail provider: its reputation is\nnever propagated to the address"
        },
        "localPart": {
          "type": "string"
        },
        "mx": {
          "type": [
            "boolean",
            "null"
          ],
          "description": "The domain publishes MX hosts (`true`), publishes a null MX — it\naccepts no mail (`false`), or no cached answer settles it (`null`: no\ncached DNS answer, or an empty MX answer, which a failed lookup also\ngives) — this path never resolves"
        }
      }
    },
    "EvidenceConfidence": {
      "type": "object",
      "description": "Confidence excerpt included in SOC evidence",
      "required": [
        "score",
        "level"
      ],
      "properties": {
        "level": {
          "type": "string"
        },
        "score": {
          "type": "integer",
          "format": "int32"
        }
      }
    },
    "EvidenceSourceSummary": {
      "type": "object",
      "description": "Source summary included in SOC evidence",
      "required": [
        "count",
        "weightedStrength",
        "highReliabilityCount",
        "noiseWarnings"
      ],
      "properties": {
        "count": {
          "type": "integer",
          "format": "int32"
        },
        "highReliabilityCount": {
          "type": "integer",
          "format": "int32"
        },
        "noiseWarnings": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "weightedStrength": {
          "type": "number",
          "format": "double"
        }
      }
    },
    "HashInfo": {
      "type": "object",
      "description": "Identity of the hash that was looked up (hash queries only).\n\nFeed-ingested hash documents pass extra file metadata through alongside\nthese fields (file names, sizes, signatures — shape follows the source\nfeed), so treat this object as open.",
      "required": [
        "hashType",
        "hash"
      ],
      "properties": {
        "hash": {
          "type": "string",
          "description": "The hash as queried"
        },
        "hashType": {
          "type": "string",
          "description": "`md5` | `sha1` | `sha256` | `unknown`"
        },
        "nsrl": {
          "type": [
            "boolean",
            "null"
          ],
          "description": "Present and `true` when the hash is in the NSRL known-software corpus"
        }
      }
    },
    "InfrastructureAttribution": {
      "type": "object",
      "description": "What the entity IS, according to the listings that describe rather than\naccuse it. Present on a response only when at least one such listing\nexists on the document.",
      "required": [
        "attributes",
        "sources"
      ],
      "properties": {
        "attributes": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Distinct, sorted attributes drawn from the vocabulary: `tor-exit`,\n`vpn`, `proxy`, `doh-resolver`, `dns-resolver`, `sinkhole`, `cloud`,\n`cdn`, `crawler`, `scanner`, `monitoring`, `disposable-email`,\n`dynamic-dns`, `url-shortener`, `bogon`, `saas`, `allowlist`"
        },
        "sources": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/InfrastructureSource"
          },
          "description": "The non-threat listings the attributes were derived from"
        }
      }
    },
    "InfrastructureSource": {
      "type": "object",
      "description": "One non-threat listing behind the attribution.",
      "required": [
        "name",
        "threatClass"
      ],
      "properties": {
        "category": {
          "type": [
            "string",
            "null"
          ],
          "description": "The listing's primary category, as ingested"
        },
        "id": {
          "type": [
            "string",
            "null"
          ],
          "description": "Registry id of the feed (absent on legacy listings written before ids)"
        },
        "name": {
          "type": "string",
          "description": "Feed name as stored on the listing"
        },
        "threatClass": {
          "type": "string",
          "description": "`infrastructure` | `policy` | `allowlist` — never `threat` here"
        }
      }
    },
    "NoiseProfile": {
      "type": "string",
      "description": "Operational noise profile for a source",
      "enum": [
        "authoritative",
        "contextual",
        "noisy"
      ]
    },
    "PhoneIndicator": {
      "type": "object",
      "description": "The `phone` block of a contact body.",
      "required": [
        "input",
        "resolvedWith"
      ],
      "properties": {
        "countryCallingCode": {
          "type": [
            "string",
            "null"
          ],
          "description": "Country calling code, without `+`, when known"
        },
        "e164": {
          "type": [
            "string",
            "null"
          ],
          "description": "The number in E.164 form, `null` when no country could be told"
        },
        "input": {
          "type": "string",
          "description": "The query as received, trimmed; a `tel:` / `sms:` / `callto:` scheme\nand its parameters removed"
        },
        "resolvedWith": {
          "type": "string",
          "description": "`e164` (written internationally) | `country` (the `country=` hint) |\n`nanp-guess` (read as North American, no hint) | `digits` (no\ncountry could be told)"
        }
      }
    },
    "ProviderAgreement": {
      "type": "object",
      "description": "Provider agreement summary from cross-correlation signals",
      "required": [
        "status",
        "summary",
        "contradictorySignals"
      ],
      "properties": {
        "contradictorySignals": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/ProviderContradictorySignal"
          }
        },
        "status": {
          "type": "string"
        },
        "summary": {
          "type": "string"
        }
      }
    },
    "ProviderContradictorySignal": {
      "type": "object",
      "description": "Contradictory provider signal included in SOC evidence",
      "required": [
        "type",
        "severity",
        "title",
        "description"
      ],
      "properties": {
        "description": {
          "type": "string"
        },
        "severity": {
          "type": "string"
        },
        "title": {
          "type": "string"
        },
        "type": {
          "type": "string"
        }
      }
    },
    "PwnedPassword": {
      "type": "object",
      "description": "A queried digest that is the SHA-1 or NTLM hash of a breached password\n(hash queries only). Beside the file verdict, never part of it: no\nlisting in `sources`, no effect on `riskScore` or `lookupStatus`.",
      "required": [
        "found",
        "hashType",
        "count",
        "source",
        "sourceUrl"
      ],
      "properties": {
        "corpusUpdatedAt": {
          "type": [
            "string",
            "null"
          ],
          "description": "When the local copy of the corpus was downloaded"
        },
        "count": {
          "type": "integer",
          "format": "int64",
          "description": "Times the password appears in the breach corpus",
          "minimum": 0
        },
        "found": {
          "type": "boolean",
          "description": "Always `true`: the block is absent when the digest was never seen"
        },
        "hashType": {
          "type": "string",
          "description": "`sha1` for a 40-hex query, `ntlm` for a 32-hex one (the same shape as\nMD5, which `hashInfo.hashType` reports)"
        },
        "source": {
          "type": "string"
        },
        "sourceUrl": {
          "type": "string"
        }
      }
    },
    "ReliabilityLevel": {
      "type": "string",
      "description": "Source reliability level used by Data Trust evidence",
      "enum": [
        "high",
        "medium",
        "low"
      ]
    },
    "RiskFactor": {
      "type": "object",
      "description": "One weighted factor of the risk score\n(`enrichment/risk_scorer.rs::RiskFactor`).",
      "required": [
        "name",
        "weight",
        "score",
        "contribution",
        "description"
      ],
      "properties": {
        "contribution": {
          "type": "number",
          "format": "double",
          "description": "Weighted contribution to the final score"
        },
        "description": {
          "type": "string",
          "description": "Human-readable explanation"
        },
        "name": {
          "type": "string",
          "description": "Factor name"
        },
        "score": {
          "type": "number",
          "format": "double",
          "description": "Raw factor score (0-100, higher = riskier)"
        },
        "weight": {
          "type": "number",
          "format": "double",
          "description": "Weight of this factor in the composite score"
        }
      }
    },
    "RiskScore": {
      "type": "object",
      "description": "Risk score with level and contributing factors\n(`enrichment/risk_scorer.rs::RiskScore`).",
      "required": [
        "score",
        "level",
        "factors",
        "summary"
      ],
      "properties": {
        "factors": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/RiskFactor"
          },
          "description": "Factors contributing to the risk score"
        },
        "level": {
          "type": "string",
          "description": "Risk level: `safe` | `low` | `medium` | `high` | `critical` |\n`inconclusive`. `inconclusive` means too little evidence for a\nverdict — including every hash with `lookupStatus: \"unknown\"` — and is\nnever a safety verdict."
        },
        "score": {
          "type": "integer",
          "format": "int32",
          "description": "Risk score from 0-100 (higher = riskier)",
          "maximum": 100,
          "minimum": 0
        },
        "summary": {
          "type": "string",
          "description": "One-line summary of the verdict"
        }
      }
    },
    "SocEvidence": {
      "type": "object",
      "description": "SOC-ready verdict evidence attached to check responses",
      "required": [
        "verdict",
        "observedAt",
        "reasons",
        "contradictorySignals",
        "sourceSummary",
        "freshness",
        "recommendedAction",
        "analystStatus"
      ],
      "properties": {
        "analystStatus": {
          "type": "string"
        },
        "confidence": {
          "oneOf": [
            {
              "type": "null"
            },
            {
              "$ref": "#/$defs/EvidenceConfidence"
            }
          ]
        },
        "contradictorySignals": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/ProviderContradictorySignal"
          }
        },
        "dataAgeHours": {
          "type": [
            "number",
            "null"
          ],
          "format": "double"
        },
        "freshness": {
          "type": "string"
        },
        "observedAt": {
          "type": "string"
        },
        "reasons": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "recommendedAction": {
          "type": "string"
        },
        "score": {
          "type": [
            "integer",
            "null"
          ],
          "format": "int32"
        },
        "sourceSummary": {
          "$ref": "#/$defs/EvidenceSourceSummary"
        },
        "verdict": {
          "type": "string"
        }
      }
    },
    "SourceAgreement": {
      "type": "object",
      "description": "Source agreement summary across blocklists and scanners",
      "required": [
        "count",
        "weightedStrength",
        "level",
        "scannerDetections",
        "scannerSuspicious",
        "scannerClean"
      ],
      "properties": {
        "count": {
          "type": "integer",
          "format": "int32"
        },
        "level": {
          "type": "string"
        },
        "scannerClean": {
          "type": "integer",
          "format": "int32"
        },
        "scannerDetections": {
          "type": "integer",
          "format": "int32"
        },
        "scannerSuspicious": {
          "type": "integer",
          "format": "int32"
        },
        "weightedStrength": {
          "type": "number",
          "format": "double"
        }
      }
    },
    "ThreatIndicator": {
      "type": "object",
      "description": "One indicator behind the threat classification\n(`enrichment/threat_classifier.rs::ThreatIndicator`).",
      "required": [
        "type",
        "category",
        "description",
        "weight"
      ],
      "properties": {
        "category": {
          "type": "string",
          "description": "Threat category this indicator points to"
        },
        "description": {
          "type": "string",
          "description": "Human-readable explanation"
        },
        "type": {
          "type": "string",
          "description": "Indicator type"
        },
        "weight": {
          "type": "number",
          "format": "double",
          "description": "Weight of this indicator"
        }
      }
    }
  }
}