Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
a48c5e5
docs(valor): trilha de valor F1-F3 e pente fino E0-E2, com os diagnós…
BarryBits Aug 18, 2026
0f00745
feat(partes-relacionadas): liga o QSA no cadastro de sócios e varre a…
BarryBits Aug 18, 2026
ef50279
feat(categorizacao): regra por token contido — 1.358 decisões viram 1
BarryBits Aug 18, 2026
0b2a1f0
docs(atros-v3): SaaS sem consultor — o cliente é a autoridade do próp…
BarryBits Aug 18, 2026
6bfcadd
docs(valor): handoff — onde a próxima sessão pega, e o que a virada S…
BarryBits Aug 18, 2026
263a2f4
fix(build): declara o ProjetoRef que faltava — o build desta branch e…
BarryBits Aug 18, 2026
96e9bbb
feat(saas): a autoridade vem do vínculo, não do papel — o dono opera …
BarryBits Aug 18, 2026
22a9816
fix(seguranca): fecha o vazamento multi-tenant — 31 policies liberava…
BarryBits Aug 18, 2026
d4d3129
fix(cockpit): lê as ações do plano VIGENTE, não do projeto inteiro
BarryBits Aug 18, 2026
66771e8
chore(faxina): G-05 e G-08 — comentários que mentiam e o categorizado…
BarryBits Aug 18, 2026
2850f91
docs(banco): re-dump de 18/ago + handoff da sessão — o que foi feito,…
BarryBits Aug 18, 2026
4bd578b
docs(pente-fino): handoff lidera com a retomada, e duas etapas que pa…
BarryBits Aug 18, 2026
2425c6d
fix(copy): o texto ainda mandava falar com um consultor que o modelo …
BarryBits Aug 18, 2026
c8395c5
docs(pente-fino): a varredura de copy fechada, e a regra que ela deixou
BarryBits Aug 18, 2026
72275f8
feat(pente-fino): E3 — o fechamento, e o numero que o sistema pede a …
BarryBits Aug 18, 2026
60402c7
docs(pente-fino): E4-E8 fechadas — o veredito, os 52 achados e por on…
BarryBits Aug 20, 2026
2633ae8
feat(a1): a corrente do cliente vai do extrato à meta travada
BarryBits Aug 20, 2026
4401a8a
docs(pente-fino): o plano de correção — a jornada do cliente vira a l…
BarryBits Aug 20, 2026
2849b23
docs(handoff): a A1 executada — onde a próxima sessão pega, e as arma…
BarryBits Aug 20, 2026
cf26d0b
fix(e5-b): a meta do pacing vem do plano vigente, nao do rascunho mai…
BarryBits Aug 20, 2026
4125544
feat(e3-b): quem nao tem o bordero declara a taxa, e o mes fecha
BarryBits Aug 20, 2026
2a5251d
chore(banco): ESTRUTURA.md em dia — o gate estava vermelho desde a A1
BarryBits Aug 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,19 @@ do DRE). Mapa do código vivo × a spec (o que serve/aposenta/falta):

## Trilha atual

Reposicionamento financeiro client-first — plano faseado `docs/atros-v3/fin-07`.
Fases 0–4 consolidadas em `origin/main` (migrations aplicadas no remoto).
Próximo: Fase 5 (motor por evento). Handoff canônico: o mais recente
`docs/atros-v3/handoff-*.md`.
Execução do pente fino da jornada do cliente. Handoff canônico: o mais recente
`docs/atros-v3/handoff-*.md` — hoje **`handoff-2026-08-20b-a1-executada.md`**, que
diz **onde pegar** (E3-B, com a conta e a armadilha) e o roteiro do check ao vivo.

**A lei do trabalho é `docs/valor/pente-fino/PLANO-DE-CORRECAO.md`** — e dentro dele o
**§0: a jornada canônica do cliente em 14 passos**. Ela é a régua: o que não serve a
jornada, sai do backlog. O diagnóstico que a originou (52 achados) está em
`docs/valor/pente-fino/RELATORIO-TECNICO.md` (autocontido), mas **a ordem dele foi
substituída** pelo plano — a decisão D1 (autonomia total do cliente) inverteu as
prioridades.

**Estado em 20/ago:** a corrente vai do extrato à meta travada. Falta o **E3-B**
(antecipação) e o **check ao vivo** — toda a prova até aqui é estática.

## Ambiente

Expand Down
89 changes: 46 additions & 43 deletions db/ESTRUTURA.md

Large diffs are not rendered by default.

98 changes: 92 additions & 6 deletions db/snapshot/SNAPSHOT.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@

| Campo | Valor |
|---|---|
| **Status** | 🟢 **AUTORITATIVO** — inclui `giro_monthly_snapshots` (G2 do capital de giro), aplicada no SQL Editor e conferida neste dump. |
| Dump gerado em | **2026-08-17** (`supabase db dump --linked`, `--role-only` e `--data-only`, projeto `tdlxqqgechxhkygdmsxq`, CLI v2.84.0) |
| Commit git no dump | `main` `a21c084` + working tree (a migration `20260817000000` está aplicada no remoto e **ainda não commitada**) |
| `ultima_migration_incluida` | **`20260817000000`** |
| `ultima_migration_no_repo` | **`20260817000000`** |
| **Veredito** | 🟢 **autoritativo** — `schema.sql` **15.206 linhas**; `roles.sql` **13** (diff vazio); `seed.sql` **25.095**. |
| **Status** | 🔴 **OBSOLETO desde 2026-08-20** — TRÊS migrations posteriores a este dump, **todas já aplicadas no remoto**. Duas aplicadas DEPOIS deste dump (`20260820010000` readiness para de ler a escada morta · `20260820020000` a view perde o placar das 30 análises). **Não tratar `schema.sql` como verdade até o re-dump.** O que mudou: `get_dre_readiness` deriva `publish_status` da contagem de meses fechados; `vw_company_context` perdeu `analyses_completed` e `analyses_total`. Antes disso era 🟢 AUTORITATIVO — inclui as 6 migrations de 18/ago: `categorization_rules.match_type`, as 3 fatias do **SaaS sem consultor** e os 2 lotes do **fechamento do vazamento multi-tenant**. Todas aplicadas no SQL Editor e conferidas neste dump. |
| Dump gerado em | **2026-08-18** (`supabase db dump --linked`, `--role-only` e `--data-only`, projeto `tdlxqqgechxhkygdmsxq`, CLI v2.84.0) |
| Commit git no dump | `feat/partes-relacionadas-e-regra-token` `6bfcadd` + working tree (as **6** migrations estão aplicadas no remoto e **ainda não commitadas** — decisão: consertar o que está aberto antes de commitar) |
| `ultima_migration_incluida` | **`20260818050000`** |
| `ultima_migration_no_repo` | **`20260820030000`** ⚠️ **> incluída ⇒ obsoleto** |
| **`20260820030000` (E3-B)** | ✅ **aplicada no remoto em 2026-08-20 e conferida no banco vivo.** Amplia o CHECK de `dre_detalhamento.modo` com `'por_taxa'`. Prova não-destrutiva (insert com `project_id` inexistente, lendo o código do erro): `modo='por_taxa'` → `23503` (FK — passou pelo CHECK) e, como controle, `modo='modo_que_nao_existe'` → `23514` (recusado). Nenhuma linha escrita. |
| **Veredito** | 🔴 **obsoleto** (era 🟢 até 18/ago) — `schema.sql` **15.054 linhas**; `roles.sql` **13** (diff vazio); `seed.sql` **25.138**. Gate: `npx tsx scripts/saas/verificar-dump.ts`. |

## A regra, depois da baseline de 2026-08-11

Expand All @@ -26,6 +27,91 @@ O mapa legível de tudo isso é [`db/ESTRUTURA.md`](../ESTRUTURA.md), **gerado**
`npx tsx scripts/db/gerar-estrutura.ts`. Depois de todo re-dump, rode o gerador: o
diff do `.md` mostra exatamente o que mudou no banco.

### Validação do re-dump (2026-08-18b, fechamento do vazamento multi-tenant)

Migrations `20260818040000` (escopa 9 tabelas de projeto) e `20260818050000` (`projects`,
`profiles`, `class_access`). Fecham as policies que liberavam acesso por **estar logado**
(`auth.role() = authenticated`, `USING (true)`) — que, somando-se por OR, anulavam o escopo por
vínculo das vizinhas.

| Objeto | Antes | Depois | Δ |
|---|--:|--:|--:|
| Tabelas | 113 | **113** | 0 |
| Views | 13 | **13** | 0 |
| Funções · Triggers · Índices | 73 · 92 · 257 | **iguais** | 0 |
| **Policies** | 362 | **353** | **−9** |
| Tabelas com RLS | 113 | **113 de 113** | 0 |

`schema.sql` 15.043 → **15.054 linhas**. `roles.sql` diff vazio. `seed.sql` **25.138**.

**O −9 foi previsto antes do dump e bateu exato**: −7 no lote 1 (sete tabelas trocaram 2 policies
abertas por 1 escopada; `dre_subcategories` e `activity_log` saíram no zero a zero) e −2 no lote 2
(`projects` perdeu 3 e ganhou 1). Prever o delta antes é o que separa "a migration rodou" de "a
migration fez o que eu quis".

**Gate contra a realidade** (`npx tsx scripts/saas/verificar-dump.ts`, lê este dump):

- **0** policies abertas por estar logado fora de catálogo global — das 8 que restam, todas são
SELECT em tabela sem chave de tenant (`dre_categories`, `financial_benchmarks`, `class_*`,
`library_content`, `subcategories`, `categorization_patterns`): conhecimento compartilhado da
casa, não dado de cliente;
- **108** policies na view `project_access` (eram 97 depois das fatias 1–4).

**A armadilha que a policy de `profiles` teve de desviar.** `project_members` tem RLS own-row
(`project_members_self`), então subselect nela dentro de policy roda como o usuário e procurar o
vínculo de OUTRA pessoa volta **vazio, sem erro**. A policy de colega-de-projeto usa a view
`project_access` (roda como owner) de propósito. Escrita com a tabela, passaria no review e negaria
tudo em silêncio. `projects_members` pode usar a tabela porque filtra `pm.user_id = auth.uid()`.

**Ninguém foi trancado do lado de fora.** A conferência de quem perdeu o bypass por papel global
voltou **vazia**: não existe nenhum `profiles.role` em `(consultor,sdr)` no banco. O bypass que
aparecia em 120 lugares não protegia uma única pessoa — o que, retroativamente, confirma a decisão
do SaaS sem consultor.

### Validação do re-dump (2026-08-18, SaaS sem consultor — fatias 1 a 4)

Quatro migrations aplicadas no SQL Editor: `20260818000000` (`categorization_rules.match_type`,
da leva de regra por token) e as três do reposicionamento de acesso —
`20260818010000` (o dono gera e trava a própria meta), `20260818020000` (view `project_access`
+ 139 policies) e `20260818030000` (o dono conserta o próprio cadastro).

| Objeto | Antes | Depois | Δ |
|---|--:|--:|--:|
| Tabelas | 113 | **113** | 0 |
| **Views** | 12 | **13** | **+1** |
| Funções | 73 | **73** | 0 |
| Triggers | 92 | **92** | 0 |
| **Policies** | 362 | **362** | **0** |
| Tabelas com RLS | 113 | **113 de 113** | 0 |
| Índices | 257 | **257** | 0 |

`roles.sql`: diff vazio. `schema.sql` **15.206 → 15.043 linhas** — encolheu porque 139 policies
perderam um disjunto inteiro. `seed.sql` 25.130 → **25.138**.

**O número que prova a leva é `Policies +0`.** Foram 146 pares `DROP`+`CREATE` e o saldo é zero:
nenhuma policy se perdeu no caminho, nenhuma virou duplicata. Numa troca mecânica desse tamanho é
exatamente o que pode dar errado sem ninguém ver — policy dropada em tabela com RLS ligada não dá
erro, só passa a negar tudo em silêncio.

**O dump confirma a intenção, não só a migration.** `npx tsx scripts/saas/verificar-dump.ts` lê
`schema.sql` e fecha as contas contra a realidade:

- **0** policies ainda apontando pra `client_project_access`;
- **97** policies passaram a usar `project_access` (era a previsão exata do transformador);
- **4** policies ainda mencionam `consultor` — e são as 4 previstas (`commercial_*` × 3 e
`leads_owner_insert`), staff-only por desenho, deixadas de fora porque remover o bypass delas
não deixaria nenhum disjunto, ou seja, negariam tudo;
- a view `project_access` existe, **não** filtra `role = cliente` (senão excluiria o consultor) e
**não** tem `security_invoker` — roda como owner, igual à irmã, senão as 97 policies passariam a
enxergar só o próprio vínculo e quebrariam em silêncio.

No `ESTRUTURA.md` o diff é de 6 linhas: views 12→13, `project_access` entra na lista de views sem
`security_invoker` (deliberado) e `project_members` cai de 33 para 32 usos em `src/` — é o `.from()`
que sumiu quando `canOperateProject` passou a delegar pra `canAccessProject`.

Os 4 `.from()` para tabela inexistente (`budget_items`, `budgets`, `pulse_checks`,
`system_notifications`) seguem abertos desde o marco zero — não são desta leva.

### Validação do re-dump (2026-08-17, `giro_monthly_snapshots` — G2)

Migration `20260817000000_giro_monthly_snapshots.sql`, aplicada no SQL Editor. Cria a
Expand Down
Loading
Loading