mirror of
https://github.com/melgarafael/DeskcommCRM.git
synced 2026-10-02 01:28:34 +08:00
fix(#184): o gate de idempotencia deixa de ser decorativo, e a doc para de mentir
O passo "modo UPDATE" do scripts/test-db.sh re-aplicava o baseline SEM ON_ERROR_STOP e chamava isso de "provando idempotencia" (README:336). Nao era: sem a flag o psql segue apos cada erro, entao o passo saia VERDE com 301 erros dentro — inclusive os 4 `policy already exists` que faziam uma mudanca de RLS do apendice nao chegar ao clone. O update.sh tambem roda sem a flag e filtra esses erros como benignos, entao nem ele nem o gate viam o defeito. A flag e a diferenca entre "re-aplicar terminou" e "re-aplicar nao errou". PROVA de que o gate agora morde: revertendo o baseline para o de ontem, TEST_DB_EXIT=3 ==> modo UPDATE: re-aplicando baseline.sql COM ON_ERROR_STOP=1 psql:<stdin>:1918: ERROR: multiple primary keys for table "ai_agent_runs" O mesmo arquivo que passava verde. Com o baseline consertado: EXIT=0, 100 arquivos, 718 passed. DOC: - README e docs/SETUP ganham o `create extension` (vector/citext/pg_trgm) ANTES do baseline. So o deploy-selfhost tinha; a ausencia nos outros dois e a causa imediata do relato da #184 (`type public.vector does not exist`). - docs/deploy-selfhost para de mandar re-aplicar "sem a flag ON_ERROR_STOP". Essa instrucao estava certa quando o arquivo nao era idempotente; agora ela ensina a esconder erro de verdade. - A afirmacao "O baseline.sql e idempotente" passou a ser VERDADE e ganhou a data e o numero da issue, para o proximo leitor saber desde quando. - README:336 perde o "618 invariantes em 98 arquivos": o numero estava podre (sao 720 casos em 100 arquivos) e nao foi atualizado de proposito — e a quarta fonte da mesma verdade, e o proprio job ja conta. Mesma licao do numero de specs do e2e, que apodreceu tres vezes. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012RfAjBEKuCkL6tpUo77kUe
This commit is contained in:
co-authored by
Claude Opus 5
parent
bc3d610fae
commit
a8b0928064
@@ -283,6 +283,14 @@ docker compose up -d # WAHA local (opcional em dev sem WhatsApp)
|
||||
# O schema real vive no baseline.sql, o mesmo que o install.sh aplica na VPS.
|
||||
# `supabase db push` "passa" e deixa o banco vazio.
|
||||
supabase link --project-ref <seu-ref>
|
||||
|
||||
# Num projeto Supabase NOVO, habilite antes as extensões que o schema usa —
|
||||
# sem elas o baseline para em `type public.vector does not exist`.
|
||||
psql "$SUPABASE_DB_URL" -v ON_ERROR_STOP=1 -c \
|
||||
'create extension if not exists vector with schema public;
|
||||
create extension if not exists citext with schema public;
|
||||
create extension if not exists pg_trgm with schema public;'
|
||||
|
||||
psql "$SUPABASE_DB_URL" -v ON_ERROR_STOP=1 -f supabase/baseline.sql
|
||||
|
||||
pnpm dev
|
||||
@@ -333,7 +341,7 @@ pnpm test:e2e # Playwright (requer dev server)
|
||||
| Check | O que faz |
|
||||
|---|---|
|
||||
| `verify` | typecheck + lint + `lint:channels` + `test:unit` + `test:shell` |
|
||||
| `invariants` | sobe um Postgres limpo, aplica o `baseline.sql` em modo **install** (`ON_ERROR_STOP=1`) e depois em modo **update** (provando idempotência), e roda **618 invariantes em 98 arquivos** — RBAC, atribuição, escopo, roteamento, follow-up, webhooks e automações |
|
||||
| `invariants` | sobe um Postgres limpo, aplica o `baseline.sql` em modo **install** e depois em modo **update** — as duas passadas com `ON_ERROR_STOP=1`, que é o que torna a segunda uma prova de idempotência e não só um "terminou" —, e roda os invariantes de RBAC, atribuição, escopo, roteamento, follow-up, webhooks e automações |
|
||||
| `build-and-size` | `pnpm build` em Node 22 |
|
||||
| `e2e` | sobe Supabase local, aplica o `baseline.sql` e roda **44 das 45 specs** Playwright pelo frontend |
|
||||
|
||||
|
||||
+9
-1
@@ -113,7 +113,15 @@ supabase login
|
||||
# Conecte ao seu projeto (project-ref está na URL do dashboard)
|
||||
supabase link --project-ref <seu-project-ref>
|
||||
|
||||
# Aplica o SCHEMA — o baseline, não a cadeia de migrations
|
||||
# Num projeto Supabase NOVO, habilite antes as extensões que o schema usa —
|
||||
# sem elas o baseline para em `type public.vector does not exist`.
|
||||
psql "$SUPABASE_DB_URL" -v ON_ERROR_STOP=1 -c \
|
||||
'create extension if not exists vector with schema public;
|
||||
create extension if not exists citext with schema public;
|
||||
create extension if not exists pg_trgm with schema public;'
|
||||
|
||||
# Aplica o SCHEMA — o baseline, não a cadeia de migrations.
|
||||
# Re-aplicar é seguro e não erra: o arquivo é idempotente (issue #184).
|
||||
psql "$SUPABASE_DB_URL" -v ON_ERROR_STOP=1 -f supabase/baseline.sql
|
||||
```
|
||||
|
||||
|
||||
@@ -65,13 +65,20 @@ psql "$SUPABASE_DB_URL" -v ON_ERROR_STOP=1 -f supabase/baseline.sql
|
||||
```
|
||||
|
||||
O `baseline.sql` é idempotente — cria o CRM inteiro + as tabelas do agente
|
||||
(migrations 0001→atual).
|
||||
(migrations 0001→atual). Para **atualizar** uma instalação existente, rode o mesmo
|
||||
comando de novo, **com a mesma flag**: re-aplicar não erra.
|
||||
|
||||
Isso passou a ser verdade em 2026-08-13 (issue #184). Antes o arquivo era
|
||||
idempotente só em parte — as tabelas tinham `IF NOT EXISTS`, índices, constraints e
|
||||
policies não —, e re-aplicar com `ON_ERROR_STOP=1` parava em
|
||||
`multiple primary keys for table "ai_agent_runs"`. Sem a flag saía "verde" com 301
|
||||
erros dentro, e quatro deles faziam uma mudança de RLS **não chegar** ao clone.
|
||||
O gate que prova isso é o job `invariants`, que agora re-aplica com a flag.
|
||||
|
||||
> **Usando Postgres próprio em vez de Supabase?** Aplique ANTES o
|
||||
> `scripts/selfhost-prelude.sql` (roles/schemas/extensões que o dump supõe).
|
||||
> Limite: auth/storage viram stubs — o login do app exige Supabase real; o
|
||||
> worker/agente funcionam integralmente. Para ATUALIZAR uma instalação existente, rode o mesmo
|
||||
comando de novo (sem a flag `ON_ERROR_STOP`): só o que falta é aplicado.
|
||||
> worker/agente funcionam integralmente.
|
||||
|
||||
Crie também a role dedicada do worker (mais seguro que usar o superusuário):
|
||||
|
||||
|
||||
+13
-3
@@ -218,9 +218,19 @@ echo "==> modo INSTALL: aplicando baseline.sql com ON_ERROR_STOP=1"
|
||||
psql_install < "$BASELINE"
|
||||
echo " ✓ install ok"
|
||||
|
||||
echo "==> modo UPDATE: re-aplicando baseline.sql sem ON_ERROR_STOP (idempotência)"
|
||||
docker exec -i "$CONTAINER" psql -U postgres -d postgres -q -f - < "$BASELINE" >/dev/null
|
||||
echo " ✓ update ok (re-apply terminou; erros tolerados por contrato)"
|
||||
# COM `ON_ERROR_STOP=1`, e é isto que torna o passo uma prova (issue #184).
|
||||
#
|
||||
# Antes ele re-aplicava SEM a flag e chamava o resultado de "idempotência". Não
|
||||
# era: sem a flag o psql segue após cada erro, então o passo saía verde com 301
|
||||
# erros dentro — inclusive os 4 `policy already exists` que faziam uma mudança de
|
||||
# RLS do apêndice NÃO chegar ao clone. O `update.sh` também roda sem a flag e
|
||||
# filtra esses erros como benignos, então nem ele nem este gate viam o defeito, e
|
||||
# o README dizia "provando idempotência" apontando para cá.
|
||||
#
|
||||
# A flag é a diferença entre "re-aplicar terminou" e "re-aplicar não errou".
|
||||
echo "==> modo UPDATE: re-aplicando baseline.sql COM ON_ERROR_STOP=1 (idempotência de verdade)"
|
||||
psql_install < "$BASELINE"
|
||||
echo " ✓ update ok (zero erro na re-aplicação)"
|
||||
|
||||
echo "==> invariantes: vitest (tests/invariants)"
|
||||
TEST_DB_CONTAINER="$CONTAINER" vitest run --config vitest.db.config.ts "$@"
|
||||
|
||||
Reference in New Issue
Block a user