Skip to content

PR (C+A): escrita falha LOUD + caminho REST nativo de escrita (Plano A)#531

Merged
adm01-debug merged 6 commits into
mainfrom
fix/c-loud-writes
May 30, 2026
Merged

PR (C+A): escrita falha LOUD + caminho REST nativo de escrita (Plano A)#531
adm01-debug merged 6 commits into
mainfrom
fix/c-loud-writes

Conversation

@adm01-debug
Copy link
Copy Markdown
Owner

@adm01-debug adm01-debug commented May 30, 2026

Contexto

Bridge OFF (edge_external_db_bridge: enabled=false, rollout=100 → REST nativo 100%) + rest-native cobrindo só SELECT = toda ESCRITA (insert/update/delete/upsert/batch_insert) por invokeExternalDb/invokeExternalDbSingle/invokeExternalDbDelete retornava {records:[],count:0} silenciosamente. A UI dizia "salvo/excluído com sucesso" sem persistir — corrupção silenciosa.

Este PR substitui o #524 (que ficou dirty quando o main avançou e não pôde ser reaberto após recriação da branch). Refeito limpo sobre o main atual e carrega o escopo completo C+A — o conteúdo do #525 foi reconstruído aqui sobre o main vigente.

Mudanças

C — falha LOUD (bridge.ts + index.ts):

  • WriteUnavailableError (tipado) + helper isWriteOperation().
  • invokeExternalDb: escrita com bridge OFF / kill-switch / CORS agora lança em vez de retornar vazio. SELECT mantém vazio silencioso (REST nativo é o caminho real).
  • invokeExternalDbDelete: lança em vez de return silencioso.
  • index.ts exporta os novos símbolos.

A — escrita REST nativo (rest-native.ts + bridge.ts fast-path):

  • executeRestNativeWrite / tryExecuteRestNativeWrite / isRestNativeWriteEligible com 6 guardas: (A1) auth delegada ao RLS; (A2) update/delete sem filtro/id proibido (anti-mutação em massa); (A3) sempre tabela BASE (WRITE_TABLE_ALIASES), nunca view v_*_public; (A4) .select() de volta (select-back vazio por RLS ainda é sucesso); (A5) remap EN→PT no payload e filtros (tecnicas_gravacao). Sem retry em escrita; erros (RLS negada/validação) PROPAGAM LOUD.
  • invokeExternalDb/invokeExternalDbDelete chamam o fast-path de escrita antes da bridge; tabela/op não-elegível cai no WriteUnavailableError honesto.

Preserva a telemetria do #526 (recordBridgeCall/recordKillSwitchHit, com recordCall ANTES do throw) e convive com #527 (RLS, já no main) e #530.

Validação local

  • tsc --noEmit: 0 erros (apenas 2 pré-existentes em node_modules/@vitejs/plugin-react-swc, fora de escopo).
  • vitest: 23/23 verde — 12 de rest-native-write.test.ts (Plano A) + 11 de bridge.test.ts (inclui os 2 antes falhando).
  • git merge-tree vs main atual: 0 conflitos.

Série

Este PR (C+A) → #527 (RLS) já mergeado → #528 (aposentar bridge, gated, só após soak).
Ordem de merge recomendada: #531 primeiro; #528 permanece gated (não-destrutivo). Atenção ao fail-open do kill-switch (deletar a linha re-habilita a bridge): rollback do Plano A = UPDATE public.system_kill_switches SET enabled=true WHERE switch_name='edge_external_db_bridge'.

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).
Copilot AI review requested due to automatic review settings May 30, 2026 17:25
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 30, 2026

Walkthrough

A ponte de banco de dados externo agora classifica explicitamente operações de escrita e lança WriteUnavailableError quando indisponíveis, em vez de falhar silenciosamente. O contrato de tipo e publicação de APIs ocorrem primeiro, seguidos pela aplicação de erros tipados ao bridge, e validados por uma suite completa de testes.

Changes

Prevenção de falhas silenciosas em escrita

Layer / File(s) Summary
Contrato de tipo e classificação de operações de escrita
src/lib/external-db/bridge.ts, src/lib/external-db/index.ts
Exporta isWriteOperation(op) para classificar mutations (insert, update, delete, batch_insert) e introduz WriteUnavailableError com campos table e operation capturando contexto. Ambas reexportadas no barrel.
Propagação de erro na invocação do bridge
src/lib/external-db/bridge.ts
invokeExternalDb() agora lança WriteUnavailableError para writes quando kill-switch ativa ou erros CORS/rede ocorrem (non-writes ainda retornam empty); invokeExternalDbDelete() lança ao invés de retornar silenciosamente; telemetria continua registrada.
Testes de escrita nativa REST
src/lib/external-db/__tests__/rest-native-write.test.ts
Suite Vitest com mock chainable do Supabase validando elegibilidade por whitelist, escrita em tabela base, remapeamento EN→PT de payload, rejeição de mutação em massa sem id, empty select-back, propagação LOUD de erros RLS, e batch_insert com remapeamento de array.

Sequence Diagram(s)

Nenhum diagrama necessário nesta seção.


🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed O título descreve com precisão as mudanças principais: lançamento de erros em escritas (LOUD) e implementação do caminho REST nativo para operações de escrita.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/c-loud-writes

Comment @coderabbitai help to get the list of available commands and usage tips.

@vercel
Copy link
Copy Markdown

vercel Bot commented May 30, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
we-dream-big Error Error May 30, 2026 6:08pm

@supabase
Copy link
Copy Markdown

supabase Bot commented May 30, 2026

This pull request has been ignored for the connected project doufsxqlfjyuvxuezpln because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Converts silent no-op writes through the External DB bridge into loud, typed failures. With the kill-switch OFF (REST-native covers reads only), invokeExternalDb/invokeExternalDbDelete previously returned {records:[],count:0} for insert/update/delete/upsert/batch_insert, causing the UI to show success toasts without any persistence. This PR makes those paths throw a new WriteUnavailableError so callers surface real errors.

Changes:

  • Adds WriteUnavailableError class and isWriteOperation() helper in bridge.ts.
  • Throws WriteUnavailableError in invokeExternalDb for write ops when bridge is OFF, on KillSwitchActiveError, and on CORS/network errors (telemetry recordCall(false,...) still emitted before the throw). Reads keep their silent-empty behavior.
  • Replaces silent return in invokeExternalDbDelete with the same loud throw for kill-switch and CORS/network paths.
  • Re-exports the new symbols from src/lib/external-db/index.ts.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/lib/external-db/bridge.ts Adds WriteUnavailableError, isWriteOperation(), and throws on write-path no-ops in invokeExternalDb and invokeExternalDbDelete; telemetry preserved before throw.
src/lib/external-db/index.ts Re-exports isWriteOperation and WriteUnavailableError from the bridge module.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

…Write) + corrige bridge.test.ts (evita REST path no mock) — 23/23 verde
@adm01-debug adm01-debug changed the title PR#1 (C): escrita falha LOUD em vez de no-op silencioso PR (C+A): escrita falha LOUD + caminho REST nativo de escrita (Plano A) May 30, 2026
@adm01-debug adm01-debug merged commit 5a32f29 into main May 30, 2026
44 of 55 checks passed
@adm01-debug adm01-debug deleted the fix/c-loud-writes branch May 30, 2026 18:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants