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:65 — sourceId: 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).
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,DbDeliveryLoggerswallows every DB error with an empty catch (no log), and self-alert delivery rows usesourceId: 0, which violates thedelivery_log.source_idFK and is silently dropped — so the alerting pipeline can die invisibly.Evidence
apps/data-service/src/scheduler/scheduler-do.ts:190-193— send thenstorage.put; a later throw/eviction re-runsalarm()with unchangednextScheduledDate.apps/data-service/src/channels/db-delivery-logger.ts:12-14,24-26—.catch(() => {})with noconsole.error.apps/data-service/src/domain/self-alert.ts:65—sourceId: 0; FK atpackages/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 firstalarm()throw after send; call again; assertsendcalled once.db-delivery-logger.test.ts— assertsconsole.erroris called when the insert rejects.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_idnullable for system alerts (or use a system source row).