Reporter @maziggy followed the Energy Tracking wiki literally - "create a
key with Write Settings permission, PATCH /api/v1/settings with
{energy_cost_per_kwh: ...}" - and hit:
{"detail":"API keys cannot be used for administrative operations"}.
Triage showed three independent drifts:
1. Wiki listed nine fictional API-key permissions (Read Printers / Write
Settings / Admin / ...) but the UI only ever exposed four toggles
(Read Status, Manage Queue, Control Printer, Allow Cloud Access).
There was no Write Settings toggle to tick.
2. Even if it had existed, the backend hard-denies SETTINGS_UPDATE for
every API key via _APIKEY_DENIED_PERMISSIONS - intentional protection
because PATCH /settings can rewrite SMTP/LDAP/MQTT credentials and the
HA access token. Wider surface than any documented use case needs.
3. So the wiki had been promising a workflow that was never deliverable.
Fix: introduce a narrowly-scoped door rather than relax the deny list.
- New column can_update_energy_cost (default FALSE - existing keys
never silently gain settings-write capability on upgrade).
- New route POST /api/v1/settings/electricity-price accepting
{"energy_cost_per_kwh": <float >= 0>}. Field name matches what the
wiki already documented so the HA rest_command example needs only a
URL+method change, not a payload change.
- Custom dependency require_energy_cost_update() bypasses
_APIKEY_DENIED_PERMISSIONS for this one route for API keys with the
flag set. JWT users still go through standard SETTINGS_UPDATE.
- General PATCH /settings remains denied for API keys - flipping the
narrow flag does NOT widen general settings-write access. Pinned by
test_patch_settings_still_denied_with_energy_flag.
Frontend: fifth "Update electricity price" toggle on the create-API-key
card + amber "Energy" badge on existing keys with the flag set. Three
new i18n keys across all 8 locales (German translated, English fallbacks
elsewhere).
Tim (@turulix) is building a fully automated headless slicing pipeline
against Bambuddy's API and hit the wall flagged in #665: /cloud/* routes
resolve cloud_token per-user from User.cloud_token, but the auth gate
returned None for API-keyed requests, so the route fell back to the
global Settings-table token, which only carries a value in auth-disabled
deployments. Net effect on auth-enabled deployments: API keys reached
the gate just fine, then /cloud/filaments always saw user=None and
returned 401 / empty results — no path to read slicer presets or the
filament catalogue that a CLI workflow needs.
Make API keys carry an owner and route /cloud/* lookups through that
owner; gate the new capability behind an explicit opt-in scope so
existing automation doesn't gain cloud-read access on upgrade.
- APIKey gains user_id (FK to users.id, ON DELETE CASCADE) and
can_access_cloud (BOOLEAN DEFAULT 0). User-delete route also runs an
explicit DELETE FROM api_keys WHERE user_id = ? since SQLite ships
FK enforcement off — same pattern as the existing created_by_id
cleanup blocks.
- New cloud_caller dep on /cloud/* routes resolves to the JWT user OR
the API-key owner stashed by a router-level gate. The auth gate itself
continues to return None for API keys so #1182's surface stays bounded
to /cloud/* — without that bound, any route that fences API keys via
`if current_user is None: raise 403` (e.g. long-lived-token
management) would silently start accepting them.
- The /cloud/* router-level dep enforces three independent fences for
API-keyed callers: user_id IS NOT NULL (legacy keys → 401 with
recreate copy), can_access_cloud=True (otherwise 403), and owner has
cloud_token (existing fence, unchanged). Two extra one-shot fence
errors at create/update time refuse can_access_cloud=True when auth
is disabled or the key is ownerless.
- Frontend: APIKey list shows "Cloud" badge on cloud-enabled keys and
"Legacy" badge on ownerless rows; create form gains an "Allow cloud
access" toggle, default off. New i18n keys in all 8 locales (en + de
fully translated, others seeded with English fallbacks pending native
translation — matches the project's flow for newly-added features).
Migration: two idempotent ALTER TABLE statements + an index on user_id
for the auth gate's owner→keys lookup. Postgres-safe.
Tests: 9 backend integration tests in test_api_key_cloud_access.py
covering creation flags, the three /cloud/* fences, JWT no-op, and
deletion CASCADE; 2 frontend SettingsPage tests pinning the badge
matrix and the create-form contract; 5 daemon unit tests for the
related SpoolBuddy ssh-key sync work that landed in the same branch.
Full backend suite: 3578 passed; full frontend suite: 1597 passed; no
regressions.
Permission semantics for existing keys: keys created before this
release become "legacy" and are rejected at /cloud/* with the recreate
message. Every other endpoint they were used against — queue, status,
control — is untouched.
Bambuddy can now use an external PostgreSQL database via the
DATABASE_URL environment variable. SQLite remains the default.
Dialect-aware helpers handle upserts, PRAGMAs, FTS (FTS5 vs
tsvector+GIN), backup/restore, and health checks. All migration
blocks use savepoints to prevent Postgres transaction poisoning.
Backups are always portable SQLite format regardless of backend.
Cross-database restore imports SQLite backups into PostgreSQL
with automatic boolean/datetime conversion, NOT NULL default
filling, and FK constraint handling.
- New APIBrowser component with full OpenAPI schema integration
- Fetches and parses /openapi.json automatically
- Groups endpoints by API tags (printers, archives, settings, etc.)
- Expandable endpoint sections with color-coded method badges
- Path parameter, query parameter, and JSON body editors
- Auto-populates request body with schema examples
- Live API request execution with response display
- Response shows status code, timing, and formatted JSON
- Copy response button with clipboard fallback
- Search to filter endpoints across all categories
- Expand All / Collapse All buttons
- Link to Swagger UI (/docs)
- Two-column layout for API Keys tab
- Left: API key management + webhook documentation
- Right: API Browser with dedicated test key input
- Parameter validation
- Shows warning for missing required parameters
- Validates before sending requests to avoid 422 errors
- UX improvements
- "Use in API Browser" button on newly created keys
- Responsive layout (stacked on mobile, side-by-side on xl+)
### Projects / Print Grouping
- Create projects to group related prints (e.g., "Voron Build" with 50 parts)
- Track progress with target count and completion percentage
- Assign archives to projects via edit modal or context menu
- Project cards show archive thumbnails with clickable links
- Color-coded project badges on archive cards
- Filter and manage projects by status (active/completed/archived)
### Full-Text Search (FTS5)
- SQLite FTS5 virtual table for efficient searching
- Search across print_name, filename, tags, notes, designer, filament_type
- Automatic index sync with triggers for INSERT/UPDATE/DELETE
### Webhooks & API Keys
- API key authentication with granular permissions
- Permissions: can_read_status, can_manage_queue, can_control_printer
- Secure key generation with prefix display only after creation
- Settings page API Keys tab for key management
- Webhook endpoints for external integrations
### Failure Analysis
- Dashboard widget showing failure rate with color coding
- Correlate failures with conditions (filament type, printer, time)
- Top failure reasons breakdown
- Weekly trend visualization
### Archive Comparison
- Select 2-5 archives to compare side-by-side
- Highlight differences in print settings (yellow)
- Success/failure correlation insights
- Modal with close via button, X, Escape, or backdrop
### CSV/Excel Export
- Export archives and statistics with current filters
- Support for both CSV and Excel (.xlsx) formats
- openpyxl dependency added
## Bug Fixes
- Fixed context menu submenu not showing (removed overflow-hidden)
- Fixed project card thumbnails using correct API endpoint
- Fixed EditArchiveModal to invalidate projects query on save
- Fixed clipboard API fallback for HTTP contexts
- Fixed archive PATCH 500 error (FTS5 index rebuild)
- Fixed FastAPI trailing slash routing for projects endpoint
## UI Improvements
- Context menu submenu with hover/click support
- Project badge on archive cards with project color
- "Go to Project" context menu item for assigned archives
- Clickable project card thumbnails linking to archives
- Reset Layout button moved to Stats page header