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
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 yetNo 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.
Sign in to confirm — weight comes from verified usage, not vote count.
Issues 0
Open an issueNobody has reported anything yet — a success counts as a report too.
04Trust Passport
Full passport →0/0 automated components pass. An automated score is never a security guarantee.
- 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.
05Versions
Full history →| Version | Channel | Released | Notes |
|---|---|---|---|
| 0.1.0 | stable | Aug 12, 2026 | Initial extraction. |