Skip to main content

Status and intended outcome

Draft for decisions; no product implementation or launch authorization. Add customer-owned sending domains and sender identities, independent workspace newsletter tiers, and a complete newsletter workspace at mail.tuturuuu.com. Infrastructure owns platform approval and operations. Supabase remains authoritative; Cloudflare owns new schedules, queues and dispatch compute. Amazon SES is the chosen newsletter/bulk delivery provider; Polar owns subscription payments. Unapproved workspaces have zero newsletter sends, including on Free. Free provides 10/day only after workspace newsletter approval. Default access is denied. A workspace request, its sending domain, and each sender address require separate platform-admin approval. Buying a subscription never bypasses approval, consent, suppression, abuse controls or provider limits. Existing personal/connected mail and transactional notifications retain their rules. The user approved SES for newsletters on 2026-10-25. Cloudflare Email Service remains available for existing transactional mail only; its marketing restriction is no longer a newsletter launch dependency. Cloudflare still owns all new scheduling and fan-out compute. Live SES account/region production access, verified customer-domain authority, quotas and feedback configuration remain acceptance gates; provider choice is not proof they are provisioned. No sends or production writes are authorized by this draft. Sources below were checked on 2026-10-25. Repository inventory is a source snapshot at 45fdcb32ca, not a claim about live provider configuration or deployed health. No credentials, live catalog, production database or sandbox organization was read.

Workspace staff-test gate

The workspace staff-test send is closed unless newsletter_sending is on, the customer subdomain is a verified non-apex name outside tuturuuu.com, a platform admin has approved the domain and the sender local-part, and the workspace holds fewer than 10 reserved or accepted sends for the current UTC day. A send reserves its slot before the mailer is called, reservations are serialized per workspace, and only a definite mailer rejection releases a slot; a reservation that never finishes keeps its slot until the UTC day ends. Regression coverage: apps/database/supabase/tests/newsletter-delivery-cap-reservation.sql and the concurrent race in apps/database/scripts/newsletter-cap-concurrency.mjs. The only recipient is the signed-in actor. Subscriber rows are stored and are not recipients of this send.

Existing inventory and reuse boundaries

No general-purpose workspace add-on/entitlement model was identified in the examined billing/schema paths. Confirm schema drift before authoring migrations. The existing Polar client uses the installed SDK’s Polar constructor and server option (packages/payment/src/polar/server.ts); current upstream examples use versioned APIs. Pin the installed API contract and test compatibility before adopting new SDK examples or upgrading dependencies.

Runtime and ownership

Mail and Infrastructure use their authenticated satellite sessions. Resolve actors through getSatelliteAppSessionUser or the applicable satellite request actor; never use raw Supabase user helpers in satellites. Workspace aliases are normalized before all membership, preview and mutation checks. Browser requests use typed packages/internal-api helpers and TanStack Query; no raw app API fetching or useEffect fetching. New/substantially reworked Web handlers belong in apps/web/src/app/api/**. Existing app-owned Pay/Mail/Infrastructure adapters retain explicit ownership; choose their route placement with the owning platform maintainer before coding. Shared newsletter policy, entitlement and state machines have framework-free entrypoints with injected identity, storage, clock, locale and transport. Prefer @tuturuuu/utils/effect for orchestration with typed errors and bounded concurrency. No resumed Rust/TanStack runtime or broad framework migration is needed. Request flow: Mail authorizes a campaign and commits its immutable revision plus an outbox entry. A Cloudflare processor claims outbox pages and enqueues recipient IDs. Queue consumers reauthorize each recipient immediately before submission. Supabase is the transaction boundary; the queue is a wake-up hint, not permission. An outbox row survives publication failure; duplicate queue publication cannot create a second recipient claim. Provider events arrive on a separate trusted queue. Follow Cloudflare ownership and cost/stop acceptance. Use current cf/Vite+ conventions where parity is qualified; retain Wrangler for unqualified operations. New Workers join the active service inventory and require exact-commit emitted-artifact CI and isolated Worker runtime acceptance.

Domain and sender onboarding

Workspace owners submit business identity, intended content, audience provenance, expected volume, website, postal address and abuse contact. State is not_requested → pending → approved | rejected; approved can become suspended. Reapplication preserves prior decisions and reason history. Rejected or suspended workspaces cannot send even on a paid plan. A workspace sending-domain claim references the canonical domain row and tracks independent DNS state (unverified, checking, verified, failed, expired) and review state (pending, approved, rejected, suspended). Readiness requires both current DNS verification and approval. Store the exact account, zone, provider domain identifier, normalized IDNA domain, expected DNS records, revision and verified time. A domain cannot be concurrently claimed by unrelated workspaces; transfer requires revoke, ownership re-verification and a new approval. No automatic inheritance from parent-domain approval or a wildcard sender. The setup screen presents provider-returned records with host/type/value and observed status. Use SES verified domain identities, DKIM DNS records and a custom MAIL FROM subdomain with SES-issued SPF/MX; verify customer DMARC alignment. Customer DNS need not move to Cloudflare. Prove ownership in the platform SES account/region, or use explicit SES sending authorization for a customer-owned SES identity; pin account, region and identity ARN. Use provider-issued DKIM selectors; verify aligned visible From, DKIM signing domain and envelope sender. Preserve existing root MX and DMARC policy; never create two SPF records or weaken an existing DMARC policy. Prefer a dedicated sending subdomain. The customer confirms DNS changes; do not request their account-wide API token. The selected SES identity model must use narrowly scoped server credentials. Cron Control owns verification, default off. Proposed bounds: 25 due domains/tick, one provider-status lookup/domain/attempt, 12 total attempts over 48 hours, capped backoff with jitter, lease expiry and a durable cursor. A terminal/failing exhausted row stops polling. Manual Retry creates an audited new revision with a capped operator budget; it cannot reset a global spending limit. Recheck active domains under a renewable, budgeted verification lease, and fail closed on expired proof. Missing records or provider disablement suspend future sends, with clear recovery. Sender identity is an exact canonical address linked to the approved domain claim. Verify mailbox control with an expiring, single-use challenge where supported, then require platform-admin approval. Sending-subdomain control alone does not approve every local part. State includes pending_verification, pending_review, approved, rejected, suspended, revoked. Changing address/domain invalidates verification and approval; changing display name or reply-to is audited and re-reviewed if it changes represented identity. Reply-to must be verified or constrained by policy. Never create inbound mailboxes merely to approve newsletter senders. Approvers must have a fresh verified exact @tuturuuu.com identity and the explicit platform newsletter-management permission in the root workspace. Tenant admins cannot grant this permission. Decisions record actor, reason, evidence, resource revision and timestamp; stale concurrent decisions return conflict. Suspension increments the sending fence immediately. Approval never enables a provider action by itself when another gate remains closed.

Sending, idempotency and bounded cost

Chosen transport: Amazon SES, using the existing provider adapter and qualifying its Worker-safe authenticated boundary. SES v2 SendEmail supports simple/raw/templated email. Preserve custom unsubscribe headers and explicit configuration-set/identity binding. SES quotas are regional, including a rolling 24-hour sending quota and per-second rate. Sandbox accounts allow 200 messages/24 hours and one/second, with verified recipients; live account capacity and production access remain unverified. Use exactly one recipient per send, no CC/BCC; proposed newsletter content cap is 256 KiB with hosted images and no attachments for the initial release. A frozen campaign revision stores sender, content hash, audience snapshot cutoff, consent policy, schedule and maximum recipients. Key each recipient delivery by (workspace_id, campaign_revision_id, subscriber_id) with a unique constraint and payload hash. Claim, quota reservation and spending reservation occur atomically. Queue duplicates read the existing row. Changed payload requires a new campaign revision, never a reused key. Subscriber status and suppression are checked again at send time, even when the audience snapshot contains the address. States: pending → reserved → submitting → accepted | rejected | unknown, followed by monotonic delivery outcomes. A provider message ID is not inbox delivery proof. No SES idempotency guarantee is established for the selected send contract. Therefore exactly-once external delivery is not promised: timeout, process crash after submission, or receipt-write failure becomes unknown, retains quota/spend, and never auto-resubmits. Reconcile against provider message/event evidence; absent proof stays unknown. A known pre-submission failure or explicit API rejection may release reservation. Do not treat a later rejection as proof an earlier unknown attempt did not send. Proposed finite consumer limits: 25 recipient IDs/wake, concurrency 2, three durable attempts only for proven unsent failures, 24-hour retry age, bounded backoff and a DLQ. Configure Queue retries consistently with that budget; redrive preserves identity, attempts and deadlines. Provider delivery retries after acceptance are provider-owned and do not trigger a second application send. Campaigns reserve their full audience against the applicable quota before scheduling. An audience that does not fit is rejected or paused, with a choice to reduce it; it never silently spills into later days or sends a quota-sized subset.

Durable stop fence and total-spend envelope

Store global, workspace, domain and campaign stop flags with monotonic generations, lease expiry and actor audit. Before each expensive operation, submission and reschedule, a fenced transaction checks all flags, approval, entitlement, quota, remaining operation credits and lease. Serialize final submission admission and stop on a per-workspace coordinator; one in-flight provider call may already have crossed the boundary. The stop UI reports that bounded uncertainty and waits for in-flight admission receipts. A generation invalidates queued stale work; stopped or terminal work is acknowledged without fan-out or self-rescheduling. A stop endpoint requires platform authority, persists before success and works independently of Mail UI/ingress. Also document an operator path to pause Queue consumers, disable the Cron Control job and revoke the sending credential/binding. Stop cannot recall accepted mail. Test stop racing claims, submissions, crashes, queue retries, lease renewal and rescheduling in the real isolated Worker runtime. The hard envelope is not just a dollar counter around sending. Atomically reserve conservative micro-dollar cost and finite operation credits before work: provider submissions, enqueue/read/delete/DLQ operations, Worker invocations, DB calls, R2 bytes/requests, verification polls and event ingestion. Account, workspace, campaign, workspace-local-day and billing-period budgets all apply; exhaustion fails closed. Do not discount included provider allowance when reserving. Concurrent leases reserve disjoint credits; no restart resets budgets. A bounded sweeper expires leases but never refunds unknown provider writes. Queue/event deliveries themselves can cost money before application code runs. Thus application counters alone cannot cap the entire Cloudflare invoice. Require finite admitted campaign volume, producer limits, finite Queue retention/retries, bounded provider-event amplification and a separate hosted control-plane stop procedure. Measure the worst-case residual cost of already admitted messages and in-flight work. Keep production default off until hosted pause/revocation receipts and that residual envelope are accepted; do not claim an absolute invoice cap against arbitrary hostile ingress. Reject unknown external ingress before expensive work and use provider/edge controls as additional defenses. SES pricing lists à la carte outbound at $0.10/1,000 and Essentials at $0.16/1,000 in its first volume band. The chosen AWS account plan remains unverified. Email-only cost for Tier 1 is $0.20/$0.32 and Tier 2 full 31-day use is $1.55/$2.48 respectively. These exclude data, optional features, Cloudflare, storage, database, payments and support. Reserve against the verified plan’s complete cost envelope; do not use the superseded Cloudflare $0.35/1,000 calculation for SES or claim net margins. Paid tiers remain exclusive. Queues pricing bills operations, with payload billing in 64 KiB chunks and retries adding reads. Pin current rates in the implementation cost worksheet; count normal and persistent failure paths, fan-out, DLQ, event volume and storage retention. CPU caps and billing alerts are detection/containment aids, not total-spend caps. Numeric platform dollar caps, aggregate provider capacity and warm-up limits require owner approval. SES configuration-set event publishing provides delivery/bounce/complaint feedback, for example through SNS to a bounded Cloudflare ingestion Worker and trusted Queue. Verify SNS signatures/certificate source, allowlisted topic ARN, account/region, subscription and provider-message binding before admission; never blindly follow arbitrary confirmation URLs. Deduplicate event IDs; tolerate replay, out-of-order and late events. Do not accept an unauthenticated HTTP JSON event as provider evidence. Store compact normalized facts, not subject/body copies. A delivered event means remote server acceptance. Hard bounces and complaints suppress immediately before further sends. Temporary failures stay provider-owned; a proposed three soft failures in seven days triggers review/suppression, subject to provider semantics. Reconcile provider-managed SES suppressions with local decisions using bounded cursors. Provider account-wide policy suppression always wins. Workspace unsubscribe is tenant-scoped; platform abuse suppression is global and cannot reveal another tenant’s address history. Operators cannot remove provider read-only suppression by changing local state. No automatic resubscription on import, plan change, refund or successful delivery. Double opt-in is the product default: signed-up contacts remain pending until a single-use expiring confirmation token is redeemed. Store consent purpose, source, policy/version, timestamps and evidence reference. Imports require consent mapping and an attestation plus evidence; imported unconfirmed contacts do not receive a campaign. Purchased/scraped lists are forbidden. Historical proven consent can use an explicit reviewed migration exception; do not blast confirmation emails at an unverified imported list. Confirmation/test sends need their own abuse and cost budgets, cannot be an open relay, and must respect suppression. Every campaign includes visible unsubscribe, business identity, postal address and accurate subject/From. Implement HTTPS List-Unsubscribe plus List-Unsubscribe-Post: List-Unsubscribe=One-Click under RFC 8058, and verify DKIM covers the required headers in received messages. The opaque high-entropy token is scoped to workspace, subscriber and purpose; store a hash, redact it from logs and avoid third-party assets/referrers. Unauthenticated POST unsubscribes idempotently without login or confirmation. GET shows the preference page and does not mutate (link scanners). Suppress immediately, including queued recipients. List-specific preferences may narrow subscription choices but must offer workspace-wide newsletter opt-out. The FTC CAN-SPAM guide requires truthful headers/subjects, required commercial identification and postal address, a working opt-out and honoring it within ten business days. This design uses immediate suppression and does not charge for opting out. Keep suppression available even while billing/access is suspended. For GDPR, record the lawful basis, withdrawal, access/export/erasure and retention process; double opt-in is a product policy, not a claim of automatic legal compliance. Confirm local ePrivacy/direct marketing requirements, processor agreements, transfer terms and controller roles with the legal owner before launch. Minimize IP/user-agent retention; consent evidence references must not become permanent raw tracking logs. Retain only the minimum suppression tombstone needed to prevent reimport, under an approved lawful basis and retention policy. Deletion fences prevent queued work resurrecting data. Open/click tracking defaults off, needs explicit privacy policy and consent review, and must be labeled approximate (proxies/scanners distort it). Initial analytics are accepted/delivered/deferred/bounced/complained/unsubscribed counts. Warm up each domain; proposed review triggers are any complaint among the first 100 accepted messages, or at least 0.1% complaints / 2% hard bounces over a defined 1,000-message window. These are conservative draft controls, not provider guarantees. Sparse samples need review; stale feedback or event ingestion failures pause expansion.

Retention — user-approved 2026-10-25

This approved newsletter retention standard covers GDPR and Vietnam PDPD Decree 13/2023 requirements for legal review; they do not establish compliance by themselves. The legal owner must also check Vietnam’s currently effective successor legislation and shorter statutory response deadlines; a product 30-day SLA cannot override a shorter legal duty. Erasure overrides routine three-year consent retention unless a documented lawful exception applies. Workspace deletion overrides indefinite suppression retention; recreating a workspace cannot silently restore consent. HMAC is pseudonymous data, not anonymous: keep keys outside tenant-visible data, version them, isolate them per workspace, and support deletion and bounded key rotation without storing raw email. Existing provider account-wide suppressions are a separate safety boundary; verify their plaintext retention/deletion capabilities and processor obligations before claiming end-to-end no-plaintext suppression. Global local abuse suppression must also avoid plaintext recipient storage; its scope is distinct from tenant opt-outs. Retention jobs run on Cloudflare with bounded pages, durable deletion fences, audit and no resurrection from queues or backups. Document backup expiry and processor deletion in the acceptance plan.

Proposed data model and authorization

Names below are proposals, not migrations. Use private service-only tables with RLS enabled and no anon/authenticated grants by default; member-facing APIs expose minimal authorized projections. Every tenant row has ws_id, and composite foreign keys (ws_id, resource_id) prevent cross-workspace parent/child references. Member access requires live workspace membership plus granular permissions for viewing newsletters, managing audiences, editing campaigns, sending campaigns, managing domains and managing subscriptions. Reuse manage_subscription for billing where appropriate. Sending and subscriber export require explicit rights; mailbox membership alone is insufficient. Test permission removal during a job. Privileged Workers receive narrow RPC capability, not a general user-facing service-role query proxy. Each RPC validates workspace, resource, claim lease and generation. Prefer invoker functions. Necessary SECURITY DEFINER functions use SET search_path = '', schema-qualified tables/functions, fixed SQL, explicit actor checks and narrow EXECUTE grants; revoke PUBLIC/anon/authenticated unless explicitly required. No caller-supplied actor ID substitutes for authentication. Audit decisions and provider/billing mutations append-only with redacted fields. A failed audit write aborts the associated approval or entitlement mutation.

Migration and rollout safety

Create additive private tables and indexes first, RLS/grants in the same migration. Avoid rewriting hot Mail/subscription tables or backfilling customer approval from legacy active flags. Add nullable references, backfill bounded keyset batches, add FK/check constraints NOT VALID where supported, then validate separately under short lock/statement timeouts. Use concurrent index creation for populated tables only in a migration path verified to permit nontransactional DDL. Never place CREATE INDEX CONCURRENTLY inside a transaction blindly. Retry only bounded known lock failures; record unknown migration outcome before retrying. Rehearse full reset and upgrade from a production-shaped anonymized fixture in an isolated database, including lock contention, RLS negative controls, constraint validation and rollback-by-disabling flags. Generate types from applied schema. Keep schema and its consuming contracts in the same rollout unit when required. CI builds the exact app commits; staging migration must pass before authorized production promotion and the gated supabase-production.yaml result. No manual sb:push/sb:linkpush. This design PR executes no migration.

Add-ons, Polar and daily quota

Recorded product decisions (2026-10-25)

The user approved SES for newsletter/bulk delivery and approved the retention and billing policies below as written. Free is 10/day only after workspace newsletter approval; every unapproved workspace receives 0 newsletter sends, regardless of payment. Domain and sender approvals remain independent prerequisites. Platform-wide GDPR/PDPD implementation is a separate lane; this document defines the newsletter retention standard that lane may cite, without expanding its scope. Scope: customer newsletter sending in Mail and platform administration in Infrastructure. Transactional email, connected accounts, workspace base tiers and AI credits retain their current policies. These decisions govern live and future migration paths; no older $5/500 or $2/2,000-per-day proposal may be seeded. A workspace has exactly one newsletter tier. No stacking, additive free allowance, simultaneous paid-tier grants or quota multiplication is permitted. The generic workspace add-on catalog remains useful for attaching this newsletter capability independently of base workspace billing, but its newsletter entries belong to one exclusive tier group. Rename provisional tables if a narrower newsletter-specific implementation is clearer. Tier selection must not replace the workspace’s unrelated FREE/PLUS/PRO/ENTERPRISE base subscription. The prices, caps and tier exclusivity are user decisions. Workspace timezone day boundaries, billing-anniversary pool reset, exact corporate identity plus explicit platform permission for approvers, conservative workspace daily/monthly spending caps and a global kill switch are orchestrator-selected defaults the user can override. Numeric spend caps remain a launch configuration gate. A Polar discount changes price, not entitlement. Coupons remain supported as product-restricted Polar discounts on either paid tier. Never infer quota from paid amount or browser coupon text. Bind each catalog entry to merchant, environment, product, price, currency and immutable entitlement version. Transition an existing paid tier through one subscription change instead of buying a second subscription; reconcile duplicate external subscriptions without granting twice. Entitlement resolution is a pure versioned function over approval, provider eligibility, the one effective tier and valid promotions. All grants remain constrained by global/provider/domain/abuse/spending ceilings. Workspace secrets may lower abuse limits but cannot create grants or bypass approval. Tier 1 permits at most 200/day while its 2,000-period pool remains; exhaustion permits zero sends until renewal, not a fallback extra 10/day. Tier 2 permits 500/day. Free permits 10/day only after newsletter approval; without approval every tier permits zero. Tier changes preserve prior usage and cannot reset the day’s consumed or reserved capacity to zero. Daily quota uses database time converted through the workspace’s persisted IANA timezone and resets at local midnight. Store timezone version, period start/end UTC instants and local date, not a bare date alone. DST days may be 23/25 hours. New timezone settings take effect at a scheduled boundary without opening an extra bucket; retain prior usage and enforce a transition interval that cannot grant two allowances. The UI shows the actual next reset in the workspace timezone. This product quota is separate from SES’s regional rolling 24-hour quota. Monthly pool periods use authoritative subscription billing-period start/end instants, anchored to the billing anniversary, not calendar months, quota-day boundaries or a reset cron. Respect Polar’s returned interval for short months, leap days and subscription changes; do not approximate it as 30 days. A UTC instant at the boundary belongs to exactly one half-open interval. Webhook reconciliation can reveal the new period late, but must never backdate duplicate grants. Period renewal and subscription eligibility must be verified before creating new capacity. In one transaction, freeze the full eligible audience and conditionally reserve the entire campaign recipient count against its tier daily allowance, monthly pool when applicable, and spending credits. The transaction either admits all recipients or none. Store quota_source, daily period ID, billing period ID, entitlement revision and reservation state. Count accepted and unknown submissions, including accepted hard bounces; release only proven unsent attempts to their original source and period. A proven-unsent reservation crossing either boundary is reallocated atomically against the new eligible periods before submission; accepted/unknown remains charged to its submission periods. Release cannot revive expired capacity. Upgrades do not reset existing use. No rollover or reset on retry, restart, coupon change or duplicate webhook; no negative balances under concurrency. Tests and confirmations have separate bounded budgets and cannot masquerade as campaigns. Regression requirements for these product decisions: Free 10/day; Tier 1 200/day and 2,000/period; exhausted pool denying sends; Tier 2 500/day; exact single-tier enforcement; pending/unapproved denial; full-count reservation and quota rejection without a partial campaign; local-midnight/DST/timezone-edit transitions; billing anniversary/short-month renewal; replay and concurrent reservation races. These are required implementation coverage, not tests executed by this documentation PR.

Checkout and lifecycle

Use the platform merchant’s separate Tier 2 ($10) and Tier 1 ($2) recurring products, fixed USD minor-unit prices of 1000 and 200 and environment-specific allowlisted IDs. Preserve existing seat/base subscription handling and classify newsletter_tier separately from tier and credit-pack products. Polar subscriptions and discounts support recurring offers and once, fixed-month or forever discount durations. Restrict codes to the intended product, dates and redemptions; record the advertised post-promotion price.
  1. A current member with billing rights requests an allowlisted plan. Server binds workspace/customer/environment and validates approval and coupon eligibility.
  2. Persist a unique checkout intent before calling Polar. Bind server-owned metadata and external customer identity to that intent; never trust workspace metadata submitted by the browser. A duplicate request reuses the intent.
  3. Create checkout through the installed SDK’s verified contract. Restrict success and return URLs to approved Mail/Pay routes. Unknown create outcome reconciles the same intent rather than blindly creating another subscription.
  4. Return from checkout shows payment pending until a verified webhook/readback confirms entitlement. Client success parameters never grant access.
Extend the existing Pay webhook adapter and Polar signature verification. Verify the exact raw body with the official SDK, timestamp and signature headers before parsing/dispatch. Enforce body size, environment, organization, product, customer/workspace and checkout-intent binding. Unique webhook receipt and entitlement update commit atomically; duplicates acknowledge the durable receipt, not a half-finished side effect. Out-of-order events trigger a bounded authoritative subscription readback instead of reverting newer state. A durable inbox permits fast acknowledgement after persistence and bounded Cloudflare processing; failures before persistence return retryable errors. Do not log signatures or whole payloads.

Billing behavior — user-approved 2026-10-25

Upgrades apply immediately after the verified Polar transition and are prorated through Polar. Downgrades/cancellations take effect at period end, then select the lower tier or Free; no mid-cycle cut. Prior usage remains charged. Tier 1’s pool starts only at the verified paid billing-period boundary and never receives an unverified extra pool during upgrade/downgrade reconciliation. On past_due, retain the existing full tier limits for seven days from the verified first past-due transition. Send bounded idempotent notices on days 0, 3 and 6 through Cloudflare-owned scheduling. Repeated events cannot restart grace. At expiry use Free limits until paid. Canceled (effective ended cancellation) or unpaid uses Free until resubscription; a future cancellation flag retains the current tier until period end. Non-payment never deletes data, and domain/sender approvals remain approved unless independently revoked for security or abuse. Refunds/chargebacks need reconciled explicit revocation rules; they never reset quota or silently delete content. Reserve the full eligible recipient count at scheduling, including daily quota, Tier 1 pool and spend. For future dates, reserve against the intended workspace-local day and verified subscription period; do not reserve beyond a known paid period or borrow unverified renewal capacity. If a later date’s tier cannot be established, leave the campaign draft until it can be admitted. A tier/grace/approval change revalidates all queued campaigns. If the remaining audience no longer fits, pause with a notice; never select a smaller quota-sized subset. Require explicit re-admission to resume. When several campaigns compete, use deterministic schedule/creation order in one locked allocation transaction. Full reservation prevents quota-driven partial sends; it cannot guarantee atomic external delivery. Bounces, withdrawal, abuse suspension, provider failure or Stop can still interrupt a campaign after some recipients were accepted. Show those partial outcomes truthfully and retain unknown-send fences. Recheck consent and suppression per recipient; never send to an unsubscribed person to preserve an all-recipient promise. Test downgrade/grace expiry before dispatch and mid-run, releasing only proven-unsent reservations and preserving accepted/unknown charges.

Sandbox acceptance plan

The design phase performs no provider writes. Provider feasibility uses a dedicated Polar sandbox, sandbox API/token/webhook secret and sandbox catalog IDs. The environment is separate from production; assert endpoint/organization before each setup action. Never fall back to production when credentials are absent. Current sandbox confirmation emails have recipient restrictions; lack of an email is not payment failure evidence. Create $10/month 500/day and $2/month 2,000-per-period (200/day) sandbox products, recurring prices and once/fixed/forever restricted discounts only in that sandbox. Exercise successful/failed checkout, invalid/expired/exhausted coupon, duplicate click, abandoned checkout, renewal, upgrade/proration, downgrade, scheduled and immediate cancellation, recovery, refund/chargeback where supported and portal return. Use supported test payment methods. Test forged/stale signatures, raw-body mutation, duplicate and reordered events, processing crash after receipt, wrong workspace/product/merchant/environment, subscription duplication and unknown provider writes. Freeze clocks for day/month boundaries. Unsupported lifecycle simulations use labeled fixtures and remain a hosted acceptance gap. Keep a redacted evidence matrix with product IDs privately; never put keys or customer data in PRs.

UX specification

Infrastructure platform console

Add Newsletter approvals under platform administration: workspace, domain and sender review tabs, pending counts, age, risk filters and detail panels. Detail shows submitted identity/consent evidence, exact DNS results and timestamps, provider eligibility, previous decisions and associated workspace. Approve/reject needs a reason and current revision; suspend/revoke is always available with appropriate authority. No one-click bulk approval in the first release. Access requesters see actionable rejection reasons without internal risk notes. Sending health shows queue lag, oldest unknown send, feedback freshness, delivery/bounce/complaint rates with sample sizes, suppression sync state, provider capacity, budget reserved/spent/remaining and stop status. Scoped and global Stop controls show persisted generation and in-flight uncertainty; resume requires review and a fresh bounded lease. Domain setup displays DNS instructions and state even while approval is pending. Existing Infrastructure global templates, blacklist and transactional queue remain distinct destinations.

Mail newsletter workspace

Add Newsletter as a first-class workspace destination. Any eligible workspace member can discover the request/status screen without creating an internal Mail mailbox. Approved users reach Campaigns, Audiences, Templates, Domains & senders, and Plan & usage. Build the access bootstrap separately from inbox-only corporate admission so customers can use newsletters without access to staff mailboxes.
  • Access request: business/contact, expected content/volume and audience consent inputs; submitted/pending/rejected/suspended states, timestamps and recovery. Billing stays unavailable until required eligibility is established.
  • Audiences and lists: subscriber status/consent timeline, tags and segments, search and permission-gated export; bounded CSV import with preview, field map, duplicate/suppressed counts, consent evidence and resumable errors. Neutralize spreadsheet formulas in exports. Lists do not override workspace opt-out.
  • Composer and templates: subject/preheader, approved sender, accessible rich text and plain-text version, desktop/mobile preview, safe merge-field allowlist, autosaved version history and test send. Mandatory identity/unsubscribe footer cannot be removed. Sanitize HTML; no scripts, arbitrary template execution or remote server-side URL fetches. Show missing fields before scheduling.
  • Scheduling: explicit timezone plus resolved send date/offset; persist UTC instant and IANA zone, resolve DST ambiguity explicitly. Review audience count, exclusions, quota, estimated cost and readiness, then confirm immutable revision. Scheduling creates a durable Cloudflare-owned job, not a browser timer.
  • Campaigns and analytics: draft/scheduled/sending/paused/completed/canceled, recipient-level authorized outcomes, unknown counts, progress and bounded retry recovery. Accepted and delivered are separate. Do not promise inbox placement.
  • Domain and sender setup: step-by-step DNS rows, copy controls, last checked, next check/expiry, independent verification and approval badges, denial reason and bounded retry. Explain SES identity verification and account readiness before collecting payment.
  • Plan and usage: daily accepted/unknown/reserved and remaining quota sources and monthly pool balance, workspace-local reset and subscription-period end, current price/discount duration/next price, payment state, upgrade/coupon entry and manage/cancel link. Show both plan and safety ceilings when the latter limits sends; avoid misleading unused-capacity claims.
Every new label/error goes into EN and VI bundles in every shipping shared surface; run bun i18n:sort. Update each app’s navigation.tsx aliases, children, icons and permissions. Use existing shell hierarchy and accessible status text/focus handling, not color-only states, native dialogs or hard-coded hue classes. Keep new files under 700 LOC and split components near 200 LOC. Browser verification for this task uses an admitted fleet host.

Security and threat model

No secrets in workspace_secrets projections, client bundles, analytics or audit. Store provider credentials in the established server secret mechanism; workspace rows contain references/configuration only. Do not read or print existing secrets to inventory them. Independent security review is required before integrating identity, RLS, billing, webhook or Worker control changes. Open critical/high findings retain the repository release hold.

Delivery plan and review boundaries

Each row is a small PR boundary; split a row further if its implementation exceeds a reviewable scope. Use native GitHub stacks only for real dependencies; independent UI scaffolding and provider research can be separate. The integration owner owns merge/promotion. This draft PR is never merged by the design child. Local verification stays build-free; queue heavy tests/type checks through ttr resources and use an admitted devbox where appropriate. CI must run applicable lint/type/test and real app/Worker builds on the exact commit. Do not run bun validate or app release builds on this machine. Required database reset tests run only in an admitted isolated environment. Production cutover, Polar live catalog writes and customer sending need separate release authorization and proof.

Remaining implementation gates

SES account/region, identity ownership/delegation, configuration set, verified feedback and actual pricing/quotas need read-only acceptance. Numerical spending caps need owner configuration. Refund/chargeback disposition remains explicit; no quota resets or silent content deletion. Retention and billing policies above are approved, not pending decisions. No live checks, sends or production writes are included in this documentation update; credentials must use request_secret.