Hub centralizado de notificações do ecossistema iGRP — email, SMS, WhatsApp, push, in-app e offline, com suporte a templates, envios em massa e recorrência.
O iGRP Notification Service é o microserviço de notificações do iGRP 3.0. Cada aplicação do Access Management envia notificações por um SDK (TypeScript ou Java) ou pela API REST; o serviço trata de canais, templates, retentativas, auditoria e RGPD.
Para ligar uma aplicação, segue a página Envio — SDKs e API. Templates e definições geram-se na Notifications UI, a consola de administração.
Já integrado nos processos
O runtime dos processos BPMN avisa por IN_APP quem tem acesso à etapa seguinte de cada processo — ver Notificações de tarefas.
Canais suportados
| Canal | Provider | Caso de uso típico |
|---|---|---|
EMAIL | SMTP | Recibos, confirmações, convites |
SMS | Agregador HTTP | Alertas urgentes, OTP |
WHATSAPP | Meta Cloud API | Mensagens com templates aprovados |
PUSH | Firebase Cloud Messaging | Aplicações móveis |
IN_APP | Caixa de entrada na base de dados | Sino de notificações na UI web |
OFFLINE | Sem transporte — fica registado para entrega manual | Balcão, carta |
Todos os providers vêm desligados: cada canal só envia depois de configurado — ver Configurar os canais.
Modos de envio
| Modo | Descrição |
|---|---|
| Recipient único | Um destinatário, um ou mais canais |
| Multi-destinatário | Lista de destinatários numa única chamada |
| Bulk | Lista grande ou ficheiro CSV; resposta com batchId |
| Grupos | Grupos internos ou sincronizados com o Access Manager |
| Recorrente | Cron ou intervalo via Temporal Schedules |
Envio de notificações
Antes do primeiro envio, confirma estes quatro pontos. Cada um, se faltar, faz o pedido falhar com um erro diferente:
| # | Requisito | Onde se configura | Se faltar |
|---|---|---|---|
| 1 | Cliente M2M associado à aplicação, com a permissão igrp.notification.send | Access Management (conta de serviço do cliente) | 403, ou 422 ACCESS_MANAGER_UNAVAILABLE se o token não trouxer application_code |
| 2 | Provider do canal ligado no serviço — para EMAIL, o SMTP | Variáveis do Notification Service — Configurar os canais | 422 CHANNEL_NOT_ENABLED |
| 3 | Canal ativo na aplicação | Consola › Definições › Canais permitidos | 422 CHANNEL_NOT_ENABLED |
| 4 | Template publicado no código, canal e locale do envio (ou conteúdo inline) | Consola › Templates | 422 TEMPLATE_ERROR |
EMAIL precisa de SMTP configurado
Sem o provider SMTP configurado no Notification Service (NOTIFICATION_PROVIDERS_EMAILSMTP_*: servidor, porta, credenciais e remetente), nenhum email é enviado: a API recusa o pedido com 422 CHANNEL_NOT_ENABLED. Ver EMAIL (SMTP).
Com os requisitos cumpridos, o envio é um pedido M2M:
curl -X POST "$NOTIFICATION_SERVICE_BASE_URL/api/v1/notifications" \
-H "Authorization: Bearer $TOKEN_M2M" \
-H "Content-Type: application/json" \
-d '{
"channelStrategy": "SPECIFIC",
"channels": ["EMAIL"],
"recipients": [{ "email": "utente@exemplo.cv" }],
"template": { "code": "pedido-confirmacao", "locale": "pt-CV" },
"variables": { "nome": "Maria Silva", "numeroPedido": "PED-2026-0456" },
"businessKey": "PED-2026-0456",
"idempotencyKey": "pedido-confirmacao-PED-2026-0456"
}'A resposta é 202 Accepted, com uma entrega por destinatário e canal. A entrega segue em segundo plano: acompanha o estado (QUEUED → SENT → DELIVERED) em Envios na consola ou em GET /api/v1/notifications/{id}.
| Para… | Ver |
|---|---|
| Enviar a partir de uma app Next.js ou de um serviço Spring Boot | Envio — SDKs e API |
| Os campos do pedido e os erros | API REST › Notificações |
| Os SDKs | TypeScript · Java |
Arquitetura
- A aplicação chama
POST /api/v1/notificationscom um token M2M. O serviço valida o pedido (aplicação, canal ativo, template publicado), grava-o e responde202 Acceptedcom uma entrega por destinatário e canal. - O Temporal entrega em segundo plano, com filas por prioridade e retentativas. Se o Temporal não responder, a entrega é feita na hora, dentro do pedido.
- O provider do canal envia (SMTP, FCM, …). Os recibos de entrega e leitura voltam por
/webhooks/{providerId}e atualizam o estado (SENT→DELIVERED→READ). - IN_APP não sai do serviço: a mensagem fica na inbox do utilizador, lida com o token dele.
O código segue hexagonal + DDD em 13 módulos Maven:
| Módulo | Responsabilidade |
|---|---|
notification-domain | Modelo de domínio (sem Spring) |
notification-application | Casos de uso e portas |
notification-provider-spi | Interface ChannelProvider |
provider-email-smtp | EMAIL por SMTP |
provider-sms-aggregator | SMS |
provider-whatsapp-meta | |
provider-push-fcm | PUSH |
provider-inapp, provider-offline | IN_APP e OFFLINE |
provider-email-sendgrid | Reservado — ainda sem implementação |
notification-app | Executável Spring Boot 3.5 / Java 26 (API + workers) |
client | SDK Java |
notification-bom | Versões |
Um canal novo é um módulo provider-* novo, sem mexer no núcleo.
Configurar os canais
Um envio para um canal sem provider ativo é recusado logo na API com 422 CHANNEL_NOT_ENABLED. O canal tem de estar ligado no serviço (provider) e na aplicação (Definições › Canais permitidos).
EMAIL (SMTP)
Sem SMTP configurado, nenhum email sai. Liga o provider com o servidor de correio do ambiente:
| Propriedade | Variável de ambiente | Notas |
|---|---|---|
notification.providers.email-smtp.enabled | NOTIFICATION_PROVIDERS_EMAILSMTP_ENABLED | true para ativar |
…email-smtp.host | NOTIFICATION_PROVIDERS_EMAILSMTP_HOST | Servidor SMTP |
…email-smtp.port | NOTIFICATION_PROVIDERS_EMAILSMTP_PORT | Por omissão 587 |
…email-smtp.username, …password | NOTIFICATION_PROVIDERS_EMAILSMTP_USERNAME, …_PASSWORD | Se o servidor exigir autenticação |
…email-smtp.starttls | NOTIFICATION_PROVIDERS_EMAILSMTP_STARTTLS | Por omissão true |
…email-smtp.from | NOTIFICATION_PROVIDERS_EMAILSMTP_FROM | Remetente de todos os emails |
O remetente vem do SMTP
O From dos emails é sempre o from do provider SMTP. Os remetentes configurados nas Definições da aplicação ainda não são usados no envio.
Para testes sem enviar emails reais, aponta o SMTP para um servidor de captura (por exemplo Mailpit).
Outros canais
| Canal | Ativar com | Precisa de |
|---|---|---|
IN_APP | INAPP_ENABLED=true | — |
OFFLINE | OFFLINE_ENABLED=true | — |
SMS | notification.providers.sms-aggregator.enabled=true | url, token, from do agregador |
WHATSAPP | WHATSAPP_ENABLED=true | WHATSAPP_PHONE_NUMBER_ID, WHATSAPP_ACCESS_TOKEN, WHATSAPP_APP_SECRET |
PUSH | FCM_ENABLED=true | FCM_CREDENTIALS (conta de serviço Firebase) |
Observabilidade
- OpenAPI em
/v3/api-docs· Swagger UI em/swagger-ui.html - Logs estruturados (ECS JSON em produção —
LOG_STRUCTURED_FORMAT=ecs) - OpenTelemetry: tracing ligado por omissão, exportado para
OTEL_EXPORTER_OTLP_ENDPOINT(desliga comTRACING_ENABLED=false) - GraphQL em
/graphql(desliga a introspection em produção comGRAPHQL_INTROSPECTION=false)
Variáveis de ambiente
O serviço é distribuído como imagem e corre no cluster ou no Docker do workspace, ao lado dos outros serviços da plataforma. Configura-se por variáveis de ambiente.
Autenticação e Access Management
| Variável | Descrição |
|---|---|
AUTH_JWT_ISSUER | Obrigatória. Issuer do Access Management; o serviço valida os tokens com ele |
NOTIFICATION_ACCESSMANAGEMENT_ENABLED | true para verificar se o utilizador tem acesso à aplicação de cada pedido (necessário para a consola e para tokens de utilizador) |
NOTIFICATION_ACCESSMANAGEMENT_BASEURL | Base do Access Management |
NOTIFICATION_ACCESSMANAGEMENT_CLIENTID, …_CLIENTSECRET | Cliente M2M do serviço no Access Management |
No arranque o serviço regista no Access Management as suas permissões (igrp.notification.*).
Base de dados, Temporal e anexos
| Variável | Descrição |
|---|---|
SPRING_DATASOURCE_URL, …_USERNAME, …_PASSWORD | PostgreSQL (o esquema é criado pelo Flyway) |
TEMPORAL_ENABLED | true por omissão; false entrega de forma síncrona, sem Temporal |
TEMPORAL_TARGET, TEMPORAL_NAMESPACE | Servidor Temporal (host:7233) e namespace |
STORAGE_ENDPOINT, STORAGE_BUCKET, STORAGE_REGION | Armazenamento S3 dos anexos (MinIO: endpoint próprio) |
STORAGE_ACCESS_KEY, STORAGE_SECRET_KEY | Credenciais S3 |
STORAGE_PATH_STYLE, STORAGE_SSE | true/false para MinIO (path-style ligado, encriptação SSE desligada) |
STORAGE_ALLOWED_MIME_TYPES | Tipos de anexo aceites |
Canais e templates
| Variável | Descrição |
|---|---|
NOTIFICATION_PROVIDERS_EMAILSMTP_*, INAPP_ENABLED, … | Providers — ver Configurar os canais |
NOTIFICATION_SEED_DEFAULT_TEMPLATES | false para não publicar os templates de convite no arranque |
Observabilidade
| Variável | Descrição |
|---|---|
TRACING_ENABLED, TRACING_SAMPLING_PROBABILITY, OTEL_EXPORTER_OTLP_ENDPOINT | Tracing OpenTelemetry |
LOG_STRUCTURED_FORMAT | Formato dos logs (ecs por omissão) |
GRAPHQL_INTROSPECTION | false em produção |
Última atualização:
