@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,243 @@
1
+ ---
2
+ tags: [seedgrid, extension, billing, quarkus, configuracao]
3
+ fonte: java/seedgrid-quarkus-ext-billing
4
+ branch: main
5
+ commit: ba38efc347
6
+ analisado-em: 2026-10-14
7
+ ---
8
+
9
+ # Billing (Quarkus): configuração
10
+
11
+ Voltar para [[SeedGrid/Extensions/billing/Visao-geral|Visão geral do billing]] · [[SeedGrid/Extensions/billing/Exemplos|Exemplos]]
12
+
13
+ ## 1. Cabeçalho
14
+
15
+ | Item | Valor |
16
+ |---|---|
17
+ | Prefixos | `seedgrid.billing.*` no core e `seedgrid.billing.stripe.*` no provider Stripe |
18
+ | Classes `@ConfigMapping` (core) | `BillingAccessGateConfig` (`seedgrid.billing.access-gate`), `BillingApiConfig` (`seedgrid.billing.api`), `BillingCatalogConfig` (`.catalog`), `BillingCheckoutConfig` (`.checkout`), `BillingPortalConfig` (`.portal`), `BillingTrialConfig` (`.trial`), `BillingFeatureGateConfig` (`.feature-gate`), `PlanTermAttributesConfig` (`.plan-term.additional-attributes`), `BillingReconciliationConfig` (`.reconciliation`) |
19
+ | `@ConfigProperty` (core) | `BillingConfig` (business-timezone, currency, overage-meter-name), `BillingEntityManager` (persistence-unit), `PlanPublicationService` (stripe.product, como fallback) |
20
+ | `ConfigProvider` direto | `BillingApiOpenApiFilter` (`seedgrid.billing.api.enabled`) |
21
+ | `@ConfigProperty` (stripe) | `StripeBillingProvider` (apiKey, webhookSecret, defaultSuccessUrl, defaultCancelUrl, test-clock-enabled) e `StripeProductBootstrap` (product, product-name) |
22
+ | Defaults em arquivo | `seedgrid-billing-core/runtime/src/main/resources/META-INF/microprofile-config.properties` (ordinal 100) |
23
+ | Fase | **Todas são de runtime.** Não há `@ConfigRoot` nem `*BuildTimeConfig` nos deployments. Os processors só registram feature, beans e `ConsumesUsageSites`. |
24
+
25
+ Abreviações usadas na coluna Origem:
26
+ - `core/` = `java/seedgrid-quarkus-ext-billing/seedgrid-billing-core/runtime/src/main/java/br/com/seedgrid/billing/`
27
+ - `stripe/` = `java/seedgrid-quarkus-ext-billing/seedgrid-billing-stripe/runtime/src/main/java/br/com/seedgrid/billing/stripe/`
28
+ - `core-mp` = `seedgrid-billing-core/runtime/src/main/resources/META-INF/microprofile-config.properties`
29
+
30
+ **Por que cada grupo tem um prefixo próprio:** o SmallRye recusa chave desconhecida sob o prefixo de um mapping. Se houvesse um mapping único em `seedgrid.billing`, as chaves `seedgrid.billing.stripe.*` derrubariam o boot. **Confirmado** (javadoc de `BillingConfig`).
31
+
32
+ **Variáveis de ambiente:** a regra MicroProfile se aplica sem ambiguidade a todas as propriedades abaixo, porque a busca vai da propriedade para a env. Exemplos: `seedgrid.billing.access-gate.enabled` vira `SEEDGRID_BILLING_ACCESS_GATE_ENABLED`, e `seedgrid.billing.stripe.apiKey` vira `SEEDGRID_BILLING_STRIPE_APIKEY`. Além disso, o `core-mp` expande **nomes explícitos** em algumas chaves, indicados na coluna Relações. Três deles **diferem** da regra MP.
33
+
34
+ ## 2. Propriedades próprias
35
+
36
+ ### 2.1 Geral / negócio
37
+
38
+ | Propriedade | Tipo | Valores aceitos | Padrão | Obrigatória | Comportamento | Uso | Relações | Fase | Origem |
39
+ |---|---|---|---|---|---|---|---|---|---|
40
+ | `seedgrid.billing.business-timezone` | String (ZoneId) | qualquer `ZoneId` válido | `America/Sao_Paulo` | Não | Define o fuso em que o negócio conta os dias: vigência de preço, virada do ciclo e data nos e-mails de acesso. Valor vazio ou inválido gera um WARN e usa `America/Sao_Paulo`, sem derrubar o boot. | `BusinessTimeZone` → services de ciclo, `UserAccessEmails` | `core-mp` expande `${SEEDGRID_BILLING_BUSINESS_TIMEZONE:America/Sao_Paulo}`. É independente de `seedgrid.app.business-timezone` (commons). | runtime | declaração: `core/configs/BillingConfig.java` (construtor); consumo: `core/configs/BusinessTimeZone#resolve` |
41
+ | `seedgrid.billing.currency` | String | código ISO 4217 em minúsculas (ex.: `brl`, `usd`), como o Stripe espera | `brl` | Não | Moeda dos preços publicados no provider (fixo e metered) e do overview. | `PlanPublicationService#publish`, `BillingOverviewService` | `core-mp`: `${SEEDGRID_BILLING_CURRENCY:brl}` | runtime | `core/configs/BillingConfig.java`; consumo `core/services/PlanPublicationService#publish` |
42
+ | `seedgrid.billing.overage-meter-name` | String | texto livre | `Excedente` | Não | Prefixo do nome **exibido** do meter de excedente no provider: `"<valor> - <label do contador>"`. O identificador técnico é o event name `overage_<produto>_<contador>`. | `PlanPublicationService#publish` | — | runtime | `core/configs/BillingConfig.java`; consumo `core/services/PlanPublicationService#publish` |
43
+ | `seedgrid.billing.persistence-unit` | Optional\<String\> | nome de PU; vazio ou `<default>` = PU default | — (sem valor = PU default) | Não | Escolhe o `EntityManager` das tabelas do billing. | `BillingEntityManager` (repositories do billing) | O `subdomain-tenancy` define `master` no microprofile-config dele (**Confirmado**). Usuários e security continuam no EntityManager da security. | runtime | `core/repositories/BillingEntityManager.java` (construtor) |
44
+
45
+ ### 2.2 API e bloqueio geral
46
+
47
+ | Propriedade | Tipo | Valores aceitos | Padrão | Obrigatória | Comportamento | Uso | Relações | Fase | Origem |
48
+ |---|---|---|---|---|---|---|---|---|---|
49
+ | `seedgrid.billing.api.enabled` | boolean | `true`/`false` | `true` | Não | Com `false`, os prefixos `/admin/plans`, `/admin/subscriptions`, `/admin/accounts`, `/admin/billing`, `/me/plans`, `/me/subscription`, `/me/usage` e `/me/billing` respondem 404 (pre-matching, antes da autenticação) e somem do OpenAPI. O webhook continua. | `BillingApiToggleFilter#filter` (lido por requisição) e `BillingApiOpenApiFilter` (no startup) | O login-tenancy liga este valor a `seedgrid.login-tenancy.modules.billing.enabled` (BILLING_INTEGRATION_GUIDE). O default fica no `@WithDefault` de propósito, para um tenancy poder definir o próprio default sem empatar em ordinal. | runtime | `core/configs/BillingApiConfig#enabled`; consumo `core/filters/BillingApiToggleFilter`, `core/filters/BillingApiOpenApiFilter#filterOpenAPI` |
50
+ | `seedgrid.billing.access-gate.enabled` | boolean | `true`/`false` | `false` | Não | Liga o bloqueio **geral**: conta sem assinatura vigente recebe 402 em qualquer endpoint autenticado. Ficam liberados `OPTIONS`, anônimos, `/public`, `/q/`, `/me/plans`, `/me/subscription`, `/me/usage`, `/me/billing`, `allowed-paths`, `@PlatformScope` e usuário sem conta. | `AccessGateFilter#filter` (por requisição) | O bloqueio por funcionalidade (`@ConsumesUsage`/`@RequiresPlanFeature`) independe deste. | runtime | `core/configs/BillingAccessGateConfig#enabled`; consumo `core/filters/AccessGateFilter#filter` |
51
+ | `seedgrid.billing.access-gate.block-past-due` | boolean | `true`/`false` | `true` | Não | Assinatura `PAST_DUE` também nega acesso no bloqueio geral (402 `PAYMENT_PAST_DUE`). | `SubscriptionAccessService#denialForAccess`, chamado só por `AccessGateFilter` | **Confirmado:** só tem efeito com `access-gate.enabled=true`. O **consumo** (`denialForConsumption`/`denialForAnyConsumption`) sempre bloqueia `PAST_DUE`, independentemente desta flag. | runtime | `core/configs/BillingAccessGateConfig#blockPastDue`; consumo `core/services/SubscriptionAccessService#denialForAccess` |
52
+ | `seedgrid.billing.access-gate.allowed-paths` | Optional\<List\<String\>\> | prefixos separados por vírgula; casa por fronteira de segmento (`/me/plans` não casa `/me/plansx`); prefixo terminado em `/` casa qualquer coisa abaixo | — | Não | Prefixos extras sempre liberados pelo bloqueio geral. | `AccessGateFilter#allowedPaths`, `BillingPaths#startsWithAny` | Somados a `RestControllerPath.ACCESS_GATE_ALWAYS_ALLOWED`. | runtime | `core/configs/BillingAccessGateConfig#allowedPaths` |
53
+
54
+ ### 2.3 Catálogo, checkout e portal
55
+
56
+ | Propriedade | Tipo | Valores aceitos | Padrão | Obrigatória | Comportamento | Uso | Relações | Fase | Origem |
57
+ |---|---|---|---|---|---|---|---|---|---|
58
+ | `seedgrid.billing.catalog.product-id` | Optional\<String\> | ID do produto no provider | — (cai em `seedgrid.billing.stripe.product`) | Condicional: um dos dois é necessário para publicar term, criar meter e reportar excedente | Define o produto sob o qual os preços dos planos e os meters (`overage_<produto>_<contador>`) são criados. Sem nenhum dos dois, a publicação lança `ProviderProductNotConfiguredException`, e o consumo com excedente não reporta ao provider (retorno silencioso). | `PlanPublicationService#productId`, `UsageService#reportOverageAfterCommit` | Fallback: `seedgrid.billing.stripe.product`. | runtime | `core/configs/BillingCatalogConfig#productId`; consumo `core/services/PlanPublicationService#productId` |
59
+ | `seedgrid.billing.checkout.success-url` | Optional\<String\> | URL absoluta | — | Condicional: o Stripe exige URL de sucesso; sem ela, vale `seedgrid.billing.stripe.defaultSuccessUrl` | URL para onde o provider devolve o cliente após o checkout. | `CheckoutService` → `CheckoutRequest.successUrl` | O Stripe usa `defaultSuccessUrl` quando esta é nula. Se ambas faltarem, envia `""` (**Inferência:** o Stripe recusaria a sessão). | runtime | `core/configs/BillingCheckoutConfig#successUrl`; consumo `core/services/CheckoutService` (l.120) |
60
+ | `seedgrid.billing.checkout.cancel-url` | Optional\<String\> | URL absoluta | — | Condicional (idem) | URL de retorno quando o cliente cancela o checkout. | `CheckoutService` | Fallback: `seedgrid.billing.stripe.defaultCancelUrl`. | runtime | `core/configs/BillingCheckoutConfig#cancelUrl`; consumo `core/services/CheckoutService` (l.121) |
61
+ | `seedgrid.billing.portal.return-url` | Optional\<String\> | URL absoluta | — | Não | URL de retorno do customer portal. Sem valor, não chama `setReturnUrl` (o Stripe usa o default da conta). | `SubscriptionChangeService#portal` → `StripeBillingProvider#createPortal` | — | runtime | `core/configs/BillingPortalConfig#returnUrl`; consumo `core/services/SubscriptionChangeService` (l.86) |
62
+
63
+ ### 2.4 Trial e feature gate
64
+
65
+ | Propriedade | Tipo | Valores aceitos | Padrão | Obrigatória | Comportamento | Uso | Relações | Fase | Origem |
66
+ |---|---|---|---|---|---|---|---|---|---|
67
+ | `seedgrid.billing.trial.enabled` | boolean | `true`/`false` | `true` | Não | Conta nova sem nenhuma assinatura ganha uma assinatura `ACTIVE` no term do trial. | `TrialService#provisionTrial` | `core-mp`: `${SEEDGRID_BILLING_TRIAL_ENABLED:true}` | runtime | `core/configs/BillingTrialConfig#enabled`; consumo `core/services/TrialService#provisionTrial` |
68
+ | `seedgrid.billing.trial.plan-term-public-id` | String | `publicId` de um term do plano TRIAL | `00000000-0000-0000-0000-0000000000a2` (semeado pela V505) | Não | Define o term usado no trial. Se não existir, `provisionTrial` só registra um WARN, enquanto `/admin/plans/trial` lança `TrialPlanNotFoundException`. Um term de outro plano também é recusado. | `TrialService#requireTrialTerm`, `#provisionTrial` | `core-mp`: `${SEEDGRID_BILLING_TRIAL_PLAN_TERM_PUBLIC_ID:...}` | runtime | `core/configs/BillingTrialConfig#planTermPublicId` |
69
+ | `seedgrid.billing.feature-gate.exempt-company-ids` | Optional\<List\<Long\>\> | IDs internos de `Company`, separados por vírgula | — | Não | Companies nunca bloqueadas por `@RequiresPlanFeature`, por exemplo a empresa da plataforma. | `PlanFeatureGate#isExempt` | — | runtime | `core/configs/BillingFeatureGateConfig#exemptCompanyIds`; consumo `core/services/PlanFeatureGate` |
70
+
71
+ ### 2.5 Limites dos `additionalAttributes` e reconciliação
72
+
73
+ | Propriedade | Tipo | Valores aceitos | Padrão | Obrigatória | Comportamento | Uso | Relações | Fase | Origem |
74
+ |---|---|---|---|---|---|---|---|---|---|
75
+ | `seedgrid.billing.plan-term.additional-attributes.max-size-bytes` | int | inteiro positivo | `16384` | Não | Tamanho máximo, em bytes UTF-8, do JSON final. Se exceder, responde HTTP 400. | `PlanTermAttributesService` | `core-mp` expande `${SEEDGRID_BILLING_PLAN_TERM_ATTRIBUTES_MAX_SIZE_BYTES:16384}`. **O nome explícito difere** da regra MP (`SEEDGRID_BILLING_PLAN_TERM_ADDITIONAL_ATTRIBUTES_MAX_SIZE_BYTES`). Ambos funcionam (Inferência pela precedência de ordinais). | runtime | `core/configs/PlanTermAttributesConfig#maxSizeBytes`; consumo `core/services/PlanTermAttributesService` (l.50) |
76
+ | `seedgrid.billing.plan-term.additional-attributes.max-depth` | int | inteiro positivo (objeto raiz = 1) | `5` | Não | Profundidade máxima de aninhamento. | idem | `core-mp`: `SEEDGRID_BILLING_PLAN_TERM_ATTRIBUTES_MAX_DEPTH` (difere da regra MP) | runtime | `core/configs/PlanTermAttributesConfig#maxDepth` |
77
+ | `seedgrid.billing.plan-term.additional-attributes.max-keys` | int | inteiro positivo | `100` | Não | Total de chaves em todos os objetos, inclusive aninhados e dentro de arrays. | idem | `core-mp`: `SEEDGRID_BILLING_PLAN_TERM_ATTRIBUTES_MAX_KEYS` (difere da regra MP) | runtime | `core/configs/PlanTermAttributesConfig#maxKeys` |
78
+ | `seedgrid.billing.reconciliation.throttle-seconds` | long | `>= 0`; `0` = sem throttle | `60` | Não | Intervalo mínimo entre reconciliações **implícitas** da mesma conta com o provider (anti-stampede, guardado em memória). | `SubscriptionReconciliationService#reconcileThrottled` | `core-mp`: `${SEEDGRID_BILLING_RECONCILIATION_THROTTLE_SECONDS:60}` | runtime | `core/configs/BillingReconciliationConfig#throttleSeconds`; consumo `core/services/SubscriptionReconciliationService` (construtor) |
79
+
80
+ ### 2.6 Provider Stripe (`seedgrid-billing-stripe`)
81
+
82
+ | Propriedade | Tipo | Valores aceitos | Padrão | Obrigatória | Comportamento | Uso | Relações | Fase | Origem |
83
+ |---|---|---|---|---|---|---|---|---|---|
84
+ | 🔒 `seedgrid.billing.stripe.apiKey` | String | secret key do Stripe (`sk_test_…`/`sk_live_…`); **não** use a publishable `pk_…` | — | **Sim**, com o módulo stripe presente (**Inferência forte**: `@ConfigProperty` String sem default; o teste de deployment define valor dummy) | Atribuída a `Stripe.apiKey` global no `@PostConstruct`. O prefixo `sk_test` ativa o Test Clock e a busca de customers em clocks. | `StripeBillingProvider#init`, `#maybeCreateTestClockCustomer` | env: `SEEDGRID_BILLING_STRIPE_APIKEY`. O guia de integração sugere `${STRIPE_API_KEY}` no host. | runtime | `stripe/spis/impl/StripeBillingProvider.java` (construtor) |
85
+ | 🔒 `seedgrid.billing.stripe.webhookSecret` | String | signing secret do endpoint (`whsec_…`) | — | **Sim**, com o módulo stripe (mesma inferência) | Valida o header `Stripe-Signature` em `Webhook.constructEvent`. Se falhar, responde 400. | `StripeBillingProvider#parseAndVerifyWebhook` | env: `SEEDGRID_BILLING_STRIPE_WEBHOOKSECRET`. Em dev, vem do `stripe listen`. | runtime | idem (l.251) |
86
+ | `seedgrid.billing.stripe.defaultSuccessUrl` | Optional\<String\> | URL absoluta | — | Condicional (ver `checkout.success-url`) | Fallback quando o core não envia a URL de sucesso. Sem nenhuma das duas, envia `""`. | `StripeBillingProvider#createCheckout` | Preferir `seedgrid.billing.checkout.success-url`. | runtime | idem (l.126) |
87
+ | `seedgrid.billing.stripe.defaultCancelUrl` | Optional\<String\> | URL absoluta | — | Condicional | Fallback da URL de cancelamento. | `StripeBillingProvider#createCheckout` | Preferir `seedgrid.billing.checkout.cancel-url`. | runtime | idem (l.127) |
88
+ | `seedgrid.billing.stripe.test-clock-enabled` | boolean | `true`/`false` | `true` | Não | Com chave `sk_test`, a nova assinatura nasce num customer preso a um Stripe Test Clock, para testes E2E. Com chave live, é ignorada. | `StripeBillingProvider#maybeCreateTestClockCustomer` | Só tem efeito com `apiKey` iniciada por `sk_test`. | runtime | idem (construtor, l.101) |
89
+ | `seedgrid.billing.stripe.product` | Optional\<String\> | ID do produto Stripe (fixo, escolhido pelo host) | — | Condicional (ver `catalog.product-id`) | No startup, `StripeProductBootstrap` faz retrieve-or-create do produto. É best-effort: falha gera WARN. Também serve de fallback do `catalog.product-id`. | `StripeProductBootstrap#onStart`, `PlanPublicationService#productId` | Lida também pelo **core**. | runtime | `stripe/services/StripeProductBootstrap.java`; `core/services/PlanPublicationService.java` (construtor) |
90
+ | `seedgrid.billing.stripe.product-name` | Optional\<String\> | texto | — (usa o próprio ID) | Não | Nome do produto criado no bootstrap. | `StripeProductBootstrap#onStart` | Só tem efeito com `seedgrid.billing.stripe.product`. | runtime | `stripe/services/StripeProductBootstrap.java` |
91
+
92
+ ### 2.7 Propriedades de outras extensions lidas ou exigidas pelo billing
93
+
94
+ | Propriedade | Dona | Uso no billing | Origem |
95
+ |---|---|---|---|
96
+ | `seedgrid.show-dev-message` (default `false`) | commons/security (mesma chave em `ApiExceptionHandler` do commons) | `BillingApiExceptionExtension` inclui a mensagem de desenvolvedor no problem+json | `core/exceptions/BillingApiExceptionExtension.java` (construtor) |
97
+ | `seedgrid.ratelimit.billing-webhook.{enabled,permits,window}` | resilience (`RateLimitService`) | ajusta o rate limit do webhook (default 300/min) | `core/controllers/BillingWebhookController` (`@SeedGridRateLimit(configKey="billing-webhook")`) |
98
+ | `seedgrid.ratelimit.billing-checkout.{enabled,permits,window}` | resilience | checkout (default 30/min) | `core/controllers/MeBillingController` |
99
+ | `seedgrid.ratelimit.billing-portal.{enabled,permits,window}` | resilience | portal (default 30/min) | `core/controllers/MeBillingController` |
100
+ | `seedgrid.security.encryption.key` 🔒, `seedgrid.security.default-company.*`, `seedgrid.security.jwt.*` | security | obrigatórias da security, que o billing passou a exigir transitivamente em 2026-09-10 | comentário em `seedgrid-billing-core/deployment/src/test/resources/application.properties` |
101
+
102
+ Ver [[SeedGrid/Extensions/resilience/Configuracao|Configuração do resilience]] e [[SeedGrid/Extensions/security/Configuracao|Configuração do security]].
103
+
104
+ ## 3. Propriedades de frameworks (definidas no `core-mp`, ordinal 100)
105
+
106
+ | Propriedade | Valor no `core-mp` | Efeito / recomendação |
107
+ |---|---|---|
108
+ | `quarkus.flyway.locations` | `db/migration/billing` | Só as migrations do billing. Um host com Flyway nativo **precisa** sobrescrever com `db/migration/security,db/migration/billing` (mais as próprias), senão o boot falha com `relation "companies" does not exist`. |
109
+ | `quarkus.flyway.table` | `flyway_schema_history_billing` | Os testes de deployment sobrescrevem para `flyway_schema_history`. |
110
+ | `quarkus.flyway.migrate-at-start` | `true` | — |
111
+ | `quarkus.flyway.baseline-on-migrate` | `true` | — |
112
+ | `quarkus.flyway.baseline-version` | `0` | — |
113
+ | `quarkus.hibernate-orm.database.generation` | `none` | — |
114
+ | `quarkus.hibernate-orm.physical-naming-strategy` | (não definido) | **Recomendado** pelos testes: `org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy`. As entidades da security exigem esse valor. O login-tenancy já o fixa. |
115
+ | `quarkus.flyway.out-of-order` | (não definido) | Só para upgrade de bancos criados com versões ≤ 2026.07.02 (V501 destravada). Ver README do core. |
116
+
117
+ > Login-tenancy e subdomain-tenancy desligam o Flyway nativo e rodam as migrations por módulo (`LoginTenancyMigrationService`, `MigrationService`). Nesses hosts, os `quarkus.flyway.*` acima não governam a ordem.
118
+
119
+ ## 4. Propriedades usadas só em testes
120
+
121
+ | Arquivo | Propriedades relevantes |
122
+ |---|---|
123
+ | `seedgrid-billing-core/deployment/src/test/resources/application.properties` | `quarkus.flyway.locations=db/migration/security,db/migration/billing`, `quarkus.flyway.table`, naming strategy, `quarkus.hibernate-orm.schema-management.strategy=none`, `seedgrid.security.*` (valores de teste) |
124
+ | `seedgrid-billing-core/integration-tests/src/test/resources/application.properties` | datasource e Flyway (`classpath:db/migration/security,…/audit,…/billing`, `clean-at-start=true`), `seedgrid.audit.*`, `seedgrid.security.*`, `mp.jwt.*`, `smallrye.jwt.*`, `quarkus.mailer.mock`, `seedgrid.ratelimit.{login,auth-refresh,billing-checkout,billing-portal,billing-webhook}.enabled=false`, `quarkus.index-dependency.seedgrid-filemanagement.*`, `quarkus.arc.exclude-types`, e valores de teste para `seedgrid.billing.catalog.product-id`, `checkout.*`, `portal.return-url`, `reconciliation.throttle-seconds=0` e `plan-term.additional-attributes.*` (2048/4/20) |
125
+ | `seedgrid-billing-core/integration-tests/.../TestData.java` | lê `seedgrid.security.default-company.cnpj` via `ConfigProvider` |
126
+ | `seedgrid-billing-stripe/deployment/src/test/resources/application.properties` | `seedgrid.billing.stripe.apiKey`/`webhookSecret` com valores dummy, `seedgrid.security.*`, Flyway |
127
+ | `seedgrid-billing-stripe/integration-tests/src/main/resources/application.properties` | vazio |
128
+
129
+ ## 5. Aliases, obsoletas e renomeações
130
+
131
+ | Propriedade | Situação |
132
+ |---|---|
133
+ | `seedgrid.billing.stripe.product` usada pelo core | Alias de fato de `seedgrid.billing.catalog.product-id`. `PlanPublicationService` a chama de `legacyStripeProductId`. Precedência: `catalog.product-id` primeiro, depois `stripe.product`. |
134
+ | `seedgrid.billing.stripe.defaultSuccessUrl`/`defaultCancelUrl` | Fallback legado de `seedgrid.billing.checkout.success-url`/`cancel-url`. O README do Stripe recomenda as do core. |
135
+ | Nomes camelCase (`apiKey`, `webhookSecret`, `defaultSuccessUrl`) | Fogem do padrão kebab-case do restante. São os nomes reais, sem alias kebab. |
136
+
137
+ ## 6. Configuração mínima (`application.properties`)
138
+
139
+ ```properties
140
+ # Provider Stripe (segredos SOMENTE via ambiente)
141
+ seedgrid.billing.stripe.apiKey=${STRIPE_API_KEY} # <SEGREDO:stripe-api-key>
142
+ seedgrid.billing.stripe.webhookSecret=${STRIPE_WEBHOOK_SECRET} # <SEGREDO:stripe-webhook-secret>
143
+
144
+ # Produto base no provider (necessário para publicar terms)
145
+ seedgrid.billing.stripe.product=<id-do-produto>
146
+
147
+ # Retorno do checkout (o Stripe exige as duas)
148
+ seedgrid.billing.checkout.success-url=https://<seu-app>/assinatura?ok=1
149
+ seedgrid.billing.checkout.cancel-url=https://<seu-app>/assinatura
150
+
151
+ # Host com Flyway nativo (sem login/subdomain-tenancy): security antes do billing
152
+ quarkus.flyway.locations=db/migration/security,db/migration/billing
153
+ quarkus.hibernate-orm.physical-naming-strategy=org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy
154
+ ```
155
+
156
+ Mais as obrigatórias da security: [[SeedGrid/Extensions/security/Configuracao|Configuração do security]].
157
+
158
+ ## 7. Configuração completa comentada
159
+
160
+ ```properties
161
+ # ---------- Negócio ----------
162
+ # Fuso do dia civil (vigência de preço, virada de ciclo). Default America/Sao_Paulo.
163
+ seedgrid.billing.business-timezone=America/Sao_Paulo
164
+ # Moeda ISO 4217 em minúsculas. Default brl.
165
+ seedgrid.billing.currency=brl
166
+ # Prefixo do nome exibido do meter de excedente. Default Excedente.
167
+ seedgrid.billing.overage-meter-name=Excedente
168
+ # PU das tabelas do billing. Sem valor = PU default. subdomain-tenancy usa master.
169
+ #seedgrid.billing.persistence-unit=master
170
+
171
+ # ---------- API REST ----------
172
+ # false = endpoints de plano/assinatura/me respondem 404 e somem do OpenAPI (webhook continua). Default true.
173
+ seedgrid.billing.api.enabled=true
174
+
175
+ # ---------- Bloqueio geral (opcional) ----------
176
+ # Default false. true = conta sem assinatura vigente só alcança o caminho para pagar.
177
+ seedgrid.billing.access-gate.enabled=false
178
+ # Default true. PAST_DUE entra no bloqueio geral.
179
+ seedgrid.billing.access-gate.block-past-due=true
180
+ # Prefixos extras liberados (sem default).
181
+ #seedgrid.billing.access-gate.allowed-paths=/me/permissions,/me/profile
182
+
183
+ # ---------- Catálogo / checkout / portal ----------
184
+ # Produto do provider; sem valor usa seedgrid.billing.stripe.product.
185
+ #seedgrid.billing.catalog.product-id=<id-do-produto>
186
+ seedgrid.billing.checkout.success-url=https://<seu-app>/assinatura?ok=1
187
+ seedgrid.billing.checkout.cancel-url=https://<seu-app>/assinatura
188
+ seedgrid.billing.portal.return-url=https://<seu-app>/assinatura
189
+
190
+ # ---------- Trial ----------
191
+ # Default true.
192
+ seedgrid.billing.trial.enabled=true
193
+ # Default 00000000-0000-0000-0000-0000000000a2 (seed V505).
194
+ #seedgrid.billing.trial.plan-term-public-id=<public-id-do-term-trial>
195
+
196
+ # ---------- Feature gate ----------
197
+ # IDs de Company nunca bloqueados por @RequiresPlanFeature (sem default).
198
+ #seedgrid.billing.feature-gate.exempt-company-ids=<id-company-plataforma>
199
+
200
+ # ---------- Limites de additionalAttributes (HTTP 400 ao exceder) ----------
201
+ # Defaults 16384 / 5 / 100.
202
+ seedgrid.billing.plan-term.additional-attributes.max-size-bytes=16384
203
+ seedgrid.billing.plan-term.additional-attributes.max-depth=5
204
+ seedgrid.billing.plan-term.additional-attributes.max-keys=100
205
+
206
+ # ---------- Reconciliação ----------
207
+ # Segundos mínimos entre reconciliações implícitas da mesma conta. Default 60; 0 = sempre.
208
+ seedgrid.billing.reconciliation.throttle-seconds=60
209
+
210
+ # ---------- Stripe ----------
211
+ seedgrid.billing.stripe.apiKey=${STRIPE_API_KEY} # <SEGREDO:stripe-api-key>
212
+ seedgrid.billing.stripe.webhookSecret=${STRIPE_WEBHOOK_SECRET} # <SEGREDO:stripe-webhook-secret>
213
+ seedgrid.billing.stripe.product=<id-do-produto>
214
+ seedgrid.billing.stripe.product-name=<Nome do Produto>
215
+ # Fallbacks (prefira as do core):
216
+ #seedgrid.billing.stripe.defaultSuccessUrl=https://<seu-app>/sucesso
217
+ #seedgrid.billing.stripe.defaultCancelUrl=https://<seu-app>/cancelado
218
+ # Só tem efeito com chave sk_test. Default true.
219
+ seedgrid.billing.stripe.test-clock-enabled=true
220
+
221
+ # ---------- Rate limit (extension resilience) ----------
222
+ #seedgrid.ratelimit.billing-webhook.permits=300
223
+ #seedgrid.ratelimit.billing-webhook.window=PT1M
224
+ #seedgrid.ratelimit.billing-checkout.enabled=true
225
+ ```
226
+
227
+ ## 8. Receitas
228
+
229
+ | Caso | Configuração |
230
+ |---|---|
231
+ | Bloquear tudo quando o trial acabar ou não houver pagamento | `seedgrid.billing.access-gate.enabled=true`. Para liberar telas extras, use `seedgrid.billing.access-gate.allowed-paths=/me/profile`. |
232
+ | Bloquear só funcionalidades anotadas (padrão) | Não configure nada. Use `@ConsumesUsage`/`@RequiresPlanFeature`. |
233
+ | Empresa da plataforma nunca bloqueada por plano | `seedgrid.billing.feature-gate.exempt-company-ids=<id>` |
234
+ | Host com billing desligado (sem tabelas) | `seedgrid.billing.api.enabled=false`. No login-tenancy isso segue `seedgrid.login-tenancy.modules.billing.enabled`. |
235
+ | subdomain-tenancy | `seedgrid.billing.persistence-unit=master` (já definido pela extension de tenancy) |
236
+ | Desenvolvimento local com Stripe | `SEEDGRID_BILLING_STRIPE_APIKEY=<SEGREDO:stripe-test-key>`, `stripe listen --forward-to localhost:8080/public/billing/webhook` e `SEEDGRID_BILLING_STRIPE_WEBHOOKSECRET=<SEGREDO:whsec-do-cli>` |
237
+ | Produção | Webhook em `https://<dominio>/public/billing/webhook` com no mínimo `checkout.session.completed` e `invoice.paid`, chave live e test clock irrelevante |
238
+ | Testes de integração sem esperar throttle | `seedgrid.billing.reconciliation.throttle-seconds=0` |
239
+
240
+ ## 9. Dúvidas e lacunas
241
+ - `apiKey`/`webhookSecret` obrigatórias: dedução pela semântica do `@ConfigProperty` sem default, não testada aqui. O `@ApplicationScoped` é lazy, mas o Quarkus valida injection points de config no startup.
242
+ - Sem URL de sucesso ou cancelamento em lugar nenhum, o Stripe recebe `""`. O comportamento exato (erro do Stripe) não foi verificado.
243
+ - Nomes de env explícitos de `plan-term.additional-attributes.*` diferem da regra MP. Ambos devem funcionar, mas isso não foi testado.
@@ -0,0 +1,165 @@
1
+ ---
2
+ tags: [seedgrid, extension, billing, quarkus, enum]
3
+ fonte: java/seedgrid-quarkus-ext-billing
4
+ branch: main
5
+ commit: ba38efc347
6
+ analisado-em: 2026-10-14
7
+ ---
8
+
9
+ # Billing (Quarkus): enums
10
+
11
+ Voltar para [[SeedGrid/Extensions/billing/Visao-geral|Visão geral]] · [[SeedGrid/Extensions/billing/Configuracao|Configuração]]. Porte Rust: [[SeedGrid/Extensions/billing/Rust|Rust]].
12
+
13
+ Nenhum enum é tipo de propriedade de configuração. Nenhum tem `@JsonValue`/`@JsonProperty`: no JSON aparecem pelo **nome da constante** (Jackson padrão, case-sensitive). Todos os enums persistidos usam `@Enumerated(EnumType.STRING)` e as colunas são `varchar` **sem CHECK constraint** nas migrations, então o banco aceita qualquer texto. O módulo `seedgrid-billing-stripe` não define enums: só converte os do core.
14
+
15
+ ## Índice
16
+
17
+ Arquivos em `java/seedgrid-quarkus-ext-billing/seedgrid-billing-core/runtime/src/main/java/br/com/seedgrid/billing/`.
18
+
19
+ | Enum | Arquivo | Usado em | Público? |
20
+ |---|---|---|---|
21
+ | `SubscriptionStatus` | `entities/SubscriptionStatus.java` | `tenant_subscriptions.status`, `AdminSubscriptionRequest.status` | sim |
22
+ | `AccountStatus` | `entities/AccountStatus.java` | `accounts.status` | sim (entidade) |
23
+ | `PurchaseStatus` | `entities/PurchaseStatus.java` | `billing_purchases.status` | sim (entidade) |
24
+ | `AccountHistoryType` | `entities/AccountHistoryType.java` | `billing_account_history.type`; `AccountHistoryResponse.type` (String) | sim |
25
+ | `SubscriptionLifecycleEvent.Type` | `dtos/events/SubscriptionLifecycleEvent.java` | evento CDI e códigos `billing.*` | sim |
26
+ | `UserAccessEvent.Type` | `dtos/events/UserAccessEvent.java` | evento CDI e e-mails de acesso | sim |
27
+ | `BillingEventType` | `dtos/BillingEventType.java` | `BillingEvent.type` (SPIs), `billing_events.type` | sim |
28
+ | `RecurringInterval` | `dtos/RecurringInterval.java` | `CreatePriceRequest`, `CreateMeteredPriceRequest`, `PriceInfo` | sim |
29
+ | `TiersMode` | `dtos/TiersMode.java` | `CreateMeteredPriceRequest.tiersMode` | sim |
30
+ | `AggregationFormula` | `dtos/AggregationFormula.java` | `CreateMeterRequest.aggregation` | sim |
31
+
32
+ ## SubscriptionStatus
33
+ FQN `br.com.seedgrid.billing.entities.SubscriptionStatus`. STRING em `tenant_subscriptions.status varchar(32)` (V509), sem CHECK. Sem campos nem métodos.
34
+
35
+ | Valor | Significado | Efeito / onde é tratado | Observações |
36
+ |---|---|---|---|
37
+ | `ACTIVE` | Assinatura em vigor. | Vigente = `ACTIVE` ou `PAST_DUE` já iniciada e não terminada (`Subscription#isResolvable`, `SubscriptionRepository`). Default no `@PrePersist`. | Confirmado. Cancelamento agendado (`cancelAtPeriodEnd`) segue `ACTIVE` até o provider avisar. |
38
+ | `PAST_DUE` | Pagamento falhou (dunning no provider). | Continua vigente para a UI e **sempre bloqueia consumo** (`SubscriptionAccessService`). Bloqueia o acesso geral só se `seedgrid.billing.access-gate.block-past-due=true` (ver [[SeedGrid/Extensions/billing/Configuracao|Configuração]]). | Confirmado. |
39
+ | `INACTIVE` | Substituída por outra assinatura (checkout de outro plano, fim do trial). | Deixa de ser vigente. `SubscriptionActivationService#activate` também fixa `endsAt = agora`. | Confirmado. |
40
+ | `CANCELED` | Encerrada. | Definida por `SUBSCRIPTION_CANCELED` e por `syncFromProvider` quando o provider diz `canceled`/`incomplete_expired`; preenche `endsAt` se nulo. | Confirmado. |
41
+
42
+ Mapeamento de status do provider (`SubscriptionActivationService#mapProviderStatus`): `active`, `trialing` → `ACTIVE`; `past_due`, `unpaid` → `PAST_DUE`; `canceled`, `incomplete_expired` → `CANCELED`; qualquer outro → nada muda.
43
+
44
+ ```mermaid
45
+ stateDiagram-v2
46
+ [*] --> ACTIVE
47
+ ACTIVE --> PAST_DUE: PAYMENT_FAILED, DISPUTE_OPENED, provider past_due
48
+ PAST_DUE --> ACTIVE: PAYMENT_CONFIRMED, recompra do mesmo term, provider active
49
+ ACTIVE --> INACTIVE: outro term ativado na conta
50
+ PAST_DUE --> INACTIVE: outro term ativado na conta
51
+ ACTIVE --> CANCELED: SUBSCRIPTION_CANCELED, provider canceled
52
+ PAST_DUE --> CANCELED: SUBSCRIPTION_CANCELED, provider canceled
53
+ ```
54
+
55
+ Também pode ser enviado em `POST /admin/subscriptions` (`AdminSubscriptionRequest.status`, qualquer valor do enum; ausente = `ACTIVE`). O filtro `active`/`inactive` da listagem admin é texto livre, não este enum.
56
+
57
+ ## AccountStatus
58
+ FQN `br.com.seedgrid.billing.entities.AccountStatus`. STRING em `accounts.status varchar(64)` (V502), sem CHECK.
59
+
60
+ | Valor | Significado | Efeito / onde é tratado | Observações |
61
+ |---|---|---|---|
62
+ | `PENDING_EMAIL_VERIFICATION` | Conta criada, e-mail ainda não verificado. | Default quando o status é nulo (`Account#prePersist`). | Confirmado. Nenhum código consulta esse valor. |
63
+ | `ACTIVE` | Conta ativa. | `AccountCreationService` grava `ACTIVE` ao criar a conta. | Confirmado. |
64
+ | `SUSPENDED` | Conta suspensa. | **Existe no enum, mas nenhum código grava ou trata esse valor.** Gravado direto no banco, não tem efeito. | Confirmado por busca no módulo. |
65
+
66
+ Na prática o status da conta não influencia o acesso: quem decide é a assinatura.
67
+
68
+ ## PurchaseStatus
69
+ FQN `br.com.seedgrid.billing.entities.PurchaseStatus`. STRING em `billing_purchases.status varchar(64)` (V509), sem CHECK.
70
+
71
+ | Valor | Significado | Efeito / onde é tratado | Observações |
72
+ |---|---|---|---|
73
+ | `PENDING` | Compra registrada, não confirmada. | Default em `Purchase#prePersist`. | Nenhum fluxo grava `PENDING` explicitamente. |
74
+ | `PAID` | Pagamento confirmado. | `SubscriptionBillingEventHandler#handlePayment` grava em `CHECKOUT_COMPLETED`/`PAYMENT_CONFIRMED`. `PurchaseRepository` filtra `PAID`. | Confirmado. |
75
+ | `FAILED` | Compra falhou. | **Existe no enum, mas nenhum código grava ou consulta esse valor.** `PAYMENT_FAILED` só altera a assinatura. | Confirmado. |
76
+ | `REFUNDED` | Reembolsada. | `REFUND_CREATED` marca a compra localizada por `providerReference`. | Confirmado. Como a consulta usa só `PAID`, deixa de contar. |
77
+
78
+ ## AccountHistoryType
79
+ FQN `br.com.seedgrid.billing.entities.AccountHistoryType`. STRING em `billing_account_history.type varchar(40)` (V511), sem CHECK. O método `static of(SubscriptionLifecycleEvent.Type)` faz `valueOf(type.name())`: os 9 primeiros valores **precisam** ter o mesmo nome das constantes de `SubscriptionLifecycleEvent.Type`.
80
+
81
+ | Valor | Significado | Efeito / onde é tratado | Observações |
82
+ |---|---|---|---|
83
+ | `ACTIVATED` | Assinatura ativada. | Gravado por `AccountHistoryService` ao receber o evento de ciclo de vida. | Espelha o evento. |
84
+ | `UPGRADED` | Upgrade. | Contado no overview (`BillingOverviewService`). | Espelha o evento. |
85
+ | `DOWNGRADE_SCHEDULED` | Downgrade agendado. | Contado no overview como downgrade. | Espelha o evento. |
86
+ | `DOWNGRADE_CANCELED` | Downgrade desfeito. | Só histórico. | Espelha o evento. |
87
+ | `CANCELLATION_REQUESTED` | Cancelamento pedido. | Só histórico. | Espelha o evento. |
88
+ | `CANCELED` | Cancelamento efetivado. | Só histórico. | Espelha o evento. |
89
+ | `REACTIVATED` | Reativada. | Só histórico. | Espelha o evento. |
90
+ | `PAST_DUE` | Pagamento pendente. | Só histórico. | Espelha o evento. |
91
+ | `TRIAL_ENDED` | Trial encerrado. | Só histórico. | Espelha o evento. |
92
+ | `UNITS_GRANTED` | Unidades extras concedidas no ciclo. | `AdminAccountService` (`POST /admin/accounts/{id}/grant-units`). | Só do admin. |
93
+ | `TRIAL_EXTENDED` | Dias a mais no trial. | `AdminAccountService` (`POST .../grant-trial-days`). | Só do admin. |
94
+
95
+ A resposta REST (`AccountHistoryResponse.type`) é `String`: sai o nome da constante.
96
+
97
+ ## SubscriptionLifecycleEvent.Type
98
+ FQN `br.com.seedgrid.billing.dtos.events.SubscriptionLifecycleEvent.Type`. Não persistido diretamente (vira `AccountHistoryType`).
99
+
100
+ | Valor | Significado | Disparado por | Código de notificação |
101
+ |---|---|---|---|
102
+ | `ACTIVATED` | Nova assinatura ativada. | `SubscriptionBillingEventHandler#handlePayment` | `billing.subscription-activated` |
103
+ | `UPGRADED` | Plano de preço igual ou maior. | `SubscriptionChangeService` | `billing.subscription-upgraded` |
104
+ | `DOWNGRADE_SCHEDULED` | Downgrade agendado para o fim do ciclo. | `SubscriptionChangeService` | `billing.subscription-downgraded` |
105
+ | `DOWNGRADE_CANCELED` | Downgrade desfeito. | `SubscriptionChangeService` | `billing.downgrade-canceled` |
106
+ | `CANCELLATION_REQUESTED` | Cancelamento no fim do período pedido. | `SubscriptionChangeService` | `billing.cancellation-requested` |
107
+ | `CANCELED` | Assinatura encerrada. | `SubscriptionBillingEventHandler` (`SUBSCRIPTION_CANCELED`) | `billing.subscription-canceled` |
108
+ | `REACTIVATED` | Cancelamento agendado revertido. | `SubscriptionChangeService` | `billing.subscription-reactivated` |
109
+ | `PAST_DUE` | Pagamento falhou. | `SubscriptionBillingEventHandler` (`PAYMENT_FAILED`) | `billing.payment-past-due` |
110
+ | `TRIAL_ENDED` | Trial terminou; `reason` = `TIME` ou `QUOTA`. | `TrialEndedNotifier` (uma vez por assinatura) | `billing.trial-ended` |
111
+
112
+ Confirmado em `BillingLifecycleNotificationObserver` (switch exaustivo). `DISPUTE_OPENED` coloca a assinatura em `PAST_DUE`, mas **não dispara** este evento.
113
+
114
+ ## UserAccessEvent.Type
115
+ FQN `br.com.seedgrid.billing.dtos.events.UserAccessEvent.Type`. Não persistido.
116
+
117
+ | Valor | Significado | Disparado por | Efeito |
118
+ |---|---|---|---|
119
+ | `LOSS_SCHEDULED` | Usuário escolhido para perder acesso quando o plano com menos vagas valer. | `SeatService` | `UserAccessEmailObserver` envia `accessLoss` com data. |
120
+ | `LOSS_APPLIED` | Perdeu o acesso agora. | `SeatService` | `accessLoss` imediato. |
121
+ | `RESTORED` | Estava escolhido, mas o downgrade foi desfeito. | `SeatService` | `accessRestored`. |
122
+
123
+ ## BillingEventType
124
+ FQN `br.com.seedgrid.billing.dtos.BillingEventType`. Campo `BillingEvent.type`. Persistido por nome em `billing_events.type varchar(50)` (idempotência do webhook). Evento Stripe não mapeado gera `UnsupportedEventException` e resposta 204.
125
+
126
+ | Valor | Significado | Efeito no `SubscriptionBillingEventHandler` | Origem no Stripe |
127
+ |---|---|---|---|
128
+ | `CHECKOUT_COMPLETED` | Checkout concluído. | Registra a compra `PAID` e ativa o term do metadata. Sem term, só registra a compra. | `checkout.session.completed` |
129
+ | `PAYMENT_CONFIRMED` | Fatura paga. | Regulariza `PAST_DUE`, efetiva a virada de ciclo, registra a compra e ativa o term se houver metadata. | `invoice.paid` |
130
+ | `PAYMENT_FAILED` | Falha de pagamento. | Marca `PAST_DUE` e dispara `PAST_DUE`. | `invoice.payment_failed` |
131
+ | `SUBSCRIPTION_CREATED` | Assinatura criada no provider. | **Existe no enum e o Stripe o emite, mas o handler não o trata** (cai no `default`, sem efeito). | `customer.subscription.created` |
132
+ | `SUBSCRIPTION_UPDATED` | Assinatura alterada. | Sincroniza status e `cancelAtPeriodEnd` com o provider. | `customer.subscription.updated` |
133
+ | `SUBSCRIPTION_CANCELED` | Assinatura cancelada. | `CANCELED` e dispara `CANCELED`. | `customer.subscription.deleted` |
134
+ | `REFUND_CREATED` | Reembolso. | Compra → `REFUNDED`. | `charge.refunded` |
135
+ | `DISPUTE_OPENED` | Disputa aberta. | Suspende (`PAST_DUE`) as assinaturas do customer. | `charge.dispute.created` |
136
+
137
+ ## RecurringInterval
138
+ FQN `br.com.seedgrid.billing.dtos.RecurringInterval`.
139
+
140
+ | Valor | Significado | Efeito | Observações |
141
+ |---|---|---|---|
142
+ | `DAY` | Diário. | Stripe `Interval.DAY`; leitura `"day"`. | O core só usa `MONTH`. |
143
+ | `WEEK` | Semanal. | Stripe `WEEK`; leitura `"week"`. | idem |
144
+ | `MONTH` | Mensal. | Stripe `MONTH`. **Default** para `null` e para qualquer string desconhecida na leitura. | `PlanPublicationService` sempre envia `MONTH`. |
145
+ | `YEAR` | Anual. | Stripe `YEAR`; leitura `"year"`. | — |
146
+
147
+ ## TiersMode
148
+ FQN `br.com.seedgrid.billing.dtos.TiersMode`.
149
+
150
+ | Valor | Significado | Efeito | Observações |
151
+ |---|---|---|---|
152
+ | `GRADUATED` | Cada faixa cobra seu preço pela parcela que cai nela (Javadoc). | Stripe `TiersMode.GRADUATED`; é o resultado para `null`. | O core não usa tiers. |
153
+ | `VOLUME` | Toda a quantidade é cobrada no preço da faixa do total (Javadoc). | Stripe `TiersMode.VOLUME`. | idem |
154
+
155
+ ## AggregationFormula
156
+ FQN `br.com.seedgrid.billing.dtos.AggregationFormula`. Default `SUM` quando `null`.
157
+
158
+ | Valor | Significado | Efeito | Observações |
159
+ |---|---|---|---|
160
+ | `SUM` | Soma dos valores de uso. | Stripe `Formula.SUM`. Único usado pelo core (`PlanPublicationService`). | Default. |
161
+ | `COUNT` | Contagem de eventos. | Stripe `Formula.COUNT`. | — |
162
+ | `LAST` | Último valor do período. | **O provider Stripe não implementa**: cai em `SUM` (comentário no código: o SDK só expõe SUM e COUNT). | Confirmado em `StripeBillingProvider#toMeterFormula`. |
163
+
164
+ ## Internos
165
+ Nenhum enum interno em `seedgrid-billing-core` nem em `seedgrid-billing-stripe` (fora dos testes).
@@ -0,0 +1,205 @@
1
+ ---
2
+ tags: [seedgrid, extension, billing, quarkus, exemplos]
3
+ fonte: java/seedgrid-quarkus-ext-billing
4
+ branch: main
5
+ commit: ba38efc347
6
+ analisado-em: 2026-10-14
7
+ ---
8
+
9
+ # Billing (Quarkus): exemplos
10
+
11
+ Ver também [[SeedGrid/Extensions/billing/Visao-geral|Visão geral]] e [[SeedGrid/Extensions/billing/Configuracao|Configuração]].
12
+
13
+ Os exemplos usam a API real do código. A fonte de cada um está indicada.
14
+
15
+ ## 1. Dependências
16
+
17
+ Fonte: `README.md` (raiz). Versão alinhada ao pom `2026.10.14-1`.
18
+
19
+ ```xml
20
+ <dependency>
21
+ <groupId>br.com.seedgrid</groupId>
22
+ <artifactId>seedgrid-billing-core</artifactId>
23
+ <version>2026.10.14-1</version>
24
+ </dependency>
25
+ <dependency>
26
+ <groupId>br.com.seedgrid</groupId>
27
+ <artifactId>seedgrid-billing-stripe</artifactId>
28
+ <version>2026.10.14-1</version>
29
+ </dependency>
30
+ ```
31
+
32
+ Com `seedgrid-login-tenancy`, o core já vem da foundation. Declare só o `seedgrid-billing-stripe` (README do Stripe).
33
+
34
+ ## 2. Declarar os contadores de uso
35
+
36
+ Fonte: `seedgrid-billing-core/integration-tests/src/test/java/br/com/seedgrid/billing/it/ProductUsageMeters.java`.
37
+
38
+ ```java
39
+ @ApplicationScoped
40
+ public class ProductUsageMeters implements UsageMeterContributor {
41
+
42
+ public static final String REQUESTS = "requests";
43
+ public static final String STORAGE = "storage-mb";
44
+
45
+ @Override
46
+ public List<UsageMeterDefinition> meters() {
47
+ return List.of(
48
+ new UsageMeterDefinition(REQUESTS, "Requisicoes"),
49
+ new UsageMeterDefinition(STORAGE, "MB armazenados"));
50
+ }
51
+ }
52
+ ```
53
+
54
+ Regras do README:
55
+ - O código usa `[a-z0-9-]`, com até 40 caracteres, e é uma identidade permanente: não reaproveite.
56
+ - Vários beans `UsageMeterContributor` são somados.
57
+
58
+ ## 3. Consumo por anotação, consumo programático e gate por plano
59
+
60
+ Fonte: `integration-tests/.../ProductController.java`.
61
+
62
+ ```java
63
+ @Path("/it/product")
64
+ @Authenticated
65
+ @Produces(MediaType.APPLICATION_JSON)
66
+ public class ProductController {
67
+
68
+ private final CurrentAccountResolver currentAccountResolver;
69
+ private final UsageService usageService;
70
+
71
+ public ProductController(CurrentAccountResolver currentAccountResolver, UsageService usageService) {
72
+ this.currentAccountResolver = currentAccountResolver;
73
+ this.usageService = usageService;
74
+ }
75
+
76
+ // 1 unidade de "requests"; só contabiliza se o método retornar
77
+ @POST
78
+ @Path("/work")
79
+ @ConsumesUsage(meter = ProductUsageMeters.REQUESTS)
80
+ public Map<String, String> work() {
81
+ return Map.of("status", "done");
82
+ }
83
+
84
+ // quantidade conhecida só em runtime
85
+ @POST
86
+ @Path("/store")
87
+ @Transactional
88
+ public Map<String, Object> store(@QueryParam("mb") int mb) {
89
+ Account account = currentAccountResolver.requireCurrentAccount();
90
+ usageService.assertCanConsume(account, ProductUsageMeters.STORAGE, mb);
91
+ usageService.consume(account, ProductUsageMeters.STORAGE, mb, "store-" + UUID.randomUUID());
92
+ return Map.of("storedMb", mb);
93
+ }
94
+
95
+ // o plano vigente precisa liberar a permissão; senão 402 FEATURE_NOT_IN_PLAN
96
+ @POST
97
+ @Path("/premium")
98
+ @RequiresPlanFeature("IT_PREMIUM_REPORT")
99
+ public Map<String, String> premium() {
100
+ return Map.of("status", "premium");
101
+ }
102
+ }
103
+ ```
104
+
105
+ `@ConsumesUsage` também aceita `units` (padrão `1`). `@RequiresPlanFeature` aceita `message` para personalizar o `detail` do 402.
106
+
107
+ ## 4. Validar `additionalAttributes` do term
108
+
109
+ Fonte: `integration-tests/.../ProductPlanTermValidator.java`.
110
+
111
+ ```java
112
+ @ApplicationScoped
113
+ public class ProductPlanTermValidator implements PlanTermAdditionalFieldsValidator {
114
+
115
+ @Override
116
+ public void validate(PlanTerm term, Map<String, JsonNode> additionalAttributes) {
117
+ JsonNode quota = additionalAttributes.get("monthlyRequests");
118
+ if (quota != null && (!quota.canConvertToInt() || !quota.isIntegralNumber() || quota.asInt() <= 0)) {
119
+ throw new InvalidPlanTermAdditionalAttributesException("monthlyRequests deve ser inteiro positivo");
120
+ }
121
+ }
122
+ }
123
+ ```
124
+
125
+ ## 5. Restringir as contas visíveis no admin
126
+
127
+ Fonte: `seedgrid-billing-core/BILLING_INTEGRATION_GUIDE.md`. O `PartnerService` é do host.
128
+
129
+ ```java
130
+ @RequestScoped
131
+ public class PartnerBillingAccountScope implements BillingAccountScope {
132
+ @Inject PartnerService partners;
133
+
134
+ @Override
135
+ public Optional<Set<Long>> visibleCompanyIds() {
136
+ return partners.currentPartner().map(p -> partners.companyIdsOf(p)); // empty() = operador da casa
137
+ }
138
+ }
139
+ ```
140
+
141
+ ## 6. Observar eventos
142
+
143
+ Fonte: README do Stripe, seção 9, e javadoc de `SubscriptionLifecycleEvent`.
144
+
145
+ ```java
146
+ void aoMudar(@Observes(during = TransactionPhase.AFTER_SUCCESS) SubscriptionLifecycleEvent event) {
147
+ // event.type(): ACTIVATED, UPGRADED, DOWNGRADE_SCHEDULED, CANCELED, PAST_DUE, TRIAL_ENDED...
148
+ // event.accountPublicId(), event.toPlanName(), event.effectiveAt(), event.reason()
149
+ }
150
+
151
+ void aoConsumir(@Observes UsageConsumedEvent event) {
152
+ // mesma transação do consumo: grave o detalhe do produto
153
+ // event.meter(), event.units(), event.overageUnits(), event.balanceAfter()
154
+ }
155
+ ```
156
+
157
+ ## 7. Criar um term com contadores (REST)
158
+
159
+ Fonte: README da raiz.
160
+
161
+ ```http
162
+ POST /admin/plans/{planId}/terms
163
+ Content-Type: application/json
164
+
165
+ { "monthlyPrice": 149.90, "maxUsers": 3,
166
+ "meters": [
167
+ { "meter": "requests", "includedUnits": 1000, "overagePrice": 0.10 },
168
+ { "meter": "storage-mb", "includedUnits": 500, "overagePrice": 0 } ],
169
+ "additionalAttributes": { "supportLevel": "priority" } }
170
+ ```
171
+
172
+ - `overagePrice > 0`: cada unidade além da franquia é cobrada no meter do contador.
173
+ - `overagePrice = 0`: esgotar a franquia bloqueia com 402.
174
+
175
+ ## 8. Configuração mínima com Stripe
176
+
177
+ Fonte: `BILLING_INTEGRATION_GUIDE.md`, passo 2. Ver também a [[SeedGrid/Extensions/billing/Configuracao|tabela completa]].
178
+
179
+ ```properties
180
+ seedgrid.billing.stripe.apiKey=${STRIPE_API_KEY} # <SEGREDO:stripe-api-key>
181
+ seedgrid.billing.stripe.webhookSecret=${STRIPE_WEBHOOK_SECRET} # <SEGREDO:stripe-webhook-secret>
182
+ seedgrid.billing.stripe.product=meu-produto
183
+ seedgrid.billing.checkout.success-url=https://app.exemplo.com/assinatura?ok=1
184
+ seedgrid.billing.checkout.cancel-url=https://app.exemplo.com/assinatura
185
+ seedgrid.billing.portal.return-url=https://app.exemplo.com/assinatura
186
+ seedgrid.billing.feature-gate.exempt-company-ids=1
187
+ ```
188
+
189
+ Em desenvolvimento local, segundo o README do Stripe:
190
+
191
+ ```bash
192
+ stripe login
193
+ stripe listen --forward-to localhost:8080/public/billing/webhook
194
+ # copie o whsec_... impresso para SEEDGRID_BILLING_STRIPE_WEBHOOKSECRET e reinicie a app
195
+ ```
196
+
197
+ ## 9. Personalizar os e-mails de acesso
198
+
199
+ Fonte: `BILLING_INTEGRATION_GUIDE.md`, passo 5, e `UserAccessEmails`.
200
+
201
+ Coloque arquivos no host em `src/main/resources/templates/billing/{html,txt}/`:
202
+ - `user-access-loss.html` e `user-access-loss.txt`
203
+ - `user-access-restored.html` e `user-access-restored.txt`
204
+
205
+ Os placeholders disponíveis são `{name}`, `{plan}`, `{explanation}` e `{notice}`.