wisewigdocs

Publish operations

Publishing has two phases: a tenant-local commit and asynchronous delivery. The content commit is authoritative and cannot be rolled back merely because a queue or plugin is temporarily unavailable.

Durable state machine

Each tenant workspace stores publish operations beside its documents. Immediate multi-page publication commits pages, navigation, redirects, and the current theme pin in one SQLite transaction, creates an operation, and sends a small version-addressed event. Scheduled publication stores the expected versions of all four draft resources and uses the Durable Object alarm; if any draft changes before the alarm, the transaction rolls back and the operation fails with a version conflict rather than publishing an unreviewed mixture.

Statuses are scheduled, queued, delivering, succeeded, superseded, failed, dead, and cancelled. Queue-send failures leave the publication committed and the operation visibly retryable. An older event becomes superseded when a newer version is already public; it must never overwrite the newer public index.

The management interface can schedule a draft up to 90 days ahead, cancel a still-scheduled operation, inspect attempts/errors, and explicitly retry failed/dead delivery. In managed hosting, listing and every effect use fixed dispatcher operations and execute inside the selected tenant Worker. These effects require content.publish, same-origin protection, confirmation, idempotency, quota enforcement, and tenant-local audit through the shared command layer.

Queue delivery

The non-public tenant workspace Worker consumes wise-wig-publish-events. For the exact published version it:

  1. replaces the sanitized PUBLIC_CONTENT record used by anonymous MCP;
  2. deletes verified-domain root entries from the named public HTML cache; and
  3. invokes enabled sandbox plugin content.afterPublish hooks through the isolated plugin service.

Each message is acknowledged individually. Failures use bounded exponential retry delays, five configured retries, and wise-wig-publish-dlq. The same Worker consumes the dead-letter queue and marks the durable operation dead; operators or authorized site owners can retry it. Delivery is idempotent because the event addresses an immutable version and index/cache writes are replacements/deletes.

The queue Worker has D1 only to enumerate verified hostnames, public-content KV, the tenant namespace, and the isolated plugin service. The anonymous public MCP Worker still receives none of those privileged bindings.

Managed tenant delivery

Workers for Platforms installations use one Queue per tenant rather than the shared self-hosted Queue. The operator attaches the platform-owned tenant dispatch Worker as the Queue’s sole consumer. Each message must resolve through the persisted Queue/tenant/site tuple, then claim an exact tenant-local operation ID and published version through an event dispatch audience before indexing begins. The tenant user Worker never receives shared public KV, cache, analytics, D1, or plugin-sandbox bindings.

The managed beta consumer records a sixth failed attempt as dead and acknowledges it for explicit retry. A per-tenant dead-letter Queue is not required for correctness because the durable operation is the recovery ledger; adding provider-level DLQ retention is still an operations hardening option.

Host adapter boundary

The framework semantics are portable: commit a version, record an operation, enqueue an immutable event, deliver idempotently, and expose status. The Cloudflare adapter implements scheduling with Durable Object alarms, transport with Queues/DLQ, indexing with KV, and invalidation with Cache API. Another adapter may use a database job table, a conventional queue, or host cache purge API while preserving the same state machine.