Repository navigation
1.3.0
Security
- Fixed two stored-XSS vectors in the viewer: virtual way IDs are now strictly validated server-side (
<int>or<int>:<int>only) before being stored in the annotation store or change log, the changes/hidden panels build rows via DOM APIs instead of inlineonclickstrings, andescHtmlescapes quotes so attribute-context interpolation (e.g. the tag editor'svalue="...") cannot break out - CSRF protection for cookie-based auth: with
MAP_DATA_ACCESS_TOKENset, the cookie alone now authenticates only safe methods — state-changing requests must carry theX-Requested-Withheader (attached automatically by the viewer's same-origin fetches) or the token header/query parameter; threat model documented in the viewer docs - Request bodies are capped at 100 MB (
MAX_CONTENT_LENGTH), so an oversized upload can no longer fill the data directory cost_gridandcreate_replanvalidate every client parameter up front (bbox sanity, cell budget of at mostMAX_GRID_CELLS, numeric ranges forcell_size/inflate_obstacles/grid_cost_weight, cost-dict shapes, path points within UTM-supported ranges), closing a compute-DoS lever and turning deep planner 500s into clean 400s
Fixed
- Annotation edits no longer race: a shared
annotation_storecontext manager holds the per-file lock across the whole load → mutate → save cycle in all 16 mutating viewer routes, fixing lost updates between concurrent editors and duplicate synthetic node IDs from concurrentadd_way_nodecalls GraphPlannerapplies annotation splits per way in descending segment order (junctions no longer land between the wrong nodes when one way is split in several places) and splices into per-planner node-list copies instead of mutating the sharedMapData(a second planner on the same map no longer raisesKeyError)grid_astardiagonal moves require both edge-adjacent cells to be free, so paths can no longer cut through the corner where two blocked cells touch; grid cells are sampled at their centers, removing the half-cell obstacle-membership bias- Douglas–Peucker simplification in
replan/grid_astarcollision-checks every shortcut it introduces and keeps the original vertices where a chord would cross an obstacle - RRT* rewiring propagates cost changes to descendants and keeps the informed ellipse synced with the goal's true cost, instead of sampling from a stale, oversized ellipse
GraphPlanner.plan()returnsNonefor fewer than two waypoints (per its documented contract) and rejects waypoints farther than a configurablemax_snap_distance(default 100 m) from the network instead of silently snapping to an arbitrarily distant edge- GPX/YAML parsing forces every waypoint into the first point's UTM zone, so a route crossing a zone boundary no longer produces a ~400 km easting discontinuity
- Overpass HTTP-200 error bodies (a
remarkruntime error or an HTML page from a busy mirror) now rotate to the next mirror and retry like server errors instead of crashing the fetch; unparseable bodies — including a corrupt cached response — degrade gracefully - OSM relation inner rings are subtracted from the outer polygons, so courtyards and islands are no longer covered by the merged barrier; member ways consumed by a relation merge are dropped from the parse, eliminating duplicated barrier geometry
- Degenerate OSM ways (too few coordinates for their geometry type) are skipped with a warning instead of aborting the whole parse
.mapdataand OSM-cache writes are atomic (temp file +os.replace), so a crash or full disk mid-save can no longer truncate a previously good filemap_data_inforeports the footway centerline length instead of the buffered-polygon perimeter (which was roughly double the walked distance)MapDataaccepts a 1-Dcurrent_robot_positionand reconciles its elevation column against the waypoints;_csv_to_dicthandles single-row CSVs; loaded instances restore thepointsattribute- Viewer:
cancel_replan,create_wormhole, andcancel_wormholereturn a clean 400 on a missing/non-JSON body (previously an unhandled 500); the two cancel endpoints also 400 on a missingtransfer_id - Abandoned fetch tasks are swept from the registry after the 60 s retention window on every new fetch; cancelled replan transfer IDs are discarded on entry and exit, so a late cancel cannot poison the next replan with the same transfer ID
Added
- Regression tests for every fix above plus coverage for the previously untested riskiest paths: Overpass body-level failures,
GraphPlannerannotation splicing, the auth/CSRF gate,cost_grid/create_replanvalidation,upload_mapdata, native export, mocked wormhole transfers,info.get_stats,combine_waysbackward-prepend and closed-ring merges, grid A* cost-weighting, and replan cancellation (~130 new tests; suite now 311 tests in ~6 s) tests/conftest.pywith a shared mocked-Overpass fixture, and pytest configuration centralized in[tool.pytest.ini_options]so a plainpytestruns with the same coverage flags locally and in CI
Pull requests
- v1.3.0: fix 27 backlog items — planner and parsing bugs, viewer security hardening, test coverage by @vlk-jan in #13
Full Changelog: v1.2.1...v1.3.0 · changelog