--- phase: 17-telegram-scheduler plan: 04 subsystem: telegram tags: [telego, telegram, notifications, subscribers, scheduler] requires: - phase: 17-01 provides: Bot struct, Config, command dispatch, Start/Stop lifecycle - phase: 17-02 provides: subscribers table CRUD (AddSubscriber, RemoveSubscriber, ListSubscribers, IsSubscribed), scheduler JobResult provides: - /subscribe and /unsubscribe command handlers - NotifyNewFindings dispatcher (scheduler to bot bridge) - NotifyFinding real-time individual finding notification - formatNotification/formatErrorNotification/formatFindingNotification helpers affects: [17-05, serve-command, scheduled-scanning] tech-stack: added: [] patterns: [separate-format-from-send for testable notification logic, per-subscriber error resilience] key-files: created: - pkg/bot/subscribe.go - pkg/bot/notify.go - pkg/bot/subscribe_test.go modified: - pkg/bot/bot.go key-decisions: - "Separated formatting from sending for testability without mocking telego" - "Nil bot field used as test-mode indicator to skip actual SendMessage calls" - "Zero-finding results produce no notification (silent success)" patterns-established: - "Format+Send separation: formatNotification returns string, NotifyNewFindings iterates subscribers" - "Per-subscriber resilience: log error and continue to next subscriber on send failure" requirements-completed: [TELE-05, TELE-07, SCHED-03] duration: 3min completed: 2026-04-06 --- # Phase 17 Plan 04: Subscribe/Unsubscribe + Notification Dispatcher Summary **/subscribe and /unsubscribe handlers with NotifyNewFindings dispatcher bridging scheduler job completions to Telegram messages for all subscribers** ## Performance - **Duration:** 3 min - **Started:** 2026-04-06T14:30:33Z - **Completed:** 2026-04-06T14:33:36Z - **Tasks:** 2 - **Files modified:** 4 ## Accomplishments - /subscribe checks IsSubscribed before adding, /unsubscribe reports rows affected - NotifyNewFindings sends formatted message to all subscribers when scheduled scans find keys - NotifyFinding provides real-time per-finding notification with always-masked keys - 6 tests covering subscribe DB round-trip, no-subscriber no-op, zero-finding skip, message format validation ## Task Commits Each task was committed atomically: 1. **Task 1: Implement /subscribe, /unsubscribe handlers** - `d671695` (feat) 2. **Task 2: Notification dispatcher and tests (RED)** - `f7162aa` (test) 3. **Task 2: Notification dispatcher and tests (GREEN)** - `2643927` (feat) ## Files Created/Modified - `pkg/bot/subscribe.go` - /subscribe and /unsubscribe command handlers using storage layer - `pkg/bot/notify.go` - NotifyNewFindings, NotifyFinding dispatchers with format helpers - `pkg/bot/subscribe_test.go` - 6 tests for subscribe/unsubscribe and notification formatting - `pkg/bot/bot.go` - Removed stub implementations replaced by subscribe.go ## Decisions Made - Separated formatting from sending: formatNotification/formatErrorNotification/formatFindingNotification return strings, tested independently without telego mock - Nil telego.Bot field used as test-mode indicator to skip actual SendMessage calls while still exercising all logic paths - Zero-finding scan completions produce no notification (avoids subscriber fatigue) - Error results get a separate error notification format ## Deviations from Plan None - plan executed exactly as written. ## Issues Encountered - go.sum had merge conflict markers from worktree merge; resolved by removing conflict markers and running go mod tidy ## User Setup Required None - no external service configuration required. ## Next Phase Readiness - Notification pipeline complete: scheduler OnComplete -> NotifyNewFindings -> all subscribers - Ready for Plan 17-05 (serve command integration wiring bot + scheduler together) --- *Phase: 17-telegram-scheduler* *Completed: 2026-04-06*