3.0 KiB
OpenSpec Change: enterprise-api-plugin-campaigns
- Change ID: enterprise-api-plugin-campaigns
- Package:
@suaveplan/api-plugin-campaigns - Category: api/comms
- Target path:
api/comms/api-plugin-campaigns - Status: PROPOSED
- Date: 2026-04-24
- Reference spec:
/mnt/s/web/suaveplan/enterprise/api-plugin-campaigns.md
Summary
Deliver @suaveplan/api-plugin-campaigns on the genesis branch from scratch at enterprise quality. Email/SMS marketing campaign plugin: campaign CRUD (draft/scheduled/active/paused/completed), audience segments (contact list filters from @suaveplan/api-plugin-contacts), template selection via @suaveplan/templates, scheduled dispatch via a background job scheduler, per-recipient delivery tracking (sent/opened/clicked/bounced/unsubscribed), aggregate stats (open rate, click rate, bounce rate), and suppression enforcement via @suaveplan/suppression. Routes under /campaigns. Per-table SurrealQL. Typed bus events: campaign:started, campaign:completed, campaign:unsubscribed.
Available workspace deps on genesis
| Package | Role |
|---|---|
@suaveplan/api (workspace:^) |
definePlugin |
@suaveplan/api-shared (workspace:^) |
Helpers |
@suaveplan/api-plugin-auth (workspace:^) |
requireAuth, requireRole |
@suaveplan/api-plugin-database (workspace:^) |
SurrealDB |
@suaveplan/api-plugin-contacts (workspace:^) |
Contact audience |
@suaveplan/api-plugin-notifications (workspace:^) |
Delivery layer |
@suaveplan/templates (workspace:^) |
Message templates |
@suaveplan/suppression (workspace:^) |
Suppression list |
@suaveplan/events (workspace:^) |
Event bus |
@suaveplan/error (workspace:^) |
CampaignError hierarchy |
@suaveplan/rate-limiter (workspace:^) |
Rate limits |
hono + @hono/zod-openapi + zod |
Routes |
@opentelemetry/api |
OTel |
Public API surface
function createCampaignsPlugin(config?: CampaignsPluginConfig): PluginDescriptor
// Services: CampaignService, SegmentService, DeliveryTrackingService, StatsService
// Routes: /campaigns, /campaigns/:id, /campaigns/:id/send,
// /campaigns/:id/stats, /campaigns/:id/recipients,
// /campaigns/unsubscribe (public webhook)
Error codes
type CampaignErrorCode =
| "CAMPAIGN_NOT_FOUND"
| "CAMPAIGN_ALREADY_SENT"
| "CAMPAIGN_NO_RECIPIENTS"
| "CAMPAIGN_TEMPLATE_MISSING"
| "CAMPAIGN_SEGMENT_EMPTY"
File layout
api/comms/api-plugin-campaigns/
package.json tsconfig.json vitest.config.ts
surql/ (campaign, campaign_recipient, campaign_stats tables)
src/
index.ts events.ts types/ errors/ schemas/
services/campaign/ services/segment/ services/delivery-tracking/ services/stats/
routes/campaigns/
tests/integration.test.ts
Impact
Prerequisites: @suaveplan/api, @suaveplan/api-plugin-auth, @suaveplan/api-plugin-database, @suaveplan/api-plugin-contacts, @suaveplan/api-plugin-notifications, @suaveplan/templates, @suaveplan/suppression.