PR#2 (A): escrita via PostgREST nativo + RLS (6 guardas)#525
Conversation
Estende o rest-native para insert/update/delete/upsert/batch_insert, com as 6 guardas do Plano A: - A1 sessão autenticada → delegada ao RLS (supabase-js anexa o JWT). - A2 update/delete SEM filtro/id → proibido (proteção contra mutação em massa). - A3 escrita SEMPRE na tabela BASE (WRITE_TABLE_ALIASES), nunca na view v_*_public read-only — NÃO reusa TABLE_ALIASES de leitura. - A4 `.select()` de volta; insert OK com select-back vazio (RLS de SELECT) ainda é sucesso. - A5 remap EN→PT no payload e filtros (COLUMN_ALIASES_BY_TABLE), evita 400. - Sem retry em escrita (evita insert/upsert duplicado); erro real PROPAGA LOUD. Novos exports: isRestNativeWriteEligible, executeRestNativeWrite, tryExecuteRestNativeWrite. Whitelist de escrita = as 13 tabelas base usadas pelos 12 hooks de admin. Testes: src/lib/external-db/__tests__/rest-native-write.test.ts — 12 casos cobrindo todas as 6 guardas + elegibilidade + propagação LOUD + batch array remap.
…Db + delete - invokeExternalDb: novo WRITE fast-path (isRestNativeWriteEligible → tryExecuteRestNativeWrite) logo após o READ fast-path. Sucesso retorna; erro de RLS/validação PROPAGA LOUD; tabela/op não-elegível cai no WriteUnavailableError. - invokeExternalDbDelete: roteia REST nativo (RLS) primeiro; fallback bridge; senão LOUD. - bridge.test.ts: os 3 testes de contrato da bridge passam a usar tabela NÃO-whitelisted (audit_logs) — onde a bridge continua sendo o caminho — preservando a intenção (o caminho REST nativo é coberto por rest-native-write.test.ts). Também corrige 2 falhas pré-existentes no arquivo (string de acento + chave auth duplicada). tsc --noEmit limpo; vitest: bridge.test.ts + __tests__/ = 32/32 verdes. Depende do PR#3 (RLS WITH CHECK) para a escrita efetivamente persistir; sem ele, a escrita falha LOUD (honesto), nunca silenciosa.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. 🗂️ Base branches to auto review (1)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
…destrutivo) O passo destrutivo do PR#4 (deletar a Edge Function + limpar kill-switch) é GATED em "A verde" (merge de #525/#527 + soak em prod) — A ainda está em draft. Em vez de disparar a remoção fora de ordem (que quebraria o fallback do main e o rollback do PR#2), este PR entrega o runbook com a ordem correta e duas armadilhas documentadas: 1. fail-open do kill-switch: DELETE da linha RELIGA a bridge (enabled=true) — nunca deletar a linha enquanto o cliente ainda a lê. 2. main ainda usa a bridge como fallback até o PR#2 mergear — não deletar a função antes. Inclui ordem de execução, critérios de soak e rollback. Nenhuma alteração de código ou DDL; nada destrutivo é executado aqui.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
…atual (#524) Rebase sobre o main atual (inclui #526, telemetria recordBridgeCall) para eliminar o conflito do #524. Branch recriada a partir do main + este \u00fanico commit. - WRITE_OPERATIONS + isWriteOperation + WriteUnavailableError (novos).\n- invokeExternalDb: escrita com bridge OFF/kill-switch/CORS agora THROW (ap\u00f3s reportSilentEmpty + recordCall + recordKillSwitchHit do #526); leitura segue retornando vazio.\n- invokeExternalDbDelete: THROW em vez de no-op silencioso.\n- index.ts: exporta WriteUnavailableError e isWriteOperation. Toda a telemetria do #526 preservada (7x recordCall). tsc --noEmit limpo. Escopo do PR#1 = apenas bridge.ts + index.ts (rest-native writes + testes ficam no PR#2/#525).
Rebase limpo sobre main atual (inclui #526 telemetria, #527 RLS, #530). - bridge.ts: WRITE_OPERATIONS + isWriteOperation() + WriteUnavailableError; escrita com bridge OFF / kill-switch / CORS agora LANCA em vez de retornar vazio. Leitura mantem vazio silencioso. Telemetria do #526 preservada (recordBridgeCall/recordKillSwitchHit) — recordCall roda ANTES do throw. - index.ts: exporta isWriteOperation + WriteUnavailableError. Apenas estes 2 arquivos (rest-native writes + testes ficam no #525).
…A) (#531) * PR#1 (C): escrita falha LOUD em vez de no-op silencioso Rebase limpo sobre main atual (inclui #526 telemetria, #527 RLS, #530). - bridge.ts: WRITE_OPERATIONS + isWriteOperation() + WriteUnavailableError; escrita com bridge OFF / kill-switch / CORS agora LANCA em vez de retornar vazio. Leitura mantem vazio silencioso. Telemetria do #526 preservada (recordBridgeCall/recordKillSwitchHit) — recordCall roda ANTES do throw. - index.ts: exporta isWriteOperation + WriteUnavailableError. Apenas estes 2 arquivos (rest-native writes + testes ficam no #525). * test(A): cobertura do caminho de escrita REST nativo (Plano A) — 12 testes das 6 guardas + remap + LOUD * feat(A): escrita REST nativo (Plano A) em rest-native.ts — 6 guardas, remap EN→PT, fail LOUD; preserva telemetria #526 * style(A): normaliza separadores de comentário em rest-native.ts (byte-exato ao artefato validado) * style(A): separadores uniformes em rest-native.ts (determinístico, byte-exato 32a30c5c) * feat(A)+test: wire write fast-path em bridge.ts (tryExecuteRestNativeWrite) + corrige bridge.test.ts (evita REST path no mock) — 23/23 verde
…destrutivo) (#528) O passo destrutivo do PR#4 (deletar a Edge Function + limpar kill-switch) é GATED em "A verde" (merge de #525/#527 + soak em prod) — A ainda está em draft. Em vez de disparar a remoção fora de ordem (que quebraria o fallback do main e o rollback do PR#2), este PR entrega o runbook com a ordem correta e duas armadilhas documentadas: 1. fail-open do kill-switch: DELETE da linha RELIGA a bridge (enabled=true) — nunca deletar a linha enquanto o cliente ainda a lê. 2. main ainda usa a bridge como fallback até o PR#2 mergear — não deletar a função antes. Inclui ordem de execução, critérios de soak e rollback. Nenhuma alteração de código ou DDL; nada destrutivo é executado aqui.
Empilha sobre #524 (PR#1/C). Base =
fix/c-loud-writespara o diff mostrar só o incremento do Plano A.O que faz
Reintroduz o caminho de escrita real, agora via PostgREST nativo + RLS (independente da bridge/kill-switch), substituindo o no-op silencioso que o PR#1 passou a sinalizar com erro.
rest-native.tsganhainsert/update/delete/upsert/batch_insertcom as 6 guardas:update/deleteSEM filtro/id → proibido (proteção contra mutação em massa).WRITE_TABLE_ALIASES), nunca na viewv_*_publicread-only — não reusa oTABLE_ALIASESde leitura..select()de volta; insert OK com select-back vazio (RLS de SELECT) ainda é sucesso.COLUMN_ALIASES_BY_TABLE), evita 400.bridge.ts: WRITE fast-path eminvokeExternalDb(após o READ fast-path) +invokeExternalDbDeleteroteando REST nativo primeiro. Whitelist de escrita = as 13 tabelas base dos 12 hooks de admin.Validação
tsc --noEmit: 0 erros no source.vitest:rest-native-write.test.ts(12 casos cobrindo as 6 guardas + elegibilidade + propagação LOUD + batch remap) +bridge.test.ts+__tests__/= 32/32 verdes.bridge.test.ts: 3 testes de contrato da bridge repassados para tabela não-whitelisted (audit_logs, onde a bridge ainda é o caminho); 2 falhas pré-existentes corrigidas de brinde.Dependência
Para a escrita persistir, precisa do PR#3 (RLS WITH CHECK por role). Sem o PR#3, a escrita falha LOUD (honesto) — nunca silenciosa. Mergear #3 junto/antes.
Série: #1 (C) → #2 (A núcleo) → #3 (A RLS) → #4 (aposentar bridge).
Summary by cubic
Habilita escrita nativa via
PostgRESTcom RLS (Plano A), independente da bridge/kill-switch, substituindo o no‑op por operações reais com erro “loud”. Adiciona fast‑path de escrita e guardas para segurança e compatibilidade.New Features
WRITE_TABLE_ALIASES(nunca emv_*_public)..select()após a escrita; insert com select-back vazio ainda é sucesso. Remapeia EN→PT no payload e filtros viaCOLUMN_ALIASES_BY_TABLE; sem retry; erros propagam “loud”.invokeExternalDbeinvokeExternalDbDeletetentam o caminho nativo primeiro; bridge segue para tabelas fora da whitelist. Testes cobrindo elegibilidade, guardas e batch;bridge.test.tsajustado paraaudit_logs.Migration
Written for commit 8f8205f. Summary will update on new commits.