fix(gsm): secure and harden SMS delivery - #362
Merged
Merged
Conversation
Adamskiee
marked this pull request as ready for review
August 14, 2026 09:10
This was referenced Aug 15, 2026
Adamskiee
added a commit
that referenced
this pull request
Aug 16, 2026
…rict environment config This release merges the latest changes from `develop` into `main`, bringing in significant enhancements and bug fixes across the server, GSM module, and mobile components. Key Changes: GSM & Networking: - GSM Emulator: Added a new virtual modem development stack for testing without physical hardware (#373). - GSM Security & Routing: Secured SMS delivery (#362), required verified phone numbers for outgoing SMS (#375), and routed gateway traffic correctly on the Docker network (#372). Server & Environment: - Typed Configuration: Introduced strict typed environment configuration (#363), failing fast when GSM_SECRET is unset (#361), and replacing example secrets in configs (#366). - API & Data Integrity: Hardened error handling logs, made role writes atomic (#377), ignored activity writes for deleted users (#374), and hardened QA route guards (#367). Mobile: - Connectivity: Refactored connectivity to remove the background signaling task (#364). - EAS Debugging: Enabled the debug menu in preview builds (#360).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Hardens the complete SMS delivery path across the GSM gateway, main server, and mobile app.
QUEUE_FULL.GSM_SECRETin the GSM service and validatesX-GSM-SecretbeforePOST /sms/sendcan create a log row or occupy the modem.X-GSM-Secretfrom the main server for every direct gateway send.pendinglog rows at startup asfailed/SERVICE_CRASHEDbefore the serial worker starts.NO_ACCOUNT,BANNED_SENDER, orUNVERIFIED_SENDER.Why
The GSM modem is a physical serial bottleneck that takes seconds to process each message. Unbounded or unauthenticated access can occupy the only outbound disaster-response channel and cause a denial of service.
Power loss can also leave
sms_logrows permanently pending. Startup marks those rows failed instead of replaying them because the modem may already have transmitted the SMS before the crash, and replay could duplicate emergency messages.Behavior
Gateway admission
SMS_SEND_QUEUE_MAXSIZEaccepts values from 1 through 20 and defaults to 10 waiting requests.QUEUE_FULL.SERVICE_STOPPING.Service authentication
Both HTTP directions use the same shared secret:
POST /sms/sendwithX-GSM-SecretPOST /gsm/inboundwithX-GSM-SecretBoth services fail startup when their required secret is missing. Port 8001 remains restricted to host loopback or the trusted Compose network as an additional boundary.
Crash recovery and observability
Before constructing
SerialWorker, gateway startup changes every orphanedpendingrow to:Inbound sender eligibility failures are retained as rejected audit records rather than appearing as successfully received traffic.
Validation
.expo/types/router.d.tsgit diff --check: passedThe full server suite still depends on correctly isolated Redis, WebSocket lifespan, and database test services. The GSM-focused server tests pass.
Deployment notes
Set the same strong
GSM_SECRETin the main server and GSM gateway environment files before restarting either service. Existing installed systemd units and restricted files under/etc/sapot/still require the normal operator deployment procedure.Do not automatically replay
SERVICE_CRASHEDmessages. Operators should inspect them before deciding whether a manual resend is safe.Additional QA coverage
verified-phonetesting scenario, which seedsqa_phone_verifiedwith a valid Philippine phone number and aPhoneVerifiedrecord.qa_phone_verifiedto the testing login-fixture allowlist for phone-verification-gated flows./testing/login-as/qa_phone_verified.Focused verification:
./venv/bin/pytest tests/test_qa_scenarios.py tests/test_testing_endpoints.py(28 passed).A full server-suite run remains unavailable in this environment because the configured
redisanddbDocker hostnames cannot be resolved.