From 617a7ebee1237ef5891ae9212dcfe2556e2c25e7 Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Mon, 11 May 2026 06:59:22 -0400 Subject: [PATCH] spec(comply_test_controller): add account.sandbox: true gate (closes #3755) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds optional `account` object to the request schema with a required `sandbox: true` const constraint when present. The seller-side gate is already normative in docs (sellers MUST refuse requests targeting non- sandbox accounts); this PR adds the schema-layer defense-in-depth so a runner asserting `sandbox: false` schema-rejects before reaching the seller. Foundation of the (Sandbox) verification tier decided in #4379. The (Sandbox) mark attests "real production endpoint correctly handles sandbox-flagged traffic across the full storyboard suite" — this gate is what makes the boundary schema-enforceable. Soft-land path per the issue's option 2: schema gate ships now, storyboard sample_requests stay valid in transition, follow-up sweep tightens to required after all sample_requests include the field. Out of scope (filed as follow-up): - Sweep ~25 sample_request blocks across 8 storyboard YAMLs to add `account: { sandbox: true }` - Move `account` into the required array once sweep is complete - Storyboard lint that requires account on every comply_test_controller sample_request Cross-links: - #4379 — (Sandbox) framing verdict - #4028 — keystone storyboard for live-mode account denial - #4226 — UNKNOWN_SCENARIO grading (just merged as #4228) Co-Authored-By: Claude Opus 4.7 (1M context) --- .../comply-test-controller-account-sandbox.md | 4 ++++ .../comply-test-controller-request.json | 15 +++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 .changeset/comply-test-controller-account-sandbox.md diff --git a/.changeset/comply-test-controller-account-sandbox.md b/.changeset/comply-test-controller-account-sandbox.md new file mode 100644 index 0000000000..e41511598c --- /dev/null +++ b/.changeset/comply-test-controller-account-sandbox.md @@ -0,0 +1,4 @@ +--- +--- + +Adds optional `account` object to `comply_test_controller` request schema with `sandbox: true` const constraint when present. Defense-in-depth on top of the per-request seller-side gate: a runner asserting `sandbox: false` schema-rejects before reaching the seller. Foundation of the (Sandbox) verification tier framing decided in #4379 — closes #3755 (soft-land path); the runner contract MUST set the field, and the follow-up sweep tightens to required once all storyboard sample_requests are updated. diff --git a/static/schemas/source/compliance/comply-test-controller-request.json b/static/schemas/source/compliance/comply-test-controller-request.json index 92067d815c..c4a2ec6a03 100644 --- a/static/schemas/source/compliance/comply-test-controller-request.json +++ b/static/schemas/source/compliance/comply-test-controller-request.json @@ -561,6 +561,21 @@ }, "ext": { "$ref": "/schemas/core/ext.json" + }, + "account": { + "type": "object", + "description": "Sandbox account assertion. The runner SHOULD set sandbox: true on every comply_test_controller request; required in a future version. The seller MUST refuse the request (returning a structured error) if the targeted account is not a sandbox account in the seller's persisted records. This field is a caller-side declaration of intent — it does not grant sandbox status; sellers verify against their own account state. The (Sandbox) verification tier is defined by this gate: real production endpoints accept sandbox-flagged traffic and process it without real-world side effects, no separate test-mode endpoint required. See spec issue #3755 and the (Sandbox) framing in #4379. NOTE: optional in this version while existing storyboards add the field; the const: true constraint applies when present, so a request asserting sandbox: false schema-rejects regardless. A subsequent version bump will move this field into the required array; follow-up issue tracks the storyboard sweep that unblocks that.", + "required": [ + "sandbox" + ], + "properties": { + "sandbox": { + "type": "boolean", + "const": true, + "description": "MUST be true. The seller MUST verify the targeted account is sandbox by looking up the persisted account record, not by trusting this field. A request asserting sandbox: false schema-rejects before reaching the seller — defense-in-depth on top of the per-request gate." + } + }, + "additionalProperties": true } }, "required": [