To verify a Gateway receipt, you check that (1) the receipt signature is valid for clawproxy’s public key, and (2) the receipt is cryptographically bound to the exact request context you expected: the model request/response hashes, the CST scope hash, and (optionally) a pinned WPC hash.
In Claw EA, the receipt is strongest when it is carried inside a proof bundle, because the bundle captures the job context and makes replay and “receipt swapping” easier to detect during audit.
Step-by-step runbook
-
Collect inputs. Get the Gateway receipt (or a proof bundle containing it), plus the expected job metadata from your control plane: job id, agent/session identifiers, the CST you issued for the run, and the WPC hash you intended to enforce.
If you run OpenClaw as the baseline agent runtime, also capture the OpenClaw run identifiers you use to correlate model calls to a job (for example, session key and agent name from your own orchestration layer).
-
Fetch the policy you claim you ran under. Resolve the WPC by its hash from the WPC registry, then verify it is correctly signed and the hash matches what you pinned.
This step is what makes “permissioned execution” concrete: the run is constrained by a signed artifact, not by a prompt that the model can ignore.
-
Verify the CST binding. Inspect the CST (issued by clawscope) and confirm the scope hash matches the expected scope for this job. If you are using optional policy hash pinning, confirm the CST claims include the intended WPC hash and that it matches the fetched WPC.
Reject if the CST is expired, revoked, not job-scoped (if your deployment requires job scoping), or missing the expected pin.
-
Verify the receipt signature (fail closed). Validate the receipt signature using clawproxy’s public key material (for example, via a pinned key or an approved key distribution mechanism in your environment).
Reject if the signature is invalid, the receipt format is unexpected, or required fields are missing. Do not “best-effort” accept partial receipts.
-
Verify receipt bindings: what is signed and what is hashed. Compute hashes over the canonicalized request and response bodies (or the referenced content hashes) and compare to the receipt’s hash fields.
Also compare the receipt’s CST scope hash and any WPC hash fields against the CST and WPC you verified earlier.
-
Check anti-replay and job scoping. Confirm the receipt is bound to the job-scoped CST (marketplace anti-replay binding) and that the job id and nonce-like fields (if present in your bundle schema) are consistent across the bundle.
Reject if the same receipt id appears in multiple jobs, or if a receipt from another job can be “attached” without detection.
-
Store verification results with evidence. Persist the receipt, verification decision, and key metadata (policy hash, scope hash, model/provider identifiers, timestamps) as an immutable audit record.
If you use Trust Pulse, publish the artifact for reviewers; otherwise store internally with the proof bundle.
Threat model
A Gateway receipt is designed to make model-call evidence portable and checkable after the fact. Verification should assume the agent, the model, and any upstream prompt content can be hostile, and should treat receipts as untrusted until proven valid.
Prompt-only control is insufficient because the model can be instructed to ignore constraints, fabricate logs, or omit actions. Policy-as-code via WPC and CST makes the execution layer permissioned and verifiable even when prompts are adversarial.
| Threat | What happens | Control |
|---|---|---|
| Receipt forgery | An attacker fabricates a “receipt-like” JSON to claim a model call occurred. | Verify clawproxy signature and reject if the signing key is not trusted for your environment. |
| Receipt swapping | A valid receipt from another run is attached to this job to “prove” compliant behavior. | Verify binding to the job-scoped CST and the expected CST scope hash; prefer validation in a proof bundle. |
| Policy bypass via prompt | The model is instructed to ignore rules and call tools or models outside intended constraints. | Use a WPC and require CST policy hash pinning (optional) so receipts must match the intended policy hash. |
| Partial logging | Only some calls are shown, hiding unsafe outputs or data exfiltration attempts. | Require receipts for every model call routed through clawproxy; audit for gaps per session/job. |
| Key confusion / wrong verifier key | A verifier uses the wrong public key and accepts receipts from an unapproved proxy. | Pin allowed signer keys per environment and rotate keys with an explicit approval workflow. |
Policy-as-code example
This example shows the shape you want to bind into a WPC and optionally pin into the CST. Keep it minimal and deterministic so you can verify the exact same bytes (or canonical form) across systems.
It is intentionally “JSON-like” and omits endpoints. In practice, the WPC is a signed, hash-addressed artifact served by clawcontrols.
{
"wpc_version": "v1",
"policy": {
"job": {
"purpose": "customer_support_triage",
"data_class": "internal"
},
"model_routing": {
"require_gateway_receipts": true,
"allowed_provider": ["openrouter_via_fal"],
"allowed_models": ["exact-model-id-here"]
},
"tool_policy": {
"allow": ["read", "write", "http"],
"deny": ["exec", "browser_control"]
}
},
"verification": {
"require_cst_scope_hash": true,
"pin_wpc_hash_in_cst": true
}
}
What proof do you get?
Gateway receipts are signed receipts emitted by clawproxy for model calls. They are intended to be checked independently from the agent and independently from any prompt transcript.
A proof bundle packages one or more receipts plus metadata needed for audit and verification. It is the unit you should store and hand to reviewers, because it reduces ambiguity about “which run” a receipt belongs to.
A minimal receipt and bundle shape looks like this (illustrative fields only). The important part is that the signature covers the binding fields, and that you can recompute the referenced hashes.
{
"proof_bundle": {
"bundle_id": "bnd_...",
"job_id": "job_...",
"cst_scope_hash": "h_scope_...",
"wpc_hash": "h_wpc_...",
"receipts": [
{
"receipt_id": "rcpt_...",
"issuer": "clawproxy",
"issued_at": "2026-02-11T12:34:56Z",
"provider": "openrouter_via_fal",
"model": "exact-model-id-here",
"request_hash": "h_req_...",
"response_hash": "h_resp_...",
"binding": {
"job_id": "job_...",
"cst_scope_hash": "h_scope_...",
"wpc_hash": "h_wpc_..."
},
"signature": "sig_..."
}
]
}
}
What is signed: the binding fields (job id, scope hash, optional WPC hash), the request and response hashes, and issuer metadata. What is hashed: the request payload and response payload (or their canonical encodings) so you can detect any edit after issuance.
What is replayable: a receipt can be copied as bytes, but it should fail verification for a different job when you enforce job-scoped CST binding and compare bundle metadata to your expected job context.
Rollback posture
Receipt verification should degrade safely. If verification fails, your system should behave as if the model call is untrusted, even if the content looks plausible.
Rollbacks are operational decisions. Keep them tied to evidence you can show later, ideally by attaching the failed receipt and verifier output to the same case ticket.
| Action | Safe rollback | Evidence |
|---|---|---|
| Receipt signature fails | Quarantine the run output; block downstream automation; require re-run under a fresh CST. | Receipt bytes, signer key id used, signature verification error, timestamp. |
| Scope hash mismatch | Treat as cross-job contamination; invalidate the job; rotate job-scoped CST issuance path. | Expected CST scope hash, observed scope hash in receipt/bundle, job id mapping. |
| WPC pin mismatch (when required) | Stop processing and re-run only after re-issuing CST with the correct WPC hash pin. | WPC hash from clawcontrols, CST claims showing pinned hash, receipt binding fields. |
| Hash mismatch for request/response | Assume tampering or serialization mismatch; store raw payloads and canonicalization rules; re-run verification with agreed canonical form. | Computed hashes, canonicalization method/version, raw payload digests, receipt hashes. |
| Missing receipts for some calls | Fail the job audit; require all model calls to route through clawproxy; review OpenClaw provider configuration. | Expected call count vs receipts count, session timeline, proof bundle contents. |
FAQ
Can I verify a Gateway receipt without a proof bundle?
Yes, if you have the receipt bytes, the correct public key for clawproxy, and the expected context (job id, CST scope hash, and any pinned WPC hash). In practice, teams use proof bundles because they reduce “missing context” failures and make audits easier.
Why do I need policy-as-code instead of putting rules in the prompt?
A prompt is not a permission boundary. A WPC is a signed artifact, and a CST can optionally pin that policy hash, so the execution layer can reject runs that do not match the intended constraints even if the model was instructed otherwise.
What should I treat as the source of truth: the transcript or the receipt?
For “did a specific model call happen with specific inputs and outputs,” the receipt is the evidence object because it is signed and hash-bound. Transcripts can still be useful, but they are easier to edit and harder to bind to a specific call.
What are common verification pitfalls?
The most common are: using the wrong signer key, skipping canonicalization rules when recomputing hashes, and failing to enforce job scoping so a receipt can be moved between jobs. Another pitfall is accepting “receipt-like” logs from the agent instead of verifying the clawproxy signature.
How does this relate to OpenClaw security controls?
OpenClaw controls what tools can run and where they run (sandbox vs host), but that does not automatically produce third-party verifiable evidence of model calls. Gateway receipts and proof bundles complement OpenClaw by providing audit artifacts for the model gateway path.