# Riff platform testing contract

Version 1.0.0 · October 8, 2026

This is the shared testing instruction set returned by browser controls, WebMCP and MCP. Read it alongside the app's declared service documentation. Test labels never grant authority or a spending allowance.

## Three distinct test lanes

| Lane | Configuration | Expected result | Model costs |
| --- | --- | --- | --- |
| Local functional | Local fixtures, mocked image SDK and room-v2 simulator | Simulated success, failures, deadlines, checksums and recovery | No hosted model dispatch |
| Hosted no-dispatch | Open preview with `modelTest=1`; direct managed-image mutation calls include `X-Riff-Execution-Mode: test` | `model_test_mode_no_dispatch`, not a generated image | Zero model provider calls for protected calls |
| Live acceptance | Deliberately omit the no-dispatch marker, with owner-approved exact-revision grant, bounded allowance and expiry | Actual generated media; record evidence and actual/unknown cost | Metered; approval and grant required |

Normal hosting, storage and room traffic can still consume infrastructure resources. No-dispatch mode is not a claim that all infrastructure is free.

## Configure browser tests

For an accepted revision, use:

```text
https://riff.marantz.net/create/preview?id=sub_<32 lowercase hex>&modelTest=1&test_agent=1
```

`modelTest=1` activates the trusted parent bridge's model blocking. It blocks managed image operations except capability discovery before HTTP dispatch. A blocked call must be asserted as an expected test outcome. `test_agent=1` classifies analytics only; it DOES NOT suppress model generation by itself. Preserve the modelTest parameter through every preview reload and navigation. Removing it restores ordinary grant-controlled behavior.

Use separate browser identities for host, member and spectator. Cover reload/resume, absent-player deadlines, host disconnect, hidden inputs and private votes, reveal navigation, idempotent retries, permission failures and pause/quota error UI. Do not put player answers, private saves, room credentials or creator keys in test reports.

## Configure direct model API tests

Send `X-Riff-Execution-Mode: test` on EVERY managed-image mutation request. The gateway returns HTTP 409 with `error: "model_test_mode_no_dispatch"`, `executionMode: "test"`, and `providerCalls: 0` before job allocation. Unknown header values fail closed. A request without the header is not a test request and can incur costs. The public capability GET is safe to read.

No generic wrapper can protect an unrelated URL or a request that discards the marker. Inject your configured test transport through the app's test harness; assert the header on every image request. Use local fixtures for success-path artwork. Do not repeatedly retry expected no-dispatch errors.

## Submission checks are not live image tests

The public `/create/submit-v2.mjs` helper has a `validate` path; consult its `--help` and the upload/2 guide for manifest, credentials-file and package-directory arguments. It streams and validates the package without publishing it. Upload/storage quotas still apply; publication quota is not consumed until explicit publication. After streaming, `validate_upload` performs the same server validation through all three interfaces. It requires ownership of the upload session.

Use the local `/create/room-v2-simulator.mjs` helper and its downloadable bundle for multi-seat phase tests without publication. Simulator evidence is not proof of hosted concurrency or live generation.

## Evidence to return

Record revision/digest, SDK pin, mode, test time, browser identities/roles (no secrets), expected/observed outcomes, safe request/job identifiers and known limitations. Separate fixtures, no-dispatch integration and paid live tests. For live acceptance report the effective shared allowance, expiry, attempted calls and measured or unknown billing. Stop on operator pause, exhausted allowance, provider billing failure or unexplained repeated failures. Do not switch providers, upgrade tiers or retry uncertain calls to bypass a limit.

## Provisional testing readiness and bounded live activation

Submit the complete `manifest.services` list in every revision. Standard `realtime-room` does not require premium; `realtime-room-v2`, `private-player-data`, `count-metrics`, `leaderboards` and `managed-images-v1` require the applicable premium access. Retain the matching `roomPlan` and `playerServices` configuration. Do not remove a dependency to bypass a grant check. Declarations state intended dependencies, not proof of actual usage.

For model testing, give the operator the exact submission ID and artifact digest, image adapter/game ID, expected rooms, calls per room, concurrent calls and test end date. Agree on a bounded total testing exposure as well as per-room limits. The operator must verify live family, creator and platform allowances; a per-room ceiling is not a total testing cap. No secrets or personal prompts belong in this handoff. New revisions need a new exact-revision image grant; discovery approval and premium upload access do not grant model spending.

The owner review page checks `GET /api/contributions/{submissionId}/testing-readiness` (owner-authenticated, private/no-store). It compares the stored declarations with current premium status, exact ID/digest image grants, expiry, pauses, provider billing circuit and remaining shared budgets. It makes no model calls and reserves no credits. The snapshot is diagnostic: per-request gates remain authoritative and live provider health is not probed. Existing room quota consumption, provider balances and undeclared dependencies cannot be inferred as a successful live test.

The embedded review player starts image apps in `modelTest=1` mode by default. This blocks model workflows rather than fabricating successful images. The reviewer can explicitly choose live testing against existing authorized grants; that toggle cannot create a grant, increase quota or authorize new spending. Mode changes stop the running player. History links default to no-model-cost testing. `test_agent=1` classifies traffic only; it never prevents spending by itself.

The review phone hides the standalone preview header. Player details and device controls are available from the surrounding review page; the opaque app sandbox and explicit Play action remain. Standalone preview URLs retain their normal header.
