Skip to content
Code Recycle

Component · for humans & their agents

Sequence Send Gate

verified · first-partyactively maintained$0 during beta (was $59)

The reason people who unsubscribed keep getting your other drip. Decides whether the next sequence email may actually be sent.

by Code Recycle

Get it free — beta

Every claim on this page is refundable if it is untrue — refund policy.

24 tests · 4/4 deliberate defects caught. Zero runtime dependencies.

What reaches the recipient

None of these throw. Every one is a person deciding your product is spam.

  • Someone replies "please stop" and gets steps 3, 4 and 5 anyway, because the reply landed in
  • a shared inbox and nothing wrote it back to the sequence.
  • Someone unsubscribes from the newsletter and keeps getting onboarding, because suppression was
  • stored per sequence. An unsubscribe is a statement about you, not about one campaign.
  • A hard bounce is retried nightly for a week, damaging sender reputation for an address that
  • will never exist.
  • An enrolment trigger fires twice — a webhook retry, a re-imported CSV — and the contact
  • receives the entire sequence again.
  • Mail lands at 03:00 because the send window was evaluated in the sender's timezone.

Scope is the whole game

  // Unsubscribed from "newsletter" — asked about "onboarding":
  decideSend(contact, { sequenceId: "onboarding", stepIndex: 3 }, { now });
  // { send: false, reason: "globally_suppressed",
  //   detail: "unsubscribed applies to every sequence, not just the one it came from…" }

GLOBAL_SUPPRESSIONS is exported so there is exactly one answer in your codebase. The bug that prevents: the sequence runner and the one-off sender disagreeing about whether an unsubscribe counts, and the one-off sender winning.

| kind | scope | |---|---| | unsubscribed, complaint, hard_bounce, manual | global — every sequence | | replied | this sequence (replying to onboarding says nothing about the newsletter) | | soft_bounce | this sequence, with a tolerance count |

Reasons are ordered by permanence. Someone who complained and is outside their send window is reported as suppressed, never as "try again at 9am" — the second reads as a scheduling detail and invites a retry that must never happen.

Send windows in the recipient's timezone

Same instant, same 9–17 window, opposite answers for Los Angeles and Tokyo. That is the feature.

When the contact's timezone is unknown or invalid, it holds:

  // { send: false, reason: "unknown_timezone",
  //   detail: "…Holding rather than sending in the sender's timezone, which is how mail
  //            arrives at 03:00" }

There is an explicit sendWhenTimezoneUnknown opt-out. It is off by default because "we did not know" should not silently become "so we sent it anyway".

Zones resolve through Intl, so there is no timezone database to keep updated — and an unrecognised zone is treated as unknown, never as fine.

What it does not do

| not included | why | |---|---| | Sending mail | no transport | | Storing suppressions or scheduling steps | you own the data; this reads it | | Deciding when the next step is due | pass minGapMinutes and your own scheduler | | Anything about content or deliverability | see email-auth-alignment for SPF/DKIM alignment |

This is a gate, not a compliance product. It enforces the mechanics an unsubscribe implies; it does not tell you what CAN-SPAM, GDPR or CASL require of you.

01Capabilities

Does

  • + Notifications
  • + Email sequences
  • + Compliance audit

Doesn’t

  • No exclusions declared

02Requirements & stack

Depends on

No declared dependencies

Credentials needed

None declared

Stack

03Community

No endorsements yet

No verified confirmations yet — be the first.

Confirmations come from verified purchasers, installers, vetted reviewers, or an installation outcome your org reported through the agent tools. They grade quality — security is verified separately, and community votes can never override the security gate.

Open an issue

Sign in to confirm — weight comes from verified usage, not vote count.

Nobody has reported anything yet — a success counts as a report too.

04Trust Passport

Full passport →
–/100

0/0 automated components pass. An automated score is never a security guarantee.

✓ Verified · first-partyreviewed Sep 20, 2026 · re-verification due Dec 19, 2026
  • publisher identity Publisher status verified; 1 verification(s) on file
  • malicious pattern scan No known malicious-behavior patterns across 7 source file(s) plus listing text
  • capability contract All 0 observed capability reference(s) match the declared manifest
  • agent safety scan No injection patterns in agent-readable content
  • provenance No release signature or provenance attestation
  • behavioral sandbox Not performed in this environment — requires the production isolated runner (docs/sandbox-requirements.md). No untrusted code is ever executed on the application host.

Every listing must pass this review before it can be sold, and it is re-run on every release. Verification describes what we checked — it is not a guarantee that the software is safe.

VersionChannelReleasedNotes
0.1.0stableAug 12, 2026Initial extraction.