The PDF host (free-justice.openapi.gov.il) requires the same x-client-id
header as the search API, so a normal browser click on the URL fails.
This tool carries the auth header automatically and saves the PDF to a
configurable local directory.
Safety properties:
- SSRF guard: only download from free-justice.openapi.gov.il and
pub-justice.openapi.gov.il.
- Path-traversal guard: filename is reduced to its basename; arbitrary
paths are stripped.
- Content-type guard: rejects 200-OK responses whose body is not a real
PDF (gateway sometimes returns JSON-error 200s).
- Atomic write via .tmp + rename so partial downloads never replace the
cached copy.
- Caches by destination path; re-downloads are no-ops unless overwrite=True.
DECISIVE_APPRAISER_DOWNLOAD_DIR env var configures the output dir
(default: ./downloads/decisive_appraisals). 6 new unit tests cover the
happy path, caching, and all four guards. End-to-end live test confirmed
a 1.4MB real PDF lands on disk with valid `%PDF-1.7` header.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a new MCP tool `search_decisive_appraisals` that queries the
Ministry of Justice public registry (~30K published decisions) by
block (גוש), plot (חלקה), appraiser name, committee, decision/publicity
date ranges, or free text — and returns metadata + direct PDF URLs.
Implementation notes:
- New `nadlan_mcp/govil/` package, parallel to `nadlan_mcp/govmap/`,
for gov.il APIs that are not Govmap. Pydantic v2 models match the
upstream PascalCase response via aliases.
- Upstream sits behind an F5 WAF that rejects standard `requests`;
uses `curl_cffi` with Chrome 120 impersonation to traverse it.
- Static `x-client-id` header (issued to the gov.il SPA, public, visible
in any DevTools session) is required by the gateway — without it
every call returns a generic 500.
- 14 unit tests cover model parsing, body shape, pagination, and the
500-is-fatal contract (configuration error, not retryable).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>