← Back to Pollis

Frequently Asked Questions

Short answers. Flip to dev mode if you want the technical version.

What is Pollis?

A desktop messaging app with group channels and direct messages, like Slack, but your messages are encrypted on your device before they leave it. The people running Pollis can't read them.

Tauri desktop client with a React UI and a Rust core for cryptography, MLS group state, and real-time media. The Rust core talks only to the Delivery Service — an in-repo axum server — for every remote read and every write; it holds no database credential of its own, and pollis-core does not link a database driver at all. Messages are end-to-end encrypted with MLS (RFC 9420) via openmls; neither the database nor the Delivery Service can read plaintext — they see ciphertext envelopes plus routing metadata.

How is it different from Slack, Signal, or Discord?

Slack and Discord can read your messages. Signal can't read yours either, but it's phone-number based and built for personal chats. Pollis is built for group workspaces like Slack, but with Signal-style privacy.

Slack/Discord: plaintext server storage. Signal: Double Ratchet, phone-number identity, optimized for 1:1 + small groups. Pollis: MLS-based group ratchet, username + email identity, Slack-style multi-channel workspaces, native desktop only.

Is it really end-to-end encrypted?

Yes. Messages, files, and voice are all encrypted on your device using the same kind of cryptography banks and secure messengers use. Your private keys never leave your computer.

The server can see who is messaging when, but not what.

Client-side MLS encryption (RFC 9420) via openmls. Private keys live in the OS keystore (macOS Keychain / Windows Credential Manager / Linux Secret Service) through the keyring crate, never on disk, never sent anywhere.

Voice is end-to-end encrypted too: audio frames are AES-GCM encrypted by libwebrtc's FrameCryptor post-Opus / pre-SRTP, keyed by a 32-byte secret derived from the channel's MLS group via MlsGroup::export_secret("pollis/voice/v1", epoch, 32). The LiveKit SFU forwards ciphertext only; the key rotates on every MLS epoch advance.

Server sees: user IDs, group/channel membership, message timestamps, sizes, public keys, voice presence and RTP routing metadata. Server does not see: message plaintext, file contents, voice audio, private keys.

Can the server tell who sent a message?

Not from what it stores. The saved record of a message no longer says who sent it, only the people in the conversation can tell, from the sealed contents. So a database breach, or a legal demand for stored data, can't reveal who said what.

One honest caveat, stated plainly: at the instant you hit send, the delivery server still checks that you're allowed to post in that conversation, so in that moment it does see it's you. Removing even that is future work.

Sealed sender (shipped). MLS already authenticates the sender inside the ciphertext via the message's BasicCredential ({user_id}:{device_id}), so the plaintext sender_id the server used to store was cryptographically redundant. The stored envelope is now sealed (migration 000008_message_envelope_sealed_sender.sql) and the recipient attributes the message from the MLS credential on decrypt, not from a server column.

Scope is at-rest only: the Delivery Service still authenticates the send with an X-Pollis-User header, so it sees the sender at the live moment. Anonymous membership proofs (which would remove even that) are future work, not shipped.

Does the length of my messages give anything away?

No. Every text message is padded out to a standard size before it's sealed, so its length reveals nothing, the server can't tell a one-word reply from a long paragraph by measuring it. (Attachments are handled separately and aren't padded.)

Text plaintext is padded to fixed size buckets before MLS encryption (pollis-core/src/commands/messages/framing.rs), so ciphertext size no longer correlates with message length. Attachments are the exception, they're shared via convergent encryption keyed on real file size, so they aren't bucketed.

Do notifications leak who's messaging me?

No. The real-time "new message" ping that tells your app to go fetch something no longer carries who sent it. It's just a nudge, your device learns the real sender only after it opens the sealed message.

The realtime signalling payload for new_message is stripped of sender_id, it's a wake-up ping only, and the recipient re-derives the sender from the decrypted MLS envelope. Same metadata-minimization work as sealed sender.

What happens if someone's cryptographic key changes?

Pollis detects it automatically and warns you. A red shield appears next to that person's name in every conversation you share (direct messages, group member lists, channels) and an inline notice shows up in the chat so you can re-verify them out-of-band (in person, by phone, however you trust).

You only need to verify a person once. After that, the green shield follows them everywhere they appear in your account. If their key ever changes, all those shields turn red at the same moment.

Signal-style 60-digit safety numbers derived from both parties' account_id_pub (SHA-512^5200, see pollis-core/src/commands/safety.rs). First-seen keys are pinned silently (TOFU) and surfaced on mismatch via a KeyChanged realtime event. Pinning runs on every DM ingest and on every group-reconcile commit (batch_check_and_pin_account_keys), so a Turso-side key swap is caught regardless of conversation type. Verification state lives in contact_verification keyed by peer_user_id (not per-conversation), which is what gives the per-user "shield follows the contact" behavior.

What happens to my messages if I get a new device or reset my account?

You will likely lose your old messages. This is on purpose.

A new device only sees messages sent after it's added. Resetting your account wipes prior messages. We don't back up your history to the cloud, because doing so would be a target for attackers and subpoenas.

If you need a permanent archive of everything you've ever said, Pollis isn't the right tool.

Message history is not a product guarantee. A new device joining an existing MLS group receives keys for the current epoch only, no historical backfill. Identity reset wipes local message storage. No encrypted cloud backup (no Megolm-style key-backup), and none is planned. This is explicit in CLAUDE.md as a design principle: simpler model, smaller attack surface, no key escrow.

Which platforms are supported?

macOS, Windows, and Linux.

macOS (universal binary, Apple Silicon + Intel), Windows x64, Linux (.deb, .rpm, .AppImage, AUR). Binaries are code-signed: Apple Developer ID on macOS, Azure Trusted Signing on Windows.

Is there an iOS or Android app?

No.

No. Voice/media is implemented directly in Rust (not in the webview), so mobile isn't a UI-only port, it would require native clients.

Is Pollis open source?

No, not in the strict sense of that phrase. The right word is source-available. The whole source is public on GitHub and you can read it, build it, and check our work — that part is real, and it is the part every verification claim on this site depends on. But the licence only permits personal and noncommercial use. Using Pollis inside a business needs a separate commercial licence from us.

No — source-available, not OSI open source, and we would rather say so than let the word do work it hasn't earned.

The repo at github.com/actuallydan/pollis is published under the PolyForm Noncommercial License 1.0.0. Any noncommercial purpose is permitted, which includes personal use, hobby projects, academic and public research, and use by charities, schools and government institutions — you may run it, modify it, and redistribute it for those purposes, provided you pass the licence terms along. Any commercial or business use requires a separate commercial licence; contact dankral01@gmail.com. The canonical text is LICENSE.md in the repo.

What this does not restrict is auditing. Nothing about the licence limits reading the source, rebuilding a release to compare it against the transparency log, or building and running pollis-verify yourself. The licence governs what you may ship, not what you may check.

How do I know the app I downloaded hasn't been tampered with?

Pollis publishes a fingerprint of every version it releases into a public, tamper-evident log. A small tool, pollis-verify, lets anyone confirm that the app they're running is one Pollis has publicly published, so nobody can quietly slip a single person a tampered build without it either showing up in that public log forever or being conspicuously missing from it.

On Linux this goes one step further: after every release an automated rebuild from the public source confirms the released app matches, byte for byte. On macOS and Windows that last step isn't there yet, so on those two the log proves the app matches what Pollis published, not yet that those bytes came from the source you can read.

Binary transparency (shipped). Each released artifact's hashes are appended to an append-only log at verify.pollis.com/v1/binaries, anchored to a single pinned log key (post-quantum ML-DSA-44; the key is published on the artifacts page). pollis-verify release <tag> checks a build against the log, trusting only that key rather than Pollis's word.

Each leaf also carries a toolchain field meant to record the exact build recipe — and here it has to be said plainly that every leaf published so far records unknown in it. No workflow ever set those values, so all 258 entries in the log today, through v1.9.7, carry "rustc": "unknown". The log is append-only, so those leaves cannot be corrected; they are permanently wrong about the recipe, while remaining correct about the hashes, which is what the log is actually relied on for. The release workflow now hard-fails rather than recording unknown, so leaves from the next release onward carry a real recipe. Do not read the existing 258 as containing one.

Also published per release, from the next release onward: a CycloneDX SBOM (pollis-<tag>.cdx.json) listing every Rust and JavaScript dependency the build resolved, and a build-recipe sidecar per platform. The SBOM is itself a provenance subject, so its digest is anchored in Sigstore's public log and a quieter replacement could not go unnoticed.

Also shipped: a post-release workflow that rebuilds the Linux AppImage from public source and asserts its hash against the log, failing the job on any mismatch; SLSA build provenance plus keyless cosign signatures on every artifact for all three platforms, published beside the downloads and anchored in Sigstore's public Rekor log, so verification needs no Pollis-held key; and an in-app "verify this build" button on the security screen, which hashes the running binary and re-runs the same release check the CLI does.

Their limits, stated plainly: the rebuild covers the Linux AppImage only (not .deb/.rpm, not macOS, not Windows) and needs the published build recipe rather than source alone, because a build-time value is baked in; every release's verdict is now published as a durable ledger on the assurance page, including the two historical red runs that were a since-fixed reporting bug and the one whose rebuild landed on a different CI machine image than the release — re-run on a matching image, that release reproduced byte-for-byte, and the page explains why. Provenance is not a release gate, and two earlier releases shipped without it. The in-app check is advisory, proves log inclusion rather than reproduction from source, and reports pending until the log's next daily rebuild covers a new release.

Is it free?

For personal and other noncommercial use, yes — free to download and free to run, with no account tier to buy. Using it inside a business is the one exception: that needs a separate commercial licence.

Free for any noncommercial purpose under PolyForm Noncommercial 1.0.0. Commercial or business use requires a separate commercial licence — see the licensing question above.

Why MLS instead of Signal Protocol?

Pollis is built around group chats. MLS is a newer standard designed for groups; Signal's protocol is great for 1:1 but gets slow and expensive at group scale.

MLS (RFC 9420) provides a single group key ratchet with O(log n) membership changes. Signal's Double Ratchet pairwise-ratchets between every member, so a group of N costs O(N) per sender per message. For a Slack-style product with large channels, MLS is the right primitive.

Do you store my email address?

Yes, we need it to send you sign-in codes. No phone number required.

Yes. Email OTP is the auth primitive, so the email is stored server-side to deliver the OTP and bind it to the account. Session tokens are held in the OS keystore.

How do I create or join a group?

Anyone can create a group inside the app. To add someone, invite them by their Pollis username, they need an account already.

Groups are created via the create_group backend command; members are added by username via send_group_invite. Adding someone generates an MLS Welcome that seeds their device into the group ratchet at the current epoch. DMs are implemented as 2-person MLS groups.

What happens if the server goes down?

You won't be able to send or receive new messages until it's back, but you can still open the app and read what you already have. A server outage is never a privacy problem, only a reachability one.

The server is required for message delivery, MLS commit routing, and R2 uploads. Read-only operation against the local encrypted SQLite store still works during an outage. Because the server can't decrypt, downtime has no confidentiality impact.

Where do my files go when I attach something?

Files are encrypted on your device before upload. The storage provider only ever sees scrambled bytes; only people in the group can decrypt them.

Attachments are encrypted client-side and uploaded to Cloudflare R2. The decryption key travels inside the MLS-encrypted message, so R2 only ever holds ciphertext. Recipients fetch by key and decrypt locally.

Should I trust Pollis with my life?

Pollis is in open preview and has not been independently audited. If your physical safety depends on unbreakable communication, use a mature, audited tool built for that threat model.

Open preview status, no third-party cryptographic audit yet. Protocol choices (MLS, keystore-backed identity, client-side encryption) target a Slack-style workspace threat model, not a nation-state adversary. For high-risk use, pick a tool with a documented audit history.