Skip to content

Bizcom Portal — Notification Routing Audit

Author: Apolinario Ratio
Date: 2026-03-25
Status: implementation-ready
Target branch: bizcom/notification-routing-audit


Summary

Outbound email logs from the last 7 days indicate two likely defects in the Bizcom notification subsystem:

  1. Recipient targeting is too broad for some notification classes, especially feedback and digest/account-update emails.
  2. Duplicate or repeated sends are likely occurring for the same subject-recipient combinations over time.

This is a user-trust, privacy, and operational-noise issue. The routing logic should be made record-scoped and default-deny, and the send pipeline should be made idempotent and auditable.


Evidence reviewed

Source file analyzed from NAS:

  • nas:agents-shared/ventures/bizcom/Bizcom Portal/emails-sent-1774418369547.csv

Observed patterns:

FindingEvidenceImplication
Feedback notification sent to multiple recipientsNew Feedback: other from Alex Gari went to 7 recipients; same for Angelyn Portafeedback routing is broader than necessary
Digest/account-update subjects sent to many recipients[BIZCOM] 4 updates on your account reached 13 recipientsdigest grouping/routing likely not partitioned tightly enough
Same subject-recipient pair repeated many timese.g. [BIZCOM] 3 updates on your account sent 46 times to one recipient over the 7-day windowdedupe / send-state / replay issue likely exists
Some alerts are single-recipientoverdue alerts for specific tasks went to one recipient onlynot all notification paths are broken; issue appears concentrated in digest/feedback flows

Problem statement

The notification subsystem appears to be mixing two failure modes:

1. Over-broad routing

Some notifications are being sent to role groups or broad recipient sets instead of only the users directly relevant to the underlying record or event.

2. Duplicate delivery

Some notifications appear to be re-sent repeatedly to the same recipient for the same subject/event class over time, suggesting weak idempotency or incorrect digest rebuild behavior.


Desired behavior

Routing principle

Default deny, then include explicit recipients only.

The system must derive recipients from the record/event itself, not from a broad role group unless that is explicitly the intended behavior.

Allowed routing by notification type

Notification typeIntended recipients
Client-specific updateauthorized contact(s) for that client only
Staff task/activity updateassigned staff only
Admin oversight eventadmins only
Feedback submissionconfigured reviewers / admins only
Internal workflow eventonly users attached to that workflow record

Failure rule

If the system cannot confidently derive recipients:

  • do not broadcast
  • do not silently fallback to everyone
  • log a routing-resolution failure
  • optionally notify admins as a system exception only

Engineering goals

  1. Targeted delivery — only relevant users receive a given event.
  2. Idempotency — the same event-recipient pair should not be re-sent unintentionally.
  3. Auditability — every outbound email can be traced to an event, a resolver, and a recipient reason.
  4. Safe fallback behavior — unresolved routing should degrade safely, not noisily.

Likely root-cause areas to inspect

A. Recipient selection logic

Check whether current logic:

  • expands too early to all admins/staff
  • uses role buckets where record-scoped recipients should be used
  • merges unrelated recipients into a shared digest/send list
  • treats "account updates" as org-global rather than recipient-partitioned

B. Digest builder / aggregation

Check whether digest generation is incorrectly grouped by:

  • organization instead of recipient
  • client instead of authorized contact
  • event class without recipient partitioning

C. Queue replay / sent-state handling

Check whether repeated sends happen because:

  • sent status is not persisted reliably
  • retries lack idempotency protection
  • scheduler re-collects previously included events
  • digest windowing allows old events to be rebuilt into new sends repeatedly

D. Feedback notifications

Check whether feedback submission currently notifies a broad internal audience rather than an explicit configured reviewer set.


Phase 1 — Trace current behavior

Add structured internal logging around outbound notification resolution:

  • notification type
  • source record id / event id
  • resolved recipients
  • why each recipient was included
  • dedupe key / idempotency key
  • send vs skip decision

Goal: confirm the exact failure point before invasive changes.

Phase 2 — Isolate recipient resolution

Refactor recipient selection into explicit resolver functions/modules per notification type.

Requirements:

  • no broad fallback by default
  • record-scoped resolution where applicable
  • explicit admin-only and reviewer-only paths
  • deterministic output for the same input event

Phase 3 — Add idempotency protection

Introduce stable dedupe keys such as:

<notification_type>:<source_event_id>:<recipient_id>:<window>

Use them to prevent:

  • duplicate queue processing
  • digest rebuild duplicates
  • retry duplication after partial failure

Phase 4 — Add observability and tests

Create tests and/or fixtures covering:

  • one client, one staff, one admin
  • multiple clients in the same org
  • repeated scheduler runs
  • retry after transient provider failure
  • feedback notification reviewer scoping

Acceptance criteria

Routing correctness

  • Feedback submission notifies only configured reviewers/admins.
  • Client update notifications reach only that client's allowed contacts.
  • Staff task notifications reach only assigned staff.
  • Admin-only events do not reach clients or unrelated staff.

Deduplication correctness

  • Re-running the same queue job does not resend the same event-recipient pair.
  • Rebuilding a digest does not duplicate already-sent items.
  • Retries do not create multiple successful sends for the same recipient/event.

Auditability

For any sent email, engineering/admin should be able to answer:

  • what event triggered it
  • why this recipient was included
  • whether it was first-send or retry
  • which dedupe key applied

Proposed testing plan for staging

  1. Seed one client with one authorized contact.
  2. Seed one assigned staff user and one admin.
  3. Trigger each relevant notification class:
    • feedback submission
    • task/activity update
    • client-facing update
    • admin-only event
  4. Verify exact recipients.
  5. Re-run scheduler / queue job.
  6. Verify no duplicate sends.
  7. Inspect logs for recipient resolution trace and dedupe keys.

Suggested implementation ticket title

Fix over-broad notification routing and duplicate email sends


Codex task framing

Use this document as the implementation source of truth.

Primary objective:

  • audit current recipient resolution and dedupe behavior
  • implement targeted routing and idempotency protections
  • preserve existing intended single-recipient alert behavior
  • keep changes staging-safe and testable tomorrow

First-pass implementation notes

Current branch implementation now applies these staging-safe controls:

  • Feedback submission emails resolve to explicit reviewers: active admin / superadmin users plus staff explicitly granted feedback.manage.
  • Feedback email routing now default-denies when no reviewer recipients can be resolved, and logs the routing failure instead of broadcasting.
  • Queue insertion now supports optional dedupe keys and logs duplicate-skip decisions.
  • Queue insertion also suppresses exact duplicate pending/processing rows for the same recipient + content within the dedupe window.
  • Client-facing task/compliance digest contributors now enqueue with recipient-scoped dedupe keys over an 8-hour window:
    • task_waiting
    • task_completed
    • approval_needed
    • documents_needed
    • document_reviewed

Remaining gaps for a later pass:

  • Other notification producers still rely on their existing caller-side guards and have not yet been moved to dedicated resolver modules.
  • Queue idempotency is currently opt-in for sent-row replay prevention; broader event-id based coverage would require standardizing dedupe keys across all producers.

Bizcom Portal Guide