funifier-mcp 0.3.16 → 0.3.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/.cursor/rules/funifier.mdc +1 -0
  2. package/.github/copilot-instructions.md +1 -0
  3. package/AGENTS.md +1 -0
  4. package/datasource-funifier-docs/.coverage.json +12 -5
  5. package/datasource-funifier-docs/.search-index.json +59345 -0
  6. package/datasource-funifier-docs/.skills-map.json +145 -0
  7. package/datasource-funifier-docs/.validation.json +38 -2
  8. package/datasource-funifier-docs/knowledge/guides/permission-audit.md +229 -0
  9. package/datasource-funifier-docs/knowledge/index.md +1 -0
  10. package/dist/mcp/bundle.js +108 -108
  11. package/dist/mcp/tools/_audit.d.ts +103 -0
  12. package/dist/mcp/tools/_audit.d.ts.map +1 -0
  13. package/dist/mcp/tools/_audit.js +241 -0
  14. package/dist/mcp/tools/_audit.js.map +1 -0
  15. package/dist/mcp/tools/_audit.test.d.ts +2 -0
  16. package/dist/mcp/tools/_audit.test.d.ts.map +1 -0
  17. package/dist/mcp/tools/_audit.test.js +412 -0
  18. package/dist/mcp/tools/_audit.test.js.map +1 -0
  19. package/dist/mcp/tools/_backup.d.ts +37 -3
  20. package/dist/mcp/tools/_backup.d.ts.map +1 -1
  21. package/dist/mcp/tools/_backup.js +137 -8
  22. package/dist/mcp/tools/_backup.js.map +1 -1
  23. package/dist/mcp/tools/_backup.test.js +195 -0
  24. package/dist/mcp/tools/_backup.test.js.map +1 -1
  25. package/dist/mcp/tools/_scope-engine.d.ts +40 -0
  26. package/dist/mcp/tools/_scope-engine.d.ts.map +1 -0
  27. package/dist/mcp/tools/_scope-engine.js +197 -0
  28. package/dist/mcp/tools/_scope-engine.js.map +1 -0
  29. package/dist/mcp/tools/_scope-engine.test.d.ts +2 -0
  30. package/dist/mcp/tools/_scope-engine.test.d.ts.map +1 -0
  31. package/dist/mcp/tools/_scope-engine.test.js +241 -0
  32. package/dist/mcp/tools/_scope-engine.test.js.map +1 -0
  33. package/dist/mcp/tools/permissions.d.ts.map +1 -1
  34. package/dist/mcp/tools/permissions.js +68 -11
  35. package/dist/mcp/tools/permissions.js.map +1 -1
  36. package/dist/mcp/tools/permissions.test.js +268 -4
  37. package/dist/mcp/tools/permissions.test.js.map +1 -1
  38. package/package.json +1 -1
  39. package/skills/funifier/SKILL.md +1 -0
  40. package/skills/funifier/references/audit-permissions.md +89 -0
  41. package/skills/funifier/references/configure-security.md +0 -6
  42. package/skills/funifier/references/create-action.md +0 -7
  43. package/skills/funifier/references/create-aggregate.md +3 -7
  44. package/skills/funifier/references/create-audit.md +0 -8
  45. package/skills/funifier/references/create-challenge.md +0 -7
  46. package/skills/funifier/references/create-competition.md +0 -7
  47. package/skills/funifier/references/create-crossword.md +0 -6
  48. package/skills/funifier/references/create-custom-object.md +0 -6
  49. package/skills/funifier/references/create-custom-page.md +0 -6
  50. package/skills/funifier/references/create-folder.md +0 -7
  51. package/skills/funifier/references/create-lastmile.md +0 -6
  52. package/skills/funifier/references/create-leaderboard.md +0 -6
  53. package/skills/funifier/references/create-level.md +0 -7
  54. package/skills/funifier/references/create-lottery.md +0 -7
  55. package/skills/funifier/references/create-mystery.md +0 -6
  56. package/skills/funifier/references/create-notification.md +0 -6
  57. package/skills/funifier/references/create-point.md +0 -7
  58. package/skills/funifier/references/create-quiz.md +0 -7
  59. package/skills/funifier/references/create-scheduler.md +0 -6
  60. package/skills/funifier/references/create-story.md +0 -6
  61. package/skills/funifier/references/create-swap.md +0 -6
  62. package/skills/funifier/references/create-trigger.md +0 -8
  63. package/skills/funifier/references/create-virtual-good.md +0 -6
  64. package/skills/funifier/references/create-webhook.md +0 -6
  65. package/skills/funifier/references/create-websocket.md +0 -6
  66. package/skills/funifier/references/create-widget.md +0 -6
  67. package/skills/funifier/references/date-handling.md +0 -6
  68. package/skills/funifier/references/debug.md +0 -6
  69. package/skills/funifier/references/help.md +0 -6
  70. package/skills/funifier/references/implement-frontend.md +0 -7
  71. package/skills/funifier/references/import-csv.md +0 -6
  72. package/skills/funifier/references/manage-indexes.md +0 -6
  73. package/skills/funifier/references/manage-player.md +0 -7
  74. package/skills/funifier/references/manage-team.md +0 -6
  75. package/skills/funifier/references/upload-file.md +0 -6
@@ -0,0 +1,145 @@
1
+ {
2
+ "funifier-create-trigger": [
3
+ "knowledge/modules/trigger.md",
4
+ "knowledge/guides/triggers-guide.md",
5
+ "knowledge/guides/java-entities.md",
6
+ "knowledge/guides/java-managers.md",
7
+ "knowledge/guides/trigger-examples.md"
8
+ ],
9
+ "funifier-create-scheduler": [
10
+ "knowledge/modules/scheduler.md",
11
+ "knowledge/guides/java-managers.md",
12
+ "knowledge/guides/java-libraries.md"
13
+ ],
14
+ "funifier-create-aggregate": [
15
+ "knowledge/guides/aggregates.md",
16
+ "knowledge/guides/database-access.md",
17
+ "knowledge/modules/database.md"
18
+ ],
19
+ "funifier-date-handling": [
20
+ "knowledge/guides/database-access.md",
21
+ "knowledge/guides/aggregates.md",
22
+ "knowledge/modules/database.md"
23
+ ],
24
+ "funifier-create-challenge": [
25
+ "knowledge/modules/challenge.md",
26
+ "knowledge/modules/action.md",
27
+ "knowledge/modules/point.md"
28
+ ],
29
+ "funifier-create-action": [
30
+ "knowledge/modules/action.md",
31
+ "knowledge/modules/action-log.md"
32
+ ],
33
+ "funifier-create-audit": [
34
+ "knowledge/modules/audit.md",
35
+ "knowledge/modules/database.md"
36
+ ],
37
+ "funifier-create-point": [
38
+ "knowledge/modules/point.md",
39
+ "knowledge/modules/achievement.md"
40
+ ],
41
+ "funifier-create-level": [
42
+ "knowledge/modules/level.md",
43
+ "knowledge/modules/point.md"
44
+ ],
45
+ "funifier-create-leaderboard": [
46
+ "knowledge/modules/leaderboard.md",
47
+ "knowledge/modules/point.md",
48
+ "knowledge/modules/action.md"
49
+ ],
50
+ "funifier-create-quiz": [
51
+ "knowledge/modules/quiz.md",
52
+ "knowledge/modules/question.md"
53
+ ],
54
+ "funifier-create-virtual-good": [
55
+ "knowledge/modules/virtual-good.md",
56
+ "knowledge/modules/point.md"
57
+ ],
58
+ "funifier-create-custom-page": [
59
+ "knowledge/modules/studio-page.md",
60
+ "knowledge/guides/aggregates.md",
61
+ "knowledge/modules/auth.md"
62
+ ],
63
+ "funifier-implement-frontend": [
64
+ "knowledge/modules/auth.md",
65
+ "knowledge/guides/aggregates.md",
66
+ "knowledge/guides/database-access.md",
67
+ "knowledge/modules/patterns.md",
68
+ "knowledge/modules/action-log.md",
69
+ "knowledge/modules/static-repo.md"
70
+ ],
71
+ "funifier-debug": [
72
+ "knowledge/guides/java-libraries.md",
73
+ "knowledge/modules/trigger.md",
74
+ "knowledge/guides/triggers-guide.md",
75
+ "knowledge/guides/trigger-examples.md",
76
+ "knowledge/modules/scheduler.md",
77
+ "knowledge/guides/aggregates.md",
78
+ "knowledge/modules/public.md"
79
+ ],
80
+ "funifier-help": [
81
+ "knowledge/index.md"
82
+ ],
83
+ "funifier-manage-player": [
84
+ "knowledge/modules/player.md"
85
+ ],
86
+ "funifier-manage-team": [
87
+ "knowledge/modules/team.md"
88
+ ],
89
+ "funifier-create-competition": [
90
+ "knowledge/modules/competition.md"
91
+ ],
92
+ "funifier-create-folder": [
93
+ "knowledge/modules/folder.md"
94
+ ],
95
+ "funifier-create-lottery": [
96
+ "knowledge/modules/lottery.md"
97
+ ],
98
+ "funifier-create-mystery": [
99
+ "knowledge/modules/mystery.md"
100
+ ],
101
+ "funifier-create-story": [
102
+ "knowledge/modules/story.md"
103
+ ],
104
+ "funifier-create-crossword": [
105
+ "knowledge/modules/crossword.md"
106
+ ],
107
+ "funifier-create-notification": [
108
+ "knowledge/modules/notification.md"
109
+ ],
110
+ "funifier-create-lastmile": [
111
+ "knowledge/modules/lastmile.md"
112
+ ],
113
+ "funifier-create-webhook": [
114
+ "knowledge/modules/webhook.md"
115
+ ],
116
+ "funifier-create-websocket": [
117
+ "knowledge/modules/websocket.md"
118
+ ],
119
+ "funifier-create-widget": [
120
+ "knowledge/modules/widget.md"
121
+ ],
122
+ "funifier-create-swap": [
123
+ "knowledge/modules/swap.md"
124
+ ],
125
+ "funifier-create-custom-object": [
126
+ "knowledge/modules/custom-object.md",
127
+ "knowledge/modules/database.md"
128
+ ],
129
+ "funifier-configure-security": [
130
+ "knowledge/modules/security.md"
131
+ ],
132
+ "funifier-import-csv": [
133
+ "knowledge/modules/csv-data.md"
134
+ ],
135
+ "funifier-upload-file": [
136
+ "knowledge/modules/upload.md"
137
+ ],
138
+ "funifier-manage-indexes": [
139
+ "knowledge/modules/database.md"
140
+ ],
141
+ "funifier-audit-permissions": [
142
+ "knowledge/guides/permission-audit.md",
143
+ "knowledge/modules/security.md"
144
+ ]
145
+ }
@@ -1,6 +1,42 @@
1
1
  {
2
- "generatedAt": "2026-06-11T23:04:00Z",
2
+ "generatedAt": "2026-06-12T16:08:00Z",
3
3
  "skills": {
4
+ "funifier-audit-permissions": {
5
+ "configHash": "f0569bdb0e11e1a2c6a11f6a4ff9cfd940668c7431bee06342b29faab32510fc",
6
+ "status": "verified",
7
+ "claims": [
8
+ {
9
+ "claim": "SecurityFilter.doFilter evaluates (method, path) by computing verb (GET→read, POST/PUT→write, DELETE→delete) and entity_full (path after /v3/ with slash→underscore), then matching scope tokens in order: {verb}_all, exact {verb}_{entity_full}, fallback {verb}_{prefix}_all minus-1 and minus-2 trailing segments",
10
+ "gitnexusQuery": "SecurityFilter",
11
+ "critical": true,
12
+ "status": "verified",
13
+ "evidence": {
14
+ "symbol": "Class:src/main/java/com/funifier/rest/v3/filter/SecurityFilter.java:SecurityFilter",
15
+ "file": "src/main/java/com/funifier/rest/v3/filter/SecurityFilter.java"
16
+ }
17
+ },
18
+ {
19
+ "claim": "DatabaseRest requires the literal 'database' scope keyword on ALL /v3/database handlers including GET operations — grammar tokens such as read_all alone are insufficient; this is enforced within SecurityFilter.doFilter before requests reach DatabaseRest handlers",
20
+ "gitnexusQuery": "doFilter",
21
+ "critical": true,
22
+ "status": "verified",
23
+ "evidence": {
24
+ "symbol": "Method:src/main/java/com/funifier/rest/v3/filter/SecurityFilter.java:SecurityFilter.doFilter#3",
25
+ "file": "src/main/java/com/funifier/rest/v3/filter/SecurityFilter.java"
26
+ }
27
+ },
28
+ {
29
+ "claim": "Bearer tokens embed the player's role scope string at login time; role scope changes only affect sessions created after the change — existing live Bearer tokens carry the scope at their issuance time",
30
+ "gitnexusQuery": "SecurityFilter",
31
+ "critical": true,
32
+ "status": "verified",
33
+ "evidence": {
34
+ "symbol": "Class:src/main/java/com/funifier/rest/v3/filter/SecurityFilter.java:SecurityFilter",
35
+ "file": "src/main/java/com/funifier/rest/v3/filter/SecurityFilter.java"
36
+ }
37
+ }
38
+ ]
39
+ },
4
40
  "funifier-configure-security": {
5
41
  "configHash": "a05c3dc778b494d2d9d781787dd2231c1ae5720c3e368b41071f02df85a1a922",
6
42
  "status": "verified",
@@ -537,7 +573,7 @@
537
573
  ]
538
574
  },
539
575
  "funifier-help": {
540
- "configHash": "3880c7e32947710dcf855641e2822bc5eead0d39b8910305ec7bc2706a1196ca",
576
+ "configHash": "1da15e3fcabe8f807cab51fcfbba47686a1a4c03407b6808f5364c314f963908",
541
577
  "status": "verified",
542
578
  "claims": [
543
579
  {
@@ -0,0 +1,229 @@
1
+ # Permission Audit Guide
2
+
3
+ ## 1. Visão Geral
4
+
5
+ ### 1.1 O que é este documento
6
+
7
+ Este guia descreve como usar o `funifier_permissions action=audit` para verificar deterministicamente se os escopos salvos no documento de segurança cobrem os endpoints que o seu projeto usa — e se há escopos concedidos que nenhum endpoint requer. O motor de auditoria espelha `SecurityFilter.doFilter` de `funifier-service`; o veredicto é reproduzível e unit-testado, não dependente de raciocínio LLM.
8
+
9
+ ### 1.2 Quando consultar
10
+
11
+ - Antes de alterar escopos: saber o que cada role/app autoriza hoje.
12
+ - Após adicionar endpoints: verificar se o scope cobre as novas chamadas.
13
+ - Quando ocorrem 401 inesperados: mapear exatamente qual token está faltando.
14
+ - Ao auditar mínimo privilégio: identificar tokens excedentes que podem ser removidos.
15
+
16
+ ### 1.3 Quando NÃO consultar
17
+
18
+ - Para **alterar** escopos — use `save_security_role` / `save_api_app` (ações separadas, requerem confirmação do utilizador).
19
+ - Para **perguntas sobre Studio roles/assignments** (permissões de interface) — o audit cobre só API scopes (documento `security`).
20
+ - Para **verificar backups** — use `verify_backup`.
21
+
22
+ ### 1.4 Índice de decisão
23
+
24
+ | Problema / Situação | O que fazer | Seção |
25
+ |---|---|---|
26
+ | Saber qual auth context usar para uma chamada | Tabela de autenticação | §2 |
27
+ | Construir o manifest de chamadas do projeto | Formato do manifest + exemplo | §3 |
28
+ | Interpretar `missing` / `excess` / `danger` / `missing-principal` | Tipos de finding | §4 |
29
+ | Entender como o motor avalia `(method, path, scope)` | Gramática de escopo | §5 |
30
+ | Saber o que fazer com os findings | Regra de read-only + remediação | §6 |
31
+
32
+ ### 1.5 Restrições críticas
33
+
34
+ > ⚠️ **O audit é estritamente read-only.** Nenhuma chamada de escrita é feita; nenhum snapshot é gravado. Findings são candidatos para revisão — nunca são aplicados automaticamente.
35
+
36
+ > ⚠️ **Bearer tokens embtem o scope no momento do login.** Uma alteração de role só afeta sessões novas. Se você corrigiu o scope mas o jogador ainda recebe 401, peça-lhe que faça login novamente.
37
+
38
+ > ⚠️ **O manifest cobre um repo de cada vez.** Se a sua aplicação tem múltiplos repositórios a chamar a mesma gamificação, combine as entradas manualmente no manifest.
39
+
40
+ ---
41
+
42
+ ## 2. Tabela de Auth Context
43
+
44
+ Cada chamada API usa um mecanismo de autenticação diferente. O motor resolve qual scope se aplica com base nesse mecanismo (`SecurityFilter.java:153-211`):
45
+
46
+ | `auth` no manifest | Mecanismo HTTP | Scope usado |
47
+ |--------------------|----------------|-------------|
48
+ | `"public"` | `Basic base64(API_KEY:)` — sem secret | Scope da role `public` no documento de segurança |
49
+ | `"player"` | `Bearer <player token>` | Scope da role sob a qual o jogador fez login (normalmente `player`) — **embutido no token no momento do login** |
50
+ | `"app:<name>"` | `Basic base64(API_KEY:APP_SECRET)` | Scope da entrada `apps[]` cujo `name` é `<name>` |
51
+ | `"role:<name>"` | Qualquer Bearer com role customizada | Scope da role `<name>` no documento de segurança |
52
+
53
+ **Heurísticas de classificação por stack:**
54
+
55
+ - Chamadas sem cabeçalho `Authorization` (ou com API_KEY sem secret) → `"public"`
56
+ - Chamadas com token JWT player (`Authorization: Bearer ...`) → `"player"` (ou o nome da role customizada se o SDK permitir escolher)
57
+ - Chamadas com app_secret embutido em env var / config → `"app:<name>"` (use o `name` do entry em `apps[]`)
58
+ - Chamadas de servidor para servidor com secret fixo → `"app:<name>"`
59
+
60
+ ---
61
+
62
+ ## 3. Formato do Manifest
63
+
64
+ ### 3.1 Schema
65
+
66
+ ```json
67
+ {
68
+ "version": 1,
69
+ "entries": [
70
+ {
71
+ "method": "GET | POST | PUT | DELETE",
72
+ "path": "/v3/...",
73
+ "auth": "<auth context — ver §2>",
74
+ "evidence": "<file:line ou descrição>",
75
+ "confidence": "high | low"
76
+ }
77
+ ]
78
+ }
79
+ ```
80
+
81
+ - **`version`**: deve ser `1`.
82
+ - **`entries`**: máximo de 500 entradas. Cada entrada representa uma chamada distinta de `(method, path, auth)`.
83
+ - **`method`**: case-insensitive; normalizado para maiúsculas internamente.
84
+ - **`path`**: o prefixo `/v3` é adicionado automaticamente se ausente.
85
+ - **`auth`**: obrigatório. Sem `auth` o motor não sabe qual scope avaliar.
86
+ - **`evidence`**: obrigatório. `"src/api.ts:42"` ou `"chamada descoberta em SDK wrapper"`.
87
+ - **`confidence`**: `"high"` (default) para chamadas confirmadas por código; `"low"` para URLs dinâmicas ou inferidas.
88
+
89
+ ### 3.2 Exemplo
90
+
91
+ ```json
92
+ {
93
+ "version": 1,
94
+ "entries": [
95
+ { "method": "GET", "path": "/v3/player/me", "auth": "player", "evidence": "src/profile.ts:12", "confidence": "high" },
96
+ { "method": "POST", "path": "/v3/action/log", "auth": "player", "evidence": "src/events.ts:58", "confidence": "high" },
97
+ { "method": "GET", "path": "/v3/widget/rankings", "auth": "public", "evidence": "src/embed.html:1" },
98
+ { "method": "POST", "path": "/v3/player", "auth": "app:backend", "evidence": "workers/sync.ts:34", "confidence": "high" },
99
+ { "method": "GET", "path": "/v3/database/orders", "auth": "app:backend", "evidence": "workers/sync.ts:80", "confidence": "high" },
100
+ { "method": "GET", "path": "/v3/challenge", "auth": "player", "evidence": "src/gamification.ts:7" }
101
+ ]
102
+ }
103
+ ```
104
+
105
+ ### 3.3 Chamadas com URL dinâmica ou cliente wrapper
106
+
107
+ Quando não é possível determinar o path exato estaticamente:
108
+ - Use o prefixo mais específico que conhece (e.g. `/v3/database/orders` em vez de só `/v3/database`).
109
+ - Defina `"confidence": "low"` para sinalizar incerteza.
110
+ - **Nunca omita** uma chamada suspeita — é melhor um finding de baixa confiança do que um 401 não detectado em produção.
111
+
112
+ ---
113
+
114
+ ## 4. Tipos de Finding
115
+
116
+ | Severity | Significado | Impacto |
117
+ |----------|-------------|---------|
118
+ | `missing` | A chamada seria negada com o scope atual | Quebra funcionalidade — 401 em produção |
119
+ | `excess` | Token concedido mas nenhuma entrada do manifest o requer | Candidato a remoção (mínimo privilégio) |
120
+ | `danger` | Padrão de risco estático (independente do manifest) | Risco de segurança — revisar imediatamente |
121
+ | `manual-review` | Token não-path (`cross_domain`, `write_upload`, etc.) — não verificável por análise de caminhos | Verificar manualmente |
122
+ | `public-no-scope-needed` | Path público — scope não é verificado pelo servidor | Informativo; não entra no cálculo de missing/excess |
123
+ | `missing-principal` | Auth context referenciado no manifest não existe no documento de segurança | Entradas desse auth não foram avaliadas |
124
+
125
+ ### 4.1 Findings de `danger` estáticos
126
+
127
+ Estes são verificados independentemente do manifest:
128
+
129
+ - `write_all` / `delete_all` / `database` na role `public` → unauthenticated callers têm acesso privilegiado
130
+ - `read_encrypted_field_values` / `read_encrypted_player_password` na role `public` ou `player` → dados encriptados expostos
131
+ - App com `scope` vazio → nenhuma chamada será autorizada para esse app
132
+
133
+ ### 4.2 Narrowing para tokens broad
134
+
135
+ Quando `read_all`, `write_all` ou `delete_all` autoriza as suas entradas mas tokens exatos (`read_player`, `write_game`, etc.) cobririam o mesmo uso, o finding inclui `narrowingSuggestion` com os tokens exatos sugeridos. Verifique se há consumidores fora deste manifest antes de remover o token broad.
136
+
137
+ ---
138
+
139
+ ## 5. Gramática de Escopo (SecurityFilter.java)
140
+
141
+ O motor espelha exatamente `SecurityFilter.doFilter`. Ordem de avaliação para cada `(method, path)`:
142
+
143
+ ### 5.1 Paths públicos (sem scope)
144
+
145
+ `GET /v3/widget`, `GET /v3/global`, `GET /v3/system/global` e seus sub-paths passam sem verificação de scope (`SecurityFilter.java:108-151`). Entradas que acertam estes paths são classificadas `public-no-scope-needed`.
146
+
147
+ ### 5.2 Contexto de autenticação → scope
148
+
149
+ O scope avaliado depende do mecanismo de auth (ver §2). Studio/Account tokens não passam pela gramática de scope — estão fora do escopo do audit.
150
+
151
+ ### 5.3 Exceções especiais de POST
152
+
153
+ Verificadas antes da gramática (`SecurityFilter.java:259-263`):
154
+
155
+ - `POST /v3/action/log` → autorizado se o scope contiver `write_actionlog` (sem precisar de `write_all` ou `write_action_log`)
156
+ - `POST /v3/mobile/device` → autorizado com qualquer scope não-vazio
157
+
158
+ ### 5.4 Regras gramaticais
159
+
160
+ Para `(method, path)` não cobertos acima (`SecurityFilter.java:230-253`):
161
+
162
+ 1. **verb** = `GET`→`read`, `POST`/`PUT`→`write`, `DELETE`→`delete`
163
+ 2. **entity_full** = path após `/v3/`, com `/` substituído por `_` (e.g. `/v3/database/orders/aggregate` → `database_orders_aggregate`)
164
+ 3. Verifica na ordem:
165
+ - `{verb}_all` → rule `all`
166
+ - `{verb}_{entity_full}` → rule `exact`
167
+ - `{verb}_{prefix}_all` (minus-1 trailing segment) → rule `fallback-m1`
168
+ - `{verb}_{prefix}_all` (minus-2 trailing segments) → rule `fallback-m2`
169
+ - Se nenhum → denied
170
+
171
+ > **O motor para em m2.** Não há fallback m3 ou superior, mesmo que o path tenha mais segmentos.
172
+
173
+ ### 5.5 Keyword `database` (DatabaseRest.java)
174
+
175
+ **Regra crítica:** qualquer path `/v3/database/...` requer o token literal `database` no scope, **além** do token gramatical. Aplica-se a **todos os verbos incluindo GET**. Os 13 handlers de `DatabaseRest.java` verificam este keyword explicitamente.
176
+
177
+ Exemplo: para autorizar `GET /v3/database/orders`, o scope precisa de `read_database_orders` (ou `read_all`) **E** `database`.
178
+
179
+ ### 5.6 Normalização do scope
180
+
181
+ Espaços são removidos e tokens são separados por vírgula antes da avaliação. `"read_all, write_all"` equivale a `"read_all,write_all"`.
182
+
183
+ ---
184
+
185
+ ## 6. Read-Only Rule e Remediação
186
+
187
+ ### 6.1 O audit nunca escreve
188
+
189
+ O `funifier_permissions action=audit` é a única ação deste tool que não requer conexão para findings de `danger` (ainda requer para carregar o documento de segurança). Não faz mutações, não grava snapshots.
190
+
191
+ ### 6.2 Fluxo de remediação
192
+
193
+ Para cada finding `missing`:
194
+ 1. Identifique o token exato sugerido em `requiredTokens`.
195
+ 2. Decida se vai adicionar ao scope da role (`save_security_role`) ou do app (`save_api_app`).
196
+ 3. Confirme a intenção com o utilizador antes de executar.
197
+ 4. O tool escreverá um backup automático antes de qualquer mutação.
198
+
199
+ Para cada finding `excess`:
200
+ 1. Verifique se o token pode ser necessário a consumidores **fora** deste manifest.
201
+ 2. Se seguro, remova com `save_security_role` / `save_api_app`.
202
+ 3. Após remover, corra o audit novamente para confirmar que não surgiram novos `missing`.
203
+
204
+ Para findings `danger`:
205
+ 1. Avalie o risco: quem está a usar o contexto público/player afetado?
206
+ 2. Remova o token perigoso ou restrinja o role conforme necessário.
207
+ 3. Para `read_encrypted_*` em `public`: é quase sempre um erro de configuração.
208
+
209
+ ---
210
+
211
+ ## 7. Invocação
212
+
213
+ ```
214
+ funifier_permissions action=audit data=<manifest JSON>
215
+ ```
216
+
217
+ O manifest é passado como string JSON no campo `data`. Exemplo de chamada:
218
+
219
+ ```json
220
+ {
221
+ "action": "audit",
222
+ "data": "{\"version\":1,\"entries\":[{\"method\":\"GET\",\"path\":\"/v3/player/me\",\"auth\":\"player\",\"evidence\":\"src/api.ts:10\"}]}"
223
+ }
224
+ ```
225
+
226
+ O resultado inclui:
227
+ - `manifest_entries`: número de entradas avaliadas
228
+ - `findings`: lista de findings com `severity`, `principal`, `rule`, `evidence`, `requiredTokens`, `excessTokens`, `narrowingSuggestion`, `detail`
229
+ - `notes`: notas de completude, Bearer freshness, e instrução de verificação para excess
@@ -106,6 +106,7 @@ A Funifier funciona como um **backend de aplicações**. Independentemente do ti
106
106
  | Java Managers | `guides/java-managers.md` | Referência de managers Java | Métodos disponíveis em cada manager (PlayerManager, ActionManager, etc.) para uso em triggers, schedulers e public endpoints |
107
107
  | Java Entities | `guides/java-entities.md` | Referência de entidades Java | Campos e tipos dos objetos (Player, Achievement, ActionLog, etc.) e mapeamento para coleções MongoDB |
108
108
  | Java Libraries | `guides/java-libraries.md` | Bibliotecas e utilitários Java | JsonUtil, Guid, DateUtil, Unirest, EmailBuilder, Jongo — métodos e exemplos de uso |
109
+ | Permission Audit | `guides/permission-audit.md` | Auditoria de permissões de API | Cross-check código↔Funifier: manifest de chamadas → missing scopes, excess tokens, danger findings; gramática de scope (SecurityFilter), keyword `database`, auth context, remediação |
109
110
 
110
111
  ---
111
112