feat(onboarding): cadeia de pré-requisito Welcome => Squads (#351) - #475
Conversation
SquadsOnboardingFlow::prerequisites() passa a declarar [Welcome] e StartOnboarding valida os pré-requisitos via OnboardingCompletionGate antes de qualquer escrita, lançando PrerequisiteNotMetException com o tipo bloqueado e o pré-requisito faltante como motivo.
sirelves
left a comment
There was a problem hiding this comment.
Implementação está correta e no tamanho certo do problema: os pré-requisitos são
validados antes da transação (nenhum onboarding órfão), a exception carrega o
type e o prerequisite como motivo, e o throw_unless com named args segue o
mesmo padrão que já existe no createNextStep do Squads. Nada de camada nova pra
resolver isso, que era o risco aqui.
Deixei um comentário num teste, é uma linha e não trava o merge.
Sobre os outros testes que usam ->completed()->create() sem dizer o tipo: não me
preocupa. Se o default do factory mudar, eles falham em vez de passar errado, que
é o comportamento que a gente quer. Fica como preferência: um
['type' => OnboardingType::Welcome] explícito faria o cenário se ler no próprio
teste, sem precisar abrir o factory.
Aproveitando: cheguei a levantar se a validação no handle poderia bloquear um
Squads que já existe, já que o firstOrCreate fazia o método ser idempotente. Fui
olhar e o OnboardingStatus::Completed é terminal (allowedTransitions() retorna
[]), então um Welcome concluído nunca volta a ficar incompleto e o cenário não é
alcançável. Deixo registrado só pra não ficar a dúvida.
Contexto
O onboarding
Squads(APTO) não pode ser iniciado por quem ainda não concluiu o onboardingWelcome— essa é a cadeia de pré-requisito inter-tipo prevista no PRD (#341). Até então,SquadsOnboardingFlow::prerequisites()retornava[](com umTO-DO: #351) e oStartOnboardingnão validava nada, permitindo iniciar o Squads sem o Welcome concluído.Este PR implementa a cadeia: o flow do Squads declara
[Welcome]como pré-requisito e oStartOnboardingvalida cada pré-requisito através do gate públicoOnboardingCompletionGate::isCompleted()(#349) antes de qualquer escrita. Quando o pré-requisito não estácompleted, o início é bloqueado com umaPrerequisiteNotMetExceptionque carrega o tipo bloqueado e o pré-requisito faltante como motivo — nenhum onboarding órfão é persistido.Alterações
src/Flows/SquadsOnboardingFlow.php—prerequisites()passa a retornar[OnboardingType::Welcome].src/Actions/StartOnboarding.php— recebe oOnboardingCompletionGatepor injeção e valida os pré-requisitos do flow antes da transação; classe agora éfinal readonly.src/Exceptions/PrerequisiteNotMetException.php— nova exception comtypeeprerequisitepúblicos (o motivo do bloqueio), no mesmo estilo daGateBlockedException.database/factories/OnboardingFactory.php— novo statecompleted()para os testes.tests/Feature/OnboardingPrerequisiteChainTest.php— novo teste cobrindo os cenários BDD da issue: Squads sem Welcome é bloqueado com o motivo (inclusive com Welcome apenasin_progress), Welcome concluído destrava o Squads, e Welcome segue sem pré-requisitos.tests/Feature/SquadsOnboardingFlowTest.php— atualizado:prerequisites()agora esperado como[Welcome]e os testes que iniciam Squads concluem o Welcome antes.Critérios de aceite
prerequisites()do Squads =[Welcome]Plano de Testes
make check(Rector, Pint e PHPStan passando)make test— módulo onboarding: 35/35 testes passandoMergeDuplicateDiscordProfilesTest(módulointegration-discord) e pré-existentes: reproduzem de forma idêntica na basefeat/squads(8ab4cce0) sem este commit. Este PR toca apenasapp-modules/onboarding, sem código compartilhado com esse testeIssues Relacionadas
Closes #351
Related to #341