immutable-ledger

star 1

Skill executável para o Ledger Financeiro Imutável do StreamShare. Use quando precisar: registrar movimentações financeiras, substituir cobranças canceladas, auditar o histórico de saldo, ou estruturar entradas no FinancialLedger. Triggers: "ledger", "entrada no ledger", "registrar pagamento", "substituir cobrança", "auditoria financeira", "saldo da wallet", "fluxo espelhado"

MateusNGF By MateusNGF schedule Updated 6/3/2026

name: immutable-ledger description: | Skill executável para o Ledger Financeiro Imutável do StreamShare. Use quando precisar: registrar movimentações financeiras, substituir cobranças canceladas, auditar o histórico de saldo, ou estruturar entradas no FinancialLedger. Triggers: "ledger", "entrada no ledger", "registrar pagamento", "substituir cobrança", "auditoria financeira", "saldo da wallet", "fluxo espelhado"

Skill: Immutable Financial Ledger

Quando invocar esta skill: Sempre que precisar escrever código que toque FinancialLedger, Wallet, CobrancaLoteHistorico, ou qualquer operação que envolva substituição de Cobrança.


📐 PROCEDIMENTO 1 — Registrar Entrada no Ledger

Contexto

Toda movimentação financeira DEVE ser registrada via LedgerService.processEntry(). Nunca escreva diretamente em FinancialLedger via Prisma.

Passos

Step 1 — Gere um correlationId único para agrupar a operação atômica:

import { randomUUID } from "crypto";
const correlationId = randomUUID();

Step 2 — Monte os payloads de entrada usando o padrão de Fluxo Espelhado:

Para pagamento de cobrança individual (4 entradas obrigatórias):

const entries = [
  // 1. Aporte externo: dinheiro entra no sistema pelo participante
  {
    walletId: participanteWalletId,
    tipoOperacao: "ENTRADA",
    tipoEvento: "PAGAMENTO_RECEBIDO",
    valor: new Prisma.Decimal(cobranca.valorFinal),
    referenciaId: cobranca.id,
    metadata: { correlationId, descricao: "Aporte PIX - Pagamento recebido" }
  },
  // 2. Liquidação interna: participante quita a dívida
  {
    walletId: participanteWalletId,
    tipoOperacao: "SAIDA",
    tipoEvento: "PAGAMENTO_RECEBIDO",
    valor: new Prisma.Decimal(cobranca.valorFinal),
    referenciaId: cobranca.id,
    metadata: { correlationId, descricao: "Liquidação de fatura" }
  },
  // 3. Recebimento bruto na conta do organizador
  {
    walletId: contaWalletId,
    tipoOperacao: "ENTRADA",
    tipoEvento: "PAGAMENTO_RECEBIDO",
    valor: new Prisma.Decimal(cobranca.valorOriginal),
    referenciaId: cobranca.id,
    metadata: { correlationId, descricao: "Repasse líquido ao organizador" }
  },
  // 4. Dedução de taxas da conta do organizador
  {
    walletId: contaWalletId,
    tipoOperacao: "SAIDA",
    tipoEvento: "TAXA_PLATAFORMA",
    valor: new Prisma.Decimal(cobranca.valorTaxaPlataforma),
    referenciaId: cobranca.id,
    metadata: { correlationId, descricao: "Taxa da plataforma StreamShare" }
  },
];

Step 3 — Execute DENTRO de prisma.$transaction:

await prisma.$transaction(async (tx) => {
  // ... lógica de negócio ...
  await LedgerService.processEntry(tx, entries);
});

📐 PROCEDIMENTO 2 — Substituir Cobrança Cancelada (Imutabilidade)

⚠️ NUNCA faça UPDATE em campos sensíveis. A única forma de corrigir uma cobrança é substituindo-a.

Passos

Step 1 — Valide que a substituição é permitida:

// Verificar: assinatura ativa, sem cobrança ativa no mesmo período
const cobrancaExistente = await tx.cobranca.findFirst({
  where: {
    assinaturaId: original.assinaturaId,
    periodoInicio: original.periodoInicio,
    status: { not: "cancelado" },
    id: { not: original.id }
  }
});
if (cobrancaExistente) throw new Error("Já existe cobrança ativa para este período");

Step 2 — Cancele o PIX antigo (se existir):

await PaymentService.cancelPixForCobranca(tx, original.id);

Step 3 — Crie a nova cobrança com substituidaPorId nulo (ela é a nova versão):

const nova = await tx.cobranca.create({
  data: {
    ...dadosAtualizados,
    status: "pendente",
    metadataJson: {
      ...dadosAtualizados.metadataJson,
      referenciaCobrancaAnteriorId: original.id,
    }
  }
});

Step 4 — Vincule a original à nova via substituidaPorId:

await tx.cobranca.update({
  where: { id: original.id },
  data: {
    substituidaPorId: nova.id,
    status: "cancelado",
    deletedAt: new Date()
  }
});

Step 5 — Registre o log de transação para auditoria:

await tx.logTransacaoGateway.create({
  data: {
    contaId,
    tipo: "SUBSTITUICAO",
    referenciaId: original.id.toString(),
    metadata: { novaCobrancaId: nova.id, motivo: "..." }
  }
});

📐 PROCEDIMENTO 3 — Consultar Saldo de Wallet

⚠️ NUNCA calcule saldo com reduce em memória sobre todos os registros.

// ✅ Correto — usa agregação SQL com snapshot como âncora
const saldo = await LedgerService.getBalance(walletId);

// O serviço internamente faz:
// 1. Busca o último LedgerSnapshot para o walletId
// 2. Soma as entradas/saídas posteriores ao snapshot
// 3. Retorna Prisma.Decimal

📐 PROCEDIMENTO 4 — Audit de Rastreabilidade de Lotes

Toda adição/remoção de cobrança em lote deve ser registrada no histórico:

// Ao adicionar ao lote:
await tx.cobrancaLoteHistorico.create({
  data: { cobrancaId, lotePagamentoId, adicionadoEm: new Date() }
});

// Ao remover do lote:
await tx.cobrancaLoteHistorico.updateMany({
  where: { cobrancaId, lotePagamentoId, removidoEm: null },
  data: { removidoEm: new Date(), motivoRemocao: "..." }
});

// NUNCA deletar registros históricos

🚫 Antipadrões a Evitar

❌ Proibido ✅ Correto
UPDATE cobranca SET valorFinal = x Padrão de substituição (Procedimento 2)
FinancialLedger.create() direto LedgerService.processEntry()
Saldo via entries.reduce() LedgerService.getBalance(walletId)
valorFinal = subtotal * 1.01 valorFinal = subtotal / (1 - GATEWAY_FEE)
Valores como number nativo new Prisma.Decimal(valor)
Deletar CobrancaLoteHistorico Marcar removidoEm

🔗 Referências

  • Regras financeiras completas: .agents/agents/financial-agent.md
  • Casos de teste BDD: .agents/docs/financial-ledger-spec.md
  • Motor de faturamento: .agents/docs/rules/BILLING_ENGINE.md
Install via CLI
npx skills add https://github.com/MateusNGF/streamshare --skill immutable-ledger
Repository Details
star Stars 1
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator