- check_relative: spaces before the first dot are dropped (CON .txt), superscript COM/LPT digits are device names.
- gltf_references refuses a reference to a missing file; drops the broad ValueError catch and redundant relative_to so the specific refusal (a link) reaches the receipt.
- _render_still makes folders only after every Blender-side refusal (unknown engine used to leave them behind).
- Tests for each.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- resolve_inside maps OSError from resolving a component (WinError 448 on a mklink /J junction) to a link refusal.
- Direct check_relative test for '..' and NUL; OSError mapping test.
- headless_smoke.py makes real junctions on Windows (outside and inside the root) and an existing-output case.
- install.md documents the path rules and the residual TOCTOU.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
WIP for review fixes, tests pass (61); mutation confirmation and Starfire re-run pending.
- importGltf parses .gltf JSON and .glb's JSON chunk, checks every buffers/images uri.
- Names are relative plain paths: no drive, UNC, extended, ':' (ADS), '..', device names.
- No symlink/junction component under the root; output must not already exist.
- Path and file stamps re-checked right before use; residual TOCTOU documented in code.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Found by running the actions on Blender 5.2.3 headless: the render engine enum is
dynamic, bl_rna lists only BLENDER_EEVEE, so CYCLES and WORKBENCH were refused.
The fake in the tests now behaves like the real enum. surfaces/blender/tests/live/
headless_smoke.py runs every scene action against real bpy.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Paths for importGltf and renderStill are confined to the Import Directory and
Render Output Directory preferences (empty disables the action; .. , absolute
paths and escaping symlinks are refused). Every field is validated before bpy is
touched. renderStill restores render settings afterwards. Tests use a fake bpy;
Blender was not run.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>