Skip to content

About

No description, website, or topics provided.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Repository files navigation

BYO-SIM SMS Gateway

Send application SMS and one-time passcodes through an Android phone and SIM that you control.

TypeScript React Expo Android Convex Vite

Overview

BYO-SIM SMS Gateway turns an Android device into an account-owned SMS gateway. A web dashboard manages devices, SIM routing, API keys, messages, OTP requests, and reliability data. Convex is the authoritative backend, while the Android app claims queued work and hands messages to the selected SIM through a Kotlin SmsManager bridge.

The project is designed for transactional messages sent with the account owner's own device, carrier plan, and recipient consent. It does not provide anonymous sending, sender spoofing, bulk campaigns, contact-list blasting, or carrier infrastructure.

Features

  • Password authentication with email verification, recovery, rate limits, and authenticated dashboard access.
  • Single-use, expiring pairing codes that bind an Android gateway to one account.
  • Android SMS permissions, SIM discovery, enable/disable controls, manual number fallback, and default-SIM selection.
  • Hashed, revocable API keys for sending SMS and OTP requests from server-side integrations.
  • An atomic queued → claimed → sending → sent/failed message lifecycle with device-scoped claims.
  • Message history, status details, failure reasons, device health, and reliability drill-downs.
  • Android foreground-service, boot recovery, heartbeat, diagnostics, and telemetry support.
  • OTP expiry, attempt limits, resend controls, and phone-number throttling.

Tech Stack

Area Technology Responsibility
Admin application React 18, Vite 6, Tailwind CSS 4 Authentication, gateway management, messaging, API help, and reliability UI
Backend Convex, Convex Auth HTTP APIs, authorization, validation, durable state, rate limits, and scheduled cleanup
Gateway application Expo 51, React Native 0.74 Pairing, readiness, SIM settings, and gateway lifecycle UI
Native Android bridge Kotlin, Android SmsManager Permissions, subscriptions, SMS callbacks, foreground service, boot handling, and secure credentials
Language and tooling TypeScript, Node.js, npm Shared application code, scripts, builds, and tests
Testing Node test runner, Vitest, convex-test, Android/JUnit Backend, web, gateway, acceptance, and native regression coverage

Architecture

flowchart LR
    Integration["Developer application"] -->|"API key: SMS or OTP"| Backend["Convex HTTP API and domain modules"]
    Dashboard["Vite admin dashboard"] -->|"Authenticated management requests"| Backend
    Backend -->|"Read and write"| Data[("Convex data")]
    Backend -->|"Queued jobs"| Gateway["Android gateway app"]
    Gateway -->|"Pairing, claims, heartbeat, status, telemetry"| Backend
    Gateway --> Native["Kotlin gateway module"]
    Native -->|"SmsManager"| Carrier["User SIM and mobile carrier"]
Loading

Convex owns identity, account and device ownership, message state, OTP state, and rate limits. The Android app is a device-scoped executor: it keeps local configuration and transient send state, but it is not the source of truth for authorization or delivery status. Polling and authoritative rereads let the gateway recover after connectivity or process interruptions.

See the architecture index, system overview, and architecture decisions for the detailed model.

Getting Started

Prerequisites

  • Node.js and npm. The repository does not currently declare a minimum Node.js version.
  • A Convex project for connected authentication, API, and persistence.
  • Android Studio and the Android SDK for native gateway development.
  • An Android device with SMS capability, an active SIM/carrier plan, and the required Android permissions.

Install dependencies

This repository uses separate npm lockfiles for the root, web app, and gateway app:

npm install
npm --prefix apps/web install
npm --prefix apps/gateway install

Configure the applications

Copy the tracked environment templates:

cp apps/web/.env.example apps/web/.env.local
cp apps/gateway/.env.example apps/gateway/.env.local

Configure the public application endpoints without committing their values:

# apps/web/.env.local
VITE_CONVEX_URL=
VITE_GATEWAY_API_URL=

# apps/gateway/.env.local
EXPO_PUBLIC_CONVEX_SITE_URL=

VITE_CONVEX_URL connects the browser to Convex. VITE_GATEWAY_API_URL and EXPO_PUBLIC_CONVEX_SITE_URL point to the deployed Convex HTTP origin. Production web endpoints must use HTTPS.

The Convex deployment also needs its authentication, email, allowed web origin, and rate-limit secrets configured in the provider environment. Before enabling production, prepare and review operational procedures for identity migration, account recovery, browser sessions, and CSP enforcement.

Run locally

Start Convex development from the repository root:

npm run convex:dev

In another terminal, start the admin application:

npm run dev

Run the native Android gateway from a configured Android development environment:

npm --prefix apps/gateway run android

For UI-only development, the web app has an explicit offline-auth mode. Add VITE_ENABLE_OFFLINE_AUTH=true only to a local Vite development environment; it is intentionally blocked from production use.

Usage

  1. Register or sign in through the web dashboard.
  2. Create a pairing code under Devices.
  3. Enter that code in the Android gateway app, grant the requested permissions, and configure the available SIMs.
  4. Start the gateway service and wait for the dashboard to report the device as ready.
  5. Create an API key and store the one-time secret in your server-side secret manager.
  6. Send a message from a trusted server-side integration:
export BYO_GATEWAY_URL="https://your-convex-http-origin.example"
export BYO_SMS_API_KEY="replace-with-your-api-key"
export BYO_RECIPIENT="+1xxxxxxxxxx"

curl --fail-with-body -X POST "$BYO_GATEWAY_URL/v1/messages/send" \
  -H "Authorization: Bearer $BYO_SMS_API_KEY" \
  -H "Content-Type: application/json" \
  --data '{"to":"'"$BYO_RECIPIENT"'","message":"Hello from your app"}'

A successful request returns a message ID and queued status. Use GET /v1/messages/{messageId} or the dashboard to follow the result. A sent status means Android handed the SMS to the carrier; it does not prove handset delivery.

Public API

Method Path Purpose
POST /v1/messages/send Queue an SMS using an API key
GET /v1/messages/{messageId} Read an owned message's status
POST /v1/otp/send Create and send a one-time passcode
POST /v1/otp/verify Verify a one-time passcode

The authenticated dashboard and device gateway use separate /dashboard/* and /gateway/* contracts. The web application's API Docs screen documents request bodies, responses, and error codes for the public API.

Project Structure

apps/
├── web/                         # Vite admin dashboard
└── gateway/                     # Expo/React Native Android gateway
    └── modules/gateway-native/  # Kotlin SMS and lifecycle bridge
convex/                          # Backend schema, functions, HTTP routes, and tests
docs/                            # Architecture, ADRs, security runbooks, and receipts
packages/
├── contracts/                   # Reserved shared transport-contract boundary
└── domain/                      # Reserved shared domain boundary
scripts/                         # Repository verification utilities
tests/acceptance/                # Cross-surface reliability acceptance checks

The root package coordinates the independently locked applications through npm --prefix commands; it is not declared as an npm workspace.

Testing and Verification

Run the TypeScript test suites:

npm test

Run the production web build and gateway typecheck:

npm run build

Additional backend and native checks:

npx tsc --noEmit -p convex/tsconfig.json
apps/gateway/android/gradlew -p apps/gateway/android :gateway-native:testDebugUnitTest

Dependency and lockfile checks are also available:

npm run audit:production
npm run audit:complete
npm run verify:lockfiles

Some acceptance tests target an explicitly enabled synthetic endpoint. They fail closed unless the required opt-in configuration is present; see the NEXT-01 validation receipt before running them against a deployment.

Deployment

The system has three independent release surfaces:

  • Convex backend: deploy the schema, functions, HTTP actions, crons, and provider-managed secrets.
  • Web dashboard: build apps/web with its public Convex and HTTP endpoints, then serve the generated static assets with the documented CSP and response headers.
  • Android gateway: produce and sign a native Android build with the Convex HTTP origin configured. Distribution is a release decision; the repository does not claim a public app-store release.

There is no root one-command production deployment configuration. Review the deployment data flow and security and operations guidance before promoting any surface.

Security and Responsible Use

  • Account identity comes from the authenticated Convex context rather than caller-supplied user IDs.
  • Pairing codes expire and are consumed once; API keys, OTP codes, and device tokens are stored as hashes.
  • Ownership checks isolate account and device data, while claimant-only transitions protect message state.
  • HTTPS validation, bounded payloads, rate limits, redacted logs, and production CSP controls reduce abuse and data exposure.
  • Device credentials are kept in Android secure storage; API keys belong only in trusted server-side integrations.

You are responsible for device ownership, SIM costs or load, recipient consent, applicable law, carrier terms, and local Android/OEM background-service behavior. Never use the project for unsolicited or deceptive messaging.

Documentation

License

The project is available under the MIT License. Third-party dependencies and vendored tooling remain subject to their respective licenses.

About

No description, website, or topics provided.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages