@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.
- package/LICENSE +21 -0
- package/README.md +151 -2
- package/dist/adapters/claude.js +114 -0
- package/dist/adapters/codex.js +108 -0
- package/dist/adapters/index.js +17 -0
- package/dist/adapters/shared.js +142 -0
- package/dist/adapters/types.js +1 -0
- package/dist/cli.js +203 -0
- package/dist/commands/common.js +98 -0
- package/dist/commands/doctor.js +290 -0
- package/dist/commands/init.js +9 -0
- package/dist/commands/install.js +107 -0
- package/dist/commands/remove.js +54 -0
- package/dist/commands/review.js +127 -0
- package/dist/commands/status.js +73 -0
- package/dist/commands/update.js +8 -0
- package/dist/commands/validate.js +27 -0
- package/dist/core/apply.js +181 -0
- package/dist/core/blocks.js +64 -0
- package/dist/core/content.js +528 -0
- package/dist/core/env.js +40 -0
- package/dist/core/frontmatter.js +29 -0
- package/dist/core/hash.js +14 -0
- package/dist/core/inspect.js +51 -0
- package/dist/core/lock.js +124 -0
- package/dist/core/paths.js +65 -0
- package/dist/core/plan.js +242 -0
- package/dist/core/tools.js +62 -0
- package/dist/core/types.js +11 -0
- package/dist/core/updates.js +121 -0
- package/docs/arquitetura.md +80 -0
- package/docs/compatibilidade.md +50 -0
- package/docs/formato.md +155 -0
- package/docs/instalacao.md +105 -0
- package/docs/manutencao.md +115 -0
- package/package.json +43 -4
- package/seedgridKB/SeedGrid/Extensions/Catalogo-de-enums.md +161 -0
- package/seedgridKB/SeedGrid/Extensions/Catalogo-de-propriedades.md +971 -0
- package/seedgridKB/SeedGrid/Extensions/Indice.md +63 -0
- package/seedgridKB/SeedGrid/Extensions/ai-pricing/Configuracao.md +124 -0
- package/seedgridKB/SeedGrid/Extensions/ai-pricing/Enums.md +40 -0
- package/seedgridKB/SeedGrid/Extensions/ai-pricing/Exemplos.md +97 -0
- package/seedgridKB/SeedGrid/Extensions/ai-pricing/Visao-geral.md +114 -0
- package/seedgridKB/SeedGrid/Extensions/apikeys/Configuracao-Rust.md +69 -0
- package/seedgridKB/SeedGrid/Extensions/apikeys/Configuracao.md +88 -0
- package/seedgridKB/SeedGrid/Extensions/apikeys/Enums.md +33 -0
- package/seedgridKB/SeedGrid/Extensions/apikeys/Exemplos.md +121 -0
- package/seedgridKB/SeedGrid/Extensions/apikeys/Rust.md +126 -0
- package/seedgridKB/SeedGrid/Extensions/apikeys/Visao-geral.md +111 -0
- package/seedgridKB/SeedGrid/Extensions/audit/Configuracao-Rust.md +93 -0
- package/seedgridKB/SeedGrid/Extensions/audit/Configuracao.md +127 -0
- package/seedgridKB/SeedGrid/Extensions/audit/Enums.md +66 -0
- package/seedgridKB/SeedGrid/Extensions/audit/Exemplos.md +151 -0
- package/seedgridKB/SeedGrid/Extensions/audit/Rust.md +120 -0
- package/seedgridKB/SeedGrid/Extensions/audit/Visao-geral.md +114 -0
- package/seedgridKB/SeedGrid/Extensions/backup/Configuracao-Rust.md +136 -0
- package/seedgridKB/SeedGrid/Extensions/backup/Configuracao.md +319 -0
- package/seedgridKB/SeedGrid/Extensions/backup/Enums.md +131 -0
- package/seedgridKB/SeedGrid/Extensions/backup/Exemplos.md +210 -0
- package/seedgridKB/SeedGrid/Extensions/backup/Rust.md +135 -0
- package/seedgridKB/SeedGrid/Extensions/backup/Visao-geral.md +150 -0
- package/seedgridKB/SeedGrid/Extensions/billing/Configuracao-Rust.md +86 -0
- package/seedgridKB/SeedGrid/Extensions/billing/Configuracao.md +243 -0
- package/seedgridKB/SeedGrid/Extensions/billing/Enums.md +165 -0
- package/seedgridKB/SeedGrid/Extensions/billing/Exemplos.md +205 -0
- package/seedgridKB/SeedGrid/Extensions/billing/Rust.md +109 -0
- package/seedgridKB/SeedGrid/Extensions/billing/Visao-geral.md +181 -0
- package/seedgridKB/SeedGrid/Extensions/broker/Configuracao-Rust.md +40 -0
- package/seedgridKB/SeedGrid/Extensions/broker/Visao-geral.md +114 -0
- package/seedgridKB/SeedGrid/Extensions/cache/Configuracao-Rust.md +73 -0
- package/seedgridKB/SeedGrid/Extensions/cache/Configuracao.md +112 -0
- package/seedgridKB/SeedGrid/Extensions/cache/Enums.md +36 -0
- package/seedgridKB/SeedGrid/Extensions/cache/Exemplos.md +149 -0
- package/seedgridKB/SeedGrid/Extensions/cache/Rust.md +81 -0
- package/seedgridKB/SeedGrid/Extensions/cache/Visao-geral.md +90 -0
- package/seedgridKB/SeedGrid/Extensions/commons/Configuracao.md +107 -0
- package/seedgridKB/SeedGrid/Extensions/commons/Enums.md +105 -0
- package/seedgridKB/SeedGrid/Extensions/commons/Exemplos.md +141 -0
- package/seedgridKB/SeedGrid/Extensions/commons/Visao-geral.md +99 -0
- package/seedgridKB/SeedGrid/Extensions/exchange/Configuracao.md +122 -0
- package/seedgridKB/SeedGrid/Extensions/exchange/Enums.md +29 -0
- package/seedgridKB/SeedGrid/Extensions/exchange/Exemplos.md +82 -0
- package/seedgridKB/SeedGrid/Extensions/exchange/Visao-geral.md +118 -0
- package/seedgridKB/SeedGrid/Extensions/filemanagement/Configuracao-Rust.md +110 -0
- package/seedgridKB/SeedGrid/Extensions/filemanagement/Configuracao.md +157 -0
- package/seedgridKB/SeedGrid/Extensions/filemanagement/Exemplos.md +157 -0
- package/seedgridKB/SeedGrid/Extensions/filemanagement/Rust.md +70 -0
- package/seedgridKB/SeedGrid/Extensions/filemanagement/Visao-geral.md +88 -0
- package/seedgridKB/SeedGrid/Extensions/login-tenancy/Configuracao-Rust.md +124 -0
- package/seedgridKB/SeedGrid/Extensions/login-tenancy/Configuracao.md +195 -0
- package/seedgridKB/SeedGrid/Extensions/login-tenancy/Enums.md +71 -0
- package/seedgridKB/SeedGrid/Extensions/login-tenancy/Exemplos.md +149 -0
- package/seedgridKB/SeedGrid/Extensions/login-tenancy/Rust.md +139 -0
- package/seedgridKB/SeedGrid/Extensions/login-tenancy/Visao-geral.md +130 -0
- package/seedgridKB/SeedGrid/Extensions/notification/Configuracao.md +141 -0
- package/seedgridKB/SeedGrid/Extensions/notification/Enums.md +52 -0
- package/seedgridKB/SeedGrid/Extensions/notification/Exemplos.md +141 -0
- package/seedgridKB/SeedGrid/Extensions/notification/Visao-geral.md +113 -0
- package/seedgridKB/SeedGrid/Extensions/privacy/Configuracao-Rust.md +67 -0
- package/seedgridKB/SeedGrid/Extensions/privacy/Configuracao.md +94 -0
- package/seedgridKB/SeedGrid/Extensions/privacy/Enums.md +79 -0
- package/seedgridKB/SeedGrid/Extensions/privacy/Exemplos.md +172 -0
- package/seedgridKB/SeedGrid/Extensions/privacy/Rust.md +107 -0
- package/seedgridKB/SeedGrid/Extensions/privacy/Visao-geral.md +90 -0
- package/seedgridKB/SeedGrid/Extensions/realtime/Configuracao-Rust.md +72 -0
- package/seedgridKB/SeedGrid/Extensions/realtime/Configuracao.md +104 -0
- package/seedgridKB/SeedGrid/Extensions/realtime/Exemplos.md +104 -0
- package/seedgridKB/SeedGrid/Extensions/realtime/Rust.md +69 -0
- package/seedgridKB/SeedGrid/Extensions/realtime/Visao-geral.md +105 -0
- package/seedgridKB/SeedGrid/Extensions/resilience/Configuracao-Rust.md +68 -0
- package/seedgridKB/SeedGrid/Extensions/resilience/Configuracao.md +186 -0
- package/seedgridKB/SeedGrid/Extensions/resilience/Enums.md +96 -0
- package/seedgridKB/SeedGrid/Extensions/resilience/Exemplos.md +229 -0
- package/seedgridKB/SeedGrid/Extensions/resilience/Rust.md +80 -0
- package/seedgridKB/SeedGrid/Extensions/resilience/Visao-geral.md +112 -0
- package/seedgridKB/SeedGrid/Extensions/runtime/Configuracao-Rust.md +90 -0
- package/seedgridKB/SeedGrid/Extensions/runtime/Visao-geral.md +114 -0
- package/seedgridKB/SeedGrid/Extensions/security/Configuracao-Rust.md +327 -0
- package/seedgridKB/SeedGrid/Extensions/security/Configuracao.md +510 -0
- package/seedgridKB/SeedGrid/Extensions/security/Enums.md +95 -0
- package/seedgridKB/SeedGrid/Extensions/security/Exemplos.md +218 -0
- package/seedgridKB/SeedGrid/Extensions/security/Rust.md +203 -0
- package/seedgridKB/SeedGrid/Extensions/security/Visao-geral.md +131 -0
- package/seedgridKB/SeedGrid/Extensions/subdomain-tenancy/Configuracao-Rust.md +188 -0
- package/seedgridKB/SeedGrid/Extensions/subdomain-tenancy/Configuracao.md +345 -0
- package/seedgridKB/SeedGrid/Extensions/subdomain-tenancy/Enums.md +117 -0
- package/seedgridKB/SeedGrid/Extensions/subdomain-tenancy/Exemplos.md +205 -0
- package/seedgridKB/SeedGrid/Extensions/subdomain-tenancy/Rust.md +161 -0
- package/seedgridKB/SeedGrid/Extensions/subdomain-tenancy/Visao-geral.md +142 -0
- package/seedgridKB/SeedGrid/Extensions/whatsapp/Configuracao-Rust.md +75 -0
- package/seedgridKB/SeedGrid/Extensions/whatsapp/Configuracao.md +152 -0
- package/seedgridKB/SeedGrid/Extensions/whatsapp/Enums.md +198 -0
- package/seedgridKB/SeedGrid/Extensions/whatsapp/Exemplos.md +173 -0
- package/seedgridKB/SeedGrid/Extensions/whatsapp/Rust.md +83 -0
- package/seedgridKB/SeedGrid/Extensions/whatsapp/Visao-geral.md +99 -0
- package/seedgridKB/SeedGrid/Mapa-dos-repositorios.md +112 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/Indice.md +323 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/buttons/API.md +257 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/buttons/Exemplos.md +307 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/buttons/Visao-geral.md +51 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/datatable/API.md +174 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/datatable/Exemplos.md +236 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/datatable/Visao-geral.md +76 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/digits/API.md +339 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/digits/Exemplos.md +311 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/digits/Visao-geral.md +57 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/editor/API.md +125 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/editor/Exemplos.md +116 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/editor/Visao-geral.md +86 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/feedback-e-exibicao/API.md +490 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/feedback-e-exibicao/Exemplos.md +544 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/feedback-e-exibicao/Visao-geral.md +69 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/fundamentos/API.md +113 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/fundamentos/Exemplos.md +159 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/fundamentos/Visao-geral.md +92 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/gadgets/API.md +516 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/gadgets/Exemplos.md +629 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/gadgets/Visao-geral.md +80 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/inputs-selecao/API.md +615 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/inputs-selecao/Exemplos.md +384 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/inputs-selecao/Visao-geral.md +111 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/inputs-texto/API.md +661 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/inputs-texto/Exemplos.md +312 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/inputs-texto/Visao-geral.md +123 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/layout/API.md +1090 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/layout/Exemplos.md +1172 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/layout/Visao-geral.md +98 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/modulos/Visao-geral.md +98 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/modulos/fe-apikeys.md +118 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/modulos/fe-audit.md +88 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/modulos/fe-backup.md +131 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/modulos/fe-billing-platform.md +132 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/modulos/fe-billing-user.md +120 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/modulos/fe-login-tenancy.md +119 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/modulos/fe-security.md +427 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/modulos/fe-self-enter.md +104 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/modulos/fe-subdomain-tenancy.md +110 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/navegacao-e-overlay/API.md +490 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/navegacao-e-overlay/Exemplos.md +561 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/navegacao-e-overlay/Visao-geral.md +82 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/pacotes/Visao-geral.md +68 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/pacotes/fe-commons.md +61 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/pacotes/fe-core.md +140 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/pacotes/fe-playground.md +112 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/pacotes/fe-theme.md +97 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/providers/API.md +177 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/providers/Exemplos.md +332 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/providers/Visao-geral.md +106 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/showcase.md +70 -0
- package/seedgridKB/SeedGrid/Toolkit/agents/arquiteto.md +53 -0
- package/seedgridKB/SeedGrid/Toolkit/agents/backend-java.md +45 -0
- package/seedgridKB/SeedGrid/Toolkit/agents/backend-rust.md +43 -0
- package/seedgridKB/SeedGrid/Toolkit/agents/frontend-react.md +41 -0
- package/seedgridKB/SeedGrid/Toolkit/agents/qa.md +44 -0
- package/seedgridKB/SeedGrid/Toolkit/agents/revisor.md +40 -0
- package/seedgridKB/SeedGrid/Toolkit/references/fluxo-de-trabalho.md +78 -0
- package/seedgridKB/SeedGrid/Toolkit/references/glossario.md +15 -0
- package/seedgridKB/SeedGrid/Toolkit/references/modos-shared-native.md +27 -0
- package/seedgridKB/SeedGrid/Toolkit/rules/backend-java-seedgrid.md +54 -0
- package/seedgridKB/SeedGrid/Toolkit/rules/coordenacao.md +39 -0
- package/seedgridKB/SeedGrid/Toolkit/rules/formato-entrega.md +29 -0
- package/seedgridKB/SeedGrid/Toolkit/rules/frontend-seedgrid.md +47 -0
- package/seedgridKB/SeedGrid/Toolkit/rules/personalizacao-local.md +22 -0
- package/seedgridKB/SeedGrid/Toolkit/skills/planejar-mudanca/SKILL.md +38 -0
- package/seedgridKB/SeedGrid/Toolkit/skills/revisar-codigo/SKILL.md +33 -0
- package/seedgridKB/SeedGrid/Toolkit/skills/revisar-codigo/references/checklist.md +25 -0
- package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-backend-crud/SKILL.md +29 -0
- package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-bump/SKILL.md +26 -0
- package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-crud/SKILL.md +221 -0
- package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-crud/agents/openai.yaml +4 -0
- package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-crud/references/checklist.md +31 -0
- package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-crud/references/patterns.md +185 -0
- package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-crud/references/routing.md +66 -0
- package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-new-screen/SKILL.md +56 -0
- package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-new-screen/agents/openai.yaml +4 -0
- package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-new-screen/references/checklist.md +32 -0
- package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-new-screen/references/steps.md +114 -0
- package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-review/SKILL.md +61 -0
- package/seedgridKB/SeedGrid/Toolkit/skills/validar-mudanca/SKILL.md +29 -0
- package/seedgridKB/SeedGrid/Toolkit/templates/decisao-arquitetura.md +29 -0
- package/seedgridKB/SeedGrid/Toolkit/templates/especificacao-tarefa.md +32 -0
- package/seedgridKB/SeedGrid/Toolkit/templates/relatorio-validacao.md +30 -0
- package/seedgridKB/SeedGrid/Versoes.md +64 -0
- package/seedgridKB/SeedGrid/Visao-geral.md +35 -0
- package/seedgridKB/manifest.json +142 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
---
|
|
2
|
+
tags: [seedgrid, extension, security, enum]
|
|
3
|
+
fonte: java/seedgrid-quarkus-ext-security
|
|
4
|
+
branch: main
|
|
5
|
+
commit: 450735386e
|
|
6
|
+
analisado-em: 2026-10-14
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# security — Enums (Quarkus)
|
|
10
|
+
|
|
11
|
+
Voltar para [[SeedGrid/Extensions/security/Visao-geral|Visão geral do security]] · [[SeedGrid/Extensions/security/Configuracao|Configuração]] · [[SeedGrid/Extensions/security/Rust|Porte Rust]]
|
|
12
|
+
|
|
13
|
+
Caminho-base: `java/seedgrid-quarkus-ext-security/runtime/src/main/java/br/com/seedgrid/security/`. Os módulos `deployment` e testes não declaram enums de contrato.
|
|
14
|
+
|
|
15
|
+
## Índice
|
|
16
|
+
|
|
17
|
+
| Enum | Pacote/arquivo | Usado em | Público? |
|
|
18
|
+
|---|---|---|---|
|
|
19
|
+
| [[SeedGrid/Extensions/security/Enums#TwoFactorMethodType\|TwoFactorMethodType]] | `twofactors/TwoFactorMethodType.java` | Corpo de `POST /2f/enable` e `POST /2f/setup/confirm`, resposta de enable, estratégias 2FA, config `2f.allowed-methods` (por código textual) | Sim |
|
|
20
|
+
| [[SeedGrid/Extensions/security/Enums#EntryRequestStatus\|EntryRequestStatus]] | `entities/EntryRequestStatus.java` | Coluna `entry_requests.status`, self-enter, job de limpeza | Sim (persistido) |
|
|
21
|
+
| [[SeedGrid/Extensions/security/Enums#EntryRequestOrigin\|EntryRequestOrigin]] | `entities/EntryRequestOrigin.java` | Coluna `entry_requests.origin`, self-enter | Sim (persistido) |
|
|
22
|
+
| [[SeedGrid/Extensions/security/Enums#UserCreateOptions.Delivery\|UserCreateOptions.Delivery]] | `services/UserCreateOptions.java` (enum aninhado) | API Java para quem cria usuário por fluxo próprio (`UserService#createUser`) | Sim (API de bean) |
|
|
23
|
+
|
|
24
|
+
## TwoFactorMethodType
|
|
25
|
+
|
|
26
|
+
Arquivo: `…/security/twofactors/TwoFactorMethodType.java` — FQN `br.com.seedgrid.security.twofactors.TwoFactorMethodType`. Javadoc: helper de tipo para os métodos 2FA padrão; o código do método é guardado como **String** no banco para permitir implementações custom.
|
|
27
|
+
|
|
28
|
+
| Valor | Significado | Efeito / onde é tratado | Observações |
|
|
29
|
+
|---|---|---|---|
|
|
30
|
+
| `EMAIL` | Código de uso único por e-mail | `EmailTwoFactorStrategy#getMethodCode`; `TwoFactorController` exige e-mail confirmado para ativar | Confirmado |
|
|
31
|
+
| `WHATSAPP` | Código de uso único por WhatsApp | `WhatsappTwoFactorStrategy#getMethodCode`; ativação exige WhatsApp do usuário e `2f.whatsapp.channel-id`; `MeProfileController` compara com o método primário | Confirmado |
|
|
32
|
+
| `TOTP` | Código de app autenticador | `TotpTwoFactorStrategy#getMethodCode`; `TwoFactorController` (setup/confirm e disable); `TwoFactorService` grava como método primário ao confirmar | Confirmado |
|
|
33
|
+
| `BACKUP_CODE` | Código de backup | Existe no enum, mas **nenhum código o referencia** (não há estratégia com esse código; o fallback por backup code em `TwoFactorService` usa `BackupCodeService` direto). Enviá-lo em `method` passa na desserialização, mas não há estratégia registrada para ele | Confirmado (busca por referências) |
|
|
34
|
+
|
|
35
|
+
- **Campos/métodos:** `getCode()` (igual ao nome da constante) e `static fromCode(String)` — comparação `equalsIgnoreCase`, retorna `null` se não achar. `fromCode` não é chamado em lugar nenhum do módulo.
|
|
36
|
+
- **JSON:** sem `@JsonValue`/`@JsonCreator`; o Jackson usa o **nome exato** (maiúsculas, case-sensitive) em `Enable2FADTO.method`, `SetupConfirmDTO.method` e `Enable2FAResponseDTO.method`. Valor desconhecido → erro de desserialização (400).
|
|
37
|
+
- **Persistência:** o enum **não** é persistido; `users.two_factor_primary_method` é `VARCHAR(32)` com o código textual (`User#enableTwoFactor(String)`). Não há CHECK constraint (V202), então estratégias custom (ex.: `SMS`) podem ser gravadas.
|
|
38
|
+
- **Config:** `seedgrid.security.2f.allowed-methods` é `List<String>` (não usa o enum); os valores são normalizados com `trim().toUpperCase()` e cruzados com as estratégias registradas. Ver [[SeedGrid/Extensions/security/Configuracao|Configuração §2.5]].
|
|
39
|
+
- **Observação:** como o DTO usa o enum, um método custom (`SMS`) não pode ser ativado por `POST /2f/enable` (o corpo é rejeitado) mesmo estando em `allowed-methods`. *Inferência* a partir do tipo do campo `method`.
|
|
40
|
+
|
|
41
|
+
## EntryRequestStatus
|
|
42
|
+
|
|
43
|
+
Arquivo: `…/security/entities/EntryRequestStatus.java` — FQN `br.com.seedgrid.security.entities.EntryRequestStatus`. Sem Javadoc; significados deduzidos do tratamento.
|
|
44
|
+
|
|
45
|
+
| Valor | Significado | Efeito / onde é tratado | Observações |
|
|
46
|
+
|---|---|---|---|
|
|
47
|
+
| `PENDING_EMAIL` | Aguardando confirmação do e-mail (OTP no signup público; aceite do convite) | Estado inicial de `requestAccess` e do convite (`SelfEnterService`); `confirmEmail`/`resendEmail` exigem este estado; o job expira registros neste estado | Confirmado |
|
|
48
|
+
| `PENDING_APPROVAL` | Aguardando aprovação administrativa | `EntryRequest#markEmailConfirmed` e `#markInvitationAccepted` levam a este estado; `approve`/`reject` só aceitam este estado; listagem "to-approve" | Confirmado |
|
|
49
|
+
| `APPROVED` | Aprovada; usuário criado | `EntryRequest#approve`; elegível a purga | Confirmado |
|
|
50
|
+
| `REJECTED` | Rejeitada por um administrador | `EntryRequest#reject`; elegível a purga | Confirmado |
|
|
51
|
+
| `EXPIRED` | Expirada | `EntryRequest#expire` (ao aprovar/confirmar uma solicitação vencida) e `EntryRequestRepository#expireOldRequests` (PENDING_EMAIL/PENDING_APPROVAL com `expiresAt` vencido); elegível a purga | Confirmado |
|
|
52
|
+
|
|
53
|
+
- **Persistência:** `@Enumerated(EnumType.STRING)` em `entry_requests.status` (`VARCHAR(30)`). **CHECK** `chk_entry_request_status` (V201) aceita exatamente `PENDING_EMAIL, PENDING_APPROVAL, APPROVED, REJECTED, EXPIRED` — igual às constantes.
|
|
54
|
+
- **JSON:** `EntryRequestDTORes.status` é do tipo `EntryRequestStatus`, serializado pelo nome da constante (sem `@JsonValue`).
|
|
55
|
+
- **Purga:** `EntryRequestCleanupJob` apaga `APPROVED/REJECTED/EXPIRED` mais antigos que `self-enter.cleanup.purge-after` ([[SeedGrid/Extensions/security/Configuracao|Configuração]]).
|
|
56
|
+
|
|
57
|
+
```mermaid
|
|
58
|
+
stateDiagram-v2
|
|
59
|
+
[*] --> PENDING_EMAIL: requestAccess / convite
|
|
60
|
+
PENDING_EMAIL --> PENDING_APPROVAL: confirmEmail / aceite do convite
|
|
61
|
+
PENDING_APPROVAL --> APPROVED: approve
|
|
62
|
+
PENDING_APPROVAL --> REJECTED: reject
|
|
63
|
+
PENDING_EMAIL --> EXPIRED: expira
|
|
64
|
+
PENDING_APPROVAL --> EXPIRED: expira
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Convite com `invite-needs-approval=false` chama `approve` logo após o aceite (vai direto a `APPROVED`).
|
|
68
|
+
|
|
69
|
+
## EntryRequestOrigin
|
|
70
|
+
|
|
71
|
+
Arquivo: `…/security/entities/EntryRequestOrigin.java` — FQN `br.com.seedgrid.security.entities.EntryRequestOrigin`.
|
|
72
|
+
|
|
73
|
+
| Valor | Significado | Efeito / onde é tratado | Observações |
|
|
74
|
+
|---|---|---|---|
|
|
75
|
+
| `PUBLIC` | Pedido criado pelo signup público | `SelfEnterService#requestAccess`; confirmação/reenvio de e-mail exigem esta origem; também é o default em `@PrePersist` quando nulo e o `DEFAULT 'PUBLIC'` da coluna | Confirmado |
|
|
76
|
+
| `INVITE` | Pedido criado por convite administrativo | `SelfEnterService` (convite); aceite/complete/reenvio de convite exigem esta origem; repositório consulta convites pendentes | Confirmado |
|
|
77
|
+
|
|
78
|
+
- **Persistência:** `@Enumerated(EnumType.STRING)`, coluna `origin VARCHAR(20) NOT NULL DEFAULT 'PUBLIC'` (V217). **Não há CHECK constraint** para `origin` (diferente de `status`).
|
|
79
|
+
- Relações: `public-enabled` rege `PUBLIC`; `invite-enabled` rege `INVITE` — [[SeedGrid/Extensions/security/Configuracao|Configuração §2.6]].
|
|
80
|
+
|
|
81
|
+
## UserCreateOptions.Delivery
|
|
82
|
+
|
|
83
|
+
Arquivo: `…/security/services/UserCreateOptions.java` — FQN `br.com.seedgrid.security.services.UserCreateOptions.Delivery` (enum aninhado no record `UserCreateOptions`). Define como as credenciais iniciais chegam ao usuário criado por `UserService#createUser(dto, options)`.
|
|
84
|
+
|
|
85
|
+
| Valor | Significado | Efeito / onde é tratado | Observações |
|
|
86
|
+
|---|---|---|---|
|
|
87
|
+
| `SECURITY_WELCOME_EMAIL` | E-mail de boas-vindas do security | `UserService#deliverInitialCredentials` chama `EmailServiceInterface#sendWelcomeEmail`; é o default (`UserCreateOptions.defaults()` e quando `delivery` é nulo) | Confirmado |
|
|
88
|
+
| `NONE` | Nenhum envio | Sem ação; `createUser` lança `BadRequestException("Senha obrigatoria…")` se a senha teria de ser gerada | Confirmado |
|
|
89
|
+
| `CALLBACK` | Envio feito pelo host via `ActivationMailer` | Exige `activationMailer` não nulo (senão `IllegalArgumentException`); falha do envio só é logada com `mailerBestEffort=true` | Confirmado |
|
|
90
|
+
|
|
91
|
+
- Não é persistido nem serializado em JSON; é parâmetro Java. Construtores de conveniência no record criam as variantes `NONE` e `CALLBACK`.
|
|
92
|
+
|
|
93
|
+
## Internos
|
|
94
|
+
|
|
95
|
+
Nenhum enum interno encontrado no `runtime` além dos listados.
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
---
|
|
2
|
+
tags: [seedgrid, extension, security, exemplos]
|
|
3
|
+
fonte: java/seedgrid-quarkus-ext-security; java/examples/seedgrid-security-example
|
|
4
|
+
branch: main
|
|
5
|
+
commit: 450735386e
|
|
6
|
+
analisado-em: 2026-10-14
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# security — Exemplos (Quarkus)
|
|
10
|
+
|
|
11
|
+
Ver também: [[SeedGrid/Extensions/security/Visao-geral|Visão geral do security]] · [[SeedGrid/Extensions/security/Configuracao|Configuração do security]] · [[SeedGrid/Extensions/security/Rust|Porte Rust]]
|
|
12
|
+
|
|
13
|
+
Fontes: assinaturas lidas em `java/seedgrid-quarkus-ext-security/runtime/src/main/java/br/com/seedgrid/security/spi/*.java`; testes em `runtime/src/test/java/br/com/seedgrid/security/`; `README.md` da extension; exemplo `java/examples/seedgrid-security-example` (repo próprio, commit `86cfc37`, depende de `seedgrid-security:2026.09.25`). Exemplos marcados *ilustrativo* combinam a API real com lógica de negócio fictícia.
|
|
14
|
+
|
|
15
|
+
## 1. Dependência
|
|
16
|
+
|
|
17
|
+
```xml
|
|
18
|
+
<dependency>
|
|
19
|
+
<groupId>br.com.seedgrid</groupId>
|
|
20
|
+
<artifactId>seedgrid-security</artifactId>
|
|
21
|
+
<version>2026.10.14</version>
|
|
22
|
+
</dependency>
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Chaves RSA (README):
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
openssl genrsa -out src/main/resources/keys/private.pem 2048
|
|
29
|
+
openssl rsa -in src/main/resources/keys/private.pem -pubout -out src/main/resources/keys/public.pem
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
> A chave privada lida por `RsaKeyProvider` precisa estar em PKCS#8 (`-----BEGIN PRIVATE KEY-----`). OpenSSL 3 gera PKCS#8 por padrão; com OpenSSL 1.x use `openssl pkcs8 -topk8 -nocrypt` (*Inferência* a partir do `PKCS8EncodedKeySpec` usado no código).
|
|
33
|
+
|
|
34
|
+
Configuração mínima: [[SeedGrid/Extensions/security/Configuracao|Configuração §6]].
|
|
35
|
+
|
|
36
|
+
## 2. Proteger endpoints do host
|
|
37
|
+
|
|
38
|
+
Anotações Quarkus + RBAC do security (README "Proteger endpoints"). As permissões vêm das roles do token via `RbacSecurityIdentityAugmentor`.
|
|
39
|
+
|
|
40
|
+
```java
|
|
41
|
+
import br.com.seedgrid.security.annotations.MonoCompany;
|
|
42
|
+
import io.quarkus.security.Authenticated;
|
|
43
|
+
import io.quarkus.security.PermissionsAllowed;
|
|
44
|
+
import jakarta.annotation.security.RolesAllowed;
|
|
45
|
+
import jakarta.ws.rs.*;
|
|
46
|
+
|
|
47
|
+
@Path("/relatorios") // path sem "/public/" => exige Bearer JWT
|
|
48
|
+
public class RelatorioResource { // ilustrativo
|
|
49
|
+
|
|
50
|
+
@GET
|
|
51
|
+
@PermissionsAllowed("USER_READ") // permissão derivada das roles
|
|
52
|
+
public String listar() { return "ok"; }
|
|
53
|
+
|
|
54
|
+
@GET @Path("/admin")
|
|
55
|
+
@RolesAllowed("ADMIN")
|
|
56
|
+
public String admin() { return "ok"; }
|
|
57
|
+
|
|
58
|
+
@GET @Path("/sem-empresa")
|
|
59
|
+
@Authenticated
|
|
60
|
+
@MonoCompany // CompanyContextFilter ignora
|
|
61
|
+
public String semEmpresa() { return "ok"; }
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Rotas públicas precisam ter `/public/` no path (`JwtAuthenticationFilter#isPublicPath`).
|
|
66
|
+
|
|
67
|
+
## 3. Fluxo HTTP do cliente
|
|
68
|
+
|
|
69
|
+
```http
|
|
70
|
+
POST /public/auth/login
|
|
71
|
+
{ "login": "admin@exemplo.com", "password": "<senha>" }
|
|
72
|
+
-> 200 { "token": "<JWT>", "tokenType": "Bearer", "refreshToken": "<opaco>" }
|
|
73
|
+
ou desafio 2FA com tempToken (quando 2f.enabled=true e o usuário ativou 2FA)
|
|
74
|
+
|
|
75
|
+
POST /public/2f/verify
|
|
76
|
+
{ "tempToken": "<tempToken>", "code": "123456" }
|
|
77
|
+
|
|
78
|
+
POST /me/select-company (Authorization: Bearer <JWT>)
|
|
79
|
+
{ "companyPublicId": "<uuid>" } -> novo par escopado | 403
|
|
80
|
+
|
|
81
|
+
POST /public/auth/refresh
|
|
82
|
+
{ "refreshToken": "<opaco>" } -> preserva a empresa do token
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
(README §"Exemplos de rotas".)
|
|
86
|
+
|
|
87
|
+
## 4. SPIs
|
|
88
|
+
|
|
89
|
+
Todas as implementações padrão são `@DefaultBean`; um bean `@ApplicationScoped` do host com o mesmo tipo substitui.
|
|
90
|
+
|
|
91
|
+
### 4.1 `UserAdditionalFieldsValidator` — regras de `additionalAttributes`
|
|
92
|
+
|
|
93
|
+
Assinatura: `void validate(User user, Map<String, JsonNode> additionalAttributes)`. Exemplo real do teste `RejectingUserAdditionalFieldsValidator`:
|
|
94
|
+
|
|
95
|
+
```java
|
|
96
|
+
import br.com.seedgrid.security.entities.User;
|
|
97
|
+
import br.com.seedgrid.security.exceptions.InvalidUserAdditionalAttributesException;
|
|
98
|
+
import br.com.seedgrid.security.spi.UserAdditionalFieldsValidator;
|
|
99
|
+
import com.fasterxml.jackson.databind.JsonNode;
|
|
100
|
+
import jakarta.enterprise.context.ApplicationScoped;
|
|
101
|
+
import java.util.Map;
|
|
102
|
+
|
|
103
|
+
@ApplicationScoped
|
|
104
|
+
public class RejectingUserAdditionalFieldsValidator implements UserAdditionalFieldsValidator {
|
|
105
|
+
|
|
106
|
+
public static final String REJECT_KEY = "__reject";
|
|
107
|
+
|
|
108
|
+
@Override
|
|
109
|
+
public void validate(User user, Map<String, JsonNode> additionalAttributes) {
|
|
110
|
+
if (additionalAttributes != null && additionalAttributes.containsKey(REJECT_KEY)) {
|
|
111
|
+
throw new InvalidUserAdditionalAttributesException(
|
|
112
|
+
"Atributo " + REJECT_KEY + " rejeitado pela aplicacao");
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
A exceção vira HTTP 400. Os limites de tamanho/profundidade/chaves são aplicados antes, por `seedgrid.security.user.additional-attributes.*`.
|
|
119
|
+
|
|
120
|
+
### 4.2 `AllowedCompaniesResolver` — visão "todas as empresas"
|
|
121
|
+
|
|
122
|
+
Assinatura: `AllowedCompanies resolve(User user, List<String> roles)`; `AllowedCompanies.of(List<Long>)` e `AllowedCompanies.seeingAll(List<Long>)`. *Ilustrativo* (adaptado do README — o README usa `getMemberships()`; a entidade expõe `getActiveCompanies()`):
|
|
123
|
+
|
|
124
|
+
```java
|
|
125
|
+
@ApplicationScoped
|
|
126
|
+
public class MyAllowedCompaniesResolver implements AllowedCompaniesResolver {
|
|
127
|
+
@Override
|
|
128
|
+
public AllowedCompanies resolve(User user, List<String> roles) {
|
|
129
|
+
List<Long> ids = user.getActiveCompanies().stream().map(Company::getId).toList();
|
|
130
|
+
return roles.contains("PLATFORM_ADMIN") ? AllowedCompanies.seeingAll(ids) : AllowedCompanies.of(ids);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### 4.3 `JwtTokenCustomizer` — claims extras (ex.: `audience`)
|
|
136
|
+
|
|
137
|
+
Assinatura **atual**: `Map<String, Object> customizeClaims(User user, List<String> roles, String hostHeader, Long scopedCompanyId)` (o README mostra uma versão antiga com 3 parâmetros). O claim `audience` é o que o `RbacSecurityIdentityAugmentor` usa para filtrar permissões por audience. *Ilustrativo*:
|
|
138
|
+
|
|
139
|
+
```java
|
|
140
|
+
@ApplicationScoped
|
|
141
|
+
public class AudienceTokenCustomizer implements JwtTokenCustomizer {
|
|
142
|
+
@Override
|
|
143
|
+
public Map<String, Object> customizeClaims(User user, List<String> roles, String hostHeader, Long scopedCompanyId) {
|
|
144
|
+
return scopedCompanyId == null ? Map.of() : Map.of("audience", "client");
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Combine com `seedgrid.security.account.assignable-permission-audiences=client` para que admins de conta possam atribuir permissões `client`.
|
|
150
|
+
|
|
151
|
+
### 4.4 `JwtTokenValidator`
|
|
152
|
+
|
|
153
|
+
`void validateCustomClaims(JWTClaimsSet claims, String hostHeader)` (Nimbus `JWTClaimsSet`) — chamado por `TokenVerifier` depois de assinatura, issuer e expiração. Use para validar claims próprios (ex.: subdomínio).
|
|
154
|
+
|
|
155
|
+
### 4.5 `TwoFactorStrategy` — novo método 2FA
|
|
156
|
+
|
|
157
|
+
```java
|
|
158
|
+
public interface TwoFactorStrategy {
|
|
159
|
+
String getMethodCode();
|
|
160
|
+
boolean canInitiate(User user);
|
|
161
|
+
default boolean canEnroll(User user) { return canInitiate(user); }
|
|
162
|
+
TwoFactorInitResult initiate(User user, TwoFactorContext context);
|
|
163
|
+
TwoFactorVerifyResult verify(User user, String code, TwoFactorContext context);
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
O código retornado por `getMethodCode()` precisa constar em `seedgrid.security.2f.allowed-methods` para aparecer ao usuário (`TwoFactorController#getAllowedMethods`).
|
|
168
|
+
|
|
169
|
+
### 4.6 E-mail e templates
|
|
170
|
+
|
|
171
|
+
- `EmailServiceInterface`: `sendEmailConfirmation`, `sendPasswordReset`, `generateToken`, `sendHtmlEmail(to, subject, htmlBody, textBody)`, `sendWelcomeEmail(user, temporaryPassword, confirmationToken)`. Os testes trocam a implementação com `@Alternative @Priority(1)` (`TestEmailService`), usando `TemplateSecurityProvider` + `SecurityLinkBuilder`.
|
|
172
|
+
- `TemplateSecurityProvider`: `emailConfirmation`, `passwordReset`, `entryRequestConfirmation`, `entryRequestApproved`, `welcomeEmail`, `twoFactorCode` (abstratos) e `entryRequestConfirmationCode`, `entryRequestInvitation`, `twoFactorWhatsappText` (default). `entryRequestApproved` precisa ser implementado, mas hoje não é chamado (o e-mail de aprovação do self-enter não é enviado). Templates padrão: `runtime/src/main/resources/templates/security-default/html/*.html` e `txt/two-factor-code-whatsapp.txt`.
|
|
173
|
+
- `TwoFactorEmailTemplateProvider#buildCodeEmail(User, String code, int expiresInMinutes)` → `EmailTemplate(subject, htmlBody, textBody)`.
|
|
174
|
+
|
|
175
|
+
### 4.7 Outras SPIs
|
|
176
|
+
|
|
177
|
+
| SPI | Método |
|
|
178
|
+
|---|---|
|
|
179
|
+
| `LoginScopeResolver` | `Long resolveLoginScope(User user, String requestedScope)` |
|
|
180
|
+
| `SecurityScopeResolverProvider` | `String currentScope()` |
|
|
181
|
+
| `UserQuotaValidator` | `void assertCanAddUser(Company company)` |
|
|
182
|
+
| `AccountUserActivationMailer` | `void deliver(User user, ActivationCredentials credentials)` |
|
|
183
|
+
|
|
184
|
+
## 5. Configuração por cenário (testes)
|
|
185
|
+
|
|
186
|
+
Profiles reais de teste mostram combinações válidas:
|
|
187
|
+
|
|
188
|
+
```java
|
|
189
|
+
// SelfEnterInviteOnlyProfile
|
|
190
|
+
Map.of(
|
|
191
|
+
"seedgrid.security.self-enter.enabled", "true",
|
|
192
|
+
"seedgrid.security.self-enter.public-enabled", "false",
|
|
193
|
+
"seedgrid.security.self-enter.invite-enabled", "true");
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Outros: `SelfEnterInviteAutoApproveProfile` (`invite-needs-approval=false`), `SelfEnterNoDefaultRoleProfile` (`default-role` inexistente → aprovação falha), `BootstrapDisabledProfile` (`bootstrap.enabled=false`), `RefreshTokenGraceWindowProfile` (`refresh-token.reuse-grace-window`).
|
|
197
|
+
|
|
198
|
+
## 6. Trecho de `application.properties` do exemplo
|
|
199
|
+
|
|
200
|
+
De `java/examples/seedgrid-security-example/src/main/resources/application.properties` (segredos substituídos por placeholders):
|
|
201
|
+
|
|
202
|
+
```properties
|
|
203
|
+
seedgrid.security.2f.enabled=true
|
|
204
|
+
seedgrid.security.2f.allowed-methods=EMAIL,TOTP,WHATSAPP
|
|
205
|
+
seedgrid.security.2f.totp.issuer=SeedGrid.CRM
|
|
206
|
+
seedgrid.security.2f.otp-qrcode.branding.enabled=true
|
|
207
|
+
seedgrid.security.2f.otp-qrcode.logo=classpath:/images/logo-qrcode-otp.png
|
|
208
|
+
seedgrid.security.2f.otp-qrcode.size=350
|
|
209
|
+
seedgrid.security.rbac.cache-ttl=${SECURITY_RBAC_CACHE_TTL:PT5M}
|
|
210
|
+
seedgrid.security.encryption.key=<SEGREDO:security-encryption-key-base64-32-bytes>
|
|
211
|
+
seedgrid.security.self-enter.enabled=true
|
|
212
|
+
seedgrid.security.self-enter.request-ttl=PT2M
|
|
213
|
+
seedgrid.security.self-enter.email-token-ttl=PT10M
|
|
214
|
+
seedgrid.security.self-enter.cleanup.purge-after=PT10M
|
|
215
|
+
seedgrid.security.self-enter.cleanup.cron=0 */5 * * * ?
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Observação: o exemplo não define `seedgrid.security.frontend.self-enter-path` (cai no default do mp-config) e usa TTLs curtos de demonstração.
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
---
|
|
2
|
+
tags: [seedgrid, extension, security, rust]
|
|
3
|
+
fonte: rust/seedgrid-rust-crate-security
|
|
4
|
+
branch: main
|
|
5
|
+
commit: be738a2d1e
|
|
6
|
+
analisado-em: 2026-10-14
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# `seedgrid-security` — porte Rust
|
|
10
|
+
|
|
11
|
+
Lado Java: [[SeedGrid/Extensions/security/Visao-geral|Visão geral do security (Quarkus)]] · [[SeedGrid/Extensions/security/Configuracao|Configuração Java]]
|
|
12
|
+
Configuração deste crate: [[SeedGrid/Extensions/security/Configuracao-Rust|Configuração Rust do security]]
|
|
13
|
+
|
|
14
|
+
## Objetivo
|
|
15
|
+
|
|
16
|
+
Porte em Rust da extensão `seedgrid-quarkus-ext-security`, distribuído como **crate biblioteca** (Axum 0.8 + sqlx/Postgres). O host constrói um `SecurityState` e monta o `router` no servidor Axum dele. Funcionalidades (Confirmado em `src/lib.rs`, `README.md`, `src/routes.rs`):
|
|
17
|
+
|
|
18
|
+
- Autenticação **JWT RS256** (claims `sub/upn/userName/whatsapp/groups/allowedCompanies/companyId/companyRoot/allCompanies` + claims via SPI).
|
|
19
|
+
- **Refresh tokens** rotativos com *family*, detecção de reuso e janela de graça para rotação concorrente.
|
|
20
|
+
- Senha **BCrypt** sobre `publicId + senha` (emite `$2a$10$`, compatível com o jBCrypt do Java).
|
|
21
|
+
- **RBAC** (roles + permissões com `audience`/`is_default`), empresas, memberships por conta (`is_root`, roles por conta, desativação por conta), gestão pela plataforma e pela própria conta (`/me/security/*`).
|
|
22
|
+
- **2FA** TOTP / e-mail / WhatsApp + backup codes; segredo TOTP cifrado (AES-256-GCM).
|
|
23
|
+
- **Self-enter** (auto-registro com OTP + aprovação, convites).
|
|
24
|
+
- **Avatar** via crate `seedgrid-filemanagement`; **auditoria** via `seedgrid-audit`; **rate limit** via `seedgrid-resilience` + `seedgrid-cache`; **PII at-rest** via `seedgrid-privacy`; SMTP real via `lettre`.
|
|
25
|
+
- Erros RFC 7807 (`application/problem+json`); OpenAPI própria via `utoipa` (`seedgrid_security::openapi()`).
|
|
26
|
+
|
|
27
|
+
## Coordenadas
|
|
28
|
+
|
|
29
|
+
| Item | Valor |
|
|
30
|
+
|---|---|
|
|
31
|
+
| Diretório | `rust/seedgrid-rust-crate-security` |
|
|
32
|
+
| Pacote Cargo / lib | `seedgrid-security` / `seedgrid_security` |
|
|
33
|
+
| Versão | `version.workspace = true` → `2026.10.14` (`rust/Cargo.toml`, `[workspace.package]`). |
|
|
34
|
+
| Edição / MSRV | `edition = "2021"`, `rust-version = "1.82"` |
|
|
35
|
+
| Licença declarada | `LicenseRef-Commercial` |
|
|
36
|
+
| Features Cargo | nenhuma |
|
|
37
|
+
| Dependências SeedGrid | `seedgrid-rust-crate-filemanagent` (como `seedgrid-filemanagement`), `-audit`, `-resilience`, `-cache`, `-whatsapp`, `-privacy` (path deps). Reexporta `seedgrid_audit`, `seedgrid_cache`, `seedgrid_resilience`, `seedgrid_whatsapp`. |
|
|
38
|
+
|
|
39
|
+
## API pública (principais símbolos)
|
|
40
|
+
|
|
41
|
+
| Símbolo | Papel |
|
|
42
|
+
|---|---|
|
|
43
|
+
| `SecurityConfig` (+ `from_env`, `new`) | configuração agregada — ver [[SeedGrid/Extensions/security/Configuracao-Rust\|Configuração Rust]] |
|
|
44
|
+
| `migrate(&PgPool)` / `MIGRATOR` | aplica `migrations/0199..0230` em tabela de histórico própria `_sqlx_migrations_security` (`src/migrations.rs`) |
|
|
45
|
+
| `SecurityState::builder(pool, config)` → `SecurityStateBuilder` | seams: `.email`, `.whatsapp`, `.storage`, `.scope_resolver`, `.jwt_customizer`, `.jwt_validator`, `.login_scope_resolver`, `.allowed_companies`, `.user_quota_validator`, `.user_additional_fields_validator`, `.auditor`, `.cache`, `.template_provider`, `.two_factor_template_provider`, `.pool_resolver`, `.account_user_activation_mailer`; `.build()` |
|
|
46
|
+
| `router(SecurityState)` | `axum::Router` com todas as rotas abaixo |
|
|
47
|
+
| `bootstrap(&SecurityState)` | garante a empresa-plataforma e o primeiro admin |
|
|
48
|
+
| `cleanup_entry_requests` / `spawn_entry_request_cleanup(state, interval)` | limpeza de pedidos de self-enter (job tokio) |
|
|
49
|
+
| `SecurityPlatform::assemble(Option<&PgPool>, SecurityOverrides)` | "autostart" estilo Quarkus: habilita só com Postgres **e** chaves RSA; roda `migrate`, `build` e (opcional) `bootstrap`; retorna `Ok(None)` se desabilitado |
|
|
50
|
+
| `SmtpEmailService`, `DefaultTemplateSecurityProvider`, `DefaultTwoFactorEmailTemplateProvider`, `TemplateSecurityProvider`, `TwoFactorEmailTemplateProvider` | e-mail e templates |
|
|
51
|
+
| `spi::*` | `PoolResolver`, `AllowedCompaniesResolver`, `LoginScopeResolver`, `UserQuotaValidator`, `UserAdditionalFieldsValidator`, `JwtTokenCustomizer`, `JwtTokenValidator`, `ScopeResolver`, `EmailService`, `WhatsappSender`, `AvatarStorage` (todos com default embutido) |
|
|
52
|
+
| `services::users`, `services::rbac`, `services::company_users`, `services::company_roles`... | serviços reutilizados pelos crates de tenancy/apikeys (ex.: `users::create_user_with_options`, `rbac::resolve_for_company`, `rbac::require_platform_scope`) |
|
|
53
|
+
|
|
54
|
+
## Endpoints (Confirmado em `src/routes.rs`)
|
|
55
|
+
|
|
56
|
+
| Grupo | Método + path |
|
|
57
|
+
|---|---|
|
|
58
|
+
| Auth pública | `POST /public/auth/login`, `POST /public/auth/refresh`, `GET /public/auth/confirm-email`, `POST /public/auth/forgot-password`, `GET /public/auth/reset-password` |
|
|
59
|
+
| 2FA pública | `POST /public/2f/verify`, `POST /public/2f/resend` |
|
|
60
|
+
| Self-enter público | `POST /public/self-enter/requests`, `POST /public/self-enter/requests/{id}/confirm-email`, `POST /public/self-enter/requests/{id}/resend-email`, `GET /public/self-enter/invitations/{token}`, `POST /public/self-enter/invitations/{token}/complete` |
|
|
61
|
+
| Outras públicas | `GET /public/companies` |
|
|
62
|
+
| Usuário logado | `GET /me/permissions`, `GET /me/companies`, `POST /me/select-company`, `GET\|PUT /me/profile`, `PUT /me/profile/password`, `POST\|GET\|DELETE /me/profile/avatar` |
|
|
63
|
+
| Gestão pela conta | `GET\|POST /me/security/roles`, `GET /me/security/roles/permissions`, `GET\|PUT\|DELETE /me/security/roles/{id}`, `GET\|POST /me/security/users`, `GET\|PUT\|DELETE /me/security/users/{id}`, `POST /me/security/users/{id}/resend-activation` |
|
|
64
|
+
| Usuários (plataforma) | `GET\|POST /users`, `GET\|PATCH\|DELETE /users/{public_id}`, `POST /users/avatars/defaults`, `POST\|GET\|DELETE /users/{public_id}/avatar`, `PUT /users/change-password`, `PUT /users/{public_id}/memberships`, `PUT\|DELETE /users/{public_id}/memberships/{company_public_id}` |
|
|
65
|
+
| Roles / permissões | `GET\|POST /roles`, `GET /roles/integration`, `GET\|PATCH\|DELETE /roles/{public_id}`, `GET /permissions`, `GET /permissions/{public_id}` |
|
|
66
|
+
| Empresas | `GET\|POST /companies`, `GET\|PATCH\|DELETE /companies/{public_id}` |
|
|
67
|
+
| 2FA autenticado | `POST /2f/setup`, `/2f/confirm`, `/2f/disable`, `/2f/backup-codes`, `/2f/enable`, `/2f/setup/confirm`, `/2f/totp/confirm`; `GET /2f/status` |
|
|
68
|
+
| Self-enter admin | `GET /self-enter/requests/to-approve`, `GET\|POST /self-enter/invitations`, `POST /self-enter/invitations/{id}/resend`, `POST /self-enter/requests/{id}/approve`, `POST /self-enter/requests/{id}/reject` |
|
|
69
|
+
|
|
70
|
+
Rotas de plataforma (`/users`, `/roles`, `/permissions`, `/companies`) exigem, além da permissão, root global ou membro ativo da empresa-plataforma (`rbac::require_platform_scope`). Rotas `/self-enter*` respondem 404 antes da autenticação quando o self-enter está desligado. Rotas públicas têm rate limit por IP (`src/ratelimit.rs`).
|
|
71
|
+
|
|
72
|
+
## Exemplos
|
|
73
|
+
|
|
74
|
+
Uso básico (Confirmado em `src/lib.rs` doc-test e `README.md`):
|
|
75
|
+
|
|
76
|
+
```rust
|
|
77
|
+
use seedgrid_security::{router, SecurityConfig, SecurityState};
|
|
78
|
+
|
|
79
|
+
async fn boot(pool: sqlx::PgPool) -> Result<(), Box<dyn std::error::Error>> {
|
|
80
|
+
let config = SecurityConfig::from_env()?;
|
|
81
|
+
seedgrid_security::migrate(&pool).await?;
|
|
82
|
+
let state = SecurityState::builder(pool, config).build()?;
|
|
83
|
+
let app = axum::Router::new().merge(router(state));
|
|
84
|
+
let _ = app;
|
|
85
|
+
Ok(())
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Montagem "estilo Quarkus" (Confirmado em `src/platform.rs`):
|
|
90
|
+
|
|
91
|
+
```rust
|
|
92
|
+
use seedgrid_security::{SecurityOverrides, SecurityPlatform};
|
|
93
|
+
|
|
94
|
+
async fn boot(pool: Option<sqlx::PgPool>) -> Result<(), String> {
|
|
95
|
+
if let Some(state) = SecurityPlatform::assemble(pool.as_ref(), SecurityOverrides::enabled()).await? {
|
|
96
|
+
let app = axum::Router::new().merge(seedgrid_security::router(state));
|
|
97
|
+
let _ = app;
|
|
98
|
+
}
|
|
99
|
+
Ok(())
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
> `SecurityOverrides::default()` deixa `run_bootstrap = false` (derive `Default`); `SecurityOverrides::enabled()` liga o bootstrap.
|
|
104
|
+
|
|
105
|
+
Validador de `additionalAttributes` e override de templates: ver `README.md` do crate (`UserAdditionalFieldsValidator`, `DefaultTemplateSecurityProvider::with_host_dir`).
|
|
106
|
+
|
|
107
|
+
Exemplo executável: `rust/examples/seedgrid-security-apikeys-example/src/main.rs` (security + apikeys; migra security antes de apikeys, `from_env`, `bootstrap`, merge dos routers e middleware `api_key_auth`).
|
|
108
|
+
|
|
109
|
+
## Migrations
|
|
110
|
+
|
|
111
|
+
`migrations/0199_enable_extensions.sql` a `0230_user_company_active.sql` (32 arquivos), porte das V200..V233 do Flyway Java. Tabela de histórico isolada `_sqlx_migrations_security`. Precisam rodar **antes** das de apikeys/login-tenancy/backup (dependência de dados: `users`, `roles`, `permissions`, `companies`).
|
|
112
|
+
|
|
113
|
+
## Testes
|
|
114
|
+
|
|
115
|
+
- Unitários em `src/**` (`cargo test --lib`), ex.: `config::tests` (durações, base64 DER→PEM, bool).
|
|
116
|
+
- Integração em `tests/` com Postgres real via Testcontainers: `integration.rs`, `rate_limit.rs`, `email_templates.rs` e ~30 arquivos `java_parity_*.rs` (port dos testes Java: auth, refresh grace window, 2FA, self-enter, RBAC, memberships, cripto de campos, bootstrap do primeiro admin, gestão de conta/plataforma etc.).
|
|
117
|
+
- **Não executados** nesta análise.
|
|
118
|
+
|
|
119
|
+
## Limitações conhecidas
|
|
120
|
+
|
|
121
|
+
- Sem cache RBAC (resolução direta no banco).
|
|
122
|
+
- Status HTTP 422 do módulo Java viram 400 em várias regras.
|
|
123
|
+
- Política de senha com defaults mais rígidos que o módulo Java.
|
|
124
|
+
- Backend de storage do avatar é seam do host (não lido de config).
|
|
125
|
+
- Tolerância TOTP fixa em ±1 janela (sem config); nomes JWT `SEEDGRID_SECURITY_JWT_ISSUER/KID/TTL` não lidos — ver [[SeedGrid/Extensions/security/Configuracao-Rust|Configuração Rust]] §9.
|
|
126
|
+
- `is_effective_root` segue modelo de união (Java: override).
|
|
127
|
+
- Self-enter: `default_role` é obrigatória com self-enter ligado (`from_env` falha sem ela); se a role não existe, a aprovação é recusada antes de criar o usuário, como no Java — ver [[SeedGrid/Extensions/security/Configuracao-Rust|Configuração Rust]] §2.7.
|
|
128
|
+
|
|
129
|
+
## Enums
|
|
130
|
+
|
|
131
|
+
Enums públicos do crate (`rust/seedgrid-rust-crate-security/src`). Equivalentes Java em [[SeedGrid/Extensions/security/Enums|Enums (Quarkus)]].
|
|
132
|
+
|
|
133
|
+
| Enum | Arquivo | Usado em | Equivalente Java |
|
|
134
|
+
|---|---|---|---|
|
|
135
|
+
| `EntryRequestStatus` | `models/entry_request.rs` | coluna `entry_requests.status`; fluxo de self-enter | [[SeedGrid/Extensions/security/Enums#EntryRequestStatus\|EntryRequestStatus]] |
|
|
136
|
+
| `EntryRequestOrigin` | `models/entry_request.rs` | coluna `entry_requests.origin` | [[SeedGrid/Extensions/security/Enums#EntryRequestOrigin\|EntryRequestOrigin]] |
|
|
137
|
+
| `CredentialDelivery` | `services/users.rs` | `UserCreateOptions.delivery` (API de serviço para o host) | [[SeedGrid/Extensions/security/Enums#Delivery\|Delivery]] |
|
|
138
|
+
| `SecurityError` | `error.rs` | erro de serviços/handlers; corpo RFC 7807 | exceções do Java (sem enum equivalente) |
|
|
139
|
+
| `TemplateError` | `templates.rs` | retorno de `TemplateSecurityProvider` | `TemplateNotFoundException` / `TemplateCantLoadException` |
|
|
140
|
+
|
|
141
|
+
### EntryRequestStatus
|
|
142
|
+
|
|
143
|
+
Estado do pedido de self-enter. Coluna `status VARCHAR(30)` com `CHECK chk_entry_request_status` (`migrations/0201_create_entry_requests_table.sql`) que aceita exatamente os 5 valores abaixo.
|
|
144
|
+
|
|
145
|
+
| Variante | Valor | Onde é tratado |
|
|
146
|
+
|---|---|---|
|
|
147
|
+
| `PendingEmail` | `PENDING_EMAIL` | estado inicial do pedido público e do convite (`services/selfenter.rs`); expira por `expires_at` |
|
|
148
|
+
| `PendingApproval` | `PENDING_APPROVAL` | depois de confirmar o OTP de e-mail; só nesse estado a aprovação é aceita (senão erro `INVALID_STATUS`) |
|
|
149
|
+
| `Approved` | `APPROVED` | a aprovação cria o usuário e grava `approved_at`/`approved_by` |
|
|
150
|
+
| `Rejected` | `REJECTED` | a rejeição grava `rejected_at`/`rejected_by` |
|
|
151
|
+
| `Expired` | `EXPIRED` | o job de limpeza marca pendentes vencidos; depois de `purge_after` o registro é purgado junto com APPROVED/REJECTED |
|
|
152
|
+
|
|
153
|
+
- Serde: `rename_all = "SCREAMING_SNAKE_CASE"` (apenas `Serialize`). Conversões: `as_str()` e `parse(&str) -> Option<Self>` (sensível a caixa). A struct `EntryRequest` guarda `status` como `String` e as queries comparam literais SQL.
|
|
154
|
+
- Java: mesmos 5 valores na mesma ordem. Igual (Confirmado).
|
|
155
|
+
|
|
156
|
+
### EntryRequestOrigin
|
|
157
|
+
|
|
158
|
+
| Variante | Valor | Onde é tratado |
|
|
159
|
+
|---|---|---|
|
|
160
|
+
| `Public` | `PUBLIC` | pedido do link público; default da coluna `origin` |
|
|
161
|
+
| `Invite` | `INVITE` | convite criado por admin; as consultas de convites filtram `origin = 'INVITE'` |
|
|
162
|
+
|
|
163
|
+
- Coluna `origin VARCHAR(20) NOT NULL DEFAULT 'PUBLIC'` (migration `0217`), sem CHECK. Serde `rename_all = "UPPERCASE"`; `as_str()` / `parse()`.
|
|
164
|
+
- Java: `PUBLIC`, `INVITE`: idêntico.
|
|
165
|
+
|
|
166
|
+
### CredentialDelivery
|
|
167
|
+
|
|
168
|
+
Enum com dados, não serializável: `SecurityWelcomeEmail` (e-mail de boas-vindas do security), `None` (nada é enviado; exige senha informada) e `Callback { mailer: Arc<dyn ActivationMailer>, best_effort: bool }` (envio do host; `best_effort` faz a falha só logar). No Java, `Delivery` tem `SECURITY_WELCOME_EMAIL`, `NONE`, `CALLBACK`, e o mailer e o best-effort são campos separados do record `UserCreateOptions`. Mesmos 3 casos; muda só o formato.
|
|
169
|
+
|
|
170
|
+
### SecurityError
|
|
171
|
+
|
|
172
|
+
Cada variante tem status HTTP e `code` estável no corpo `application/problem+json` (`error.rs`).
|
|
173
|
+
|
|
174
|
+
| Variante | HTTP | `code` |
|
|
175
|
+
|---|---|---|
|
|
176
|
+
| `InvalidCredentials` | 401 | `INVALID_CREDENTIALS` |
|
|
177
|
+
| `Unauthorized` | 401 | `UNAUTHORIZED` |
|
|
178
|
+
| `TokenValidation` | 401 | `TOKEN_VALIDATION` |
|
|
179
|
+
| `Forbidden` | 403 | `FORBIDDEN` |
|
|
180
|
+
| `NotFound` | 404 | o `code` informado |
|
|
181
|
+
| `Conflict` | 409 | o `code` informado |
|
|
182
|
+
| `Validation` | 400 | `VALIDATION_ERROR` (com `violations`) |
|
|
183
|
+
| `BadRequest` | 400 | o `code` informado (ex.: `INVALID_USER_ADDITIONAL_ATTRIBUTES`) |
|
|
184
|
+
| `TwoFactorRequired` | 202 | `TWO_FACTOR_REQUIRED` (com `session_token` e `primary_method`) |
|
|
185
|
+
| `Database` | 500 | `DATABASE_ERROR` |
|
|
186
|
+
| `Internal` | 500 | `INTERNAL_ERROR` |
|
|
187
|
+
|
|
188
|
+
Convenção do crate: regras que o Java responde 422 viram 400.
|
|
189
|
+
|
|
190
|
+
### TemplateError
|
|
191
|
+
|
|
192
|
+
`NotFound(String)` e `CantLoad(String)`. O provider default só os usa internamente (cai para o template embutido); ficam expostos para providers do host.
|
|
193
|
+
|
|
194
|
+
### Métodos de 2FA (sem enum)
|
|
195
|
+
|
|
196
|
+
O Java tem `TwoFactorMethodType` (`EMAIL`, `WHATSAPP`, `TOTP`, `BACKUP_CODE`, com `fromCode` sem diferenciar caixa). O Rust **não tem enum**: o método é `String` em `users.two_factor_primary_method` e em `two_factor.allowed_methods` / `default_method`. Valores executáveis: `SUPPORTED_METHODS = ["TOTP","EMAIL","WHATSAPP"]` (`services/twofactor.rs`); os itens de `allowed_methods` são aparados e passados para maiúsculas, mas o que estiver fora dessa lista nunca é oferecido. `BACKUP_CODE` não é um método no Rust: o código de backup é um campo à parte (`backupCode`) verificado por `consume_backup_code`. Ver [[SeedGrid/Extensions/security/Enums#TwoFactorMethodType|TwoFactorMethodType]].
|
|
197
|
+
|
|
198
|
+
### Internos
|
|
199
|
+
|
|
200
|
+
| Enum | Arquivo |
|
|
201
|
+
|---|---|
|
|
202
|
+
| `UsersListResponse`, `RolesListResponse`, `EntryListResponse` (respostas lista simples ou página) | `routes.rs` |
|
|
203
|
+
| `PlatformRolesTarget` | `services/users.rs` |
|