forlogic-core 2.2.2 → 2.2.4
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/dist/index.esm.js +1 -1
- package/dist/index.js +1 -1
- package/dist/supabase/legacyKeyGuard.d.ts +19 -0
- package/docs/STORAGE_BUCKETS.md +163 -96
- package/docs/SUPABASE_SECRETS.md +122 -0
- package/docs/WORKSPACE_KNOWLEDGE.md +34 -0
- package/docs/design-system/patterns/feature-flags.md +57 -0
- package/docs/design-system/patterns/vite-tailwind-setup.md +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detecta se a VITE_SUPABASE_PUBLISHABLE_KEY é uma legacy anon key (JWT)
|
|
3
|
+
* e oferece fallback via VITE_SUPABASE_PK_OVERRIDE.
|
|
4
|
+
*
|
|
5
|
+
* O Supabase desativou legacy API keys — a nova key usa formato `sb_publishable_*`.
|
|
6
|
+
* O Lovable auto-regenera o .env sobrescrevendo VITE_SUPABASE_PUBLISHABLE_KEY com a
|
|
7
|
+
* legacy key. Para contornar, os projetos podem definir VITE_SUPABASE_PK_OVERRIDE
|
|
8
|
+
* que o Lovable nunca toca.
|
|
9
|
+
*/
|
|
10
|
+
/** Retorna true se a key é um JWT legado (começa com `eyJ`). */
|
|
11
|
+
export declare function isLegacyAnonKey(key: string | undefined): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Resolve a publishable key correta:
|
|
14
|
+
* 1. Se VITE_SUPABASE_PK_OVERRIDE existe → usa ela (ignora a outra)
|
|
15
|
+
* 2. Senão → usa VITE_SUPABASE_PUBLISHABLE_KEY
|
|
16
|
+
*/
|
|
17
|
+
export declare function resolvePublishableKey(): string;
|
|
18
|
+
/** Verifica a env var e loga erro/info no console (uma única vez). Retorna true se legada sem override. */
|
|
19
|
+
export declare function warnIfLegacyKey(): boolean;
|
package/docs/STORAGE_BUCKETS.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Supabase Storage — Inventário e mapa de consumidores
|
|
2
2
|
|
|
3
3
|
> **Projeto Supabase:** `ccjfvpnndclajkleyqkc` (qualiex-db, prod)
|
|
4
|
-
> **Snapshot:** 2026-04
|
|
4
|
+
> **Snapshot:** 2026-05-04
|
|
5
5
|
> **Objetivo:** mapear todos os buckets, quem os consome, suas RLS atuais e os riscos para guiar o próximo ciclo de hardening.
|
|
6
6
|
> **Escopo:** apenas documentação — nenhuma policy, bucket ou código foi alterado.
|
|
7
7
|
|
|
@@ -9,28 +9,35 @@
|
|
|
9
9
|
|
|
10
10
|
## 1. Visão geral
|
|
11
11
|
|
|
12
|
-
15 buckets ativos. Tamanho total ≈
|
|
12
|
+
15 buckets ativos. Tamanho total ≈ 332 GB (dominado por `content-videos`).
|
|
13
13
|
|
|
14
14
|
| # | Bucket | Público | Objetos | Tamanho | MIME limit | File size limit |
|
|
15
15
|
|---|---|---|---:|---:|---|---|
|
|
16
16
|
| 1 | `career-banners` | ✅ | 4 | 349 kB | — | — |
|
|
17
|
-
| 2 | `certificates` | ✅ | 2.
|
|
18
|
-
| 3 | `content-files` | ✅ | 5.
|
|
19
|
-
| 4 | `content-videos` | ✅ | 1.
|
|
17
|
+
| 2 | `certificates` | ✅ | 2.470 | 982 MB | — | — |
|
|
18
|
+
| 3 | `content-files` | ✅ | 5.474 | 2,7 GB | lista ampla | 2 GB |
|
|
19
|
+
| 4 | `content-videos` | ✅ | 1.929 | 326 GB | só vídeo | 3 GB |
|
|
20
20
|
| 5 | `contracts` | 🔒 | 151 | 47 MB | — | — |
|
|
21
21
|
| 6 | `imports` | 🔒 | 3 | 569 kB | — | — |
|
|
22
22
|
| 7 | `knowledge-files` | 🔒 | 8 | 24 MB | — | — |
|
|
23
23
|
| 8 | `library-assets` | ✅ | 10 | 105 kB | — | — |
|
|
24
|
-
| 9 | `
|
|
25
|
-
| 10 | `performance
|
|
26
|
-
| 11 | `resumes` | 🔒 |
|
|
27
|
-
| 12 | `thumbnails` | ✅ | 1.
|
|
28
|
-
| 13 | `trainings` | 🔒 |
|
|
29
|
-
| 14 | `university-assets` | ✅ |
|
|
30
|
-
| 15 | `user-uploads` | 🔒 | 1.
|
|
24
|
+
| 9 | `pdi-uploads` | 🔒 | 8 | 14 MB | — | — |
|
|
25
|
+
| 10 | `performance` | 🔒 | 76 | 19 MB | — | — |
|
|
26
|
+
| 11 | `resumes` | 🔒 | 745 | 162 MB | pdf/doc/docx | 10 MB |
|
|
27
|
+
| 12 | `thumbnails` | ✅ | 1.158 | 585 MB | — | — |
|
|
28
|
+
| 13 | `trainings` | 🔒 | 27 | 13 MB | — | — |
|
|
29
|
+
| 14 | `university-assets` | ✅ | 284 | 308 MB | — | — |
|
|
30
|
+
| 15 | `user-uploads` | 🔒 | 1.001 | 1,5 GB | — | — |
|
|
31
31
|
|
|
32
32
|
> ℹ️ A coluna **Público** indica `storage.buckets.public`. Buckets públicos liberam download anônimo via `/storage/v1/object/public/<bucket>/<path>` e, sem policy explícita, também permitem `LIST` anônimo.
|
|
33
33
|
|
|
34
|
+
### Changelog
|
|
35
|
+
|
|
36
|
+
| Data | Mudança |
|
|
37
|
+
|------|---------|
|
|
38
|
+
| 2026-05-04 | `performance` tornado privado com 4 policies (SELECT/INSERT/UPDATE/DELETE) escopadas por alias. `performance-files` removido (deprecado). Snapshot atualizado. |
|
|
39
|
+
| 2026-04-29 | Snapshot inicial. `library-assets` INSERT anônimo removido. `thumbnails` rollback para policies permissivas. |
|
|
40
|
+
|
|
34
41
|
---
|
|
35
42
|
|
|
36
43
|
## 2. Matriz Bucket × Projeto
|
|
@@ -64,10 +71,10 @@ Projetos do ecossistema (Lovable):
|
|
|
64
71
|
| `career-banners` | | | ✅ | | | | | | |
|
|
65
72
|
| `resumes` | | | ✅ | | | | | (policy) | |
|
|
66
73
|
| `contracts` | | | ✅ | | | | | | |
|
|
67
|
-
| `user-uploads` | | | ✅ (interviews) | ✅ (training-requests, trainings, imported-evidence) | ✅ (evidence-images, evidence-attachments) |
|
|
74
|
+
| `user-uploads` | | | ✅ (interviews) | ✅ (training-requests, trainings, imported-evidence) | ✅ (evidence-images, evidence-attachments) | | | | |
|
|
75
|
+
| `pdi-uploads` | | | | | | ✅ (evidences) | | | |
|
|
68
76
|
| `trainings` | | | | ✅ | | | | | |
|
|
69
77
|
| `performance` | | | | | | | ✅ (1:1) | | |
|
|
70
|
-
| `performance-files` | | | | | | | ⚠️ órfão | | |
|
|
71
78
|
| `knowledge-files` | | | | | | | | | ❓ |
|
|
72
79
|
|
|
73
80
|
Legenda: ✅ uso confirmado em código · 🔎 só leitura · (policy) tem RLS mas sem código consumidor encontrado · ❓ a confirmar com o time.
|
|
@@ -82,7 +89,7 @@ Legenda: ✅ uso confirmado em código · 🔎 só leitura · (policy) tem RLS m
|
|
|
82
89
|
- **Consumidor:** [Admin](/projects/9dc9be11-bf85-4561-b36a-8d8f35fdbc06) — `lib/assets/index.ts`, `lib/setup/favicon.ts`. Consumido como leitura pública por todos os projetos via URL pública.
|
|
83
90
|
- **Estrutura:** raiz do bucket (`logo-qualiex-white.svg`, `favicon.png`, etc.).
|
|
84
91
|
- **Visibilidade:** público.
|
|
85
|
-
- **RLS atuais
|
|
92
|
+
- **RLS atuais:** **nenhuma policy de write** no `storage.objects` para esse bucket. SELECT continua público pelo flag de bucket público. INSERT/UPDATE/DELETE bloqueados para qualquer role (apenas service_role contorna RLS).
|
|
86
93
|
- **Mudança recente:** a antiga policy `Allow public upload to library assets` (INSERT anônimo sem condição) foi **removida**.
|
|
87
94
|
- **Riscos:**
|
|
88
95
|
- 🟢 Upload anônimo eliminado.
|
|
@@ -97,25 +104,29 @@ Legenda: ✅ uso confirmado em código · 🔎 só leitura · (policy) tem RLS m
|
|
|
97
104
|
- **Consumidor:** [Admin](/projects/9dc9be11-bf85-4561-b36a-8d8f35fdbc06) — `src/imports/wizard/services/importJobService.ts`.
|
|
98
105
|
- **Estrutura:** `{alias}/{timestamp}_{filename}`.
|
|
99
106
|
- **Visibilidade:** privado.
|
|
100
|
-
- **RLS atuais:**
|
|
107
|
+
- **RLS atuais:**
|
|
108
|
+
- `imports_bucket_select` — SELECT, role `public`, `auth.role() = 'authenticated'` + `foldername[1] = jwt.alias`.
|
|
109
|
+
- `imports_bucket_insert` — INSERT, role `public`, `auth.role() = 'authenticated'` + `foldername[1] = jwt.alias`.
|
|
110
|
+
- `imports_bucket_update` — UPDATE, role `public`, `auth.role() = 'authenticated'` + `foldername[1] = jwt.alias`.
|
|
111
|
+
- `imports_bucket_delete` — DELETE, role `public`, `auth.role() = 'authenticated'` + `foldername[1] = jwt.alias`.
|
|
101
112
|
- **Riscos:**
|
|
102
|
-
- 🟡 Policies estão atribuídas ao role `public
|
|
113
|
+
- 🟡 Policies estão atribuídas ao role `public` — funcional, mas inconsistente com o padrão `TO authenticated`.
|
|
103
114
|
- **Recomendação:** converter as policies para `TO authenticated` (mais explícito e linter-friendly).
|
|
104
115
|
|
|
105
116
|
---
|
|
106
117
|
|
|
107
|
-
### 3.3 `thumbnails` — ⚠️
|
|
118
|
+
### 3.3 `thumbnails` — ⚠️ sem scoping por alias
|
|
108
119
|
|
|
109
120
|
- **Finalidade:** miniaturas/capas de cursos e conteúdos.
|
|
110
121
|
- **Consumidor:** [Educação](/projects/075796dc-6ed4-43d3-92e3-3ab7f6314db6) — `src/modules/contents/hooks/useImageUpload.ts` (default bucket).
|
|
111
122
|
- **Estrutura atual:** sem prefixo obrigatório (uploads vão na raiz).
|
|
112
123
|
- **Visibilidade:** público.
|
|
113
|
-
- **RLS atuais
|
|
124
|
+
- **RLS atuais:**
|
|
114
125
|
- `Users can upload thumbnails` — INSERT `TO authenticated`, sem scoping por alias.
|
|
115
126
|
- `Users can update thumbnails` — UPDATE `TO authenticated`, sem scoping por alias.
|
|
116
127
|
- `Users can delete thumbnails` — DELETE `TO authenticated`, sem scoping por alias.
|
|
117
128
|
- **Histórico:**
|
|
118
|
-
- Hardening anterior (`thumbnails_auth_insert/update/delete` exigindo `
|
|
129
|
+
- Hardening anterior (`thumbnails_auth_insert/update/delete` exigindo `foldername[1] = jwt.alias`) quebrou os uploads do projeto Educação, que escreve direto na raiz do bucket.
|
|
119
130
|
- Em 29/04/2026 fizemos rollback para o estado anterior (3 policies permissivas para `authenticated`).
|
|
120
131
|
- **Riscos:**
|
|
121
132
|
- 🔴 Sem isolamento multi-tenant: qualquer usuário autenticado pode sobrescrever/apagar arquivos de qualquer tenant.
|
|
@@ -130,7 +141,10 @@ Legenda: ✅ uso confirmado em código · 🔎 só leitura · (policy) tem RLS m
|
|
|
130
141
|
- **Consumidor:** [Educação](/projects/075796dc-6ed4-43d3-92e3-3ab7f6314db6) — `src/hooks/useImageUpload.ts`, `src/modules/contents/services/aiDocsService.ts`.
|
|
131
142
|
- **Estrutura:** `{alias}/...` em parte das chamadas (não obrigatório).
|
|
132
143
|
- **Visibilidade:** público.
|
|
133
|
-
- **RLS atuais:**
|
|
144
|
+
- **RLS atuais:**
|
|
145
|
+
- `university_assets_auth_insert` — INSERT `TO authenticated`, `jwt.alias IS NOT NULL`. Sem scoping por pasta.
|
|
146
|
+
- `university_assets_auth_update` — UPDATE `TO authenticated`, `jwt.alias IS NOT NULL`. Sem scoping por pasta.
|
|
147
|
+
- `university_assets_auth_delete` — DELETE `TO authenticated`, `jwt.alias IS NOT NULL`. Sem scoping por pasta.
|
|
134
148
|
- **Riscos:**
|
|
135
149
|
- 🟠 Qualquer usuário autenticado de qualquer tenant pode sobrescrever/excluir arquivos de qualquer outro tenant.
|
|
136
150
|
- 🟡 `LIST` público.
|
|
@@ -146,7 +160,10 @@ Legenda: ✅ uso confirmado em código · 🔎 só leitura · (policy) tem RLS m
|
|
|
146
160
|
- [Treinamentos](/projects/e02280e1-3f95-4114-8d83-80d3e8ced304) — `src/training/utils/evidenceUrlResolver.ts` (leitura via `getPublicUrl`).
|
|
147
161
|
- **Estrutura:** sem padrão por alias (arquivos no root).
|
|
148
162
|
- **Visibilidade:** público (mesmo o código gerando signed URLs — ou seja, a privacidade pretendida não é real).
|
|
149
|
-
- **RLS atuais:**
|
|
163
|
+
- **RLS atuais:**
|
|
164
|
+
- `Authenticated users can upload certificates` — INSERT `TO authenticated`, sem scoping.
|
|
165
|
+
- `Authenticated users can update certificates` — UPDATE `TO authenticated`, sem scoping.
|
|
166
|
+
- `Authenticated users can delete certificates` — DELETE `TO authenticated`, sem scoping.
|
|
150
167
|
- **Riscos:**
|
|
151
168
|
- 🔴 Certificados são **PII** (nome do aluno, curso, datas). Bucket público + sem scoping = qualquer URL adivinhada/descoberta vaza dados pessoais.
|
|
152
169
|
- 🟠 `LIST` anônimo expõe inventário com nomes de arquivo.
|
|
@@ -160,7 +177,10 @@ Legenda: ✅ uso confirmado em código · 🔎 só leitura · (policy) tem RLS m
|
|
|
160
177
|
- **Consumidor:** [Educação](/projects/075796dc-6ed4-43d3-92e3-3ab7f6314db6) — `src/modules/contents/hooks/useFileUpload.ts`, `docs/SCORM_IMPLEMENTATION.md`.
|
|
161
178
|
- **Estrutura:** `{packageFolder}/...` (SCORM); demais sem padrão claro.
|
|
162
179
|
- **Visibilidade:** público.
|
|
163
|
-
- **RLS atuais:**
|
|
180
|
+
- **RLS atuais:**
|
|
181
|
+
- `Authenticated users can upload content-files` — INSERT `TO authenticated`, sem scoping.
|
|
182
|
+
- `Authenticated users can update content-files` — UPDATE `TO authenticated`, sem scoping.
|
|
183
|
+
- `Authenticated users can delete content-files` — DELETE `TO authenticated`, sem scoping.
|
|
164
184
|
- **Riscos:**
|
|
165
185
|
- 🟠 Materiais de treinamento de um cliente podem estar acessíveis publicamente para quem tiver a URL/listar o bucket.
|
|
166
186
|
- 🟡 `LIST` público.
|
|
@@ -174,10 +194,13 @@ Legenda: ✅ uso confirmado em código · 🔎 só leitura · (policy) tem RLS m
|
|
|
174
194
|
- **Consumidor:** [Educação](/projects/075796dc-6ed4-43d3-92e3-3ab7f6314db6) — `src/contexts/UploadQueueContext.tsx`, `src/modules/contents/hooks/useVideoUpload.ts`.
|
|
175
195
|
- **Estrutura:** `{alias}/{filename}`.
|
|
176
196
|
- **Visibilidade:** público.
|
|
177
|
-
- **RLS atuais:**
|
|
197
|
+
- **RLS atuais:**
|
|
198
|
+
- `content_videos_auth_insert` — INSERT `TO authenticated`, `foldername[1] = jwt.alias`.
|
|
199
|
+
- `content_videos_auth_update` — UPDATE `TO authenticated`, `foldername[1] = jwt.alias`.
|
|
200
|
+
- `content_videos_auth_delete` — DELETE `TO authenticated`, `foldername[1] = jwt.alias`.
|
|
178
201
|
- **Riscos:**
|
|
179
202
|
- 🟠 Vídeos premium acessíveis por URL pública direta.
|
|
180
|
-
- 🟡 `LIST` público (alto volume —
|
|
203
|
+
- 🟡 `LIST` público (alto volume — 326 GB).
|
|
181
204
|
- **Recomendação:** considerar privado + signed URLs (igual a Vimeo/Mux). Custo: rever player e CDN.
|
|
182
205
|
|
|
183
206
|
---
|
|
@@ -188,10 +211,13 @@ Legenda: ✅ uso confirmado em código · 🔎 só leitura · (policy) tem RLS m
|
|
|
188
211
|
- **Consumidor:** [Colaboradores](/projects/37cdf18f-3d54-4af2-a02b-9f7e2d94e654).
|
|
189
212
|
- **Estrutura:** raiz.
|
|
190
213
|
- **Visibilidade:** público.
|
|
191
|
-
- **RLS atuais:**
|
|
214
|
+
- **RLS atuais:**
|
|
215
|
+
- `career_banners_upload` — INSERT, role `public`, `auth.role() = 'authenticated'`.
|
|
216
|
+
- `career_banners_delete` — DELETE, role `public`, `auth.role() = 'authenticated'`.
|
|
192
217
|
- **Riscos:**
|
|
193
218
|
- 🟡 Sem scoping por alias — qualquer admin de qualquer tenant pode deletar banners de outro.
|
|
194
|
-
-
|
|
219
|
+
- 🟡 Policies em role `public` em vez de `TO authenticated`.
|
|
220
|
+
- **Recomendação:** scoping por alias se for multi-tenant. Padronizar para `TO authenticated`.
|
|
195
221
|
|
|
196
222
|
---
|
|
197
223
|
|
|
@@ -204,11 +230,13 @@ Legenda: ✅ uso confirmado em código · 🔎 só leitura · (policy) tem RLS m
|
|
|
204
230
|
- **Estrutura:** `{alias}/{filename}` (Colaboradores) e `{auth.uid()}/...` (Cockpit) — **dois esquemas convivendo**.
|
|
205
231
|
- **Visibilidade:** privado.
|
|
206
232
|
- **RLS atuais:**
|
|
207
|
-
- `resumes_alias_select
|
|
233
|
+
- `resumes_alias_select` — SELECT `TO authenticated`, `foldername[1] = jwt.alias`.
|
|
234
|
+
- `resumes_auth_upload` — INSERT `TO authenticated`, `foldername[1] = jwt.alias` + extensões `pdf|doc|docx|jpg|jpeg|png`.
|
|
235
|
+
- **⚠️ Incongruência MIME:** o bucket aceita apenas `pdf/doc/docx` (configuração `allowed_mime_types`), mas a policy `resumes_auth_upload` lista também `jpg|jpeg|png`. Na prática o bucket rejeitaria imagens pelo MIME antes da policy ser avaliada, mas a policy está desatualizada.
|
|
208
236
|
- **Riscos:**
|
|
209
237
|
- 🟠 Há duas convenções de path conflitantes (alias vs uid). Pode haver arquivos "órfãos" que não casam com nenhuma policy.
|
|
210
238
|
- 🟠 Não há policy explícita de UPDATE/DELETE listada.
|
|
211
|
-
- **Recomendação:** alinhar uma única convenção (`{alias}/{auth.uid()}/{file}` cobre os dois) e adicionar UPDATE/DELETE.
|
|
239
|
+
- **Recomendação:** alinhar uma única convenção (`{alias}/{auth.uid()}/{file}` cobre os dois) e adicionar UPDATE/DELETE. Remover extensões de imagem da policy para casar com o bucket.
|
|
212
240
|
|
|
213
241
|
---
|
|
214
242
|
|
|
@@ -218,17 +246,21 @@ Legenda: ✅ uso confirmado em código · 🔎 só leitura · (policy) tem RLS m
|
|
|
218
246
|
- **Consumidor:** [Colaboradores](/projects/37cdf18f-3d54-4af2-a02b-9f7e2d94e654) — `src/contracts/contractService.ts`, edge function `contract-processor`.
|
|
219
247
|
- **Estrutura:** `{templates|generated}/{alias}/{filename}`.
|
|
220
248
|
- **Visibilidade:** privado.
|
|
221
|
-
- **RLS atuais:**
|
|
249
|
+
- **RLS atuais:**
|
|
250
|
+
- `contracts_select` — SELECT, role `public`, `foldername[1] IN ('templates','generated')` + `foldername[2] = jwt.alias`.
|
|
251
|
+
- `contracts_insert` — INSERT, role `public`, mesma condição.
|
|
252
|
+
- `contracts_update` — UPDATE, role `public`, mesma condição.
|
|
253
|
+
- `contracts_delete` — DELETE `TO authenticated`, mesma condição.
|
|
222
254
|
- **Riscos:**
|
|
223
|
-
- 🟢 Bem segregado.
|
|
224
|
-
- 🟡
|
|
255
|
+
- 🟢 Bem segregado por alias.
|
|
256
|
+
- 🟡 SELECT/INSERT/UPDATE em role `public` (funcional mas inconsistente).
|
|
225
257
|
- **Recomendação:** padronizar para `TO authenticated`.
|
|
226
258
|
|
|
227
259
|
---
|
|
228
260
|
|
|
229
261
|
### 3.11 `user-uploads` — 🚨 alta complexidade
|
|
230
262
|
|
|
231
|
-
Bucket multi-projeto, segregado por subpasta. **Usado por
|
|
263
|
+
Bucket multi-projeto, segregado por subpasta. **Usado por 3 projetos** (Colaboradores, Treinamentos, Matriz de Foco).
|
|
232
264
|
|
|
233
265
|
- **Visibilidade:** privado.
|
|
234
266
|
- **Estrutura por consumidor:**
|
|
@@ -241,28 +273,31 @@ Bucket multi-projeto, segregado por subpasta. **Usado por 4 projetos** (Colabora
|
|
|
241
273
|
| `trainings/.../{alias}/...` | Treinamentos | Evidências de treinamento (alias na 3ª pasta) |
|
|
242
274
|
| `evidence-images/...` | Matriz de Foco | Imagens coladas no rich-text editor |
|
|
243
275
|
| `evidence-attachments/{evidenceId}/...` | Matriz de Foco | Anexos de evidências |
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
276
|
+
|
|
277
|
+
- **RLS atuais (05/05/2026):**
|
|
278
|
+
|
|
279
|
+
| Policy | Cmd | Role | Scoping |
|
|
280
|
+
|--------|-----|------|---------|
|
|
281
|
+
| `interview_scoped_select` | SELECT | `public` | `foldername[1] = 'interviews'` + `foldername[2] = jwt.alias` |
|
|
282
|
+
| `authenticated_interview_upload` | INSERT | `public` | `auth.role() = 'authenticated'` — **sem scoping por subpasta/alias** ⚠️ |
|
|
283
|
+
| `training_requests_attachments_select` | SELECT | `public` | `foldername[1] = 'training-requests'` + `foldername[2] = jwt.alias` |
|
|
284
|
+
| `training_requests_attachments_insert` | INSERT | `public` | `foldername[1] = 'training-requests'` + `foldername[2] = jwt.alias` |
|
|
285
|
+
| `training_requests_attachments_delete` | DELETE | `public` | `foldername[1] = 'training-requests'` + `foldername[2] = jwt.alias` |
|
|
286
|
+
| `imported_evidence_select` | SELECT | `public` | `foldername[1] = 'imported-evidence'` + `foldername[2] = jwt.alias` |
|
|
287
|
+
| `imported_evidence_insert` | INSERT | `public` | `foldername[1] = 'imported-evidence'` + `foldername[2] = jwt.alias` |
|
|
288
|
+
| `evidence_uploads_select` | SELECT | `authenticated` | `foldername[1] IN ('evidence-images','evidence-attachments')` + `jwt.alias IS NOT NULL` — **sem checagem de alias** ⚠️ |
|
|
289
|
+
| `evidence_uploads_delete` | DELETE | `authenticated` | `foldername[1] IN ('evidence-images','evidence-attachments')` + `jwt.alias IS NOT NULL` — **sem checagem de alias** ⚠️ |
|
|
290
|
+
| `Authenticated users can update user-uploads` | UPDATE | `authenticated` | `foldername[2] = jwt.alias` (cobre `*/{alias}/...`, mas não `evidence-images/` nem `evidences/`) |
|
|
255
291
|
|
|
256
292
|
- **Riscos:**
|
|
257
293
|
- 🔴 `authenticated_interview_upload` continua permitindo que qualquer authenticated grave em qualquer subpasta do bucket (cross-tenant + cross-projeto).
|
|
258
294
|
- 🔴 `evidence_uploads_select/delete` não checam alias — qualquer authenticated lê/deleta evidências da Matriz de Foco de outros tenants.
|
|
259
|
-
- 🟠 PDI (`evidences/...`) sem policies dedicadas; depende da policy genérica.
|
|
260
295
|
- 🟠 Padrão de path inconsistente entre projetos (uns usam alias na 1ª pasta, outros na 3ª, outros não usam).
|
|
261
296
|
|
|
262
297
|
- **Recomendação:**
|
|
263
298
|
- Padronizar para `{projeto}/{alias}/...`.
|
|
264
299
|
- Substituir `authenticated_interview_upload` por INSERT por subpasta + alias.
|
|
265
|
-
- Adicionar checagem de alias em `evidence_uploads_select/delete` (Matriz de Foco)
|
|
300
|
+
- Adicionar checagem de alias em `evidence_uploads_select/delete` (Matriz de Foco).
|
|
266
301
|
|
|
267
302
|
---
|
|
268
303
|
|
|
@@ -272,87 +307,117 @@ Bucket multi-projeto, segregado por subpasta. **Usado por 4 projetos** (Colabora
|
|
|
272
307
|
- **Consumidor:** [Treinamentos](/projects/e02280e1-3f95-4114-8d83-80d3e8ced304) — `LeaderResolveModal`, `LeaderPendingSelectModal`.
|
|
273
308
|
- **Estrutura:** `.../.../{alias}/...` (alias na 3ª pasta — esquisito).
|
|
274
309
|
- **Visibilidade:** privado.
|
|
275
|
-
- **RLS atuais:**
|
|
310
|
+
- **RLS atuais:**
|
|
311
|
+
- `trainings_bucket_select` — SELECT, role `public`, `foldername[2] = jwt.alias`.
|
|
312
|
+
- `trainings_bucket_insert` — INSERT, role `public`, `foldername[2] = jwt.alias`.
|
|
276
313
|
- **Riscos:**
|
|
277
314
|
- 🟡 Discrepância: a policy usa pasta `[2]`, mas o resolver de evidências em `evidenceUrlResolver.ts` aceita o bucket. Validar se o path real bate.
|
|
278
315
|
- 🟠 Sem policy explícita de UPDATE/DELETE.
|
|
279
|
-
-
|
|
316
|
+
- 🟡 Policies em role `public` (funcional mas inconsistente).
|
|
317
|
+
- **Recomendação:** confirmar convenção de path, adicionar UPDATE/DELETE escopados e padronizar para `TO authenticated`.
|
|
280
318
|
|
|
281
319
|
---
|
|
282
320
|
|
|
283
|
-
### 3.13 `performance` —
|
|
321
|
+
### 3.13 `performance` — ✅ corrigido (05/2026)
|
|
284
322
|
|
|
285
|
-
- **Finalidade:** anexos do módulo de **One-on-One** dentro de Desempenho — evidências de tarefas e relatórios
|
|
323
|
+
- **Finalidade:** anexos do módulo de **One-on-One** dentro de Desempenho — evidências de tarefas e relatórios.
|
|
286
324
|
- **Consumidor:** [Desempenho](/projects/7c73eab6-bf0a-4cb5-93b3-e1809d1363d7)
|
|
287
325
|
- `src/one-on-ones/services/evidenceService.ts` → pasta `evidences/`
|
|
288
326
|
- `src/one-on-ones/services/taskReportService.ts` → pasta `task-reports/`
|
|
289
|
-
|
|
290
|
-
- **
|
|
291
|
-
- **
|
|
292
|
-
-
|
|
293
|
-
-
|
|
294
|
-
-
|
|
295
|
-
-
|
|
296
|
-
|
|
297
|
-
- **Recomendação:**
|
|
298
|
-
1. Realinhar o código para `{alias}/evidences/...` e `{alias}/task-reports/...` (ou alterar a policy para casar com o path atual).
|
|
299
|
-
2. Tornar privado e migrar o front para signed URLs.
|
|
300
|
-
3. Adicionar SELECT/UPDATE/DELETE escopados por alias + autor.
|
|
301
|
-
|
|
302
|
-
---
|
|
303
|
-
|
|
304
|
-
### 3.14 `performance-files` — ⚠️ órfão (candidato a deprecar)
|
|
305
|
-
|
|
306
|
-
- **Origem:** criado pela migração `20260203114103_ffecc964-7e28-4605-8516-b851f62d0433.sql` no projeto Desempenho ("bucket dedicado para o módulo de desempenho").
|
|
307
|
-
- **Consumidor atual:** **nenhum** — busca em todo o projeto Desempenho (e nos demais 13 projetos do ecossistema) não encontra nenhuma referência ao nome `performance-files` fora da própria migração. Os 33 objetos existentes parecem ser de testes manuais ou de uma implementação anterior que foi substituída por `performance`.
|
|
308
|
-
- **Estrutura:** `{auth.uid()}/...` (assumido pela policy de DELETE).
|
|
309
|
-
- **Visibilidade:** público.
|
|
310
|
-
- **RLS atuais:**
|
|
311
|
-
- `performance_files_public_read` — SELECT para `public` sem condição.
|
|
312
|
-
- `performance_files_authenticated_insert` — INSERT só `authenticated`, sem scoping por alias.
|
|
313
|
-
- `performance_files_owner_delete` — DELETE só pelo dono via `auth.uid()`.
|
|
327
|
+
- **Estrutura:** `{alias}/evidences/...` e `{alias}/task-reports/...`.
|
|
328
|
+
- **Visibilidade:** 🔒 **privado** (alterado de público para privado).
|
|
329
|
+
- **RLS atuais (pós-hardening):**
|
|
330
|
+
- `performance_authenticated_select` — SELECT `TO authenticated`, `jwt.alias = foldername[1]`.
|
|
331
|
+
- `performance_authenticated_insert` — INSERT, role `public`, `jwt.alias = foldername[1]`.
|
|
332
|
+
- `performance_authenticated_update` — UPDATE, role `public`, `jwt.alias = foldername[1]`.
|
|
333
|
+
- `performance_authenticated_delete` — DELETE, role `public`, `jwt.alias = foldername[1]`.
|
|
334
|
+
- **Mudança recente:** bucket tornado privado + 4 policies com scoping por alias na 1ª pasta. Resolve os riscos P0 apontados anteriormente.
|
|
314
335
|
- **Riscos:**
|
|
315
|
-
-
|
|
316
|
-
-
|
|
317
|
-
-
|
|
336
|
+
- 🟢 Isolamento multi-tenant via alias — resolvido.
|
|
337
|
+
- 🟡 INSERT/UPDATE/DELETE em role `public` (funcional mas inconsistente com o padrão `TO authenticated`).
|
|
338
|
+
- 🟡 O código de Desempenho pode precisar migrar de `getPublicUrl` para `createSignedUrl` (bucket agora privado).
|
|
339
|
+
- **Recomendação:** padronizar policies para `TO authenticated`. Confirmar que o front de Desempenho já usa signed URLs.
|
|
318
340
|
|
|
319
341
|
---
|
|
320
342
|
|
|
321
|
-
### 3.
|
|
343
|
+
### 3.14 `knowledge-files` — ❓ a confirmar
|
|
322
344
|
|
|
323
345
|
- **Finalidade provável:** base de conhecimento para IA / chatbot.
|
|
324
346
|
- **Consumidor:** sem uso direto encontrado em nenhum dos 14 projetos. 8 objetos, último em março/2026.
|
|
325
347
|
- **Estrutura:** `{alias}/...`.
|
|
326
348
|
- **Visibilidade:** privado.
|
|
327
|
-
- **RLS atuais:**
|
|
349
|
+
- **RLS atuais:**
|
|
350
|
+
- `knowledge_files_select` — SELECT, role `public`, `auth.role() = 'authenticated'` + `foldername[1] = jwt.alias`.
|
|
351
|
+
- `knowledge_files_upload` — INSERT, role `public`, `auth.role() = 'authenticated'` + `foldername[1] = jwt.alias`.
|
|
328
352
|
- **Riscos:**
|
|
329
353
|
- 🟡 Sem UPDATE/DELETE explícitos.
|
|
330
354
|
- 🟡 Provavelmente consumido por uma edge function (não por front) — confirmar.
|
|
355
|
+
- 🟡 Policies em role `public` (funcional mas inconsistente).
|
|
331
356
|
- **Recomendação:** identificar consumidor e validar fluxo antes de mexer.
|
|
332
357
|
|
|
333
358
|
---
|
|
334
359
|
|
|
360
|
+
### 3.15 `pdi-uploads` — ✅ novo (05/2026)
|
|
361
|
+
|
|
362
|
+
- **Finalidade:** evidências de ações nos Planos de Desenvolvimento Individual (PDI).
|
|
363
|
+
- **Consumidor:** exclusivamente [PDI](/projects/7269db93-bd03-4b7d-842a-cd74404d2606)
|
|
364
|
+
- `src/modules/plans/utils/evidenceStorage.ts` — helper centralizado (`uploadEvidence`, `resolveEvidenceUrl`, `getEvidenceSignedUrl`)
|
|
365
|
+
- `src/modules/plans/components/tracking/EvidenceModal.tsx` — upload de evidências no acompanhamento
|
|
366
|
+
- `src/modules/plans/components/ActionManagementModal.tsx` — upload/edição de evidências em ações
|
|
367
|
+
- **Estrutura:** `{alias}/evidences/{timestamp}_{sanitized_filename}`.
|
|
368
|
+
- **Visibilidade:** 🔒 **privado** — acesso via signed URLs (1h de validade).
|
|
369
|
+
- **Limites:** sem restrição de MIME type ou tamanho no bucket (validação no front: 10 MB max).
|
|
370
|
+
- **RLS atuais (3 policies, todas `TO authenticated` com scoping por alias):**
|
|
371
|
+
- `pdi_uploads_select` — SELECT, `bucket_id = 'pdi-uploads' AND foldername[1] = jwt.alias`.
|
|
372
|
+
- `pdi_uploads_insert` — INSERT, mesma condição em `WITH CHECK`.
|
|
373
|
+
- `pdi_uploads_update` — UPDATE, mesma condição em `USING` e `WITH CHECK`.
|
|
374
|
+
- **Sem policy de DELETE** — alinhado com a regra de soft delete do projeto (evidências são desvinculadas no registro, não apagadas do storage).
|
|
375
|
+
- **Origem:** bucket criado durante migração de evidências do PDI, que antes usava `user-uploads/evidences/`. Migração concluída em 05/2026 (ver `docs/pdi-storage-migration-plan.md`).
|
|
376
|
+
- **Riscos:**
|
|
377
|
+
- 🟢 Isolamento multi-tenant via alias — correto desde a criação.
|
|
378
|
+
- 🟢 Todas as policies usam `TO authenticated` (padrão correto).
|
|
379
|
+
- 🟢 Signed URLs no front (bucket privado desde o início).
|
|
380
|
+
- **Recomendação:** nenhuma ação necessária — bucket exemplar.
|
|
381
|
+
|
|
382
|
+
---
|
|
383
|
+
|
|
335
384
|
## 4. Padrões de policies (síntese)
|
|
336
385
|
|
|
337
|
-
Boas práticas observadas
|
|
386
|
+
### 4.1 Boas práticas observadas
|
|
338
387
|
|
|
339
388
|
| Padrão | Onde aparece | Recomendar generalizar |
|
|
340
389
|
|---|---|---|
|
|
341
|
-
| `(storage.foldername(name))[1] = ((SELECT auth.jwt()) ->> 'alias')` | content-videos, contracts, imports, knowledge-files, training-requests, imported-evidence, resumes | ✅ sim — virar padrão |
|
|
342
|
-
| `TO authenticated` explícito | thumbnails, certificates, content-files, university-assets, content-videos, resumes | ✅ sim — converter as policies em role `public` |
|
|
390
|
+
| `(storage.foldername(name))[1] = ((SELECT auth.jwt()) ->> 'alias')` | content-videos, contracts, imports, knowledge-files, training-requests, imported-evidence, resumes, performance, **pdi-uploads** | ✅ sim — virar padrão |
|
|
391
|
+
| `TO authenticated` explícito | thumbnails, certificates, content-files, university-assets, content-videos, resumes, evidence_uploads, **pdi-uploads** | ✅ sim — converter as policies em role `public` |
|
|
343
392
|
| `(SELECT auth.jwt())` (e não `auth.jwt()`) | a maioria das policies novas | ✅ obrigatório (linter) |
|
|
344
|
-
| Bucket privado + signed URLs | certificates (Educação), contracts | ✅ aplicar a thumbnails, content-files, content-videos |
|
|
393
|
+
| Bucket privado + signed URLs | certificates (Educação), contracts, performance, **pdi-uploads** | ✅ aplicar a thumbnails, content-files, content-videos |
|
|
394
|
+
|
|
395
|
+
### 4.2 Policies com role `public` (debt técnico)
|
|
396
|
+
|
|
397
|
+
As seguintes policies usam `roles: {public}` com `auth.role() = 'authenticated'` no body em vez do mais correto `TO authenticated`. Funcionam, mas geram warnings no linter e são inconsistentes com o padrão:
|
|
398
|
+
|
|
399
|
+
| Bucket | Policies afetadas |
|
|
400
|
+
|--------|-------------------|
|
|
401
|
+
| `career-banners` | `career_banners_upload`, `career_banners_delete` |
|
|
402
|
+
| `contracts` | `contracts_select`, `contracts_insert`, `contracts_update` |
|
|
403
|
+
| `imports` | `imports_bucket_select`, `imports_bucket_insert`, `imports_bucket_update`, `imports_bucket_delete` |
|
|
404
|
+
| `knowledge-files` | `knowledge_files_select`, `knowledge_files_upload` |
|
|
405
|
+
| `performance` | `performance_authenticated_insert`, `performance_authenticated_update`, `performance_authenticated_delete` |
|
|
406
|
+
| `trainings` | `trainings_bucket_select`, `trainings_bucket_insert` |
|
|
407
|
+
| `user-uploads` | `authenticated_interview_upload`, `interview_scoped_select`, `training_requests_*`, `imported_evidence_*` |
|
|
408
|
+
|
|
409
|
+
**Recomendação:** migrar todas para `TO authenticated` em uma migration batch (P2 — sem mudança funcional).
|
|
345
410
|
|
|
346
411
|
---
|
|
347
412
|
|
|
348
413
|
## 5. Itens em aberto (a confirmar com o time)
|
|
349
414
|
|
|
350
415
|
1. **`knowledge-files`**: quem consome? É edge function?
|
|
351
|
-
2. **`performance
|
|
352
|
-
3. **`
|
|
353
|
-
4. **`
|
|
354
|
-
5. **`
|
|
355
|
-
6. **`
|
|
416
|
+
2. **`performance`**: confirmar que o front de Desempenho já migrou de `getPublicUrl` para signed URLs após o bucket ser tornado privado.
|
|
417
|
+
3. **`certificates` precisa ser público?** O código de Educação já gera signed URLs, então não.
|
|
418
|
+
4. **`content-videos` privado?** Avaliar custo (player) vs benefício (proteger PII e propriedade intelectual).
|
|
419
|
+
5. **`user-uploads` para Matriz de Foco**: `evidence_uploads_select/delete` não checam alias — risco cross-tenant confirmado. (PDI já migrou para `pdi-uploads`).
|
|
420
|
+
6. **`resumes`**: policy permite `jpg/jpeg/png` mas bucket só aceita `pdf/doc/docx` — limpar policy.
|
|
356
421
|
|
|
357
422
|
---
|
|
358
423
|
|
|
@@ -363,17 +428,19 @@ Boas práticas observadas no projeto:
|
|
|
363
428
|
| Prioridade | Bucket | Ação |
|
|
364
429
|
|---|---|---|
|
|
365
430
|
| ✅ done | `library-assets` | INSERT anônimo removido (sem policies de write). |
|
|
366
|
-
| ✅ done | `thumbnails` | INSERT/UPDATE/DELETE `TO authenticated`
|
|
367
|
-
|
|
|
431
|
+
| ✅ done | `thumbnails` | INSERT/UPDATE/DELETE `TO authenticated` (sem scoping — pendente ajuste no front). |
|
|
432
|
+
| ✅ done | `performance` | Tornado privado + 4 policies com scoping por alias. |
|
|
433
|
+
| ✅ done | `performance-files` | Bucket deprecado e removido. |
|
|
434
|
+
| ✅ done | `pdi-uploads` | Bucket criado (privado) + 3 policies `TO authenticated` com scoping por alias. Migração de `user-uploads` concluída. |
|
|
435
|
+
| 🔴 P0 | `user-uploads` | Substituir `authenticated_interview_upload` (INSERT genérico) por INSERT por subpasta + alias; adicionar checagem de alias em `evidence_uploads_select/delete` (Matriz de Foco). |
|
|
368
436
|
| 🔴 P0 | `certificates` | Tornar privado + migrar Treinamentos para signed URLs. |
|
|
369
|
-
|
|
|
437
|
+
| 🟠 P1 | `thumbnails` | Ajustar front de Educação para gravar em `{alias}/...` e reaplicar scoping por alias. |
|
|
370
438
|
| 🟠 P1 | `university-assets`, `content-files` | Adicionar scoping por alias em UPDATE/DELETE/INSERT. |
|
|
371
|
-
| 🟠 P1 | `
|
|
372
|
-
|
|
|
373
|
-
| 🟡 P2 | `contracts`, `imports` | Padronizar `TO authenticated` (limpeza
|
|
439
|
+
| 🟠 P1 | `resumes` | Unificar convenção de path (alias + uid), adicionar UPDATE/DELETE, remover extensões de imagem da policy. |
|
|
440
|
+
| 🟡 P2 | Múltiplos | Padronizar ~20 policies de role `public` para `TO authenticated` (limpeza, sem mudança funcional). Ver seção 4.2. |
|
|
441
|
+
| 🟡 P2 | `contracts`, `imports` | Padronizar `TO authenticated` (limpeza). |
|
|
374
442
|
| 🟡 P2 | `career-banners` | Scoping por alias se for multi-tenant. |
|
|
375
443
|
| 🟡 P2 | `content-videos` | Avaliar privado + signed URLs (impacto no player). |
|
|
376
|
-
| 🟡 P2 | Todos públicos | Substituir SELECT default por SELECT `TO authenticated` (ou `TO public` apenas para os realmente públicos como `library-assets` e `career-banners`) — alinha com plano já existente em [Cockpit `.lovable/plan.md`](/projects/e6853fb4-67f9-4776-b427-7768a9136f10). |
|
|
377
444
|
|
|
378
445
|
---
|
|
379
446
|
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Supabase Secrets — Inventário
|
|
2
|
+
|
|
3
|
+
> **Projeto Supabase:** `ccjfvpnndclajkleyqkc`
|
|
4
|
+
>
|
|
5
|
+
> Todas as secrets são compartilhadas entre os projetos Lovable que apontam para este mesmo projeto Supabase.
|
|
6
|
+
> Última atualização: 2026-05-04
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Infraestrutura Supabase (automáticas)
|
|
11
|
+
|
|
12
|
+
Secrets gerenciadas automaticamente pelo Supabase. **Não editar manualmente.**
|
|
13
|
+
|
|
14
|
+
| Secret | Finalidade | Projetos |
|
|
15
|
+
|--------|-----------|----------|
|
|
16
|
+
| `SUPABASE_URL` | URL do projeto Supabase | Todos com edge functions |
|
|
17
|
+
| `SUPABASE_SERVICE_ROLE_KEY` | Chave admin — bypass de RLS em edge functions | Todos com edge functions |
|
|
18
|
+
| `SUPABASE_ANON_KEY` | Chave pública anon (usada em `createClient` server-side) | Cockpit, Educação, PDI, Competências, Colaboradores |
|
|
19
|
+
| `SUPABASE_DB_URL` | Connection string PostgreSQL | Infraestrutura interna Supabase |
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Autenticação e JWT
|
|
24
|
+
|
|
25
|
+
| Secret | Finalidade | Projetos | Observações |
|
|
26
|
+
|--------|-----------|----------|-------------|
|
|
27
|
+
| `JWT_SECRET` | Verificação de assinatura HMAC-SHA256 dos JWTs customizados | **Admin** (validate-token, azure-blob-upload, clicksign, d4sign, send-email), **Cockpit** (_shared/auth), **Colaboradores** (sensitive-data, entra-id-sync, collaborator-webhook, contract-*), **PDI** (dev-tokens) | Crítica — usada para validar tokens em todas as edge functions protegidas |
|
|
28
|
+
| `VALIDATE_JWT_ENDPOINT` | URL de endpoint externo para validação de JWT (Qualiex API) | **Admin** (validate-token), **Treinamentos** (docs-documents-used, docs-process-outdated, notify-leader) | Fallback quando JWT_SECRET não é usado diretamente |
|
|
29
|
+
| `SUPABASE_PUBLISHABLE_KEY` | Chave pública do projeto (alias da anon key) | **Admin** (validate-token) | Usada para validar tokens de projetos consumidores |
|
|
30
|
+
| `SUPABASE_PUBLISHABLE_KEYS` | Lista de chaves públicas de múltiplos projetos | **Admin** (validate-token) | Suporte multi-projeto na validação |
|
|
31
|
+
| `SUPABASE_SECRET_KEYS` | Lista de chaves secretas de múltiplos projetos | **Admin** (validate-token) | Suporte multi-projeto na validação |
|
|
32
|
+
| `SUPABASE_JWKS` | JSON Web Key Set para validação de tokens | **Admin** (validate-token) | Padrão JWKS para rotação de chaves |
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Desenvolvimento e Preview
|
|
37
|
+
|
|
38
|
+
| Secret | Finalidade | Projetos | Observações |
|
|
39
|
+
|--------|-----------|----------|-------------|
|
|
40
|
+
| `DEV_ACCESS_TOKEN` | Token OAuth pré-configurado para ambiente de preview | **Admin**, **Cockpit** (sync-completed, view-pendencias), **Documentos**, **PDI** | Permite autenticação no preview Lovable sem fluxo OAuth |
|
|
41
|
+
| `DEV_ID_TOKEN` | ID token pré-configurado para ambiente de preview | **Admin**, **Cockpit**, **Documentos**, **PDI** | Par do DEV_ACCESS_TOKEN |
|
|
42
|
+
| `DEV_TOKENS_SECRET` | Secret de autenticação da edge function `dev-tokens` | **Admin** | Protege o endpoint que retorna os tokens de dev |
|
|
43
|
+
| `CRON_SECRET` | Header de autenticação do cron job `audit-ship` | **Admin** | Enviado como `x-cron-secret` pelo pg_cron |
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## E-mail (AWS SES)
|
|
48
|
+
|
|
49
|
+
| Secret | Finalidade | Projetos |
|
|
50
|
+
|--------|-----------|----------|
|
|
51
|
+
| `AWS_ACCESS_KEY_ID` | Credencial IAM para AWS SES | **Admin** (send-email), **Cockpit** (notify-suggestion), **Treinamentos** (docs-process-outdated) |
|
|
52
|
+
| `AWS_SECRET_ACCESS_KEY` | Credencial IAM para AWS SES | **Admin** (send-email), **Cockpit** (notify-suggestion), **Treinamentos** (docs-process-outdated) |
|
|
53
|
+
| `AWS_SES_REGION` | Região do SES (default: `us-east-1`) | **Admin**, **Cockpit**, **Treinamentos** |
|
|
54
|
+
| `AWS_SES_FROM_EMAIL` | Endereço de e-mail remetente | **Admin**, **Cockpit**, **Treinamentos** |
|
|
55
|
+
| `AWS_SES_FROM_NAME` | Nome exibido como remetente | **Admin**, **Cockpit**, **Treinamentos** |
|
|
56
|
+
| `SUGGESTION_NOTIFY_EMAIL` | E-mail destino para notificações de sugestões do Cockpit | **Cockpit** (notify-suggestion) |
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Azure
|
|
61
|
+
|
|
62
|
+
| Secret | Finalidade | Projetos | Observações |
|
|
63
|
+
|--------|-----------|----------|-------------|
|
|
64
|
+
| `AZURE_BLOB_ACCOUNT_URL` | URL da conta Azure Blob Storage | **Admin** (azure-blob-upload) | Upload de arquivos para Azure |
|
|
65
|
+
| `AZURE_BLOB_ACCOUNT_KEY` | SharedKey da conta Azure Blob | **Admin** (azure-blob-upload) | Método preferido de autenticação |
|
|
66
|
+
| `AZURE_BLOB_SAS_TOKEN` | SAS Token para Azure Blob | **Admin** (azure-blob-upload) | ⚠️ **Deprecated** — fallback do `AZURE_BLOB_ACCOUNT_KEY` |
|
|
67
|
+
| `AZURE_TENANT_ID` | Tenant ID do Azure AD (Entra ID) | **Colaboradores** (entra-id-sync) | Sincronização de usuários via Microsoft Graph |
|
|
68
|
+
| `AZURE_CLIENT_ID` | Client ID do app Azure AD | **Colaboradores** (entra-id-sync) | Par do AZURE_TENANT_ID |
|
|
69
|
+
|
|
70
|
+
> **Nota:** Existia uma secret `AZURE_CLIENT_SECRET` que era recriada indevidamente. Nenhum projeto no workspace a referencia no código — a origem da recriação não foi identificada.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Integrações de IA
|
|
75
|
+
|
|
76
|
+
| Secret | Finalidade | Projetos |
|
|
77
|
+
|--------|-----------|----------|
|
|
78
|
+
| `OPENAI_API_KEY` | Chave da API OpenAI (GPT) | **Educação** (generate-block-content, generate-course-structure, process-document, extract-certificate-data, generate-quiz-from-document), **Desempenho** (generate-questions-ai, performance-generate-*), **PDI** (generate-pdi-actions, generate-strategic-plan), **Competências** (generate-questions-ai), **Pulso** (analyze-comments, analyze-survey-data, generate-action-plan, refine-action-plan, analyze-custom-survey, generate-survey-action-plan), **Treinamentos** (generate-quiz-from-document, suggest-evaluation-criteria, validate-certificate) |
|
|
79
|
+
| `OPENROUTER_API_KEY` | Chave do OpenRouter (modelo: `google/gemini-2.5-flash`) | **Matriz de Foco** (generic-app-scan, manager-chat, outlook-calendar, redundancy-hunter, smart-assistant) |
|
|
80
|
+
| `LOVABLE_API_KEY` | Chave da API Lovable (AI Gateway) | **Educação** (generate-questions-ai) |
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Integrações Externas
|
|
85
|
+
|
|
86
|
+
| Secret | Finalidade | Projetos | Observações |
|
|
87
|
+
|--------|-----------|----------|-------------|
|
|
88
|
+
| `CLICKSIGN_SANDBOX_API_KEY` | API Key do Clicksign (ambiente sandbox) | **Admin** (clicksign) | Assinatura eletrônica de documentos |
|
|
89
|
+
| `ELASTIC_URL` | URL do cluster Elasticsearch | **Admin** (audit-ship) | Destino dos logs de auditoria |
|
|
90
|
+
| `ELASTIC_API_KEY` | API Key do Elasticsearch | **Admin** (audit-ship) | Autenticação no cluster |
|
|
91
|
+
| `HUBSPOT_PRIVATE_APP_TOKEN` | Token de app privado do HubSpot | **Cockpit** (hubspot-tickets) | No código é lido como `HUBSPOT_ACCESS_TOKEN` via `Deno.env.get()` |
|
|
92
|
+
| `SENSITIVE_DATA_KEY` | Chave AES-GCM para criptografia de dados sensíveis (CPF, etc.) | **Colaboradores** (sensitive-data, api-export-sensitive-data, entra-id-sync), **Matriz de Foco** (generic-app-scan, generic-app-secrets, migrate-legacy-tokens) | Chave hex de 256 bits |
|
|
93
|
+
| `VITE_QUALIEX_API_URL` | URL da API Qualiex | **Admin** (validate-token), **Cockpit** (_shared/auth), **Treinamentos** (docs-process-outdated, notify-leader) | Configuração de ambiente (prod vs dev) |
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Secrets sem Referência no Código
|
|
98
|
+
|
|
99
|
+
| Secret | Status | Recomendação |
|
|
100
|
+
|--------|--------|-------------|
|
|
101
|
+
| `VITE_BUILDER_API_KEY` | Nenhuma edge function ou código frontend referencia esta secret | ⚠️ Candidata a remoção — verificar se algum serviço externo a utiliza antes de deletar |
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Secrets Específicas de Projetos (não listadas acima)
|
|
106
|
+
|
|
107
|
+
Estas secrets são usadas apenas por projetos específicos mas vivem no mesmo projeto Supabase:
|
|
108
|
+
|
|
109
|
+
| Secret (no código) | Projeto | Finalidade |
|
|
110
|
+
|---------------------|---------|-----------|
|
|
111
|
+
| `TRAININGS_SERVICE_API_KEY` | **Treinamentos** | Auth service-to-service entre edge functions |
|
|
112
|
+
| `HUBSPOT_ACCESS_TOKEN` | **Cockpit** | Mesmo valor de `HUBSPOT_PRIVATE_APP_TOKEN` (nome diferente no `Deno.env.get`) |
|
|
113
|
+
|
|
114
|
+
> **Nota:** Estas secrets podem não estar na lista do dashboard se foram adicionadas diretamente ou por outro projeto. Verifique no [painel de secrets](https://supabase.com/dashboard/project/ccjfvpnndclajkleyqkc/settings/functions).
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Referências
|
|
119
|
+
|
|
120
|
+
- [Painel de Secrets do Supabase](https://supabase.com/dashboard/project/ccjfvpnndclajkleyqkc/settings/functions)
|
|
121
|
+
- [Plano de Segurança (Fase 2)](./../.lovable/plan.md)
|
|
122
|
+
- [Inventário de Storage Buckets](./STORAGE_BUCKETS.md)
|