Skip to content

PR#3 (A): RLS de escrita p/ print_area_techniques e supplier_branches#527

Merged
adm01-debug merged 1 commit into
mainfrom
feat/a-rls-write-policies
May 30, 2026
Merged

PR#3 (A): RLS de escrita p/ print_area_techniques e supplier_branches#527
adm01-debug merged 1 commit into
mainfrom
feat/a-rls-write-policies

Conversation

@adm01-debug
Copy link
Copy Markdown
Owner

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

O que faz

Fecha os 2 únicos gaps de RLS de escrita encontrados na auditoria das 13 tabelas-base do Plano A. As outras 11 (products, suppliers, categories, product_variants, variant_supplier_sources, collections, collection_products, tecnicas_gravacao, tabela_preco_gravacao_oficial) já tinham insert/update/delete por role/org — o "write gap" era client-side (rest-native não roteava escrita), resolvido no PR#2.

Gaps fechados:

  • print_area_techniques (filha de products via product_id): só tinha pat_all_service (service_role). Espelha product_variants — insert/update via user_is_org_member, delete via is_org_owner_or_admin, org resolvida pelo produto-pai. A policy pat_all_service fica intacta.
  • supplier_branches (filha de suppliers via supplier_id): nenhuma policy de escrita. Espelha suppliers — insert/update/delete via is_org_owner_or_admin, org resolvida pelo fornecedor-pai.

Segurança

Modelo idêntico ao das tabelas-irmãs (anon não escreve: os helpers is_org_owner_or_admin/user_is_org_member retornam false sem auth.uid()). Isso elimina a única superfície de risco que a simulação do Plano A apontou (policy permissiva demais) — aqui as policies são role/org-scoped, espelhadas de policies já auditadas.

Validação

  • Idempotente: DROP POLICY IF EXISTS + CREATE (+ ENABLE RLS no-op).
  • Expressões validadas via EXPLAIN contra o schema de produção (colunas product_id/supplier_id/organization_id, funções is_org_owner_or_admin/user_is_org_member e os joins resolvem).
  • tecnica_gravacao_variante e fornecedor_gravacao não existem como tabelas — fora de escopo (escrita a elas falha LOUD via PR#1/fix(imports): corrigir 32 imports quebrados pelo refactor T1 (19/mai) #2, nunca silenciosa).

Ordem de merge

Inócuo sem o código do PR#2 → pode/deve mergear primeiro ou junto. Com #3 aplicado, a escrita do Plano A (PR#2) passa a persistir nas 13 tabelas; sem #3, falha LOUD nas 2 (honesto).

Série: #1 (C) → #2 (A núcleo) → #3 (A RLS)#4 (aposentar bridge).


Summary by cubic

Adds write RLS policies for print_area_techniques and supplier_branches, mirroring their parent tables’ org-scoped rules. This closes the last two write gaps so authenticated native REST writes work across all 13 tables.

  • Bug Fixes
    • print_area_techniques: insert/update allowed for user_is_org_member of parent products; delete requires is_org_owner_or_admin. Keeps pat_all_service unchanged.
    • supplier_branches: insert/update/delete allowed only for is_org_owner_or_admin of parent suppliers.
    • Org resolved via product_id/supplier_id; anonymous users cannot write.
    • Idempotent migration: RLS ensured enabled; policies created with DROP IF EXISTS.

Written for commit d64f6ec. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Bug Fixes

    • Corrigidas limitações de escrita autenticada ao adicionar políticas explícitas de controle de acesso para operações de inserção, atualização e exclusão em tabelas específicas.
  • Chores

    • Implementada camada de segurança em nível de linha para fortalecer a integridade dos dados com validações de organização.

Review Change Stack

…supplier_branches

Fecha os 2 únicos gaps de RLS de escrita encontrados na auditoria das 13 tabelas
do Plano A (as outras 11 já tinham insert/update/delete por role/org).

- print_area_techniques (filha de products via product_id): espelha product_variants
  — insert/update via user_is_org_member, delete via is_org_owner_or_admin,
  resolvendo a org pelo produto-pai. A policy service_role (pat_all_service) fica intacta.
- supplier_branches (filha de suppliers via supplier_id): espelha suppliers —
  insert/update/delete via is_org_owner_or_admin, org resolvida pelo fornecedor-pai.

Idempotente (DROP POLICY IF EXISTS + CREATE). Expressões validadas via EXPLAIN
contra o schema real (colunas/funções/joins resolvem). tecnica_gravacao_variante e
fornecedor_gravacao não existem como tabelas — fora de escopo (escrita a elas é LOUD).

Inócuo sem o código do PR#2; pode mergear primeiro/independente.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 30, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 041de951-c618-4ddc-8ba8-54aafe535fc9

📥 Commits

Reviewing files that changed from the base of the PR and between 72dab92 and d64f6ec.

📒 Files selected for processing (1)
  • supabase/migrations/20260530170000_rls_write_print_area_techniques_supplier_branches.sql

Walkthrough

Migration habilita RLS em print_area_techniques e supplier_branches e cria policies idempotentes de escrita com validação de organização via tabelas pai: print_area_techniques valida membership para INSERT/UPDATE e ownership para DELETE via products; supplier_branches valida ownership/admin para todas operações via suppliers.

Changes

RLS Write Policies — print_area_techniques e supplier_branches

Layer / File(s) Summary
RLS enablement nas tabelas
supabase/migrations/20260530170000_rls_write_print_area_techniques_supplier_branches.sql
ALTER TABLE statements habilitam RLS em print_area_techniques e supplier_branches, fechando gaps de segurança em escrita autenticada.
Policies de escrita para print_area_techniques
supabase/migrations/20260530170000_rls_write_print_area_techniques_supplier_branches.sql
pat_org_insert/update (membership via products) e pat_org_delete (ownership/admin via products) permitem escrita com validação de organização.
Policies de escrita para supplier_branches
supabase/migrations/20260530170000_rls_write_print_area_techniques_supplier_branches.sql
supplier_branches_org_insert/update/delete (ownership/admin via suppliers) controlam escrita com validação consistente de organização.

Pontos de Atenção de Segurança

  • DROP POLICY IF EXISTS: Idempotência confirmada; múltiplas execuções são seguras.
  • Validação de org: Ambas tabelas validam via tabela pai (products/suppliers); confirmar que product_id e supplier_id são FKs e imutáveis em UPDATE.
  • Assimetria de permissão: print_area_techniques permite INSERT/UPDATE a qualquer membro; supplier_branches restringe a owner/admin. Verificar se isso é intencional e alinhado com regras de negócio.
  • WITH CHECK em UPDATE: Ambas policies usam WITH CHECK corretamente, impedindo privilege escalation em UPDATE.
  • No SELECT/DELETE policies distintas: Assumir que DELETE sem USING é equivalente a UPDATE USING (mesmo objeto); confirmar que é intencional.

🎯 2 (Simple) | ⏱️ ~12 minutos

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/a-rls-write-policies

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 4:43pm

@supabase
Copy link
Copy Markdown

supabase Bot commented May 30, 2026

Updates to Preview Branch (feat/a-rls-write-policies) ↗︎

Deployments Status Updated
Database Sat, 30 May 2026 16:45:47 UTC
Services Sat, 30 May 2026 16:45:47 UTC
APIs Sat, 30 May 2026 16:45:47 UTC

Tasks are run on every commit but only new migration files are pushed.
Close and reopen this PR if you want to apply changes from existing seed or migration files.

Tasks Status Updated
Configurations Sat, 30 May 2026 16:45:52 UTC
Migrations Sat, 30 May 2026 16:49:15 UTC
Seeding ⏸️ Sat, 30 May 2026 16:45:41 UTC
Edge Functions ⏸️ Sat, 30 May 2026 16:45:41 UTC

❌ Branch Error • Sat, 30 May 2026 16:49:15 UTC

ERROR: cannot change return type of existing function (SQLSTATE 42P13)
At statement: 10
CREATE OR REPLACE FUNCTION public.fn_run_and_persist_smoke_tests()
RETURNS void
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path TO 'public'
AS $function$
DECLARE
  v_ran_at timestamptz := now();
BEGIN
  IF NOT public.is_admin_or_above((SELECT auth.uid())) THEN
    RAISE EXCEPTION 'not authorized';
  END IF;

  INSERT INTO public.smoke_test_runs (
    ran_at,
    test_name,
    test_category,
    result,
    details,
    duration_ms
  )
  SELECT
    v_ran_at,
    test_name,
    test_category,
    result,
    details,
    duration_ms
  FROM public.fn_run_smoke_tests();
END;
$function$

View logs for this Workflow Run ↗︎.
Learn more about Supabase for Git ↗︎.

adm01-debug added a commit that referenced this pull request May 30, 2026
…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.
@adm01-debug adm01-debug marked this pull request as ready for review May 30, 2026 16:52
Copilot AI review requested due to automatic review settings May 30, 2026 16:52
@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.

@adm01-debug adm01-debug merged commit ede662b into main May 30, 2026
40 of 53 checks passed
@adm01-debug adm01-debug deleted the feat/a-rls-write-policies branch May 30, 2026 16:52
adm01-debug added a commit that referenced this pull request May 30, 2026
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).
adm01-debug added a commit that referenced this pull request May 30, 2026
…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
adm01-debug added a commit that referenced this pull request May 31, 2026
…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.
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.

1 participant