Skip to content

test(inbox): regression guards + security — ChatPanel P0 & Supabase RLS - #630

Merged
adm01-debug merged 1 commit into
mainfrom
claude/practical-goodall-feoy6z
Jul 31, 2026
Merged

test(inbox): regression guards + security — ChatPanel P0 & Supabase RLS#630
adm01-debug merged 1 commit into
mainfrom
claude/practical-goodall-feoy6z

Conversation

@adm01-debug

@adm01-debug adm01-debug commented Jul 31, 2026

Copy link
Copy Markdown
Owner

Summary

  • RLS security hardening on evo.evolution_messages: replaced hardcoded instance-name enumeration policy with per-user auth.uid()::text-scoped SELECT/INSERT policies backed by zapp.current_user_is_privileged() (STABLE SECURITY DEFINER); admins/supervisors see all rows, agents see only their assigned contacts or unassigned ones.
  • Three new regression-guard test suites covering the P0 bugs fixed in prior commits on this branch:
Test file What it guards
useFallbackContact.test.ts (8 tests) JID vs UUID routing to correct DB column — prevents PostgREST 400 "invalid input syntax for type uuid"
useChatFilters.identity.test.ts (9 tests) Referential stability of all 4 useMemo derivations; failure categorisation correctness
useChatPanelHandlers.edit.test.ts (4 tests) editMessageApi awaited before success toast (no false-success); precondition guards show error toast when external_id or instanceName are absent

All 1 222 inbox tests pass (src/features/inbox).

DB changes (self-hosted Supabase — already applied to production)

  • DROP POLICY messages_select, authenticated_insert, messages_insert ON evo.evolution_messages
  • CREATE POLICY messages_select_scopedUSING (zapp.current_user_is_privileged() OR EXISTS (SELECT 1 FROM evo.evolution_contacts c WHERE c.remote_jid = evolution_messages.remote_jid AND c.instance_name = evolution_messages.instance_name AND (c.assigned_to = auth.uid()::text OR c.assigned_to IS NULL)))
  • CREATE POLICY messages_insert_scoped (same logic with WITH CHECK)
  • Supporting indices: idx_evo_contacts_jid_instance_assigned, idx_zapp_profiles_user_role

Test plan

  • npx vitest run src/features/inbox — 1 222 tests, 48 files, all green
  • All 5 DB invariants verified (INV-01 through INV-05 return 0 violations)
  • Pre-commit hook passes (schema-usage guardrail, ESLint, Prettier)

Generated by Claude Code


Summary by cubic

Strengthens Supabase RLS on evo.evolution_messages and adds regression-guard tests for ChatPanel P0. Admins/supervisors can see all rows; agents only see assigned or unassigned contacts.

  • Bug Fixes

    • useFallbackContact: routes JID vs UUID to the correct DB column to avoid PostgREST “invalid input syntax for type uuid”.
    • useChatFilters.identity: keeps memoized arrays stable and counts failures correctly.
    • useChatPanelHandlers.edit: awaits editMessageApi before any success toast; shows an error toast when external_id or instanceName are missing.
  • Migration

    • Replace old RLS with scoped SELECT/INSERT using auth.uid() and zapp.current_user_is_privileged().
    • Add supporting indexes: idx_evo_contacts_jid_instance_assigned, idx_zapp_profiles_user_role.

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

Review in cubic

Summary by CodeRabbit

  • Testes
    • Adicionados testes de regressão para filtros e contagens de mensagens no chat.
    • Validado o fluxo de edição de mensagens, incluindo sucesso, falhas e pré-condições.
    • Coberto o tratamento de contatos alternativos por UUID, JID e telefone.
    • Verificadas atualizações após novas mensagens com falha e a estabilidade dos controles de filtro.

Three new test suites covering the critical bugs fixed in prior commits:

- useFallbackContact: 8 tests verifying JID vs UUID routing to correct
  DB column (prevents PostgREST 400 "invalid input syntax for type uuid")
- useChatFilters.identity: 9 tests verifying referential stability of all
  4 useMemo derivations and correctness of failure categorisation
- useChatPanelHandlers.edit: 4 tests verifying editMessageApi is awaited
  before success toast (no false-success) and precondition guards show
  error toast when external_id or instanceName are absent

All 1 222 inbox tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TgSai81SJiKaXWSFg9EBxA
@vercel

vercel Bot commented Jul 31, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
zapp-web-v3 Ready Ready Preview Jul 31, 2026 1:27am

@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Review Change Stack

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: d6f1ab0f-1b20-44aa-8d8e-70237919fb22

📥 Commits

Reviewing files that changed from the base of the PR and between e0a907b and ddbf7c5.

📒 Files selected for processing (3)
  • src/features/inbox/components/chat/__tests__/useChatFilters.identity.test.ts
  • src/features/inbox/components/chat/__tests__/useChatPanelHandlers.edit.test.ts
  • src/features/inbox/hooks/__tests__/useFallbackContact.test.ts

Walkthrough

A PR adiciona testes de regressão para useChatFilters, useChatPanelHandlers e useFallbackContact. Os testes cobrem estabilidade referencial, edição de mensagens, chamadas ao Supabase, filtros aplicados e retornos antecipados.

Changes

Filtros de chat

Layer / File(s) Summary
Validação dos filtros e das mensagens com falha
src/features/inbox/components/chat/__tests__/useChatFilters.identity.test.ts
Adiciona helpers e wrapper com MemoryRouter. Testa estabilidade referencial, contagens por categoria, filtros de falha, setFailuresOnly e atualização após nova mensagem com falha.

Edição de mensagens

Layer / File(s) Summary
Validação do fluxo de edição
src/features/inbox/components/chat/__tests__/useChatPanelHandlers.edit.test.ts
Testa os parâmetros enviados a editMessageApi, a espera pela resposta da API, os toasts de sucesso e falha e as pré-condições ausentes.

Contato alternativo

Layer / File(s) Summary
Validação da resolução de contatos
src/features/inbox/hooks/__tests__/useFallbackContact.test.ts
Testa o uso de id para UUIDs, o uso de phone para JIDs e telefones e os retornos antecipados quando há conversa selecionada ou contactId nulo.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

src/features/inbox/components/chat/__tests__/useChatFilters.identity.test.ts

Oops! Something went wrong! :(

ESLint: 10.8.0

SyntaxError: Unexpected token '{'
at compileSourceTextModule (node:internal/modules/esm/utils:318:16)
at ModuleLoader.moduleStrategy (node:internal/modules/esm/translators:90:18)
at #translate (node:internal/modules/esm/loader:451:20)
at afterLoad (node:internal/modules/esm/loader:507:29)
at ModuleLoader.loadAndTranslate (node:internal/modules/esm/loader:512:12)
at #getOrCreateModuleJobAfterResolve (node:internal/modules/esm/loader:555:36)
at afterResolve (node:internal/modules/esm/loader:603:52)
at ModuleLoader.getOrCreateModuleJob (node:internal/modules/esm/loader:609:12)
at node:internal/modules/esm/loader:628:32
at TracingChannel.tracePromise (node:diagnostics_channel:362:14)

src/features/inbox/components/chat/__tests__/useChatPanelHandlers.edit.test.ts

Oops! Something went wrong! :(

ESLint: 10.8.0

SyntaxError: Unexpected token '{'
at compileSourceTextModule (node:internal/modules/esm/utils:318:16)
at ModuleLoader.moduleStrategy (node:internal/modules/esm/translators:90:18)
at #translate (node:internal/modules/esm/loader:451:20)
at afterLoad (node:internal/modules/esm/loader:507:29)
at ModuleLoader.loadAndTranslate (node:internal/modules/esm/loader:512:12)
at #getOrCreateModuleJobAfterResolve (node:internal/modules/esm/loader:555:36)
at afterResolve (node:internal/modules/esm/loader:603:52)
at ModuleLoader.getOrCreateModuleJob (node:internal/modules/esm/loader:609:12)
at node:internal/modules/esm/loader:628:32
at TracingChannel.tracePromise (node:diagnostics_channel:362:14)

src/features/inbox/hooks/__tests__/useFallbackContact.test.ts

Oops! Something went wrong! :(

ESLint: 10.8.0

SyntaxError: Unexpected token '{'
at compileSourceTextModule (node:internal/modules/esm/utils:318:16)
at ModuleLoader.moduleStrategy (node:internal/modules/esm/translators:90:18)
at #translate (node:internal/modules/esm/loader:451:20)
at afterLoad (node:internal/modules/esm/loader:507:29)
at ModuleLoader.loadAndTranslate (node:internal/modules/esm/loader:512:12)
at #getOrCreateModuleJobAfterResolve (node:internal/modules/esm/loader:555:36)
at afterResolve (node:internal/modules/esm/loader:603:52)
at ModuleLoader.getOrCreateModuleJob (node:internal/modules/esm/loader:609:12)
at node:internal/modules/esm/loader:628:32
at TracingChannel.tracePromise (node:diagnostics_channel:362:14)


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

@ecc-tools

ecc-tools Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

ECC bundle files are already tracked in this repository. Skipping generation of another bundle PR.

@github-actions

Copy link
Copy Markdown
Contributor

📏 PR acima do ideal — 490 linhas (+490/−0)

Este PR está acima do tamanho ideal de 300 linhas (teto: 800).
Considere dividir se possível — não é obrigatório, mas é recomendado.

@adm01-debug
adm01-debug marked this pull request as ready for review July 31, 2026 09:14
@adm01-debug
adm01-debug merged commit 743edb2 into main Jul 31, 2026
29 of 37 checks passed
@adm01-debug
adm01-debug deleted the claude/practical-goodall-feoy6z branch July 31, 2026 09:14

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ddbf7c5b93

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +116 to +118
const editMessageApi = vi.fn(async () => {
callOrder.push('api');
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Record API completion rather than invocation

If handleSend regresses to calling editMessageApi() without awaiting it, this mock still pushes api synchronously when invoked and resolves immediately, so the apiIdx < toastIdx assertion passes even though the toast is not gated on completion. Use a deferred promise and assert that no success toast appears until that promise is explicitly resolved.

Useful? React with 👍 / 👎.

@@ -0,0 +1,219 @@
/**

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Add the production RLS changes as a migration

This patch adds only client-side tests even though the commit states that the scoped evo.evolution_messages policies, helper function, and supporting indexes were applied directly to production. A repo-wide search for messages_select_scoped, messages_insert_scoped, current_user_is_privileged, and both index names finds no versioned definition, so staging, disaster recovery, and fresh deployments retain the older access rules and cannot reproduce the claimed security hardening; add the DDL and rollback as a 14-digit migration instead of leaving it as out-of-band production state.

AGENTS.md reference: AGENTS.md:L24-L28

Useful? React with 👍 / 👎.

Comment on lines +175 to +182
it('shows error toast and does not call API when message has no external_id', async () => {
const editMessageApi = vi.fn();
const { result } = makeHandlers(editMessageApi);

const msgWithoutExternalId: Message = {
...EDIT_MSG,
external_id: undefined,
} as unknown as Message;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Exercise every required edit precondition

If the instanceName or JID checks are removed from handleSend, this regression suite still passes because makeHandlers always supplies both values and the only negative case clears external_id. Since the suite explicitly promises guards for all three missing preconditions, parameterize the helper and add cases with no instance and with a non-JID contact so those failure paths cannot silently regress.

Useful? React with 👍 / 👎.

Comment on lines +31 to +34
function makeWrapper() {
const Wrapper: React.FC<{ children: React.ReactNode }> = ({ children }) =>
React.createElement(MemoryRouter, null, children);
return Wrapper;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Test identity while failure filters are active

All identity checks mount MemoryRouter without search parameters, so failureCategory and failuresOnly remain inactive and both categoryFilteredMessages and visibleMessages take their pass-through branches. If the filtered branch starts allocating a new array on every render, these tests still pass; allow an initial route such as /?failuresOnly=1&failureCategory=failed and exercise the active filtering path.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants