Recover a long-paused continuation
Save paused work so it survives a long review or a process restart. Receive the signed outcome separately. Before applying it, the worker must confirm that the exact saved continuation still exists and matches the outcome.
Use the Core Human Review lifecycle guide for the complete response and resume-mode matrix.
Do not keep a short-lived employee session, workload credential, signing secret, or in-memory callback object as the only way to continue. Do not poll for the decision. Email is a notice, not a continuation signal.
Store the pause before waiting
Persist the server-issued binding for the exact paused branch:
- tenant, application, and environment;
- workflow instance and branch;
- continuation ID and checkpoint generation;
- review case and decision version;
- protected action ID; and
- the bound state fingerprint and policy decision identity.
Store the checkpoint and continuation binding in a durable store: your own, or the hosted store described next. Keep credentials in an approved secret manager, not in the checkpoint.
Use the hosted checkpoint store
The TypeScript, Python, and .NET core SDKs can keep checkpoints and accepted outcomes in VeriProof instead of an application database. Pass the hosted store where you would pass your own store:
- TypeScript:
veriproof.reviews({ store: veriproof.hostedReviewStore(), revalidate }) - Python:
client.reviews(store=client.hosted_review_store(), revalidate=...) - .NET:
Store = veriproof.HostedReviewStore<TInput>()inHumanReviewRuntimeOptions
The hosted store gives the same guarantees as an application-owned store: one checkpoint per continuation that can’t be overwritten with different content, each signed outcome accepted once, one worker lease at a time, an execution fence before your code runs, and reconciliation of an uncertain execution. The key you use needs the review-continuation grant.
What changes and what doesn’t:
- The signed callback still arrives at your receiver, which verifies it before the hosted store keeps it. Any worker process can then claim pending outcomes from VeriProof and resume, so the receiver and the worker don’t share a database.
- VeriProof keeps only what the SDK already puts in a checkpoint. Checkpoints and outcomes are encrypted at rest and confined to your tenant and application. VeriProof accepts an outcome only if it recorded that outcome for the application.
- A checkpoint must belong to a VeriProof review case for the same application. It’s deleted 7 days after its continuation resolves, and no later than 7 days after the case’s checkpoint retention deadline.
- A checkpoint can be up to 256 KiB, and an application can hold up to 10,000 open checkpoints.
Use your own store when checkpoints must stay in your environment.
Refresh the workload credential for each acknowledgment
The application execution acknowledgment uses an application API key with the
review-continuations.write scope. Resolve the current X-API-Key when each acknowledgment
request is sent. Do not capture the key when the application first pauses and
do not require the process to restart after key rotation.
With a workload identity credential, the SDK refreshes its short-lived access token for you, so a long pause never outlives the credential.
An expired or revoked key must not change continuation state. Obtain the current key through the application’s credential provider, then retry the same idempotent acknowledgment. An exact acknowledgment replay returns the stored result; a conflicting replay fails closed.
Callback signing keys verify incoming outcomes. Application workload credentials authorize outgoing acknowledgment requests. Do not substitute one for the other after rotation.
Keep branches independent
A workflow may have more than one paused branch. Store, claim, apply, and acknowledge each branch by its full server-issued binding. Never select work by session ID alone, by branch label, by action type, or by whichever pause is newest.
One branch may resume while another remains paused, terminates, or needs attention. Show that as a mixed session. Do not let one branch’s receipt, decision, or acknowledgment update a sibling branch.
Recover after a process restart
Accept and store the outcome
Verify the untouched callback bytes and exact binding. Store the accepted outcome durably before returning the receipt.
Let the worker claim pending work
After restart, read pending accepted outcomes from the durable store. Claim the exact continuation atomically so two workers cannot apply it together.
Apply the directive once
Recheck current application policy. Use protectedActionId as the durable
side-effect idempotency key. approved with continue_original may resume only
the exact bound branch. response_submitted may use resume_with_response,
enter an application-owned revision path with route_to_revision, or remain
paused with none. The revision path must not execute the superseded protected
payload. Rejection, cancellation, and expiry must not run the protected action,
and follow-up must remain paused.
For a typed response, verify the saved profile, request, response, protected
payload, and editable-scope digests. Apply only permitted replace operations
to registered JSON Pointer paths on the locally held payload. Reject a stale,
unknown, root, or sensitive path and route a revision through the
application-owned revision path.
Acknowledge the application result
Send resumed, terminated, remained_paused, superseded, or failed only
after the application knows that result. Resolve the current workload
credential for this request. If VeriProof answers 409 with
durable_receipt_pending, it hasn’t finished recording your callback receipt
yet. Send the same acknowledgment again after Retry-After; the SDKs do this
for you.
An exact callback replay returns the stored durable receipt. It does not create another claim or protected action. If a worker stops after applying the action but before acknowledging it, the durable action marker lets the next worker report the prior result without repeating the action.
Fail closed when the checkpoint is missing
Keep the signed outcome and receipt evidence, but do not rebuild application
state from the callback and do not run the protected action. Record a
lost_checkpoint incident for the exact application and continuation. Send a
failed or superseded execution acknowledgment when that state is known, and
route the incident to the responsible developer and continuation operator.
Checkpoint loss does not erase or reverse the human decision. The application team must restore a trustworthy checkpoint through its recovery process or end the affected continuation. Keep the recovery record separate from the original decision.
If application state changes before a decision, cancel the still-open case with
checkpoint_superseded and a new idempotency key. If it changes after durable
receipt, record superseded, execute nothing, and acknowledge that result.
Verify recovery with synthetic data
Use the runnable SDK examples and shared conformance harness to test:
- a pause that outlives the original workload credential;
- two branches decided in reverse order;
- a restart after durable receipt but before application work;
- a restart after the protected action but before acknowledgment; and
- a missing checkpoint that records an incident and executes no protected action.
Keep each test tenant, application, callback registration, credential, and durable store isolated. These synthetic checks do not authorize live customer data or replace production recovery exercises.
Advanced multi-stage approvals and third-party continuation connectors are not available in this release.