End-to-end encrypted emergency messaging • Offline-first • No server required
Lifeline Mesh is a browser-based, cryptographically secure messaging system designed for emergency situations where traditional infrastructure may be degraded or unavailable.
Mission: When disaster strikes and infrastructure fails, people still need to communicate. This project aims to provide that lifeline.
This project could save lives, but it needs contributors to grow.
Open Contribution Areas:
| Priority | Task | Skills | Notes |
|---|---|---|---|
| 🟡 High | Mobile BLE peripheral implementation (experimental → shipped) | Capacitor / WebView bridge / native BLE APIs | v0.1.x first supported peripheral path is Node relay appliance (node-bleno); mobile/browser peripheral remains unresolved |
| 🟡 High | UI/UX Overhaul | Design, CSS, Accessibility | Functional but not polished |
| 🟢 Good First | Documentation i18n | Any language | Good first issue |
| 🟢 Good First | Playwright E2E expansion | Testing, browser automation | Real-browser harness exists; coverage can be widened |
Read the full roadmap: DEEP_DIVE_ANALYSIS.md | TECHNICAL_ROADMAP.md
Every contribution matters. Let's build this together.
https://hiroshitanaka-creator.github.io/lifeline-mesh/
git clone https://github.com/hiroshitanaka-creator/lifeline-mesh.git
cd lifeline-mesh
npm ci --prefix app
npm run dev --prefix app # opens http://localhost:5173Then: Generate keys → Add contacts → Encrypt/Decrypt
If you want a single HTML file that works offline without a server or npm run dev:
git clone https://github.com/hiroshitanaka-creator/lifeline-mesh.git
cd lifeline-mesh
npm ci --prefix app
npm run build --prefix app
# Then open app/dist/index.html directly in Chrome or EdgeAll JavaScript, CSS, and WASM is inlined into one file (app/dist/index.html) by vite-plugin-singlefile, so it works from file:// without any CORS issues and with no external network requests.
Note: Opening the source file
app/index.htmldirectly asfile://will fail with CORS errors. Always usenpm run devor the builtapp/dist/index.html.
- 🔐 Ed25519 signatures for message authentication
- 🔒 X25519-XSalsa20-Poly1305 encryption for confidentiality
- 🔑 Ephemeral encryption keys (forward secrecy approximation)
- 🎯 Recipient binding prevents message redirection
- 🛡️ Replay protection with 30-day nonce tracking
- ✅ TOFU (Trust On First Use) with key pinning
- 🔏 Contact verification workflow: mark contacts as verified or compromised, with safety numbers and per-contact status badges
- 🔗 Subresource Integrity (SRI) for CDN scripts
- 🔑 Auto-generate Ed25519 + X25519 key pairs
- 💾 Export keys (Argon2id/PBKDF2 password-protected backup)
- 📥 Import keys (restore from file)
- 🗑️ Reset all data (emergency key rotation)
- 👥 Create named groups with member lists
- 🔒 Sender Keys protocol (DMESH_GROUP_V1, domain-separated)
- 🔄 Chain key ratcheting per message (forward secrecy within session)
- 📡 Multi-link runtime: multiple concurrent BLE connections with real store-and-forward relay
- 🔀 N-hop routing: MeshRouter Phase 2 proactive route advertisements (auto-enabled at ≥2 links)
- 🧩 Transport boundary (
transport/) withTransportLinkadapters for browser-central BLE, Node peripheral reference path, and native peripheral contract stubs - 🔁 Phase 3 sync engine: append-only event log with outbox/inbox transition events, deterministic replay projectors, and Lamport anti-entropy primitives for partition/heal convergence
- 🌉 Phase 4 gateway bridge (
gateway/): dedicated island bridge service for local mesh ingest + duplicate-safe backhaul sync (no endpoint Starlink/browser mesh claims) - 🧪 Phase 5 verification support: deterministic simulator (
sim/), parser-fuzz/property integration tests, and simulation-based energy profiling - 📤 Outbox queuing (priority / TTL / per-link targeting) with automatic flush on reconnect
- 📥 Inbox persistence for received messages
- 🔌 GATT server layer (
bluetooth/gatt-server.js): pluggableIGATTBackendinterface ready for native adapters (Capacitor, noble) - 🖥️ Node.js relay server (
node-server/): persistent single-client relay mode with durable message store (persistent-relay-store.js) for infrastructure-independent forwarding
- 📊 Live mesh state dashboard: active links, route table, relay counters, route-advertisement activity
- 🟢 Color-coded link health (green ≥2 links, yellow = 1, red = 0)
- 🛡️ XSS-safe rendering; polling interval configurable
- 📱 Offline-first (works without internet)
- 📦 PWA manifest + share target (
title/textGET params) + app-shell service worker caching for scope/lifeline-mesh/ - 🆘 Emergency Mode (simplified, form-based disaster messaging)
- 📋 Copy/paste encrypted messages; keyboard shortcuts (Ctrl+K/E/D)
- 📚 Embedded documentation
- 🌐 No server required
- 🚀 Relay-agnostic (send via any channel: QR, Bluetooth, USB, radio, etc.)
- Usage Guide - Quick start, security practices, troubleshooting
- FAQ - 30+ questions about security, features, and usage
- Web Bluetooth Support - Browser/platform compatibility and fallback guidance
- BLE Peripheral ADR - Frozen v0.1.x decision: Node relay appliance is first supported peripheral endpoint
- BLE Peripheral Capability Matrix - Shipped vs contract-only vs experimental peripheral paths
- BLE Manual Validation Runbook - Hardware test matrix and repeatable contributor checks
- A↔B↔C Relay Drill - Unified interop drill for browser-central ↔ Node-peripheral path
- Hardware Smoke Path - Formalized realistic hardware validation path
- Node Relay Appliance Path - Install/run/operator workflow for the first supported BLE peripheral endpoint
- Protocol Specification - Current protocol specification (with vnext cross-link)
- Protocol VNext Freeze - Canonical phase-1 sign-target definitions and ID derivation
- State Model - Verification state machine + signed state/event model
- Phase 5 Model Spec - Deterministic simulator invariants and state transitions
- Threat Model - Comprehensive security analysis
- Crypto Core API - Reusable crypto functions
- Contributing Guide - How to contribute
- Security Policy - Vulnerability reporting
- Project Charter - Scope and goals
Validation gate status: passing (see commands below) ✓
| Validation Gate | Command |
|---|---|
| Lint | npm run lint |
| Typecheck | npm run typecheck |
| Unit (crypto + vectors) | npm run test:unit |
| Integration | npm run test:integration |
| Node relay appliance validation | npm run test:relay-appliance |
| Local aggregate | npm run validate |
# Run everything
npm run test:unit && npm run test:integration
# Crypto unit tests only
cd crypto && npm test
# Test vectors only
cd tools && npm run validate-vectors
# Smoke check (file-presence; no browser required)
npm run test:e2e:smoke
# Real Playwright E2E (requires: npm run test:e2e:install first)
npm run test:e2e:playwright
# Full real-browser path (install + Playwright run)
npm run test:e2e:real-browser
# Node relay appliance path validation (first supported BLE peripheral endpoint)
npm run test:relay-applianceCI note:
- Fast PR gate (
e2e_browser_smokejob in CI) runs the Playwright critical-path spec (main-ci-critical-path.spec.js) — full key-gen → encrypt → decrypt → verify → compromised flow. - Full Playwright suite runs in
.github/workflows/e2e-real-browser.yml(nightly, manual dispatch, and pushes to main/master). npm run validatemaps tovalidate:local(smoke E2E for faster local iteration), while CI usesvalidate:ci(addstypecheck:runtime+ Playwright critical path gate).
/app Demo UI (Vite build, ES6 modules, PWA)
src/
runtime-mesh.js Multi-link mesh runtime (addLink/removeLink, route adv)
operator-panel.js Live operator dashboard (polling, XSS-safe renderer)
/bluetooth BLE manager + MeshRouter + GATT server layer
ble-manager.js BLE central/client with store-and-forward
mesh-router.js Phase 1 (1-hop dedup) + Phase 2 (N-hop route adv)
gatt-server.js GATT peripheral layer with pluggable IGATTBackend
/transport Phase 2 transport-link adapters + retry policy + envelope strategy
/crypto Core crypto, group messaging, transport, store (schema v5 + event log)
/node-server Node.js relay server (persistent single-client relay mode)
/gateway Phase 4 gateway bridge service (island ingest/store/backhaul dedupe)
relay-node.js Relay session manager
persistent-relay-store.js Durable message store for relay forwarding
/spec Threat model + protocol specification
/tools Test vectors, validator, SRI generator
/docs Usage guide, FAQ, phase progress
/tests Integration and E2E test suites
/types TypeScript declaration files (.d.ts)
.github/ CI/CD workflows, templates
- Signing: Ed25519 (nacl.sign)
- Encryption: X25519-XSalsa20-Poly1305 (nacl.box)
- Hashing: SHA-512 (for fingerprints)
- Library: TweetNaCl (audited, compact)
Alice Relay Network Bob
| | |
| 1. Generate ephemeral | |
| 2. Encrypt (ECDH) | |
| 3. Sign (Ed25519) | |
| 4. Send JSON ---------> | Forward ----------> |
| | 5. Verify
| | 6. Decrypt
| | 7. Read
[Alice] ──BLE-link-A──► [Relay node] ──BLE-link-B──► [Bob]
│
runtime-mesh.js
MeshRouter (Phase 1+2)
route adv broadcast (30 s interval)
The app runtime (app/src/runtime-mesh.js) maintains a Map<peerId, BLEManager> for concurrent links. Incoming messages on link-A are forwarded to other links (egress loop), and route advertisements propagate topology automatically when ≥2 links are active.
The Node relay (node-server/) is intentionally single-client per active BLE session, with durable pending/delivered store state and observable cleanup/snapshot counters exposed via relay-ops.js and FileRelayStore#getSnapshot().
Gateway backhaul is a separate service (gateway/) and is not endpoint mesh runtime. Local mesh continues without gateway uplink; backhaul bridge logic only handles signed event replication between islands with loop/duplicate suppression. Gateway server event storage is append-only durable JSONL (.lifeline-gateway/<islandId>.events.jsonl by default, configurable with LIFELINE_GATEWAY_DATA_DIR / LIFELINE_GATEWAY_EVENT_STORE_PATH).
✅ Confidentiality: Only recipient can decrypt ✅ Authenticity: Sender verified via signature ✅ Integrity: Tampering detected ✅ Recipient binding: Message tied to specific recipient ✅ Replay resistance: 30-day nonce tracking
❌ Anonymity: Sender/recipient public keys visible to relays
❌ Traffic analysis resistance: Message patterns observable
❌ Post-quantum security: Vulnerable to quantum computers
❌ Perfect forward secrecy: Long-term signing keys used
❌ BLE availability: Web Bluetooth is effectively Chromium-only and requires a secure context (https:// or http://localhost)
bluetooth/backends/node-bleno.js); mobile/browser peripheral remains unresolved (operational bypass, not closure)
app/index.html as file:// fails (ES module CORS). Use npm run dev, or build once (npm run build --prefix app) to get app/dist/index.html, which is fully self-contained and works from file://
See THREAT_MODEL.md for comprehensive analysis. See WEB_BLUETOOTH_SUPPORT.md for current browser/platform BLE caveats.
- Shelter status updates
- Supply requests/offers
- Safety check-ins
- Evacuation coordination
- Natural disasters (earthquakes, floods, hurricanes)
- Infrastructure failure (power outages, network collapse)
- Remote/rural areas with limited connectivity
- Politically sensitive communications
- Mesh networks: WiFi Direct, Bluetooth mesh
- Sneakernet: USB sticks, SD cards
- QR codes: Display → scan
- Radio: LoRa, ham radio (encode JSON as text)
- Manual: Print encrypted JSON, hand-deliver
Automatically deployed from main branch via .github/workflows/pages.yml.
The workflow runs npm install --prefix app && npm run build --prefix app and deploys app/dist/ (Vite build output).
Live URL: https://hiroshitanaka-creator.github.io/lifeline-mesh/
- Run
npm ci --prefix app && npm run build --prefix app - Serve
app/dist/directory from your web server - Recommended: Add CSP headers for extra security
- SRI added to all CDN scripts
- Validation gates passing (
npm run lint,npm run typecheck,npm run test:unit,npm run test:integration) - Documentation complete
- Consider self-hosting TweetNaCl (avoid CDN dependency)
- Add Content Security Policy headers
- Set up monitoring/analytics (optional)
# All tests (crypto + vectors + integration)
npm test
# Crypto only
cd crypto && npm test
# Test vectors
cd tools && npm run validate-vectors
# Integration suites
npm run test:integrationcd tools
npm run generate-vectorscd tools
npm run generate-sri
# Copy output to app/index.html- Languages: JavaScript (ES6 modules), TypeScript (declaration files in
types/) - Crypto: TweetNaCl 1.0.3 + tweetnacl-util + argon2 (key backup)
- Storage: IndexedDB schema v5 via
crypto/store.js(includes outbox priority/TTL/link targeting fields and append-onlyeventLogwith rebuildable outbox/inbox views) - Build: Vite (app/), no build needed for crypto/tools
We welcome all contributors! Here's how to get started:
- Read DEEP_DIVE_ANALYSIS.md to understand the vision
- Check TECHNICAL_ROADMAP.md for implementation details
- Look for issues labeled
good first issue - Join the discussion in GitHub Discussions
- Code: Native GATT backend (Capacitor/noble), UI polish, LoRa/radio transport
- Security: Reviews, audits, vulnerability research
- Design: UX for emergency scenarios, accessibility
- Docs: Translations, tutorials, examples
- Testing: E2E coverage expansion, test vectors, edge cases
- Ideas: Protocol improvements, use cases, partnerships
git clone https://github.com/hiroshitanaka-creator/lifeline-mesh.git
cd lifeline-mesh
npm install
npm test # Run all testsSee CONTRIBUTING.md for detailed guidelines.
Current Version: 0.1.0 (v0.1.0 release gate passed; prototype quality)
- Core crypto (Ed25519 + X25519-XSalsa20-Poly1305), covered by unit + vector + integration gates
- Key management: generate, export/import (Argon2id/PBKDF2 password-protected backup)
- Transport layer: Clipboard, QR, File, BLE (via TransportManager abstraction)
- Multi-link BLE runtime: concurrent links via
Map<peerId, BLEManager>, egress relay loop, route-adv broadcast - MeshRouter Phase 1 + Phase 2: 1-hop relay with dedup; N-hop proactive routing with route advertisements (auto-enabled at ≥2 links)
- GATT server layer:
bluetooth/gatt-server.jswith pluggableIGATTBackend+MockGATTBackendfor unit testing - Operator Panel: live mesh monitoring UI (
app/src/operator-panel.js), mounted in app with 2 s polling - Store schema v5: outbox
priority/ttl/linkIdsupport plus append-onlyeventLogwith replayable outbox/inbox materialized views - TypeScript declarations:
types/runtime-mesh.d.ts,types/operator-panel.d.ts,types/gatt-server.d.ts,types/app-globals.d.ts - Contact verification workflow: safety-number display, verify / mark-compromised per contact, encryption blocked for compromised recipients
- Node.js relay server (
node-server/): persistent single-client relay with durable store; lifecycle/replay/dedup/failure-mode integration coverage - Group messaging MVP (Sender Keys / DMESH_GROUP_V1 protocol)
- Multi-job CI (lint, typecheck, unit, integration, compat, security, E2E Playwright critical-path)
- GitHub Pages deployment (Vite build)
- Comprehensive docs and threat model
- Browser/mobile peripheral backend gap (not closed): Node relay appliance is the only officially supported peripheral endpoint in v0.1.x. Native/mobile peripheral paths remain contract-only or experimental
- Mobile apps, LoRa integration, post-quantum crypto
- Full TypeScript strict-mode coverage for
app/src/andbluetooth/
Full Roadmap: DEEP_DIVE_ANALYSIS.md | TECHNICAL_ROADMAP.md
日本語ドキュメント: docs/DEEP_DIVE_ANALYSIS_JA.md
Found a vulnerability? Please use GitHub's private vulnerability reporting or contact maintainers directly. Do not open public issues for security reports.
See SECURITY.md for details.
MIT License - see LICENSE file.
Copyright (c) 2026 Lifeline Mesh Contributors
- TweetNaCl - Audited NaCl implementation by @dchest
- Emergency responders - Inspiration for real-world use cases
- Open source community - Testing and feedback
- Live Demo: https://hiroshitanaka-creator.github.io/lifeline-mesh/
- Documentation: docs/
- Issues: https://github.com/hiroshitanaka-creator/lifeline-mesh/issues
- Discussions: https://github.com/hiroshitanaka-creator/lifeline-mesh/discussions
A lifeline is a rope or chain thrown to rescue someone in danger. A mesh network ensures that if one connection breaks, others remain.
Lifeline Mesh is built to stay connected when everything else goes dark.
Thanks for your interest in contributing!
- Please keep changes small and focused (one topic per PR).
- Please avoid touching security, workflows, or CI configuration unless explicitly discussed first.
- Please describe:
- Why the change is needed
- How you tested it
- Any risks / edge cases
For safety and stability, I may ask for changes or close PRs while the repository is being stabilized. If you are unsure, please open an Issue first to discuss the approach.