Skip to content

Duplicate Telegram send on alarm retry; delivery logging swallows errors and self-alert violates FK #65

Description

@tkowalczyk

Summary

alarm() has no "already sent for date X" guard, so an alarm retried after a post-send crash re-sends the same message. Separately, DbDeliveryLogger swallows every DB error with an empty catch (no log), and self-alert delivery rows use sourceId: 0, which violates the delivery_log.source_id FK and is silently dropped — so the alerting pipeline can die invisibly.

Evidence

  • apps/data-service/src/scheduler/scheduler-do.ts:190-193 — send then storage.put; a later throw/eviction re-runs alarm() with unchanged nextScheduledDate.
  • apps/data-service/src/channels/db-delivery-logger.ts:12-14,24-26.catch(() => {}) with no console.error.
  • apps/data-service/src/domain/self-alert.ts:65sourceId: 0; FK at packages/data-ops/src/drizzle/schema.ts:107-109,127-129 (no source id 0 exists).

Proposed failing tests (TDD)

  • scheduler-do.workers.test.ts"does not re-send for the same scheduledDate on alarm retry": counting channel; make the first alarm() throw after send; call again; assert send called once.
  • db-delivery-logger.test.ts — asserts console.error is called when the insert rejects.
  • A test pinning self-alert log behavior for sourceId:0 (nullable FK or a sentinel source).

Fix direction

Persist a per-date "sent" marker before send (or make logging idempotent); log swallowed errors; make delivery_log.source_id nullable for system alerts (or use a system source row).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    audit/2026-06Filed from June 2026 deep auditbugSomething isn't workingseverity/mediumMedium severity security or reliability risk

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions