# Seed tests (Full depth)

A configuration finding is a lead. A seed test turns it into evidence: a controlled identity goes through the real path and the result is recorded with timestamps. In Full depth every FAIL and every P0 or P1 WARN gets a seed result, or is labelled unconfirmed with the reason. Plan template: [../assets/seed-test-plan-template.yaml](../assets/seed-test-plan-template.yaml).

## Safety

- Explicit approval per test, from the person the user names, recorded in the plan. A seed test creates profiles, sends messages or changes subscription states, so it is never part of the read-only pass.
- A person the user names runs each approved test; the agent writes the steps and records the evidence. If the agent runs one itself, it goes through agent-write-safety with that approval, in the test workspace or internal test group. The plan records who ran each test.
- Run in a test workspace or project where one exists. Otherwise use an internal test group in production, after listing every live journey that shares the seed's trigger or exit events, so seeds cannot enter journeys nobody planned.
- Use mailboxes and numbers the team controls. Klaviyo does not accept @example.com addresses into its event or profile processing (custom integration FAQ, read 2026-11-02), so seeds need real controlled mailboxes. Numbers are entered by the user in the platform, never pasted into chat. The plan and the report name seeds by key (seed-01); addresses and numbers stay in the platform seed list.
- Braze "Test Canvas" previews admit ineligible users, so they prove content and branch logic only, not eligibility (from braze-implementation-qa).
- List every record a test creates, flag seeds as internal (SG04) and exclude them from metrics.
- Never use real customer profiles. Never generate load against vendor APIs.

## Seed matrix

### S01 new eligible entrant (JC01, JC02, JC09)

- Setup: a seed meets the entry condition through the real producer, not an import.
- Action: trigger the business event once.
- Expected: one entry and the first message within the documented delay.
- Evidence: the entry record with its timestamp; the received message with headers saved.

### S02 goal reached during a delay (JC04, JC05)

- Setup: the seed enters a multi-step journey.
- Action: complete the goal during the first delay.
- Expected: exit on the goal; no later message.
- Evidence: the exit record with its reason; no message after the goal timestamp.

### S03 topic opt-out with another topic allowed (PC04)

- Setup: the seed is subscribed to two topics.
- Action: turn one topic off in the preference centre.
- Expected: the switched-off topic stops in every sender; the other still sends.
- Evidence: the preference state in each sender; the next send per topic.

### S04 one-click unsubscribe from the mail client (PC03, FC08, DL07)

- Setup: the seed receives a marketing message from each bulk stream.
- Action: use the client's unsubscribe button (the one-click POST).
- Expected: suppressed in every sender that can reach the address within the audit target of 1 hour.
- Evidence: the click time; the suppression time in each sender; the next scheduled send skipped.

### S05 body link scope against one-click scope (PC04, DL07)

- Setup: a second seed, same as S04.
- Action: use the body unsubscribe link.
- Expected: the scope matches what the page promises and what one-click does; no login or password; done on one page.
- Evidence: the scope reached by each mechanism, per sender; whether the link asked for a login or password; how many pages it took to finish (DL07 rates a login or more than one page WARN, FAIL under CAN-SPAM).

### S06 duplicate profiles with mixed states (PC09, TD07)

- Setup: two seed profiles share one controlled address; one is unsubscribed.
- Action: send a marketing message whose audience includes both.
- Expected: nothing reaches the address.
- Evidence: the send log for both profiles.

### S07 SMS STOP (PC08)

- Setup: an SMS seed opted in.
- Action: reply STOP from the controlled number.
- Expected: no further SMS from any sender that can text the number.
- Evidence: the STOP timestamp; the opt-out state in each SMS-capable sender.

### S08 holdout member (MH03, MH04)

- Setup: a seed assigned to the holdout through the real assignment path.
- Action: make the seed eligible for optional journeys in every sender.
- Expected: no optional message from any sender; required service messages still arrive.
- Evidence: the send log per sender for the seed.

### S09 quiet hours with a known timezone (FC07, TD08)

- Setup: a seed whose timezone puts local time inside the quiet window.
- Action: trigger an optional message.
- Expected: held or aborted as configured; nothing delivered inside the window.
- Evidence: the send time in recipient local time.

### S10 cap collision across senders (FC04, FC09)

- Setup: a seed eligible for optional messages from two senders on the same day.
- Action: trigger both, then a task-critical message.
- Expected: the policy cap holds across senders and the task-critical message is not blocked by broad campaigns.
- Evidence: sends per sender with timestamps; block reasons.

### S11 stale-write replay after an opt-out (PC01, PC02)

- Setup: the seed opts out of a topic.
- Action: wait past the next scheduled sync or import that writes the preference field.
- Expected: the opt-out stands in every sender; no optional send in that scope.
- Evidence: the preference history per sender; the sync run time; the send log.

### S12 multi-account recipient (TD07)

- Setup: the seed administers two accounts in different states.
- Action: trigger an account journey for one account.
- Expected: the message names the right account and its state.
- Evidence: the message content with the account reference.

### S13 import gate (TD04)

- Setup: a historical seed profile created more than 30 days ago.
- Action: run the import path, with its documented gate, on a one-row batch.
- Expected: profile history updates; no live journey entry.
- Evidence: the entry log after the import; the gate setting.

## Timing

- Wait for every sync schedule in the path before judging (a nightly sync means checking after its next run).
- Record timestamps with the timezone, and the clock source (platform log, mail client, warehouse).
- Recheck after the longest delay in the journey under test.

## Recording

- Fill the plan's result and records_created fields as tests run.
- Put the evidence reference next to the finding in the report and the gap list: "S11 passed 2026-10-16 03:10 UTC, seed-03 still opted out in both senders".
- A test that could not run gets "not run" and the reason; its finding stays labelled unconfirmed.
