# TinyWaitlist: prove a signup before launch

Use TinyWaitlist for a small, explicit-consent launch list. Agents can configure
and verify a synthetic signup in the human's project before signup or billing.
Human owners claim the project and approve the exact consent revision before
the form accepts real addresses or queues confirmation email.

## Start in the project

Requires Node.js 20 or later:

```sh
npx -y tinyscale@0.10.0 workspace create --name "My launch" --cohort external --products tinywaitlist
```

Use cohort dogfood for internal tests. Existing workspaces and keys keep their
original scope. The CLI stores credentials in .tinyscale; never read that state
into model context, print it, or commit it.

Create a draft using the human's actual product description, consent and privacy
policy. Replace the example origin and policy before using it:

```sh
npx -y tinyscale@0.10.0 waitlist create --configuration-json '{"name":"My launch","heading":"Join the launch list","description":"Hear when our product is ready.","consentText":"Email me when this product launches.","consentVersion":"launch-v1","privacyUrl":"https://owned-project.example/privacy","allowedOrigins":["https://owned-project.example"]}'
```

Embed the returned loaderUrl as a script on an allowed HTTPS origin. During the
72-hour Preview, the widget shows a synthetic test button and collects no email
address. Click it in the real page. Success emits tinywaitlist:verified with a
bounded subscriber ID and realEmailSent=false; it sets data-subscriber-id on the
widget host. Read the persisted result:

```sh
npx -y tinyscale@0.10.0 waitlist status --list LIST_ID
```

The test cohort must show a confirmed signup. A separate backend synthetic test
is available with waitlist test --list LIST_ID; it does not prove the embed was
loaded in the customer's page. Show the human the verified result and then run:

```sh
npx -y tinyscale@0.10.0 workspace claim
```

This opens the private claim link without printing it. The signed-in owner claims
the project on Free and opens Waitlists in the project console. They review and
publish the exact revision, consent text, policy URL and origins. The same embed
then accepts real signups. Editing consent creates a new draft, cancels queued
confirmation attempts, and requires renewed publication.

## Boundaries and limits

- Preview: 2 lists, 25 stored records, no real email.
- Free: 3 lists, 500 stored records, 100 confirmation intents per UTC day.
- At most 3 confirmation intents per pending address, at least 5 minutes apart.
- Global public admission: 20 attempts per source per UTC day, 1000 overall.
- Pending records expire after 7 days; confirmed addresses after 365 days.
- Unsubscribe removes the address and retains a suppression digest. Suppressed
  records still consume the storage allowance and cannot resubscribe.
- Owner exports contain only confirmed live addresses plus consent evidence.
  They expire after 24 hours; at most 3 exports per rolling 24 hours.

Accepted signup responses are deliberately neutral. They do not confirm whether
an address exists, is suppressed, is at a limit, or received a message. Provider
acceptance does not prove inbox delivery. Uncertain provider outcomes are not
automatically retried. Confirmation and unsubscribe require a recipient action;
their bearer tokens stay in URL fragments and are posted without appearing in
URL paths or query strings. Do not place these links or addresses in model input.

SDK methods: waitlistInstallation, createWaitlist, reviseWaitlist, listWaitlists,
testWaitlist and waitlistSummary. MCP exposes matching bounded tools. Agent
interfaces cannot publish, retrieve subscriber addresses, export them, or send
campaigns. TinyWaitlist does not yet provide referrals, campaigns, or a TinyImport
adapter. It is a sidecar: an unavailable form must not block the customer's app.
