Implements ADR 0012.
Scope
layouts SQL table with schema from ADR 0012
- Seed layouts on startup if missing (snipeit-asset-12mm, grocy-product-12mm, spoolman-spool-12mm, etc.)
- API endpoints:
- GET /api/layouts (filter by integration, tape_mm, printer_model)
- GET /api/layouts/{id}
- GET /api/layouts/{id}/preview (rendered with synthetic data)
- POST /api/layouts (create custom)
- PUT /api/layouts/{id} (update — forbidden on is_seed=true)
- POST /api/layouts/{id}/set-default (atomic)
- DELETE /api/layouts/{id} (soft-delete)
- POST /api/print/{printer} accepts optional
layout_id
- Webhook /api/webhook/grocy accepts optional
layout_id
- Layout dropdown in the UI per integration tab
- LabelRenderer consumes Layout instead of hard-coded TemplateService
Acceptance
- Unique-default invariant per (integration, tape_mm)
- Seed layouts re-created on missing
- is_disabled vs deletion distinction works
- Preview cache invalidates on definition change
Out of scope
Visual editor (separate issue #17, post-MVP)
Implements ADR 0012.
Scope
layoutsSQL table with schema from ADR 0012layout_idlayout_idAcceptance
Out of scope
Visual editor (separate issue #17, post-MVP)