RepoPilotOpen in app →

signalapp/Signal-Server

Server supporting the Signal Private Messenger applications on Android, Desktop, and iOS

Healthy

Healthy across the board

weakest axis
Use as dependencyConcerns

copyleft license (AGPL-3.0) — review compatibility

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit 1d ago
  • 7 active contributors
  • Distributed ownership (top contributor 44% of recent commits)
Show all 7 evidence items →
  • AGPL-3.0 licensed
  • CI configured
  • Tests present
  • AGPL-3.0 is copyleft — check downstream compatibility
What would change the summary?
  • Use as dependency ConcernsMixed if: relicense under MIT/Apache-2.0 (rare for established libs)

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/signalapp/signal-server)](https://repopilot.app/r/signalapp/signal-server)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/signalapp/signal-server on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: signalapp/Signal-Server

Generated by RepoPilot · 2026-05-09 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/signalapp/Signal-Server shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO — Healthy across the board

  • Last commit 1d ago
  • 7 active contributors
  • Distributed ownership (top contributor 44% of recent commits)
  • AGPL-3.0 licensed
  • CI configured
  • Tests present
  • ⚠ AGPL-3.0 is copyleft — check downstream compatibility

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live signalapp/Signal-Server repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/signalapp/Signal-Server.

What it runs against: a local clone of signalapp/Signal-Server — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in signalapp/Signal-Server | Confirms the artifact applies here, not a fork | | 2 | License is still AGPL-3.0 | Catches relicense before you depend on it | | 3 | Default branch main exists | Catches branch renames | | 4 | Last commit ≤ 31 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>signalapp/Signal-Server</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of signalapp/Signal-Server. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/signalapp/Signal-Server.git
#   cd Signal-Server
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of signalapp/Signal-Server and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "signalapp/Signal-Server(\\.git)?\\b" \\
  && ok "origin remote is signalapp/Signal-Server" \\
  || miss "origin remote is not signalapp/Signal-Server (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(AGPL-3\\.0)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"AGPL-3\\.0\"" package.json 2>/dev/null) \\
  && ok "license is AGPL-3.0" \\
  || miss "license drift — was AGPL-3.0 at generation time"

# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
  && ok "default branch main exists" \\
  || miss "default branch main no longer exists"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 31 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~1d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/signalapp/Signal-Server"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

Signal-Server is the backend infrastructure for the Signal Private Messenger, a privacy-focused communication platform with end-to-end encryption. It handles account registration, message routing, and device management for Signal's iOS, Android, and Desktop clients. Built in Java with FoundationDB as the primary data layer, it processes millions of secure communications while maintaining cryptographic integrity across multiple client platforms. Multi-module Maven monorepo: api-doc/ generates OpenAPI documentation from service annotations, integration-tests/ contains end-to-end test suites for account and device flows, and the parent service/ module (not shown but referenced in pom.xml) contains the main server code. The build system uses Maven Wrapper (.mvn/wrapper/) and jgitver versioning (.mvn/jgitver.config.xml), with Docker containerization via Jib Maven plugin for deployment.

👥Who it's for

DevOps engineers and backend developers deploying or contributing to Signal's infrastructure, security researchers auditing encrypted communication systems, and organizations running private Signal servers via the open-source codebase. Contributors need deep understanding of cryptography, distributed systems, and privacy-preserving architectures.

🌱Maturity & risk

This is a production-grade, actively maintained project (6.1MB of Java code, comprehensive CI/CD in .github/workflows/, integration tests in integration-tests/). The presence of integration tests, documented build process requiring FoundationDB, and explicit security contact (security@signal.org) indicate enterprise maturity. The AGPLv3 license and cryptography notice show this is a serious, legally-reviewed system used by millions in production.

The single dependency on FoundationDB (mentioned explicitly in README, not packaged) creates operational risk—the system cannot function without a working FoundationDB instance. The integration test suite (integration-tests/src/test/java/) suggests some integration scenarios are tested, but test coverage depth is unknown from file listing alone. The codebase is large (6MB Java) and touches cryptography—this requires expert review for contributions. AGPLv3 licensing has deployment implications (source disclosure requirements).

Active areas of work

Unable to determine from file structure alone—you'll need to check GitHub branches and recent commits. The .github/workflows/ directory contains integration-tests.yml, test.yml, and documentation.yml, suggesting active CI/CD for testing and API doc generation. Dependabot is configured (.github/dependabot.yml), indicating active dependency management.

🚀Get running

# Install FoundationDB client library (required before build)
# On macOS: brew install foundationdb; on Linux: see https://www.foundationdb.org/download/

git clone https://github.com/signalapp/Signal-Server.git
cd Signal-Server
./mvnw clean test

Daily commands:

./mvnw clean test          # Run all unit and integration tests locally
./mvnw clean compile       # Build without running tests (requires FoundationDB running)

Full server startup requires FoundationDB instance running (see FoundationDB docs) and would be configured via files in the main service/ module (not shown in this subset).

🗺️Map of the codebase

🛠️How to make changes

  1. Adding API endpoints: work in service/ module (not shown), annotate with Jakarta REST/Swagger annotations; regenerated by api-doc/ module's swagger-maven-plugin-jakarta.
  2. Adding tests: place test classes in integration-tests/src/test/java/org/signal/integration/ following pattern of AccountTest.java; use TestUser.java and TestDevice.java fixtures.
  3. Configuration/dependencies: modify parent pom.xml (not shown); module-level overrides in api-doc/pom.xml and integration-tests/pom.xml.
  4. Build/CI changes: edit .github/workflows/*.yml files directly.

🪤Traps & gotchas

FoundationDB required before build: The README explicitly states FoundationDB client library must be installed on the host system first—./mvnw clean test will fail if FoundationDB isn't present. Version management: Version is dynamically determined by jgitver (.mvn/jgitver.config.xml), not hardcoded—git tag/branch history affects build versioning. Integration test dependencies: integration-tests/ assumes access to live or mocked Signal services (see Config.java and DynamoDbTables.java)—local testing may require Docker or AWS DynamoDB access. AGPLv3 compliance: Any deployment triggers source code distribution requirements—not just a build issue but a legal one.

💡Concepts to learn

  • Signal Protocol (Double Ratchet Algorithm) — The cryptographic foundation of all Signal communications—understanding forward secrecy, session state, and key ratcheting is essential for any server-side changes touching message encryption or device registration
  • FoundationDB (Distributed Transactional Key-Value Store) — Signal-Server's primary data layer; understanding ACID properties, layer architecture, and tuple encoding is mandatory for database schema changes or performance tuning
  • Multi-Device Synchronization (Linked Devices) — Signal allows one user to register multiple devices (phones, tablets, desktop); the server must track device keys, sync messages across devices, and handle device removal—this complexity permeates the account and message routing logic
  • Prekeys and One-Time Keys (OTK rotation) — Signal clients upload prekeys to the server for initial session establishment; the server manages OTK inventory and rotation—this affects message delivery reliability and performance characteristics
  • End-to-End Encrypted Backup (SEALED SENDER) — Signal supports anonymous, sealed sender messages where the server cannot decrypt or see sender metadata; server-side routing logic must handle this without breaking privacy
  • OpenAPI/Swagger Code Generation — API documentation is auto-generated from source code annotations via swagger-maven-plugin-jakarta; understanding how REST annotations map to OpenAPI YAML is necessary for API-facing changes
  • signalapp/libsignal — Core cryptographic library (Signal protocol, Curve25519 operations) that Signal-Server depends on; implements the encryption/decryption primitives
  • signalapp/Signal-Android — Official Android client that communicates with Signal-Server; understanding the client side clarifies server API contracts and data format expectations
  • signalapp/Signal-iOS — Official iOS client; server must maintain protocol compatibility with both iOS and Android simultaneously
  • signalapp/Signal-Desktop — Official Electron-based desktop client; server handles linked device registration and message sync for desktop instances
  • element-hq/synapse — Similar distributed messaging server (Matrix protocol) that also handles end-to-end encryption and multi-device scenarios; useful architectural reference for comparison

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add integration tests for GraphQL Braintree payment operations

The repo contains GraphQL schemas for Braintree PayPal operations (ChargePayPalOneTimePayment, CreatePayPalBillingAgreement, TokenizePayPalOneTimePayment, etc.) in service/src/main/graphql/braintree/, but there are no corresponding integration tests. Given that integration-tests/src/test/java/org/signal/integration/ has AccountTest, MessagingTest, and RegistrationTest, adding PaymentTest would ensure payment workflows are validated end-to-end, which is critical for production systems handling real transactions.

  • [ ] Create integration-tests/src/test/java/org/signal/integration/PaymentTest.java
  • [ ] Add test cases for each Braintree GraphQL operation (ChargePayPalOneTimePayment, CreatePayPalBillingAgreement, TokenizePayPalOneTimePayment)
  • [ ] Reference the existing TestUser and TestDevice patterns from AccountTest.java for consistency
  • [ ] Update integration-tests/pom.xml if additional Braintree SDK dependencies are needed
  • [ ] Document test setup requirements in TESTING.md for PayPal sandbox credentials

Add GitHub Actions workflow for OpenAPI documentation generation validation

The api-doc module generates OpenAPI specifications via the swagger-maven-plugin-jakarta, but there's no dedicated CI workflow (.github/workflows/) to validate that OpenAPI documentation builds successfully and stays in sync with code changes. This prevents documentation drift and ensures the OpenAPI spec is always deployable. Add a workflow alongside existing test.yml and integration-tests.yml.

  • [ ] Create .github/workflows/openapi-validation.yml
  • [ ] Configure Maven build step to run 'mvn clean compile' on the api-doc module specifically
  • [ ] Add validation step to verify signal-server-openapi.yaml is generated in target/openapi/
  • [ ] Optionally add a step to lint the OpenAPI YAML against the OpenAPI 3.0 spec using a tool like spectacle or swagger-cli
  • [ ] Trigger workflow on changes to service/src/main/java (API controllers), api-doc/, and service/pom.xml

Add unit tests for api-doc OpenAPI extension classes

The api-doc module contains custom OpenAPI extension logic in src/main/java/org/signal/openapi/ (OpenApiExtension.java, OpenApiReader.java), but there are no corresponding unit tests in api-doc/src/test/. This is a gap compared to the service module's test coverage. Testing these extensions ensures custom OpenAPI generation logic works correctly before reaching integration tests.

  • [ ] Create api-doc/src/test/java/org/signal/openapi/ directory structure
  • [ ] Create api-doc/src/test/java/org/signal/openapi/OpenApiExtensionTest.java to test extension registration and behavior
  • [ ] Create api-doc/src/test/java/org/signal/openapi/OpenApiReaderTest.java to test OpenAPI schema reading logic
  • [ ] Add JUnit 5 and Mockito dependencies to api-doc/pom.xml if not already present (inherit from parent)
  • [ ] Add test execution to Maven's default lifecycle in api-doc/pom.xml using maven-surefire-plugin

🌿Good first issues

  • Document FoundationDB setup requirements in TESTING.md: TESTING.md exists but README implies complex FoundationDB setup—documenting platform-specific installation (macOS brew, Ubuntu apt, Docker) with expected versions would reduce onboarding friction for new contributors
  • Add OpenAPI endpoint documentation comments to existing service endpoints: The swagger-maven-plugin in api-doc/pom.xml auto-generates signal-server-openapi.yaml from annotations—many service endpoints (in service/ module, not shown) likely lack proper @Operation, @Parameter, @Schema Swagger annotations; adding these improves API documentation
  • Extend integration tests to cover device synchronization edge cases: TestDevice.java and AccountTest.java show multi-device test infrastructure exists, but common Signal edge cases (device sync during offline window, concurrent registration, key rotation timing) could have dedicated test scenarios in integration-tests/src/test/

Top contributors

Click to expand

📝Recent commits

Click to expand
  • bde52d7 — Update to the latest version of the spam filter (ameya-signal)
  • 59f2f04 — Handle BackupFailedZkAuthenticationException in grpc SetPublicKey (ravi-signal)
  • 305b015 — Update to the latest version of the spam filter (eager-signal)
  • f6ebde8 — Add Profile gRPC services to server (eager-signal)
  • 58d4a3b — Bump aws-actions/configure-aws-credentials (dependabot[bot])
  • 9c6ec78 — Match profiles V2 test table name in Java and configuration (eager-signal)
  • 1e3b2c8 — Profiles gRPC: initial v2 implementation (eager-signal)
  • 1b11c3e — Log when DynamoDB/JSON phone numbers differ (katherine-signal)
  • b441fde — Enforce key-ids fit in a positive signed 32-bit int (ravi-signal)
  • de5cb33 — Don't try to decode null session IDs (jon-signal)

🔒Security observations

The Signal-Server codebase demonstrates reasonable security practices with a mature project structure and proper use of dependency management. However, several medium-severity issues were identified: potential GraphQL injection risks lacking explicit validation mechanisms, sample secrets configuration files that could be accidentally overwritten with real secrets, and missing visibility into critical security headers configuration. Additionally, Swagger/OpenAPI plugin versions should be explicitly pinned, and Docker/container security posture could not be fully assessed from the provided files. The project should implement strict input validation for GraphQL operations, enforce environment-based secret management, document security header policies, and ensure comprehensive vulnerability scanning in the CI/CD pipeline.

  • Medium · Swagger Maven Plugin Version Not Pinned — api-doc/pom.xml - swagger-maven-plugin-jakarta dependency. The swagger-maven-plugin-jakarta dependency uses ${swagger.version} variable which is not explicitly shown in the provided pom.xml. This could lead to unexpected version updates and potential vulnerabilities if the parent POM uses a permissive version range. Fix: Explicitly pin the Swagger plugin version to a known-good release and regularly audit for security updates. Review the parent POM to ensure version constraints are appropriate.
  • Medium · GraphQL Schema Files Not Validated — service/src/main/graphql/braintree/ - GraphQL files. GraphQL schema files (ChargePayPalOneTimePayment.graphql, etc.) are present but there is no indication of input validation or schema validation mechanisms. GraphQL endpoints can be vulnerable to injection attacks and denial of service if queries are not properly validated. Fix: Implement strict GraphQL query depth limiting, query complexity analysis, and input validation. Use tools like graphql-java's QueryComplexityInstrumentation or similar validation frameworks.
  • Medium · Sample Secrets File In Repository — service/config/sample-secrets-bundle.yml. The file 'service/config/sample-secrets-bundle.yml' suggests the presence of secrets configuration. Even if marked as 'sample', accidental commits of actual secrets files to this directory is a risk. Fix: Ensure all actual secrets files are in .gitignore. Use environment variables or secure secret management systems (AWS Secrets Manager, HashiCorp Vault, etc.) for runtime secrets. Never commit real credentials.
  • Medium · Missing Dependency Version Management — api-doc/pom.xml and service/pom.xml. The provided pom.xml excerpt uses ${project.version} for internal dependencies but the parent POM version is set to 'JGITVER' (git-based versioning). This introduces complexity in version management and could lead to dependency conflicts or unexpected version mismatches. Fix: Document the JGITVER versioning scheme clearly. Implement dependency version convergence checks in the build pipeline. Use maven-enforcer-plugin to validate consistent versions.
  • Low · No Security Headers Configuration Visible — service/config/ - configuration files. No explicit security headers configuration (CSP, X-Frame-Options, X-Content-Type-Options, etc.) is visible in the provided configuration files. This is critical for a web service like Signal-Server. Fix: Implement comprehensive security headers in the web server configuration. Include: Content-Security-Policy, X-Frame-Options: DENY, X-Content-Type-Options: nosniff, Strict-Transport-Security, X-XSS-Protection.
  • Low · Limited Docker Security Configuration Visibility — Docker/Container configuration (not provided). No Docker configuration files (Dockerfile) are visible in the provided structure, though the jib-maven-plugin is configured. Docker image security practices cannot be fully assessed from provided data. Fix: Review Dockerfile for: non-root user execution, minimal base images, regular vulnerability scanning, explicit healthchecks, and resource limits. Integrate container scanning in CI/CD pipeline.
  • Low · Maven Wrapper Included Without SHA Verification — .mvn/wrapper/maven-wrapper.jar. The Maven wrapper files (mvnw, mvnw.cmd, maven-wrapper.jar) are committed to the repository. While convenient for builds, ensure the wrapper JAR is regularly audited for tampering. Fix: Implement checksum verification of maven-wrapper.jar. Document the SHA-256 hash of trusted wrapper versions. Consider using Maven's --strict-checksums flag in CI/CD.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · signalapp/Signal-Server — RepoPilot