Sequences modeled as state machines
Why it matters
Without a state machine model, sequence position exists only as an implicit calculation derived from send timestamps — and that calculation breaks the moment history is incomplete. A cron loop that re-derives step index on every run will duplicate sends when emails are delayed, skip steps when records are missing, and produce divergent behavior across contacts that should be in identical states. CWE-372 (Incomplete Internal State) captures the class of defect: the system behaves correctly in the happy path but enters an undefined state under any pressure — process restart, partial failure, manual intervention. The business impact is concrete: contacts receive redundant outreach, or fall silent mid-sequence, with no audit trail to diagnose either.
Severity rationale
Critical because missing per-contact state causes duplicate sends and irreversible data loss on any process restart or partial failure.
Remediation
Add a contact_sequences enrollment table with an explicit status enum and advance contacts through transitions — never re-derive step position from history. The status column must carry at least active, paused, completed, replied, and opted_out as distinct values.
// contacts_in_sequences table
// columns: id, contact_id, sequence_id, current_step_index,
// status ('active'|'paused'|'completed'|'replied'|'opted_out'), updated_at
async function advanceContact(enrollmentId: string) {
const enrollment = await db.contactSequence.findUnique({ where: { id: enrollmentId } })
if (enrollment.status !== 'active') return // Guard: invalid transition
const nextStep = sequence.steps[enrollment.currentStepIndex + 1]
if (!nextStep) {
await db.contactSequence.update({ where: { id: enrollmentId }, data: { status: 'completed' } })
return
}
await db.contactSequence.update({
where: { id: enrollmentId },
data: { currentStepIndex: enrollment.currentStepIndex + 1 }
})
await scheduleStep(enrollmentId, nextStep)
}
DetectionPro
The detection method for this pattern is part of AuditBuffet Pro.
The full method (what to look for, pass and fail conditions, and how results get reported) ships inside the Campaign Orchestration & Sequencing Audit. The pattern definition, severity rationale, and remediation remain openly licensed under CC-BY-4.0.
External references
- cwe · CWE-372 — Incomplete Internal State Distinction
- iso-25010:2011 · reliability.fault-tolerance
Taxons
History
- 2026-04-18·v1.0.0·Initial import from campaign-orchestration-sequencing·automated