Encrypted transfer delivery
The Rust service started by make run serves transfer data over the same
HTTPS origin as the intent service. Neon stores this data durably in seal_delivery,
separately from seal_deferred and the seal_relayer queue. Neither
execution nor intent cleanup controls ciphertext retention.
Sender and recipient flow
- The sender encrypts recipient and refund envelopes and saves exact bytes in the encrypted local account before any upload or transaction submission.
- With
transferDelivery: "relayer", the browser tries/archive/batch. Its eight-second deadline includes admission work. Only a committed upload withstored: truecounts as automatic delivery. - A failed upload does not block proof preparation or wallet submission. After confirmation, the UI opens the file-sharing controls and tells the sender to share the encrypted transfer. A successful upload keeps file sharing available.
- The recipient scans canonical chain events and public encrypted data, then matches ownership and verifies hashes locally. Uploading a draft alone cannot create a spendable transfer. The normal five-minute/reload/manual sync schedule applies. Account history, balances and Google Drive backups remain local or in the user's existing encrypted backup system.
- On later syncs, senders or importers republish locally retained envelopes missing from the service. Retries use the same bytes and are idempotent. Failed downloads remain retryable; they never advance a private discovery cursor or erase saved transfers. Public download selection does not depend on ownership.
Availability failures briefly stop additional requests in the same scan, so a large history does not incur one timeout per envelope. Missing individual files remain independently retryable. Sync never reports an unavailable delivery read as a successfully checked inbox. Optional delivery outages do not create account recovery errors or pause verified balances, wallet actions, or backups. The transfer screen reports the blockchain scan as complete and Receive offers file import with a quiet automatic-retry note. The last complete discovery block is preserved until the public delivery check succeeds.
This fallback covers delivery, not uncertain transaction execution. An unknown submission remains tracked through saved transaction evidence; the UI does not silently resubmit it through another executor.
API and storage
| Endpoint | Purpose |
|---|---|
POST /archive/batch |
At most 64 blobs and 64 matching public discovery headers, 2 MiB request limit, admission work required |
GET /archive/blobs/:hash |
Exact immutable ciphertext, or an explicit missing/unavailable response |
GET /archive/headers?after=0&limit=100 |
Ordered public discovery headers, maximum 500 per page |
GET /archive/health |
Storage readability and remaining write capacity |
The service validates each content hash and discovery header. Writes commit as
one transaction; an invalid reference, collision or exceeded quota rolls back
the batch. A shared row lock orders sequence allocation and commit across
processes, preventing pagination from skipping a late commit. Duplicate uploads
do not increase quota usage. Database triggers reject updates/deletes of stored
blobs and headers; schema access is revoked from PUBLIC. Queries use bound
parameters, verified TLS and a bounded connection pool. Connection details and
SQL errors are not sent to clients.
The initial quota is 1 GiB of accounted ciphertext/index data, not a physical
database-size guarantee. Accounted bytes include stored hex text and per-record
overhead. /archive/health stops reporting write readiness at 90% utilization;
reads and exact retries continue at capacity. An operator can change
seal_delivery.state.max_bytes after reviewing capacity. This is intentionally
separate from deferred-intent admission and retention.
There is no automatic TTL. Reclaim eligibility after seven days is not transfer expiry: an unclaimed transfer may still need its envelope. Keep database backups and monitor size/availability. Lost ciphertext cannot be recreated from its on-chain hash. If the service is down, already downloaded data and imported files still work with a funded wallet and available RPC. If its HTTP process stops, its delivery endpoints stop too; Neon retains the committed records for restart.
The service receives ciphertext and public discovery metadata, not wallet keys, plaintext balances or account snapshots. It can observe upload timing, hashes and request metadata. Encryption does not provide network anonymity.
Activation and verification
Review and apply 004_transfer_delivery.sql intent-service-rs/migrations/004_transfer_delivery.sql with
make delivery-migrate, which reads the existing private .env.
SEAL_TRANSFER_DATABASE_URL optionally selects a separate server credential;
otherwise the existing SEAL_DATABASE_URL is reused. The migration is additive
and does not rotate credentials. Normal startup makes no schema changes, so a
frontend deployed before migration safely uses file fallback. Restart make run
after installing dependencies. See the intent service runbook.
For separate runtime credentials, grant schema usage; SELECT, INSERT on
blobs and headers; SELECT, UPDATE on state; and usage on the header
sequence. Migration ownership stays with the operator. These grants do not
confer access to relay jobs or account backups. Never expose a PostgreSQL URL
through a VITE_* setting or an HTTP response.
cargo test --locked --manifest-path intent-service-rs/Cargo.toml delivery_postgres -- --ignored creates a disposable loopback PostgreSQL instance
with TLS and fresh credentials. It exercises the native HTTP/database path,
concurrent retries, pagination, atomic rollback, quota behavior and immutable
records. Rust SDK-vector tests separately verify recipient decryption. It never uses a live
Neon URL. SEAL_TEST_PG_BIN can select a local PostgreSQL installation.
Web tests cover timeout and lost acknowledgement fallback, sending a decryptable file after delivery failure, local-save failures, discovery retry and republishing old local sends. Existing file-import and chain verification tests remain applicable.