freelancer-payment-protection

Servidor MCP que encapsula a CLI fpp para verificações de risco de pagamento de clientes freelancers.

Documentação

freelancer-payment-protection

npm version PyPI version last commit coverage 70%+ enforced CodeQL enabled License: MIT

Distintivos da pilha tecnológica completa

Python 3.12 FastAPI 0.111 Next.js 14 App Router TypeScript 5.4 Turborepo monorepo Claude Sonnet 4.6 AI core Supabase PostgreSQL + RLS Celery + Redis workers Framer Motion animations Row Level Security on all tables


O Claude redige cartas de cobrança com referência jurisdicional e pontuações de risco do cliente de 0 a 100 com raciocínio completo, integradas a um painel FastAPI + Next.js auto-hospedado e a uma CLI scriptável.

CI status PyPI version npm version License: MIT CodeQL enabled

Construído por Rudrendu Paul & Sourav Nandy

fpp CLI: logging in and listing overdue invoices against a live workspace

Nota sobre a licença: este projeto é licenciado sob MIT. Os direitos autorais pertencem a Rudrendu Paul e Sourav Nandy. Veja Licença abaixo para os termos completos.

Instalar a CLI

pip install freelancer-payment-protection-cli
# or: uvx freelancer-payment-protection-cli --help
# or: npx freelancer-payment-protection-cli --help

Isso instala o fpp, um cliente de linha de comando tipado para o backend FastAPI abaixo (faturas, escalonamentos, pontuação de risco do cliente, --json em todo comando de dados). Ele fala com uma instância de API freelancer-payment-protection que você mesmo executa. Veja Executar a pilha completa localmente para configurar uma, ou aponte o FPP_API_URL para uma que já esteja em execução.

Sumário


O que é isto

FreshBooks e HoneyBook param em "fatura enviada". Nenhum deles redige o que dizer quando um cliente fica em silêncio, e nenhum pontua o risco de não pagamento de um cliente antes de você começar o trabalho. Este projeto é um aplicativo FastAPI + Next.js, apoiado por Claude, que faz duas coisas específicas bem: ele redige um e-mail de escalonamento adequado à etapa ou uma carta de cobrança com referência jurisdicional para uma fatura vencida, e pontua o risco de pagamento de um cliente de 0 a 100 com uma análise completa dos fatores, ambos com uma trilha de confiança/raciocínio gerada por IA que um humano revisa antes de qualquer coisa ser enviada.

Não é um sistema de automação do tipo "configure e esqueça". Não há agendador em segundo plano impondo tempos de espera entre etapas e nenhuma sincronização ao vivo com FreshBooks/QuickBooks/Wave hoje. Veja O que ainda não foi implementado para a lacuna honesta entre o diagrama de arquitetura e o que está conectado. O que é real: a redação por IA, a pontuação de risco, o cofre de evidências e uma CLI que automatiza os três.


Recursos

CapacidadeO que está realmente implementado
Redação de escalonamento por IACinco etapas ordenadas (polite_reminderfirm_noticefinal_warninglegal_demandlegal_action). POST /api/v1/escalations/{id}/draft pede ao Claude o assunto/corpo/tom/pontuação de confiança da próxima etapa. É uma prévia: o endpoint não envia o e-mail nem persiste a mudança de etapa (apps/api/app/services/escalation_service.py).
Cartas de cobrança com referência jurisdicionalClaude redige uma carta para uma string de jurisdição que você fornece. Quatro jurisdições (Califórnia, Nova York, Inglaterra e País de Gales, Ontário) têm um arquivo de modelo dedicado em legal-templates/; qualquer outra jurisdição ainda recebe um rascunho, formatado a partir do conhecimento geral do modelo em vez de um modelo codificado. Cada carta traz um parágrafo fixo de aviso de IA. Transmite para a UI via SSE por meio de uma ponte threading.Threadqueue.Queueasyncio.run_in_executor (apps/api/app/services/ai_service.py), verificado como real e não apenas um efeito de máquina de escrever da UI.
Pontuação de risco do clientePOST /api/v1/risk/score retorna uma pontuação de 0 a 100, um nível (baixo/médio/alto/crítico) e um array factors. O prompt pede ao Claude para pesar 7 fatores nomeados (cultura de pagamento do setor, duração dos prazos de pagamento, atraso histórico, qualidade do contrato, tamanho da fatura, geografia, proporção do saldo em aberto) e retornar seu raciocínio. Se a chamada ao Claude falhar, risk_service.py recorre a uma pontuação heurística determinística em vez de gerar erro. Limitado a 30 requisições/minuto.
Cofre de evidênciasUpload manual de arquivos PDF/PNG/JPEG/.eml/texto simples (limite de 25MB), listados e excluíveis por fatura, apoiados pelo Supabase Storage em produção. Não há captura automática por arrastar e soltar e nenhum endpoint de exportação ZIP hoje. Os uploads acontecem um arquivo por vez via POST /api/v1/evidence/{invoice_id}/upload.
CLI (fpp)Todo comando que retorna dados suporta --json. Login persistente contra o endpoint de concessão de senha do próprio Supabase, armazenado em cache em ~/.config/freelancer-payment-protection-cli/credentials.json (modo 600), atualização transparente. Publicado no PyPI e npm como freelancer-payment-protection-cli.
Controles de segurançaSegurança em nível de linha em todas as tabelas Postgres (packages/db/migrations/versions/002_rls_policies.sql), autenticação JWT do Supabase sem bypass local, limite de taxa slowapi (10/min nas rotas de redação por IA, 30/min na pontuação de risco, 100/min global), CodeQL em todo PR, varredura de dependências pip-audit + pnpm audit e varredura de segredos TruffleHog no CI.

Executar a pilha completa localmente

Verificado em um clone limpo. Pré-requisitos: Node.js 20+, pnpm 9.x, Python 3.12.x (3.13/3.14 não são suportados por este checkout: 3.14 falha em pip install para uma das dependências fixadas do backend).

[!AVISO] Requer Python 3.12.x especificamente. 3.13 e 3.14 ainda não são suportados.

git clone https://github.com/RudrenduPaul/freelancer-payment-protection.git
cd freelancer-payment-protection
pnpm install

# Backend env
cp apps/api/.env.example apps/api/.env
# apps/api/.env.example ships two values that don't parse as written. See the
# Troubleshooting question in the FAQ before you skip this:
#   ALLOWED_ORIGINS=["http://localhost:3000"]   (needs the JSON-array brackets)
#   delete the DATABASE_URL= line entirely (Settings doesn't accept it; the
#   app already defaults to sqlite:///./dev.db without it)

cp apps/web/.env.example apps/web/.env.local

pip install -r apps/api/requirements.txt
python -m alembic -c packages/db/migrations/alembic.ini upgrade head
python scripts/seed_dev.py

pnpm dev

O script de seed não precisa de serviços externos e produz 8 clientes, 16 faturas e eventos de escalonamento pré-gerados, todos consultáveis pela API ou pela CLI após o seed. Verificado de ponta a ponta em um venv limpo: alembic upgrade head roda limpo, seed_dev.py popula o SQLite, e uvicorn app.main:app inicia e serve /health e /health/ready assim que as duas correções .env acima forem aplicadas.

ServiçoURL
Painelhttp://localhost:3000
API + documentação OpenAPIhttp://localhost:8000/docs

Entrar no painel web requer um projeto Supabase real (o nível gratuito é suficiente). apps/api/app/middleware/auth.py valida um JWT emitido pelo Supabase sem bypass local. Os dados semeados são totalmente acessíveis pela API/CLI sem um. Os recursos de IA (cartas de cobrança, pontuação de risco, rascunhos de escalonamento) precisam de um ANTHROPIC_API_KEY real em apps/api/.env; sem um, a pontuação de risco recorre à pontuação heurística e as outras duas rotas de IA retornam 503.


Interface de Linha de Comando

Verificado contra a saída real de --help do pacote instalado.

fpp login                                   Log in (prompts for email/password)
fpp logout                                  Delete cached credentials
fpp whoami [--json]                         Show cached workspace/session info

fpp invoice list [--status] [--client-id] [--page] [--page-size] [--json]
fpp invoice create --client-id --invoice-number --amount --due-date [--currency] [--source-system] [--external-id] [--json]
fpp invoice show <invoice-id> [--json]
fpp invoice set-status <invoice-id> <status> [--json]

fpp escalation list [--json]                Active escalations, grouped by stage
fpp escalation status <invoice-id> [--json] Current stage + full history
fpp escalation advance <invoice-id> [--json] Preview the next stage's AI-drafted email (does not send or persist)

fpp client list [--risk-level] [--search] [--page] [--page-size] [--json]
fpp client show <client-id> [--json]
fpp client risk <client-id> [--json]        Compute/refresh the AI risk score
fpp login
fpp invoice list --status overdue --json | jq '.[] | {id, invoiceNumber, daysPastDue}'
fpp client risk <client-id> --json | jq '.level'

--status em invoice list aceita disputed, overdue, paid, pending, written_off. Referência completa de flags para qualquer comando: fpp <command> --help. Guia completo de instalação, configuração e autenticação: packages/cli/README.md.

fpp CLI: filtering overdue invoices and scoring a client

Referência da API

OpenAPI interativo em http://localhost:8000/docs. Verificado diretamente contra o código-fonte do roteador:

GET    /health                                Liveness probe
GET    /health/ready                          Readiness (DB)

GET    /api/v1/clients                        List
POST   /api/v1/clients                        Create
GET    /api/v1/clients/{client_id}            Detail
PUT    /api/v1/clients/{client_id}            Update
DELETE /api/v1/clients/{client_id}            Delete

GET    /api/v1/invoices                       List
POST   /api/v1/invoices                       Create (manual)
GET    /api/v1/invoices/{invoice_id}          Detail
PATCH  /api/v1/invoices/{invoice_id}/status   Update status

GET    /api/v1/escalations                    Active escalations
POST   /api/v1/escalations/{invoice_id}/draft    AI-draft next escalation email (preview only)
GET    /api/v1/escalations/{invoice_id}/history  Full history

POST   /api/v1/legal/demand-letter            Generate demand letter
POST   /api/v1/legal/demand-letter/stream     Generate + stream (SSE)

GET    /api/v1/evidence/{invoice_id}          Evidence items
POST   /api/v1/evidence/{invoice_id}/upload   Manual upload
DELETE /api/v1/evidence/{item_id}             Remove

POST   /api/v1/risk/score                     AI risk score, structured JSON

GET    /api/v1/analytics/overview             Dashboard totals

Comparação

Cada linha não-freelancer-payment-protection abaixo é proveniente da documentação/central de ajuda de cada fornecedor, verificada em agosto de 2026.

CapacidadeSpreadsheetsFreshBooksHoneyBookHubSpotfreelancer-payment-protection
Lembretes de pagamento em atrasoAutomáticos, até 3 por fatura, temporização configurável, baseados em modeloAutomáticos, 4 temporizações fixas (7 dias antes, dia do vencimento, 2 dias depois, recorrente), baseados em modeloFluxo de trabalho automatizado "Lembrete de Pagamento" (baseado em regras)Redigido por IA por etapa, calibrado por tom, com pontuação de confiança (apenas prévia, não enviado automaticamente)
Cartas de cobrança legais com referência jurisdicional✗ (não documentado)✗ (não documentado)✗ (não documentado)Redigidas por IA; 4 jurisdições têm um modelo dedicado (CA, NY, UK, Ontário)
Pontuação de risco de cliente/fatura✗ (não documentado)✗ (não documentado)Breeze Invoice Prioritization, um ranking por IA de faturas vencidas por risco/idade/valor do cliente, beta público do Revenue Hub a partir de junho de 2026; sem pontuação publicada de 0–100 ou raciocínio por fatorPontuação de 0–100, 7 fatores nomeados, raciocínio completo da IA retornado por cliente, fallback heurístico se a IA estiver fora
Armazenamento de evidências/documentos por fatura✗ (não documentado)✗ (não documentado)✗ (não documentado)Upload manual, apoiado pelo Supabase Storage, sem exportação ZIP ainda
Geração de IA em streaming na UIStreaming SSE real (verificado no código-fonte, não apenas uma animação da UI)
Faturamento nativoSim (produto principal)Sim (produto principal)Sim (Commerce/Payments)Não. As faturas são criadas via API/CLI, não sincronizadas de uma ferramenta contábil hoje
Automação de trabalhos em segundo plano (sincronização, escalonamento agendado)N/ANativoNativoNativoNão implementado. Veja O que ainda não foi implementado

A leitura honesta: FreshBooks e HoneyBook são mais fortes no lembrete mecânico e baseado em regras que já fazem bem. O beta Breeze de junho de 2026 da HubSpot é a coisa mais próxima de um recurso concorrente de pontuação de risco nesta lista e vale a pena observar. Ninguém aqui redige uma carta de cobrança com referência jurisdicional ou transmite geração de IA na UI; essa é a lacuna real que este projeto preenche, não "automação completa de cobrança", que nenhum destes, incluindo este projeto, entrega de ponta a ponta ainda.


Arquitetura

Diagrama do sistema (o que está realmente implementado)

graph TB
    subgraph "Frontend: Next.js 14"
        A[App Router Pages]
        B[TanStack Query Cache]
        C[Framer Motion UI]
        D[Supabase Auth Client]
    end

    subgraph "Backend: FastAPI, Python 3.12"
        E[FastAPI App Factory]
        F[JWT Middleware]
        G[slowapi Rate Limiter]
        H["Routers: 8 domains"]
        I[Services: business logic only]
    end

    subgraph "AI: Claude Sonnet 4.6"
        J[packages/legal_ai/client.py]
        K[Demand Letter: streaming SSE]
        L[Escalation Email: structured draft]
        M[Risk Scorer: JSON output]
    end

    subgraph "Data Layer"
        T[(Supabase PostgreSQL + RLS)]
        U[Supabase Storage]
        W[(SQLite Dev DB)]
    end

    A --> E
    D --> T
    B --> E
    E --> F --> G --> H --> I
    I --> J
    J --> K
    J --> L
    J --> M
    I --> T & U

Celery e Redis são dependências declaradas (requirements.txt) sem código de worker no repositório hoje: não existe diretório apps/workers/ e não há trabalho agendado que avance automaticamente a etapa de uma fatura. Veja O que ainda não foi implementado.

Por que Python para o backend, não Node

A redação de documentos legais usa python-docx/WeasyPrint nos caminhos de código que estão conectados para isso, e o SDK Python da Anthropic é a implementação de referência. O ecossistema Python também é onde ferramentas de análise de contratos (NLTK, spaCy) viveriam para um futuro recurso de análise de disputas.

Por que centralizar todas as chamadas ao Claude em um único arquivo

packages/legal_ai/client.py (chamado de apps/api/app/services/ai_service.py) é o único lugar onde o SDK da Anthropic é importado. Versão do modelo, tentativas e a ponte sync-SDK/async-FastAPI vivem lá, então atualizar o modelo é uma mudança de um único arquivo.

Por que Pydantic Settings com validação fail-fast

settings = Settings() é executado no momento da importação. Se ANTHROPIC_API_KEY estiver ausente, o aplicativo gera erro antes de servir uma requisição em vez de degradar silenciosamente. O trade-off: o modelo de configurações também é estrito em relação a campos não reconhecidos, o que é a causa raiz de um dos dois problemas .env.example no FAQ abaixo.

Todo comando que retorna dados também aceita --json para saída estruturada que um agente ou script pode analisar diretamente:

freelancer-payment-protection-cli: running fpp commands with --json to get structured, machine-parseable output

Servidor MCP

freelancer-payment-protection-cli inclui um servidor Model Context Protocol (MCP), para que um agente (Claude Desktop, Claude Code ou qualquer outro cliente MCP) possa chamar os mesmos comandos acima (invoice list, client risk, escalation status, ...) como chamadas de ferramenta em vez de executar a CLI diretamente.

Instalação:

pip install "freelancer-payment-protection-cli[mcp]"

Configuração do Claude Desktop (claude_desktop_config.json):

{
  "mcpServers": {
    "freelancer-payment-protection": {
      "command": "fpp-mcp"
    }
  }
}

O servidor expõe uma ferramenta, run, que executa o binário fpp instalado com a lista de argumentos fornecida e retorna sua saída como JSON estruturado quando possível — todo subcomando de fpp é acessível por meio dela, não apenas um subconjunto selecionado. Exemplo de chamada: run(args=["client", "risk", "<client-id>", "--json"]) retorna o mesmo score de risco de 0 a 100, a decomposição dos fatores e o raciocínio de IA que fpp client risk <client-id> --json imprime no terminal.


Segurança

ControleImplementação
AutenticaçãoJWT do Supabase validado em toda rota protegida, sem bypass local
AutorizaçãoRow Level Security em todas as tabelas, com isolamento de workspace aplicado no banco de dados, não na camada da aplicação
SegredosPydantic SecretStr; o app falha ao iniciar se uma variável obrigatória estiver ausente
Validação de entradaPydantic v2 em todos os endpoints
Rate limiting100 req/min padrão global; 10/min nas rotas de rascunho com IA; 30/min no score de risco
Injeção de SQLSomente SQLAlchemy ORM, sem SQL bruto nos roteadores/serviços revisados
Acesso a evidênciasArquivos enviados validados por tipo MIME e tamanho (limite de 25MB) antes do armazenamento
Auditoria de dependênciaspip-audit (backend) + pnpm audit (frontend), ambos executados no CI
Varredura de segredosTruffleHog em todo push/PR
SASTCodeQL (Python + TypeScript) em todo PR

O Que Ainda Não Foi Implementado

Sendo direto sobre isso porque os diagramas de arquitetura e a lista de dependências exageram o contrário:

  • Sem worker ou agendador em segundo plano. celery e redis estão fixados em requirements.txt, mas não existe código de apps/workers/ no repositório. Nada avança o estágio de escalonamento de uma fatura automaticamente ou por temporizador.
  • Sem aplicação de tempo mínimo de espera. O get_next_stage() de escalation_service.py é uma busca ordenada simples, sem verificação de data/timedelta em nenhum ponto do caminho de chamada. Qualquer chamador autenticado pode solicitar um rascunho para o próximo estágio, independentemente de há quanto tempo a fatura está vencida; o endpoint também nunca grava o novo estágio de volta na fatura.
  • Sem sincronização com FreshBooks/QuickBooks/Wave. packages/integrations/__init__.py é um arquivo vazio. As faturas são criadas via API/CLI, não sincronizadas a partir de uma ferramenta contábil.
  • Sem exportação de PDF/DOCX em produção ainda. O docstring de doc_gen_service.py diz isso claramente: builds de desenvolvimento salvam a carta rascunhada como um arquivo .txt; o caminho de produção python-docx/WeasyPrint não está conectado.
  • Sem exportação de ZIP de evidências. O roteador de evidências suporta apenas listar/enviar/excluir.

Nada disso é segredo. É o que a execução do código mostra. As partes que são reais (rascunho com IA, score de risco com raciocínio, streaming, a CLI) estão descritas acima com especificidades, não com adjetivos.


FAQ

O que é isso e qual é o diferencial real em relação ao FreshBooks ou HoneyBook? Ambos lidam com o envio de uma fatura e o lembrete ao cliente em um cronograma fixo. Nenhum deles redige uma carta de cobrança legal com referência jurisdicional ou calcula o risco de pagamento de um cliente com um rastro de raciocínio gerado por IA. Este projeto faz ambos, respaldado por uma chamada real à API do Claude que você pode ver em packages/legal_ai/ e apps/api/app/services/, não uma troca de template pré-fabricado.

Isso é open source? Posso fazer um fork ou usar o código no meu próprio projeto? Sim. O repositório é licenciado sob MIT: faça fork, modifique ou incorpore o código no seu próprio projeto, sujeito apenas aos termos padrão do MIT em LICENSE (mantenha o aviso de copyright/permissão). O pacote freelancer-payment-protection-cli no PyPI/npm é instalável e executável como está sob a mesma licença.

Quais plataformas a CLI suporta? Python 3.10–3.13 em Linux, macOS ou Windows, instalado via pip, uvx ou pipx. O pacote npm (freelancer-payment-protection-cli no npm) é um wrapper fino que executa uvx ou pipx em tempo de execução, em vez de empacotar um binário de plataforma; ele precisa de um desses dois no PATH. Executar a stack completa de backend/frontend requer Python 3.12.x especificamente; 3.13/3.14 não são suportados pelos pins de dependência atuais.

Como isso é diferente do novo recurso Breeze Invoice Prioritization da HubSpot? O Breeze (Revenue Hub, beta público em junho de 2026) classifica as faturas vencidas de um usuário do HubSpot por risco, idade e valor do cliente, mais próximo de uma ordem de classificação do que de um score. fpp client risk retorna um score de 0 a 100 com uma decomposição de fatores nomeados e um parágrafo de raciocínio escrito por cliente, funciona de forma independente sem adotar o restante do CRM da HubSpot, e combina com a redação de cartas de cobrança com referência jurisdicional que a HubSpot não oferece. Vale revisitar quando o Breeze sair do beta.

Segui o Quick Start exatamente e o uvicorn app.main:app --reload travou na inicialização. Isso é um bug? Sim, um bug real no apps/api/.env.example distribuído. Dois de seus valores padrão não sobrevivem à validação do Settings(): ALLOWED_ORIGINS=http://localhost:3000 precisa ser um array JSON (["http://localhost:3000"]) porque o campo é tipado como list[str], e DATABASE_URL=sqlite:///./dev.db não é um campo que o modelo Settings declara, então falha com Extra inputs are not permitted. Corrija ambas as linhas no seu .env (ou apenas exclua a linha DATABASE_URL; apps/api/app/database.py já usa o mesmo caminho SQLite por padrão de forma independente) e o servidor inicia. Confirmado executando os passos documentados em um clone limpo.

O fpp escalation advance realmente envia o e-mail ou avança a fatura? Não. Ele chama /api/v1/escalations/{id}/draft, que retorna apenas uma prévia rascunhada por IA. O backend não tem nenhum endpoint hoje que persista uma mudança de estágio ou envie o e-mail. Veja O Que Ainda Não Foi Implementado.

O que acontece se eu não tiver um ANTHROPIC_API_KEY definido? O app ainda inicia depois que as duas correções de .env acima são aplicadas, mas as rotas de IA se comportam de forma diferente: client risk recorre a um score heurístico determinístico (documentado em risk_service.py), enquanto escalation advance e os endpoints de carta de cobrança retornam um 503 sem fallback.

Posso usar isso em um engajamento real com cliente hoje? Para a CLI contra seu próprio backend auto-hospedado e projeto Supabase, sim. A licença MIT também permite usar ou incorporar isso em um engajamento real com cliente ou no seu próprio produto; veja Licença para os termos exatos.


Contribuindo

As GitHub Issues estão abertas para relatos de bugs e solicitações de recursos. Pull requests são bem-vindos; abra uma issue primeiro para qualquer coisa não trivial para que a abordagem possa ser acordada antes de você investir o trabalho. Entre em contato via github.com/RudrenduPaul com perguntas.

Licença

MIT. Veja LICENSE para os termos completos.

Contato: github.com/RudrenduPaul


Construído por Rudrendu Paul e Sourav Nandy · Desenvolvido com Claude Code