Protocol

September 8, 2026 · View on GitHub

crates/dezoomify-protocol is the Rust source of the boundary between the shared UI, CLI front ends, and runtimes. It generates the schema and packages/protocol-ts bindings plus serialization and compatibility tests. Other handwritten protocol types are not accepted.

Protocol v1 boundary interactions

InteractionProducerConsumerDirectionOrderingPayload ownershipFailureDeterministic test
Discovery fetch needjobhostjob→host effectFIFO per jobjob allocates request ID; host returns bytes or typed failuretyped fetch/decode errorP05-VARIANTS golden round trip
Deferred image selectionjobUIjob→UI eventonce per catalogjob owns catalog IDsinvalid selection rejectedP05-CATALOG
Fixed tile acquisitionjobhostjob→host effectbounded concurrencyout-of-band buffer handlesretry/partial policyP05-BUFFERS
Adaptive probe/observationjobhosteffect/response pairdeterministic priorityhost reports observationprobe limit errorP05-VARIANTS
Decode/process/write/encode/finalize/publicationhostjobhost→job responsecorrelated by effect IDbuffers released exactly oncetyped outcomeP05-OUTPUT
Scan candidateextensionjobhost→jobfirst-seen orderscan-scoped IDsstale scan rejectedP05-SCAN
Website/deep-link handoffwebsite/OSappinbound intentone-shot + confirmreceiver validates untrusted inputhandoff.rejectedP05-HANDOFF
Destination request/responsejobhosteffect/response pairbefore any writeopaque destination IDrejection recoversP05-OUTPUT
Recovery choicejob/UIjobevent/command paircorrelated by recovery IDtyped allowed actionsstale choice rejectedP05-RECOVERY
Progress snapshotjobUIjob→UI eventmonotonicabsolute countsn/a (transient)P05-VARIANTS
Terminal outcomejobUIjob→UI eventexactly onceoutput ID or errorterminal winsP05-VARIANTS

Commands

Commands express user intent and carry a request or job identifier. They cover discovery, selection, job start, cancellation, pause and resume (Pause v1 suspend-acquisition), recovery choice, output confirmation, and handoff import. Pause stops scheduling new tiles while in-flight work finishes and decoded output is retained; resume re-drives the pending queue. Duplicate pause is ignored; resume without pause is rejected. Commands are idempotent where retries are expected; duplicate identifiers do not duplicate work.

Events

Events are ordered per job and include state snapshots, selection requests, phase changes, progress, active transport and transport transitions where applicable, warnings, recovery requests, output readiness, completion, cancellation, failure, and pause/resume (paused/resumed, replayable, never terminal). Every event has a schema version, sequence number, and correlation identifier. Consumers can request a fresh snapshot after a gap.

Capabilities

The website baseline reports encoders [png, jpeg, tiff].

At connection time a runtime reports supported input schemes, fetch modes, decoders, encoders, processing operations, storage features, concurrency, practical size limits, bulk support, pause support, and handoff support. The shared UI gates controls from this declaration. The job engine also validates the final request, so capability checks are not UI-only. Bulk text discovery yields deferred entries that resolve one at a time; the website single-queue and the desktop multi-job queue run sequential single-job runs in their integration layers, so bulk_supported is true on the browser and native baselines. Queue availability is negotiated per connection: both peers must advertise bulk_supported, and an N-1 peer without it runs single jobs with the queue controls hidden. Pause v1 is negotiated the same way: both peers must advertise paused_supported (N-1 payloads omit it and default to false, hiding pause controls without breaking the 1.0 handshake). Handoff import is supported through validated HandoffDto. The native baseline reports encoders [png, jpeg, tiff, zif, webp], destination modes [file, iiif-dir], storage modes [cache], bulk_supported true, and paused_supported true. The CLI --bulk loop runs one bounded single-job run per list entry and shares the queue per-entry plus totals reporting.

Errors

Protocol errors contain a stable code, phase, retryability, safe user message, structured context, and permitted recovery actions. Host exception text is diagnostic data and never becomes the contract. See Errors.

Handoff

A website or deep-link handoff contains bounded non-secret input such as the source, selection, recipe, output intent, required capabilities, expiration, and originating application version. The sender offers it as a one-click Send to desktop action with an origin/scope summary (origin, no-credential scope, desktop recipient, single memory-only job); the receiver treats every field as untrusted, validates it by URL parsing plus exact sensitive-key matching, and requires user confirmation. Validation rejects userinfo, non-http(s) schemes, oversize input, unknown or duplicate fields, unsupported versions, malformed encoding, and sensitive query or fragment keys; /cookie-recipe/ stays valid while ?token=secret is rejected. No credentials travel in the URL and no client-side signing is used. Error text redaction has a single source in crates/dezoomify-protocol; all hosts delegate to it.

Extension-to-native handoff uses only allowlisted Native Messaging. Browser enforcement of the native host's allowed extension IDs authenticates the extension sender to the native host. A fresh challenge and one-use nonce bind the handoff messages to one explicit consent session and prevent replay; they do not establish sender identity. Cookies use that separate consent-bound channel, are scoped to named origins, and are not intentionally persisted; consent names origins, scope, recipient, and job, stays memory-only, and never carries over to later jobs. See Security.

Version handshake

Every connection starts with application version, protocol version range, schema fingerprint, runtime kind, and capabilities. Peers select a mutually supported protocol version before exchanging job data. Declared fields, challenges, and nonces do not establish identity. On the extension-to-native channel, sender authentication comes from browser enforcement of the native host's allowed extension IDs; challenge and nonce provide session binding and replay defense only. No version overlap produces protocol.incompatible with an update recovery action, and unknown fields never authorize behavior.

Release automation verifies generated files, schema fingerprints, compatibility fixtures, and the supported version matrix. See Releases.