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.
- Tracking configs: filter by name + provider type
- Template configs: filter by name + provider type
- Command configs: filter by name + provider type
- Notification trackers: filter by name + provider
- Command trackers: filter by name + provider
- Targets: filter by name (type filtering already existed)
- Nav badge counts include system-owned entities (user_id=0)
- Shows "no items match filter" vs "no items yet" empty states
- Add $state-based entity cache layer with 30s TTL, request deduplication,
and local mutation helpers (entity-cache.svelte.ts + caches.svelte.ts)
- Wire all 10 page components to use shared caches for cross-page data
- Add slide animation for nav tree expand/collapse with rotating chevron
- Remove aggregate count badges from container nav nodes (keep on leaves)
- Convert Targets from flat leaf to group with per-type children
(Telegram, Webhook, Email, Discord, Slack, ntfy, Matrix)
- Add URL-based type filtering on Targets page with per-type descriptions
- Add Bots group children for Email and Matrix alongside Telegram
- Tab-based routing for bots page (?tab=telegram/email/matrix)
- Add per-type target counts and email/matrix bot counts to /status/counts
- Split CLAUDE.md into focused context files under .claude/docs/
- Fix .gitignore: scope lib/ to root, allow .claude/docs/ tracking
- Clear all caches on logout
- Reset form state when switching target type tabs
Navigation:
- Restructure flat nav into grouped tree: Notification (Trackers,
Configs, Templates), Commands (same), Bots (Telegram), Settings
(Common, Users)
- Collapsible groups with expand/collapse state persisted in localStorage
- Auto-expand group containing the active page
- Counter badges on groups (sum of children) and individual items
- New /api/status/counts endpoint for nav badge data
- Mobile bottom nav uses flattened key pages
Dashboard:
- Rename "Recent Events" to "Events"
- Move chart under Events section (after filters, before event list)
- Filters (event type, provider, search) now affect both the event
list AND the chart simultaneously
- Add event_type, provider_id, search filter params to /api/status/chart
Rework entity schema: rename Tracker→NotificationTracker, add CommandConfig/
CommandTracker/CommandTrackerListener entities for decoupled command handling.
Commands now resolve through CommandTracker→CommandConfig instead of
TelegramBot.commands_config. Smart ref-counted bot polling based on active
listeners. Add chat_action to telegram targets. Full frontend CRUD pages
for command configs and command trackers. Idempotent SQLite migrations.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds telegram bot command system with 13 commands (search, latest, random, etc.),
webhook/polling handlers, rate limiting, app settings page, and various UI/UX
improvements across all entity pages.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace 3 test buttons with unified dropdown menu (basic/periodic/scheduled/memory)
- Send text message first, then assets as reply (not combined caption+media)
- Pass all target config settings to Telegram client (disable_url_preview, max_media, chunk_delay, etc.)
- Real data test notifications for periodic/scheduled/memory (fetch from Immich)
- Provider card URL is now a clickable hyperlink
- Localized test type labels (EN/RU)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Show entity icons on all cards with fallback defaults (providers, trackers, targets, bots)
- Enrich EventLog with provider_name, tracker_name, assets_count; add DB migration
- Dashboard events: filtering (type, provider, search), sorting, pagination, dynamic page size
- Friendly chat names on telegram target cards (resolve from TelegramChat table)
- Test message button on bot chat items with locale-aware messages
- Album public link validation on tracker save with auto-create dialog
- Support albums without public links: conditional <a href> in templates
- Fetch shared links during poll, enrich events with public_url/protected_url
- Per-asset public_url in template context ({share_url}/photos/{asset_id})
- Common date/location detection: common_date + common_location context vars
- Dual date formats: date_format (datetime) + date_only_format (date only)
- Template clone button, HTML link rendering in template preview
- Fix Telegram asset download 401: pass x-api-key headers through client
- Fix provider external_url matching for API key scoping
- Fix event timestamp timezone (append Z suffix for UTC)
- Localize event filter controls, test messages (EN/RU)
- Template variable UI helpers updated with all new fields
- CLAUDE.md: template system sync rules documentation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Backend API (38 routes):
- providers: full CRUD + test connection + list collections + API key masking
- trackers: full CRUD + trigger + history + test-periodic/memory
- tracking-configs: full CRUD with Pydantic models, provider_type filter
- template-configs: full CRUD + preview + preview-raw with two-pass validation
- targets: full CRUD + test notification + config masking
- telegram-bots: full CRUD + chat discovery + token endpoint
- users: full admin CRUD + password reset + self-delete protection
- status: dashboard endpoint with providers/trackers/targets/events counts
Frontend pages updated:
- Dashboard with animated stat cards and event timeline
- Providers with proper components, delete confirm, snackbar
- Trackers/targets/tracking-configs/template-configs/telegram-bots/users
all use PageHeader, Card, Loading, MdiIcon with correct i18n keys
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>