Inspiration

Disasters always happen soon everywhere, people cannot wait for connectivity to return, the suppy was disconnected. The only way to help people is to respond to their SOS messages ASAP to the closest responders. The emergency response is a race against time. there is no time to wait for connectivity to return.

So the Safety Alarm is an offline-first disaster response that keeps SOS messages moving, prioritizes life-threatening cases, and coordinates rescue work until connectivity returns.

What it does

Safety Alarm is an offline-first disaster help and rescue coordination system. A resident creates a one-tap SOS; sensitive details are sealed, and every operation is signed on the originating device. Requests can move through a mesh/store-and-forward transport abstraction, reach a local rescue node, become volunteer tasks, and synchronize through a cursor-based operation log when connectivity returns. A

The current delivery also includes a rescue management center at /admin. It shows a live priority queue, danger and vulnerability reasons, status counts, and rescue tasks. Coordinators can acknowledge a request and create a rescue task. The priority engine keeps the waiting bonus through acknowledged and stops it only at tasked, so a button press cannot make an undispatched case fall in the queue.

For life-threatening conditions, we have the six bounded danger signal metrics that apply a conservative hard floor of 120 points. The score helps coordinate response; it is not a replacement for clinical triage.

How we built it

We built a strict TypeScript monorepo with one pure core shared by device and server code:

  • packages/core contains schemas, state machines, priority rules, HLC/oplog sync, conflict resolution, signatures, and sealed-box primitives with no I/O.
  • apps/mobile is an Expo/React Native client with an offline SQLite oplog and transport adapters for HTTP, mock mesh, and a Phase 2 BLE boundary.
  • apps/server is Fastify with better-sqlite3. The oplog is the source of truth; request and task tables are materialized views rebuilt by core replay.
  • The management UI is served by the same Fastify node. Its write actions do not update database rows directly. The server identity creates Ed25519-signed operations, then sends them through the same verification, ingest, and replay pipeline as every other node.

The real time clocks are used to sort operations in the oplog. The oplog is a list of operations that have been applied to the state machine. The operations are sorted by the clock value. The clock value is a 64-bit integer that is incremented for each operation. The clock value is used to determine the order of operations.

Challenges we ran into

The hardest problem was not drawing the screens. It was protecting system truth under delay, duplication, disconnection, and conflict, consistency, and concurrency.

First, we found gray boundaries in a purely additive priority score. A routine case with multiple tags could outrank a life-threatening symptom, while acknowledging an old case could remove 30 waiting points before anyone was dispatched. We corrected this with a bounded danger gate and a waiting window tied to operational task creation.

Second, every convenient server shortcut was dangerous. A direct database update or server-signed volunteer claim would bypass provenance and become indistinguishable downstream. We kept claims self-signed by volunteers and made management actions server-originated, signed oplog events that still pass verification and the core state machine.

Third, privacy and usability pull in opposite directions during emergencies. We kept the management overview useful without silently decrypting notes or precise locations. Authorized PII unsealing and audit trails remain a separate, explicit design step.

Fourth, the connection node was not enough. We needed a mesh/store-and-forward transport abstraction to keep SOS messages moving until connectivity returns. We also needed a local rescue node to coordinate rescue work. We also needed a cursor-based operation log to synchronize rescue work when connectivity returns.

Accomplishments that we're proud of

  • An end-to-end offline-first architecture from SOS to store-and-forward, rescue task, and reconnect sync.
  • Deterministic convergence guarded by property-based tests.
  • Signature rejection at every ingest boundary, including management-originated operations.
  • A six-signal danger metric with a 120-point floor and explainable UI reasons.
  • Waiting priority that survives acknowledgement and stops only at real dispatch.

What we learned

Offline-first is not a caching feature; it changes the authority model. Once multiple devices can act independently, every state change consistency and convergence become operational concerns. We also learned that explainability is an operational feature. A coordinator needs to see not only that a request scored 120, but whether that came from respiratory distress, long waiting time, or vulnerability. Clear reasons make it easier to challenge, correct, and safely use the ranking.

Finally, we learned to separate administrative progress from real-world progress. “Acknowledged” is useful coordination metadata. “Tasked” is the point where the system can honestly say that rescue handling has begun.

What's next for Safety Alarm

The next milestone is real multi-device BLE transport on Android through an Expo development client and native foreground service, followed by three-device TTL, relay, and deduplication tests, also used by raspberry pi devices.

For rescue organizations, we will add organization keys, role-based access, audited PII unsealing, map views, token rotation, and deployment behind TLS. We also plan resumable media upload, push notifications, de-identified heat maps, and cross-organization oplog exchange without creating a second data path.

In the end, there's the boundry about the charity case. We need to decide if we want to keep the project open source and how to handle the charity case.

Built With

  • ed25519
  • expo.io
  • fast-check
  • fastify
  • hybrid
  • logical
  • mesh
  • nacl
  • native
  • networking
  • offline-first
  • operation
  • react
  • sqlite
  • vitest
  • x25519
  • zod
Share this project:

Updates