Skip to main content

campaign-service — Jira-Ready Epics & User Stories

Status: populated Owner: Product Last updated: 2026-04-21 Service prefix: CAMP Scope: Campaign builder (segments, schedule, throttle, A/B, kill-switch); template catalog with merge fields, conditional content, multi-language; approved-template workflow paired with EP-CE-13; campaign reporting. Per ADR-0004 §3 and 07-epics-and-user-stories.md §6.11.


Epic Summary

Epic IDTitleStoriesPoints
EP-CAMP-01Campaign Builder (segments, schedule, throttle, A/B, kill-switch)US-CAMP-001 – US-CAMP-00838
EP-CAMP-02Template Catalog (merge fields, conditional content, multi-language)US-CAMP-009 – US-CAMP-01424
EP-CAMP-03Approved-Template Workflow (paired with EP-CE-13)US-CAMP-015 – US-CAMP-01816
EP-CAMP-04Campaign Reporting (deliverability, spend, opt-outs, conversion)US-CAMP-019 – US-CAMP-02214
Total22 stories92

EP-CAMP-01 · Campaign Builder (segments, schedule, throttle, A/B, kill-switch)

Context: Tenants build, schedule, throttle, A/B-test, and emergency-stop campaigns. Throttle policy must respect tenant TPS budgets and per-MNO ceilings. Kill-switch must take effect within 5 s end-to-end. Pre-flight cost estimate prevents bill-shock.

US-CAMP-001 · Define Recipient Segment Using JSON DSL

Type: Feature | Points: 8

Description: As a campaign manager, I need to define a recipient segment using a JSON DSL (filters on consent scope, country, opt-in date, custom tenant attributes) so I can target the exact audience without writing SQL.

Acceptance Criteria:

  • POST /v1/campaigns/segments accepts JSON DSL with predicates (eq, in, gt, lt, between, not, and, or)
  • Predicate fields: consent.scope, consent.grantedAfter, country, lineType (mobile/fixed), tenant-defined attribute keys
  • Returns segmentId + estimatedCount (P95 ≤ 2 s for segments < 5 M)
  • Segment materialised in camp.segments and snapshot stored
  • Saved segment re-usable across campaigns

US-CAMP-002 · Schedule Campaign (one-shot, recurring, time-zone aware)

Type: Feature | Points: 5

Description: As a campaign manager, I want to schedule a campaign one-shot at a specific time, recurring (daily/weekly/monthly), or immediately, with proper time-zone handling.

Acceptance Criteria:

  • POST /v1/campaigns/{id}/schedule accepts { type: ONE_SHOT|RECURRING|IMMEDIATE, scheduledAt, tz, recurrenceRule (RRULE) }
  • Tz mandatory; default Asia/Kabul
  • Scheduled campaigns visible on a calendar view
  • Recurrence honours regulator quiet windows (per EP-RE-07)

US-CAMP-003 · Throttle Dispatch by Tenant TPS and Per-MNO Ceiling

Type: Feature | Points: 8

Description: As a campaign manager, I want dispatch throttled to my tenant's TPS budget and per-MNO contracts so a campaign cannot exceed reserved capacity.

Acceptance Criteria:

  • Token-bucket rate-limit at submit-time; tenant TPS reads from auth.tenant_rate_limits
  • Per-MNO TPS ceiling enforced via routing-engine reservation (per EP-RE-06)
  • Excess work queued; pacing metric camp_pacing_seconds_in_queue
  • Tenant can override TPS down (not up) per campaign

US-CAMP-004 · A/B Variant Assignment by Consistent Hashing

Type: Feature | Points: 5

Description: As a campaign manager, I want A/B variant assignment by consistent hashing on recipient MSISDN so the same recipient sees the same variant across resends.

Acceptance Criteria:

  • POST /v1/campaigns/{id}/variants defines variants with weights (must sum 1.0)
  • Assignment: bucketIdx = murmur3(msisdn || campaignId) mod totalWeight
  • Variant assignment persisted in camp.variant_assignments
  • Re-running same campaign yields same variant per recipient

US-CAMP-005 · Kill-Switch Halts In-Flight Dispatch Within 5 s

Type: Feature | Points: 5

Description: As a campaign manager, I want a kill-switch that halts in-flight dispatch end-to-end within 5 s so a problematic campaign can be stopped immediately.

Acceptance Criteria:

  • POST /v1/campaigns/{id}/kill flips Redis flag camp:kill:{id}
  • All workers consult flag every 1 s; on positive, abort current batch
  • In-flight messages already at smpp-connector NOT recallable (documented)
  • Audit row + camp.killed.v1 event with kill timestamp + initiator
  • Test: 1 M-recipient campaign killed within 5 s end-to-end

US-CAMP-006 · Pause and Resume Campaign

Type: Feature | Points: 3

Description: As a campaign manager, I want to pause and resume a long-running campaign without losing state.

Acceptance Criteria:

  • POST /v1/campaigns/{id}/pause and /resume
  • Pause stops dispatch; queued recipients held in camp.pending
  • Resume continues from last checkpoint
  • Status transitions logged

US-CAMP-007 · Pre-Flight Spend Estimate

Type: Feature | Points: 3

Description: As a campaign manager, I want a pre-flight cost estimate before I launch so I avoid bill-shock.

Acceptance Criteria:

  • POST /v1/campaigns/{id}/estimate returns { recipients, perRecipientPrice, totalEstimated, currency, breakdownByMno }
  • Pricing pulled from billing-service
  • Estimated count from US-CAMP-001 segment snapshot
  • Estimate refreshed if segment is re-materialised

US-CAMP-008 · Per-Tenant Quotas (Active Campaigns, Daily Volume, Segment Size)

Type: Feature | Points: 3

Description: As a platform admin, I need per-tenant quotas on active campaigns, daily volume, and segment size to prevent platform-wide abuse.

Acceptance Criteria:

  • camp.tenant_quotas table with defaults per tenant tier
  • Quota check at create + at launch
  • Breach → 422 with code QUOTA_EXCEEDED
  • Override requires platform-admin role + audit

EP-CAMP-02 · Template Catalog (merge fields, conditional content, multi-language)

US-CAMP-009 · Create Template with Mustache + ICU Plurals

Type: Feature | Points: 5

Description: As a campaign manager, I need to create a template using Mustache merge fields and ICU plurals so localisation and personalisation work correctly.

Acceptance Criteria:

  • Template body supports {{firstName}} Mustache + {count, plural, =0 {none} =1 {one} other {#}} ICU
  • Variables declared in variableSchema (name, type, required, default)
  • Validation rejects undeclared variables
  • Unit tests cover ICU plurals for Pashto/Dari/Arabic/English

US-CAMP-010 · Template Versioning

Type: Feature | Points: 3

Description: As a campaign manager, I want template edits to create new versions without breaking running campaigns.

Acceptance Criteria:

  • Each save creates a new camp.template_versions row; previous versions immutable
  • Running campaigns continue with the version they started with
  • New campaigns use latest by default; explicit pin available

US-CAMP-011 · Multi-Language Template Variants

Type: Feature | Points: 5

Description: As a campaign manager, I want a single logical template with per-language variants (Pashto/Dari/Arabic/English) so recipients receive their preferred language.

Acceptance Criteria:

  • Template object has variants[] keyed by language ISO 639-1
  • Recipient language inferred from consent-ledger-service profile or default tenant locale
  • Missing variant → fallback to default language
  • Localisation glossary linked (EP-CUST-09)

US-CAMP-012 · Conditional Content Blocks

Type: Feature | Points: 5

Description: As a campaign manager, I want conditional content blocks so the same template renders different content for different recipient attributes.

Acceptance Criteria:

  • Syntax: {{#if isPremium}} … {{/if}}
  • Conditions can reference any segment attribute
  • Linter prevents nested conditions deeper than 3
  • Preview tool renders sample for each attribute combination

US-CAMP-013 · Template Catalog Search and Filter

Type: Feature | Points: 3

Description: As a campaign manager, I want to search and filter the template catalog so I find re-usable templates fast.

Acceptance Criteria:

  • Filters: tenant, category, status (DRAFT/APPROVED/SUSPENDED), language, last-used date
  • Free-text search on name + body excerpt
  • Default sort: most recently used first

US-CAMP-014 · Template Quality Score

Type: Feature | Points: 3

Description: As a campaign manager, I want a quality score per template (length, link count, opt-out instruction presence, language correctness) so I can improve templates before launch.

Acceptance Criteria:

  • Score 0–100 computed at template-save time
  • Components: length (penalty for >2 segments), opt-out presence (mandatory for marketing), language-spelling, link-count (penalty for >2)
  • Score visible in template editor with improvement suggestions

EP-CAMP-03 · Approved-Template Workflow (paired with EP-CE-13)

US-CAMP-015 · Submit Template for Compliance Approval

Type: Feature | Points: 5

Description: As a campaign manager, I want to submit a template for compliance approval so it can be used by trusted-tenant fast-path.

Acceptance Criteria:

  • POST /v1/campaigns/templates/:id/submit-approval → status PENDING_APPROVAL
  • Routes to compliance-engine via gRPC SubmitTemplate(EP-CE-13)
  • Tenant receives notification on decision (APPROVED/REJECTED/REQUEST_INFO)

US-CAMP-016 · Trusted-Tenant Fast-Path (EP-CE-13)

Type: Feature | Points: 3

Description: As a trusted tenant, I want approved templates to be eligible for the trusted-tenant fast-path so OTP-class messages skip blocking compliance evaluation.

Acceptance Criteria:

  • On approval, compliance.template.approved.v1 consumed; template flagged eligible
  • Orchestrator (per EP-ORCH-07) verifies fingerprint + tenant grant at submit
  • Eligible flag visible in template editor

US-CAMP-017 · Approval Workflow States and Reviewer Actions

Type: Feature | Points: 5

Description: As a compliance reviewer, I want approve/reject/request-info actions with mandatory reason for templates.

Acceptance Criteria:

  • Reviewer UI in admin-dashboard
  • Three actions; reason mandatory
  • APPROVED valid 12 months; renewal required
  • REJECTED → tenant sees reason; can edit + resubmit

US-CAMP-018 · Template Approval SLA & Auto-Escalation

Type: Feature | Points: 3

Description: As a tenant, I want approval SLA enforced so I can plan launches.

Acceptance Criteria:

  • SLA: 2 business days; cron flags overdue
  • Auto-escalation to compliance lead at +1 day
  • Tenant-portal countdown visible

EP-CAMP-04 · Campaign Reporting (deliverability, spend, opt-outs, conversion)

US-CAMP-019 · Campaign Reporting Dashboard (Deliverability, Spend, Opt-Outs)

Type: Feature | Points: 5

Description: As a campaign manager, I want a per-campaign dashboard showing deliverability, spend, opt-outs, conversion in real time.

Acceptance Criteria:

  • Live tiles: total recipients, sent, delivered, failed, opted-out, spend
  • Per-MNO breakdown
  • Per-variant breakdown (when A/B)
  • Updates every 30 s via WebSocket

US-CAMP-020 · Conversion Tracking via Signed Callback URL

Type: Feature | Points: 3

Description: As a campaign manager, I want to track conversion via a per-recipient signed callback URL so I can attribute outcomes to the campaign.

Acceptance Criteria:

  • Per-recipient short-link https://g.ghasi.io/c/{token}; HMAC-signed token
  • Click handler logs camp.conversion.v1 event with campaign, variant, recipient
  • Click→destination redirect; tenant configures destination per campaign
  • Conversion rate visible on campaign dashboard

US-CAMP-021 · Live Opt-Out Drop During Running Campaign

Type: Feature | Points: 3

Description: As a compliance officer, I want recipients who opt-out mid-campaign to be dropped from remaining dispatches within 60 s.

Acceptance Criteria:

  • Consumer for consent.revoked.v1; matches against running-campaign queues
  • Matched recipients removed; metric camp_opt_out_dropped_total incremented
  • Audit row written

US-CAMP-022 · Per-Variant Reporting with Statistical Significance

Type: Feature | Points: 3

Description: As a campaign manager, I want per-variant deliverability and conversion with statistical-significance indicator so I can decide a winner.

Acceptance Criteria:

  • Two-proportion z-test computed at p < 0.05 threshold
  • Winner indicator only displayed once significance reached
  • Sample-size advisory shown when too small