
A Stripe customer metadata sweep pages through a segment using has_more and starting_after, flags anyone missing a required field like country, then writes corrections back. The business risk is that the sweep completes with fewer customers matching the requested segment than the segment is expected to hold. Without a guard, the worker treats that short count as a complete picture and writes anyway.
The guard compares scan.segment.length against input.expectedMin. If customers matching the requested segment fall short of that declared minimum, the workflow skips writes and sends a RevOps alert instead. That lower bound is not a total-customer count across all of Stripe, not a per-page size check, and not proof that every intended customer ID was present in the pages that arrived. It is a segment-count floor: a necessary condition, not a sufficient one.
The workflow source and executable contract are pinned to the source revision named by the October 27 app-declared version. The contract declares the expected behaviors up front. FetchSandbox runs those cases through app requests and lets you inspect the reported state, not just whether the provider returned HTTP 200. For context on how Stripe pages results, see the official pagination mechanics covering has_more and starting_after continuation.
What the Oct 27 run declared
A run recorded October 27 against test twins declared eight checks under app-declared version acme-ops-customer-data-sweep-1.0.0-c2ec0d5. All eight passed. The public receipt is here.
The declared checks covered:
-
Workflow recorded a start event
-
A small segment flagged customers with missing country
-
A 250-customer segment across 3 pages flagged 25 missing-country customers
-
Actions beyond the automatic write limit waited for approval (whether those actions ultimately completed was not part of the declared checks)
-
A rerun of the same segment added no new flags
-
A scan returning fewer customers matching the requested segment than
expectedMinskipped writes and sent a RevOps alert -
A rate-limited list response triggered no writes
-
An invalid segment was rejected before agents ran
These were application-reported HTTP states against test twins, not independent database reads or live Stripe API calls. This run did not measure changing datasets, concurrent inserts or deletes mid-scan, or exact record membership. The expectedMin lower bound guards against the too-few-customers case only.
Version note:
The app-declared version identifier is not cryptographically bound to the measured executable by the runner. The source at this commit is now publicly accessible, which is separate from runner attestation that this exact code ran. The workflow guide at this commit also links an older receipt from a separate historical run that recorded 4 passed and 4 failed checks; that record is distinct from the October 27 passing receipt above and neither resolves the other.
Run the unit tests locally
git clone https://github.com/fetchsandbox/playground.git
cd playground
git checkout --detach c2ec0d59261327b3b76ca9d4cf4586ce14827f61
cd acme-ops
npm ci
npx vitest run test/customer-data-sweep.test.ts
This runs the Vitest suite against the pinned source. The README covers environment variables, test-twin setup, and the separate prerequisites for hosted relay and authentication. Relay access requires a private FetchSandbox account and the prerequisites described in that README; it is not an automatic capability of the MCP connection alone.
Connect an agent for tool-level verification
Unit tests cover the local fake-world path. To verify the incomplete-scan and repeat-run behaviors against actual test twins, connect Claude or Codex via fetchsandbox.com/mcp, provide this workflow, and ask the agent to run the declared cases. Hosted relay access requires the separate setup described in the README. That path distinguishes local Vitest results from app-level acceptance through FetchSandbox's relay. Keep credentials test-only and do not send real customer identities to any sandbox environment.
What is still open
The incomplete-scan guard handles the too-few-customers case. It does not verify the identity of every intended record, address concurrent inserts or deletes mid-scan, or establish production completeness. Stronger membership checks are the natural next step if you are running this against real customer segments at scale.