
Sistema de fluxos e aprovações
| Área | Processos e automação |
|---|---|
| O que faz | Antes, o pedido rodava por e-mail sem controle. Agora cada etapa tem dono, prazo e escalonamento automático. |
| Funções | Alçada por valor · Atraso sobe ao gestor · Integração com o ERP |
| Habilidades | Levantamento de processo · Desenho de fluxos · Regras de aprovação · Integração com ERP |
O que o sistema cobre.
Sistema que executa os processos internos de compras, RH e financeiro: pedido de compra, reembolso, cadastro de fornecedor, admissão. O gestor desenha as etapas no editor visual: entrada, validação, aprovação por alçada, integração com ERP ou folha, aviso aos envolvidos e encerramento. O sistema roda cada etapa, guarda quem decidiu o quê e mostra onde cada processo está.
Para quem
Empresas com aprovações de compras, reembolso e RH que hoje rodam por e-mail, planilha ou WhatsApp, sem dono nem prazo.
O que mudou na empresa
Aprovação saiu do e-mail e da planilha: cada pedido tem responsável, prazo e escalonamento no atraso. Se o ERP falha, o processo espera e retoma da mesma etapa. Quem decidiu o quê fica registrado.
Módulos e funções.
8 partes do sistema, cada uma com o que faz.
Editor visual de fluxo
Monta as etapas do processo sem programar. Cada publicação vira uma versão guardada.
Entrada e validação
Abre o pedido com os campos do fluxo e confere obrigatórios, formato e limites.
Aprovação por alçada
Roteia pelo valor e pelos dados do pedido. Gera tarefa ao aprovador com prazo e escalonamento.
Caixa do aprovador
Pendências do aprovador com prazo, delegação e quem assume no atraso. Também recebe erros de integração.
Integração com sistemas
Envia o pedido ao ERP, CRM, folha ou banco. Se falhar, espera e tenta de novo.
Notificações
Avisa por e-mail ou mensagem quem precisa saber. Falha no aviso não trava o processo.
Painel de operação
Mostra em que etapa cada processo está, onde travou e permite retomar do ponto exato.
Trilha de auditoria
Registra quem fez o quê, quando, com qual entrada, saída e versão do fluxo.
Três telas.
O design é meu. Cada legenda diz o que a tela faz.



Como funciona por dentro.
Um motor que executa processos corporativos como código: o usuário desenha o fluxo, o sistema roda cada passo com estado durável, retry e trilha de auditoria.
- Desenho do fluxoO usuário monta o grafo no editor visual. Salvar publica uma versão imutável do workflow, com hash do grafo e das regras.
- EntradaFormulário renderizado a partir do schema do nó de entrada. Cria a instância, congela a versão do workflow e gera o número do processo.
- ValidaçãoA regra roda em sandbox sobre o payload mais um contexto pré-carregado: os lookups de cadastro que o nó declara são resolvidos pelo runtime antes da avaliação. Campos obrigatórios, formato, limites. Falha volta ao solicitante com o erro por campo.
- AprovaçãoRoteia por alçada e por dado do processo. Gera tarefa na caixa do aprovador, com SLA, escalonamento por tempo e registro de quem decidiu o quê.
- IntegraçãoChamada ao sistema externo, ERP, CRM, folha, banco, pela fila de integração, com chave de idempotência, timeout curto e retry que devolve a instância ao mesmo nó.
- NotificaçãoE-mail, webhook ou mensagem para os interessados. Fila própria, best-effort com retry; falha aqui não trava o processo, vira alerta.
- FinalizaçãoEstado terminal, fechamento da trilha de auditoria e emissão do evento de conclusão para quem estiver escutando.
- AuditoriaToda transição fica em log append-only: quem, quando, entrada, saída, versão do workflow e da regra. É a fonte para reconstruir qualquer processo.
O problema e a saída.
O problema
Todo processo corporativo já existe antes do software, mora numa planilha, num grupo de WhatsApp e na cabeça de três pessoas. A saída usual é um sistema por processo: seis backlogs e seis lugares onde o retry foi implementado errado.
A saída
Campos, alçadas e qual API chamar viram dado; estado, fila, retry e auditoria viram motor. Outbox: estado e evento no mesmo commit ou em nenhum; filas por tipo de nó: ERP lento não segura aprovação; sem chave aceita, o worker confere o efeito antes do retry.
Arquitetura.
Como as partes se encaixam.
No centro há uma máquina de estados persistida. Um workflow é um grafo de nós tipados: entrada, validação, aprovação, integração, notificação, finalização. Cada nó declara o que consome, o que produz e como falha. Uma instância desse grafo é um processo em andamento, e ela vive em duas tabelas: `instance`, com o estado corrente, e `step_run`, com uma linha por tentativa de execução de nó. O estado nunca mora na memória do worker. Se o processo morre no meio da integração, outro worker pega a instância exatamente no passo em que ela parou, porque o passo anterior já foi commitado.
O avanço entre nós passa por fila. O executor não chama o próximo nó direto: ele grava o resultado do nó atual e publica o evento de transição na mesma transação, usando outbox, a linha do evento vai para uma tabela junto com o commit do estado, e um relay a entrega ao broker depois. Isso elimina a janela clássica onde o banco commita e a mensagem se perde, ou a mensagem sai e o banco faz rollback. Filas separadas por tipo de nó: integração e notificação têm perfis de latência e falha completamente diferentes, e uma API de ERP lenta não pode segurar a fila de aprovação.
Cada execução de nó carrega uma chave de idempotência derivada de `(instance_id, node_id, attempt_group)`. O worker grava essa chave antes de chamar o sistema externo e a envia como header quando a API do outro lado suporta. Onde o parceiro não aceita chave de idempotência, a dedupe é por conciliação: antes do retry, o worker consulta o sistema externo pela referência do processo e, se o efeito já está lá, fecha o passo em vez de chamar de novo. O que diferencia o retry aqui é para onde o erro devolve a instância. Timeout e 5xx voltam para a fila no mesmo nó do grafo. 4xx de validação param a instância e abrem pendência humana, que não é um alerta, é um passo do fluxo, com dono, caixa de tarefas e SLA. O que estoura o teto vai para a dead-letter com payload e motivo, e o reprocesso recoloca a instância naquele nó: o processo não reabre, o número não muda, a trilha continua a mesma.
Diário de construção.
Por onde comecei, onde travou e o que mudou no caminho.
Comecei pelo runtime, não pelo editor. A primeira versão não tinha tela nenhuma: workflow era um JSON versionado em disco e a instância avançava por chamada de API. Isso forçou o modelo de dados a ficar honesto antes de existir uma interface bonita escondendo problema. Só quando o motor executava um fluxo de seis nós com falha injetada em cada um deles, e o reprocesso batia na chave de idempotência em vez de abrir um segundo pedido do outro lado, é que o editor visual entrou.
A parte difícil não foi executar o caminho feliz, foi o que acontece quando o grafo muda. Um processo de compra pode ficar dez dias esperando aprovação, e nesse intervalo alguém edita o fluxo. Resolvi congelando a versão: cada instância guarda a versão do workflow com que nasceu e termina nela. Publicar uma versão nova não move instância em voo. Migração entre versões existe, mas é operação explícita, com mapeamento de nó para nó e registro de quem migrou.
A segunda dor foi o motor de regras. A tentação era permitir código arbitrário no nó de validação. Recusei: regra roda como expressão declarativa em sandbox, com timeout e sem I/O na mão da regra, o que ela precisa do cadastro é declarado no próprio nó e o runtime resolve antes de avaliar. Perde poder, ganha previsibilidade: regra de negócio escrita por analista não derruba worker de produção nem vira vetor de execução remota.
Tecnologias e o porquê.
| Camada | Escolha | Por quê |
|---|---|---|
| Runtime do motor | Serviço de workers stateless + máquina de estados no banco | Escala horizontal simples. O estado é do banco, não do processo; matar um worker no meio não perde passo, e a repetição é barrada pela chave de idempotência do passo. |
| Persistência | PostgreSQL com particionamento por data em step_run e RLS por tenant | Transação forte para o par estado+outbox. Partição mantém a tabela de execuções gerenciável. O isolamento multi-empresa é FORCE ROW LEVEL SECURITY em instance e step_run, worker conectando com role sem BYPASSRLS e tenant setado por sessão no início da transação, quem checa é o banco, não o código de aplicação. |
| Mensageria | Filas por tipo de nó, com outbox transacional e dead-letter que aponta para o nó do grafo | Integração lenta não segura aprovação. E a mensagem morta aqui não é um evento avulso: é a instância parada no nó X da versão Y, com o payload congelado. Reprocessar recoloca ela naquele nó, sem reabrir o processo nem renumerar. |
| Frontend | Editor de grafo em canvas + caixa de tarefas do aprovador | Duas interfaces com públicos opostos: quem desenha o processo uma vez e quem despacha vinte tarefas por dia. A segunda é otimizada para teclado. |
| Integrações | Conectores com contrato tipado por nó, timeout por chamada e breaker que devolve a instância ao nó | Com o breaker aberto a instância não queima tentativas até estourar o teto: volta para 'aguardando integração' e fica ali, dias se preciso, na versão do fluxo em que nasceu. Parceiro fora do ar vira processo visivelmente parado no painel, não erro engolido. |
| Observabilidade | Trace por instância, métrica por nó e fila de exceções operacional | A pergunta real do operador é 'onde meu processo travou'. Trace correlacionado por instance_id responde isso em um clique. |
Decisões de projeto.
Grafo congelado na versão de nascimento
Publicar cria versão nova; a instância morre na versão em que nasceu. Custa N versões vivas e migração explícita, mapeamento nó a nó, com autor. Editar no lugar faria da auditoria ficção.
Regra declarativa, não script livre
Expressão em sandbox, sem I/O: o nó declara os lookups e o runtime os resolve antes de avaliar, então a regra é analisável antes de publicar. Perdi lógica complexa: vira nó de integração.
Retry classificado por tipo de falha
Timeout e 5xx voltam ao mesmo nó; 4xx para a instância e abre pendência humana com dono e SLA, não alerta; teto vai à dead-letter e reprocessa ali, sem renumerar. Custa três caminhos.
Escopo.
O que o sistema cobre
- Editor visual de fluxo: nós de entrada, validação, aprovação, integração, notificação e finalização, ligados em grafo versionado.
- Runtime que executa cada instância com estado durável, retry classificado e chave de idempotência por passo.
- Caixa de tarefas do aprovador com alçada, SLA, escalonamento por tempo e delegação, e a mesma caixa recebe a pendência aberta por erro de validação na integração.
- Conectores para sistemas externos com timeout, circuit breaker e reprocessamento a partir da dead-letter direto no nó em que a instância parou.
- Trilha de auditoria append-only: quem, quando, qual entrada, qual saída, qual versão do fluxo e da regra.
- Painel de operação para ver onde cada processo travou e retomar do passo exato, sem reabrir do zero.
O que não está publicado
- Nome da empresa e números de operação não são divulgados aqui.
- O código não é público. O que dá para ver: o processo, as telas e as decisões.
Da mesma faixa.
Processos e automação
Quer ver este sistema de perto?
Mostro o processo que mudou, os módulos, as telas e como foi construído.

