# Sandbox, review, and production lifecycle

## What is available now

Public operator registration and each integration's synthetic sandbox are
available. Production data is intentionally disabled until BOT completes the
mobile consent/upload rollout and every legal and operational release gate.

Sandbox access is real mTLS access to the real v1 contract, but every resource,
history item, code, tombstone, and statistic is synthetic. Sandbox success never
authorizes production data or commercial use. The current
[BOT Integration Terms](https://integration.boringordertracker.com/terms) apply
throughout the lifecycle.

## Synthetic corpus and provisioning

Creating an integration queues its corpus; it does not generate hundreds of
rows inside the browser request. The Sandbox page shows `Queued`, `Preparing
data`, `Ready`, or a fail-closed attention state. Link-code generation remains
disabled until the corpus is fully validated and atomically activated.

Corpus version `sandbox-2026-09-v1` contains exactly 500 synthetic orders and
50 synthetic existing vehicles. Orders cover lifecycle and delivery-window
changes, permitted shipping examples, resolved configuration, and reviewed
option-code vocabulary. Vehicles contain plausible bounded telemetry and
monotonic odometer history. Every resource is marked `history_complete` only
after its complete generated history has committed.

The generator is deterministic for one secret/version/integration domain, but
uses a distinct HMAC domain for every field and identifier. It composes new
records from a reviewed static distribution model. It never selects, exports,
shifts, hashes, or stores a mapping to a production order, account, VIN,
vehicle, or history row. Changing dates alone is not anonymization and is not
used by BOT's sandbox.

Every synthetic order's `delivery_center` ends with the exact suffix
` - SANDBOX`. The same marked value appears in snapshots and any generated
statistics, so screenshots, exports, and downstream test databases cannot be
mistaken for production delivery-center data.

Integrations created before corpus version `sandbox-2026-09-v1` are not reset
silently. A BOT administrator runs the private, explicitly confirmed
`bin/sandbox-reset.php` command for one reviewed integration ID. The command
proves that every affected sandbox connection, grant, and alias belongs to a
known synthetic identifier domain, preserves operator/profile/client/
certificate and all production rows, then queues the current corpus. Repeating
the command is idempotent.

## Environment separation

Sandbox and production have separate clients, certificates, approved scopes,
quotas, resource IDs, cursors, ETags, webhooks, and audit/usage streams. The base
URL is the same; the verified client certificate selects the environment.

Never copy a sandbox cursor, fixture ID, certificate, or cached record into a
production database. Use visibly separate secrets and storage namespaces.

## Sandbox acceptance checklist

- `GET /capabilities` identifies `sandbox` and the expected scopes.
- A leading-zero ten-digit code survives form transport and is redeemable once.
- The initial sync is applied transactionally before its cursor is committed.
- Delta sync and `If-None-Match`/`304` behavior are covered.
- Every granted detail/history page is consumed and pagination is bounded.
- `history_complete=false` is represented as incomplete.
- A tombstone removes local individual and derived data.
- Deletion acknowledgement is idempotent and retry-safe.
- `429` honors `Retry-After`; `503` uses bounded backoff.
- Statistics are stored separately and contain no individual records.
- Logs and errors contain no certificate private key, link code, personal data,
  VIN, real order number, raw payload, or internal BOT identifier.

## Review inputs

Production review requires a complete integration profile, sanitized logo,
public policies, public linking page, narrow scopes, accepted BOT credit/app
link, polling/webhook concept, and a public review URL. The review URL should
exercise the user-facing link flow with synthetic data and show the exact BOT
attribution that will be used after launch. The credit and app link must be
prominent and readable wherever BOT data is displayed.

The operator must explicitly accept the current version of the
[BOT Integration Terms](https://integration.boringordertracker.com/terms) before
creating an integration and explicitly accept every later version. The standard
licence is non-commercial only. Ads, Google AdSense, sponsorships, affiliate
revenue, subscriptions, paid access, lead generation, data licensing/resale,
and any other direct or indirect monetization are commercial use and require an
individual written BOT agreement before that use begins.

For mixed-source output, every BOT-derived dataset, record, entry, chart series,
or result must be identified directly where it is displayed. A footer or
page-wide statement alone does not identify individual BOT-derived entries.

BOT reviews the current profile version. A material name, purpose, privacy URL,
or scope change creates a new consent boundary and does not inherit approval or
expand existing grants.

## Status transitions

`sandbox` → `submitted` → `approved` → `active`

BOT may transition a submission to `rejected` with notes. After approval, the
integration owner explicitly uses **Activate for production** for the reviewed
profile. BOT administrators may activate/reactivate operationally and may
transition an active integration to `suspended` or `retired` when access must
stop.

Approval accepts only the reviewed profile/scopes and permits production
credential preparation. Owner activation is a separate explicit confirmation.
Production API authentication requires `active`, and production data endpoints
also require `production_data_enabled=true`.

## Final activation gates

BOT enables the separate production-data gate only after all of the following
are satisfied:

- mobile app consent and upload behavior is released and verified;
- privacy/integration terms and retention periods have legal approval;
- production certificate issuance and real mTLS staging tests pass;
- operator deletion, revocation, rate limiting, and recovery behavior passes;
- the operator displays the mandatory BOT attribution and app link;
- the current Integration Terms version has been explicitly accepted;
- the intended use is non-commercial, or an individual written BOT agreement
  covers every commercial or monetized use;
- mixed-source output labels each BOT-derived record, entry, series, or result
  at its output point;
- rollback and operational monitoring are tested;
- BOT makes an explicit go-live decision.

Until then, keep production secrets unused and treat the sandbox as the only
available data environment.

## First production run

1. Obtain a separate production certificate after approval.
2. Call `GET /capabilities` and verify environment, status, exact scopes, quotas,
   and `production_data_enabled`.
3. Stop if the integration is not `active` or the data gate is false.
4. Start `GET /sync` without a cursor and commit each page atomically.
5. Store only the final committed opaque cursor.
6. Begin the documented 15-minute poll cadence.
7. Monitor certificate expiry, last sync, rate headers, tombstones, deletion
   deadlines, and—if enabled—webhook dead letters.

No record appears merely because an integration is active. A signed-in BOT user
must explicitly grant selected resources to the reviewed integration, and BOT
must have received the allowed snapshot/history from the app.

Continue to monitor the terms version, attribution placement, data provenance,
and business model after launch. A new terms version requires a new explicit
acceptance. Adding ads, AdSense, paid access, sponsorships, affiliate revenue,
resale, or any other monetization requires a written BOT agreement before the
change goes live; neither production approval nor user consent grants that
commercial permission.
