The SliceModal forces the user to pick four slots every time (printer /
process / filament(s) / bed type). For fleet production that's tedious
and error-prone. Pipelines let an operator save a named bundle and apply
it with one click on the next file.
PR A is bundle-and-management only. PR B adds single-target dispatch,
PR C adds multi-copy batch with capability-matched fanout. Future-PR
columns (target_kind / target_printer_id / target_model_class /
fanout_strategy) ship in this migration so PR B+ is code-only, not a
schema bump.
Backend
- New model SlicerPipeline + slicer_pipelines table; soft-delete via
is_deleted so PR B+ run history can still resolve metadata.
- Pydantic schemas reuse the existing PresetRef shape from
schemas/slicer.py.
- CRUD routes at /api/v1/slicer-pipelines/ — list (newest first by id
DESC), create (201), get-by-id, partial PUT, soft-delete (204).
- Three new permissions: PIPELINES_READ / PIPELINES_WRITE / PIPELINES_RUN.
Administrators + Operators get all three; Viewers get READ.
Backfill in seed_default_groups() so existing installs upgrade
cleanly. All three denied to API keys for now.
Frontend
- Settings → Workflow splits into two horizontal sub-tabs mirroring
the Authentication tab pattern: "Queue & Dispatch" (existing
Workflow content) and "Pipelines" (new). URL deep-link via
?tab=queue&sub=pipelines.
- SlicerPipelinesPanel — list, inline rename, delete, stale-preset
warning when a referenced preset no longer resolves.
- SliceModal gets "Apply pipeline ▾" + "Save as pipeline". Apply
fills all four slot states; the filament list right-pads from
current state so a pipeline with fewer entries than the current
source's slot count keeps the existing tail.