{"id":47684404,"url":"https://github.com/rhonda-rodododo/llamenos-hotline","last_synced_at":"2026-04-19T14:12:11.543Z","repository":{"id":337487984,"uuid":"1153120763","full_name":"rhonda-rodododo/llamenos-hotline","owner":"rhonda-rodododo","description":"End to end encrypted hotline/messaging centre for the people. V1 of the llamenos project","archived":false,"fork":false,"pushed_at":"2026-04-11T04:21:23.000Z","size":74869,"stargazers_count":2,"open_issues_count":12,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-11T05:35:39.399Z","etag":null,"topics":["asterisk","e2ee","freeswitch","hotline","hotlines","human-rights","kamailio","nostr","pbx","plivo","rapid-response","signal","sip-client","sms","telephony","twilio","whatsapp"],"latest_commit_sha":null,"homepage":"https://llamenos-hotline.com","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rhonda-rodododo.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":".github/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-08T23:18:27.000Z","updated_at":"2026-04-11T04:21:29.000Z","dependencies_parsed_at":"2026-03-04T03:17:05.627Z","dependency_job_id":null,"html_url":"https://github.com/rhonda-rodododo/llamenos-hotline","commit_stats":null,"previous_names":["rhonda-rodododo/llamenos","rhonda-rodododo/llamenos-hotline"],"tags_count":65,"template":false,"template_full_name":null,"purl":"pkg:github/rhonda-rodododo/llamenos-hotline","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhonda-rodododo%2Fllamenos-hotline","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhonda-rodododo%2Fllamenos-hotline/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhonda-rodododo%2Fllamenos-hotline/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhonda-rodododo%2Fllamenos-hotline/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rhonda-rodododo","download_url":"https://codeload.github.com/rhonda-rodododo/llamenos-hotline/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhonda-rodododo%2Fllamenos-hotline/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31779947,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-14T02:24:21.117Z","status":"ssl_error","status_checked_at":"2026-04-14T02:24:20.627Z","response_time":153,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asterisk","e2ee","freeswitch","hotline","hotlines","human-rights","kamailio","nostr","pbx","plivo","rapid-response","signal","sip-client","sms","telephony","twilio","whatsapp"],"created_at":"2026-04-02T14:34:04.832Z","updated_at":"2026-04-14T03:00:48.705Z","avatar_url":"https://github.com/rhonda-rodododo.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Llámenos (v1)\n\nA secure, self-hosted crisis response platform. Supports voice calls, SMS, WhatsApp, and Signal — all routed to on-shift volunteers. Volunteers log encrypted notes and manage conversations in a webapp. Admins manage shifts, volunteers, channels, and ban lists. Reporters can submit encrypted reports through a dedicated portal.\n\nBuilt for organizations that need to protect the identity of callers, reporters, and volunteers against well-funded adversaries.\n\nA more sophisticated Llámenos v2 (aka [Llámenos Platform](https://github.com/rhonda-rodododo/llamenos-platform)) is under development, however we will be continuing to support Llámenos Hotline (v1) as a robust application into 2027, and provide a migration path once the v2 platform lands in app stores.\n\n## Screenshots\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"site/public/screenshots/dashboard-desktop.png\" alt=\"Dashboard\" width=\"600\" /\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cem\u003eAdmin dashboard with real-time volunteer presence and active calls\u003c/em\u003e\n\u003c/p\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eMore screenshots\u003c/strong\u003e\u003c/summary\u003e\n\n### Conversations\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"site/public/screenshots/conversations-desktop.png\" alt=\"Conversations\" width=\"600\" /\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\u003cem\u003eUnified messaging view for SMS, WhatsApp, and Signal\u003c/em\u003e\u003c/p\u003e\n\n### Volunteers\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"site/public/screenshots/volunteers-desktop.png\" alt=\"Volunteers\" width=\"600\" /\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\u003cem\u003eManage volunteer accounts and permissions\u003c/em\u003e\u003c/p\u003e\n\n### Shifts\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"site/public/screenshots/shifts-desktop.png\" alt=\"Shifts\" width=\"600\" /\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\u003cem\u003eCreate recurring shift schedules\u003c/em\u003e\u003c/p\u003e\n\n### Mobile\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"site/public/screenshots/dashboard-mobile.png\" alt=\"Mobile Dashboard\" width=\"200\" /\u003e\n  \u003cimg src=\"site/public/screenshots/conversations-mobile.png\" alt=\"Mobile Conversations\" width=\"200\" /\u003e\n  \u003cimg src=\"site/public/screenshots/notes-mobile.png\" alt=\"Mobile Notes\" width=\"200\" /\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\u003cem\u003eFully responsive mobile interface\u003c/em\u003e\u003c/p\u003e\n\n\u003c/details\u003e\n\n## How it works\n\n```mermaid\nflowchart TD\n    A[\"Incoming Call\"] --\u003e B{\"Shift Active?\"}\n    B --\u003e|Yes| C[\"Ring All On-Shift Volunteers\"]\n    B --\u003e|No| D[\"Ring Fallback Group\"]\n    C --\u003e E{\"First Pickup\"}\n    D --\u003e E\n    E --\u003e|Answered| F[\"Connect Call\"]\n    E --\u003e|No Answer| G[\"Voicemail\"]\n    F --\u003e H[\"Save Encrypted Note\"]\n```\n\n## Features\n\n### Voice Calling\n- **Multi-provider telephony** — Twilio, SignalWire, Vonage, Plivo, or self-hosted Asterisk\n- **Parallel ringing** — all on-shift volunteers ring at once; first pickup wins\n- **WebRTC browser calling** — volunteers can answer calls directly in the browser\n- **Automated shift scheduling** — recurring schedules with fallback ring groups\n- **Call spam mitigation** — real-time ban lists, voice CAPTCHA, rate limiting\n- **Client-side transcription** — WASM Whisper via ONNX runtime, audio never leaves the browser\n- **Voicemail** — automatic fallback when no volunteers are available\n- **Reproducible builds** — deterministic Docker builds with SLSA provenance and checksum verification\n\n### Multi-Channel Messaging\n- **SMS** — inbound/outbound SMS via Twilio, SignalWire, Vonage, or Plivo\n- **WhatsApp Business** — Meta Cloud API with template messages, media support, and 24-hour window handling\n- **Signal** — via signal-cli-rest-api bridge with voice message transcription\n- **Threaded conversations** — all messaging channels flow into a unified conversation view with message bubbles, timestamps, and direction indicators\n- **Real-time updates** — new messages and conversations appear instantly via WebSocket\n- **E2EE messaging** — per-message envelope encryption; server never sees plaintext\n\n### Encrypted Notes \u0026 Reports\n- **End-to-end encrypted notes** — the server never sees plaintext\n- **Custom note fields** — admin-configurable fields (text, number, select, checkbox)\n- **Reporter role** — dedicated portal for submitting encrypted reports with file attachments\n- **Report workflow** — categories, status tracking (open/claimed/resolved), threaded replies\n\n### Contact Directory\n- **E2EE contact records** — organizations, individuals, and relationships with encrypted fields\n- **PBAC (policy-based access control)** — team-scoped visibility and granular permissions\n- **Tags and intake forms** — categorize contacts and capture structured data\n- **Bulk operations** — import, export, and batch updates with encryption\n\n### Volunteer Experience\n- **Command palette** — Ctrl/Cmd+K for quick navigation, search, and one-click note creation\n- **Real-time notifications** — ringtone, browser push notifications, and tab title flash on incoming calls\n- **Volunteer presence** — real-time online/offline/on-break status visible to admins\n- **Note draft auto-save** — encrypted drafts preserved in the browser across reloads\n- **Keyboard shortcuts** — press `?` for a full shortcut reference dialog\n- **Dark/light/system themes** — toggle in sidebar, persisted per session\n\n### Administration\n- **Setup wizard** — guided multi-step setup on first admin login (name, channels, providers)\n- **In-app help** — FAQ, role-specific guides, getting started checklist\n- **Custom IVR voice prompts** — record greetings per language via MediaRecorder; falls back to TTS\n- **Configurable call settings** — queue timeout and voicemail duration (30-300s each)\n- **Audit log** — every call, note, message, and admin action tracked with hashed IP metadata\n- **Encrypted data export** — GDPR-compliant notes export encrypted with user's key (.enc format)\n- **Session management** — idle timeout warnings, auto-renewal, and forced re-auth on expiry\n- **13 languages** — English, Spanish, Chinese, Tagalog, Vietnamese, Arabic, French, Haitian Creole, Korean, Russian, Hindi, Portuguese, German\n- **Mobile responsive PWA** — installable on any device with push notifications\n- **Accessibility** — skip nav, ARIA labels, RTL support, screen reader friendly\n- **GDPR compliant** — designed for EU-based organizations\n\n## Quick Start\n\nOnly Docker is required. No Node.js, Bun, or other runtimes needed.\n\n```bash\ngit clone https://github.com/your-org/llamenos.git\ncd llamenos\n./scripts/docker-setup.sh\n```\n\nThis generates secrets, builds the app, and starts all services. Once running, visit **http://localhost:8000** — the setup wizard walks you through creating an admin account and configuring your hotline.\n\n### Try demo mode\n\nTo explore with pre-seeded data and one-click demo login:\n\n```bash\n./scripts/docker-setup.sh --demo\n```\n\n## Deployment\n\n### Self-Hosted (Docker Compose) — Recommended\n\nRun Llamenos on your own infrastructure. All data stays on your server.\n\n**Local development:**\n\n```bash\n./scripts/docker-setup.sh\n```\n\nRuns at http://localhost:8000 with plain HTTP.\n\n**Production deployment:**\n\n```bash\n./scripts/docker-setup.sh --domain hotline.yourorg.com --email admin@yourorg.com\n```\n\nCaddy auto-provisions TLS certificates via Let's Encrypt. The `--domain` flag activates the production Docker Compose overlay (`docker-compose.production.yml`) which adds TLS termination, log rotation, and resource limits.\n\n**Core services:** app, PostgreSQL, Caddy (reverse proxy), RustFS (S3-compatible blob storage), strfry (Nostr relay), Authentik (authentik-server + authentik-worker, IdP/OIDC).\n\n**Optional profiles:**\n\n```bash\n# Self-hosted transcription (Whisper)\ndocker compose -f deploy/docker/docker-compose.yml -f deploy/docker/docker-compose.production.yml --profile transcription up -d\n\n# Self-hosted Asterisk PBX\ndocker compose -f deploy/docker/docker-compose.yml -f deploy/docker/docker-compose.production.yml --profile asterisk up -d\n\n# Signal messaging bridge\ndocker compose -f deploy/docker/docker-compose.yml -f deploy/docker/docker-compose.production.yml --profile signal up -d\n```\n\nSee the full [self-hosting guide](https://llamenos-hotline.com/docs/self-hosting) and [QUICKSTART.md](docs/QUICKSTART.md) for VPS provisioning, server hardening, and operational runbooks.\n\n### Kubernetes (Helm)\n\n```bash\nhelm install llamenos deploy/helm/llamenos/ \\\n  --set secrets.storageAccessKey=your-access-key \\\n  --set secrets.storageSecretKey=your-secret-key \\\n  --set ingress.hosts[0].host=hotline.yourdomain.com\n```\n\n## Telephony Providers\n\nConfigure your provider in **Admin Settings \u003e Telephony Provider** or during the setup wizard.\n\n| Provider | Type | Voice | SMS | Best For |\n|----------|------|-------|-----|----------|\n| **Twilio** | Cloud | Yes | Yes | Getting started quickly |\n| **SignalWire** | Cloud | Yes | Yes | Cost-conscious orgs |\n| **Vonage** | Cloud | Yes | Yes | International coverage |\n| **Plivo** | Cloud | Yes | Yes | Budget cloud option |\n| **Asterisk** | Self-hosted | Yes | No | Maximum privacy, at-scale |\n\n## Messaging Channels\n\n| Channel | Provider | Setup |\n|---------|----------|-------|\n| **SMS** | Twilio, SignalWire, Vonage, or Plivo | Configure in admin settings; point inbound webhook to `/api/messaging/sms/webhook` |\n| **WhatsApp** | Meta WhatsApp Business Cloud API | Requires Meta Business account; configure webhook at `/api/messaging/whatsapp/webhook` |\n| **Signal** | signal-cli-rest-api bridge | Self-hosted bridge service; configure bridge URL in admin settings |\n\nAll messaging channels flow into a unified **Conversations** view. Enable/disable channels from Admin Settings or the setup wizard.\n\nSee the [setup guides](https://llamenos-hotline.com/docs) for detailed instructions per provider and channel.\n\n## Webhooks\n\nPoint your telephony provider's webhooks to your deployment URL:\n\n| Webhook | URL |\n|---------|-----|\n| Voice (incoming) | `https://your-domain/api/telephony/incoming` |\n| Voice (status) | `https://your-domain/api/telephony/status` |\n| SMS | `https://your-domain/api/messaging/sms/webhook` |\n| WhatsApp | `https://your-domain/api/messaging/whatsapp/webhook` |\n| Signal | Configure bridge to forward to `https://your-domain/api/messaging/signal/webhook` |\n\n## Customization\n\n### Hotline name\n\nSet during the setup wizard, or via `HOTLINE_NAME` environment variable.\n\n### Languages\n\nTranslation files are in `src/client/locales/`. Language config is centralized in `src/shared/languages.ts`.\n\n## Architecture\n\n```\nsrc/\n  client/          # React SPA (Vite + TanStack Router)\n    routes/        # File-based routing (/setup, /conversations, /reports, /help, etc.)\n    components/    # shadcn/ui components\n    locales/       # Translation files (13 locales)\n    lib/           # Auth, crypto, WebRTC, API client\n  server/          # Bun/Hono backend\n    services/      # PostgreSQL-backed business logic services\n    telephony/     # Voice provider adapters (Twilio, SignalWire, Vonage, Plivo, Asterisk)\n    messaging/     # Messaging channel adapters (SMS, WhatsApp, Signal)\n    idp/           # Identity provider adapter interface + Authentik implementation\n    routes/        # API route handlers (includes auth-facade.ts for /api/auth/*)\n    db/            # Drizzle ORM schema + migrations\n    lib/           # Server utilities (auth, crypto, webauthn)\n  shared/          # Code shared between client and server\n    types.ts       # Shared types (roles, conversations, reports, etc.)\n    languages.ts   # Centralized language config\ndeploy/\n  docker/          # Docker Compose deployment (Dockerfile, Caddyfile, .env.example)\n  ansible/         # Ansible deployment for VPS\n  helm/            # Kubernetes Helm chart\nsip-bridge/        # Unified SIP bridge for self-hosted PBX (Asterisk default, FreeSWITCH/Kamailio also supported)\nsite/              # Marketing site (Astro + Tailwind, Cloudflare Pages)\n```\n\n### Security model\n\n- **Self-hosted by design** — all data stays on your infrastructure\n- **Authentication**: JWT + Authentik IdP (OIDC) + multi-factor KEK + WebAuthn passkeys\n- **Local key protection**: PIN-encrypted key store (PBKDF2 600K iterations + XChaCha20-Poly1305); raw nsec never in sessionStorage — in-memory closure only, zeroed on lock\n- **Note encryption**: Per-note forward secrecy — each note encrypted with a unique random key, wrapped via ECIES for each authorized reader\n- **Transcription encryption**: ECIES (ephemeral ECDH + XChaCha20-Poly1305) dual-key\n- **Report encryption**: ECIES encrypted body + encrypted file attachments\n- **Device linking**: Signal-style QR provisioning via ephemeral ECDH key exchange; 5-minute single-use relay rooms\n- **Recovery keys**: 128-bit Base32 recovery keys with mandatory encrypted backup download\n- **Zero-knowledge server**: the server never sees plaintext notes, transcriptions, report content, or per-note encryption keys\n- **Volunteer privacy**: personal info visible only to admins\n\n### Roles\n\n| Role | Can see | Can do |\n|------|---------|--------|\n| Caller | Nothing (GSM/SMS/WhatsApp/Signal) | Call or message the hotline |\n| Volunteer | Own notes, assigned conversations | Answer calls, write notes, respond to messages |\n| Reporter | Own reports only | Submit encrypted reports with file attachments |\n| Admin | All notes, reports, audit logs, conversations | Manage everything |\n\n## Development\n\nRequires [Bun](https://bun.sh/) and [Docker](https://docs.docker.com/get-docker/) for local development.\n\n```bash\nbun install\nbun run dev:docker   # Start backing services (postgres, rustfs, strfry, authentik)\nbun run migrate      # Apply database migrations\nbun run dev          # Vite dev server (frontend)\nbun run dev:server   # Bun watch server (backend, localhost:3000)\nbun run build        # Build frontend\nbun run typecheck    # TypeScript type checking\nbun run test:all     # Run all tests\n```\n\nSee [DEVELOPMENT.md](DEVELOPMENT.md) for the full development guide.\n\n## CI/CD\n\nEvery push to `main` triggers the CI pipeline (`.github/workflows/ci.yml`):\n\n1. **Build \u0026 validate** — typecheck, Vite build, esbuild (Node.js), Astro site build\n2. **Auto-version** — determines `major`/`minor`/`patch` bump from conventional commit messages\n3. **Changelog** — generates via [git-cliff](https://git-cliff.org) from commit history\n4. **Deploy** — parallel deploy to staging\n5. **Release** — creates GitHub Release with changelog notes\n6. **Docker** — the created tag triggers `docker.yml` to build + push images to GHCR\n\n### Versioning\n\nUses [conventional commits](https://www.conventionalcommits.org/) to determine the version bump:\n\n- `feat:` → minor bump (0.x.0)\n- `fix:`, `docs:`, `chore:`, etc. → patch bump (0.0.x)\n- `feat!:` or `BREAKING CHANGE` → major bump (x.0.0)\n\n## License\n\nAGPL-3.0-or-later\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frhonda-rodododo%2Fllamenos-hotline","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frhonda-rodododo%2Fllamenos-hotline","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frhonda-rodododo%2Fllamenos-hotline/lists"}