Zumik
Guides

Purge semantics

The difference between delete and purge, the five guarantee classes, the signed receipt, namespace-generation invalidation, and why a purged artifact can never be resurrected from a stale cache.

Deletion in Zumik is explicit, profile-specific, and verifiable. There are two distinct operations, and they make different promises.

Delete is not purge

OperationPromise
DELETE /v2/artifacts/{id}Revoke the handle immediately. The id stops resolving.
POST /v2/purge-jobsRemove the retained state, invalidate dependent caches, and emit a signed receipt of what was confirmed.
GET /v2/purge-jobs/{id}/receiptRetrieve the receipt with per-processor evidence.

A delete makes the artifact unusable through the API. A purge goes further: it physically removes the stored bytes, bumps the isolation-namespace generation so any cached realization is poisoned, and records cryptographic evidence of the result. Use delete for routine cleanup; use purge when you need to prove state is gone - a data-subject erasure, a leaked secret, an end-of-contract teardown.

Run a purge

POST /v2/purge-jobs with the artifacts in scope. Each must be an artifact in your project.

curl https://api.zumik.ai/v2/purge-jobs \
  -H "Authorization: Bearer zk_live_..." \
  -H "Content-Type: application/json" \
  -d '{"artifact_ids":["art_01jy…"]}'
Job
{
  "id": "pjb_01jy…",
  "object": "purge_job",
  "status": "completed",
  "scope": { "project_id": "prj_01jy…", "artifact_ids": ["art_01jy…"] },
  "requested_at": "2026-06-15T12:00:00Z"
}

Under the hood a purge job revokes the handles, tombstones the artifacts and bundles, invalidates the sessions and snapshots that depend on them, increments the namespace purge generation, removes the canonical blobs and materializations, drops retained traces per the project's trace mode, invalidates runtime cache namespaces, requests provider-side deletion where supported, records each processor's acknowledgment, and issues the receipt.

The receipt

GET /v2/purge-jobs/{id}/receipt returns the evidence. It is keyed by the job id.

{
  "id": "pur_01jy…",
  "object": "purge_receipt",
  "requested_at": "2026-06-15T12:00:00Z",
  "completed_at": "2026-06-15T12:00:10Z",
  "scope": { "project_id": "prj_01jy…", "artifact_ids": ["art_01jy…"] },
  "guarantee": "verified_physical_purge",
  "processors": [ { "name": "state_store", "status": "purged" } ],
  "receipt_digest": "sha256:9f86d081…"
}

The receipt_digest is a recomputable SHA-256 over the job id, project id, the new namespace generation, every artifact id, and the completion time. It is evidence you can verify, not a marketing checkmark.

Guarantee classes

The receipt's guarantee is the weakest class any in-scope processor reported - a chain is only as strong as its weakest link. From weakest to strongest:

ClassMeaning
access_revokedCustomer handles stop working immediately.
best_effort_expiryA provider-controlled cache expires under the provider's own policy; expires_at is reported.
verified_namespace_invalidationThe namespace generation moved, so any stale physical cache can no longer be reused.
verified_physical_purgeManaged storage and cache processors confirmed deletion of the bytes.
cryptographic_purgeKey destruction makes encrypted retained bytes permanently unreadable.

A purge of an artifact held only in Zumik's own store, with no BYOC runtime attached, reaches verified_physical_purge - the state store reports purged and there is no weaker processor to drag the guarantee down. When a self-hosted runtime profile is in scope, a byoc_runtime processor appears and the guarantee reflects what that runtime could confirm.

The byoc_runtime processor is only added when the project has a live BYOC cluster. Zumik never fabricates a processor for infrastructure that isn't running, so the guarantee always reflects real acknowledgments.

Provider-profile limitation

For managed-provider traffic, Zumik can revoke access and invalidate its own caches, but it cannot force a third-party provider to physically erase a cache faster than that provider's policy allows. Those processors report best_effort_expiry with a concrete expires_at. The receipt states this honestly rather than overclaiming a physical purge it cannot verify.

Resurrection prevention

The point of bumping the namespace generation is that a purged artifact can never come back to life from a cache that outlived it. Physical caches are keyed by generation, so after a purge every prior realization is unreachable - a stale KV block from before the purge will never be served. This is the mechanism behind the purge_verification replay class: you can replay traffic that referenced a purged artifact and confirm it is not reusable.

Verify erasure with replay

Run a purge_verification replay to prove invalidated artifacts cannot be reused.

On this page