8.2 KiB
8.2 KiB
v0.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 sendVideo cap by switching to sendDocument, partial-failure visibility on the dashboard via a new dispatch_summary block on every EventLog row, 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)