Targets page: collapse targets under a per-bot header (BotGroupHeader)
with a count chip and an "Open bot" cross-link. Receivers are hidden
by default and expand per group; non-bot types fall back to a "Direct
delivery" group. Telegram "Add receiver" now opens the EntitySelect
chat palette directly instead of an inline form — EntitySelect grew a
bindable `open` flag, `showTrigger`, and an `onclose` cancel signal.
Backup settings page: split the monolithic +page into focused panels
(BackupHero, BackupLedger, ExportPanel, ImportPanel, PendingStrip,
ScheduleCassette) and introduce a stepwise export/import flow with
category groups, secrets handling, conflict policy, and validation
gating. New i18n keys in both locales cover the bot grouping labels
and the backup step copy.
- Auto-refresh ticker is now silent: skips ``eventsLoading`` so the
loading placeholder no longer flashes, uses ``(event.id)`` key on
the events ``{#each}`` so unchanged rows reuse their DOM nodes, and
short-circuits the array reassignment when the visible page is
identical to what we already rendered. No-op refreshes leave the
list completely untouched.
- ``PageHeader`` crumbs (Routing · Notification, Operators · Bots, …)
were hard-coded literals. Moved to a new ``crumbs`` i18n namespace
with 9 keys; updated all 15 call sites to ``t('crumbs.*')`` so they
switch with the language.
- Tracker form's Immich feature-discovery banner now exposes both
``Open Tracking Config`` and ``Open Template Config``. Added the
``?edit=<id>`` auto-open hook to ``/template-configs`` (mirrors the
existing one on ``/tracking-configs``) so the new link lands users
directly on the editor.
Comprehensive pre-production sweep across the Aurora redesign — drives
svelte-check to 0 errors / 0 warnings (was 61) without changing visual
intent. Highlights:
- Mobile: hero title shrinks at 480px, signal-list stacks timestamp
under sentence below 640px, sidebar icon buttons bumped to 40x40
- Light theme: muted-foreground darkened to #3a3560 to clear WCAG AA
on glass surfaces and the modal close button
- Perf: topbar backdrop-filter 28→14px, mobile-more sheet 28→12px to
cut concurrent blur layers on mid-tier mobile
- a11y: prefers-reduced-motion mute for aurora drift / pulses /
shimmer / stagger; aria-label on every icon-only button;
aria-describedby on Hint; combobox/listbox/aria-activedescendant on
SearchPalette; modal dialog tabindex; 47 label-without-control
warnings across 14 form pages cleaned up via for=/id= or label→div
- Dashboard derived state split into topology- vs status-bound layers
so polling no longer re-runs the full provider/wires computation
- Mobile bottom nav derived from baseNavEntries by key lookup so
adding a top-level nav entry keeps the two trees in sync
- Bug: template-configs page now respects the global provider filter
for both the count meter and the type pill (was reading the
unfiltered cache)
- Misc: portal EventChart tooltip and switch its swatches to Aurora
tokens; CollapsibleSlot warning state uses warning-fg/-bg tokens
instead of #d97706; Hint z-index 99999→9999; element refs across
Modal/EntitySelect/MultiEntitySelect/SearchPalette/IconGridSelect/
Hint/targets converted to \$state for reactivity; 4 dead
.topbar-cta selectors removed
Big batch — every secondary page now wears the same glass-card hero
that landed on Providers earlier:
- notification-trackers, tracking-configs, template-configs
- command-trackers, command-configs, command-template-configs
- targets (with active-tab title), actions
- bots (telegram / email / matrix tabs)
- settings, settings/backup, users
Each page picks an italic-em emphasis word, an editorial crumb (e.g.
'Routing · Notification', 'Operators · Bots', 'System · Maintenance'),
a count meter, and entity-specific status pills derived from live
data: 'X armed / Y paused' for trackers and actions, 'X types' for
configs/templates, 'X channels' or '$N receivers' for targets.
Other changes in this commit:
- Button.svelte: redesigned. Primary variant becomes a real Aurora
CTA — gradient lavender → orchid pill, 40px tall md / 34px sm,
inset highlight, lift + glow on hover. Secondary, danger, ghost
variants reworked to match. The 'Add <Type>' button on every page
now reads as the page's primary action instead of a flat lavender
rectangle.
- JinjaEditor: overrode oneDark's hardcoded background with
!important so the editor surface picks up var(--color-input-bg).
Gutters / scroller / selection / autocomplete tooltip all match
Aurora glass tokens now. Template editors stop visually clashing
with the surrounding panel.
- Aurora pulse dot: rewritten as a self-contained box-shadow glow
pulse (no transform, no pseudo-element). The dot's bounding box is
now stable so ancestors with overflow:hidden can never clip the
visible dot — only the (decorative) outer glow halo. Fixes the
'half-moon clipping' on the dashboard 'On watch' deck.
- topbar-action.svelte.ts left in tree but unused (topbar CTA was
reverted per your call). Will clean up in a later commit.
- Form input baseline styling moved into app.css (rounded 0.625rem,
glass background, hover/focus rings) so untouched filter inputs
on the per-type pages stop looking out of place.
i18n: emphasis / countLabel / armed / paused / receiver / receivers
/ channelsCount keys added across en + ru.
Build clean: 0 errors, 61 pre-existing a11y warnings unchanged.
Backend
- Per-chat album scope for Immich commands (search/latest/memory/...): new
allowed_album_ids on CommandTrackerListener, threaded listener/page kwargs
through ProviderCommandHandler.handle; PATCH listener-scope endpoint.
- /search and /find accept a trailing page number; Immich client search_smart
/ search_metadata take a page param.
- Immich person-asset lookup switched from removed GET /api/people/{id}/assets
to POST /api/search/metadata with personIds (fixes /person command and
auto_organize rules silently returning zero candidates on Immich 1.106+).
- Auto_organize rule now sets the target album's thumbnail to the first added
image when missing (falls back to any asset type); failures do not fail the
rule. add_assets_to_album surfaces the Immich error body on non-2xx.
- EventLog.user_id / action_id / action_name columns with defensive migration
+ backfill. Status query filters by user_id directly; Immich/webhook paths
emit user_id explicitly. action_runner writes an action_success/partial/
failed event on each non-dry-run.
- Dashboard DELETE /api/status/events (scoped to user_id) + rendering live
tracker/provider/action names via FK join with snapshot fallback.
- PATCH /api/users/{id} for username/role change with last-admin guard.
- Deletion protection returns structured {message, entity, blocked_by}
(ApiError carries .blockedBy; frontend opens BlockedByModal).
- Backup prepare-restore → AppSetting markers + atomic write of
pending_restore.json; lifespan hook applies on next startup and archives
under data/applied_restores/. apply-restart sends SIGTERM so the lifespan
shutdown runs; NOTIFY_BRIDGE_SUPERVISED env override gates the button.
Manual POST /api/backup/files (same format as scheduled).
- New periodic-summary test path reuses shared collect_scheduled_assets
(limit=0) so test and future production code go through one primitive.
- Per-receiver locale for Telegram test messages (resolves
TelegramChat.language_override per chat instead of applying the first
receiver's locale to everyone).
- Bounded concurrency (semaphores) in NotificationDispatcher._preload_asset_data
and _refresh_telegram_chat_titles; chat title sweep extended to 24h since
save_chat_from_webhook covers active chats opportunistically.
- Telegram poller detects the \"webhook is active\" 409 and auto-calls
deleteWebhook for bots whose DB update_mode is polling (throttled per bot).
- TelegramClient.get_chat added (CLAUDE.md rule 6); set_album_thumbnail added.
- Seeds: rename \"Default Commands\" → \"Default Immich Commands\";
track_assets_removed default False.
Frontend
- Global provider selector visible when there is only one provider.
- Clear-events button + i18n + ConfirmModal on the dashboard; new icons/
labels/filters/colors for action_success / action_partial / action_failed.
- Auto-select first available tracking/template/command/config + bot on
create forms (trackers, command-trackers, targets, template/command
configs).
- Telegram target disable_url_preview defaults to true.
- BlockedByModal wired into 8 deletion flows; fetchAuth helper for
multipart/binary calls (reuses api()'s refresh + ApiError mapping).
- Immich tracker 'Checking links' parallelised (concurrency cap 6).
- Backup page: pending-restore banner + Apply-now / Apply-later modal,
restarting overlay polling /api/health, manual 'Create backup' button.
- Command-trackers listener row gets an 'Edit album scope' modal with
inherit/explicit multiselect.
- Users page: Edit user modal (username + role).
- parseDate helper for consistent UTC date rendering.
Migrations / schema
- event_log: + user_id, action_id, action_name (+ backfill user_id from
notification_tracker).
- command_tracker_listener: + allowed_album_ids.
Add person exclude criteria to Immich auto-organize — assets containing
excluded persons are filtered out after candidate gathering. Also adds
full backup/restore system with export, import, scheduled backups, and
retention management.