@seedgrid/ai-toolkit 0.3.2 → 0.3.3

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.
Files changed (43) hide show
  1. package/docs/formato.md +1 -1
  2. package/package.json +1 -1
  3. package/seedgridKB/SeedGrid/Extensions/Catalogo-de-propriedades.md +3 -2
  4. package/seedgridKB/SeedGrid/Extensions/Indice.md +1 -0
  5. package/seedgridKB/SeedGrid/Extensions/ai-pricing/Configuracao.md +11 -18
  6. package/seedgridKB/SeedGrid/Extensions/ai-pricing/Exemplos.md +2 -2
  7. package/seedgridKB/SeedGrid/Extensions/ai-pricing/Visao-geral.md +2 -2
  8. package/seedgridKB/SeedGrid/Extensions/business-days/Configuracao.md +36 -0
  9. package/seedgridKB/SeedGrid/Extensions/business-days/Exemplos.md +37 -0
  10. package/seedgridKB/SeedGrid/Extensions/business-days/Visao-geral.md +48 -0
  11. package/seedgridKB/SeedGrid/Extensions/exchange/Configuracao.md +10 -16
  12. package/seedgridKB/SeedGrid/Extensions/exchange/Exemplos.md +2 -2
  13. package/seedgridKB/SeedGrid/Extensions/exchange/Visao-geral.md +2 -2
  14. package/seedgridKB/SeedGrid/Extensions/login-tenancy/Configuracao.md +4 -5
  15. package/seedgridKB/SeedGrid/Extensions/login-tenancy/Visao-geral.md +1 -1
  16. package/seedgridKB/SeedGrid/Extensions/subdomain-tenancy/Configuracao.md +3 -2
  17. package/seedgridKB/SeedGrid/Extensions/subdomain-tenancy/Visao-geral.md +2 -2
  18. package/seedgridKB/SeedGrid/Mapa-dos-repositorios.md +9 -0
  19. package/seedgridKB/SeedGrid/Produtos/Pulse/Autenticacao-e-chaves.md +89 -0
  20. package/seedgridKB/SeedGrid/Produtos/Pulse/Exemplos.md +44 -0
  21. package/seedgridKB/SeedGrid/Produtos/Pulse/Protocolo-e-API.md +191 -0
  22. package/seedgridKB/SeedGrid/Produtos/Pulse/SDKs.md +287 -0
  23. package/seedgridKB/SeedGrid/Produtos/Pulse/Servidor/Configuracao.md +128 -0
  24. package/seedgridKB/SeedGrid/Produtos/Pulse/Servidor/Instalacao.md +105 -0
  25. package/seedgridKB/SeedGrid/Produtos/Pulse/Servidor/Operacao.md +86 -0
  26. package/seedgridKB/SeedGrid/Produtos/Pulse/Servidor/Providers.md +121 -0
  27. package/seedgridKB/SeedGrid/Produtos/Pulse/UI/Configuracao.md +61 -0
  28. package/seedgridKB/SeedGrid/Produtos/Pulse/UI/Visao-geral.md +74 -0
  29. package/seedgridKB/SeedGrid/Produtos/Pulse/Visao-geral.md +96 -0
  30. package/seedgridKB/SeedGrid/Toolkit/rules/backend-java-seedgrid.md +25 -1
  31. package/seedgridKB/SeedGrid/Toolkit/skills/sg-code-review/SKILL.md +1 -1
  32. package/seedgridKB/SeedGrid/Toolkit/skills/sg-crud-back/SKILL.md +1 -1
  33. package/seedgridKB/SeedGrid/Toolkit/skills/sg-crud-front/SKILL.md +3 -3
  34. package/seedgridKB/SeedGrid/Toolkit/skills/sg-new-screen/SKILL.md +2 -2
  35. package/seedgridKB/SeedGrid/Toolkit/skills/sg-new-skill/SKILL.md +20 -5
  36. package/seedgridKB/SeedGrid/Visao-geral.md +7 -0
  37. package/seedgridKB/manifest.json +7 -7
  38. /package/seedgridKB/SeedGrid/Toolkit/skills/sg-code-review/references/{checklist.md → code-review-checklist.md} +0 -0
  39. /package/seedgridKB/SeedGrid/Toolkit/skills/sg-crud-front/references/{checklist.md → crud-front-checklist.md} +0 -0
  40. /package/seedgridKB/SeedGrid/Toolkit/skills/sg-crud-front/references/{patterns.md → crud-front-patterns.md} +0 -0
  41. /package/seedgridKB/SeedGrid/Toolkit/skills/sg-crud-front/references/{routing.md → crud-front-routing.md} +0 -0
  42. /package/seedgridKB/SeedGrid/Toolkit/skills/sg-new-screen/references/{checklist.md → new-screen-checklist.md} +0 -0
  43. /package/seedgridKB/SeedGrid/Toolkit/skills/sg-new-screen/references/{steps.md → new-screen-steps.md} +0 -0
@@ -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.
@@ -0,0 +1,96 @@
1
+ ---
2
+ tags: [seedgrid, produto, pulse, realtime]
3
+ fonte: seedgrid-products/seedgrid-pulse
4
+ branch: main
5
+ commit: 9dcbdad
6
+ analisado-em: 2026-10-16
7
+ ---
8
+
9
+ # SeedGrid Pulse — visão geral
10
+
11
+ Hub **realtime** da plataforma SeedGrid: um produto (servidor Rust + UI Next.js + SDKs) que qualquer sistema SeedGrid usa para **publicar** eventos/comandos por HTTP e **entregar** a clientes conectados por WebSocket, sem reimplementar WebSocket, replay, retry, presença, backlog e isolamento de destino.
12
+
13
+ > O Pulse é um **produto** (`seedgrid-products/seedgrid-pulse`), não uma extension de `seedgrid-platform`. Ele *consome* crates da plataforma (security, login-tenancy, audit, apikeys); ver [[SeedGrid/Visao-geral|visão geral da plataforma]].
14
+
15
+ ## O que o Pulse resolve
16
+
17
+ | Necessidade | Como o Pulse atende |
18
+ |---|---|
19
+ | Backend precisa avisar usuário/grupo/conta inteira em tempo real | `POST /api/v1/messages` com a chave `project` |
20
+ | Navegador/app precisa receber, sem segredo no cliente | **token curto** (`pct_…`) emitido pelo backend do produto |
21
+ | Agente instalado na máquina do cliente precisa ficar conectado | chave `client` + WebSocket com reconexão e **replay** |
22
+ | Confirmar recebimento e execução | `ack` (recebimento) e `result` (execução, com retry e DLQ) |
23
+ | Operar: ver conexões, backlog, falhas, apagar com segurança | UI operacional, métricas Prometheus, lixeira e audit |
24
+
25
+ ## Duas funções: mensagens e tarefas
26
+
27
+ O Pulse faz dois trabalhos diferentes com o mesmo caminho `publisher → Pulse → subscriber`. Quem publica escolhe o trabalho com o `deliveryMode`:
28
+
29
+ | | **Mensagem** (envio simples) | **Tarefa** (execução) |
30
+ |---|---|---|
31
+ | Para que serve | avisar, notificar, atualizar tela: "o pedido mudou" | mandar alguém **fazer** algo e saber se deu certo: "renderize este relatório" |
32
+ | `deliveryMode` | `notification` (padrão) ou `acknowledged` | `processed` |
33
+ | O que o subscriber devolve | nada (`notification`) ou só o `ack` de recebimento (`acknowledged`) | `ack` e depois o `result`: `success`, `retryable` ou `permanent` |
34
+ | Se a execução falhar | não existe execução: não há o que falhar | retry automático e, esgotado o retry, **DLQ**; se o consumidor travar, o prazo de execução (`resultTimeoutSeconds`, Pulse 0.3.0) conta como falha |
35
+ | Termina quando | o servidor escreve no socket (`notification`) ou o `ack` chega (`acknowledged`) | `result: success` |
36
+ | Pode ir à DLQ | **nunca** | **sim**, e só ela |
37
+
38
+ Regra prática: se você só precisa que a informação **chegue**, use mensagem. Se precisa que algo seja **executado** e quer ser avisado (e poder reprocessar) quando falhar, use tarefa. Detalhes: [[SeedGrid/Produtos/Pulse/Protocolo-e-API#Delivery modes|Delivery modes]] e [[SeedGrid/Produtos/Pulse/Protocolo-e-API#DLQ: quando uma mensagem vai para lá|DLQ]].
39
+
40
+ ## Peças
41
+
42
+ | Peça | Onde (no repo) | Tecnologia |
43
+ |---|---|---|
44
+ | Servidor | `backend/` | Rust, Axum, Postgres, Redis opcional |
45
+ | UI operacional | `frontend/seedgrid-pulse-ui/` | Next.js + `@seedgrid/fe-components` |
46
+ | SDKs publisher | `components/publishers/` | Java, Next, Dart, PHP, Rust, Delphi |
47
+ | SDKs subscriber | `components/subscribers/` | React, Angular, Flutter, Rust, Delphi |
48
+ | Exemplos prontos | `examples/` | Delphi VCL, Flutter, React (e Angular) |
49
+ | Harness de integração | `integration/seedgrid-pulse-sdk-it/` | contra Pulse real |
50
+
51
+ Versão do servidor e da UI na análise: **0.3.0** (Confirmado — `backend/Cargo.toml`, `frontend/seedgrid-pulse-ui/package.json`).
52
+
53
+ ## Modelo mental (3 minutos)
54
+
55
+ ```
56
+ backend do produto ──(chave project)──▶ POST /api/v1/messages ─┐
57
+ ▼
58
+ navegador/app ◀──WebSocket── Pulse ◀── conta (fronteira de isolamento)
59
+ (token curto) │ └─ canal › grupo › usuário › evento
60
+ agente instalado ◀────────── │
61
+ (chave client) └─ pendente? fica guardado e é reentregue (replay)
62
+ ```
63
+
64
+ - **Conta** é a fronteira: entrega e replay nunca cruzam contas.
65
+ - **Credenciais têm papéis distintos** e nunca se substituem — ver [[SeedGrid/Produtos/Pulse/Autenticacao-e-chaves|Autenticação e chaves]].
66
+ - **Delivery mode** escolhe o ciclo de vida: `notification` (padrão), `acknowledged`, `processed` — ver [[SeedGrid/Produtos/Pulse/Protocolo-e-API|Protocolo e API]].
67
+
68
+ ## Mapa desta documentação
69
+
70
+ **Pulse (servidor)** — o backend Rust, com variáveis próprias:
71
+ - [[SeedGrid/Produtos/Pulse/Servidor/Instalacao|Instalação e execução]]
72
+ - [[SeedGrid/Produtos/Pulse/Servidor/Configuracao|Variáveis de ambiente do servidor]]
73
+ - [[SeedGrid/Produtos/Pulse/Servidor/Providers|Providers: Redis, Valkey, Dragonfly, NATS, RabbitMQ, Postgres]]
74
+ - [[SeedGrid/Produtos/Pulse/Servidor/Operacao|Operação: lixeira, retenção, auditoria, métricas, escala]]
75
+
76
+ **Pulse UI** — o painel Next.js, com variáveis próprias:
77
+ - [[SeedGrid/Produtos/Pulse/UI/Visao-geral|Visão geral, instalação e deploy]]
78
+ - [[SeedGrid/Produtos/Pulse/UI/Configuracao|Variáveis de ambiente da UI]]
79
+
80
+ **Transversal:**
81
+ - [[SeedGrid/Produtos/Pulse/Autenticacao-e-chaves|Autenticação, chaves, token curto e permissions]]
82
+ - [[SeedGrid/Produtos/Pulse/Protocolo-e-API|Protocolo realtime e API HTTP]]
83
+ - [[SeedGrid/Produtos/Pulse/SDKs|SDKs (publisher e subscriber por linguagem)]]
84
+ - [[SeedGrid/Produtos/Pulse/Exemplos|Exemplos executáveis (Delphi, Flutter, React, Angular)]]
85
+
86
+ ## Como usar o Pulse em um projeto SeedGrid (receita curta)
87
+
88
+ 1. Peça à operação do Pulse uma **conta** para o seu produto e as chaves: uma `project` (backend) e, se houver agentes, `client`.
89
+ 2. Guarde a chave `project` **só no backend** (env/secret). Nunca em código de navegador/mobile.
90
+ 3. No backend, instale o SDK **publisher** da sua linguagem e publique.
91
+ 4. Se o cliente é navegador/app: crie uma rota autenticada no backend que chama `issueConnectToken` com o `subject` **da sessão**; o front usa o SDK **subscriber** com `getToken`.
92
+ 5. Defina `channel`/`event` por convenção do produto (ex.: `orders` / `order.updated`) e use o `publicId` do usuário, nunca e-mail.
93
+
94
+ ## Confiabilidade das informações
95
+
96
+ Conteúdo extraído de `README.md`, `backend/README.md`, `backend/env.md`, `backend/PROTOCOL.md`, `backend/docs/LIXEIRA-mensagens-e-contas.md`, `backend/src/config.rs`, `backend/migrations/` e dos READMEs dos SDKs. Quando algo vem só de documentação (não relido no código nesta análise), a nota diz.
@@ -11,7 +11,31 @@ Regras **obrigatórias** para novos projetos e bibliotecas SeedGrid. Cada regra
11
11
  - **BE-02.** Toda pasta (pacote) no **plural**.
12
12
  - **BE-03.** Resources REST terminam em `Controller`, não `Resource` (`ClienteController`).
13
13
  - **BE-04.** Use sempre a biblioteca `seedgrid-commons` nos projetos.
14
- - **BE-05.** DTOs: sufixo `Request` para entrada e `Response` para saída; se o mesmo DTO serve aos dois, sufixo `DTO`. O Request tem só as propriedades necessárias (um update não precisa do `id`). O Response é "raso": ids e descrições em vez de objetos aninhados (`categoriaId`, `categoriaDescricao`).
14
+ - **BE-05.** DTOs: sufixo `DTOReq` para entrada (request) e `DTORes` para saída (response): `ClienteDTOReq`, `ClienteDTORes`.
15
+ - O **Req** leva só as propriedades necessárias (um update não precisa do `id`) e, para relacionamentos, **somente a chave estrangeira** pelo `publicId` (`cidadePublicId`), nunca campos nem objeto da entidade relacionada. Validações (`@NotNull`, `@Size`...) ficam no próprio record; para exigir os obrigatórios só no POST/PUT, use um grupo `Full extends Default` dentro do record.
16
+ - O **Res** é **plano** ("plain"): tudo no mesmo nível, sem objetos aninhados. Traz o `publicId` (nunca o `id` interno) e, para cada relacionamento, o `publicId` e a descrição (`cidadePublicId`, `cidadeDescricao`), inclusive os de mais de um nível (`paisPublicId`, `paisDescricao`). Pode existir mais de um Res para a mesma entidade, com menos campos, conforme o uso (por exemplo uma listagem enxuta).
17
+ - Records Java, na pasta `dtos/` (BE-01).
18
+
19
+ ```java
20
+ public record ClienteDTOReq(
21
+ @NotNull(groups = ClienteDTOReq.Full.class, message = "Informe o nome.")
22
+ @Pattern(regexp = ".*\\S.*", message = "Informe o nome.")
23
+ @Size(max = 255) String nome,
24
+ @NotNull(groups = ClienteDTOReq.Full.class) String cidadePublicId,
25
+ @NotNull(groups = ClienteDTOReq.Full.class) String categoriaPublicId
26
+ ) {
27
+ /** Grupo do POST/PUT: exige os obrigatórios. Estende Default para manter @Size e @Pattern. */
28
+ public interface Full extends Default {}
29
+ }
30
+
31
+ public record ClienteDTORes(
32
+ String publicId,
33
+ String nome,
34
+ String cidadePublicId, String cidadeDescricao,
35
+ String paisPublicId, String paisDescricao,
36
+ String categoriaPublicId, String categoriaDescricao
37
+ ) {}
38
+ ```
15
39
  - **BE-06.** Todo SPI criado é indexado com o `jandex-maven-plugin` (goal `jandex`).
16
40
 
17
41
  ## Injeção e exceptions
@@ -13,7 +13,7 @@ Encontre problemas reais e verificáveis; evite comentários de estilo sem impac
13
13
 
14
14
  1. **Escopo.** Obtenha o diff (por exemplo, `git diff` ou `git diff <base>...HEAD`) e o objetivo da mudança. Sem diff disponível, peça a lista de arquivos alterados.
15
15
  2. **Contexto.** Leia o código ao redor de cada trecho alterado e os pontos que o chamam.
16
- 3. **Análise.** Percorra o [checklist](references/checklist.md). Para cada suspeita, construa um cenário concreto: entrada/estado → comportamento errado.
16
+ 3. **Análise.** Percorra o [checklist](references/code-review-checklist.md). Para cada suspeita, construa um cenário concreto: entrada/estado → comportamento errado.
17
17
  4. **Filtro.** Descarte suspeitas que não sustentam um cenário concreto. Não reporte preferências pessoais como defeitos.
18
18
  5. **Verificações somente leitura.** Se útil, rode testes ou lint existentes para confirmar um achado. Não altere arquivos.
19
19
 
@@ -17,7 +17,7 @@ Monta um cadastro completo no padrão `.ai/rules/backend-java-seedgrid.md` (regr
17
17
  4. **Migration Flyway** (BE-20, BE-22, BE-24): tabela com `id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY`, as colunas da base escolhida (`public_id`, `created_at`, `updated_at` como `timestamptz`, `create_user_public_id`, `update_user_public_id`, e `active` só no `BaseEntity`; a lib não traz migrations), colunas cifradas com `VARCHAR(512)` e de hash com `VARCHAR(64)`, e `CREATE UNIQUE INDEX idx_<tabela>_public_id ON <tabela>(public_id)`. A pasta segue `db/migration/<projeto>`.
18
18
  5. **Repository** (`repositories/`, JPA puro em libs; Panache só em hosts, BE-21). Busca por campo cifrado usa o hash: `CryptoProvider.getSecureSearch().hashForSearch(valor, <mesma normalização>)`.
19
19
  6. **Service** (`services/`, injeção por construtor, BE-10): regras de negócio e exceptions tipadas (BE-11). Criar, alterar e excluir com `@Transactional` e `@Audit(entityFqcn = "...", operation = AuditOperationEnum.CREATE|UPDATE|DELETE, description = "...")` (BE-64). Para UPDATE/DELETE, o repository precisa expor `findByIdOptional` (é por ele que o `@Audit` captura o "antes").
20
- 7. **DTOs** (`dtos/`, BE-05): `...Request` só com o necessário, `...Response` raso, com `publicId` e **sem** `id`. Nada de dado pessoal em claro em respostas de erro ou log.
20
+ 7. **DTOs** (`dtos/`, BE-05): `...DTOReq` só com o necessário e relacionamentos apenas pela chave estrangeira (`cidadePublicId`); `...DTORes` plano, com `publicId` e **sem** `id`, e `publicId`+descrição de cada relacionamento (`cidadePublicId`, `cidadeDescricao`, `paisPublicId`...). Nada de dado pessoal em claro em respostas de erro ou log.
21
21
  8. **Controller** (`controllers/`, BE-03, BE-31): primeiro acrescente a seção do recurso em `RestControllerPath` (base, `..._BY_PUBLIC_ID`, `..._FULL`; o controller usa base e sub-paths, o teste usa os `_FULL`); `GET` paginado (`page`, `size`, `sortField`, `sortOrder`, com `LIKE` por prefixo, BE-32), `GET` por `publicId`, `POST`, `PUT`, `DELETE`. Proteja com `@PermissionsAllowed("<ENTIDADE>_READ|CREATE|EDIT|DELETE")` (ou `@RolesAllowed`), conforme a extension `security` (BE-65), e registre as permissões como o projeto faz.
22
22
  9. **Testes** (BE-40, BE-41): unitário do service e de integração do controller com Testcontainers + PostgreSQL, cobrindo CRUD, validação, permissão negada, **dado pessoal gravado cifrado** (consulta direta na coluna), busca pelo hash e registro de auditoria sem dado pessoal em claro. Vários asserts: `assertAll`.
23
23
  10. **Fechar** (BE-50): rode build e testes, remova o que sobrou e liste os TODO.
@@ -31,10 +31,10 @@ To register the menu item, icon and permission of a new screen, use the `sg-new-
31
31
 
32
32
  ## Required Patterns
33
33
 
34
- - Use the list/edit split described in `references/patterns.md`.
35
- - Use `publicId` routing and proxy conventions from `references/routing.md`.
34
+ - Use the list/edit split described in `references/crud-front-patterns.md`.
35
+ - Use `publicId` routing and proxy conventions from `references/crud-front-routing.md`.
36
36
  - Use `SgInputTextSearch` as the standard remote-search input.
37
- - Use the checklist in `references/checklist.md` before closing the task.
37
+ - Use the checklist in `references/crud-front-checklist.md` before closing the task.
38
38
 
39
39
  ## Required UI Components
40
40
 
@@ -19,7 +19,7 @@ Nao executar sem o usuario pedir.)
19
19
 
20
20
  ## Passo a passo
21
21
 
22
- Detalhes e exemplos de codigo de cada passo em `references/steps.md`.
22
+ Detalhes e exemplos de codigo de cada passo em `references/new-screen-steps.md`.
23
23
 
24
24
  1. **Permissao (backend)** - migration nova em `backend/src/main/resources/db/migration/app/`
25
25
  (`V3xxx__<assunto>.sql`, nunca editar uma ja aplicada): `insert into permissions` com o `audience` certo,
@@ -43,7 +43,7 @@ Detalhes e exemplos de codigo de cada passo em `references/steps.md`.
43
43
 
44
44
  ## Verificacao
45
45
 
46
- Rodar o checklist de `references/checklist.md` antes de encerrar. No minimo:
46
+ Rodar o checklist de `references/new-screen-checklist.md` antes de encerrar. No minimo:
47
47
 
48
48
  ```bash
49
49
  # os dois catalogos do cliente iguais (ignorando fim de linha)