5 Commits
Author SHA1 Message Date
maziggy f5ecc61cda fix(spoolbuddy): lower /update permission to INVENTORY_UPDATE so kiosk's own Settings -> Update button works
The kiosk's Settings -> Update Daemon button returned "API keys cannot
  be used for administrative operations" because POST /spoolbuddy/devices/
  {id}/update was gated on Permission.SETTINGS_UPDATE, and SETTINGS_UPDATE
  is in the _APIKEY_DENIED_PERMISSIONS deny-list introduced by PR #1241.
  Every kiosk-side request tripped the deny-list before the API key's
  scope set (Read / Print Queue / Control / Legacy) was even consulted.

  Same root cause as the four QuickMenu System buttons fixed in 0.2.4b3
  (Restart Daemon / Restart Browser / Reboot / Shutdown). Missed /update
  in that audit on the reasoning "replaces the daemon binary, different
  threat surface" — but that's wrong: restart_daemon already replaces
  the running daemon process, so daemon-replacement is not a step up in
  blast radius. The SSH update is also strictly scoped to the one device
  the operator physically controls (git fetch + pip install + systemctl
  restart on that host) — same threat profile as the system commands
  already running on INVENTORY_UPDATE.

  Lower /spoolbuddy/devices/{id}/update from SETTINGS_UPDATE to
  INVENTORY_UPDATE so it aligns with the rest of the kiosk-scoped routes
  (calibration/tare, display, cancel-write, system/command,
  system/command-result, update-status). The main Bambuddy in-app updater
  at POST /api/v1/updates/apply keeps SETTINGS_UPDATE — that one runs on
  the Bambuddy host and is correctly fenced behind the deny-list.
2026-05-08 14:28:41 +02:00
maziggy ef7fd4fa5c fix(spoolbuddy): respect Spoolman mode end-to-end + multiple cache/UX/permission fixes
Seven intertwined SpoolBuddy + Spoolman bugs from feature/spoolman-inventory-ui
  testing, fixed as one batch since they all live on the same path:

  1. /spoolbuddy/nfc/tag-scanned always tried local DB first and only
     consulted Spoolman as a fallback on local-DB miss. A stale local
     row silently won over the authoritative Spoolman record. Now gates
     on _get_spoolman_client_or_none() so the route uses Spoolman
     exclusively when enabled, local exclusively otherwise.

  2. Dashboard "Assign to AMS" button was a no-op when the matched
     spool wasn't yet in the cached spools query (newly created in
     Spoolman, or unarchived after page load). The card rendered via
     `displayedSpool ?? sbState.matchedSpool` fallback but the modal's
     stricter guard silently failed to mount. New effectiveModalSpool
     synthesises an InventorySpool-shaped object from the WebSocket-
     delivered MatchedSpool (9-field subset, sufficient for the modal
     since it only needs `id` to route the assign API).

  3. AMS-page slot picker explicitly returned null for the
     assign/unassign branch when a slot had a SpoolmanSlotAssignment
     but no tag-linked spool — only Configure stayed visible. Now
     resolves the assignment via spoolmanSlotAssignmentsAll +
     spoolmanInventorySpoolsCache, renders a "Assigned spool" info
     card, and exposes an Unassign button wired to a new
     unassignSpoolmanSlotMutation (DELETE
     /spoolman/inventory/slot-assignments/<id>).

  4. LinkSpoolModal showed "Unknown color" for every Spoolman spool
     because Spoolman doesn't standardise color_name — most installs
     only populate color_hex and filament.name (which often carries
     the colour, e.g. "PLA Basic Red"). _map_spoolman_spool now falls
     back to the filament's subtype (filament name minus material
     prefix) when color_name is empty, so spools are visually
     distinguishable. The NFC write-tag warning specifically checks
     the raw filament.color_name (not the mapped value) so the
     "tag encodes empty color name" warning still fires on installs
     that genuinely lack the field.

  5. Writing a tag for spool B didn't clear the same tag from spool A,
     so a single NFC UID could map to two spools at once and
     find_spool_by_tag returned whichever came first in the cached
     list. nfc_write_result now searches Spoolman for any other spool
     currently bound to the target UID and clears its extra.tag
     (best-effort: cleanup failure logs a warning but doesn't block
     the write, since the chip is already written).

  6. The kiosk display held stale spoolmanSlotAssignments cache
     permanently because a long-running browser window has no
     focus/remount triggers to fire a refetch. Adds
     refetchInterval: 3_000 so the kiosk picks up changes from another
     client (Bambuddy main UI, direct Spoolman edit) within seconds.

  7. Kiosk QuickMenu System buttons (Restart Daemon / Restart Browser /
     Reboot / Shutdown) all 403'd silently. /system/command was gated
     on Permission.SETTINGS_UPDATE (T-Gap 2 from a prior security
     audit) but every other kiosk-scoped device route uses
     INVENTORY_UPDATE; the kiosk operator's session has the latter,
     not the former. Lowered to INVENTORY_UPDATE so operators can
     recover the kiosk from the kiosk. Risk is bounded — only the 4
     named commands are accepted (no RCE), reboot/shutdown require
     physical-access recovery anyway, the same operator already
     controls printers + weighs spools. /update keeps SETTINGS_UPDATE
     because it can replace the daemon binary.
2026-05-08 12:09:34 +02:00
MartinNYHC b30a283184 Feature/spoolman inventory UI (#1241)
feat(spoolman-inventory): squashed feature work for rebase onto dev

Squashed all commits from feature/spoolman-inventory-ui onto a single commit
to enable a clean rebase onto dev. Original per-commit history preserved at
backup tag backup/spoolman-inventory-ui-prerebase-20260507-105721.
2026-05-08 11:52:42 +02:00
MartinNYHC dac2a31192 Revert "feat(inventory): unified Spoolman inventory UI + AMS slot assignments…" (#1232)
This reverts commit 55d71498e9.
2026-05-07 11:30:31 +02:00
Sn0rrii 55d71498e9 feat(inventory): unified Spoolman inventory UI + AMS slot assignments + Storage Location + NFC write support + Spoolman Filament Catalog Picker (#1114)
feat(spoolman-inventory): squashed feature work for rebase onto dev

Squashed all commits from feature/spoolman-inventory-ui onto a single commit
to enable a clean rebase onto dev. Original per-commit history preserved at
backup tag backup/spoolman-inventory-ui-prerebase-20260507-105721.
2026-05-07 11:15:24 +02:00