@portablecore/email-broadcasts
v0.3.0
Published
Shared email-broadcast (Mailshrimp parity) primitives for Portable platforms
Maintainers
Readme
@portablecore/email-broadcasts
Shared email-broadcast (Mailshrimp parity) primitives for Portable platforms. Consumed by Portable Expert and Portable Team.
What's here
Per Lisagor's day-one extraction call (consult thread pep_1777165952764):
- Pure helper functions —
generateUnsubscribeToken,verifyUnsubscribeToken,getUnsubscribeUrl,isEmailUnsubscribed,recordUnsubscribe,updateCampaignStats. - Send-batch orchestrator —
orchestrateBatchSend(stub today; lands with the first port of Expert's send pipeline). - Audience resolution —
resolveAudienceMembers(stub today). - HTML render / Postmark handoff —
renderCampaignEmail(stub today). - Schema-shape types —
EmailCampaign,EmailCampaignRecipient,EmailAudienceGroup,EmailUnsubscribe,AudienceMember, etc.
What stays per-platform
- Schema migrations and RLS policies. Tables are convergent in shape
but Team carries an extra
workspace_profile_idFK. Both platforms own their migration files. - API route handlers (
apps/web/app/api/...). - Admin UI components.
- The unsubscribe salt itself — each platform sets
UNSUBSCRIBE_TOKEN_SALTin its environment and passes the value into the token helpers as a parameter.
Usage
import {
generateUnsubscribeToken,
verifyUnsubscribeToken,
getUnsubscribeUrl,
isEmailUnsubscribed,
} from "@portablecore/email-broadcasts";
// Generate the link that goes in the email footer:
const url = getUnsubscribeUrl(
"[email protected]",
process.env.UNSUBSCRIBE_TOKEN_SALT!,
process.env.NEXT_PUBLIC_APP_URL!,
);
// Verify a click on the unsubscribe link:
const ok = verifyUnsubscribeToken(
email,
token,
process.env.UNSUBSCRIBE_TOKEN_SALT!,
);Token scheme
The current scheme is sha256(email + salt). This is byte-for-byte
compatible with Portable Expert's existing tokens-in-the-wild (see
apps/web/lib/email/campaign.ts and apps/web/app/api/unsubscribe
in the Expert repo).
It's not HMAC. A future hardening pass should migrate both platforms to HMAC together. Until then, the salt is the secret — keep it out of client bundles and out of public repos.
Status
This package is currently scaffolded. The token helpers
(tokens.ts) and recipient/stats helpers (recipients.ts,
stats.ts) are implemented. The send-pipeline pieces
(orchestrator.ts, audience.ts, rendering.ts) are stubs that will
be filled in when Workstream A's port of Expert's lib/email/campaign.ts
lib/email/send.tslands.
See docs/handoffs/JOSE_TOOLSET_REPLACEMENT.md §3 for the
broader work plan.
