From 5028f15f4fb30b42a95825e37f5deabc9a47a8d4 Mon Sep 17 00:00:00 2001 From: "alexei.dolgolyov" Date: Wed, 22 Apr 2026 03:30:45 +0300 Subject: [PATCH] chore: release v0.2.3 --- RELEASE_NOTES.md | 35 +++++++++++++++++++--------------- frontend/package.json | 2 +- packages/core/pyproject.toml | 2 +- packages/server/pyproject.toml | 2 +- 4 files changed, 23 insertions(+), 18 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 4e01512..94ece04 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,27 +1,32 @@ -## v0.2.2 (2026-04-22) +## v0.2.3 (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 shipped `docker-compose.yml`. +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 (missing `public_url` enrichment, 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 walking `TargetReceiver → NotificationTarget → NotificationTrackerTarget → NotificationTracker` and unioning the collection IDs. `/albums`, `/random`, `/search`, `/find`, `/latest`, `/memory`, `/summary`, `/favorites`, `/place`, `/person`, `/status`, `/events` all 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](https://git.dolgolyov-family.by/alexei.dolgolyov/notify-bridge/commit/3b76a09)) +- **Scope modal relabeled** — the per-listener `allowed_album_ids` UI 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](https://git.dolgolyov-family.by/alexei.dolgolyov/notify-bridge/commit/3b76a09)) +- **Drop tracker counts from `/status`** — `trackers_active` / `trackers_total` were per-provider aggregates that would leak info about trackers a chat has no visibility into. Immich default `/status` templates (en, ru) now show only *Albums* + *Last event*; the template-editor variable catalog no longer suggests the removed vars for the Immich `/status` slot. **Note:** custom templates that reference `{{ trackers_active }}` / `{{ trackers_total }}` need to be updated. ([5a232f1](https://git.dolgolyov-family.by/alexei.dolgolyov/notify-bridge/commit/5a232f1)) ### Bug Fixes -- **Default `NOTIFY_BRIDGE_ALLOW_PRIVATE_URLS=1` in `docker-compose.yml`** — the shipped compose is intended for homelab use. The flag is now hardcoded in the `environment:` 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](https://git.dolgolyov-family.by/alexei.dolgolyov/notify-bridge/commit/4e23d2b)) - -### Documentation - -- **Surface `NOTIFY_BRIDGE_ALLOW_PRIVATE_URLS` hint in SSRF rejection errors** — the `UnsafeURLError` raised by `ImmichClient` now tells operators how to allow LAN targets, instead of leaving them to dig through source. ([58cba88](https://git.dolgolyov-family.by/alexei.dolgolyov/notify-bridge/commit/58cba88)) +- **`/albums` honors per-chat scope** — previously ignored `CommandTrackerListener.allowed_album_ids` and listed every album tracked by the provider, so scoped chats saw neighbours' albums. Now applies the same intersect filter the `/_cmd_immich` media commands use. ([4ff3876](https://git.dolgolyov-family.by/alexei.dolgolyov/notify-bridge/commit/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_reply` now always passes `disable_web_page_preview=True`. ([4ff3876](https://git.dolgolyov-family.by/alexei.dolgolyov/notify-bridge/commit/4ff3876)) +- **Restore `public_url` enrichment 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](https://git.dolgolyov-family.by/alexei.dolgolyov/notify-bridge/commit/3b76a09)) +- **Surface Immich search errors instead of silently returning `[]`** — `search_smart` / `search_metadata` consolidated into a `_search_items` helper 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](https://git.dolgolyov-family.by/alexei.dolgolyov/notify-bridge/commit/3b76a09)) +- **Redact Immich search error bodies** before they land in server logs — credentials echoed by authenticating proxies no longer leak into logs. ([3b76a09](https://git.dolgolyov-family.by/alexei.dolgolyov/notify-bridge/commit/3b76a09)) ---
All Commits -- [4e23d2b](https://git.dolgolyov-family.by/alexei.dolgolyov/notify-bridge/commit/4e23d2b) — chore(compose): hardcode NOTIFY_BRIDGE_ALLOW_PRIVATE_URLS=1 in compose _(alexei.dolgolyov)_ -- [f7d51b2](https://git.dolgolyov-family.by/alexei.dolgolyov/notify-bridge/commit/f7d51b2) — Revert "chore(compose): default NOTIFY_BRIDGE_ALLOW_PRIVATE_URLS=1 for homelab" _(alexei.dolgolyov)_ -- [3bb0585](https://git.dolgolyov-family.by/alexei.dolgolyov/notify-bridge/commit/3bb0585) — chore(compose): default NOTIFY_BRIDGE_ALLOW_PRIVATE_URLS=1 for homelab _(alexei.dolgolyov)_ -- [58cba88](https://git.dolgolyov-family.by/alexei.dolgolyov/notify-bridge/commit/58cba88) — docs(immich-ssrf): surface NOTIFY_BRIDGE_ALLOW_PRIVATE_URLS hint in error _(alexei.dolgolyov)_ +- [5a232f1](https://git.dolgolyov-family.by/alexei.dolgolyov/notify-bridge/commit/5a232f1) — feat(commands): drop tracker counts from /status *(alexei.dolgolyov)* +- [4ff3876](https://git.dolgolyov-family.by/alexei.dolgolyov/notify-bridge/commit/4ff3876) — fix(commands): /albums honors per-chat scope, disable link previews *(alexei.dolgolyov)* +- [3b76a09](https://git.dolgolyov-family.by/alexei.dolgolyov/notify-bridge/commit/3b76a09) — feat(commands): per-chat album scope derived from notification routing *(alexei.dolgolyov)*
diff --git a/frontend/package.json b/frontend/package.json index 846d93b..ad1169d 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,7 +1,7 @@ { "name": "notify-bridge-frontend", "private": true, - "version": "0.2.2", + "version": "0.2.3", "type": "module", "scripts": { "dev": "vite dev", diff --git a/packages/core/pyproject.toml b/packages/core/pyproject.toml index 82d1a22..0941f82 100644 --- a/packages/core/pyproject.toml +++ b/packages/core/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "notify-bridge-core" -version = "0.2.2" +version = "0.2.3" description = "Core library for Notify Bridge — service provider abstractions, models, notifications, and templates" requires-python = ">=3.12" dependencies = [ diff --git a/packages/server/pyproject.toml b/packages/server/pyproject.toml index 423f185..ea36ea2 100644 --- a/packages/server/pyproject.toml +++ b/packages/server/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "notify-bridge-server" -version = "0.2.2" +version = "0.2.3" description = "Standalone Notify Bridge server — FastAPI REST API with SQLite database" requires-python = ">=3.12" dependencies = [