F6.3 (PREPARADA, NAO APLICADA): DROP das tabelas tenant em public

manual/f6_3_drop_public_tenant_tables.supabase_admin.sql — ponto de nao-retorno,
revisar antes de aplicar:
- pre-flight assert (tenants=schemas, 78 tabelas, 6 anon NAO no template)
- 2 FKs public->tenant viram coluna solta (document_share_links.documento_id,
  whatsapp_credits_transactions.conversation_message_id)
- dropa 9 views public (6 recriadas por schema + 2 dead + v_twilio item#1)
- DROP CASCADE das 78 tabelas (derivado de _tenant_template; dados ja nos schemas)
- limpa financial_records_inject_tenant (obsoleto)

ITENS EM ABERTO verificados (16 reads FE remanescentes, TODOS na superficie
SaaS-admin ja flagada na F3): SaasFeriadosPage (feriados defaults),
SaasNotificationTemplatesPage (templates default), SaasWhatsappPage +
v_twilio_whatsapp_overview/getAllChannels (whatsapp admin cross-tenant).
Resolver (apontar pra _tenant_template ou fan-out por schema) ANTES do DROP.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Leonardo
2026-06-13 16:44:37 -03:00
parent af2395c723
commit cdb9ce10ee
@@ -0,0 +1,116 @@
-- =============================================================================
-- F6.3 — DROP das tabelas tenant em public (PONTO DE NÃO-RETORNO)
--
-- 🛑 NÃO APLICAR AINDA. Este arquivo está PREPARADO para revisão. Aplicar só
-- depois de:
-- (a) Leonardo testar o app no branch e validar os fluxos;
-- (b) os ITENS EM ABERTO abaixo resolvidos;
-- (c) backup fresco confirmado.
--
-- ⚠️ APLICAR COMO supabase_admin (DROP CASCADE; tabelas documents/document_* são
-- owned por supabase_admin).
-- docker exec -i -e PGPASSWORD=postgres supabase_db_agenciapsi-primesakai \
-- psql -U supabase_admin -h 127.0.0.1 -d postgres -v ON_ERROR_STOP=1 \
-- < database-novo/manual/f6_3_drop_public_tenant_tables.supabase_admin.sql
--
-- BACKUP ANTES (obrigatório):
-- docker exec supabase_db_agenciapsi-primesakai pg_dump -U postgres -d postgres \
-- --schema=public --no-owner --no-acl > database-novo/backups/pre-F6.3/public.sql
--
-- ─────────────────────────────────────────────────────────────────────────────
-- ⛔ ITENS EM ABERTO (resolver ANTES de aplicar) — superfície SaaS-admin / anon
-- que AINDA aponta pra public e quebraria com o DROP:
--
-- 1. v_twilio_whatsapp_overview + twilioWhatsappService.getAllChannels()
-- → view SaaS-admin cross-tenant sobre notification_channels +
-- twilio_subaccount_usage (tenant). Reescrever getAllChannels pra varrer
-- os schemas (ou usar public.channel_routing) antes do DROP.
-- 2. Páginas SaaS revertidas na F3 (SaasFeriadosPage, SaasNotificationTemplates,
-- SaasDocumentTemplates, SaasWhatsappPage) — gerenciam defaults do sistema /
-- views cross-tenant; hoje leem public.<tabela_tenant>. Redirecionar pra
-- _tenant_template (defaults) ou fan-out por schema.
-- 3. notification-webhook (Meta) — fan-out por message_id em public; conferir
-- que só usa channel_routing/schemas.
-- 4. AgendadorPublicoPage — já usa RPCs roteadas (OK); confirmar.
--
-- Rodar pra detectar referências FE remanescentes a tabelas tenant em public:
-- grep -rnE "supabase\.from\('(patients|agenda_eventos|financial_records|
-- documents|notification_channels|conversation_messages|...)'\)" src
-- ─────────────────────────────────────────────────────────────────────────────
-- =============================================================================
\set ON_ERROR_STOP on
BEGIN;
-- ── 0) PRÉ-FLIGHT: aborta se algo essencial não bate ────────────────────────
DO $$
DECLARE v_tenants int; v_schemas int; v_drop int;
BEGIN
SELECT count(*) INTO v_tenants FROM public.tenants;
SELECT count(*) INTO v_schemas FROM public.tenant_schemas;
IF v_tenants <> v_schemas THEN
RAISE EXCEPTION 'F6.3 ABORT: % tenants mas % schemas provisionados — nem todos migrados', v_tenants, v_schemas;
END IF;
SELECT count(*) INTO v_drop FROM information_schema.tables
WHERE table_schema='_tenant_template' AND table_type='BASE TABLE' AND table_name NOT LIKE '\_%';
IF v_drop <> 78 THEN
RAISE EXCEPTION 'F6.3 ABORT: _tenant_template tem % tabelas, esperava 78', v_drop;
END IF;
-- guarda: nenhuma das 6 anon-facing pode estar na lista de drop
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema='_tenant_template'
AND table_name IN ('patient_intake_requests','patient_invites','patient_invite_attempts',
'document_share_links','agendador_configuracoes','agendador_solicitacoes')) THEN
RAISE EXCEPTION 'F6.3 ABORT: tabela anon-facing presente no template (não deveria sair de public)';
END IF;
RAISE NOTICE 'F6.3 pré-flight OK: % tenants = % schemas, 78 tabelas a dropar', v_tenants, v_schemas;
END $$;
-- ── 1) FKs de tabelas que FICAM → tabelas que SAEM: viram coluna solta ──────
-- (validação fica no app/RPC via token; alvo vai pro schema do tenant)
ALTER TABLE public.document_share_links DROP CONSTRAINT IF EXISTS document_share_links_documento_id_fkey;
ALTER TABLE public.whatsapp_credits_transactions DROP CONSTRAINT IF EXISTS whatsapp_credits_transactions_conversation_message_id_fkey;
-- ── 2) Views public que referenciam tabelas tenant ──────────────────────────
-- As 6 do template são recriadas POR SCHEMA (F1). v_patient_engajamento e
-- v_patients_risco são dead code (0 uso no FE). v_twilio_whatsapp_overview:
-- ⚠️ ver ITEM EM ABERTO #1 — só dropar após reescrever getAllChannels.
DROP VIEW IF EXISTS public.audit_log_unified CASCADE;
DROP VIEW IF EXISTS public.conversation_threads CASCADE;
DROP VIEW IF EXISTS public.v_cashflow_projection CASCADE;
DROP VIEW IF EXISTS public.v_commitment_totals CASCADE;
DROP VIEW IF EXISTS public.v_patient_groups_with_counts CASCADE;
DROP VIEW IF EXISTS public.v_tag_patient_counts CASCADE;
DROP VIEW IF EXISTS public.v_patient_engajamento CASCADE; -- dead code
DROP VIEW IF EXISTS public.v_patients_risco CASCADE; -- dead code
DROP VIEW IF EXISTS public.v_twilio_whatsapp_overview CASCADE; -- ⚠️ item #1
-- ── 3) DROP das 78 tabelas tenant em public (derivado de _tenant_template) ──
-- CASCADE leva junto triggers das tabelas + FKs intra-tenant. Dados já estão
-- nos schemas (F6.1) — estas são as cópias velhas.
DO $$
DECLARE r record;
BEGIN
FOR r IN
SELECT table_name FROM information_schema.tables
WHERE table_schema='_tenant_template' AND table_type='BASE TABLE' AND table_name NOT LIKE '\_%'
ORDER BY table_name
LOOP
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema='public' AND table_name=r.table_name) THEN
EXECUTE format('DROP TABLE public.%I CASCADE', r.table_name);
RAISE NOTICE 'F6.3 dropou public.%', r.table_name;
END IF;
END LOOP;
END $$;
-- ── 4) Limpeza de funções obsoletas pós-drop ────────────────────────────────
-- financial_records_inject_tenant só fazia sentido em public.financial_records
-- (já dropada); não está anexado em nenhum schema.
DROP FUNCTION IF EXISTS public.financial_records_inject_tenant() CASCADE;
COMMIT;
-- ── 5) PÓS-DROP: verificações manuais (rodar separado) ───────────────────────
-- SELECT 'tabelas tenant restantes em public: ' || count(*) FROM information_schema.tables
-- WHERE table_schema='public' AND table_name IN (SELECT table_name FROM _tenant_template.information... );
-- NOTIFY pgrst, 'reload schema';
-- Conferir app: nenhuma query 4xx/PGRST200 no console.