# CONTRACT.md — Mango

What this product does. Every clause has a stable ID and requires at least one tagged test before release; `pnpm verify` will report each as satisfied, overridden, or broken once the seed-spec harness replaces the prototype-only verifier described in `HANDOVER.md`. Security, privacy, and operational guarantees are in `BASELINE.md`; a clause here may supersede one of them by naming its `BASE-` ID. One does: CONT-013 supersedes BASE-DATA-003 for contact erasure. Capacity and rate limits are in `seed.json → limits`. Times are p95 at those limits. Clauses marked *Policy* have a default that buyers may replace through the named extension point.

## Scope

An approval-first marketing desk for one ecommerce store. Mango reads first-party store and audience signals, proposes an evidence-backed email and SMS campaign, lets an operator inspect and edit every recipient rule and message, and sends only the exact revision an operator approves. It reports what providers actually did without presenting forecasts as facts.

## Home

- **HOME-001 — Owner front door.** The sessionless landing at `/` names the configured deployment owner, shows their configured one-line description of Mango, and links to `/signin`. It contains no vendor pricing, feature tour, testimonials, metrics, cross-store claims, or telemetry. It may show the static credit `Powered by Mango · runeditrun.com` only when the owner enables it in configuration.

## Terms

- **Operator** — a signed-in human running this deployment.
- **Source record** — one imported commerce fact (customer, product, variant, inventory level, order, refund, cart, or browsing event) with the identifier and occurrence time the store gave it.
- **Contact** — one person, identified by a canonical email address, phone number, or both, with an independent consent state per channel.
- **Channel** — email or SMS.
- **Proposal** — a generated, unsent recommendation for a campaign.
- **Campaign** — the operator-owned object a proposal becomes. It holds one or more **steps**, each a single channel with its own content and scheduled instant.
- **Revision** — an immutable snapshot of a campaign's name, channels, audience rule, content, sender identity, and schedule. Operators approve a revision, not a campaign.
- **Candidate** — a contact matching an approved revision's inclusion rule before exclusions.
- **Eligible contact** — a candidate that survives every exclusion in AUD-002, AUD-003, and AUD-004.
- **Recipient-step** — one eligible contact paired with one step: the unit that is handed to a provider, retried, and given a terminal outcome.
- **Dispatch** — the process that turns a step's recipient-steps into provider hand-offs.
- **Delivery** — a provider-confirmed arrival, distinct from a hand-off and from provider acceptance (SEND-006).

## Operators

- **OPER-001 — Equal operators.** Every operator can see and act on every proposal, campaign, contact, and setting. There are no roles.
- **OPER-002 — Management.** Operators are invited and removed in settings. The operator configured at setup can be removed only by themselves. *Policy: `operator.management.v1`; default: any operator may invite or remove.*
- **OPER-003 — Removal does not rewrite history.** Removing an operator revokes their sessions and leaves every proposal, approval, revision, and audit entry attributed to them intact.

## Store signals

- **STORE-001 — Store connection.** One commerce connection imports customers, products, variants, inventory, orders, refunds, carts, and browsing events through `commerce.store.v1`, retaining each source record's identifier and occurrence time.
- **STORE-002 — Source identity.** A commerce webhook or scheduled sync carrying a source identifier already stored updates that source record; it never creates a second customer, order, cart, refund, or browsing event.
- **STORE-003 — Freshness.** The Decision Desk shows, per source type, the completion time of the last successful sync and the error of any sync that has failed since it.
- **STORE-004 — Source failure.** If the configured commerce adapter is unavailable, ingestion and proposal generation record a failed operation carrying the adapter's error; saved drafts and already recorded delivery outcomes remain readable and no campaign is sent as a side effect.
- **STORE-005 — Stale sources block approval.** A source type is stale when its last successful sync completed more than 24 hours ago or a sync has failed since it. A proposal or campaign whose inclusion or exclusion rule reads a stale source type is labelled stale and cannot be approved until that source type syncs successfully.
- **STORE-006 — Declared adapter capability.** The commerce connection declares which source types it supplies. An audience rule, exclusion, or proposal that requires a source type the connection does not supply is shown as unavailable and cannot be approved; it never resolves to an empty or partial audience.
- **STORE-007 — Ingestion latency.** A source record from an accepted commerce webhook is readable in the operator app within 60 seconds of the webhook being acknowledged.

## Contacts and consent

- **CONT-001 — Contact identity.** Email addresses are compared case-insensitively after trimming, phone numbers are stored in E.164 form, and one canonical email address or phone number identifies at most one contact.
- **CONT-002 — Channel status.** Each contact has an independent state per channel: *pending* (consent captured, confirmation outstanding), *subscribed*, *non-subscribed* (no consent evidence recorded), *unsubscribed* (opted out), or *suppressed* (blocked by CONT-006 or CONT-013). Only *subscribed* is eligible for a marketing send. Store activity or consent on one channel never changes the other channel's state.
- **CONT-003 — Consent evidence.** Every subscription stores the channel, brand or legal sender, SMS sender or programme where applicable, message subject or category, disclosed frequency, destination jurisdiction, capture method and source, occurrence time, consent text and version, and confirmation evidence. Consent applies only to that recorded scope and current recipient; a capture or import without the evidence creates a non-subscribed contact, and a phone number reported as reassigned or no longer belonging to that recipient becomes non-subscribed until fresh evidence is captured.
- **CONT-004 — Opt-out precedence.** An email unsubscribe, one-click unsubscribe, or SMS opt-out sets that channel to unsubscribed before the request is acknowledged, and excludes it from every draft, scheduled campaign, and queued recipient-step. Later imports, syncs, store events, merges, or operator edits never reverse it.
- **CONT-005 — Resubscription.** A previously unsubscribed channel becomes subscribed only from new affirmative consent evidence recorded after the opt-out and confirmed per CONT-009. A suppressed channel also requires the suppression cause to be resolved. An operator edit alone cannot resubscribe either state.
- **CONT-006 — Email suppression.** A hard bounce, spam complaint, or provider suppression suppresses that email address before the next hand-off to any campaign. Soft bounces are recorded and visible, and suppress the address according to the bounce policy; a later provider-confirmed delivery resets its consecutive-soft-bounce count. *Policy: `contact.soft-bounce.v1`; default: suppress after three consecutive soft bounces.*
- **CONT-007 — SMS compliance replies.** A signed inbound SMS webhook consumes the adapter's canonical result for that sender, programme, and destination jurisdiction. STOP, STOPALL, END, QUIT, CANCEL, UNSUBSCRIBE, OPTOUT, and REVOKE always opt out; HELP and INFO request help; START and UNSTOP begin the fresh-consent flow required by CONT-005 and never subscribe by themselves. Mango records each reply once and applies an opt-out before acknowledging the webhook. It returns the configured compliance response only when the provider has not already sent the required reply.
- **CONT-008 — Contact history.** A contact page shows source activity, consent changes, suppressions, campaign eligibility decisions, channel deliveries, and operator actions in time order.
- **CONT-009 — Confirmation.** Where the opt-in policy requires confirmation for a channel, a contact captured with consent on it enters *pending* and receives one confirmation message on that channel; following its opaque per-contact confirmation link sets the channel to *subscribed* and stores the confirming request's time. A pending channel receives no marketing send, and a confirmation link stops working 30 days after it is issued. Where the policy does not require confirmation, the captured consent evidence of CONT-003 sets the channel to *subscribed* directly. *Policy: `contact.opt-in.v1`; default: confirmation is required on both channels.*
- **CONT-010 — Import.** An operator imports contacts from a CSV whose rows carry an email address or phone number and, optionally, the consent evidence CONT-003 requires. Each row is validated independently; a row matching an existing canonical identifier updates that contact rather than creating a second; re-running the same file changes nothing further. The import reports created, updated, and rejected row counts with a reason per rejected row, and never sets a channel to subscribed for a contact CONT-004 has unsubscribed.
- **CONT-011 — Merge.** An operator can merge two contacts. The surviving contact keeps the union of source activity, consent records, campaign history, and suppressions, and takes the most restrictive state per channel: suppressed beats unsubscribed, which beats non-subscribed, which beats pending, which beats subscribed. A merge cannot resubscribe a channel.
- **CONT-012 — Dormancy without deletion.** A contact with no recorded click, order, or consent change inside the dormancy window is labelled dormant and excluded by the audience policy (AUD-003). Mango never deletes, unsubscribes, or suppresses a contact for inactivity; BASE-DATA-002 stands, and clearing a dormant list is an operator action.
- **CONT-013 — Erasure and surviving opt-out.** Deleting a contact removes their profile, source activity, consent evidence, message content, and delivery detail within five minutes, confirms completion, and anonymises their actor identity in retained audit entries as BASE-DATA-003 requires. It retains only one opt-out record per unsubscribed or suppressed channel: a salted one-way hash of the email address or phone number, the channel, reason, and time. A later import, sync, or capture matching that hash creates a contact whose channel is already unsubscribed. **Supersedes BASE-DATA-003 only for this opt-out dependency**; all of that baseline clause's other guarantees and all other personal-data entities remain unchanged.

## Proposals

- **PROP-001 — Decision Desk.** The Decision Desk lists proposals in the *proposed* state ordered by the proposal policy, highest-ranked first. *Policy: `proposal.selection.v1`; default: rank by expected revenue where this deployment has enough of its own attribution history (RESULT-003) to estimate it, then by the earliest send-by instant; proposals with neither rank last.*
- **PROP-002 — Evidence.** A proposal names its triggering source events, lookback window, inclusion rule, exclusion rule, source-data as-of time, send-by instant, proposed channels and step instants, and the method behind every forecast or confidence label.
- **PROP-003 — Counts.** A proposal distinguishes candidates, excluded contacts, eligible contacts, and per-channel recipient-steps. No count is labelled recipients until exclusions have been applied.
- **PROP-004 — Content.** A proposal contains an editable campaign name, email subject and body, SMS body when SMS is proposed, sender identity, destination links, and a preview for every selected channel.
- **PROP-005 — Owner control.** A generated proposal is a draft and cannot schedule or send anything until an operator explicitly approves a particular saved revision.
- **PROP-006 — Grounded generation.** AI-generated audience explanations, timing claims, and forecasts use only this deployment's imported store data and configured knowledge, supplied to `ai.provider.v1`. A generation containing a claim not derivable from that evidence is rejected and the proposal is marked failed per PROP-007; no generic marketing copy is substituted.
- **PROP-007 — Generation failure.** If the configured AI adapter returns invalid output or does not complete within 60 seconds, the proposal is marked failed carrying the provider error, no semantic fallback is created, and existing proposals and campaigns are unaffected.
- **PROP-008 — Forecast provenance.** Every revenue, recovery-rate, or confidence figure names the deployment's own campaigns and store events it was computed from and the number of them. Mango never presents a benchmark drawn from other stores, and where its own history is too thin to compute a figure it says so instead of showing a range.
- **PROP-009 — Proposal states.** A proposal is *proposed*, *approved* (an operator approved a revision and a campaign exists), *dismissed* (an operator rejected it, with the reason recorded), *expired* (its send-by instant passed), or *failed* (PROP-007). Only a proposed proposal can be approved or dismissed, and every transition records its actor and time.

## Audiences

- **AUD-001 — Review snapshot.** Campaign review shows the audience rule and as-of time, candidate count, each exclusion reason with its count, eligible contact count, and the recipient-step count per channel.
- **AUD-002 — Consent and suppression.** Contacts whose state on a channel is pending, non-subscribed, unsubscribed, or suppressed are excluded from that channel regardless of segment membership or an operator-authored inclusion rule.
- **AUD-003 — Commerce and dormancy exclusions.** Contacts excluded by the audience policy are listed in review with their reason and count. *Policy: `audience.exclusions.v1`; default: exclude a contact from a product campaign for seven days after purchasing that product, while a refund or return of it is unresolved, and while the contact is dormant under a twelve-month dormancy window (CONT-012).*
- **AUD-004 — Frequency protection.** A contact inside the channel's frequency window is excluded from that step and recorded with the reason `frequency-window`, never silently deferred to a later time. *Policy: `audience.frequency.v1`; default: 24 hours since the contact's last marketing email and 72 hours since their last marketing SMS.*
- **AUD-005 — Dispatch recheck.** Eligibility is recalculated when a step's dispatch begins and again immediately before each provider hand-off, so a purchase, refund, opt-out, bounce, complaint, consent change, merge, or frequency-window change after approval prevents that delivery and is recorded as the exclusion reason. Every source type used by the audience must still satisfy STORE-005; if refresh fails or the source becomes stale, the affected channel pauses before any further hand-off and resumes only after a successful refresh.
- **AUD-006 — Multi-step exit.** Each later step re-applies its audience and exclusion rules; a contact who converts or becomes ineligible after an earlier step receives no later step.
- **AUD-007 — Frozen candidate set.** Approval freezes the candidate set resolved at that instant. A contact who first matches the inclusion rule after approval is never added to the approved campaign, and each contact yields at most one recipient-step per channel per step even when they match the rule more than once. Exclusions still apply at dispatch (AUD-005).

## Campaigns

- **CAMP-001 — States.** A campaign is *draft* (editable, nothing scheduled), *scheduled* (an approved revision with a future step instant), *dispatching* (a step has begun handing off), *paused* (dispatch stopped by SEND-009), *completed* (SEND-007), *cancelled* (CAMP-009), or *failed* (its first step could not begin before its deadline because a required adapter or sender registration was unavailable). Every transition records its actor or the feature that acted, and its time; an invalid transition is rejected.
- **CAMP-002 — Draft editing.** Operators can edit and persist the campaign name, selected channels, audience rule, message content, sender identity, links, and schedule while a campaign is a draft.
- **CAMP-003 — Revision preview.** Desktop, mobile, and plain-text previews render from the saved revision that will be approved, including resolved personalisation examples and the compliance footer or SMS opt-out text that will be sent.
- **CAMP-004 — Approval checks.** Approval atomically validates the audience, consent, source freshness (STORE-005), sender registration, email authentication, sending reputation (MSG-011), compliance content, personalisation, links, schedule, and adapter configuration. A sender adapter must provide effective deduplication and provider reconciliation as required by SEND-001 and SEND-008. Any failure leaves the campaign a draft and names every blocking check.
- **CAMP-005 — Idempotent approval.** Repeated approval requests carrying the same campaign and revision identifier produce one scheduled campaign and one set of steps and recipient-steps, whatever the number of requests.
- **CAMP-006 — Schedule.** Each step stores an IANA time zone and the resolved UTC instant. A local time that does not exist or is ambiguous under daylight saving is rejected until the operator chooses an unambiguous instant. *Policy: `campaign.send-time.v1`; default: resolve every step against the store time zone and the operator-selected local time.*
- **CAMP-007 — Scheduled edits.** Editing a scheduled campaign creates a new draft revision and leaves the approved revision active until the replacement passes approval. Replacement approval atomically makes the new revision the campaign's only active schedule and cancels every pending recipient-step of the prior revision. Once any step has begun dispatching, edits can only create a new campaign; the original campaign and its later steps remain active until the operator explicitly cancels them.
- **CAMP-008 — Test send.** A test sends only to the configured operator test addresses or phone numbers, is visibly marked as a test in its content and in campaign history, and changes no contact activity, reporting, attribution, or frequency protection.
- **CAMP-009 — Cancellation.** Cancelling a scheduled, dispatching, or paused campaign stops every step and every recipient-step confirmed not handed to a provider within 30 seconds, records provider-confirmed hand-offs separately, and leaves an in-flight request in `handoff-unknown` until SEND-008 reconciles it. It never claims to recall a delivered message. Campaign detail shows the time remaining until the next step dispatches.
- **CAMP-010 — Step deadline.** Each step carries a send-by instant, defaulting to the end of that step's scheduled local day. Recipient-steps not handed to a provider by then are skipped and recorded as `deadline-passed`; a step whose deadline passes before dispatch begins does not send.
- **CAMP-011 — Dispatch punctuality.** Dispatch of a scheduled step begins within 60 seconds of its resolved UTC instant, and each step's instant dispatches exactly once even if the scheduler runs twice.

## Message safety

- **MSG-001 — Sender identity.** Every email uses the configured business display name, From address, reply-to address, and physical postal address; every SMS uses a sender registered for the recipient's country.
- **MSG-002 — Email authentication.** A marketing email cannot be scheduled unless the mail adapter reports SPF, DKIM, and DMARC passing for the sending domain and the visible From domain aligns with an authenticated domain.
- **MSG-003 — Email unsubscribe.** Every marketing email carries a visible unsubscribe link and an opaque per-recipient HTTPS `List-Unsubscribe` URL with `List-Unsubscribe-Post: List-Unsubscribe=One-Click`; DKIM covers both headers. The one-click URL accepts a context-free HTTPS POST body of `List-Unsubscribe=One-Click`, does not redirect, and applies CONT-004 before returning success. The visible link opens a page that applies CONT-004 on a single confirming action and never on page load, so a mailbox scanner or link prefetcher cannot unsubscribe anyone. Both paths are idempotent under repeats, need no session or cookie, and reveal no contact other than their own.
- **MSG-004 — SMS permission.** An SMS is eligible only when its phone number is subscribed for the recorded consent scope and the SMS adapter confirms an approved sender for that recipient's country. For every permitted sender and jurisdiction, the adapter must be able to receive and enforce the standard opt-out and help keywords in CONT-007; otherwise SMS is blocked for that recipient.
- **MSG-005 — SMS opt-out.** Every marketing SMS carries the configured programme identity and `Reply STOP to unsubscribe`, or the jurisdiction's required equivalent, and the configured frequency disclosure where required. An opaque unsubscribe URL may be additional but never replaces reply-based opt-out. Review shows the exact compliance text and resulting segment count.
- **MSG-006 — Links.** Scheduling is blocked when a destination link is malformed, is not HTTPS, or resolves to a host outside the allowed link hosts configured in settings. Review names every blocked link.
- **MSG-007 — Content checks.** Review names blocking and advisory content findings per channel. An operator can acknowledge an advisory finding; the consent, sender registration, opt-out, authentication, link, personalisation, and reputation checks are blocking and cannot be overridden.
- **MSG-008 — Personalisation.** Every personalisation token carries a fallback value. Scheduling is blocked when a token has no fallback and cannot be resolved for any one eligible contact; otherwise the fallback is rendered and the count of contacts using it is shown in review.
- **MSG-009 — Email body.** Every marketing email is sent as `multipart/alternative` with an HTML part and a plain-text part carrying the same offer, links, and unsubscribe link, plus the preheader text set on the revision. Operator-authored HTML is transmitted as authored within the allowed tag and attribute set, which admits no script, form, or remote stylesheet; the preview renders it sanitised per BASE-INPUT-002.
- **MSG-010 — Unsubscribe availability.** The unsubscribe path answers within 2 seconds and is rate-limited per unsubscribe token at the limit in `seed.json`, not per client IP address. The token is the rate-limit key declared for this public path under BASE-ACCESS-003, so mailbox-provider requests for unrelated recipients cannot consume one another's allowance; an exceeded token allowance returns 429 without affecting other tokens.
- **MSG-011 — Sending reputation.** Once a sending domain has at least 1,000 marketing deliveries in the reporting window, scheduling a marketing email from it is blocked while provider-reported complaints divided by delivered marketing emails are at or above 0.3%, or hard bounces divided by attempted marketing hand-offs are at or above 5% (RESULT-006). A provider's stricter block applies at any volume. The block names each numerator, denominator, reporting window, and provider rule, cannot be acknowledged away, recomputes when late facts arrive, and clears only when every applicable threshold is below its limit.

## Delivery

- **SEND-001 — Provider hand-off.** Email uses `mail.sender.v1` and SMS uses `sms.sender.v1`. Every recipient-step carries a provider-effective idempotency key derived from the campaign, revision, step, and contact. Mango stores the provider message identifier before treating it as handed off. A timeout or lost response becomes `handoff-unknown` and is reconciled by provider lookup before any retry; an adapter whose deduplication retention cannot cover the campaign deadline and reconciliation window cannot pass CAMP-004. A retried job, redelivered queue message, or resumed dispatch therefore never produces a second provider message.
- **SEND-002 — Quiet hours.** SMS is handed off only inside the recipient-local legal and provider-required windows. The recipient time zone is resolved from recorded location evidence with its source and freshness, never substituted with the store time zone; an unknown or stale zone blocks hand-off. Legal and provider windows are mandatory minima that a policy cannot weaken. *Policy: `sms.quiet-hours.v1`; default: defer until the next allowed instant at or before the step's send-by instant (CAMP-010), otherwise skip and record `quiet-hours-deadline`.*
- **SEND-003 — Throttling and progress.** Dispatch paces hand-offs to the provider and carrier rate limits in `seed.json`. Campaign status shows the estimated completion instant and updates the handed-off, delivered, skipped, and failed counts within 30 seconds of each change.
- **SEND-004 — Transport failure.** A transient provider or network failure on a recipient-step is retried up to 5 times over 1 hour with increasing delay, except that `handoff-unknown` is reconciled rather than retried. A permanent rejection or exhausted retry budget marks that recipient-step failed with the provider's error and campaign detail shows it; a hard rejection, complaint, or provider suppression also updates CONT-006 atomically before another hand-off.
- **SEND-005 — Provider-event identity.** Every signed provider webhook is stored once as an immutable fact using the strongest identity that adapter declares: provider event identifier where supplied, otherwise provider message identifier, event kind, provider event time or version, and a stable payload digest. Replaying or reordering delivery, bounce, complaint, suppression, and SMS reply facts produces the same derived delivery disposition and contact state, and an older fact never downgrades a later provider disposition.
- **SEND-006 — Delivery truth.** A recipient-step has a transport disposition of queued, handoff-unknown, handed-off, accepted, delivered, bounced, skipped, or failed, plus independent complaint and suppression facts. *Delivered* is recorded only from a provider fact asserting delivery; provider acceptance is never reported as delivery. A later complaint remains visible without erasing the earlier delivery fact, and a skipped disposition carries its reason.
- **SEND-007 — Partial completion.** A campaign becomes completed only once every recipient-step has a terminal transport disposition; `handoff-unknown` is not terminal. Its summary keeps delivered, skipped, failed, bounced, complained, and suppressed totals separate and never sums them into a single success figure. Later complaint or suppression facts update the completed campaign's summary and the contact ledger.
- **SEND-008 — Resumable dispatch and reconciliation.** Dispatch survives worker eviction, redeployment, and restart: it resumes from recipient-steps without a terminal transport disposition, sends nothing twice (SEND-001), and needs no operator action. At the reconciliation interval in `seed.json`, it queries the provider for handoff-unknown and other unresolved messages and imports missed provider facts. After the provider's declared lookup window expires, an unresolved message becomes failed with `outcome-unconfirmed`; it is never counted as delivered or retried blindly. A campaign never remains dispatching with no work or reconciliation in progress.
- **SEND-009 — Provider outage.** When hand-offs to a provider fail transiently for 5 continuous minutes, or the adapter reports the provider unavailable, the affected campaign channel moves to paused and no recipient hand-offs are attempted on it. The adapter runs a bounded health probe or non-recipient canary at the reconciliation interval in `seed.json`; a successful probe resumes dispatch automatically, subject to CAMP-010 and AUD-005. The pause and provider error are shown on campaign detail, and each operator is emailed once as soon as the mail provider is available.

## Results

- **RESULT-001 — Campaign history.** Operators can list campaigns by state and channel, open the approved revision, and inspect its audience snapshot, delivery timeline, cancellation, and per-channel outcome totals.
- **RESULT-002 — Engagement.** Clicks and store conversions are shown as observed events. Open tracking is off by default; when an operator enables it, opens are labelled privacy-sensitive estimates and never support a confidence, deliverability, or attribution figure.
- **RESULT-003 — Attribution.** Revenue attributed to a campaign names the qualifying store event and attribution window, is reported separately from any forecast, and is assigned at most once per order. *Policy: `campaign.attribution.v1`; default: the most recent non-automated tracked click in the seven days before purchase wins; a cancellation or refund subtracts the corresponding attributed amount.*
- **RESULT-004 — Cost.** Each AI call and provider hand-off records the external provider, model or channel, billable units, and reported cost; totals are visible by campaign and by day.
- **RESULT-005 — Link tracking.** A tracked link is rewritten to an opaque per-recipient-step redirect on this deployment that records the request and forwards to the original URL. The redirect sets no cookie, loads nothing, and carries no contact identifier in the destination URL. Known mailbox security scanners and bot requests are retained as automated events but excluded from engagement and attribution. An operator can disable tracking per campaign, which sends the original URLs and records no clicks.
- **RESULT-006 — Deliverability reporting.** Per sending domain and SMS sender, Mango shows the delivered, bounced, complained, and failed counts and the resulting hard-bounce and spam-complaint rates over the reporting window in `seed.json`, and the rates MSG-011 is currently evaluating.

## Data

- **DATA-001 — Export contents.** The export contains every contact, source record, consent record, suppression and surviving opt-out record (CONT-013), proposal, campaign, revision, audience decision, message, recipient-step outcome, attribution event, setting, and audit entry as JSON, and every uploaded campaign asset as its original file.

## Out of scope

Declared in `seed.json` as non-goals and not tested: multiple stores or workspaces, roles and permissions, a general CRM, signup-form, landing-page, and website builders (the deployment serves only its own consent-confirmation and unsubscribe pages), social and advertising campaigns, store transactional messaging such as order, shipping, and account notifications, autonomous sends, visual journey automation, A/B and multivariate testing, predictive send-time models, multi-touch attribution, purchased-list prospecting, and native mobile apps.
