Introdução
O problema
A maior parte dos sistemas entregues segue sempre a mesma forma:
- Expõe um endpoint que recebe dados via body, header ou query — ou consome um evento de um broker de mensageria.
- Valida o payload recebido antes de qualquer processamento.
- Consulta o banco para avaliar se o recurso existe, e decide o que fazer a partir disso.
- Mapeia os dados para um modelo — a regra de negócio em si.
- Persiste o dado.
- 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
- Primeiro projeto — suba uma aplicação mínima em minutos, das duas formas possíveis.
- Conceitos fundamentais — o modelo de execução do pipeline e a anatomia do documento YAML.
- Referência de configuração YAML — todo campo, com descrição.