Introdução

O problema

A maior parte dos sistemas entregues segue sempre a mesma forma:

  1. Expõe um endpoint que recebe dados via body, header ou query — ou consome um evento de um broker de mensageria.
  2. Valida o payload recebido antes de qualquer processamento.
  3. Consulta o banco para avaliar se o recurso existe, e decide o que fazer a partir disso.
  4. Mapeia os dados para um modelo — a regra de negócio em si.
  5. Persiste o dado.
  6. Publica um evento.

Reescrever esse mesmo esqueleto à mão em cada novo serviço é o gargalo de agilidade real. O que varia entre um serviço e outro são as regras de validação, o formato do mapeamento e os nomes das entidades — não a estrutura. Toda essa estrutura vira, de novo, controller + serviço + repositório

  • DTO + mapeamento manual, com pouquíssima variação real de um serviço para o outro.

A ideia central

Pipevine é um framework .NET onde a aplicação é declarada em YAML como uma lista ordenada de steps, e o framework monta o host — API HTTP ou consumidor de mensageria — a partir dessa definição:

apiVersion: pipevine.dev/v1
kind: Application
metadata: { name: orders, version: 1.0.0 }
spec:
  type: api
  routes:
    - id: createOrder
      method: POST
      path: /orders
      pipeline:
        - { type: validate,   rules: [{ expr: "$count(input.body.items) > 0", code: EMPTY_ORDER, message: "pedido sem itens" }] }
        - { type: db.find,    id: customer, entity: Customer, where: { id: "input.body.customerId" } }
        - { type: fail,       when: "steps.customer.result = null", status: 404, code: CUSTOMER_NOT_FOUND }
        - { type: map,        id: order, to: vars.order, expr: "{ 'id': $uuid(), 'customerId': input.body.customerId }" }
        - { type: db.persist, entity: Order, data: "vars.order" }
        - { type: publish,    event: OrderCreated, payload: "vars.order", mode: outbox }
      response: { status: 201, body: "vars.order" }

Cada linha do pipeline é um step: um passo autocontido, com um type que resolve qual implementação executa, um estado compartilhado (input, vars, o resultado de steps anteriores) e regras claras sobre quando roda. O framework compila esse documento YAML num host real — rotas mapeadas, contratos de request/response gerados, validação e mapeamento avaliados, persistência, cache, mensageria e chamadas outbound conectadas — sem que você escreva um controller, um DTO ou um repositório à mão.

O mesmo modelo de pipeline serve tanto para uma rota HTTP (spec.type: api) quanto para um consumidor de mensageria (spec.type: consumer) — os steps disponíveis dentro do pipeline são exatamente os mesmos nos dois casos.

Do que Pipevine é feito

  • JSON Schema valida a forma do payload — campos obrigatórios, tipos, formatos.
  • JSONata escreve tanto a regra de negócio (relações entre campos, condições de domínio) quanto o mapeamento de dados, avaliada sobre o estado do pipeline. É o que permite mudar uma regra sem recompilar nada, com expressividade real em vez de uma mini-linguagem própria.
  • Persistência, cache, mensageria e integrações outbound têm steps dedicados (db.*, cache.*, publish, http.call/grpc.call), configurados declarativamente no mesmo YAML.
  • Autenticação e autorização — JWT, OIDC, mTLS e Basic — são selecionáveis por YAML e reusam os mesmos esquemas tanto para proteger rotas de entrada quanto para autenticar chamadas de saída.
  • Contratos são gerados, não escritos à mão: tipos C# de request/response, o grafo de steps compilado, e a partir deles o OpenAPI (para api) e o AsyncAPI (para os eventos publicados e consumidos). Erros de configuração — uma chave de step desconhecida, uma expressão JSONata com sintaxe inválida — são diagnósticos apontando linha e coluna do YAML no build, não uma exceção na primeira requisição.
  • Extensibilidade sem fork: um step, um provider de banco, um broker, um provider de cache ou um esquema de autenticação novo pode ser adicionado por um pacote de terceiro, ativado apenas por uma chave no YAML — veja Extensibilidade.

Um exemplo completo, rodando

samples/03-inventory-orders (no repositório do Pipevine) é uma aplicação real exercitando quase tudo deste guia de uma vez: autenticação, persistência, transação e todo o controle de fluxo, numa única rota. samples/06-full-stack vai além: PostgreSQL, Redis, RabbitMQ, Kafka, uma integração HTTP outbound e JWT, todos numa única rota real, com dashboard de observabilidade incluído.

Para onde ir daqui

Índice do guia

  1. Introdução
  2. Primeiro projeto
  3. Conceitos fundamentais
  4. Validação e mapeamento
  5. Persistência
  6. Controle de fluxo
  7. Autenticação e autorização
  8. Cache
  9. Mensageria e eventos
  10. Integrações outbound
  11. Implantação
  12. Observabilidade
  13. Testando sua aplicação