Rune Courier¶
Servico de chat em tempo real para a plataforma HAUS — conversas user-to-user com isolamento multi-tenant e multi-aplicacao.
Visao Geral¶
O Rune Courier e o servico centralizado de chat da plataforma HAUS. Cada aplicacao (Hotel, Chronicle, Chronos) utiliza o mesmo servico com isolamento duplo: por aplicacao e por tenant.
Funcionalidades Principais¶
| Modulo | Descricao |
|---|---|
| Conversas | Diretas (1:1) e em grupo com participantes |
| Mensagens | Texto, imagem, arquivo e sistema com cursor pagination |
| WebSocket | Atualizacoes em tempo real (mensagens, typing, presenca) |
| Presenca | Status online/offline por tenant via Redis |
| Typing | Indicador de digitacao com TTL de 5 segundos |
| Read Receipts | Marcacao de leitura e contagem de nao-lidos |
| Multi-tenant | Isolamento duplo (application_id, tenant_id) |
Stack¶
| Camada | Tecnologia |
|---|---|
| Backend | Quarkus 3.17 + Java 21 + PostgreSQL 16 |
| Real-time | Quarkus WebSockets Next |
| Cache | Redis 7 (presenca, typing, unread) |
| Auth | JWT via OATH + BaseAuthFilter (SDK) |
| Permissoes | Guild (roles PARLEY_ADMIN, PARLEY_USER) |
| SDK | ChatClientService no haus-quarkus-sdk |
Multi-Tenancy¶
Isolamento duplo via (application_id, tenant_id):
graph TB
subgraph "application_id = HOTEL-BACKEND"
H1["tenant_id = hotel-A<br/>Staff + Hospedes"]
H2["tenant_id = hotel-B<br/>Staff + Hospedes"]
end
subgraph "application_id = CHRONICLE"
C1["tenant_id = org-X<br/>Membros"]
C2["tenant_id = org-Y<br/>Membros"]
end
subgraph "application_id = CHRONOS"
T1["tenant_id = clinica-1<br/>Profissionais + Clientes"]
end
Como funciona¶
- Frontend envia JWT + headers
X-Application-IdeX-Tenant-Id AuthFiltervalida token via OATH introspectionParleyContextextrai(applicationId, tenantId, userId)do request- Toda query no banco inclui
WHERE application_id = ? AND tenant_id = ? - WebSocket recebe
appetenantcomo query params na conexao
Uso por projeto¶
| Projeto | application_id | tenant_id | Quem conversa |
|---|---|---|---|
| Hotel | HOTEL-BACKEND |
hotel_id |
Staff interno + hospede-recepcao |
| Chronicle | CHRONICLE |
organization_id |
Membros da organizacao |
| Chronos | CHRONOS |
tenant_id |
Profissionais + clientes |
Tipos de Conversa¶
DIRECT (1:1)¶
Conversa entre dois usuarios. O sistema previne duplicatas — se ja existe uma conversa direta entre os dois usuarios no mesmo tenant, ela e reutilizada.
GROUP¶
Conversa com multiplos participantes. Possui nome e o criador recebe role ADMIN.
Canais no Hotel¶
No Hotel, as conversas sao separadas por canal via metadata JSONB:
INTERNAL— Apenas staff (HOTEL_ADMIN, HOTEL_GERENTE). Chat entre funcionarios.SUPPORT— Hospede conversa com recepcao/staff. Canal de atendimento.
Tipos de Mensagem¶
| Tipo | Descricao |
|---|---|
TEXT |
Mensagem de texto |
IMAGE |
Imagem (URL do Vault) |
FILE |
Arquivo (URL do Vault) |
SYSTEM |
Notificacao automatica do sistema |
WebSocket¶
Conexao em tempo real para receber eventos:
Eventos Server → Client¶
| Evento | Descricao |
|---|---|
MESSAGE_RECEIVED |
Nova mensagem |
MESSAGE_UPDATED |
Mensagem editada |
MESSAGE_DELETED |
Mensagem removida |
TYPING_START |
Usuario comecou a digitar |
TYPING_STOP |
Usuario parou de digitar |
READ_RECEIPT |
Conversa marcada como lida |
PRESENCE_CHANGED |
Status online/offline |
CONVERSATION_CREATED |
Nova conversa criada |
Eventos Client → Server¶
{ "type": "TYPING", "conversationId": "uuid" }
{ "type": "TYPING_STOP", "conversationId": "uuid" }
{ "type": "MARK_READ", "conversationId": "uuid", "messageId": "uuid" }
SDK — ChatClientService¶
O haus-quarkus-sdk inclui o ChatClientService para integracao server-to-server:
@Inject ChatClientService chatClient;
// Enviar mensagem de sistema
chatClient.sendSystemMessage(tenantId, conversationId, "Reserva confirmada!");
// Criar conversa direta
chatClient.findOrCreateDirect(tenantId, userId, email, name);
// Criar grupo
chatClient.createGroup(tenantId, "Equipe Recepcao", participants);
Configuracao (application.properties)¶
quarkus.rest-client.chat-api.url=http://parley:8080
haus.chat.enabled=true
haus.chat.application-id=hotel-backend
haus.chat.auth.email=hotel-backend
haus.chat.auth.password=HOTEL-BACKEND987!@#
Integracoes¶
| Servico | Uso |
|---|---|
| OATH | Autenticacao JWT + introspection |
| Guild | Registro de roles e permissoes no startup |
| Herald | Notificacoes offline (quando usuario sem WebSocket ativo) |
| Scrolls | Audit log de eventos (criacao de conversa, delete de msg) |
| Vault | Anexos — frontend faz upload para Vault, URL vai no metadata da mensagem |