freelancer-payment-protection

Servidor MCP que envuelve la CLI de fpp para comprobaciones de riesgo de pago de clientes freelancer.

Documentación

freelancer-payment-protection

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

Insignias de la pila 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


Claude redacta cartas de demanda con referencia jurisdiccional y puntuaciones de riesgo de cliente de 0 a 100 con razonamiento completo, integradas en un panel de control autohospedado de FastAPI + Next.js y una CLI programable.

CI status PyPI version npm version License: MIT CodeQL enabled

Creado por Rudrendu Paul & Sourav Nandy

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

Nota sobre la licencia: este proyecto tiene licencia MIT. Los derechos de autor pertenecen a Rudrendu Paul y Sourav Nandy. Consulta Licencia a continuación para conocer los términos completos.

Instalar la CLI

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

Eso instala fpp, un cliente de línea de comandos tipado para el backend de FastAPI que se describe a continuación (facturas, escalamientos, puntuación de riesgo de cliente, --json en cada comando de datos). Se comunica con una instancia de API freelancer-payment-protection que tú mismo ejecutas. Consulta Ejecutar la pila completa localmente para poner una en marcha, o apunta FPP_API_URL a una que ya esté en ejecución.

Tabla de contenidos


Qué es esto

FreshBooks y HoneyBook se detienen en "factura enviada". Ninguno redacta qué decir cuando un cliente deja de responder, y ninguno puntúa el riesgo de impago de un cliente antes de que comiences el trabajo. Este proyecto es una aplicación de FastAPI + Next.js, respaldada por Claude, que hace dos cosas específicas muy bien: redacta un correo de escalamiento apropiado para la etapa o una carta de demanda con referencia jurisdiccional para una factura vencida, y puntúa el riesgo de pago de un cliente de 0 a 100 con un desglose completo de factores, ambos con un rastro de confianza/razonamiento generado por IA que un humano revisa antes de que se envíe cualquier cosa.

No es un sistema de automatización de configurar y olvidar. No hay un programador en segundo plano que imponga tiempos de espera entre etapas ni sincronización en vivo con FreshBooks/QuickBooks/Wave por ahora. Consulta Lo que aún no está implementado para ver la brecha honesta entre el diagrama de arquitectura y lo que está conectado. Lo que es real: la redacción con IA, la puntuación de riesgo, el archivador de evidencia y una CLI que automatiza los tres.


Características

CapacidadLo que realmente está implementado
Redacción de escalamientos con IACinco etapas ordenadas (polite_reminderfirm_noticefinal_warninglegal_demandlegal_action). POST /api/v1/escalations/{id}/draft le pide a Claude el asunto/cuerpo/tono/puntuación de confianza de la siguiente etapa. Es una vista previa: el endpoint no envía el correo ni persiste el cambio de etapa (apps/api/app/services/escalation_service.py).
Cartas de demanda con referencia jurisdiccionalClaude redacta una carta para una cadena de jurisdicción que tú proporcionas. Cuatro jurisdicciones (California, Nueva York, Inglaterra y Gales, Ontario) tienen una plantilla dedicada en legal-templates/; cualquier otra jurisdicción aún recibe un borrador, formateado a partir del conocimiento general del modelo en lugar de una plantilla codificada. Cada carta incluye un párrafo fijo de descargo de responsabilidad de IA. Se transmite a la interfaz de usuario mediante SSE a través de un puente threading.Threadqueue.Queueasyncio.run_in_executor (apps/api/app/services/ai_service.py), verificado como real y no solo un efecto de máquina de escribir de la interfaz.
Puntuación de riesgo de clientePOST /api/v1/risk/score devuelve una puntuación de 0 a 100, un nivel (bajo/medio/alto/crítico) y un arreglo factors. El prompt le pide a Claude que pondere 7 factores nombrados (cultura de pago de la industria, duración de los términos de pago, retraso histórico, calidad del contrato, tamaño de la factura, geografía, proporción de saldo pendiente) y que devuelva su razonamiento. Si la llamada a Claude falla, risk_service.py recurre a una puntuación heurística determinista en lugar de dar error. Limitado a 30 solicitudes/minuto.
Archivador de evidenciaCarga manual de archivos PDF/PNG/JPEG/.eml/texto plano (límite de 25 MB), listados y eliminables por factura, respaldados por Supabase Storage en producción. No hay captura automática por arrastrar y soltar ni endpoint de exportación ZIP por ahora. Las cargas se realizan un archivo a la vez mediante POST /api/v1/evidence/{invoice_id}/upload.
CLI (fpp)Cada comando que devuelve datos admite --json. Inicio de sesión persistente contra el endpoint de concesión de contraseña de Supabase, almacenado en caché en ~/.config/freelancer-payment-protection-cli/credentials.json (modo 600), renovación transparente. Publicado en PyPI y npm como freelancer-payment-protection-cli.
Controles de seguridadSeguridad a nivel de fila en cada tabla de Postgres (packages/db/migrations/versions/002_rls_policies.sql), autenticación JWT de Supabase sin omisión local, limitación de velocidad slowapi (10/min en las rutas de redacción con IA, 30/min en la puntuación de riesgo, 100/min global), CodeQL en cada PR, escaneo de dependencias pip-audit + pnpm audit y escaneo de secretos TruffleHog en CI.

Ejecutar la pila completa localmente

Verificado contra un clon nuevo. Requisitos previos: Node.js 20+, pnpm 9.x, Python 3.12.x (3.13/3.14 no son compatibles con este checkout: 3.14 falla en pip install para una de las dependencias fijadas del backend).

[!ADVERTENCIA] Requiere Python 3.12.x específicamente. 3.13 y 3.14 aún no son compatibles.

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

El script de siembra no necesita servicios externos y produce 8 clientes, 16 facturas y eventos de escalamiento pregenerados, todos consultables a través de la API o la CLI una vez sembrados. Verificado de extremo a extremo en un venv nuevo: alembic upgrade head se ejecuta limpio, seed_dev.py puebla SQLite y uvicorn app.main:app arranca y sirve /health y /health/ready una vez aplicados los dos arreglos de .env mencionados anteriormente.

ServicioURL
Panel de controlhttp://localhost:3000
API + documentación de OpenAPIhttp://localhost:8000/docs

Iniciar sesión en el panel de control web requiere un proyecto real de Supabase (el nivel gratuito está bien). apps/api/app/middleware/auth.py valida un JWT emitido por Supabase sin omisión local. Los datos sembrados son totalmente accesibles a través de la API/CLI sin uno. Las funciones de IA (cartas de demanda, puntuación de riesgo, borradores de escalamiento) necesitan una ANTHROPIC_API_KEY real en apps/api/.env; sin una, la puntuación de riesgo recurre a la puntuación heurística y las otras dos rutas de IA devuelven un 503.


Interfaz de línea de comandos

Verificado contra la salida real de --help del paquete 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 en invoice list acepta disputed, overdue, paid, pending, written_off. Referencia completa de banderas para cualquier comando: fpp <command> --help. Guía completa de instalación, configuración y autenticación: packages/cli/README.md.

fpp CLI: filtering overdue invoices and scoring a client

Referencia de la API

OpenAPI interactivo en http://localhost:8000/docs. Verificado directamente contra el código fuente del enrutador:

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

Comparación

Cada fila que no sea freelancer-payment-protection a continuación proviene de la documentación o el centro de ayuda de cada proveedor, verificada en agosto de 2026.

CapacidadHojas de cálculoFreshBooksHoneyBookHubSpotfreelancer-payment-protection
Recordatorios de pago vencidoAutomáticos, hasta 3 por factura, temporización configurable, basados en plantillasAutomáticos, 4 temporizaciones fijas (7 días antes, día de vencimiento, 2 días después, recurrentes), basados en plantillasFlujo de trabajo automatizado de "Recordatorio de pago" (basado en reglas)Redactados por IA por etapa, tono calibrado, con puntuación de confianza (solo vista previa, no envío automático)
Cartas de demanda legales con referencia jurisdiccional✗ (no documentado)✗ (no documentado)✗ (no documentado)Redactadas por IA; 4 jurisdicciones tienen una plantilla dedicada (CA, NY, Reino Unido, Ontario)
Puntuación de riesgo de cliente/factura✗ (no documentado)✗ (no documentado)Breeze Invoice Prioritization, una clasificación por IA de facturas vencidas por riesgo/antigüedad/valor del cliente, beta pública de Revenue Hub a partir de junio de 2026; sin puntuación publicada de 0 a 100 ni razonamiento por factorPuntuación de 0 a 100, 7 factores nombrados, razonamiento completo de IA devuelto por cliente, respaldo heurístico si la IA está caída
Almacenamiento de evidencia/documentos por factura✗ (no documentado)✗ (no documentado)✗ (no documentado)Carga manual, respaldado por Supabase Storage, sin exportación ZIP aún
Generación de IA en streaming en la interfazStreaming SSE real (verificado en el código fuente, no solo una animación de la interfaz)
Facturación nativaSí (producto principal)Sí (producto principal)Sí (Commerce/Payments)No. Las facturas se crean mediante API/CLI, no se sincronizan desde una herramienta contable por ahora
Automatización de trabajos en segundo plano (sincronización, escalamiento programado)N/DNativaNativaNativaNo implementado. Consulta Lo que aún no está implementado

La lectura honesta: FreshBooks y HoneyBook son más fuertes en el recordatorio mecánico basado en reglas que ya hacen bien. La beta Breeze de junio de 2026 de HubSpot es lo más cercano a una función competidora de puntuación de riesgo en esta lista y vale la pena seguirla. Nadie aquí redacta una carta de demanda con referencia jurisdiccional ni transmite generación de IA en la interfaz; ese es el vacío real que este proyecto llena, no "automatización completa de cobros", que ninguno de estos, incluido este proyecto, ofrece de extremo a extremo todavía.


Arquitectura

Diagrama del sistema (lo que realmente está 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 y Redis son dependencias declaradas (requirements.txt) sin código de trabajador en el repositorio hoy: no existe un directorio apps/workers/ y no hay un trabajo programado que avance automáticamente la etapa de una factura. Consulta Lo que aún no está implementado.

Por qué Python para el backend, no Node

La redacción de documentos legales usa python-docx/WeasyPrint en las rutas de código que están conectadas para ello, y el SDK de Python de Anthropic es la implementación de referencia. El ecosistema de Python también es donde vivirían las herramientas de análisis de contratos (NLTK, spaCy) para una futura función de análisis de disputas.

Por qué centralizar todas las llamadas a Claude en un solo archivo

packages/legal_ai/client.py (llamado desde apps/api/app/services/ai_service.py) es el único lugar donde se importa el SDK de Anthropic. La versión del modelo, los reintentos y el puente SDK síncrono/FastAPI asíncrono viven allí, por lo que actualizar el modelo es un cambio de un solo archivo.

Por qué Pydantic Settings con validación de fallo rápido

settings = Settings() se ejecuta en el momento de la importación. Si ANTHROPIC_API_KEY está ausente, la aplicación se eleva antes de servir una solicitud en lugar de degradarse silenciosamente. La compensación: el modelo de configuración también es estricto con los campos no reconocidos, que es la causa raíz de uno de los dos problemas de .env.example en las preguntas frecuentes a continuación.

Cada comando que devuelve datos también acepta --json para salida estructurada que un agente o script puede analizar directamente:

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

Servidor MCP

freelancer-payment-protection-cli incluye un servidor de Protocolo de Contexto de Modelo (MCP), por lo que un agente (Claude Desktop, Claude Code o cualquier otro cliente MCP) puede llamar a los mismos comandos anteriores (invoice list, client risk, escalation status, ...) como llamadas a herramientas en lugar de ejecutar la CLI directamente.

Instalación:

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

Configuración de Claude Desktop (claude_desktop_config.json):

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

El servidor expone una herramienta, run, que invoca el binario fpp instalado con la lista de argumentos dada y devuelve su salida como JSON estructurado cuando es posible — cada subcomando de fpp es accesible a través de ella, no solo un subconjunto seleccionado. Ejemplo de llamada: run(args=["client", "risk", "<client-id>", "--json"]) devuelve la misma puntuación de riesgo de 0-100, el desglose de factores y el razonamiento de IA que fpp client risk <client-id> --json imprime en una terminal.


Seguridad

ControlImplementación
AutenticaciónJWT de Supabase validado en cada ruta protegida, sin bypass local
AutorizaciónSeguridad a nivel de fila en cada tabla, con aislamiento de espacio de trabajo aplicado en la base de datos, no en la capa de la aplicación
SecretosPydantic SecretStr; la aplicación falla al iniciar si falta una variable requerida
Validación de entradaPydantic v2 en cada endpoint
Límite de tasa100 req/min predeterminado global; 10/min en las rutas de redacción con IA; 30/min en la puntuación de riesgo
Inyección SQLSolo SQLAlchemy ORM, sin SQL crudo en los routers/servicios revisados
Acceso a evidenciaLos archivos subidos se validan por tipo MIME y tamaño (límite de 25MB) antes del almacenamiento
Auditoría de dependenciaspip-audit (backend) + pnpm audit (frontend), ambos ejecutados en CI
Escaneo de secretosTruffleHog en cada push/PR
SASTCodeQL (Python + TypeScript) en cada PR

Lo que aún no está implementado

Siendo directos al respecto porque los diagramas de arquitectura y la lista de dependencias lo exageran de otro modo:

  • Sin trabajador en segundo plano ni programador. celery y redis están fijados en requirements.txt, pero no existe código de apps/workers/ en el repositorio. Nada avanza la etapa de escalamiento de una factura automáticamente o mediante un temporizador.
  • Sin aplicación del tiempo mínimo de espera. escalation_service.py's get_next_stage() es una búsqueda ordenada simple sin verificación de fecha/timedelta en ningún punto de la ruta de llamada. Cualquier llamador autenticado puede solicitar un borrador para la siguiente etapa sin importar cuánto tiempo lleva la factura vencida; el endpoint tampoco escribe nunca la nueva etapa de vuelta en la factura.
  • Sin sincronización con FreshBooks/QuickBooks/Wave. packages/integrations/__init__.py es un archivo vacío. Las facturas se crean a través de la API/CLI, no se sincronizan desde una herramienta de contabilidad.
  • Sin exportación de PDF/DOCX de producción todavía. El docstring de doc_gen_service.py lo dice claramente: las compilaciones de desarrollo guardan la carta redactada como un archivo .txt; la ruta de producción python-docx/WeasyPrint no está conectada.
  • Sin exportación de ZIP de evidencia. El router de evidencia solo admite listar/subir/eliminar.

Nada de esto es secreto. Es lo que muestra la ejecución del código. Las partes que son reales (redacción con IA, puntuación de riesgo con razonamiento, streaming, la CLI) se describen arriba con detalles concretos, no con adjetivos.


Preguntas frecuentes

¿Qué es esto y cuál es el diferenciador real frente a FreshBooks o HoneyBook? Ambos manejan el envío de una factura y el recordatorio al cliente en un cronograma fijo. Ninguno redacta una carta de demanda legal con referencia jurisdiccional ni puntúa el riesgo de pago de un cliente con un rastro de razonamiento generado por IA. Este proyecto hace ambas cosas, respaldado por una llamada real a la API de Claude que puedes ver en packages/legal_ai/ y apps/api/app/services/, no un intercambio de plantilla genérica.

¿Es de código abierto? ¿Puedo hacer un fork o usar el código en mi propio proyecto? Sí. El repositorio tiene licencia MIT: hazle fork, modifícalo o integra el código en tu propio proyecto, sujeto únicamente a los términos estándar de MIT en LICENSE (conserva el aviso de copyright/permiso). El paquete freelancer-payment-protection-cli en PyPI/npm es instalable y ejecutable tal cual bajo la misma licencia.

¿Qué plataformas admite la CLI? Python 3.10–3.13 en Linux, macOS o Windows, instalado mediante pip, uvx o pipx. El paquete npm (freelancer-payment-protection-cli en npm) es un envoltorio ligero que invoca uvx o pipx en tiempo de ejecución en lugar de incluir un binario de plataforma; necesita uno de esos dos en PATH. Ejecutar la pila completa de backend/frontend requiere Python 3.12.x específicamente; 3.13/3.14 no son compatibles con las fijaciones de dependencias actuales.

¿En qué se diferencia esto de la nueva función Breeze Invoice Prioritization de HubSpot? Breeze (Revenue Hub, beta pública a partir de junio de 2026) clasifica las facturas vencidas de un usuario de HubSpot por riesgo, antigüedad y valor del cliente, más cercano a un orden de clasificación que a una puntuación. fpp client risk devuelve una puntuación de 0–100 con un desglose de factores nombrados y un párrafo de razonamiento escrito por cliente, funciona de forma independiente sin adoptar el resto del CRM de HubSpot, y se combina con la redacción de cartas de demanda con referencia jurisdiccional que HubSpot no ofrece. Vale la pena revisarlo cuando Breeze salga de la beta.

Seguí la Guía de inicio rápido exactamente y uvicorn app.main:app --reload falló al iniciar. ¿Es un error? Sí, uno real en el apps/api/.env.example publicado. Dos de sus valores predeterminados no sobreviven la validación de Settings(): ALLOWED_ORIGINS=http://localhost:3000 debe ser un array JSON (["http://localhost:3000"]) porque el campo está tipado como list[str], y DATABASE_URL=sqlite:///./dev.db no es un campo que el modelo Settings declare en absoluto, por lo que falla con Extra inputs are not permitted. Corrige ambas líneas en tu .env (o simplemente elimina la línea de DATABASE_URL; apps/api/app/database.py ya tiene como valor predeterminado esa misma ruta de SQLite de forma independiente) y el servidor arranca. Confirmado ejecutando los pasos documentados en un clon limpio.

¿fpp escalation advance realmente envía el correo o avanza la factura? No. Llama a /api/v1/escalations/{id}/draft, que devuelve solo una vista previa redactada por IA. El backend no tiene hoy ningún endpoint que persista un cambio de etapa o envíe el correo. Consulta Lo que aún no está implementado.

¿Qué sucede si no tengo un ANTHROPIC_API_KEY configurado? La aplicación aún se inicia una vez aplicadas las dos correcciones de .env anteriores, pero las rutas de IA se comportan de manera diferente: client risk recurre a una puntuación heurística determinista (documentada en risk_service.py), mientras que escalation advance y los endpoints de carta de demanda devuelven un 503 sin alternativa.

¿Puedo usar esto para un compromiso real con un cliente hoy? Para la CLI contra tu propio backend autoalojado y proyecto de Supabase, sí. La licencia MIT también permite usar o integrar esto en un compromiso real con un cliente o en tu propio producto; consulta Licencia para los términos exactos.


Contribuciones

Los Issues de GitHub están abiertos para informes de errores y solicitudes de funciones. Las Pull Requests son bienvenidas; abre un issue primero para cualquier cosa no trivial para que el enfoque pueda acordarse antes de que hagas el trabajo. Contacta a través de github.com/RudrenduPaul con preguntas.

Licencia

MIT. Consulta LICENSE para los términos completos.

Contacto: github.com/RudrenduPaul


Creado por Rudrendu Paul y Sourav Nandy · Desarrollado con Claude Code