Counting visitors…
Browse all docs
Start · 9Find your path through RunifoldLearn Runifold in 45 minutesUnderstand the complete Runifold platformYour first trustworthy runChoose the right execution APIChoose crates and Cargo featuresBuild common Runifold applicationsRunifold frequently asked questionsTroubleshoot Runifold applications
Execution kernel · 7Understand RunContextCoordinate external effects safelyBound work with budgets and cancellationHandle errors and retries safelyEvents, journals, and execution evidenceDesign capability-safe executionRecover safely from checkpoints
Models & providers · 7Route across models without duplicate outputChoose and configure a providerUse the provider-neutral model protocolBuild on the Provider Runtime contractUse OpenAI control-plane and Realtime APIsTest and benchmark provider adaptersSet up OpenAI, Anthropic, Gemini, and Ollama
Agents · 7Build and configure an AgentGive an Agent typed toolsAdd conversations and semantic memoryDelegate to child Agents safelyReturn structured Rust valuesStream without losing semanticsGround an Agent with retrieval
Durable workflows · 7Compose deterministic workflowsMake workflows durableOperate durable workflow workersCoordinate timers, signals, and durable waitsRun multi-tenant workflow infrastructureRun parallel branches and safe racesVersion and evolve durable workflows
Integrations · 7Connect through MCPChoose stores and persistence boundariesExpose durable work through MCP TasksBuild and evaluate retrieval pipelinesUse MCP Resources, Prompts, and SamplingCache MCP responses without crossing authorityDeploy Runifold in a Rust web service
Quality & operations · 10Test without the networkEvaluate quality and prevent regressionsObserve the complete run treeRun safely in browsers and at the edgeRead reliability claims preciselyRun reproducible evaluations in CIOperate Runifold with SLOsGovern Task retention and deletionArchive audit evidence to S3-compatible WORM storageManage compatibility and trusted releases
Docs/Quality and operations
NEW TO RUNIFOLD?Build the complete mental model in 45 minutes
Quality and operations

Archive audit evidence to S3-compatible WORM storage

Use application-owned pre-signing, stable object keys, conditional writes, checksums, Object Lock, and HEAD reconciliation after ambiguity.

Practical guide·12 min

Archive boundary

WorkflowTaskTombstoneArchive receives an exact ordered tombstone batch and a stable idempotency key derived from tenant and cursor range. It must persist that exact batch or replay the original receipt. The database export watermark advances only after the receipt returns.

Archive is evidence delivery, not ordinary logging. Failure blocks later purge authority.

Object contract

The S3-compatible adapter writes canonical JSON under a stable object key with conditional If-None-Match: *, SHA-256 checksum request and durable checksum metadata, required server-side encryption, and optional GOVERNANCE or COMPLIANCE Object Lock.

The receipt contains only bucket, object key, and checksum. Validate retention configuration in the object store; a request header is not proof that bucket policy accepted WORM semantics.

Credential model

Runifold uses application-owned pre-signing rather than storing long-lived cloud credentials. The pre-signer grants authority for one object and bounded PUT or HEAD operations through short-lived URLs.

Never persist or log signing credentials or pre-signed URLs. Bound the pre-signer's own network and credential I/O separately from archive request timeouts.

Ambiguous PUT recovery

A lost response does not prove the object was not committed. Runifold never blindly sends a second PUT inside the same archive call. It obtains independent HEAD authority and accepts success only when stored checksum metadata exactly matches the stable payload.

Timeout, authorization, unavailable, integrity, ambiguous, configuration, and other failures stay distinct and low-cardinality. Messages exclude URLs, credentials, payloads, and tenant identities.

Compliance checklist

  • enable versioning and required Object Lock before bucket creation policy is finalized;
  • select encryption and KMS ownership;
  • bound URL lifetime and allowed headers;
  • test conditional replay and response-loss reconciliation;
  • verify retention and legal-hold behavior against the real object store;
  • monitor export watermark lag and archive failure kind;
  • document restore, audit access, deletion exception, and key-rotation policy.

Construct the S3 archive

Enable the archive-s3 Feature and build policy and credentials outside the workflow worker. This example uses path-style addressing for MinIO; use the endpoint style required by your provider.

use runifold::archive_s3::{
    S3ArchiveEncryption, S3ObjectLock, S3ObjectLockMode, S3SigV4Credentials,
    S3SigV4Presigner, S3SigV4PresignerConfig, S3TombstoneArchive,
    S3TombstoneArchiveConfig,
};
use std::{num::NonZeroU32, sync::Arc, time::Duration};
 
let policy = S3TombstoneArchiveConfig::new("audit-bucket", "runifold", S3ArchiveEncryption::Aes256)?
    .with_request_timeout(Duration::from_secs(30))?
    .with_object_lock(S3ObjectLock {
        mode: S3ObjectLockMode::Compliance,
        retention_days: NonZeroU32::new(365).expect("retention is non-zero"),
    });
let signer = S3SigV4Presigner::new(
    S3SigV4PresignerConfig::new(endpoint, "us-east-1", 300, true)?,
    S3SigV4Credentials::new(access_key, secret_key, session_token)?,
);
let archive = S3TombstoneArchive::new(policy, Arc::new(signer));

Run the live MinIO/AWS reconciliation test before production. A successful PUT followed by a lost response must reconcile through HEAD and checksum equality; any mismatch blocks watermark advancement and therefore blocks purge.