mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-18 21:16:47 +00:00
2a7ad1e241
The scoping guard asked whether a referenced id belongs to a different trip. An id that belongs to no row at all cannot, so it passed, reached the raw INSERT/UPDATE, and SQLite's own foreign-key enforcement threw. Nothing caught it, so a stale place_id from a client-side race came back as a bare 500 with no actionable message — where the same route answers a clean 400 for an id that does exist somewhere else. A second, disjoint guard now names the ids that resolve to nothing and answers 400. It deliberately does not cover accommodation_id: that column has no row to find once a shortened trip cascades its stay away, and refusing the write there would make the booking permanently uneditable. The controller guard reads the request body, which is not enough on its own — an update rebinds whatever the row already held, so a stored id whose row is gone reaches SQL untouched. day_id, end_day_id, place_id and assignment_id are all declared ON DELETE SET NULL, so a reference that resolves to nothing is precisely the state that cascade leaves behind and is now cleared to NULL, the same way a dangling accommodation_id already heals. day_accommodations' day columns are NOT NULL and have nothing to heal to, so those are refused. The plugin surface ran neither guard. It now refuses an unresolvable id, which turns a crash into an error; it still accepts an id from another trip, because taking that away belongs to the plugin contract and not to a bug fix. The reservation MCP tools already validated every referenced id against the trip. Closes #2355