@seedgrid/ai-toolkit 0.0.0-stage → 0.3.1

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 (226) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +162 -2
  3. package/dist/adapters/claude.js +114 -0
  4. package/dist/adapters/codex.js +108 -0
  5. package/dist/adapters/index.js +17 -0
  6. package/dist/adapters/shared.js +142 -0
  7. package/dist/adapters/types.js +1 -0
  8. package/dist/cli.js +209 -0
  9. package/dist/commands/common.js +98 -0
  10. package/dist/commands/doctor.js +290 -0
  11. package/dist/commands/init.js +9 -0
  12. package/dist/commands/install.js +107 -0
  13. package/dist/commands/remove.js +54 -0
  14. package/dist/commands/review.js +127 -0
  15. package/dist/commands/selfinstall.js +63 -0
  16. package/dist/commands/status.js +73 -0
  17. package/dist/commands/update.js +8 -0
  18. package/dist/commands/validate.js +27 -0
  19. package/dist/core/apply.js +181 -0
  20. package/dist/core/blocks.js +64 -0
  21. package/dist/core/content.js +528 -0
  22. package/dist/core/env.js +40 -0
  23. package/dist/core/frontmatter.js +29 -0
  24. package/dist/core/hash.js +14 -0
  25. package/dist/core/inspect.js +51 -0
  26. package/dist/core/lock.js +124 -0
  27. package/dist/core/paths.js +65 -0
  28. package/dist/core/plan.js +242 -0
  29. package/dist/core/tools.js +62 -0
  30. package/dist/core/types.js +11 -0
  31. package/dist/core/updates.js +121 -0
  32. package/docs/arquitetura.md +80 -0
  33. package/docs/compatibilidade.md +50 -0
  34. package/docs/formato.md +155 -0
  35. package/docs/instalacao.md +105 -0
  36. package/docs/manutencao.md +115 -0
  37. package/package.json +43 -4
  38. package/seedgridKB/SeedGrid/Extensions/Catalogo-de-enums.md +161 -0
  39. package/seedgridKB/SeedGrid/Extensions/Catalogo-de-propriedades.md +971 -0
  40. package/seedgridKB/SeedGrid/Extensions/Indice.md +63 -0
  41. package/seedgridKB/SeedGrid/Extensions/ai-pricing/Configuracao.md +124 -0
  42. package/seedgridKB/SeedGrid/Extensions/ai-pricing/Enums.md +40 -0
  43. package/seedgridKB/SeedGrid/Extensions/ai-pricing/Exemplos.md +97 -0
  44. package/seedgridKB/SeedGrid/Extensions/ai-pricing/Visao-geral.md +114 -0
  45. package/seedgridKB/SeedGrid/Extensions/apikeys/Configuracao-Rust.md +69 -0
  46. package/seedgridKB/SeedGrid/Extensions/apikeys/Configuracao.md +88 -0
  47. package/seedgridKB/SeedGrid/Extensions/apikeys/Enums.md +33 -0
  48. package/seedgridKB/SeedGrid/Extensions/apikeys/Exemplos.md +121 -0
  49. package/seedgridKB/SeedGrid/Extensions/apikeys/Rust.md +126 -0
  50. package/seedgridKB/SeedGrid/Extensions/apikeys/Visao-geral.md +111 -0
  51. package/seedgridKB/SeedGrid/Extensions/audit/Configuracao-Rust.md +93 -0
  52. package/seedgridKB/SeedGrid/Extensions/audit/Configuracao.md +127 -0
  53. package/seedgridKB/SeedGrid/Extensions/audit/Enums.md +66 -0
  54. package/seedgridKB/SeedGrid/Extensions/audit/Exemplos.md +151 -0
  55. package/seedgridKB/SeedGrid/Extensions/audit/Rust.md +120 -0
  56. package/seedgridKB/SeedGrid/Extensions/audit/Visao-geral.md +114 -0
  57. package/seedgridKB/SeedGrid/Extensions/backup/Configuracao-Rust.md +136 -0
  58. package/seedgridKB/SeedGrid/Extensions/backup/Configuracao.md +319 -0
  59. package/seedgridKB/SeedGrid/Extensions/backup/Enums.md +131 -0
  60. package/seedgridKB/SeedGrid/Extensions/backup/Exemplos.md +210 -0
  61. package/seedgridKB/SeedGrid/Extensions/backup/Rust.md +135 -0
  62. package/seedgridKB/SeedGrid/Extensions/backup/Visao-geral.md +150 -0
  63. package/seedgridKB/SeedGrid/Extensions/billing/Configuracao-Rust.md +86 -0
  64. package/seedgridKB/SeedGrid/Extensions/billing/Configuracao.md +243 -0
  65. package/seedgridKB/SeedGrid/Extensions/billing/Enums.md +165 -0
  66. package/seedgridKB/SeedGrid/Extensions/billing/Exemplos.md +205 -0
  67. package/seedgridKB/SeedGrid/Extensions/billing/Rust.md +109 -0
  68. package/seedgridKB/SeedGrid/Extensions/billing/Visao-geral.md +181 -0
  69. package/seedgridKB/SeedGrid/Extensions/broker/Configuracao-Rust.md +40 -0
  70. package/seedgridKB/SeedGrid/Extensions/broker/Visao-geral.md +114 -0
  71. package/seedgridKB/SeedGrid/Extensions/cache/Configuracao-Rust.md +73 -0
  72. package/seedgridKB/SeedGrid/Extensions/cache/Configuracao.md +112 -0
  73. package/seedgridKB/SeedGrid/Extensions/cache/Enums.md +36 -0
  74. package/seedgridKB/SeedGrid/Extensions/cache/Exemplos.md +149 -0
  75. package/seedgridKB/SeedGrid/Extensions/cache/Rust.md +81 -0
  76. package/seedgridKB/SeedGrid/Extensions/cache/Visao-geral.md +90 -0
  77. package/seedgridKB/SeedGrid/Extensions/commons/Configuracao.md +107 -0
  78. package/seedgridKB/SeedGrid/Extensions/commons/Enums.md +105 -0
  79. package/seedgridKB/SeedGrid/Extensions/commons/Exemplos.md +141 -0
  80. package/seedgridKB/SeedGrid/Extensions/commons/Visao-geral.md +99 -0
  81. package/seedgridKB/SeedGrid/Extensions/exchange/Configuracao.md +122 -0
  82. package/seedgridKB/SeedGrid/Extensions/exchange/Enums.md +29 -0
  83. package/seedgridKB/SeedGrid/Extensions/exchange/Exemplos.md +82 -0
  84. package/seedgridKB/SeedGrid/Extensions/exchange/Visao-geral.md +118 -0
  85. package/seedgridKB/SeedGrid/Extensions/filemanagement/Configuracao-Rust.md +110 -0
  86. package/seedgridKB/SeedGrid/Extensions/filemanagement/Configuracao.md +157 -0
  87. package/seedgridKB/SeedGrid/Extensions/filemanagement/Exemplos.md +157 -0
  88. package/seedgridKB/SeedGrid/Extensions/filemanagement/Rust.md +70 -0
  89. package/seedgridKB/SeedGrid/Extensions/filemanagement/Visao-geral.md +88 -0
  90. package/seedgridKB/SeedGrid/Extensions/login-tenancy/Configuracao-Rust.md +124 -0
  91. package/seedgridKB/SeedGrid/Extensions/login-tenancy/Configuracao.md +195 -0
  92. package/seedgridKB/SeedGrid/Extensions/login-tenancy/Enums.md +71 -0
  93. package/seedgridKB/SeedGrid/Extensions/login-tenancy/Exemplos.md +149 -0
  94. package/seedgridKB/SeedGrid/Extensions/login-tenancy/Rust.md +139 -0
  95. package/seedgridKB/SeedGrid/Extensions/login-tenancy/Visao-geral.md +130 -0
  96. package/seedgridKB/SeedGrid/Extensions/notification/Configuracao.md +141 -0
  97. package/seedgridKB/SeedGrid/Extensions/notification/Enums.md +52 -0
  98. package/seedgridKB/SeedGrid/Extensions/notification/Exemplos.md +141 -0
  99. package/seedgridKB/SeedGrid/Extensions/notification/Visao-geral.md +113 -0
  100. package/seedgridKB/SeedGrid/Extensions/privacy/Configuracao-Rust.md +67 -0
  101. package/seedgridKB/SeedGrid/Extensions/privacy/Configuracao.md +94 -0
  102. package/seedgridKB/SeedGrid/Extensions/privacy/Enums.md +79 -0
  103. package/seedgridKB/SeedGrid/Extensions/privacy/Exemplos.md +172 -0
  104. package/seedgridKB/SeedGrid/Extensions/privacy/Rust.md +107 -0
  105. package/seedgridKB/SeedGrid/Extensions/privacy/Visao-geral.md +90 -0
  106. package/seedgridKB/SeedGrid/Extensions/realtime/Configuracao-Rust.md +72 -0
  107. package/seedgridKB/SeedGrid/Extensions/realtime/Configuracao.md +104 -0
  108. package/seedgridKB/SeedGrid/Extensions/realtime/Exemplos.md +104 -0
  109. package/seedgridKB/SeedGrid/Extensions/realtime/Rust.md +69 -0
  110. package/seedgridKB/SeedGrid/Extensions/realtime/Visao-geral.md +105 -0
  111. package/seedgridKB/SeedGrid/Extensions/resilience/Configuracao-Rust.md +68 -0
  112. package/seedgridKB/SeedGrid/Extensions/resilience/Configuracao.md +186 -0
  113. package/seedgridKB/SeedGrid/Extensions/resilience/Enums.md +96 -0
  114. package/seedgridKB/SeedGrid/Extensions/resilience/Exemplos.md +229 -0
  115. package/seedgridKB/SeedGrid/Extensions/resilience/Rust.md +80 -0
  116. package/seedgridKB/SeedGrid/Extensions/resilience/Visao-geral.md +112 -0
  117. package/seedgridKB/SeedGrid/Extensions/runtime/Configuracao-Rust.md +90 -0
  118. package/seedgridKB/SeedGrid/Extensions/runtime/Visao-geral.md +114 -0
  119. package/seedgridKB/SeedGrid/Extensions/security/Configuracao-Rust.md +327 -0
  120. package/seedgridKB/SeedGrid/Extensions/security/Configuracao.md +510 -0
  121. package/seedgridKB/SeedGrid/Extensions/security/Enums.md +95 -0
  122. package/seedgridKB/SeedGrid/Extensions/security/Exemplos.md +218 -0
  123. package/seedgridKB/SeedGrid/Extensions/security/Rust.md +203 -0
  124. package/seedgridKB/SeedGrid/Extensions/security/Visao-geral.md +131 -0
  125. package/seedgridKB/SeedGrid/Extensions/subdomain-tenancy/Configuracao-Rust.md +188 -0
  126. package/seedgridKB/SeedGrid/Extensions/subdomain-tenancy/Configuracao.md +345 -0
  127. package/seedgridKB/SeedGrid/Extensions/subdomain-tenancy/Enums.md +117 -0
  128. package/seedgridKB/SeedGrid/Extensions/subdomain-tenancy/Exemplos.md +205 -0
  129. package/seedgridKB/SeedGrid/Extensions/subdomain-tenancy/Rust.md +161 -0
  130. package/seedgridKB/SeedGrid/Extensions/subdomain-tenancy/Visao-geral.md +142 -0
  131. package/seedgridKB/SeedGrid/Extensions/whatsapp/Configuracao-Rust.md +75 -0
  132. package/seedgridKB/SeedGrid/Extensions/whatsapp/Configuracao.md +152 -0
  133. package/seedgridKB/SeedGrid/Extensions/whatsapp/Enums.md +198 -0
  134. package/seedgridKB/SeedGrid/Extensions/whatsapp/Exemplos.md +173 -0
  135. package/seedgridKB/SeedGrid/Extensions/whatsapp/Rust.md +83 -0
  136. package/seedgridKB/SeedGrid/Extensions/whatsapp/Visao-geral.md +99 -0
  137. package/seedgridKB/SeedGrid/Mapa-dos-repositorios.md +112 -0
  138. package/seedgridKB/SeedGrid/SeedGrid-components/Indice.md +323 -0
  139. package/seedgridKB/SeedGrid/SeedGrid-components/buttons/API.md +257 -0
  140. package/seedgridKB/SeedGrid/SeedGrid-components/buttons/Exemplos.md +307 -0
  141. package/seedgridKB/SeedGrid/SeedGrid-components/buttons/Visao-geral.md +51 -0
  142. package/seedgridKB/SeedGrid/SeedGrid-components/datatable/API.md +174 -0
  143. package/seedgridKB/SeedGrid/SeedGrid-components/datatable/Exemplos.md +236 -0
  144. package/seedgridKB/SeedGrid/SeedGrid-components/datatable/Visao-geral.md +76 -0
  145. package/seedgridKB/SeedGrid/SeedGrid-components/digits/API.md +339 -0
  146. package/seedgridKB/SeedGrid/SeedGrid-components/digits/Exemplos.md +311 -0
  147. package/seedgridKB/SeedGrid/SeedGrid-components/digits/Visao-geral.md +57 -0
  148. package/seedgridKB/SeedGrid/SeedGrid-components/editor/API.md +125 -0
  149. package/seedgridKB/SeedGrid/SeedGrid-components/editor/Exemplos.md +116 -0
  150. package/seedgridKB/SeedGrid/SeedGrid-components/editor/Visao-geral.md +86 -0
  151. package/seedgridKB/SeedGrid/SeedGrid-components/feedback-e-exibicao/API.md +490 -0
  152. package/seedgridKB/SeedGrid/SeedGrid-components/feedback-e-exibicao/Exemplos.md +544 -0
  153. package/seedgridKB/SeedGrid/SeedGrid-components/feedback-e-exibicao/Visao-geral.md +69 -0
  154. package/seedgridKB/SeedGrid/SeedGrid-components/fundamentos/API.md +113 -0
  155. package/seedgridKB/SeedGrid/SeedGrid-components/fundamentos/Exemplos.md +159 -0
  156. package/seedgridKB/SeedGrid/SeedGrid-components/fundamentos/Visao-geral.md +92 -0
  157. package/seedgridKB/SeedGrid/SeedGrid-components/gadgets/API.md +516 -0
  158. package/seedgridKB/SeedGrid/SeedGrid-components/gadgets/Exemplos.md +629 -0
  159. package/seedgridKB/SeedGrid/SeedGrid-components/gadgets/Visao-geral.md +80 -0
  160. package/seedgridKB/SeedGrid/SeedGrid-components/inputs-selecao/API.md +615 -0
  161. package/seedgridKB/SeedGrid/SeedGrid-components/inputs-selecao/Exemplos.md +384 -0
  162. package/seedgridKB/SeedGrid/SeedGrid-components/inputs-selecao/Visao-geral.md +111 -0
  163. package/seedgridKB/SeedGrid/SeedGrid-components/inputs-texto/API.md +661 -0
  164. package/seedgridKB/SeedGrid/SeedGrid-components/inputs-texto/Exemplos.md +312 -0
  165. package/seedgridKB/SeedGrid/SeedGrid-components/inputs-texto/Visao-geral.md +123 -0
  166. package/seedgridKB/SeedGrid/SeedGrid-components/layout/API.md +1090 -0
  167. package/seedgridKB/SeedGrid/SeedGrid-components/layout/Exemplos.md +1172 -0
  168. package/seedgridKB/SeedGrid/SeedGrid-components/layout/Visao-geral.md +98 -0
  169. package/seedgridKB/SeedGrid/SeedGrid-components/modulos/Visao-geral.md +98 -0
  170. package/seedgridKB/SeedGrid/SeedGrid-components/modulos/fe-apikeys.md +118 -0
  171. package/seedgridKB/SeedGrid/SeedGrid-components/modulos/fe-audit.md +88 -0
  172. package/seedgridKB/SeedGrid/SeedGrid-components/modulos/fe-backup.md +131 -0
  173. package/seedgridKB/SeedGrid/SeedGrid-components/modulos/fe-billing-platform.md +132 -0
  174. package/seedgridKB/SeedGrid/SeedGrid-components/modulos/fe-billing-user.md +120 -0
  175. package/seedgridKB/SeedGrid/SeedGrid-components/modulos/fe-login-tenancy.md +119 -0
  176. package/seedgridKB/SeedGrid/SeedGrid-components/modulos/fe-security.md +427 -0
  177. package/seedgridKB/SeedGrid/SeedGrid-components/modulos/fe-self-enter.md +104 -0
  178. package/seedgridKB/SeedGrid/SeedGrid-components/modulos/fe-subdomain-tenancy.md +110 -0
  179. package/seedgridKB/SeedGrid/SeedGrid-components/navegacao-e-overlay/API.md +490 -0
  180. package/seedgridKB/SeedGrid/SeedGrid-components/navegacao-e-overlay/Exemplos.md +561 -0
  181. package/seedgridKB/SeedGrid/SeedGrid-components/navegacao-e-overlay/Visao-geral.md +82 -0
  182. package/seedgridKB/SeedGrid/SeedGrid-components/pacotes/Visao-geral.md +68 -0
  183. package/seedgridKB/SeedGrid/SeedGrid-components/pacotes/fe-commons.md +61 -0
  184. package/seedgridKB/SeedGrid/SeedGrid-components/pacotes/fe-core.md +140 -0
  185. package/seedgridKB/SeedGrid/SeedGrid-components/pacotes/fe-playground.md +112 -0
  186. package/seedgridKB/SeedGrid/SeedGrid-components/pacotes/fe-theme.md +97 -0
  187. package/seedgridKB/SeedGrid/SeedGrid-components/providers/API.md +177 -0
  188. package/seedgridKB/SeedGrid/SeedGrid-components/providers/Exemplos.md +332 -0
  189. package/seedgridKB/SeedGrid/SeedGrid-components/providers/Visao-geral.md +106 -0
  190. package/seedgridKB/SeedGrid/SeedGrid-components/showcase.md +70 -0
  191. package/seedgridKB/SeedGrid/Toolkit/agents/arquiteto.md +53 -0
  192. package/seedgridKB/SeedGrid/Toolkit/agents/backend-java.md +45 -0
  193. package/seedgridKB/SeedGrid/Toolkit/agents/backend-rust.md +43 -0
  194. package/seedgridKB/SeedGrid/Toolkit/agents/frontend-react.md +41 -0
  195. package/seedgridKB/SeedGrid/Toolkit/agents/qa.md +44 -0
  196. package/seedgridKB/SeedGrid/Toolkit/agents/revisor.md +40 -0
  197. package/seedgridKB/SeedGrid/Toolkit/references/fluxo-de-trabalho.md +78 -0
  198. package/seedgridKB/SeedGrid/Toolkit/references/glossario.md +15 -0
  199. package/seedgridKB/SeedGrid/Toolkit/references/modos-shared-native.md +27 -0
  200. package/seedgridKB/SeedGrid/Toolkit/rules/backend-java-seedgrid.md +54 -0
  201. package/seedgridKB/SeedGrid/Toolkit/rules/coordenacao.md +39 -0
  202. package/seedgridKB/SeedGrid/Toolkit/rules/formato-entrega.md +29 -0
  203. package/seedgridKB/SeedGrid/Toolkit/rules/frontend-seedgrid.md +47 -0
  204. package/seedgridKB/SeedGrid/Toolkit/rules/personalizacao-local.md +22 -0
  205. package/seedgridKB/SeedGrid/Toolkit/skills/planejar-mudanca/SKILL.md +38 -0
  206. package/seedgridKB/SeedGrid/Toolkit/skills/revisar-codigo/SKILL.md +33 -0
  207. package/seedgridKB/SeedGrid/Toolkit/skills/revisar-codigo/references/checklist.md +25 -0
  208. package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-backend-crud/SKILL.md +29 -0
  209. package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-bump/SKILL.md +26 -0
  210. package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-crud/SKILL.md +221 -0
  211. package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-crud/agents/openai.yaml +4 -0
  212. package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-crud/references/checklist.md +31 -0
  213. package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-crud/references/patterns.md +185 -0
  214. package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-crud/references/routing.md +66 -0
  215. package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-new-screen/SKILL.md +56 -0
  216. package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-new-screen/agents/openai.yaml +4 -0
  217. package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-new-screen/references/checklist.md +32 -0
  218. package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-new-screen/references/steps.md +114 -0
  219. package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-review/SKILL.md +61 -0
  220. package/seedgridKB/SeedGrid/Toolkit/skills/validar-mudanca/SKILL.md +29 -0
  221. package/seedgridKB/SeedGrid/Toolkit/templates/decisao-arquitetura.md +29 -0
  222. package/seedgridKB/SeedGrid/Toolkit/templates/especificacao-tarefa.md +32 -0
  223. package/seedgridKB/SeedGrid/Toolkit/templates/relatorio-validacao.md +30 -0
  224. package/seedgridKB/SeedGrid/Versoes.md +64 -0
  225. package/seedgridKB/SeedGrid/Visao-geral.md +35 -0
  226. package/seedgridKB/manifest.json +142 -0
@@ -0,0 +1,107 @@
1
+ ---
2
+ tags: [seedgrid, extension, privacy, rust]
3
+ fonte: rust/seedgrid-rust-crate-privacy
4
+ branch: main
5
+ commit: be738a2d1e
6
+ analisado-em: 2026-10-14
7
+ ---
8
+
9
+ # privacy — porte Rust (`seedgrid-rust-crate-privacy`)
10
+
11
+ Porte da lib Java `seedgrid-quarkus-lib-privacy`. Lado Java: [[SeedGrid/Extensions/privacy/Visao-geral|Visão geral do privacy (Java)]] · [[SeedGrid/Extensions/privacy/Configuracao|Configuração do privacy (Java)]]. Configuração Rust: [[SeedGrid/Extensions/privacy/Configuracao-Rust|Configuração Rust do privacy]].
12
+
13
+ Base de privacidade LGPD/PII com duas capacidades: (1) **mascaramento** de dados pessoais em JSON/objetos; (2) **criptografia de campo at-rest** AES-256-GCM com **hash de busca** determinístico HMAC-SHA256. Crate puro (sem Axum/DB). **Confirmado** (`src/lib.rs`).
14
+
15
+ ## Identificação
16
+ | Item | Valor |
17
+ |---|---|
18
+ | Pacote Cargo | `seedgrid-rust-crate-privacy` (lib `seedgrid_privacy`) |
19
+ | Versão | workspace `2026.10.14` |
20
+ | Features | nenhuma |
21
+ | Dependência SeedGrid | `seedgrid-macros` (derive `PersonalData`) |
22
+ | Consumidores (Cargo.toml) | audit (reexporta `masking`), login-tenancy, security, subdomain-tenancy |
23
+
24
+ ## API pública
25
+ | Módulo / símbolo | Papel |
26
+ |---|---|
27
+ | `masking`: `MaskingStrategy` (`Full`, `Format`, `Partial`, `Hash`, `Template`, `Remove`), `MaskRule` (`format`, `hash`, `remove`…), `mask_json`, `PersonalDataResolver`, `PersonalDataSanitizer`, `ResolvedRule`, `masker::{cpf, cnpj, cep}`, `sha256_hex` | mascaramento; caminhos `a.b`, `lista[].campo`; regra repetida segue a ordem de inserção do `LinkedHashMap` Java |
28
+ | `crypto`: `CryptoService`, `AesGcmCryptoService::from_key_spec` / `from_raw_key`, `looks_encrypted`, `VERSION_PREFIX` (`v1`), `CryptoError` | cifra; formato `v1:BASE64(iv):BASE64(ct‖tag)` igual ao Java |
29
+ | `search`: `SearchHashService`, `HmacSha256SearchHashService::from_key_spec`, `SearchNormalization` (`None`, `Canonical`, `Email`), `ValueNormalizer`, `DefaultValueNormalizer`, `SecureSearch`, `EncryptedFieldSearch` | hash de busca |
30
+ | `field`: `CryptoProvider` (estado global), `EncryptedFieldConverter` (`from_provider`, `with_service`), `EncryptedFieldListener`, `SecureFieldsCarrier`, `SecureFieldDescriptor`, `apply_search_hashes_via_provider`, `FieldError`; constantes `ENCRYPTION_ENABLED_PROPERTY`, `CRYPTO_KEY_PROPERTY`, `SEARCH_KEY_PROPERTY` | integração com entidades (sem reflexão/JPA) |
31
+ | `#[derive(PersonalData)]` (de `seedgrid-macros`) | gera `SecureFieldsCarrier` + `encrypt_personal_data`/`decrypt_personal_data` a partir de `#[personal_data(search = "...", normalize = "...")]` |
32
+
33
+ ### `CryptoProvider` (global)
34
+ - `is_encryption_enabled()`: override programático (`set_encryption_enabled_for_tests`) vence; senão lê `SEEDGRID_PRIVACY_ENCRYPTION_ENABLED`; padrão `false`.
35
+ - `get_crypto_service()` / `get_search_hash_service()`: o serviço configurado (`configure`, `configure_with_key`, `configure_search_hash_service`, `configure_search_with_key`) vence; senão é construído **sob demanda** a partir de `SEEDGRID_PRIVACY_CRYPTO_KEY` / `SEEDGRID_PRIVACY_SEARCH_KEY` e guardado em cache. Chave inválida → `None`.
36
+ - `get_secure_search()`, `configure_normalizer`, `get_normalizer`, `reset_for_tests`.
37
+
38
+ Fonte: `src/field.rs` → `impl CryptoProvider`. Detalhes em [[SeedGrid/Extensions/privacy/Configuracao-Rust|Configuração Rust]].
39
+
40
+ ## Exemplos
41
+ Mascaramento:
42
+ ```rust
43
+ use seedgrid_privacy::{mask_json, MaskRule, masker};
44
+ use serde_json::json;
45
+
46
+ let v = json!({ "cpf": "12345678900", "nome": "Joao", "email": "joao@x.com" });
47
+ let out = mask_json(&v, &[
48
+ MaskRule::format("cpf", "***.***.***-**"),
49
+ MaskRule::hash("email"),
50
+ MaskRule::remove("nome"),
51
+ ]);
52
+ assert_eq!(masker::cpf(Some("12345678900")), "***.***.***-00");
53
+ ```
54
+ Derive (de `tests/personal_data_derive.rs`):
55
+ ```rust
56
+ use seedgrid_privacy::{CryptoProvider, PersonalData, SecureFieldsCarrier};
57
+
58
+ #[derive(PersonalData, Default)]
59
+ struct User {
60
+ #[personal_data(search = "email_hash", normalize = "email")]
61
+ email: String,
62
+ email_hash: Option<String>,
63
+ #[personal_data(search = "whats_app_hash")] // normalize padrão = canonical
64
+ whats_app: Option<String>,
65
+ whats_app_hash: Option<String>,
66
+ #[personal_data] // cifra sem gerar hash
67
+ cnpj: Option<String>,
68
+ }
69
+ ```
70
+
71
+ ## Testes
72
+ Unitários em `src/*` (vetores portados do Java, ex.: `SHA-256("abc")`) e `tests/personal_data_derive.rs`. **Não executados.** Sem exemplo em `rust/examples/` (o `seedgrid-login-tenancy-example` usa a crate indiretamente).
73
+
74
+ ## Notas de comportamento
75
+
76
+ - **Chave ausente/inválida com cifra ligada**: falha (fail-closed); o Rust devolve `CryptoError::InvalidKey` em vez de gravar em claro (`EncryptedFieldConverter::resolve_for_write`). Chave AES > 32 bytes é rejeitada (sem truncar).
77
+ - As mensagens de erro de chave inválida citam `seedgrid.crypto.key` / `seedgrid.search.key` (`src/crypto.rs`, `src/search.rs` → `decode_key`); a propriedade Java é `seedgrid.privacy.crypto.key`.
78
+ - `PARTIAL` com parâmetro negativo cai no padrão 2; `PARTIAL`/`TEMPLATE` contam caracteres Unicode (Java conta UTF-16).
79
+ - Os enums `CryptoAlgorithm`/`SearchAlgorithm` não existem no Rust.
80
+
81
+ ## Enums
82
+ Java: [[SeedGrid/Extensions/privacy/Enums|Enums do privacy (Java)]].
83
+
84
+ | Enum | Arquivo | Java equivalente |
85
+ |---|---|---|
86
+ | `MaskingStrategy` | `src/masking.rs` | [[SeedGrid/Extensions/privacy/Enums#MaskingStrategy\|MaskingStrategy]] |
87
+ | `SearchNormalization` | `src/search.rs` | [[SeedGrid/Extensions/privacy/Enums#SearchNormalization\|SearchNormalization]] |
88
+ | `CryptoError`, `FieldError` | `src/crypto.rs`, `src/field.rs` | exceções |
89
+
90
+ ### MaskingStrategy
91
+ Variantes: `Full`, `Format`, `Partial`, `Hash`, `Template`, `Remove` (os mesmos 6 valores do Java). Sem serde; as regras são montadas por código (`MaskRule::format/hash/remove…`).
92
+
93
+ | Valor | Efeito (`mask_value`) |
94
+ |---|---|
95
+ | `Full` | valor fixo = `param` ou `***` |
96
+ | `Format` | `param` como máscara pronta (vazio → `***`) |
97
+ | `Partial` | só os últimos N caracteres visíveis (`param` = N, padrão 2; negativo cai em 2 — o Java estoura) |
98
+ | `Hash` | SHA-256 hex minúsculo |
99
+ | `Template` | `#` revela, `*` mascara, outro char é literal |
100
+ | `Remove` | estrutural: remove o campo (`is_removal()`; `mask_value` devolve `None`) |
101
+
102
+ Conta caracteres Unicode (o Java conta unidades UTF-16).
103
+
104
+ ### SearchNormalization
105
+ `None` (padrão), `Canonical`, `Email` — iguais ao Java (`NONE`, `CANONICAL`, `EMAIL`). `None` = valor exato; `Canonical` = trim + NFD sem acentos + minúsculas + só `[a-z0-9]`; `Email` = trim + minúsculas. No derive: `normalize = "none"|"canonical"|"email"` (padrão `canonical`). Sem serde.
106
+
107
+ `CryptoAlgorithm` (`AES_256_GCM`) e `SearchAlgorithm` (`HMAC_SHA256`) do Java **não existem** no Rust (o algoritmo é fixo).
@@ -0,0 +1,90 @@
1
+ ---
2
+ tags: [seedgrid, library, privacy]
3
+ fonte: java/seedgrid-quarkus-lib-privacy
4
+ branch: main
5
+ commit: 79f8b03eeb
6
+ analisado-em: 2026-10-14
7
+ ---
8
+
9
+ # SeedGrid Privacy — Visão geral
10
+
11
+ > [!info] Library, não extension Quarkus
12
+ > `seedgrid-quarkus-lib-privacy` é uma **library Java** (jar único com índice Jandex), **não** uma extension Quarkus com `runtime`/`deployment`. Não há `@ConfigRoot`/`@ConfigMapping`; a config é lida via `ConfigProvider`. Documentada nesta estrutura por uniformidade.
13
+
14
+ Configuração: [[SeedGrid/Extensions/privacy/Configuracao|Configuração do privacy]] · Enums: [[SeedGrid/Extensions/privacy/Enums|Enums do privacy]] · Exemplos: [[SeedGrid/Extensions/privacy/Exemplos|Exemplos do privacy]] · [[SeedGrid/Extensions/privacy/Rust|Porte Rust]]
15
+
16
+ ## Objetivo
17
+
18
+ Primitivas de privacidade (LGPD/GDPR) para entidades JPA. **Confirmado** (`README.md`, código):
19
+ 1. **Secure Fields** — cifra reversível de campos `String` no banco (AES-256-GCM, formato `v1:base64(iv):base64(ciphertext)`) e hash determinístico HMAC-SHA256 (hex, 64 chars) num campo irmão para busca por igualdade. **Opt-in** por `seedgrid.privacy.encryption.enabled` (padrão desligado → grava valor cru).
20
+ 2. **Masking de PII** — redação one-way nas saídas (auditoria, export, e-mail, log, resposta de API) via `@PersonalData`/`@MaskRule` + `PersonalDataSanitizer`, ou valor a valor com `PersonalDataMasker`. Não usa chave e funciona nos dois modos.
21
+
22
+ ## Coordenadas e dependências
23
+
24
+ | Item | Valor |
25
+ |---|---|
26
+ | groupId:artifactId | `br.com.seedgrid:seedgrid-privacy` |
27
+ | Versão (pom) | `2026.07.27` |
28
+ | Parent | `br.com.seedgrid:seedgrid-parent:2026.07.02` |
29
+ | Dependências | `quarkus-arc`, `quarkus-hibernate-orm`, `quarkus-jackson`; testes: `quarkus-junit5`, AssertJ, Mockito, PostgreSQL + Testcontainers |
30
+ | Dependências SeedGrid | nenhuma. É usada por `seedgrid-commons` (embeddables `Address`/`Contact`) e por extensions (audit, security, subdomain-tenancy — segundo o README) |
31
+
32
+ Fonte: `java/seedgrid-quarkus-lib-privacy/pom.xml`. **Confirmado.**
33
+
34
+ ## Arquitetura
35
+
36
+ ```mermaid
37
+ flowchart TB
38
+ subgraph SF["Secure Fields (estático, sem CDI no caminho JPA)"]
39
+ BOOT["CryptoBootstrap<br/>@Singleton @Startup"] -->|"se chaves presentes"| CP["CryptoProvider<br/>(estado estático)"]
40
+ CONV["EncryptedFieldAttributeConverter<br/>@Convert"] --> CP
41
+ LIS["EncryptedFieldListener<br/>@EntityListeners"] --> CP
42
+ SRCH["EncryptedFieldSearch"] --> CP
43
+ CP --> AES["AesGcmCryptoService<br/>(crypto.key)"]
44
+ CP --> HMAC["HmacSha256SearchHashService<br/>(search.key)"]
45
+ end
46
+ subgraph MK["Masking (CDI)"]
47
+ SAN["PersonalDataSanitizer<br/>@ApplicationScoped"] --> RES["PersonalDataResolver<br/>@ApplicationScoped (cache por classe)"]
48
+ MASK["PersonalDataMasker (estático)"] --> STRAT["MaskingStrategy"]
49
+ SAN --> STRAT
50
+ end
51
+ ```
52
+
53
+ Fluxo do Secure Fields (**Confirmado**):
54
+ - **Escrita** (`EncryptedFieldAttributeConverter#convertToDatabaseColumn`): flag desligado → grava cru; ligado → cifra (valor já `v1:` não é recifrado).
55
+ - **Leitura** (`convertToEntityAttribute`): segue o **dado**, não o flag — valor `v1:...` é decifrado (exige `crypto.key`), valor cru volta como está.
56
+ - **Hash** (`EncryptedFieldListener`, `@PrePersist`/`@PreUpdate`): só se `@EncryptedField.searchField` estiver preenchido e o flag ligado; aplica `SearchNormalization` (`NONE`/`CANONICAL`/`EMAIL`), desce recursivamente em campos `@Embeddable` (profundidade máx. 5); o campo de hash deve ser **irmão** no mesmo objeto, senão `IllegalStateException`.
57
+ - **Busca**: `EncryptedFieldSearch#hashForSearch(valor[, normalização])` — usar a mesma normalização da anotação; `hashForSearch(valor)` usa `CANONICAL`.
58
+ - `CryptoBootstrap` (startup) configura os serviços se as chaves existirem; senão os serviços são criados lazy no primeiro uso.
59
+
60
+ ## APIs públicas
61
+
62
+ | Pacote/Símbolo | Papel |
63
+ |---|---|
64
+ | `@EncryptedField(searchField, normalize)` | marca campo `String` sensível (cifra sempre AES-256-GCM e hash sempre HMAC-SHA256) |
65
+ | `EncryptedFieldAttributeConverter` | `AttributeConverter<String,String>` (`@Converter`, aplicar com `@Convert`) |
66
+ | `EncryptedFieldListener` | entity listener (`@EntityListeners`) |
67
+ | `EncryptedFieldSearch` | `hashForSearch(String)`, `hashForSearch(String, SearchNormalization)` |
68
+ | `CryptoProvider` (estático) | `isEncryptionEnabled()`, `looksEncrypted()`, `getCryptoService()`, `getSearchHashService()`, `getSecureSearch()`, `configure*()`, `setEncryptionEnabledForTests()`, `resetForTests()`; constantes dos nomes de propriedade |
69
+ | `CryptoService`, `SearchHashService`, `ValueNormalizer` (+ `AesGcmCryptoService`, `HmacSha256SearchHashService`, `DefaultValueNormalizer`) | interfaces/implementações substituíveis via `CryptoProvider.configure*` |
70
+ | `CryptoProperties` | POJO `cryptoKey`/`searchKey` |
71
+ | `masking.@PersonalData(type, maskWith)` | campo/getter com PII para redação |
72
+ | `masking.@MaskRule(field, type, maskWith, remove)` | regra por caminho (`cpf`, `endereco.cep`, `dependentes[].cpf`), usada por quem chama (ex.: `@Audit`) |
73
+ | `masking.MaskingStrategy` | `FULL`, `FORMAT`, `PARTIAL`, `HASH` (SHA-256), `TEMPLATE`, `REMOVE` |
74
+ | `masking.PersonalDataSanitizer` (bean) | `sanitizeToJson(value, sourceType, rules)`, `sanitizeToJson(value, rules)`, `sanitize(value, type[, rules])` (fail-closed) |
75
+ | `masking.PersonalDataResolver` (bean) | `resolveRules(Class)` |
76
+ | `masking.PersonalDataMasker` (estático) | `mask(value, strategy, param)`, `cpf()`, `cnpj()`, `cep()` |
77
+
78
+ Sem endpoints REST, eventos CDI ou migrations (as colunas cifradas/hash são do host; o exemplo usa `length = 512` para cifrado e `64` para hash).
79
+
80
+ ## Testes existentes (não executados)
81
+
82
+ `src/test/java/br/com/seedgrid/privacy/`: `AesGcmCryptoServiceTest`, `HmacSha256SearchHashServiceTest`, `DefaultValueNormalizerTest`, `SearchNormalizationTest`, `EncryptedFieldAttributeConverterTest`, `EncryptedFieldListenerTest`, `EncryptionEnabledFlagTest`, `EncryptedFieldEmbeddableJpaTest` (JPA com `PrivacyTestPersistenceUnitInfo`, PostgreSQL/Testcontainers), `masking/{MaskingStrategy,PersonalDataMasker,PersonalDataResolver,PersonalDataSanitizer}Test`. ~57 anotações `@Test`/`@ParameterizedTest` por grep. Exemplo com testes de integração: `java/examples/seedgrid-privacy-example` (`CustomerEncryptionTest`, `PrivacySchemaBootstrapTest`). **Não executados.**
83
+
84
+ ## Limitações
85
+
86
+ - **Validação no boot é parcial**: o `CryptoBootstrap` **não** verifica o flag nem a ausência de chaves; a falha ocorre no primeiro persist/hash/decifra. Por outro lado, uma chave **presente e inválida** (Base64 inválido ou < 32 bytes) lança no `CryptoBootstrap` mesmo com o flag desligado. **Confirmado** pelo código; que a exceção em bean `@Startup` aborta o boot é **Inferência**.
87
+ - `crypto.key` com mais de 32 bytes passa no `KeyDecoder` (mínimo 32) mas o AES só aceita 16/24/32 bytes — falharia no primeiro `encrypt` (**Inferência**, comportamento do JCE). Use exatamente 32 bytes.
88
+ - Estado global estático em `CryptoProvider` (não é bean CDI) — compartilhado por toda a JVM.
89
+ - Para e-mail use `SearchNormalization.EMAIL`; `CANONICAL` remove a pontuação e faria e-mails diferentes colidirem (Javadoc de `SearchNormalization`).
90
+ - Trocar de modo com dados existentes exige migração: desligado→ligado deixa registros antigos crus e sem hash; ligado→desligado exige a chave para ler valores `v1:`.
@@ -0,0 +1,72 @@
1
+ ---
2
+ tags: [seedgrid, extension, realtime, rust, configuracao]
3
+ fonte: rust/seedgrid-rust-crate-realtime
4
+ branch: main
5
+ commit: be738a2d1e
6
+ analisado-em: 2026-10-14
7
+ ---
8
+
9
+ # realtime — Configuração Rust
10
+
11
+ Visão do crate: [[SeedGrid/Extensions/realtime/Rust|Porte Rust do realtime]] · Java: [[SeedGrid/Extensions/realtime/Configuracao|Configuração do realtime (Java)]].
12
+
13
+ ## Cabeçalho
14
+ | Item | Valor |
15
+ |---|---|
16
+ | Struct | `RealtimeConfig` — `rust/seedgrid-rust-crate-realtime/src/config.rs` |
17
+ | Mecanismo | `RealtimeConfig::from_env()` (= `from_lookup(std::env::var)`), `RealtimePublisher::from_env()`, ou struct do host |
18
+ | Prefixo Java | `seedgrid.realtime` (`@ConfigMapping` em `java/seedgrid-quarkus-ext-realtime/runtime/.../configs/RealtimeConfig.java`) |
19
+ | Leitura | no boot (`from_env`); o limite por minuto é fixado ao montar `rest::router` |
20
+
21
+ Regra de leitura (`from_lookup`): valor `trim`ado; vazio = ausente; valor que não parseia → padrão.
22
+
23
+ ## Variáveis de ambiente
24
+ | Propriedade | Tipo | Valores aceitos | Padrão | Obrigatória | Comportamento | Uso | Relações | Leitura | Origem |
25
+ |---|---|---|---|---|---|---|---|---|---|
26
+ | `SEEDGRID_REALTIME_ENABLED` (Java `seedgrid.realtime.enabled`) | bool | `true` (case-insensitive) liga; qualquer outro valor desliga | `false` | Não | desligado: `connect` responde `{enabled:false}` e avisos são no-op | `RealtimePublisher::new` | exige URL + chave | `from_env()` | `config.rs`; `publisher.rs` → `new` |
27
+ | `SEEDGRID_REALTIME_PULSE_BASE_URL` (Java `seedgrid.realtime.pulse.base-url`) | `Option<String>` | URL | — | Condicional: obrigatória se ligado | ligado sem ela → log de erro e realtime desligado | `PulsePublisher::builder` | `PULSE_PROJECT_KEY` | `from_env()` | `publisher.rs` → `new` |
28
+ | 🔒 `SEEDGRID_REALTIME_PULSE_PROJECT_KEY` (Java `seedgrid.realtime.pulse.project-key`) | `Option<String>` | chave `project` do Pulse | — | Condicional: obrigatória se ligado | idem | idem | `PULSE_BASE_URL` | `from_env()` | idem |
29
+ | `SEEDGRID_REALTIME_TOKEN_TTL` (Java `seedgrid.realtime.token-ttl`) | Duration | ISO `PTnHnMnS`; número = segundos; sufixos via `seedgrid_runtime::parse_duration` (ex.: `5m`, `300s`); `0`/inválido → padrão | `PT5M` (300 s) | Não | janela para **conectar** com o token (`ttl_seconds`, mínimo 1) | `issue_connect_token` | — | `from_env()` | `config.rs` → `parse_duration`; `publisher.rs` |
30
+ | `SEEDGRID_REALTIME_CHANNELS` (Java `seedgrid.realtime.channels`) | `Option<Vec<String>>` | lista separada por vírgula | todos os da conta (`None`) | Não | channels que o token deixa assinar; também devolvidos no JSON | `issue_connect_token`, `connect` | — | `from_env()` | `config.rs`; `rest.rs` |
31
+ | `SEEDGRID_REALTIME_CONNECT_RATE_PER_MINUTE` (Java `seedgrid.realtime.connect-rate-per-minute`) | u32 | inteiro ≥ 0; `0` desliga | `30` | Não | pedidos de token por minuto, por usuário, por instância | `ConnectRateLimiter` em `rest::router` | — | `from_env()`; fixado em `router()` | `config.rs`; `rest.rs`; `rate_limit.rs` |
32
+
33
+ Mapeamento Java ↔ env: **Confirmado** (nomes dos métodos do `RealtimeConfig.java` + regra MicroProfile sem ambiguidade; o teste `reads_the_same_env_as_the_java_extension` usa esses nomes). Padrões iguais ao Java (`false`, `PT5M`, `30`).
34
+
35
+ ## Struct `RealtimeConfig`
36
+ | Campo | `Default` |
37
+ |---|---|
38
+ | `enabled` | `false` |
39
+ | `pulse_base_url` | `None` |
40
+ | `pulse_project_key` | `None` |
41
+ | `token_ttl` | 300 s |
42
+ | `channels` | `None` |
43
+ | `connect_rate_per_minute` | `30` |
44
+
45
+ ## Features Cargo
46
+ Nenhuma.
47
+
48
+ ## Somente testes
49
+ | Variável | Onde |
50
+ |---|---|
51
+ | `REALTIME_E2E_PULSE_URL`, 🔒 `REALTIME_E2E_SERVER_KEY` | `tests/pulse_e2e_it.rs` (`#[ignore]`) |
52
+
53
+ ## Configuração mínima
54
+ ```dotenv
55
+ SEEDGRID_REALTIME_ENABLED=true
56
+ SEEDGRID_REALTIME_PULSE_BASE_URL=http://<pulse-host>:<porta>
57
+ SEEDGRID_REALTIME_PULSE_PROJECT_KEY=<SEGREDO:pulse-project-key>
58
+ ```
59
+
60
+ ## Configuração completa comentada
61
+ ```dotenv
62
+ SEEDGRID_REALTIME_ENABLED=true
63
+ SEEDGRID_REALTIME_PULSE_BASE_URL=http://<pulse-host>:<porta> # endereço visto pelo backend
64
+ SEEDGRID_REALTIME_PULSE_PROJECT_KEY=<SEGREDO:pulse-project-key>
65
+ SEEDGRID_REALTIME_TOKEN_TTL=PT5M # ou 300 / 5m
66
+ SEEDGRID_REALTIME_CHANNELS=backup,report # vazio = todos
67
+ SEEDGRID_REALTIME_CONNECT_RATE_PER_MINUTE=30 # 0 desliga
68
+ ```
69
+
70
+ ## Receitas
71
+ - **Desligado (padrão)**: nada a configurar; o front fica no polling.
72
+ - **Avisos do backup**: `RealtimePublisher::from_env()` e passe-o em `BackupOverrides.user_events` ([[SeedGrid/Extensions/backup/Configuracao-Rust|Configuração Rust do backup]]).
@@ -0,0 +1,104 @@
1
+ ---
2
+ tags: [seedgrid, extension, realtime, configuracao]
3
+ fonte: java/seedgrid-quarkus-ext-realtime
4
+ branch: main
5
+ commit: 8f13639b3c
6
+ analisado-em: 2026-10-14
7
+ ---
8
+
9
+ # Realtime (Quarkus) — configuração
10
+
11
+ Voltar: [[SeedGrid/Extensions/realtime/Visao-geral|Visão geral do realtime]] · [[SeedGrid/Extensions/realtime/Exemplos|Exemplos]] · [[SeedGrid/Extensions/realtime/Rust|Porte Rust]]
12
+
13
+ ## 1. Cabeçalho
14
+
15
+ | Item | Valor |
16
+ |---|---|
17
+ | Prefixo | `seedgrid.realtime` |
18
+ | Classe de config | `java/seedgrid-quarkus-ext-realtime/runtime/src/main/java/br/com/seedgrid/realtime/configs/RealtimeConfig.java` → `RealtimeConfig` (grupo aninhado `RealtimeConfig.Pulse`) |
19
+ | Mecanismo | SmallRye `@ConfigMapping(prefix = "seedgrid.realtime")` + `@StaticInitSafe`; registrado também por `SeedgridRealtimeProcessor#config()` (`ConfigMappingBuildItem`) |
20
+ | Fase | Runtime (ConfigMapping no módulo runtime). Na prática os valores são lidos uma vez, quando o bean `RealtimePublisher`/`ConnectRateLimiter` é criado. |
21
+ | Outras fontes | Não há `microprofile-config.properties` no runtime nem `@ConfigProperty`/`ConfigProvider` adicionais. |
22
+
23
+ Variáveis de ambiente: a regra MicroProfile se aplica sem ambiguidade a todas as chaves abaixo, e os nomes `SEEDGRID_REALTIME_*` estão confirmados no README e na mensagem de log de `RealtimePublisher#connect`.
24
+
25
+ ## 2. Propriedades da extension
26
+
27
+ ### Ativação e conexão com o Pulse
28
+
29
+ | Propriedade | Tipo | Valores aceitos | Padrão | Obrigatória | Comportamento | Uso | Relações | Fase | Origem |
30
+ |---|---|---|---|---|---|---|---|---|---|
31
+ | `seedgrid.realtime.enabled` (env `SEEDGRID_REALTIME_ENABLED`) | `boolean` | `true`/`false` | `false` | Não | Liga o realtime. Desligado: `/realtime/connect` responde `200 {enabled:false}`, `publishToUser` é no-op e nada fala com o Pulse. | Liga a integração com o Pulse | Ligado exige `pulse.base-url` e `pulse.project-key`; se faltar algum, o realtime fica desligado e é logado ERROR (a aplicação sobe) | Runtime | Decl.: `RealtimeConfig#enabled()`. Consumo: `RealtimePublisher#connect(RealtimeConfig)` |
32
+ | `seedgrid.realtime.pulse.base-url` (env `SEEDGRID_REALTIME_PULSE_BASE_URL`) | `Optional<String>` | URL do Pulse visível pelo backend (pode ser endereço interno) | — | Condicional: necessária quando `enabled=true` | Valor em branco é tratado como ausente (`filter(!isBlank)`). Passado a `PulsePublisher.builder().baseUrl(...)`. | Endereço do Pulse | Com `enabled=true` e sem valor → realtime desligado + log ERROR | Runtime | Decl.: `RealtimeConfig.Pulse#baseUrl()`. Consumo: `RealtimePublisher#connect` |
33
+ | 🔒 `seedgrid.realtime.pulse.project-key` (env `SEEDGRID_REALTIME_PULSE_PROJECT_KEY`) | `Optional<String>` | chave `project` da conta no Pulse | — | Condicional: necessária quando `enabled=true` | Segredo; fica só no backend. Em branco = ausente. Enviada pelo SDK ao Pulse (header `x-api-key` nos testes). | Autenticar o backend no Pulse | Idem `base-url` | Runtime | Decl.: `RealtimeConfig.Pulse#projectKey()`. Consumo: `RealtimePublisher#connect` |
34
+
35
+ ### Token de conexão e limites
36
+
37
+ | Propriedade | Tipo | Valores aceitos | Padrão | Obrigatória | Comportamento | Uso | Relações | Fase | Origem |
38
+ |---|---|---|---|---|---|---|---|---|---|
39
+ | `seedgrid.realtime.token-ttl` (env `SEEDGRID_REALTIME_TOKEN_TTL`) | `Duration` | ISO-8601 (`PT5M`) ou formatos aceitos pelo conversor de `Duration` do SmallRye | `PT5M` | Não | Janela para **conectar**; a conexão aberta segue depois do vencimento. Repassado ao Pulse em `IssueConnectTokenInput` (o teste com `PT2M` confirma o envio de `ttlSeconds: 120`). Sem validação local de faixa. | Validade do token | Só tem efeito com o realtime ligado | Runtime | Decl.: `RealtimeConfig#tokenTtl()`. Consumo: `RealtimePublisher#issueConnectToken` |
40
+ | `seedgrid.realtime.channels` (env `SEEDGRID_REALTIME_CHANNELS`) | `Optional<List<String>>` | lista separada por vírgula | — (ausente = todos os channels da conta) | Não | Restringe os channels que o token deixa assinar; também é devolvido no corpo do `/realtime/connect`. | Escopo de assinatura | — | Runtime | Decl.: `RealtimeConfig#channels()`. Consumo: `RealtimePublisher#issueConnectToken`, `RealtimeController#connect` |
41
+ | `seedgrid.realtime.connect-rate-per-minute` (env `SEEDGRID_REALTIME_CONNECT_RATE_PER_MINUTE`) | `int` | inteiro; `<= 0` desliga | `30` | Não | Pedidos de token por minuto **por usuário**, janela fixa de 60 s, em memória por instância. Excedido → `429` com `Retry-After` (segundos, mínimo 1). | Proteger a cota de emissões da project key | Só é consultado com o realtime ligado (o controller responde `enabled:false` antes) | Runtime | Decl.: `RealtimeConfig#connectRatePerMinute()`. Consumo: `ConnectRateLimiter(RealtimeConfig)` / `#tryAcquire` |
42
+
43
+ Total: **6 propriedades públicas**.
44
+
45
+ ## 3. Propriedades de frameworks/bibliotecas
46
+
47
+ A extension não define nem exige propriedades `quarkus.*`, `mp.*` ou `smallrye.*` (não há `microprofile-config.properties` nem `RunTimeConfigurationDefaultBuildItem`). Indiretamente, `@Authenticated` depende do mecanismo de autenticação configurado no host (ex.: JWT do `seedgrid-security`). (Inferência)
48
+
49
+ ## 4. Propriedades usadas só em testes
50
+
51
+ Arquivo `runtime/src/test/resources/application.properties` e `FakePulse`:
52
+
53
+ | Propriedade | Valor no teste | Observação |
54
+ |---|---|---|
55
+ | `quarkus.http.test-port` | `0` | porta aleatória |
56
+ | `seedgrid.realtime.enabled` | `true` | `RealtimeDisabledTest` sobrescreve para `false` via `QuarkusTestProfile` |
57
+ | `seedgrid.realtime.pulse.project-key` | `<SEGREDO:pulse-project-key-de-teste>` | valor fictício de teste (não copiado) |
58
+ | `seedgrid.realtime.token-ttl` | `PT2M` | — |
59
+ | `seedgrid.realtime.connect-rate-per-minute` | `1000` | evita 429 nos testes |
60
+ | `seedgrid.realtime.pulse.base-url` | URL do WireMock | injetada por `FakePulse#start()` |
61
+
62
+ ## 5. Aliases, obsoletas, renomeações
63
+
64
+ Nenhum alias encontrado. O README declara que a crate Rust usa "mesmo contrato: rota, corpo, config, eventos" — detalhes em [[SeedGrid/Extensions/realtime/Rust|Porte Rust]].
65
+
66
+ ## 6. Configuração mínima
67
+
68
+ ```properties
69
+ seedgrid.realtime.enabled=true
70
+ seedgrid.realtime.pulse.base-url=<URL-DO-PULSE-VISTA-PELO-BACKEND>
71
+ seedgrid.realtime.pulse.project-key=${SEEDGRID_REALTIME_PULSE_PROJECT_KEY}
72
+ ```
73
+
74
+ Sem nenhuma configuração a extension fica desligada (padrão `enabled=false`) e o endpoint responde `{enabled:false}`.
75
+
76
+ ## 7. Configuração completa comentada
77
+
78
+ ```properties
79
+ # Liga o realtime (padrão: false)
80
+ seedgrid.realtime.enabled=true
81
+ # Pulse visto pelo backend (pode ser endereço interno)
82
+ seedgrid.realtime.pulse.base-url=<URL-DO-PULSE>
83
+ # SEGREDO: chave "project" da conta no Pulse. Use variável de ambiente.
84
+ seedgrid.realtime.pulse.project-key=<SEGREDO:pulse-project-key>
85
+ # Janela para conectar (padrão: PT5M)
86
+ seedgrid.realtime.token-ttl=PT5M
87
+ # Channels permitidos no token (ausente = todos os da conta)
88
+ seedgrid.realtime.channels=backup,report
89
+ # Pedidos de token por minuto, por usuário e por instância (padrão: 30; 0 desliga)
90
+ seedgrid.realtime.connect-rate-per-minute=30
91
+ ```
92
+
93
+ ## 8. Receitas
94
+
95
+ - **Desligar em um ambiente**: `SEEDGRID_REALTIME_ENABLED=false` (ou não definir). A tela recebe `{enabled:false}` e fica no polling.
96
+ - **Restringir assinaturas a poucos channels**: `SEEDGRID_REALTIME_CHANNELS=backup,report`.
97
+ - **Remover o limite de emissão** (ex.: testes de carga): `SEEDGRID_REALTIME_CONNECT_RATE_PER_MINUTE=0`.
98
+ - **Pulse em rede interna**: aponte `pulse.base-url` para o endereço interno; o front usa o `connectUrl` devolvido pelo Pulse (não configurado aqui).
99
+
100
+ ## 9. Dúvidas e lacunas
101
+
102
+ - O formato aceito de `Duration` além do ISO-8601 depende do conversor do SmallRye/Quarkus (Não confirmado neste repositório).
103
+ - Não há validação local de `token-ttl` (negativo/zero); o comportamento fica a cargo do Pulse (Não confirmado).
104
+ - Com várias réplicas, o limite de `connect-rate-per-minute` é por instância (Inferência).
@@ -0,0 +1,104 @@
1
+ ---
2
+ tags: [seedgrid, extension, realtime, exemplos]
3
+ fonte: java/seedgrid-quarkus-ext-realtime
4
+ branch: main
5
+ commit: 8f13639b3c
6
+ analisado-em: 2026-10-14
7
+ ---
8
+
9
+ # Realtime (Quarkus) — exemplos
10
+
11
+ Voltar: [[SeedGrid/Extensions/realtime/Visao-geral|Visão geral do realtime]] · [[SeedGrid/Extensions/realtime/Configuracao|Configuração]]
12
+
13
+ ## 1. Dependência
14
+
15
+ Fonte: `README.md`.
16
+
17
+ ```xml
18
+ <dependency>
19
+ <groupId>br.com.seedgrid</groupId>
20
+ <artifactId>seedgrid-realtime</artifactId>
21
+ <version>2026.10.08</version>
22
+ </dependency>
23
+ ```
24
+
25
+ ## 2. Avisar um usuário pelo evento neutro (preferido)
26
+
27
+ Fonte: `README.md` e `RealtimeEnabledTest#userEventIsPublishedToThatUser`. O processo não depende desta extension — só do `SgUserEvent` do `seedgrid-commons`. Construtor: `SgUserEvent(userPublicId, channel, event, data)`.
28
+
29
+ ```java
30
+ import br.com.seedgrid.commons.events.SgUserEvent;
31
+ import jakarta.enterprise.event.Event;
32
+ import jakarta.inject.Inject;
33
+ import java.util.Map;
34
+
35
+ @Inject Event<SgUserEvent> userEvents;
36
+
37
+ // Dentro da transação que grava o resultado: o aviso sai depois do commit (AFTER_SUCCESS).
38
+ userEvents.fire(new SgUserEvent(userPublicId, "report", "report.finished.success",
39
+ Map.of("reportPublicId", report.getPublicId())));
40
+ ```
41
+
42
+ `data` leva apenas identificadores; a tela busca o registro pela API normal.
43
+
44
+ ## 3. Avisar diretamente com o `RealtimePublisher`
45
+
46
+ Fonte: assinatura de `RealtimePublisher#publishToUser(String, String, String, Map<String,Object>)`.
47
+
48
+ ```java
49
+ import br.com.seedgrid.realtime.services.RealtimePublisher;
50
+
51
+ @Inject RealtimePublisher realtime;
52
+
53
+ // Assíncrono; nunca propaga erro. Desligado = no-op.
54
+ realtime.publishToUser("backup", "backup.finished.success", userPublicId,
55
+ Map.of("exportPublicId", exportPublicId, "status", "DONE"));
56
+ ```
57
+
58
+ ## 4. Front pedindo o token
59
+
60
+ Fonte: `RealtimeController` e tabela do `README.md`.
61
+
62
+ ```http
63
+ POST /realtime/connect
64
+ Authorization: Bearer <JWT-DO-USUARIO>
65
+ ```
66
+
67
+ Respostas possíveis:
68
+
69
+ ```json
70
+ { "enabled": false }
71
+ ```
72
+
73
+ ```json
74
+ { "enabled": true, "token": "pct_...", "expiresAt": 1791119100, "connectUrl": "wss://...", "channels": ["backup"] }
75
+ ```
76
+
77
+ `401` (sem usuário), `429` com `Retry-After`, `503` (Pulse indisponível → manter polling).
78
+
79
+ ## 5. Configuração por ambiente
80
+
81
+ Fonte: `RealtimeConfig` e `README.md`. Detalhes em [[SeedGrid/Extensions/realtime/Configuracao|Configuração]].
82
+
83
+ ```bash
84
+ SEEDGRID_REALTIME_ENABLED=true
85
+ SEEDGRID_REALTIME_PULSE_BASE_URL=<URL-DO-PULSE>
86
+ SEEDGRID_REALTIME_PULSE_PROJECT_KEY=<SEGREDO:pulse-project-key>
87
+ SEEDGRID_REALTIME_TOKEN_TTL=PT5M
88
+ ```
89
+
90
+ ## 6. Testando com Pulse fingido
91
+
92
+ Fonte: `runtime/src/test/java/br/com/seedgrid/realtime/FakePulse.java` — um `QuarkusTestResourceLifecycleManager` que sobe WireMock e devolve `seedgrid.realtime.pulse.base-url` apontando para ele.
93
+
94
+ ```java
95
+ @QuarkusTest
96
+ @QuarkusTestResource(FakePulse.class)
97
+ class MeuTeste {
98
+ @Test
99
+ @TestSecurity(user = "7f3a9c1e-0000-4000-8000-000000000001")
100
+ void conecta() {
101
+ given().when().post("/realtime/connect").then().statusCode(200);
102
+ }
103
+ }
104
+ ```
@@ -0,0 +1,69 @@
1
+ ---
2
+ tags: [seedgrid, extension, realtime, rust]
3
+ fonte: rust/seedgrid-rust-crate-realtime
4
+ branch: main
5
+ commit: be738a2d1e
6
+ analisado-em: 2026-10-14
7
+ ---
8
+
9
+ # realtime — porte Rust (`seedgrid-rust-crate-realtime`)
10
+
11
+ Porte da extensão Quarkus `seedgrid-quarkus-ext-realtime` ("mesmo env, mesma rota, mesmo JSON"). Lado Java: [[SeedGrid/Extensions/realtime/Visao-geral|Visão geral do realtime (Java)]] · [[SeedGrid/Extensions/realtime/Configuracao|Configuração do realtime (Java)]]. Configuração Rust: [[SeedGrid/Extensions/realtime/Configuracao-Rust|Configuração Rust do realtime]].
12
+
13
+ Avisos em tempo real ao **usuário logado** via SeedGrid Pulse: entrega ao front um token curto de conexão (`POST /realtime/connect`) e publica os `SgUserEvent` da plataforma. **Confirmado** (`src/lib.rs`, README).
14
+
15
+ ## Identificação
16
+ | Item | Valor |
17
+ |---|---|
18
+ | Pacote Cargo | `seedgrid-rust-crate-realtime` (lib `seedgrid_realtime`) |
19
+ | Versão | workspace `2026.10.14` |
20
+ | Features | nenhuma |
21
+ | Dependências SeedGrid | `seedgrid-runtime` (eventos `SgUserEvent`/`UserEventSink`, `parse_duration`); `seedgrid-pulse-publisher-rust` (path `../../../seedgrid-products/seedgrid-pulse/components/publishers/seedgrid-pulse-publisher-rust`, **fora** do `seedgrid-platform`) |
22
+ | Dev-deps | `seedgrid-pulse-subscriber-rust` (também fora do repo), `wiremock` |
23
+
24
+ Observação: o crate só compila com o repositório `seedgrid-products` presente ao lado de `seedgrid-platform` (**Confirmado** pelo `Cargo.toml`; o caminho existe nesta máquina em `seedgrid-products/...`).
25
+
26
+ ## API pública
27
+ | Símbolo | Papel | Fonte |
28
+ |---|---|---|
29
+ | `RealtimeConfig` (`from_env`, `from_lookup`, `Default`), `config::parse_duration` | config | `src/config.rs` |
30
+ | `RealtimePublisher::new(config)` / `from_env()` | cliente do Pulse; ligado sem URL ou chave → loga erro e fica desligado (a app sobe) | `src/publisher.rs` |
31
+ | `RealtimePublisher::is_enabled`, `config`, `publish_to_user(channel, event, user_public_id, data)`, `issue_connect_token(user_public_id)` | publicação (nunca propaga erro) e emissão de token | `src/publisher.rs` |
32
+ | `impl UserEventSink for RealtimePublisher` | publica `SgUserEvent` numa task própria (par do `@Observes(during = AFTER_SUCCESS)` Java) | `src/publisher.rs` |
33
+ | `IssueError::{Disabled, Pulse}` | erro de emissão | `src/publisher.rs` |
34
+ | `rest::router(publisher, Arc<dyn RealtimeIdentityResolver>)` | rota `POST /realtime/connect` | `src/rest.rs` |
35
+ | trait `RealtimeIdentityResolver` | o host informa o usuário da sessão (ex.: `sub` do JWT) | `src/rest.rs` |
36
+ | `RealtimeConnectResponse` | JSON de resposta (`enabled`, `token`, `expiresAt`, `connectUrl`, `channels`) | `src/rest.rs` |
37
+ | `rate_limit::ConnectRateLimiter` | janela fixa de 1 min por usuário, em memória, por instância | `src/rate_limit.rs` |
38
+
39
+ ## Endpoint `POST /realtime/connect`
40
+ | Status | Quando |
41
+ |---|---|
42
+ | 401 | sem usuário (vale mesmo com realtime desligado) |
43
+ | 200 `{enabled:false}` | desligado ou não configurado |
44
+ | 429 + `Retry-After` | limite `connect_rate_per_minute` excedido |
45
+ | 200 `{enabled:true, token, expiresAt, connectUrl, channels}` | token emitido |
46
+ | 503 | Pulse não respondeu/recusou |
47
+
48
+ Fonte: `src/rest.rs` → `connect`.
49
+
50
+ ## Exemplo (doc de `src/lib.rs`)
51
+ ```rust
52
+ use seedgrid_realtime::RealtimePublisher;
53
+ use seedgrid_runtime::events::UserEventSink;
54
+
55
+ let realtime = RealtimePublisher::from_env();
56
+ let api = seedgrid_realtime::rest::router(realtime.clone(), identity);
57
+ let user_events: Arc<dyn UserEventSink> = Arc::new(realtime.clone());
58
+ // avisos do backup:
59
+ let overrides = BackupOverrides { user_events: Arc::new(realtime), ..Default::default() };
60
+ ```
61
+ Não há app em `rust/examples/` para realtime.
62
+
63
+ ## Testes
64
+ - Unitários (`src/config.rs`: durações, mesmo env do Java, padrão desligado) e `tests/realtime_it.rs` (router contra Pulse simulado com `wiremock`: 401, 429, 503, desligado, publicação).
65
+ - `tests/pulse_e2e_it.rs` (`#[ignore]`) contra Pulse real com `REALTIME_E2E_PULSE_URL` e `REALTIME_E2E_SERVER_KEY`.
66
+ - **Não executados.**
67
+
68
+ ## Enums
69
+ Sem enums de domínio. Enum público de erro: `IssueError` (`src/publisher.rs`) — `Disabled` (realtime desligado; `POST /realtime/connect` responde `{enabled:false}`) e `Pulse(PulseError)` (Pulse recusou ou não respondeu; vira HTTP 503).