753 Commits
Author SHA1 Message Date
maziggy 29a81520d9 feat(external-links): an app can show a count on its sidebar link (PUT /external-links/badge with "Send notifications"; Bambuddy Orders shows its To do count), the count disappears when not updated for ten minutes 2026-10-21 17:51:18 +02:00
maziggy ee2d6e69aa test: close the coroutines that mocked create_task, wait_for, run_coroutine_threadsafe, spawn_background_task and AsyncMock sessions left unawaited (reported as unraisable warnings in unrelated later tests); the Spoolman recovery tests archive under their own tmp_path instead of the shared archive/ 2026-10-21 13:18:54 +02:00
maziggy 9f2d15f70f Merge perf/farm-fanout: batched printer-card reads (/api/v1/bulk) and server-paged queue history
Brought in line with dev: bulk card plugs shaped per caller (REST URLs only for plug editors), bulk archive folders keep to the caller's printers, queue delete and Clear History share dev's end time and grouping refresh, Clear History with an API key keeps to its owner's read-own limit, type fixes, Queue page wiring tests on the paged history, watchdog duration test tolerant of a slow run.
2026-10-21 12:00:02 +02:00
maziggy 833a096da6 test/chore: Bandit findings on PR #3350 marked with reasons (ftplib in tests, migration SQL built from module constants), a misplaced nosec moved to its SQL line; layer timelapse tests use tmp_path instead of a shared /tmp/test_bambuddy 2026-10-21 10:51:10 +02:00
maziggy 2443cea174 feat: USB cameras are picked from a list of detected devices (refresh, not-found marking, manual fallback, Docker hint; device listing off the event loop, /dev/video0-99 only); fix: timelapse editor saves as a background job with progress and cancel (ffmpeg stopped on cancel, no overwrite of a timelapse removed or replaced meanwhile, ffprobe/thumbnail timeouts), and the music volume is applied 2026-10-21 08:56:46 +02:00
maziggy 460c11ca30 chore: remove dead code (audit step 4): unused backend helpers and schema classes, 51 unused API client wrappers, test-only components (BackupModal, RestoreModal, VirtualPrinterSettings, TagDetectedModal, WeightDisplay, useLongPress) and their translations; removed POST /printers/test, the two printer debug routes and the SpoolBuddy update-status channel; legacy virtual printer settings fields removed from the settings API; first-run setup redirect tested 2026-10-21 08:12:17 +02:00
maziggy 770c6bfdf9 fix: firmware upload only for idle printers (dialog, server, re-check after download, queue waits during upload); AMS Reset Slot asks first and is refused while printing; confirms for shopping list Clear all, Git history Clear and SSO unlink (last SSO link of an account without password stays); LDAP/SMTP test use the form's values; emptying a user's email removes it; local backup delete errors are shown; removed the unreachable printer-card Spoolman link/unlink 2026-10-20 21:35:41 +02:00
maziggy 57ed8253ea Security hardening (maziggy/bambuddy-security #N) 2026-10-20 21:35:14 +02:00
maziggy 6cdf4eb2d0 Tests: 21 in the new test_api_key_own_rows.py. Before the change, 8 of them failed; the rest pass either way because they check refusals and unchanged behaviour. All 7 mutations were killed. In the #3256 tests (test_api_key_queue_acts_as_owner.py), I tightened the bulk assertion and fixed the outdated docstring. The wiki's API keys page had documented the old refusal; that block is rewritten. 2026-10-20 17:08:09 +02:00
maziggy c6598afec8 test: library/queue probe files get unique names, so parallel workers no longer delete each other's files ("File not found on disk" flake) 2026-10-20 15:35:54 +02:00
maziggy bd692ac3c7 fix(stats): date filters use calendar days in the browser's time zone instead of UTC days; the Statistics page sends its zone, and the date-filtered archive, statistics and inventory-statistics endpoints take an optional tz (Bambuddy's own TZ when omitted) 2026-10-20 15:20:10 +02:00
maziggy ac4806f029 fix: a failed first run no longer leaves the archive at its partial cost (built-in inventory); completion stops the start cost estimate before writing the real cost; 2FA/SSO logins report LDAP/OIDC users' auth source; a fault in both print_error and HMS is listed once; a refused H2D load's tray target expires; refused K-profile re-applies are logged; the cloud filament-name map is fetched once per account without holding a DB connection; the library edit route refuses folder changes across the external boundary; a slow slice-progress answer is not reported as an unreachable sidecar 2026-10-20 14:29:08 +02:00
maziggy 27003de368 fix(ftp): a slow folder listing is reported as slow instead of "printer unavailable", and a refresh joins the listing still running instead of starting another; printer file times without a year are dated against UTC, so evening files on hosts behind UTC are not dated a year back 2026-10-20 12:30:27 +02:00
maziggy ba93abdb9d fix(spoolbuddy): writing a sticker no longer replaces a Bambu spool's AMS link in Spoolman (refused with the reason on Spoolman before 0.27, and such spools are not listed as untagged); the colour-name warning only appears when the name is really missing; an update stops when installing dependencies times out instead of restarting the daemon and reporting success 2026-10-20 12:04:38 +02:00
maziggy b9b62f739f fix(virtual-printer): a late slicer update leaves a queue job the scheduler already claimed alone (its archive still keeps the slicer's AMS pick); a backup restore really stops the virtual printers; the legacy PUT /settings/virtual-printer refuses the settings it no longer applies and is no longer blocked by stale legacy values 2026-10-20 11:39:38 +02:00
maziggy 175758d25a fix(maintenance): a printer's time offline is not counted as print time; duplicate maintenance items are merged on upgrade and prevented by a unique index; the "performed" response honours the item's own interval type 2026-10-20 10:37:17 +02:00
maziggy dad7fea37b fix(notifications): the daily digest goes out during quiet hours and a failed one keeps its events for the next (dropped after two days); a deleted queued archive no longer leaves its creator to be named on a later print; a print closed at reconnect reports no actual duration; the template editor knows the print outcome confirmation and names every event 2026-10-20 10:07:53 +02:00
maziggy ab5ccc1082 fix(printers): a Stop on an idle printer no longer marks it as user-stopped, so a later failed print is not reported as cancelled; Configure Slot warns when a manual K value could not be sent; Skip Objects and the connection diagnostic release their DB connection before talking to the printer 2026-10-20 09:41:21 +02:00
maziggy cf0ba31f19 fix(camera): the plate check holds the chamber light like other camera uses, so a live view opened meanwhile keeps it; captures use the live frame of a watched single-client external camera; a reconnecting X1C live view is not ended by the cleanup; camera test/diagnose/plate routes release their DB connection before capturing 2026-10-20 09:16:41 +02:00
maziggy 07d99f3383 fix(queue): GET /queue?status= takes several comma-separated statuses, as documented; remove the archive rescan and project attachment routes that had no UI (cover images keep their storage) 2026-10-20 08:39:48 +02:00
maziggy 51610b9f19 fix(ui): one toast and one close when saving an edited queue item; a failed Unassign on the printer card shows its error; the OBS overlay applies live status updates; bulk upload shows each same-named file its own result; queue timeline and history rows show the queued plate's thumbnail; remove the Inventory "Full" column that nothing fills 2026-10-20 08:15:03 +02:00
maziggy fcc20cb62c fix(spoolman): AMS syncs write only the slots whose spool they changed and keep a spool assigned meanwhile; the Sync buttons announce slot changes and update the slot preset; a new Spoolman spool is not seeded from leftover built-in assignments 2026-10-19 21:49:18 +02:00
maziggy c2bc41a5ef fix(spoolman): a location delete is refused while Spoolman can't be read; labels print for archived spools; archived spools are not assigned or linked to slots; slot requests outside the AMS ranges are refused before Spoolman is written; bulk counter resets report the spools that failed 2026-10-19 21:22:29 +02:00
maziggy 5afb485c12 fix(inventory): a finished print is not charged a second time by an AMS update while its usage is booked; a completion reported without any file name closes the print session instead of keeping the AMS weight sync off until the next print 2026-10-19 17:36:53 +02:00
maziggy 5b34997dfa fix(inventory): hand assign, unassign and add-from-slot wait for the printer's slot lock; the AMS remain sync and a print's usage no longer overwrite a weight set by hand or weighed meanwhile; a spool deleted while a print is charged is skipped 2026-10-19 16:10:02 +02:00
maziggy 5edbe7586d fix(inventory): deleting a spool frees and announces its slots; scale, AMS and manual weight syncs and a finished print's usage refresh other tabs and the printer cards; a deleted printer's spool assignments go with it on SQLite; a pre-assigned slot the printer could not be told about is retried; CSV last_used is stored in UTC 2026-10-19 15:23:41 +02:00
maziggy a6a4b7648c fix(queue): an override counts an equivalent filament type in its colour; preheat and keep-warm heat the bed for the plate the job prints; queue colour names and the colour name saved with an override follow the filament's product line 2026-10-19 14:46:26 +02:00
maziggy 2b5cd87c7f fix(queue): pipeline cancel stops the preheat and frees the budget; an offline stop frees the budget; the SD cleanup at a print's end is bounded to 45 s; a refused print start is logged and retried at once without a reconnect 2026-10-19 13:58:55 +02:00
maziggy 918aa26ffa fix(queue): models matched without regard to case when adding jobs and in pipelines, stored in the printers' spelling; webhook reprints reuse the slicer's AMS slots; a multi-plate file queued without a plate stores the plate that prints 2026-10-19 13:35:13 +02:00
maziggy abc971a718 fix(queue): a job edited during a scheduler round waits for the next one instead of being dispatched or mapped from the stale copy; the claim requires the selected printer; bulk edit rechecks the claim; no transaction held through a power-on wait 2026-10-19 13:09:44 +02:00
maziggy 3b7c287f68 fix(queue): a print is charged with its own plate and AMS mapping (a fresh dispatch replaces a never-started one's, a failed send leaves a running plate's, completion drains the mapping) 2026-10-19 12:44:10 +02:00
maziggy b342124f0e fix(timelapse): a video goes to the run it belongs to (scan stops on a newer run, claimed videos left out of matching, camera video replaces the printer's without orphaning it); every timelapse change refreshes open Archives pages 2026-10-19 12:11:47 +02:00
maziggy 461c3f045d fix(archives): a cost set through the API or by Recalculate reaches the run that had it; edits during a reprint leave the previous run alone; archive cost bounded; a 422 survives Infinity/NaN 2026-10-19 11:27:38 +02:00
maziggy 879acdbf1f fix(archives): archives made without their 3MF store #RRGGBB colours (existing ones repaired at startup), find AMS-HT filament and are priced from their spools once the 3MF arrives; nozzle temperature of the printed plate 2026-10-19 10:58:15 +02:00
maziggy bb0bf03f68 fix(archives): an offline stop is logged and its real end replaces it; one log entry per run; untracked completions and print start find the print's own archive and 3MF 2026-10-19 10:29:01 +02:00
maziggy 44a5c7a7f5 test(queue,billing,vp): pin dispatch failures, creator scope and busy-printer holds, aborted-print usage fallbacks, end-to-end print completion and billing, VP MQTT pre-login and rate-limit guards; test schema loads every model 2026-10-19 09:50:39 +02:00
maziggy 69c2ff1b44 test(auth): pin disabled keys, ended sessions on every gate, own-only key owners, long-lived token scope, model targets of limited keys; stricter route-auth backstop 2026-10-19 09:22:10 +02:00
maziggy c9c13b6440 fix(archives): the A1/A1 Mini/P1/A2L built-in calibration is not archived as a print 2026-10-18 16:41:47 +02:00
maziggy e05a917445 fix(notifications,drying): printer-limited channels get only their printer's events; blocking mode pre-dries for scheduled jobs; model jobs say "(drying)"; remove dead load-tray state 2026-10-18 16:25:16 +02:00
maziggy 92d299bf20 Security hardening (maziggy/bambuddy-security #43) 2026-10-18 16:04:37 +02:00
maziggy 26e9a05707 fix(queue): a plate printed from the external spool keeps the AMS off on multi-plate files; slot reuse respects the finish; any-model VPs keep the AMS on; cloud filament id read from the preset too 2026-10-18 14:21:05 +02:00
maziggy f45cc599f3 fix(kprofiles): an AMS change leaves the K-profile to the lost-selection check; command answers no longer change the nozzle; unconfirmed writes say so and edits read back; skip refusals are logged; stop-drying toast says sent 2026-10-18 13:57:24 +02:00
maziggy cacaaf4dae fix(printers): live status carries nozzles, firmware, developer mode and the print's AMS mapping; run-out hint narrows by nozzle; AMS-HT is its unit id; rotate check sees loaded slots 2026-10-18 13:27:23 +02:00
maziggy ac976e0003 fix(archives): kill-switch stops archive as cancelled; offline queue stop stores a reason key; SpoolBuddy config save offers a daemon restart 2026-10-18 12:39:38 +02:00
maziggy 3c2ab99635 fix(archives): re-sliced archives read as not printed with a cost; restore checks its numbers; prints are bound under one set of names
- A re-sliced archive is "archived" (Not printed) and priced like any
  archive with grams (estimate_filament_cost, shared with archive_print).
- A reprint deletes a timelapse with no plate on record when the 3MF has
  exactly one plate.
- on_print_start binds every print through _bind_active_print, so a
  resumed print keeps its #3240 plate-restore binding.
- A model job's own nozzle_mapping is cleared on assignment to a nozzle-rack
  printer (not on H2D, not for variants).
- GitHub restore: grams, costs, energy, print times and usage weights must be
  finite numbers >= 0 (grams <= 100000, ints <= 2^31-1), else left empty
  with a note; quantity 0..10000 is kept.
2026-10-18 12:13:46 +02:00
maziggy f7bd06641a fix(inventory): a used weight entered for a new spool is kept; Spoolman last_used means print use; the slot K picker accounts for nozzle flow
- Create, Add copies and CSV import lock a used weight above 0 (an
  explicit weight_locked wins); a negative used weight is refused on create
  and edit, more than the label is still taken.
- update_spool no longer stamps last_used: syncs, location changes and
  weighing are not use. Print usage goes through Spoolman's /use, which sets it.
- ConfigureAmsSlotModal matches K-profiles to the fitted nozzle's flow
  (others under Other) and labels each [HF] / [S]; the spool form uses the
  same flowApplies helper.
2026-10-18 11:35:56 +02:00
maziggy 741539a740 chore(api): remove dead firmware WS progress, the delete-all plate calibration route and unused client wrappers
- Firmware upload progress was broadcast over WebSocket with no listener;
  the page polls the upload status. Broadcast removed, docstrings fixed.
- DELETE /printers/{id}/camera/plate-detection/calibrate (delete every
  reference at once) had no caller; references are deleted one at a time.
- 12 unused frontend API wrappers removed; the routes stay as API.
- /spoolbuddy/calibration redirects to the SpoolBuddy settings page, where
  calibration lives; the dead page is gone.
2026-10-18 11:04:10 +02:00
maziggy 5fec296d72 chore(virtual-printer): log K-profile, filament and load commands from the slicer in full
The publish log line stops at 100 characters, which cut every K-profile
command off before its tray_id, the field that says how BambuStudio numbers
an A2L or AMS-HT tray. Those commands carry no credentials and are now
logged whole, so a support bundle settles it.

--------------

Security hardening (maziggy/bambuddy-security #42)
2026-10-18 10:36:18 +02:00
maziggy 5a9415e2e1 fix(ams): Load and Unload work on an AMS-HT
The printer card sent unit*4+slot for an AMS-HT slot (512 for HT-A), which
the load route refused, and the commands turned the AMS-HT into ams_id 32.
An AMS-HT tray is now addressed by its unit id (128-135), as tray_now
reports it and as BambuStudio sends it (ams_id = target = unit, slot 0);
the A2L AMS-Lite load target is its unit 16, as BambuStudio sends. Unload
from an AMS-HT slot names that slot, a load behind a Filament Track Switch
asks which nozzle for an AMS-HT too, and the dual-nozzle load confirmation
resolves AMS-HT B-H to their unit instead of AMS 0.
2026-10-18 09:52:42 +02:00
maziggy 3542005110 test: register sqlite_only and docker marks in pytest.ini, drop redundant asyncio marks
The suite reads backend/tests/pytest.ini, not pyproject.toml, so every
sqlite_only use warned "Unknown pytest.mark". Two modules marked their sync
tests asyncio; asyncio_mode is auto, so the mark was redundant.
2026-10-17 17:01:32 +02:00