Skip to content

Checkpoints and Participant Data Perimeter

Workflow-engine execution state is client-carried. The MCP server signs opaque continuation tokens, verifies them on the next call, and recomputes all semantic meaning from the immutable release and the caller's submitted contracts. It does not store participant sessions, artifact bodies, validator findings, queues, or run rows.

This state model is the core safety distinction between the current four-tool protocol and the legacy local registry documented in Legacy Local Registry and Pilot.

This flow shows that durable participant state lives with the participant harness, not in Rimthan persistence.

WorkflowTokenSigner

WorkflowTokenSigner in src/rimthan_workflow_mcp/workflow_engine.py signs canonical JSON payloads using HMAC-SHA256 and encodes them as base64url(body).base64url(signature). The body includes key_id, and verification selects the secret by key ID before using hmac.compare_digest.

Configuration enters through RemoteHttpConfig or local server CLI:

  • RIMTHAN_WORKFLOW_SIGNING_SECRET: active signing secret, minimum 32 bytes.
  • RIMTHAN_WORKFLOW_SIGNING_KEY_ID: active key ID.
  • RIMTHAN_WORKFLOW_VERIFICATION_KEYS_JSON: JSON object of retired key IDs to secrets, bounded to 16 retained keys and forbidden from redefining the active key.

parse_workflow_verification_keys validates the retired-key JSON shape. tests/test_workflow_engine.py::test_checkpoint_rotation_retains_old_verification_and_issues_new_key proves older checkpoints can verify while new checkpoints are signed by the active key.

Checkpoint contents

A workflow checkpoint envelope is returned as structured JSON and contains identity plus a signed continuation token. The token payload is intentionally digest-heavy and content-light. It records:

  • token schema and active key_id;
  • registry release and manifest digest;
  • workflow ID/version and current step;
  • sequence number and parent checkpoint digest;
  • confirmed-state SHA-256 digest, not confirmed-state content;
  • artifact receipt map of artifact ID to content digest;
  • validator receipt map of validator ID/version to pass outcome and input digest;
  • host binding: harness, adapter version, host capabilities, validator capabilities;
  • issue timestamp.

Verification checks both the envelope and the signed token payload. _verify_checkpoint verifies the token signature, then requires the envelope's registry_id, registry_release, workflow, current_step, sequence, parent_checkpoint_sha256, confirmed_state_sha256, artifacts, validators, host, and manifest digest to agree with the signed payload and the active pinned registry. A release mismatch, manifest mismatch, unavailable workflow/step, malformed host binding, unknown signing key, or envelope/token disagreement fails closed with WorkflowCheckpointError.

It does not contain participant artifact bodies, validator finding messages, user objectives, repository files, bearer tokens, private keys, or model output text. test_complete_stateless_validation_loop_fails_repairs_and_advances asserts the objective does not appear in the continuation token. test_participant_artifacts_and_findings_are_transient_and_not_checkpointed submits a unique marker in artifact content and findings, then asserts the marker is absent from validation bundles, checkpoints, query.__dict__, registry files, and logs.

Validation bundle tokens

prepare_step_validation signs a separate validation-bundle token after deterministic checks pass. The bundle binds:

  • workflow and registry release;
  • manifest digest;
  • step ID;
  • checkpoint digest;
  • artifact IDs and SHA-256 receipts;
  • validators, instruction digests, input artifact IDs, required flags, and report_required booleans;
  • issue timestamp and signing key ID.

The bundle also avoids participant bodies. Semantic validator reports must match the signed bundle exactly on instruction digest and input artifact digests. This prevents a harness from submitting a report for a different artifact or stale validator instruction.

Release-pinned resume

server._McpStateProvider.for_tool_call inspects a checkpoint's registry_release and verified token. If a workflow-engine client calls any checkpoint-bearing tool and the active in-memory release has changed, the provider loads or reuses the pinned release scope for that call. for_resource performs the same release routing for rimthan://registry/{release}/... resources.

This design lets Admin API activate a newer release while old participant checkpoints continue against their pinned immutable release. tests/test_workflow_engine.py::test_checkpoint_pinned_release_resumes_after_active_release_and_process_change builds a new active process but routes a checkpoint from release 1.0.0 back to the old verified scope. Corrupt active refresh is fail-soft to the last verified snapshot, proven by test_corrupt_active_refresh_retains_last_verified_snapshot.

Data perimeter

docs/operations/participant-data-perimeter.md is the operational authority for transient participant payloads. The implementation aligns with it as follows:

Data classRuntime handlingProhibited durable destinations
Artifact bodies submitted to prepare_step_validationParsed and validated in-process, converted to canonical SHA-256 receipts, then dropped after response.PostgreSQL, files, logs, metrics, traces, caches, checkpoints.
Validator reports submitted to submit_step_validationSchema-validated, binding-checked, findings echoed only to same caller on failure, pass receipts reduced to input digests.Durable sessions, release tables, checkpoints, logs.
Confirmed stateValidated against a release-pinned schema and represented in checkpoints by digest.Token body content and server persistence.
CheckpointsReturned to harness; harness writes .rimthan/workflow-session.json.Server-side workflow run storage.

RemoteHttpConfig defaults RIMTHAN_MCP_MAX_REQUEST_BYTES to a larger value for workflow-engine than operator profiles while still bounding requests. HTTP responses use private/no-store cache controls and deployment disables access logging according to the operations document.

Failure and integrity behavior

Malformed, stale, cross-workflow, cross-release, unknown-key, or invalid-signature checkpoints raise WorkflowCheckpointError. The server returns safe structured tool errors instead of proceeding. tests/test_workflow_engine.py::test_tampered_checkpoint_fails_closed covers token tampering. Migration invalidates prior artifacts and validators and restarts at setup-workspace, preventing old receipts from silently applying to a newer release.

Focused validation

  • Checkpoint privacy and transient data: uv run pytest tests/test_workflow_engine.py -k transient
  • Tamper and rotation: uv run pytest tests/test_workflow_engine.py -k "tampered_checkpoint or checkpoint_rotation"
  • Release-pinned resume: uv run pytest tests/test_workflow_engine.py -k pinned_release
  • Operational perimeter review: docs/operations/participant-data-perimeter.md

Generated from the committed OpenWiki knowledge bundle.