-
Notify Bridge 0.3.0
StableRelease / release (push) Successful in 1m19sreleased this
2026-04-22 18:59:15 +03:00 | 85 commits to master since this releasev0.3.0 (2026-04-22)
Major polling perf overhaul for large Immich libraries plus a UX fix for
slow bot commands. Combined impact on idle albums: per-tick cost drops
from ~150 MB fetched to a few hundred bytes; active albums now fetch
O(changes) instead of O(library). Tested against a ~200k-asset library.Schema change: adds a
meta_fingerprintJSON column to
notification_tracker_state— applied automatically by the startup
migration, no manual step required.Performance
- Skip full album fetch on idle ticks — new
ImmichAlbumMeta+get_album_meta()probe using?withoutAssets=trueas a cheap change-detection fingerprint. When the fingerprint matches and no pending assets are outstanding,poll()short-circuits and does no asset fetch at all. (fe38d20) - Delta-fetch active albums — when the fingerprint changes, poll with
updatedAfterinstead of refetching the whole album; falls back to a full fetch only on count decrease or mixed add+remove that delta can't reconcile. (fe38d20) - Parallel meta probes —
asyncio.gatherover album meta probes so a 20-album tracker pays one round-trip of latency instead of 20. (fe38d20) - Tick-scoped shared-links cache — new
get_all_shared_links_by_album()coalesces to one/api/shared-linksrequest per tick instead of one per changed album. (fe38d20) - Module-level users cache — 1 h TTL, sha256-keyed, shared across providers that target the same Immich server. (fe38d20)
- Skip
asset_idsDB rewrite on idle ticks — watcher no longer rewrites the (potentially ~8 MB for huge albums) JSON column when the fingerprint didn't change. (fe38d20) - Adaptive polling — after 10 empty ticks the scheduler skips 1-in-2, after 30 empty ticks skips 1-in-4; resets on the first detected change or any schedule edit. (fe38d20)
- APScheduler jitter —
interval/4, capped at 30 s, to smooth thundering-herd bursts when many trackers share the samescan_interval. (fe38d20) - Event payload cap — 50 added / 200 removed assets per event so a bulk import can't explode a Jinja template or exceed Telegram message limits. (fe38d20)
Features
- Chat-action hint stays alive during slow command fetches — Telegram chat actions expire after ~5 s, so slow bot commands (
/latest,/random,/favorites,/memory,/search,/find,/person,/place,/summary) previously showed a hint that vanished long before the media arrived and users saw nothing happening. Newtelegram_chat_actionasync context manager starts a keep-alive task that re-posts the action every 4 s until it exits;classify_command_chat_actionmaps each command to the right action (upload_photofor media-returning commands,typingfor/summary, none for fast DB-only commands like/status//events). Wired into both the webhook and long-poll paths. (69711bb)
All Commits
Changelog
155d25echore: release v0.3.0
69711bbfeat(commands): keep chat-action hint alive during slow command fetches
fe38d20perf(immich): skip full album fetch on idle ticks; delta-fetch for active onesDownloads
- Skip full album fetch on idle ticks — new
-
Notify Bridge 0.2.8
StableRelease / release (push) Successful in 1m58sreleased this
2026-04-22 18:02:09 +03:00 | 88 commits to master since this releasev0.2.8 (2026-04-22)
Follow-up fix to v0.2.7's Telegram-send unification. The shared factory was
in place, but commands and notifications were still writing into different
cache-key namespaces — so in practice the caches never actually shared entries.Bug Fixes
- Commands and notifications now share one
file_idcache namespace —common._format_assetswas passingcache_key=<bare asset UUID>, while the notification dispatcher writes keys as<host>:<uuid>(derived from the URL byextract_asset_id_from_url). The two paths populated different keys for the same asset, so neither could hit the other's cachedfile_idand the Settings → cache-stats card only ever reflected the notification side. Dropped the explicitcache_key—TelegramClientnow derives<host>:<uuid>from the URL on both paths, so onefile_idcached by any dispatch or/random//latestreply is reused by every later send. (7dae68f)
All Commits
- 7dae68f — fix(commands): match notification cache-key format so writes share one namespace (alexei.dolgolyov)
Changelog
d026160chore: release v0.2.8
7dae68ffix(commands): match notification cache-key format so writes share one namespaceDownloads
- Commands and notifications now share one
-
Notify Bridge 0.2.7
StableRelease / release (push) Successful in 4m23sreleased this
2026-04-22 16:47:25 +03:00 | 90 commits to master since this releasev0.2.7 (2026-04-22)
Follow-up to v0.2.6: unifies the Telegram send routine across notifications
and bot commands so both sides share the same aiohttp session, the same
file_idcaches, and the same rules for video / thumbnail URL construction.
Eliminates repeat uploads that happened because single-asset sends and media
groups were keyed in different caches.Bug Fixes
- Single-asset sends now hit the asset cache —
TelegramClient._get_cache_and_keytreatscache_keyvalues that look like asset UUIDs as asset-cache entries. Single-asset sends were storingfile_ids inurl_cachewhile the media-group path stored them inasset_cache, so repeat sends of the same asset never hit the cache and re-uploaded. (6de9a12) - Notifications and commands now share the Telegram client factory — new
services/telegram_send.pyis the single construction path forTelegramClient: always wires the shared aiohttp session and bothfile_idcaches.send_replyandsend_media_groupincommands/handler.pynow delegate to the factory instead of constructing their own uncached clients, so commands reusefile_ids populated by notification dispatches (and vice versa) instead of re-uploading the same bytes. (6de9a12) - Single rule for
/video/playbackvs thumbnail URLs — extractedbuild_asset_media_urlsso the notification dispatcher'sasset_to_mediaand the bot command handlers'common._format_assetsagree on when to use the playback URL and when to use the thumbnail. Removes a subtle drift that could show stills in one path and video in the other for the same asset. (6de9a12)
All Commits
- 6de9a12 — fix(telegram): unify send routine across notifications and commands (alexei.dolgolyov)
Changelog
e648160chore: release v0.2.7
6de9a12fix(telegram): unify send routine across notifications and commandsDownloads
- Single-asset sends now hit the asset cache —
-
Notify Bridge 0.2.6
StableRelease / release (push) Successful in 1m19sreleased this
2026-04-22 16:29:24 +03:00 | 92 commits to master since this releasev0.2.6 (2026-04-22)
Bug-fix release. Notably: saving settings was silently overwriting the
Telegram webhook secret with its own display mask, invalidating HMAC on
every webhook-mode bot after any settings save. Also fixes template-editor
variable discovery for provider-specific command slots (/search,/status,
/repos,/issues,/boards), asset enrichment (city / country / favorite)
for Immich/search//find//person//place, and video rendering
in command media groups.Bug Fixes
- Don't clobber the Telegram webhook secret with its mask on save —
GET /settingsreturns the secret masked as***<last4>; the frontend bound that masked value into state and shipped it back on any Save, so the PUT handler persisted the mask as the new secret. The next GET re-masked the mask to itself, so the UI showed no corruption while HMAC verification silently broke for every webhook-mode bot. Incoming values that begin with***are now treated as unchanged; empty strings still clear the secret explicitly. Operators running webhook-mode bots should save the page once with a known-good secret after upgrading. (8531168) - Surface Variables button / autocomplete for provider-specific command slots — the command-template-configs UI only resolved slot variables against the shared catalog, so Immich's
/searchand/status, Gitea's/repos//issues, and Planka's/boardsoffered no autocomplete. It now resolves against the active provider (varsRef[provider_type][slot]) first, falling back to shared entries. (fab6169) - Enrich raw Immich search results through
build_asset_dict—/search,/find,/person,/placepreviously handed raw API rows to templates, socity/country(fromexifInfo) andis_favorite(mapped fromisFavorite) were missing and templates couldn't render location or favorite indicators. Now normalised the same way as notification events. (fab6169) - Videos render correctly in command media groups —
/latest,/random,/favoriteswere sending videos as still thumbnails because the media-group path duplicated asset-typing logic. Extractedbuild_telegram_asset_entryinto a shared helper so the notification dispatcher and command groups agree on video typing and/video/playbackURLs. (fab6169) - Command media groups reuse the Telegram
file_idcache —send_media_groupwas re-uploading assets on every repeat command instead of honoring the cache the notification dispatcher already populates. Now shares the cache, avoiding re-upload churn. (fab6169)
All Commits
Changelog
325eabdchore: release v0.2.6
fab6169fix(commands): enrich search assets, surface variables for all command slots
8531168fix(settings): don't clobber webhook secret with its mask on saveDownloads
- Don't clobber the Telegram webhook secret with its mask on save —
-
Notify Bridge 0.2.5
StableRelease / release (push) Successful in 1m9sreleased this
2026-04-22 15:56:20 +03:00 | 95 commits to master since this releasev0.2.5 (2026-04-22)
Hotfix release on top of v0.2.4 — the settings page couldn't save numeric
fields after the cache-TTL / max-entries rework. See v0.2.4 notes for the
main changes (thumbhash-validated cache, settings UX overhaul, mobile-nav
parity).Bug Fixes
- Accept numeric values in settings update payload — Svelte's
bind:valueon<input type="number">coerces to a JS number, and Pydantic v2 wouldn't auto-coerceint → str, producing a 422 on every save that touched a numeric setting (TTL, max entries) after v0.2.4. Widened numeric fields toint | str | NoneinSettingsUpdateand normalized tostrbefore persisting. (d7d0a5d)
All Commits
- d7d0a5d — fix(settings): accept numeric values in update payload (alexei.dolgolyov)
Changelog
d7daadachore: release v0.2.5
e04ad16docs: add hotfix note to v0.2.4 release notes
d7d0a5dfix(settings): accept numeric values in update payloadDownloads
- Accept numeric values in settings update payload — Svelte's
-
Notify Bridge 0.2.4
StableRelease / release (push) Successful in 1m18sreleased this
2026-04-22 15:36:08 +03:00 | 98 commits to master since this releasev0.2.4 (2026-04-22)
Telegram media cache rebuilt around thumbhash validation — asset cache
entries now invalidate when the visual content changes, not after a fixed
TTL — plus a settings-page overhaul (cache stats, clear button, timezone /
locale pickers) and full mobile-nav parity with the desktop sidebar.Features
Telegram media cache
- Thumbhash-validated asset cache — dispatcher builds an
asset.id → thumbhashresolver fromevent.added_assets(Immich already populatesthumbhashinextra) and passes it toTelegramClient. Asset-cache entries now invalidate on visual change rather than age. (2be608b) - Configurable cache cap & stats —
TelegramFileCachegets amax_entriesLRU cap (applies in both TTL and thumbhash modes),ttl_seconds <= 0disables TTL entirely, and astats()method exposes per-bucket counts / sizes / oldest+newest timestamps. New settings:telegram_asset_cache_max_entries(default 5000);telegram_cache_ttl_hoursdefault bumped48 → 720(30 days) and is now URL-only. (2be608b) - Cache admin endpoints —
GET /settings/telegram-cache/statsandPOST /settings/telegram-cache/clear.PUT /settingsnow soft-resets the in-memory caches when cache-shaping keys change (on-diskfile_ids preserved). (2be608b)
Settings page
- Cache stats card — per-bucket (URL / asset) counts, cumulative uploaded-to-Telegram byte size, oldest/newest timestamps, and a hint explaining what the size means. Clear-cache button behind a confirm modal. (2be608b)
- New
TimezoneSelectorandLocaleSelectorcomponents replace the raw inputs with IANA-aware searchable pickers. Max-entries input exposed; TTL range widened to0..8760hours (0= disabled). (2be608b)
Mobile nav
- Full sidebar parity in the More panel — now mirrors the desktop sidebar tree (groups + subnodes) so every destination is reachable from mobile. Previously the panel carried a hand-picked flat list that drifted behind newly-added routes. (2be608b)
- Safe-area handling — nav height uses
env(safe-area-inset-bottom); panel bottom +z-indexfixed so page content can no longer visually overlay the bottom bar. (2be608b)
Bug Fixes
update_settingsTypeError —any(await ... for ...)was an async generator (not an iterator) and raised at runtime; replaced with an explicit loop so settings updates actually commit. (2be608b)
Accessibility
- Password-manager association on the password-change form — hidden
usernamefield +autocompletehints on all three password inputs so browsers stop warning and password managers fill correctly. (2be608b) - Telegram webhook secret wrapped in a no-op form with
autocomplete=offto silence DOM/a11y warnings. (2be608b)
All Commits
- 2be608b — feat(cache): thumbhash-validated asset cache + settings UX overhaul (alexei.dolgolyov)
Changelog
93df538chore: release v0.2.4
2be608bfeat(cache): thumbhash-validated asset cache + settings UX overhaulDownloads
- Thumbhash-validated asset cache — dispatcher builds an
-
Notify Bridge 0.2.3
StableRelease / release (push) Successful in 1m17sreleased this
2026-04-22 03:30:45 +03:00 | 100 commits to master since this releasev0.2.3 (2026-04-22)
Bot-command scope hardening: commands now see only what their chat is wired to
receive notifications about, closing a leak where a bot serving multiple chats
exposed the whole provider catalog to every chat. Plus a handful of Immich
command fixes (missingpublic_urlenrichment, silently-swallowed search errors,
always-on link previews).Features
- Per-chat album scope derived from notification routing — for a
(provider, bot, chat_id)triple, the allowed album set is now computed by walkingTargetReceiver → NotificationTarget → NotificationTrackerTarget → NotificationTrackerand unioning the collection IDs./albums,/random,/search,/find,/latest,/memory,/summary,/favorites,/place,/person,/status,/eventsall intersect their results with the resolved scope. Chats with no notification routing for a tracker return nothing rather than leaking the provider's catalog. (3b76a09) - Scope modal relabeled — the per-listener
allowed_album_idsUI is now explicitly an override for this bot (escape hatch when you want a divergent scope for a whole bot); the default is derive from notification routing, which matches what operators have already configured elsewhere. (3b76a09) - Drop tracker counts from
/status—trackers_active/trackers_totalwere per-provider aggregates that would leak info about trackers a chat has no visibility into. Immich default/statustemplates (en, ru) now show only Albums + Last event; the template-editor variable catalog no longer suggests the removed vars for the Immich/statusslot. Note: custom templates that reference{{ trackers_active }}/{{ trackers_total }}need to be updated. (5a232f1)
Bug Fixes
/albumshonors per-chat scope — previously ignoredCommandTrackerListener.allowed_album_idsand listed every album tracked by the provider, so scoped chats saw neighbours' albums. Now applies the same intersect filter the/_cmd_immichmedia commands use. (4ff3876)- Disable Telegram link previews on command text replies — listings (
/albums,/events,/people, …) embed multiple links and were rendering a preview for the first URL regardless of the operator's Disable link previews toggle.send_replynow always passesdisable_web_page_preview=True. (4ff3876) - Restore
public_urlenrichment on/search,/find,/person,/place—_enrich_assets's return value was being discarded, dropping the public URL populated on each asset. Now assigned properly. (3b76a09) - Surface Immich search errors instead of silently returning
[]—search_smart/search_metadataconsolidated into a_search_itemshelper that logs non-200 responses and transport errors, and accepts the alternate{"assets": [...]}flat-list shape from older Immich versions. "Always no results" bugs are now diagnosable. (3b76a09) - Redact Immich search error bodies before they land in server logs — credentials echoed by authenticating proxies no longer leak into logs. (3b76a09)
All Commits
Changelog
5028f15chore: release v0.2.3
5a232f1feat(commands): drop tracker counts from /status
3b76a09feat(commands): per-chat album scope derived from notification routing
4ff3876fix(commands): /albums honors per-chat scope, disable link previewsDownloads
- Per-chat album scope derived from notification routing — for a
-
Notify Bridge 0.2.2
StableRelease / release (push) Successful in 1m0sreleased this
2026-04-22 02:51:10 +03:00 | 104 commits to master since this releasev0.2.2 (2026-04-22)
Patch release — homelab usability fixes on top of v0.2.1. The SSRF hardening
introduced in v0.2.1 blocks outbound requests to RFC1918 / link-local hosts,
which breaks tracking of Immich / Gitea / etc. running on the same LAN.
This release makes the workaround discoverable and enables it by default
in the shippeddocker-compose.yml.Bug Fixes
- Default
NOTIFY_BRIDGE_ALLOW_PRIVATE_URLS=1indocker-compose.yml— the shipped compose is intended for homelab use. The flag is now hardcoded in theenvironment:block (not a${...}substitution) so it works correctly with Portainer's per-stack env panel, which only does compose-file substitution and not runtime container env. Operators running on a public-facing host can drop the line. (4e23d2b)
Documentation
- Surface
NOTIFY_BRIDGE_ALLOW_PRIVATE_URLShint in SSRF rejection errors — theUnsafeURLErrorraised byImmichClientnow tells operators how to allow LAN targets, instead of leaving them to dig through source. (58cba88)
All Commits
- 4e23d2b — chore(compose): hardcode NOTIFY_BRIDGE_ALLOW_PRIVATE_URLS=1 in compose (alexei.dolgolyov)
- f7d51b2 — Revert "chore(compose): default NOTIFY_BRIDGE_ALLOW_PRIVATE_URLS=1 for homelab" (alexei.dolgolyov)
- 3bb0585 — chore(compose): default NOTIFY_BRIDGE_ALLOW_PRIVATE_URLS=1 for homelab (alexei.dolgolyov)
- 58cba88 — docs(immich-ssrf): surface NOTIFY_BRIDGE_ALLOW_PRIVATE_URLS hint in error (alexei.dolgolyov)
Changelog
8321547chore: release v0.2.2
4e23d2bchore(compose): hardcode NOTIFY_BRIDGE_ALLOW_PRIVATE_URLS=1 in compose
f7d51b2Revert "chore(compose): default NOTIFY_BRIDGE_ALLOW_PRIVATE_URLS=1 for homelab"
3bb0585chore(compose): default NOTIFY_BRIDGE_ALLOW_PRIVATE_URLS=1 for homelab
58cba88docs(immich-ssrf): surface NOTIFY_BRIDGE_ALLOW_PRIVATE_URLS hint in errorDownloads
- Default
-
Notify Bridge 0.2.1
StableRelease / release (push) Successful in 1m27sreleased this
2026-04-22 02:35:38 +03:00 | 109 commits to master since this releasev0.2.1 (2026-04-22)
Security-focused release on top of v0.2.0. Hardens the restore/backup flow,
CSRF/SSRF surfaces, JWT revocation on role change, and template-context
leakage; adds a new per-tracking-config quiet hours feature with
app-level IANA timezone support; plus a handful of performance fixes.Features
- Per-tracking-config quiet hours with app-level IANA timezone — new
Timezoneapp setting (defaults toUTC) and aQuiet Hourssection on the Immich tracking-config form. HH:MM windows (including overnight, e.g.22:00–07:00) are interpreted in the configured timezone and suppress all notifications for that tracker. (6c3dd67)
Security
- Signed & verified pending-restore bundles — SHA256 stored in
AppSettingand checked on startup apply; files outsidedata_dirare refused and permissions tightened to0600. (56993d2) - Same-origin check on
POST /api/backup/apply-restart— Bearer-in-localStorage was CSRF-reachable from any XSS'd admin tab; require matchingOrigin/Referer. (56993d2) - JWT
token_versionbumps on demotion — role/username change and admin password reset now bumptoken_versionso already-issued tokens lose admin. Last-admin TOCTOU guarded byCOUNT+ post-commit recheck that rolls back on race. (56993d2) - SSRF guard extended to
ImmichClient.__init__and theexternal_domainsetter — admin-mutable URLs were bypassing the check that webhook / Slack / Discord paths already used. Devscripts/restart-backend.shnow setsNOTIFY_BRIDGE_ALLOW_PRIVATE_URLS=1so homelab Immich instances still work. (56993d2) - Redact & cap Immich error bodies (~120 chars) before they flow into
ActionExecution.error/EventLog.details(both UI-visible). (56993d2) - Deny-list sensitive keys (
api_key,token,secret,password,authorization,cookie, …) in template-context merges so a rogue template cannot exfiltrate provider creds via{{ api_key }}. (56993d2) - Cap user-controlled Immich search params —
query≤ 256,person_ids≤ 50,size≤ 100 — so a Telegram listener cannot DoS upstream. (56993d2) - Stream upload reads with a running byte counter +
Content-Lengthprecheck instead of buffering the full body and then rejecting. (56993d2) - Log Telegram
parse_modefallbacks instead of swallowing silently — template escape bugs now surface in server logs. (56993d2) - Rollback partial imports on pending-restore failure (error recorded on a fresh session). (56993d2)
Performance
- Fix N+1 in
_refresh_telegram_chat_titles— singleINquery instead ofsession.getper chat. (56993d2) - Parallelize album & shared-link fetches in
test_dispatchviaasyncio.gather, and per-receiver Telegram test sends in the notifier with a semaphore of 5. (56993d2) - Early-exit
collect_scheduled_assets(limit=0)so the periodic-summary test path skips the full per-album filter/sample (was O(album_assets)). (56993d2) - Explicit
CREATE INDEX IF NOT EXISTSforevent_log(user_id/action_id/provider_id) so the first boot after upgrade isn't left unindexed for the dashboard query. (56993d2) - Add
AbortControllertimeout (120s) tofetchAuthso uploads/downloads don't hang indefinitely. (56993d2)
All Commits
Changelog
645331dchore: release v0.2.1
6c3dd67feat(tracking): per-config quiet hours with app-level IANA timezone
56993d2fix(security,perf): harden restore, CSRF, token_version + perf passDownloads
- Per-tracking-config quiet hours with app-level IANA timezone — new
-
Notify Bridge 0.2.0
StableRelease / release (push) Successful in 1m20sreleased this
2026-04-22 01:35:24 +03:00 | 112 commits to master since this releasev0.2.0 (2026-04-22)
First feature release since the initial
v0.1.0cut: a broad polish pass across
the backend, frontend, and schema, plus two fixes landed on top.Features
Immich commands & tracking
- Per-chat album scope for Immich commands (
/search,/latest,/memory, etc.) with a new Edit album scope modal on command-tracker listeners (inherit or explicit multiselect) (a7a2b4e) /searchand/findaccept a trailing page number; Immich clientsearch_smart/search_metadatatake apageparam (a7a2b4e)- Auto-organize rules now set the target album's thumbnail to the first added image (falls back to any asset type) when the album has none (a7a2b4e)
Dashboard & status
- Action events (
action_success/action_partial/action_failed) are emitted on every non-dry-run and surfaced on the dashboard with icons, filters, and colors (a7a2b4e) - Clear-events button + confirm modal on the dashboard (
DELETE /api/status/events, scoped to the current user) (a7a2b4e) - Event rows render live tracker/provider/action names via FK join, with snapshot fallback when an entity has been deleted (a7a2b4e)
Backup & restore
- Full backup restore flow: prepare-restore writes a pending marker, a restart banner offers Apply-now / Apply-later, and the lifespan hook applies on next startup and archives under
data/applied_restores/(a7a2b4e) - Manual Create backup button on the Backup page (
POST /api/backup/files, same format as scheduled) (a7a2b4e) apply-restartsends SIGTERM so the lifespan shutdown runs;NOTIFY_BRIDGE_SUPERVISEDenv var gates the button (a7a2b4e)
Users & deletion protection
PATCH /api/users/{id}for username and role changes with a last-admin guard, plus an Edit user modal on the Users page (a7a2b4e)- Deletion protection now returns structured
{message, entity, blocked_by};ApiErrorcarries.blockedByand the newBlockedByModalis wired into 8 deletion flows (a7a2b4e)
Telegram
- Per-receiver locale for Telegram test messages (resolves
TelegramChat.language_overrideper chat instead of applying the first receiver's locale to everyone) (a7a2b4e) - Telegram poller detects the "webhook is active" 409 and auto-calls
deleteWebhookfor bots whose DBupdate_modeis polling (throttled per bot) (a7a2b4e) - New
TelegramClient.get_chatandset_album_thumbnailhelpers (CLAUDE.md rule 6 — all Bot API calls go throughTelegramClient) (a7a2b4e)
Form UX
- Auto-select first available tracking / template / command / config + bot on create forms (trackers, command-trackers, targets, template/command configs) (a7a2b4e)
- Global provider selector is visible even when there is only one provider (a7a2b4e)
- Telegram target
disable_url_previewdefaults totrue(a7a2b4e)
Bug Fixes
- Telegram target list: load chats/listeners before expanding so the slide animation computes the right height (cf4976d)
- Test dispatch falls back to tracker defaults for tracking/template config (matching
load_link_data), distinguishes "no template config linked" vs. "slot missing in linked config", and the frontendtestTrackerTargetnow treats{success:false,error:...}in a 2xx body as a failure instead of flashing a success snack (80c034d) - Immich person-asset lookup switched from the removed
GET /api/people/{id}/assetstoPOST /api/search/metadatawithpersonIds— fixes/personand auto-organize rules silently returning zero candidates on Immich 1.106+ (a7a2b4e) add_assets_to_albumnow surfaces the Immich error body on non-2xx responses (a7a2b4e)- Immich tracker "Checking links" parallelised (concurrency cap 6) (a7a2b4e)
Development / Internal
Schema / Migrations
event_log: adduser_id,action_id,action_name(+ defensive migration and backfill ofuser_idfromnotification_tracker) (a7a2b4e)command_tracker_listener: addallowed_album_ids(a7a2b4e)
Refactors & Internals
- Bounded concurrency (semaphores) in
NotificationDispatcher._preload_asset_dataand_refresh_telegram_chat_titles; chat-title sweep extended to 24h sincesave_chat_from_webhookcovers active chats opportunistically (a7a2b4e) - Periodic-summary test path reuses the shared
collect_scheduled_assetsprimitive (limit=0) so test and production go through one path (a7a2b4e) - New
fetchAuthhelper for multipart/binary calls (reusesapi()'s refresh +ApiErrormapping) (a7a2b4e) parseDatehelper for consistent UTC date rendering (a7a2b4e)
Seeds
- Rename "Default Commands" → "Default Immich Commands";
track_assets_removednow defaults toFalse(a7a2b4e)
All Commits
Hash Message Author cf4976d fix(telegram): load chats/listeners before expanding to fix slide animation height alexei.dolgolyov 80c034d fix(test-dispatch): fall back to tracker defaults, surface soft errors alexei.dolgolyov a7a2b4e feat: large polish pass — UX fixes, per-chat scope, restore/backup, action events alexei.dolgolyov Changelog
fe92b20chore: release v0.2.0
cf4976dfix(telegram): load chats/listeners before expanding to fix slide animation height
80c034dfix(test-dispatch): fall back to tracker defaults, surface soft errors
a7a2b4efeat: large polish pass — UX fixes, per-chat scope, restore/backup, action eventsDownloads
- Per-chat album scope for Immich commands (