Offline Services
Status: Self-reviewed draft
Scope: optional mailbox and object storage services after the online MVP
Purpose
Section titled “Purpose”Offline services improve availability when devices are not online at the same time.
They do not become trusted authorities. They provide hints and encrypted bytes that clients verify against signatures, hashes, membership, epochs, and local anti-rollback state.
Phase Boundary
Section titled “Phase Boundary”Offline services are not required for the production online MVP.
They should be implemented only after:
- online v2 sync is reliable
- application session authorization is complete
- anti-rollback persistence is crash-safe
- membership and revocation behavior are implemented
- resource transfer is correct for attachments and custom icons
Mailbox Semantics
Section titled “Mailbox Semantics”A mailbox stores encrypted hints for a recipient device.
Allowed mailbox contents:
- blinded mailbox ID
- encrypted envelope
- expiry time
- small encrypted head hint
- storage or peer fetch hints
- admission metadata
Forbidden mailbox contents:
- full KDBX snapshots
- attachment payloads
- custom icon payloads
- durable revision history
- canonical latest-head pointer
Mailbox delivery is best effort. Absence of a mailbox message is not evidence that no newer revision exists.
Mailbox IDs
Section titled “Mailbox IDs”Mailbox IDs are blinded and epoch-scoped:
mailbox_id = BLAKE3("lattice-mailbox-id" || repo_secret || recipient_device_encryption_key || epoch)Membership changes rotate mailbox IDs.
Mailbox Admission
Section titled “Mailbox Admission”Recommended first supported mode:
capability-token mailboxCapability tokens should be scoped by:
- mailbox ID
- operation
- maximum bytes
- maximum messages
- expiry time
- optional sender identity
Account-authenticated mailbox mode is acceptable for hosted products and organizations.
Proof-of-work and unauthenticated mailbox deposits are excluded from the production MVP. They can be reconsidered only after there is an explicit abuse budget and operational policy.
Mailbox Limits
Section titled “Mailbox Limits”The first post-MVP mailbox profile is mailbox-capability-v1.
admission: capability tokenmax envelope size: 32 KiBmax envelopes per mailbox ID: 50max total bytes per mailbox ID: 1 MiBmax TTL: 14 daysmax writes per mailbox ID per day: 500max polls per mailbox ID per hour: 120drop policy: reject newest when quota is fullOperators may lower these limits. Operators may raise them only for authenticated or paid contexts with explicit quota accounting.
Future unauthenticated mailbox profiles, if any, must use a separate profile ID and a separate resource pool.
max TTL for any future unauthenticated mode: 24-72 hoursThe mailbox server must expose its policy so clients can decide whether deposits are useful.
Mailbox Capability v1 Wire Rules
Section titled “Mailbox Capability v1 Wire Rules”mailbox-capability-v1 uses /lattice/mailbox/1 over an authenticated,
encrypted libp2p connection. The service capability is an HMAC-authenticated
claim set scoped to one mailbox ID, an operation set (deposit, poll, and/or
acknowledge), byte and message ceilings, an expiry time, and an optional
libp2p peer ID. Capability failures do not reveal whether a mailbox exists.
Each mailbox envelope contains only an expiry, an ephemeral X25519 public key, AEAD parameters, and recipient ciphertext. The ciphertext contains a signed head hint: vault and membership bindings, epoch, sender and recipient device IDs, revision head and manifest hash, bounded peer-fetch addresses, and an optional object-manifest hash. It cannot contain records, resource payloads, or a full revision manifest. The sender signs the hint with its membership device key, then encrypts it to the recipient device encryption key using XChaCha20-Poly1305 and a key derived from ephemeral X25519 with HKDF-SHA-256.
Deposit is idempotent by a ciphertext-bound envelope ID. Poll does not delete; the recipient acknowledges envelope IDs only after decrypting and validating the hint. The service atomically persists deposits, acknowledgements, expiry pruning, and rate counters before reporting success. Quota exhaustion rejects the new envelope and retains previously accepted envelopes.
Object Storage Semantics
Section titled “Object Storage Semantics”Object storage stores immutable encrypted objects addressed by hash.
Allowed objects:
- encrypted resource chunks
- encrypted manifests
- future encrypted snapshot checkpoints
- advisory signed head pointers
Required verification:
- object hash
- manifest signature
- membership epoch
- writer authority
- resource descriptor hash
- local anti-rollback state
The storage server may provide convenience indexes, but clients must treat them as advisory.
Object Storage Admission
Section titled “Object Storage Admission”Public unauthenticated durable storage is not supported.
Allowed admission modes:
- account authentication
- storage capability token
- self-hosted credentials
- private allowlist
- paid or quota-backed hosted plan
Object storage must enforce quotas before accepting bytes.
Object Storage Limits
Section titled “Object Storage Limits”The first post-MVP object storage profile is object-storage-capability-v1.
admission: account auth, storage capability token, or self-hosted credentialsmax object size: 4 MiBtarget chunk size: 256 KiBmax manifest size: 1 MiBmax chunks per manifest: 8192max repo size: provider policy, advertised before uploadmax retained revisions: provider policy, advertised before uploadmax pinned objects: provider policy, advertised before uploadmax writes per token per day: provider policy, advertised before uploadgarbage collection: never collect pinned objects; unpinned objects may be collected after 30 daysProviders may choose smaller repo, retention, pin, write, and bandwidth limits, but must advertise them before clients upload. Clients must treat quota rejection as sync backpressure, not data loss.
Opaque KDBX snapshots, if added later, are quota-sensitive because attachments can make vault files large.
Advisory Head Pointers
Section titled “Advisory Head Pointers”Storage may expose signed head pointers for convenience.
Rules:
- A head pointer is never canonical by itself.
- Clients verify the pointed-to signed manifest.
- Clients compare the result against local rollback floors.
- Clients treat stale, missing, or conflicting head pointers as sync hints, not final truth.
- A storage server cannot make a client forget locally known heads.
Privacy Limits
Section titled “Privacy Limits”Offline services protect content but not all metadata.
Servers may observe:
- update timing
- ciphertext sizes
- mailbox polling times
- object fetch groupings
- network addresses
- account or token usage patterns
Mitigations:
- padded mailbox envelopes
- fixed or bucketed chunk sizes
- batching deposits
- rotating mailbox IDs by epoch
- avoiding human-readable vault names
- optional multi-provider storage
- privacy-heavy mode with no mailbox or object storage
The product must not claim anonymity.
Success Criteria
Section titled “Success Criteria”- Mailbox-only mode can notify a device about missing work but does not claim full offline catch-up.
- Mailbox plus object storage can catch up when no other user device is online.
- Object storage cannot forge, modify, or silently roll back accepted state.
- Stateful services have quota and abuse controls before public deployment.
- Proof-of-work and unauthenticated durable storage remain out of MVP defaults.
Implementation Status
Section titled “Implementation Status”The mailbox implementation includes the exact epoch/recipient blinded ID,
signed recipient-encrypted hints, scoped capability authentication, the fixed
mailbox-capability-v1 limits, idempotent deposit, explicit acknowledgement,
expiry and rate enforcement, crash-safe persistence, a bounded libp2p codec,
and a separately packaged mailbox process with operator capability issuance.
Pinned per-vault client endpoints and bearer capabilities stored in the
encrypted credential-cache KDBX are also implemented. The daemon performs
periodic deposit/poll cycles, persists exact outbound envelopes for restart and
lost-response idempotency, isolates capability failures, and acknowledges only
hints already present in the authenticated local revision graph.
Object storage implements immutable epoch-encrypted record/resource bundles, including historical conflict records, with scoped capabilities, pinning, garbage collection, quotas, advisory signed heads, a bounded libp2p protocol, and a separately packaged process. The daemon publishes a verified bundle before depositing its hint, reuses cached bundle bytes across retries, and fetches and verifies the advertised manifest, records, conflicts, and resources before materialization. The offline outage/restart E2E proves catch-up after the publishing user device goes offline and proves that stale redelivery cannot roll back a newer local edit. Phases 4 and 5 are complete.