A production-ready Android app for administering Synapse homeservers. Manage users, devices, rooms, media, federation, and server health across multiple Synapse instances from a single, secure, mobile-first admin panel.
- Multi-server management — Add unlimited Synapse servers via
.well-knowndiscovery or manual URL; switch between them from the home screen. - Secure authentication — Admin login per server; access tokens stored in Android Keystore (
EncryptedSharedPreferences); passwords are never persisted. - User lifecycle — List, search (paginated), create, edit, lock/unlock, suspend/unsuspend, and deactivate users; optional media erasure before deactivation.
- Device & session control — View, inspect, and revoke device sessions; whois active-connection view.
- Rooms — List rooms, view details, block/unblock, delete, add members, set room admin.
- Media — List room/user media (room listings are unencrypted-events only per Synapse), MXC-aware per-item selection and deletes, optional scoped user bulk delete and delete-listed-room-media (
DELETE …/users/{id}/media, room-scoped deletes via listed MXC rows). - Federation — List federated servers, view details, reset connection.
- Server dashboard — View server version and key metrics; background jobs (updates status, pause/resume, start job).
- Moderation — List and manage event reports (view, dismiss).
- Audit logging — Destructive actions (deactivate, delete device/room/media, federation reset, etc.) are recorded locally in a Room database (no in-app audit viewer/export; re-verify before each release if you rely on this behavior).
- App lock — Optional PIN gate on app resume; configurable in Settings.
The app supports two authentication paths against Synapse homeservers:
- OAuth 2.0 + PKCE (MSC3861 / MAS) — used automatically when the
homeserver advertises
org.matrix.msc2965.authenticationin its.well-known/matrix/client. The app discovers the OIDC issuer, performs dynamic client registration (RFC 7591), drives the auth-code flow with PKCE-S256 in a Custom Tab, and requests theurn:synapse:admin:*scope. - Legacy password login — used for non-MAS Synapse deployments.
POST /_matrix/client/v3/loginwith username + password.
Tokens are persisted in EncryptedSharedPreferences (Android Keystore-backed).
Refresh tokens issued by MAS are used transparently to keep sessions alive.
Even after a successful OAuth login, the homeserver only grants
urn:synapse:admin:* to users who have can_request_admin = true in MAS.
If the scope is denied, the app surfaces a clear error and the operator must
run on the MAS host:
mas-cli manage set-can-request-admin <username> --admin
after which the user can log in again and obtain an admin-scoped token.
:app — Main activity, Compose navigation, tab bar, Hilt
:core:network — Retrofit + OkHttp + kotlinx-serialization, capability detection
:core:security — EncryptedSharedPreferences token store (no password persistence)
:core:database — Room audit log (AuditLogEntity, AuditLogDao, AuditLogger)
:core:model — Domain models (Server, ServerCapabilities)
:core:ui — Shared UI (SynapseTopBar, EmptyState, Spacing)
:core:testing — Standalone contract tests for Synapse API (no app dependency)
:feature:auth — Login screen, session validation
:feature:servers — Server discovery (.well-known), profile management
:feature:users — User list/detail/create/edit, deactivate flow
:feature:devices — Device list, delete, whois
:feature:rooms — Room list/detail, block, delete, members, admin
:feature:media — Media list/detail, quarantine, delete, bulk actions
:feature:federation — Federation list/detail, reset connection
:feature:stats — Server dashboard (version, metrics)
:feature:jobs — Background jobs (updates status, pause/resume, start job)
:feature:moderation — Event reports list/detail, dismiss
:feature:settings — App lock settings, PIN create/change flow
Clean Architecture + MVVM: ViewModels call use cases, use cases call repositories, repositories use per-server Retrofit instances from RetrofitFactory.
| Requirement | Value |
|---|---|
| Min Android | API 26 (Android 8.0) |
| Target Android | API 35 (Android 15) |
| Min Synapse | See Compatibility matrix |
| Build | JDK 17, AGP 8.6.x, Kotlin 2.1.x |
git clone https://github.com/sureserverman/matrix-synapse-manager-android.git
cd matrix-synapse-manager-androidSet the Android SDK path (or use ANDROID_HOME):
echo "sdk.dir=$HOME/Android/Sdk" > local.propertiesBuild and test:
./gradlew :app:assembleDebug
./gradlew testDebugUnitTest
./gradlew lint testDebugUnitTestInstall the debug build on a device or emulator:
./gradlew :app:installDebugSee docs/threat-model.md for the full threat model. Summary:
- Admin passwords are never stored; only short-lived access tokens are persisted.
- Tokens are kept in
EncryptedSharedPreferencesbacked by Android Keystore (AES-256-GCM). - Cleartext HTTP is disabled (
usesCleartextTraffic=false). - Destructive operations require explicit confirmation (and, for deactivation, typing the user ID).
- Optional app lock (PIN) protects the app when the device is unlocked.
| Document | Description |
|---|---|
| docs/privacy.md | Privacy policy — what data the app stores and where it is sent |
| docs/threat-model.md | Security design, assets, and mitigations |
| docs/compatibility-matrix.md | Synapse versions and admin API endpoints used by the app |
| docs/publishing-f-droid.md | How to publish the app to F-Droid |
| docs/publishing-google-play.md | How to publish the app to Google Play |
| docs/UI_UX_ANALYSIS_AND_IMPROVEMENTS.md | UI/UX analysis and spacing/empty-state alignment |
| docs/AUDIT_LOG_AND_DELETE_UX_PROPOSALS.md | Proposals for audit log and delete flows |
- Create a feature branch from
main. - Follow TDD where applicable: failing test → implement → green → commit.
- Run
./gradlew lint testDebugUnitTestbefore opening a PR. - Respect the project’s security and build rules (e.g. no cleartext, no password persistence).
This project is licensed under the Apache License 2.0.
Copyright 2026 The Matrix Synapse Manager Android Project.
Replace the copyright holder in LICENSE with your name or organization if you fork or distribute.
