feat(auth): adiciona confirmação de troca de e-mail - #238

Open
Jovinull wants to merge 3 commits into
Cla-Code-Community:developfrom
Jovinull:feature/pav-36-troca-email-confirmacao
Open

feat(auth): adiciona confirmação de troca de e-mail#238
Jovinull wants to merge 3 commits into
Cla-Code-Community:developfrom
Jovinull:feature/pav-36-troca-email-confirmacao

Conversation

@Jovinull

@JovinullJovinull commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Card

  • PAV-36

Objetivo e escopo

  • Exigir confirmação antes de efetivar a troca de e-mail de um usuário.
  • Manter o e-mail atual até a confirmação do token recebido no novo endereço.

O que foi feito

  • Adiciona a tabela e migration de pedidos de troca de e-mail.
  • Cria o serviço que invalida pedidos anteriores, valida duplicidade de e-mail, gera o pedido e confirma a troca por token.
  • Adiciona POST /users/email-change para solicitar a troca com sessão autenticada.
  • Adiciona POST /auth/email-change/confirm para confirmar o token sem exigir sessão.
  • Inclui template de e-mail, formulário no perfil e a tela /confirmar-email.
  • Torna o campo de e-mail do perfil somente leitura, direcionando a alteração para o fluxo de confirmação.

Módulos afetados

  • backend/drizzle/0014_panoramic_leopardon.sql
  • backend/src/modules/users/emailChange.service.ts
  • backend/src/routes/auth.routes.ts
  • backend/src/routes/users.routes.ts
  • backend/src/modules/email/templates/emailChangeConfirmation.tsx
  • frontend/src/domains/new_dashboard/components/profile/EmailChangeForm.tsx
  • frontend/src/domains/auth/presentation/pages/ConfirmEmailChangePage.tsx

Validação

  • CI do PR concluído com sucesso, incluindo coverage de frontend e backend, lint e build.
  • npm exec --workspace=backend vitest run tests/integration/routes/auth.routes.test.ts tests/integration/routes/user.routes.test.ts tests/unit/modules/email/email.service.test.ts tests/unit/modules/users/emailChange.service.test.ts - 4 arquivos e 67 testes aprovados.
  • npm exec --workspace=frontend vitest run tests/unit/new_dashboard/emailChange.test.tsx - 1 arquivo e 3 testes aprovados.
  • Os testes cobrem solicitação autenticada, e-mail inválido, ausência de sessão, confirmação sem sessão, token inválido ou expirado, e-mail já utilizado, tela de confirmação e link sem token.
  • npm run lint --workspace=frontend - concluído sem erros.
  • npm run build --workspace=frontend - concluído com sucesso.
  • Smoke manual em navegador: acessei /confirmar-email sem token, validei a mensagem de link inválido e a navegação para o login.

Riscos e observações

  • A migration 0014_panoramic_leopardon.sql precisa ser aplicada antes de disponibilizar o fluxo.
  • O envio efetivo pelo Resend não foi executado nesta validação, pois não há credencial configurada. O contrato de enfileiramento e o conteúdo da URL de confirmação foram validados por teste automatizado.
  • A confirmação com token válido contra uma instância real de banco e serviço de e-mail permanece pendente de ambiente configurado.

hltavand others added 2 commits August 23, 2026 18:32
…ode-Community#230)
## Linear
Issue: PAV-119
Closes PAV-119
## Branch flow
- [ ] Este PR é uma feature/fix/chore destinada a `develop`.
- [x] Este é um PR de release com origem `develop` e destino `master`.
- [x] Este PR não pula o fluxo obrigatório entre `develop` e `master`.
## Objetivo
Promover para `master` a implementação do lock distribuído do scraper,
garantindo no máximo uma execução ativa do pipeline entre diferentes
origens de disparo.
## Resumo das Alterações
- Implementa lock distribuído no Valkey compartilhado por cron, execução
manual administrativa e cache miss de `/scrape`.
- Utiliza aquisição atômica com `SET NX PX`, TTL e renovação periódica.
- Protege renovação e liberação por ownership/token.
- Implementa comportamento fail-closed quando o Valkey não confirma a
aquisição.
- Cancela a execução de forma segura em caso de perda do lock.
- Adiciona estado operacional com `runId`, origem, início e expiração
sem expor o token proprietário.
- Adiciona contratos HTTP para execução concorrente e indisponibilidade
do run lock.
- Alinha os defaults de `SCRAPER_RUN_LOCK_TTL` e
`SCRAPER_RUN_LOCK_RENEW_INTERVAL` à semântica fail-fast definida
anteriormente.
- Adiciona cobertura de testes para concorrência, ownership,
configuração, renovação, liberação e cenários de falha.
- Atualiza documentação e configuração do Docker Compose.
## Arquivos e Módulos Afetados
- Scraper Go
- Run lock / Valkey
- Scheduler e pipeline do scraper
- Backend administrativo
- Configuração do scraper
- Docker Compose
- Testes Go e backend
- Documentação operacional
## Validação
- [x] Implementação revisada contra o escopo da PAV-119.
- [x] Ajustes solicitados no code review aplicados.
- [x] Semântica fail-fast das configurações do run lock validada.
- [x] Nenhuma alteração de frontend incluída no escopo.
- [ ] CI final do PR de release validado.
## Observações
Este PR promove alterações já integradas e revisadas em `develop`.
Não realizar squash ou alterações adicionais diretamente em `master`
fora do fluxo de release.

@hltavhltav left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

PR fora do padrão de contribuição do projeto.

Antes da revisão técnica, por favor ajuste a descrição conforme o template/documentação do repositório, incluindo card relacionado, objetivo, resumo das alterações, arquivos/módulos afetados, validações executadas e observações relevantes.

Com 24 arquivos alterados e mais de 2 mil linhas adicionadas, precisamos desse contexto para realizar uma revisão segura e rastreável. Após a adequação da PR, seguimos com a revisão do código.

@hltavhltav left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

A implementação está bem encaminhada e cobre boa parte do fluxo da PAV-36, mas como esse PR altera um fluxo sensível de identidade/autenticação, ainda precisamos fechar alguns pontos antes da aprovação.

O principal problema está na relação entre a criação da solicitação de troca e o envio do e-mail de confirmação. Hoje a solicitação é persistida e considerada concluída mesmo quando o módulo centralizado de e-mail não consegue enfileirar a mensagem, porque esse módulo foi originalmente desenhado para tratar falha de envio como não bloqueante. Nesse fluxo específico, porém, o e-mail é parte obrigatória da operação: sem ele o usuário não consegue concluir a troca.

Revise esse comportamento para que a API não sinalize sucesso quando a confirmação não puder ser efetivamente disponibilizada ao usuário. Essa revisão também deve considerar o estado da solicitação já persistida e de eventuais solicitações anteriores invalidadas.

Além disso, gostaria que fossem revisados os cenários de concorrência do fluxo. Em especial, precisamos garantir consistência quando houver solicitações simultâneas para o mesmo novo e-mail, múltiplas solicitações para o mesmo usuário e concorrência entre confirmação de token e criação de uma nova solicitação. O banco e a camada de serviço precisam preservar as invariantes do fluxo também nesses casos.

A cobertura atual contempla bem o happy path, token inválido/expirado e e-mail já utilizado, mas precisa incluir os cenários de falha de infraestrutura e concorrência relevantes para essa feature. Como esse fluxo altera users, credentials e a nova tabela de solicitações dentro do processo de confirmação, gostaria também de cobertura explícita garantindo atomicidade: ou a troca é concluída integralmente, ou o estado anterior permanece consistente.

Por fim, valide o comportamento de sessão após a confirmação da troca de e-mail. Como a identidade persistida é alterada em users e credentials, precisamos garantir que sessões/autenticações existentes continuem com o comportamento definido pelo produto e que não exista inconsistência entre o e-mail exibido, o e-mail usado para login e os dados da sessão após a confirmação.

Com esses pontos tratados e cobertos por testes, o PR fica em condição de aprovação.

@Jovinull

Copy link
Copy Markdown
ContributorAuthor

Atualiza??o aplicada em resposta ao review t?cnico:

  • O envio do e-mail de confirma??o agora pode ser marcado como obrigat?rio.
  • No fluxo de troca de e-mail, falhas ao enfileirar a confirma??o s?o propagadas para a API.
  • A cria??o do pedido e o envio obrigat?rio s?o executados dentro da transa??o; se o envio falhar, a solicita??o n?o ? conclu?da.
  • Adicionados testes para falha de infraestrutura no enqueue e para o comportamento de envio obrigat?rio.

Valida??o:

  • Suite completa do backend: 61 arquivos e 584 testes aprovados.
  • Lint do frontend: conclu?do sem erros (apenas warning preexistente de depend?ncia de hook).
  • Build do frontend: conclu?do com sucesso.

Commit: 56d36ae

Sign up for freeto 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

@Jovinull@hltav
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

feat(auth): adiciona confirmação de troca de e-mail - #238

Open
Jovinull wants to merge 3 commits into
Cla-Code-Community:developfrom
Jovinull:feature/pav-36-troca-email-confirmacao
Open

feat(auth): adiciona confirmação de troca de e-mail#238
Jovinull wants to merge 3 commits into
Cla-Code-Community:developfrom
Jovinull:feature/pav-36-troca-email-confirmacao

Conversation

@Jovinull

@JovinullJovinull commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Card

  • PAV-36

Objetivo e escopo

  • Exigir confirmação antes de efetivar a troca de e-mail de um usuário.
  • Manter o e-mail atual até a confirmação do token recebido no novo endereço.

O que foi feito

  • Adiciona a tabela e migration de pedidos de troca de e-mail.
  • Cria o serviço que invalida pedidos anteriores, valida duplicidade de e-mail, gera o pedido e confirma a troca por token.
  • Adiciona POST /users/email-change para solicitar a troca com sessão autenticada.
  • Adiciona POST /auth/email-change/confirm para confirmar o token sem exigir sessão.
  • Inclui template de e-mail, formulário no perfil e a tela /confirmar-email.
  • Torna o campo de e-mail do perfil somente leitura, direcionando a alteração para o fluxo de confirmação.

Módulos afetados

  • backend/drizzle/0014_panoramic_leopardon.sql
  • backend/src/modules/users/emailChange.service.ts
  • backend/src/routes/auth.routes.ts
  • backend/src/routes/users.routes.ts
  • backend/src/modules/email/templates/emailChangeConfirmation.tsx
  • frontend/src/domains/new_dashboard/components/profile/EmailChangeForm.tsx
  • frontend/src/domains/auth/presentation/pages/ConfirmEmailChangePage.tsx

Validação

  • CI do PR concluído com sucesso, incluindo coverage de frontend e backend, lint e build.
  • npm exec --workspace=backend vitest run tests/integration/routes/auth.routes.test.ts tests/integration/routes/user.routes.test.ts tests/unit/modules/email/email.service.test.ts tests/unit/modules/users/emailChange.service.test.ts - 4 arquivos e 67 testes aprovados.
  • npm exec --workspace=frontend vitest run tests/unit/new_dashboard/emailChange.test.tsx - 1 arquivo e 3 testes aprovados.
  • Os testes cobrem solicitação autenticada, e-mail inválido, ausência de sessão, confirmação sem sessão, token inválido ou expirado, e-mail já utilizado, tela de confirmação e link sem token.
  • npm run lint --workspace=frontend - concluído sem erros.
  • npm run build --workspace=frontend - concluído com sucesso.
  • Smoke manual em navegador: acessei /confirmar-email sem token, validei a mensagem de link inválido e a navegação para o login.

Riscos e observações

  • A migration 0014_panoramic_leopardon.sql precisa ser aplicada antes de disponibilizar o fluxo.
  • O envio efetivo pelo Resend não foi executado nesta validação, pois não há credencial configurada. O contrato de enfileiramento e o conteúdo da URL de confirmação foram validados por teste automatizado.
  • A confirmação com token válido contra uma instância real de banco e serviço de e-mail permanece pendente de ambiente configurado.

hltavand others added 2 commits August 23, 2026 18:32
…ode-Community#230)
## Linear
Issue: PAV-119
Closes PAV-119
## Branch flow
- [ ] Este PR é uma feature/fix/chore destinada a `develop`.
- [x] Este é um PR de release com origem `develop` e destino `master`.
- [x] Este PR não pula o fluxo obrigatório entre `develop` e `master`.
## Objetivo
Promover para `master` a implementação do lock distribuído do scraper,
garantindo no máximo uma execução ativa do pipeline entre diferentes
origens de disparo.
## Resumo das Alterações
- Implementa lock distribuído no Valkey compartilhado por cron, execução
manual administrativa e cache miss de `/scrape`.
- Utiliza aquisição atômica com `SET NX PX`, TTL e renovação periódica.
- Protege renovação e liberação por ownership/token.
- Implementa comportamento fail-closed quando o Valkey não confirma a
aquisição.
- Cancela a execução de forma segura em caso de perda do lock.
- Adiciona estado operacional com `runId`, origem, início e expiração
sem expor o token proprietário.
- Adiciona contratos HTTP para execução concorrente e indisponibilidade
do run lock.
- Alinha os defaults de `SCRAPER_RUN_LOCK_TTL` e
`SCRAPER_RUN_LOCK_RENEW_INTERVAL` à semântica fail-fast definida
anteriormente.
- Adiciona cobertura de testes para concorrência, ownership,
configuração, renovação, liberação e cenários de falha.
- Atualiza documentação e configuração do Docker Compose.
## Arquivos e Módulos Afetados
- Scraper Go
- Run lock / Valkey
- Scheduler e pipeline do scraper
- Backend administrativo
- Configuração do scraper
- Docker Compose
- Testes Go e backend
- Documentação operacional
## Validação
- [x] Implementação revisada contra o escopo da PAV-119.
- [x] Ajustes solicitados no code review aplicados.
- [x] Semântica fail-fast das configurações do run lock validada.
- [x] Nenhuma alteração de frontend incluída no escopo.
- [ ] CI final do PR de release validado.
## Observações
Este PR promove alterações já integradas e revisadas em `develop`.
Não realizar squash ou alterações adicionais diretamente em `master`
fora do fluxo de release.

@hltavhltav left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

PR fora do padrão de contribuição do projeto.

Antes da revisão técnica, por favor ajuste a descrição conforme o template/documentação do repositório, incluindo card relacionado, objetivo, resumo das alterações, arquivos/módulos afetados, validações executadas e observações relevantes.

Com 24 arquivos alterados e mais de 2 mil linhas adicionadas, precisamos desse contexto para realizar uma revisão segura e rastreável. Após a adequação da PR, seguimos com a revisão do código.

@hltavhltav left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

A implementação está bem encaminhada e cobre boa parte do fluxo da PAV-36, mas como esse PR altera um fluxo sensível de identidade/autenticação, ainda precisamos fechar alguns pontos antes da aprovação.

O principal problema está na relação entre a criação da solicitação de troca e o envio do e-mail de confirmação. Hoje a solicitação é persistida e considerada concluída mesmo quando o módulo centralizado de e-mail não consegue enfileirar a mensagem, porque esse módulo foi originalmente desenhado para tratar falha de envio como não bloqueante. Nesse fluxo específico, porém, o e-mail é parte obrigatória da operação: sem ele o usuário não consegue concluir a troca.

Revise esse comportamento para que a API não sinalize sucesso quando a confirmação não puder ser efetivamente disponibilizada ao usuário. Essa revisão também deve considerar o estado da solicitação já persistida e de eventuais solicitações anteriores invalidadas.

Além disso, gostaria que fossem revisados os cenários de concorrência do fluxo. Em especial, precisamos garantir consistência quando houver solicitações simultâneas para o mesmo novo e-mail, múltiplas solicitações para o mesmo usuário e concorrência entre confirmação de token e criação de uma nova solicitação. O banco e a camada de serviço precisam preservar as invariantes do fluxo também nesses casos.

A cobertura atual contempla bem o happy path, token inválido/expirado e e-mail já utilizado, mas precisa incluir os cenários de falha de infraestrutura e concorrência relevantes para essa feature. Como esse fluxo altera users, credentials e a nova tabela de solicitações dentro do processo de confirmação, gostaria também de cobertura explícita garantindo atomicidade: ou a troca é concluída integralmente, ou o estado anterior permanece consistente.

Por fim, valide o comportamento de sessão após a confirmação da troca de e-mail. Como a identidade persistida é alterada em users e credentials, precisamos garantir que sessões/autenticações existentes continuem com o comportamento definido pelo produto e que não exista inconsistência entre o e-mail exibido, o e-mail usado para login e os dados da sessão após a confirmação.

Com esses pontos tratados e cobertos por testes, o PR fica em condição de aprovação.

@Jovinull

Copy link
Copy Markdown
ContributorAuthor

Atualiza??o aplicada em resposta ao review t?cnico:

  • O envio do e-mail de confirma??o agora pode ser marcado como obrigat?rio.
  • No fluxo de troca de e-mail, falhas ao enfileirar a confirma??o s?o propagadas para a API.
  • A cria??o do pedido e o envio obrigat?rio s?o executados dentro da transa??o; se o envio falhar, a solicita??o n?o ? conclu?da.
  • Adicionados testes para falha de infraestrutura no enqueue e para o comportamento de envio obrigat?rio.

Valida??o:

  • Suite completa do backend: 61 arquivos e 584 testes aprovados.
  • Lint do frontend: conclu?do sem erros (apenas warning preexistente de depend?ncia de hook).
  • Build do frontend: conclu?do com sucesso.

Commit: 56d36ae

Sign up for freeto 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

@Jovinull@hltav
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(auth): adiciona confirmação de troca de e-mail - #238

Open
Jovinull wants to merge 3 commits into
Cla-Code-Community:developfrom
Jovinull:feature/pav-36-troca-email-confirmacao
Open

feat(auth): adiciona confirmação de troca de e-mail#238
Jovinull wants to merge 3 commits into
Cla-Code-Community:developfrom
Jovinull:feature/pav-36-troca-email-confirmacao

Conversation

@Jovinull

@JovinullJovinull commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Card

  • PAV-36

Objetivo e escopo

  • Exigir confirmação antes de efetivar a troca de e-mail de um usuário.
  • Manter o e-mail atual até a confirmação do token recebido no novo endereço.

O que foi feito

  • Adiciona a tabela e migration de pedidos de troca de e-mail.
  • Cria o serviço que invalida pedidos anteriores, valida duplicidade de e-mail, gera o pedido e confirma a troca por token.
  • Adiciona POST /users/email-change para solicitar a troca com sessão autenticada.
  • Adiciona POST /auth/email-change/confirm para confirmar o token sem exigir sessão.
  • Inclui template de e-mail, formulário no perfil e a tela /confirmar-email.
  • Torna o campo de e-mail do perfil somente leitura, direcionando a alteração para o fluxo de confirmação.

Módulos afetados

  • backend/drizzle/0014_panoramic_leopardon.sql
  • backend/src/modules/users/emailChange.service.ts
  • backend/src/routes/auth.routes.ts
  • backend/src/routes/users.routes.ts
  • backend/src/modules/email/templates/emailChangeConfirmation.tsx
  • frontend/src/domains/new_dashboard/components/profile/EmailChangeForm.tsx
  • frontend/src/domains/auth/presentation/pages/ConfirmEmailChangePage.tsx

Validação

  • CI do PR concluído com sucesso, incluindo coverage de frontend e backend, lint e build.
  • npm exec --workspace=backend vitest run tests/integration/routes/auth.routes.test.ts tests/integration/routes/user.routes.test.ts tests/unit/modules/email/email.service.test.ts tests/unit/modules/users/emailChange.service.test.ts - 4 arquivos e 67 testes aprovados.
  • npm exec --workspace=frontend vitest run tests/unit/new_dashboard/emailChange.test.tsx - 1 arquivo e 3 testes aprovados.
  • Os testes cobrem solicitação autenticada, e-mail inválido, ausência de sessão, confirmação sem sessão, token inválido ou expirado, e-mail já utilizado, tela de confirmação e link sem token.
  • npm run lint --workspace=frontend - concluído sem erros.
  • npm run build --workspace=frontend - concluído com sucesso.
  • Smoke manual em navegador: acessei /confirmar-email sem token, validei a mensagem de link inválido e a navegação para o login.

Riscos e observações

  • A migration 0014_panoramic_leopardon.sql precisa ser aplicada antes de disponibilizar o fluxo.
  • O envio efetivo pelo Resend não foi executado nesta validação, pois não há credencial configurada. O contrato de enfileiramento e o conteúdo da URL de confirmação foram validados por teste automatizado.
  • A confirmação com token válido contra uma instância real de banco e serviço de e-mail permanece pendente de ambiente configurado.

hltavand others added 2 commits August 23, 2026 18:32
…ode-Community#230)
## Linear
Issue: PAV-119
Closes PAV-119
## Branch flow
- [ ] Este PR é uma feature/fix/chore destinada a `develop`.
- [x] Este é um PR de release com origem `develop` e destino `master`.
- [x] Este PR não pula o fluxo obrigatório entre `develop` e `master`.
## Objetivo
Promover para `master` a implementação do lock distribuído do scraper,
garantindo no máximo uma execução ativa do pipeline entre diferentes
origens de disparo.
## Resumo das Alterações
- Implementa lock distribuído no Valkey compartilhado por cron, execução
manual administrativa e cache miss de `/scrape`.
- Utiliza aquisição atômica com `SET NX PX`, TTL e renovação periódica.
- Protege renovação e liberação por ownership/token.
- Implementa comportamento fail-closed quando o Valkey não confirma a
aquisição.
- Cancela a execução de forma segura em caso de perda do lock.
- Adiciona estado operacional com `runId`, origem, início e expiração
sem expor o token proprietário.
- Adiciona contratos HTTP para execução concorrente e indisponibilidade
do run lock.
- Alinha os defaults de `SCRAPER_RUN_LOCK_TTL` e
`SCRAPER_RUN_LOCK_RENEW_INTERVAL` à semântica fail-fast definida
anteriormente.
- Adiciona cobertura de testes para concorrência, ownership,
configuração, renovação, liberação e cenários de falha.
- Atualiza documentação e configuração do Docker Compose.
## Arquivos e Módulos Afetados
- Scraper Go
- Run lock / Valkey
- Scheduler e pipeline do scraper
- Backend administrativo
- Configuração do scraper
- Docker Compose
- Testes Go e backend
- Documentação operacional
## Validação
- [x] Implementação revisada contra o escopo da PAV-119.
- [x] Ajustes solicitados no code review aplicados.
- [x] Semântica fail-fast das configurações do run lock validada.
- [x] Nenhuma alteração de frontend incluída no escopo.
- [ ] CI final do PR de release validado.
## Observações
Este PR promove alterações já integradas e revisadas em `develop`.
Não realizar squash ou alterações adicionais diretamente em `master`
fora do fluxo de release.

@hltavhltav left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

PR fora do padrão de contribuição do projeto.

Antes da revisão técnica, por favor ajuste a descrição conforme o template/documentação do repositório, incluindo card relacionado, objetivo, resumo das alterações, arquivos/módulos afetados, validações executadas e observações relevantes.

Com 24 arquivos alterados e mais de 2 mil linhas adicionadas, precisamos desse contexto para realizar uma revisão segura e rastreável. Após a adequação da PR, seguimos com a revisão do código.

@hltavhltav left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

A implementação está bem encaminhada e cobre boa parte do fluxo da PAV-36, mas como esse PR altera um fluxo sensível de identidade/autenticação, ainda precisamos fechar alguns pontos antes da aprovação.

O principal problema está na relação entre a criação da solicitação de troca e o envio do e-mail de confirmação. Hoje a solicitação é persistida e considerada concluída mesmo quando o módulo centralizado de e-mail não consegue enfileirar a mensagem, porque esse módulo foi originalmente desenhado para tratar falha de envio como não bloqueante. Nesse fluxo específico, porém, o e-mail é parte obrigatória da operação: sem ele o usuário não consegue concluir a troca.

Revise esse comportamento para que a API não sinalize sucesso quando a confirmação não puder ser efetivamente disponibilizada ao usuário. Essa revisão também deve considerar o estado da solicitação já persistida e de eventuais solicitações anteriores invalidadas.

Além disso, gostaria que fossem revisados os cenários de concorrência do fluxo. Em especial, precisamos garantir consistência quando houver solicitações simultâneas para o mesmo novo e-mail, múltiplas solicitações para o mesmo usuário e concorrência entre confirmação de token e criação de uma nova solicitação. O banco e a camada de serviço precisam preservar as invariantes do fluxo também nesses casos.

A cobertura atual contempla bem o happy path, token inválido/expirado e e-mail já utilizado, mas precisa incluir os cenários de falha de infraestrutura e concorrência relevantes para essa feature. Como esse fluxo altera users, credentials e a nova tabela de solicitações dentro do processo de confirmação, gostaria também de cobertura explícita garantindo atomicidade: ou a troca é concluída integralmente, ou o estado anterior permanece consistente.

Por fim, valide o comportamento de sessão após a confirmação da troca de e-mail. Como a identidade persistida é alterada em users e credentials, precisamos garantir que sessões/autenticações existentes continuem com o comportamento definido pelo produto e que não exista inconsistência entre o e-mail exibido, o e-mail usado para login e os dados da sessão após a confirmação.

Com esses pontos tratados e cobertos por testes, o PR fica em condição de aprovação.

@Jovinull

Copy link
Copy Markdown
ContributorAuthor

Atualiza??o aplicada em resposta ao review t?cnico:

  • O envio do e-mail de confirma??o agora pode ser marcado como obrigat?rio.
  • No fluxo de troca de e-mail, falhas ao enfileirar a confirma??o s?o propagadas para a API.
  • A cria??o do pedido e o envio obrigat?rio s?o executados dentro da transa??o; se o envio falhar, a solicita??o n?o ? conclu?da.
  • Adicionados testes para falha de infraestrutura no enqueue e para o comportamento de envio obrigat?rio.

Valida??o:

  • Suite completa do backend: 61 arquivos e 584 testes aprovados.
  • Lint do frontend: conclu?do sem erros (apenas warning preexistente de depend?ncia de hook).
  • Build do frontend: conclu?do com sucesso.

Commit: 56d36ae

Sign up for freeto 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

@Jovinull@hltav
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(auth): adiciona confirmação de troca de e-mail - #238

Open
Jovinull wants to merge 3 commits into
Cla-Code-Community:developfrom
Jovinull:feature/pav-36-troca-email-confirmacao
Open

feat(auth): adiciona confirmação de troca de e-mail#238
Jovinull wants to merge 3 commits into
Cla-Code-Community:developfrom
Jovinull:feature/pav-36-troca-email-confirmacao

Conversation

@Jovinull

@JovinullJovinull commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Card

  • PAV-36

Objetivo e escopo

  • Exigir confirmação antes de efetivar a troca de e-mail de um usuário.
  • Manter o e-mail atual até a confirmação do token recebido no novo endereço.

O que foi feito

  • Adiciona a tabela e migration de pedidos de troca de e-mail.
  • Cria o serviço que invalida pedidos anteriores, valida duplicidade de e-mail, gera o pedido e confirma a troca por token.
  • Adiciona POST /users/email-change para solicitar a troca com sessão autenticada.
  • Adiciona POST /auth/email-change/confirm para confirmar o token sem exigir sessão.
  • Inclui template de e-mail, formulário no perfil e a tela /confirmar-email.
  • Torna o campo de e-mail do perfil somente leitura, direcionando a alteração para o fluxo de confirmação.

Módulos afetados

  • backend/drizzle/0014_panoramic_leopardon.sql
  • backend/src/modules/users/emailChange.service.ts
  • backend/src/routes/auth.routes.ts
  • backend/src/routes/users.routes.ts
  • backend/src/modules/email/templates/emailChangeConfirmation.tsx
  • frontend/src/domains/new_dashboard/components/profile/EmailChangeForm.tsx
  • frontend/src/domains/auth/presentation/pages/ConfirmEmailChangePage.tsx

Validação

  • CI do PR concluído com sucesso, incluindo coverage de frontend e backend, lint e build.
  • npm exec --workspace=backend vitest run tests/integration/routes/auth.routes.test.ts tests/integration/routes/user.routes.test.ts tests/unit/modules/email/email.service.test.ts tests/unit/modules/users/emailChange.service.test.ts - 4 arquivos e 67 testes aprovados.
  • npm exec --workspace=frontend vitest run tests/unit/new_dashboard/emailChange.test.tsx - 1 arquivo e 3 testes aprovados.
  • Os testes cobrem solicitação autenticada, e-mail inválido, ausência de sessão, confirmação sem sessão, token inválido ou expirado, e-mail já utilizado, tela de confirmação e link sem token.
  • npm run lint --workspace=frontend - concluído sem erros.
  • npm run build --workspace=frontend - concluído com sucesso.
  • Smoke manual em navegador: acessei /confirmar-email sem token, validei a mensagem de link inválido e a navegação para o login.

Riscos e observações

  • A migration 0014_panoramic_leopardon.sql precisa ser aplicada antes de disponibilizar o fluxo.
  • O envio efetivo pelo Resend não foi executado nesta validação, pois não há credencial configurada. O contrato de enfileiramento e o conteúdo da URL de confirmação foram validados por teste automatizado.
  • A confirmação com token válido contra uma instância real de banco e serviço de e-mail permanece pendente de ambiente configurado.

hltavand others added 2 commits August 23, 2026 18:32
…ode-Community#230)
## Linear
Issue: PAV-119
Closes PAV-119
## Branch flow
- [ ] Este PR é uma feature/fix/chore destinada a `develop`.
- [x] Este é um PR de release com origem `develop` e destino `master`.
- [x] Este PR não pula o fluxo obrigatório entre `develop` e `master`.
## Objetivo
Promover para `master` a implementação do lock distribuído do scraper,
garantindo no máximo uma execução ativa do pipeline entre diferentes
origens de disparo.
## Resumo das Alterações
- Implementa lock distribuído no Valkey compartilhado por cron, execução
manual administrativa e cache miss de `/scrape`.
- Utiliza aquisição atômica com `SET NX PX`, TTL e renovação periódica.
- Protege renovação e liberação por ownership/token.
- Implementa comportamento fail-closed quando o Valkey não confirma a
aquisição.
- Cancela a execução de forma segura em caso de perda do lock.
- Adiciona estado operacional com `runId`, origem, início e expiração
sem expor o token proprietário.
- Adiciona contratos HTTP para execução concorrente e indisponibilidade
do run lock.
- Alinha os defaults de `SCRAPER_RUN_LOCK_TTL` e
`SCRAPER_RUN_LOCK_RENEW_INTERVAL` à semântica fail-fast definida
anteriormente.
- Adiciona cobertura de testes para concorrência, ownership,
configuração, renovação, liberação e cenários de falha.
- Atualiza documentação e configuração do Docker Compose.
## Arquivos e Módulos Afetados
- Scraper Go
- Run lock / Valkey
- Scheduler e pipeline do scraper
- Backend administrativo
- Configuração do scraper
- Docker Compose
- Testes Go e backend
- Documentação operacional
## Validação
- [x] Implementação revisada contra o escopo da PAV-119.
- [x] Ajustes solicitados no code review aplicados.
- [x] Semântica fail-fast das configurações do run lock validada.
- [x] Nenhuma alteração de frontend incluída no escopo.
- [ ] CI final do PR de release validado.
## Observações
Este PR promove alterações já integradas e revisadas em `develop`.
Não realizar squash ou alterações adicionais diretamente em `master`
fora do fluxo de release.

@hltavhltav left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

PR fora do padrão de contribuição do projeto.

Antes da revisão técnica, por favor ajuste a descrição conforme o template/documentação do repositório, incluindo card relacionado, objetivo, resumo das alterações, arquivos/módulos afetados, validações executadas e observações relevantes.

Com 24 arquivos alterados e mais de 2 mil linhas adicionadas, precisamos desse contexto para realizar uma revisão segura e rastreável. Após a adequação da PR, seguimos com a revisão do código.

@hltavhltav left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

A implementação está bem encaminhada e cobre boa parte do fluxo da PAV-36, mas como esse PR altera um fluxo sensível de identidade/autenticação, ainda precisamos fechar alguns pontos antes da aprovação.

O principal problema está na relação entre a criação da solicitação de troca e o envio do e-mail de confirmação. Hoje a solicitação é persistida e considerada concluída mesmo quando o módulo centralizado de e-mail não consegue enfileirar a mensagem, porque esse módulo foi originalmente desenhado para tratar falha de envio como não bloqueante. Nesse fluxo específico, porém, o e-mail é parte obrigatória da operação: sem ele o usuário não consegue concluir a troca.

Revise esse comportamento para que a API não sinalize sucesso quando a confirmação não puder ser efetivamente disponibilizada ao usuário. Essa revisão também deve considerar o estado da solicitação já persistida e de eventuais solicitações anteriores invalidadas.

Além disso, gostaria que fossem revisados os cenários de concorrência do fluxo. Em especial, precisamos garantir consistência quando houver solicitações simultâneas para o mesmo novo e-mail, múltiplas solicitações para o mesmo usuário e concorrência entre confirmação de token e criação de uma nova solicitação. O banco e a camada de serviço precisam preservar as invariantes do fluxo também nesses casos.

A cobertura atual contempla bem o happy path, token inválido/expirado e e-mail já utilizado, mas precisa incluir os cenários de falha de infraestrutura e concorrência relevantes para essa feature. Como esse fluxo altera users, credentials e a nova tabela de solicitações dentro do processo de confirmação, gostaria também de cobertura explícita garantindo atomicidade: ou a troca é concluída integralmente, ou o estado anterior permanece consistente.

Por fim, valide o comportamento de sessão após a confirmação da troca de e-mail. Como a identidade persistida é alterada em users e credentials, precisamos garantir que sessões/autenticações existentes continuem com o comportamento definido pelo produto e que não exista inconsistência entre o e-mail exibido, o e-mail usado para login e os dados da sessão após a confirmação.

Com esses pontos tratados e cobertos por testes, o PR fica em condição de aprovação.

@Jovinull

Copy link
Copy Markdown
ContributorAuthor

Atualiza??o aplicada em resposta ao review t?cnico:

  • O envio do e-mail de confirma??o agora pode ser marcado como obrigat?rio.
  • No fluxo de troca de e-mail, falhas ao enfileirar a confirma??o s?o propagadas para a API.
  • A cria??o do pedido e o envio obrigat?rio s?o executados dentro da transa??o; se o envio falhar, a solicita??o n?o ? conclu?da.
  • Adicionados testes para falha de infraestrutura no enqueue e para o comportamento de envio obrigat?rio.

Valida??o:

  • Suite completa do backend: 61 arquivos e 584 testes aprovados.
  • Lint do frontend: conclu?do sem erros (apenas warning preexistente de depend?ncia de hook).
  • Build do frontend: conclu?do com sucesso.

Commit: 56d36ae

Sign up for freeto 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

@Jovinull@hltav
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

feat(auth): adiciona confirmação de troca de e-mail - #238

Open
Jovinull wants to merge 3 commits into
Cla-Code-Community:developfrom
Jovinull:feature/pav-36-troca-email-confirmacao
Open

feat(auth): adiciona confirmação de troca de e-mail#238
Jovinull wants to merge 3 commits into
Cla-Code-Community:developfrom
Jovinull:feature/pav-36-troca-email-confirmacao

Conversation

@Jovinull

@JovinullJovinull commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Card

  • PAV-36

Objetivo e escopo

  • Exigir confirmação antes de efetivar a troca de e-mail de um usuário.
  • Manter o e-mail atual até a confirmação do token recebido no novo endereço.

O que foi feito

  • Adiciona a tabela e migration de pedidos de troca de e-mail.
  • Cria o serviço que invalida pedidos anteriores, valida duplicidade de e-mail, gera o pedido e confirma a troca por token.
  • Adiciona POST /users/email-change para solicitar a troca com sessão autenticada.
  • Adiciona POST /auth/email-change/confirm para confirmar o token sem exigir sessão.
  • Inclui template de e-mail, formulário no perfil e a tela /confirmar-email.
  • Torna o campo de e-mail do perfil somente leitura, direcionando a alteração para o fluxo de confirmação.

Módulos afetados

  • backend/drizzle/0014_panoramic_leopardon.sql
  • backend/src/modules/users/emailChange.service.ts
  • backend/src/routes/auth.routes.ts
  • backend/src/routes/users.routes.ts
  • backend/src/modules/email/templates/emailChangeConfirmation.tsx
  • frontend/src/domains/new_dashboard/components/profile/EmailChangeForm.tsx
  • frontend/src/domains/auth/presentation/pages/ConfirmEmailChangePage.tsx

Validação

  • CI do PR concluído com sucesso, incluindo coverage de frontend e backend, lint e build.
  • npm exec --workspace=backend vitest run tests/integration/routes/auth.routes.test.ts tests/integration/routes/user.routes.test.ts tests/unit/modules/email/email.service.test.ts tests/unit/modules/users/emailChange.service.test.ts - 4 arquivos e 67 testes aprovados.
  • npm exec --workspace=frontend vitest run tests/unit/new_dashboard/emailChange.test.tsx - 1 arquivo e 3 testes aprovados.
  • Os testes cobrem solicitação autenticada, e-mail inválido, ausência de sessão, confirmação sem sessão, token inválido ou expirado, e-mail já utilizado, tela de confirmação e link sem token.
  • npm run lint --workspace=frontend - concluído sem erros.
  • npm run build --workspace=frontend - concluído com sucesso.
  • Smoke manual em navegador: acessei /confirmar-email sem token, validei a mensagem de link inválido e a navegação para o login.

Riscos e observações

  • A migration 0014_panoramic_leopardon.sql precisa ser aplicada antes de disponibilizar o fluxo.
  • O envio efetivo pelo Resend não foi executado nesta validação, pois não há credencial configurada. O contrato de enfileiramento e o conteúdo da URL de confirmação foram validados por teste automatizado.
  • A confirmação com token válido contra uma instância real de banco e serviço de e-mail permanece pendente de ambiente configurado.

hltavand others added 2 commits August 23, 2026 18:32
…ode-Community#230)
## Linear
Issue: PAV-119
Closes PAV-119
## Branch flow
- [ ] Este PR é uma feature/fix/chore destinada a `develop`.
- [x] Este é um PR de release com origem `develop` e destino `master`.
- [x] Este PR não pula o fluxo obrigatório entre `develop` e `master`.
## Objetivo
Promover para `master` a implementação do lock distribuído do scraper,
garantindo no máximo uma execução ativa do pipeline entre diferentes
origens de disparo.
## Resumo das Alterações
- Implementa lock distribuído no Valkey compartilhado por cron, execução
manual administrativa e cache miss de `/scrape`.
- Utiliza aquisição atômica com `SET NX PX`, TTL e renovação periódica.
- Protege renovação e liberação por ownership/token.
- Implementa comportamento fail-closed quando o Valkey não confirma a
aquisição.
- Cancela a execução de forma segura em caso de perda do lock.
- Adiciona estado operacional com `runId`, origem, início e expiração
sem expor o token proprietário.
- Adiciona contratos HTTP para execução concorrente e indisponibilidade
do run lock.
- Alinha os defaults de `SCRAPER_RUN_LOCK_TTL` e
`SCRAPER_RUN_LOCK_RENEW_INTERVAL` à semântica fail-fast definida
anteriormente.
- Adiciona cobertura de testes para concorrência, ownership,
configuração, renovação, liberação e cenários de falha.
- Atualiza documentação e configuração do Docker Compose.
## Arquivos e Módulos Afetados
- Scraper Go
- Run lock / Valkey
- Scheduler e pipeline do scraper
- Backend administrativo
- Configuração do scraper
- Docker Compose
- Testes Go e backend
- Documentação operacional
## Validação
- [x] Implementação revisada contra o escopo da PAV-119.
- [x] Ajustes solicitados no code review aplicados.
- [x] Semântica fail-fast das configurações do run lock validada.
- [x] Nenhuma alteração de frontend incluída no escopo.
- [ ] CI final do PR de release validado.
## Observações
Este PR promove alterações já integradas e revisadas em `develop`.
Não realizar squash ou alterações adicionais diretamente em `master`
fora do fluxo de release.

@hltavhltav left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

PR fora do padrão de contribuição do projeto.

Antes da revisão técnica, por favor ajuste a descrição conforme o template/documentação do repositório, incluindo card relacionado, objetivo, resumo das alterações, arquivos/módulos afetados, validações executadas e observações relevantes.

Com 24 arquivos alterados e mais de 2 mil linhas adicionadas, precisamos desse contexto para realizar uma revisão segura e rastreável. Após a adequação da PR, seguimos com a revisão do código.

@hltavhltav left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

A implementação está bem encaminhada e cobre boa parte do fluxo da PAV-36, mas como esse PR altera um fluxo sensível de identidade/autenticação, ainda precisamos fechar alguns pontos antes da aprovação.

O principal problema está na relação entre a criação da solicitação de troca e o envio do e-mail de confirmação. Hoje a solicitação é persistida e considerada concluída mesmo quando o módulo centralizado de e-mail não consegue enfileirar a mensagem, porque esse módulo foi originalmente desenhado para tratar falha de envio como não bloqueante. Nesse fluxo específico, porém, o e-mail é parte obrigatória da operação: sem ele o usuário não consegue concluir a troca.

Revise esse comportamento para que a API não sinalize sucesso quando a confirmação não puder ser efetivamente disponibilizada ao usuário. Essa revisão também deve considerar o estado da solicitação já persistida e de eventuais solicitações anteriores invalidadas.

Além disso, gostaria que fossem revisados os cenários de concorrência do fluxo. Em especial, precisamos garantir consistência quando houver solicitações simultâneas para o mesmo novo e-mail, múltiplas solicitações para o mesmo usuário e concorrência entre confirmação de token e criação de uma nova solicitação. O banco e a camada de serviço precisam preservar as invariantes do fluxo também nesses casos.

A cobertura atual contempla bem o happy path, token inválido/expirado e e-mail já utilizado, mas precisa incluir os cenários de falha de infraestrutura e concorrência relevantes para essa feature. Como esse fluxo altera users, credentials e a nova tabela de solicitações dentro do processo de confirmação, gostaria também de cobertura explícita garantindo atomicidade: ou a troca é concluída integralmente, ou o estado anterior permanece consistente.

Por fim, valide o comportamento de sessão após a confirmação da troca de e-mail. Como a identidade persistida é alterada em users e credentials, precisamos garantir que sessões/autenticações existentes continuem com o comportamento definido pelo produto e que não exista inconsistência entre o e-mail exibido, o e-mail usado para login e os dados da sessão após a confirmação.

Com esses pontos tratados e cobertos por testes, o PR fica em condição de aprovação.

@Jovinull

Copy link
Copy Markdown
ContributorAuthor

Atualiza??o aplicada em resposta ao review t?cnico:

  • O envio do e-mail de confirma??o agora pode ser marcado como obrigat?rio.
  • No fluxo de troca de e-mail, falhas ao enfileirar a confirma??o s?o propagadas para a API.
  • A cria??o do pedido e o envio obrigat?rio s?o executados dentro da transa??o; se o envio falhar, a solicita??o n?o ? conclu?da.
  • Adicionados testes para falha de infraestrutura no enqueue e para o comportamento de envio obrigat?rio.

Valida??o:

  • Suite completa do backend: 61 arquivos e 584 testes aprovados.
  • Lint do frontend: conclu?do sem erros (apenas warning preexistente de depend?ncia de hook).
  • Build do frontend: conclu?do com sucesso.

Commit: 56d36ae

Sign up for freeto 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

@Jovinull@hltav
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(auth): adiciona confirmação de troca de e-mail - #238

Open
Jovinull wants to merge 3 commits into
Cla-Code-Community:developfrom
Jovinull:feature/pav-36-troca-email-confirmacao
Open

feat(auth): adiciona confirmação de troca de e-mail#238
Jovinull wants to merge 3 commits into
Cla-Code-Community:developfrom
Jovinull:feature/pav-36-troca-email-confirmacao

Conversation

@Jovinull

@JovinullJovinull commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Card

  • PAV-36

Objetivo e escopo

  • Exigir confirmação antes de efetivar a troca de e-mail de um usuário.
  • Manter o e-mail atual até a confirmação do token recebido no novo endereço.

O que foi feito

  • Adiciona a tabela e migration de pedidos de troca de e-mail.
  • Cria o serviço que invalida pedidos anteriores, valida duplicidade de e-mail, gera o pedido e confirma a troca por token.
  • Adiciona POST /users/email-change para solicitar a troca com sessão autenticada.
  • Adiciona POST /auth/email-change/confirm para confirmar o token sem exigir sessão.
  • Inclui template de e-mail, formulário no perfil e a tela /confirmar-email.
  • Torna o campo de e-mail do perfil somente leitura, direcionando a alteração para o fluxo de confirmação.

Módulos afetados

  • backend/drizzle/0014_panoramic_leopardon.sql
  • backend/src/modules/users/emailChange.service.ts
  • backend/src/routes/auth.routes.ts
  • backend/src/routes/users.routes.ts
  • backend/src/modules/email/templates/emailChangeConfirmation.tsx
  • frontend/src/domains/new_dashboard/components/profile/EmailChangeForm.tsx
  • frontend/src/domains/auth/presentation/pages/ConfirmEmailChangePage.tsx

Validação

  • CI do PR concluído com sucesso, incluindo coverage de frontend e backend, lint e build.
  • npm exec --workspace=backend vitest run tests/integration/routes/auth.routes.test.ts tests/integration/routes/user.routes.test.ts tests/unit/modules/email/email.service.test.ts tests/unit/modules/users/emailChange.service.test.ts - 4 arquivos e 67 testes aprovados.
  • npm exec --workspace=frontend vitest run tests/unit/new_dashboard/emailChange.test.tsx - 1 arquivo e 3 testes aprovados.
  • Os testes cobrem solicitação autenticada, e-mail inválido, ausência de sessão, confirmação sem sessão, token inválido ou expirado, e-mail já utilizado, tela de confirmação e link sem token.
  • npm run lint --workspace=frontend - concluído sem erros.
  • npm run build --workspace=frontend - concluído com sucesso.
  • Smoke manual em navegador: acessei /confirmar-email sem token, validei a mensagem de link inválido e a navegação para o login.

Riscos e observações

  • A migration 0014_panoramic_leopardon.sql precisa ser aplicada antes de disponibilizar o fluxo.
  • O envio efetivo pelo Resend não foi executado nesta validação, pois não há credencial configurada. O contrato de enfileiramento e o conteúdo da URL de confirmação foram validados por teste automatizado.
  • A confirmação com token válido contra uma instância real de banco e serviço de e-mail permanece pendente de ambiente configurado.

hltavand others added 2 commits August 23, 2026 18:32
…ode-Community#230)
## Linear
Issue: PAV-119
Closes PAV-119
## Branch flow
- [ ] Este PR é uma feature/fix/chore destinada a `develop`.
- [x] Este é um PR de release com origem `develop` e destino `master`.
- [x] Este PR não pula o fluxo obrigatório entre `develop` e `master`.
## Objetivo
Promover para `master` a implementação do lock distribuído do scraper,
garantindo no máximo uma execução ativa do pipeline entre diferentes
origens de disparo.
## Resumo das Alterações
- Implementa lock distribuído no Valkey compartilhado por cron, execução
manual administrativa e cache miss de `/scrape`.
- Utiliza aquisição atômica com `SET NX PX`, TTL e renovação periódica.
- Protege renovação e liberação por ownership/token.
- Implementa comportamento fail-closed quando o Valkey não confirma a
aquisição.
- Cancela a execução de forma segura em caso de perda do lock.
- Adiciona estado operacional com `runId`, origem, início e expiração
sem expor o token proprietário.
- Adiciona contratos HTTP para execução concorrente e indisponibilidade
do run lock.
- Alinha os defaults de `SCRAPER_RUN_LOCK_TTL` e
`SCRAPER_RUN_LOCK_RENEW_INTERVAL` à semântica fail-fast definida
anteriormente.
- Adiciona cobertura de testes para concorrência, ownership,
configuração, renovação, liberação e cenários de falha.
- Atualiza documentação e configuração do Docker Compose.
## Arquivos e Módulos Afetados
- Scraper Go
- Run lock / Valkey
- Scheduler e pipeline do scraper
- Backend administrativo
- Configuração do scraper
- Docker Compose
- Testes Go e backend
- Documentação operacional
## Validação
- [x] Implementação revisada contra o escopo da PAV-119.
- [x] Ajustes solicitados no code review aplicados.
- [x] Semântica fail-fast das configurações do run lock validada.
- [x] Nenhuma alteração de frontend incluída no escopo.
- [ ] CI final do PR de release validado.
## Observações
Este PR promove alterações já integradas e revisadas em `develop`.
Não realizar squash ou alterações adicionais diretamente em `master`
fora do fluxo de release.

@hltavhltav left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

PR fora do padrão de contribuição do projeto.

Antes da revisão técnica, por favor ajuste a descrição conforme o template/documentação do repositório, incluindo card relacionado, objetivo, resumo das alterações, arquivos/módulos afetados, validações executadas e observações relevantes.

Com 24 arquivos alterados e mais de 2 mil linhas adicionadas, precisamos desse contexto para realizar uma revisão segura e rastreável. Após a adequação da PR, seguimos com a revisão do código.

@hltavhltav left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

A implementação está bem encaminhada e cobre boa parte do fluxo da PAV-36, mas como esse PR altera um fluxo sensível de identidade/autenticação, ainda precisamos fechar alguns pontos antes da aprovação.

O principal problema está na relação entre a criação da solicitação de troca e o envio do e-mail de confirmação. Hoje a solicitação é persistida e considerada concluída mesmo quando o módulo centralizado de e-mail não consegue enfileirar a mensagem, porque esse módulo foi originalmente desenhado para tratar falha de envio como não bloqueante. Nesse fluxo específico, porém, o e-mail é parte obrigatória da operação: sem ele o usuário não consegue concluir a troca.

Revise esse comportamento para que a API não sinalize sucesso quando a confirmação não puder ser efetivamente disponibilizada ao usuário. Essa revisão também deve considerar o estado da solicitação já persistida e de eventuais solicitações anteriores invalidadas.

Além disso, gostaria que fossem revisados os cenários de concorrência do fluxo. Em especial, precisamos garantir consistência quando houver solicitações simultâneas para o mesmo novo e-mail, múltiplas solicitações para o mesmo usuário e concorrência entre confirmação de token e criação de uma nova solicitação. O banco e a camada de serviço precisam preservar as invariantes do fluxo também nesses casos.

A cobertura atual contempla bem o happy path, token inválido/expirado e e-mail já utilizado, mas precisa incluir os cenários de falha de infraestrutura e concorrência relevantes para essa feature. Como esse fluxo altera users, credentials e a nova tabela de solicitações dentro do processo de confirmação, gostaria também de cobertura explícita garantindo atomicidade: ou a troca é concluída integralmente, ou o estado anterior permanece consistente.

Por fim, valide o comportamento de sessão após a confirmação da troca de e-mail. Como a identidade persistida é alterada em users e credentials, precisamos garantir que sessões/autenticações existentes continuem com o comportamento definido pelo produto e que não exista inconsistência entre o e-mail exibido, o e-mail usado para login e os dados da sessão após a confirmação.

Com esses pontos tratados e cobertos por testes, o PR fica em condição de aprovação.

@Jovinull

Copy link
Copy Markdown
ContributorAuthor

Atualiza??o aplicada em resposta ao review t?cnico:

  • O envio do e-mail de confirma??o agora pode ser marcado como obrigat?rio.
  • No fluxo de troca de e-mail, falhas ao enfileirar a confirma??o s?o propagadas para a API.
  • A cria??o do pedido e o envio obrigat?rio s?o executados dentro da transa??o; se o envio falhar, a solicita??o n?o ? conclu?da.
  • Adicionados testes para falha de infraestrutura no enqueue e para o comportamento de envio obrigat?rio.

Valida??o:

  • Suite completa do backend: 61 arquivos e 584 testes aprovados.
  • Lint do frontend: conclu?do sem erros (apenas warning preexistente de depend?ncia de hook).
  • Build do frontend: conclu?do com sucesso.

Commit: 56d36ae

Sign up for freeto 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

@Jovinull@hltav
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(auth): adiciona confirmação de troca de e-mail - #238

Open
Jovinull wants to merge 3 commits into
Cla-Code-Community:developfrom
Jovinull:feature/pav-36-troca-email-confirmacao
Open

feat(auth): adiciona confirmação de troca de e-mail#238
Jovinull wants to merge 3 commits into
Cla-Code-Community:developfrom
Jovinull:feature/pav-36-troca-email-confirmacao

Conversation

@Jovinull

@JovinullJovinull commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Card

  • PAV-36

Objetivo e escopo

  • Exigir confirmação antes de efetivar a troca de e-mail de um usuário.
  • Manter o e-mail atual até a confirmação do token recebido no novo endereço.

O que foi feito

  • Adiciona a tabela e migration de pedidos de troca de e-mail.
  • Cria o serviço que invalida pedidos anteriores, valida duplicidade de e-mail, gera o pedido e confirma a troca por token.
  • Adiciona POST /users/email-change para solicitar a troca com sessão autenticada.
  • Adiciona POST /auth/email-change/confirm para confirmar o token sem exigir sessão.
  • Inclui template de e-mail, formulário no perfil e a tela /confirmar-email.
  • Torna o campo de e-mail do perfil somente leitura, direcionando a alteração para o fluxo de confirmação.

Módulos afetados

  • backend/drizzle/0014_panoramic_leopardon.sql
  • backend/src/modules/users/emailChange.service.ts
  • backend/src/routes/auth.routes.ts
  • backend/src/routes/users.routes.ts
  • backend/src/modules/email/templates/emailChangeConfirmation.tsx
  • frontend/src/domains/new_dashboard/components/profile/EmailChangeForm.tsx
  • frontend/src/domains/auth/presentation/pages/ConfirmEmailChangePage.tsx

Validação

  • CI do PR concluído com sucesso, incluindo coverage de frontend e backend, lint e build.
  • npm exec --workspace=backend vitest run tests/integration/routes/auth.routes.test.ts tests/integration/routes/user.routes.test.ts tests/unit/modules/email/email.service.test.ts tests/unit/modules/users/emailChange.service.test.ts - 4 arquivos e 67 testes aprovados.
  • npm exec --workspace=frontend vitest run tests/unit/new_dashboard/emailChange.test.tsx - 1 arquivo e 3 testes aprovados.
  • Os testes cobrem solicitação autenticada, e-mail inválido, ausência de sessão, confirmação sem sessão, token inválido ou expirado, e-mail já utilizado, tela de confirmação e link sem token.
  • npm run lint --workspace=frontend - concluído sem erros.
  • npm run build --workspace=frontend - concluído com sucesso.
  • Smoke manual em navegador: acessei /confirmar-email sem token, validei a mensagem de link inválido e a navegação para o login.

Riscos e observações

  • A migration 0014_panoramic_leopardon.sql precisa ser aplicada antes de disponibilizar o fluxo.
  • O envio efetivo pelo Resend não foi executado nesta validação, pois não há credencial configurada. O contrato de enfileiramento e o conteúdo da URL de confirmação foram validados por teste automatizado.
  • A confirmação com token válido contra uma instância real de banco e serviço de e-mail permanece pendente de ambiente configurado.

hltavand others added 2 commits August 23, 2026 18:32
…ode-Community#230)
## Linear
Issue: PAV-119
Closes PAV-119
## Branch flow
- [ ] Este PR é uma feature/fix/chore destinada a `develop`.
- [x] Este é um PR de release com origem `develop` e destino `master`.
- [x] Este PR não pula o fluxo obrigatório entre `develop` e `master`.
## Objetivo
Promover para `master` a implementação do lock distribuído do scraper,
garantindo no máximo uma execução ativa do pipeline entre diferentes
origens de disparo.
## Resumo das Alterações
- Implementa lock distribuído no Valkey compartilhado por cron, execução
manual administrativa e cache miss de `/scrape`.
- Utiliza aquisição atômica com `SET NX PX`, TTL e renovação periódica.
- Protege renovação e liberação por ownership/token.
- Implementa comportamento fail-closed quando o Valkey não confirma a
aquisição.
- Cancela a execução de forma segura em caso de perda do lock.
- Adiciona estado operacional com `runId`, origem, início e expiração
sem expor o token proprietário.
- Adiciona contratos HTTP para execução concorrente e indisponibilidade
do run lock.
- Alinha os defaults de `SCRAPER_RUN_LOCK_TTL` e
`SCRAPER_RUN_LOCK_RENEW_INTERVAL` à semântica fail-fast definida
anteriormente.
- Adiciona cobertura de testes para concorrência, ownership,
configuração, renovação, liberação e cenários de falha.
- Atualiza documentação e configuração do Docker Compose.
## Arquivos e Módulos Afetados
- Scraper Go
- Run lock / Valkey
- Scheduler e pipeline do scraper
- Backend administrativo
- Configuração do scraper
- Docker Compose
- Testes Go e backend
- Documentação operacional
## Validação
- [x] Implementação revisada contra o escopo da PAV-119.
- [x] Ajustes solicitados no code review aplicados.
- [x] Semântica fail-fast das configurações do run lock validada.
- [x] Nenhuma alteração de frontend incluída no escopo.
- [ ] CI final do PR de release validado.
## Observações
Este PR promove alterações já integradas e revisadas em `develop`.
Não realizar squash ou alterações adicionais diretamente em `master`
fora do fluxo de release.

@hltavhltav left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

PR fora do padrão de contribuição do projeto.

Antes da revisão técnica, por favor ajuste a descrição conforme o template/documentação do repositório, incluindo card relacionado, objetivo, resumo das alterações, arquivos/módulos afetados, validações executadas e observações relevantes.

Com 24 arquivos alterados e mais de 2 mil linhas adicionadas, precisamos desse contexto para realizar uma revisão segura e rastreável. Após a adequação da PR, seguimos com a revisão do código.

@hltavhltav left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

A implementação está bem encaminhada e cobre boa parte do fluxo da PAV-36, mas como esse PR altera um fluxo sensível de identidade/autenticação, ainda precisamos fechar alguns pontos antes da aprovação.

O principal problema está na relação entre a criação da solicitação de troca e o envio do e-mail de confirmação. Hoje a solicitação é persistida e considerada concluída mesmo quando o módulo centralizado de e-mail não consegue enfileirar a mensagem, porque esse módulo foi originalmente desenhado para tratar falha de envio como não bloqueante. Nesse fluxo específico, porém, o e-mail é parte obrigatória da operação: sem ele o usuário não consegue concluir a troca.

Revise esse comportamento para que a API não sinalize sucesso quando a confirmação não puder ser efetivamente disponibilizada ao usuário. Essa revisão também deve considerar o estado da solicitação já persistida e de eventuais solicitações anteriores invalidadas.

Além disso, gostaria que fossem revisados os cenários de concorrência do fluxo. Em especial, precisamos garantir consistência quando houver solicitações simultâneas para o mesmo novo e-mail, múltiplas solicitações para o mesmo usuário e concorrência entre confirmação de token e criação de uma nova solicitação. O banco e a camada de serviço precisam preservar as invariantes do fluxo também nesses casos.

A cobertura atual contempla bem o happy path, token inválido/expirado e e-mail já utilizado, mas precisa incluir os cenários de falha de infraestrutura e concorrência relevantes para essa feature. Como esse fluxo altera users, credentials e a nova tabela de solicitações dentro do processo de confirmação, gostaria também de cobertura explícita garantindo atomicidade: ou a troca é concluída integralmente, ou o estado anterior permanece consistente.

Por fim, valide o comportamento de sessão após a confirmação da troca de e-mail. Como a identidade persistida é alterada em users e credentials, precisamos garantir que sessões/autenticações existentes continuem com o comportamento definido pelo produto e que não exista inconsistência entre o e-mail exibido, o e-mail usado para login e os dados da sessão após a confirmação.

Com esses pontos tratados e cobertos por testes, o PR fica em condição de aprovação.

@Jovinull

Copy link
Copy Markdown
ContributorAuthor

Atualiza??o aplicada em resposta ao review t?cnico:

  • O envio do e-mail de confirma??o agora pode ser marcado como obrigat?rio.
  • No fluxo de troca de e-mail, falhas ao enfileirar a confirma??o s?o propagadas para a API.
  • A cria??o do pedido e o envio obrigat?rio s?o executados dentro da transa??o; se o envio falhar, a solicita??o n?o ? conclu?da.
  • Adicionados testes para falha de infraestrutura no enqueue e para o comportamento de envio obrigat?rio.

Valida??o:

  • Suite completa do backend: 61 arquivos e 584 testes aprovados.
  • Lint do frontend: conclu?do sem erros (apenas warning preexistente de depend?ncia de hook).
  • Build do frontend: conclu?do com sucesso.

Commit: 56d36ae

Sign up for freeto 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

@Jovinull@hltav
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

feat(auth): adiciona confirmação de troca de e-mail - #238

Open
Jovinull wants to merge 3 commits into
Cla-Code-Community:developfrom
Jovinull:feature/pav-36-troca-email-confirmacao
Open

feat(auth): adiciona confirmação de troca de e-mail#238
Jovinull wants to merge 3 commits into
Cla-Code-Community:developfrom
Jovinull:feature/pav-36-troca-email-confirmacao

Conversation

@Jovinull

@JovinullJovinull commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Card

  • PAV-36

Objetivo e escopo

  • Exigir confirmação antes de efetivar a troca de e-mail de um usuário.
  • Manter o e-mail atual até a confirmação do token recebido no novo endereço.

O que foi feito

  • Adiciona a tabela e migration de pedidos de troca de e-mail.
  • Cria o serviço que invalida pedidos anteriores, valida duplicidade de e-mail, gera o pedido e confirma a troca por token.
  • Adiciona POST /users/email-change para solicitar a troca com sessão autenticada.
  • Adiciona POST /auth/email-change/confirm para confirmar o token sem exigir sessão.
  • Inclui template de e-mail, formulário no perfil e a tela /confirmar-email.
  • Torna o campo de e-mail do perfil somente leitura, direcionando a alteração para o fluxo de confirmação.

Módulos afetados

  • backend/drizzle/0014_panoramic_leopardon.sql
  • backend/src/modules/users/emailChange.service.ts
  • backend/src/routes/auth.routes.ts
  • backend/src/routes/users.routes.ts
  • backend/src/modules/email/templates/emailChangeConfirmation.tsx
  • frontend/src/domains/new_dashboard/components/profile/EmailChangeForm.tsx
  • frontend/src/domains/auth/presentation/pages/ConfirmEmailChangePage.tsx

Validação

  • CI do PR concluído com sucesso, incluindo coverage de frontend e backend, lint e build.
  • npm exec --workspace=backend vitest run tests/integration/routes/auth.routes.test.ts tests/integration/routes/user.routes.test.ts tests/unit/modules/email/email.service.test.ts tests/unit/modules/users/emailChange.service.test.ts - 4 arquivos e 67 testes aprovados.
  • npm exec --workspace=frontend vitest run tests/unit/new_dashboard/emailChange.test.tsx - 1 arquivo e 3 testes aprovados.
  • Os testes cobrem solicitação autenticada, e-mail inválido, ausência de sessão, confirmação sem sessão, token inválido ou expirado, e-mail já utilizado, tela de confirmação e link sem token.
  • npm run lint --workspace=frontend - concluído sem erros.
  • npm run build --workspace=frontend - concluído com sucesso.
  • Smoke manual em navegador: acessei /confirmar-email sem token, validei a mensagem de link inválido e a navegação para o login.

Riscos e observações

  • A migration 0014_panoramic_leopardon.sql precisa ser aplicada antes de disponibilizar o fluxo.
  • O envio efetivo pelo Resend não foi executado nesta validação, pois não há credencial configurada. O contrato de enfileiramento e o conteúdo da URL de confirmação foram validados por teste automatizado.
  • A confirmação com token válido contra uma instância real de banco e serviço de e-mail permanece pendente de ambiente configurado.

hltavand others added 2 commits August 23, 2026 18:32
…ode-Community#230)
## Linear
Issue: PAV-119
Closes PAV-119
## Branch flow
- [ ] Este PR é uma feature/fix/chore destinada a `develop`.
- [x] Este é um PR de release com origem `develop` e destino `master`.
- [x] Este PR não pula o fluxo obrigatório entre `develop` e `master`.
## Objetivo
Promover para `master` a implementação do lock distribuído do scraper,
garantindo no máximo uma execução ativa do pipeline entre diferentes
origens de disparo.
## Resumo das Alterações
- Implementa lock distribuído no Valkey compartilhado por cron, execução
manual administrativa e cache miss de `/scrape`.
- Utiliza aquisição atômica com `SET NX PX`, TTL e renovação periódica.
- Protege renovação e liberação por ownership/token.
- Implementa comportamento fail-closed quando o Valkey não confirma a
aquisição.
- Cancela a execução de forma segura em caso de perda do lock.
- Adiciona estado operacional com `runId`, origem, início e expiração
sem expor o token proprietário.
- Adiciona contratos HTTP para execução concorrente e indisponibilidade
do run lock.
- Alinha os defaults de `SCRAPER_RUN_LOCK_TTL` e
`SCRAPER_RUN_LOCK_RENEW_INTERVAL` à semântica fail-fast definida
anteriormente.
- Adiciona cobertura de testes para concorrência, ownership,
configuração, renovação, liberação e cenários de falha.
- Atualiza documentação e configuração do Docker Compose.
## Arquivos e Módulos Afetados
- Scraper Go
- Run lock / Valkey
- Scheduler e pipeline do scraper
- Backend administrativo
- Configuração do scraper
- Docker Compose
- Testes Go e backend
- Documentação operacional
## Validação
- [x] Implementação revisada contra o escopo da PAV-119.
- [x] Ajustes solicitados no code review aplicados.
- [x] Semântica fail-fast das configurações do run lock validada.
- [x] Nenhuma alteração de frontend incluída no escopo.
- [ ] CI final do PR de release validado.
## Observações
Este PR promove alterações já integradas e revisadas em `develop`.
Não realizar squash ou alterações adicionais diretamente em `master`
fora do fluxo de release.

@hltavhltav left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

PR fora do padrão de contribuição do projeto.

Antes da revisão técnica, por favor ajuste a descrição conforme o template/documentação do repositório, incluindo card relacionado, objetivo, resumo das alterações, arquivos/módulos afetados, validações executadas e observações relevantes.

Com 24 arquivos alterados e mais de 2 mil linhas adicionadas, precisamos desse contexto para realizar uma revisão segura e rastreável. Após a adequação da PR, seguimos com a revisão do código.

@hltavhltav left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

A implementação está bem encaminhada e cobre boa parte do fluxo da PAV-36, mas como esse PR altera um fluxo sensível de identidade/autenticação, ainda precisamos fechar alguns pontos antes da aprovação.

O principal problema está na relação entre a criação da solicitação de troca e o envio do e-mail de confirmação. Hoje a solicitação é persistida e considerada concluída mesmo quando o módulo centralizado de e-mail não consegue enfileirar a mensagem, porque esse módulo foi originalmente desenhado para tratar falha de envio como não bloqueante. Nesse fluxo específico, porém, o e-mail é parte obrigatória da operação: sem ele o usuário não consegue concluir a troca.

Revise esse comportamento para que a API não sinalize sucesso quando a confirmação não puder ser efetivamente disponibilizada ao usuário. Essa revisão também deve considerar o estado da solicitação já persistida e de eventuais solicitações anteriores invalidadas.

Além disso, gostaria que fossem revisados os cenários de concorrência do fluxo. Em especial, precisamos garantir consistência quando houver solicitações simultâneas para o mesmo novo e-mail, múltiplas solicitações para o mesmo usuário e concorrência entre confirmação de token e criação de uma nova solicitação. O banco e a camada de serviço precisam preservar as invariantes do fluxo também nesses casos.

A cobertura atual contempla bem o happy path, token inválido/expirado e e-mail já utilizado, mas precisa incluir os cenários de falha de infraestrutura e concorrência relevantes para essa feature. Como esse fluxo altera users, credentials e a nova tabela de solicitações dentro do processo de confirmação, gostaria também de cobertura explícita garantindo atomicidade: ou a troca é concluída integralmente, ou o estado anterior permanece consistente.

Por fim, valide o comportamento de sessão após a confirmação da troca de e-mail. Como a identidade persistida é alterada em users e credentials, precisamos garantir que sessões/autenticações existentes continuem com o comportamento definido pelo produto e que não exista inconsistência entre o e-mail exibido, o e-mail usado para login e os dados da sessão após a confirmação.

Com esses pontos tratados e cobertos por testes, o PR fica em condição de aprovação.

@Jovinull

Copy link
Copy Markdown
ContributorAuthor

Atualiza??o aplicada em resposta ao review t?cnico:

  • O envio do e-mail de confirma??o agora pode ser marcado como obrigat?rio.
  • No fluxo de troca de e-mail, falhas ao enfileirar a confirma??o s?o propagadas para a API.
  • A cria??o do pedido e o envio obrigat?rio s?o executados dentro da transa??o; se o envio falhar, a solicita??o n?o ? conclu?da.
  • Adicionados testes para falha de infraestrutura no enqueue e para o comportamento de envio obrigat?rio.

Valida??o:

  • Suite completa do backend: 61 arquivos e 584 testes aprovados.
  • Lint do frontend: conclu?do sem erros (apenas warning preexistente de depend?ncia de hook).
  • Build do frontend: conclu?do com sucesso.

Commit: 56d36ae

Sign up for freeto 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

@Jovinull@hltav