POST /library/files only rejected the read-only external branch and
then unconditionally wrote to get_library_files_dir() with a UUID
filename. The resulting LibraryFile row pointed at the external folder
via folder_id, so the file showed up in Bambuddy's UI, but the bytes
physically lived in archive/library/files/ and never touched the mount
-- invisible from any other machine accessing the NAS/SMB share.
Writable external uploads now write through to <external_path>/<filename>
with the original filename preserved, and the DB row matches what scan
produces (is_external=True, file_path=<absolute mount path>). Collisions
return 409 instead of silently overwriting; inaccessible or non-writable
mount returns 400; path-traversal filenames are rejected via resolve +
relative_to.
Extract-zip is now rejected against any external folder (not just
read-only) with a clear "extract on the mount and run Scan" message --
the nested-subfolder creation path would need mkdir on the mount plus
matching is_external LibraryFolder rows, which is a separate design.
Scan already handles that shape.
External folder scan now mirrors disk subfolder structure into the folder
tree instead of flattening all files into root. Hidden directories are
filtered, orphaned subfolders are cleaned up on rescan. Fixes#890.
File manager delete endpoints (folder, file, bulk) now commit before
returning the response — previously relied on post-response auto-commit,
causing a race where the frontend refetch arrived before the commit.
Host directories (NAS, USB, network shares) can now be mounted
into the File Manager without copying files. Files are indexed
into the database on scan but read directly from their original
location. Supports read-only mode, hidden file filtering, and
automatic thumbnail extraction for 3MF/STL/gcode.
- POST /library/folders/external — create with path validation
- POST /library/folders/{id}/scan — discover/sync files
- Block uploads, moves, and deletes for read-only external folders
- Never delete actual files from external paths (DB-only removal)
- Purple folder icon + info bar with rescan button in UI
- i18n for all 7 languages
- 19 backend + 11 frontend tests