@seedgrid/ai-toolkit 0.3.2 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/adapters/shared.js +1 -0
- package/docs/formato.md +1 -1
- package/package.json +1 -1
- package/seedgridKB/SeedGrid/Extensions/Catalogo-de-propriedades.md +3 -2
- package/seedgridKB/SeedGrid/Extensions/Indice.md +1 -0
- package/seedgridKB/SeedGrid/Extensions/ai-pricing/Configuracao.md +11 -18
- package/seedgridKB/SeedGrid/Extensions/ai-pricing/Exemplos.md +2 -2
- package/seedgridKB/SeedGrid/Extensions/ai-pricing/Visao-geral.md +2 -2
- package/seedgridKB/SeedGrid/Extensions/business-days/Configuracao.md +36 -0
- package/seedgridKB/SeedGrid/Extensions/business-days/Exemplos.md +37 -0
- package/seedgridKB/SeedGrid/Extensions/business-days/Visao-geral.md +48 -0
- package/seedgridKB/SeedGrid/Extensions/exchange/Configuracao.md +10 -16
- package/seedgridKB/SeedGrid/Extensions/exchange/Exemplos.md +2 -2
- package/seedgridKB/SeedGrid/Extensions/exchange/Visao-geral.md +2 -2
- package/seedgridKB/SeedGrid/Extensions/login-tenancy/Configuracao.md +4 -5
- package/seedgridKB/SeedGrid/Extensions/login-tenancy/Visao-geral.md +1 -1
- package/seedgridKB/SeedGrid/Extensions/subdomain-tenancy/Configuracao.md +3 -2
- package/seedgridKB/SeedGrid/Extensions/subdomain-tenancy/Visao-geral.md +2 -2
- package/seedgridKB/SeedGrid/Mapa-dos-repositorios.md +9 -0
- package/seedgridKB/SeedGrid/Produtos/Pulse/Autenticacao-e-chaves.md +89 -0
- package/seedgridKB/SeedGrid/Produtos/Pulse/Exemplos.md +44 -0
- package/seedgridKB/SeedGrid/Produtos/Pulse/Protocolo-e-API.md +191 -0
- package/seedgridKB/SeedGrid/Produtos/Pulse/SDKs.md +287 -0
- package/seedgridKB/SeedGrid/Produtos/Pulse/Servidor/Configuracao.md +128 -0
- package/seedgridKB/SeedGrid/Produtos/Pulse/Servidor/Instalacao.md +105 -0
- package/seedgridKB/SeedGrid/Produtos/Pulse/Servidor/Operacao.md +86 -0
- package/seedgridKB/SeedGrid/Produtos/Pulse/Servidor/Providers.md +121 -0
- package/seedgridKB/SeedGrid/Produtos/Pulse/UI/Configuracao.md +61 -0
- package/seedgridKB/SeedGrid/Produtos/Pulse/UI/Visao-geral.md +74 -0
- package/seedgridKB/SeedGrid/Produtos/Pulse/Visao-geral.md +96 -0
- package/seedgridKB/SeedGrid/Toolkit/agents/backend-java.md +1 -1
- package/seedgridKB/SeedGrid/Toolkit/agents/backend-rust.md +1 -1
- package/seedgridKB/SeedGrid/Toolkit/agents/qa.md +1 -1
- package/seedgridKB/SeedGrid/Toolkit/rules/backend-java-seedgrid.md +38 -26
- package/seedgridKB/SeedGrid/Toolkit/rules/backend-seedgrid.md +45 -0
- package/seedgridKB/SeedGrid/Toolkit/skills/sg-code-review/SKILL.md +1 -1
- package/seedgridKB/SeedGrid/Toolkit/skills/sg-crud-back/SKILL.md +4 -4
- package/seedgridKB/SeedGrid/Toolkit/skills/sg-crud-front/SKILL.md +3 -3
- package/seedgridKB/SeedGrid/Toolkit/skills/sg-new-screen/SKILL.md +2 -2
- package/seedgridKB/SeedGrid/Toolkit/skills/sg-new-skill/SKILL.md +20 -5
- package/seedgridKB/SeedGrid/Toolkit/skills/sg-review/SKILL.md +3 -3
- package/seedgridKB/SeedGrid/Visao-geral.md +7 -0
- package/seedgridKB/manifest.json +8 -7
- /package/seedgridKB/SeedGrid/Toolkit/skills/sg-code-review/references/{checklist.md → code-review-checklist.md} +0 -0
- /package/seedgridKB/SeedGrid/Toolkit/skills/sg-crud-front/references/{checklist.md → crud-front-checklist.md} +0 -0
- /package/seedgridKB/SeedGrid/Toolkit/skills/sg-crud-front/references/{patterns.md → crud-front-patterns.md} +0 -0
- /package/seedgridKB/SeedGrid/Toolkit/skills/sg-crud-front/references/{routing.md → crud-front-routing.md} +0 -0
- /package/seedgridKB/SeedGrid/Toolkit/skills/sg-new-screen/references/{checklist.md → new-screen-checklist.md} +0 -0
- /package/seedgridKB/SeedGrid/Toolkit/skills/sg-new-screen/references/{steps.md → new-screen-steps.md} +0 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
---
|
|
2
|
+
tags: [seedgrid, produto, pulse, servidor, configuracao, variaveis]
|
|
3
|
+
fonte: seedgrid-products/seedgrid-pulse/backend (src/config.rs, env.md)
|
|
4
|
+
branch: main
|
|
5
|
+
commit: 9dcbdad
|
|
6
|
+
analisado-em: 2026-10-16
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Pulse (servidor) — variáveis de ambiente
|
|
10
|
+
|
|
11
|
+
Todas as variáveis do **servidor**. As da UI estão em [[SeedGrid/Produtos/Pulse/UI/Configuracao|Configuração da UI]]. Arquitetura atual: **login-tenancy, banco único** — a separação entre clientes é lógica, por `company_id`. Sem `POSTGRES_URL` o servidor sobe em modo memória/dev com a plataforma desabilitada.
|
|
12
|
+
|
|
13
|
+
Convenção: 🔒 = segredo (nunca em repositório/log); valores de exemplo são placeholders, **não** padrões.
|
|
14
|
+
|
|
15
|
+
## Runtime (HTTP, WebSocket, CORS)
|
|
16
|
+
|
|
17
|
+
| Variável | Padrão | Descrição |
|
|
18
|
+
|---|---|---|
|
|
19
|
+
| `HTTP_HOST` | `127.0.0.1` | IP de bind. Em container use `0.0.0.0`. |
|
|
20
|
+
| `HTTP_PORT` | `8080` | Porta HTTP. |
|
|
21
|
+
| `WS_PATH` | `/ws` | Path do WebSocket legado (o endpoint do protocolo é `/api/v1/connect`). |
|
|
22
|
+
| `CORS_ALLOWED_ORIGINS` | vazio | Lista separada por vírgula. Vazio = nenhuma origem liberada. |
|
|
23
|
+
| `WS_HEARTBEAT_INTERVAL_SECONDS` | `30` | Heartbeat do WebSocket. |
|
|
24
|
+
| `WS_IDLE_TIMEOUT_SECONDS` | `90` | Fecha conexão ociosa. |
|
|
25
|
+
|
|
26
|
+
## Credenciais do Pulse 🔒
|
|
27
|
+
|
|
28
|
+
| Variável | Padrão | Descrição |
|
|
29
|
+
|---|---|---|
|
|
30
|
+
| `SEEDGRID_PULSE_SERVER_KEY` | — | Chave **administrativa** (contas/chaves, métricas) em `x-api-key`. **Não publica** (403). Só em ENV; fica só com a operação do Pulse. |
|
|
31
|
+
| `SEEDGRID_PULSE_CONNECT_TOKEN_SECRET` | — | Segredo HMAC-SHA256 que assina o token curto de conexão. Sem ele, `POST /api/v1/connect-tokens` responde 503. |
|
|
32
|
+
| `SEEDGRID_PULSE_CONNECT_TOKEN_PREVIOUS_SECRET` | — | Segredo anterior, aceito só na verificação (rotação sem derrubar tokens válidos). |
|
|
33
|
+
| `SEEDGRID_PULSE_CONNECT_TOKEN_TTL_SECS` | `300` | Validade do token quando o pedido não informa `ttlSeconds`. É a janela para **conectar**. |
|
|
34
|
+
| `SEEDGRID_PULSE_CONNECT_TOKEN_MAX_TTL_SECS` | `900` | Teto: pedido acima → 422. |
|
|
35
|
+
| `SEEDGRID_PULSE_CONNECT_TOKEN_RATE_PER_KEY` | `600` | Emissões/min por chave `project`; `0` desliga. Por instância. |
|
|
36
|
+
| `SEEDGRID_PULSE_CONNECT_TOKEN_RATE_PER_SUBJECT` | `30` | Emissões/min por `subject` na mesma chave; `0` desliga. Por instância. |
|
|
37
|
+
| `SEEDGRID_PULSE_PUBLIC_WS_URL` | — | Endereço **público** do WebSocket devolvido em `connectUrl`. Ausente = campo omitido. |
|
|
38
|
+
|
|
39
|
+
Quem usa cada credencial: [[SeedGrid/Produtos/Pulse/Autenticacao-e-chaves|Autenticação e chaves]].
|
|
40
|
+
|
|
41
|
+
## Persistência e mensageria
|
|
42
|
+
|
|
43
|
+
| Variável | Padrão | Descrição |
|
|
44
|
+
|---|---|---|
|
|
45
|
+
| `POSTGRES_URL` | — | **Interruptor da plataforma.** Sem ela, security/login-tenancy/audit/apikeys ficam desligados. 🔒 |
|
|
46
|
+
| `POSTGRES_RUN_MIGRATIONS` | `true` | Roda migrations na subida. |
|
|
47
|
+
| `DELIVERY_STORE_BACKEND` | `memory` | `memory` \| `postgres`. Em produção, `postgres`. |
|
|
48
|
+
| `BROKER_PROVIDER` | `memory` | `memory` \| `redis` \| `nats` \| `rabbitmq` (fallback `EVENT_BUS_BACKEND`). Valor desconhecido cai em `memory`. Detalhes e variáveis por provider: [[SeedGrid/Produtos/Pulse/Servidor/Providers|Providers]]. |
|
|
49
|
+
| `PRESENCE_BACKEND` | `memory` | `memory` \| `redis`. Multi-réplica ⇒ `redis`. |
|
|
50
|
+
| `BROKER_REDIS_URL` | — | URL Redis-compatível (fallback `REDIS_URL`). 🔒 |
|
|
51
|
+
| `BROKER_REDIS_CHANNEL` | `seedgrid:pulse:events` | Canal pub/sub (fallback `REDIS_PUBSUB_CHANNEL`). |
|
|
52
|
+
| `BROKER_NATS_URL` | — | URL do NATS (`nats://host:4222`; fallback `NATS_URL`). Obrigatória com `nats`. 🔒 |
|
|
53
|
+
| `BROKER_NATS_SUBJECT` | `seedgrid.pulse.events` | Subject do pub/sub. |
|
|
54
|
+
| `BROKER_RABBITMQ_URL` | — | URL AMQP (fallbacks `RABBITMQ_URL`, `AMQP_URL`). Obrigatória com `rabbitmq`. 🔒 |
|
|
55
|
+
| `BROKER_RABBITMQ_EXCHANGE` | `seedgrid.pulse.events` | Exchange fanout. |
|
|
56
|
+
|
|
57
|
+
As URLs Redis-compatíveis servem para Valkey e Dragonfly sem mudar mais nada; ver [[SeedGrid/Produtos/Pulse/Servidor/Providers|Providers]].
|
|
58
|
+
|
|
59
|
+
## Entrega (retry, TTL, limpeza)
|
|
60
|
+
|
|
61
|
+
Os pares `*_CAP` são o **teto** que uma configuração por mensagem pode pedir; omitidos, assumem o valor base. Todos (exceto o intervalo de limpeza) são editáveis em runtime em **Configurações**.
|
|
62
|
+
|
|
63
|
+
| Variável | Padrão | Descrição |
|
|
64
|
+
|---|---|---|
|
|
65
|
+
| `DELIVERY_RETRY_STRATEGY` | `exponential` | `exponential` (qualquer outro valor = `fixed`: atraso constante de `DELIVERY_RETRY_BASE_MS`). |
|
|
66
|
+
| `DELIVERY_RETRY_BASE_MS` | `300` | Backoff base. |
|
|
67
|
+
| `DELIVERY_RETRY_MAX_MS` | `5000` | Backoff máximo. |
|
|
68
|
+
| `DELIVERY_MAX_ATTEMPTS` | `20` | Tentativas de execução por mensagem (modo `processed`). |
|
|
69
|
+
| `DELIVERY_TTL_SECONDS` | `86400` | TTL da mensagem (1 dia). |
|
|
70
|
+
| `DELIVERY_RESULT_TIMEOUT_SECONDS` | `0` (sem prazo) | **Prazo de execução** padrão (modo `processed`): segundos entre o `ack` e o `result`. `0` desliga. Estourado, vale como `retryable` com motivo `result_timeout`. Editável em Configurações, sem reinício. |
|
|
71
|
+
| `DELIVERY_RESULT_TIMEOUT_SECONDS_CAP` | `86400` (ou o padrão, se maior) | Teto do prazo que o publisher pode pedir; `0` **proíbe** o prazo de execução. |
|
|
72
|
+
| `DELIVERY_RETRY_BASE_MS_CAP` / `DELIVERY_RETRY_MAX_MS_CAP` / `DELIVERY_MAX_ATTEMPTS_CAP` / `DELIVERY_TTL_SECONDS_CAP` | = valor base | Tetos para o override por mensagem. |
|
|
73
|
+
| `DELIVERY_CLEANUP_INTERVAL_SECONDS` | `60` | Intervalo da varredura de retenção (`DELIVERY_CLEANUP_RETENTION_DAYS`) e da limpeza automática da lixeira. **Não** controla a expiração por TTL, que tem verificador próprio (a cada `ceil(DELIVERY_RETRY_BASE_MS/1000)` s, mínimo 1 s). Exige reinício. |
|
|
74
|
+
| `DELIVERY_CLEANUP_RETENTION_DAYS` | `0` (nunca apaga) | **Dias** que uma mensagem em estado final (`completed`/`dead_letter`/`expired`) é mantida. `0` desliga a varredura: o histórico é prova. Obsoleta: `DELIVERY_CLEANUP_RETENTION_SECONDS` (lida só se a de dias não existir). |
|
|
75
|
+
| `DELIVERY_TRASH_AUTO_CLEAN_DAYS` | `0` (só manual) | Dias na lixeira antes da limpeza automática. Cada limpeza vai ao audit como `system:pulse`. |
|
|
76
|
+
|
|
77
|
+
Detalhes e as regras de lixeira: [[SeedGrid/Produtos/Pulse/Servidor/Operacao|Operação]].
|
|
78
|
+
|
|
79
|
+
## Security (login, JWT, RBAC)
|
|
80
|
+
|
|
81
|
+
Habilitado com `POSTGRES_URL` **e** as chaves RSA. Nomes alinhados à extension Java `security` ([[SeedGrid/Extensions/security/Configuracao|Configuração do security]]).
|
|
82
|
+
|
|
83
|
+
| Variável | Descrição |
|
|
84
|
+
|---|---|
|
|
85
|
+
| `SECURITY_PRIVATE_KEY_LOCATION` / `SECURITY_PUBLIC_KEY_LOCATION` | Caminhos do par RSA (primários). 🔒 |
|
|
86
|
+
| `SECURITY_JWT_PRIVATE_KEY_PEM` / `SECURITY_JWT_PUBLIC_KEY_PEM` | PEM inline (secundário). 🔒 |
|
|
87
|
+
| `SECURITY_JWT_ISSUER` / `SECURITY_JWT_KID` | Issuer e `kid` do JWT. |
|
|
88
|
+
| `SECURITY_JWT_TTL` | Validade do access token, ISO-8601 (`PT8H`). |
|
|
89
|
+
| `SECURITY_REFRESH_TOKEN_TTL` | Validade do refresh token (`P30D`). |
|
|
90
|
+
| `SECURITY_PASSWORD_MIN_SIZE` / `_EXPIRATION_DAYS` / `_MAX_HISTORY` | Política de senha. |
|
|
91
|
+
| `SECURITY_ENCRYPTION_KEY` | AES-256 (base64) da cripto de campo; obrigatória se usar TOTP. 🔒 |
|
|
92
|
+
| `SECURITY_FRONTEND_BASE_URL` | Base da UI nos links de e-mail. |
|
|
93
|
+
| `SEEDGRID_SECURITY_FIRST_ADMIN_USER_EMAIL` / `_NAME` / `_INITIAL_PASSWORD` | Bootstrap do primeiro admin. 🔒 |
|
|
94
|
+
| `SEEDGRID_SECURITY_DEFAULT_COMPANY_CNPJ` / `_CORPORATE_NAME` / `_TRADE_NAME` | Company da plataforma (razão social e fantasia são obrigatórias no bootstrap). |
|
|
95
|
+
|
|
96
|
+
### 2FA
|
|
97
|
+
|
|
98
|
+
Desligado por padrão. `SEEDGRID_SECURITY_2F_ENABLED=true` liga; `_ALLOWED_METHODS` (`EMAIL,TOTP`), `_DEFAULT_METHOD` (`TOTP`), `_EMAIL_CODE_TTL`, `_SESSION_TTL`, `_VERIFY_MAX_ATTEMPTS` (5), `_TOTP_ISSUER` (`SeedGrid`; vale trocar para `SeedGrid Pulse`), `_TOTP_DIGITS` (6), `_TOTP_PERIOD` (30), `_TOTP_WINDOW` (1), `_BACKUP_CODES_COUNT` (10). WhatsApp: `SEEDGRID_SECURITY_2F_WHATSAPP_CHANNEL_ID` mais um provider em `SEEDGRID_WHATSAPP_API` (`evolution`/`cloud`) com credenciais ([[SeedGrid/Extensions/whatsapp/Configuracao|whatsapp]]).
|
|
99
|
+
|
|
100
|
+
### E-mail (SMTP)
|
|
101
|
+
|
|
102
|
+
`SECURITY_MAILER_USERNAME` e `_PASSWORD` ligam o SMTP real (🔒); `_HOST` (`smtp.gmail.com`), `_PORT` (587), `_START_TLS` (`REQUIRED`), `_FROM`. **Sem usuário e senha o e-mail só vai para o log** — confirmação, reset de senha e 2FA por e-mail não chegam.
|
|
103
|
+
|
|
104
|
+
## Login-tenancy
|
|
105
|
+
|
|
106
|
+
`SEEDGRID_LOGIN_TENANCY_APP_CODE` (`seedgrid-app`; use `seedgrid-pulse`), `_APP_NAME`, `_DATABASE_MIGRATE_AT_START` (`true`), `_DATABASE_BASELINE_ON_MIGRATE` (`true`), `_FOUNDATION_STATUS_ENABLED`, `_FOUNDATION_HEALTH_ENABLED`, `_BOOTSTRAP_ENABLED`, `_BOOTSTRAP_ADMIN_ENABLED`. Não existe flag "enabled": a dependência ativa o baseline. `SEEDGRID_SHOW_DEV_MESSAGE` (`false`) inclui detalhe interno nos erros — **nunca em produção**. Ver [[SeedGrid/Extensions/login-tenancy/Configuracao|login-tenancy]].
|
|
107
|
+
|
|
108
|
+
## Audit
|
|
109
|
+
|
|
110
|
+
`SEEDGRID_AUDIT_ENABLED` (`true`), `AUDIT_STRATEGY` (`JPA` = Postgres \| `MONGODB`), `SEEDGRID_AUDIT_DB_*` só para banco de auditoria separado, `SEEDGRID_AUDIT_MONGODB_URI`/`_DATABASE`. No deploy padrão as migrations de audit rodam no mesmo banco. A leitura é escopada por `company_id` via headers internos sobrescritos pelo JWT — não os repasse de proxy. Ver [[SeedGrid/Extensions/audit/Configuracao|audit]].
|
|
111
|
+
|
|
112
|
+
## API keys
|
|
113
|
+
|
|
114
|
+
`SEEDGRID_APIKEYS_PREFIX_LENGTH` (`8`), `SEEDGRID_APIKEYS_KEY_BYTES` (`32`). Ver [[SeedGrid/Extensions/apikeys/Configuracao|apikeys]].
|
|
115
|
+
|
|
116
|
+
## Observabilidade
|
|
117
|
+
|
|
118
|
+
`RUST_LOG` (ex.: `info`). Métricas: `GET /metrics` (JSON) e `GET /metrics/prometheus`; Prometheus e Grafana vêm no compose.
|
|
119
|
+
|
|
120
|
+
## Variáveis removidas (não configure)
|
|
121
|
+
|
|
122
|
+
As de multitenancy por subdomínio (`DOMAIN_SUFFIX`, `SEEDGRID_MULTITENANCY_*`, `PRODUCT_PREFIX`, `MULTITENANCY_MAILER_*`) foram eliminadas e são ignoradas. Backup (`BACKUP_*`) e billing (`SEEDGRID_BILLING_*`) não se aplicam ao Pulse hoje.
|
|
123
|
+
|
|
124
|
+
## Pegadinhas
|
|
125
|
+
|
|
126
|
+
- A chave de servidor nunca vai para produto nenhum nem para o serviço da UI.
|
|
127
|
+
- Variável definida no EasyPanel **vence** o padrão de código: ao mudar um padrão, confira o ambiente.
|
|
128
|
+
- `0` em retenção/limpeza significa **desligado** (não "apagar tudo").
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
---
|
|
2
|
+
tags: [seedgrid, produto, pulse, servidor, instalacao, deploy]
|
|
3
|
+
fonte: seedgrid-products/seedgrid-pulse/backend
|
|
4
|
+
branch: main
|
|
5
|
+
commit: 9dcbdad
|
|
6
|
+
analisado-em: 2026-10-16
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Pulse (servidor) — instalação e execução
|
|
10
|
+
|
|
11
|
+
O **servidor Pulse** é o backend Rust (Axum): API REST, WebSocket, entrega, retry, DLQ, presença e módulos de plataforma. A UI é outro componente: [[SeedGrid/Produtos/Pulse/UI/Visao-geral|Pulse UI]].
|
|
12
|
+
|
|
13
|
+
Voltar: [[SeedGrid/Produtos/Pulse/Visao-geral|Visão geral]] · variáveis: [[SeedGrid/Produtos/Pulse/Servidor/Configuracao|Configuração do servidor]] · brokers: [[SeedGrid/Produtos/Pulse/Servidor/Providers|Providers (Redis, Valkey, Dragonfly, NATS, RabbitMQ)]]
|
|
14
|
+
|
|
15
|
+
## Modos de execução
|
|
16
|
+
|
|
17
|
+
| Modo | Quando | Persistência |
|
|
18
|
+
|---|---|---|
|
|
19
|
+
| **Memória** (sem `POSTGRES_URL`) | desenvolvimento rápido, testes | nenhuma; plataforma (login, audit, apikeys) **desabilitada** — só o núcleo realtime |
|
|
20
|
+
| **Postgres** | produção de instância única | mensagens, contas, usuários, audit |
|
|
21
|
+
| **Distribuído** | várias réplicas | Postgres + broker pub/sub + presença em Redis |
|
|
22
|
+
|
|
23
|
+
Exemplos de `env` (Confirmado — `backend/README.md`):
|
|
24
|
+
|
|
25
|
+
```env
|
|
26
|
+
# simples
|
|
27
|
+
BROKER_PROVIDER=memory
|
|
28
|
+
PRESENCE_BACKEND=memory
|
|
29
|
+
DELIVERY_STORE_BACKEND=memory
|
|
30
|
+
|
|
31
|
+
# com Postgres
|
|
32
|
+
DELIVERY_STORE_BACKEND=postgres
|
|
33
|
+
POSTGRES_URL=postgres://<user>:<senha>@<host>:5432/<db>
|
|
34
|
+
|
|
35
|
+
# distribuído
|
|
36
|
+
BROKER_PROVIDER=redis
|
|
37
|
+
PRESENCE_BACKEND=redis
|
|
38
|
+
DELIVERY_STORE_BACKEND=postgres
|
|
39
|
+
BROKER_REDIS_URL=redis://<host>:6379/0
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Subir com Docker/Podman Compose
|
|
43
|
+
|
|
44
|
+
Em `backend/`:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
docker compose up -d --build
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Sobe `postgres`, `redis`, `seedgrid-pulse`, `prometheus`, `grafana` e `seedgrid-pulse-ui`. Portas locais (Confirmado — `docker-compose.yml`): API `18080`, Prometheus `19090`, Grafana `13001`, UI `13000`.
|
|
51
|
+
|
|
52
|
+
O compose de desenvolvimento traz valores de exemplo (chave de servidor, segredo do token, admin inicial). **Troque todos** em qualquer ambiente real. 🔒
|
|
53
|
+
|
|
54
|
+
## Rodar a partir do fonte
|
|
55
|
+
|
|
56
|
+
Pré-requisitos: Rust estável recente (edition 2024) e o repositório de crates da plataforma clonado ao lado (path dependencies).
|
|
57
|
+
|
|
58
|
+
```text
|
|
59
|
+
<raiz>/
|
|
60
|
+
├─ seedgrid-platform/rust/ # crates seedgrid-rust-crate-*
|
|
61
|
+
└─ seedgrid-products/seedgrid-pulse/ # este repo
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
O prefixo `../../../seedgrid-platform/rust/` está em `backend/Cargo.toml`; ajuste-o se o layout for outro.
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
cd backend
|
|
68
|
+
docker compose up -d postgres redis
|
|
69
|
+
cargo run
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
O build não precisa de banco (não há `sqlx::query!` verificada em compilação).
|
|
73
|
+
|
|
74
|
+
## Primeiro acesso
|
|
75
|
+
|
|
76
|
+
Com `POSTGRES_URL` e o par RSA do JWT, o boot roda as migrations e cria a company da plataforma e o **primeiro admin** a partir de `SEEDGRID_SECURITY_FIRST_ADMIN_USER_*` e `SEEDGRID_SECURITY_DEFAULT_COMPANY_*` ([[SeedGrid/Produtos/Pulse/Servidor/Configuracao|Configuração]]). Entre na UI com esse admin, crie a **conta** do seu produto e as **chaves** (Contas → conta → Chaves → Nova chave). O segredo da chave aparece **uma única vez**.
|
|
77
|
+
|
|
78
|
+
Par RSA do JWT (exemplo):
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out private.pem
|
|
82
|
+
openssl rsa -pubout -in private.pem -out public.pem
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Aponte `SECURITY_PRIVATE_KEY_LOCATION` / `SECURITY_PUBLIC_KEY_LOCATION` (ou use PEM inline).
|
|
86
|
+
|
|
87
|
+
## Imagem e deploy
|
|
88
|
+
|
|
89
|
+
- Imagem no GHCR: `ghcr.io/seedgrid/seedgrid-pulse-backend` (Confirmado — `.github/workflows/deploy.yml`).
|
|
90
|
+
- `push` em `main` dispara o workflow, que detecta o que mudou, publica a imagem e chama o webhook do EasyPanel (secret `EASYPANEL_DEPLOY_URL_PULSE_BACKEND`). Commit só de documentação **não** redeploya.
|
|
91
|
+
- O container escuta `8080`; use `HTTP_HOST=0.0.0.0` em container.
|
|
92
|
+
- Probes: liveness `GET /health`, readiness `GET /ready` (200/503 com o estado de store, broker e presença).
|
|
93
|
+
- Migrations rodam no boot (`POSTGRES_RUN_MIGRATIONS`, padrão `true`).
|
|
94
|
+
|
|
95
|
+
## Checklist de produção
|
|
96
|
+
|
|
97
|
+
- [ ] `POSTGRES_URL` + `DELIVERY_STORE_BACKEND=postgres`.
|
|
98
|
+
- [ ] Mais de uma réplica ⇒ broker pub/sub (`redis`, ou `nats`/`rabbitmq` — ver [[SeedGrid/Produtos/Pulse/Servidor/Providers|Providers]]) **e** `PRESENCE_BACKEND=redis`.
|
|
99
|
+
- [ ] `SEEDGRID_PULSE_SERVER_KEY` e `SEEDGRID_PULSE_CONNECT_TOKEN_SECRET` longos e aleatórios, só em ENV. 🔒
|
|
100
|
+
- [ ] `SEEDGRID_PULSE_PUBLIC_WS_URL` com o endereço público do WebSocket (`wss://…`), se há clientes de navegador.
|
|
101
|
+
- [ ] `CORS_ALLOWED_ORIGINS` com a origem da UI.
|
|
102
|
+
- [ ] Par RSA do JWT próprio; admin inicial trocado.
|
|
103
|
+
- [ ] `SEEDGRID_SHOW_DEV_MESSAGE` desligado (padrão).
|
|
104
|
+
- [ ] Proxy reverso **não** repassa `x-seedgrid-company-id` / `x-seedgrid-all-companies` vindos do cliente.
|
|
105
|
+
- [ ] Retenção do histórico decidida (padrão: nunca apagar) — [[SeedGrid/Produtos/Pulse/Servidor/Operacao|Operação]].
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
---
|
|
2
|
+
tags: [seedgrid, produto, pulse, servidor, operacao, lixeira, retencao]
|
|
3
|
+
fonte: seedgrid-products/seedgrid-pulse/backend (docs/LIXEIRA-mensagens-e-contas.md, README.md)
|
|
4
|
+
branch: main
|
|
5
|
+
commit: 9dcbdad
|
|
6
|
+
analisado-em: 2026-10-16
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Pulse (servidor) — operação
|
|
10
|
+
|
|
11
|
+
Lixeira, retenção, auditoria, observabilidade e escala. Voltar: [[SeedGrid/Produtos/Pulse/Visao-geral|Visão geral]] · variáveis: [[SeedGrid/Produtos/Pulse/Servidor/Configuracao|Configuração]].
|
|
12
|
+
|
|
13
|
+
## Princípios
|
|
14
|
+
|
|
15
|
+
- O **histórico de entregas é prova**: por padrão **nunca é apagado sozinho**.
|
|
16
|
+
- Apagar é **sempre ação humana**, com permission própria, confirmação na UI e **audit** (quem, o quê, quantos).
|
|
17
|
+
- A chave de servidor **não apaga nada** (401): toda exclusão tem um autor.
|
|
18
|
+
|
|
19
|
+
## Lixeira de mensagens
|
|
20
|
+
|
|
21
|
+
- **Só mensagens `pending`** podem ir para a lixeira (mensagens entregues/processadas são histórico; só saem com a exclusão da conta).
|
|
22
|
+
- Na UI: **Mensagens**, filtro de status **"Na lixeira"**. Mover (`PULSE_MESSAGE_DELETE`), restaurar (volta a `pending`) e limpar de vez (`PULSE_MESSAGE_PURGE`, apaga também as entregas por destinatário).
|
|
23
|
+
- API: `POST /api/v1/messages/trash` · `/trash/restore` · `/trash/purge`, lote de até **1000** ids (`400 BATCH_TOO_LARGE`), resposta `{requested, affected, skipped}`.
|
|
24
|
+
- Mensagem na lixeira não é entregue, não expira por TTL e some das listas padrão.
|
|
25
|
+
- **Descartar** (tela Pendências, `PULSE_BACKLOG_DISCARD`) e **Lixeira** coexistem como ações distintas; só a lixeira tem restaurar e limpar de vez.
|
|
26
|
+
- Tarefas `delivered` sem `result` e sem prazo de execução (as anteriores ao Pulse 0.3.0, ou quando `resultTimeoutSeconds` não foi usado) só saem por **descarte**; veja [[SeedGrid/Produtos/Pulse/Protocolo-e-API#Prazo de execução (resultTimeoutSeconds)|Prazo de execução]].
|
|
27
|
+
|
|
28
|
+
## Lixeira de contas
|
|
29
|
+
|
|
30
|
+
- A lixeirinha da lista de contas pede confirmação e leva a conta para `pending_delete` (`PULSE_ACCOUNT_DELETE`). A conta **deixa de autenticar** e suas conexões são derrubadas.
|
|
31
|
+
- **Lixeira de contas** (menu): restaurar (volta ao status anterior) ou **apagar definitivamente** (`PULSE_ACCOUNT_PURGE`), que remove a conta, suas chaves e **todas as suas mensagens** em cascata. O diálogo mostra antes quantas chaves e mensagens saem (`GET /accounts/{id}/deletion-summary`).
|
|
32
|
+
- O apagar definitivo **não é uma transação única**: mensagens primeiro, conta por último. Se falhar no meio, a conta continua na lixeira e dá para repetir.
|
|
33
|
+
|
|
34
|
+
## Retenção e limpeza automática
|
|
35
|
+
|
|
36
|
+
| Variável | Padrão | Efeito |
|
|
37
|
+
|---|---|---|
|
|
38
|
+
| `DELIVERY_CLEANUP_RETENTION_DAYS` | `0` | Dias que uma mensagem **final** (`completed`/`dead_letter`/`expired`) é mantida. `0` = **nunca apaga**. |
|
|
39
|
+
| `DELIVERY_TRASH_AUTO_CLEAN_DAYS` | `0` | Dias na lixeira antes de apagar sozinho. `0` = só manual. Cada limpeza vai ao audit como `system:pulse`. |
|
|
40
|
+
|
|
41
|
+
As duas **não se sobrepõem**: a primeira atua no histórico (estados finais), a segunda na lixeira (`trashed`). Mensagens `pending` e `delivered` nunca são limpas pela retenção. A obsoleta `DELIVERY_CLEANUP_RETENTION_SECONDS` só vale se a de dias não existir. Ambas são editáveis em **Configurações**, sem redeploy.
|
|
42
|
+
|
|
43
|
+
> **Mudança de comportamento (2026-10-15):** o padrão era 7 dias e `0` apagava tudo. Ambientes que definem a variável explicitamente (EasyPanel) mantêm o valor definido.
|
|
44
|
+
|
|
45
|
+
Sem consumidor, uma `pending` não fica para sempre: o TTL (`DELIVERY_TTL_SECONDS`, 1 dia) a expira.
|
|
46
|
+
|
|
47
|
+
## Ordem das listas e paginação
|
|
48
|
+
|
|
49
|
+
As telas listam **da mais recente para a mais antiga** (quem acabou de publicar vê a sua primeira): contas por `created_at`, mensagens por `published_at` e entregas por destinatário por `delivered_at`, todas **com desempate por id**. A paginação é 1-based (`page`, `pageSize`; a Auditoria usa `page`/`size` e o backend dela é base 0, convertido pela UI). Até o Pulse 0.2.1 a lista de contas ordenava sem desempate, e contas criadas no mesmo segundo repetiam ou sumiam entre páginas (corrigido no 0.2.2). O **replay** e as pendências devidas continuam em ordem cronológica (do mais antigo ao mais novo), porque entregar na ordem de publicação é o comportamento certo (Confirmado em `delivery/repo.rs`).
|
|
50
|
+
|
|
51
|
+
## Auditoria
|
|
52
|
+
|
|
53
|
+
Toda operação destrutiva (mover para lixeira, restaurar, limpar; contas e mensagens) grava em `audit_log` o autor (claim `sub` do JWT, e-mail na descrição), a ação e as contagens, **somente se algo mudou**. Visível em **Segurança → Auditoria** (escopo por `company_id`).
|
|
54
|
+
|
|
55
|
+
## Observabilidade
|
|
56
|
+
|
|
57
|
+
| O quê | Onde |
|
|
58
|
+
|---|---|
|
|
59
|
+
| Liveness / readiness | `GET /health` · `GET /ready` (200 `READY` / 503 `NOT_READY`, com store, broker e presença) |
|
|
60
|
+
| Métricas | `GET /metrics` (JSON) · `GET /metrics/prometheus` |
|
|
61
|
+
| Dashboards | Prometheus + Grafana no compose (`SeedGrid Pulse Overview`) |
|
|
62
|
+
| Telas | dashboard, conexões, backlog, DLQ, mensagens, entregas por destinatário |
|
|
63
|
+
|
|
64
|
+
Métricas úteis: `publish_requests_total`, `delivery_attempts_total`, `delivery_success_total`, `delivery_dead_letter_total`, `delivery_expired_total`, `delivery_result_timeout_total` (prazo de execução estourado), `ack_total`, `ws_connections_opened_total`/`_closed_total`, latências `publish_to_deliver_*` e `deliver_to_ack_*`.
|
|
65
|
+
|
|
66
|
+
## Escala (várias réplicas)
|
|
67
|
+
|
|
68
|
+
- Estado durável no **Postgres** (`DELIVERY_STORE_BACKEND=postgres`).
|
|
69
|
+
- Entrega entre instâncias via **broker pub/sub** (`BROKER_PROVIDER`) e presença em Redis (`PRESENCE_BACKEND=redis`): ver [[SeedGrid/Produtos/Pulse/Servidor/Providers|Providers]].
|
|
70
|
+
- Revogação de credencial atravessa o broker (tópico `pulse.revocations`) e derruba as conexões em **todas** as instâncias.
|
|
71
|
+
- Limites de emissão de token são **por instância**: com N réplicas o efetivo é até N vezes.
|
|
72
|
+
|
|
73
|
+
## Diagnóstico rápido
|
|
74
|
+
|
|
75
|
+
| Sintoma | Verifique |
|
|
76
|
+
|---|---|
|
|
77
|
+
| Publicou e ninguém recebeu | `accountId`/conta ativa; `channel` e `event` batem com o `subscribe`; `user` do destino = `subject` da conexão; entrega fica `pending` até alguém conectar |
|
|
78
|
+
| 403 ao publicar | está usando chave `client` ou a chave de servidor; use a `project` |
|
|
79
|
+
| WebSocket 401 | credencial ausente/revogada; token `pct_` vencido antes de conectar |
|
|
80
|
+
| Conexão fecha com `4403` | chave/conta revogada: não reconecte com a mesma credencial |
|
|
81
|
+
| `connect-tokens` 503 | falta `SEEDGRID_PULSE_CONNECT_TOKEN_SECRET` |
|
|
82
|
+
| E-mail/2FA por e-mail não chega | `SECURITY_MAILER_USERNAME`/`_PASSWORD` ausentes (só loga) |
|
|
83
|
+
| Histórico "sumiu" | retenção definida no ambiente (`DELIVERY_CLEANUP_RETENTION_*`) |
|
|
84
|
+
| Réplica B não recebe o que A publicou | broker `memory` em produção multi-réplica |
|
|
85
|
+
|
|
86
|
+
Testes e CI: `cargo test` (unitários e e2e); com Docker/Podman, `cargo test redis_ -- --ignored`, `postgres_ -- --ignored` e `--test trash_integration -- --ignored --test-threads=1` sobem Postgres/Redis via testcontainers.
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
---
|
|
2
|
+
tags: [seedgrid, produto, pulse, servidor, broker, redis, valkey, dragonfly, nats, rabbitmq, postgres]
|
|
3
|
+
fonte: seedgrid-products/seedgrid-pulse/backend (src/config.rs, src/broker.rs, tests/) + seedgrid-platform/rust/seedgrid-rust-crate-broker
|
|
4
|
+
branch: main
|
|
5
|
+
commit: 9dcbdad
|
|
6
|
+
analisado-em: 2026-10-16
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Pulse (servidor) — providers: broker, presença e store
|
|
10
|
+
|
|
11
|
+
O Pulse separa três responsabilidades, cada uma com seu provider. Voltar: [[SeedGrid/Produtos/Pulse/Servidor/Configuracao|Configuração do servidor]] · [[SeedGrid/Produtos/Pulse/Servidor/Instalacao|Instalação]].
|
|
12
|
+
|
|
13
|
+
| Responsabilidade | Variável | Opções | Para quê |
|
|
14
|
+
|---|---|---|---|
|
|
15
|
+
| **Broker** (pub/sub entre instâncias) | `BROKER_PROVIDER` | `memory`, `redis`, `nats`, `rabbitmq` | levar uma publicação a **todas** as instâncias, para a que tem o WebSocket entregar; e propagar revogação de credencial |
|
|
16
|
+
| **Presença** (quem está conectado em quê) | `PRESENCE_BACKEND` | `memory`, `redis` | presença por canal/grupo compartilhada entre instâncias |
|
|
17
|
+
| **Store de entregas** (mensagens, estados, DLQ) | `DELIVERY_STORE_BACKEND` | `memory`, `postgres` | durabilidade, replay, histórico |
|
|
18
|
+
|
|
19
|
+
## Quando precisa de quê
|
|
20
|
+
|
|
21
|
+
| Cenário | Broker | Presença | Store |
|
|
22
|
+
|---|---|---|---|
|
|
23
|
+
| Desenvolvimento / uma instância sem persistência | `memory` | `memory` | `memory` |
|
|
24
|
+
| **Uma instância em produção** | `memory` | `memory` | `postgres` |
|
|
25
|
+
| **Várias réplicas (escala)** | `redis` \| `nats` \| `rabbitmq` | **`redis`** | `postgres` |
|
|
26
|
+
|
|
27
|
+
- Sem broker compartilhado, uma réplica não entrega o que outra publicou (ver [[SeedGrid/Produtos/Pulse/Servidor/Operacao|Operação — diagnóstico]]).
|
|
28
|
+
- **A presença só tem `memory` e `redis`.** Com NATS ou RabbitMQ como broker em várias réplicas, ainda é preciso um servidor Redis-compatível para `PRESENCE_BACKEND=redis` (Confirmado — `config.rs`).
|
|
29
|
+
- O estado de entrega vive no **Postgres**; o broker é só o barramento. Por isso um broker sem persistência (NATS core) não perde mensagem do Pulse: o replay a recupera do banco.
|
|
30
|
+
|
|
31
|
+
## Redis e compatíveis (Valkey, Dragonfly, KeyDB…)
|
|
32
|
+
|
|
33
|
+
Usa pub/sub do protocolo Redis. Variáveis:
|
|
34
|
+
|
|
35
|
+
| Variável | Padrão | Descrição |
|
|
36
|
+
|---|---|---|
|
|
37
|
+
| `BROKER_PROVIDER=redis` | | |
|
|
38
|
+
| `BROKER_REDIS_URL` (fallback `REDIS_URL`) | — | `redis://host:6379/0`; use `rediss://` para TLS. 🔒 |
|
|
39
|
+
| `BROKER_REDIS_CHANNEL` (fallback `REDIS_PUBSUB_CHANNEL`) | `seedgrid:pulse:events` | canal pub/sub |
|
|
40
|
+
| `PRESENCE_BACKEND=redis` | | usa a mesma `BROKER_REDIS_URL` |
|
|
41
|
+
|
|
42
|
+
Como o Pulse só fala o protocolo Redis (cliente `redis` 0.32), qualquer servidor compatível serve — **basta apontar a URL**. Verificado em 2026-10-16 rodando a suíte `redis_integration` (broker pub/sub, presença com expiração/heartbeat e revogação entre instâncias) contra:
|
|
43
|
+
|
|
44
|
+
| Servidor | Imagem testada | Resultado |
|
|
45
|
+
|---|---|---|
|
|
46
|
+
| Redis | `redis:7.2.4` | 5/5 ✅ |
|
|
47
|
+
| Valkey | `valkey/valkey:8` | 5/5 ✅ |
|
|
48
|
+
| Dragonfly | `docker.dragonflydb.io/dragonflydb/dragonfly:latest` | 5/5 ✅ |
|
|
49
|
+
|
|
50
|
+
KeyDB e serviços gerenciados (ElastiCache, Memorystore, Upstash…) **não foram testados** aqui; devem funcionar por falarem o mesmo protocolo (Inferência) — rode a suíte antes de adotar.
|
|
51
|
+
|
|
52
|
+
Para validar outro servidor:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
SG_PULSE_TEST_REDIS_IMAGE=<imagem>:<tag> \
|
|
56
|
+
DOCKER_HOST='npipe:////./pipe/podman-machine-default' TESTCONTAINERS_RYUK_DISABLED=true \
|
|
57
|
+
cargo test --test redis_integration -- --ignored --test-threads=1
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Exemplo de troca (compose): no serviço `redis`, use a imagem `valkey/valkey:8` (ou Dragonfly) e mantenha `BROKER_REDIS_URL=redis://redis:6379/0`; nenhuma outra variável muda.
|
|
61
|
+
|
|
62
|
+
## NATS
|
|
63
|
+
|
|
64
|
+
Pub/sub **core** do NATS em um `subject`; cada instância assina o mesmo subject e recebe tudo (fan-out).
|
|
65
|
+
|
|
66
|
+
| Variável | Padrão | Descrição |
|
|
67
|
+
|---|---|---|
|
|
68
|
+
| `BROKER_PROVIDER=nats` | | |
|
|
69
|
+
| `BROKER_NATS_URL` (fallback `NATS_URL`) | — | `nats://host:4222`. **Obrigatória.** 🔒 |
|
|
70
|
+
| `BROKER_NATS_SUBJECT` | `seedgrid.pulse.events` | sem espaços nem curingas `*`/`>` |
|
|
71
|
+
| `PRESENCE_BACKEND` | `memory` | `redis` em multi-réplica |
|
|
72
|
+
|
|
73
|
+
- Entrega **at-most-once**, sem persistência (NATS core). Aceitável porque o estado de entrega está no Postgres e volta pelo replay.
|
|
74
|
+
- Sem reconexão automática do stream do broker (igual ao Redis): se a conexão cair, o stream termina com `warn`. Mantenha supervisão/restart do serviço.
|
|
75
|
+
|
|
76
|
+
Exemplo:
|
|
77
|
+
|
|
78
|
+
```env
|
|
79
|
+
BROKER_PROVIDER=nats
|
|
80
|
+
BROKER_NATS_URL=nats://nats:4222
|
|
81
|
+
PRESENCE_BACKEND=redis
|
|
82
|
+
BROKER_REDIS_URL=redis://redis:6379/0
|
|
83
|
+
DELIVERY_STORE_BACKEND=postgres
|
|
84
|
+
POSTGRES_URL=postgres://<user>:<senha>@<host>:5432/<db>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## RabbitMQ
|
|
88
|
+
|
|
89
|
+
Exchange **fanout** durável declarada no boot; cada instância cria a **própria fila exclusiva e auto-delete**, ligada ao exchange (fan-out entre instâncias).
|
|
90
|
+
|
|
91
|
+
| Variável | Padrão | Descrição |
|
|
92
|
+
|---|---|---|
|
|
93
|
+
| `BROKER_PROVIDER=rabbitmq` | | |
|
|
94
|
+
| `BROKER_RABBITMQ_URL` (fallbacks `RABBITMQ_URL`, `AMQP_URL`) | — | `amqp://user:senha@host:5672/%2f` (vhost codificado). **Obrigatória.** 🔒 |
|
|
95
|
+
| `BROKER_RABBITMQ_EXCHANGE` | `seedgrid.pulse.events` | nome do exchange fanout |
|
|
96
|
+
| `PRESENCE_BACKEND` | `memory` | `redis` em multi-réplica |
|
|
97
|
+
|
|
98
|
+
- `amqps://` (TLS) está habilitado na crate mas **não foi testado**.
|
|
99
|
+
- Sem reconexão automática do broker; filas exclusivas somem quando a instância cai (comportamento desejado no fan-out).
|
|
100
|
+
|
|
101
|
+
## Memória
|
|
102
|
+
|
|
103
|
+
`BROKER_PROVIDER=memory` (padrão; valor desconhecido também cai nele): barramento em processo. Só serve para **uma instância**.
|
|
104
|
+
|
|
105
|
+
## Readiness
|
|
106
|
+
|
|
107
|
+
`GET /ready` testa store, broker e presença e responde 200 `READY` ou 503 `NOT_READY` com o detalhe por componente. Para NATS e RabbitMQ a sonda é um `ping` com timeout de 5 s.
|
|
108
|
+
|
|
109
|
+
## Postgres (store de entregas e plataforma)
|
|
110
|
+
|
|
111
|
+
`POSTGRES_URL` é o interruptor da plataforma (login, audit, apikeys) e `DELIVERY_STORE_BACKEND=postgres` liga a persistência de entregas. As migrations rodam no boot (`POSTGRES_RUN_MIGRATIONS=true`); cada módulo usa a própria tabela de histórico (`_sqlx_migrations_*`). Qualquer Postgres gerenciado serve. Banco único, separação lógica por `company_id`.
|
|
112
|
+
|
|
113
|
+
## Como foi verificado
|
|
114
|
+
|
|
115
|
+
| Item | Evidência |
|
|
116
|
+
|---|---|
|
|
117
|
+
| Redis / Valkey / Dragonfly | `tests/redis_integration.rs`, 5/5 por servidor (Podman, testcontainers) |
|
|
118
|
+
| NATS e RabbitMQ | testes de container nas crates `seedgrid-broker-nats`/`-rabbitmq` (fan-out para 3 subscribers em 2 instâncias, payload malformado sem derrubar o stream, `ping`) e `tests/broker_providers_integration.rs` no Pulse (`build_broker` entrega a todos; `/ready` UP) |
|
|
119
|
+
| Postgres | `tests/postgres_integration.rs` |
|
|
120
|
+
|
|
121
|
+
Código-fonte dos brokers: `seedgrid-platform/rust/seedgrid-rust-crate-broker` (crates `-spi`, `-memory`, `-redis`, `-nats`, `-rabbitmq`); README da crate descreve o contrato `Broker` (`publish`/`subscribe`).
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
tags: [seedgrid, produto, pulse, ui, configuracao, variaveis]
|
|
3
|
+
fonte: seedgrid-products/seedgrid-pulse/frontend/seedgrid-pulse-ui (.env.example, src/app/layout.tsx)
|
|
4
|
+
branch: main
|
|
5
|
+
commit: 9dcbdad
|
|
6
|
+
analisado-em: 2026-10-16
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Pulse UI — variáveis de ambiente
|
|
10
|
+
|
|
11
|
+
Variáveis da **UI**. As do servidor estão em [[SeedGrid/Produtos/Pulse/Servidor/Configuracao|Configuração do servidor]]. Lidas em **runtime** (layout `force-dynamic`): no EasyPanel são env do container, sem rebuild. Visão geral: [[SeedGrid/Produtos/Pulse/UI/Visao-geral|Pulse UI]].
|
|
12
|
+
|
|
13
|
+
## Conexão com o Pulse
|
|
14
|
+
|
|
15
|
+
| Variável | Padrão | Descrição |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| `SEEDGRID_PULSE_SERVER_BASE_URL` | `http://127.0.0.1:18080` (exemplo do `.env.example`) | Base URL da API Pulse **alcançável pelo navegador**. Única informação de conexão entregue ao client. Fallback legado: `NEXT_PUBLIC_PULSE_BASE_URL`. |
|
|
18
|
+
| `SEEDGRID_PULSE_INTERNAL_BASE_URL` | = a anterior | Base URL usada pelo **servidor da UI** nos proxies (`/api/security/*`, `/api/pulse/messages`). Só precisa quando difere (containers na mesma rede, ex.: `http://seedgrid-pulse:8080`). |
|
|
19
|
+
|
|
20
|
+
Não existe credencial aqui: nem usuário/senha nem chave. As telas autenticam com o JWT do operador logado.
|
|
21
|
+
|
|
22
|
+
## Aparência e idioma
|
|
23
|
+
|
|
24
|
+
| Variável | Padrão | Descrição |
|
|
25
|
+
|---|---|---|
|
|
26
|
+
| `SEEDGRID_PULSE_DEFAULT_THEME_SEED` | `#16803D` | Cor semente do tema. Legado: `NEXT_PUBLIC_DEFAULT_THEME_SEED`. |
|
|
27
|
+
| `SEEDGRID_PULSE_DEFAULT_THEME_MODE` | `light` | `light` ou `dark`. Legado: `NEXT_PUBLIC_DEFAULT_THEME_MODE`. |
|
|
28
|
+
| `SEEDGRID_PULSE_UI_DEFAULT_LOCALE` | `pt-BR` | Idioma padrão: `en`, `pt-BR`, `pt-PT`, `fr`, `es`. Legado: `NEXT_PUBLIC_PULSE_UI_DEFAULT_LOCALE`. |
|
|
29
|
+
|
|
30
|
+
Os nomes `NEXT_PUBLIC_*` antigos seguem aceitos como fallback para imagens antigas; prefira os `SEEDGRID_PULSE_*`.
|
|
31
|
+
|
|
32
|
+
## Auto-refresh (polling, em segundos)
|
|
33
|
+
|
|
34
|
+
Padrão de todos: **30**.
|
|
35
|
+
|
|
36
|
+
| Variável | Tela |
|
|
37
|
+
|---|---|
|
|
38
|
+
| `NEXT_PUBLIC_DASHBOARD_REFRESH_SECONDS` | dashboard |
|
|
39
|
+
| `NEXT_PUBLIC_CONNECTIONS_REFRESH_SECONDS` | conexões |
|
|
40
|
+
| `NEXT_PUBLIC_MESSAGES_REFRESH_SECONDS` | mensagens |
|
|
41
|
+
| `NEXT_PUBLIC_BACKLOG_REFRESH_SECONDS` | backlog |
|
|
42
|
+
| `NEXT_PUBLIC_DELIVERIES_REFRESH_SECONDS` | entregas |
|
|
43
|
+
| `NEXT_PUBLIC_DLQ_REFRESH_SECONDS` | DLQ |
|
|
44
|
+
|
|
45
|
+
> **Não confirmado se mudar estes valores tem efeito.** A UI lê cada uma com `process.env[nome]` dinâmico (`src/lib/ui-refresh.ts`); em componente client o Next só substitui acessos estáticos (`process.env.NEXT_PUBLIC_X`) no build. Se o intervalo não mudar após definir a variável, o padrão de 30 s está valendo. Tratar como pendência a verificar antes de contar com este ajuste.
|
|
46
|
+
|
|
47
|
+
## Exemplo mínimo de produção
|
|
48
|
+
|
|
49
|
+
```env
|
|
50
|
+
SEEDGRID_PULSE_SERVER_BASE_URL=https://pulse.<seu-dominio>
|
|
51
|
+
SEEDGRID_PULSE_INTERNAL_BASE_URL=http://seedgrid-pulse:8080
|
|
52
|
+
SEEDGRID_PULSE_UI_DEFAULT_LOCALE=pt-BR
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
No servidor correspondente: `CORS_ALLOWED_ORIGINS=https://pulse-ui.<seu-dominio>`.
|
|
56
|
+
|
|
57
|
+
## O que NÃO colocar na UI
|
|
58
|
+
|
|
59
|
+
- `SEEDGRID_PULSE_SERVER_KEY` (chave de servidor) — a UI não a usa e ela não publica.
|
|
60
|
+
- Qualquer chave `project` ou `client`.
|
|
61
|
+
- Usuário/senha de operador em ENV (removido; o login é pela tela).
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
---
|
|
2
|
+
tags: [seedgrid, produto, pulse, ui, nextjs]
|
|
3
|
+
fonte: seedgrid-products/seedgrid-pulse/frontend/seedgrid-pulse-ui
|
|
4
|
+
branch: main
|
|
5
|
+
commit: 9dcbdad
|
|
6
|
+
analisado-em: 2026-10-16
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Pulse UI — visão geral, instalação e execução
|
|
10
|
+
|
|
11
|
+
Painel web **operacional/administrativo** do Pulse (Next.js + React + `@seedgrid/fe-components`). É um componente separado do servidor: tem imagem, deploy e variáveis próprios. Variáveis: [[SeedGrid/Produtos/Pulse/UI/Configuracao|Configuração da UI]]. Servidor: [[SeedGrid/Produtos/Pulse/Servidor/Instalacao|Pulse (servidor)]].
|
|
12
|
+
|
|
13
|
+
Voltar: [[SeedGrid/Produtos/Pulse/Visao-geral|Visão geral do Pulse]]
|
|
14
|
+
|
|
15
|
+
## O que a UI faz
|
|
16
|
+
|
|
17
|
+
| Área | Telas |
|
|
18
|
+
|---|---|
|
|
19
|
+
| Visão operacional | dashboard, conexões ativas, métricas e agregados |
|
|
20
|
+
| Mensagens | listagem (mais recente primeiro), detalhe (entregas por destinatário e tentativas, com o motivo `result_timeout` traduzido), publicação manual (inclui o campo opcional "Prazo de execução (s)"), **lixeira** (filtro "Na lixeira") |
|
|
21
|
+
| Pendências | backlog, descarte |
|
|
22
|
+
| Falhas | DLQ (reprocessar, limpar), lixeira da DLQ |
|
|
23
|
+
| Entregas | entregas por destinatário |
|
|
24
|
+
| Contas | contas, chaves (criar, rotacionar, revogar), **lixeira de contas** |
|
|
25
|
+
| Segurança | usuários, perfis/permissions, auditoria |
|
|
26
|
+
| Configurações | ajustes de entrega em runtime (retry, TTL, retenção, lixeira) |
|
|
27
|
+
|
|
28
|
+
Idiomas: en, pt-BR, pt-PT, fr, es.
|
|
29
|
+
|
|
30
|
+
## Como ela autentica
|
|
31
|
+
|
|
32
|
+
A UI **não guarda credencial de conexão**. As telas usam o **JWT do operador logado** (login do `security`) e cada ação exige a **permission** correspondente (RBAC) — ver [[SeedGrid/Produtos/Pulse/Autenticacao-e-chaves|Autenticação e chaves]]. Antes existiam `NEXT_PUBLIC_PULSE_BASIC_USER/_PASSWORD`; foram removidas porque o Next as embutia no bundle e elas ficavam legíveis no HTML. A tela de publicação publica **como o operador** (`PULSE_MESSAGE_PUBLISH`), não com a chave de servidor.
|
|
33
|
+
|
|
34
|
+
## Instalação e execução
|
|
35
|
+
|
|
36
|
+
Requisitos: Node 22 (a imagem usa `node:22-bookworm-slim`; Next 16, React 19).
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
cd frontend/seedgrid-pulse-ui
|
|
40
|
+
npm install
|
|
41
|
+
npm run dev # http://127.0.0.1:3000
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Variáveis em `.env` (copie de `.env.example`). Com o `podman-compose`/`docker compose` da pasta, a UI sobe em `http://127.0.0.1:13000` junto de Pulse, Postgres e Redis.
|
|
45
|
+
|
|
46
|
+
Qualidade e testes:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npm run lint
|
|
50
|
+
npm run build
|
|
51
|
+
npm test # unitários (vitest)
|
|
52
|
+
npm run test:integration # sobe um mock do Pulse com testcontainers
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Imagem e deploy
|
|
56
|
+
|
|
57
|
+
- Imagem no GHCR: `ghcr.io/seedgrid/seedgrid-pulse-ui` (Confirmado — `.github/workflows/deploy.yml`).
|
|
58
|
+
- `push` em `main` com mudança em `frontend/**` publica a imagem e chama o webhook do EasyPanel (secret `EASYPANEL_DEPLOY_URL_PULSE_UI`).
|
|
59
|
+
- As variáveis são lidas em **runtime** pelo layout (`force-dynamic`): troca-se de ambiente mudando o env do container, **sem rebuild**.
|
|
60
|
+
|
|
61
|
+
## Rede: dois endereços do mesmo servidor
|
|
62
|
+
|
|
63
|
+
| Quem acessa | Variável | Exemplo |
|
|
64
|
+
|---|---|---|
|
|
65
|
+
| **Navegador** do operador | `SEEDGRID_PULSE_SERVER_BASE_URL` | `https://pulse.exemplo.com` |
|
|
66
|
+
| **Servidor da UI** (proxies `/api/security/*`, `/api/pulse/messages`) | `SEEDGRID_PULSE_INTERNAL_BASE_URL` | `http://seedgrid-pulse:8080` (mesma rede de containers) |
|
|
67
|
+
|
|
68
|
+
Se a UI e o servidor estão em containers na mesma rede, defina os dois; o interno é opcional e, ausente, usa o primeiro.
|
|
69
|
+
|
|
70
|
+
## Atenção
|
|
71
|
+
|
|
72
|
+
- A UI não deve receber `SEEDGRID_PULSE_SERVER_KEY`: a chave de servidor não publica e não pertence ao serviço da UI.
|
|
73
|
+
- O servidor precisa de `CORS_ALLOWED_ORIGINS` com a origem da UI.
|
|
74
|
+
- Papel `ADMIN` herda as permissions de lixeira (`PULSE_MESSAGE_DELETE/PURGE`, `PULSE_ACCOUNT_DELETE/PURGE`); outros perfis precisam recebê-las para ver os botões.
|