An expired token was indistinguishable from a working one. set_token()
stamped token_expiry = now + 30 days every time a stored token was loaded,
so the expiry reset on every request and is_authenticated could never
return False. /cloud/status answered "connected" for as long as any token
existed, while every cloud call 401'd — and the user was shown Bambu's own
{"error": "Please login."} verbatim.
Bambu is now the authority: /cloud/status validates the token upstream
(cached 5m), and any 401 from any authenticated call durably records the
credential as dead via users.cloud_token_invalid_at, so MakerWorld, cloud
profiles, slicer presets and firmware checks all agree at once. An
unreachable Bambu is treated as unknown, never as expired, so an outage
cannot sign a working session out.
The user-facing message now names the Profiles page, where the Bambu Cloud
sign-in actually lives; the old text pointed at a Settings page that does
not exist. Same stale path corrected in the wiki.
The makerworld /status, /resolve, and /import handlers passed
current_user directly into get_stored_token / _build_service.
require_permission_if_auth_enabled returns None for API-keyed
callers by design (core/auth.py:1414), so the lookup always
missed even when the key's owner had a stored Bambu Cloud session.
Result: a "requires a Bambu Cloud login" 400 on every API-keyed
import, regardless of the owning account's actual cloud state.
Wire resolve_api_key_cloud_owner (already used by the slice path
in #1182 — slicer_presets.py:491 and library.py:3871) into the
three makerworld routes that read the cloud token. The handler
falls back to the API-key owner via cloud_token_user =
current_user or api_key_cloud_owner, then passes that through.
import_instance also propagates the resolved user to the
owner_id arg on save_3mf_bytes_to_library, so the resulting
LibraryFile.created_by_id reflects the key's owner instead of
NULL.
Fail-closed semantics preserved: resolve_api_key_cloud_owner
already fences on api_key.can_access_cloud, so keys with only
the per-route scope (can_read_status / can_manage_library) still
take the existing "requires Bambu Cloud login" path — no auth
widening.
/recent-imports is unchanged — it only uses current_user as a
permission gate (_ = current_user) and never touches the cloud
token.