-
Notify Bridge 0.10.0
Stablereleased this
2026-06-05 21:04:57 +03:00 | 0 commits to master since this releasev0.10.0 (2026-06-05)
Multi-time-point scheduling for Immich. The single comma-separated "times" text box is replaced with an add/remove list of native HH:MM pickers for the scheduled assets, periodic summary, and memory slots — entering several fire times per day is now discoverable, and the read/write path is hardened end to end. This release also pins
aiohttp<3.14in the backend test environment so the suite stays green against the currentaioresponses. No breaking changes; no migrations required.User-facing changes
Features
- Immich multi-time scheduling UI. A new
TimeListEditorreplaces the comma-separated text box with an add/remove list of native HH:MM pickers for the scheduled-assets, periodic-summary, and memory slots. It dedupes and sorts on save, enforces a per-day cap, collapses on-screen duplicates, and gives each row an aria-label. Keyboard entry is no longer clobbered mid-edit — it syncs from the value prop only on external changes via anuntrackguard (8065e6e) - Per-section save guard. An enabled feature section (scheduled / periodic / memory) must now have at least one time before it can be saved, enforced in the provider descriptor (8065e6e)
- Refreshed copy. New en/ru i18n keys and updated help text for the editor; the dead
invalidTimeListstring was removed (8065e6e)
Bug Fixes
- Server-side
*_timesnormalization. Thetracking_configsAPI now normalizesscheduled_times/periodic_times/memory_timeson every write (validate, dedup, sort, cap at 24), returns 422 on malformed input, and refuses to enable a slot whose times list is empty (8065e6e) - Restored scheduler observability. The scheduler now warns when an enabled slot has zero or dropped fire times, restoring the visibility that was lost when the old per-call warning was removed (8065e6e)
Development / Internal
CI/Build
- Pin
aiohttp<3.14in the backend test install.aioresponses0.7.8 (latest) does not pass thestream_writerkeyword argument that aiohttp 3.14 made required onClientResponse, so every aioresponses-mocked HTTP test failed to construct a response.notify-bridge-coredeclaresaiohttp>=3.9with no upper bound, so CI floated to 3.14.0 — the pin keeps the test environment reproducible in bothbuild.ymlandrelease.ymluntil aioresponses ships an aiohttp-3.14-compatible release (11593ea)
Refactoring
- Shared time-list service. A new
services/time_list.pyexposesnormalize_time_list(raisingTimeListError) and a lenientparse_hhmm_list; the scheduler drops its private parser copy in favour of the shared one (8065e6e)
Tests
- Time-list coverage. New tests for time-list normalization and parsing (including non-ASCII and odd-shaped input) and for the "enabled implies at least one time" validation (8065e6e)
Chores
- Checked-in vex config. A
.vex.tomlenabling semantic embeddings, call-graph, BM25, and auto-update for the vex code-search index (d01e519)
All Commits
Changelog
6877c4dchore: release v0.10.0
d01e519chore: add vex semantic-search config
11593eafix(ci): pin aiohttp<3.14 in backend test deps
8065e6efeat(immich): multi-time-point scheduling for scheduled/periodic/memoryDownloads
- Immich multi-time scheduling UI. A new
-
Notify Bridge 0.9.0
Stablereleased this
2026-05-28 15:33:00 +03:00 | 4 commits to master since this releasev0.9.0 (2026-05-28)
A feature + observability release. The headline additions are per-receiver Telegram options (silent send and forum-topic routing), an oversized-video fallback that bypasses Telegram's 50 MB
sendVideocap by switching tosendDocument, partial-failure visibility on the dashboard via a newdispatch_summaryblock on everyEventLogrow, and an admin diagnostic-mode panel for temporary per-module DEBUG logging with auto-revert. End-to-end correlation IDs (dispatch_id,X-Request-Id) now tie log lines to the database rows they produced. No breaking changes; no migrations required.User-facing changes
Features
- Per-receiver Telegram options. Each Telegram chat receiver can now be configured to send silently (
disable_notification— no sound or vibration on the recipient) and to route into a specific forum topic (message_thread_id) on supergroups with topics enabled. A new cog-icon button on the receiver row opens an inline editor; active options surface as a bell-off icon and a#thread-idchip on the receiver header. The plumbing uses aContextVarbound at the public send entry points, so every internal payload builder (sendMessage,sendPhoto/Video/Document,sendMediaGroup, cache-hit POST) picks them up without a signature change (6a8f374) - Send oversized videos as documents. A new per-target toggle,
send_large_videos_as_documents, falls back tosendDocumentwhen a video would exceed Telegram's 50 MBsendVideolimit. Useful for archival use cases (Immich library shares with users on free Telegram accounts) where the video would otherwise be silently dropped or noisily 413'd. Pairs with the existingsend_large_photos_as_documentstoggle. Translated copy lives undertargets.sendLargeVideosAsDocuments(6a8f374) - Diagnostic mode for temporary DEBUG logging. A new Diagnostics cassette on the Settings page lets an admin flip one module to DEBUG for a bounded window (1 minute to 4 hours) with an automatic revert. Useful for investigating a specific dispatch failure without flooding stderr; the revert reads the current DB-configured
log_levelsat expiry so a setting change made during the window is honored. State is in-memory only — a restart wipes overrides, andsetup_logging()re-applies the DB baseline at boot, so a forgotten override cannot silently survive a deploy (6a8f374) - Partial-delivery visibility in the dashboard. Every event-, watcher-, scheduled-, deferred-, action-, and command-dispatch path now writes a
dispatch_summaryblock ontoEventLog.details: per-target succeeded/failed counts, Telegram mediadelivered_count/skipped_count/failed_count, and a truncated list of error strings. Partial outcomes (one target out of three failed, two of ten assets dropped) are no longer indistinguishable from a clean success (6a8f374) - Inbound request correlation IDs. A new middleware accepts
X-Request-Idfrom the inbound request (so an upstream proxy with its own correlation system can propagate its id) and echoes the value back on the response. Values are sanitised to a bounded charset to prevent CR/LF injection into log lines. The id is bound into log context for every request and copied onto anyEventLogrow written during the same request, so the SPA can surface it for bug reports (6a8f374)
Bug Fixes
- sendMediaGroup byte-budget enforcement. Telegram's
sendMediaGroupenvelope tops out near 50 MB total (multipart bytes including form overhead). Previously the per-item budget admitted items that, when summed, busted Telegram's request cap and 413'd. A new 45 MB total-bytes budget (TELEGRAM_MAX_GROUP_TOTAL_BYTES) splits groups before the overhead pushes us over, with safety margin (6a8f374) - Per-item fallback inside
sendMediaGroup. A stalefile_idreference (cache poisoning by Telegram's GC, or a video that's no longer downloadable from the cached URL) used to silently lose the cached asset because the failed chunk had no re-download path. Each cached item now retains itssource_url+download_headersso the per-item fallback can re-fetch and retry as a single send when itsfile_idPOST returns transient errors (6a8f374)
Development / Internal
Observability
- Shared
dispatch_idacross log lines andEventLogrows. Adisp:<12 hex>correlation id is bound at the top of every dispatch entry point (dispatch_provider_event,check_tracker,dispatch_scheduled_for_tracker,_process_rowin deferred dispatch,run_action, command handler, HA status logger) viaContextVar. Nested dispatcher calls reuse the bound id instead of generating their own, so a single dispatch's log lines and theEventLog.details.dispatch_idfield share one searchable id (6a8f374) enrich_details_with_correlation()helper. New helper innotify_bridge_core.log_contextmerges the bounddispatch_idandrequest_idontoEventLog.detailsdicts at write time without overwriting caller-provided keys. EveryEventLoginsertion site has been migrated to use it (6a8f374)
Architecture
split_media_by_upload_sizeretired. Per-item upload accounting moved onto the new_MediaItemdataclass (upload_bytesproperty) and the splitter logic moved into_send_media_group, where the byte budget and per-item fallback live (6a8f374)- API endpoints for diagnostic mode. New routes under
/api/app-settings/diagnostic-mode(GETlist,POSTactivate,DELETE /{module:path}revert) with admin-auth requirement and a curated module allowlist that blocks the root logger (6a8f374)
Tests
- New suites:
test_diagnostic_mode.py,test_dispatch_summary.py,test_request_correlation.py,test_telegram_media_group_partial.py,test_telegram_per_send_options.py. Total: 294 tests passing (up from 283 in v0.8.2) (6a8f374) - Test scaffolding fix:
_reset_state()intest_diagnostic_mode.pynow also clears the_bg_tasksset so a long-window schedule from one test doesn't pollutelen(_bg_tasks)in the next test's assertion. Cross-loop.cancel()is intentionally skipped — the prior test's loop is closed and cancelling there raisesRuntimeErroron the next test's setup (9aada75)
Documentation
- Six-axis production-readiness review (
/.claude/reviews/) covering backend, frontend, security, performance/DB, UI/UX, and bugs+features. Snapshots the v0.8.1 codebase; informed several items shipped in v0.8.2 and this release (6a8f374) - Functional review of Telegram / Immich / Logging subsystems (
.claude/docs/functional-review-2026-05-28.md). Captures what's in place, in-flight work, and ranked gaps for each subsystem; pairs with the existing feature backlog (6a8f374)
All Commits
Changelog
e2c17ddchore: release v0.9.0
9aada75fix(tests): clear diagnostic_mode _bg_tasks between cases
6a8f374feat: observability, per-receiver Telegram options, oversized-video fallbackDownloads
- Per-receiver Telegram options. Each Telegram chat receiver can now be configured to send silently (
-
Notify Bridge 0.8.2
Stablereleased this
2026-05-22 22:54:00 +03:00 | 7 commits to master since this releasev0.8.2 (2026-05-22)
A production-readiness hardening release that follows up on v0.8.1 with six isolated, low-risk fixes surfaced by a parallel full-codebase review (backend, frontend, security, performance, UI/UX, bugs+features). No breaking changes; no migrations required.
User-facing changes
Security
- Provider
access_tokenmasked in API responses. The provider GET endpoints were leaking plaintext credentials — most importantly Home Assistant long-lived tokens — in their JSON payloads. The field is now masked on read and dropped on edit when the***placeholder is sent back, so the UI can show "set" / "unset" without ever round-tripping the secret. Centralized throughPROVIDER_SECRET_FIELDSso every call site stays in sync (2d59a5b) - Pre-auth resource-exhaustion amplifier closed on webhook ingest. The Gitea provider used to read the 1 MiB request body before checking whether a secret was even configured or whether the request had a signature header — an unauthenticated client could force a body read on every hit. The generic-webhook bearer-token path had the same shape: body read before Authorization check. Both now bail out before consuming the body when the auth precondition fails (2d59a5b)
Bug Fixes
- Home Assistant status-change events no longer silently lost.
ha_status_changedrows are written fromasyncio.create_task(...), butcreate_taskonly keeps a weak reference — the task was being garbage-collected before the row landed, so connection-flap events disappeared. The task handles are now held in a module-level set with adone_callbackto release them on completion (2d59a5b) - Telegram-webhook handler exceptions can no longer leak writes. The catch-all error path in the Telegram inbound endpoint now rolls back the request's SQLAlchemy session before returning, so a handler crash mid-transaction cannot bleed uncommitted state into the next request on the same connection (2d59a5b)
Accessibility
- Toast notifications now announced by screen readers. Added
role="region"on the snackbar container plus per-toastrole/aria-live/aria-atomicattributes, with a localized region name (snackbar.region) in bothenandru(2d59a5b) - Active sidebar link now has an accessible state.
aria-current="page"is now set on the matching nav item, so assistive tech can announce the active route (2d59a5b)
Development / Internal
Refactoring
- Last
provider.type === 'immich'check removed from components. The action-rule editor's "Auto-organize" affordance now consumes asupportsAutoOrganizecapability onProviderDescriptorinstead of branching on the provider type — bringing the rule editor under CLAUDE.md rule 8 (no provider-specific hardcoding in components) (2d59a5b)
Chores
- Synced
.facts-sync.jsonwithclaude-code-facts@cfdafa9. Both previously pending suggestions (venv install for monorepos + hatchling METADATA workaround) were applied upstream; the local queue is empty (a20635a)
Known gaps (tracked for follow-up)
The full-codebase review surfaced more ship-blockers than this release fixes. Each of the items below needs more than a mechanical edit and is tracked in
.claude/reviews/README.md:- Secret encryption at rest
- JWT moved into an HTTP-only cookie
- Alembic adoption (currently
create_all) - Webhook delivery idempotency
- Deferred-dispatch crash window
- Persisted Telegram update watermark
bridge_selfcounter lock
All Commits
Changelog
85a8f1echore: release v0.8.2
2d59a5bfix: production-readiness hardening from full-codebase review
a20635achore: sync .facts-sync.json with claude-code-facts@cfdafa9Downloads
- Provider
-
Notify Bridge 0.8.1
Stablereleased this
2026-05-16 18:33:41 +03:00 | 10 commits to master since this releasev0.8.1 (2026-05-16)
⚠️ Breaking Changes
- Telegram webhook secret is now mandatory.
NOTIFY_BRIDGE_TELEGRAM_WEBHOOK_SECRETmust be set when running Telegram bots in webhook mode — the inbound endpoint returns 401 without it. Polling-mode bots are unaffected (10d30fc) - Generic webhooks with
auth_mode="none"require explicit opt-in. Existing unauthenticated webhook providers must setacknowledge_unauthenticated=truein their config or they will be rejected. Generic webhook ingest is also rate-limited to 60 requests/min per source IP (10d30fc) - Every user now gets a
bridge_selfprovider auto-seeded. It is internal-only and excluded from the "create provider" wizard, but appears in the provider list. Wire it to a Telegram/Email/Matrix target to receive bridge health alerts (10d30fc)
User-facing changes
Features
- Home Assistant provider. New service provider that subscribes to a Home Assistant instance over WebSocket (long-lived connection with auth handshake, exponential-backoff reconnect, area-registry enrichment) and emits 4 event types:
state_changed,automation_triggered,call_service,event_fired. Trackers support entity-glob, domain-allowlist, and exact-id filters via the newTagInputUI control (22127e2) - Home Assistant bot commands.
/status,/entities [glob],/state <entity_id>,/areas— query your HA instance from chat. Multi-command WS sessions reuse a single handshake; sensitive attributes (camera access tokens, entity pictures, etc.) are blocklisted and/stateoutput is capped at 30 attributes to stay within Telegram message limits (22127e2) - Bridge self-monitoring (
bridge_selfprovider). A new internal provider type emits health events from the bridge itself:bridge_self_poll_failures(consecutive tracker poll failures),bridge_self_deferred_backlog(pending defers above threshold),bridge_self_target_failures(consecutive 5xx/network failures per target). Per-user thresholds default to 3 / 100 / 5 and are configurable. Self-loop guard ensures bridge_self failures never count toward target-failure thresholds (10d30fc) - bridge_self bot commands.
/status,/thresholds,/reset,/healthlet operators inspect bridge health and reset counters from chat. Includes Jinja2 templates for both locales (8651767) - On-watch stats scope selector. New icon toggle on the "On watch" provider deck switches between page-scoped stats (legacy) and full-corpus stats that aggregate across every event matching the active filters (dec0839)
Bug Fixes
- Immich periodic summary now honors
periodic_interval_days. A configured 3-day interval was firing every day because the dispatch path never consulted the interval or start date. The scheduler now gates on(today - start_date).days % interval == 0and logsinterval_not_dueskips so operators can distinguish suppressed-by-interval from other skip causes (90f958b) - Planka webhook crash fixed. The handler had a
NameErroron every call when reading the request body — webhook ingest from Planka now works (10d30fc) - HA quiet-hours dropped events.
ha_state_changed,automation_triggered,service_called, andevent_firedwere missing from the deferrable set and were silently dropped during quiet windows. They now defer like every other event type (10d30fc) - Notifier no longer cancels peer sends on a single failure. Switched the per-receiver fan-out to
asyncio.gather(return_exceptions=True); one bad chat won't cancel sends to the rest (10d30fc) - Quiet-hours gate now respects event-type-disabled. When a tracker has the event type disabled, that wins over the deferral path — events are dropped, not stored to be drained later (10d30fc)
- NUT first poll seeds silently. No more spurious
ups_on_batterynotification on the very first poll after adding a NUT provider (10d30fc) - HA disconnect/reconnect now logged. Status changes write
ha_status_*rows to the EventLog so operators can see WS supervisor health in the UI (10d30fc)
Performance
- Jinja2 template compilation cached with
lru_cache(maxsize=512)— repeated renders of the same template no longer reparse the source (10d30fc) - Per-locale render cache in
NotificationDispatcherskips re-rendering identical content for receivers sharing a locale (10d30fc) - Tracker list cached per
provider_idwith a 5s TTL plus explicit invalidation on tracker CRUD — relieves the HA chat-bus rate-query pressure (10d30fc) - Nav-counts collapsed from 16 round-trips to a single
UNION ALL(10d30fc) - HA event_log skips empty events —
assets_added/assets_removedevents with empty payloads are no longer persisted (10d30fc)
Security
- DNS-rebinding SSRF protection.
PinnedResolveris now wired into the shared aiohttp session — outbound URL validation pins the resolved IP for the lifetime of the request (10d30fc) - Mass-assignment guards added on Action create/update; cron expressions with sub-minute granularity are rejected (10d30fc)
- Backup import hardening. JSON depth capped at 10, node count at 100k;
_sanitize_confignow extends to all JSON-typed fields on import (10d30fc) - Telegram
_safe_getwalks redirects manually with SSRF revalidation at every hop (10d30fc) - Bcrypt 72-byte password length cap with a clear
422response (was silently truncating before) (10d30fc) - Webhook payload body redaction. Sensitive substring set extended with
oauth,client_secret,webhook_secret,csrfin both header filter and template-extras filter (10d30fc)
Operations
- Deep healthcheck at
/api/ready— checks DBSELECT 1, scheduler running, HA supervisor presence; returns{ready, checks, errors, version}(10d30fc) - Prometheus metrics at
/api/metrics—deferred_pending,event_log_total,dispatch_duration,poll_failures,send_failures(10d30fc) - New
OPERATIONS.mdcovering deploy, healthchecks, metrics, backup/restore procedures, log handling, common scenarios, and upgrade flow (10d30fc)
Development / Internal
Architecture
- Shared dispatch pipeline. Extracted webhook ingest's event-log + deferred-dispatch + quiet-hours code path from
api/webhooks.pyintoservices/event_dispatch.pyso HA subscription and webhook ingest now share the same pipeline (22127e2) ServiceProviderABC gains optionalsubscribe()for push-style providers;HomeAssistantServiceProvideruses it via a per-provider supervisor task started in the FastAPI lifespan (22127e2)- Provider construction switched from if/elif ladder to factory registry (10d30fc)
- Provider credential resolution unified across all 5 dispatch sites (10d30fc)
NotificationDispatcherhoisted out of the per-tracker loop (10d30fc)
Database
- New UNIQUE indexes:
service_provider.webhook_token,telegram_bot.webhook_path_id, partial UNIQUE ontelegram_bot.bot_id,telegram_chat(bot_id, chat_id),notification_tracker_targetunique link, partial UNIQUE onbridge_selfprovider per user (10d30fc) - Composite
ix_event_log_user_event_type_createdindex (10d30fc) save_chat_from_webhookswitched toON CONFLICT DO UPDATE(was racy under concurrent webhook delivery) (10d30fc)ondelete=CASCADEon user-id FKs (model annotation; app-side cascade delete added for existing data) (10d30fc)delete_notification_trackerconverted from N+1 to bulk DELETE/UPDATE (10d30fc)- Module-level
asyncio.Lockreplaced with lazy_get_lock()pattern (avoids cross-event-loop binding) (10d30fc) - VACUUM INTO snapshot now
PRAGMA integrity_check-verified before being returned (10d30fc) - Batched
receivers/chats/botsinload_link_data(was per-target N+1) (10d30fc) flag_modifiedon JSON column reassignments in deferred_dispatch (10d30fc)
Frontend
- 76
catch (err: any)sites converted toerrMsg(err)helper (10d30fc) globalProviderFiltermade a pure getter; reconciliation moved to a one-time$effectin+layout(10d30fc)- Provider-filter binding simplified — paired
$effects and the_syncingFilterflag removed; now a one-way derived value (10d30fc) entity-cachegot a separate_refreshingflag for background re-fetches so loading spinners don't appear on revalidation (10d30fc)api.ts401 handling rewritten:AuthRedirectErrorclass + dedup_redirectingflag,goto()instead ofwindow.location.href(10d30fc)- Accessibility:
aria-expandedon mobile More menu,role=switch+aria-checkedon Telegram bot toggles (10d30fc) - Provider-specific hardcoding removed: Immich-only block extracted to descriptor
featureDiscoveryHint(10d30fc) - 5
svelte-checknull-narrowing errors fixed inEventDetailModal(10d30fc) - New
TagInputcomponent for free-text glob/domain lists; new toggleConfigFieldtype for HA descriptor (22127e2)
CI/Build
- CI pytest gate added to
.gitea/workflows/build.ymlandrelease.yml(wheel-built install to dodge editable-install slowness on the hosted runner) (10d30fc)
Tests
- New test suites:
test_bridge_self(11),test_gitea_parser(9),test_planka_parser(6),test_immich_change_detector(6),test_backup_roundtrip(1) (10d30fc)
Other
command_syncsnapshot+expunge bot before exitingAsyncSession(was raising on detached-instance access) (10d30fc)- HA
asyncio.shieldnow drains inner task on cancellation (was leaking tasks on supervisor restart) (10d30fc) - APScheduler drain job ID resolution upgraded to seconds (was minute-bucketed; collisions possible) (10d30fc)
- Webhook payload rollback failures now logged (were swallowed) (10d30fc)
All Commits
Hash Message Author 8651767 feat: bridge_self bot commands — status, thresholds, reset, health alexei.dolgolyov 10d30fc feat: production readiness — security, perf, bug fixes, bridge self-monitoring alexei.dolgolyov 22127e2 feat: Home Assistant provider — WebSocket subscription + bot commands alexei.dolgolyov 90f958b fix(server): honor periodic_interval_days for Immich periodic summary alexei.dolgolyov dec0839 feat: on-watch stats scope selector (page vs all) alexei.dolgolyov Changelog
d7c48b0ci: isolate test backend install in venv
66f152efix(tests): green pytest gate for v0.8.1
faaaa39chore: release v0.8.1
8651767feat: bridge_self bot commands — status, thresholds, reset, health
10d30fcfeat: production readiness — security, perf, bug fixes, bridge self-monitoring
22127e2feat: Home Assistant provider — WebSocket subscription + bot commands
90f958bfix(server): honor periodic_interval_days for Immich periodic summary
dec0839feat: on-watch stats scope selector (page vs all)Downloads
- Telegram webhook secret is now mandatory.
-
Notify Bridge 0.8.0
StableRelease / release (push) Successful in 1m55sreleased this
2026-05-12 03:01:06 +03:00 | 18 commits to master since this releasev0.8.0 (2026-05-12)
User-facing changes
Features
- Quiet hours now defer notifications instead of dropping them. Events that arrive during a tracker's quiet window are stored on disk and re-fired at the window end. Asset events for the same
(link, event_type, collection)coalesce so a flurry of adds/removes during the night collapses into a single morning notification (ba199f2) - Upstream release check. New "Release Cassette" in Settings polls a configurable Gitea or GitHub repo on a schedule and surfaces the latest tag in the UI so you know when a newer Notify Bridge is available. Pre-release filtering and interval are operator-configurable; the install ships pointed at this repo's own upstream (ba199f2)
- Frontend polish across the board. New
MetaStripcomponent, expandedEventDetailModal, and i18n additions land alongside cohesive Aurora-glass styling tweaks on most management pages — providers, targets, bots, trackers, command and notification templates, users, actions, layout, and dashboard (ba199f2)
Documentation
- README rewritten to cover every supported provider, target type, bot command, and smart action — including the deploy / env-var matrix (bb5afcc, 4335036)
Development / Internal
Architecture
- New
deferred_dispatchtable with two migrations: anON DELETE SET NULLFK rebuild onevent_log_id(so the daily event-log retention sweep no longer deadlocks against pending defers), and a partial unique index on(link_id, collection_id, event_type) WHERE status='pending'to make coalescing race-safe under SQLite's serializable writes (ba199f2) - Drain scheduler with three layers: a one-shot APScheduler
datejob per window-end (idempotent, minute-bucketed), a 5-minute periodic catch-up scan as safety net for misfire-grace overflow and process-restart gaps, andload_pending_drain_jobsto re-arm scheduled drains on boot (ba199f2) - Release-check provider abstraction (
packages/core/.../release/) with Gitea and GitHub adapters, SSRF-safe outbound URL validation, a registry/factory, and a server-side scheduler probe with cached state and on-settings-change cache invalidation (ba199f2) - Version resolution helper (
packages/server/.../version.py) that returns the max of installed-package metadata vs sourcepyproject.toml— fixes the long-running editable-install bug where bumping the version without reinstalling kept the old number visible in the UI (ba199f2)
Tests
- New test suites:
test_deferred_dispatch.py(drain + coalescing + retention interaction),test_release_provider.py(Gitea and GitHub adapter parsing and error paths), andtest_release_service.py(scheduler-level caching and settings invalidation) (ba199f2)
All Commits
Hash Message Author ba199f2 feat: deferred dispatch, release-check provider, settings polish alexei.dolgolyov bb5afcc docs: expand README with all providers, targets, bot commands, and smart actions alexei.dolgolyov 4335036 docs: sync README deploy section with actual env vars alexei.dolgolyov Changelog
dfd7329chore: release v0.8.0
ba199f2feat: deferred dispatch, release-check provider, settings polish
bb5afccdocs: expand README with all providers, targets, bot commands, and smart actions
4335036docs: sync README deploy section with actual env varsDownloads
- Quiet hours now defer notifications instead of dropping them. Events that arrive during a tracker's quiet window are stored on disk and re-fired at the window end. Asset events for the same
-
Notify Bridge 0.7.2
StableRelease / release (push) Successful in 1m10sreleased this
2026-05-11 00:39:06 +03:00 | 22 commits to master since this releasev0.7.2 (2026-05-11)
Features
- Redesign settings/common with Aurora cassettes — refreshed identity, logging, Telegram, and cache-ledger sections with the new glass/cassette UI (6229bf9)
- Group targets by bot in the targets view and redesign backup settings (a666bad)
- Add
/statuscommand handler for webhook providers (bede928)
Bug Fixes
- Stop event-log flicker on pagination (87cb33c)
All Commits
Hash Message Author 6229bf9 feat(frontend): redesign settings/common with Aurora cassettes alexei.dolgolyov a666bad feat(frontend): group targets by bot, redesign backup settings alexei.dolgolyov bede928 feat(server): add /status command handler for webhook providers alexei.dolgolyov 87cb33c fix(frontend): stop event-log flicker on pagination alexei.dolgolyov Changelog
5d41a39chore: release v0.7.2
6229bf9feat(frontend): redesign settings/common with Aurora cassettes
a666badfeat(frontend): group targets by bot, redesign backup settings
bede928feat(server): add /status command handler for webhook providers
87cb33cfix(frontend): stop event-log flicker on paginationDownloads
-
Notify Bridge 0.7.1
StableRelease / release (push) Successful in 2m11sreleased this
2026-05-07 23:33:09 +03:00 | 27 commits to master since this releasev0.7.1 (2026-05-07)
Features
- Bot command invocations now appear in the dashboard event stream with
command_handled,command_rate_limited, andcommand_failedrows — closing the last user-initiated path that was invisible to the dashboard (35a3008) - Click any event row to open a detail modal with full provenance (bot → chat → issuer → provider), raw
detailsJSON, and per-entity action buttons that deep-link into the relevant list page with the card scrolled into view and pulsing (35a3008) - Configurable event auto-refresh dropdown (Off / 10s / 30s / 1m / 5m), persisted in
localStorage; ticker pauses while the tab is hidden (35a3008) - Smoother event refresh — no more loading-placeholder flicker on auto-refresh; unchanged rows reuse their DOM nodes and identical pages skip re-rendering entirely (b170c2b)
- Page header breadcrumbs are now translated (new
crumbs.*i18n namespace covering all 15 call sites), soRouting · Notification,Operators · Bots, etc. switch with the active language (b170c2b) - Tracker form's Immich feature-discovery banner now offers an
Open Template Configshortcut alongsideOpen Tracking Config, and/template-configs?edit=<id>auto-opens the editor on landing (b170c2b) - Event-type filter, dashboard verb labels, and gradients extended for the three new
command_*types; filled in previously missing i18n keys (common.hide,common.show,commandConfig.noCommandsForProvider) (35a3008) - Telegram issuer info (
from) captured in both poller and webhook paths and persisted underdetails.issuer, whitelisted to identity fields only by_normalize_issuersolanguage_codeand any future PII fields are dropped (35a3008)
Bug Fixes
- Cyrillic glyphs in sidebar nav links, section labels, and monospace badges now render in Geist instead of falling back to Segoe UI / Cascadia / Consolas. Switched to
@fontsource-variable/geist(latin + latin-ext + cyrillic) and added@fontsource/geist-monocyrillic subsets for weights 400/500/600 (73b046f)
Development / Internal
Database
EventLoggains nullablecommand_tracker_id/telegram_bot_idFKs plus deletion-snapshot name columns; idempotent migration (35a3008)/api/statusresolves liveCommandTracker/TelegramBotnames (mirroring the action pattern) and exposestracker_id,command_tracker_id,telegram_bot_idso the frontend can deep-link (35a3008)
Tests
- New
test_command_event_logging.pycovers subject formatting, issuer normalization, the three event branches, and graceful failure when the DB is unreachable; full server suite passing 96/96 (35a3008)
All Commits
Hash Message Author 73b046f fix(frontend): cyrillic glyphs for nav and section labels alexei.dolgolyov b170c2b feat(frontend): smoother event refresh, localized crumbs, template config deep-link alexei.dolgolyov 35a3008 feat: log bot command invocations to the event stream alexei.dolgolyov Changelog
757271dchore: release v0.7.1
73b046ffix(frontend): cyrillic glyphs for nav and section labels
b170c2bfeat(frontend): smoother event refresh, localized crumbs, template config deep-link
35a3008feat: log bot command invocations to the event streamDownloads
- Bot command invocations now appear in the dashboard event stream with
-
Notify Bridge 0.7.0
StableRelease / release (push) Successful in 1m19sreleased this
2026-05-07 14:03:48 +03:00 | 31 commits to master since this releasev0.7.0 (2026-05-07)
Hardened notification stack with shared HTTP base, SSRF protections, secret redaction, and a bounded queue across every provider client; Settings logging selectors switched to icon grids; entity names autogenerate from the chosen type or provider across bots, targets, trackers, actions, and configs.
User-facing changes
Features
- Settings: replace log level and log format dropdowns with icon-grid selectors carrying per-option icons and i18n descriptions (0eb899a)
- Forms: auto-generate entity names from the selected type/provider across bots, targets, notification trackers, command trackers, actions, and tracking/template/command/command-template configs — names update live until you manually edit, then your edit is preserved (5bd63a2)
Reliability & Security
- Notification stack hardening: shared HTTP base, SSRF protections, secret redaction in error logs, and a bounded delivery queue across the dispatcher, receiver, and all provider clients (telegram, discord, email, matrix, ntfy, slack, webhook) (0eb899a)
Development / Internal
Refactoring
- Notifications: extract shared
http_base,redact, and SSRF helpers; refactor dispatcher, queue, receiver, and every provider client onto the new base (0eb899a)
Tests
- New coverage: SSRF hardening, secret redaction, HTTP base, bounded queue, dispatcher aggregation, Telegram media partitioning, email and matrix clients (0eb899a)
Tooling
- Document code-review-graph MCP usage in CLAUDE.md, register
.mcp.json, and gitignore.code-review-graph/(0eb899a)
All Commits
Click to expand
Hash Message Author 0eb899a feat: harden notification stack and switch logging selectors to icon grid alexei.dolgolyov 5bd63a2 feat(frontend): autogenerate entity names from type/provider alexei.dolgolyov Changelog
632e4c1chore: release v0.7.0
0eb899afeat: harden notification stack and switch logging selectors to icon grid
5bd63a2feat(frontend): autogenerate entity names from type/providerDownloads
-
Notify Bridge 0.6.5
StableRelease / release (push) Successful in 1m36sreleased this
2026-04-28 19:10:49 +03:00 | 34 commits to master since this releasev0.6.5 (2026-04-28)
UI polish across the redesign: command-template editing now groups slots into four labelled fieldsets that mirror the notification-template page, modal/popup scrolling no longer drags the page underneath, and Telegram's Discover Chats keeps the existing list visible with a smooth shimmer instead of blanking it to "Loading…".
User-facing changes
Features
- Command template slots grouped into 4 fieldsets: the command-template configs page now mirrors the notification-template layout, splitting slots by name prefix into Command Responses, Error Messages (
rate_limited/no_results), Command Descriptions (desc_*), and Usage Examples (usage_*). The language picker, reset-all button, and slot filter are hoisted above the groups so they apply across all fieldsets, and empty groups are hidden so providers withoutusage_*slots don't render an empty header (04c8e3c)
Bug Fixes
- Modal scroll chaining contained: scrolling past the inner boundary of a modal or popup no longer scrolls the page underneath.
overscroll-behavior: containwas added to every in-modal/popup scroll container — Modal body,EntitySelect,MultiEntitySelect,IconPicker,IconGridSelect,SearchPalette, andTimezoneSelector(9afd38e) - Smoother Telegram Discover Chats refresh: Discover Chats no longer collapses the existing chat list into a "Loading…" placeholder. The initial-load state (
chatsLoading) is now split from the refresh state (chatsRefreshing); rows are keyed bychat.idwith flip+fade animations, the list dims with a sweeping shimmer while the Discover button shows a spinning icon and a "Discovering chats…" label. Honorsprefers-reduced-motion(9afd38e)
Development / Internal
i18n
- Drop orphan
cmdTemplateConfig.commandResponsesHintkey —hints.commandResponsesreplaces it (04c8e3c)
All Commits
Hash Message Author 04c8e3c feat(frontend): group command template slots into 4 logical fieldsets alexei.dolgolyov 9afd38e fix(redesign): contain modal scroll chaining and smooth Telegram chat refresh alexei.dolgolyov Changelog
349e913chore: release v0.6.5
04c8e3cfeat(frontend): group command template slots into 4 logical fieldsets
9afd38efix(redesign): contain modal scroll chaining and smooth Telegram chat refreshDownloads
- Command template slots grouped into 4 fieldsets: the command-template configs page now mirrors the notification-template layout, splitting slots by name prefix into Command Responses, Error Messages (
-
Notify Bridge 0.6.4
StableRelease / release (push) Successful in 1m41sreleased this
2026-04-27 18:27:09 +03:00 | 37 commits to master since this releasev0.6.4 (2026-04-27)
Fixes Telegram chat actions: the indicator the user picks in the UI is now actually sent, and the phantom "typing…" bubble that lingered for ~5s after a notification arrived is gone.
User-facing changes
Bug Fixes
- Telegram chat action UI choice now respected:
chat_actionwas stored in two places — the model column and the config JSON — and dispatch unconditionally overrode the config value with the column. The frontend only ever wrote the JSON path, so picking "upload_photo" / "record_voice" / etc. in the UI silently had no effect on outgoing chat actions. The column is now the single source of truth: the frontend sendschat_actiontop-level, dispatch reads from the column, and a one-time migration backfills existing config values into the column and strips the legacy key (72dd611) - Phantom Telegram chat-action indicator: a long-standing race in the keepalive loop (bare
sleep(4)+finally cancel) could fire one lastsendChatActionafter the response had already arrived, leaving a "typing…" / "uploading…" bubble in the chat for ~5 seconds. Replaced with a stop event +wait_forso callers signal stop cleanly via the newstop_keepalivehelper (72dd611)
Development / Internal
Database
- Migration: new one-shot migration moves
chat_actionfromnotification_target.configJSON into the dedicated column on existing rows, then deletes the legacy key from config. No action required — runs automatically on backend start (72dd611)
All Commits
Hash Message Author 72dd611 fix(telegram): respect chat_action UI choice, drop phantom indicator alexei.dolgolyov Changelog
aa9548dchore: release v0.6.4
72dd611fix(telegram): respect chat_action UI choice, drop phantom indicatorDownloads
- Telegram chat action UI choice now respected: