Backend (Supabase)
Schema mydb, edge functions deployadas, padrão RPC, migrations
versionadas e automações Postgres. É a contraparte server-side das
Lambdas (AWS): tudo que mora no Supabase e
sustenta o produto.
Onde mora o módulo
O lado Supabase do Neuroredes tem três pilares: o schema
mydb com as tabelas da aplicação, as edge functions em
supabase/functions/ e as RPCs em rpc/. Tudo
que não cabe em Lambda nem em Server Component vive aqui.
Diretórios no repositório
- supabase/functions/<nome>/index.ts
- Edge functions versionadas — Deno + TypeScript. Hoje, 30 funções no repo contra 49 deployadas (ver Capítulo 08).
- supabase/migrations/*.sql
- Migrations versionadas. 17 arquivos cobrindo mudanças posteriores ao reset do versionamento. Migrations antigas (criação inicial de
mydb.*, RPCs históricas) não estão rastreáveis no repo. - rpc/<domínio>/*.ts
- Wrappers de
supabase.rpc()direto, sem passar por edge function. Domínios:surveys,companies,surveyors,viewers. Detalhe no Capítulo 04. - lib/supabase/{client,server,middleware}.ts
- Três variantes do
@supabase/ssrusadas pelo Next.js. Coberto em Autenticação — Capítulo 05.
Conexões com o resto da stack
- Next.js → Supabase: Server Components leem perfil do cookie e chamam ou RPCs (
rpc/*) ou edges (viaservices/*.client.service.tseservices/*.service.ts). - Lambdas → Supabase: as cinco Lambdas em
../lambda/escrevem emmydbusando aSERVICE_ROLE_KEYguardada no AWS Secrets Manager. Ver Lambdas — Capítulo 05. - Edge → Lambda: a edge
whatsapp-send-bulkpublica em SQS, consumida porbulk-whatsapp-consumer(Lambda).
Dois schemas, papéis distintos
mydb é onde a aplicação vive — tabelas de pesquisa,
identidade, mensagens. public é a interface da Data API
(PostgREST e GraphQL): hospeda funções RPC, três views que projetam
tabelas de mydb (public.surveys,
public.survey_respondents,
public.survey_responses) e duas tabelas próprias
(public.relatorios, public.survey_cache).
Detalhamento no Capítulo 02.
Schema mydb
Vinte e cinco tabelas no total, divididas em três blocos: aplicação ativa, mensagens/envio em massa e legado do Laravel. A coluna “Página” aponta o capítulo canônico — quando aplicável, backend.html só lista; a profundidade fica na página de origem.
Pesquisa
| Tabela | RLS | Propósito |
|---|---|---|
mydb.surveys | Sim | Cabeçalho da pesquisa, perguntas e status. Pesquisas — Cap. 02. |
mydb.survey_attributes | Sim | Nomes dos sete atributos categorizadores da pesquisa. |
mydb.survey_respondents | Sim | Pessoas que respondem. Valores de atributo + flags de envio. |
mydb.survey_responses | Sim | Respostas. PK composta (respondent_id, evaluatee_id). |
mydb.survey_respondent_tokens | Não | Magic links: hash do token, expiração, revogação. Envio. |
mydb.survey_processing_results | Sim | Cache atual de Neurocalc e grafo, com processing_status. |
mydb.survey_processing_log | Sim | Histórico de processamentos. |
mydb.survey_cache | Sim | Cache legado. Lambdas HTTP ainda gravam aqui — ver Lambdas — Cap. 08. |
Identidade e empresa
Detalhe completo em Autenticação — Capítulo 02.
Resumo: papel é derivado de em qual das três tabelas-perfil o
supabase_auth_id aparece.
| Tabela | RLS | Propósito |
|---|---|---|
mydb.users | Sim | Tabela-perfil de ADMIN. |
mydb.surveyors | Sim | Tabela-perfil de SURVEYOR, com company_id. |
mydb.survey_viewers | Sim | Tabela-perfil de VIEWER, com survey_id. |
mydb.companies | Sim | Organizações. CRUD via companies-crud e RPCs de empresa. |
Envio em massa e mensagens
| Tabela | RLS | Propósito |
|---|---|---|
mydb.bulk_email_batches | Não | Batches de envio de email. Coberto em Lambdas — Cap. 04. |
mydb.bulk_whatsapp_batches | Não | Batches de envio de WhatsApp. |
mydb.survey_messages | Não | Cabeçalho da campanha de envio do ponto de vista do produto. |
mydb.survey_message_respondents | Não | Status por destinatário, por canal. |
Laravel legacy
Oito tabelas remanescentes da aplicação Laravel anterior ao Supabase.
Confirmado via pg_stat_user_tables: zero linhas e zero
atividade desde o cutover. Têm RLS habilitada com policy apenas para
service_role, então não vazam pela Data API, mas continuam
ocupando o catálogo.
| Tabela | Função original (Laravel) |
|---|---|
mydb.cache e mydb.cache_locks | Cache framework-level. |
mydb.jobs, mydb.job_batches, mydb.failed_jobs | Fila de jobs do Laravel. |
mydb.sessions | Sessões web. |
mydb.password_reset_tokens, mydb.personal_access_tokens | Tokens de senha e Sanctum. |
mydb.migrations | Tracking de migrations do Laravel — distinto do tracking do Supabase. |
Schema public
public é a interface da Data API. Além das funções
descritas no Capítulo 06, contém:
- Views
public.surveys,public.survey_respondents,public.survey_responses - Projeções 1:1 (sem WHERE/JOIN) das tabelas de
mydb. São updatable por padrão — é por isso quepublic.close_expired_surveys()consegue rodarUPDATE public.surveysdiretamente. public.relatorios- Índice de relatórios gerados:
id uuid,nome_arquivo text,gerado_em timestamptz. Distinto do bucket de Storage homônimo — ver Capítulo 07. public.survey_cache- Par de
mydb.survey_cacheexposto via Data API. Tem a única RLS realmente escopada do projeto: a policysurvey_cache_select_consolidatedfaz JOIN com as três tabelas-perfil pra liberar leitura só pra quem pertence à pesquisa.
Edge Functions deployadas
Quarenta e nove edge functions ativas no projeto Supabase
(bcrxccejmzgwylfyetle) em 2026-05-21. Trinta delas estão
versionadas em supabase/functions/; as outras ~19 vivem
só no deploy — quem precisar do código real usa
mcp__supabase__get_edge_function. A divergência completa
está no Capítulo 08.
Esta seção agrupa as funções por propósito. Os detalhes de cada fluxo (payload, validação, side-effects) pertencem às páginas dos módulos que as consomem.
CRUD e escrita de domínio
Doze funções que cobrem criação, edição e exclusão das entidades
principais. As de pesquisa (create-survey,
edit-survey, delete-survey,
close-survey) têm fluxo detalhado em
Pesquisas — Capítulo 05.
| Função | O que faz |
|---|---|
companies-crud | Operações de organização. Substituídas em leitura por rpc/companies/*; escrita ainda passa pela edge. |
surveyors-crud, viewers-crud | Atualização e exclusão das tabelas-perfil. Listagem usa RPC. |
create-user-surveyor, create-user-viewer | Convite + insert na tabela-perfil. Precisam de auth.admin.inviteUserByEmail. Auth — Cap. 04. |
create-respondent, update-respondent, delete-respondent | CRUD de respondentes de uma pesquisa. |
create-survey, edit-survey, delete-survey, close-survey | Ciclo de vida da pesquisa, incluindo a cascata de exclusão em sete passos. |
Magic link e respondente público
Seis funções que sustentam o fluxo de resposta sem login. Detalhe em Envio (Magic Links) e Resposta Pública.
magic-link-send— envia link individual por email.magic-link-send-bulk— versão em lote. Hoje envia direto por SMTP (Brevo), não enfileira em SQS — ver Lambdas — Cap. 08.magic-link-validate— valida o hash SHA-256 do token contramydb.survey_respondent_tokens.magic-link-revoke— marcarevoked_at = NOW().get-respondents— listagem para o frontend autenticado.save-responses— gravação das respostas do formulário público.
Envio em massa e status
whatsapp-send-bulk— produtor SQS. Cria batch, gera tokens, enfileira em lotes de 10.get-bulk-email-status— consulta de progresso para a UI.
Análise legado (fallback das Lambdas HTTP)
Onze funções que respondem dashboard, grafo e Excel quando as Lambdas
HTTP não estão configuradas: survey-handler,
survey-handler-front, calc-new,
calc-new-front, graph,
graph-handler, graph-complete,
excel, export-excel,
download-excel-from-bucket, list-excel-files.
Em produção, a UI lê a URL da Lambda equivalente em
NEXT_PUBLIC_*_PROCESSOR_URL e usa a edge como fallback
documentado. Detalhe em Lambdas — Cap. 02.
Neurocalc e experimentação
Cerca de dezenove funções que pertencem ao motor do Neurocalc ou a
cenários de experimentação (neurocalc-*,
grafo-results, survey-results-query,
save-graph-cache, save-neurocalc-cache,
save-report, get-dataset,
get-research, get-post,
create-test-survey). Não estão no caminho principal do
produto. Várias não têm código versionado no repo. Ver
Neurocalc para a fronteira de
responsabilidade desta doc.
Identidade
get-profile— chamada por/verify-userpara resolver papel após login. Desde 2026-06-10 deriva a identidade do JWT (ignorauserIddo corpo) e devolve o perfil do próprio chamador. Auth — Cap. 03.
Flag verify_jwt
Quando uma edge tem verify_jwt: false, o Supabase aceita
a chamada sem JWT — a validação do chamador é responsabilidade
exclusiva do código da edge. Quando está em true, o
gateway rejeita qualquer requisição sem um JWT de usuário válido
antes de ela chegar ao código.
As 30 funções do repo passaram por um endurecimento de auth (commit
98deda8 na branch dev). Hoje, das 30, apenas
7 mantêm verify_jwt: false — todas
chamadas sem um JWT de usuário. As outras 23 estão em
verify_jwt: true e derivam a identidade do chamador do
próprio JWT via _shared/auth.ts
(getAuthedUser → getUser(token) +
resolveRole), com autorização deny-by-default.
O profile/userId do corpo da requisição
não é mais confiável para autorização.
As 7 funções do repo que continuam em verify_jwt: false:
| Edge | Por que é isenta |
|---|---|
magic-link-validate, save-responses | Fluxos públicos no browser, sem JWT de usuário — protegidos pelo token do magic link. Ver Resposta Pública. |
excel, neurocalc, graph-handler, graph-complete, survey-handler | Callbacks máquina-a-máquina das Lambdas AWS — não enviam JWT de usuário nem Origin. Ver Lambdas. |
As edges sensíveis que antes validavam o papel manualmente a partir do
corpo (companies-crud, surveyors-crud,
viewers-crud, create-user-surveyor,
create-user-viewer, create-full-user,
get-profile, o CRUD de pesquisa e de respondentes, os
magic-link-* de envio/revogação e as funções de leitura)
agora estão todas em verify_jwt: true e resolvem
identidade + escopo pelo JWT. Histórico do vetor antigo na seção
Pegadinhas — Capítulo 08.
Edge nova com verify_jwt: false e sem checagem manual
é buraco de segurança imediato — qualquer cliente que conheça a
URL invoca sem credencial. Padrão é manter o flag em
true a menos que o caso de uso exija (frontend
público token-seguro, ou callback de Lambda máquina-a-máquina).
CORS: allowlist de origem
O wildcard Access-Control-Allow-Origin: * que todas as
edges usavam foi substituído por uma allowlist via o helper
compartilhado _shared/cors.ts (buildCorsHeaders(req)).
O helper espelha o Origin da requisição de volta como
ACAO somente quando ele está na allowlist; caso contrário o
header ACAO é omitido (o browser bloqueia a leitura
cross-origin). As quatro origens permitidas:
http://localhost:3000http://localhost:3001https://pesquisa-neuroredes.vercel.apphttps://neuroredes-pesquisa.vercel.app
Vary: Origin é sempre enviado (evita contaminação de
cache). Callers servidor-a-servidor (Lambdas) não mandam Origin
e não são afetados. Não confundir com o CORS das
Lambda Function URLs, que é
configurado no CDK/console AWS, não neste helper.
Deploy: config.toml como fonte única
O flag verify_jwt não é mais passado por comando
(--no-verify-jwt por função). Ele vive em
supabase/config.toml, com um bloco
[functions.<nome>] verify_jwt = false apenas para as
7 funções isentas; o default é true. Isso elimina o risco
de esquecer um flag em deploy individual. Todas as funções vão para
produção em um comando, da pasta pesquisa/:
supabase functions deploy --project-ref eahqtrsdkqmjfsbmukqa
Sem nomes, sem flags. O código compartilhado fica em
functions/_shared/ — o prefixo _ faz o CLI
pular a pasta no deploy em massa (ela é empacotada em cada função que
a importa, não deployada como função).
Padrão RPC
Edge functions cobravam latência por dois saltos (rede + função Deno
+ RPC interna). O padrão atual é, quando possível, chamar a função
Postgres diretamente do Server Component via supabase.rpc(),
eliminando a edge intermediária. A regra de decisão está em
docs/rpc-approach.md; o resumo abaixo é suficiente para
o dia a dia.
Quando usar cada caminho
| Operação | Caminho | Por quê |
|---|---|---|
| Listar pesquisas por papel | RPC | Sem efeito externo. rpc/surveys/get-surveys.ts chama public.get_surveys_by_profile em uma ida ao Postgres. |
| CRUD de organização (listar) | RPC | rpc/companies/get-companies.ts. Idem. |
| CRUD de organização (criar/editar/excluir) | RPC | Sem auth.admin nem efeito externo. |
| Convidar SURVEYOR ou VIEWER | Edge | Precisa auth.admin.inviteUserByEmail com SERVICE_ROLE_KEY. |
| Excluir pesquisa | Edge | Cascata de sete passos com rollback aplicativo. |
| Enviar magic links | Edge | Efeito externo (SMTP ou SQS). |
| Gerar relatório Excel | Lambda | Computação pesada e geração de signed URL. Lambdas — Cap. 02. |
Estrutura do código
Cada RPC é um arquivo pequeno em rpc/<domínio>/<verbo>-<substantivo>.ts
com uma função exportada <verboSubstantivo>Rpc:
import { createClient } from '@/lib/supabase/server';
export async function getCompaniesRpc(params: GetCompaniesParams) {
const supabase = await createClient();
const { data, error } = await supabase.rpc('get_companies_paginated', {
p_schema: 'mydb',
p_search: params.search,
p_page: params.page,
p_per_page: params.perPage,
});
if (error) throw new Error(error.message);
return data;
}
Os domínios já convertidos são surveys,
companies, surveyors e viewers.
Server Actions em app/(main)/<domínio>/actions.ts
chamam essas funções e disparam revalidatePath quando
precisam invalidar o cache do Next.js.
Para o exemplo canônico de despacho por papel em
getSurveysRpc (ADMIN → get_all_surveys,
SURVEYOR → get_surveys_by_company, VIEWER →
get_survey_by_id), ver Pesquisas — Capítulo 05.
Migrations & Data API Grants
Dezessete migrations versionadas em supabase/migrations/,
todas datadas a partir de outubro/2025. A consulta
mcp__supabase__list_migrations devolve exatamente essas
dezessete — ou seja, o tracking interno do Supabase só conhece o que
foi versionado depois do reset.
| Versão | Migração |
|---|---|
20251027221300 | create_get_survey_attributes_rpc |
202512011430 | add_magic_link_rpcs |
20260119171501 | add_end_date_to_magic_get_survey_payload |
202601221000 | add_bulk_email_batches |
202601241200 | fix_magic_update_email_sent |
202602051430 | add_bulk_whatsapp_batches |
20260310120000 | fix_security_advisor_errors |
20260310120100 | fix_search_path_warnings |
20260310120200 | fix_overly_permissive_rls_policies |
20260313120000 | invalidate_graph_cache_on_data_change |
20260316120000 | fix_disk_io_performance |
20260407120000 | auto_close_expired_surveys |
20260407150000 | reduce_disk_io |
20260413185612 | add_survey_messages |
20260430203459 | reset_failed_message_respondents |
20260430204929 | fix_reset_failed_schema |
20260513191724 | preventive_explicit_grants_data_api |
A criação inicial das tabelas em mydb, as RPCs antigas
e parte das edge functions deployadas não têm migration
rastreável: arquivos foram perdidos antes do reset.
Rodar Postgres local só com as 17 migrations do repo não reconstrói
o schema atual. A consulta direta ao banco em produção via Supabase
MCP é a fonte de verdade.
Padrão obrigatório de Data API Grants
Em 30/10/2026, o Supabase muda o default da Data API: tabelas,
sequences e views novas em public deixam de ser
auto-expostas via PostgREST/GraphQL sem GRANT explícito
para anon, authenticated e
service_role. A migration 20260513191724
adota o novo comportamento antes do prazo, revogando os defaults para
que migrations sem grant falhem rápido em desenvolvimento.
create table public.foo ( ... );
grant select, insert, update, delete, truncate, references, trigger
on public.foo to anon, authenticated, service_role;
-- se houver sequence (serial/bigserial)
grant usage, select on sequence public.foo_id_seq
to anon, authenticated, service_role;
alter table public.foo enable row level security;
create policy "..." on public.foo for select to authenticated using (...);
Se a tabela não deve ser exposta na Data API, manter o
grant apenas para service_role. RLS continua
sendo a barreira por linha — grant é a barreira de
acesso à tabela. O schema mydb tem grants per-tabela
intencionais (por exemplo, survey_respondent_tokens
restrito a service_role) e não cai sob a regra do
public, mas mudanças lá seguem o mesmo padrão.
pg_cron, triggers & funções Postgres
pg_cron
Único job ativo: close-expired-surveys. A migration
20260407120000_auto_close_expired_surveys.sql criou a
função public.close_expired_surveys() e a agendou com
cron.schedule('close-expired-surveys', '*/5 * * * *', ...).
Hoje, a tabela cron.job reporta a schedule como
*/15 * * * * — alteração feita pós-migration, sem
arquivo correspondente.
UPDATE public.surveys
SET status = 3,
updated_at = NOW()
WHERE status <> 3
AND end_date IS NOT NULL
AND end_date <= NOW();
A função opera sobre a view public.surveys, que é
updatable por projetar mydb.surveys 1:1. Sem efeito
colateral além da mudança de status: dados intactos,
pesquisa segue acessível para leitura, relatório e dashboard.
Triggers
Dois triggers, ambos disparando
mydb.invalidate_survey_cache() (apaga as linhas
correspondentes em mydb.survey_cache):
| Trigger | Disparo |
|---|---|
trigger_invalidate_cache_respondents em mydb.survey_respondents | AFTER INSERT, UPDATE, DELETE |
trigger_invalidate_cache em mydb.survey_responses | AFTER INSERT, UPDATE, DELETE |
O efeito: qualquer mudança em respondentes ou respostas zera o cache
legado da pesquisa, forçando o recálculo no próximo acesso ao
dashboard ou grafo. O cache novo (mydb.survey_processing_results)
não é alvo dos triggers — segue a regra de invalidação aplicativa
descrita no Cap. 08 das Lambdas.
Funções SECURITY DEFINER
A maioria das funções em public.* e mydb.*
é marcada como SECURITY DEFINER: a execução acontece
com privilégios do owner (tipicamente postgres ou
supabase_admin), bypassando RLS. Por
isso as RPCs funcionam quando o cliente usa apenas a chave
anon: a checagem real de quem pode ver o quê fica
dentro da função, via parâmetros como p_role e
p_company_id.
Famílias de funções (sem enumerar todas as ~85):
get_surveys_*,get_all_surveys,get_surveys_by_company,get_survey_by_id— listagem de pesquisas.magic_*— criação, validação, revogação de tokens de magic link (magic_create_token,magic_get_token_record,magic_revoke_tokens, etc.).bulk_email_*ebulk_whatsapp_*— criação de batch, incremento de contadores.survey_messages_*esurvey_message_respondents_*— campanhas e status por destinatário.get_companies_paginated,create_company,update_company,delete_company,get_surveyors_paginated,update_surveyor_profile,delete_surveyor_profile,get_viewers_paginated,update_viewer_profile,delete_viewer_profile— CRUDs.
Storage
Dois buckets configurados no projeto:
| Bucket | Público | Uso |
|---|---|---|
relatorios |
Não | Planilhas Excel geradas pela Lambda excel-processor e datasets brutos JSON gravados pela Lambda dashboard-processor. Leitura via signed URL de 3600 s. Detalhe em Lambdas — Capítulo 02. |
assets |
Sim | Bucket de propósito geral. Tem dois objetos hoje; uso não documentado em código rastreável. |
Ao lado do bucket relatorios existe a tabela
public.relatorios (id uuid,
nome_arquivo text, gerado_em timestamptz) —
índice em SQL dos arquivos gerados. Coincidência de nome com o
bucket é proposital: o bucket guarda o arquivo, a tabela guarda o
catálogo.
Pegadinhas & alertas
Divergência entre repo e deploy de edges
Trinta funções estão em supabase/functions/ (todas
deployadas); o total deployado é 52 (consulta MCP em 2026-06-10). As
~22 ausentes do repo cobrem Neurocalc experimental
(neurocalc-*), fallbacks de grafo (graph,
save-graph-cache, grafo-results) e edges
legadas (save-report, survey-results-query,
calc-new, get-post,
create-test-survey, …). Para ler o código real em
produção, usar mcp__supabase__get_edge_function com o slug.
O config.toml só governa o verify_jwt das
30 funções do repo. As edges deployadas-mas-sem-código-no-repo não
são alcançadas por ele — entre elas, 11 ainda estão em
verify_jwt: false (save-report,
graph, survey-results-query,
save-graph-cache, calc-new,
get-post, neurocalc-results,
create-test-survey, calc-new-front,
survey-handler-front, grafo-results).
São legado de experimentação fora do caminho principal, mas
continuam acessíveis sem JWT. Confirmar o flag real sempre via
list_edge_functions, não pelo repo.
Nota histórica: companies-crud,
surveyors-crud e create-user-surveyor já
foram catalogadas aqui como “deployadas mas sem código no
repo”. Desde o endurecimento de 2026-06-10 elas vivem em
supabase/functions/, em verify_jwt: true.
Cinco tabelas operacionais sem RLS
mydb.survey_respondent_tokens,
mydb.bulk_email_batches,
mydb.bulk_whatsapp_batches,
mydb.survey_messages e
mydb.survey_message_respondents. Edge functions usam
SERVICE_ROLE_KEY e validam manualmente, mas qualquer
acesso direto via anon key ignora as validações. Vetor
já marcado nos “Alertas de segurança pendentes” do
ROADMAP.
RLS habilitada não é RLS escopada
Algumas tabelas em mydb têm RLS habilitada mas a única
policy de SELECT é auth.role() = 'authenticated', sem
filtro de ownership — por exemplo, mydb.surveys,
mydb.users, mydb.companies. Qualquer
usuário autenticado consegue ler a tabela inteira via
supabase.schema('mydb').from(...).select(). A defesa
real do produto vem das RPCs SECURITY DEFINER que
recebem p_role/p_company_id e das edges
que rodam com service_role e validam o payload. O
aprofundamento desse mapa fica como errata futura em
Autenticação & Papéis.
public.relatorios com policy aberta para anon
A tabela tem RLS habilitada, mas a única policy é
using = true em SELECT para a role anon.
Efetivamente leitura aberta para qualquer cliente com a
anon key pública.
verify_jwt: false em edges sensíveis
As quatro edges de identidade que motivaram este alerta
(companies-crud, surveyors-crud,
create-user-surveyor e get-profile) foram
endurecidas: agora rodam em verify_jwt: true e derivam
a identidade do JWT via _shared/auth.ts, com
autorização deny-by-default — o profile/userId
do corpo deixou de ser confiável (commit 98deda8).
Histórico do vetor. Originalmente ~20 edges
deployadas tinham o flag desabilitado e validavam papel manualmente a
partir do profile no payload — o contrato dependia de
cada edge fazer a checagem certa, sem rede a partir do Supabase, e a
anon key pública bastava para invocá-las. Hoje, das 30
funções do repo, só 7 mantêm verify_jwt: false (fluxos
públicos token-seguros e callbacks de Lambda — ver
Capítulo 03). O resíduo de risco está nas
~11 edges legadas fora do repo que continuam em
false (catalogadas acima em “Divergência entre repo
e deploy”). Edge nova sem JWT e sem validação continua sendo
buraco imediato.
Cron */5 na migration, */15 no banco
A migration 20260407120000_auto_close_expired_surveys.sql
agendou o job a cada cinco minutos; o banco hoje roda a cada quinze.
A alteração foi feita direto na cron.job sem migration
de follow-up, então recriar o banco a partir do repo restabelece o
schedule original. A página Pesquisas — Capítulo 03
afirma “cinco minutos” — vai precisar de errata.
Seis sobrecargas de get_surveys_by_profile
A função public.get_surveys_by_profile existe em seis
assinaturas diferentes (variações de tipo e ordem de parâmetros).
Sinal de cleanup pendente: chamar uma assinatura específica é
frágil porque o roteamento entre sobrecargas depende dos tipos
passados. Hoje a RPC getSurveysRpc despacha para
get_all_surveys, get_surveys_by_company
ou get_survey_by_id, evitando o problema. Funções nova
em rpc/ devem reaproveitar essas três e não criar
sobrecarga adicional.
Tabelas Laravel residuais no mydb
Oito tabelas (cache, cache_locks,
failed_jobs, job_batches, jobs,
migrations, password_reset_tokens,
personal_access_tokens, sessions)
continuam no schema sem uso — confirmado por contagem zero e
ausência de escrita em pg_stat_user_tables. RLS só
permite service_role, então não vazam pela Data API,
mas poluem o catálogo. mydb.migrations em particular
confunde quem espera tracking do Supabase — esse fica em
supabase_migrations.schema_migrations.