The detector_distance_mm sent to JFJoch and written to the DB came from the live detector readback (diffraction.dtz_mm) captured before the detector finished moving, so a scan requested at e.g. 100 mm could be recorded at the old position (e.g. 800 mm). - JFJoch + DB now read the validated request target (request.dtz) instead of the live diffraction.dtz_mm; diffraction.dtz_mm stays live for the local-contact readout. - jfjoch: raise if request.dtz is unset (setup_datacollection must validate it first) instead of silently falling back to the live readback. - raster + rotation services: wait for the detector to reach request.dtz (set_dtz wait=True) right before triggering the scan, since the sa2dc move is non-blocking. (Raster setup-before-measure reorder landed earlier in daq.py.) - tests: request.dtz now required in jfjoch/aaredb tests; xtal-snapshot exposure assertion updated to 1 ms. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>