SMPP Stack
The stack splits into two layers.
- The transport layer: (Bun/Elysia API),
services/rabbitmq(broker), andservices/smpp(Rust SMPP transceiver) accepts message requests over HTTP, persists them, and submits them to the SMSC, tracking every status transition back to the database. - The product layer ingests Huawei network alarms from an IMAP mailbox, resolves who is on call from an escalation ladder synced out of Microsoft Entra, and pages them by SMS (through the transport layer) and email.
Message Flow
▲
The "status update" half of the return path is
performed by the server app after it decodes the protobuf
message.
Session Lifecycle
▲ health.smpp_bound
is set true immediately after a successful bind and false on
ConnectionLost.
The Idle state deliberately leaves it true, so an
idle-unbound service still reports healthy.
SMPP Transceiver Service
▲
Rust ESME for the stack. It binds to the carrier SMSC as an SMPP
transceiver, consumes protobuf-encoded work items from RabbitMQ,
submits them as submit_sm, and publishes every status
transition plus every inbound deliver_sm back onto the exchange.
Here the server app persists it to Postgres and fans it out over WebSocket.
The transceiver service does not hold a database connection; it is a pure
protocol bridge between AMQP and the SMSC with an optional pre-send number-type
lookup and an HTTP readiness probe.
SMPP Server App
▲HTTP/API front door for SMPP messaging in the stack. A Bun + Elysia application that accepts message requests over HTTP, validates and persists them to Postgres, publishes work batches to RabbitMQ, hands protobuf-encoded messages to the Rust smpp transceiver for submission to the SMSC, consumes status updates coming back from that transceiver, maintains a full status history per message, and exposes monitoring, message-template CRUD, WebSocket fan-out, authentication (better-auth) and an OpenAPI document.
Outbound path
Inbound / status path
Paging App
▲
Product-level integration of the netops-paging stack. This Bun +
Elysia app ingests network alarms from a Huawei alarm mailbox
over IMAP, normalizes them into the paging Postgres database,
resolves who is currently on call from Microsoft Entra group
membership, and pages that person by SMS (through the RabbitMQ
-> apps/server -> services/smpp chain) and/or email (direct
SMTP). Inbound "ACK" replies flow back through the same broker
and clear the alarms.
Alarm ingestion, on-call resolution, and dispatch are three
separate stages that communicate only through Postgres. The active_alarms
view is the boundary: the mail side writes alarm_instance rows, the paging side reads the view (which has already resolved
the next escalation level and its contact addresses) and emits messages.