Quando uma mudança na configuração ou nos dados de negócio pode afetar outros usuários, uma aplicação pode precisar que uma pessoa a proponha e outra a revise antes que entre em vigor. Projetar esse processo como um fluxo de aprovação de mudanças em SaaS PHP exige mais do que adicionar um botão de «aprovar»: é preciso separar a proposta do dado atual, proteger cada transição e definir o que acontece se o contexto mudar enquanto a solicitação aguarda.
O objetivo é que o sistema possa responder, de forma verificável, o que foi solicitado, quem revisou, com quais permissões e se chegou a ser aplicado. A solução deve ser proporcional ao risco: um fluxo desnecessário acrescenta atrito, enquanto um fluxo insuficiente pode permitir mudanças incorretas ou difíceis de rastrear.
Decidir quais mudanças exigem aprovação

Comece classificando as mudanças por impacto, alcance e possibilidade de correção. Nem todo dado editável precisa de revisão. Um usuário que altera uma preferência pessoal de baixo impacto pode salvar a mudança diretamente. Em contrapartida, pode ser razoável exigir aprovação para alterar uma regra de faturamento, uma configuração compartilhada por uma organização ou um dado mestre que afete vários processos.
Defina critérios explícitos de produto. Por exemplo, pergunte se a mudança afeta mais usuários além de quem a propõe, se pode alterar valores ou permissões, se uma segunda pessoa é exigida por política interna e quanto custaria corrigi-la. Documente também as exceções e quem pode alterá-las. Evite transformar a aprovação em um mecanismo geral para operações sem relação com o caso: o escopo aqui são mudanças de configuração ou de dados de negócio.
A decisão precisa ser aplicada no servidor, não apenas na interface. Ocultar um botão não impede que alguém invoque diretamente um endpoint. A API deve determinar se o tipo de mudança exige aprovação e aplicar a regra tanto às operações individuais quanto às ações em massa ou integrações que possam alterar o mesmo dado.
Separar a solicitação do dado vigente
Não sobrescreva o dado vigente ao criar uma proposta. Armazene uma solicitação independente com, no mínimo, a organização, o recurso afetado, os valores propostos, o estado, quem a criou e quando. Dependendo do produto, também pode ser necessário armazenar um motivo, a origem da solicitação, um prazo ou uma versão do dado original.
Para representar os valores, você pode armazenar campos tipados ou uma estrutura serializada validada pelo servidor. Em ambos os casos, evite aceitar um payload arbitrário como se fosse uma atualização direta. Valide o esquema, os campos permitidos, os formatos e as regras de negócio ao receber a proposta. Valide novamente o que for pertinente ao aplicá-la, pois as condições podem ter mudado enquanto ela aguardava.
Esse design permite comparar o valor vigente com o proposto sem alterar a experiência de outros usuários. Também permite que a tela de revisão mostre uma diferença compreensível. Não apresente como vigente um valor que está apenas pendente; deixe claro qual é o dado aplicado e qual é a proposta.
Modelar estados e transições explícitas
Defina um conjunto pequeno de estados com significados precisos. Uma sequência comum pode incluir proposed (proposta), in_review (em revisão), approved (aprovada), rejected (rejeitada), expired (expirada) e applied (aplicada). Nem todos os produtos precisam do estado de revisão: se uma decisão imediata for suficiente, ele pode ser omitido. O importante é que cada estado descreva uma situação operacional e não seja um rótulo decorativo.
Especifique as transições válidas. Por exemplo, uma proposta pode passar para revisão ou ser rejeitada; uma solicitação em revisão pode ser aprovada ou rejeitada; uma aprovação pode ser aplicada se ainda estiver vigente. Uma solicitação expirada não deve ser aprovada pelo mesmo fluxo de uma solicitação ativa. Ações não permitidas devem falhar com uma resposta consistente, mesmo que a interface não ofereça essa opção.
«Aprovada» e «aplicada» não são equivalentes. A aprovação registra uma decisão; a aplicação modifica o dado vigente. Manter as duas etapas permite detectar falhas de aplicação e mostrar solicitações aprovadas que ainda precisam de atenção. Se o processo puder ser concluído em uma única transação curta, a decisão e a gravação poderão ser coordenadas, mas o modelo ainda deve distinguir o que aconteceu.
Verificar as permissões em cada transição
Autorize cada ação no servidor de acordo com a organização, o papel, o recurso e o estado atual. Não presuma que poder criar uma solicitação concede permissão para aprová-la ou aplicá-la. Também não confie no identificador de organização enviado pelo cliente: resolva o escopo a partir de uma sessão ou credencial validada e verifique se a solicitação e o recurso pertencem a esse mesmo escopo.
Se a autoaprovação for proibida, verifique se a identidade de quem aprova é diferente da de quem propôs. Essa regra deve ser executada na transição, não apenas na visualização. Defina também o que acontece com solicitações de administradores, usuários de serviço e processos automatizados; as exceções exigem uma política deliberada, não uma omissão acidental.
Uma aprovação deve estar vinculada a uma proposta específica. Se o conteúdo mudar, a aprovação anterior deixa de ser válida: crie uma nova versão da solicitação ou retorne a um estado que exija revisão. Alterar silenciosamente os valores depois de aprovados rompe a correspondência entre o que foi revisado e o que foi aplicado.
Gerenciar concorrência, expiração e aplicação
Enquanto uma solicitação aguarda, outro agente pode modificar o dado original. Para detectar essa situação, registre a versão do recurso ou os valores relevantes quando a proposta for criada. Ao aplicá-la, compare a versão esperada com a vigente. Se não coincidirem, não sobrescreva a mudança mais recente sem um critério: bloqueie a aplicação, marque um conflito ou solicite uma nova revisão, de acordo com as regras do produto.
Em um banco de dados relacional, uma transação pode proteger a leitura da solicitação, a verificação do estado e a atualização do recurso. O padrão específico depende do mecanismo e do nível de concorrência; um bloqueio pessimista ou uma atualização condicional por versão podem ser adequados. Em qualquer caso, a transição deve ser atômica: duas solicitações simultâneas não devem aplicar a mesma mudança duas vezes.
Faça com que a aplicação seja idempotente ou rejeite novas tentativas de forma segura. Se os dados forem atualizados no banco de dados e, além disso, uma notificação for enviada ou um evento for publicado, considere registrar o evento pendente na mesma transação e processá-lo depois. Isso reduz o risco de exibir uma notificação de sucesso para uma gravação que não foi confirmada.
Defina também uma política de expiração: por quanto tempo uma proposta pode permanecer ativa, o que a expira e se ela pode ser renovada. A expiração deve ser verificada no servidor ao aprovar e aplicar; não basta mudar o estado por meio de uma tarefa agendada. Se uma demora fizer com que os valores ou as condições deixem de ser confiáveis, exija uma nova proposta.
Auditar e operar o fluxo
Mantenha um registro de quem propôs, aprovou, rejeitou e aplicou cada mudança, com datas, identificadores da organização e do recurso, resultado e contexto necessário para uma investigação. Armazene uma referência à versão proposta e à decisão. O registro de auditoria não deve poder ser alterado pelas funções normais de edição de solicitações. Limite os dados registrados ao necessário e aplique as políticas de acesso e retenção do produto.
A interface operacional deve ajudar a encontrar solicitações pendentes, expiradas, bloqueadas por conflitos ou aprovadas, mas não aplicadas. Explique o motivo do bloqueio e ofereça um caminho seguro para resolvê-lo; não transforme um erro de aplicação em uma aprovação automática. As notificações podem avisar sobre novas tarefas e decisões, mas são apenas um recurso auxiliar: o estado persistido e consultável é a fonte da verdade.
Testar invariantes, permissões e falhas

Os testes devem verificar as regras que nunca podem ser violadas. Uma solicitação não aprovada não modifica o dado vigente; uma pessoa sem acesso à organização não pode lê-la nem realizar transições nela; a autoaprovação falha quando é proibida; e uma solicitação aprovada não pode ser aplicada com conteúdo diferente do que foi revisado. Inclua testes para estados terminais, solicitações expiradas e transições inválidas.
Teste também condições de corrida entre duas aprovações ou entre uma aprovação e uma edição do dado original. Simule falhas durante a aplicação e verifique se a solicitação não fica marcada como aplicada quando a gravação não foi confirmada. Se houver uma tarefa que expira solicitações, verifique se a execução repetida é segura. Esses testes transformam as regras de negócio em garantias verificáveis e ajudam a manter o fluxo quando as permissões ou o modelo de dados mudarem.
Como critério de design, cada etapa deve ter um responsável, uma condição verificável e um resultado observável. Se a equipe não puder explicar quem tem permissão para cada transição, o que acontece diante de uma mudança concorrente ou como reconstruir uma decisão, o fluxo ainda precisa ser definido antes de chegar à produção.



