-
Notify Bridge 0.6.3
StableRelease / release (push) Successful in 1m15sreleased this
2026-04-27 15:42:04 +03:00 | 39 commits to master since this releasev0.6.3 (2026-04-27)
Adds user filters for the Gitea tracker, makes the dashboard navigable, removes leftover webhook polling, and fixes the theme/sidebar flash on hard reload.
User-facing changes
Features
- Gitea — sender filters:
NotificationTrackernow exposessender_allowlistandsender_blocklistviaMultiEntitySelect. The picker is populated fromGitea /users/searchmerged with pastEventLogsenders, so it is useful even before the first webhook arrives (42af7a6) - Dashboard navigability: stat cards are now
<a>links that route to providers, trackers, targets, command-trackers, or scroll to the events panel. Provider deck rows highlight the target provider on click (42af7a6) - Command trackers / configs: auto-reselect the matching config when the provider type changes, matching notification-tracker behaviour (42af7a6)
- Webhook providers (gitea, planka, webhook): stop scheduling interval polling jobs on tracker create/update/startup, and hide the misleading "every Xs" indicator in the tracker list — webhook trackers do not poll (42af7a6)
Bug Fixes
- Theme FOUC on hard reload: an inline blocking script in
app.htmlnow resolves the theme fromlocalStorage(orprefers-color-scheme) and setsdata-themeon<html>before first paint, eliminating the dark→light flash users saw when the light theme was selected (b107b01) - Sidebar jump on reload: sidebar collapsed state and expanded nav groups now hydrate synchronously in their
$stateinitialisers instead of insideonMount, so the sidebar no longer snaps from expanded→collapsed and groups no longer slide open after mount (b107b01) - Provider-filter row pop-in: the global provider-filter row now stays rendered while
providersCache.fetchedAt === 0, so it no longer pops in mid-paint and pushes the nav down once the cache resolves (b107b01)
Development / Internal
Build
- Build-time app version:
vite.config.tsnow readsfrontend/package.jsonand exposes its version as an__APP_VERSION__global via Vite'sdefine, with an ambient declaration inapp.d.tsso the layout's brand version badge type-checks (4307955)
Database
- Migration: drop legacy
batch_durationcolumn fromnotification_tracker— the field had been removed from the model but itsNOT NULLconstraint still blocked inserts on older DBs (42af7a6)
Documentation
- Refresh
.claude/docs/entity-relationships.mdwith currentNotificationTrackerfields (filters,adaptive_max_skip,default_*_config_id) (42af7a6)
All Commits
Hash Message Author 4307955 feat(frontend): inject __APP_VERSION__from package.json at build timealexei.dolgolyov b107b01 fix(redesign): prevent theme FOUC and sidebar jump on hard reload alexei.dolgolyov 42af7a6 feat(trackers): user filters for Gitea, webhook polling cleanup, dashboard navigability alexei.dolgolyov Changelog
0e675c4chore: release v0.6.3
4307955feat(frontend): inject APP_VERSION from package.json at build time
b107b01fix(redesign): prevent theme FOUC and sidebar jump on hard reload
42af7a6feat(trackers): user filters for Gitea, webhook polling cleanup, dashboard navigabilityDownloads
- Gitea — sender filters:
-
Notify Bridge 0.6.2
StableRelease / release (push) Successful in 1m39sreleased this
2026-04-27 14:29:44 +03:00 | 43 commits to master since this releasev0.6.2 (2026-04-27)
Polishing pass on locale and timezone pickers in the redesigned UI: editors and selectors now use the same
EntitySelectpalette pattern, and the timezone dropdown is portalled to escape Card clipping.User-facing changes
Bug Fixes
- Template editors (notification & command) now use
EntitySelectfor locale switching and default to the configured primary locale when opening, editing, or cloning a config (previously always defaulted toen) (1bfec52) LocaleSelectoradd-flow now usesEntitySelectfor catalog pick; custom BCP-47 codes (e.g.de-CH) keep a small dedicated input (1bfec52)TimezoneSelectordropdown was being clipped by Card'soverflow: hiddenandbackdrop-filter; portalled to<body>with an overlay backdrop and styled as a centered modal palette (same pattern asEntitySelect) (1bfec52)- Removed top padding on the timezone scroll list so sticky region group headers no longer leak rows above them (1bfec52)
Development / Internal
Refactoring
- Extracted shared locale catalog to
frontend/src/lib/locales.tsfor reuse across selectors (1bfec52)
Changelog
c43dc59chore: release v0.6.2
1bfec52fix(redesign): EntitySelect for language pickers + portal Timezone pickerDownloads
- Template editors (notification & command) now use
-
Notify Bridge 0.6.1
StableRelease / release (push) Successful in 3m17sreleased this
2026-04-25 15:25:23 +03:00 | 45 commits to master since this releasev0.6.1 (2026-04-25)
Small visual follow-up to the Aurora redesign: the Active Wires pipe on the dashboard now reads more prominently.
User-facing changes
Bug Fixes
- Make Active Wires pipe visually prominent (cc8d961)
Changelog
b320090chore: release v0.6.1
cc8d961fix(redesign): make Active Wires pipe visually prominentDownloads
-
Notify Bridge 0.6.0
StableRelease / release (push) Successful in 1m25sreleased this
2026-04-25 14:54:16 +03:00 | 47 commits to master since this releasev0.6.0 (2026-04-25)
This release ships the Aurora redesign of the frontend — a glass-and-tokens visual language applied across the dashboard, sidebar, page headers, and overlays — together with per-chat command localization for the Telegram bot.
User-facing changes
Features
Frontend — Aurora redesign
- Aurora foundation: design tokens, glass sidebar, redesigned dashboard (d9ef3c6)
- Project mockup richness onto the live dashboard (d3210fd)
- Subpage hero header, IconPicker portal, tighter gaps (9733e5c)
- Roll subpage hero across all pages, plus Aurora Button, JinjaEditor, and pulse fix (d662b50)
- Stack PageHeader meter top-right, action button bottom-right (9643fe5)
- Collapsible dashboard sections + glass mobile-more sheet (9eb76c1)
Telegram
- Per-chat command localization with a unified locale resolver (ef942b7)
Bug Fixes
- Portal IconGridSelect popup + snap navbar to mockup (0105d9f)
- Brand snap, event sentences, palette glass, full-width layouts (1895c5e)
- Align topbar horizontal padding with page content (46a4a6e)
- Portal overlays + solid popup surfaces for legibility (d356e5a)
- A11y, mobile, and perf polish for production push (711f218)
Development / Internal
Chores
- Add Aurora redesign mockups + chooser under
design-mockups/(1e35724)
All Commits
Hash Message Author ef942b7 feat(telegram): per-chat command localization + unified locale resolver alexei.dolgolyov 711f218 fix(redesign): a11y, mobile, perf polish for production push alexei.dolgolyov 9eb76c1 feat(redesign): collapsible dashboard sections + glass mobile-more sheet alexei.dolgolyov d356e5a fix(redesign): portal overlays + solid popup surfaces for legibility alexei.dolgolyov 9643fe5 feat(redesign): stack PageHeader meter top-right, button bottom-right alexei.dolgolyov d662b50 feat(redesign): roll subpage hero across all pages + Aurora Button + JinjaEditor + pulse fix alexei.dolgolyov 9733e5c feat(redesign): subpage hero header + iconpicker portal + tighter gaps alexei.dolgolyov 46a4a6e fix(redesign): align topbar horizontal padding with page content alexei.dolgolyov 1895c5e fix(redesign): brand snap, event sentences, palette glass, full width alexei.dolgolyov 0105d9f fix(redesign): portal IconGridSelect popup + snap navbar to mockup alexei.dolgolyov d3210fd feat(redesign): project mockup richness onto live dashboard alexei.dolgolyov d9ef3c6 feat(redesign): aurora foundation — tokens, glass sidebar, dashboard alexei.dolgolyov 1e35724 chore(design): add aurora redesign mockups + chooser alexei.dolgolyov Changelog
9eb478fchore: release v0.6.0
ef942b7feat(telegram): per-chat command localization + unified locale resolver
711f218fix(redesign): a11y, mobile, perf polish for production push
9eb76c1feat(redesign): collapsible dashboard sections + glass mobile-more sheet
d356e5afix(redesign): portal overlays + solid popup surfaces for legibility
9643fe5feat(redesign): stack PageHeader meter top-right, button bottom-right
d662b50feat(redesign): roll subpage hero across all pages + Aurora Button + JinjaEditor + pulse fix
9733e5cfeat(redesign): subpage hero header + iconpicker portal + tighter gaps
46a4a6efix(redesign): align topbar horizontal padding with page content
1895c5efix(redesign): brand snap, event sentences, palette glass, full width
0105d9ffix(redesign): portal IconGridSelect popup + snap navbar to mockup
d3210fdfeat(redesign): project mockup richness onto live dashboard
d9ef3c6feat(redesign): aurora foundation — tokens, glass sidebar, dashboard
1e35724chore(design): add aurora redesign mockups + chooserDownloads
-
Notify Bridge 0.5.2
StableRelease / release (push) Successful in 1m48sreleased this
2026-04-24 21:58:40 +03:00 | 61 commits to master since this releasev0.5.2 (2026-04-24)
Two related improvements to the notification-tracker stack: the display-filter fields on
TrackingConfig(favorites-only, sort, max-assets, strip-tags, strip-asset-details) are now actually honored by every dispatch path — they previously existed in the model but were silently ignored on watcher / webhook / scheduled / memory / test fires. And the fixedbatch_durationknob onNotificationTrackeris replaced by a per-trackeradaptive_max_skip, so quiet trackers can opt into back-off without affecting busy ones.Features
- Tracking-config display filters wired into every dispatch path — the filter fields on Immich
TrackingConfignow apply consistently across watcher events, inbound webhooks, scheduled / periodic / memory cron fires, and manual test dispatch (ab621b6):favorites_onlydrops events with no favorited new assets, or filtersadded_assetsdown to favorites onlyassets_order_by/assets_ordersort the rendered list (date / name / rating / random / none)max_assets_to_showcaps rendered + attached media (default raised from 5 → 10)include_tagsstrips people from event extras and tags from each asset when disabledinclude_asset_detailsstripscity/country/state/lat/lon/is_favorite/rating/descriptionwhen disabled — load-bearing fields (thumbhash,file_size,playback_size, cache keys) are preserved either way- New
apply_tracking_display_filtershelper indispatch_helpersis the single source of truth - Targets sharing a
TrackingConfigare dispatched together; targets with different configs each see their own shaped event
- Per-tracker adaptive polling — replaces the global-feeling
NotificationTracker.batch_durationwithadaptive_max_skip, an opt-in cap on poll back-off (ab621b6):NULL/0→ disabled, every tick runs (previous default behavior preserved)- Positive
N→ caps the skip factor at(N-1)-in-Nafter a long idle stretch - Scheduler caches the cap in module state for the tick fast-path
- Migration adds the new column; API schemas / responses, frontend types, i18n, and the tracker form are all updated to match
Upgrade Notes
batch_duration→adaptive_max_skiponNotificationTracker. The migration runs automatically; existing trackers default to disabled (every tick polls), matching previous behavior. Set a positive value per-tracker if you want quiet trackers to back off.- Default
max_assets_to_showis now 10 (was 5). Existing tracking configs with a stored value are unaffected; only the default for newly created configs (or unset fields) changes. If you relied on the 5-asset implicit cap, set it explicitly. - Display filters now actually take effect. If you had configured
favorites_only,include_tags,include_asset_details, etc. previously and expected them to do something — they will now. Review your tracking configs after upgrade if you don't want the filtering applied.
All Commits
Hash Message Author ab621b6 feat: wire tracking-config display filters + per-tracker adaptive polling alexei.dolgolyov Changelog
770c198chore: release v0.5.2
ab621b6feat: wire tracking-config display filters + per-tracker adaptive pollingDownloads
- Tracking-config display filters wired into every dispatch path — the filter fields on Immich
-
Notify Bridge 0.5.1
StableRelease / release (push) Successful in 1m49sreleased this
2026-04-24 19:21:39 +03:00 | 63 commits to master since this releasev0.5.1 (2026-04-24)
Extends the Immich scheduled/memory dispatch shipped in v0.5.0 with a per-album fan-out mode and rich multi-album templates, adds "Reset to default" tooling and an inline preview modal for notification / command templates, and introduces a
nonelistener mode for Telegram bots (safer default for shared-token deployments). Also fixes an infinite-recursion bug in the notification dispatcher that was breaking test dispatch for periodic / scheduled / memory slots.Features
- Per-album Immich dispatch for scheduled / memory slots — honors the new
{kind}_collection_modeonTrackingConfig:per_collectionfans out one event per album,combinedpools assets as before. Combined mode now attachesalbum_name/album_url/album_public_urlto each asset so templates can attribute rows to their source album. Defaultscheduled_assetsandmemory_modetemplates render a multi-album header with an inline album list and per-row album link. The cron and test-dispatch paths now share a singlebuild_immich_dispatch_eventshelper (b61394f). - "Reset to default" for template slots — new per-slot and whole-template reset buttons on notification and command template configs, backed by
GET /*-template-configs/defaultsendpoints. Confirmations use the app'sConfirmModalinstead ofwindow.confirm(b61394f). - Inline template preview + deep-link edit — tracking-configs "Preview template" now opens an inline preview modal with locale tabs instead of navigating away. The Edit button deep-links with
?edit_slot=<name>so the destination auto-opens the config and scrolls to the requested slot (b61394f). - Telegram bot
nonelistener mode — third option alongside polling and webhook. Disables both long-polling and webhook delivery; useful when another instance owns the listener or the bot is send-only. Switching intononeunschedules polling and unregisters the active webhook so Telegram stops delivering updates (be15463).
Bug Fixes
- Fix
NotificationDispatcher._session_ctxinfinite recursion when no sharedaiohttp.ClientSessionwas passed — broke test dispatch for periodic / scheduled / memory slots (cron path was unaffected) (b61394f). telegram-bots /chats/{id}/testnow resolveschat.language_override/language_codeinstead of using the raw?localequery param, matching the resolution the tracker-target test endpoint already used (b61394f).- Default
scheduled_assetstemplate no longer emits a blank line between the header and the first asset when the multi-album branch is taken (b61394f).
Upgrade Notes
- New Telegram bots default to
none(safer when multiple bridges share a token). Existing bots upgraded from a pre-update_modeschema keeppolling, so their behavior is unchanged. When creating a new bot, explicitly switch topollingorwebhookif you want it to receive updates. - A new
{kind}_collection_modefield was added toTrackingConfigfor Immich scheduled/memory slots. Existing trackers keep the previouscombinedbehavior by default; switch toper_collectionper-tracker to opt in to one-event-per-album fan-out.
All Commits
Hash Message Author b61394f feat(immich): per-album scheduled/memory dispatch + template tooling alexei.dolgolyov be15463 feat(telegram): add 'none' listener mode for bots alexei.dolgolyov Changelog
187b889chore: release v0.5.1
b61394ffeat(immich): per-album scheduled/memory dispatch + template tooling
be15463feat(telegram): add 'none' listener mode for botsDownloads
- Per-album Immich dispatch for scheduled / memory slots — honors the new
-
Notify Bridge 0.5.0
StableRelease / release (push) Successful in 1m10sreleased this
2026-04-24 14:16:34 +03:00 | 66 commits to master since this releasev0.5.0 (2026-04-24)
A small but impactful release that finally makes the Immich scheduled / periodic / memory dispatch fire on its own. The slot was already visible in the tracker UI and the "Test" button worked — but no production scheduler was reading the config, so users only ever saw fires through manual tests. This release wires the missing cron jobs end-to-end.
Features
- Cron-fired Immich dispatch for scheduled / periodic / memory slots — adds the missing production fan-out so
scheduled_enabled/scheduled_times(and the periodic / memory counterparts) onTrackingConfigactually fire on their own, not only through "Test" (309dec2):- New
services/scheduled_dispatch.pyreuses the test-path event builders, picks the slot template per kind (scheduled_assets/periodic_assets/memory_assets), and writes anEventLogrow per fire so the dashboard reflects it. services/scheduler.pygains_load_immich_dispatch_jobs, which builds oneCronTriggerper(tracker, kind, HH:MM)from each tracker's defaultTrackingConfig, all keyed off the app-level IANA timezone.reschedule_immich_dispatch_jobsrebuilds the job set on any relevant CRUD or timezone change.- Tracker / link / tracking-config CRUD endpoints now invalidate the schedule, so edits take effect immediately without a restart.
- Dispatch is skipped when scheduled / memory queries yield zero matching assets — prevents header-only "On this day:" spam when nothing qualifies.
- EN / RU default
scheduled_assetstemplates updated to surface that the delivery is a scheduled random selection.
- New
Upgrade Notes
- No config changes required. Existing
scheduled_enabled/scheduled_times/periodic_*/memory_*settings on tracking configs will start firing automatically on the next startup. - If you had been relying on the "Test" button as a workaround, you can stop doing that now.
All Commits
Hash Message Author 309dec2 feat(immich): wire cron-fired scheduled/periodic/memory dispatch alexei.dolgolyov Changelog
461fb49chore: release v0.5.0
309dec2feat(immich): wire cron-fired scheduled/periodic/memory dispatchDownloads
- Cron-fired Immich dispatch for scheduled / periodic / memory slots — adds the missing production fan-out so
-
Notify Bridge 0.4.0
StableRelease / release (push) Successful in 1m3sreleased this
2026-04-23 21:12:17 +03:00 | 68 commits to master since this releasev0.4.0 (2026-04-23)
A production-readiness release focused on hardening the service for real-world deployment: end-to-end structured logging with runtime controls, a broad security and runtime review across the HTTP, auth, DB, and scheduler layers, and a new pre-migration database snapshot that makes upgrades recoverable with a single file restore. Release CI and the Docker image build were also reworked for speed and reliability.
Features
- Production-grade logging with per-request correlation (
request_id/command/chat_id/bot_id/dispatch_id), secret masking in both messages and tracebacks, JSON or text format, runtime log level + per-module overrides editable from the settings UI, and env-var boot overrides (NOTIFY_BRIDGE_LOG_LEVEL/_FORMAT/_LEVELS). Closes every silent drop in the Telegram send path —/randomand media-group failures now logWARN/ERRORwith full context instead of disappearing (f50d465) - Production-readiness hardening across security, async, DB, and ops (920920b):
- Security: async SSRF-safe DNS resolver;
allow_redirects=Falseon all outbound clients; Matrixhomeserver_urlvalidation; rejection of***-masked secrets on provider / email-bot updates; bcrypt moved off the event loop; JWTiss/aud+ leeway with strict claim rejection; setup TOCTOU closed inside a transaction; expanded rate limits; constant-time login; config rejects known dev secret keys and validates CORS / ports / token lifetimes; webhook bodies capped at 1 MiB; Discord 429 retries bounded; CSP + HSTS headers added. - Async / runtime: SQLite engine tuned (WAL,
synchronous=NORMAL,foreign_keys=ON, busy timeout, pool pre-ping); ordered lifespan shutdown; sharedaiohttpsession race-free; blocking storage / backup writes offloaded to threads; NUT client timeouts; Telegram poller switched from 3 s short-poll to 30 s + 25 s long-poll (~10x fewer API calls). - Database: new performance-index migration covering every FK and hot-path composite; new
schema_versiontable;__system__placeholder user (id=0) seeded to satisfy FKs;list_notification_trackersrewritten from1+N+N*Mto batched loads; retention job extended to event / webhook / action-execution logs. - Scheduler:
AsyncIOSchedulerjob defaults set (coalesce,misfire_grace_time=300,max_instances=1). - Ops: uvicorn runs with
proxy_headers/forwarded_allow_ips/ graceful shutdown timeout; access log suppressed outside debug; FastAPI version read fromimportlib.metadata; new/api/readyendpoint; docker-compose adds resource / PID limits,read_only+ tmpfs,cap_drop: ALL,no-new-privileges, drops theALLOW_PRIVATE_URLS=1default, and points healthcheck at/api/ready. - Frontend:
/loginredirects already-authenticated users to/and shows a distinct "backend unreachable" banner (en / ru) when/auth/needs-setupfails.
- Security: async SSRF-safe DNS resolver;
- Pre-migration SQLite snapshots via
VACUUM INTOat lifespan startup — takes a consistent, atomic copy of the DB before migrations run, so a botched upgrade is recoverable by restoring a single file. Safe under WAL; best-effort (failures log but never raise); configurable viaNOTIFY_BRIDGE_PRE_MIGRATE_SNAPSHOT_KEEP(default 5; 0 disables). Snapshots land indata_dir/backups/pre-migrate-<ts>.dband the N oldest are pruned each boot (7cbb02b)
Bug Fixes
- Allow
unsafe-inlinescripts in CSP so SvelteKit's hydration bootstrap inline<script>runs in production — without it the frontend failed to hydrate under the hardened CSP introduced in this release (8f0346e)
Upgrade Notes
ALLOW_PRIVATE_URLS=1is no longer set by default indocker-compose.yml. If your deployment targets private network URLs, set it explicitly.- Docker healthchecks now probe
/api/ready(separate from/api/health); update any external monitors accordingly. - Config startup now rejects known dev secret keys — set real values (e.g.
JWT_SECRET) before upgrading. - Log format and level can now be changed at runtime from the settings UI; the
log_formatfield still requires a restart to apply (aWARNis logged noting this).
Development / Internal
Tests
- New
packages/server/tests/suite with 29 passing tests: config validation; JWT round-trip andaud/alg=nonerejection; SSRF scheme and private-range enforcement (sync + async); Discord bounded retry; a lifespan-level/api/health+/api/readysmoke check.services/test_dispatch.pyrenamed tomanual_dispatch.pyso pytest no longer auto-collects production code (920920b)
CI / Build
- CI now runs on push / PR with frontend
svelte-check+ build, and a non-push image build. Release workflow is gated on tests and publishes an immutablesha-<commit>image tag (920920b) - Install editable packages inside a venv (2bec253)
- Cache pip downloads and collapse install into a single pip call (3b683ce)
- Drop backend pytest from Gitea CI — editable install is too slow on the hosted runner (f904037)
- Skip
build.ymlon release commits to avoid redundant runs (bbcdf1c) - Drop Trivy scan from release (output was discarded and it never failed) (19036a9)
Performance
- Split external Docker deps into a cacheable layer and swap pip for uv for faster image builds (592e1b6)
- Install uv from PyPI instead of the ghcr.io distroless image to avoid slow GHCR pulls on CI (a6a854a)
All Commits
Hash Message Author 8f0346e fix(csp): allow unsafe-inline scripts for SvelteKit hydration bootstrap alexei.dolgolyov a6a854a perf(docker): install uv from PyPI instead of ghcr.io (avoid slow GHCR pulls) alexei.dolgolyov 19036a9 ci: drop trivy scan from release (never failed, output discarded) alexei.dolgolyov 592e1b6 perf(docker): split external deps into a cacheable layer, swap pip for uv alexei.dolgolyov bbcdf1c ci: skip build.yml on release commits alexei.dolgolyov f904037 ci: drop backend pytest stage (too slow on hosted runner) alexei.dolgolyov 3b683ce ci: cache pip downloads and collapse install into one pip call alexei.dolgolyov 2bec253 ci: install editable packages inside a venv alexei.dolgolyov 7cbb02b feat(db): pre-migration SQLite snapshots via VACUUM INTO alexei.dolgolyov 920920b feat: production-readiness hardening across security, async, DB, ops alexei.dolgolyov f50d465 feat(logging): production-grade logging with context vars, secret masking, and runtime level control alexei.dolgolyov Changelog
90def11chore: release v0.4.0
8f0346efix(csp): allow unsafe-inline scripts for SvelteKit hydration bootstrap
a6a854aperf(docker): install uv from PyPI instead of ghcr.io (avoid slow GHCR pulls)
19036a9ci: drop trivy scan from release (never failed, output discarded)
592e1b6perf(docker): split external deps into a cacheable layer, swap pip for uv
bbcdf1cci: skip build.yml on release commits
f904037ci: drop backend pytest stage (too slow on hosted runner)
3b683ceci: cache pip downloads and collapse install into one pip call
2bec253ci: install editable packages inside a venv
e44d387chore: release v0.4.0
7cbb02bfeat(db): pre-migration SQLite snapshots via VACUUM INTO
920920bfeat: production-readiness hardening across security, async, DB, ops
f50d465feat(logging): production-grade logging with context vars, secret masking, and runtime level controlDownloads
- Production-grade logging with per-request correlation (
-
Notify Bridge 0.3.2
StableRelease / release (push) Successful in 1m22sreleased this
2026-04-23 13:38:28 +03:00 | 81 commits to master since this releasev0.3.2 (2026-04-22)
Scheduler now honors the app-level timezone. Before this, a cron expression
like0 9 * * *was firing at 09:00 in the server's host-local tz — not
at 09:00 in the timezone the admin configured under Settings — because
CronTrigger.from_crontabwas constructed without a tz. Same fix extends
to scheduler-provider template rendering so{{ current_date }}/{{ current_time }}
match the configured tz, and scheduled firings now show up in the dashboard
event feed with context.Bug Fixes
- Cron triggers honor app timezone — all tracker and action cron triggers are now built with the configured app tz;
CronTriggerfreezes its tz at construction, so thePUT /settingsendpoint rebuilds existing cron jobs when the timezone changes. Scheduled messages that were silently firing at host-local time will fire at the intended time after upgrade. (1024085) - Scheduler template context renders in the app tz —
current_date,current_time,current_datetime,current_weekdayin scheduler-provider templates are now formatted in the configured timezone instead of UTC/host-local. Custom templates that built date strings in the wrong tz now render correctly. (1024085)
Features
- New
timezonetemplate variable — scheduler-provider templates can reference{{ timezone }}to display the active IANA tz alongside a date/time. Added across the context builder, variable catalog, sample context, and runtime validator (per the project's 6-file sync rule for template vars). (1024085) scheduled_messageevents surface in the dashboard feed —EventLogentries for scheduled firings now carryschedule_type,cron_expression/interval_seconds,timezone, andfire_count; the dashboard renders them with a dedicated label, icon, and colour so operators can see at a glance when scheduled messages actually fired. (1024085)
All Commits
- 1024085 — fix(scheduler): honor app timezone for cron triggers and log scheduled events (alexei.dolgolyov)
Changelog
1f880dachore: release v0.3.2
1024085fix(scheduler): honor app timezone for cron triggers and log scheduled eventsDownloads
- Cron triggers honor app timezone — all tracker and action cron triggers are now built with the configured app tz;
-
Notify Bridge 0.3.1
StableRelease / release (push) Successful in 1m1sreleased this
2026-04-22 19:27:45 +03:00 | 83 commits to master since this releasev0.3.1 (2026-04-22)
Follow-up perf pass on top of v0.3.0's polling overhaul — extends the same
caching discipline to the bot-command read paths so repeat/random,
/latest,/memory, etc. against the same album don't each refetch a
multi-megabyte album body or pay for a full server-wide/api/shared-links
listing.Performance
- TTL-cache
GET /api/albums/{id}responses — 60 s TTL, 32-entry FIFO cap, keyed by(server_digest, album_id). Module-scoped rather than instance-scoped becauseImmichClientis constructed fresh per request in several places (api/providers.py,services/action_runner.py, command handlers), so an instance cache would never survive a second caller. Mirrors the existing_users_cachepattern. (3b7808a) - TTL-cache the bucketed shared-links map — 60 s TTL, keyed by server digest.
/api/shared-linkshas no per-album filter, so everyget_shared_links(album_id)call was already paying for the full server-wide list; now one fetch serves every album until the TTL elapses. (3b7808a) - Collapse concurrent cache misses to one fetch — async lock with an under-lock re-check around the album / shared-links populate step, so a burst of parallel commands hitting the same cold key issues one HTTP call instead of N. (3b7808a)
use_cache=Falseescape hatch on mutation / event-detection paths —ImmichActionExecutor.execute(which diffs the current album state to decide what to add) andImmichServiceProvider.poll's full-fetch path (where a stale entry would silently delay asset-removal events) explicitly bypass the cache. Non-cached fetches still populate it for subsequent readers. (3b7808a)
All Commits
- 3b7808a — perf(immich): TTL cache for album bodies and shared-link listings (alexei.dolgolyov)
Changelog
5604c73chore: release v0.3.1
3b7808aperf(immich): TTL cache for album bodies and shared-link listingsDownloads
- TTL-cache