Objective
- Ensure Action Flow email actions that use contact tag conditions (e.g. Tags Contains
vip agent - dana) behave as ops expect: send when any contact on the work order has the tag, including when To is company internal (user-company). - Stop false-positive “successful” action status when no email was queued or sent to Resend.
- Align job-wide condition semantics across trigger time and per-recipient send time so internal alerts are reliable.
Background
- NHI reported an internal VIP agent notification that appeared triggered successfully on the work order but had no matching send in Resend. Example: inspection 1008592748.
- The action is configured with a single condition: Tags Contains
vip agent - dana, with intent “send if any contact on the job has this tag.” That mental model matches how tags are resolved when the full inspection is evaluated (allpeopleon the job). - Current behavior: On email send,
sendToRecipientinrenderEmail.tsre-runs action conditions per To recipient withpeople: [toPerson]. For Send to company,toPersonis a synthetic company contact (companyFlagToFakeContact) withtags: []. The tags resolver inattributePathResolver.tsreadsinspection.peopleonly (not_conditionScopePeople), so the second pass sees no tags → condition fails → noqueueRawEmail/ no Resend. - The flow action worker can still record
completed/ UI successful becausehandleEventTriggerdByBulltreats the action assentwhenrenderEmailFromTemplatereturns no top-level error, even if every recipient returned “Contact filtered out by conditions” inresData.dataandemailResultswas never populated. - Related sibling bug: ATT-1485 — same subsystem (Action Flow condition evaluation at send time). ATT-1485 is
contact-already-on-job/ role replacement; this ticket istags(and similar job-wide attributes) + company recipient. Fixes can share patterns (e.g._conditionScopePeople) but are not duplicates and should not block each other. - Separate timing note: If the tagged agent was added after
confirmed_jobfired, the action would not re-run (people changes do not re-trigger that event). Confirm on example jobs whether failure was scope bug vs late contact add.
Scope
Backend
- Condition evaluation:
attik-backend/src/util/functions/actionFlows/attributePathResolver.ts—tags(and other job-wide contact attributes as needed) should respect_conditionScopePeoplewhen set, consistent withcontact-already-on-job. - Per-recipient send:
attik-backend/src/util/functions/emailBuilder/renderEmail.ts—sendToRecipientalready sets_conditionScopePeople: jobData.people; ensure job-wide attributes use it on the second pass. - Action execution:
attik-backend/src/util/functions/actionFlows/handleEventTriggerdByBull.ts— do not returnsent/completedwhen all recipients were filtered or nothing was queued. - Status API:
attik-backend/src/routes/flowOnJob.ts—normalizedStatus: successfulshould require evidence of send (e.g.emailResultswithresendId, or documented queued+completed path), not onlyFlowActionResult.status === completed. - Async email path:
attik-backend/src/util/functions/emails/handleRawEmail.ts,attik-backend/src/events/bullmq/emailWorker.ts—emailResults/resendIdappended after Resend; gaps here explain empty Resend when UI looks green. - Tests: Extend
tests/integration/email.rendering.test.tsand/ortests/unit/attributePathResolver.test.ts— company To + tags Contains on full job should queue/send; zero recipients should not report success.
Frontend
- Flow status UI:
attik-frontend/src/components/flowStatus/ActionStatusCard.tsx,FlowAccordion.tsx— surface per-recipient filter errors whenemailResultsis empty butresData.datahas errors (e.g. “Contact filtered out by conditions”). - Builder guardrail (optional):
attik-frontend/src/app/tools/action-flow/— warn when To includes company and conditions reference tags / contact roles.
Out of scope (unless investigation proves otherwise)
- Changing the meaning of Tags Contains (substring match on any single tag value is current behavior).
- ATT-1485 role-replacement /
contact-already-on-joblogic (track on that ticket).
Investigation outcomes (draft acceptance)
- [ ] Repro: action with Tags Contains + To: company; confirm first pass passes when any person has tag, second pass fails today; no Resend row.
- [ ] Fix: with tag on any contact, company internal email queues and Resend receives the message.
- [ ] Fix: action status not successful when all recipients filtered / no send.
- [ ] Regression test(s) committed.
- [ ] Verify example 1008592748 or cloned scenario.
References
- Example inspection 1008592748
- ATT-1485 — related: contact-already-on-job / recipient-scoped evaluation
attik-backend/src/util/functions/emailBuilder/renderEmail.tsattik-backend/src/util/functions/actionFlows/attributePathResolver.tsattik-backend/src/util/functions/actionFlows/handleEventTriggerdByBull.tsattik-backend/src/routes/flowOnJob.tsattik-backend/src/util/functions/actionFlows/companyFlagToFakeContact.ts