Calls the way the web client and Element Call do them, with the same
events, so the three can share a call. The famedly SDK's own group calls
use com.famedly.call.member events, which the others don't read, so this
is written against the matrix-js-sdk wire format instead (lib/matrix/
calls.dart):
- Membership: org.matrix.msc3401.call.member state, key
_@user:server_DEVICE_m.call, with the legacy session fields the js-sdk
sends (application m.call, call_id "", membershipID, expires,
focus_active, foci_preferred). An empty delayed copy (MSC4140) is
scheduled first and pushed back every 5 s; leaving sends the empty
state and cancels it.
- Media: a LiveKit token from the JWT service (the call's, else the
homeserver's rtc/transports or .well-known rtc_foci) for an OpenID
token; livekit_client connects.
- Encrypted rooms: a random 16-byte key per device, sent to every other
device in the call over encrypted to-device
io.element.call.encryption_keys, keys from others applied per LiveKit
identity (@user:server:DEVICE); per-participant keys, no ratcheting,
HKDF, like the web client's livekit-client.
- Ringing: a call started in a room of two sends a ring notification
(MSC4075); the other side gets an incoming-call card and an insistent
ringtone notification (full screen on a locked phone), declines with
MSC4310 or answers by joining. The caller gives up after a minute or on
a decline.
- UI: voice and video buttons in the room header, a call screen (the
other person large and you in the corner, or a grid; mute, camera, flip,
leave), a Join banner and a room-list marker for calls going on.
Not tested end to end yet: it needs a LiveKit SFU and JWT service.
README: replies, reactions, threads, spaces, QR verification, sliding
sync and calls.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
apps/mobile is a Matrix client for Android on the famedly Matrix Dart SDK,
with vodozemac (compiled from Rust during the build) for end-to-end
encryption. It speaks the plain Client-Server API and uses the web
client's design tokens, fonts and symbol.
- Sign in by server name (.well-known), homeserver address or full user ID;
sign up with the dummy and registration token stages. Sessions survive
restarts: SQLite in private storage, credentials also in the Keystore,
both excluded from backups and device transfers.
- Room list with unread and mention counts, invites, search and filters.
Timeline with grouping, day separators, notices, history on scroll,
links, images and files (authenticated media). Sending text, photos,
camera shots and files, with Sending/Sent/Read/Not sent and Retry.
Typing, receipts, deleting. New rooms and DMs, encrypted by default;
joining by address; room info with members, invite, rename, topic,
notification level, leave.
- Encryption: one-step setup behind a recovery key, verifying a new session
with the recovery key (restoring the backup) or another session, emoji
verification of people and sessions, reset. Undecryptable messages say
why. Session list with verify and sign out.
- Notifications while running, and push through UnifiedPush (no Firebase):
the distributor's endpoint becomes an event_id_only pusher, the gateway
is discovered, and a push starts the app headless to fetch, decrypt and
show the event.
Make targets: mobile (release APKs per ABI into bin/), mobile-run,
mobile-test. Kotlin incremental compilation is off (Windows, project and
pub cache on different drives), and Tink's JVM artifact is excluded in
favour of tink-android.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
apps/web: a Matrix client for the browser on Vue 3, Tailwind and
matrix-js-sdk, built on @warp/ui. Like the admin panel it is an optional,
separate service: warp-web embeds the built app, serves /config.json and
proxies only /_matrix/client and /_matrix/media to the homeserver (or,
with -public-homeserver, lets the browser call it directly).
Sign-in and sign-up with registration tokens, room list, timeline with
back-pagination, text, images, video and files over authenticated media,
local echo with sent/read/failed states, receipts, typing, invites,
creating, joining and leaving rooms, room info, settings, phone layout.
End-to-end encryption through the Rust crypto: encrypted messages and
files, emoji verification, key backup setup and restore.
apps/ui: WRoomItem, WMessageBubble and WComposer from the brand package,
and the icons the client needs.
syncapi fixes found with the client:
- A room joined inside the sync window was sent as the join alone with
limited: false, so clients thought they had the whole room. It is now
read like an initial sync; a profile change is not mistaken for a join.
- A live typing notification was reported on every sync, so every long
poll returned at once while anybody typed. Typing now has a position
in the sync token and is reported when it changes, including the empty
list when the last person stops.
Also: Dockerfile, a `web` compose profile, Makefile targets, a CI job
with a proxy smoke test, docs. PLAN.md moves out of the repository.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
apps/ui: Warp's design system for Vue 3 + Tailwind v4. Tokens, fonts,
icons and logo come from the brand package, with a Tailwind theme on the
tokens and Vue components on the brand component styles.
apps/admin: the admin panel as a separate, optional service. warp-admin
embeds the built Vue app and proxies only the login endpoints and
/_warp/admin/v1 to the homeserver. Pages: dashboard, users, rooms,
federation, registration and tokens, server notices, application
services, audit log.
Also: pnpm workspace, go.work entry, Dockerfile, an `admin` compose
profile, Makefile targets, a CI job with a proxy smoke test, and docs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Scaffolds the server module and everything Phase 0 of PLAN.md calls for:
a binary that boots, serves its discovery endpoints and nothing else yet.
- config: one YAML file plus per-field WARP_* environment overrides,
unknown fields rejected, validation that reports every problem at once
- logging and metrics: slog, a Prometheus registry, per-route HTTP
instrumentation labelled by pattern rather than path
- httputil: the Matrix error envelope, error-returning handlers, CORS,
request logging, panic recovery, and a router over http.ServeMux
- endpoints: /_matrix/client/versions, /.well-known/matrix/client,
/.well-known/matrix/server (gated), /healthz, /metrics, and
M_UNRECOGNIZED for everything else
- storage: driver registry, shared database/sql base, checksummed
migration runner, sqlite and postgres drivers, pocketbase stub
- settings: server_settings table behind a cached service, so the
federation and registration switches change without a restart
- federation: the gate that makes federation a runtime mode
- cmd/warp: serve, migrate, generate-keys, version
- Makefile, golangci-lint v2, GitHub Actions CI (Linux and Windows tests,
race on Linux, storage tests against PostgreSQL, lint, boot smoke test),
Dockerfile, example config and docs
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>