File size: 3,723 Bytes
0633246
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
from __future__ import annotations

from typing import Any

from .evidence import make_evidence
from .http_client import get_json
from .models import EvidenceItem

NOMINATIM_REVERSE_URL = "https://nominatim.openstreetmap.org/reverse"


def reverse_geocode_site(lat: float, lon: float) -> tuple[dict[str, Any], list[EvidenceItem]]:
    """Return an OSM-derived address identity for the site anchor.

    This is intentionally treated as contextual identity, not official address
    verification. Nominatim public usage is kept to one generate-time reverse
    lookup instead of interactive autocomplete.
    """
    try:
        payload = get_json(
            NOMINATIM_REVERSE_URL,
            {
                "format": "jsonv2",
                "lat": lat,
                "lon": lon,
                "addressdetails": 1,
                "zoom": 18,
            },
            timeout=18,
        )
        address = payload.get("address") or {}
        identity = {
            "display_name": payload.get("display_name"),
            "road": address.get("road") or address.get("pedestrian") or address.get("path"),
            "neighbourhood": address.get("neighbourhood")
            or address.get("suburb")
            or address.get("quarter"),
            "city": address.get("city") or address.get("town") or address.get("village"),
            "district": address.get("county") or address.get("state_district"),
            "state": address.get("state"),
            "postcode": address.get("postcode"),
            "country": address.get("country"),
            "lat": lat,
            "lon": lon,
        }
        evidence = [
            make_evidence(
                category="Site identity",
                finding="Approximate address and administrative context were reverse-geocoded from the site anchor.",
                source_name="OpenStreetMap Nominatim",
                source_url="https://nominatim.org/release-docs/latest/api/Reverse/",
                source_type="open geocoding service",
                resolution_or_scope="single reverse-geocoding request at site anchor/centroid",
                confidence="medium" if identity.get("display_name") else "low",
                limitation="OSM-derived address context may be incomplete, approximate, or outdated. It is not legal address verification.",
                design_implication="Use this to label the site and organize studio research by street, city, state, and country.",
                verification_needed="Confirm final address and administrative names from project brief, faculty, client, or local records.",
                output_label="public_data",
            )
        ]
        return identity, evidence
    except Exception as exc:  # noqa: BLE001
        return {
            "display_name": None,
            "lat": lat,
            "lon": lon,
            "error": f"{type(exc).__name__}: {exc}",
        }, [
            make_evidence(
                category="Site identity",
                finding="Reverse-geocoded address could not be retrieved.",
                source_name="OpenStreetMap Nominatim",
                source_url="https://nominatim.org/release-docs/latest/api/Reverse/",
                source_type="open geocoding service",
                resolution_or_scope="not available",
                confidence="low",
                limitation=f"Reverse geocoder failed: {type(exc).__name__}.",
                design_implication="Do not infer street/city/state labels from missing geocoding data.",
                verification_needed="Enter address details manually from the project brief or site documents.",
                output_label="site_visit_required",
            )
        ]