@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,427 @@
|
|
|
1
|
+
---
|
|
2
|
+
tags: [seedgrid, front, modulo, fe-security]
|
|
3
|
+
fonte: front/seedgrid-fe-components/packages/modules/seedgrid-fe-security
|
|
4
|
+
branch: main
|
|
5
|
+
commit: ad30fc11de
|
|
6
|
+
analisado-em: 2026-10-14
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# @seedgrid/fe-security
|
|
10
|
+
|
|
11
|
+
Links: [[SeedGrid/SeedGrid-components/modulos/Visao-geral|Módulos front]] · [[SeedGrid/SeedGrid-components/pacotes/fe-core|@seedgrid/fe-core]] · [[SeedGrid/Extensions/security/Visao-geral|Extension security (backend)]]
|
|
12
|
+
|
|
13
|
+
> Convenção de fontes: caminhos relativos a `seedgrid-platform`. Abreviação usada nas tabelas: `PKG` = `front/seedgrid-fe-components/packages/modules/seedgrid-fe-security`.
|
|
14
|
+
> Testes **não executados**; nenhum build foi rodado nesta análise.
|
|
15
|
+
|
|
16
|
+
## Objetivo
|
|
17
|
+
|
|
18
|
+
Módulo-base de segurança do front SeedGrid (Next.js): sessão server-side com cookies httpOnly (login, refresh em 401, logout, 2FA), contrato de paths REST da extension backend `security`, helpers de permissão, DTOs, mensagens i18n e componentes client. Os demais módulos front (`fe-apikeys`, `fe-audit`, `fe-backup`, `fe-billing-*`, `fe-login-tenancy`, `fe-self-enter`, `fe-subdomain-tenancy`) declaram `requires: ["security"]` e compõem seus engines sobre `SecurityServer`. **Confirmado** (`PKG/README.md`; `packages/modules/*/src/module.ts`; ex.: `packages/modules/seedgrid-fe-apikeys/src/server/create-apikeys-server.ts → createApiKeysServer(session: SecurityServer)`).
|
|
19
|
+
|
|
20
|
+
O pacote tem duas partes distribuídas juntas (`"files": ["dist", "scaffold"]`):
|
|
21
|
+
|
|
22
|
+
| Parte | Onde | Natureza |
|
|
23
|
+
|---|---|---|
|
|
24
|
+
| Lib versionada | `PKG/src/**` → `dist/**` | Importada via npm; não se edita no app |
|
|
25
|
+
| Scaffold | `PKG/scaffold/src/**` | Copiado pelo SeedGrid CLI para dentro do app gerado (o app é dono do código). Contém templates `.hbs` |
|
|
26
|
+
|
|
27
|
+
**Confirmado** (`PKG/package.json → files`; `PKG/scaffold/README.md`).
|
|
28
|
+
|
|
29
|
+
## Pacote npm
|
|
30
|
+
|
|
31
|
+
| Item | Valor | Certeza / fonte |
|
|
32
|
+
|---|---|---|
|
|
33
|
+
| Nome | `@seedgrid/fe-security` | Confirmado — `PKG/package.json` |
|
|
34
|
+
| Versão | `2026.7.3` | Confirmado |
|
|
35
|
+
| Tipo | `"type": "module"` (ESM); `main: dist/index.js`, `types: dist/index.d.ts` | Confirmado |
|
|
36
|
+
| peerDependencies | `@seedgrid/fe-components: *`, `@seedgrid/fe-core: *`, `next: >=14` (opcional), `react: ^18.2.0 \|\| ^19.0.0` (opcional) | Confirmado (`peerDependenciesMeta`) |
|
|
37
|
+
| dependencies | nenhuma | Confirmado |
|
|
38
|
+
| devDependencies | `@seedgrid/fe-components` e `@seedgrid/fe-core` (`workspace:*`), `next 15.0.7`, `react 19.0.0`, `@types/react ^19` | Confirmado |
|
|
39
|
+
| Licença | MIT (declarada no README; não há campo `license` no `package.json`) | Confirmado |
|
|
40
|
+
|
|
41
|
+
Observação: `next` e `react` são opcionais no peer, mas `./client` importa `react`/`next/navigation` e `./server` importa `next/headers`/`next/server`; só `.` e `./paths` funcionam sem eles. **Inferência** (pelos imports).
|
|
42
|
+
|
|
43
|
+
### Campo `exports`
|
|
44
|
+
|
|
45
|
+
| Subpath | types | default | Natureza |
|
|
46
|
+
|---|---|---|---|
|
|
47
|
+
| `.` | `./dist/index.d.ts` | `./dist/index.js` | client-safe (sem `next/*`) |
|
|
48
|
+
| `./server` | `./dist/server/index.d.ts` | `./dist/server/index.js` | SERVER-ONLY (`next/headers`, `next/server`) |
|
|
49
|
+
| `./client` | `./dist/client/index.d.ts` | `./dist/client/index.js` | client (`"use client"`, React, `next/navigation`) |
|
|
50
|
+
| `./paths` | `./dist/paths.d.ts` | `./dist/paths.js` | standalone, só `SecurityPaths` |
|
|
51
|
+
|
|
52
|
+
**Confirmado** (`PKG/package.json → exports`; comentários em `PKG/src/index.ts`, `PKG/src/server/index.ts`, `PKG/src/client/index.ts`).
|
|
53
|
+
|
|
54
|
+
`dist/module.js` / `dist/module.json` são gerados mas **não** estão no mapa `exports` (o CLI lê o arquivo diretamente). **Confirmado**.
|
|
55
|
+
|
|
56
|
+
### Build e scripts
|
|
57
|
+
|
|
58
|
+
| Script | Comando |
|
|
59
|
+
|---|---|
|
|
60
|
+
| `build` | `tsc -p tsconfig.json` (`rootDir: src`, `outDir: dist`, `declaration`, `declarationMap`; estende `../../../tsconfig.base.json`) |
|
|
61
|
+
| `postbuild` | `node scripts/emit-module-manifest.mjs` — importa `dist/module.js` e grava `dist/module.json` |
|
|
62
|
+
| `typecheck` | `tsc -p tsconfig.json --noEmit` |
|
|
63
|
+
| `test` | `pnpm run build && node --test tests/paths.test.mjs tests/module-manifest.test.mjs tests/permissions.test.mjs` |
|
|
64
|
+
|
|
65
|
+
**Confirmado** (`PKG/package.json`, `PKG/tsconfig.json`, `PKG/scripts/emit-module-manifest.mjs`). O `tsconfig` inclui só `src`; o `scaffold/` não é compilado pelo pacote.
|
|
66
|
+
|
|
67
|
+
## Exports públicos por subpath
|
|
68
|
+
|
|
69
|
+
Contagem (Confirmado, lendo os barrels): **`.` = 32**, **`./client` = 6**, **`./server` = 10** (2 deles são re-export de tipos de `.`), **`./paths` = 1**.
|
|
70
|
+
|
|
71
|
+
### `.` (client-safe) — `PKG/src/index.ts`
|
|
72
|
+
|
|
73
|
+
| Export | Tipo | Subpath | Descrição | Fonte |
|
|
74
|
+
|---|---|---|---|---|
|
|
75
|
+
| `SecurityPaths` | const + type | `.`, `./paths` | Paths REST da extension security (auth, twoFactor, users, roles, permissions, me, companies, selfEnter); builders aplicam `encodeURIComponent` | `PKG/src/paths.ts → SecurityPaths` |
|
|
76
|
+
| `SecuritySessionCookieNames` | interface | `.` | Nomes dos cookies `token`, `refresh`, `passwordChangeRequired` | `PKG/src/config.ts` |
|
|
77
|
+
| `SecurityServerConfig` | interface | `.` | Config do motor de sessão (ver Configuração) | `PKG/src/config.ts` |
|
|
78
|
+
| `SecurityLoginResponse` | type (união) | `.` | Resposta de login: `status:"OK"` (token…), `status:"2F_REQUIRED"` (tempToken), genérica | `PKG/src/session-contract.ts` |
|
|
79
|
+
| `SecurityResend2FAResponse` | type | `.` | Resposta de reenvio 2FA | idem |
|
|
80
|
+
| `MePermissions` | interface | `.` | `{ userPublicId, name, roles[], permissions[] }` (GET `/me/permissions`) | idem |
|
|
81
|
+
| `isLoginSuccess` | função | `.` | Type guard de login `OK` com `token` string | idem |
|
|
82
|
+
| `ProblemDetail` | interface | `.` | Problem Details RFC 7807 serializável (`status`, `title`, `detail`, `violations`) | `PKG/src/session-result.ts` |
|
|
83
|
+
| `ActionResult<T>` | type | `.` | `{ok:true,data}` \| `{ok:false,problem}` para Server Actions | idem |
|
|
84
|
+
| `readProblemMessage` | função | `.` | Mensagem exibível: `detail` → 1ª violation → `title` → `Erro {status}` | idem |
|
|
85
|
+
| `SecurityFetchOptions` | type | `.`, `./server` | `RequestInit` com `headers?: HeadersInit` | `PKG/src/server-contract.ts` |
|
|
86
|
+
| `SecurityServer` | interface | `.`, `./server` | Contrato do motor: `fetchWithSession`, `apiFetchSecurity`, `apiFetchServer`, `buildHeaders`, `applySessionCookies`, `clearAuthCookies`, `isInvalidSessionResponse` | idem |
|
|
87
|
+
| `PaginatedResult<T>` | interface | `.` | Página do backend (`items`, `totalRecords`, `page`, `size`, `sortField`, `sortOrder`, `query`) | `PKG/src/dtos.ts` |
|
|
88
|
+
| `PermissionOption` | interface | `.` | `{publicId,name,description}` | idem |
|
|
89
|
+
| `RoleSummary` | interface | `.` | `{publicId,name}` | idem |
|
|
90
|
+
| `RoleEntry` | interface | `.` | Role completa com `permissions` e `forIntegration` | idem |
|
|
91
|
+
| `UserEntry` | interface | `.` | Usuário (root, 2FA, emailConfirmed, roles…) | idem |
|
|
92
|
+
| `TwoFactorMethod` | type | `.` | `"TOTP" \| "EMAIL" \| "WHATSAPP"` | idem |
|
|
93
|
+
| `TwoFactorStatus` | interface | `.` | Status 2FA do usuário | idem |
|
|
94
|
+
| `TwoFactorEnableResponse` | interface | `.` | Resposta de enable/confirm (qrCode, secret, backupCodes, metadata) | idem |
|
|
95
|
+
| `PickListOption` | interface | `.` | Opção para `PickListField` | idem |
|
|
96
|
+
| `NavItem` | interface | `.` | Item de menu com `permission?` | `PKG/src/menu.ts` |
|
|
97
|
+
| `resolveNavHref` | função | `.` | Href do 1º filho ou do próprio item | idem |
|
|
98
|
+
| `canShowItem` | função | `.` | Regra de visibilidade (grupo, `/` público, `permission`, senão `adminRole`) | idem |
|
|
99
|
+
| `filterNavItems` | função | `.` | Filtra a árvore recursivamente, dropa grupos vazios | idem |
|
|
100
|
+
| `normalizePermission` | função | `.` | `.`/espaço/`-` → `_`, upper case | `PKG/src/permissions.ts` |
|
|
101
|
+
| `createPermissionSet` | função | `.` | `Set` normalizado | idem |
|
|
102
|
+
| `hasPermission` | função | `.` | Checa permissão normalizada | idem |
|
|
103
|
+
| `hasAnyPermission` | função | `.` | Alguma das exigidas | idem |
|
|
104
|
+
| `hasAllPermissions` | função | `.` | Todas as exigidas | idem |
|
|
105
|
+
| `buildCrudPermissions` | função | `.` | `RES` → `{read,create,update,delete}` = `RES_READ`… (remove sufixo CRUD se vier) | idem |
|
|
106
|
+
| `securityMessages` | const | `.` | Bundle i18n: `en`, `es`, `fr`, `pt-BR`, `pt-PT` (locales parciais fazem merge sobre `en`; `pt-PT` sobre `en`+`pt-BR`) | `PKG/src/messages.ts` |
|
|
107
|
+
|
|
108
|
+
### `./client` — `PKG/src/client/index.ts`
|
|
109
|
+
|
|
110
|
+
| Export | Tipo | Subpath | Descrição | Fonte |
|
|
111
|
+
|---|---|---|---|---|
|
|
112
|
+
| `PermissionProvider` | componente React | `./client` | Contexto de permissões; faz `fetch(meUrl, {cache:"no-store"})` a cada mudança de `pathname`; `adminRole` implica todas as permissões | `PKG/src/client/permission-provider.tsx` |
|
|
113
|
+
| `usePermissions` | hook | `./client` | Lê `{loading, me, hasRole, hasPermission}` | idem |
|
|
114
|
+
| `PermissionContextValue` | type | `./client` | Valor do contexto | idem |
|
|
115
|
+
| `PermissionProviderProps` | type | `./client` | `children`, `meUrl?`, `adminRole?` | idem |
|
|
116
|
+
| `StatusBadge` | componente | `./client` | `SgBadge` success/neutral a partir de `active` | `PKG/src/client/status-badge.tsx` |
|
|
117
|
+
| `PickListField` | componente | `./client` | Wrapper de `SgPickList` (source/target com filtro, `readOnly`) | `PKG/src/client/pick-list-field.tsx` |
|
|
118
|
+
|
|
119
|
+
### `./server` — `PKG/src/server/index.ts`
|
|
120
|
+
|
|
121
|
+
| Export | Tipo | Subpath | Descrição | Fonte |
|
|
122
|
+
|---|---|---|---|---|
|
|
123
|
+
| `createSecurityServer` | função (factory) | `./server` | Cria o motor de sessão a partir de `SecurityServerConfig` | `PKG/src/server/create-security-server.ts` |
|
|
124
|
+
| `SecurityServer`, `SecurityFetchOptions` | type (re-export) | `./server` | Ver `.` | `PKG/src/server-contract.ts` |
|
|
125
|
+
| `ApiRequestError` | classe | `./server` | Erro com corpo cru (`status`, `body`) — usado por `apiFetchServer` | `PKG/src/server/errors.ts` |
|
|
126
|
+
| `ApiConnectionError` | classe | `./server` | Falha de rede (`path`, `cause`) | idem |
|
|
127
|
+
| `isApiConnectionError` | função | `./server` | Type guard | idem |
|
|
128
|
+
| `problemResponse` | função | `./server` | `ApiClientError` → `NextResponse` `application/problem+json` com status upstream; outros erros → 502 | `PKG/src/server/problem-response.ts` |
|
|
129
|
+
| `toProblem` | função | `./server` | Erro → `ProblemDetail` serializável (502 para erro de rede) | `PKG/src/server/to-problem.ts` |
|
|
130
|
+
| `toActionResult` | função | `./server` | Envolve Server Action em `ActionResult` (nunca lança) | `PKG/src/server/action.ts` |
|
|
131
|
+
| `toRouteResponse` | função | `./server` | Envolve route handler: sucesso → JSON (ou 204 se `null`/`undefined`), erro → `problemResponse` | `PKG/src/server/route.ts` |
|
|
132
|
+
|
|
133
|
+
### `./paths`
|
|
134
|
+
|
|
135
|
+
`SecurityPaths` (mesmo objeto de `.`). **Confirmado** (`PKG/src/paths.ts`).
|
|
136
|
+
|
|
137
|
+
### Comportamento do motor `createSecurityServer` (Confirmado — `PKG/src/server/create-security-server.ts`)
|
|
138
|
+
|
|
139
|
+
- `buildHeaders`: `Authorization: Bearer <cookie token>`; se não houver cookie e houver `serviceToken`, usa `Bearer <serviceToken>`; mescla `resolveTenancyHeaders()` e headers da chamada.
|
|
140
|
+
- `safeFetch`: `fetch(apiBaseUrl + path)` com `Content-Type: application/json`, `cache: "no-store"`; erro de rede → `ApiConnectionError`.
|
|
141
|
+
- `fetchWithSession`: em 401 chama `tryRefreshSession` (POST `SecurityPaths.auth.refresh` com `{refreshToken}` do cookie) e repete uma vez; refresh falho limpa cookies.
|
|
142
|
+
- `applySessionCookies`: grava `token`, `refresh` (se vier) e `passwordChangeRequired="1"` (ou apaga), com `httpOnly`, `path:"/"`, `sameSite:"lax"`, `secure` — **sem `maxAge`** (cookie de sessão).
|
|
143
|
+
- `isInvalidSessionResponse`: só 401 (ou corpo contendo "usuario nao encontrado"/"usuário não encontrado") invalida sessão; **403 não desloga**.
|
|
144
|
+
- `apiFetchSecurity` lança `ApiClientError` (de `@seedgrid/fe-core`) com corpo parseado; 204 → `null`. `apiFetchServer` lança `ApiRequestError` (retrocompat).
|
|
145
|
+
- Não há dedup/single-flight de refresh no motor da lib (cada chamada que recebe 401 faz seu refresh). **Confirmado** (ausência no código); o dedup existe só no scaffold (`session-routes.ts.hbs → pendingRefreshResponses`).
|
|
146
|
+
|
|
147
|
+
## Registro no @seedgrid/fe-core (manifesto CLI)
|
|
148
|
+
|
|
149
|
+
Não há registro em runtime: o "registro" é um **manifesto estático** tipado por `SeedGridCliModuleManifest` (de `@seedgrid/fe-core`), serializado para `dist/module.json` no `postbuild` e lido pelo SeedGrid CLI (Rust). **Confirmado** (`PKG/src/module.ts → module`; `front/seedgrid-fe-components/packages/seedgrid-fe-core/src/cli-module-manifest.ts → SeedGridCliModuleManifest`). O próprio fe-core avisa que `SeedGridModuleManifest` (de `./module`) é um rascunho de registry runtime não usado. Ver [[SeedGrid/SeedGrid-components/pacotes/fe-core|@seedgrid/fe-core]].
|
|
150
|
+
|
|
151
|
+
| Campo | Valor | Observação |
|
|
152
|
+
|---|---|---|
|
|
153
|
+
| `id` | `security` | |
|
|
154
|
+
| `configKey` | `security` | |
|
|
155
|
+
| `requires` | — (ausente) | É a raiz das dependências |
|
|
156
|
+
| `provider` | `[{ import: "AuthProvider", from: "@/modules/security" }]` | Alias do app (scaffold), não import npm |
|
|
157
|
+
| `navigation` | `{ import: "useSecurityAppShellSections", from: "@/modules/security" }` | Hook do scaffold que monta o menu |
|
|
158
|
+
| `messages` | `{ import: "securityMessages", from: "@seedgrid/fe-security" }` | |
|
|
159
|
+
| `postAuthResolver` | — | Ponto de extensão consumido por outros módulos (marcadores em `scaffold/src/modules/security/navigation.ts`) |
|
|
160
|
+
|
|
161
|
+
**Rotas/paths no manifesto:** 0 — o tipo `SeedGridCliModuleManifest` não tem campos de rotas, menu ou permissões. Rotas vêm do scaffold copiado (19 páginas + 6 route handlers, abaixo); menu vem de `useSecurityAppShellSections`. **Confirmado**.
|
|
162
|
+
|
|
163
|
+
Ponto de extensão `postAuthResolver`: `scaffold/src/modules/security/navigation.ts → resolvePostAuthPath` percorre resolvers inseridos pelo CLI entre os marcadores `seedgrid:post-auth-resolvers-*`; resolver que lança é ignorado; fallback `securityConfig.routes.dashboard`. **Confirmado**.
|
|
164
|
+
|
|
165
|
+
## Rotas e páginas (scaffold)
|
|
166
|
+
|
|
167
|
+
Páginas Next (App Router) em `PKG/scaffold/src/app/` — **Confirmado** (listagem de arquivos):
|
|
168
|
+
|
|
169
|
+
| Rota | Arquivo | Guarda / permissão |
|
|
170
|
+
|---|---|---|
|
|
171
|
+
| `/` | `app/page.tsx` (`SecurityDashboard`) | `RouteGuard` (autenticado) |
|
|
172
|
+
| `/login` | `app/login/page.tsx` | redireciona para `securityConfig.routes.login` |
|
|
173
|
+
| `/auth/login` | `app/auth/login/page.tsx` | pública |
|
|
174
|
+
| `/auth/2fa/verify` | `app/auth/2fa/verify/page.tsx` | pública |
|
|
175
|
+
| `/auth/forgot-password` (+ `/confirm`, `/success`) | `app/auth/forgot-password/**` | pública |
|
|
176
|
+
| `/auth/welcome` | `app/auth/welcome/page.tsx` | pública (confirma e-mail) |
|
|
177
|
+
| `/security/users` | `app/security/users/(list)/page.tsx` | `USER_READ` |
|
|
178
|
+
| `/security/users/new` | `app/security/users/(create)/new/page.tsx` | `USER_CREATE` |
|
|
179
|
+
| `/security/users/[publicId]` | `app/security/users/(edit)/[publicId]/page.tsx` | `USER_READ` |
|
|
180
|
+
| `/security/roles`, `/new`, `/[publicId]` | `app/security/roles/**` | `ROLE_READ` / `ROLE_CREATE` / `ROLE_READ` |
|
|
181
|
+
| `/security/companies`, `/new`, `/[publicId]` | `app/security/companies/**` | `COMPANY_READ` / `COMPANY_CREATE` / `COMPANY_READ` (+ `CompanyManagementGuard`) |
|
|
182
|
+
| `/security/profile` | `app/security/profile/page.tsx` | `RouteGuard`; edição usa `USER_UPDATE` |
|
|
183
|
+
| `/security/2fa` | `app/security/2fa/page.tsx` | `RouteGuard` |
|
|
184
|
+
| `/users/change-password` | `app/users/change-password/page.tsx` | autenticado (o `RouteGuard` força esta rota quando `changePasswordRequired`) |
|
|
185
|
+
|
|
186
|
+
Route handlers (proxy BFF) — **Confirmado**:
|
|
187
|
+
|
|
188
|
+
| Método + rota Next | Handler | Encaminha para backend |
|
|
189
|
+
|---|---|---|
|
|
190
|
+
| `POST /api/security/session/login` | `createLoginRouteResponse` | `POST /public/auth/login` |
|
|
191
|
+
| `POST /api/security/session/2fa/verify` | `createVerifyTwoFactorRouteResponse` | `POST /public/2f/verify` |
|
|
192
|
+
| `POST /api/security/session/2fa/resend` | `createResendTwoFactorRouteResponse` | `POST /public/2f/resend` |
|
|
193
|
+
| `POST /api/security/session/refresh` | `createRefreshRouteResponse` (dedup por refresh token) | `POST /public/auth/refresh` |
|
|
194
|
+
| `POST /api/security/session/logout` | `createLogoutRouteResponse` | — (só limpa cookies) |
|
|
195
|
+
| `GET /api/security/users/[publicId]/avatar` | `createUserAvatarRouteResponse` (usa `getSecuritySessionServer().fetchWithSession`) | `GET /users/{publicId}/avatar[?v=]` |
|
|
196
|
+
|
|
197
|
+
`securityConfig.routes` também aponta para `/security/api-keys`, `/auth/self-enter`, `/self-enter/requests/to-approve` e `/self-enter/invitations`, cujas páginas **não** estão neste scaffold — vêm de `fe-apikeys` (`scaffold/src/app/security/`) e `fe-self-enter` (`scaffold/src/app/auth/self-enter`, `scaffold/src/app/self-enter/**`). **Confirmado** (listagem dos scaffolds vizinhos).
|
|
198
|
+
|
|
199
|
+
## APIs backend chamadas
|
|
200
|
+
|
|
201
|
+
Paths relativos a `apiBaseUrl` (no client o scaffold usa `"/api"` e depende de um proxy `/api/[[...path]]` do app base, que **não** está neste pacote — **Inferência** pelo comentário em `scaffold/src/modules/security/config.ts → resolveApiBaseUrl`). O scaffold usa strings literais, **não** `SecurityPaths`. Total: **47** pares método+path distintos (Confirmado, contagem manual em `scaffold/src/modules/security/services/*.ts`, `server/*.hbs`/`.ts` e na lib).
|
|
202
|
+
|
|
203
|
+
| Grupo | Método + path | Origem |
|
|
204
|
+
|---|---|---|
|
|
205
|
+
| Sessão (server) | `POST /public/auth/login`, `POST /public/2f/verify`, `POST /public/2f/resend`, `POST /public/auth/refresh` | `scaffold/.../server/session-routes.ts.hbs`; refresh também em `PKG/src/server/create-security-server.ts → tryRefreshSession` |
|
|
206
|
+
| Auth (client) | `POST /public/auth/forgot-password`, `GET /public/auth/reset-password?token=`, `GET /public/auth/confirm-email?token=`, `GET /me/permissions` | `scaffold/.../services/auth-service.ts → authService` |
|
|
207
|
+
| Users | `GET /users` (paginado; query `search`/`name`/`email`), `GET /users/{publicId}`, `POST /users`, `PATCH /users/{publicId}`, `DELETE /users/{publicId}`, `GET /users/{publicId}/avatar`, `POST /users/{publicId}/avatar` (body `{filename, contentType, base64}`), `PUT /users/change-password` | `scaffold/.../services/security-service.ts → securityService`; avatar GET também em `server/avatar-routes.ts` |
|
|
208
|
+
| Roles / permissões | `GET /roles` (paginado e lista), `GET /roles/{publicId}`, `POST /roles`, `PATCH /roles/{publicId}`, `DELETE /roles/{publicId}`, `GET /roles/integration`, `GET /permissions` | idem |
|
|
209
|
+
| Companies | `GET /companies`, `GET /companies/{publicId}`, `POST /companies`, `PATCH /companies/{publicId}`, `DELETE /companies/{publicId}` | idem |
|
|
210
|
+
| 2FA | `GET /2f/status`, `POST /2f/enable`, `POST /2f/totp/confirm`, `POST /2f/disable` | idem |
|
|
211
|
+
| Self-enter | `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`, `POST /self-enter/invitations`, `GET /self-enter/invitations`, `POST /self-enter/invitations/{id}/resend`, `GET /self-enter/requests/to-approve`, `POST /self-enter/requests/{id}/approve`, `POST /self-enter/requests/{id}/reject` | idem |
|
|
212
|
+
| API keys | `GET /apikeys`, `GET /apikeys/role/{roleName}`, `POST /apikeys/role/{roleName}`, `POST /apikeys/{publicId}/revoke` | idem (endpoints da extension apikeys) |
|
|
213
|
+
|
|
214
|
+
A correspondência 1:1 de `SecurityPaths` com `RestControllerPath.java` é afirmada no README/comentário, mas **não confirmada** nesta nota (ver [[SeedGrid/Extensions/security/Visao-geral|Extension security (backend)]]).
|
|
215
|
+
|
|
216
|
+
## Permissões e roles
|
|
217
|
+
|
|
218
|
+
| Permissão | Onde é usada | Certeza |
|
|
219
|
+
|---|---|---|
|
|
220
|
+
| `USER_READ`, `USER_CREATE`, `USER_UPDATE`, `USER_DELETE` | `RouteGuard` das páginas de users, `useCrudPermission("USER")`, menu, profile (`USER_UPDATE`) | Confirmado |
|
|
221
|
+
| `ROLE_READ`, `ROLE_CREATE`, `ROLE_UPDATE`, `ROLE_DELETE` | páginas de roles, `useCrudPermission("ROLE")`, menu | Confirmado |
|
|
222
|
+
| `COMPANY_READ`, `COMPANY_CREATE`, `COMPANY_UPDATE`, `COMPANY_DELETE` | páginas de companies, menu (só se `isCompanyManagementEnabledForHostKind` ≠ `master`) | Confirmado |
|
|
223
|
+
| `APIKEY_READ`, `APIKEY_CREATE`, `APIKEY_REVOKE` | menu e dashboard, só se o template tiver `security_api_keys_enabled` | Confirmado |
|
|
224
|
+
| `SELFENTER_APPROVE`, `SELFENTER_REJECT`, `SELFENTER_INVITE` | menu, só se o template tiver `security_self_enter_enabled` | Confirmado |
|
|
225
|
+
| Role `ADMIN` | default de `adminRole` em `PermissionProvider` (implica todas) e em `canShowItem`/`filterNavItems` (itens sem `permission`) | Confirmado |
|
|
226
|
+
|
|
227
|
+
Menu (`scaffold/src/modules/security/useSecurityAppShellSections.tsx.hbs`): seção `application` → grupo `access-management` (`users` ordem 10, `companies` 20, `roles` 30, `api-keys` 40) e, com self-enter, grupo `self-enter` (`self-enter-approval` 50, `self-enter-invitations` 60). Itens só-leitura recebem badge `security.common.readonly`. **Confirmado**.
|
|
228
|
+
|
|
229
|
+
`hasPermission` da lib normaliza (`user.read` = `USER_READ`); o `PermissionProvider` compara **sem** normalizar (`permissions.has(permission)`). **Confirmado** — diferença sutil de semântica.
|
|
230
|
+
|
|
231
|
+
## Separação client/server
|
|
232
|
+
|
|
233
|
+
| Camada | Pode importar `next/headers`? | Conteúdo |
|
|
234
|
+
|---|---|---|
|
|
235
|
+
| `@seedgrid/fe-security` (`.`) | Não | Tipos, paths, helpers puros, mensagens |
|
|
236
|
+
| `@seedgrid/fe-security/paths` | Não | `SecurityPaths` |
|
|
237
|
+
| `@seedgrid/fe-security/client` | Não (`"use client"`) | Provider/hook/componentes |
|
|
238
|
+
| `@seedgrid/fe-security/server` | Sim (SERVER-ONLY) | Motor de sessão e helpers de rota/action |
|
|
239
|
+
| Scaffold `server/*` | Sim | `session-routes`, `session-server` (`"use server"`), `avatar-routes`, `public-api-base-url` (`"use server"`) |
|
|
240
|
+
|
|
241
|
+
`SecurityServer` (tipo) mora em `.` para que outros pacotes (ex.: `fe-login-tenancy`) o importem sem puxar `next/headers`. **Confirmado** (`PKG/src/server-contract.ts`, comentário).
|
|
242
|
+
|
|
243
|
+
No scaffold há **dois caminhos de sessão**: (1) estabelecimento (`session-routes.ts.hbs`, grava cookies `access`/`refresh` com `maxAge`, refresh com dedup via `Map`) e (2) consumo autenticado (`session-server.ts.hbs → getSecuritySessionServer()` → `createSecurityServer`). Mantidos separados de propósito. **Confirmado** (`PKG/scaffold/README.md`).
|
|
244
|
+
|
|
245
|
+
## Configuração
|
|
246
|
+
|
|
247
|
+
A **lib não lê `process.env`**, exceto `NODE_ENV` como default de `secureCookies`. Toda env é lida pelo **scaffold** (código do app). **Confirmado** (`PKG/src/config.ts`, comentário; grep `process.env` em `PKG/src` → só `create-security-server.ts`).
|
|
248
|
+
|
|
249
|
+
Legenda de Fase: **build (NEXT_PUBLIC inline)** = Next substitui o valor no bundle no build; **runtime server** = lido no processo Node do Next; **runtime client** = resolvido no browser; **código (factory)** = valor passado pelo app no código; **geração (CLI/.hbs)** = substituído pelo CLI ao copiar o scaffold.
|
|
250
|
+
|
|
251
|
+
### Variáveis de ambiente
|
|
252
|
+
|
|
253
|
+
| Propriedade | Tipo | Valores aceitos | Padrão | Obrigatória | Comportamento | Uso | Relações | Fase | Origem |
|
|
254
|
+
|---|---|---|---|---|---|---|---|---|---|
|
|
255
|
+
| `NEXT_PUBLIC_SECURITY_SELF_ENTER_ENABLED` | string → boolean | `"true"` (case-insensitive, com trim) habilita; qualquer outro valor = `false` | `false` (ausente) | Não | Define `securityConfig.features.selfEnterEnabled` | Flag de self-enter no client (o menu de self-enter, porém, é decidido pelo template `security_self_enter_enabled`) | `security_self_enter_enabled` (template); módulo `fe-self-enter` | build (NEXT_PUBLIC inline) | `PKG/scaffold/src/modules/security/config.ts → resolveBooleanFlag`; consumo em `seedgrid-fe-self-enter/scaffold/src/app/auth/self-enter/page.tsx` |
|
|
256
|
+
| `SEEDGRID_SECURITY_ACCESS_COOKIE_NAME` | string | nome de cookie | `sg_{{project_slug}}_access_token` | Não | Nome do cookie httpOnly do access token (trim; vazio cai no padrão) | Login/refresh/logout e motor de sessão | Deve ser igual nos dois arquivos que a leem | runtime server | `PKG/scaffold/src/modules/security/server/session-routes.ts.hbs → ACCESS_COOKIE_NAME`; `.../server/session-server.ts.hbs → ACCESS_COOKIE_NAME` |
|
|
257
|
+
| `SEEDGRID_SECURITY_REFRESH_COOKIE_NAME` | string | nome de cookie | `sg_{{project_slug}}_refresh_token` | Não | Nome do cookie httpOnly do refresh token | idem | idem | runtime server | idem `REFRESH_COOKIE_NAME` |
|
|
258
|
+
| `SEEDGRID_SECURITY_REFRESH_COOKIE_MAX_AGE_SECONDS` | string → inteiro | inteiro > 0 | `2592000` (30 dias) | Não | `maxAge` do cookie de refresh; inválido/≤0 cai no padrão | `setRefreshTokenCookie` | Só no caminho `session-routes` (o motor da lib não usa `maxAge`) | runtime server | `.../session-routes.ts.hbs → resolveRefreshCookieMaxAge` |
|
|
259
|
+
| `NODE_ENV` | string | `production` / outros | — | Não | `secure` dos cookies = `NODE_ENV === "production"` | cookies do scaffold; default de `secureCookies` na lib | `SecurityServerConfig.secureCookies` sobrepõe na lib | runtime server (Inferência: o Next pode inlinear `NODE_ENV` no build) | `PKG/src/server/create-security-server.ts → createSecurityServer`; `.../session-routes.ts.hbs` |
|
|
260
|
+
|
|
261
|
+
Variáveis do app base consumidas indiretamente (via `@/config/environment`, fora deste pacote): `appEnvironment.hosts.apiOrigin`, `appEnvironment.hosts.masterAppHost`, `appEnvironment.persistence.scope`, `resolveApiBaseUrlForHostname(hostname)`. As envs que os alimentam **não estão neste repositório** — **Não confirmado**.
|
|
262
|
+
|
|
263
|
+
### `SecurityServerConfig` (lib — `createSecurityServer`)
|
|
264
|
+
|
|
265
|
+
| Propriedade | Tipo | Valores aceitos | Padrão | Obrigatória | Comportamento | Uso | Relações | Fase | Origem |
|
|
266
|
+
|---|---|---|---|---|---|---|---|---|---|
|
|
267
|
+
| `apiBaseUrl` | `string` | URL base do report-api, sem barra final (é concatenada com o path) | — | Sim | Prefixo de todas as chamadas | `safeFetch`, `tryRefreshSession` | No scaffold vem de `resolvePublicApiBaseUrl()` (por hostname) | código (factory), resolvido em runtime server | `PKG/src/config.ts → SecurityServerConfig`; `PKG/src/server/create-security-server.ts` |
|
|
268
|
+
| `cookies.token` | `string` | nome de cookie | — | Sim | Lê o access token → `Authorization: Bearer` | `buildHeaders`, `applySessionCookies`, `clearAuthCookies` | `SEEDGRID_SECURITY_ACCESS_COOKIE_NAME` no scaffold | código (factory) | `PKG/src/config.ts → SecuritySessionCookieNames` |
|
|
269
|
+
| `cookies.refresh` | `string` | nome de cookie | — | Sim | Refresh token usado em 401 | `tryRefreshSession` | `SEEDGRID_SECURITY_REFRESH_COOKIE_NAME` | código (factory) | idem |
|
|
270
|
+
| `cookies.passwordChangeRequired` | `string` | nome de cookie | — | Sim | Cookie `"1"` quando login exige troca de senha | `applySessionCookies`, `clearAuthCookies` | Scaffold fixa `sg_{{project_slug}}_password_change_required` (sem env) | código (factory) | idem; `.../session-server.ts.hbs` |
|
|
271
|
+
| `secureCookies` | `boolean` | `true`/`false` | `process.env.NODE_ENV === "production"` | Não | Flag `secure` dos cookies gravados | `applySessionCookies` | `NODE_ENV` | código (factory) / runtime server | `PKG/src/server/create-security-server.ts` |
|
|
272
|
+
| `serviceToken` 🔒 | `string` | `<SEGREDO:report-api-service-token>` | — | Não | `Bearer` usado **apenas** sem cookie de sessão | `buildHeaders` | Passado só via código na factory; o scaffold não o define | código (factory) | idem |
|
|
273
|
+
| `resolveTenancyHeaders` | `() => Promise<HeadersInit> \| HeadersInit` | função | — | Não | Headers extras por request (ex.: `X-Company-Id`, header de tenant) | `buildHeaders` | Plug de `fe-login-tenancy`/`fe-subdomain-tenancy` (Inferência pelo comentário) | código (factory), runtime server | `PKG/src/config.ts` |
|
|
274
|
+
|
|
275
|
+
### Props/parâmetros configuráveis da lib (client/menu)
|
|
276
|
+
|
|
277
|
+
| Propriedade | Tipo | Valores aceitos | Padrão | Obrigatória | Comportamento | Uso | Relações | Fase | Origem |
|
|
278
|
+
|---|---|---|---|---|---|---|---|---|---|
|
|
279
|
+
| `PermissionProvider.meUrl` | `string` | URL que devolve `MePermissions` | `"/api/auth/me"` | Não | Fetch a cada troca de `pathname` | `loadPermissions` | Rota `/api/auth/me` **não existe** no scaffold | runtime client | `PKG/src/client/permission-provider.tsx` |
|
|
280
|
+
| `PermissionProvider.adminRole` | `string` | nome de role | `"ADMIN"` | Não | Role que implica todas as permissões | `hasPermission` do contexto | `canShowItem.adminRole` | runtime client | idem |
|
|
281
|
+
| `canShowItem` / `filterNavItems` `adminRole` | `string` | nome de role | `"ADMIN"` | Não | Itens folha sem `permission` só aparecem para essa role | filtragem de menu | `PermissionProvider.adminRole` | runtime client | `PKG/src/menu.ts` |
|
|
282
|
+
|
|
283
|
+
### `securityConfig` (scaffold — `scaffold/src/modules/security/config.ts`)
|
|
284
|
+
|
|
285
|
+
Valores literais no código copiado para o app (editáveis no app). **Confirmado**.
|
|
286
|
+
|
|
287
|
+
| Propriedade | Tipo | Valores aceitos | Padrão | Obrigatória | Comportamento | Uso | Relações | Fase | Origem |
|
|
288
|
+
|---|---|---|---|---|---|---|---|---|---|
|
|
289
|
+
| `apiBaseUrl` | `string` | — | client: `"/api"`; server: `appEnvironment.hosts.apiOrigin` | — (calculado) | Base dos clients `createApiClient` privado/público | `services/security-api.ts` | Proxy `/api/[[...path]]` do app base (Inferência) | runtime client / runtime server (avaliado no import) | `config.ts → resolveApiBaseUrl` |
|
|
290
|
+
| `pagination.defaultPageSize` | number | inteiro | `10` | — | Tamanho de página padrão | listas CRUD | | código (scaffold) | `config.ts` |
|
|
291
|
+
| `pagination.pageSizeOptions` | number[] | — | `[10, 20, 50]` | — | Opções de página | listas CRUD | | código (scaffold) | `config.ts` |
|
|
292
|
+
| `search.debounceMs` | number | ms | `1000` | — | Debounce da busca | `useDebouncedSearch` (Inferência pelo README do scaffold) | | código (scaffold) | `config.ts` |
|
|
293
|
+
| `search.minLength` | number | — | `3` | — | Mínimo de caracteres da busca | listas | `security.common.search_hint` | código (scaffold) | `config.ts` |
|
|
294
|
+
| `storage.sessionKey` | string | — | `` `${appEnvironment.persistence.scope}:security:session` `` | — | Chave no `localStorage` da sessão client | `services/session-storage.ts` | `appEnvironment.persistence.scope` | runtime client | `config.ts` |
|
|
295
|
+
| `storage.pendingTwoFactorKey` | string | — | `` `${scope}:security:pending-2fa` `` | — | Chave do 2FA pendente (tempToken) | idem | idem | runtime client | `config.ts` |
|
|
296
|
+
| `features.selfEnterEnabled` | boolean | — | `false` | — | Ver `NEXT_PUBLIC_SECURITY_SELF_ENTER_ENABLED` | Bloqueia a tela pública `/auth/self-enter` do fe-self-enter quando `false` | | build (NEXT_PUBLIC inline) | `config.ts` |
|
|
297
|
+
| `routes.dashboard` | string | path | `/` | — | Destino pós-login padrão | `resolvePostAuthPath` | | código (scaffold) | `config.ts` |
|
|
298
|
+
| `routes.profile` | string | path | `/security/profile` | — | | menu/telas | | código (scaffold) | `config.ts` |
|
|
299
|
+
| `routes.login` | string | path | `/auth/login` | — | Redirect do `RouteGuard` | `RouteGuard`, `/login` | | código (scaffold) | `config.ts` |
|
|
300
|
+
| `routes.welcome` | string | path | `/auth/welcome` | — | | | | código (scaffold) | `config.ts` |
|
|
301
|
+
| `routes.forgotPassword` | string | path | `/auth/forgot-password` | — | | | | código (scaffold) | `config.ts` |
|
|
302
|
+
| `routes.forgotPasswordConfirm` | string | path | `/auth/forgot-password/confirm` | — | | | | código (scaffold) | `config.ts` |
|
|
303
|
+
| `routes.forgotPasswordSuccess` | string | path | `/auth/forgot-password/success` | — | | | | código (scaffold) | `config.ts` |
|
|
304
|
+
| `routes.verifyTwoFactor` | string | path | `/auth/2fa/verify` | — | | | | código (scaffold) | `config.ts` |
|
|
305
|
+
| `routes.users` | string | path | `/security/users` | — | | menu | | código (scaffold) | `config.ts` |
|
|
306
|
+
| `routes.companies` | string | path | `/security/companies` | — | | menu | | código (scaffold) | `config.ts` |
|
|
307
|
+
| `routes.roles` | string | path | `/security/roles` | — | | menu | | código (scaffold) | `config.ts` |
|
|
308
|
+
| `routes.twoFactor` | string | path | `/security/2fa` | — | | | | código (scaffold) | `config.ts` |
|
|
309
|
+
| `routes.apiKeys` | string | path | `/security/api-keys` | — | Página vem de `fe-apikeys` | menu | | código (scaffold) | `config.ts` |
|
|
310
|
+
| `routes.changePassword` | string | path | `/users/change-password` | — | Redirect forçado quando `changePasswordRequired` | `RouteGuard` | | código (scaffold) | `config.ts` |
|
|
311
|
+
| `routes.selfEnterPublic` | string | path | `/auth/self-enter` | — | Página vem de `fe-self-enter` | | | código (scaffold) | `config.ts` |
|
|
312
|
+
| `routes.selfEnterApproval` | string | path | `/self-enter/requests/to-approve` | — | idem | menu | | código (scaffold) | `config.ts` |
|
|
313
|
+
| `routes.selfEnterInvitations` | string | path | `/self-enter/invitations` | — | idem | menu | | código (scaffold) | `config.ts` |
|
|
314
|
+
|
|
315
|
+
### Variáveis de template (CLI)
|
|
316
|
+
|
|
317
|
+
| Propriedade | Tipo | Valores aceitos | Padrão | Obrigatória | Comportamento | Uso | Relações | Fase | Origem |
|
|
318
|
+
|---|---|---|---|---|---|---|---|---|---|
|
|
319
|
+
| `project_slug` | string | slug | não confirmado (definido pelo CLI) | Sim (para os `.hbs`) | Compõe nomes padrão de cookie | `session-routes.ts.hbs`, `session-server.ts.hbs` | `SEEDGRID_SECURITY_*_COOKIE_NAME` | geração (CLI/.hbs) | grep `{{project_slug}}` |
|
|
320
|
+
| `security_api_keys_enabled` | boolean | — | não confirmado | Não | Inclui menu/atalhos de API keys | `useSecurityAppShellSections.tsx.hbs`, `SecurityDashboard.tsx.hbs` | módulo `fe-apikeys` | geração (CLI/.hbs) | `{{#if security_api_keys_enabled}}` |
|
|
321
|
+
| `security_self_enter_enabled` | boolean | — | não confirmado | Não | Inclui menu de self-enter | idem | `NEXT_PUBLIC_SECURITY_SELF_ENTER_ENABLED`; módulo `fe-self-enter` | geração (CLI/.hbs) | `{{#if security_self_enter_enabled}}` |
|
|
322
|
+
|
|
323
|
+
Valores fixos (não configuráveis por env): `maxAge` do cookie de access no scaffold = `expiresIn` da resposta ou `900` s; cookies com `sameSite:"lax"`, `path:"/"`, `httpOnly`. **Confirmado** (`session-routes.ts.hbs → setAccessTokenCookie`).
|
|
324
|
+
|
|
325
|
+
## Exemplos de uso reais
|
|
326
|
+
|
|
327
|
+
Não há uso em `apps/showcase` (grep sem resultados). Exemplos abaixo vêm do README e de módulos consumidores do mesmo repositório.
|
|
328
|
+
|
|
329
|
+
1. Instância do motor no app gerado — `PKG/scaffold/src/modules/security/server/session-server.ts.hbs`:
|
|
330
|
+
|
|
331
|
+
```ts
|
|
332
|
+
import { createSecurityServer } from "@seedgrid/fe-security/server";
|
|
333
|
+
import { resolvePublicApiBaseUrl } from "./public-api-base-url";
|
|
334
|
+
|
|
335
|
+
export async function getSecuritySessionServer() {
|
|
336
|
+
return createSecurityServer({
|
|
337
|
+
apiBaseUrl: await resolvePublicApiBaseUrl(),
|
|
338
|
+
cookies: {
|
|
339
|
+
token: ACCESS_COOKIE_NAME,
|
|
340
|
+
refresh: REFRESH_COOKIE_NAME,
|
|
341
|
+
passwordChangeRequired: PASSWORD_CHANGE_REQUIRED_COOKIE_NAME,
|
|
342
|
+
},
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
2. Route handler com `toRouteResponse` — `packages/modules/seedgrid-fe-billing-user/scaffold/src/app/api/billing/me/route.ts`:
|
|
348
|
+
|
|
349
|
+
```ts
|
|
350
|
+
import { toRouteResponse } from "@seedgrid/fe-security/server";
|
|
351
|
+
import { getBillingUserServer } from "@/modules/billing-user/server";
|
|
352
|
+
|
|
353
|
+
export async function GET() {
|
|
354
|
+
return toRouteResponse(async () => {
|
|
355
|
+
const billing = await getBillingUserServer();
|
|
356
|
+
const [subscription, usage] = await Promise.all([
|
|
357
|
+
billing.getSubscription(),
|
|
358
|
+
billing.getUsageSummary(),
|
|
359
|
+
]);
|
|
360
|
+
return { subscription, usage };
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
3. Composição de outro módulo sobre `SecurityServer` — `packages/modules/seedgrid-fe-apikeys/src/server/create-apikeys-server.ts`:
|
|
366
|
+
|
|
367
|
+
```ts
|
|
368
|
+
import type { SecurityServer } from "@seedgrid/fe-security";
|
|
369
|
+
|
|
370
|
+
export function createApiKeysServer(session: SecurityServer): ApiKeysServer {
|
|
371
|
+
const P = ApiKeyPaths;
|
|
372
|
+
return {
|
|
373
|
+
createForRole: (roleName, req) =>
|
|
374
|
+
session.apiFetchSecurity<ApiKeyCreateResponse>(P.byRole(roleName), {
|
|
375
|
+
method: "POST",
|
|
376
|
+
body: JSON.stringify(req),
|
|
377
|
+
}),
|
|
378
|
+
// ...
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
4. Checagem de permissão — `PKG/README.md` (Uso rápido) e `PKG/scaffold/src/modules/security/hooks/usePermission.ts → useCrudPermission`:
|
|
384
|
+
|
|
385
|
+
```ts
|
|
386
|
+
import { hasPermission, buildCrudPermissions } from "@seedgrid/fe-security";
|
|
387
|
+
|
|
388
|
+
const USER_PERMISSIONS = buildCrudPermissions("USER"); // USER_READ, USER_CREATE, ...
|
|
389
|
+
if (hasPermission(userPermissions, USER_PERMISSIONS.read)) {
|
|
390
|
+
// renderiza a lista de usuários
|
|
391
|
+
}
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
5. Server Action — comentário de uso em `PKG/src/server/action.ts`:
|
|
395
|
+
|
|
396
|
+
```ts
|
|
397
|
+
"use server";
|
|
398
|
+
export async function updateUser(input) {
|
|
399
|
+
return toActionResult(() =>
|
|
400
|
+
security.apiFetchSecurity(SecurityPaths.users.byPublicId(input.id), {
|
|
401
|
+
method: "PUT", body: JSON.stringify(input),
|
|
402
|
+
}),
|
|
403
|
+
);
|
|
404
|
+
}
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
> Observação: o exemplo 5 usa `PUT /users/{publicId}`, mas o scaffold atualiza usuário com `PATCH` (`securityService.updateUser`). O método aceito pelo backend não foi confirmado aqui.
|
|
408
|
+
|
|
409
|
+
## Testes existentes (não executados)
|
|
410
|
+
|
|
411
|
+
| Arquivo | Runner | Cobre |
|
|
412
|
+
|---|---|---|
|
|
413
|
+
| `PKG/tests/paths.test.mjs` | `node --test` (sobre `dist/`) | Valores de `SecurityPaths` (auth, 2FA, users com encode, roles, permissions, me, companies, self-enter). Não cobre `twoFactor.status`, `me.companies` |
|
|
414
|
+
| `PKG/tests/module-manifest.test.mjs` | `node --test` (sobre `dist/module.json`) | `id`, `configKey`, `env`, `provider`, `messages` — **não** verifica `navigation` |
|
|
415
|
+
| `PKG/tests/permissions.test.mjs` | `node --test` | `normalizePermission`, `createPermissionSet`, `hasPermission`, `hasAny/AllPermissions`, `buildCrudPermissions` |
|
|
416
|
+
| `PKG/scaffold/src/modules/security/services/security-api.test.ts` | vitest (no app gerado; vitest não está nas devDeps do pacote — Inferência) | `extractApiMessage` (violations, RFC 7807, erros serializados, falha de fetch) |
|
|
417
|
+
| `PKG/scaffold/src/modules/security/services/security-service.test.ts` | vitest | `classifySelfEnterInvitationError`, `isSelfEnterInvitationEmailMismatchError`, `classifySelfEnterInvitationAdminError` |
|
|
418
|
+
|
|
419
|
+
Sem testes para `createSecurityServer`, `problemResponse`/`toProblem`, `PermissionProvider`, `menu.ts` ou as rotas de sessão (o próprio `scaffold/README.md` cita a falta de testes de runtime no login). **Confirmado**.
|
|
420
|
+
|
|
421
|
+
## Limitações
|
|
422
|
+
|
|
423
|
+
- O app base precisa fornecer `@/config/environment` (`apiOrigin`, `masterAppHost`, `persistence.scope`, `resolveApiBaseUrlForHostname`) e o proxy `/api/[[...path]]` usado pelos services do scaffold; não fazem parte deste pacote.
|
|
424
|
+
- O `session-routes` do scaffold não grava o cookie `passwordChangeRequired` (só `applySessionCookies` da lib o faria, e o scaffold não o chama no login).
|
|
425
|
+
- Cookies: `session-routes` grava refresh com `maxAge` (30 d) e access com `expiresIn`/900 s; a lib grava cookies de sessão sem `maxAge` ao renovar via `fetchWithSession`.
|
|
426
|
+
- Confira no backend os métodos HTTP aceitos (ex.: `PATCH` vs `PUT` em `/users/{publicId}`) contra `SecurityPaths`.
|
|
427
|
+
- Traduções `pt-BR`/`es`/`fr`/`pt-PT` são parciais (fallback para `en`).
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
---
|
|
2
|
+
tags: [seedgrid, front, modulo, fe-self-enter]
|
|
3
|
+
fonte: front/seedgrid-fe-components/packages/modules/seedgrid-fe-self-enter
|
|
4
|
+
branch: main
|
|
5
|
+
commit: ad30fc11de
|
|
6
|
+
analisado-em: 2026-10-14
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# @seedgrid/fe-self-enter
|
|
10
|
+
|
|
11
|
+
Módulo front de **auto-cadastro de usuário** (self-enter): pedido público de acesso (nome/e-mail/senha) com confirmação de e-mail, convites de administrador e fila de aprovação. Não confundir com o cadastro de **empresa** ([[SeedGrid/SeedGrid-components/modulos/fe-login-tenancy|fe-login-tenancy]] / [[SeedGrid/SeedGrid-components/modulos/fe-subdomain-tenancy|fe-subdomain-tenancy]]). Compõe sobre o [[SeedGrid/SeedGrid-components/modulos/fe-security|fe-security]]. Parte dos [[SeedGrid/SeedGrid-components/modulos/Visao-geral|Módulos front]].
|
|
12
|
+
|
|
13
|
+
Backend: **extension security**, não uma extension própria — [[SeedGrid/Extensions/security/Visao-geral|extension security]]. **Confirmado**: o engine usa `SecurityPaths.selfEnter` (fe-security), cujos valores batem com `RestControllerPath` de `java/seedgrid-quarkus-ext-security/runtime/src/main/java/br/com/seedgrid/security/controllers/` (`SELF_ENTER*`), atendidos por `SelfEnterController`; a feature tem config própria (`SelfEnterConfig`). Modos no backend: `disabled` / `invite-only` / `public` (segundo comentário de `src/self-enter.ts`; **Não confirmado** aqui no Java).
|
|
14
|
+
|
|
15
|
+
## Pacote
|
|
16
|
+
|
|
17
|
+
| Item | Valor |
|
|
18
|
+
|---|---|
|
|
19
|
+
| Nome npm / versão | `@seedgrid/fe-self-enter` `2026.7.0` |
|
|
20
|
+
| peerDependencies | `@seedgrid/fe-core: *`, `@seedgrid/fe-security: *` |
|
|
21
|
+
| `files` | `dist`, `scaffold` |
|
|
22
|
+
| Build | `tsc -p tsconfig.json` + `postbuild` `emit-module-manifest.mjs` |
|
|
23
|
+
| `exports` | `.` → `./dist/index.{d.ts,js}`; `./server` → `./dist/server/index.{d.ts,js}` |
|
|
24
|
+
|
|
25
|
+
Dependência de módulo: **requer `security`** — inclusive em runtime (importa o valor `SecurityPaths` de `@seedgrid/fe-security`).
|
|
26
|
+
|
|
27
|
+
## Exports públicos
|
|
28
|
+
|
|
29
|
+
| Export | Tipo | Subpath | Descrição | Fonte |
|
|
30
|
+
|---|---|---|---|---|
|
|
31
|
+
| `EntryRequestOrigin` | type | `.` | `"INVITE" \| "PUBLIC"` | `front/seedgrid-fe-components/packages/modules/seedgrid-fe-self-enter/src/self-enter.ts → EntryRequestOrigin` |
|
|
32
|
+
| `EntryRequestStatus` | type | `.` | `PENDING_EMAIL`, `PENDING_APPROVAL`, `APPROVED`, `REJECTED`, `EXPIRED` | `.../src/self-enter.ts → EntryRequestStatus` |
|
|
33
|
+
| `CreateEntryRequest` | interface | `.` | `{ name; email; password }` | `.../src/self-enter.ts` |
|
|
34
|
+
| `EntryRequestResponse` | interface | `.` | Pedido (status, aprovado/rejeitado por/quando, convite) | `.../src/self-enter.ts` |
|
|
35
|
+
| `CreateEntryInvitation` | interface | `.` | `{ email; name; roles? }` (`roles` vazio → `default-role` do backend) | `.../src/self-enter.ts` |
|
|
36
|
+
| `EntryInvitationResponse` | interface | `.` | Convite | `.../src/self-enter.ts` |
|
|
37
|
+
| `CompleteEntryInvitation` | interface | `.` | `{ name; email; password }` | `.../src/self-enter.ts` |
|
|
38
|
+
| `createSelfEnterServer` | função | `./server` | `(session) => SelfEnterServer` | `.../src/server/create-self-enter-server.ts → createSelfEnterServer` |
|
|
39
|
+
| `SelfEnterServer` | interface | `./server` | 5 métodos públicos + 6 de admin | idem |
|
|
40
|
+
|
|
41
|
+
Contagem: `.` = 7; `./server` = 2. Os paths **não** são exportados aqui (ficam em `SecurityPaths.selfEnter`).
|
|
42
|
+
|
|
43
|
+
## Registro no @seedgrid/fe-core (manifesto do CLI)
|
|
44
|
+
|
|
45
|
+
`SeedGridCliModuleManifest` ([[SeedGrid/SeedGrid-components/pacotes/fe-core|@seedgrid/fe-core]]): `id: "self-enter"`, `requires: ["security"]`, `configKey: "self-enter"`. Sem `navigation`/`messages`/`provider`: menu e atalho de dashboard vivem no scaffold do fe-security, condicionados por `{{#if security_self_enter_enabled}}` (`config.is_module_enabled("self-enter")`) — **Confirmado** pelo comentário de `src/module.ts`. As chaves i18n usadas (`security.self_enter.*`) também pertencem ao fe-security.
|
|
46
|
+
|
|
47
|
+
## Páginas (scaffold) e permissões
|
|
48
|
+
|
|
49
|
+
| Rota | Arquivo | Permissão |
|
|
50
|
+
|---|---|---|
|
|
51
|
+
| `/auth/self-enter` (público; `?token=` = modo convite) | `scaffold/src/app/auth/self-enter/page.tsx` | nenhuma; bloqueado se `securityConfig.features.selfEnterEnabled` for falso (exceto modo convite); sucesso redireciona para `securityConfig.routes.login` após 1,2 s |
|
|
52
|
+
| `/self-enter/invitations` | `scaffold/src/app/self-enter/invitations/page.tsx` | `SELFENTER_INVITE` |
|
|
53
|
+
| `/self-enter/requests/to-approve` | `scaffold/src/app/self-enter/requests/to-approve/page.tsx` | `SELFENTER_APPROVE` ou `SELFENTER_REJECT` (`permissionMode="any"`) |
|
|
54
|
+
|
|
55
|
+
As telas usam `securityService` do scaffold do fe-security (`createSelfEnterRequest`, `confirmSelfEnterRequestEmail`, `getSelfEnterInvitation`, `listSelfEnterInvitationsPage`, `approveSelfEnterRequest`…), e não `createSelfEnterServer`. Código de confirmação: 6 caracteres (`SgInputOTP`, máscara `### ###`).
|
|
56
|
+
|
|
57
|
+
## APIs backend chamadas (`createSelfEnterServer`)
|
|
58
|
+
|
|
59
|
+
| Método | Path | Função | Autenticação |
|
|
60
|
+
|---|---|---|---|
|
|
61
|
+
| POST | `/public/self-enter/requests` | `submitRequest` | pública |
|
|
62
|
+
| POST | `/public/self-enter/requests/{id}/confirm-email` | `confirmEmail` | pública |
|
|
63
|
+
| POST | `/public/self-enter/requests/{id}/resend-email` | `resendEmail` | pública |
|
|
64
|
+
| GET | `/public/self-enter/invitations/{token}` | `getInvitation` | pública |
|
|
65
|
+
| POST | `/public/self-enter/invitations/{token}/complete` | `completeInvitation` | pública |
|
|
66
|
+
| GET | `/self-enter/requests/to-approve` | `listToApprove` | sessão admin |
|
|
67
|
+
| POST | `/self-enter/requests/{id}/approve` | `approve` | sessão admin |
|
|
68
|
+
| POST | `/self-enter/requests/{id}/reject` | `reject` | sessão admin |
|
|
69
|
+
| POST | `/self-enter/invitations` | `createInvitation` | sessão admin |
|
|
70
|
+
| GET | `/self-enter/invitations` | `listInvitations` | sessão admin |
|
|
71
|
+
| POST | `/self-enter/invitations/{id}/resend` | `resendInvitation` | sessão admin |
|
|
72
|
+
|
|
73
|
+
11 endpoints.
|
|
74
|
+
|
|
75
|
+
## Separação client/server
|
|
76
|
+
|
|
77
|
+
`.` só tipos; `./server` SERVER-ONLY (sobre `SecurityServer.apiFetchSecurity`).
|
|
78
|
+
|
|
79
|
+
## Configuração
|
|
80
|
+
|
|
81
|
+
Nenhuma variável de ambiente lida pelo pacote nem pelo seu scaffold (verificado com `grep process.env`). Dependência indireta: a tela pública consulta `securityConfig.features.selfEnterEnabled`, que no scaffold do fe-security vem de `process.env.NEXT_PUBLIC_SECURITY_SELF_ENTER_ENABLED` (build, NEXT_PUBLIC inline) — documentado em [[SeedGrid/SeedGrid-components/modulos/fe-security|fe-security]].
|
|
82
|
+
|
|
83
|
+
## Exemplo (fonte: README)
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
import { createSelfEnterServer } from "@seedgrid/fe-self-enter/server";
|
|
87
|
+
const selfEnter = createSelfEnterServer(session);
|
|
88
|
+
await selfEnter.createInvitation({ name: "Maria", email: "maria@empresa.com" });
|
|
89
|
+
const pendentes = await selfEnter.listToApprove();
|
|
90
|
+
await selfEnter.approve(pendentes[0].id);
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Sem consumidor em `apps/showcase`.
|
|
94
|
+
|
|
95
|
+
## Testes (não executados)
|
|
96
|
+
|
|
97
|
+
`tests/module-manifest.test.mjs` — `id`, `requires`, `configKey`.
|
|
98
|
+
|
|
99
|
+
## Limitações
|
|
100
|
+
|
|
101
|
+
- A tela de convites não envia `CreateEntryInvitation.roles`.
|
|
102
|
+
- `SecurityPaths.selfEnter.requestById` e o endpoint `public-link` do backend (`SELF_ENTER_PUBLIC_LINK`) não são usados pelo engine.
|
|
103
|
+
- `confirmEmail`/`approve`/`reject` aceitam `body?: unknown` (corpo sem tipagem).
|
|
104
|
+
|