Bug: Action flow SMS fails when smsBuilderId references a cross-company template

Objective

  • Prevent Action Flow SMS actions from failing at send time due to a _companyId mismatch between an SmsBuilder document and the FlowAction that references it.
  • Surface the misconfiguration at setup time (when an SMS action is saved or an Action Flow is copied) rather than at send time, so the failure doesn't silently block a live job.

Background

  • Catherine Lemoine (SE/Residential) reported an Action Flow failure on inspection 1008602312 (June 24, 2026). The error displayed in the activity feed was: Error: SMS template company mismatch for FlowAction 6a25e8cf2ee5be4f7c0a2693.
  • The failure has nothing to do with the inspection itself, the contact record, or the flow's conditions — all of those were valid. The action failed before any of that was evaluated.
  • In renderSmsFromTemplate, when a FlowAction.actionTemplate contains a smsBuilderId, the system fetches the referenced SmsBuilder document and compares saved._companyId against smsFlowAction._companyId. If they don't match, it returns a hard error and sends nothing.
  • The ownership check is correct in principle — cross-company template access shouldn't be permitted. The bug is that no validation occurs at configuration time, so an admin can save a FlowAction pointing to an SmsBuilder from a different company without any warning or error. The problem only surfaces when the flow fires on a real job.
  • The most likely path to this state is the Action Flow copy system (copyActionFlowToCompany.ts). That function collects smsBuilderId values from source FlowAction documents and attempts to copy each referenced SmsBuilder under the target company, building a mapping. If the SMS copy step silently fails (missing source doc, mapping gap, etc.) and the FlowAction is still saved with the original source smsBuilderId, the cross-company reference is baked into production data with no visible error.

Product Decisions

Locked

  1. Ownership check — The existing _companyId comparison in renderSmsFromTemplate is correct behavior and should be preserved.
  2. Validation points — Fix should enforce same-company ownership at both save time (validate on FlowAction write) and copy time (prevent a FlowAction from being saved if its SMS mapping is incomplete).

Open

  1. Failure mode in copy — If an SMS template can't be copied (source doc missing, etc.), should copyActionFlowToCompany abort the whole flow copy, skip that action, or save the action in a broken/draft state with a warning? Current behavior logs a warning but may proceed.

Scope

Backend (attik monorepo / attik-backend)

  • apps/backend/src/util/functions/actionFlows/renderSms.ts — Contains the _companyId mismatch check. No change needed here; the guard is correct.
  • apps/backend/src/util/functions/actionFlows/copyActionFlowToCompany.tscopySmsBuilders() and copyFlowActions() are the likely source of the broken state. When smsBuilderMapping doesn't contain a source ID, copyFlowActions logs a warning and proceeds without updating smsBuilderId, meaning the saved FlowAction retains the original cross-company ID.
  • apps/backend/src/models/flowSchema.tsFlowAction schema; consider whether a pre-save hook or route-level validation should enforce same-company ownership of actionTemplate.smsBuilderId.
  • apps/backend/src/models/smsBuilderSchema.tsSmsBuilder schema; reference point for _companyId field structure.

Frontend (attik monorepo / attik-frontend)

  • apps/frontend/src/components/flowStatus/SmsSendModal.tsx — Surfaces SMS action state in the UI; may need to surface a degraded/broken state for actions with a cross-company template reference, similar to how broken service references are handled.

References

Please authenticate to join the conversation.

Upvoters
Status

Planned

Board
🏠

Main App

Date

About 5 hours ago

Author

Linear

Subscribe to post

Get notified by email when there are changes.