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
Distintivos da pilha tecnológica completa
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.
Construído por Rudrendu Paul & Sourav Nandy
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
- Recursos
- Executar a pilha completa localmente
- Interface de Linha de Comando
- Referência da API
- Comparação
- Arquitetura
- Servidor MCP
- Segurança
- O que ainda não foi implementado
- FAQ
- Contribuindo
- Licença
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
| Capacidade | O que está realmente implementado |
|---|---|
| Redação de escalonamento por IA | Cinco etapas ordenadas (polite_reminder → firm_notice → final_warning → legal_demand → legal_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 jurisdicional | Claude 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.Thread → queue.Queue → asyncio.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 cliente | POST /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ências | Upload 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ça | Seguranç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ço | URL |
|---|---|
| Painel | http://localhost:3000 |
| API + documentação OpenAPI | http://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.
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.
| Capacidade | Spreadsheets | FreshBooks | HoneyBook | HubSpot | freelancer-payment-protection |
|---|---|---|---|---|---|
| Lembretes de pagamento em atraso | ✗ | Automáticos, até 3 por fatura, temporização configurável, baseados em modelo | Automáticos, 4 temporizações fixas (7 dias antes, dia do vencimento, 2 dias depois, recorrente), baseados em modelo | Fluxo 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 fator | Pontuaçã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 UI | ✗ | ✗ | ✗ | ✗ | Streaming SSE real (verificado no código-fonte, não apenas uma animação da UI) |
| Faturamento nativo | ✗ | Sim (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/A | Nativo | Nativo | Nativo | Nã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:
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
| Controle | Implementação |
|---|---|
| Autenticação | JWT do Supabase validado em toda rota protegida, sem bypass local |
| Autorização | Row Level Security em todas as tabelas, com isolamento de workspace aplicado no banco de dados, não na camada da aplicação |
| Segredos | Pydantic SecretStr; o app falha ao iniciar se uma variável obrigatória estiver ausente |
| Validação de entrada | Pydantic v2 em todos os endpoints |
| Rate limiting | 100 req/min padrão global; 10/min nas rotas de rascunho com IA; 30/min no score de risco |
| Injeção de SQL | Somente SQLAlchemy ORM, sem SQL bruto nos roteadores/serviços revisados |
| Acesso a evidências | Arquivos enviados validados por tipo MIME e tamanho (limite de 25MB) antes do armazenamento |
| Auditoria de dependências | pip-audit (backend) + pnpm audit (frontend), ambos executados no CI |
| Varredura de segredos | TruffleHog em todo push/PR |
| SAST | CodeQL (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.
celeryeredisestão fixados emrequirements.txt, mas não existe código deapps/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()deescalation_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.pydiz isso claramente: builds de desenvolvimento salvam a carta rascunhada como um arquivo.txt; o caminho de produçãopython-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