Sloppy Voice DevelopersSloppy Voice ↗

Sloppy Voice protocol design

This technical document explains the implemented control/text protocol and identifies its authoritative contracts. It is an implementation guide, not a claim that every proposed architecture or physical-platform acceptance case is complete. The specification sources retain their CONFIRMED, PROPOSED, OPEN and DEFERRED labels.

Authority boundaries

An instance owns account identities, password verifiers, approved device rosters and login sessions. A deployed server owns its channel policies and history. The logical-servers/1 extension adds multiple independently owned logical servers sharing the instance account authority. The creator becomes a logical owner; neither a logical owner nor an instance owner implicitly inherits the other's authority. Shared accounts keep one identity/key roster while server memberships remain independent.

A server authorizes every operation; client controls are conveniences. Hidden/inaccessible resources return the same 404 as unknown IDs. Channels use explicit admission, current device authority, deny-first inherited permissions, and immutable encryption mode. Public/private discovery and encryption are distinct properties. Direct conversations require E2EE. SPEC-002, SPEC-003, SPEC-010, SPEC-015, SPEC-018 and SPEC-022 own these boundaries.

Transport and authentication

Control uses HTTPS JSON under /api/, with same-origin credentials or explicitly allowed browser origins. The library refuses redirects, omits cookies, bounds responses and scopes bearer credentials to the selected service base. Service discovery binds identity domains to explicit HTTPS bases; a domain/host locator alone grants no rights.

Devices have independent X25519 encryption and Ed25519 signing keys. Registration proves possession of the signing key. Password login signs a single-use username/device challenge; a known device ID alone is insufficient. Signed login tokens remain subject to current server-side session/device revocation. Linked devices and recovery use SPEC-011; signed session lifetimes and rotation use SPEC-009/SPEC-016. The SDK reuses the existing proof implementation.

Mutations and durable outcomes

A command is {ticket,action,expectedRevision,payload}. The server issues a purpose/audience/account/device/scope-bound ticket with an operation UUID and deadline. Canonical JSON recursively sorts object keys, retains array order, rejects unsupported values, and contains no whitespace. A SHA-256 fingerprint binds the first accepted action, revision and payload to the operation.

Authentication and current authorization precede mutation and replay disclosure. Revision checks prevent stale writes. A transaction commits resource changes, result identity and audit metadata together. An identical retry returns the original authorized result; an altered retry conflicts. An expired ticket with no retained result cannot become a new operation. Network failure after commit leaves an ambiguous outcome, so clients retain and retry the original command. SPEC-006, SPEC-009 and SPEC-028 own this behavior.

Message envelopes

An envelope contains profile, UUID id, room, sender, device, revision, boxes, and signature. Host-bound variants add serverId and senderDomain. An E2EE box contains a target device ID, 24-byte nonce and ciphertext authenticated using X25519/XSalsa20-Poly1305 through libsodium. Ed25519 signs the complete canonical unsigned envelope. The encrypted inner body binds the message ID, actual room, sender/device, revision, recipient, optional server/conversation/reply/visibility context and text.

The server requires exactly the current admitted approved-recipient device set and verifies the authenticated signer matches the session. A stale recipient set conflicts. In a server_readable channel, boxes is empty and the signed envelope instead contains encryption: server_readable plus bounded text. Room mode determines the exact accepted variant; no implicit plaintext fallback exists. A message ID reused with different signed bytes conflicts even with a new command ticket.

Non-visible channel control envelopes add signed boolean nonVisible:true, also bound inside ciphertext. They share the channel's authority, encryption and retention. Default history omits controls; explicit API retrieval includes them. This is presentation metadata rather than a privilege or confidentiality boundary. Control content cannot become pins or reply/thread references. See SPEC-009, SPEC-011, SPEC-012 and SPEC-028.

History, pagination and membership intervals

Admission/removal and accepted messages advance monotonically increasing channel positions. Membership intervals include their admission boundary and exclude their removal boundary. Retrieval requires current admission and filters retained records against the union of eligible intervals. Reconnect does not create a new interval; leaving and later joining excludes absence-period content. History-copy proofs preserve original eligibility, signed context and expiry rather than broadening retention.

Each page considers at most 50 eligible records. Presentation filtering may produce an empty page while advancing the cursor. Use the returned cursor rather than deriving it from the last displayed message. Text is at most 4096 UTF-8 bytes, complete envelopes at most 524288 bytes, and normal channel retention is seven days. Instance storage is bounded by the existing 10,000-message/64 MiB envelope quotas, and send limits remain 20/account/minute. SPEC-006 and SPEC-009/011/012 own these limits.

Synchronization and media separation

Authenticated state/history reads remain canonical. sync/1 batches the deployed server's reads; optional event-hints/1 WebSockets carry content-free synchronization hints, with polling maintained for fallback. A hint authorizes nothing and does not contain message bodies, secret keys or media grants. The initial logical-server API uses polling and does not advertise event-hint or media support.

Existing voice admission produces bounded, revision-bound leases separate from login and command credentials. Every forwarding path enforces current permissions and deadlines; a setup token is not indefinite authority. Opus voice, temporary authenticated voice keys, peer/relay routing, screen media and managed SFU delivery are described by SPEC-004/016/017/021/023/024/025. The API library does not implement capture, playback or these transports.

Storage, upgrades and limits of guarantees

Acknowledged mutations require durable storage. Schema 10 retains schema-9 records and message tables and marks the first stored control message or logical server; predecessor servers refuse the newer marker, preventing rollback from exposing hidden messages. Existing account IDs, device keys, memberships and message bytes are preserved. Rollback requires compatible code, not lowering the marker.

E2EE does not stop authorized participants forwarding content, compromised endpoints, metadata analysis, denial of service or malicious application-level bot commands. Current text keys do not establish forward secrecy for archived messages. Hosted rollout checks, platform/media acceptance and physical audio tests remain separate evidence. SPEC-007 defines validation; document/source publication alone does not establish those acceptance cases.

Authoritative sources and licensing

The searchable specification collection includes every active numbered specification and the decision register. Follow the linked source pages to inspect approval scope, configuration, tests and acceptance criteria. Historical or proposed sections must not override active accepted successors. Original library code, documentation and specifications use Apache-2.0 with project attribution; independently implemented clients/servers may use other licences under SPEC-000.