cleanup: remove /api/offroute + /api/mvum handlers + lib/offroute/ package (extraction #8 shadow)

/api/offroute (POST) and /api/mvum (GET) are edge-shadowed since extraction #8
— navi-offroute :8428 serves both via nginx. Cleanup #4 removed the last
in-process consumer of lib/offroute/dem.py (netsyms_api._reverse_elevation +
the module-level _DEM = DEMReader()), so the entire 9-file lib/offroute/
package is now orphaned and goes with this PR.

- api.py: drop both handlers (api_offroute, api_mvum) + their section comments.
  Both used in-function lazy imports of offroute, so no top-of-file import
  survives.
- DELETE lib/offroute/ wholesale (__init__, router, mvum, cost, barriers, dem,
  friction, trails, prototype). prototype.py was already dead at runtime.

Closes the recon->navi navi-shadow cleanup loop: recon now serves zero navi-*
shadow routes.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
malice 2026-05-23 04:25:54 -06:00 committed by GitHub
commit 86c902f7b5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 0 additions and 4387 deletions

View file

@ -2553,214 +2553,3 @@ def api_auth_whoami():
'authenticated': False,
'username': None,
})
# ── OFFROUTE API ──
@app.route("/api/offroute", methods=["POST"])
def api_offroute():
"""
Off-network routing from wilderness to destination.
Request body:
{
"start": [lat, lon],
"end": [lat, lon],
"mode": "foot" | "mtb" | "atv", (default: "foot")
"boundary_mode": "strict" | "pragmatic" | "emergency" (default: "pragmatic")
}
Response:
{
"status": "ok",
"route": { GeoJSON FeatureCollection with wilderness + network segments },
"summary": { total_distance_km, total_effort_minutes, ... }
}
"""
try:
data = request.get_json()
if not data:
return jsonify({"status": "error", "message": "No JSON body provided"}), 400
# Parse coordinates
start = data.get("start")
end = data.get("end")
if not start or not end:
return jsonify({"status": "error", "message": "Missing start or end coordinates"}), 400
if not isinstance(start, (list, tuple)) or len(start) != 2:
return jsonify({"status": "error", "message": "start must be [lat, lon]"}), 400
if not isinstance(end, (list, tuple)) or len(end) != 2:
return jsonify({"status": "error", "message": "end must be [lat, lon]"}), 400
start_lat, start_lon = float(start[0]), float(start[1])
end_lat, end_lon = float(end[0]), float(end[1])
# Parse options
mode = data.get("mode", "foot")
if mode not in ("auto", "foot", "mtb", "atv", "vehicle"):
return jsonify({"status": "error", "message": "mode must be auto, foot, mtb, atv, or vehicle"}), 400
boundary_mode = data.get("boundary_mode", "pragmatic")
if boundary_mode not in ("strict", "pragmatic", "emergency"):
return jsonify({"status": "error", "message": "boundary_mode must be strict, pragmatic, or emergency"}), 400
# Import and run router
from .offroute.router import OffrouteRouter
router = OffrouteRouter()
try:
result = router.route(
start_lat=start_lat,
start_lon=start_lon,
end_lat=end_lat,
end_lon=end_lon,
mode=mode,
boundary_mode=boundary_mode
)
finally:
router.close()
if result.get("status") == "error":
return jsonify(result), 400
return jsonify(result)
except Exception as e:
logger.exception("Offroute error")
return jsonify({"status": "error", "message": str(e)}), 500
# ── MVUM Places Panel API ──
@app.route("/api/mvum", methods=["GET"])
def api_mvum():
"""
Query MVUM (Motor Vehicle Use Map) features near a point.
Used by the Navi frontend places panel when a user taps near a road/trail.
Query params:
lat: Latitude
lon: Longitude
radius: Search radius in meters (default: 50)
Response:
{
"status": "ok",
"feature": {
"id": "FR 123",
"name": "Some Forest Road",
"forest": "Sawtooth National Forest",
"district": "Ketchum Ranger District",
"surface": "NAT",
"maintenance_level": 2,
"seasonal": "Seasonal",
"symbol": 2,
"access": {
"passenger_vehicle": { "status": "Open", "dates": "06/15-10/15" },
"high_clearance": { "status": "Open", "dates": "06/15-10/15" },
"atv": { "status": "Open", "dates": "06/15-10/15" },
...
},
"geometry": { GeoJSON LineString }
}
}
If no MVUM feature within radius:
{ "status": "ok", "feature": null }
"""
try:
lat = request.args.get("lat", type=float)
lon = request.args.get("lon", type=float)
radius = request.args.get("radius", 50, type=float)
if lat is None or lon is None:
return jsonify({"status": "error", "message": "lat and lon required"}), 400
from .offroute.mvum import MVUMReader
reader = MVUMReader()
try:
# Try roads first, then trails
feature = reader.query_nearest(lat, lon, radius, "mvum_roads")
if feature is None:
feature = reader.query_nearest(lat, lon, radius, "mvum_trails")
if feature is None:
return jsonify({"status": "ok", "feature": None})
# Format access info
access = {
"passenger_vehicle": {
"status": feature.get("passengervehicle"),
"dates": feature.get("passengervehicle_datesopen")
},
"high_clearance": {
"status": feature.get("highclearancevehicle"),
"dates": feature.get("highclearancevehicle_datesopen")
},
"atv": {
"status": feature.get("atv"),
"dates": feature.get("atv_datesopen")
},
"motorcycle": {
"status": feature.get("motorcycle"),
"dates": feature.get("motorcycle_datesopen")
},
"4wd_gt50": {
"status": feature.get("fourwd_gt50inches"),
"dates": feature.get("fourwd_gt50_datesopen")
},
"2wd_gt50": {
"status": feature.get("twowd_gt50inches"),
"dates": feature.get("twowd_gt50_datesopen")
},
"e_bike_class1": {
"status": feature.get("e_bike_class1"),
"dates": feature.get("e_bike_class1_dur")
},
"e_bike_class2": {
"status": feature.get("e_bike_class2"),
"dates": feature.get("e_bike_class2_dur")
},
"e_bike_class3": {
"status": feature.get("e_bike_class3"),
"dates": feature.get("e_bike_class3_dur")
},
}
# Parse maintenance level
maint_level = feature.get("operationalmaintlevel", "")
maint_num = None
if maint_level:
# Extract first digit: "2 - HIGH CLEARANCE VEHICLES" -> 2
import re
match = re.match(r"(\d+)", maint_level)
if match:
maint_num = int(match.group(1))
result = {
"id": feature.get("id"),
"name": feature.get("name"),
"forest": feature.get("forestname"),
"district": feature.get("districtname"),
"surface": feature.get("surfacetype"),
"maintenance_level": maint_num,
"seasonal": feature.get("seasonal"),
"symbol": feature.get("symbol"),
"trail_class": feature.get("trailclass"),
"trail_system": feature.get("trailsystem"),
"access": access,
"geometry": feature.get("geojson")
}
return jsonify({"status": "ok", "feature": result})
finally:
reader.close()
except Exception as e:
logger.exception("MVUM query error")
return jsonify({"status": "error", "message": str(e)}), 500