The path of an incoming message
Tenancy
Tenant context is a runtime coordinate, not an option.- Tenant context is mandatory; runtime code fails fast without it
- There is one runtime model, with no deployment mode to branch on
- Context switching is encapsulated by the Tenancy domain
- User data lives in tenant schemas
Flow engine
- A flow is stored as a JSON graph
- The execution loop is deterministic
- Handlers resolve by
(type, version) - Registries are built at boot, with no database lookup on the hot path
sourceHandle, and the engine resolves
the next node from the flow’s edges. See
Handler contract.
Concurrency
Incoming message processing has three protection layers, and they guard different failures:
A lock that cannot be acquired produces a busy notice, not a dropped message —
the job goes to a backoff queue.
Webhook routing
The URL is/webhook/{channel}/{public_hash}, and public_hash resolves through
Redis.
Inbound messages are handed to IncomingMessageJob and resolved through the
tenant-aware routing pipeline.