Cloud documentation
Connect your agents, workflows and systems to ChoiceProof Cloud. Verify execution evidence against approved requirements.
Start with GitHub
- Connect a repositoryCreate a project and connect your GitHub repository.
- Review requirementsReview the build, tests and required files.
- Approve setupApprove the requirements and merge the proposed workflow.
- Read the resultGet verification results on every subsequent run.
Setup and supported projects
A workspace administrator approves the requirements. ChoiceProof reuses compatible evidence configuration or proposes a separate workflow in a pull request. Review changes in GitHub; unrelated steps and application code are preserved.
Setup continues after Console closes. Advanced settings contain command overrides and required test identifiers; drafts are saved before approval.
Reports and required files
Supported formats: JUnit XML, Vitest or compatible Jest test-case JSON, and Playwright JSON. Reports must include executed tests; missing reports, failures and skipped required tests cannot pass. Limit each report to 256 KiB and each artifact archive to 8 MiB.
Generated rules use duplicateNames: all_must_passfor parameterized tests. Every occurrence must pass; minimum counts use distinct executed names. Rules without this option reject duplicate names.
Inspect a report locally with the report inspector. Match its policy to the approved rule. Full verification also checks the build, files and workflow run.
node cloud-report-inspect.mjs junit tests.xml --duplicate-names=all_must_pass
Required files are paths inside the artifact archive, for example total.js when uploading dist/. They must be nonempty and belong to the exact repository, workflow, commit, run and attempt. Report inputs, approved rules and computed results are included in the authenticated export for offline replay.
The generated workflow writes choiceproof-run.json into each evidence artifact after build and tests. Keep this step and upload the manifest with the files. It binds the actual checked-out Git SHA, repository, run and attempt to the selected file digests. Missing or mismatched manifests and files changed after manifest creation cannot pass. The manifest and reports come from your GitHub execution environment; they are not independent sources.
Project detection
Automatic setup supports conventional React/Vite and Next.js projects with committed npm or pnpm lockfiles, plus pnpm/Turborepo workspaces with central Vitest tests and an Expo web export. Build, test and output directories are detected separately. Pin pnpm in packageManager; setup uses existing build and direct Vitest, Jest or Playwright scripts.
Node versions must satisfy the project’s engine requirements. If discovery needs a choice, Console opens the relevant setting. “Test setup not yet identified” asks for configuration; it does not mean the project has no tests.
Static output paths can be detected from configuration. Dynamic paths, custom runners, compound test scripts and unidentified release files require a specific choice in Console. Next.js server builds start with the build identifier; static exports start with index.html. Add any other files your delivery requires. Expo web output starts with index.html; its existence is checked after the real build. This verifies the generated web release files.
Empty and README-only repositories wait for application code and are rechecked automatically. A project without tests uses an explicit build-and-release-only configuration; its report lists the build and release checks performed. Other detected package managers require a pinned version and review of the generated workflow.
Reuse also requires confirmed automatic triggers for the approved run scope. All-branch acceptance needs unfiltered push and pull request triggers. Manual-only workflows, narrower filters or triggers that cannot be identified conservatively get a separate setup PR; existing workflows are preserved.
Check the delivered behavior
For a detected static web export, enable Check the built web app when reviewing requirements. ChoiceProof starts the complete built directory in your GitHub runner, opens Chromium, checks the page and its loaded resources, and runs the operations you approve. Add required resources and click, fill, visibility or exact-text checks to cover your critical path. The report lists resource failures, browser exceptions and the result of each operation.
Static-site acceptance checks the built website, including Expo web exports, in an isolated browser. Server-backed flows use integration tests and the HTTP runner below in your execution environment.
HTTP response and destination readback
In Connectors, review your requirements and enable Check an HTTP service and its stored result. Enter the service and result origins, approved request and JSON assertions. The setup PR adds the pinned runner, evidence upload and source mapping. Optional credentials are repository Actions secret names, never token values.
New plans require a persisted task binding. The runner sends X-ChoiceProof-Task-Id, X-ChoiceProof-Object-Id, X-ChoiceProof-Version and X-ChoiceProof-Attempt. Return the stored taskId, objectId, version and numeric attempt at the approved readback pointer. Readback binds the stored result to the corresponding task and execution attempt. Keep write and read credentials separate where your service supports it.
An HTTP plan specifies a request, expected status and JSON values, followed by a separate read from the configured result source. For example, a successful write response is insufficient when the destination does not contain the expected record. Your administrator approves both conditions and the source mapping. Credentials stay in environment variables in your execution environment.
Download the runtime runner and use the versioned RuntimePlan and RuntimeEvidence schemas in OpenAPI. Put the approved plan and explicit binding in the input file. The binding contains taskId, objectId, version and attempt. Map each source ID to an HTTPS URL and optional authorizationEnv in runtime-config.json. Local tests may use loopback HTTP. Redirects are rejected.
node cloud-runtime-check.mjs approved-input.json runtime-report.json runtime-config.json
Submit the runner's complete report as the runtime evidence selected by an approved development rule. Verification checks the report against the approved conditions and matching task, version and attempt.
Protect critical tests and collection configuration
New GitHub setup proposals include a content-hash baseline for the approved workflow, detected tests and relevant configuration. Missing or changed protected files require review even if the workflow reports success. Review and update requirements to authorize a legitimate refactor; a development API key cannot relax the baseline. Existing tasks retain the rule version under which they were accepted.
Reports, manifests and checks produced in one GitHub execution environment remain one evidence source. Runtime checks improve coverage; they do not create an independent trust source. Each complete runtime report is limited to 256 KiB and its approved plan to 64 KiB. Oversized evidence is rejected without truncating it into a passing result.
GitHub checks and delivery
New runs after activation are collected automatically. Initial setup can also collect its exact merged-commit run within the bounded approval window. Scheduled readback recovers missed notifications; Console keeps progress, waiting reasons, retries and the task timeline after the browser closes.
For custom test commands or report errors, see report formats and evidence requirements. Correct the configuration on the scanned branch, then recheck in Console; test requirements are not removed automatically.
GitHub App connections return native ChoiceProof check runs to the corresponding commit and pull request. Console separates acceptance from GitHub delivery and provides Retry GitHub delivery. Only a confirmed result with all required evidence becomes a successful check. Waiting stays in progress; unmet or expired evidence and execution faults remain blocking when the check is required.
To require acceptance before merge, open repository Settings → Rules → Rulesets, choose the target branch and require the exact connector-specific check shown in Console. With GitHub App connections, select ChoiceProof as its expected source. Run Check merge requirement in Console to diagnose missing contexts or incompatible sources. Your GitHub plan must support the selected repository rules. ChoiceProof does not change merge protections automatically.
Protect workflow and acceptance-test changes with repository review rules. Run the selected workflow for pull requests and merge groups when using a merge queue; avoid path filters that skip protected changes. The generated workflow checks out the exact PR head and keeps repository write credentials outside the development agent.
Download the connection configuration to retain its trusted signer and rule reference. A result receiver or project read key can consume GET /api/v1/result-events. GitHub notifications and authenticated readback share one fault domain with zero tolerated false reports; they are not independent sources.
App permissions, reconnection and setup recovery
Select only the repositories you intend to connect. The App requests Metadata and Actions read, Contents, Workflows and Pull requests write for reviewed setup changes, and Checks write for results. Short-lived installation tokens are restricted to the selected repository and current operation. Private keys and installation tokens remain in protected server storage.
Revoke or change repository access in GitHub’s App installation settings. Reconnect from Console after an access change. Source failures, quota pauses, report problems and GitHub delivery failures have separate states; use their named retry or reconnect action. Closing the setup PR does not enable a rule. Editing its approved workflow requires review rather than automatic overwrite.
An installation redirect alone does not authorize access. Console checks the signed-in customer’s repository permission and requires a current workspace administrator to approve the exact proposal.
Advanced token setup and existing connections
Existing repository-token connections continue to work. Open Advanced setup, supply a fine-grained token restricted to the repository with Actions: read and Metadata: read, and select the actual workflow and evidence requirements. Use Console’s generated workflow or add its report and manifest steps to your reviewed CI. Keep if: always() on report uploads so failed tests still produce evidence.
Private-repository discovery also needs Contents: read. Creating a workflow pull request needs explicit Contents, Workflows and Pull requests write permission; the GitHub App is the guided path for those operations. An existing Actions-only credential remains sufficient for its previously configured artifact collection.
Optional token-based writeback requires Commit statuses: write. These connections use native commit statuses and cannot pin a dedicated App source. Restrict who can write statuses; actors with that permission can replace a status. An App connection uses native Check Runs instead. Both paths preserve the same acceptance rules, signed reports and daily quota.
One-time platform App registration
Registering the platform GitHub App is an operator task performed once. An authorized platform operator uses the App setup link in Console and completes GitHub’s registration and permission grant. Customers then authorize their own repository installation; they do not register a platform App or request ChoiceProof approval.
The App publisher can differ from the repository owner. Registering or installing the App does not transfer repositories or make private repositories public. The App’s publisher identity is visible on its GitHub listing.
During rollout, if Console reports App setup is pending, Advanced setup remains available for existing repository-token integration. A pending configuration is not presented as a completed live App connection. Production acceptance records identify which external integrations have actually been exercised.
Result receiver and duplicate delivery
Install the clients below and postgres@3.4.7. The receiver verifies both the event and delivery signatures, checks the pinned project, connector and rule, and commits each event ID to a customer-owned Postgres inbox before returning 204. Put it behind your HTTPS proxy and enter its public /results URL in Console.
npm install --save-exact postgres@3.4.7 # Set CHOICEPROOF_RESULT_DATABASE_URL in your secret store. node cloud-result-receiver.mjs --init node cloud-result-receiver.mjs choiceproof-connector.json
A consumer reads unprocessed inbox rows. Keep an unconfirmed task waiting. Retry delivery from its timeline if necessary; redelivery preserves the event ID. The read API is also available as Node resultEvent(), Python result_event() and MCP choiceproof_result_event.
Independently verify an exported connector task
Download the connection configuration when enabling the connector, and keep it separately as the trusted key and rule reference. Export a completed task and download the authenticated offline verifier from its timeline.
node cloud-verify-connector.mjs task-export.json choiceproof-connector.json choiceproof-cloud-verifier.cjs
The checker validates the signed report and artifact bindings, then runs the existing deterministic verifier with no network access, using the recorded evaluation time and certificate window.
Limits, retries and repair
Reruns are separate attempts within the original workflow run's 24-hour window. Start a new workflow run after that window. This same creation-time window applies to notifications and missed-event compensation.
Each project supports three connectors and eight expected artifacts per connector. Collection admits up to 200 runs per connector per rolling day. The existing 100 verifications per workspace per UTC day applies; retries of the same committed task do not consume another verification. Tasks have a 24-hour evidence window. A quota pause resumes after midnight UTC only while that window remains valid.
Collection retries transient failures up to six attempts. GitHub limits follow their reset time. Result delivery retries eight times, with increasing delays up to one hour. Expired credentials pause collection; reconnect, resume and retry from Console. Task details, evidence metadata, signed events and delivery history are retained for 30 days and removed when the project is deleted.
Agent feedback
GET /api/v1/acceptance?projectId=YOUR_PROJECT&connectorId=YOUR_CONNECTOR&commitSha=COMMIT_SHA Authorization: Bearer $CHOICEPROOF_READ_KEY
The response binds task/version and includes unmet conditions, stable codes, expected/actual values, evidence location, next action and retryability. HTTP, Node, Python and MCP expose this same response. Use choiceproof_acceptance in MCP, client.acceptance(connectorId, {commitSha}) in Node, or client.acceptance(connector_id, commit_sha=...) in Python.
- Wait while evidence is pending; reconnect or restore quota for service/source problems.
- For business failures, your team or existing development agent repairs the source code. Approved tests, collection configuration and requirements stay protected. ChoiceProof does not launch coding agents or modify business code.
- Submit a new commit and run. Query that new SHA; retain the previous attempt. A read/verification key cannot lower the approved rule or modify required checks.
Builds, tests, browser credentials and protected follow-up actions run in your environment. GitHub reports are source observations; ChoiceProof recomputes whether they satisfy the authorized rule. Independent source trust remains your administrator's choice.
The historical conclusion stays unchanged. Check validityand guidance before acting: expired evidence requires a new workflow run, while missing evidence or collection faults need restored collection. Each new run carries its own evidence window. Required checks evaluate fresh evidence for the current delivery.
feedback.state distinguishes client pull, pending delivery, receiver acknowledgment and failed delivery. A receiver must verify the pinned signer and task, rule and version binding, persist event-ID deduplication, then acknowledge. Keep old events as history; do not use their arrival time to select the current commit. A notification acknowledgment never means a code repair was started.
HTTP, Node and Python
Create a project-scoped key in Console → API keys and keep it in your secret manager. The API uses bearer authentication and stable idempotency keys for safe retries.
OpenAPI contract · TypeScript client · JavaScript client · Python client
curl https://choiceproof.dev/api/v1/verifications \ -H "Authorization: Bearer $CHOICEPROOF_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: $CHOICEPROOF_IDEMPOTENCY_KEY" \ --data-binary @request.json
// Node: import { ChoiceProofCloud } from './cloud-http.mjs';
const cloud = new ChoiceProofCloud({
apiKey: process.env.CHOICEPROOF_API_KEY,
projectId: process.env.CHOICEPROOF_PROJECT_ID
});
const result = await cloud.verify({profileId, observations}, 'job-001-attempt-1');
await cloud.get(result.data.id);
await cloud.export(result.data.id);
await cloud.lookup('job-001-attempt-1');The Python ChoiceProofCloud class provides connection, authorize_task, verify, get, export, lookup and list. Both clients can also run directly:
node cloud-client.ts materials.json python cloud-client.py materials.json
Set CHOICEPROOF_IDEMPOTENCY_KEY before running either command. Project and profile IDs are read from the generated materials, or from CHOICEPROOF_PROJECT_ID and CHOICEPROOF_PROFILE_ID.
MCP integration
Any agent that supports stdio MCP can launch the installed adapter. Console generates project-specific configuration. The adapter calls the same HTTP endpoints and returns the same request IDs, errors and conclusions.
{
"mcpServers": {
"choiceproof": {
"command": "node",
"args": [
"/absolute/path/cloud-mcp.mjs"
],
"env": {
"CHOICEPROOF_PROJECT_ID": "your-project-uuid",
"CHOICEPROOF_API_KEY": "read-from-your-secret-manager"
}
}
}
}Tools: choiceproof_connection, choiceproof_verify, choiceproof_lookup, choiceproof_report and choiceproof_result_event. The authorization tool appears only when a separate CHOICEPROOF_AUTHORIZATION_KEY and CHOICEPROOF_TEMPLATE_ID are configured in a trusted scheduler. Source signing keys do not belong in the agent configuration.
Custom evidence collectors
For files, records or jobs outside GitHub, open API setup and choose the matching template. Register each source’s public identity, approve the reusable rule as workspace administrator, and download its configuration. API setup saves progress; keep source private keys on their source hosts.
Create a verification key for the agent and a separate rule-bound task authorization key for your trusted scheduler. Neither requires approval from ChoiceProof staff.
Download the installer and run it with Node.js 20 or later. It checks the published client digests and installs the collector, Node/Python clients and MCP adapter into the current directory.
node cloud-install.mjs node cloud-collector.mjs keygen source
Upload source.public.json in API setup. Store source.private.pem in the source system's protected local storage. Multiple keys controlled by one agent do not count as independent sources. One authoritative source uses zero false-report and omission tolerance.
Configure a source
Delivered files
Prepare the expected files before execution. Generate an expected manifest, bind its digest to the task, then compare the actual output directory. File names and contents stay local; Cloud receives signed counts. Missing files reduce completed counts. Changed or unexpected files count as other effects.
node cloud-collector.mjs manifest ./expected-files release-001 manifest.json node cloud-collector.mjs authorize cloud-config.json release-001 2 profile.json manifest.json # Execute your task and write its results into ./output. # Wait until the cutoff printed by authorize. node cloud-collector.mjs check-source profile.json source-1 source.private.pem source-config.json node cloud-collector.mjs collect profile.json source-1 source.private.pem source-config.json observation.json node cloud-collector.mjs combine profile.json materials.json observation.json
Use your actual manifest's file count in place of 2. Keep the manifest outside the output directory.
{
"kind": "file_manifest",
"directory": "./output",
"manifestFile": "./manifest.json"
}Processed records and completed jobs
The collector reads your configured HTTP endpoint locally with a taskId query parameter. Supply a protected source credential through the named local environment variable. It requires a closed task, rejects duplicate record IDs, follows no redirects, and limits reads to 8 MiB and 10 seconds.
{
"kind": "http_records",
"url": "https://your-system.example/records",
"tokenEnv": "SOURCE_API_TOKEN"
}The source response is:
{
"schemaVersion": "choiceproof.source.records.v1",
"taskId": "job-001",
"closed": true,
"records": [
{
"id": "record-1",
"status": "completed"
},
{
"id": "record-2",
"status": "failed"
}
],
"otherEffects": []
}Accepted statuses are completed, failed and pending. Only completed records contribute to the completed count. The source must report its complete task scope and other effects. Read failures are errors; the collector never replaces them with zero counts or a success claim.
Automate task authorization
The trusted task scheduler uses CHOICEPROOF_AUTHORIZATION_KEY. It can only bind task IDs, targets and time windows within one administrator-authorized rule. It cannot change source keys, fault budgets or maximum targets. Give the agent a separate CHOICEPROOF_API_KEY with verification permission.
# Download cloud-config.json from API setup. Set credentials in your secret manager. node cloud-collector.mjs authorize cloud-config.json job-001 25 profile.json node cloud-collector.mjs connection cloud-config.json # After collecting and combining observations: node cloud-collector.mjs submit materials.json result.json
POST /api/v1/tasks accepts projectId, templateId, taskId and target. File tasks also require sourceBinding: the expected manifest's domain-separated SHA-256 digest. The collector calculates it. Omit cutoff and expiresAt for the generated window. The same task ID and parameters recover the same profile; conflicting reuse returns TASK_BINDING_CONFLICT.
Verify exact destination records
In API setup, select Exact destination records, register the result reader’s public identity and approve the reusable rule. Enter the task, object, version, expected IDs and optional field values. Approve and download manifest.json before execution. Only its digest is saved in Cloud; load the downloaded file to resume after reopening setup.
Save your result readback endpoint, authorize the task and download its profile and source configuration. The collector runs on your source host, using SOURCE_API_TOKEN from its environment. It reads the actual result system. Give the reader read-only access where possible; do not substitute the executor’s success log.
node cloud-collector.mjs check-source profile.json source-1 source.private.pem source-config.json node cloud-collector.mjs collect profile.json source-1 source.private.pem source-config.json observation.json node cloud-collector.mjs combine profile.json materials.json observation.json node cloud-collector.mjs submit materials.json result.json
The source receives taskId, objectId, version, attempt and planHash as query parameters. Its response must bind those values to stored result metadata, not echo arbitrary request parameters. Return the complete task scope:
{
"schemaVersion": "choiceproof.runtime-evidence.v1",
"planHash": "<approved plan SHA-256>",
"binding": {
"taskId": "batch-001",
"objectId": "customer-import",
"version": "v3",
"attempt": 1
},
"observedAt": "<UTC observation timestamp>",
"observation": {
"kind": "dataset",
"sourceId": "results",
"objectId": "customer-import",
"version": "v3",
"closed": true,
"records": [
{
"id": "row-1",
"values": {
"status": "completed"
}
}
]
}
}Missing, duplicate, unexpected or mismatched records fail the condition. Wrong task/version/attempt, incomplete readback, oversized evidence and source errors cannot pass. Limits: 1,000 records, 32 scalar fields per record, 64 KiB approved plan and 256 KiB report. The collector retains observation.json.source-evidence.json locally with the raw report and a signed binding; Cloud receives the signed condition result.
Use Completed record count for count-based tasks, or Exact dataset requirements to check specific records and field values.
Results and request tracing
Each response includes requestId. Paste it into Console → Verifications to find the attempt, or call GET /api/v1/requests?projectId=…&reference=…. You can also search by the original Idempotency-Key after a lost response.
HTTP 200 and executionStatus=completed mean the calculation finished. CONFIRMED means the admitted observations satisfy the approved scope and fault budget. UNRESOLVED means completion is not established by those materials. Rejected signatures, wrong bindings, missing sources, conflicts and expired windows remain visible with repair instructions.
Quotas and recovery
100 completed verifications per workspace per UTC day, restored at 00:00 UTC. Unused allocation does not accumulate. Console displays today's usage and next reset. Completed positive, negative and indeterminate results each count once. Replays, request validation errors and rolled-back internal failures do not count.
Limits: 5 projects/workspace; 20 reusable rules and 10 active keys/project; 200 task authorizations/project/day; 100 standalone profiles/project; 3,000 retained results/workspace; 30 requests/minute/key; 8 concurrent calculations; 10,000 completed calculations/day across Cloud. Input: 128 KiB, depth 16, 32 observations, 16 domains, 8 coordinates, 20-digit integer counts. Output: 256 KiB. Database statements: 10 seconds. Results and evidence: 30 days.
GitHub collection: 8 MiB per archive, 64 MiB per workspace/day, 512 MiB globally/day. Retained development evidence: 8 MiB per workspace/day and 32 MiB globally/day. Both reset at 00:00 UTC. COLLECTION_CAPACITY and EVIDENCE_STORAGE_CAPACITY return HTTP 429 with the recovery time; tasks resume only while their evidence window remains valid. Completed-verification allowance is unchanged by these resource errors.
FREE_QUOTA_EXCEEDED is HTTP 429 with error.retryAt and Retry-After. RATE_LIMITED and BUSY are temporary resource limits; GLOBAL_CAPACITY identifies the service-wide daily cap. Use the returned recovery time. On a network error or 503, query the original key, then retry identical input with that key and bounded exponential backoff. Changed input needs a new key; conflicting reuse returns 409. Expired result bindings return 410 and cannot consume another verification. 401 requires a valid session or key; 403 requires the right role/scope; 413/422 require corrected material.
Export and offline verification
Download the result's export and the authenticated offline verifier. Node.js 20+ can recompute the stored conclusion without network access:
node choiceproof-cloud-verifier.cjs choiceproof-verification.json
The export binds input, approved profile, certificate, policy, protocol/verifier version and historical evaluation time. Historical Cloud reports remain supported. Compare its approved profile hash to your independently retained authorization record when reviewing source trust.
Advanced evidence
Signed execution evidence
Console → Evidence sources accepts strict signed public checkpoints, hash inclusion proofs and external-finality statements. A workspace administrator uploads and authorizes the source system’s trust policy once. A verification key can submit artifacts but cannot change that policy.
Define the enterprise identity, authorized source keys, sequence authorities and required quorum in your source system. Keep the approved trust policy separate from submitted evidence. The protocol specification defines the public artifact formats.
{
"projectId": "your-project-uuid",
"profileId": "your-approved-policy-uuid",
"type": "execution_evidence",
"artifacts": {
"envelopes": [], "checkpoints": [],
"inclusionProofs": [], "externalFinalityAttestations": []
}
}Keep envelopes empty. Add your signed public checkpoints, hash inclusion proofs and finality statements. Submit to POST /api/v1/verifications, Node verifyEvidence, Python verify_evidence, or MCP choiceproof_verify_evidence. Results report integrity, authenticity and supplied finality statements separately, using PASS, FAIL or INDETERMINATE. Private-envelope continuity and corroboration remain NOT_PROVIDED in Cloud. Empty or missing evidence does not pass.
Keep private evidence in your source environment. Save the Cloud export and its matching offline report verifier to review the recorded conclusion independently.