@seedgrid/ai-toolkit 0.0.0-stage → 0.3.0

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 (225) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +151 -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 +203 -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/status.js +73 -0
  16. package/dist/commands/update.js +8 -0
  17. package/dist/commands/validate.js +27 -0
  18. package/dist/core/apply.js +181 -0
  19. package/dist/core/blocks.js +64 -0
  20. package/dist/core/content.js +528 -0
  21. package/dist/core/env.js +40 -0
  22. package/dist/core/frontmatter.js +29 -0
  23. package/dist/core/hash.js +14 -0
  24. package/dist/core/inspect.js +51 -0
  25. package/dist/core/lock.js +124 -0
  26. package/dist/core/paths.js +65 -0
  27. package/dist/core/plan.js +242 -0
  28. package/dist/core/tools.js +62 -0
  29. package/dist/core/types.js +11 -0
  30. package/dist/core/updates.js +121 -0
  31. package/docs/arquitetura.md +80 -0
  32. package/docs/compatibilidade.md +50 -0
  33. package/docs/formato.md +155 -0
  34. package/docs/instalacao.md +105 -0
  35. package/docs/manutencao.md +115 -0
  36. package/package.json +43 -4
  37. package/seedgridKB/SeedGrid/Extensions/Catalogo-de-enums.md +161 -0
  38. package/seedgridKB/SeedGrid/Extensions/Catalogo-de-propriedades.md +971 -0
  39. package/seedgridKB/SeedGrid/Extensions/Indice.md +63 -0
  40. package/seedgridKB/SeedGrid/Extensions/ai-pricing/Configuracao.md +124 -0
  41. package/seedgridKB/SeedGrid/Extensions/ai-pricing/Enums.md +40 -0
  42. package/seedgridKB/SeedGrid/Extensions/ai-pricing/Exemplos.md +97 -0
  43. package/seedgridKB/SeedGrid/Extensions/ai-pricing/Visao-geral.md +114 -0
  44. package/seedgridKB/SeedGrid/Extensions/apikeys/Configuracao-Rust.md +69 -0
  45. package/seedgridKB/SeedGrid/Extensions/apikeys/Configuracao.md +88 -0
  46. package/seedgridKB/SeedGrid/Extensions/apikeys/Enums.md +33 -0
  47. package/seedgridKB/SeedGrid/Extensions/apikeys/Exemplos.md +121 -0
  48. package/seedgridKB/SeedGrid/Extensions/apikeys/Rust.md +126 -0
  49. package/seedgridKB/SeedGrid/Extensions/apikeys/Visao-geral.md +111 -0
  50. package/seedgridKB/SeedGrid/Extensions/audit/Configuracao-Rust.md +93 -0
  51. package/seedgridKB/SeedGrid/Extensions/audit/Configuracao.md +127 -0
  52. package/seedgridKB/SeedGrid/Extensions/audit/Enums.md +66 -0
  53. package/seedgridKB/SeedGrid/Extensions/audit/Exemplos.md +151 -0
  54. package/seedgridKB/SeedGrid/Extensions/audit/Rust.md +120 -0
  55. package/seedgridKB/SeedGrid/Extensions/audit/Visao-geral.md +114 -0
  56. package/seedgridKB/SeedGrid/Extensions/backup/Configuracao-Rust.md +136 -0
  57. package/seedgridKB/SeedGrid/Extensions/backup/Configuracao.md +319 -0
  58. package/seedgridKB/SeedGrid/Extensions/backup/Enums.md +131 -0
  59. package/seedgridKB/SeedGrid/Extensions/backup/Exemplos.md +210 -0
  60. package/seedgridKB/SeedGrid/Extensions/backup/Rust.md +135 -0
  61. package/seedgridKB/SeedGrid/Extensions/backup/Visao-geral.md +150 -0
  62. package/seedgridKB/SeedGrid/Extensions/billing/Configuracao-Rust.md +86 -0
  63. package/seedgridKB/SeedGrid/Extensions/billing/Configuracao.md +243 -0
  64. package/seedgridKB/SeedGrid/Extensions/billing/Enums.md +165 -0
  65. package/seedgridKB/SeedGrid/Extensions/billing/Exemplos.md +205 -0
  66. package/seedgridKB/SeedGrid/Extensions/billing/Rust.md +109 -0
  67. package/seedgridKB/SeedGrid/Extensions/billing/Visao-geral.md +181 -0
  68. package/seedgridKB/SeedGrid/Extensions/broker/Configuracao-Rust.md +40 -0
  69. package/seedgridKB/SeedGrid/Extensions/broker/Visao-geral.md +114 -0
  70. package/seedgridKB/SeedGrid/Extensions/cache/Configuracao-Rust.md +73 -0
  71. package/seedgridKB/SeedGrid/Extensions/cache/Configuracao.md +112 -0
  72. package/seedgridKB/SeedGrid/Extensions/cache/Enums.md +36 -0
  73. package/seedgridKB/SeedGrid/Extensions/cache/Exemplos.md +149 -0
  74. package/seedgridKB/SeedGrid/Extensions/cache/Rust.md +81 -0
  75. package/seedgridKB/SeedGrid/Extensions/cache/Visao-geral.md +90 -0
  76. package/seedgridKB/SeedGrid/Extensions/commons/Configuracao.md +107 -0
  77. package/seedgridKB/SeedGrid/Extensions/commons/Enums.md +105 -0
  78. package/seedgridKB/SeedGrid/Extensions/commons/Exemplos.md +141 -0
  79. package/seedgridKB/SeedGrid/Extensions/commons/Visao-geral.md +99 -0
  80. package/seedgridKB/SeedGrid/Extensions/exchange/Configuracao.md +122 -0
  81. package/seedgridKB/SeedGrid/Extensions/exchange/Enums.md +29 -0
  82. package/seedgridKB/SeedGrid/Extensions/exchange/Exemplos.md +82 -0
  83. package/seedgridKB/SeedGrid/Extensions/exchange/Visao-geral.md +118 -0
  84. package/seedgridKB/SeedGrid/Extensions/filemanagement/Configuracao-Rust.md +110 -0
  85. package/seedgridKB/SeedGrid/Extensions/filemanagement/Configuracao.md +157 -0
  86. package/seedgridKB/SeedGrid/Extensions/filemanagement/Exemplos.md +157 -0
  87. package/seedgridKB/SeedGrid/Extensions/filemanagement/Rust.md +70 -0
  88. package/seedgridKB/SeedGrid/Extensions/filemanagement/Visao-geral.md +88 -0
  89. package/seedgridKB/SeedGrid/Extensions/login-tenancy/Configuracao-Rust.md +124 -0
  90. package/seedgridKB/SeedGrid/Extensions/login-tenancy/Configuracao.md +195 -0
  91. package/seedgridKB/SeedGrid/Extensions/login-tenancy/Enums.md +71 -0
  92. package/seedgridKB/SeedGrid/Extensions/login-tenancy/Exemplos.md +149 -0
  93. package/seedgridKB/SeedGrid/Extensions/login-tenancy/Rust.md +139 -0
  94. package/seedgridKB/SeedGrid/Extensions/login-tenancy/Visao-geral.md +130 -0
  95. package/seedgridKB/SeedGrid/Extensions/notification/Configuracao.md +141 -0
  96. package/seedgridKB/SeedGrid/Extensions/notification/Enums.md +52 -0
  97. package/seedgridKB/SeedGrid/Extensions/notification/Exemplos.md +141 -0
  98. package/seedgridKB/SeedGrid/Extensions/notification/Visao-geral.md +113 -0
  99. package/seedgridKB/SeedGrid/Extensions/privacy/Configuracao-Rust.md +67 -0
  100. package/seedgridKB/SeedGrid/Extensions/privacy/Configuracao.md +94 -0
  101. package/seedgridKB/SeedGrid/Extensions/privacy/Enums.md +79 -0
  102. package/seedgridKB/SeedGrid/Extensions/privacy/Exemplos.md +172 -0
  103. package/seedgridKB/SeedGrid/Extensions/privacy/Rust.md +107 -0
  104. package/seedgridKB/SeedGrid/Extensions/privacy/Visao-geral.md +90 -0
  105. package/seedgridKB/SeedGrid/Extensions/realtime/Configuracao-Rust.md +72 -0
  106. package/seedgridKB/SeedGrid/Extensions/realtime/Configuracao.md +104 -0
  107. package/seedgridKB/SeedGrid/Extensions/realtime/Exemplos.md +104 -0
  108. package/seedgridKB/SeedGrid/Extensions/realtime/Rust.md +69 -0
  109. package/seedgridKB/SeedGrid/Extensions/realtime/Visao-geral.md +105 -0
  110. package/seedgridKB/SeedGrid/Extensions/resilience/Configuracao-Rust.md +68 -0
  111. package/seedgridKB/SeedGrid/Extensions/resilience/Configuracao.md +186 -0
  112. package/seedgridKB/SeedGrid/Extensions/resilience/Enums.md +96 -0
  113. package/seedgridKB/SeedGrid/Extensions/resilience/Exemplos.md +229 -0
  114. package/seedgridKB/SeedGrid/Extensions/resilience/Rust.md +80 -0
  115. package/seedgridKB/SeedGrid/Extensions/resilience/Visao-geral.md +112 -0
  116. package/seedgridKB/SeedGrid/Extensions/runtime/Configuracao-Rust.md +90 -0
  117. package/seedgridKB/SeedGrid/Extensions/runtime/Visao-geral.md +114 -0
  118. package/seedgridKB/SeedGrid/Extensions/security/Configuracao-Rust.md +327 -0
  119. package/seedgridKB/SeedGrid/Extensions/security/Configuracao.md +510 -0
  120. package/seedgridKB/SeedGrid/Extensions/security/Enums.md +95 -0
  121. package/seedgridKB/SeedGrid/Extensions/security/Exemplos.md +218 -0
  122. package/seedgridKB/SeedGrid/Extensions/security/Rust.md +203 -0
  123. package/seedgridKB/SeedGrid/Extensions/security/Visao-geral.md +131 -0
  124. package/seedgridKB/SeedGrid/Extensions/subdomain-tenancy/Configuracao-Rust.md +188 -0
  125. package/seedgridKB/SeedGrid/Extensions/subdomain-tenancy/Configuracao.md +345 -0
  126. package/seedgridKB/SeedGrid/Extensions/subdomain-tenancy/Enums.md +117 -0
  127. package/seedgridKB/SeedGrid/Extensions/subdomain-tenancy/Exemplos.md +205 -0
  128. package/seedgridKB/SeedGrid/Extensions/subdomain-tenancy/Rust.md +161 -0
  129. package/seedgridKB/SeedGrid/Extensions/subdomain-tenancy/Visao-geral.md +142 -0
  130. package/seedgridKB/SeedGrid/Extensions/whatsapp/Configuracao-Rust.md +75 -0
  131. package/seedgridKB/SeedGrid/Extensions/whatsapp/Configuracao.md +152 -0
  132. package/seedgridKB/SeedGrid/Extensions/whatsapp/Enums.md +198 -0
  133. package/seedgridKB/SeedGrid/Extensions/whatsapp/Exemplos.md +173 -0
  134. package/seedgridKB/SeedGrid/Extensions/whatsapp/Rust.md +83 -0
  135. package/seedgridKB/SeedGrid/Extensions/whatsapp/Visao-geral.md +99 -0
  136. package/seedgridKB/SeedGrid/Mapa-dos-repositorios.md +112 -0
  137. package/seedgridKB/SeedGrid/SeedGrid-components/Indice.md +323 -0
  138. package/seedgridKB/SeedGrid/SeedGrid-components/buttons/API.md +257 -0
  139. package/seedgridKB/SeedGrid/SeedGrid-components/buttons/Exemplos.md +307 -0
  140. package/seedgridKB/SeedGrid/SeedGrid-components/buttons/Visao-geral.md +51 -0
  141. package/seedgridKB/SeedGrid/SeedGrid-components/datatable/API.md +174 -0
  142. package/seedgridKB/SeedGrid/SeedGrid-components/datatable/Exemplos.md +236 -0
  143. package/seedgridKB/SeedGrid/SeedGrid-components/datatable/Visao-geral.md +76 -0
  144. package/seedgridKB/SeedGrid/SeedGrid-components/digits/API.md +339 -0
  145. package/seedgridKB/SeedGrid/SeedGrid-components/digits/Exemplos.md +311 -0
  146. package/seedgridKB/SeedGrid/SeedGrid-components/digits/Visao-geral.md +57 -0
  147. package/seedgridKB/SeedGrid/SeedGrid-components/editor/API.md +125 -0
  148. package/seedgridKB/SeedGrid/SeedGrid-components/editor/Exemplos.md +116 -0
  149. package/seedgridKB/SeedGrid/SeedGrid-components/editor/Visao-geral.md +86 -0
  150. package/seedgridKB/SeedGrid/SeedGrid-components/feedback-e-exibicao/API.md +490 -0
  151. package/seedgridKB/SeedGrid/SeedGrid-components/feedback-e-exibicao/Exemplos.md +544 -0
  152. package/seedgridKB/SeedGrid/SeedGrid-components/feedback-e-exibicao/Visao-geral.md +69 -0
  153. package/seedgridKB/SeedGrid/SeedGrid-components/fundamentos/API.md +113 -0
  154. package/seedgridKB/SeedGrid/SeedGrid-components/fundamentos/Exemplos.md +159 -0
  155. package/seedgridKB/SeedGrid/SeedGrid-components/fundamentos/Visao-geral.md +92 -0
  156. package/seedgridKB/SeedGrid/SeedGrid-components/gadgets/API.md +516 -0
  157. package/seedgridKB/SeedGrid/SeedGrid-components/gadgets/Exemplos.md +629 -0
  158. package/seedgridKB/SeedGrid/SeedGrid-components/gadgets/Visao-geral.md +80 -0
  159. package/seedgridKB/SeedGrid/SeedGrid-components/inputs-selecao/API.md +615 -0
  160. package/seedgridKB/SeedGrid/SeedGrid-components/inputs-selecao/Exemplos.md +384 -0
  161. package/seedgridKB/SeedGrid/SeedGrid-components/inputs-selecao/Visao-geral.md +111 -0
  162. package/seedgridKB/SeedGrid/SeedGrid-components/inputs-texto/API.md +661 -0
  163. package/seedgridKB/SeedGrid/SeedGrid-components/inputs-texto/Exemplos.md +312 -0
  164. package/seedgridKB/SeedGrid/SeedGrid-components/inputs-texto/Visao-geral.md +123 -0
  165. package/seedgridKB/SeedGrid/SeedGrid-components/layout/API.md +1090 -0
  166. package/seedgridKB/SeedGrid/SeedGrid-components/layout/Exemplos.md +1172 -0
  167. package/seedgridKB/SeedGrid/SeedGrid-components/layout/Visao-geral.md +98 -0
  168. package/seedgridKB/SeedGrid/SeedGrid-components/modulos/Visao-geral.md +98 -0
  169. package/seedgridKB/SeedGrid/SeedGrid-components/modulos/fe-apikeys.md +118 -0
  170. package/seedgridKB/SeedGrid/SeedGrid-components/modulos/fe-audit.md +88 -0
  171. package/seedgridKB/SeedGrid/SeedGrid-components/modulos/fe-backup.md +131 -0
  172. package/seedgridKB/SeedGrid/SeedGrid-components/modulos/fe-billing-platform.md +132 -0
  173. package/seedgridKB/SeedGrid/SeedGrid-components/modulos/fe-billing-user.md +120 -0
  174. package/seedgridKB/SeedGrid/SeedGrid-components/modulos/fe-login-tenancy.md +119 -0
  175. package/seedgridKB/SeedGrid/SeedGrid-components/modulos/fe-security.md +427 -0
  176. package/seedgridKB/SeedGrid/SeedGrid-components/modulos/fe-self-enter.md +104 -0
  177. package/seedgridKB/SeedGrid/SeedGrid-components/modulos/fe-subdomain-tenancy.md +110 -0
  178. package/seedgridKB/SeedGrid/SeedGrid-components/navegacao-e-overlay/API.md +490 -0
  179. package/seedgridKB/SeedGrid/SeedGrid-components/navegacao-e-overlay/Exemplos.md +561 -0
  180. package/seedgridKB/SeedGrid/SeedGrid-components/navegacao-e-overlay/Visao-geral.md +82 -0
  181. package/seedgridKB/SeedGrid/SeedGrid-components/pacotes/Visao-geral.md +68 -0
  182. package/seedgridKB/SeedGrid/SeedGrid-components/pacotes/fe-commons.md +61 -0
  183. package/seedgridKB/SeedGrid/SeedGrid-components/pacotes/fe-core.md +140 -0
  184. package/seedgridKB/SeedGrid/SeedGrid-components/pacotes/fe-playground.md +112 -0
  185. package/seedgridKB/SeedGrid/SeedGrid-components/pacotes/fe-theme.md +97 -0
  186. package/seedgridKB/SeedGrid/SeedGrid-components/providers/API.md +177 -0
  187. package/seedgridKB/SeedGrid/SeedGrid-components/providers/Exemplos.md +332 -0
  188. package/seedgridKB/SeedGrid/SeedGrid-components/providers/Visao-geral.md +106 -0
  189. package/seedgridKB/SeedGrid/SeedGrid-components/showcase.md +70 -0
  190. package/seedgridKB/SeedGrid/Toolkit/agents/arquiteto.md +53 -0
  191. package/seedgridKB/SeedGrid/Toolkit/agents/backend-java.md +45 -0
  192. package/seedgridKB/SeedGrid/Toolkit/agents/backend-rust.md +43 -0
  193. package/seedgridKB/SeedGrid/Toolkit/agents/frontend-react.md +41 -0
  194. package/seedgridKB/SeedGrid/Toolkit/agents/qa.md +44 -0
  195. package/seedgridKB/SeedGrid/Toolkit/agents/revisor.md +40 -0
  196. package/seedgridKB/SeedGrid/Toolkit/references/fluxo-de-trabalho.md +78 -0
  197. package/seedgridKB/SeedGrid/Toolkit/references/glossario.md +15 -0
  198. package/seedgridKB/SeedGrid/Toolkit/references/modos-shared-native.md +27 -0
  199. package/seedgridKB/SeedGrid/Toolkit/rules/backend-java-seedgrid.md +54 -0
  200. package/seedgridKB/SeedGrid/Toolkit/rules/coordenacao.md +39 -0
  201. package/seedgridKB/SeedGrid/Toolkit/rules/formato-entrega.md +29 -0
  202. package/seedgridKB/SeedGrid/Toolkit/rules/frontend-seedgrid.md +47 -0
  203. package/seedgridKB/SeedGrid/Toolkit/rules/personalizacao-local.md +22 -0
  204. package/seedgridKB/SeedGrid/Toolkit/skills/planejar-mudanca/SKILL.md +38 -0
  205. package/seedgridKB/SeedGrid/Toolkit/skills/revisar-codigo/SKILL.md +33 -0
  206. package/seedgridKB/SeedGrid/Toolkit/skills/revisar-codigo/references/checklist.md +25 -0
  207. package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-backend-crud/SKILL.md +29 -0
  208. package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-bump/SKILL.md +26 -0
  209. package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-crud/SKILL.md +221 -0
  210. package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-crud/agents/openai.yaml +4 -0
  211. package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-crud/references/checklist.md +31 -0
  212. package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-crud/references/patterns.md +185 -0
  213. package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-crud/references/routing.md +66 -0
  214. package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-new-screen/SKILL.md +56 -0
  215. package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-new-screen/agents/openai.yaml +4 -0
  216. package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-new-screen/references/checklist.md +32 -0
  217. package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-new-screen/references/steps.md +114 -0
  218. package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-review/SKILL.md +61 -0
  219. package/seedgridKB/SeedGrid/Toolkit/skills/validar-mudanca/SKILL.md +29 -0
  220. package/seedgridKB/SeedGrid/Toolkit/templates/decisao-arquitetura.md +29 -0
  221. package/seedgridKB/SeedGrid/Toolkit/templates/especificacao-tarefa.md +32 -0
  222. package/seedgridKB/SeedGrid/Toolkit/templates/relatorio-validacao.md +30 -0
  223. package/seedgridKB/SeedGrid/Versoes.md +64 -0
  224. package/seedgridKB/SeedGrid/Visao-geral.md +35 -0
  225. package/seedgridKB/manifest.json +142 -0
@@ -0,0 +1,210 @@
1
+ ---
2
+ tags: [seedgrid, extension, backup, exemplos]
3
+ fonte: java/seedgrid-quarkus-ext-backup
4
+ branch: main
5
+ commit: 3bed4075ea
6
+ analisado-em: 2026-10-14
7
+ ---
8
+
9
+ # Exemplos — backup (Quarkus)
10
+
11
+ Voltar: [[SeedGrid/Extensions/backup/Visao-geral|Visão geral do backup]] · Propriedades: [[SeedGrid/Extensions/backup/Configuracao|Configuração do backup]]
12
+
13
+ Todos os exemplos usam tipos e assinaturas reais do runtime (`br.com.seedgrid.backup.*`). Fonte indicada em cada um.
14
+
15
+ ## 1. Dependência Maven
16
+
17
+ Fonte: `runtime/pom.xml` (coordenadas reais).
18
+
19
+ ```xml
20
+ <dependency>
21
+ <groupId>br.com.seedgrid</groupId>
22
+ <artifactId>seedgrid-backup</artifactId>
23
+ <version>2026.10.09</version>
24
+ </dependency>
25
+ ```
26
+
27
+ O host também precisa de: datasource PostgreSQL, um bean `CurrentUserProvider` (commons), um `UserContactProvider` (para o e-mail) e, para `@Audit` persistir, um provider de auditoria (ex. `seedgrid-audit-postgresql`) — ver [[SeedGrid/Extensions/audit/Visao-geral|audit]].
28
+
29
+ ## 2. Fluxo REST
30
+
31
+ Fonte: `ExportController`, `ExportRequest`, `ExportResponse`, `README.md` (seção "Endpoints REST").
32
+
33
+ ```bash
34
+ # Criar (BACKUP_CREATE) -> 201
35
+ curl -X POST https://<host>/exports \
36
+ -H "Authorization: Bearer <SEGREDO:token>" \
37
+ -H "Content-Type: application/json" \
38
+ -d '{ "format": "CSV_ZIP", "scope": "DOMAIN" }'
39
+
40
+ # Listar jobs do usuário corrente (BACKUP_READ)
41
+ curl "https://<host>/exports?page=0&size=20" -H "Authorization: Bearer <SEGREDO:token>"
42
+
43
+ # Status (BACKUP_READ) -> 200 / 404
44
+ curl https://<host>/exports/<jobId> -H "Authorization: Bearer <SEGREDO:token>"
45
+
46
+ # Download (BACKUP_DOWNLOAD) -> 200 application/zip / 404 não pronto / 410 expirado ou falho
47
+ curl -OJ https://<host>/exports/<jobId>/download -H "Authorization: Bearer <SEGREDO:token>"
48
+
49
+ # Cancelar ou excluir (BACKUP_DELETE) -> 204 / 404
50
+ curl -X DELETE https://<host>/exports/<jobId> -H "Authorization: Bearer <SEGREDO:token>"
51
+ ```
52
+
53
+ Valores aceitos: `format` = `CSV_ZIP` | `SQL_DUMP_ZIP`; `scope` = `DOMAIN` | `RAW`. Resposta de criação: `ExportResponse` com `status = QUEUED`, `progress = 0`.
54
+
55
+ Conteúdo do ZIP `CSV_ZIP` (fonte: `CsvZipExporter#createZipArchive`): `data/<tabela-ou-entidade>.csv`, `manifest.json`, `checksums.txt`; nome `export_<schema>_<timestamp>.zip`, gravado sob o prefixo `<schema>/exports` do storage.
56
+
57
+ ## 3. Exporter customizado (SPI `BackupExporter`)
58
+
59
+ Fonte: `spi/BackupExporter.java`, `spi/ExportContext.java`, `spi/ExportResult.java`; adaptado do `README.md` ("Implementar um BackupExporter"). Atenção: a extensão já registra exporters para `CSV_ZIP` e `SQL_DUMP_ZIP`; o `BackupExporterRegistry` lança `IllegalStateException` no startup se houver dois beans para o mesmo `BackupFormat`. Portanto um exporter próprio só pode coexistir se o default do mesmo formato for removido (ex. `quarkus.arc.exclude-types`) — **Inferência**; não há novos valores de `BackupFormat` além dos dois existentes.
60
+
61
+ ```java
62
+ import java.util.List;
63
+
64
+ import br.com.seedgrid.backup.domains.BackupFormat;
65
+ import br.com.seedgrid.backup.domains.ExportScope;
66
+ import br.com.seedgrid.backup.spi.BackupExporter;
67
+ import br.com.seedgrid.backup.spi.ExportContext;
68
+ import br.com.seedgrid.backup.spi.ExportException;
69
+ import br.com.seedgrid.backup.spi.ExportResult;
70
+ import br.com.seedgrid.backup.spi.ExportValidationException;
71
+ import jakarta.enterprise.context.ApplicationScoped;
72
+
73
+ @ApplicationScoped
74
+ public class MySqlDumpExporter implements BackupExporter {
75
+
76
+ @Override
77
+ public BackupFormat format() {
78
+ return BackupFormat.SQL_DUMP_ZIP;
79
+ }
80
+
81
+ @Override
82
+ public void validate(ExportContext ctx) throws ExportValidationException {
83
+ if (ctx.getScope() != ExportScope.RAW) {
84
+ throw new ExportValidationException("só RAW é suportado");
85
+ }
86
+ }
87
+
88
+ @Override
89
+ public ExportResult export(ExportContext ctx) throws ExportException {
90
+ ctx.updateProgress(10, "extraindo dados");
91
+ byte[] zipBytes = buildZip(ctx); // sua lógica
92
+ String key = ctx.getStorageService().store("export.zip", zipBytes);
93
+ ctx.updateProgress(100, "concluído");
94
+
95
+ return ExportResult.builder()
96
+ .artifacts(List.of(ExportResult.ArtifactData.builder()
97
+ .type(ExportResult.ArtifactType.ZIP)
98
+ .storageKey(key)
99
+ .filename("export.zip")
100
+ .sizeBytes(zipBytes.length)
101
+ .mimeType("application/zip")
102
+ .build()))
103
+ .totalSizeBytes(zipBytes.length)
104
+ .build();
105
+ }
106
+
107
+ private byte[] buildZip(ExportContext ctx) {
108
+ throw new UnsupportedOperationException("implementar");
109
+ }
110
+ }
111
+ ```
112
+
113
+ `ExportContext` expõe (Lombok `@Data`): `getJobId()`, `getFormat()`, `getScope()`, `getDatabaseSchema()`, `getOptions()`, `getOption(key, default)` (mapa `options` do pedido; os exporters embutidos não o leem), `updateProgress(int, String)`, `getStorageService()` (`store`/`retrieve`/`delete`) e `getExportJob()` (pode ser `null` — o pipeline não o preenche mais).
114
+
115
+ ## 4. `TenantProvider` para host multitenant
116
+
117
+ Fonte: `spi/TenantProvider.java`; default `configs/SingleTenantBackupProvider` (`@DefaultBean`, tenant `"public"`). O valor do tenant é usado como **schema PostgreSQL** (filtro de `information_schema`) e como prefixo do storage. Schedulers iteram `getAllTenants()` e não fazem nada se a lista vier vazia.
118
+
119
+ ```java
120
+ import java.util.List;
121
+ import java.util.Optional;
122
+
123
+ import br.com.seedgrid.backup.spi.TenantProvider;
124
+ import jakarta.enterprise.context.ApplicationScoped;
125
+
126
+ @ApplicationScoped
127
+ public class MyTenantBackupProvider implements TenantProvider {
128
+
129
+ private static final ThreadLocal<String> CURRENT = new ThreadLocal<>();
130
+
131
+ @Override
132
+ public Optional<String> getCurrentTenant() {
133
+ return Optional.ofNullable(CURRENT.get()); // ou resolver do contexto da requisição
134
+ }
135
+
136
+ @Override
137
+ public void setCurrentTenant(String tenantId) {
138
+ CURRENT.set(tenantId);
139
+ }
140
+
141
+ @Override
142
+ public void clearCurrentTenant() {
143
+ CURRENT.remove();
144
+ }
145
+
146
+ @Override
147
+ public List<String> getAllTenants() {
148
+ return List.of("tenant_a", "tenant_b"); // schemas existentes
149
+ }
150
+ }
151
+ ```
152
+
153
+ O teste `TestTenantProvider` usa o mesmo padrão com `@Alternative @Priority(1)`; a extensão `seedgrid-subdomain-tenancy` fornece um `MultiTenantBackupProvider` (`java/seedgrid-quarkus-ext-subdomain-tenancy/runtime/src/main/java/br/com/seedgrid/subdomaintenancy/backup/MultiTenantBackupProvider.java`).
154
+
155
+ ## 5. Reagir ao fim do export (`SgUserEvent`)
156
+
157
+ Fonte: `ExportService#notifyRequester` e teste `services/ExportUserEventIT` (observer `AFTER_SUCCESS`).
158
+
159
+ ```java
160
+ import br.com.seedgrid.commons.events.SgUserEvent;
161
+ import jakarta.enterprise.context.ApplicationScoped;
162
+ import jakarta.enterprise.event.Observes;
163
+ import jakarta.enterprise.event.TransactionPhase;
164
+
165
+ @ApplicationScoped
166
+ public class BackupFinishedListener {
167
+
168
+ void on(@Observes(during = TransactionPhase.AFTER_SUCCESS) SgUserEvent event) {
169
+ if (!"backup".equals(event.channel())) {
170
+ return;
171
+ }
172
+ // event.event(): "backup.finished.success" ou "backup.finished.error"
173
+ String jobId = (String) event.data().get("exportPublicId");
174
+ String status = (String) event.data().get("status"); // "DONE" ou "FAILED"
175
+ String user = event.userPublicId();
176
+ // ex.: empurrar notificação realtime ao usuário
177
+ }
178
+ }
179
+ ```
180
+
181
+ ## 6. Trocar o canal de notificação (`ExportNotificationService`)
182
+
183
+ Fonte: `spi/ExportNotificationService.java`; default `EmailExportNotificationService` é `@DefaultBean`, então basta declarar outro bean. O `NotificationSchedulerService` só chama `notifyReady` quando `isEnabled()` e `seedgrid.backup.notification.enabled` são `true`; exceção → `notificationError` gravado e nova tentativa após `retry-delay`, até `max-retries`.
184
+
185
+ ```java
186
+ import br.com.seedgrid.backup.entities.ExportJob;
187
+ import br.com.seedgrid.backup.spi.ExportNotificationService;
188
+ import jakarta.enterprise.context.ApplicationScoped;
189
+
190
+ @ApplicationScoped
191
+ public class WebhookExportNotificationService implements ExportNotificationService {
192
+
193
+ @Override
194
+ public void notifyReady(ExportJob job) throws Exception {
195
+ String jobId = job.getPublicId();
196
+ String requester = job.getCreateUserPublicId();
197
+ // enviar para o canal desejado; lançar exceção para provocar retry
198
+ }
199
+ }
200
+ ```
201
+
202
+ ## 7. Template do e-mail
203
+
204
+ Fonte: `spi/impl/DefaultTemplateBackupProvider.java`. Sem código: coloque no classpath do host `templates/backup/ready-notification.html` (tem prioridade sobre `templates/backup-default/html/ready-notification.html`). Placeholders substituídos por `String.replace`: `{{jobId}}`, `{{format}}`, `{{scope}}`, `{{sizeBytes}}`, `{{finishedAt}}`.
205
+
206
+ Ou implemente `TemplateBackupProvider#readyNotification(ExportJob)` em um bean próprio.
207
+
208
+ ## 8. Configuração
209
+
210
+ Exemplos de `application.properties` (mínimo, completo e receitas) estão em [[SeedGrid/Extensions/backup/Configuracao|Configuração do backup]].
@@ -0,0 +1,135 @@
1
+ ---
2
+ tags: [seedgrid, extension, backup, rust]
3
+ fonte: rust/seedgrid-rust-crate-backup
4
+ branch: main
5
+ commit: be738a2d1e
6
+ analisado-em: 2026-10-14
7
+ ---
8
+
9
+ # backup — porte Rust (`seedgrid-rust-crate-backup`)
10
+
11
+ Porte da extensão Quarkus `seedgrid-quarkus-ext-backup`. Lado Java: [[SeedGrid/Extensions/backup/Visao-geral|Visão geral do backup (Java)]] · [[SeedGrid/Extensions/backup/Configuracao|Configuração do backup (Java)]]. Configuração Rust: [[SeedGrid/Extensions/backup/Configuracao-Rust|Configuração Rust do backup]].
12
+
13
+ Motor de **export** de dados de tenant: dump do Postgres para CSV compactado em ZIP, rastreio de jobs no banco, storage plugável (via filemanagement), auditoria (via audit), rate limit no create (via resilience) e notificação por e-mail. **Não** é backup de arquivos/SO e **não** tem restore. **Confirmado** (`src/lib.rs`).
14
+
15
+ ## Identificação
16
+ | Item | Valor |
17
+ |---|---|
18
+ | Pacote Cargo | `seedgrid-rust-crate-backup` (lib `seedgrid_backup`) |
19
+ | Versão | workspace `2026.10.14` |
20
+ | Edição / MSRV | 2021 / 1.82 |
21
+ | Features Cargo | nenhuma |
22
+ | Dependências SeedGrid | `seedgrid-rust-crate-filemanagent` (lib `seedgrid_filemanagement`), `seedgrid-rust-crate-audit`, `seedgrid-rust-crate-resilience`, `seedgrid-rust-crate-cache`, `seedgrid-runtime` (eventos `UserEventSink`) |
23
+
24
+ ## Fluxo
25
+ 1. `ExportService::create_export_job` grava o job `QUEUED`; com `async_enabled`, dispara worker `tokio`: claim (`RUNNING`) → exporter → `DONE` (ou `FAILED`).
26
+ 2. `ExtractDataService`: escopo **RAW** lê `information_schema.tables` (exclui `flyway_%` e tabelas internas `export_jobs`, `export_artifacts`, `audit_log*`) e faz `SELECT <col>::text`; **DOMAIN** usa o SPI `DomainDatasetProvider` do host (default vazio); **CUSTOM** gera erro.
27
+ 3. `CsvZipExporter` (único exporter): ZIP nível 9 com `manifest.json`, `checksums.txt` (formato `sha256sum`) e `data/<nome>.csv` por dataset não vazio.
28
+ 4. Retenção: `expires_at = agora + retention_days`; `BackupScheduler::clean_expired_exports` apaga expirados.
29
+ 5. `BackupScheduler::spawn` roda `process_queued_exports` (a cada `queue_poll_interval`, respeita `max_concurrent_exports`) e `process_notifications` (a cada `notification.poll_interval`, com `max_retries`/`retry_delay`).
30
+ 6. Notificação `EmailExportNotificationService`: `is_enabled = notification.enabled && mailer.from && mailer.host`; envio pelo SPI `Mailer` (default `LoggingMailer`; `SmtpMailer::from_config` para SMTP real via lettre).
31
+
32
+ Fonte: `src/service.rs`, `src/extract.rs`, `src/exporter.rs`, `src/scheduler.rs`, `src/notification.rs`, `src/email_smtp.rs`.
33
+
34
+ ## API pública principal
35
+ | Símbolo | Papel |
36
+ |---|---|
37
+ | `BackupConfig` | config ([[SeedGrid/Extensions/backup/Configuracao-Rust\|Configuração Rust]]) |
38
+ | `BackupPlatform::assemble(Option<&PgPool>, BackupOverrides)` → `Option<Arc<BackupAssembly>>` | montagem a partir do ambiente (opt-in + migrations) |
39
+ | `BackupAssembly::build_service(pool)` / `config()` | `ExportService` por banco (single-DB ou por tenant) |
40
+ | `BackupOverrides { domain_provider, require_opt_in, auditor, user_events }` | seams do host; `Default`: `EmptyDomainDatasetProvider`, `require_opt_in = true`, `NoopAuditor`, sink no-op |
41
+ | `ExportService` | `create_export_job`, `get_export_status`, `list_export_jobs`, `cancel_export_job`, `delete_export_job`, `download_export_file`, `execute_export_async`… |
42
+ | `BackupScheduler` | `spawn`, `clean_expired_exports`, `process_queued_exports`, `process_notifications` |
43
+ | `router(BackupApiState)` / `router_with_resolver(...)` | rotas `/exports` |
44
+ | `rest::export_create_rate_limit()` | `SeedGridRateLimit` (`export-create`, 10/hora) para o host acoplar |
45
+ | `migrate(&PgPool)` / `MIGRATOR` | migrations `0400`–`0402`, histórico `_sqlx_migrations_backup` |
46
+ | `openapi()` | spec utoipa |
47
+ | SPIs: `BackupExporter`, `DomainDatasetProvider`, `TenantProvider` (default `SingleTenantBackupProvider` → `public`), `CurrentUserProvider`, `PermissionGuard` (default `AllowAllPermissionGuard`), `ExportNotificationService`, `Mailer`, `TemplateBackupProvider`, `UserContactProvider` | `src/spi.rs`, `src/rest.rs` |
48
+
49
+ ## Endpoints
50
+ | Método | Path | Permissão (host-enforced via `PermissionGuard`) |
51
+ |---|---|---|
52
+ | POST | `/exports` | `BACKUP_CREATE` (+ rate limit `export-create`) |
53
+ | GET | `/exports?page&size` | `BACKUP_READ` |
54
+ | GET | `/exports/{jobId}` | `BACKUP_READ` |
55
+ | DELETE | `/exports/{jobId}` | `BACKUP_DELETE` |
56
+ | GET | `/exports/{jobId}/download` | `BACKUP_DOWNLOAD` (410 para terminal expirado/falho) |
57
+
58
+ Fonte: `src/rest.rs` → `router`. O guard default (`AllowAllPermissionGuard`) libera tudo; as permissões `BACKUP_*` são aplicadas pelo host.
59
+
60
+ ## Exemplo (de `rust/examples/seedgrid-backup-example/src/main.rs`)
61
+ ```rust
62
+ let mut config = BackupConfig { async_enabled, storage: "filesystem".to_string(), ..BackupConfig::default() };
63
+ config.filesystem.base_path = base_path.to_string();
64
+ let config = Arc::new(config);
65
+ let fs_registry = Arc::new(FileStorageRegistry::new(BuiltInStorageFactories::all()).expect("storage registry"));
66
+ let extract = Arc::new(ExtractDataService::new(pool.clone(), Arc::new(EmptyDomainDatasetProvider)));
67
+ let exporter = Arc::new(CsvZipExporter::new(fs_registry.clone(), extract, config.clone()));
68
+ let exporter_registry = Arc::new(BackupExporterRegistry::new(vec![exporter as Arc<dyn BackupExporter>]).expect("exporter registry"));
69
+ let service = ExportService::new(exporter_registry, ExportJobRepository::new(pool), fs_registry,
70
+ Arc::new(SingleTenantBackupProvider::new()), config, Arc::new(NoopAuditor));
71
+ ```
72
+ O exemplo constrói `BackupConfig` à mão (não chama `from_env`).
73
+
74
+ ## Testes
75
+ - Unitários em `src/*` (checksum, manifest, CSV/ZIP, config/durações).
76
+ - ITs `tests/csv_zip_exporter_it.rs`, `export_async_flow_it.rs`, `export_resource_it.rs`, `extract_data_it.rs`, `user_event_it.rs` com gate `BACKUP_TEST_DATABASE_URL` (`tests/common/mod.rs`).
77
+ - E2E Testcontainers: `rust/examples/seedgrid-backup-example/tests/`.
78
+ - **Não executados.**
79
+
80
+ ## Limitações conhecidas
81
+
82
+ - `SQL_DUMP_ZIP` não tem exporter e `CUSTOM` retorna erro.
83
+ - `includeAttachments` é ignorado e `appVersion` é fixo em `1.0.0`.
84
+ - O mailer de notificação vem ligado por padrão.
85
+
86
+ ## Enums
87
+ Equivalentes Java: [[SeedGrid/Extensions/backup/Enums|Enums do backup (Java)]].
88
+
89
+ | Enum | Arquivo | Java equivalente |
90
+ |---|---|---|
91
+ | `ExportStatus` | `src/enums.rs` | [[SeedGrid/Extensions/backup/Enums#ExportStatus\|ExportStatus]] |
92
+ | `ExportScope` | `src/enums.rs` | [[SeedGrid/Extensions/backup/Enums#ExportScope\|ExportScope]] |
93
+ | `BackupFormat` | `src/enums.rs` | [[SeedGrid/Extensions/backup/Enums#BackupFormat\|BackupFormat]] |
94
+ | `ArtifactType` | `src/enums.rs` | [[SeedGrid/Extensions/backup/Enums#ArtifactType\|ArtifactType]] (aninhado em `ExportArtifact`/`ExportResult` no Java) |
95
+ | `ExportError` | `src/error.rs` | exceções do backup |
96
+
97
+ Todos usam `#[serde(rename_all = "SCREAMING_SNAKE_CASE")]` (JSON igual ao nome Java) e são gravados como `VARCHAR` com o nome em maiúsculas (`as_str()`; leitura por `from_db`, que falha em valor desconhecido). `code()`/`from_code()` usam o código curto (`"done-notified"`, `"csv-zip"`…), case-insensitive.
98
+
99
+ ### ExportStatus
100
+ | Valor | `as_str` / `code` | Efeito no Rust |
101
+ |---|---|---|
102
+ | `Requested` | `REQUESTED` / `requested` | estado inicial da entidade; o claim aceita `Requested` ou `Queued` (`service.rs`) |
103
+ | `Queued` | `QUEUED` / `queued` | gravado por `create_export_job`; `process_queued_exports` lê `status='QUEUED'` |
104
+ | `Running` | `RUNNING` / `running` | gravado no claim; `max_concurrent_exports` conta `status='RUNNING'` |
105
+ | `Done` | `DONE` / `done` | fim com sucesso; `process_notifications` lê `status='DONE'`; baixável |
106
+ | `DoneNotified` | `DONE_NOTIFIED` / `done-notified` | gravado pelo scheduler após o e-mail; baixável e terminal |
107
+ | `Failed` | `FAILED` / `failed` | falha no export; terminal |
108
+ | `Expired` | `EXPIRED` / `expired` | **existe no enum, mas nenhum código o atribui** (a limpeza de retenção apaga o job); terminal |
109
+ | `Cancelled` | `CANCELLED` / `cancelled` | gravado por `cancel_export_job`; terminal |
110
+
111
+ Métodos: `is_downloadable` (`Done`, `DoneNotified`), `is_terminal` (`DoneNotified`, `Failed`, `Expired`, `Cancelled`), `is_in_progress` (`Requested`, `Queued`, `Running`), `display_name`. Coluna `export_jobs.status VARCHAR(20)` (o comentário da migration lista os mesmos 8 valores; **sem CHECK constraint**). Valores iguais ao Java.
112
+
113
+ ```mermaid
114
+ stateDiagram-v2
115
+ [*] --> Queued: create_export_job
116
+ Queued --> Running: claim
117
+ Running --> Done: sucesso
118
+ Running --> Failed: erro
119
+ Done --> DoneNotified: e-mail enviado
120
+ Queued --> Cancelled: cancel
121
+ Running --> Cancelled: cancel
122
+ ```
123
+ `cancel_export_job` cancela qualquer job em andamento (`Requested`, `Queued` ou `Running`); fora disso devolve `false`. Transições conferidas em `service.rs` e `scheduler.rs`.
124
+
125
+ ### ExportScope
126
+ `Domain` (`DOMAIN`/`domain`), `Raw` (`RAW`/`raw`), `Custom` (`CUSTOM`/`custom`). `Domain` usa o `DomainDatasetProvider` do host; `Raw` dumpa as tabelas do schema; `Custom` falha com `CUSTOM scope not implemented` (`exporter.rs`). Coluna `export_jobs.scope VARCHAR(20)`. Iguais ao Java.
127
+
128
+ ### BackupFormat
129
+ `CsvZip` (`CSV_ZIP`/`csv-zip`), `SqlDumpZip` (`SQL_DUMP_ZIP`/`sql-dump-zip`); `mime_type()` sempre `application/zip`. `SqlDumpZip` existe, mas não há exporter registrado (o `BackupExporterRegistry` falha se pedido). Coluna `export_jobs.format VARCHAR(20)`. Iguais ao Java.
130
+
131
+ ### ArtifactType
132
+ `Zip`, `Manifest`, `Checksums`, `Log` (`ZIP`, `MANIFEST`, `CHECKSUMS`, `LOG`); coluna `export_artifacts.artifact_type VARCHAR(20)`. Só `Zip` é criado (`exporter.rs`) e consultado no download (`service.rs`); os demais existem no enum e no schema, sem código que os produza. Iguais ao Java.
133
+
134
+ ### ExportError
135
+ `Export` → HTTP 500; `Validation` → 422; `Retrieval`, `Checksum`, `Storage`, `Database`, `Serde`, `Io` (mapeamento HTTP em `rest.rs`).
@@ -0,0 +1,150 @@
1
+ ---
2
+ tags: [seedgrid, extension, backup]
3
+ fonte: java/seedgrid-quarkus-ext-backup
4
+ branch: main
5
+ commit: 3bed4075ea
6
+ analisado-em: 2026-10-14
7
+ ---
8
+
9
+ # Backup (extension Quarkus)
10
+
11
+ Extensão Quarkus para **exportação/backup de dados por tenant e por usuário** (portabilidade LGPD/GDPR): recebe pedidos via REST, cria jobs de export, executa-os de forma assíncrona, gera um ZIP (dados + `manifest.json` + `checksums.txt`), grava o artefato num storage plugável (via `seedgrid-filemanagement`), notifica o solicitante e expira o artefato após um período de retenção.
12
+
13
+ - Configuração: [[SeedGrid/Extensions/backup/Configuracao|Configuração do backup]]
14
+ - Exemplos: [[SeedGrid/Extensions/backup/Exemplos|Exemplos do backup]]
15
+ - Enums: [[SeedGrid/Extensions/backup/Enums|Enums do backup]] (`ExportStatus`, `ExportScope`, `BackupFormat`, `ArtifactType`)
16
+ - [[SeedGrid/Extensions/backup/Rust|Porte Rust]] (crate `rust/seedgrid-rust-crate-backup`)
17
+
18
+ ## Funcionalidades (Confirmado)
19
+
20
+ | Funcionalidade | Onde |
21
+ |---|---|
22
+ | REST `/exports` (criar, listar, status, download, cancelar/excluir) | `runtime/.../controllers/ExportController.java` |
23
+ | Ciclo de vida do job `QUEUED → RUNNING → DONE/DONE_NOTIFIED/FAILED/CANCELLED` (`REQUESTED` e `EXPIRED` existem no enum, ver [[SeedGrid/Extensions/backup/Enums#ExportStatus|ExportStatus]]) | `domains/ExportStatus.java`, `services/ExportService.java` |
24
+ | Execução assíncrona em thread de plataforma daemon por job (`Thread.ofPlatform().daemon()`), com transações curtas (claim → export sem transação → gravação final) | `ExportService#createExportJob`, `ExportService#executeExport` |
25
+ | Fila: jobs `QUEUED` iniciados pelo scheduler respeitando teto global de jobs `RUNNING` | `schedulers/BackupSchedulerService#processQueuedExports` |
26
+ | Retenção: limpeza diária (cron fixo `0 1 0 * * ?`, 00:01) de jobs com `expiresAt` vencido + artefatos | `BackupSchedulerService#cleanExpiredExports`, `ExportJobRepositoryImpl#findExpiredJobs` |
27
+ | Notificação "backup pronto" por e-mail (Vert.x Mail) com retry | `schedulers/NotificationSchedulerService`, `services/EmailExportNotificationService` |
28
+ | Evento CDI `SgUserEvent` (canal `backup`, eventos `backup.finished.success` / `backup.finished.error`) disparado dentro da transação final (observers `AFTER_SUCCESS` recebem após o commit) | `ExportService#notifyRequester`, teste `ExportUserEventIT` |
29
+ | Exporters embutidos `CSV_ZIP` e `SQL_DUMP_ZIP` (INSERTs por tabela) | `exporters/CsvZipExporter.java`, `exporters/SqlDumpZipExporter.java` |
30
+ | Escopos `DOMAIN` (entidades JPA do metamodel) e `RAW` (tabelas do schema via `information_schema`) | `services/ExtractDataService.java`, `validate()` dos exporters |
31
+ | Isolamento por dono: status/download/cancel/delete/listagem filtram por `createUserPublicId` → não-dono recebe 404 | `ExportService#findOwnedJob`, `ExportJobRepository#findByPublicIdAndUser` |
32
+ | Rate limit no `POST /exports`: `@SeedGridRateLimit(configKey = "export-create", permits = 10, window = 1, windowUnit = HOURS)` | `ExportController#createExport` |
33
+ | Auditoria `@Audit` em criar/cancelar/excluir/download | `ExportService` |
34
+ | Mapeamento de exceções: `ExportValidationException` → 422, `ExportException` → 500 (Problem Details) | `exceptions/BackupExceptionExtension.java` |
35
+
36
+ ## Módulos Maven e coordenadas (Confirmado — `pom.xml`)
37
+
38
+ | Módulo | groupId:artifactId | Versão |
39
+ |---|---|---|
40
+ | parent (pom) | `br.com.seedgrid:seedgrid-backup-parent` | `2026.10.09` |
41
+ | runtime | `br.com.seedgrid:seedgrid-backup` | `2026.10.09` |
42
+ | deployment | `br.com.seedgrid:seedgrid-backup-deployment` | `2026.10.09` |
43
+
44
+ Parent: `br.com.seedgrid:seedgrid-parent:2026.07.02`. O host depende só do runtime; o deployment é ligado via `quarkus-extension-maven-plugin` (`META-INF/quarkus-extension.properties`).
45
+
46
+ ## Dependências SeedGrid (Confirmado — `runtime/pom.xml`)
47
+
48
+ | Artefato | Versão | Uso |
49
+ |---|---|---|
50
+ | `seedgrid-commons` | 2026.10.08 | `CurrentUserProvider`, `UserContactProvider`, `BaseEntity`, `PageReq`, `SgUserEvent`, `ApiExceptionExtension` |
51
+ | `seedgrid-privacy` | 2026.07.08 | fixa convergência de versão (comentário no pom) |
52
+ | `seedgrid-filemanagement` | 2026.07.08 | `FileStorageRegistry`, `FileStorage`, `StorageKey`, `StorageOptions` |
53
+ | `seedgrid-resilience-core` (+ `-deployment` no deployment) | 2026.07.08 | `@SeedGridRateLimit` |
54
+ | `seedgrid-audit-core` | 2026.07.08 | `@Audit` (o provider de persistência de auditoria é escolha do host) |
55
+ | `seedgrid-audit-postgresql` | 2026.07.08 | **somente `test`** |
56
+
57
+ Links: [[SeedGrid/Extensions/filemanagement/Visao-geral|filemanagement]], [[SeedGrid/Extensions/resilience/Visao-geral|resilience]], [[SeedGrid/Extensions/audit/Visao-geral|audit]], [[SeedGrid/Extensions/commons/Visao-geral|commons]].
58
+
59
+ Quarkus/terceiros: `quarkus-arc`, `vertx-mail-client`, `quarkus-qute`, `quarkus-hibernate-orm-panache`, `quarkus-jdbc-postgresql`, `quarkus-flyway`, `quarkus-rest-jackson`, `quarkus-scheduler`, `quarkus-hibernate-validator`, `quarkus-smallrye-openapi`, `commons-csv 1.11.0`, `commons-compress 1.26.0`, Lombok (provided). O e-mail usa `vertx-mail-client` diretamente (não há `quarkus-mailer`).
60
+
61
+ ## Deployment (Confirmado — `deployment/.../BackupProcessor.java`)
62
+
63
+ - Feature `seedgrid-backup`.
64
+ - `ConfigMappingBuildItem(BackupConfig.class, "seedgrid.backup")`.
65
+ - Beans unremovable: `ExportService`, `ExtractDataService`, `BackupSchedulerService`, `NotificationSchedulerService`, `EmailExportNotificationService`, `BackupExporterRegistry`, `CsvZipExporter`, `SqlDumpZipExporter`, `DefaultTemplateBackupProvider`, `SingleTenantBackupProvider`, `ExportController`.
66
+ - Recurso nativo: `templates/backup-default/html/ready-notification.html`.
67
+ - Não há `*BuildTimeConfig`/`@ConfigRoot`.
68
+
69
+ ## Arquitetura e fluxo
70
+
71
+ ```mermaid
72
+ sequenceDiagram
73
+ participant C as Cliente
74
+ participant API as ExportController (/exports)
75
+ participant S as ExportService
76
+ participant W as Thread daemon / BackupSchedulerService
77
+ participant E as BackupExporter (CSV_ZIP / SQL_DUMP_ZIP)
78
+ participant FS as FileStorageRegistry (filemanagement)
79
+ participant N as NotificationSchedulerService
80
+ C->>API: POST /exports {format, scope}
81
+ API->>S: createExportJob (grava QUEUED)
82
+ alt seedgrid.backup.async-enabled=true
83
+ S->>W: thread daemon executeExportAsync
84
+ else false
85
+ W->>S: processQueuedExports (a cada queue-poll-interval)
86
+ end
87
+ W->>S: claimJob → RUNNING
88
+ S->>E: validate + export(ExportContext)
89
+ E->>FS: store(zip) em <schema>/exports
90
+ S->>S: DONE, expiresAt = agora + retention-days, SgUserEvent
91
+ N->>C: e-mail "backup pronto" (retry) → DONE_NOTIFIED
92
+ C->>API: GET /exports/{jobId}/download
93
+ ```
94
+
95
+ Observação (Confirmado): mesmo com `async-enabled=true`, o scheduler de fila também enxerga jobs `QUEUED`; `claimJob` só executa jobs em `REQUESTED`/`QUEUED`, o que evita dupla execução sequencial, mas não há lock pessimista explícito — concorrência entre os dois caminhos é **Não confirmado**.
96
+
97
+ ## APIs públicas e pontos de integração
98
+
99
+ ### Endpoints REST (Confirmado — `ExportController`, `RestControllerPath`)
100
+
101
+ | Método | Path | Permissão (`@PermissionsAllowed`) | Respostas |
102
+ |---|---|---|---|
103
+ | POST | `/exports` | `BACKUP_CREATE` | 201 + `ExportResponse`; rate limit `export-create` |
104
+ | GET | `/exports?page=&size=` | `BACKUP_READ` | 200 lista do usuário corrente |
105
+ | GET | `/exports/{jobId}` | `BACKUP_READ` | 200 / 404 |
106
+ | GET | `/exports/{jobId}/download` | `BACKUP_DOWNLOAD` | 200 `application/zip` / 404 (não pronto ou não-dono) / 410 (terminal não baixável) |
107
+ | DELETE | `/exports/{jobId}` | `BACKUP_DELETE` | 204 / 404 (cancela se em progresso; senão exclui job + artefatos) |
108
+
109
+ ### SPIs e beans substituíveis (Confirmado)
110
+
111
+ | Tipo | Default | Como substituir |
112
+ |---|---|---|
113
+ | `spi.BackupExporter` | `CsvZipExporter` (`CSV_ZIP`), `SqlDumpZipExporter` (`SQL_DUMP_ZIP`) | novo bean CDI; `BackupExporterRegistry` falha no startup se houver 2 para o mesmo `BackupFormat` |
114
+ | `spi.TenantProvider` | `configs.SingleTenantBackupProvider` (`@DefaultBean`, tenant fixo `"public"`) | bean próprio (hosts multitenant) |
115
+ | `spi.ExportNotificationService` | `services.EmailExportNotificationService` (`@DefaultBean`) | bean próprio |
116
+ | `spi.TemplateBackupProvider` | `spi.impl.DefaultTemplateBackupProvider` (`@DefaultBean`; usa `templates/backup/ready-notification.html` do host, senão `templates/backup-default/html/ready-notification.html`; placeholders `{{jobId}}`, `{{format}}`, `{{scope}}`, `{{sizeBytes}}`, `{{finishedAt}}`) | bean próprio ou template no classpath do host |
117
+ | `commons.persistence.spi.CurrentUserProvider` | nenhum na extensão | **o host deve fornecer** |
118
+ | `commons.spi.UserContactProvider` | nenhum na extensão | necessário para o e-mail (destinatário via `provideByPublicId`) — Inferência: o host/commons fornece |
119
+
120
+ ### Eventos
121
+ - `SgUserEvent(userPublicId, "backup", "backup.finished.success" | "backup.finished.error", {exportPublicId, status})` — só quando o job tem `createUserPublicId`.
122
+
123
+ ## Persistência e migrations (Confirmado)
124
+
125
+ `runtime/src/main/resources/db/migration/backup/`, tabela de histórico Flyway `flyway_schema_history_backup` (via `microprofile-config.properties`):
126
+
127
+ | Versão | Conteúdo |
128
+ |---|---|
129
+ | V400 | `export_jobs`, `export_artifacts` (PostgreSQL, `TIMESTAMPTZ`, FK `ON DELETE CASCADE`) |
130
+ | V401 | Insere permissões `BACKUP_CREATE/READ/DOWNLOAD/DELETE` em `permissions` e vincula ao papel `ADMIN` (`roles`, `role_permissions`) — exige tabelas da extensão de segurança |
131
+ | V402 | Coluna `active` nas duas tabelas |
132
+ | V403 | `audience = null` nas permissões de backup (se `permissions` existir) |
133
+
134
+ ## Testes (não executados)
135
+
136
+ `runtime/src/test/java/br/com/seedgrid/backup/` (Quarkus DevServices PostgreSQL 16, migrations de teste em `db/testdata/backup`):
137
+ - `controllers/ExportResourceIT` — endpoints REST; `controllers/ExportAsyncFlowIT` — pipeline assíncrono real com `SingleTenantBackupProvider` (perfil com `async-enabled=true`).
138
+ - `exporters/CsvZipExporterIT`, `exporters/SqlDumpZipExporterIT` — geração de ZIP.
139
+ - `services/ExtractDataServiceIT` — extração RAW/DOMAIN e exclusões; `services/ExportUserEventIT` — `SgUserEvent` após commit (sucesso/falha).
140
+ - `configs/SingleTenantBackupProviderTest`, `utils/ChecksumUtilTest` — unitários.
141
+ - Suporte: `TestTenantProvider` (`@Alternative @Priority(1)`), `TestCurrentUserProvider`, `support/SampleDomainEntity`.
142
+
143
+ ## Limitações
144
+
145
+ - `options` do `ExportRequest` (mapa livre) é serializado no job e repassado ao `ExportContext` (`getOptions()`/`getOption(key, default)`); os exporters embutidos não leem nenhuma opção — só exporters customizados podem usá-lo. **Confirmado** (`ExportService#buildExportContext`).
146
+ - Limpeza por retenção tem cron fixo (`0 1 0 * * ?`), não configurável. **Confirmado**.
147
+ - Banco: PostgreSQL (migrations, `information_schema`, `gen_random_uuid()`).
148
+ - `generateDownloadUrl` (URL assinada) lança `UnsupportedOperationException` no adapter padrão; download passa os bytes pela API.
149
+ - Notificação por e-mail fica **ativa por padrão** apontando para `smtp.gmail.com` sem credenciais (fallbacks do `microprofile-config.properties`) — ver [[SeedGrid/Extensions/backup/Configuracao|Configuração]].
150
+ - `appVersion("1.0.0")` fixo no manifest (TODO no código).
@@ -0,0 +1,86 @@
1
+ ---
2
+ tags: [seedgrid, extension, billing, rust, configuracao]
3
+ fonte: rust/seedgrid-rust-crate-billing
4
+ branch: main
5
+ commit: be738a2d1e
6
+ analisado-em: 2026-10-14
7
+ ---
8
+
9
+ # billing — Configuração Rust
10
+
11
+ Visão do crate: [[SeedGrid/Extensions/billing/Rust|Porte Rust do billing]] · Java: [[SeedGrid/Extensions/billing/Configuracao|Configuração do billing (Java)]].
12
+
13
+ ## Cabeçalho
14
+ | Item | Valor |
15
+ |---|---|
16
+ | Struct | `StripeConfig` (prefixo Java `seedgrid.billing.stripe`) — `rust/seedgrid-rust-crate-billing/src/config.rs` |
17
+ | Mecanismo | `StripeConfig::from_env()` (`std::env::var`), ou struct montada pelo host |
18
+ | Quem chama | `BillingPlatform::assemble` chama `StripeConfig::from_env()` |
19
+ | Leitura | no boot (uma vez) |
20
+
21
+ Helpers: `opt(name)` faz `trim` e trata vazio como ausente; `opt_any(names)` devolve o primeiro não vazio (primário antes do alias). `from_env` nunca falha: `api_key`/`webhook_secret` ausentes viram `""`.
22
+
23
+ ## Stripe
24
+ | Propriedade | Tipo | Valores aceitos | Padrão | Obrigatória | Comportamento | Uso | Relações | Leitura | Origem |
25
+ |---|---|---|---|---|---|---|---|---|---|
26
+ | 🔒 `SEEDGRID_BILLING_STRIPE_APIKEY` / alias `SEEDGRID_BILLING_STRIPE_API_KEY` (Java `seedgrid.billing.stripe.apiKey`) | String | chave secreta Stripe | `""` | Sim para habilitar via `BillingPlatform` (vazio → `Ok(None)`, billing desligado) | `Authorization: Bearer`; prefixo `sk_test` habilita Test Clock | `stripe/provider.rs` (transporte, Test Clock), `platform.rs` | `test_clock_enabled` | `StripeConfig::from_env()` | `config.rs`; `platform.rs` → `assemble` |
27
+ | 🔒 `SEEDGRID_BILLING_STRIPE_WEBHOOK_SECRET` (Java `webhookSecret`) | String | segredo `whsec_...` | `""` | Sim (na prática): sem ele a verificação de assinatura falha | verifica assinatura do webhook | `stripe/provider.rs` → `signature::construct_event` | — | `from_env()` | `config.rs`, `stripe/signature.rs` |
28
+ | `SEEDGRID_BILLING_STRIPE_DEFAULT_SUCCESS_URL` / alias `SEEDGRID_BILLING_STRPE_DEFAULT_SUCCESS_URL` (Java `defaultSuccessUrl`) | String | URL | `""` | Não | usada no checkout quando o request não traz URL | `stripe/provider.rs` | grafia correta tem precedência (teste `default_success_url_accepts_strpe_typo_alias_with_stripe_precedence`) | `from_env()` | `config.rs` |
29
+ | `SEEDGRID_BILLING_STRIPE_DEFAULT_CANCEL_URL` (Java `defaultCancelUrl`) | String | URL | `""` | Não | idem para cancelamento | `stripe/provider.rs` | — | `from_env()` | `config.rs` |
30
+ | `SEEDGRID_BILLING_STRIPE_TEST_CLOCK_ENABLED` (Java `test-clock-enabled`) | bool | `true`/`false` (parse `bool`, após `trim`) | `true` | Não | com chave `sk_test`, cria a assinatura sob um Test Clock | `stripe/provider.rs` | `api_key` | `from_env()` | `config.rs`, `provider.rs` |
31
+ | `SEEDGRID_BILLING_STRIPE_PRODUCT` (Java `seedgrid.billing.stripe.product`) | `Option<String>` | id de produto | — | Não | `ensure_product_bootstrap` garante o produto se definido | `stripe/bootstrap.rs` (host precisa chamar) | `product_name` | `from_env()` | `config.rs`, `bootstrap.rs` |
32
+ | `SEEDGRID_BILLING_STRIPE_PRODUCT_NAME` (Java `product-name`) | `Option<String>` | texto | — | Não | nome do produto no bootstrap | `stripe/bootstrap.rs` | `product` | `from_env()` | idem |
33
+ | `SEEDGRID_BILLING_STRIPE_API_BASE` | String | URL | `https://api.stripe.com` (`DEFAULT_STRIPE_API_BASE`) | Não | base da API (útil em testes/mocks) | `stripe/provider.rs` | sem equivalente Java | `from_env()` | `config.rs` |
34
+
35
+ Mapeamento Java ↔ env: os nomes Java vêm de `@ConfigProperty` em `java/seedgrid-quarkus-ext-billing/seedgrid-billing-stripe/runtime/.../StripeBillingProvider.java` e `StripeProductBootstrap.java` (**Confirmado**). Os nomes de env do Rust **não** seguem exatamente a regra MicroProfile para chaves camelCase (ex.: `apiKey` → `SEEDGRID_BILLING_STRIPE_APIKEY`), são convenção do projeto (doc de `config.rs`).
36
+
37
+ ## Structs
38
+ | Campo | `Default` |
39
+ |---|---|
40
+ | `StripeConfig.api_key`, `webhook_secret`, `default_success_url`, `default_cancel_url` | `""` |
41
+ | `StripeConfig.test_clock_enabled` | `true` |
42
+ | `StripeConfig.product`, `product_name` | `None` |
43
+ | `StripeConfig.api_base` | `https://api.stripe.com` |
44
+
45
+ ## Features Cargo
46
+ | Feature | Padrão | Efeito |
47
+ |---|---|---|
48
+ | `postgres` | sim | `PgBillingEventRepository`, `migrate`, `MIGRATOR` |
49
+ | `stripe` | sim | módulo `stripe` (provider, assinatura, bootstrap) |
50
+ | `postgres` + `stripe` | — | habilitam `BillingPlatform`/`BillingOverrides` |
51
+
52
+ ## Configuração não-env
53
+ - `BillingApiStateBuilder::authorizer(...)` (default `AllowAllBillingAuthorizer`).
54
+ - Rate limits fixos em código (`checkout_rate_limit`, `portal_rate_limit`, `webhook_rate_limit`); ver [[SeedGrid/Extensions/resilience/Configuracao-Rust|Configuração Rust do resilience]].
55
+
56
+ ## Somente testes
57
+ | Variável | Onde |
58
+ |---|---|
59
+ | `BILLING_IT_PG_URL` | `tests/pg_billing_events_it.rs` |
60
+ | `BILLING_STRIPE_IT_BASE`, 🔒 `BILLING_STRIPE_IT_KEY` | `tests/stripe_transport_it.rs` |
61
+
62
+ ## Configuração mínima
63
+ ```dotenv
64
+ SEEDGRID_BILLING_STRIPE_APIKEY=<SEGREDO:stripe-api-key>
65
+ SEEDGRID_BILLING_STRIPE_WEBHOOK_SECRET=<SEGREDO:stripe-webhook-secret>
66
+ ```
67
+
68
+ ## Configuração completa comentada
69
+ ```dotenv
70
+ SEEDGRID_BILLING_STRIPE_APIKEY=<SEGREDO:stripe-api-key> # alias: SEEDGRID_BILLING_STRIPE_API_KEY
71
+ SEEDGRID_BILLING_STRIPE_WEBHOOK_SECRET=<SEGREDO:stripe-webhook-secret>
72
+ SEEDGRID_BILLING_STRIPE_DEFAULT_SUCCESS_URL=https://<app>/assinatura?ok=1 # alias legado: ..._STRPE_...
73
+ SEEDGRID_BILLING_STRIPE_DEFAULT_CANCEL_URL=https://<app>/assinatura?cancel=1
74
+ SEEDGRID_BILLING_STRIPE_TEST_CLOCK_ENABLED=true # só tem efeito com chave sk_test
75
+ SEEDGRID_BILLING_STRIPE_PRODUCT=<id-produto> # bootstrap (host chama ensure_product_bootstrap)
76
+ SEEDGRID_BILLING_STRIPE_PRODUCT_NAME=<nome>
77
+ # SEEDGRID_BILLING_STRIPE_API_BASE=https://api.stripe.com
78
+ ```
79
+
80
+ ## Receitas
81
+ - **Habilitar com Stripe**: definir a API key e o webhook secret; `BillingPlatform::assemble(Some(&pool), BillingOverrides::default())`; montar `router(state)` e acoplar os rate limits.
82
+ - **Testes E2E com tempo avançado**: chave `sk_test_...` e `SEEDGRID_BILLING_STRIPE_TEST_CLOCK_ENABLED=true`.
83
+ - **Mock do Stripe**: `SEEDGRID_BILLING_STRIPE_API_BASE=http://localhost:<porta>`.
84
+
85
+ ## Dúvidas e lacunas
86
+ - Grupos de config do billing-core Java atual (`trial`, `catalog`, `checkout`, `portal`, `access-gate`, `feature-gate`, `reconciliation`, `api`, `business-timezone`, `currency`, …) **não existem** no Rust.