Sovereign-Computing.com

Reclaim your digital life. Own your sovereignty.

Estate-palette illustration on charcoal for the article Strafe Wants to Be the Third Federated Chat That Sticks. Read Its Licence First.

Strafe Wants to Be the Third Federated Chat That Sticks. Read Its Licence First.

The licence file Strafe did not have on Tuesday appeared on Thursday. It is not the licence its maintainer promised.

The code is better than the launch page deserves: a Discord clone with E2EE and a peering layer, so separate servers can talk. It reached Hacker News on 14 October.

Nothing here ran in my lab: no server, no account, no message. I read the 2 codebases, the deploy runbook, the dev docs, the thread and GIGAZINE’s write-up, and checked the claims against the raw files. This is an assessment, not a review.

Why the first 2 attempts lost

Federated chat has been tried twice at scale. Neither attempt failed on protocol.

XMPP failed on the client. Moving messages between servers that have never met is the hard part, and it works. What a person touches did not: a dozen clients, half dead, features bolted on years apart.

Matrix failed at the same cliff, later and at greater cost. Peering works and Element is a good client. But keys break when you add a device, and a group chat is asked to learn device checks. Matrix’s own project lead knows it. Posting as Arathorn in the Strafe thread, he named the weak spots in Olm and Megolm: the server tells clients who is in a room, so a bad one can slip an invite past you. Thomas Ptacek asked why anyone would build on those parts when Matrix itself is moving to MLS.

Same shape both times: the protocol came first, and the user adapted.

What Strafe copied, and why that is the clever part

What Strafe did not invent is the point.

The layout is Discord’s, with the names changed. A Space is a server, a Room is a channel, roles work the same way. The bot platform has the same 3 doors — REST, gateway, OAuth2 — with a mapping for Discord bot writers. Voice runs on a bundled LiveKit server in the same compose file.

That is the opposite of the first 2 attempts. No relearning tax.

The bigger concession is architectural. Peering is not a graph where every server holds every event. A space has an origin, the server that made it, and every other server keeps a mirror. The origin decides who is in, roles, order and bans. Relays are signed, queued per peer, retried on a backoff, and dropped after 7 days.

A graph is neater. An origin is easier to run. When someone has to go from a 5,000-member space, “ask the server that owns it” is an answer. “The graph will settle” is not.

The federation question, as found

The note I started from said nobody had found a federation protocol, and that the backend called itself unfinished. The second half holds: the README still tells people not to run it themselves.

The other half is wrong, and this is the biggest fix here. Federation is not missing. It is 21 Go files and 9,400 lines under internal/federation, with 51 signed routes for users, messages, calls, mirrors and keys. The design note runs 35 KB and admits its own gaps.

It is not ActivityPub: no WebFinger, no inbox. Strafe built its own in the Matrix shape: handles like name@domain, Ed25519 checks over method, path, time and body hash. The flagship serves the file at /.well-known/strafe today, with a live public key and version 1.0.0.

Federation exists, runs, and has a threat model. The docs run to 8 pages — getting started, apps, OAuth2, bots, gateway, REST, push — none about peering. That sits in a deploy README you find after deciding to self-host.

I could not find a second public instance. A federation of one is a self-hosted chat app with ambitious tables.

The licence question, as found

On 14 October a commenter called bratsche wrote that the site claims a permissive licence without naming it, and that the repo has no LICENSE file. Both true. Bryden Calaway, the maintainer, replied the same day: the project is AGPL-3.0, the MIT line was a placeholder a friend left on the landing page, and would add a licence to every repo.

On 16 October a commit called “Add GNU General Public License v3” added a LICENSE file to the web client. It contains GPL-3.0, and GitHub’s licence API now says GPL-3.0 for that repo. The backend has carried AGPL-3.0 since 2023.

Four licence claims coexist. The landing page says the code is “available under a permissive open source license”, which is false of GPL and AGPL alike. The footer says AGPL-3.0. The client’s package.json still says MIT. The client’s LICENSE says GPL-3.0.

There may be a workable split: GPL for the client, AGPL for the server someone might run as a service. Nobody wrote it down, and GIGAZINE printed AGPL-3.0 as fact on 15 October.

A licence is the permission to fork. It is the gap between “if this dies in 2028 I can keep my group running” and “I hope the maintainer stays generous”. The word “permissive” on the homepage is a mistake that has survived 6 days and a press cycle.

The encryption is real. The homepage is not.

Credit where due: the E2EE is not a slogan. The client module documents its own history. The old version had no key check, no ratchet, and a device signature that was a slice of the public key. It was replaced with vodozemac, Matrix’s audited Rust version of Olm and Megolm. Key backup sits under a recovery code.

Bots cannot read encrypted rooms at all, by design. The right call, and it costs them the bot ecosystem in the rooms where privacy matters.

Now the sentence that should worry you. The homepage says “all messages are encrypted by default”. The code says otherwise. In internal/modules/spaces/model.go the setting reads: nil or false means plain text, the default for space rooms. Private messages are locked by default. Space channels are not, unless someone turns it on. The docs say this correctly. The page does not.

The call is right: search, history and bots need plain text, and Discord users expect all 3. A homepage that argues with your own code is how you lose the readers who check.

What would have to be true

5 things would have to be true. 4 are not.

A second instance with real people on it. A group with its own domain, still talking to the flagship. Until then, federated is a capability, not a fact.

A shipped iOS app. The mobile repo is React Native, made 3 days before launch, and the maintainer says it is coming. Mobile is not optional, and voice on iOS needs native code.

A way to arrive. Account moves between servers sit on the project’s own “not covered yet” list, next to moderating one remote account, passing a report on, and read receipts. That is how a group leaves one server for another.

Media that does not expose the reader. Files load from the origin server’s CDN, so each image you open tells that server your address. The design note says a proxy would fix it. It is not built.

And one licence, stated once, on the site, in the footer and in every package.json. That is the cheapest item, and the only one still open.

Different, which is the problem

This is not the same failure with better branding.

Strafe removed the relearning tax, gave peering an owner instead of a vote, and built its E2EE on audited parts rather than enthusiasm. That is a real step past both earlier attempts, which is why the sloppiness matters. This one could be adopted.

But it shipped as a demo and will be adopted, if at all, as the thing groups run on. A demo can have a wrong licence page. A service cannot.

The first 2 attempts failed because the protocol came before the user. The third has the user in the right place. What it has not done is decide what it promises, in writing, to the people who would run it.

If you want the other half of this argument, about what a licence actually grants, it is here: One Year After DeepSeek.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.