Metadata-Version: 2.4
Name: reversal-engine
Version: 1.1.3
Summary: Converts any human-readable content into clean, structured AI-readable JSON.
License-Expression: MIT
Project-URL: Homepage, https://github.com/Etytabs/REVERSAL
Project-URL: Repository, https://github.com/Etytabs/REVERSAL
Project-URL: Issues, https://github.com/Etytabs/REVERSAL/issues
Keywords: ai,llm,mcp,pdf,html,json,agent
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: OS Independent
Classifier: Intended Audience :: Developers
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.31.0
Requires-Dist: beautifulsoup4>=4.12.0
Requires-Dist: lxml>=4.9.0
Requires-Dist: pdfplumber>=0.10.0
Requires-Dist: python-docx>=1.1.0
Requires-Dist: openpyxl>=3.1.0
Requires-Dist: xlrd>=2.0.1
Requires-Dist: fastapi>=0.111.0
Requires-Dist: uvicorn[standard]>=0.29.0
Requires-Dist: pydantic>=2.6.0
Requires-Dist: python-multipart>=0.0.9
Requires-Dist: anthropic>=0.25.0
Requires-Dist: python-dotenv>=1.0.0
Requires-Dist: stripe>=8.0.0
Requires-Dist: structlog>=24.0.0
Requires-Dist: slowapi>=0.1.9
Requires-Dist: prometheus-client>=0.20.0
Provides-Extra: dev
Requires-Dist: pytest>=8.0.0; extra == "dev"
Requires-Dist: pytest-cov>=5.0.0; extra == "dev"
Requires-Dist: httpx>=0.27.0; extra == "dev"
Provides-Extra: ods
Requires-Dist: pandas>=2.1.0; extra == "ods"
Requires-Dist: odfpy>=1.4.1; extra == "ods"
Provides-Extra: redis
Requires-Dist: redis>=5.0.0; extra == "redis"
Requires-Dist: arq>=0.25.0; extra == "redis"
Dynamic: license-file

# Reversal Engine

## Nouveaux endpoints PR3 (mai 2026)

Reversal expose désormais des endpoints avancés pour l’orchestration, la synthèse multi-source, la planification adaptative et l’observabilité produit.

### Endpoints PR3

| Endpoint | Description |
|---|---|
| POST `/v1/reverse/stream` | Reverse streaming SSE (résultats progressifs, planification adaptative) |
| POST `/v1/reverse/smart` | Reverse intelligent avec World Model + extraction orientée intention |
| POST `/v1/analyze` | Analyse rapide du contenu + détection d'intention agent |
| GET `/v1/explain/last` | Retourne la dernière explication de décision du World Model |
| POST `/v1/heal` | Auto-correction de conversion avec relances contrôlées |
| POST `/v1/confidence/check` | Vérifie si l'automatisation est sûre ou si revue humaine est requise |
| POST `/v1/benchmark/run` | Lance la comparaison direct vs World Model |
| POST `/v1/learning/feedback` | Alias feedback pour l'apprentissage adaptatif |
| POST `/v1/optimize/plan` | Sélectionne la meilleure stratégie parmi des candidats selon des objectifs multiples |
| POST `/v1/synthesize` | Fusionne plusieurs sources en un rapport synthétique structuré |
| POST `/v1/cache/predict` | Prédiction et préremplissage du cache pour accélérer les accès |
| POST `/v1/collaborative/decision` | Décision collaborative multi-modèle (world models) |
| GET `/v1/kpi/dashboard` | Dashboard KPI produit (latence, volume, taux succès, drift, etc.) |

### Exemples d’utilisation

**Streaming SSE**
```bash
curl -N -X POST https://your-reversal-instance/v1/reverse/stream \
  -H "Authorization: Bearer rev_xxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"source": "https://lemonde.fr/article/2025/…"}'
# ↳ Reçoit des events: plan_update, partial_result, final_result
```

**Optimisation multi-objectif**
```bash
curl -X POST https://your-reversal-instance/v1/optimize/plan \
  -H "Authorization: Bearer rev_xxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"candidates":[{"strategy":"static_fetch","quality":0.5,"time_normalized":0.1,"cost_normalized":0.1,"completeness":0.5},{"strategy":"rendered_browser","quality":0.9,"time_normalized":0.4,"cost_normalized":0.5,"completeness":0.9}],"objectives":{"quality":0.8,"speed":0.1,"cost":0.05,"completeness":0.05}}'
# ↳ { "selected": { ... } }
```

**Synthèse multi-source**
```bash
curl -X POST https://your-reversal-instance/v1/synthesize \
  -H "Authorization: Bearer rev_xxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"sources": ["https://example.com/a", "https://example.com/b"], "synthesis_goal": "rapport trimestriel", "strategy": "hierarchical_merge"}'
# ↳ { "source_count": 2, "strategy": "hierarchical_merge", ... }
```

**Prédiction cache**
```bash
curl -X POST https://your-reversal-instance/v1/cache/predict \
  -H "Authorization: Bearer rev_xxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"candidates": [{"source": "https://example.com/a", "score": 0.9}, {"source": "https://example.com/b", "score": 0.8}], "max_prefetch": 2}'
# ↳ { "count": 2, "prefetched": [...] }
```

**Décision collaborative**
```bash
curl -X POST https://your-reversal-instance/v1/collaborative/decision \
  -H "Authorization: Bearer rev_xxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"content_type": "url", "render_model": "spa", "access_model": "public", "interaction_type": "dynamic_app"}'
# ↳ { "selected_strategy": ..., "models": [...] }
```

**Dashboard KPI**
```bash
curl -X GET https://your-reversal-instance/v1/kpi/dashboard \
  -H "Authorization: Bearer rev_xxxxxxxx"
# ↳ { "kpis": {...}, "retention": {...} }
```

### Intent Profiles (détaillé)

L'endpoint `POST /v1/reverse/smart` adapte l'extraction selon `agent_goal`.

Payload de base:
```bash
curl -X POST https://your-reversal-instance/v1/reverse/smart \
  -H "Authorization: Bearer rev_xxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "https://example.com",
    "agent_goal": "Explain what OpenClaw is and whether I should try it",
    "explain_mode": true,
    "max_healing_attempts": 2
  }'
```

| Intent | Quand l'utiliser | Champs clés retournés |
|---|---|---|
| `summary` | Vue d'ensemble rapide | `main_idea`, `key_points`, `conclusion` |
| `critical_analysis` | Analyse technique et critique | `technical_analysis`, `critical_points`, `maturity_level` |
| `decision_support` | Aide au choix / arbitrage | `options`, `recommendation` |
| `tutorial` | Expliquer comment faire | `prerequisites`, `steps`, `common_pitfalls` |
| `fact_extraction` | Extraire faits/données vérifiables | `facts[]` |
| `comparison` | Comparer alternatives | `options`, `tradeoffs`, `recommendation` |
| `news_briefing` | Brief d'actualités | `main_idea`, `key_points`, `context` |
| `research` | Revue approfondie | `hypothesis`, `method`, `evidence`, `limitations` |

Exemple `critical_analysis`:
```json
{
  "source": "https://openclaw.ai",
  "agent_goal": "Explain what OpenClaw is and evaluate it critically",
  "explain_mode": true
}
```
Réponse (extrait):
```json
{
  "intent_detected": "critical_analysis",
  "quality_score": 0.92,
  "data": {
    "overview": "...",
    "technical_analysis": "...",
    "critical_points": {
      "limitations": ["..."],
      "risks": ["..."],
      "caveats": ["..."]
    },
    "maturity_level": "beta",
    "verdict": "..."
  }
}
```

Exemple `decision_support`:
```json
{
  "source": "https://example.com/stack-comparison",
  "agent_goal": "Should I choose framework A or B for a production app?"
}
```
Réponse (extrait):
```json
{
  "intent_detected": "decision_support",
  "data": {
    "options": [
      {
        "name": "A",
        "pros": ["..."],
        "cons": ["..."],
        "costs": {"financial": "...", "time": "...", "complexity": "..."},
        "risks": ["..."]
      },
      {
        "name": "B",
        "pros": ["..."],
        "cons": ["..."],
        "costs": {"financial": "...", "time": "...", "complexity": "..."},
        "risks": ["..."]
      }
    ],
    "recommendation": {
      "best_option": "...",
      "reasoning": "...",
      "conditions": "..."
    }
  }
}
```

Exemple `tutorial`:
```json
{
  "source": "https://docs.example.com/install",
  "agent_goal": "How to install and configure this project step by step"
}
```
Réponse (extrait):
```json
{
  "intent_detected": "tutorial",
  "data": {
    "prerequisites": ["..."],
    "steps": [{"number": 1, "action": "...", "explanation": "..."}],
    "examples": ["..."],
    "common_pitfalls": ["..."],
    "troubleshooting": ["..."]
  }
}
```

### Observabilité et tests SLA/charge

Les nouveaux endpoints sont couverts par des tests e2e de charge et de latence (voir `tests/test_pr3_api_and_sla.py`). Le dashboard KPI expose les métriques produit en temps réel.

> **Web Runtime Intelligence Layer.**
> Clean, structured intelligence from any URL — for your AI agents.

Raw HTML, broken PDFs, noisy spreadsheets — your agents fail on them, hallucinate on them, or overflow their context window. **Reversal normalizes any source into structured, enriched JSON in < 2s.** Every time. Every format.

```
WITHOUT REVERSAL                      WITH REVERSAL
─────────────────────                 ──────────────────────────────────────
Agent → reads raw HTML      →  50–70% accuracy, hallucinations, timeouts
Agent → reads complex PDF   →  parsing errors, missed tables
Agent → reads Excel         →  context overflow, partial data

Agent → calls Reversal → gets structured intelligence  →  99% accuracy, < 2s
```

---

## Positioning

Reversal is **not** just a scraper or HTML parser.
Reversal is a **web runtime intelligence layer** — it classifies pages, scores extraction quality, extracts structured metadata, semantically chunks content for LLMs, maps the link graph, and detects SPA/auth requirements.

> "OpenClaw/Hermes3 are the pilot. Reversal is the clean road."

---

## What It Does — The Reliability Gap

| Scenario | Without Reversal | With Reversal |
|---|---|---|
| Messy HTML / news article | Hallucinations, ads injected | Clean normalized text |
| Complex PDF layout | Parsing errors, missed tables | 99% extraction accuracy |
| Excel / dashboard screenshot | Context overflow, partial data | Structured JSON rows |
| Long document (> context window) | Truncation silently | Compressed summary + key points |
| Multiple sources in one pipeline | N re-implementations | Universal schema, one call |

---

## Native Agent Integrations

| Agent / Framework | Integration | Method |
|---|---|---|
| **GitHub Copilot** | ✓ | REST API / Python SDK |
| **Claude Desktop** | ✓ | MCP native (`.mcp.json`) |
| **Claude Code** | ✓ | MCP native (`reverse_read`) |
| **OpenAI Codex** | ✓ | MCP (`MCP_CONFIG=.mcp.json`) |
| **ChatGPT** | ✓ | Plugin / function calling |
| **OpenClaw / ClawHub** | ✓ | Skill natif (`reverse_read`, `batch_reverse`) |
| **Hermes3 (Nous Research)** | ✓ | Skill ClawHub |
| Cursor / Windsurf | ✓ | MCP native (`.cursor/mcp.json`) |
| LangChain | ✓ | Python SDK (`reversal-sdk`) |
| CrewAI | ✓ | Python SDK |
| Vercel AI SDK | ✓ | TypeScript SDK (`reversal-client`) |
| AutoGPT | ✓ | REST API |

### GitHub Copilot
```python
from reversal_sdk import ReversalClient
client = ReversalClient(api_key="rev_xxxxxxxx")
result = client.reverse("https://example.com")
print(result["summary"])
```

### Claude Code / Claude Desktop
Ajoutez `.mcp.json` à la racine du projet :
```json
{
  "mcpServers": {
    "reversal": {
      "url": "https://your-reversal-instance/v1/mcp",
      "headers": { "Authorization": "Bearer rev_xxxxxxxx" }
    }
  }
}
```
Ou en stdio (self-hosted) :
```json
{
  "mcpServers": {
    "reversal": {
      "command": "uvx",
      "args": ["reversal-engine", "--mcp"],
      "env": { "ANTHROPIC_API_KEY": "sk-ant-…" }
    }
  }
}
```

### OpenAI Codex
```bash
export MCP_CONFIG=.mcp.json
# → reverse_read(url) disponible nativement
```

### ChatGPT (function calling)
```json
{
  "name": "reversal_reverse",
  "description": "Analyse une URL ou fichier et retourne JSON structuré.",
  "parameters": { "type": "object", "properties": { "source": { "type": "string" } }, "required": ["source"] }
}
// Appel : POST /v1/reverse ou /v1/optimize/plan (PR3)
```

### OpenClaw / ClawHub
```
# Bibliothèque ClawHub → « Add Reversal skill »
# L'agent peut appeler directement :
reverse_read(source)          # → JSON structuré
batch_reverse(sources)        # → liste de résultats
detect_content_type(source)   # → type de contenu
reverse_with_planning(source, agent_goal)   # → extraction orientée intention + planification
analyze_content_only(source, agent_goal)    # → analyse rapide (sans conversion complète)
explain_last_decision()       # → explication de la dernière décision World Model
```

### Hermes3 (Nous Research via ClawHub)
```
> Analyse https://example.com/annual-report.pdf
← { "title": "…", "content_type": "pdf", "summary": "…", "key_points": […] }
```

---

## Supported Sources

| Source | Output |
|---|---|
| 🌐 Any URL / Webpage | Structured JSON with title, content, links |
| 📄 PDF | Pages, text, metadata |
| 📝 Word (.docx) | Paragraphs, headings, structure |
| 📊 Excel (.xlsx) | Sheets, headers, rows as objects |
| 🗃️ CSV | Headers + rows as JSON array |
| 🖼️ Image / Dashboard | Metrics, tables, text (via Claude Vision) |
| 📃 Plain Text | Lines, word count, content |

---

## Install

```bash
git clone <your-repo>
cd REVERSAL
pip install -r requirements.txt
export ANTHROPIC_API_KEY=your_key_here   # only needed for image parsing
```

---

## Usage

### As Python Library
```python
from reversal_engine import reverse

# Read a webpage
result = reverse("https://example.com")

# Read a PDF
result = reverse("/path/to/report.pdf")

# Read a dashboard screenshot
result = reverse("/path/to/dashboard.png")

# Read an Excel file
result = reverse("/path/to/data.xlsx")

print(result["data"]["title"])
print(result["content_type"])
print(result["processed_in_ms"])
```

### As CLI Tool
```bash
# Read a URL
python -m reversal_engine.cli https://example.com

# Read a PDF and save output
python -m reversal_engine.cli report.pdf --output result.json

# Just detect content type
python -m reversal_engine.cli dashboard.png --detect-only

# Compact output for piping
python -m reversal_engine.cli data.xlsx --format compact | jq '.data.sheets[0].rows'
```

### As REST API
```bash
# Start the server
python -m reversal_engine.api_server

# Call it
curl -X POST http://localhost:8000/reverse \
  -H "Content-Type: application/json" \
  -d '{"source": "https://example.com"}'
```

### As MCP Server (for Claude Code / AI Agents)
`.mcp.json` is already configured at the project root. Add your real API key there, then reload Claude Code — it will see `reverse_read()` as a native tool:

```
reverse_read("https://example.com")
reverse_read("/path/to/report.pdf")
reverse_read("/path/to/dashboard.png")
```

The MCP server also exposes an **HTTP endpoint** for remote agents:
```bash
curl -X POST https://your-reversal-instance/v1/mcp \
  -H "Authorization: Bearer rev_xxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
```

### Python SDK
```bash
pip install reversal-sdk
```
```python
from reversal_sdk import ReversalClient

client = ReversalClient(api_key="rev_xxxxxxxx")

# Analyse simple
result = client.reverse("https://example.com")
print(result["summary"])

# Lot de sources
results = client.batch(["https://a.com", "https://b.com/data.pdf"])

# PR3 – Optimisation multi-objectif
client.optimize_plan([...], objectives={"quality": 0.8, "speed": 0.1})

# PR3 – Synthèse multi-source
client.synthesize(["https://a.com", "https://b.com"], synthesis_goal="rapport")
```

### TypeScript SDK
```bash
npm install reversal-client
```
```typescript
import { ReversalClient } from "reversal-client";

const client = new ReversalClient({ apiKey: "rev_xxxxxxxx" });
const result = await client.reverse("https://example.com");
console.log(result.summary);

// Vercel AI SDK
import { tool } from "ai";
import { z } from "zod";

const reversalTool = tool({
  description: "Analyse une URL/document et retourne un résumé structuré.",
  parameters: z.object({ url: z.string().url() }),
  execute: async ({ url }) => {
    const r = await client.reverse(url);
    return { summary: r.summary, keyPoints: r.key_points };
  },
});
```

---

## Universal Output Schema

Every source returns the same envelope:

```json
{
  "reversal_engine": "1.0",
  "status": "ok | partial | blocked",
  "content_type": "url | pdf | word | excel | csv | image | text",
  "source": "original source string",
  "processed_in_ms": 142.5,
  "data": {
    "request_id": "uuid4",

    "page_type": {
      "primary": "article | ecommerce | docs | forum | video | dashboard | wiki | social_feed | unknown",
      "render_model": "static | spa",
      "access_model": "public | auth_required"
    },
    "quality": {
      "content_completeness": 0.87,
      "main_content_confidence": 0.91,
      "noise_ratio": 0.12,
      "structured_data_present": true
    },
    "structured_data": {
      "json_ld": [],
      "opengraph": {},
      "twitter_card": {}
    },

    "title": "...",
    "description": "...",
    "lang": "en",

    "chunks": [
      {"type": "heading", "level": 1, "text": "...", "section": ""},
      {"type": "paragraph", "text": "...", "section": "intro"},
      {"type": "list_item", "text": "...", "section": "..."},
      {"type": "code", "text": "...", "section": "..."}
    ],
    "content": ["flat paragraph list (backward compat)"],
    "headings": [],
    "word_count": 1234,
    "summary_hint": "first 300 chars...",

    "links": {
      "internal": [],
      "external": [],
      "navigation": [],
      "pagination": [],
      "social": [],
      "asset": []
    },
    "images": [],
    "content_hash": "sha256:...",

    "fetched_at": 1234567890.0,
    "http_status": 200,
    "content_length_bytes": 45678
  }
}
```

For SPA / blocked pages, a `runtime` block is added at the envelope level:

```json
{
  "runtime": {
    "requires_rendering": true,
    "requires_auth": false,
    "blocked_by": null,
    "recommended_strategy": "rendered_browser"
  }
}
```

---

## Project Structure

```
REVERSAL/
├── reversal_engine/
│   ├── __init__.py          # Public API: reverse(), detect()
│   ├── engine.py            # Core orchestrator + universal schema envelope
│   ├── detector.py          # Content type auto-detection
│   ├── pr3_engine.py        # PR3 orchestration primitives (mai 2026)
│   │                        #   collaborative_world_models_decision
│   │                        #   optimize_multiple_objectives
│   │                        #   synthesize_cross_format
│   │                        #   predictive_cache_prefetch
│   │                        #   reverse_stream_events
│   ├── mcp_server.py        # MCP server stdio + HTTP /v1/mcp
│   ├── api_server.py        # REST API (FastAPI) — 30+ routes
│   ├── auth.py              # Auth, registration, OTP, OAuth Google/GitHub
│   ├── cache.py             # Cache adaptatif + prédiction
│   ├── observability.py     # Prometheus, structlog, dashboard KPI
│   ├── jobs.py              # Async jobs (poll + SSE)
│   ├── upload.py            # Upload sécurisé (multi-format)
│   ├── webhooks.py          # Webhooks Stripe / Paddle
│   ├── cli.py               # CLI interface
│   ├── compressor.py        # Compression de contenu
│   ├── worker.py            # Background worker
│   └── parsers/
│       ├── url_parser.py    # Web runtime intelligence layer
│       ├── file_parsers.py  # PDF, Word, Excel, CSV, Text
│       └── image_parser.py  # Image / Dashboard (Claude Vision)
├── sdk/
│   ├── python/              # Python SDK (pip install reversal-sdk)
│   │   └── reversal_sdk/    #   client.py, models.py, exceptions.py
│   └── typescript/          # TypeScript SDK (npm install reversal-client)
│       └── src/             #   client.ts, types.ts, errors.ts
├── tests/
│   ├── test_pr3_engine.py   # Tests unitaires PR3
│   ├── test_pr3_api_and_sla.py  # Tests API + SLA/charge PR3
│   └── ...                  # 20+ autres modules de test
├── ui/
│   └── src/
│       ├── App.jsx          # UI principale + documentation
│       ├── AgentShowcase.jsx # Section "Reversal inside your agents"
│       └── KpiDemo.jsx      # Démo interactive dashboard KPI
├── .mcp.json                # Claude Code / Cursor MCP config
├── requirements.txt
└── README.md
```

---

## API Key Note

Image/dashboard parsing uses **Claude Vision**. All other parsers (URL, PDF, Word, Excel, CSV, Text) work **without any API key**.

To enable vision:
```bash
export ANTHROPIC_API_KEY=your_real_key_here
```

Or add it to `.mcp.json` under `env.ANTHROPIC_API_KEY`.

---

## Complete REST API Reference

### Auth
| Method | Route | Description |
|---|---|---|
| POST | `/v1/register` | Créer un compte, retourne `api_key` |
| POST | `/v1/register/request-otp` | Demande OTP par email |
| GET | `/v1/auth/config` | Config captcha/OTP côté client |
| POST | `/v1/auth/oauth/exchange` | Échange un `oauth_code` one-shot contre `api_key` |
| GET | `/v1/auth/google` | OAuth Google (redirect) |
| GET | `/v1/auth/github` | OAuth GitHub (redirect) |

### Reversal Core
| Method | Route | Description |
|---|---|---|
| POST | `/v1/reverse` | Analyse une source (sync ou async 202) |
| POST | `/v1/reverse/stream` | Streaming SSE en temps réel |
| POST | `/v1/reverse/smart` | Conversion intelligente (World Model + extraction orientée intention) |
| POST | `/v1/analyze` | Analyse de complexité + patterns + intention détectée |
| GET | `/v1/explain/last` | Dernière explication de stratégie sélectionnée |
| POST | `/v1/heal` | Relance auto-corrective de la conversion intelligente |
| POST | `/v1/confidence/check` | Décision proceed/review selon seuil de confiance |
| POST | `/v1/benchmark/run` | Benchmark direct vs World Model |
| POST | `/v1/batch` | Lot jusqu'à 10 sources |
| POST | `/v1/detect` | Détecte le type de contenu |
| POST | `/v1/feedback` | Envoie un feedback utilisateur |
| POST | `/v1/learning/feedback` | Alias feedback pour apprentissage adaptatif |
| GET | `/v1/insights/{key}` | Patterns appris par la mémoire adaptative |
| GET | `/v1/insights/{key}/history` | Historique time-series d'un pattern |

### PR3 — Orchestration Avancée
| Method | Route | Description |
|---|---|---|
| POST | `/v1/optimize/plan` | Sélectionne la meilleure stratégie (multi-objectif) |
| POST | `/v1/synthesize` | Fusionne plusieurs sources en rapport structuré |
| POST | `/v1/cache/predict` | Prédiction et préremplissage du cache |
| POST | `/v1/collaborative/decision` | Décision collaborative multi-modèle |

### Fichiers
| Method | Route | Description |
|---|---|---|
| POST | `/v1/upload` | Upload d'un fichier (PDF, image, Excel…) |
| DELETE | `/v1/files/{file_id}` | Supprime un fichier uploadé |

### Jobs Asynchrones
| Method | Route | Description |
|---|---|---|
| GET | `/v1/jobs/{job_id}` | Statut et résultat d'un job |
| GET | `/v1/jobs` | Liste des jobs de l'utilisateur |
| GET | `/v1/jobs/{job_id}/stream` | SSE streaming d'un job (plan premium) |

### Compte
| Method | Route | Description |
|---|---|---|
| GET | `/v1/me` | Infos compte et quota |
| GET | `/v1/upgrade` | Informations plan et upgrade |
| GET | `/v1/history` | Historique des appels |
| GET | `/v1/kpi/dashboard` | Dashboard KPI produit (latence, volume, drift…) |

### Système
| Method | Route | Description |
|---|---|---|
| GET | `/health` | Health check |
| GET | `/metrics` | Prometheus metrics |
| GET | `/versions` | Version de l'API |
| GET | `/well-known/reversal.json` | Manifeste public de compatibilité et de référencement |
| POST | `/v1/mcp` | MCP HTTP endpoint (JSON-RPC 2.0) |
| POST | `/webhook/stripe` | Stripe webhook |
| POST | `/webhook/paddle` | Paddle webhook |

---

## Async Jobs

Pour les sources volumineuses, `/v1/reverse` retourne `202 Accepted` avec un `job_id` :
```bash
# Lancer
POST /v1/reverse → { "job_id": "abc123", "status": "pending" }

# Poller
GET /v1/jobs/abc123 → { "status": "done", "result": { ... } }

# Ou streaming (plan premium)
GET /v1/jobs/abc123/stream  # SSE events
```

---

## Deployment Modes (Open Core)

Reversal supports two editions via environment variable:

- `REVERSAL_EDITION=saas` (default): full product behavior, including paid features
  according to plan entitlements.
- `REVERSAL_EDITION=oss`: premium SaaS features are disabled to keep the public
  edition limited to the free/open-source core.

Premium features disabled in `oss` mode:

- `/v1/batch`
- `webhook_url` usage on async jobs
- `/v1/jobs/{job_id}/stream` (SSE)
- `/v1/upgrade` and Stripe webhook activation

---

## GitHub Actions And Monitoring

The repository now includes two operational workflows:

- `CI` on push and pull request to `main`: Python tests, Ruff, frontend lint/build, and Docker smoke build.
- `Uptime Monitor` every 15 minutes and on manual dispatch: checks the production backend health endpoint, the production frontend homepage, and the Prometheus metrics endpoint when a token is configured.

### Recommended repository secrets

- `METRICS_TOKEN`: required only if production protects `/metrics`.
- `MCP_API_KEY`: optional, enables synthetic MCP checks (`initialize`, `tools/list`) in uptime monitor.
- `NPM_TOKEN`: required for npm publication in the existing release workflow.
- `PYPI_API_TOKEN_REVERSAL_ENGINE`: optional fallback token for first `reversal-engine` publish when Trusted Publishing cannot create a new PyPI project.

### Public compatibility manifest

The endpoint `GET /well-known/reversal.json` exposes a machine-readable manifest for platform listings and MCP clients. It includes:

- MCP HTTP and stdio transport details
- supported auth flows
- release version and API version
- platform readiness flags
- per-platform discovery hints for Replit, ElevenLabs, Lovable, and Emergent
- security and support contact links

This is the canonical reference to share when submitting Reversal to platform directories or partner forms.

### Production endpoints checked by the monitor

- Backend health: `https://reversal-api.onrender.com/health`
- Frontend: `https://reversal-71h.pages.dev`
- Metrics: `https://reversal-api.onrender.com/metrics`

If the monitor fails, GitHub Actions will mark the scheduled run as failed, which makes alerting and diagnosis easier from the Actions tab.
